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