PageSourceSearch

https://pwnable.xyz/static/js/plugins/bootstrap-notify.js

js pwnable.xyz collected 2026-09-25 19:44:06 UTC 15,612 bytes, 432 lines download raw bytes

vendor: 15,612 bytes, lines 1-432
1/*
2
3
4
5     Creative Tim Modifications
6
7     Lines: 238, 239 was changed from top: 5px to top: 50% and we added margin-top: -13px. In this way the close button will be aligned vertically
8     Line:222 - modified when the icon is set, we add the class "alert-with-icon", so there will be enough space for the icon.
9
10
11
12
13*/
14
15
16/*
17 * Project: Bootstrap Notify = v3.1.5
18 * Description: Turns standard Bootstrap alerts into "Growl-like" notifications.
19 * Author: Mouse0270 aka Robert McIntosh
20 * License: MIT License
21 * Website: https://github.com/mouse0270/bootstrap-growl
22 */
23
24/* global define:false, require: false, jQuery:false */
25
26(function(factory) {
27  if (typeof define === 'function' && define.amd) {
28    // AMD. Register as an anonymous module.
29    define(['jquery'], factory);
30  } else if (typeof exports === 'object') {
31    // Node/CommonJS
32    factory(require('jquery'));
33  } else {
34    // Browser globals
35    factory(jQuery);
36  }
37}(function($) {
38  // Create the defaults once
39  var defaults = {
40    element: 'body',
41    position: null,
42    type: "info",
43    allow_dismiss: true,
44    allow_duplicates: true,
45    newest_on_top: false,
46    showProgressbar: false,
47    placement: {
48      from: "top",
49      align: "right"
50    },
51    offset: 20,
52    spacing: 10,
53    z_index: 1060,
54    delay: 5000,
55    timer: 1000,
56    url_target: '_blank',
57    mouse_over: null,
58    animate: {
59      enter: 'animated fadeInDown',
60      exit: 'animated fadeOutUp'
61    },
62    onShow: null,
63    onShown: null,
64    onClose: null,
65    onClosed: null,
66    onClick: null,
67    icon_type: 'class',
68    template: '<div data-notify="container" class="col-xs-11 col-sm-4 alert alert-{0}" role="alert"><button type="button" aria-hidden="true" class="close" data-notify="dismiss"><i class="tim-icons icon-simple-remove"></i></button><span data-notify="icon"></span> <span data-notify="title">{1}</span> <span data-notify="message">{2}</span><div class="progress" data-notify="progressbar"><div class="progress-bar progress-bar-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div></div><a href="{3}" target="{4}" data-notify="url"></a></div>'
69  };
70
71  String.format = function() {
72    var args = arguments;
73    var str = arguments[0];
74    return str.replace(/(\{\{\d\}\}|\{\d\})/g, function(str) {
75      if (str.substring(0, 2) === "{{") return str;
76      var num = parseInt(str.match(/\d/)[0]);
77      return args[num + 1];
78    });
79  };
80
81  function isDuplicateNotification(notification) {
82    var isDupe = false;
83
84    $('[data-notify="container"]').each(function(i, el) {
85      var $el = $(el);
86      var title = $el.find('[data-notify="title"]').html().trim();
87      var message = $el.find('[data-notify="message"]').html().trim();
88
89      // The input string might be different than the actual parsed HTML string!
90      // (<br> vs <br /> for example)
91      // So we have to force-parse this as HTML here!
92      var isSameTitle = title === $("<div>" + notification.settings.content.title + "</div>").html().trim();
93      var isSameMsg = message === $("<div>" + notification.settings.content.message + "</div>").html().trim();
94      var isSameType = $el.hasClass('alert-' + notification.settings.type);
95
96      if (isSameTitle && isSameMsg && isSameType) {
97        //we found the dupe. Set the var and stop checking.
98        isDupe = true;
99      }
100      return !isDupe;
101    });
102
103    return isDupe;
104  }
105
106  function Notify(element, content, options) {
107    // Setup Content of Notify
108    var contentObj = {
109      content: {
110        message: typeof content === 'object' ? content.message : content,
111        title: content.title ? content.title : '',
112        icon: content.icon ? content.icon : '',
113        url: content.url ? content.url : '#',
114        target: content.target ? content.target : '-'
115      }
116    };
117
118    options = $.extend(true, {}, contentObj, options);
119    this.settings = $.extend(true, {}, defaults, options);
120    this._defaults = defaults;
121    if (this.settings.content.target === "-") {
122      this.settings.content.target = this.settings.url_target;
123    }
124    this.animations = {
125      start: 'webkitAnimationStart oanimationstart MSAnimationStart animationstart',
126      end: 'webkitAnimationEnd oanimationend MSAnimationEnd animationend'
127    };
128
129    if (typeof this.settings.offset === 'number') {
130      this.settings.offset = {
131        x: this.settings.offset,
132        y: this.settings.offset
133      };
134    }
135
136    //if duplicate messages are not allowed, then only continue if this new message is not a duplicate of one that it already showing
137    if (this.settings.allow_duplicates || (!this.settings.allow_duplicates && !isDuplicateNotification(this))) {
138      this.init();
139    }
140  }
141
142  $.extend(Notify.prototype, {
143    init: function() {
144      var self = this;
145
146      this.buildNotify();
147      if (this.settings.content.icon) {
148        this.setIcon();
149      }
150      if (this.settings.content.url != "#") {
151        this.styleURL();
152      }
153      this.styleDismiss();
154      this.placement();
155      this.bind();
156
157      this.notify = {
158        $ele: this.$ele,
159        update: function(command, update) {
160          var commands = {};
161          if (typeof command === "string") {
162            commands[command] = update;
163          } else {
164            commands = command;
165          }
166          for (var cmd in commands) {
167            switch (cmd) {
168              case "type":
169                this.$ele.removeClass('alert-' + self.settings.type);
170                this.$ele.find('[data-notify="progressbar"] > .progress-bar').removeClass('progress-bar-' + self.settings.type);
171                self.settings.type = commands[cmd];
172                this.$ele.addClass('alert-' + commands[cmd]).find('[data-notify="progressbar"] > .progress-bar').addClass('progress-bar-' + commands[cmd]);
173                break;
174              case "icon":
175                var $icon = this.$ele.find('[data-notify="icon"]');
176                if (self.settings.icon_type.toLowerCase() === 'class') {
177                  $icon.removeClass(self.settings.content.icon).addClass(commands[cmd]);
178                } else {
179                  if (!$icon.is('img')) {
180                    $icon.find('img');
181                  }
182                  $icon.attr('src', commands[cmd]);
183                }
184                self.settings.content.icon = commands[command];
185                break;
186              case "progress":
187                var newDelay = self.settings.delay - (self.settings.delay * (commands[cmd] / 100));
188                this.$ele.data('notify-delay', newDelay);
189                this.$ele.find('[data-notify="progressbar"] > div').attr('aria-valuenow', commands[cmd]).css('width', commands[cmd] + '%');
190                break;
191              case "url":
192                this.$ele.find('[data-notify="url"]').attr('href', commands[cmd]);
193                break;
194              case "target":
195                this.$ele.find('[data-notify="url"]').attr('target', commands[cmd]);
196                break;
197              default:
198                this.$ele.find('[data-notify="' + cmd + '"]').html(commands[cmd]);
199            }
200          }
201          var posX = this.$ele.outerHeight() + parseInt(self.settings.spacing) + parseInt(self.settings.offset.y);
202          self.reposition(posX);
203        },
204        close: function() {
205          self.close();
206        }
207      };
208
209    },
210    buildNotify: function() {
211      var content = this.settings.content;
212      this.$ele = $(String.format(this.settings.template, this.settings.type, content.title, content.message, content.url, content.target));
213      this.$ele.attr('data-notify-position', this.settings.placement.from + '-' + this.settings.placement.align);
214      if (!this.settings.allow_dismiss) {
215        this.$ele.find('[data-notify="dismiss"]').css('display', 'none');
216      }
217      if ((this.settings.delay <= 0 && !this.settings.showProgressbar) || !this.settings.showProgressbar) {
218        this.$ele.find('[data-notify="progressbar"]').remove();
219      }
220    },
221    setIcon: function() {
222      this.$ele.addClass('alert-with-icon');
223
224      if (this.settings.icon_type.toLowerCase() === 'class') {
225        this.$ele.find('[data-notify="icon"]').addClass(this.settings.content.icon);
226      } else {
227        if (this.$ele.find('[data-notify="icon"]').is('img')) {
228          this.$ele.find('[data-notify="icon"]').attr('src', this.settings.content.icon);
229        } else {
230          this.$ele.find('[data-notify="icon"]').append('<img src="' + this.settings.content.icon + '" alt="Notify Icon" />');
231        }
232      }
233    },
234    styleDismiss: function() {
235      this.$ele.find('[data-notify="dismiss"]').css({
236        position: 'absolute',
237        right: '10px',
238        top: '50%',
239        marginTop: '-13px',
240        zIndex: this.settings.z_index + 2
241      });
242    },
243    styleURL: function() {
244      this.$ele.find('[data-notify="url"]').css({
245        backgroundImage: 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
246        height: '100%',
247        left: 0,
248        position: 'absolute',
249        top: 0,
250        width: '100%',
251        zIndex: this.settings.z_index + 1
252      });
253    },
254    placement: function() {
255      var self = this,
256        offsetAmt = this.settings.offset.y,
257        css = {
258          display: 'inline-block',
259          margin: '0px auto',
260          position: this.settings.position ? this.settings.position : (this.settings.element === 'body' ? 'fixed' : 'absolute'),
261          transition: 'all .5s ease-in-out',
262          zIndex: this.settings.z_index
263        },
264        hasAnimation = false,
265        settings = this.settings;
266
267      $('[data-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])').each(function() {
268        offsetAmt = Math.max(offsetAmt, parseInt($(this).css(settings.placement.from)) + parseInt($(this).outerHeight()) + parseInt(settings.spacing));
269      });
270      if (this.settings.newest_on_top === true) {
271        offsetAmt = this.settings.offset.y;
272      }
273      css[this.settings.placement.from] = offsetAmt + 'px';
274
275      switch (this.settings.placement.align) {
276        case "left":
277        case "right":
278          css[this.settings.placement.align] = this.settings.offset.x + 'px';
279          break;
280        case "center":
281          css.left = 0;
282          css.right = 0;
283          break;
284      }
285      this.$ele.css(css).addClass(this.settings.animate.enter);
286      $.each(Array('webkit-', 'moz-', 'o-', 'ms-', ''), function(index, prefix) {
287        self.$ele[0].style[prefix + 'AnimationIterationCount'] = 1;
288      });
289
290      $(this.settings.element).append(this.$ele);
291
292      if (this.settings.newest_on_top === true) {
293        offsetAmt = (parseInt(offsetAmt) + parseInt(this.settings.spacing)) + this.$ele.outerHeight();
294        this.reposition(offsetAmt);
295      }
296
297      if ($.isFunction(self.settings.onShow)) {
298        self.settings.onShow.call(this.$ele);
299      }
300
301      this.$ele.one(this.animations.start, function() {
302        hasAnimation = true;
303      }).one(this.animations.end, function() {
304        self.$ele.removeClass(self.settings.animate.enter);
305        if ($.isFunction(self.settings.onShown)) {
306          self.settings.onShown.call(this);
307        }
308      });
309
310      setTimeout(function() {
311        if (!hasAnimation) {
312          if ($.isFunction(self.settings.onShown)) {
313            self.settings.onShown.call(this);
314          }
315        }
316      }, 600);
317    },
318    bind: function() {
319      var self = this;
320
321      this.$ele.find('[data-notify="dismiss"]').on('click', function() {
322        self.close();
323      });
324
325      if ($.isFunction(self.settings.onClick)) {
326        this.$ele.on('click', function(event) {
327          if (event.target != self.$ele.find('[data-notify="dismiss"]')[0]) {
328            self.settings.onClick.call(this, event);
329          }
330        });
331      }
332
333      this.$ele.mouseover(function() {
334        $(this).data('data-hover', "true");
335      }).mouseout(function() {
336        $(this).data('data-hover', "false");
337      });
338      this.$ele.data('data-hover', "false");
339
340      if (this.settings.delay > 0) {
341        self.$ele.data('notify-delay', self.settings.delay);
342        var timer = setInterval(function() {
343          var delay = parseInt(self.$ele.data('notify-delay')) - self.settings.timer;
344          if ((self.$ele.data('data-hover') === 'false' && self.settings.mouse_over === "pause") || self.settings.mouse_over != "pause") {
345            var percent = ((self.settings.delay - delay) / self.settings.delay) * 100;
346            self.$ele.data('notify-delay', delay);
347            self.$ele.find('[data-notify="progressbar"] > div').attr('aria-valuenow', percent).css('width', percent + '%');
348          }
349          if (delay <= -(self.settings.timer)) {
350            clearInterval(timer);
351            self.close();
352          }
353        }, self.settings.timer);
354      }
355    },
356    close: function() {
357      var self = this,
358        posX = parseInt(this.$ele.css(this.settings.placement.from)),
359        hasAnimation = false;
360
361      this.$ele.attr('data-closing', 'true').addClass(this.settings.animate.exit);
362      self.reposition(posX);
363
364      if ($.isFunction(self.settings.onClose)) {
365        self.settings.onClose.call(this.$ele);
366      }
367
368      this.$ele.one(this.animations.start, function() {
369        hasAnimation = true;
370      }).one(this.animations.end, function() {
371        $(this).remove();
372        if ($.isFunction(self.settings.onClosed)) {
373          self.settings.onClosed.call(this);
374        }
375      });
376
377      setTimeout(function() {
378        if (!hasAnimation) {
379          self.$ele.remove();
380          if (self.settings.onClosed) {
381            self.settings.onClosed(self.$ele);
382          }
383        }
384      }, 600);
385    },
386    reposition: function(posX) {
387      var self = this,
388        notifies = '[data-notify-position="' + this.settings.placement.from + '-' + this.settings.placement.align + '"]:not([data-closing="true"])',
389        $elements = this.$ele.nextAll(notifies);
390      if (this.settings.newest_on_top === true) {
391        $elements = this.$ele.prevAll(notifies);
392      }
393      $elements.each(function() {
394        $(this).css(self.settings.placement.from, posX);
395        posX = (parseInt(posX) + parseInt(self.settings.spacing)) + $(this).outerHeight();
396      });
397    }
398  });
399
400  $.notify = function(content, options) {
401    var plugin = new Notify(this, content, options);
402    return plugin.notify;
403  };
404  $.notifyDefaults = function(options) {
405    defaults = $.extend(true, {}, defaults, options);
406    return defaults;
407  };
408
409  $.notifyClose = function(selector) {
410
411    if (typeof selector === "undefined" || selector === "all") {
412      $('[data-notify]').find('[data-notify="dismiss"]').trigger('click');
413    } else if (selector === 'success' || selector === 'info' || selector === 'warning' || selector === 'danger') {
414      $('.alert-' + selector + '[data-notify]').find('[data-notify="dismiss"]').trigger('click');
415    } else if (selector) {
416      $(selector + '[data-notify]').find('[data-notify="dismiss"]').trigger('click');
417    } else {
418      $('[data-notify-position="' + selector + '"]').find('[data-notify="dismiss"]').trigger('click');
419    }
420  };
421
422  $.notifyCloseExcept = function(selector) {
423
424    if (selector === 'success' || selector === 'info' || selector === 'warning' || selector === 'danger') {
425      $('[data-notify]').not('.alert-' + selector).find('[data-notify="dismiss"]').trigger('click');
426    } else {
427      $('[data-notify]').not(selector).find('[data-notify="dismiss"]').trigger('click');
428    }
429  };
430
431
432}));

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.