Imitation angular Bootstrap Timepicker Create the number of minutes-seconds of input controls _angularjs

Source: Internet
Author: User
Tags constant

You need a control to enter minutes and seconds in a project, but after investigating some open source projects, you don't find the right controls. There is a similar control timepicker in the angular Bootstrap UI, but it has no depth to the precision of minutes and seconds.
So decide to refer to its source code and implement it yourself.
The final effect is as follows:

The first is the definition of the directive:

 App.directive (' Minutesecondpicker ', function () {return
 {
 restrict: ' EA ',
 require: [' Minutesecondpicker ', ' ^ngmodel '],
 controller: ' Minutesecondpickercontroller ',
 replace:true,
 scope: {
  Validity: ' = '
 },
 templateurl: ' partials/directives/minutesecondpicker.html ',
 link:function (scope, Element, Attrs, ctrls) {
  var Minutesecondpickerctrl = ctrls[0],
  Ngmodelctrl = ctrls[1];

  if (Ngmodelctrl) {
  minutesecondpickerctrl.init (Ngmodelctrl, element.find (' input '));}};
 

In the above link function, Ctrls is an array: ctrls[0] is the controller instance defined on this directive, Ctrls[1 is Ngmodelctrl, the Ng-model instance corresponding to controller. This order is actually defined by require: [' minutesecondpicker ', '? ^ngmodel '].
note that the first dependency is the name of the directive itself, and the corresponding instance of the Controller declaration in the directive is passed in. The second dependency is a bit odd: "^ngmodel", which means that even if the dependency is not found, do not throw an exception, that is, the dependency is an optional option. The meaning of ^ is to find the controller of the parent element.
Then, define some of the default settings that are used in the directive, implemented through constant directive:

App.constant (' Minutesecondpickerconfig ', {
 minutestep:1,
 secondstep:1,
 readonlyinput:false,
 Mousewheel:true
}); 

followed by the directive corresponding controller, its declaration is as follows:

 App.controller (' Minutesecondpickercontroller ', [' $scope ', ' $attrs ', ' $parse ', ' Minutesecondpickerconfig 
 ', function ($scope, $attrs, $parse, minutesecondpickerconfig) {
 ...

In the directive link function, the Init method for this controller is invoked:

 This.init = function (Ngmodelctrl_, inputs) {
 Ngmodelctrl = Ngmodelctrl_;
 Ngmodelctrl. $render = This.render;

 var Minutesinputel = inputs.eq (0),
  Secondsinputel = Inputs.eq (1);

 var mousewheel = angular.isdefined ($attrs. MouseWheel)? 
  $scope. $parent. $eval ($attrs. MouseWheel): Minutesecondpickerconfig.mousewheel;
 if (mousewheel) {
  this.setupmousewheelevents (Minutesinputel, Secondsinputel);
 }

 $scope. Readonlyinput = angular.isdefined ($attrs. readonlyinput)?
  $scope. $parent. $eval ($attrs. Readonlyinput): Minutesecondpickerconfig.readonlyinput;
 This.setupinputevents (Minutesinputel, Secondsinputel);
 }; 

The second parameter accepted by the Init method is inputs, which is passed in the link function: Element.find (' input '). So the first input box is used to enter a minute, and the second input box is used to enter a second.
Then, check to see if the MouseWheel property is overwritten, and if not overridden, use the default MouseWheel set in constant, and make the relevant settings as follows:

Respond on MouseWheel spin
 this.setupmousewheelevents = function (Minutesinputel, Secondsinputel) {
 var Isscrollingup = function (e) {
  if (e.originalevent) {
  e = e.originalevent;
  }

  Pick correct delta variable depending on event
  var delta = (e.wheeldata)? E.wheeldata:-e.deltay;
  Return (E.detail | | Delta > 0);

 Minutesinputel.bind (' MouseWheel wheel ', function (e) {
  $scope. $apply ((Isscrollingup (e))? $ Scope.incrementminutes (): $scope. Decrementminutes ());
  E.preventdefault ();
 });

 Secondsinputel.bind (' MouseWheel wheel ', function (e) {
  $scope. $apply ((Isscrollingup (e))? $ Scope.incrementseconds (): $scope. Decrementseconds ());
  E.preventdefault ();
 });
  

The Init method finally makes some settings for the inputs itself:

Respond on direct Input this.setupinputevents = function (Minutesinputel, Secondsinputel) {if ($scope. readonlyinput)
  {$scope. updateminutes = Angular.noop;
  $scope. updateseconds = Angular.noop;
 Return
  var invalidate = function (Invalidminutes, invalidseconds) {Ngmodelctrl. $setViewValue (NULL);
  Ngmodelctrl. $setValidity (' time ', false);
  $scope. Validity = false;
  if (angular.isdefined (invalidminutes)) {$scope. invalidminutes = invalidminutes;
  } if (angular.isdefined (invalidseconds)) {$scope. invalidseconds = invalidseconds;

 }
 };

  $scope. updateminutes = function () {var minutes = getminutesfromtemplate ();
  if (angular.isdefined (minutes)) {selected.minutes = minutes;
  Refresh (' m ');
  else {invalidate (true);

 }
 }; Minutesinputel.bind (' Blur ', function (e) {if (! $scope. invalidminutes && $scope. Minutes <) {$scope. $apply
  (function () {$scope. minutes = Pad ($scope. minutes);
  });

 }
 }); $scope. updateseconds = function () {var seconds = Getsecondsfromtemplate ();
  if (angular.isdefined (seconds)) {selected.seconds = seconds;
  Refresh (' s ');
  else {invalidate (undefined, true);

 }
 }; Secondsinputel.bind (' Blur ', function (e) {if (! $scope. Invalidseconds && $scope. Seconds <) {$scope. $apply
  (function () {$scope. seconds = Pad ($scope. seconds);
  });
 }
 }); 

 };

In this method, a invalidate function is declared to set the illegal entry, exposing a validity = false attribute in scope to give the page an opportunity to react appropriately.
If a user uses a variable to represent minutestep or secondstep, then a corresponding watchers is also required:

var minutestep = minutesecondpickerconfig.minutestep;
 if ($attrs. minutestep) {
 $scope. Parent. $watch ($parse ($attrs. Minutestep), function (value) {
  Minutestep = parseint (value, ten);}
 );

 var secondstep = minutesecondpickerconfig.secondstep;
 if ($attrs. secondstep) {
 $scope. Parent. $watch ($parse ($attrs. Secondstep), function (value) {
  Secondstep = parseint (value, ten);}
 );
  

The complete Directive implementation code is as follows:

var app = Angular.module ("Minutesecondpickerdemo"); 
 App.directive (' Minutesecondpicker ', function () {return {restrict: ' EA ', require: [' minutesecondpicker ', '? ^ngmodel '], Controller: ' Minutesecondpickercontroller ', replace:true, scope: {validity: ' = '}, Templateurl: ' Partials/direct
  Ives/minutesecondpicker.html ', link:function (scope, element, Attrs, ctrls) {var Minutesecondpickerctrl = ctrls[0],

  Ngmodelctrl = ctrls[1];
  if (Ngmodelctrl) {minutesecondpickerctrl.init (Ngmodelctrl, element.find (' input '));
}
 }
 };

});

App.constant (' Minutesecondpickerconfig ', {minutestep:1, secondstep:1, Readonlyinput:false, mousewheel:true}); App.controller (' Minutesecondpickercontroller ', [' $scope ', ' $attrs ', ' $parse ', ' minutesecondpickerconfig ', function ( $scope, $attrs, $parse, Minutesecondpickerconfig) {var selected = {minutes:0, seconds:0}, Ngmodelctrl = {$

 SetViewValue:angular.noop}; This.init = function (Ngmodelctrl_, inputs) {Ngmodelctrl = Ngmodelctrl_;

 Ngmodelctrl. $render = This.render;

 var Minutesinputel = inputs.eq (0), Secondsinputel = Inputs.eq (1); 
  var mousewheel = angular.isdefined ($attrs. MouseWheel)?
 $scope. $parent. $eval ($attrs. MouseWheel): Minutesecondpickerconfig.mousewheel;
 if (MouseWheel) {this.setupmousewheelevents (Minutesinputel, Secondsinputel);
  $scope. Readonlyinput = angular.isdefined ($attrs. readonlyinput)?
 $scope. $parent. $eval ($attrs. Readonlyinput): Minutesecondpickerconfig.readonlyinput;
 This.setupinputevents (Minutesinputel, Secondsinputel);

 };
 var minutestep = Minutesecondpickerconfig.minutestep; if ($attrs. minutestep) {$scope. Parent. $watch ($parse ($attrs. Minutestep), function (value) {minutestep = parseint (value
 , 10);
 });
 var secondstep = Minutesecondpickerconfig.secondstep; if ($attrs. secondstep) {$scope. Parent. $watch ($parse ($attrs. Secondstep), function (value) {secondstep = parseint (value
 , 10);
 }); }//Respond on MouseWheel spin this.setupmousewheelevents = function (Minutesinputel, Secondsinputel) {var isscrollingup = function (e) {if (e.originalevent) {e = e.original
  Event; }//Pick correct delta variable depending on event var delta = (e.wheeldata)?
  E.wheeldata:-e.deltay;
 Return (E.detail | | Delta > 0);

 }; Minutesinputel.bind (' MouseWheel wheel ', function (e) {$scope. $apply ((Isscrollingup (e)) $scope. Incrementminutes (): $
  Scope.decrementminutes ());
 E.preventdefault ();

 }); Secondsinputel.bind (' MouseWheel wheel ', function (e) {$scope. $apply ((Isscrollingup (e)) $scope. Incrementseconds (): $
  Scope.decrementseconds ());
 E.preventdefault ();
 });

 }; 
  Respond on direct Input this.setupinputevents = function (Minutesinputel, Secondsinputel) {if ($scope. readonlyinput) {
  $scope. updateminutes = Angular.noop;
  $scope. updateseconds = Angular.noop;
 Return
  var invalidate = function (Invalidminutes, invalidseconds) {Ngmodelctrl. $setViewValue (NULL);
  Ngmodelctrl. $setValidity (' time ', false); $scoPe.validity = false;
  if (angular.isdefined (invalidminutes)) {$scope. invalidminutes = invalidminutes;
  } if (angular.isdefined (invalidseconds)) {$scope. invalidseconds = invalidseconds;

 }
 };

  $scope. updateminutes = function () {var minutes = getminutesfromtemplate ();
  if (angular.isdefined (minutes)) {selected.minutes = minutes;
  Refresh (' m ');
  else {invalidate (true);

 }
 }; Minutesinputel.bind (' Blur ', function (e) {if (! $scope. invalidminutes && $scope. Minutes <) {$scope. $apply
  (function () {$scope. minutes = Pad ($scope. minutes);
  });

 }
 });

  $scope. updateseconds = function () {var seconds = getsecondsfromtemplate ();
  if (angular.isdefined (seconds)) {selected.seconds = seconds;
  Refresh (' s ');
  else {invalidate (undefined, true);

 }
 }; Secondsinputel.bind (' Blur ', function (e) {if (! $scope. Invalidseconds && $scope. Seconds <) {$scope. $apply
  (function () {$scope. seconds = Pad ($scope. seconds);
  }); }
 });

 }; This.render = function () {var time = Ngmodelctrl. $modelValue?

 {Minutes:ngmodelctrl. $modelValue. Minutes, Seconds:ngmodelctrl. $modelValue. seconds}: null;
 Adjust the time to invalid value at the I/I if (Time.minutes < 0) {time.minutes = 0;
 } if (Time.seconds < 0) {time.seconds = 0;
 var totalseconds = time.minutes + time.seconds;

 Time = {Minutes:Math.floor (totalseconds/60), seconds:totalseconds% 60};
  if (time) {selected = time;
  Makevalid ();
 Updatetemplate ();

 }
 };
 Call internally while the model is valid function refresh (keyboardchange) {makevalid ();
 Ngmodelctrl. $setViewValue ({minutes:selected.minutes, seconds:selected.seconds});
 Updatetemplate (Keyboardchange);
 function Makevalid () {Ngmodelctrl. $setValidity (' time ', true);
 $scope. Validity = true;
 $scope. Invalidminutes = false;
 $scope. Invalidseconds = false; function Updatetemplate (keyboardchange) {var minutes = Selected.minutes, SEconds = Selected.seconds; $scope. minutes = Keyboardchange = = ' m '?
 Minutes:pad (minutes); $scope. seconds = Keyboardchange = = = ' s '?
 Seconds:pad (seconds); function Pad (value) {return (angular.isdefined (value) && value.tostring (). length < 2)?
 ' 0 ' + value:value;
 function Getminutesfromtemplate () {var minutes = parseint ($scope. minutes, 10); Return (minutes >= 0)?
 minutes:undefined;
 function Getsecondsfromtemplate () {var seconds = parseint ($scope. seconds, 10);
 if (seconds >=) {seconds = 59; return (seconds >= 0)?
 seconds:undefined;
 $scope. incrementminutes = function () {addseconds (Minutestep * 60);

 };
 $scope. decrementminutes = function () {addseconds (-minutestep * 60);

 };
 $scope. incrementseconds = function () {addseconds (secondstep);

 };
 $scope. decrementseconds = function () {addseconds (-secondstep);

 }; function addseconds (seconds) {var newseconds = Selected.minutes * + selected.seconds + SecondS
 if (Newseconds < 0) {newseconds = 0;

 } selected = {Minutes:Math.floor (newseconds/60), seconds:newseconds% 60};
 Refresh (); $scope. previewtime = function (minutes, seconds) {var totalseconds = parseint (minutes, Ten) * + parseint (seconds, 1

 0), hh = Pad (Math.floor (totalseconds/3600)), MM = pad (minutes%), SS = pad (seconds);
 return hh + ': ' + mm + ': ' + ss;
}; 
 }]);

Corresponding template implementation: &NBSP;

<table> <tbody> <tr class= "Text-center" > <td> <a ng-click= "incrementminutes ()" Class= "BT n Btn-link "> <span class=" Glyphicon glyphicon-chevron-up "></span> </a> </td> <td&gt ; </td> <td> <a ng-click= "incrementseconds ()" class= "btn btn-link" > <span class= "Glyphico 
  n glyphicon-chevron-up "></span> </a> </td> <td> </td> </tr> <tr> &LT;TD style= "width:50px class=" Form-group "ng-class=" {' Has-error ': invalidminutes} "> <input type=" text "ng-m Odel= "Minutes" ng-change= "updateminutes ()" class= "Form-control text-center" ng-mousewheel= "Incrementminutes" () " Ng-readonly= "Readonlyinput" maxlength= "3" > </td> <td>:</td> <td style= "width:50px" "class=" f Orm-group "ng-class=" {' Has-error ': invalidseconds} "> <input type=" text "ng-model=" Seconds "ng-change=" Updateseconds () "class=" Form-control text-centeR "ng-mousewheel=" Incrementseconds () "ng-readonly=" Readonlyinput "maxlength=" 2 "> <td> <!--preview column
  --> <td> <span class= "label label-primary" ng-show= "validity" > {{previewtime (minutes, seconds)}} </span> </td> </tr> <tr class= "Text-center" > <td> <a ng-click= "decrementminutes () "class=" btn btn-link "> <span class=" Glyphicon glyphicon-chevron-down "></span> </a> </td&
  Gt <td> </td> <td> <a ng-click= "decrementseconds ()" class= "btn btn-link" > <span class=
 "Glyphicon glyphicon-chevron-down" ></span> </a> </td> <td> </td> </tr> 
 </tbody> </table>

Test code (that is, the source code of the previous screenshot dialog):

 <div class= "Modal-header" > 

If you want to further study, you can click here to learn, and then attach 3 wonderful topics:

Bootstrap Learning Course

Bootstrap Practical Course

Bootstrap Plugin Usage Tutorial

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.