PageSourceSearch

https://retromodel.ru/06-18/js/pnotify.js

js retromodel.ru collected 2026-10-04 00:56:44 UTC 54,575 bytes, 1,285 lines download raw bytes

1/*
2PNotify 2.0.1 sciactive.com/pnotify/
3(C) 2014 Hunter Perrin
4license GPL/LGPL/MPL
5*/
6/*
7 * ====== PNotify ======
8 *
9 * http://sciactive.com/pnotify/
10 *
11 * Copyright 2009-2014 Hunter Perrin
12 *
13 * Triple licensed under the GPL, LGPL, and MPL.
14 * 	http://gnu.org/licenses/gpl.html
15 * 	http://gnu.org/licenses/lgpl.html
16 * 	http://mozilla.org/MPL/MPL-1.1.html
17 */
18
19// Uses AMD or browser globals for jQuery.
20(function (factory) {
21    if (typeof define === 'function' && define.amd) {
22        // AMD. Register as a module.
23        define('pnotify', ['jquery'], factory);
24    } else {
25        // Browser globals
26        factory(jQuery);
27    }
28}(function ($) {
29    var default_stack = {
30        dir1: "down",
31        dir2: "left",
32        push: "top",
33        spacing1: 15,
34        spacing2: 15,
35        context: $("body")
36    };
37    var timer, // Position all timer.
38        body,
39        jwindow = $(window);
40    // Set global variables.
41    var do_when_ready = function () {
42        body = $("body");
43        PNotify.prototype.options.stack.context = body;
44        jwindow = $(window);
45        // Reposition the notices when the window resizes.
46        jwindow.bind('resize', function () {
47            if (timer)
48                clearTimeout(timer);
49            timer = setTimeout(function () {
50                PNotify.positionAll(true)
51            }, 10);
52        });
53    };
54    PNotify = function (options) {
55        this.parseOptions(options);
56        this.init();
57    };
58    $.extend(PNotify.prototype, {
59        // The current version of PNotify.
60        version: "2.0.1",
61
62        // === Options ===
63
64        // Options defaults.
65        options: {
66            // The notice's title.
67            title: false,
68            // Whether to escape the content of the title. (Not allow HTML.)
69            title_escape: false,
70            // The notice's text.
71            text: false,
72            // Whether to escape the content of the text. (Not allow HTML.)
73            text_escape: false,
74            // What styling classes to use. (Can be either jqueryui or bootstrap.)
75            styling: "bootstrap3",
76            // Additional classes to be added to the notice. (For custom styling.)
77            addclass: "",
78            // Class to be added to the notice for corner styling.
79            cornerclass: "",
80            // Display the notice when it is created.
81            auto_display: true,
82            // Width of the notice.
83            width: "290px",
84            // Minimum height of the notice. It will expand to fit content.
85            min_height: "16px",
86            // Type of the notice. "notice", "info", "success", or "error".
87            type: "notice",
88            // Set icon to true to use the default icon for the selected
89            // style/type, false for no icon, or a string for your own icon class.
90            icon: true,
91            // Opacity of the notice.
92            opacity: 1,
93            // The animation to use when displaying and hiding the notice. "none",
94            // "show", "fade", and "slide" are built in to jQuery. Others require jQuery
95            // UI. Use an object with effect_in and effect_out to use different effects.
96            animation: "fade",
97            // Speed at which the notice animates in and out. "slow", "def" or "normal",
98            // "fast" or number of milliseconds.
99            animate_speed: "slow",
100            // Specify a specific duration of position animation
101            position_animate_speed: 500,
102            // Display a drop shadow.
103            shadow: false,
104            // After a delay, remove the notice.
105            hide: true,
106            // Delay in milliseconds before the notice is removed.
107            delay: 8000,
108            // Reset the hide timer if the mouse moves over the notice.
109            mouse_reset: true,
110            // Remove the notice's elements from the DOM after it is removed.
111            remove: true,
112            // Change new lines to br tags.
113            insert_brs: true,
114            // Whether to remove notices from the global array.
115            destroy: true,
116            // The stack on which the notices will be placed. Also controls the
117            // direction the notices stack.
118            stack: default_stack
119        },
120
121        // === Modules ===
122
123        // This object holds all the PNotify modules. They are used to provide
124        // additional functionality.
125        modules: {},
126        // This runs an event on all the modules.
127        runModules: function (event, arg) {
128            var curArg;
129            for (var module in this.modules) {
130                curArg = ((typeof arg === "object" && module in arg) ? arg[module] : arg);
131                if (typeof this.modules[module][event] === 'function')
132                    this.modules[module][event](this, typeof this.options[module] === 'object' ? this.options[module] : {}, curArg);
133            }
134        },
135
136        // === Class Variables ===
137
138        state: "initializing", // The state can be "initializing", "opening", "open", "closing", and "closed".
139        timer: null, // Auto close timer.
140        styles: null,
141        elem: null,
142        container: null,
143        title_container: null,
144        text_container: null,
145        animating: false, // Stores what is currently being animated (in or out).
146        timerHide: false, // Stores whether the notice was hidden by a timer.
147
148        // === Events ===
149
150        init: function () {
151            var that = this;
152
153            // First and foremost, we don't want our module objects all referencing the prototype.
154            this.modules = {};
155            $.extend(true, this.modules, PNotify.prototype.modules);
156
157            // Get our styling object.
158            if (typeof this.options.styling === "object") {
159                this.styles = this.options.styling;
160            } else {
161                this.styles = PNotify.styling[this.options.styling];
162            }
163
164            // Create our widget.
165            // Stop animation, reset the removal timer when the user mouses over.
166            this.elem = $("<div />", {
167                "class": "ui-pnotify " + this.options.addclass,
168                "css": {"display": "none"},
169                "mouseenter": function (e) {
170                    if (that.options.mouse_reset && that.animating === "out") {
171                        if (!that.timerHide)
172                            return;
173                        that.cancelRemove();
174                    }
175                    // Stop the close timer.
176                    if (that.options.hide && that.options.mouse_reset) that.cancelRemove();
177                },
178                "mouseleave": function (e) {
179                    // Start the close timer.
180                    if (that.options.hide && that.options.mouse_reset) that.queueRemove();
181                    PNotify.positionAll();
182                }
183            });
184            // Create a container for the notice contents.
185            this.container = $("<div />", {
186                "class":
187                this.styles.container + " ui-pnotify-container " +
188                (this.options.type === "error" ? this.styles.error :
189                (this.options.type === "primary" ? this.styles.primary :
190                (this.options.type === "info" ? this.styles.info :
191                (this.options.type === "success" ? this.styles.success :
192                (this.options.type === "warning" ? this.styles.warning :
193                (this.options.type === "danger" ? this.styles.danger :
194                (this.options.type === "alert" ? this.styles.alert :
195                (this.options.type === "system" ? this.styles.system :
196                (this.options.type === "dark" ? this.styles.dark :
197                this.options.type === "success" ? this.styles.success : this.styles.notice)))))))))
198            })
199
200                .appendTo(this.elem);
201            if (this.options.cornerclass !== "")
202                this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass);
203            // Create a drop shadow.
204            if (this.options.shadow)
205                this.container.addClass("ui-pnotify-shadow");
206
207            // Add the appropriate icon.
208            if (this.options.icon !== false) {
209                $("<div />", {"class": "ui-pnotify-icon"})
210                    .append($("<span />", {
211                        "class": this.options.icon === true ?
212                        (this.options.type === "error" ? this.styles.error_icon :
213                        (this.options.type === "primary" ? this.styles.primary_icon :
214                        (this.options.type === "info" ? this.styles.info_icon :
215                        (this.options.type === "success" ? this.styles.success_icon :
216                        (this.options.type === "warning" ? this.styles.warning_icon :
217                        (this.options.type === "danger" ? this.styles.danger_icon :
218                        (this.options.type === "alert" ? this.styles.alert_icon :
219                        (this.options.type === "system" ? this.styles.system_icon :
220                        (this.options.type === "dark" ? this.styles.dark_icon : this.styles.notice_icon))))))))) : this.options.icon
221                    }))
222                    .prependTo(this.container);
223            }
224
225            // Add a title.
226            this.title_container = $("<h4 />", {
227                "class": "ui-pnotify-title"
228            })
229                .appendTo(this.container);
230            if (this.options.title === false)
231                this.title_container.hide();
232            else if (this.options.title_escape)
233                this.title_container.text(this.options.title);
234            else
235                this.title_container.html(this.options.title);
236
237            // Add text.
238            this.text_container = $("<div />", {
239                "class": "ui-pnotify-text"
240            })
241                .appendTo(this.container);
242            if (this.options.text === false)
243                this.text_container.hide();
244            else if (this.options.text_escape)
245                this.text_container.text(this.options.text);
246            else
247                this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "<br />") : this.options.text);
248
249            // Set width and min height.
250            if (typeof this.options.width === "string")
251                this.elem.css("width", this.options.width);
252            if (typeof this.options.min_height === "string")
253                this.container.css("min-height", this.options.min_height);
254
255
256            // Add the notice to the notice array.
257            if (this.options.stack.push === "top")
258                PNotify.notices = $.merge([this], PNotify.notices);
259            else
260                PNotify.notices = $.merge(PNotify.notices, [this]);
261            // Now position all the notices if they are to push to the top.
262            if (this.options.stack.push === "top")
263                this.queuePosition(false, 1);
264
265            // Mark the stack so it won't animate the new notice.
266            this.options.stack.animation = false;
267
268            // Run the modules.
269            this.runModules('init');
270
271            // Display the notice.
272            if (this.options.auto_display)
273                this.open();
274            return this;
275        },
276
277        // This function is for updating the notice.
278        update: function (options) {
279            // Save old options.
280            var oldOpts = this.options;
281            // Then update to the new options.
282            this.parseOptions(oldOpts, options);
283            // Update the corner class.
284            if (this.options.cornerclass !== oldOpts.cornerclass)
285                this.container.removeClass("ui-corner-all " + oldOpts.cornerclass).addClass(this.options.cornerclass);
286            // Update the shadow.
287            if (this.options.shadow !== oldOpts.shadow) {
288                if (this.options.shadow)
289                    this.container.addClass("ui-pnotify-shadow");
290                else
291                    this.container.removeClass("ui-pnotify-shadow");
292            }
293            // Update the additional classes.
294            if (this.options.addclass === false)
295                this.elem.removeClass(oldOpts.addclass);
296            else if (this.options.addclass !== oldOpts.addclass)
297                this.elem.removeClass(oldOpts.addclass).addClass(this.options.addclass);
298            // Update the title.
299            if (this.options.title === false)
300                this.title_container.slideUp("fast");
301            else if (this.options.title !== oldOpts.title) {
302                if (this.options.title_escape)
303                    this.title_container.text(this.options.title);
304                else
305                    this.title_container.html(this.options.title);
306                if (oldOpts.title === false)
307                    this.title_container.slideDown(200)
308            }
309            // Update the text.
310            if (this.options.text === false) {
311                this.text_container.slideUp("fast");
312            } else if (this.options.text !== oldOpts.text) {
313                if (this.options.text_escape)
314                    this.text_container.text(this.options.text);
315                else
316                    this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "<br />") : this.options.text);
317                if (oldOpts.text === false)
318                    this.text_container.slideDown(200)
319            }
320            // Change the notice type.
321            if (this.options.type !== oldOpts.type)
322                this.container.removeClass(
323                    this.styles.error + " " + this.styles.notice + " " + this.styles.primary + " " + this.styles.info + " " + this.styles.success + " " + this.styles.warning + " " + this.styles.danger + " " + this.styles.alert + " " + this.styles.system + " " + this.styles.dark
324                ).addClass(
325                    this.options.type === "error" ? this.styles.error :
326                    (this.options.type === "primary" ? this.styles.primary :
327                    (this.options.type === "info" ? this.styles.info :
328                    (this.options.type === "success" ? this.styles.success :
329                    (this.options.type === "warning" ? this.styles.warning :
330                    (this.options.type === "danger" ? this.styles.danger :
331                    (this.options.type === "alert" ? this.styles.alert :
332                    (this.options.type === "system" ? this.styles.system :
333                    (this.options.type === "dark" ? this.styles.dark :
334                    this.styles.notice
335                    ))))))))
336                );
337            if (this.options.icon !== oldOpts.icon || (this.options.icon === true && this.options.type !== oldOpts.type)) {
338                // Remove any old icon.
339                this.container.find("div.ui-pnotify-icon").remove();
340                if (this.options.icon !== false) {
341                    // Build the new icon.
342                    $("<div />", {"class": "ui-pnotify-icon"})
343                        .append($("<span />", {
344                            "class":
345                                this.options.icon === true ?
346                                (this.options.type === "error" ? this.styles.error_icon :
347                                (this.options.type === "primary" ? this.styles.primary_icon :
348                                (this.options.type === "info" ? this.styles.info_icon :
349                                (this.options.type === "success" ? this.styles.success_icon :
350                                (this.options.type === "warning" ? this.styles.warning_icon :
351                                (this.options.type === "danger" ? this.styles.danger_icon :
352                                (this.options.type === "alert" ? this.styles.alert_icon :
353                                (this.options.type === "system" ? this.styles.system_icon :
354                                (this.options.type === "dark" ? this.styles.dark_icon : this.styles.notice_icon)))))))))
355                                : this.options.icon
356                        }))
357                        .prependTo(this.container);
358                }
359            }
360            // Update the width.
361            if (this.options.width !== oldOpts.width)
362                this.elem.animate({width: this.options.width});
363            // Update the minimum height.
364            if (this.options.min_height !== oldOpts.min_height)
365                this.container.animate({minHeight: this.options.min_height});
366            // Update the opacity.
367            if (this.options.opacity !== oldOpts.opacity)
368                this.elem.fadeTo(this.options.animate_speed, this.options.opacity);
369            // Update the timed hiding.
370            if (!this.options.hide)
371                this.cancelRemove();
372            else if (!oldOpts.hide)
373                this.queueRemove();
374            this.queuePosition(true);
375
376            // Run the modules.
377            this.runModules('update', oldOpts);
378            return this;
379        },
380
381        // Display the notice.
382        open: function () {
383            this.state = "opening";
384            // Run the modules.
385            this.runModules('beforeOpen');
386
387            var that = this;
388            // If the notice is not in the DOM, append it.
389            if (!this.elem.parent().length)
390                this.elem.appendTo(this.options.stack.context ? this.options.stack.context : body);
391            // Try to put it in the right position.
392            if (this.options.stack.push !== "top")
393                this.position(true);
394            // First show it, then set its opacity, then hide it.
395            if (this.options.animation === "fade" || this.options.animation.effect_in === "fade") {
396                // If it's fading in, it should start at 0.
397                this.elem.show().fadeTo(0, 0).hide();
398            } else {
399                // Or else it should be set to the opacity.
400                if (this.options.opacity !== 1)
401                    this.elem.show().fadeTo(0, this.options.opacity).hide();
402            }
403            this.animateIn(function () {
404                that.queuePosition(true);
405
406                // Now set it to hide.
407                if (that.options.hide)
408                    that.queueRemove();
409
410                that.state = "open";
411
412                // Run the modules.
413                that.runModules('afterOpen');
414            });
415
416            return this;
417        },
418
419        // Remove the notice.
420        remove: function (timer_hide) {
421            this.state = "closing";
422            this.timerHide = !!timer_hide; // Make sure it's a boolean.
423            // Run the modules.
424            this.runModules('beforeClose');
425
426            var that = this;
427            if (this.timer) {
428                window.clearTimeout(this.timer);
429                this.timer = null;
430            }
431            this.animateOut(function () {
432                that.state = "closed";
433                // Run the modules.
434                that.runModules('afterClose');
435                that.queuePosition(true);
436                // If we're supposed to remove the notice from the DOM, do it.
437                if (that.options.remove)
438                    that.elem.detach();
439                // Run the modules.
440                that.runModules('beforeDestroy');
441                // Remove object from PNotify.notices to prevent memory leak (issue #49)
442                // unless destroy is off
443                if (that.options.destroy) {
444                    if (PNotify.notices !== null) {
445                        var idx = $.inArray(that, PNotify.notices);
446                        if (idx !== -1) {
447                            PNotify.notices.splice(idx, 1);
448                        }
449                    }
450                }
451                // Run the modules.
452                that.runModules('afterDestroy');
453            });
454
455            return this;
456        },
457
458        // === Class Methods ===
459
460        // Get the DOM element.
461        get: function () {
462            return this.elem;
463        },
464
465        // Put all the options in the right places.
466        parseOptions: function (options, moreOptions) {
467            this.options = $.extend(true, {}, PNotify.prototype.options);
468            // This is the only thing that *should* be copied by reference.
469            this.options.stack = PNotify.prototype.options.stack;
470            var optArray = [options, moreOptions], curOpts;
471            for (var curIndex in optArray) {
472                curOpts = optArray[curIndex];
473                if (typeof curOpts == "undefined")
474                    break;
475                if (typeof curOpts !== 'object') {
476                    this.options.text = curOpts;
477                } else {
478                    for (var option in curOpts) {
479                        if (this.modules[option]) {
480                            // Avoid overwriting module defaults.
481                            $.extend(true, this.options[option], curOpts[option]);
482                        } else {
483                            this.options[option] = curOpts[option];
484                        }
485                    }
486                }
487            }
488        },
489
490        // Animate the notice in.
491        animateIn: function (callback) {
492            // Declare that the notice is animating in. (Or has completed animating in.)
493            this.animating = "in";
494            var animation;
495            if (typeof this.options.animation.effect_in !== "undefined")
496                animation = this.options.animation.effect_in;
497            else
498                animation = this.options.animation;
499            if (animation === "none") {
500                this.elem.show();
501                callback();
502            } else if (animation === "show")
503                this.elem.show(this.options.animate_speed, callback);
504            else if (animation === "fade")
505                this.elem.show().fadeTo(this.options.animate_speed, this.options.opacity, callback);
506            else if (animation === "slide")
507                this.elem.slideDown(this.options.animate_speed, callback);
508            else if (typeof animation === "function")
509                animation("in", callback, this.elem);
510            else
511                this.elem.show(animation, (typeof this.options.animation.options_in === "object" ? this.options.animation.options_in : {}), this.options.animate_speed, callback);
512            if (this.elem.parent().hasClass('ui-effects-wrapper'))
513                this.elem.parent().css({"position": "fixed", "overflow": "visible"});
514            if (animation !== "slide")
515                this.elem.css("overflow", "visible");
516            this.container.css("overflow", "hidden");
517        },
518
519        // Animate the notice out.
520        animateOut: function (callback) {
521            // Declare that the notice is animating out. (Or has completed animating out.)
522            this.animating = "out";
523            var animation;
524            if (typeof this.options.animation.effect_out !== "undefined")
525                animation = this.options.animation.effect_out;
526            else
527                animation = this.options.animation;
528            if (animation === "none") {
529                this.elem.hide();
530                callback();
531            } else if (animation === "show")
532                this.elem.hide(this.options.animate_speed, callback);
533            else if (animation === "fade")
534                this.elem.fadeOut(this.options.animate_speed, callback);
535            else if (animation === "slide")
536                this.elem.slideUp(this.options.animate_speed, callback);
537            else if (typeof animation === "function")
538                animation("out", callback, this.elem);
539            else
540                this.elem.hide(animation, (typeof this.options.animation.options_out === "object" ? this.options.animation.options_out : {}), this.options.animate_speed, callback);
541            if (this.elem.parent().hasClass('ui-effects-wrapper'))
542                this.elem.parent().css({"position": "fixed", "overflow": "visible"});
543            if (animation !== "slide")
544                this.elem.css("overflow", "visible");
545            this.container.css("overflow", "hidden");
546        },
547
548        // Position the notice. dont_skip_hidden causes the notice to
549        // position even if it's not visible.
550        position: function (dontSkipHidden) {
551            // Get the notice's stack.
552            var s = this.options.stack,
553                e = this.elem;
554            if (e.parent().hasClass('ui-effects-wrapper'))
555                e = this.elem.css({"left": "0", "top": "0", "right": "0", "bottom": "0"}).parent();
556            if (typeof s.context === "undefined")
557                s.context = body;
558            if (!s) return;
559            if (typeof s.nextpos1 !== "number")
560                s.nextpos1 = s.firstpos1;
561            if (typeof s.nextpos2 !== "number")
562                s.nextpos2 = s.firstpos2;
563            if (typeof s.addpos2 !== "number")
564                s.addpos2 = 0;
565            var hidden = e.css("display") === "none";
566            // Skip this notice if it's not shown.
567            if (!hidden || dontSkipHidden) {
568                var curpos1, curpos2;
569                // Store what will need to be animated.
570                var animate = {};
571                // Calculate the current pos1 value.
572                var csspos1;
573                switch (s.dir1) {
574                    case "down":
575                        csspos1 = "top";
576                        break;
577                    case "up":
578                        csspos1 = "bottom";
579                        break;
580                    case "left":
581                        csspos1 = "right";
582                        break;
583                    case "right":
584                        csspos1 = "left";
585                        break;
586                }
587                curpos1 = parseInt(e.css(csspos1).replace(/(?:\..*|[^0-9.])/g, ''));
588                if (isNaN(curpos1))
589                    curpos1 = 0;
590                // Remember the first pos1, so the first visible notice goes there.
591                if (typeof s.firstpos1 === "undefined" && !hidden) {
592                    s.firstpos1 = curpos1;
593                    s.nextpos1 = s.firstpos1;
594                }
595                // Calculate the current pos2 value.
596                var csspos2;
597                switch (s.dir2) {
598                    case "down":
599                        csspos2 = "top";
600                        break;
601                    case "up":
602                        csspos2 = "bottom";
603                        break;
604                    case "left":
605                        csspos2 = "right";
606                        break;
607                    case "right":
608                        csspos2 = "left";
609                        break;
610                }
611                curpos2 = parseInt(e.css(csspos2).replace(/(?:\..*|[^0-9.])/g, ''));
612                if (isNaN(curpos2))
613                    curpos2 = 0;
614                // Remember the first pos2, so the first visible notice goes there.
615                if (typeof s.firstpos2 === "undefined" && !hidden) {
616                    s.firstpos2 = curpos2;
617                    s.nextpos2 = s.firstpos2;
618                }
619                // Check that it's not beyond the viewport edge.
620                if ((s.dir1 === "down" && s.nextpos1 + e.height() > (s.context.is(body) ? jwindow.height() : s.context.prop('scrollHeight'))) ||
621                    (s.dir1 === "up" && s.nextpos1 + e.height() > (s.context.is(body) ? jwindow.height() : s.context.prop('scrollHeight'))) ||
622                    (s.dir1 === "left" && s.nextpos1 + e.width() > (s.context.is(body) ? jwindow.width() : s.context.prop('scrollWidth'))) ||
623                    (s.dir1 === "right" && s.nextpos1 + e.width() > (s.context.is(body) ? jwindow.width() : s.context.prop('scrollWidth')))) {
624                    // If it is, it needs to go back to the first pos1, and over on pos2.
625                    s.nextpos1 = s.firstpos1;
626                    s.nextpos2 += s.addpos2 + (typeof s.spacing2 === "undefined" ? 25 : s.spacing2);
627                    s.addpos2 = 0;
628                }
629                // Animate if we're moving on dir2.
630                if (s.animation && s.nextpos2 < curpos2) {
631                    switch (s.dir2) {
632                        case "down":
633                            animate.top = s.nextpos2 + "px";
634                            break;
635                        case "up":
636                            animate.bottom = s.nextpos2 + "px";
637                            break;
638                        case "left":
639                            animate.right = s.nextpos2 + "px";
640                            break;
641                        case "right":
642                            animate.left = s.nextpos2 + "px";
643                            break;
644                    }
645                } else {
646                    if (typeof s.nextpos2 === "number")
647                        e.css(csspos2, s.nextpos2 + "px");
648                }
649                // Keep track of the widest/tallest notice in the column/row, so we can push the next column/row.
650                switch (s.dir2) {
651                    case "down":
652                    case "up":
653                        if (e.outerHeight(true) > s.addpos2)
654                            s.addpos2 = e.height();
655                        break;
656                    case "left":
657                    case "right":
658                        if (e.outerWidth(true) > s.addpos2)
659                            s.addpos2 = e.width();
660                        break;
661                }
662                // Move the notice on dir1.
663                if (typeof s.nextpos1 === "number") {
664                    // Animate if we're moving toward the first pos.
665                    if (s.animation && (curpos1 > s.nextpos1 || animate.top || animate.bottom || animate.right || animate.left)) {
666                        switch (s.dir1) {
667                            case "down":
668                                animate.top = s.nextpos1 + "px";
669                                break;
670                            case "up":
671                                animate.bottom = s.nextpos1 + "px";
672                                break;
673                            case "left":
674                                animate.right = s.nextpos1 + "px";
675                                break;
676                            case "right":
677                                animate.left = s.nextpos1 + "px";
678                                break;
679                        }
680                    } else
681                        e.css(csspos1, s.nextpos1 + "px");
682                }
683                // Run the animation.
684                if (animate.top || animate.bottom || animate.right || animate.left)
685                    e.animate(animate, {duration: this.options.position_animate_speed, queue: false});
686                // Calculate the next dir1 position.
687                switch (s.dir1) {
688                    case "down":
689                    case "up":
690                        s.nextpos1 += e.height() + (typeof s.spacing1 === "undefined" ? 25 : s.spacing1);
691                        break;
692                    case "left":
693                    case "right":
694                        s.nextpos1 += e.width() + (typeof s.spacing1 === "undefined" ? 25 : s.spacing1);
695                        break;
696                }
697            }
698            return this;
699        },
700        // Queue the position all function so it doesn't run repeatedly and
701        // use up resources.
702        queuePosition: function (animate, milliseconds) {
703            if (timer)
704                clearTimeout(timer);
705            if (!milliseconds)
706                milliseconds = 10;
707            timer = setTimeout(function () {
708                PNotify.positionAll(animate)
709            }, milliseconds);
710            return this;
711        },
712
713
714        // Cancel any pending removal timer.
715        cancelRemove: function () {
716            if (this.timer)
717                window.clearTimeout(this.timer);
718            if (this.state === "closing") {
719                // If it's animating out, animate back in really quickly.
720                this.elem.stop(true);
721                this.state = "open";
722                this.animating = "in";
723                this.elem.css("height", "auto").animate({
724                    "width": this.options.width,
725                    "opacity": this.options.opacity
726                }, "fast");
727            }
728            return this;
729        },
730        // Queue a removal timer.
731        queueRemove: function () {
732            var that = this;
733            // Cancel any current removal timer.
734            this.cancelRemove();
735            this.timer = window.setTimeout(function () {
736                that.remove(true);
737            }, (isNaN(this.options.delay) ? 0 : this.options.delay));
738            return this;
739        }
740    });
741    // These functions affect all notices.
742    $.extend(PNotify, {
743        // This holds all the notices.
744        notices: [],
745        removeAll: function () {
746            $.each(PNotify.notices, function () {
747                if (this.remove)
748                    this.remove();
749            });
750        },
751        positionAll: function (animate) {
752            // This timer is used for queueing this function so it doesn't run
753            // repeatedly.
754            if (timer)
755                clearTimeout(timer);
756            timer = null;
757            // Reset the next position data.
758            $.each(PNotify.notices, function () {
759                var s = this.options.stack;
760                if (!s) return;
761                s.nextpos1 = s.firstpos1;
762                s.nextpos2 = s.firstpos2;
763                s.addpos2 = 0;
764                s.animation = animate;
765            });
766            $.each(PNotify.notices, function () {
767                this.position();
768            });
769        },
770        styling: {
771            jqueryui: {
772                container: "ui-widget ui-widget-content ui-corner-all",
773                notice: "ui-state-highlight",
774                // (The actual jQUI notice icon looks terrible.)
775                notice_icon: "ui-icon ui-icon-info",
776                info: "",
777                info_icon: "ui-icon ui-icon-info",
778                success: "ui-state-default",
779                success_icon: "ui-icon ui-icon-circle-check",
780                error: "ui-state-error",
781                error_icon: "ui-icon ui-icon-alert"
782            },
783            bootstrap2: {
784                container: "alert",
785                notice: "",
786                notice_icon: "icon-exclamation-sign",
787                info: "alert-info",
788                info_icon: "icon-info-sign",
789                success: "alert-success",
790                success_icon: "icon-ok-sign",
791                error: "alert-error",
792                error_icon: "icon-warning-sign"
793            },
794            bootstrap3: {
795                container: "alert",
796                notice: "alert-default",
797                notice_icon: "glyphicon glyphicon-exclamation-sign",
798                error: "alert-danger",
799                error_icon: "glyphicon glyphicon-warning-sign",
800                primary: "alert-primary",
801                primary_icon: "glyphicon glyphicon-exclamation-sign",
802                info: "alert-info",
803                info_icon: "glyphicon glyphicon-info-sign",
804                success: "alert-success",
805                success_icon: "glyphicon glyphicon-ok-sign",
806                warning: "alert-warning",
807                warning_icon: "glyphicon glyphicon-ok-sign",
808                danger: "alert-danger",
809                danger_icon: "glyphicon glyphicon-warning-sign",
810                alert: "alert-alert",
811                alert_icon: "glyphicon glyphicon-warning-sign",
812                system: "alert-system",
813                system_icon: "glyphicon glyphicon-warning-sign",
814                dark: "alert-dark",
815                dark_icon: "glyphicon glyphicon-warning-sign",
816            }
817        }
818    });
819    /*
820     * uses icons from http://fontawesome.io/
821     * version 4.0.3
822     */
823    PNotify.styling.fontawesome = $.extend({}, PNotify.styling.bootstrap3);
824    $.extend(PNotify.styling.fontawesome, {
825        notice_icon: "fa fa-exclamation-circle",
826        error_icon: "fa fa-warning",
827        primary_icon: "fa fa-info",
828        info_icon: "fa fa-info",
829        success_icon: "fa fa-check",
830        warning_icon: "fa fa-check",
831        danger_icon: "fa fa-info",
832        alert_icon: "fa fa-check",
833        system_icon: "fa fa-warning",
834        dark_icon: "fa fa-warning",
835    });
836
837    if (document.body)
838        do_when_ready();
839    else
840        $(do_when_ready);
841    return PNotify;
842}));
843// Buttons
844// Uses AMD or browser globals for jQuery.
845(function (factory) {
846    if (typeof define === 'function' && define.amd) {
847        // AMD. Register as a module.
848        define('pnotify.buttons', ['jquery', 'pnotify'], factory);
849    } else {
850        // Browser globals
851        factory(jQuery, PNotify);
852    }
853}(function ($, PNotify) {
854    PNotify.prototype.options.buttons = {
855        // Provide a button for the user to manually close the notice.
856        closer: true,
857        // Only show the closer button on hover.
858        closer_hover: true,
859        // Provide a button for the user to manually stick the notice.
860        sticker: true,
861        // Only show the sticker button on hover.
862        sticker_hover: true,
863        // The various displayed text, helps facilitating internationalization.
864        labels: {
865            close: "Close",
866            stick: "Stick"
867        }
868    };
869    PNotify.prototype.modules.buttons = {
870        // This lets us update the options available in the closures.
871        myOptions: null,
872
873        closer: null,
874        sticker: null,
875
876        init: function (notice, options) {
877            var that = this;
878            this.myOptions = options;
879            notice.elem.on({
880                "mouseenter": function (e) {
881                    // Show the buttons.
882                    if (that.myOptions.sticker && !(notice.options.nonblock && notice.options.nonblock.nonblock)) that.sticker.trigger("pnotify_icon").css("visibility", "visible");
883                    if (that.myOptions.closer && !(notice.options.nonblock && notice.options.nonblock.nonblock)) that.closer.css("visibility", "visible");
884                },
885                "mouseleave": function (e) {
886                    // Hide the buttons.
887                    if (that.myOptions.sticker_hover)
888                        that.sticker.css("visibility", "hidden");
889                    if (that.myOptions.closer_hover)
890                        that.closer.css("visibility", "hidden");
891                }
892            });
893
894            // Provide a button to stick the notice.
895            this.sticker = $("<div />", {
896                "class": "ui-pnotify-sticker",
897                "css": {"cursor": "pointer", "visibility": options.sticker_hover ? "hidden" : "visible"},
898                "click": function () {
899                    notice.options.hide = !notice.options.hide;
900                    if (notice.options.hide)
901                        notice.queueRemove();
902                    else
903                        notice.cancelRemove();
904                    $(this).trigger("pnotify_icon");
905                }
906            })
907                .bind("pnotify_icon", function () {
908                    $(this).children().removeClass(notice.styles.pin_up + " " + notice.styles.pin_down).addClass(notice.options.hide ? notice.styles.pin_up : notice.styles.pin_down);
909                })
910                .append($("<span />", {"class": notice.styles.pin_up, "title": options.labels.stick}))
911                .prependTo(notice.container);
912            if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock))
913                this.sticker.css("display", "none");
914
915            // Provide a button to close the notice.
916            this.closer = $("<div />", {
917                "class": "ui-pnotify-closer",
918                "css": {"cursor": "pointer", "visibility": options.closer_hover ? "hidden" : "visible"},
919                "click": function () {
920                    notice.remove(false);
921                    that.sticker.css("visibility", "hidden");
922                    that.closer.css("visibility", "hidden");
923                }
924            })
925                .append($("<span />", {"class": notice.styles.closer, "title": options.labels.close}))
926                .prependTo(notice.container);
927            if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock))
928                this.closer.css("display", "none");
929        },
930        update: function (notice, options) {
931            this.myOptions = options;
932            // Update the sticker and closer buttons.
933            if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock))
934                this.closer.css("display", "none");
935            else if (options.closer)
936                this.closer.css("display", "block");
937            if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock))
938                this.sticker.css("display", "none");
939            else if (options.sticker)
940                this.sticker.css("display", "block");
941            // Update the sticker icon.
942            this.sticker.trigger("pnotify_icon");
943            // Update the hover status of the buttons.
944            if (options.sticker_hover)
945                this.sticker.css("visibility", "hidden");
946            else if (!(notice.options.nonblock && notice.options.nonblock.nonblock))
947                this.sticker.css("visibility", "visible");
948            if (options.closer_hover)
949                this.closer.css("visibility", "hidden");
950            else if (!(notice.options.nonblock && notice.options.nonblock.nonblock))
951                this.closer.css("visibility", "visible");
952        }
953    };
954    $.extend(PNotify.styling.jqueryui, {
955        closer: "ui-icon ui-icon-close",
956        pin_up: "ui-icon ui-icon-pin-w",
957        pin_down: "ui-icon ui-icon-pin-s"
958    });
959    $.extend(PNotify.styling.bootstrap2, {
960        closer: "icon-remove",
961        pin_up: "icon-pause",
962        pin_down: "icon-play"
963    });
964    $.extend(PNotify.styling.bootstrap3, {
965        closer: "glyphicon glyphicon-remove",
966        pin_up: "glyphicon glyphicon-pause",
967        pin_down: "glyphicon glyphicon-play"
968    });
969    $.extend(PNotify.styling.fontawesome, {
970        closer: "fa fa-times",
971        pin_up: "fa fa-pause",
972        pin_down: "fa fa-play"
973    });
974}));
975// Confirm
976// Uses AMD or browser globals for jQuery.
977(function (factory) {
978    if (typeof define === 'function' && define.amd) {
979        // AMD. Register as a module.
980        define('pnotify.confirm', ['jquery', 'pnotify'], factory);
981    } else {
982        // Browser globals
983        factory(jQuery, PNotify);
984    }
985}(function ($, PNotify) {
986    PNotify.prototype.options.confirm = {
987        // Make a confirmation box.
988        confirm: false,
989        // Make a prompt.
990        prompt: false,
991        // Classes to add to the input element of the prompt.
992        prompt_class: "",
993        // The default value of the prompt.
994        prompt_default: "",
995        // Whether the prompt should accept multiple lines of text.
996        prompt_multi_line: false,
997        // Where to align the buttons. (right, center, left, justify)
998        align: "right",
999        // The buttons to display, and their callbacks.
1000        buttons: [
1001            {
1002                text: "Ok",
1003                addClass: "",
1004                // Whether to trigger this button when the user hits enter in a single line prompt.
1005                promptTrigger: true,
1006                click: function (notice, value) {
1007                    notice.remove();
1008                    notice.get().trigger("pnotify.confirm", [notice, value]);
1009                }
1010            },
1011            {
1012                text: "Cancel",
1013                addClass: "",
1014                click: function (notice) {
1015                    notice.remove();
1016                    notice.get().trigger("pnotify.cancel", notice);
1017                }
1018            }
1019        ]
1020    };
1021    PNotify.prototype.modules.confirm = {
1022        // The div that contains the buttons.
1023        container: null,
1024        // The input element of a prompt.
1025        prompt: null,
1026
1027        init: function (notice, options) {
1028            this.container = $('<div style="margin-top:5px;clear:both;" />').css('text-align', options.align).appendTo(notice.container);
1029
1030            if (options.confirm || options.prompt)
1031                this.makeDialog(notice, options);
1032            else
1033                this.container.hide();
1034        },
1035
1036        update: function (notice, options) {
1037            if (options.confirm) {
1038                this.makeDialog(notice, options);
1039                this.container.show();
1040            } else {
1041                this.container.hide().empty();
1042            }
1043        },
1044
1045        afterOpen: function (notice, options) {
1046            if (options.prompt)
1047                this.prompt.focus();
1048        },
1049
1050        makeDialog: function (notice, options) {
1051            var already = false, that = this, btn, elem;
1052            this.container.empty();
1053            if (options.prompt) {
1054                this.prompt = $('<' + (options.prompt_multi_line ? 'textarea rows="5"' : 'input type="text"') + ' style="margin-bottom:5px;clear:both;" />')
1055                    .addClass(notice.styles.input + ' ' + options.prompt_class)
1056                    .val(options.prompt_default)
1057                    .appendTo(this.container);
1058            }
1059            for (var i in options.buttons) {
1060                btn = options.buttons[i];
1061                if (already)
1062                    this.container.append(' ');
1063                else
1064                    already = true;
1065                elem = $('<button type="button" />')
1066                    .addClass(notice.styles.btn + ' ' + btn.addClass)
1067                    .text(btn.text)
1068                    .appendTo(this.container)
1069                    .on("click", (function (btn) {
1070                        return function () {
1071                            if (typeof btn.click == "function") {
1072                                btn.click(notice, options.prompt ? that.prompt.val() : null);
1073                            }
1074                        }
1075                    })(btn));
1076                if (options.prompt && !options.prompt_multi_line && btn.promptTrigger)
1077                    this.prompt.keypress((function (elem) {
1078                        return function (e) {
1079                            if (e.keyCode == 13)
1080                                elem.click();
1081                        }
1082                    })(elem));
1083                if (notice.styles.text) {
1084                    elem.wrapInner('<span class="' + notice.styles.text + '"></span>');
1085                }
1086                if (notice.styles.btnhover) {
1087                    elem.hover((function (elem) {
1088                        return function () {
1089                            elem.addClass(notice.styles.btnhover);
1090                        }
1091                    })(elem), (function (elem) {
1092                        return function () {
1093                            elem.removeClass(notice.styles.btnhover);
1094                        }
1095                    })(elem));
1096                }
1097                if (notice.styles.btnactive) {
1098                    elem.on("mousedown", (function (elem) {
1099                        return function () {
1100                            elem.addClass(notice.styles.btnactive);
1101                        }
1102                    })(elem)).on("mouseup", (function (elem) {
1103                        return function () {
1104                            elem.removeClass(notice.styles.btnactive);
1105                        }
1106                    })(elem));
1107                }
1108                if (notice.styles.btnfocus) {
1109                    elem.on("focus", (function (elem) {
1110                        return function () {
1111                            elem.addClass(notice.styles.btnfocus);
1112                        }
1113                    })(elem)).on("blur", (function (elem) {
1114                        return function () {
1115                            elem.removeClass(notice.styles.btnfocus);
1116                        }
1117                    })(elem));
1118                }
1119            }
1120        }
1121    };
1122    $.extend(PNotify.styling.jqueryui, {
1123        btn: "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only",
1124        btnhover: "ui-state-hover",
1125        btnactive: "ui-state-active",
1126        btnfocus: "ui-state-focus",
1127        input: "",
1128        text: "ui-button-text"
1129    });
1130    $.extend(PNotify.styling.bootstrap2, {
1131        btn: "btn",
1132        input: ""
1133    });
1134    $.extend(PNotify.styling.bootstrap3, {
1135        btn: "btn btn-default",
1136        input: "form-control"
1137    });
1138    $.extend(PNotify.styling.fontawesome, {
1139        btn: "btn btn-default",
1140        input: "form-control"
1141    });
1142}));
1143// Desktop
1144// Uses AMD or browser globals for jQuery.
1145(function (factory) {
1146    if (typeof define === 'function' && define.amd) {
1147        // AMD. Register as a module.
1148        define('pnotify.desktop', ['jquery', 'pnotify'], factory);
1149    } else {
1150        // Browser globals
1151        factory(jQuery, PNotify);
1152    }
1153}(function ($, PNotify) {
1154    var permission;
1155    var notify = function (title, options) {
1156        // Memoize based on feature detection.
1157        if ("Notification" in window) {
1158            notify = function (title, options) {
1159                return new Notification(title, options);
1160            };
1161        } else if ("mozNotification" in navigator) {
1162            notify = function (title, options) {
1163                // Gecko < 22
1164                return navigator.mozNotification
1165                    .createNotification(title, options.body, options.icon)
1166                    .show();
1167            };
1168        } else if ("webkitNotifications" in window) {
1169            notify = function (title, options) {
1170                return window.webkitNotifications.createNotification(
1171                    options.icon,
1172                    title,
1173                    options.body
1174                );
1175            };
1176        } else {
1177            notify = function (title, options) {
1178                return null;
1179            };
1180        }
1181        return notify(title, options);
1182    };
1183
1184
1185    PNotify.prototype.options.desktop = {
1186        // Display the notification as a desktop notification.
1187        desktop: false,
1188        // The URL of the icon to display. If false, no icon will show. If null, a default icon will show.
1189        icon: null,
1190        // Using a tag lets you update an existing notice, or keep from duplicating notices between tabs.
1191        // If you leave tag null, one will be generated, facilitating the "update" function.
1192        // see: http://www.w3.org/TR/notifications/#tags-example
1193        tag: null
1194    };
1195    PNotify.prototype.modules.desktop = {
1196        tag: null,
1197        icon: null,
1198        genNotice: function (notice, options) {
1199            if (options.icon === null) {
1200                this.icon = "http://sciactive.com/pnotify/includes/desktop/" + notice.options.type + ".png";
1201            } else if (options.icon === false) {
1202                this.icon = null;
1203            } else {
1204                this.icon = options.icon;
1205            }
1206            if (this.tag === null || options.tag !== null) {
1207                this.tag = options.tag === null ? "PNotify-" + Math.round(Math.random() * 1000000) : options.tag;
1208            }
1209            notice.desktop = notify(notice.options.title, {
1210                icon: this.icon,
1211                body: notice.options.text,
1212                tag: this.tag
1213            });
1214            if (!("close" in notice.desktop)) {
1215                notice.desktop.close = function () {
1216                    notice.desktop.cancel();
1217                };
1218            }
1219            notice.desktop.onclick = function () {
1220                notice.elem.trigger("click");
1221            };
1222            notice.desktop.onclose = function () {
1223                if (notice.state !== "closing" && notice.state !== "closed") {
1224                    notice.remove();
1225                }
1226            };
1227        },
1228        init: function (notice, options) {
1229            if (!options.desktop)
1230                return;
1231            permission = PNotify.desktop.checkPermission();
1232            if (permission != 0)
1233                return;
1234            this.genNotice(notice, options);
1235        },
1236        update: function (notice, options, oldOpts) {
1237            if (permission != 0 || !options.desktop)
1238                return;
1239            this.genNotice(notice, options);
1240        },
1241        beforeOpen: function (notice, options) {
1242            if (permission != 0 || !options.desktop)
1243                return;
1244            notice.elem.css({'left': '-10000px', 'display': 'none'});
1245        },
1246        afterOpen: function (notice, options) {
1247            if (permission != 0 || !options.desktop)
1248                return;
1249            notice.elem.css({'left': '-10000px', 'display': 'none'});
1250            if ("show" in notice.desktop) {
1251                notice.desktop.show();
1252            }
1253        },
1254        beforeClose: function (notice, options) {
1255            if (permission != 0 || !options.desktop)
1256                return;
1257            notice.elem.css({'left': '-10000px', 'display': 'none'});
1258        },
1259        afterClose: function (notice, options) {
1260            if (permission != 0 || !options.desktop)
1261                return;
1262            notice.elem.css({'left': '-10000px', 'display': 'none'});
1263            notice.desktop.close();
1264        }
1265    };
1266    PNotify.desktop = {
1267        permission: function () {
1268            if (typeof Notification !== "undefined" && "requestPermission" in Notification) {
1269                Notification.requestPermission();
1270            } else if ("webkitNotifications" in window) {
1271                window.webkitNotifications.requestPermission();
1272            }
1273        },
1274        checkPermission: function () {
1275            if (typeof Notification !== "undefined" && "permission" in Notification) {
1276                return (Notification.permission == "granted" ? 0 : 1);
1277            } else if ("webkitNotifications" in window) {
1278                return window.webkitNotifications.checkPermission();
1279            } else {
1280                return 1;
1281            }
1282        }
1283    };
1284    permission = PNotify.desktop.checkPermission();
1285}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.