My first jQuery plugin. Need help formatting and understanding how it works

Today I wrote my first plugin: a simple tool so that the number in an element is counted up. It works great, but I built it on the following examples and some trial and error, so I can’t say that I understand how it works completely.

I do not understand:

a) How should I include convenient functions, such as the secondsToTime() function (if I need it to be in the function), I understand that this is not the case in this example.) Why does it work here from within this block.

b) How are variables declared ( _this, seconds, interval ) declared? All of them are saved simultaneously for each item.

c) Can this plugin be structured better?

code:

 $(document).ready(function(){ $('.ticker').countup(); }); (function($) { $.fn.countup = function() { return this.each(function(){ var _this = this, seconds = parseInt($(this).text()), interval = setInterval(updateTicker, 1000 ); updateTicker(); function updateTicker(){ seconds += 1; time = secondsToTime(seconds); outputtime = time.h + ":" + ((time.m <= 9) ? '0' + time.m : time.m) + ":" + ((time.s <= 9) ? '0' + time.s : time.s) $(_this).text(outputtime); } function secondsToTime(secs){ var hours = Math.floor(secs / (60 * 60)); var divisor_for_minutes = secs % (60 * 60); var minutes = Math.floor(divisor_for_minutes / 60); var divisor_for_seconds = divisor_for_minutes % 60; var seconds = Math.ceil(divisor_for_seconds); var obj = { "h": hours, "m": minutes, "s": seconds }; return obj; } }); }; })(jQuery); 

Thanks for your feedback.

+4
source share
2 answers

a) How to enable convenient functions like secondsToTime () function

I would move it to a level inside your function (function($) { ... })(jQuery); since it does not have to be re-created for each item.

a) ... Why does it work here from within this block?

Because the function can be accessed from code defined at the same scope level or from a nested scope.

b) How are i variables declared ( _this , seconds , interval )?

They all apply to every function call that you pass to this.each . More specifically: when a function is called, an execution context is created for the call. This execution context has a variable object that contains the variables, function arguments, and functions declared in the called function (they are all specific to the function call and therefore are created each time). Your updateTicker function (which is created for each call) is the closure of this variable object and therefore has a permanent reference to these variables. (Read more: Closing is not complicated .)

c) Can this plugin be structured better?

  • See above (a).
  • I would suggest that my plug-in function is a named function, not anonymous. (More: Anonymous Anonymous ) You already have your wrapper function (the one I mentioned in (a) above), so it would not cost anything, but it makes debugging easier when the functions really have names.
  • I would probably create a jQuery object for this only once, and then reuse it, instead of doing it twice from the start, and then again every time I execute updateTicker . For example, do var _this = this, => var _this = $(this), and use _this.text on the next line and within updateTicker .
  • As a rule, it is recommended to force the use of radix on parseInt by providing a second parameter (otherwise strange things can happen with leading zeros).
  • You can use only one time interval for updating all elements, and not an interval for each element.
  • I would add a way to stop the update.
  • Remember that timers are not entirely accurate, so your countdowns may drift. You might think about grabbing the start time and calculating how long it actually took, rather than decreasing the value of seconds .

Here's the first pass, implementing only # 1 - # 4 above, leaving the others for you:

 (function($) { $.fn.countup = MyNiftyPlugin_countup; // #2 function MyNiftyPlugin_countup() { // #2 cont'd return this.each(function(){ var _this = $(this), // #3 seconds = parseInt(_this.text(), 10), // #3 cont'd, #4 interval = setInterval(updateTicker, 1000 ); updateTicker(); function updateTicker(){ seconds += 1; time = secondsToTime(seconds); outputtime = time.h + ":" + ((time.m <= 9) ? '0' + time.m : time.m) + ":" + ((time.s <= 9) ? '0' + time.s : time.s) _this.text(outputtime); // #3 cont'd } }); } function secondsToTime(secs){ // #1 (moving this out a level) var hours = Math.floor(secs / (60 * 60)); var divisor_for_minutes = secs % (60 * 60); var minutes = Math.floor(divisor_for_minutes / 60); var divisor_for_seconds = divisor_for_minutes % 60; var seconds = Math.ceil(divisor_for_seconds); var obj = { "h": hours, "m": minutes, "s": seconds }; return obj; } })(jQuery); 
+5
source

Improvement with @ T.JCrowder code example.

Here, an interval was performed outside the loop and was executed only once. We save time as an integer in the data, so we only need to parse it once. Got the toTime function to return a formatted string. and a few other minor improvements.

 (function($) { $.fn.countup = MyNiftyPlugin_countup; function MyNiftyPlugin_countup() { var that = this; function updateTicker(){ that.each(updateNode); } function updateNode() { var $this = $(this); // cache var seconds = $this.data("time") + 1; // get time from $.data $this.data("time", seconds); //var seconds = Date.now() // alternative get accurate time right _now_ var time = secondsToTime(seconds)[1]; // get string from tuple $this.text(time).data("time", seconds); } setInterval(updateTicker, 1000); updateTicker(); return this.each(function(){ var $this = $(this); // cache $this.data("time", parseInt($this.text(), 10); }); } function secondsToTime(secs){ var hours = Math.floor(secs / (60 * 60)); var divisor_for_minutes = secs % (60 * 60); var minutes = Math.floor(divisor_for_minutes / 60); var divisor_for_seconds = divisor_for_minutes % 60; var seconds = Math.ceil(divisor_for_seconds); var time = { "h": hours, "m": minutes, "s": seconds }; var outputtime = time.h + ":" + ((time.m <= 9) ? '0' + time.m : time.m) + ":" + ((time.s <= 9) ? '0' + time.s : time.s) return [time, outputtime]; } })(jQuery); 
0
source

Source: https://habr.com/ru/post/1337944/


All Articles