Completed
Push — master ( c17b81...3a1758 )
by Dimas
19:57 queued 11s
created

libs/js/progress-timer.ts   A

Complexity

Total Complexity 23
Complexity/F 3.83

Size

Lines of Code 268
Function Count 6

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 183
dl 0
loc 268
rs 10
c 0
b 0
f 0
wmc 23
mnd 17
bc 17
fnc 6
bpm 2.8333
cpm 3.8333
noi 0
1
/// <reference path="./globals.d.ts"/>
2
3
interface progressBarTimer {
4
  warningThreshold: number;
5
}
6
/**
7
 * @see https://github.com/imalliar/jquery.progressBarTimer
8
 */
9
declare var progressBarTimer: progressBarTimer;
10
11
if (!isnode()) {
12
  /*
13
 <div class="progress">
14
 <div class="progress-bar progress-bar-success progress-bar-striped"
15
 role="progressbar" aria-valuenow="40" aria-valuemin="0"
16
 aria-valuemax="100" style="width: 40%">
17
 <span class="sr-only">40% Complete (success)</span>
18
 </div>
19
 </div>
20
 */
21
  if (typeof jQuery === "undefined") {
22
    throw new Error("jQuery progress timer requires jQuery");
23
  }
24
  /*!
25
   * jQuery lightweight plugin boilerplate
26
   * Original author: @ajpiano
27
   * Further changes, comments: @addyosmani
28
   * Licensed under the MIT license
29
   */
30
31
  (function ($, window, document, undefined) {
32
    "use strict";
33
    // undefined is used here as the undefined global
34
    // variable in ECMAScript 3 and is mutable (i.e. it can
35
    // be changed by someone else). undefined isn't really
36
    // being passed in so we can ensure that its value is
37
    // truly undefined. In ES5, undefined can no longer be
38
    // modified.
39
40
    // window and document are passed through as local
41
    // variables rather than as globals, because this (slightly)
42
    // quickens the resolution process and can be more
43
    // efficiently minified (especially when both are
44
    // regularly referenced in your plugin).
45
46
    // Create the defaults once
47
    var pluginName = "progressTimer";
48
49
    // The actual plugin constructor
50
51
    class Plugin {
52
      options: any;
53
      element: string;
54
      $elem: JQuery<HTMLElement>;
55
      defaults = {
56
        //total number of seconds
57
        timeLimit: 60,
58
        //seconds remaining triggering switch to warning color
59
        warningThreshold: 5,
60
        //invoked once the timer expires
61
        onFinish: function () {},
62
        //bootstrap progress bar style at the beginning of the timer
63
        baseStyle: "",
64
        //bootstrap progress bar style in the warning phase
65
        warningStyle: "progress-bar-danger",
66
        //bootstrap progress bar style at completion of timer
67
        completeStyle: "progress-bar-success",
68
        //show html on progress bar div area
69
        showHtmlSpan: true,
70
        //set the error text when error occurs
71
        errorText: "ERROR!",
72
        //set the success text when succes occurs
73
        successText: "100%",
74
      };
75
      _defaults = this.defaults;
76
      _name = pluginName;
77
      metadata: string;
78
      span: JQuery<HTMLElement>;
79
      barContainer: JQuery<HTMLElement>;
80
      bar: JQuery<HTMLElement>;
81
      start: Date;
82
      limit: number;
83
      warningThreshold: number;
84
      interval: NodeJS.Timer | number;
85
86
      constructor(element: string, options: any) {
87
        this.element = element;
88
        this.$elem = $(element);
89
        this.options = $.extend({}, this.defaults, options);
90
        this._defaults = this.defaults;
91
        this._name = pluginName;
92
        this.metadata = this.$elem.data("plugin-options");
93
      }
94
95
      init() {
96
        var t = this;
97
        $(t.element).empty();
98
        t.span = $("<span/>");
99
        t.barContainer = $("<div>").addClass("progress");
100
        t.bar = $("<div>")
101
          .addClass("progress-bar active progress-bar-striped")
102
          .addClass(t.options.baseStyle)
103
          .attr("role", "progressbar")
104
          .attr("aria-valuenow", "0")
105
          .attr("aria-valuemin", "0")
106
          .attr("aria-valuemax", t.options.timeLimit);
107
        t.span.appendTo(t.bar);
108
        if (!t.options.showHtmlSpan) {
109
          t.span.addClass("sr-only");
110
        }
111
        t.bar.appendTo(t.barContainer);
112
        t.barContainer.appendTo(t.element);
113
        t.start = new Date();
114
        t.limit = t.options.timeLimit * 1000;
115
        t.warningThreshold = t.options.warningThreshold * 1000;
116
        t.interval = window.setInterval(function () {
117
          t._run.call(t);
118
        }, 250);
119
        t.bar.data("progress-interval", t.interval);
120
        return true;
121
      }
122
123
      _run() {
124
        var t = this;
125
        var elapsed = new Date().valueOf() - t.start.valueOf(),
126
          width = (elapsed / t.limit) * 100;
127
        t.bar.attr("aria-valuenow", width);
128
        t.bar.width(width + "%");
129
        var percentage = new Number(width.toFixed(2));
130
        if (percentage >= 100) {
131
          percentage = 100;
132
        }
133
        if (t.options.showHtmlSpan) {
134
          t.span.html(percentage + "%");
135
        }
136
        if (elapsed >= t.warningThreshold) {
137
          t.bar
138
            .removeClass(this.options.baseStyle)
139
            .removeClass(this.options.completeStyle)
140
            .addClass(this.options.warningStyle);
141
        }
142
        if (elapsed >= t.limit) {
143
          t.complete.call(t);
144
        }
145
        return true;
146
      }
147
148
      removeInterval() {
149
        var t = this,
150
          bar = $(".progress-bar", t.element);
151
        if (typeof bar.data("progress-interval") !== "undefined") {
152
          var interval = bar.data("progress-interval");
153
          window.clearInterval(interval);
154
        }
155
        return bar;
156
      }
157
158
      destroy() {
159
        this.$elem.removeData();
160
      }
161
162
      complete() {
163
        var t = this,
164
          bar = t.removeInterval.call(t),
165
          args = arguments;
166
        if (args.length !== 0 && typeof args[0] === "object") {
167
          t.options = $.extend({}, t.options, args[0]);
168
        }
169
        bar
170
          .removeClass(t.options.baseStyle)
171
          .removeClass(t.options.warningStyle)
172
          .addClass(t.options.completeStyle);
173
        bar.width("100%");
174
        if (t.options.showHtmlSpan) {
175
          $("span", bar).html(t.options.successText);
176
        }
177
        bar.attr("aria-valuenow", 100);
178
        setTimeout(function () {
179
          t.options.onFinish.call(bar);
180
        }, 500);
181
        t.destroy.call(t);
182
      }
183
184
      error() {
185
        var t = this,
186
          bar = t.removeInterval.call(t),
187
          args = arguments;
188
        if (args.length !== 0 && typeof args[0] === "object") {
189
          t.options = $.extend({}, t.options, args[0]);
190
        }
191
        bar.removeClass(t.options.baseStyle).addClass(t.options.warningStyle);
192
        bar.width("100%");
193
        if (t.options.showHtmlSpan) {
194
          $("span", bar).html(t.options.errorText);
195
        }
196
        bar.attr("aria-valuenow", 100);
197
        setTimeout(function () {
198
          t.options.onFinish.call(bar);
199
        }, 500);
200
        t.destroy.call(t);
201
      }
202
    }
203
204
    Plugin.prototype.constructor = Plugin;
205
206
    // A really lightweight plugin wrapper around the constructor,
207
    // preventing against multiple instantiations
208
    $.fn[pluginName] = function (options: string | string[]) {
209
      var args = arguments;
210
      if (options === undefined || typeof options === "object") {
211
        // Creates a new plugin instance
212
        return this.each(function () {
213
          if (!$.data(this, "plugin_" + pluginName)) {
214
            $.data(this, "plugin_" + pluginName, new Plugin(this, options));
215
          }
216
        });
217
      } else if (
218
        typeof options === "string" &&
219
        options[0] !== "_" &&
220
        options !== "init"
221
      ) {
222
        // Call a public plugin method (not starting with an underscore) and different
223
        // from the "init" one
224
        if (
225
          Array.prototype.slice.call(args, 1).length === 0 &&
226
          $.inArray(options, $.fn[pluginName].getters) !== -1
227
        ) {
228
          // If the user does not pass any arguments and the method allows to
229
          // work as a getter then break the chainability so we can return a value
230
          // instead the element reference.
231
          var instance = $.data(this[0], "plugin_" + pluginName);
232
          return instance[options].apply(
233
            instance,
234
            Array.prototype.slice.call(args, 1)
235
          );
236
        } else {
237
          // Invoke the specified method on each selected element
238
          return this.each(function () {
239
            var instance = $.data(this, "plugin_" + pluginName);
240
            if (
241
              instance instanceof Plugin &&
242
              typeof instance[options] === "function"
243
            ) {
244
              instance[options].apply(
245
                instance,
246
                Array.prototype.slice.call(args, 1)
247
              );
248
            }
249
          });
250
        }
251
      }
252
    };
253
254
    $.fn[pluginName].getters = ["complete", "error"];
255
  })(jQuery, window, document, undefined);
256
}
257
258
interface JQueryStatic {
259
  /**
260
   * Accepts a string containing a CSS selector which is then used to match a set of elements.
261
   *
262
   * @param selector A string containing a selector expression
263
   * @param context A DOM Element, Document, or jQuery to use as context
264
   * @see {@link https://api.jquery.com/jQuery/#jQuery-selector-context}
265
   */
266
  (selector: string, context?: Element | JQuery | string): JQuery;
267
}
268