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.