diff --git a/app/main/model/systemmodel.php b/app/main/model/systemmodel.php index a2d11ffe..32dda8b2 100644 --- a/app/main/model/systemmodel.php +++ b/app/main/model/systemmodel.php @@ -115,6 +115,11 @@ class SystemModel extends BasicModel { 'type' => Schema::DT_TIMESTAMP, 'default' => null ], + 'rallyPoke' => [ + 'type' => Schema::DT_BOOL, + 'nullable' => false, + 'default' => 0 + ], 'description' => [ 'type' => Schema::DT_VARCHAR512, 'nullable' => false, @@ -234,6 +239,7 @@ class SystemModel extends BasicModel { $systemData->locked = $this->locked; $systemData->rallyUpdated = strtotime($this->rallyUpdated); + $systemData->rallyPoke = $this->rallyPoke; $systemData->description = $this->description; $systemData->statics = $this->getStaticWormholeData(); diff --git a/js/app.js b/js/app.js index b998ee8a..9864489d 100644 --- a/js/app.js +++ b/js/app.js @@ -63,7 +63,7 @@ requirejs.config({ 'datatables.net-select': 'lib/datatables/Select-1.2.0/js/dataTables.select.min', // notification plugin - pnotify: 'lib/pnotify/pnotify.core', // v2.0.1 PNotify - notification core file + pnotify: 'lib/pnotify/pnotify', // v3.0.0 PNotify - notification core file - https://sciactive.com/pnotify/ 'pnotify.buttons': 'lib/pnotify/pnotify.buttons', // PNotify - buttons notification extension 'pnotify.confirm': 'lib/pnotify/pnotify.confirm', // PNotify - confirmation notification extension 'pnotify.nonblock': 'lib/pnotify/pnotify.nonblock', // PNotify - notification non-block extension (hover effect) diff --git a/js/app/map/map.js b/js/app/map/map.js index 80bee5bc..7ab83621 100644 --- a/js/app/map/map.js +++ b/js/app/map/map.js @@ -66,9 +66,6 @@ define([ systemDialogId: 'pf-system-dialog', // id for system dialog systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element - // local storage - mapLocalStoragePrefix: 'map_', // prefix for map local storage key - // system security classes systemSec: 'pf-system-sec', systemSecHigh: 'pf-system-sec-highSec', @@ -450,68 +447,6 @@ define([ system.addClass( statusClass ); }; - /** - * set or change rallyPoint for systems - * @param rallyUpdated - * @param options - * @returns {*} - */ - $.fn.setSystemRally = function(rallyUpdated, options){ - rallyUpdated = rallyUpdated || 0; - - var defaultOptions = { - poke: false, - hideNotification: false, - hideCounter: false, - }; - options = $.extend({}, defaultOptions, options); - - return this.each(function(){ - var system = $(this); - var rally = system.data('rallyUpdated') || 0; - - if(rallyUpdated !== rally){ - // rally status changed - if( !options.hideCounter ){ - system.getMapOverlay('timer').startMapUpdateCounter(); - } - - var rallyClass = MapUtil.getInfoForSystem('rally', 'class'); - - if(rallyUpdated > 0){ - // new rally point set - system.addClass( rallyClass ); - - if( !options.hideNotification ){ - var systemName = system.getSystemInfo( ['alias'] ); - - var notificationOptions = { - title: 'Rally Point', - text: 'System: ' + systemName, - type: 'success' - }; - - if(options.poke){ - // desktop poke - Util.showNotify(notificationOptions, {desktop: true, stack: 'barBottom'}); - }else{ - Util.showNotify(notificationOptions, {stack: 'barBottom'}); - } - } - }else{ - // rally point removed - system.removeClass( rallyClass ); - - if( !options.hideNotification ){ - Util.showNotify({title: 'Rally point removed', type: 'success'}); - } - } - } - - system.data('rallyUpdated', rallyUpdated); - }); - }; - /** * returns a new system or updates an existing system * @param map @@ -669,6 +604,7 @@ define([ // rally system system.setSystemRally(data.rallyUpdated, { + poke: data.rallyPoke || false, hideNotification: true, hideCounter: true, }); @@ -1904,7 +1840,7 @@ define([ } }, setRallyPoke: { - label: ' Set rally and poke', + label: ' set rally and poke', className: 'btn-primary', callback: function() { currentSystem.setSystemRally(1, { @@ -1914,7 +1850,7 @@ define([ } }, success: { - label: ' save', + label: ' set rally', className: 'btn-success', callback: function() { currentSystem.setSystemRally(1); @@ -2500,7 +2436,7 @@ define([ if(component.data('locked') === true){ activeOptions.push('lock_system'); } - if(component.data('rally') === true){ + if(component.data('rallyUpdated') > 0){ activeOptions.push('set_rally'); } } @@ -2623,7 +2559,6 @@ define([ * @returns {*} */ $.fn.getSystemInfo = function(info){ - var systemInfo = []; for(var i = 0; i < info.length; i++){ @@ -3118,6 +3053,7 @@ define([ }; systemData.locked = system.data('locked') ? 1 : 0; systemData.rallyUpdated = system.data('rallyUpdated') || 0; + systemData.rallyPoke = system.data('rallyPoke') ? 1 : 0; systemData.currentUser = system.data('currentUser'); // if user is currently in this system systemData.statics = system.data('statics'); systemData.updated = { @@ -3337,7 +3273,7 @@ define([ var mapWrapper = mapContainer.parents('.' + config.mapWrapperClass); // auto scroll map to previous position - var promiseStore = getMapData( mapContainer.data('id') ); + var promiseStore = MapUtil.getMapData( mapContainer.data('id') ); promiseStore.then(function(data) { // This code runs once the value has been loaded // from the offline store. @@ -3365,46 +3301,6 @@ define([ }); }; - /** - * get stored map data from client cache (IndexedDB) - * @param mapId - * @returns {*} promise - */ - var getMapData = function(mapId){ - if(mapId > 0){ - var mapStorageKey = config.mapLocalStoragePrefix + mapId; - return Util.localforage.getItem(mapStorageKey); - }else{ - console.error('Map local storage requires mapId > 0'); - } - }; - - /** - * store local map config to client cache (IndexedDB) - * @param mapId - * @param key - * @param value - */ - var storeMapData = function(mapId, key, value){ - if(mapId > 0){ - // get current map config - var mapStorageKey = config.mapLocalStoragePrefix + mapId; - Util.localforage.getItem(mapStorageKey).then(function(data) { - // This code runs once the value has been loaded - // from the offline store. - data = (data === null) ? {} : data; - // set/update value - data[key] = value; - Util.localforage.setItem(mapStorageKey, data); - }).catch(function(err) { - // This code runs if there were any errors - console.error('Map local storage can not be accessed!'); - }); - }else{ - console.error('Map local storage requires mapId > 0'); - } - }; - /** * init scrollbar for Map element */ @@ -3418,7 +3314,7 @@ define([ // scroll complete var mapElement = $(this).find('.' + config.mapClass); // store new map scrollOffset -> localDB - storeMapData( mapElement.data('id'), 'offsetX', Math.abs(this.mcs.left) ); + MapUtil.storeMapData( mapElement.data('id'), 'offsetX', Math.abs(this.mcs.left) ); }, onScrollStart: function(){ // hide all open xEditable fields diff --git a/js/app/map/util.js b/js/app/map/util.js index a52fd8f6..e41b0934 100644 --- a/js/app/map/util.js +++ b/js/app/map/util.js @@ -9,6 +9,11 @@ define([ ], function($, Init, Util) { 'use strict'; + var config = { + // local storage + mapLocalStoragePrefix: 'map_', // prefix for map local storage key + }; + /** * get all available map Types * optional they can be filtered by current access level of a user @@ -326,6 +331,171 @@ define([ return scopeInfo; }; + /** + * set or change rallyPoint for systems + * @param rallyUpdated + * @param options + * @returns {*} + */ + $.fn.setSystemRally = function(rallyUpdated, options){ + rallyUpdated = rallyUpdated || 0; + var rallyPoke = false; + + var defaultOptions = { + poke: false, + hideNotification: false, + hideCounter: false, + }; + options = $.extend({}, defaultOptions, options); + + return this.each(function(){ + var system = $(this); + var rally = system.data('rallyUpdated') || 0; + + if(rallyUpdated !== rally){ + // rally status changed + if( !options.hideCounter ){ + system.getMapOverlay('timer').startMapUpdateCounter(); + } + + var rallyClass = getInfoForSystem('rally', 'class'); + + if(rallyUpdated > 0){ + // new rally point set OR update system with rally information + + system.addClass( rallyClass ); + // rallyUpdated > 0 is required for poke! + rallyPoke = options.poke; + + var notificationOptions = { + title: 'Rally Point', + text: 'System: ' + system.data('name') + }; + + if(rallyUpdated === 1){ + // rally point not saved on DB + notificationOptions.type = 'success'; + Util.showNotify(notificationOptions); + }else if(options.poke){ + // rally saved AND poke option active + + // check if desktop notification was already send + var mapId = system.data('mapid'); + var systemId = system.data('id'); + var promiseStore = getMapData(mapId); + promiseStore.then(function(data) { + // This code runs once the value has been loaded + // from the offline store. + var rallyPokeData = {}; + + if( + data && + data.rallyPoke + ){ + // poke data exists + rallyPokeData = data.rallyPoke; + } + + if( + !rallyPokeData.hasOwnProperty(this.systemId) || // rally poke was not already send to client + rallyPokeData[this.systemId] !== rallyUpdated // already send to that system but in the past + ){ + rallyPokeData[this.systemId] = rallyUpdated; + storeMapData(this.mapId, 'rallyPoke', rallyPokeData); + + notificationOptions.type = 'info'; + Util.showNotify(notificationOptions, {desktop: true, stack: 'barBottom'}); + } + }.bind({ + mapId: mapId, + systemId: systemId, + rallyUpdated: rallyUpdated + })); + } + }else{ + // rally point removed + system.removeClass( rallyClass ); + + if( !options.hideNotification ){ + Util.showNotify({title: 'Rally point removed', type: 'success'}); + } + } + } + + system.data('rallyUpdated', rallyUpdated); + system.data('rallyPoke', rallyPoke); + }); + }; + + /** + * get stored map data from client cache (IndexedDB) + * @param mapId + * @returns {*} promise + */ + var getMapData = function(mapId){ + if(mapId > 0){ + var mapStorageKey = config.mapLocalStoragePrefix + mapId; + return Util.localforage.getItem(mapStorageKey); + }else{ + console.error('Map local storage requires mapId > 0'); + } + }; + + /** + * store local map config to client cache (IndexedDB) + * @param mapId + * @param key + * @param value + */ + var storeMapData = function(mapId, key, value){ + if(mapId > 0){ + // get current map config + var mapStorageKey = config.mapLocalStoragePrefix + mapId; + Util.localforage.getItem(mapStorageKey).then(function(data) { + // This code runs once the value has been loaded + // from the offline store. + data = (data === null) ? {} : data; + // set/update value + data[this.key] = this.value; + Util.localforage.setItem(this.mapStorageKey, data); + }.bind({ + key: key, + value: value, + mapStorageKey: mapStorageKey + })).catch(function(err) { + // This code runs if there were any errors + console.error('Map local storage can not be accessed!'); + }); + }else{ + console.error('storeMapData(): Local storage requires mapId > 0'); + } + }; + + /** + * delete local map configuration by key (IndexedDB) + * @param mapId + * @param key + */ + var deleteMapData = function(mapId, key){ + if(mapId > 0){ + // get current map config + var mapStorageKey = config.mapLocalStoragePrefix + mapId; + Util.localforage.getItem(mapStorageKey).then(function(data) { + if( + data && + data.hasOwnProperty(key) + ){ + delete data[key]; + Util.localforage.setItem(this.mapStorageKey, data); + } + }.bind({ + mapStorageKey: mapStorageKey + })); + }else{ + console.error('deleteMapData(): Local storage requires mapId > 0'); + } + }; + return { getMapTypes: getMapTypes, getMapScopes: getMapScopes, @@ -341,6 +511,9 @@ define([ checkForConnection: checkForConnection, getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope, setConnectionWHStatus: setConnectionWHStatus, - getScopeInfoForConnection: getScopeInfoForConnection + getScopeInfoForConnection: getScopeInfoForConnection, + getMapData: getMapData, + storeMapData: storeMapData, + deleteMapData: deleteMapData }; }); \ No newline at end of file diff --git a/js/app/module_map.js b/js/app/module_map.js index 404b188f..17f5a5b9 100644 --- a/js/app/module_map.js +++ b/js/app/module_map.js @@ -49,13 +49,10 @@ define([ /** * get all maps for a maps module - * @param mapModule * @returns {*} */ $.fn.getMaps = function(){ - var maps = $(this).find('.' + config.mapClass); - return maps; }; diff --git a/js/app/notification.js b/js/app/notification.js index 41490338..443858ab 100644 --- a/js/app/notification.js +++ b/js/app/notification.js @@ -17,31 +17,18 @@ define([ text: '', type: '', // 'info', 'success', error, 'warning' icon: false, - opacity: 0.8, styling: 'fontawesome', // 'fontawesome', 'bootstrap3', 'jqueryui' - animate_speed: 200, // effect animation - position_animate_speed: 100, // animation speed for notifications moving up/down + animate_speed: 'fast', // animation speed for notifications moving up/down hide: true, // close after few seconds delay: 5000, // visible time for notification in browser mouse_reset: true, // Reset the hide timer if the mouse moves over the notice. shadow: true, addclass: 'stack-bottomright', // class for display, must changed on stack different stacks width: '250px', - // animation settings - animation: { - 'effect_in': 'fade', - 'options_in': { - easing: 'linear' - }, - 'effect_out': 'fade', - 'options_out': { - easing: 'linear' - } - }, // nonblock extension parameter (click through notifications) nonblock: { - nonblock: true, - nonblock_opacity: 0.2 + nonblock: true, // change for enable + nonblock_opacity: 0.9 }, // desktop extension "Web Notifications" desktop: { @@ -64,42 +51,28 @@ define([ }, addclass: 'stack-bottomright', width: '250px', - opacity: 0.8 - }, - barTop: { - stack: { - dir1: 'down', - dir2: 'right', - push: 'top', - spacing1: 0, - spacing2: 0, - - }, - addclass: 'stack-bar-top', - width: '80%', - opacity: 1 }, barBottom: { stack: { dir1: 'up', dir2: 'right', - firstpos1: 30, + // context: $('body'), spacing1: 0, spacing2: 0 }, addclass: 'stack-bar-bottom', - width: '100%', - opacity: 1 + width: '70%', } }; /** * show a notification in browser and/or "Web Notifications" in OS * @param customConfig + * @param settings */ var showNotify = function(customConfig, settings){ - customConfig = $.extend({}, config, customConfig ); + customConfig = $.extend(true, {}, config, customConfig ); // desktop notification if( @@ -114,10 +87,6 @@ define([ // make browser tab blink startTabBlink(customConfig.title); - - }else{ - customConfig.delay = 5000; - customConfig.desktop.desktop = false; } // set notification stack @@ -128,11 +97,9 @@ define([ customConfig.stack = stack[settings.stack].stack; customConfig.addclass = stack[settings.stack].addclass; customConfig.width = stack[settings.stack].width; - customConfig.opacity = stack[settings.stack].opacity; }else{ customConfig.stack = stack.bottomRight.stack; customConfig.addclass = stack.bottomRight.addclass; - customConfig.opacity = stack.bottomRight.opacity; } switch(customConfig.type){ @@ -168,7 +135,6 @@ define([ * @param blinkTitle */ var startTabBlink = function(blinkTitle){ - var initBlink = (function(blinkTitle){ var currentTitle = document.title; @@ -195,10 +161,8 @@ define([ }( blinkTitle )); initBlink(); - }; - return { showNotify: showNotify, startTabBlink: startTabBlink diff --git a/js/lib/pnotify/pnotify.buttons.js b/js/lib/pnotify/pnotify.buttons.js new file mode 100644 index 00000000..27a97fd0 --- /dev/null +++ b/js/lib/pnotify/pnotify.buttons.js @@ -0,0 +1,176 @@ +// Buttons +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.buttons', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ + PNotify.prototype.options.buttons = { + // Provide a button for the user to manually close the notice. + closer: true, + // Only show the closer button on hover. + closer_hover: true, + // Provide a button for the user to manually stick the notice. + sticker: true, + // Only show the sticker button on hover. + sticker_hover: true, + // Show the buttons even when the nonblock module is in use. + show_on_nonblock: false, + // The various displayed text, helps facilitating internationalization. + labels: { + close: "Close", + stick: "Stick", + unstick: "Unstick" + }, + // The classes to use for button icons. Leave them null to use the classes from the styling you're using. + classes: { + closer: null, + pin_up: null, + pin_down: null + } + }; + PNotify.prototype.modules.buttons = { + closer: null, + sticker: null, + + init: function(notice, options){ + var that = this; + notice.elem.on({ + "mouseenter": function(e){ + // Show the buttons. + if (that.options.sticker && (!(notice.options.nonblock && notice.options.nonblock.nonblock) || that.options.show_on_nonblock)) { + that.sticker.trigger("pnotify:buttons:toggleStick").css("visibility", "visible"); + } + if (that.options.closer && (!(notice.options.nonblock && notice.options.nonblock.nonblock) || that.options.show_on_nonblock)) { + that.closer.css("visibility", "visible"); + } + }, + "mouseleave": function(e){ + // Hide the buttons. + if (that.options.sticker_hover) { + that.sticker.css("visibility", "hidden"); + } + if (that.options.closer_hover) { + that.closer.css("visibility", "hidden"); + } + } + }); + + // Provide a button to stick the notice. + this.sticker = $("
", { + "class": "ui-pnotify-sticker", + "aria-role": "button", + "aria-pressed": notice.options.hide ? "false" : "true", + "tabindex": "0", + "title": notice.options.hide ? options.labels.stick : options.labels.unstick, + "css": { + "cursor": "pointer", + "visibility": options.sticker_hover ? "hidden" : "visible" + }, + "click": function(){ + notice.options.hide = !notice.options.hide; + if (notice.options.hide) { + notice.queueRemove(); + } else { + notice.cancelRemove(); + } + $(this).trigger("pnotify:buttons:toggleStick"); + } + }) + .bind("pnotify:buttons:toggleStick", function(){ + var pin_up = that.options.classes.pin_up === null ? notice.styles.pin_up : that.options.classes.pin_up; + var pin_down = that.options.classes.pin_down === null ? notice.styles.pin_down : that.options.classes.pin_down; + $(this) + .attr("title", notice.options.hide ? that.options.labels.stick : that.options.labels.unstick) + .children() + .attr("class", "") + .addClass(notice.options.hide ? pin_up : pin_down) + .attr("aria-pressed", notice.options.hide ? "false" : "true"); + }) + .append("") + .trigger("pnotify:buttons:toggleStick") + .prependTo(notice.container); + if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.sticker.css("display", "none"); + } + + // Provide a button to close the notice. + this.closer = $("
", { + "class": "ui-pnotify-closer", + "aria-role": "button", + "tabindex": "0", + "title": options.labels.close, + "css": {"cursor": "pointer", "visibility": options.closer_hover ? "hidden" : "visible"}, + "click": function(){ + notice.remove(false); + that.sticker.css("visibility", "hidden"); + that.closer.css("visibility", "hidden"); + } + }) + .append($("", {"class": options.classes.closer === null ? notice.styles.closer : options.classes.closer})) + .prependTo(notice.container); + if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.closer.css("display", "none"); + } + }, + update: function(notice, options){ + // Update the sticker and closer buttons. + if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.closer.css("display", "none"); + } else if (options.closer) { + this.closer.css("display", "block"); + } + if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.sticker.css("display", "none"); + } else if (options.sticker) { + this.sticker.css("display", "block"); + } + // Update the sticker icon. + this.sticker.trigger("pnotify:buttons:toggleStick"); + // Update the close icon. + this.closer.find("span").attr("class", "").addClass(options.classes.closer === null ? notice.styles.closer : options.classes.closer); + // Update the hover status of the buttons. + if (options.sticker_hover) { + this.sticker.css("visibility", "hidden"); + } else if (!(notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.sticker.css("visibility", "visible"); + } + if (options.closer_hover) { + this.closer.css("visibility", "hidden"); + } else if (!(notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.closer.css("visibility", "visible"); + } + } + }; + $.extend(PNotify.styling.brighttheme, { + closer: "brighttheme-icon-closer", + pin_up: "brighttheme-icon-sticker", + pin_down: "brighttheme-icon-sticker brighttheme-icon-stuck" + }); + $.extend(PNotify.styling.jqueryui, { + closer: "ui-icon ui-icon-close", + pin_up: "ui-icon ui-icon-pin-w", + pin_down: "ui-icon ui-icon-pin-s" + }); + $.extend(PNotify.styling.bootstrap2, { + closer: "icon-remove", + pin_up: "icon-pause", + pin_down: "icon-play" + }); + $.extend(PNotify.styling.bootstrap3, { + closer: "glyphicon glyphicon-remove", + pin_up: "glyphicon glyphicon-pause", + pin_down: "glyphicon glyphicon-play" + }); + $.extend(PNotify.styling.fontawesome, { + closer: "fa fa-times", + pin_up: "fa fa-pause", + pin_down: "fa fa-play" + }); +})); diff --git a/js/lib/pnotify/pnotify.callbacks.js b/js/lib/pnotify/pnotify.callbacks.js index a1563a3a..e24b13c5 100644 --- a/js/lib/pnotify/pnotify.callbacks.js +++ b/js/lib/pnotify/pnotify.callbacks.js @@ -1,14 +1,16 @@ // Callbacks -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify.callbacks', ['jquery', 'pnotify'], factory); - } else { - // Browser globals - factory(jQuery, PNotify); - } -}(function($, PNotify){ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.callbacks', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ var _init = PNotify.prototype.init, _open = PNotify.prototype.open, _remove = PNotify.prototype.remove; diff --git a/js/lib/pnotify/pnotify.core.js b/js/lib/pnotify/pnotify.core.js deleted file mode 100644 index c54d93fe..00000000 --- a/js/lib/pnotify/pnotify.core.js +++ /dev/null @@ -1,778 +0,0 @@ -/* -PNotify 2.0.1 sciactive.com/pnotify/ -(C) 2014 Hunter Perrin -license GPL/LGPL/MPL -*/ -/* - * ====== PNotify ====== - * - * http://sciactive.com/pnotify/ - * - * Copyright 2009-2014 Hunter Perrin - * - * Triple licensed under the GPL, LGPL, and MPL. - * http://gnu.org/licenses/gpl.html - * http://gnu.org/licenses/lgpl.html - * http://mozilla.org/MPL/MPL-1.1.html - */ - -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify', ['jquery'], factory); - } else { - // Browser globals - factory(jQuery); - } -}(function($){ - var default_stack = { - dir1: "down", - dir2: "left", - push: "bottom", - spacing1: 25, - spacing2: 25, - context: $("body") - }; - var timer, // Position all timer. - body, - jwindow = $(window); - // Set global variables. - var do_when_ready = function(){ - body = $("body"); - PNotify.prototype.options.stack.context = body; - jwindow = $(window); - // Reposition the notices when the window resizes. - jwindow.bind('resize', function(){ - if (timer) - clearTimeout(timer); - timer = setTimeout(function(){ PNotify.positionAll(true) }, 10); - }); - }; - PNotify = function(options){ - this.parseOptions(options); - this.init(); - }; - $.extend(PNotify.prototype, { - // The current version of PNotify. - version: "2.0.1", - - // === Options === - - // Options defaults. - options: { - // The notice's title. - title: false, - // Whether to escape the content of the title. (Not allow HTML.) - title_escape: false, - // The notice's text. - text: false, - // Whether to escape the content of the text. (Not allow HTML.) - text_escape: false, - // What styling classes to use. (Can be either jqueryui or bootstrap.) - styling: "bootstrap3", - // Additional classes to be added to the notice. (For custom styling.) - addclass: "", - // Class to be added to the notice for corner styling. - cornerclass: "", - // Display the notice when it is created. - auto_display: true, - // Width of the notice. - width: "300px", - // Minimum height of the notice. It will expand to fit content. - min_height: "16px", - // Type of the notice. "notice", "info", "success", or "error". - type: "notice", - // Set icon to true to use the default icon for the selected - // style/type, false for no icon, or a string for your own icon class. - icon: true, - // Opacity of the notice. - opacity: 1, - // The animation to use when displaying and hiding the notice. "none", - // "show", "fade", and "slide" are built in to jQuery. Others require jQuery - // UI. Use an object with effect_in and effect_out to use different effects. - animation: "fade", - // Speed at which the notice animates in and out. "slow", "def" or "normal", - // "fast" or number of milliseconds. - animate_speed: "slow", - // Specify a specific duration of position animation - position_animate_speed: 500, - // Display a drop shadow. - shadow: true, - // After a delay, remove the notice. - hide: true, - // Delay in milliseconds before the notice is removed. - delay: 8000, - // Reset the hide timer if the mouse moves over the notice. - mouse_reset: true, - // Remove the notice's elements from the DOM after it is removed. - remove: true, - // Change new lines to br tags. - insert_brs: true, - // Whether to remove notices from the global array. - destroy: true, - // The stack on which the notices will be placed. Also controls the - // direction the notices stack. - stack: default_stack - }, - - // === Modules === - - // This object holds all the PNotify modules. They are used to provide - // additional functionality. - modules: {}, - // This runs an event on all the modules. - runModules: function(event, arg){ - var curArg; - for (var module in this.modules) { - curArg = ((typeof arg === "object" && module in arg) ? arg[module] : arg); - if (typeof this.modules[module][event] === 'function') - this.modules[module][event](this, typeof this.options[module] === 'object' ? this.options[module] : {}, curArg); - } - }, - - // === Class Variables === - - state: "initializing", // The state can be "initializing", "opening", "open", "closing", and "closed". - timer: null, // Auto close timer. - styles: null, - elem: null, - container: null, - title_container: null, - text_container: null, - animating: false, // Stores what is currently being animated (in or out). - timerHide: false, // Stores whether the notice was hidden by a timer. - - // === Events === - - init: function(){ - var that = this; - - // First and foremost, we don't want our module objects all referencing the prototype. - this.modules = {}; - $.extend(true, this.modules, PNotify.prototype.modules); - - // Get our styling object. - if (typeof this.options.styling === "object") { - this.styles = this.options.styling; - } else { - this.styles = PNotify.styling[this.options.styling]; - } - - // Create our widget. - // Stop animation, reset the removal timer when the user mouses over. - this.elem = $("
", { - "class": "ui-pnotify "+this.options.addclass, - "css": {"display": "none"}, - "mouseenter": function(e){ - if (that.options.mouse_reset && that.animating === "out") { - if (!that.timerHide) - return; - that.cancelRemove(); - } - // Stop the close timer. - if (that.options.hide && that.options.mouse_reset) that.cancelRemove(); - }, - "mouseleave": function(e){ - // Start the close timer. - if (that.options.hide && that.options.mouse_reset) that.queueRemove(); - PNotify.positionAll(); - } - }); - // Create a container for the notice contents. - this.container = $("
", {"class": this.styles.container+" ui-pnotify-container "+(this.options.type === "error" ? this.styles.error : (this.options.type === "info" ? this.styles.info : (this.options.type === "success" ? this.styles.success : this.styles.notice)))}) - .appendTo(this.elem); - if (this.options.cornerclass !== "") - this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass); - // Create a drop shadow. - if (this.options.shadow) - this.container.addClass("ui-pnotify-shadow"); - - - // Add the appropriate icon. - if (this.options.icon !== false) { - $("
", {"class": "ui-pnotify-icon"}) - .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) - .prependTo(this.container); - } - - // Add a title. - this.title_container = $("

", { - "class": "ui-pnotify-title" - }) - .appendTo(this.container); - if (this.options.title === false) - this.title_container.hide(); - else if (this.options.title_escape) - this.title_container.text(this.options.title); - else - this.title_container.html(this.options.title); - - // Add text. - this.text_container = $("
", { - "class": "ui-pnotify-text" - }) - .appendTo(this.container); - if (this.options.text === false) - this.text_container.hide(); - else if (this.options.text_escape) - this.text_container.text(this.options.text); - else - this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); - - // Set width and min height. - if (typeof this.options.width === "string") - this.elem.css("width", this.options.width); - if (typeof this.options.min_height === "string") - this.container.css("min-height", this.options.min_height); - - - // Add the notice to the notice array. - if (this.options.stack.push === "top") - PNotify.notices = $.merge([this], PNotify.notices); - else - PNotify.notices = $.merge(PNotify.notices, [this]); - // Now position all the notices if they are to push to the top. - if (this.options.stack.push === "top") - this.queuePosition(false, 1); - - - - - // Mark the stack so it won't animate the new notice. - this.options.stack.animation = false; - - // Run the modules. - this.runModules('init'); - - // Display the notice. - if (this.options.auto_display) - this.open(); - return this; - }, - - // This function is for updating the notice. - update: function(options){ - // Save old options. - var oldOpts = this.options; - // Then update to the new options. - this.parseOptions(oldOpts, options); - // Update the corner class. - if (this.options.cornerclass !== oldOpts.cornerclass) - this.container.removeClass("ui-corner-all "+oldOpts.cornerclass).addClass(this.options.cornerclass); - // Update the shadow. - if (this.options.shadow !== oldOpts.shadow) { - if (this.options.shadow) - this.container.addClass("ui-pnotify-shadow"); - else - this.container.removeClass("ui-pnotify-shadow"); - } - // Update the additional classes. - if (this.options.addclass === false) - this.elem.removeClass(oldOpts.addclass); - else if (this.options.addclass !== oldOpts.addclass) - this.elem.removeClass(oldOpts.addclass).addClass(this.options.addclass); - // Update the title. - if (this.options.title === false) - this.title_container.slideUp("fast"); - else if (this.options.title !== oldOpts.title) { - if (this.options.title_escape) - this.title_container.text(this.options.title); - else - this.title_container.html(this.options.title); - if (oldOpts.title === false) - this.title_container.slideDown(200) - } - // Update the text. - if (this.options.text === false) { - this.text_container.slideUp("fast"); - } else if (this.options.text !== oldOpts.text) { - if (this.options.text_escape) - this.text_container.text(this.options.text); - else - this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); - if (oldOpts.text === false) - this.text_container.slideDown(200) - } - // Change the notice type. - if (this.options.type !== oldOpts.type) - this.container.removeClass( - this.styles.error+" "+this.styles.notice+" "+this.styles.success+" "+this.styles.info - ).addClass(this.options.type === "error" ? - this.styles.error : - (this.options.type === "info" ? - this.styles.info : - (this.options.type === "success" ? - this.styles.success : - this.styles.notice - ) - ) - ); - if (this.options.icon !== oldOpts.icon || (this.options.icon === true && this.options.type !== oldOpts.type)) { - // Remove any old icon. - this.container.find("div.ui-pnotify-icon").remove(); - if (this.options.icon !== false) { - // Build the new icon. - $("
", {"class": "ui-pnotify-icon"}) - .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) - .prependTo(this.container); - } - } - // Update the width. - if (this.options.width !== oldOpts.width) - this.elem.animate({width: this.options.width}); - // Update the minimum height. - if (this.options.min_height !== oldOpts.min_height) - this.container.animate({minHeight: this.options.min_height}); - // Update the opacity. - if (this.options.opacity !== oldOpts.opacity) - this.elem.fadeTo(this.options.animate_speed, this.options.opacity); - // Update the timed hiding. - if (!this.options.hide) - this.cancelRemove(); - else if (!oldOpts.hide) - this.queueRemove(); - this.queuePosition(true); - - // Run the modules. - this.runModules('update', oldOpts); - return this; - }, - - // Display the notice. - open: function(){ - this.state = "opening"; - // Run the modules. - this.runModules('beforeOpen'); - - var that = this; - // If the notice is not in the DOM, append it. - if (!this.elem.parent().length) - this.elem.appendTo(this.options.stack.context ? this.options.stack.context : body); - // Try to put it in the right position. - if (this.options.stack.push !== "top") - this.position(true); - // First show it, then set its opacity, then hide it. - if (this.options.animation === "fade" || this.options.animation.effect_in === "fade") { - // If it's fading in, it should start at 0. - this.elem.show().fadeTo(0, 0).hide(); - } else { - // Or else it should be set to the opacity. - if (this.options.opacity !== 1) - this.elem.show().fadeTo(0, this.options.opacity).hide(); - } - this.animateIn(function(){ - that.queuePosition(true); - - // Now set it to hide. - if (that.options.hide) - that.queueRemove(); - - that.state = "open"; - - // Run the modules. - that.runModules('afterOpen'); - }); - - return this; - }, - - // Remove the notice. - remove: function(timer_hide) { - this.state = "closing"; - this.timerHide = !!timer_hide; // Make sure it's a boolean. - // Run the modules. - this.runModules('beforeClose'); - - var that = this; - if (this.timer) { - window.clearTimeout(this.timer); - this.timer = null; - } - this.animateOut(function(){ - that.state = "closed"; - // Run the modules. - that.runModules('afterClose'); - that.queuePosition(true); - // If we're supposed to remove the notice from the DOM, do it. - if (that.options.remove) - that.elem.detach(); - // Run the modules. - that.runModules('beforeDestroy'); - // Remove object from PNotify.notices to prevent memory leak (issue #49) - // unless destroy is off - if (that.options.destroy) { - if (PNotify.notices !== null) { - var idx = $.inArray(that,PNotify.notices); - if (idx !== -1) { - PNotify.notices.splice(idx,1); - } - } - } - // Run the modules. - that.runModules('afterDestroy'); - }); - - return this; - }, - - // === Class Methods === - - // Get the DOM element. - get: function(){ return this.elem; }, - - // Put all the options in the right places. - parseOptions: function(options, moreOptions){ - this.options = $.extend(true, {}, PNotify.prototype.options); - // This is the only thing that *should* be copied by reference. - this.options.stack = PNotify.prototype.options.stack; - var optArray = [options, moreOptions], curOpts; - for (var curIndex in optArray) { - curOpts = optArray[curIndex]; - if (typeof curOpts == "undefined") - break; - if (typeof curOpts !== 'object') { - this.options.text = curOpts; - } else { - for (var option in curOpts) { - if (this.modules[option]) { - // Avoid overwriting module defaults. - $.extend(true, this.options[option], curOpts[option]); - } else { - this.options[option] = curOpts[option]; - } - } - } - } - }, - - // Animate the notice in. - animateIn: function(callback){ - // Declare that the notice is animating in. (Or has completed animating in.) - this.animating = "in"; - var animation; - if (typeof this.options.animation.effect_in !== "undefined") - animation = this.options.animation.effect_in; - else - animation = this.options.animation; - if (animation === "none") { - this.elem.show(); - callback(); - } else if (animation === "show") - this.elem.show(this.options.animate_speed, callback); - else if (animation === "fade") - this.elem.show().fadeTo(this.options.animate_speed, this.options.opacity, callback); - else if (animation === "slide") - this.elem.slideDown(this.options.animate_speed, callback); - else if (typeof animation === "function") - animation("in", callback, this.elem); - else - this.elem.show(animation, (typeof this.options.animation.options_in === "object" ? this.options.animation.options_in : {}), this.options.animate_speed, callback); - if (this.elem.parent().hasClass('ui-effects-wrapper')) - this.elem.parent().css({"position": "fixed", "overflow": "visible"}); - if (animation !== "slide") - this.elem.css("overflow", "visible"); - this.container.css("overflow", "hidden"); - }, - - // Animate the notice out. - animateOut: function(callback){ - // Declare that the notice is animating out. (Or has completed animating out.) - this.animating = "out"; - var animation; - if (typeof this.options.animation.effect_out !== "undefined") - animation = this.options.animation.effect_out; - else - animation = this.options.animation; - if (animation === "none") { - this.elem.hide(); - callback(); - } else if (animation === "show") - this.elem.hide(this.options.animate_speed, callback); - else if (animation === "fade") - this.elem.fadeOut(this.options.animate_speed, callback); - else if (animation === "slide") - this.elem.slideUp(this.options.animate_speed, callback); - else if (typeof animation === "function") - animation("out", callback, this.elem); - else - this.elem.hide(animation, (typeof this.options.animation.options_out === "object" ? this.options.animation.options_out : {}), this.options.animate_speed, callback); - if (this.elem.parent().hasClass('ui-effects-wrapper')) - this.elem.parent().css({"position": "fixed", "overflow": "visible"}); - if (animation !== "slide") - this.elem.css("overflow", "visible"); - this.container.css("overflow", "hidden"); - }, - - // Position the notice. dont_skip_hidden causes the notice to - // position even if it's not visible. - position: function(dontSkipHidden){ - // Get the notice's stack. - var s = this.options.stack, - e = this.elem; - if (e.parent().hasClass('ui-effects-wrapper')) - e = this.elem.css({"left": "0", "top": "0", "right": "0", "bottom": "0"}).parent(); - if (typeof s.context === "undefined") - s.context = body; - if (!s) return; - if (typeof s.nextpos1 !== "number") - s.nextpos1 = s.firstpos1; - if (typeof s.nextpos2 !== "number") - s.nextpos2 = s.firstpos2; - if (typeof s.addpos2 !== "number") - s.addpos2 = 0; - var hidden = e.css("display") === "none"; - // Skip this notice if it's not shown. - if (!hidden || dontSkipHidden) { - var curpos1, curpos2; - // Store what will need to be animated. - var animate = {}; - // Calculate the current pos1 value. - var csspos1; - switch (s.dir1) { - case "down": - csspos1 = "top"; - break; - case "up": - csspos1 = "bottom"; - break; - case "left": - csspos1 = "right"; - break; - case "right": - csspos1 = "left"; - break; - } - curpos1 = parseInt(e.css(csspos1).replace(/(?:\..*|[^0-9.])/g, '')); - if (isNaN(curpos1)) - curpos1 = 0; - // Remember the first pos1, so the first visible notice goes there. - if (typeof s.firstpos1 === "undefined" && !hidden) { - s.firstpos1 = curpos1; - s.nextpos1 = s.firstpos1; - } - // Calculate the current pos2 value. - var csspos2; - switch (s.dir2) { - case "down": - csspos2 = "top"; - break; - case "up": - csspos2 = "bottom"; - break; - case "left": - csspos2 = "right"; - break; - case "right": - csspos2 = "left"; - break; - } - curpos2 = parseInt(e.css(csspos2).replace(/(?:\..*|[^0-9.])/g, '')); - if (isNaN(curpos2)) - curpos2 = 0; - // Remember the first pos2, so the first visible notice goes there. - if (typeof s.firstpos2 === "undefined" && !hidden) { - s.firstpos2 = curpos2; - s.nextpos2 = s.firstpos2; - } - // Check that it's not beyond the viewport edge. - if ((s.dir1 === "down" && s.nextpos1 + e.height() > (s.context.is(body) ? jwindow.height() : s.context.prop('scrollHeight')) ) || - (s.dir1 === "up" && s.nextpos1 + e.height() > (s.context.is(body) ? jwindow.height() : s.context.prop('scrollHeight')) ) || - (s.dir1 === "left" && s.nextpos1 + e.width() > (s.context.is(body) ? jwindow.width() : s.context.prop('scrollWidth')) ) || - (s.dir1 === "right" && s.nextpos1 + e.width() > (s.context.is(body) ? jwindow.width() : s.context.prop('scrollWidth')) ) ) { - // If it is, it needs to go back to the first pos1, and over on pos2. - s.nextpos1 = s.firstpos1; - s.nextpos2 += s.addpos2 + (typeof s.spacing2 === "undefined" ? 25 : s.spacing2); - s.addpos2 = 0; - } - // Animate if we're moving on dir2. - if (s.animation && s.nextpos2 < curpos2) { - switch (s.dir2) { - case "down": - animate.top = s.nextpos2+"px"; - break; - case "up": - animate.bottom = s.nextpos2+"px"; - break; - case "left": - animate.right = s.nextpos2+"px"; - break; - case "right": - animate.left = s.nextpos2+"px"; - break; - } - } else { - if(typeof s.nextpos2 === "number") - e.css(csspos2, s.nextpos2+"px"); - } - // Keep track of the widest/tallest notice in the column/row, so we can push the next column/row. - switch (s.dir2) { - case "down": - case "up": - if (e.outerHeight(true) > s.addpos2) - s.addpos2 = e.height(); - break; - case "left": - case "right": - if (e.outerWidth(true) > s.addpos2) - s.addpos2 = e.width(); - break; - } - // Move the notice on dir1. - if (typeof s.nextpos1 === "number") { - // Animate if we're moving toward the first pos. - if (s.animation && (curpos1 > s.nextpos1 || animate.top || animate.bottom || animate.right || animate.left)) { - switch (s.dir1) { - case "down": - animate.top = s.nextpos1+"px"; - break; - case "up": - animate.bottom = s.nextpos1+"px"; - break; - case "left": - animate.right = s.nextpos1+"px"; - break; - case "right": - animate.left = s.nextpos1+"px"; - break; - } - } else - e.css(csspos1, s.nextpos1+"px"); - } - // Run the animation. - if (animate.top || animate.bottom || animate.right || animate.left) - e.animate(animate, {duration: this.options.position_animate_speed, queue: false}); - // Calculate the next dir1 position. - switch (s.dir1) { - case "down": - case "up": - s.nextpos1 += e.height() + (typeof s.spacing1 === "undefined" ? 25 : s.spacing1); - break; - case "left": - case "right": - s.nextpos1 += e.width() + (typeof s.spacing1 === "undefined" ? 25 : s.spacing1); - break; - } - } - return this; - }, - // Queue the position all function so it doesn't run repeatedly and - // use up resources. - queuePosition: function(animate, milliseconds){ - if (timer) - clearTimeout(timer); - if (!milliseconds) - milliseconds = 10; - timer = setTimeout(function(){ PNotify.positionAll(animate) }, milliseconds); - return this; - }, - - - // Cancel any pending removal timer. - cancelRemove: function(){ - if (this.timer) - window.clearTimeout(this.timer); - if (this.state === "closing") { - // If it's animating out, animate back in really quickly. - this.elem.stop(true); - this.state = "open"; - this.animating = "in"; - this.elem.css("height", "auto").animate({"width": this.options.width, "opacity": this.options.opacity}, "fast"); - } - return this; - }, - // Queue a removal timer. - queueRemove: function(){ - var that = this; - // Cancel any current removal timer. - this.cancelRemove(); - this.timer = window.setTimeout(function(){ - that.remove(true); - }, (isNaN(this.options.delay) ? 0 : this.options.delay)); - return this; - } - }); - // These functions affect all notices. - $.extend(PNotify, { - // This holds all the notices. - notices: [], - removeAll: function () { - $.each(PNotify.notices, function(){ - if (this.remove) - this.remove(); - }); - }, - positionAll: function (animate) { - // This timer is used for queueing this function so it doesn't run - // repeatedly. - if (timer) - clearTimeout(timer); - timer = null; - // Reset the next position data. - $.each(PNotify.notices, function(){ - var s = this.options.stack; - if (!s) return; - s.nextpos1 = s.firstpos1; - s.nextpos2 = s.firstpos2; - s.addpos2 = 0; - s.animation = animate; - }); - $.each(PNotify.notices, function(){ - this.position(); - }); - }, - styling: { - jqueryui: { - container: "ui-widget ui-widget-content ui-corner-all", - notice: "ui-state-highlight", - // (The actual jQUI notice icon looks terrible.) - notice_icon: "ui-icon ui-icon-info", - info: "", - info_icon: "ui-icon ui-icon-info", - success: "ui-state-default", - success_icon: "ui-icon ui-icon-circle-check", - error: "ui-state-error", - error_icon: "ui-icon ui-icon-alert" - }, - bootstrap2: { - container: "alert", - notice: "", - notice_icon: "icon-exclamation-sign", - info: "alert-info", - info_icon: "icon-info-sign", - success: "alert-success", - success_icon: "icon-ok-sign", - error: "alert-error", - error_icon: "icon-warning-sign" - }, - bootstrap3: { - container: "alert", - notice: "alert-warning", - notice_icon: "glyphicon glyphicon-exclamation-sign", - info: "alert-info", - info_icon: "glyphicon glyphicon-info-sign", - success: "alert-success", - success_icon: "glyphicon glyphicon-ok-sign", - error: "alert-danger", - error_icon: "glyphicon glyphicon-warning-sign" - } - } - }); - /* - * uses icons from http://fontawesome.io/ - * version 4.0.3 - */ - PNotify.styling.fontawesome = $.extend({}, PNotify.styling.bootstrap3); - $.extend(PNotify.styling.fontawesome, { - notice_icon: "fa fa-exclamation-circle", - info_icon: "fa fa-info", - success_icon: "fa fa-check", - error_icon: "fa fa-warning" - }); - - if (document.body) - do_when_ready(); - else - $(do_when_ready); - return PNotify; -})); diff --git a/js/lib/pnotify/pnotify.desktop.js b/js/lib/pnotify/pnotify.desktop.js index 1402f380..174de24f 100644 --- a/js/lib/pnotify/pnotify.desktop.js +++ b/js/lib/pnotify/pnotify.desktop.js @@ -1,14 +1,16 @@ // Desktop -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify.desktop', ['jquery', 'pnotify'], factory); - } else { - // Browser globals - factory(jQuery, PNotify); - } -}(function($, PNotify){ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.desktop', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ var permission; var notify = function(title, options){ // Memoize based on feature detection. @@ -43,6 +45,8 @@ PNotify.prototype.options.desktop = { // Display the notification as a desktop notification. desktop: false, + // If desktop notifications are not supported or allowed, fall back to a regular notice. + fallback: true, // The URL of the icon to display. If false, no icon will show. If null, a default icon will show. icon: null, // Using a tag lets you update an existing notice, or keep from duplicating notices between tabs. @@ -66,10 +70,10 @@ } notice.desktop = notify(notice.options.title, { icon: this.icon, - body: notice.options.text, + body: options.text || notice.options.text, tag: this.tag }); - if (!("close" in notice.desktop)) { + if (!("close" in notice.desktop) && ("cancel" in notice.desktop)) { notice.desktop.close = function(){ notice.desktop.cancel(); }; @@ -87,38 +91,45 @@ if (!options.desktop) return; permission = PNotify.desktop.checkPermission(); - if (permission != 0) + if (permission !== 0) { + // Keep the notice from opening if fallback is false. + if (!options.fallback) { + notice.options.auto_display = false; + } return; + } this.genNotice(notice, options); }, update: function(notice, options, oldOpts){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; this.genNotice(notice, options); }, beforeOpen: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); }, afterOpen: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); if ("show" in notice.desktop) { notice.desktop.show(); } }, beforeClose: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); }, afterClose: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); - notice.desktop.close(); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); + if ("close" in notice.desktop) { + notice.desktop.close(); + } } }; PNotify.desktop = { @@ -131,9 +142,9 @@ }, checkPermission: function(){ if (typeof Notification !== "undefined" && "permission" in Notification) { - return (Notification.permission == "granted" ? 0 : 1); + return (Notification.permission === "granted" ? 0 : 1); } else if ("webkitNotifications" in window) { - return window.webkitNotifications.checkPermission(); + return window.webkitNotifications.checkPermission() == 0 ? 0 : 1; } else { return 1; } diff --git a/js/lib/pnotify/pnotify.js b/js/lib/pnotify/pnotify.js new file mode 100644 index 00000000..3c270554 --- /dev/null +++ b/js/lib/pnotify/pnotify.js @@ -0,0 +1,873 @@ +/* + PNotify 3.0.0 sciactive.com/pnotify/ + (C) 2015 Hunter Perrin; Google, Inc. + license Apache-2.0 + */ +/* + * ====== PNotify ====== + * + * http://sciactive.com/pnotify/ + * + * Copyright 2009-2015 Hunter Perrin + * Copyright 2015 Google, Inc. + * + * Licensed under Apache License, Version 2.0. + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify', ['jquery'], function($){ + return factory($, root); + }); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), global || root); + } else { + // Browser globals + root.PNotify = factory(root.jQuery, root); + } +}(this, function($, root){ + var init = function(root){ + var default_stack = { + dir1: "down", + dir2: "left", + push: "bottom", + spacing1: 36, + spacing2: 36, + context: $("body"), + modal: false + }; + var posTimer, // Position all timer. + body, + jwindow = $(root); + // Set global variables. + var do_when_ready = function(){ + body = $("body"); + PNotify.prototype.options.stack.context = body; + jwindow = $(root); + // Reposition the notices when the window resizes. + jwindow.bind('resize', function(){ + if (posTimer) { + clearTimeout(posTimer); + } + posTimer = setTimeout(function(){ + PNotify.positionAll(true); + }, 10); + }); + }; + var createStackOverlay = function(stack) { + var overlay = $("
", {"class": "ui-pnotify-modal-overlay"}); + overlay.prependTo(stack.context); + if (stack.overlay_close) { + // Close the notices on overlay click. + overlay.click(function(){ + PNotify.removeStack(stack); + }); + } + return overlay; + }; + var PNotify = function(options){ + this.parseOptions(options); + this.init(); + }; + $.extend(PNotify.prototype, { + // The current version of PNotify. + version: "3.0.0", + + // === Options === + + // Options defaults. + options: { + // The notice's title. + title: false, + // Whether to escape the content of the title. (Not allow HTML.) + title_escape: false, + // The notice's text. + text: false, + // Whether to escape the content of the text. (Not allow HTML.) + text_escape: false, + // What styling classes to use. (Can be either "brighttheme", "jqueryui", "bootstrap2", "bootstrap3", or "fontawesome".) + styling: "brighttheme", + // Additional classes to be added to the notice. (For custom styling.) + addclass: "", + // Class to be added to the notice for corner styling. + cornerclass: "", + // Display the notice when it is created. + auto_display: true, + // Width of the notice. + width: "300px", + // Minimum height of the notice. It will expand to fit content. + min_height: "16px", + // Type of the notice. "notice", "info", "success", or "error". + type: "notice", + // Set icon to true to use the default icon for the selected + // style/type, false for no icon, or a string for your own icon class. + icon: true, + // The animation to use when displaying and hiding the notice. "none" + // and "fade" are supported through CSS. Others are supported + // through the Animate module and Animate.css. + animation: "fade", + // Speed at which the notice animates in and out. "slow", "normal", + // or "fast". Respectively, 600ms, 400ms, 200ms. + animate_speed: "normal", + // Display a drop shadow. + shadow: true, + // After a delay, remove the notice. + hide: true, + // Delay in milliseconds before the notice is removed. + delay: 8000, + // Reset the hide timer if the mouse moves over the notice. + mouse_reset: true, + // Remove the notice's elements from the DOM after it is removed. + remove: true, + // Change new lines to br tags. + insert_brs: true, + // Whether to remove notices from the global array. + destroy: true, + // The stack on which the notices will be placed. Also controls the + // direction the notices stack. + stack: default_stack + }, + + // === Modules === + + // This object holds all the PNotify modules. They are used to provide + // additional functionality. + modules: {}, + // This runs an event on all the modules. + runModules: function(event, arg){ + var curArg; + for (var module in this.modules) { + curArg = ((typeof arg === "object" && module in arg) ? arg[module] : arg); + if (typeof this.modules[module][event] === 'function') { + this.modules[module].notice = this; + this.modules[module].options = typeof this.options[module] === 'object' ? this.options[module] : {}; + this.modules[module][event](this, typeof this.options[module] === 'object' ? this.options[module] : {}, curArg); + } + } + }, + + // === Class Variables === + + state: "initializing", // The state can be "initializing", "opening", "open", "closing", and "closed". + timer: null, // Auto close timer. + animTimer: null, // Animation timer. + styles: null, + elem: null, + container: null, + title_container: null, + text_container: null, + animating: false, // Stores what is currently being animated (in or out). + timerHide: false, // Stores whether the notice was hidden by a timer. + + // === Events === + + init: function(){ + var that = this; + + // First and foremost, we don't want our module objects all referencing the prototype. + this.modules = {}; + $.extend(true, this.modules, PNotify.prototype.modules); + + // Get our styling object. + if (typeof this.options.styling === "object") { + this.styles = this.options.styling; + } else { + this.styles = PNotify.styling[this.options.styling]; + } + + // Create our widget. + // Stop animation, reset the removal timer when the user mouses over. + this.elem = $("
", { + "class": "ui-pnotify "+this.options.addclass, + "css": {"display": "none"}, + "aria-live": "assertive", + "aria-role": "alertdialog", + "mouseenter": function(e){ + if (that.options.mouse_reset && that.animating === "out") { + if (!that.timerHide) { + return; + } + that.cancelRemove(); + } + // Stop the close timer. + if (that.options.hide && that.options.mouse_reset) { + that.cancelRemove(); + } + }, + "mouseleave": function(e){ + // Start the close timer. + if (that.options.hide && that.options.mouse_reset && that.animating !== "out") { + that.queueRemove(); + } + PNotify.positionAll(); + } + }); + // Maybe we need to fade in/out. + if (this.options.animation === "fade") { + this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed); + } + // Create a container for the notice contents. + this.container = $("
", { + "class": this.styles.container+" ui-pnotify-container "+(this.options.type === "error" ? this.styles.error : (this.options.type === "info" ? this.styles.info : (this.options.type === "success" ? this.styles.success : this.styles.notice))), + "role": "alert" + }).appendTo(this.elem); + if (this.options.cornerclass !== "") { + this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass); + } + // Create a drop shadow. + if (this.options.shadow) { + this.container.addClass("ui-pnotify-shadow"); + } + + + // Add the appropriate icon. + if (this.options.icon !== false) { + $("
", {"class": "ui-pnotify-icon"}) + .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) + .prependTo(this.container); + } + + // Add a title. + this.title_container = $("

", { + "class": "ui-pnotify-title" + }) + .appendTo(this.container); + if (this.options.title === false) { + this.title_container.hide(); + } else if (this.options.title_escape) { + this.title_container.text(this.options.title); + } else { + this.title_container.html(this.options.title); + } + + // Add text. + this.text_container = $("
", { + "class": "ui-pnotify-text", + "aria-role": "alert" + }) + .appendTo(this.container); + if (this.options.text === false) { + this.text_container.hide(); + } else if (this.options.text_escape) { + this.text_container.text(this.options.text); + } else { + this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); + } + + // Set width and min height. + if (typeof this.options.width === "string") { + this.elem.css("width", this.options.width); + } + if (typeof this.options.min_height === "string") { + this.container.css("min-height", this.options.min_height); + } + + + // Add the notice to the notice array. + if (this.options.stack.push === "top") { + PNotify.notices = $.merge([this], PNotify.notices); + } else { + PNotify.notices = $.merge(PNotify.notices, [this]); + } + // Now position all the notices if they are to push to the top. + if (this.options.stack.push === "top") { + this.queuePosition(false, 1); + } + + + + + // Mark the stack so it won't animate the new notice. + this.options.stack.animation = false; + + // Run the modules. + this.runModules('init'); + + // Display the notice. + if (this.options.auto_display) { + this.open(); + } + return this; + }, + + // This function is for updating the notice. + update: function(options){ + // Save old options. + var oldOpts = this.options; + // Then update to the new options. + this.parseOptions(oldOpts, options); + // Maybe we need to fade in/out. + this.elem.removeClass("ui-pnotify-fade-slow ui-pnotify-fade-normal ui-pnotify-fade-fast"); + if (this.options.animation === "fade") { + this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed); + } + // Update the corner class. + if (this.options.cornerclass !== oldOpts.cornerclass) { + this.container.removeClass("ui-corner-all "+oldOpts.cornerclass).addClass(this.options.cornerclass); + } + // Update the shadow. + if (this.options.shadow !== oldOpts.shadow) { + if (this.options.shadow) { + this.container.addClass("ui-pnotify-shadow"); + } else { + this.container.removeClass("ui-pnotify-shadow"); + } + } + // Update the additional classes. + if (this.options.addclass === false) { + this.elem.removeClass(oldOpts.addclass); + } else if (this.options.addclass !== oldOpts.addclass) { + this.elem.removeClass(oldOpts.addclass).addClass(this.options.addclass); + } + // Update the title. + if (this.options.title === false) { + this.title_container.slideUp("fast"); + } else if (this.options.title !== oldOpts.title) { + if (this.options.title_escape) { + this.title_container.text(this.options.title); + } else { + this.title_container.html(this.options.title); + } + if (oldOpts.title === false) { + this.title_container.slideDown(200); + } + } + // Update the text. + if (this.options.text === false) { + this.text_container.slideUp("fast"); + } else if (this.options.text !== oldOpts.text) { + if (this.options.text_escape) { + this.text_container.text(this.options.text); + } else { + this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); + } + if (oldOpts.text === false) { + this.text_container.slideDown(200); + } + } + // Change the notice type. + if (this.options.type !== oldOpts.type) + this.container.removeClass( + this.styles.error+" "+this.styles.notice+" "+this.styles.success+" "+this.styles.info + ).addClass(this.options.type === "error" ? + this.styles.error : + (this.options.type === "info" ? + this.styles.info : + (this.options.type === "success" ? + this.styles.success : + this.styles.notice + ) + ) + ); + if (this.options.icon !== oldOpts.icon || (this.options.icon === true && this.options.type !== oldOpts.type)) { + // Remove any old icon. + this.container.find("div.ui-pnotify-icon").remove(); + if (this.options.icon !== false) { + // Build the new icon. + $("
", {"class": "ui-pnotify-icon"}) + .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) + .prependTo(this.container); + } + } + // Update the width. + if (this.options.width !== oldOpts.width) { + this.elem.animate({width: this.options.width}); + } + // Update the minimum height. + if (this.options.min_height !== oldOpts.min_height) { + this.container.animate({minHeight: this.options.min_height}); + } + // Update the timed hiding. + if (!this.options.hide) { + this.cancelRemove(); + } else if (!oldOpts.hide) { + this.queueRemove(); + } + this.queuePosition(true); + + // Run the modules. + this.runModules('update', oldOpts); + return this; + }, + + // Display the notice. + open: function(){ + this.state = "opening"; + // Run the modules. + this.runModules('beforeOpen'); + + var that = this; + // If the notice is not in the DOM, append it. + if (!this.elem.parent().length) { + this.elem.appendTo(this.options.stack.context ? this.options.stack.context : body); + } + // Try to put it in the right position. + if (this.options.stack.push !== "top") { + this.position(true); + } + this.animateIn(function(){ + that.queuePosition(true); + + // Now set it to hide. + if (that.options.hide) { + that.queueRemove(); + } + + that.state = "open"; + + // Run the modules. + that.runModules('afterOpen'); + }); + + return this; + }, + + // Remove the notice. + remove: function(timer_hide) { + this.state = "closing"; + this.timerHide = !!timer_hide; // Make sure it's a boolean. + // Run the modules. + this.runModules('beforeClose'); + + var that = this; + if (this.timer) { + root.clearTimeout(this.timer); + this.timer = null; + } + this.animateOut(function(){ + that.state = "closed"; + // Run the modules. + that.runModules('afterClose'); + that.queuePosition(true); + // If we're supposed to remove the notice from the DOM, do it. + if (that.options.remove) { + that.elem.detach(); + } + // Run the modules. + that.runModules('beforeDestroy'); + // Remove object from PNotify.notices to prevent memory leak (issue #49) + // unless destroy is off + if (that.options.destroy) { + if (PNotify.notices !== null) { + var idx = $.inArray(that,PNotify.notices); + if (idx !== -1) { + PNotify.notices.splice(idx,1); + } + } + } + // Run the modules. + that.runModules('afterDestroy'); + }); + + return this; + }, + + // === Class Methods === + + // Get the DOM element. + get: function(){ + return this.elem; + }, + + // Put all the options in the right places. + parseOptions: function(options, moreOptions){ + this.options = $.extend(true, {}, PNotify.prototype.options); + // This is the only thing that *should* be copied by reference. + this.options.stack = PNotify.prototype.options.stack; + var optArray = [options, moreOptions], curOpts; + for (var curIndex=0; curIndex < optArray.length; curIndex++) { + curOpts = optArray[curIndex]; + if (typeof curOpts === "undefined") { + break; + } + if (typeof curOpts !== 'object') { + this.options.text = curOpts; + } else { + for (var option in curOpts) { + if (this.modules[option]) { + // Avoid overwriting module defaults. + $.extend(true, this.options[option], curOpts[option]); + } else { + this.options[option] = curOpts[option]; + } + } + } + } + }, + + // Animate the notice in. + animateIn: function(callback){ + // Declare that the notice is animating in. + this.animating = "in"; + var that = this; + callback = (function(){ + if (that.animTimer) { + clearTimeout(that.animTimer); + } + if (that.animating !== "in") { + return; + } + if (that.elem.is(":visible")) { + if (this) { + this.call(); + } + // Declare that the notice has completed animating. + that.animating = false; + } else { + that.animTimer = setTimeout(callback, 40); + } + }).bind(callback); + + if (this.options.animation === "fade") { + this.elem.one('webkitTransitionEnd mozTransitionEnd MSTransitionEnd oTransitionEnd transitionend', callback).addClass("ui-pnotify-in"); + this.elem.css("opacity"); // This line is necessary for some reason. Some notices don't fade without it. + this.elem.addClass("ui-pnotify-fade-in"); + // Just in case the event doesn't fire, call it after 650 ms. + this.animTimer = setTimeout(callback, 650); + } else { + this.elem.addClass("ui-pnotify-in"); + callback(); + } + }, + + // Animate the notice out. + animateOut: function(callback){ + // Declare that the notice is animating out. + this.animating = "out"; + var that = this; + callback = (function(){ + if (that.animTimer) { + clearTimeout(that.animTimer); + } + if (that.animating !== "out") { + return; + } + if (that.elem.css("opacity") == "0" || !that.elem.is(":visible")) { + that.elem.removeClass("ui-pnotify-in"); + if (this) { + this.call(); + } + // Declare that the notice has completed animating. + that.animating = false; + } else { + // In case this was called before the notice finished animating. + that.animTimer = setTimeout(callback, 40); + } + }).bind(callback); + + if (this.options.animation === "fade") { + this.elem.one('webkitTransitionEnd mozTransitionEnd MSTransitionEnd oTransitionEnd transitionend', callback).removeClass("ui-pnotify-fade-in"); + // Just in case the event doesn't fire, call it after 650 ms. + this.animTimer = setTimeout(callback, 650); + } else { + this.elem.removeClass("ui-pnotify-in"); + callback(); + } + }, + + // Position the notice. dont_skip_hidden causes the notice to + // position even if it's not visible. + position: function(dontSkipHidden){ + // Get the notice's stack. + var stack = this.options.stack, + elem = this.elem; + if (typeof stack.context === "undefined") { + stack.context = body; + } + if (!stack) { + return; + } + if (typeof stack.nextpos1 !== "number") { + stack.nextpos1 = stack.firstpos1; + } + if (typeof stack.nextpos2 !== "number") { + stack.nextpos2 = stack.firstpos2; + } + if (typeof stack.addpos2 !== "number") { + stack.addpos2 = 0; + } + var hidden = !elem.hasClass("ui-pnotify-in"); + // Skip this notice if it's not shown. + if (!hidden || dontSkipHidden) { + if (stack.modal) { + if (stack.overlay) { + stack.overlay.show(); + } else { + stack.overlay = createStackOverlay(stack); + } + } + // Add animate class by default. + elem.addClass("ui-pnotify-move"); + var curpos1, curpos2; + // Calculate the current pos1 value. + var csspos1; + switch (stack.dir1) { + case "down": + csspos1 = "top"; + break; + case "up": + csspos1 = "bottom"; + break; + case "left": + csspos1 = "right"; + break; + case "right": + csspos1 = "left"; + break; + } + curpos1 = parseInt(elem.css(csspos1).replace(/(?:\..*|[^0-9.])/g, '')); + if (isNaN(curpos1)) { + curpos1 = 0; + } + // Remember the first pos1, so the first visible notice goes there. + if (typeof stack.firstpos1 === "undefined" && !hidden) { + stack.firstpos1 = curpos1; + stack.nextpos1 = stack.firstpos1; + } + // Calculate the current pos2 value. + var csspos2; + switch (stack.dir2) { + case "down": + csspos2 = "top"; + break; + case "up": + csspos2 = "bottom"; + break; + case "left": + csspos2 = "right"; + break; + case "right": + csspos2 = "left"; + break; + } + curpos2 = parseInt(elem.css(csspos2).replace(/(?:\..*|[^0-9.])/g, '')); + if (isNaN(curpos2)) { + curpos2 = 0; + } + // Remember the first pos2, so the first visible notice goes there. + if (typeof stack.firstpos2 === "undefined" && !hidden) { + stack.firstpos2 = curpos2; + stack.nextpos2 = stack.firstpos2; + } + // Check that it's not beyond the viewport edge. + if ( + (stack.dir1 === "down" && stack.nextpos1 + elem.height() > (stack.context.is(body) ? jwindow.height() : stack.context.prop('scrollHeight')) ) || + (stack.dir1 === "up" && stack.nextpos1 + elem.height() > (stack.context.is(body) ? jwindow.height() : stack.context.prop('scrollHeight')) ) || + (stack.dir1 === "left" && stack.nextpos1 + elem.width() > (stack.context.is(body) ? jwindow.width() : stack.context.prop('scrollWidth')) ) || + (stack.dir1 === "right" && stack.nextpos1 + elem.width() > (stack.context.is(body) ? jwindow.width() : stack.context.prop('scrollWidth')) ) + ) { + // If it is, it needs to go back to the first pos1, and over on pos2. + stack.nextpos1 = stack.firstpos1; + stack.nextpos2 += stack.addpos2 + (typeof stack.spacing2 === "undefined" ? 25 : stack.spacing2); + stack.addpos2 = 0; + } + if (typeof stack.nextpos2 === "number") { + if (!stack.animation) { + elem.removeClass("ui-pnotify-move"); + elem.css(csspos2, stack.nextpos2+"px"); + elem.css(csspos2); + elem.addClass("ui-pnotify-move"); + } else { + elem.css(csspos2, stack.nextpos2+"px"); + } + } + // Keep track of the widest/tallest notice in the column/row, so we can push the next column/row. + switch (stack.dir2) { + case "down": + case "up": + if (elem.outerHeight(true) > stack.addpos2) { + stack.addpos2 = elem.height(); + } + break; + case "left": + case "right": + if (elem.outerWidth(true) > stack.addpos2) { + stack.addpos2 = elem.width(); + } + break; + } + // Move the notice on dir1. + if (typeof stack.nextpos1 === "number") { + if (!stack.animation) { + elem.removeClass("ui-pnotify-move"); + elem.css(csspos1, stack.nextpos1+"px"); + elem.css(csspos1); + elem.addClass("ui-pnotify-move"); + } else { + elem.css(csspos1, stack.nextpos1+"px"); + } + } + // Calculate the next dir1 position. + switch (stack.dir1) { + case "down": + case "up": + stack.nextpos1 += elem.height() + (typeof stack.spacing1 === "undefined" ? 25 : stack.spacing1); + break; + case "left": + case "right": + stack.nextpos1 += elem.width() + (typeof stack.spacing1 === "undefined" ? 25 : stack.spacing1); + break; + } + } + return this; + }, + // Queue the position all function so it doesn't run repeatedly and + // use up resources. + queuePosition: function(animate, milliseconds){ + if (posTimer) { + clearTimeout(posTimer); + } + if (!milliseconds) { + milliseconds = 10; + } + posTimer = setTimeout(function(){ + PNotify.positionAll(animate); + }, milliseconds); + return this; + }, + + + // Cancel any pending removal timer. + cancelRemove: function(){ + if (this.timer) { + root.clearTimeout(this.timer); + } + if (this.animTimer) { + root.clearTimeout(this.animTimer); + } + if (this.state === "closing") { + // If it's animating out, stop it. + this.state = "open"; + this.animating = false; + this.elem.addClass("ui-pnotify-in"); + if (this.options.animation === "fade") { + this.elem.addClass("ui-pnotify-fade-in"); + } + } + return this; + }, + // Queue a removal timer. + queueRemove: function(){ + var that = this; + // Cancel any current removal timer. + this.cancelRemove(); + this.timer = root.setTimeout(function(){ + that.remove(true); + }, (isNaN(this.options.delay) ? 0 : this.options.delay)); + return this; + } + }); + // These functions affect all notices. + $.extend(PNotify, { + // This holds all the notices. + notices: [], + reload: init, + removeAll: function(){ + $.each(PNotify.notices, function(){ + if (this.remove) { + this.remove(false); + } + }); + }, + removeStack: function(stack){ + $.each(PNotify.notices, function(){ + if (this.remove && this.options.stack === stack) { + this.remove(false); + } + }); + }, + positionAll: function(animate){ + // This timer is used for queueing this function so it doesn't run + // repeatedly. + if (posTimer) { + clearTimeout(posTimer); + } + posTimer = null; + // Reset the next position data. + if (PNotify.notices && PNotify.notices.length) { + $.each(PNotify.notices, function(){ + var s = this.options.stack; + if (!s) { + return; + } + if (s.overlay) { + s.overlay.hide(); + } + s.nextpos1 = s.firstpos1; + s.nextpos2 = s.firstpos2; + s.addpos2 = 0; + s.animation = animate; + }); + $.each(PNotify.notices, function(){ + this.position(); + }); + } else { + var s = PNotify.prototype.options.stack; + if (s) { + delete s.nextpos1; + delete s.nextpos2; + } + } + }, + styling: { + brighttheme: { + // Bright Theme doesn't require any UI libraries. + container: "brighttheme", + notice: "brighttheme-notice", + notice_icon: "brighttheme-icon-notice", + info: "brighttheme-info", + info_icon: "brighttheme-icon-info", + success: "brighttheme-success", + success_icon: "brighttheme-icon-success", + error: "brighttheme-error", + error_icon: "brighttheme-icon-error" + }, + jqueryui: { + container: "ui-widget ui-widget-content ui-corner-all", + notice: "ui-state-highlight", + // (The actual jQUI notice icon looks terrible.) + notice_icon: "ui-icon ui-icon-info", + info: "", + info_icon: "ui-icon ui-icon-info", + success: "ui-state-default", + success_icon: "ui-icon ui-icon-circle-check", + error: "ui-state-error", + error_icon: "ui-icon ui-icon-alert" + }, + bootstrap3: { + container: "alert", + notice: "alert-warning", + notice_icon: "glyphicon glyphicon-exclamation-sign", + info: "alert-info", + info_icon: "glyphicon glyphicon-info-sign", + success: "alert-success", + success_icon: "glyphicon glyphicon-ok-sign", + error: "alert-danger", + error_icon: "glyphicon glyphicon-warning-sign" + } + } + }); + /* + * uses icons from http://fontawesome.io/ + * version 4.0.3 + */ + PNotify.styling.fontawesome = $.extend({}, PNotify.styling.bootstrap3); + $.extend(PNotify.styling.fontawesome, { + notice_icon: "fa fa-exclamation-circle", + info_icon: "fa fa-info", + success_icon: "fa fa-check", + error_icon: "fa fa-warning" + }); + + if (root.document.body) { + do_when_ready(); + } else { + $(do_when_ready); + } + return PNotify; + }; + return init(root); +})); diff --git a/js/lib/pnotify/pnotify.nonblock.js b/js/lib/pnotify/pnotify.nonblock.js index 4464f14c..3d0481ce 100644 --- a/js/lib/pnotify/pnotify.nonblock.js +++ b/js/lib/pnotify/pnotify.nonblock.js @@ -1,14 +1,16 @@ // Nonblock -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify.nonblock', ['jquery', 'pnotify'], factory); - } else { - // Browser globals - factory(jQuery, PNotify); - } -}(function($, PNotify){ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.nonblock', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ // Some useful regexes. var re_on = /^on/, re_mouse_events = /^(dbl)?click$|^mouse(move|down|up|over|out|enter|leave)$|^contextmenu$/, @@ -54,11 +56,14 @@ var nonblock_last_elem; // This is used to pass events through the notice if it is non-blocking. var nonblock_pass = function(notice, e, e_name){ - notice.elem.css("display", "none"); + notice.elem.addClass("ui-pnotify-nonblock-hide"); var element_below = document.elementFromPoint(e.clientX, e.clientY); - notice.elem.css("display", "block"); + notice.elem.removeClass("ui-pnotify-nonblock-hide"); var jelement_below = $(element_below); var cursor_style = jelement_below.css("cursor"); + if (cursor_style === "auto" && element_below.tagName === "A") { + cursor_style = "pointer"; + } notice.elem.css("cursor", cursor_style !== "auto" ? cursor_style : "default"); // If the element changed, call mouseenter, mouseleave, etc. if (!nonblock_last_elem || nonblock_last_elem.get(0) != element_below) { @@ -77,75 +82,75 @@ PNotify.prototype.options.nonblock = { // Create a non-blocking notice. It lets the user click elements underneath it. - nonblock: false, - // The opacity of the notice (if it's non-blocking) when the mouse is over it. - nonblock_opacity: .2 + nonblock: false }; PNotify.prototype.modules.nonblock = { - // This lets us update the options available in the closures. - myOptions: null, - init: function(notice, options){ var that = this; - this.myOptions = options; notice.elem.on({ "mouseenter": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); - if (that.myOptions.nonblock) { + if (that.options.nonblock) { + e.stopPropagation(); + } + if (that.options.nonblock) { // If it's non-blocking, animate to the other opacity. - notice.elem.stop().animate({"opacity": that.myOptions.nonblock_opacity}, "fast"); + notice.elem.addClass("ui-pnotify-nonblock-fade"); } }, "mouseleave": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); + if (that.options.nonblock) { + e.stopPropagation(); + } nonblock_last_elem = null; notice.elem.css("cursor", "auto"); // Animate back to the normal opacity. - if (that.myOptions.nonblock && notice.animating !== "out") - notice.elem.stop().animate({"opacity": notice.options.opacity}, "fast"); + if (that.options.nonblock && notice.animating !== "out") { + notice.elem.removeClass("ui-pnotify-nonblock-fade"); + } }, "mouseover": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); + if (that.options.nonblock) { + e.stopPropagation(); + } }, "mouseout": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); + if (that.options.nonblock) { + e.stopPropagation(); + } }, "mousemove": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); nonblock_pass(notice, e, "onmousemove"); } }, "mousedown": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); e.preventDefault(); nonblock_pass(notice, e, "onmousedown"); } }, "mouseup": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); e.preventDefault(); nonblock_pass(notice, e, "onmouseup"); } }, "click": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); nonblock_pass(notice, e, "onclick"); } }, "dblclick": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); nonblock_pass(notice, e, "ondblclick"); } } }); - }, - update: function(notice, options){ - this.myOptions = options; } }; })); diff --git a/public/css/pathfinder.css b/public/css/pathfinder.css index a449b1d9..da9c92d9 100644 --- a/public/css/pathfinder.css +++ b/public/css/pathfinder.css @@ -32,7 +32,7 @@ * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * - */.datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:6px}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:7px}.datepicker>div{display:none}.datepicker.days div.datepicker-days{display:block}.datepicker.months div.datepicker-months{display:block}.datepicker.years div.datepicker-years{display:block}.datepicker table{margin:0}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day:hover{background:#eeeeee;cursor:pointer}.datepicker table tr td.old,.datepicker table tr td.new{color:#999999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today:hover,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top, #fdd49a, #fdf59a);background-image:-ms-linear-gradient(top, #fdd49a, #fdf59a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));background-image:-webkit-linear-gradient(top, #fdd49a, #fdf59a);background-image:-o-linear-gradient(top, #fdd49a, #fdf59a);background-image:linear-gradient(to bottom, #fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today:hover,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today[disabled],.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active{background-color:#fbf069 \9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range:hover,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover{background:#eeeeee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(top, #f3c17a, #f3e97a);background-image:-ms-linear-gradient(top, #f3c17a, #f3e97a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));background-image:-webkit-linear-gradient(top, #f3c17a, #f3e97a);background-image:-o-linear-gradient(top, #f3c17a, #f3e97a);background-image:linear-gradient(to bottom, #f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled:hover[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active{background-color:#efe24b \9}.datepicker table tr td.selected,.datepicker table tr td.selected:hover,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(top, #b3b3b3, gray);background-image:-ms-linear-gradient(top, #b3b3b3, gray);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(gray));background-image:-webkit-linear-gradient(top, #b3b3b3, gray);background-image:-o-linear-gradient(top, #b3b3b3, gray);background-image:linear-gradient(to bottom, #b3b3b3,#808080);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:#808080 #808080 #595959;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled:hover[disabled]{background-color:#808080}.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active{background-color:#666666 \9}.datepicker table tr td.active,.datepicker table tr td.active:hover,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.active:hover,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active[disabled],.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span:hover{background:#eeeeee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#999999}.datepicker th.datepicker-switch{width:145px}.datepicker thead tr:first-child th,.datepicker tfoot tr th{cursor:pointer}.datepicker thead tr:first-child th:hover,.datepicker tfoot tr th:hover{background:#eeeeee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child th.cw{cursor:default;background-color:transparent}.input-append.date .add-on i,.input-prepend.date .add-on i{display:block;cursor:pointer;width:16px;height:16px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #ffffff;vertical-align:middle;background-color:#eeeeee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}.ui-pnotify{top:25px;right:25px;position:absolute;height:auto;z-index:9999}html>body>.ui-pnotify{position:fixed}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0px 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block;font-family:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-topleft,.ui-pnotify.stack-bottomleft{left:25px;right:auto}.ui-pnotify.stack-bottomright,.ui-pnotify.stack-bottomleft{bottom:25px;top:auto}.ui-pnotify.stack-bar-top{right:0;top:0}.ui-pnotify.stack-bar-bottom{right:auto;bottom:0;top:auto;left:auto}html,body,#sb-site,.sb-site-container,.sb-slidebar{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{width:100%;overflow-x:hidden}html{height:100%}body{min-height:100%;height:auto;position:relative}html.sb-scroll-lock.sb-active:not(.sb-static){overflow:hidden}#sb-site,.sb-site-container{width:100%;position:relative;z-index:1;background:url("../img/pf-bg.jpg") #05050a;background-repeat:no-repeat}.sb-slidebar{height:100%;overflow-y:auto;position:fixed;top:0;z-index:0;display:none;background-color:#313335;-webkit-transform:translate(0px)}.sb-left{left:0;-webkit-box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4)}.sb-right{right:0;-webkit-box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4)}html.sb-static .sb-slidebar,.sb-slidebar.sb-static{position:absolute}.sb-slidebar.sb-active{display:block}.sb-style-overlay{z-index:9999}.sb-momentum-scrolling{-webkit-overflow-scrolling:touch}.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}@media (max-width: 480px){.sb-slidebar{width:70%}.sb-width-thin{width:55%}.sb-width-wide{width:85%}}@media (min-width: 481px){.sb-slidebar{width:55%}.sb-width-thin{width:40%}.sb-width-wide{width:70%}}@media (min-width: 768px){.sb-slidebar{width:40%}.sb-width-thin{width:25%}.sb-width-wide{width:55%}}@media (min-width: 992px){.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}}@media (min-width: 1200px){.sb-slidebar{width:20%}.sb-width-thin{width:5%}.sb-width-wide{width:35%}}.sb-slide,#sb-site,.sb-site-container,.sb-slidebar{-webkit-transition:-webkit-transform 400ms ease;-moz-transition:-moz-transform 400ms ease;-o-transition:-o-transform 400ms ease;transition:transform 400ms ease;-webkit-transition-property:-webkit-transform, left, right;-webkit-backface-visibility:hidden}.sb-hide{display:none}.pf-pie-chart{position:relative;display:table-cell;text-align:center;vertical-align:middle}.pf-pie-chart span{display:inline-block}.pf-pie-chart canvas{position:absolute;top:0;left:0}.pf-pie-chart-map-timer{width:36px;height:36px;margin:3px}.pf-pie-chart-map-timer canvas{top:3px;left:3px}.pf-pie-chart-map-timer span{font-size:10px}.pf-pie-chart-map-timer span:after{content:'s';margin-left:1px}div.pf-map-drag-to-select{background:#375959 !important;display:block;visibility:hidden;opacity:0;z-index:9000;border:1px dashed #adadad;will-change:opacity, visibility;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-transition:opacity 0.15s linear,visibility 0.15s linear;transition:opacity 0.15s linear,visibility 0.15s linear}div.pf-map-drag-to-select.active{visibility:visible;opacity:0.3}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;color:#adadad;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.select2-container--pathfinder .select2-selection--single{background-color:#313335;border:1px solid #63676a;border-radius:0px;outline:0}.select2-container--pathfinder .select2-selection--single:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--single .select2-selection__rendered{color:#adadad;line-height:28px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear{color:#a52521;cursor:pointer;float:right;font-weight:bold;margin-right:3px;margin-left:10px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear:hover{color:#58100d}.select2-container--pathfinder .select2-selection--single .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow{background-color:#313335;border:none;border-left:none;border-top-right-radius:0px;border-bottom-right-radius:0px;height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #63676a;border-radius:0;border-top-left-radius:0px;border-bottom-left-radius:0px;left:1px;right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--single{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-selection--multiple{background-color:#313335;color:#313335;border:1px solid #63676a;border-radius:0px;cursor:text;outline:0}.select2-container--pathfinder .select2-selection--multiple:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--pathfinder .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice{background-color:#adadad;border:1px solid #63676a;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove{color:#a52521;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove:hover{color:#58100d}.select2-container--pathfinder .select2-selection--multiple .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--multiple{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-search--dropdown .select2-search__field{border:1px solid #63676a;outline:0}.select2-container--pathfinder .select2-search--inline .select2-search__field{outline:0}.select2-container--pathfinder .select2-dropdown{background-color:#313335;border:1px solid transparent;overflow:hidden;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3)}.select2-container--pathfinder .select2-dropdown--above{border-bottom:none}.select2-container--pathfinder .select2-dropdown--below{border-top:none}.select2-container--pathfinder .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--pathfinder .select2-results__option[role=group]{padding:0}.select2-container--pathfinder .select2-results__option[aria-disabled=true],.select2-container--pathfinder .select2-results__option[aria-selected=true]{color:#63676a;background-color:#3c3f41}.select2-container--pathfinder .select2-results__option[aria-disabled=true] .pf-select-item-anchor:before,.select2-container--pathfinder .select2-results__option[aria-selected=true] .pf-select-item-anchor:before{content:"\f05e";font-family:FontAwesome;font-size:9px;position:absolute;left:0;top:0;color:#63676a}.select2-container--pathfinder .select2-results__option--highlighted[aria-selected]{background-color:#adadad;color:#313335}.select2-container--pathfinder .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--pathfinder.select2-container--open .select2-dropdown{border-color:#568a89}select.select2-hidden-accessible{-moz-appearance:none;-webkit-appearance:none}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{position:absolute;top:0;right:0;bottom:0;left:0;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content{margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;opacity:1}.blueimp-gallery{position:fixed;z-index:999999;overflow:hidden;background:#000;background:rgba(0,0,0,0.9);opacity:0;display:none;direction:ltr;-ms-touch-action:none;touch-action:none}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-ms-touch-action:pan-y;touch-action:pan-y}.blueimp-gallery-display{display:block;opacity:1}.blueimp-gallery>.slides{position:relative;height:100%;overflow:hidden}.blueimp-gallery-carousel>.slides{position:absolute}.blueimp-gallery>.slides>.slide{position:relative;float:left;height:100%;text-align:center;will-change:all;-webkit-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-moz-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-ms-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-o-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1)}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-transition:opacity 0.5s linear;-moz-transition:opacity 0.5s linear;-ms-transition:opacity 0.5s linear;-o-transition:opacity 0.5s linear;transition:opacity 0.5s linear}.blueimp-gallery>.slides>.slide-loading{background-size:64px 64px}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery>.prev,.blueimp-gallery>.next{position:absolute;top:50%;left:15px;width:35px;height:35px;margin-top:-17px;font-size:22px;line-height:35px;color:#63676a;text-decoration:none;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;opacity:1;cursor:pointer;display:none}.blueimp-gallery>.next{left:auto;right:15px}.blueimp-gallery>.close,.blueimp-gallery>.title{position:absolute;bottom:15px;left:15px;margin:0 40px 0 0;font-size:14px;line-height:14px;font-font:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#63676a;text-shadow:0 1px 3px #1d1d1d;opacity:1;display:none}.blueimp-gallery>.title{margin-left:20px}.blueimp-gallery>.title:before{content:'\f101';font-family:'FontAwesome';position:absolute;top:-1px;left:-20px;height:14px;width:14px}.blueimp-gallery>.close{padding:15px;right:15px;left:auto;margin:-15px;font-size:30px;text-decoration:none;cursor:pointer}.blueimp-gallery>.play-pause{position:absolute;right:15px;bottom:15px;width:35px;height:35px;font-size:22px;line-height:35px;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;color:#e28a0d;cursor:pointer;opacity:1;display:none}.blueimp-gallery-playing>.play-pause{color:#2b2b2b}.blueimp-gallery>.prev:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.close:hover,.blueimp-gallery>.play-pause:hover{color:#e28a0d}.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.title,.blueimp-gallery-controls>.play-pause{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.prev,.blueimp-gallery-left>.prev,.blueimp-gallery-single>.next,.blueimp-gallery-right>.next,.blueimp-gallery-single>.play-pause{display:none}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.prev,.blueimp-gallery>.next,.blueimp-gallery>.close,.blueimp-gallery>.play-pause{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:last-child .blueimp-gallery-playing>.play-pause{background-position:-20px 0}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}.blueimp-gallery>.slides>.slide>.text-content{overflow:auto;margin:0 auto;overflow:hidden;text-align:left}.blueimp-gallery .modal-body{position:relative;text-align:center;padding:0 0 56.25% 0;overflow:hidden;cursor:pointer}.blueimp-gallery .modal-footer{margin:0}.blueimp-gallery .modal-body img,.blueimp-gallery .modal-body .video-content video,.blueimp-gallery .modal-body .video-content iframe,.blueimp-gallery .modal-body .video-content a{max-width:100%;max-height:100%;margin:auto;position:absolute;top:0;right:0;bottom:0;left:0}.blueimp-gallery .modal-body .video-content video{display:none}.blueimp-gallery .modal-body .video-playing video{display:block}.blueimp-gallery .modal-body .video-content iframe{width:100%;height:100%;border:none;left:100%}.blueimp-gallery .modal-body .video-playing iframe{left:0}.blueimp-gallery .modal-body .video-playing img,.blueimp-gallery .modal-body .video-playing a{display:none}.blueimp-gallery .modal-body .video-content a{cursor:pointer}.blueimp-gallery .modal-body .video-content a:after{font-family:"Glyphicons Halflings";-webkit-font-smoothing:antialiased;content:"\e029";font-size:64px;line-height:64px;width:64px;height:64px;position:absolute;top:50%;margin:-32px 0 0 -32px}.blueimp-gallery .modal-body .video-loading a{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery .modal-body .video-loading a:after{content:none}@media screen and (min-width: 768px){.blueimp-gallery .modal-dialog{right:auto;left:auto;width:auto;max-width:1200px;padding-left:5%;padding-right:5%}}/*! ======================================================================== + */.datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:6px}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:7px}.datepicker>div{display:none}.datepicker.days div.datepicker-days{display:block}.datepicker.months div.datepicker-months{display:block}.datepicker.years div.datepicker-years{display:block}.datepicker table{margin:0}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day:hover{background:#eeeeee;cursor:pointer}.datepicker table tr td.old,.datepicker table tr td.new{color:#999999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today:hover,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover{background-color:#fde19a;background-image:-moz-linear-gradient(top, #fdd49a, #fdf59a);background-image:-ms-linear-gradient(top, #fdd49a, #fdf59a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));background-image:-webkit-linear-gradient(top, #fdd49a, #fdf59a);background-image:-o-linear-gradient(top, #fdd49a, #fdf59a);background-image:linear-gradient(to bottom, #fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today:hover,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today[disabled],.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled:hover[disabled]{background-color:#fdf59a}.datepicker table tr td.today:active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:hover.active{background-color:#fbf069 \9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range:hover,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover{background:#eeeeee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(top, #f3c17a, #f3e97a);background-image:-ms-linear-gradient(top, #f3c17a, #f3e97a);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));background-image:-webkit-linear-gradient(top, #f3c17a, #f3e97a);background-image:-o-linear-gradient(top, #f3c17a, #f3e97a);background-image:linear-gradient(to bottom, #f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled:hover[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:hover.active{background-color:#efe24b \9}.datepicker table tr td.selected,.datepicker table tr td.selected:hover,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(top, #b3b3b3, gray);background-image:-ms-linear-gradient(top, #b3b3b3, gray);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(gray));background-image:-webkit-linear-gradient(top, #b3b3b3, gray);background-image:-o-linear-gradient(top, #b3b3b3, gray);background-image:linear-gradient(to bottom, #b3b3b3,#808080);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:#808080 #808080 #595959;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled:hover[disabled]{background-color:#808080}.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:hover.active{background-color:#666666 \9}.datepicker table tr td.active,.datepicker table tr td.active:hover,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td.active:hover,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active[disabled],.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td.active:active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span:hover{background:#eeeeee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:none;color:#999999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover{background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-ms-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #0088cc,#0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled:hover[disabled]{background-color:#0044cc}.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:hover.active{background-color:#003399 \9}.datepicker table tr td span.old,.datepicker table tr td span.new{color:#999999}.datepicker th.datepicker-switch{width:145px}.datepicker thead tr:first-child th,.datepicker tfoot tr th{cursor:pointer}.datepicker thead tr:first-child th:hover,.datepicker tfoot tr th:hover{background:#eeeeee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child th.cw{cursor:default;background-color:transparent}.input-append.date .add-on i,.input-prepend.date .add-on i{display:block;cursor:pointer;width:16px;height:16px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:normal;line-height:18px;text-align:center;text-shadow:0 1px 0 #ffffff;vertical-align:middle;background-color:#eeeeee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}.ui-pnotify{top:36px;right:36px;position:absolute;height:auto;z-index:2}body>.ui-pnotify{position:fixed;z-index:100040}.ui-pnotify-modal-overlay{background-color:rgba(0,0,0,0.4);top:0;left:0;position:absolute;height:100%;width:100%;z-index:1}body>.ui-pnotify-modal-overlay{position:fixed;z-index:100039}.ui-pnotify.ui-pnotify-in{display:block !important}.ui-pnotify.ui-pnotify-move{transition:left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-slow{transition:opacity .6s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move{transition:opacity .6s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-normal{transition:opacity .4s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move{transition:opacity .4s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-fast{transition:opacity .2s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move{transition:opacity .2s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease}.ui-pnotify.ui-pnotify-fade-in{opacity:1}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1);-moz-box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1);box-shadow:0px 6px 28px 0px rgba(0,0,0,0.1)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-container:after{content:" ";visibility:hidden;display:block;height:0;clear:both}.ui-pnotify-container.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-topleft,.ui-pnotify.stack-bottomleft{left:25px;right:auto}.ui-pnotify.stack-bottomright,.ui-pnotify.stack-bottomleft{bottom:25px;top:auto}.ui-pnotify.stack-modal{left:50%;right:auto;margin-left:-150px}.ui-pnotify.ui-pnotify-nonblock-fade{opacity:.2}.ui-pnotify.ui-pnotify-nonblock-hide{display:none !important}.ui-pnotify.stack-bar-bottom{margin-left:15%;margin-bottom:25px;right:auto;bottom:0;top:auto;left:auto}html,body,#sb-site,.sb-site-container,.sb-slidebar{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{width:100%;overflow-x:hidden}html{height:100%}body{min-height:100%;height:auto;position:relative}html.sb-scroll-lock.sb-active:not(.sb-static){overflow:hidden}#sb-site,.sb-site-container{width:100%;position:relative;z-index:1;background:url("../img/pf-bg.jpg") #05050a;background-repeat:no-repeat}.sb-slidebar{height:100%;overflow-y:auto;position:fixed;top:0;z-index:0;display:none;background-color:#313335;-webkit-transform:translate(0px)}.sb-left{left:0;-webkit-box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset -5px 0px 10px 0px rgba(0,0,0,0.4)}.sb-right{right:0;-webkit-box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4);box-shadow:inset 5px 0px 10px 0px rgba(0,0,0,0.4)}html.sb-static .sb-slidebar,.sb-slidebar.sb-static{position:absolute}.sb-slidebar.sb-active{display:block}.sb-style-overlay{z-index:9999}.sb-momentum-scrolling{-webkit-overflow-scrolling:touch}.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}@media (max-width: 480px){.sb-slidebar{width:70%}.sb-width-thin{width:55%}.sb-width-wide{width:85%}}@media (min-width: 481px){.sb-slidebar{width:55%}.sb-width-thin{width:40%}.sb-width-wide{width:70%}}@media (min-width: 768px){.sb-slidebar{width:40%}.sb-width-thin{width:25%}.sb-width-wide{width:55%}}@media (min-width: 992px){.sb-slidebar{width:30%}.sb-width-thin{width:15%}.sb-width-wide{width:45%}}@media (min-width: 1200px){.sb-slidebar{width:20%}.sb-width-thin{width:5%}.sb-width-wide{width:35%}}.sb-slide,#sb-site,.sb-site-container,.sb-slidebar{-webkit-transition:-webkit-transform 400ms ease;-moz-transition:-moz-transform 400ms ease;-o-transition:-o-transform 400ms ease;transition:transform 400ms ease;-webkit-transition-property:-webkit-transform, left, right;-webkit-backface-visibility:hidden}.sb-hide{display:none}.pf-pie-chart{position:relative;display:table-cell;text-align:center;vertical-align:middle}.pf-pie-chart span{display:inline-block}.pf-pie-chart canvas{position:absolute;top:0;left:0}.pf-pie-chart-map-timer{width:36px;height:36px;margin:3px}.pf-pie-chart-map-timer canvas{top:3px;left:3px}.pf-pie-chart-map-timer span{font-size:10px}.pf-pie-chart-map-timer span:after{content:'s';margin-left:1px}div.pf-map-drag-to-select{background:#375959 !important;display:block;visibility:hidden;opacity:0;z-index:9000;border:1px dashed #adadad;will-change:opacity, visibility;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-transition:opacity 0.15s linear,visibility 0.15s linear;transition:opacity 0.15s linear,visibility 0.15s linear}div.pf-map-drag-to-select.active{visibility:visible;opacity:0.3}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;color:#adadad;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.select2-container--pathfinder .select2-selection--single{background-color:#313335;border:1px solid #63676a;border-radius:0px;outline:0}.select2-container--pathfinder .select2-selection--single:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--single .select2-selection__rendered{color:#adadad;line-height:28px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear{color:#a52521;cursor:pointer;float:right;font-weight:bold;margin-right:3px;margin-left:10px}.select2-container--pathfinder .select2-selection--single .select2-selection__clear:hover{color:#58100d}.select2-container--pathfinder .select2-selection--single .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow{background-color:#313335;border:none;border-left:none;border-top-right-radius:0px;border-bottom-right-radius:0px;height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--pathfinder .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--pathfinder[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #63676a;border-radius:0;border-top-left-radius:0px;border-bottom-left-radius:0px;left:1px;right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--single{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--pathfinder.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-selection--multiple{background-color:#313335;color:#313335;border:1px solid #63676a;border-radius:0px;cursor:text;outline:0}.select2-container--pathfinder .select2-selection--multiple:focus{border:1px solid #568a89}.select2-container--pathfinder .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--pathfinder .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice{background-color:#adadad;border:1px solid #63676a;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove{color:#a52521;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--pathfinder .select2-selection--multiple .select2-selection__choice__remove:hover{color:#58100d}.select2-container--pathfinder .select2-selection--multiple .select2-selection__placeholder{color:#63676a}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--pathfinder[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--pathfinder.select2-container--open .select2-selection--multiple{border:1px solid #568a89}.select2-container--pathfinder.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--pathfinder.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--pathfinder .select2-search--dropdown .select2-search__field{border:1px solid #63676a;outline:0}.select2-container--pathfinder .select2-search--inline .select2-search__field{outline:0}.select2-container--pathfinder .select2-dropdown{background-color:#313335;border:1px solid transparent;overflow:hidden;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.3);box-shadow:0 6px 12px rgba(0,0,0,0.3)}.select2-container--pathfinder .select2-dropdown--above{border-bottom:none}.select2-container--pathfinder .select2-dropdown--below{border-top:none}.select2-container--pathfinder .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--pathfinder .select2-results__option[role=group]{padding:0}.select2-container--pathfinder .select2-results__option[aria-disabled=true],.select2-container--pathfinder .select2-results__option[aria-selected=true]{color:#63676a;background-color:#3c3f41}.select2-container--pathfinder .select2-results__option[aria-disabled=true] .pf-select-item-anchor:before,.select2-container--pathfinder .select2-results__option[aria-selected=true] .pf-select-item-anchor:before{content:"\f05e";font-family:FontAwesome;font-size:9px;position:absolute;left:0;top:0;color:#63676a}.select2-container--pathfinder .select2-results__option--highlighted[aria-selected]{background-color:#adadad;color:#313335}.select2-container--pathfinder .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--pathfinder.select2-container--open .select2-dropdown{border-color:#568a89}select.select2-hidden-accessible{-moz-appearance:none;-webkit-appearance:none}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{position:absolute;top:0;right:0;bottom:0;left:0;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content{margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;opacity:1}.blueimp-gallery{position:fixed;z-index:999999;overflow:hidden;background:#000;background:rgba(0,0,0,0.9);opacity:0;display:none;direction:ltr;-ms-touch-action:none;touch-action:none}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;-webkit-box-shadow:0 4px 10px rgba(0,0,0,0.4);box-shadow:0 4px 10px rgba(0,0,0,0.4);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-ms-touch-action:pan-y;touch-action:pan-y}.blueimp-gallery-display{display:block;opacity:1}.blueimp-gallery>.slides{position:relative;height:100%;overflow:hidden}.blueimp-gallery-carousel>.slides{position:absolute}.blueimp-gallery>.slides>.slide{position:relative;float:left;height:100%;text-align:center;will-change:all;-webkit-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-moz-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-ms-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);-o-transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1);transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1)}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-transition:opacity 0.5s linear;-moz-transition:opacity 0.5s linear;-ms-transition:opacity 0.5s linear;-o-transition:opacity 0.5s linear;transition:opacity 0.5s linear}.blueimp-gallery>.slides>.slide-loading{background-size:64px 64px}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery>.prev,.blueimp-gallery>.next{position:absolute;top:50%;left:15px;width:35px;height:35px;margin-top:-17px;font-size:22px;line-height:35px;color:#63676a;text-decoration:none;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;opacity:1;cursor:pointer;display:none}.blueimp-gallery>.next{left:auto;right:15px}.blueimp-gallery>.close,.blueimp-gallery>.title{position:absolute;bottom:15px;left:15px;margin:0 40px 0 0;font-size:14px;line-height:14px;font-font:"Oxygen Bold","Helvetica Neue",Helvetica,Arial,sans-serif;color:#63676a;text-shadow:0 1px 3px #1d1d1d;opacity:1;display:none}.blueimp-gallery>.title{margin-left:20px}.blueimp-gallery>.title:before{content:'\f101';font-family:'FontAwesome';position:absolute;top:-1px;left:-20px;height:14px;width:14px}.blueimp-gallery>.close{padding:15px;right:15px;left:auto;margin:-15px;font-size:30px;text-decoration:none;cursor:pointer}.blueimp-gallery>.play-pause{position:absolute;right:15px;bottom:15px;width:35px;height:35px;font-size:22px;line-height:35px;text-align:center;background:rgba(0,0,0,0.2);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-transition:color 0.09s linear;transition:color 0.09s linear;will-change:color;color:#e28a0d;cursor:pointer;opacity:1;display:none}.blueimp-gallery-playing>.play-pause{color:#2b2b2b}.blueimp-gallery>.prev:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.close:hover,.blueimp-gallery>.play-pause:hover{color:#e28a0d}.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.title,.blueimp-gallery-controls>.play-pause{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.prev,.blueimp-gallery-left>.prev,.blueimp-gallery-single>.next,.blueimp-gallery-right>.next,.blueimp-gallery-single>.play-pause{display:none}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.prev,.blueimp-gallery>.next,.blueimp-gallery>.close,.blueimp-gallery>.play-pause{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:last-child .blueimp-gallery-playing>.play-pause{background-position:-20px 0}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}.blueimp-gallery>.slides>.slide>.text-content{overflow:auto;margin:0 auto;overflow:hidden;text-align:left}.blueimp-gallery .modal-body{position:relative;text-align:center;padding:0 0 56.25% 0;overflow:hidden;cursor:pointer}.blueimp-gallery .modal-footer{margin:0}.blueimp-gallery .modal-body img,.blueimp-gallery .modal-body .video-content video,.blueimp-gallery .modal-body .video-content iframe,.blueimp-gallery .modal-body .video-content a{max-width:100%;max-height:100%;margin:auto;position:absolute;top:0;right:0;bottom:0;left:0}.blueimp-gallery .modal-body .video-content video{display:none}.blueimp-gallery .modal-body .video-playing video{display:block}.blueimp-gallery .modal-body .video-content iframe{width:100%;height:100%;border:none;left:100%}.blueimp-gallery .modal-body .video-playing iframe{left:0}.blueimp-gallery .modal-body .video-playing img,.blueimp-gallery .modal-body .video-playing a{display:none}.blueimp-gallery .modal-body .video-content a{cursor:pointer}.blueimp-gallery .modal-body .video-content a:after{font-family:"Glyphicons Halflings";-webkit-font-smoothing:antialiased;content:"\e029";font-size:64px;line-height:64px;width:64px;height:64px;position:absolute;top:50%;margin:-32px 0 0 -32px}.blueimp-gallery .modal-body .video-loading a{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery .modal-body .video-loading a:after{content:none}@media screen and (min-width: 768px){.blueimp-gallery .modal-dialog{right:auto;left:auto;width:auto;max-width:1200px;padding-left:5%;padding-right:5%}}/*! ======================================================================== * Bootstrap Toggle: bootstrap2-toggle.css v2.2.0 * http://www.bootstraptoggle.com * ======================================================================== diff --git a/public/js/v1.1.3/app.js b/public/js/v1.1.3/app.js index b998ee8a..9864489d 100644 --- a/public/js/v1.1.3/app.js +++ b/public/js/v1.1.3/app.js @@ -63,7 +63,7 @@ requirejs.config({ 'datatables.net-select': 'lib/datatables/Select-1.2.0/js/dataTables.select.min', // notification plugin - pnotify: 'lib/pnotify/pnotify.core', // v2.0.1 PNotify - notification core file + pnotify: 'lib/pnotify/pnotify', // v3.0.0 PNotify - notification core file - https://sciactive.com/pnotify/ 'pnotify.buttons': 'lib/pnotify/pnotify.buttons', // PNotify - buttons notification extension 'pnotify.confirm': 'lib/pnotify/pnotify.confirm', // PNotify - confirmation notification extension 'pnotify.nonblock': 'lib/pnotify/pnotify.nonblock', // PNotify - notification non-block extension (hover effect) diff --git a/public/js/v1.1.3/app/map/map.js b/public/js/v1.1.3/app/map/map.js index 80bee5bc..7ab83621 100644 --- a/public/js/v1.1.3/app/map/map.js +++ b/public/js/v1.1.3/app/map/map.js @@ -66,9 +66,6 @@ define([ systemDialogId: 'pf-system-dialog', // id for system dialog systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element - // local storage - mapLocalStoragePrefix: 'map_', // prefix for map local storage key - // system security classes systemSec: 'pf-system-sec', systemSecHigh: 'pf-system-sec-highSec', @@ -450,68 +447,6 @@ define([ system.addClass( statusClass ); }; - /** - * set or change rallyPoint for systems - * @param rallyUpdated - * @param options - * @returns {*} - */ - $.fn.setSystemRally = function(rallyUpdated, options){ - rallyUpdated = rallyUpdated || 0; - - var defaultOptions = { - poke: false, - hideNotification: false, - hideCounter: false, - }; - options = $.extend({}, defaultOptions, options); - - return this.each(function(){ - var system = $(this); - var rally = system.data('rallyUpdated') || 0; - - if(rallyUpdated !== rally){ - // rally status changed - if( !options.hideCounter ){ - system.getMapOverlay('timer').startMapUpdateCounter(); - } - - var rallyClass = MapUtil.getInfoForSystem('rally', 'class'); - - if(rallyUpdated > 0){ - // new rally point set - system.addClass( rallyClass ); - - if( !options.hideNotification ){ - var systemName = system.getSystemInfo( ['alias'] ); - - var notificationOptions = { - title: 'Rally Point', - text: 'System: ' + systemName, - type: 'success' - }; - - if(options.poke){ - // desktop poke - Util.showNotify(notificationOptions, {desktop: true, stack: 'barBottom'}); - }else{ - Util.showNotify(notificationOptions, {stack: 'barBottom'}); - } - } - }else{ - // rally point removed - system.removeClass( rallyClass ); - - if( !options.hideNotification ){ - Util.showNotify({title: 'Rally point removed', type: 'success'}); - } - } - } - - system.data('rallyUpdated', rallyUpdated); - }); - }; - /** * returns a new system or updates an existing system * @param map @@ -669,6 +604,7 @@ define([ // rally system system.setSystemRally(data.rallyUpdated, { + poke: data.rallyPoke || false, hideNotification: true, hideCounter: true, }); @@ -1904,7 +1840,7 @@ define([ } }, setRallyPoke: { - label: ' Set rally and poke', + label: ' set rally and poke', className: 'btn-primary', callback: function() { currentSystem.setSystemRally(1, { @@ -1914,7 +1850,7 @@ define([ } }, success: { - label: ' save', + label: ' set rally', className: 'btn-success', callback: function() { currentSystem.setSystemRally(1); @@ -2500,7 +2436,7 @@ define([ if(component.data('locked') === true){ activeOptions.push('lock_system'); } - if(component.data('rally') === true){ + if(component.data('rallyUpdated') > 0){ activeOptions.push('set_rally'); } } @@ -2623,7 +2559,6 @@ define([ * @returns {*} */ $.fn.getSystemInfo = function(info){ - var systemInfo = []; for(var i = 0; i < info.length; i++){ @@ -3118,6 +3053,7 @@ define([ }; systemData.locked = system.data('locked') ? 1 : 0; systemData.rallyUpdated = system.data('rallyUpdated') || 0; + systemData.rallyPoke = system.data('rallyPoke') ? 1 : 0; systemData.currentUser = system.data('currentUser'); // if user is currently in this system systemData.statics = system.data('statics'); systemData.updated = { @@ -3337,7 +3273,7 @@ define([ var mapWrapper = mapContainer.parents('.' + config.mapWrapperClass); // auto scroll map to previous position - var promiseStore = getMapData( mapContainer.data('id') ); + var promiseStore = MapUtil.getMapData( mapContainer.data('id') ); promiseStore.then(function(data) { // This code runs once the value has been loaded // from the offline store. @@ -3365,46 +3301,6 @@ define([ }); }; - /** - * get stored map data from client cache (IndexedDB) - * @param mapId - * @returns {*} promise - */ - var getMapData = function(mapId){ - if(mapId > 0){ - var mapStorageKey = config.mapLocalStoragePrefix + mapId; - return Util.localforage.getItem(mapStorageKey); - }else{ - console.error('Map local storage requires mapId > 0'); - } - }; - - /** - * store local map config to client cache (IndexedDB) - * @param mapId - * @param key - * @param value - */ - var storeMapData = function(mapId, key, value){ - if(mapId > 0){ - // get current map config - var mapStorageKey = config.mapLocalStoragePrefix + mapId; - Util.localforage.getItem(mapStorageKey).then(function(data) { - // This code runs once the value has been loaded - // from the offline store. - data = (data === null) ? {} : data; - // set/update value - data[key] = value; - Util.localforage.setItem(mapStorageKey, data); - }).catch(function(err) { - // This code runs if there were any errors - console.error('Map local storage can not be accessed!'); - }); - }else{ - console.error('Map local storage requires mapId > 0'); - } - }; - /** * init scrollbar for Map element */ @@ -3418,7 +3314,7 @@ define([ // scroll complete var mapElement = $(this).find('.' + config.mapClass); // store new map scrollOffset -> localDB - storeMapData( mapElement.data('id'), 'offsetX', Math.abs(this.mcs.left) ); + MapUtil.storeMapData( mapElement.data('id'), 'offsetX', Math.abs(this.mcs.left) ); }, onScrollStart: function(){ // hide all open xEditable fields diff --git a/public/js/v1.1.3/app/map/util.js b/public/js/v1.1.3/app/map/util.js index a52fd8f6..e41b0934 100644 --- a/public/js/v1.1.3/app/map/util.js +++ b/public/js/v1.1.3/app/map/util.js @@ -9,6 +9,11 @@ define([ ], function($, Init, Util) { 'use strict'; + var config = { + // local storage + mapLocalStoragePrefix: 'map_', // prefix for map local storage key + }; + /** * get all available map Types * optional they can be filtered by current access level of a user @@ -326,6 +331,171 @@ define([ return scopeInfo; }; + /** + * set or change rallyPoint for systems + * @param rallyUpdated + * @param options + * @returns {*} + */ + $.fn.setSystemRally = function(rallyUpdated, options){ + rallyUpdated = rallyUpdated || 0; + var rallyPoke = false; + + var defaultOptions = { + poke: false, + hideNotification: false, + hideCounter: false, + }; + options = $.extend({}, defaultOptions, options); + + return this.each(function(){ + var system = $(this); + var rally = system.data('rallyUpdated') || 0; + + if(rallyUpdated !== rally){ + // rally status changed + if( !options.hideCounter ){ + system.getMapOverlay('timer').startMapUpdateCounter(); + } + + var rallyClass = getInfoForSystem('rally', 'class'); + + if(rallyUpdated > 0){ + // new rally point set OR update system with rally information + + system.addClass( rallyClass ); + // rallyUpdated > 0 is required for poke! + rallyPoke = options.poke; + + var notificationOptions = { + title: 'Rally Point', + text: 'System: ' + system.data('name') + }; + + if(rallyUpdated === 1){ + // rally point not saved on DB + notificationOptions.type = 'success'; + Util.showNotify(notificationOptions); + }else if(options.poke){ + // rally saved AND poke option active + + // check if desktop notification was already send + var mapId = system.data('mapid'); + var systemId = system.data('id'); + var promiseStore = getMapData(mapId); + promiseStore.then(function(data) { + // This code runs once the value has been loaded + // from the offline store. + var rallyPokeData = {}; + + if( + data && + data.rallyPoke + ){ + // poke data exists + rallyPokeData = data.rallyPoke; + } + + if( + !rallyPokeData.hasOwnProperty(this.systemId) || // rally poke was not already send to client + rallyPokeData[this.systemId] !== rallyUpdated // already send to that system but in the past + ){ + rallyPokeData[this.systemId] = rallyUpdated; + storeMapData(this.mapId, 'rallyPoke', rallyPokeData); + + notificationOptions.type = 'info'; + Util.showNotify(notificationOptions, {desktop: true, stack: 'barBottom'}); + } + }.bind({ + mapId: mapId, + systemId: systemId, + rallyUpdated: rallyUpdated + })); + } + }else{ + // rally point removed + system.removeClass( rallyClass ); + + if( !options.hideNotification ){ + Util.showNotify({title: 'Rally point removed', type: 'success'}); + } + } + } + + system.data('rallyUpdated', rallyUpdated); + system.data('rallyPoke', rallyPoke); + }); + }; + + /** + * get stored map data from client cache (IndexedDB) + * @param mapId + * @returns {*} promise + */ + var getMapData = function(mapId){ + if(mapId > 0){ + var mapStorageKey = config.mapLocalStoragePrefix + mapId; + return Util.localforage.getItem(mapStorageKey); + }else{ + console.error('Map local storage requires mapId > 0'); + } + }; + + /** + * store local map config to client cache (IndexedDB) + * @param mapId + * @param key + * @param value + */ + var storeMapData = function(mapId, key, value){ + if(mapId > 0){ + // get current map config + var mapStorageKey = config.mapLocalStoragePrefix + mapId; + Util.localforage.getItem(mapStorageKey).then(function(data) { + // This code runs once the value has been loaded + // from the offline store. + data = (data === null) ? {} : data; + // set/update value + data[this.key] = this.value; + Util.localforage.setItem(this.mapStorageKey, data); + }.bind({ + key: key, + value: value, + mapStorageKey: mapStorageKey + })).catch(function(err) { + // This code runs if there were any errors + console.error('Map local storage can not be accessed!'); + }); + }else{ + console.error('storeMapData(): Local storage requires mapId > 0'); + } + }; + + /** + * delete local map configuration by key (IndexedDB) + * @param mapId + * @param key + */ + var deleteMapData = function(mapId, key){ + if(mapId > 0){ + // get current map config + var mapStorageKey = config.mapLocalStoragePrefix + mapId; + Util.localforage.getItem(mapStorageKey).then(function(data) { + if( + data && + data.hasOwnProperty(key) + ){ + delete data[key]; + Util.localforage.setItem(this.mapStorageKey, data); + } + }.bind({ + mapStorageKey: mapStorageKey + })); + }else{ + console.error('deleteMapData(): Local storage requires mapId > 0'); + } + }; + return { getMapTypes: getMapTypes, getMapScopes: getMapScopes, @@ -341,6 +511,9 @@ define([ checkForConnection: checkForConnection, getDefaultConnectionTypeByScope: getDefaultConnectionTypeByScope, setConnectionWHStatus: setConnectionWHStatus, - getScopeInfoForConnection: getScopeInfoForConnection + getScopeInfoForConnection: getScopeInfoForConnection, + getMapData: getMapData, + storeMapData: storeMapData, + deleteMapData: deleteMapData }; }); \ No newline at end of file diff --git a/public/js/v1.1.3/app/module_map.js b/public/js/v1.1.3/app/module_map.js index 404b188f..17f5a5b9 100644 --- a/public/js/v1.1.3/app/module_map.js +++ b/public/js/v1.1.3/app/module_map.js @@ -49,13 +49,10 @@ define([ /** * get all maps for a maps module - * @param mapModule * @returns {*} */ $.fn.getMaps = function(){ - var maps = $(this).find('.' + config.mapClass); - return maps; }; diff --git a/public/js/v1.1.3/app/notification.js b/public/js/v1.1.3/app/notification.js index 41490338..443858ab 100644 --- a/public/js/v1.1.3/app/notification.js +++ b/public/js/v1.1.3/app/notification.js @@ -17,31 +17,18 @@ define([ text: '', type: '', // 'info', 'success', error, 'warning' icon: false, - opacity: 0.8, styling: 'fontawesome', // 'fontawesome', 'bootstrap3', 'jqueryui' - animate_speed: 200, // effect animation - position_animate_speed: 100, // animation speed for notifications moving up/down + animate_speed: 'fast', // animation speed for notifications moving up/down hide: true, // close after few seconds delay: 5000, // visible time for notification in browser mouse_reset: true, // Reset the hide timer if the mouse moves over the notice. shadow: true, addclass: 'stack-bottomright', // class for display, must changed on stack different stacks width: '250px', - // animation settings - animation: { - 'effect_in': 'fade', - 'options_in': { - easing: 'linear' - }, - 'effect_out': 'fade', - 'options_out': { - easing: 'linear' - } - }, // nonblock extension parameter (click through notifications) nonblock: { - nonblock: true, - nonblock_opacity: 0.2 + nonblock: true, // change for enable + nonblock_opacity: 0.9 }, // desktop extension "Web Notifications" desktop: { @@ -64,42 +51,28 @@ define([ }, addclass: 'stack-bottomright', width: '250px', - opacity: 0.8 - }, - barTop: { - stack: { - dir1: 'down', - dir2: 'right', - push: 'top', - spacing1: 0, - spacing2: 0, - - }, - addclass: 'stack-bar-top', - width: '80%', - opacity: 1 }, barBottom: { stack: { dir1: 'up', dir2: 'right', - firstpos1: 30, + // context: $('body'), spacing1: 0, spacing2: 0 }, addclass: 'stack-bar-bottom', - width: '100%', - opacity: 1 + width: '70%', } }; /** * show a notification in browser and/or "Web Notifications" in OS * @param customConfig + * @param settings */ var showNotify = function(customConfig, settings){ - customConfig = $.extend({}, config, customConfig ); + customConfig = $.extend(true, {}, config, customConfig ); // desktop notification if( @@ -114,10 +87,6 @@ define([ // make browser tab blink startTabBlink(customConfig.title); - - }else{ - customConfig.delay = 5000; - customConfig.desktop.desktop = false; } // set notification stack @@ -128,11 +97,9 @@ define([ customConfig.stack = stack[settings.stack].stack; customConfig.addclass = stack[settings.stack].addclass; customConfig.width = stack[settings.stack].width; - customConfig.opacity = stack[settings.stack].opacity; }else{ customConfig.stack = stack.bottomRight.stack; customConfig.addclass = stack.bottomRight.addclass; - customConfig.opacity = stack.bottomRight.opacity; } switch(customConfig.type){ @@ -168,7 +135,6 @@ define([ * @param blinkTitle */ var startTabBlink = function(blinkTitle){ - var initBlink = (function(blinkTitle){ var currentTitle = document.title; @@ -195,10 +161,8 @@ define([ }( blinkTitle )); initBlink(); - }; - return { showNotify: showNotify, startTabBlink: startTabBlink diff --git a/public/js/v1.1.3/lib/pnotify/pnotify.buttons.js b/public/js/v1.1.3/lib/pnotify/pnotify.buttons.js new file mode 100644 index 00000000..27a97fd0 --- /dev/null +++ b/public/js/v1.1.3/lib/pnotify/pnotify.buttons.js @@ -0,0 +1,176 @@ +// Buttons +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.buttons', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ + PNotify.prototype.options.buttons = { + // Provide a button for the user to manually close the notice. + closer: true, + // Only show the closer button on hover. + closer_hover: true, + // Provide a button for the user to manually stick the notice. + sticker: true, + // Only show the sticker button on hover. + sticker_hover: true, + // Show the buttons even when the nonblock module is in use. + show_on_nonblock: false, + // The various displayed text, helps facilitating internationalization. + labels: { + close: "Close", + stick: "Stick", + unstick: "Unstick" + }, + // The classes to use for button icons. Leave them null to use the classes from the styling you're using. + classes: { + closer: null, + pin_up: null, + pin_down: null + } + }; + PNotify.prototype.modules.buttons = { + closer: null, + sticker: null, + + init: function(notice, options){ + var that = this; + notice.elem.on({ + "mouseenter": function(e){ + // Show the buttons. + if (that.options.sticker && (!(notice.options.nonblock && notice.options.nonblock.nonblock) || that.options.show_on_nonblock)) { + that.sticker.trigger("pnotify:buttons:toggleStick").css("visibility", "visible"); + } + if (that.options.closer && (!(notice.options.nonblock && notice.options.nonblock.nonblock) || that.options.show_on_nonblock)) { + that.closer.css("visibility", "visible"); + } + }, + "mouseleave": function(e){ + // Hide the buttons. + if (that.options.sticker_hover) { + that.sticker.css("visibility", "hidden"); + } + if (that.options.closer_hover) { + that.closer.css("visibility", "hidden"); + } + } + }); + + // Provide a button to stick the notice. + this.sticker = $("
", { + "class": "ui-pnotify-sticker", + "aria-role": "button", + "aria-pressed": notice.options.hide ? "false" : "true", + "tabindex": "0", + "title": notice.options.hide ? options.labels.stick : options.labels.unstick, + "css": { + "cursor": "pointer", + "visibility": options.sticker_hover ? "hidden" : "visible" + }, + "click": function(){ + notice.options.hide = !notice.options.hide; + if (notice.options.hide) { + notice.queueRemove(); + } else { + notice.cancelRemove(); + } + $(this).trigger("pnotify:buttons:toggleStick"); + } + }) + .bind("pnotify:buttons:toggleStick", function(){ + var pin_up = that.options.classes.pin_up === null ? notice.styles.pin_up : that.options.classes.pin_up; + var pin_down = that.options.classes.pin_down === null ? notice.styles.pin_down : that.options.classes.pin_down; + $(this) + .attr("title", notice.options.hide ? that.options.labels.stick : that.options.labels.unstick) + .children() + .attr("class", "") + .addClass(notice.options.hide ? pin_up : pin_down) + .attr("aria-pressed", notice.options.hide ? "false" : "true"); + }) + .append("") + .trigger("pnotify:buttons:toggleStick") + .prependTo(notice.container); + if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.sticker.css("display", "none"); + } + + // Provide a button to close the notice. + this.closer = $("
", { + "class": "ui-pnotify-closer", + "aria-role": "button", + "tabindex": "0", + "title": options.labels.close, + "css": {"cursor": "pointer", "visibility": options.closer_hover ? "hidden" : "visible"}, + "click": function(){ + notice.remove(false); + that.sticker.css("visibility", "hidden"); + that.closer.css("visibility", "hidden"); + } + }) + .append($("", {"class": options.classes.closer === null ? notice.styles.closer : options.classes.closer})) + .prependTo(notice.container); + if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.closer.css("display", "none"); + } + }, + update: function(notice, options){ + // Update the sticker and closer buttons. + if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.closer.css("display", "none"); + } else if (options.closer) { + this.closer.css("display", "block"); + } + if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.sticker.css("display", "none"); + } else if (options.sticker) { + this.sticker.css("display", "block"); + } + // Update the sticker icon. + this.sticker.trigger("pnotify:buttons:toggleStick"); + // Update the close icon. + this.closer.find("span").attr("class", "").addClass(options.classes.closer === null ? notice.styles.closer : options.classes.closer); + // Update the hover status of the buttons. + if (options.sticker_hover) { + this.sticker.css("visibility", "hidden"); + } else if (!(notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.sticker.css("visibility", "visible"); + } + if (options.closer_hover) { + this.closer.css("visibility", "hidden"); + } else if (!(notice.options.nonblock && notice.options.nonblock.nonblock && !options.show_on_nonblock)) { + this.closer.css("visibility", "visible"); + } + } + }; + $.extend(PNotify.styling.brighttheme, { + closer: "brighttheme-icon-closer", + pin_up: "brighttheme-icon-sticker", + pin_down: "brighttheme-icon-sticker brighttheme-icon-stuck" + }); + $.extend(PNotify.styling.jqueryui, { + closer: "ui-icon ui-icon-close", + pin_up: "ui-icon ui-icon-pin-w", + pin_down: "ui-icon ui-icon-pin-s" + }); + $.extend(PNotify.styling.bootstrap2, { + closer: "icon-remove", + pin_up: "icon-pause", + pin_down: "icon-play" + }); + $.extend(PNotify.styling.bootstrap3, { + closer: "glyphicon glyphicon-remove", + pin_up: "glyphicon glyphicon-pause", + pin_down: "glyphicon glyphicon-play" + }); + $.extend(PNotify.styling.fontawesome, { + closer: "fa fa-times", + pin_up: "fa fa-pause", + pin_down: "fa fa-play" + }); +})); diff --git a/public/js/v1.1.3/lib/pnotify/pnotify.callbacks.js b/public/js/v1.1.3/lib/pnotify/pnotify.callbacks.js index a1563a3a..e24b13c5 100644 --- a/public/js/v1.1.3/lib/pnotify/pnotify.callbacks.js +++ b/public/js/v1.1.3/lib/pnotify/pnotify.callbacks.js @@ -1,14 +1,16 @@ // Callbacks -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify.callbacks', ['jquery', 'pnotify'], factory); - } else { - // Browser globals - factory(jQuery, PNotify); - } -}(function($, PNotify){ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.callbacks', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ var _init = PNotify.prototype.init, _open = PNotify.prototype.open, _remove = PNotify.prototype.remove; diff --git a/public/js/v1.1.3/lib/pnotify/pnotify.core.js b/public/js/v1.1.3/lib/pnotify/pnotify.core.js deleted file mode 100644 index c54d93fe..00000000 --- a/public/js/v1.1.3/lib/pnotify/pnotify.core.js +++ /dev/null @@ -1,778 +0,0 @@ -/* -PNotify 2.0.1 sciactive.com/pnotify/ -(C) 2014 Hunter Perrin -license GPL/LGPL/MPL -*/ -/* - * ====== PNotify ====== - * - * http://sciactive.com/pnotify/ - * - * Copyright 2009-2014 Hunter Perrin - * - * Triple licensed under the GPL, LGPL, and MPL. - * http://gnu.org/licenses/gpl.html - * http://gnu.org/licenses/lgpl.html - * http://mozilla.org/MPL/MPL-1.1.html - */ - -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify', ['jquery'], factory); - } else { - // Browser globals - factory(jQuery); - } -}(function($){ - var default_stack = { - dir1: "down", - dir2: "left", - push: "bottom", - spacing1: 25, - spacing2: 25, - context: $("body") - }; - var timer, // Position all timer. - body, - jwindow = $(window); - // Set global variables. - var do_when_ready = function(){ - body = $("body"); - PNotify.prototype.options.stack.context = body; - jwindow = $(window); - // Reposition the notices when the window resizes. - jwindow.bind('resize', function(){ - if (timer) - clearTimeout(timer); - timer = setTimeout(function(){ PNotify.positionAll(true) }, 10); - }); - }; - PNotify = function(options){ - this.parseOptions(options); - this.init(); - }; - $.extend(PNotify.prototype, { - // The current version of PNotify. - version: "2.0.1", - - // === Options === - - // Options defaults. - options: { - // The notice's title. - title: false, - // Whether to escape the content of the title. (Not allow HTML.) - title_escape: false, - // The notice's text. - text: false, - // Whether to escape the content of the text. (Not allow HTML.) - text_escape: false, - // What styling classes to use. (Can be either jqueryui or bootstrap.) - styling: "bootstrap3", - // Additional classes to be added to the notice. (For custom styling.) - addclass: "", - // Class to be added to the notice for corner styling. - cornerclass: "", - // Display the notice when it is created. - auto_display: true, - // Width of the notice. - width: "300px", - // Minimum height of the notice. It will expand to fit content. - min_height: "16px", - // Type of the notice. "notice", "info", "success", or "error". - type: "notice", - // Set icon to true to use the default icon for the selected - // style/type, false for no icon, or a string for your own icon class. - icon: true, - // Opacity of the notice. - opacity: 1, - // The animation to use when displaying and hiding the notice. "none", - // "show", "fade", and "slide" are built in to jQuery. Others require jQuery - // UI. Use an object with effect_in and effect_out to use different effects. - animation: "fade", - // Speed at which the notice animates in and out. "slow", "def" or "normal", - // "fast" or number of milliseconds. - animate_speed: "slow", - // Specify a specific duration of position animation - position_animate_speed: 500, - // Display a drop shadow. - shadow: true, - // After a delay, remove the notice. - hide: true, - // Delay in milliseconds before the notice is removed. - delay: 8000, - // Reset the hide timer if the mouse moves over the notice. - mouse_reset: true, - // Remove the notice's elements from the DOM after it is removed. - remove: true, - // Change new lines to br tags. - insert_brs: true, - // Whether to remove notices from the global array. - destroy: true, - // The stack on which the notices will be placed. Also controls the - // direction the notices stack. - stack: default_stack - }, - - // === Modules === - - // This object holds all the PNotify modules. They are used to provide - // additional functionality. - modules: {}, - // This runs an event on all the modules. - runModules: function(event, arg){ - var curArg; - for (var module in this.modules) { - curArg = ((typeof arg === "object" && module in arg) ? arg[module] : arg); - if (typeof this.modules[module][event] === 'function') - this.modules[module][event](this, typeof this.options[module] === 'object' ? this.options[module] : {}, curArg); - } - }, - - // === Class Variables === - - state: "initializing", // The state can be "initializing", "opening", "open", "closing", and "closed". - timer: null, // Auto close timer. - styles: null, - elem: null, - container: null, - title_container: null, - text_container: null, - animating: false, // Stores what is currently being animated (in or out). - timerHide: false, // Stores whether the notice was hidden by a timer. - - // === Events === - - init: function(){ - var that = this; - - // First and foremost, we don't want our module objects all referencing the prototype. - this.modules = {}; - $.extend(true, this.modules, PNotify.prototype.modules); - - // Get our styling object. - if (typeof this.options.styling === "object") { - this.styles = this.options.styling; - } else { - this.styles = PNotify.styling[this.options.styling]; - } - - // Create our widget. - // Stop animation, reset the removal timer when the user mouses over. - this.elem = $("
", { - "class": "ui-pnotify "+this.options.addclass, - "css": {"display": "none"}, - "mouseenter": function(e){ - if (that.options.mouse_reset && that.animating === "out") { - if (!that.timerHide) - return; - that.cancelRemove(); - } - // Stop the close timer. - if (that.options.hide && that.options.mouse_reset) that.cancelRemove(); - }, - "mouseleave": function(e){ - // Start the close timer. - if (that.options.hide && that.options.mouse_reset) that.queueRemove(); - PNotify.positionAll(); - } - }); - // Create a container for the notice contents. - this.container = $("
", {"class": this.styles.container+" ui-pnotify-container "+(this.options.type === "error" ? this.styles.error : (this.options.type === "info" ? this.styles.info : (this.options.type === "success" ? this.styles.success : this.styles.notice)))}) - .appendTo(this.elem); - if (this.options.cornerclass !== "") - this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass); - // Create a drop shadow. - if (this.options.shadow) - this.container.addClass("ui-pnotify-shadow"); - - - // Add the appropriate icon. - if (this.options.icon !== false) { - $("
", {"class": "ui-pnotify-icon"}) - .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) - .prependTo(this.container); - } - - // Add a title. - this.title_container = $("

", { - "class": "ui-pnotify-title" - }) - .appendTo(this.container); - if (this.options.title === false) - this.title_container.hide(); - else if (this.options.title_escape) - this.title_container.text(this.options.title); - else - this.title_container.html(this.options.title); - - // Add text. - this.text_container = $("
", { - "class": "ui-pnotify-text" - }) - .appendTo(this.container); - if (this.options.text === false) - this.text_container.hide(); - else if (this.options.text_escape) - this.text_container.text(this.options.text); - else - this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); - - // Set width and min height. - if (typeof this.options.width === "string") - this.elem.css("width", this.options.width); - if (typeof this.options.min_height === "string") - this.container.css("min-height", this.options.min_height); - - - // Add the notice to the notice array. - if (this.options.stack.push === "top") - PNotify.notices = $.merge([this], PNotify.notices); - else - PNotify.notices = $.merge(PNotify.notices, [this]); - // Now position all the notices if they are to push to the top. - if (this.options.stack.push === "top") - this.queuePosition(false, 1); - - - - - // Mark the stack so it won't animate the new notice. - this.options.stack.animation = false; - - // Run the modules. - this.runModules('init'); - - // Display the notice. - if (this.options.auto_display) - this.open(); - return this; - }, - - // This function is for updating the notice. - update: function(options){ - // Save old options. - var oldOpts = this.options; - // Then update to the new options. - this.parseOptions(oldOpts, options); - // Update the corner class. - if (this.options.cornerclass !== oldOpts.cornerclass) - this.container.removeClass("ui-corner-all "+oldOpts.cornerclass).addClass(this.options.cornerclass); - // Update the shadow. - if (this.options.shadow !== oldOpts.shadow) { - if (this.options.shadow) - this.container.addClass("ui-pnotify-shadow"); - else - this.container.removeClass("ui-pnotify-shadow"); - } - // Update the additional classes. - if (this.options.addclass === false) - this.elem.removeClass(oldOpts.addclass); - else if (this.options.addclass !== oldOpts.addclass) - this.elem.removeClass(oldOpts.addclass).addClass(this.options.addclass); - // Update the title. - if (this.options.title === false) - this.title_container.slideUp("fast"); - else if (this.options.title !== oldOpts.title) { - if (this.options.title_escape) - this.title_container.text(this.options.title); - else - this.title_container.html(this.options.title); - if (oldOpts.title === false) - this.title_container.slideDown(200) - } - // Update the text. - if (this.options.text === false) { - this.text_container.slideUp("fast"); - } else if (this.options.text !== oldOpts.text) { - if (this.options.text_escape) - this.text_container.text(this.options.text); - else - this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); - if (oldOpts.text === false) - this.text_container.slideDown(200) - } - // Change the notice type. - if (this.options.type !== oldOpts.type) - this.container.removeClass( - this.styles.error+" "+this.styles.notice+" "+this.styles.success+" "+this.styles.info - ).addClass(this.options.type === "error" ? - this.styles.error : - (this.options.type === "info" ? - this.styles.info : - (this.options.type === "success" ? - this.styles.success : - this.styles.notice - ) - ) - ); - if (this.options.icon !== oldOpts.icon || (this.options.icon === true && this.options.type !== oldOpts.type)) { - // Remove any old icon. - this.container.find("div.ui-pnotify-icon").remove(); - if (this.options.icon !== false) { - // Build the new icon. - $("
", {"class": "ui-pnotify-icon"}) - .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) - .prependTo(this.container); - } - } - // Update the width. - if (this.options.width !== oldOpts.width) - this.elem.animate({width: this.options.width}); - // Update the minimum height. - if (this.options.min_height !== oldOpts.min_height) - this.container.animate({minHeight: this.options.min_height}); - // Update the opacity. - if (this.options.opacity !== oldOpts.opacity) - this.elem.fadeTo(this.options.animate_speed, this.options.opacity); - // Update the timed hiding. - if (!this.options.hide) - this.cancelRemove(); - else if (!oldOpts.hide) - this.queueRemove(); - this.queuePosition(true); - - // Run the modules. - this.runModules('update', oldOpts); - return this; - }, - - // Display the notice. - open: function(){ - this.state = "opening"; - // Run the modules. - this.runModules('beforeOpen'); - - var that = this; - // If the notice is not in the DOM, append it. - if (!this.elem.parent().length) - this.elem.appendTo(this.options.stack.context ? this.options.stack.context : body); - // Try to put it in the right position. - if (this.options.stack.push !== "top") - this.position(true); - // First show it, then set its opacity, then hide it. - if (this.options.animation === "fade" || this.options.animation.effect_in === "fade") { - // If it's fading in, it should start at 0. - this.elem.show().fadeTo(0, 0).hide(); - } else { - // Or else it should be set to the opacity. - if (this.options.opacity !== 1) - this.elem.show().fadeTo(0, this.options.opacity).hide(); - } - this.animateIn(function(){ - that.queuePosition(true); - - // Now set it to hide. - if (that.options.hide) - that.queueRemove(); - - that.state = "open"; - - // Run the modules. - that.runModules('afterOpen'); - }); - - return this; - }, - - // Remove the notice. - remove: function(timer_hide) { - this.state = "closing"; - this.timerHide = !!timer_hide; // Make sure it's a boolean. - // Run the modules. - this.runModules('beforeClose'); - - var that = this; - if (this.timer) { - window.clearTimeout(this.timer); - this.timer = null; - } - this.animateOut(function(){ - that.state = "closed"; - // Run the modules. - that.runModules('afterClose'); - that.queuePosition(true); - // If we're supposed to remove the notice from the DOM, do it. - if (that.options.remove) - that.elem.detach(); - // Run the modules. - that.runModules('beforeDestroy'); - // Remove object from PNotify.notices to prevent memory leak (issue #49) - // unless destroy is off - if (that.options.destroy) { - if (PNotify.notices !== null) { - var idx = $.inArray(that,PNotify.notices); - if (idx !== -1) { - PNotify.notices.splice(idx,1); - } - } - } - // Run the modules. - that.runModules('afterDestroy'); - }); - - return this; - }, - - // === Class Methods === - - // Get the DOM element. - get: function(){ return this.elem; }, - - // Put all the options in the right places. - parseOptions: function(options, moreOptions){ - this.options = $.extend(true, {}, PNotify.prototype.options); - // This is the only thing that *should* be copied by reference. - this.options.stack = PNotify.prototype.options.stack; - var optArray = [options, moreOptions], curOpts; - for (var curIndex in optArray) { - curOpts = optArray[curIndex]; - if (typeof curOpts == "undefined") - break; - if (typeof curOpts !== 'object') { - this.options.text = curOpts; - } else { - for (var option in curOpts) { - if (this.modules[option]) { - // Avoid overwriting module defaults. - $.extend(true, this.options[option], curOpts[option]); - } else { - this.options[option] = curOpts[option]; - } - } - } - } - }, - - // Animate the notice in. - animateIn: function(callback){ - // Declare that the notice is animating in. (Or has completed animating in.) - this.animating = "in"; - var animation; - if (typeof this.options.animation.effect_in !== "undefined") - animation = this.options.animation.effect_in; - else - animation = this.options.animation; - if (animation === "none") { - this.elem.show(); - callback(); - } else if (animation === "show") - this.elem.show(this.options.animate_speed, callback); - else if (animation === "fade") - this.elem.show().fadeTo(this.options.animate_speed, this.options.opacity, callback); - else if (animation === "slide") - this.elem.slideDown(this.options.animate_speed, callback); - else if (typeof animation === "function") - animation("in", callback, this.elem); - else - this.elem.show(animation, (typeof this.options.animation.options_in === "object" ? this.options.animation.options_in : {}), this.options.animate_speed, callback); - if (this.elem.parent().hasClass('ui-effects-wrapper')) - this.elem.parent().css({"position": "fixed", "overflow": "visible"}); - if (animation !== "slide") - this.elem.css("overflow", "visible"); - this.container.css("overflow", "hidden"); - }, - - // Animate the notice out. - animateOut: function(callback){ - // Declare that the notice is animating out. (Or has completed animating out.) - this.animating = "out"; - var animation; - if (typeof this.options.animation.effect_out !== "undefined") - animation = this.options.animation.effect_out; - else - animation = this.options.animation; - if (animation === "none") { - this.elem.hide(); - callback(); - } else if (animation === "show") - this.elem.hide(this.options.animate_speed, callback); - else if (animation === "fade") - this.elem.fadeOut(this.options.animate_speed, callback); - else if (animation === "slide") - this.elem.slideUp(this.options.animate_speed, callback); - else if (typeof animation === "function") - animation("out", callback, this.elem); - else - this.elem.hide(animation, (typeof this.options.animation.options_out === "object" ? this.options.animation.options_out : {}), this.options.animate_speed, callback); - if (this.elem.parent().hasClass('ui-effects-wrapper')) - this.elem.parent().css({"position": "fixed", "overflow": "visible"}); - if (animation !== "slide") - this.elem.css("overflow", "visible"); - this.container.css("overflow", "hidden"); - }, - - // Position the notice. dont_skip_hidden causes the notice to - // position even if it's not visible. - position: function(dontSkipHidden){ - // Get the notice's stack. - var s = this.options.stack, - e = this.elem; - if (e.parent().hasClass('ui-effects-wrapper')) - e = this.elem.css({"left": "0", "top": "0", "right": "0", "bottom": "0"}).parent(); - if (typeof s.context === "undefined") - s.context = body; - if (!s) return; - if (typeof s.nextpos1 !== "number") - s.nextpos1 = s.firstpos1; - if (typeof s.nextpos2 !== "number") - s.nextpos2 = s.firstpos2; - if (typeof s.addpos2 !== "number") - s.addpos2 = 0; - var hidden = e.css("display") === "none"; - // Skip this notice if it's not shown. - if (!hidden || dontSkipHidden) { - var curpos1, curpos2; - // Store what will need to be animated. - var animate = {}; - // Calculate the current pos1 value. - var csspos1; - switch (s.dir1) { - case "down": - csspos1 = "top"; - break; - case "up": - csspos1 = "bottom"; - break; - case "left": - csspos1 = "right"; - break; - case "right": - csspos1 = "left"; - break; - } - curpos1 = parseInt(e.css(csspos1).replace(/(?:\..*|[^0-9.])/g, '')); - if (isNaN(curpos1)) - curpos1 = 0; - // Remember the first pos1, so the first visible notice goes there. - if (typeof s.firstpos1 === "undefined" && !hidden) { - s.firstpos1 = curpos1; - s.nextpos1 = s.firstpos1; - } - // Calculate the current pos2 value. - var csspos2; - switch (s.dir2) { - case "down": - csspos2 = "top"; - break; - case "up": - csspos2 = "bottom"; - break; - case "left": - csspos2 = "right"; - break; - case "right": - csspos2 = "left"; - break; - } - curpos2 = parseInt(e.css(csspos2).replace(/(?:\..*|[^0-9.])/g, '')); - if (isNaN(curpos2)) - curpos2 = 0; - // Remember the first pos2, so the first visible notice goes there. - if (typeof s.firstpos2 === "undefined" && !hidden) { - s.firstpos2 = curpos2; - s.nextpos2 = s.firstpos2; - } - // Check that it's not beyond the viewport edge. - if ((s.dir1 === "down" && s.nextpos1 + e.height() > (s.context.is(body) ? jwindow.height() : s.context.prop('scrollHeight')) ) || - (s.dir1 === "up" && s.nextpos1 + e.height() > (s.context.is(body) ? jwindow.height() : s.context.prop('scrollHeight')) ) || - (s.dir1 === "left" && s.nextpos1 + e.width() > (s.context.is(body) ? jwindow.width() : s.context.prop('scrollWidth')) ) || - (s.dir1 === "right" && s.nextpos1 + e.width() > (s.context.is(body) ? jwindow.width() : s.context.prop('scrollWidth')) ) ) { - // If it is, it needs to go back to the first pos1, and over on pos2. - s.nextpos1 = s.firstpos1; - s.nextpos2 += s.addpos2 + (typeof s.spacing2 === "undefined" ? 25 : s.spacing2); - s.addpos2 = 0; - } - // Animate if we're moving on dir2. - if (s.animation && s.nextpos2 < curpos2) { - switch (s.dir2) { - case "down": - animate.top = s.nextpos2+"px"; - break; - case "up": - animate.bottom = s.nextpos2+"px"; - break; - case "left": - animate.right = s.nextpos2+"px"; - break; - case "right": - animate.left = s.nextpos2+"px"; - break; - } - } else { - if(typeof s.nextpos2 === "number") - e.css(csspos2, s.nextpos2+"px"); - } - // Keep track of the widest/tallest notice in the column/row, so we can push the next column/row. - switch (s.dir2) { - case "down": - case "up": - if (e.outerHeight(true) > s.addpos2) - s.addpos2 = e.height(); - break; - case "left": - case "right": - if (e.outerWidth(true) > s.addpos2) - s.addpos2 = e.width(); - break; - } - // Move the notice on dir1. - if (typeof s.nextpos1 === "number") { - // Animate if we're moving toward the first pos. - if (s.animation && (curpos1 > s.nextpos1 || animate.top || animate.bottom || animate.right || animate.left)) { - switch (s.dir1) { - case "down": - animate.top = s.nextpos1+"px"; - break; - case "up": - animate.bottom = s.nextpos1+"px"; - break; - case "left": - animate.right = s.nextpos1+"px"; - break; - case "right": - animate.left = s.nextpos1+"px"; - break; - } - } else - e.css(csspos1, s.nextpos1+"px"); - } - // Run the animation. - if (animate.top || animate.bottom || animate.right || animate.left) - e.animate(animate, {duration: this.options.position_animate_speed, queue: false}); - // Calculate the next dir1 position. - switch (s.dir1) { - case "down": - case "up": - s.nextpos1 += e.height() + (typeof s.spacing1 === "undefined" ? 25 : s.spacing1); - break; - case "left": - case "right": - s.nextpos1 += e.width() + (typeof s.spacing1 === "undefined" ? 25 : s.spacing1); - break; - } - } - return this; - }, - // Queue the position all function so it doesn't run repeatedly and - // use up resources. - queuePosition: function(animate, milliseconds){ - if (timer) - clearTimeout(timer); - if (!milliseconds) - milliseconds = 10; - timer = setTimeout(function(){ PNotify.positionAll(animate) }, milliseconds); - return this; - }, - - - // Cancel any pending removal timer. - cancelRemove: function(){ - if (this.timer) - window.clearTimeout(this.timer); - if (this.state === "closing") { - // If it's animating out, animate back in really quickly. - this.elem.stop(true); - this.state = "open"; - this.animating = "in"; - this.elem.css("height", "auto").animate({"width": this.options.width, "opacity": this.options.opacity}, "fast"); - } - return this; - }, - // Queue a removal timer. - queueRemove: function(){ - var that = this; - // Cancel any current removal timer. - this.cancelRemove(); - this.timer = window.setTimeout(function(){ - that.remove(true); - }, (isNaN(this.options.delay) ? 0 : this.options.delay)); - return this; - } - }); - // These functions affect all notices. - $.extend(PNotify, { - // This holds all the notices. - notices: [], - removeAll: function () { - $.each(PNotify.notices, function(){ - if (this.remove) - this.remove(); - }); - }, - positionAll: function (animate) { - // This timer is used for queueing this function so it doesn't run - // repeatedly. - if (timer) - clearTimeout(timer); - timer = null; - // Reset the next position data. - $.each(PNotify.notices, function(){ - var s = this.options.stack; - if (!s) return; - s.nextpos1 = s.firstpos1; - s.nextpos2 = s.firstpos2; - s.addpos2 = 0; - s.animation = animate; - }); - $.each(PNotify.notices, function(){ - this.position(); - }); - }, - styling: { - jqueryui: { - container: "ui-widget ui-widget-content ui-corner-all", - notice: "ui-state-highlight", - // (The actual jQUI notice icon looks terrible.) - notice_icon: "ui-icon ui-icon-info", - info: "", - info_icon: "ui-icon ui-icon-info", - success: "ui-state-default", - success_icon: "ui-icon ui-icon-circle-check", - error: "ui-state-error", - error_icon: "ui-icon ui-icon-alert" - }, - bootstrap2: { - container: "alert", - notice: "", - notice_icon: "icon-exclamation-sign", - info: "alert-info", - info_icon: "icon-info-sign", - success: "alert-success", - success_icon: "icon-ok-sign", - error: "alert-error", - error_icon: "icon-warning-sign" - }, - bootstrap3: { - container: "alert", - notice: "alert-warning", - notice_icon: "glyphicon glyphicon-exclamation-sign", - info: "alert-info", - info_icon: "glyphicon glyphicon-info-sign", - success: "alert-success", - success_icon: "glyphicon glyphicon-ok-sign", - error: "alert-danger", - error_icon: "glyphicon glyphicon-warning-sign" - } - } - }); - /* - * uses icons from http://fontawesome.io/ - * version 4.0.3 - */ - PNotify.styling.fontawesome = $.extend({}, PNotify.styling.bootstrap3); - $.extend(PNotify.styling.fontawesome, { - notice_icon: "fa fa-exclamation-circle", - info_icon: "fa fa-info", - success_icon: "fa fa-check", - error_icon: "fa fa-warning" - }); - - if (document.body) - do_when_ready(); - else - $(do_when_ready); - return PNotify; -})); diff --git a/public/js/v1.1.3/lib/pnotify/pnotify.desktop.js b/public/js/v1.1.3/lib/pnotify/pnotify.desktop.js index 1402f380..174de24f 100644 --- a/public/js/v1.1.3/lib/pnotify/pnotify.desktop.js +++ b/public/js/v1.1.3/lib/pnotify/pnotify.desktop.js @@ -1,14 +1,16 @@ // Desktop -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify.desktop', ['jquery', 'pnotify'], factory); - } else { - // Browser globals - factory(jQuery, PNotify); - } -}(function($, PNotify){ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.desktop', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ var permission; var notify = function(title, options){ // Memoize based on feature detection. @@ -43,6 +45,8 @@ PNotify.prototype.options.desktop = { // Display the notification as a desktop notification. desktop: false, + // If desktop notifications are not supported or allowed, fall back to a regular notice. + fallback: true, // The URL of the icon to display. If false, no icon will show. If null, a default icon will show. icon: null, // Using a tag lets you update an existing notice, or keep from duplicating notices between tabs. @@ -66,10 +70,10 @@ } notice.desktop = notify(notice.options.title, { icon: this.icon, - body: notice.options.text, + body: options.text || notice.options.text, tag: this.tag }); - if (!("close" in notice.desktop)) { + if (!("close" in notice.desktop) && ("cancel" in notice.desktop)) { notice.desktop.close = function(){ notice.desktop.cancel(); }; @@ -87,38 +91,45 @@ if (!options.desktop) return; permission = PNotify.desktop.checkPermission(); - if (permission != 0) + if (permission !== 0) { + // Keep the notice from opening if fallback is false. + if (!options.fallback) { + notice.options.auto_display = false; + } return; + } this.genNotice(notice, options); }, update: function(notice, options, oldOpts){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; this.genNotice(notice, options); }, beforeOpen: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); }, afterOpen: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); if ("show" in notice.desktop) { notice.desktop.show(); } }, beforeClose: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); }, afterClose: function(notice, options){ - if (permission != 0 || !options.desktop) + if ((permission !== 0 && options.fallback) || !options.desktop) return; - notice.elem.css({'left': '-10000px', 'display': 'none'}); - notice.desktop.close(); + notice.elem.css({'left': '-10000px'}).removeClass('ui-pnotify-in'); + if ("close" in notice.desktop) { + notice.desktop.close(); + } } }; PNotify.desktop = { @@ -131,9 +142,9 @@ }, checkPermission: function(){ if (typeof Notification !== "undefined" && "permission" in Notification) { - return (Notification.permission == "granted" ? 0 : 1); + return (Notification.permission === "granted" ? 0 : 1); } else if ("webkitNotifications" in window) { - return window.webkitNotifications.checkPermission(); + return window.webkitNotifications.checkPermission() == 0 ? 0 : 1; } else { return 1; } diff --git a/public/js/v1.1.3/lib/pnotify/pnotify.js b/public/js/v1.1.3/lib/pnotify/pnotify.js new file mode 100644 index 00000000..3c270554 --- /dev/null +++ b/public/js/v1.1.3/lib/pnotify/pnotify.js @@ -0,0 +1,873 @@ +/* + PNotify 3.0.0 sciactive.com/pnotify/ + (C) 2015 Hunter Perrin; Google, Inc. + license Apache-2.0 + */ +/* + * ====== PNotify ====== + * + * http://sciactive.com/pnotify/ + * + * Copyright 2009-2015 Hunter Perrin + * Copyright 2015 Google, Inc. + * + * Licensed under Apache License, Version 2.0. + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify', ['jquery'], function($){ + return factory($, root); + }); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), global || root); + } else { + // Browser globals + root.PNotify = factory(root.jQuery, root); + } +}(this, function($, root){ + var init = function(root){ + var default_stack = { + dir1: "down", + dir2: "left", + push: "bottom", + spacing1: 36, + spacing2: 36, + context: $("body"), + modal: false + }; + var posTimer, // Position all timer. + body, + jwindow = $(root); + // Set global variables. + var do_when_ready = function(){ + body = $("body"); + PNotify.prototype.options.stack.context = body; + jwindow = $(root); + // Reposition the notices when the window resizes. + jwindow.bind('resize', function(){ + if (posTimer) { + clearTimeout(posTimer); + } + posTimer = setTimeout(function(){ + PNotify.positionAll(true); + }, 10); + }); + }; + var createStackOverlay = function(stack) { + var overlay = $("
", {"class": "ui-pnotify-modal-overlay"}); + overlay.prependTo(stack.context); + if (stack.overlay_close) { + // Close the notices on overlay click. + overlay.click(function(){ + PNotify.removeStack(stack); + }); + } + return overlay; + }; + var PNotify = function(options){ + this.parseOptions(options); + this.init(); + }; + $.extend(PNotify.prototype, { + // The current version of PNotify. + version: "3.0.0", + + // === Options === + + // Options defaults. + options: { + // The notice's title. + title: false, + // Whether to escape the content of the title. (Not allow HTML.) + title_escape: false, + // The notice's text. + text: false, + // Whether to escape the content of the text. (Not allow HTML.) + text_escape: false, + // What styling classes to use. (Can be either "brighttheme", "jqueryui", "bootstrap2", "bootstrap3", or "fontawesome".) + styling: "brighttheme", + // Additional classes to be added to the notice. (For custom styling.) + addclass: "", + // Class to be added to the notice for corner styling. + cornerclass: "", + // Display the notice when it is created. + auto_display: true, + // Width of the notice. + width: "300px", + // Minimum height of the notice. It will expand to fit content. + min_height: "16px", + // Type of the notice. "notice", "info", "success", or "error". + type: "notice", + // Set icon to true to use the default icon for the selected + // style/type, false for no icon, or a string for your own icon class. + icon: true, + // The animation to use when displaying and hiding the notice. "none" + // and "fade" are supported through CSS. Others are supported + // through the Animate module and Animate.css. + animation: "fade", + // Speed at which the notice animates in and out. "slow", "normal", + // or "fast". Respectively, 600ms, 400ms, 200ms. + animate_speed: "normal", + // Display a drop shadow. + shadow: true, + // After a delay, remove the notice. + hide: true, + // Delay in milliseconds before the notice is removed. + delay: 8000, + // Reset the hide timer if the mouse moves over the notice. + mouse_reset: true, + // Remove the notice's elements from the DOM after it is removed. + remove: true, + // Change new lines to br tags. + insert_brs: true, + // Whether to remove notices from the global array. + destroy: true, + // The stack on which the notices will be placed. Also controls the + // direction the notices stack. + stack: default_stack + }, + + // === Modules === + + // This object holds all the PNotify modules. They are used to provide + // additional functionality. + modules: {}, + // This runs an event on all the modules. + runModules: function(event, arg){ + var curArg; + for (var module in this.modules) { + curArg = ((typeof arg === "object" && module in arg) ? arg[module] : arg); + if (typeof this.modules[module][event] === 'function') { + this.modules[module].notice = this; + this.modules[module].options = typeof this.options[module] === 'object' ? this.options[module] : {}; + this.modules[module][event](this, typeof this.options[module] === 'object' ? this.options[module] : {}, curArg); + } + } + }, + + // === Class Variables === + + state: "initializing", // The state can be "initializing", "opening", "open", "closing", and "closed". + timer: null, // Auto close timer. + animTimer: null, // Animation timer. + styles: null, + elem: null, + container: null, + title_container: null, + text_container: null, + animating: false, // Stores what is currently being animated (in or out). + timerHide: false, // Stores whether the notice was hidden by a timer. + + // === Events === + + init: function(){ + var that = this; + + // First and foremost, we don't want our module objects all referencing the prototype. + this.modules = {}; + $.extend(true, this.modules, PNotify.prototype.modules); + + // Get our styling object. + if (typeof this.options.styling === "object") { + this.styles = this.options.styling; + } else { + this.styles = PNotify.styling[this.options.styling]; + } + + // Create our widget. + // Stop animation, reset the removal timer when the user mouses over. + this.elem = $("
", { + "class": "ui-pnotify "+this.options.addclass, + "css": {"display": "none"}, + "aria-live": "assertive", + "aria-role": "alertdialog", + "mouseenter": function(e){ + if (that.options.mouse_reset && that.animating === "out") { + if (!that.timerHide) { + return; + } + that.cancelRemove(); + } + // Stop the close timer. + if (that.options.hide && that.options.mouse_reset) { + that.cancelRemove(); + } + }, + "mouseleave": function(e){ + // Start the close timer. + if (that.options.hide && that.options.mouse_reset && that.animating !== "out") { + that.queueRemove(); + } + PNotify.positionAll(); + } + }); + // Maybe we need to fade in/out. + if (this.options.animation === "fade") { + this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed); + } + // Create a container for the notice contents. + this.container = $("
", { + "class": this.styles.container+" ui-pnotify-container "+(this.options.type === "error" ? this.styles.error : (this.options.type === "info" ? this.styles.info : (this.options.type === "success" ? this.styles.success : this.styles.notice))), + "role": "alert" + }).appendTo(this.elem); + if (this.options.cornerclass !== "") { + this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass); + } + // Create a drop shadow. + if (this.options.shadow) { + this.container.addClass("ui-pnotify-shadow"); + } + + + // Add the appropriate icon. + if (this.options.icon !== false) { + $("
", {"class": "ui-pnotify-icon"}) + .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) + .prependTo(this.container); + } + + // Add a title. + this.title_container = $("

", { + "class": "ui-pnotify-title" + }) + .appendTo(this.container); + if (this.options.title === false) { + this.title_container.hide(); + } else if (this.options.title_escape) { + this.title_container.text(this.options.title); + } else { + this.title_container.html(this.options.title); + } + + // Add text. + this.text_container = $("
", { + "class": "ui-pnotify-text", + "aria-role": "alert" + }) + .appendTo(this.container); + if (this.options.text === false) { + this.text_container.hide(); + } else if (this.options.text_escape) { + this.text_container.text(this.options.text); + } else { + this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); + } + + // Set width and min height. + if (typeof this.options.width === "string") { + this.elem.css("width", this.options.width); + } + if (typeof this.options.min_height === "string") { + this.container.css("min-height", this.options.min_height); + } + + + // Add the notice to the notice array. + if (this.options.stack.push === "top") { + PNotify.notices = $.merge([this], PNotify.notices); + } else { + PNotify.notices = $.merge(PNotify.notices, [this]); + } + // Now position all the notices if they are to push to the top. + if (this.options.stack.push === "top") { + this.queuePosition(false, 1); + } + + + + + // Mark the stack so it won't animate the new notice. + this.options.stack.animation = false; + + // Run the modules. + this.runModules('init'); + + // Display the notice. + if (this.options.auto_display) { + this.open(); + } + return this; + }, + + // This function is for updating the notice. + update: function(options){ + // Save old options. + var oldOpts = this.options; + // Then update to the new options. + this.parseOptions(oldOpts, options); + // Maybe we need to fade in/out. + this.elem.removeClass("ui-pnotify-fade-slow ui-pnotify-fade-normal ui-pnotify-fade-fast"); + if (this.options.animation === "fade") { + this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed); + } + // Update the corner class. + if (this.options.cornerclass !== oldOpts.cornerclass) { + this.container.removeClass("ui-corner-all "+oldOpts.cornerclass).addClass(this.options.cornerclass); + } + // Update the shadow. + if (this.options.shadow !== oldOpts.shadow) { + if (this.options.shadow) { + this.container.addClass("ui-pnotify-shadow"); + } else { + this.container.removeClass("ui-pnotify-shadow"); + } + } + // Update the additional classes. + if (this.options.addclass === false) { + this.elem.removeClass(oldOpts.addclass); + } else if (this.options.addclass !== oldOpts.addclass) { + this.elem.removeClass(oldOpts.addclass).addClass(this.options.addclass); + } + // Update the title. + if (this.options.title === false) { + this.title_container.slideUp("fast"); + } else if (this.options.title !== oldOpts.title) { + if (this.options.title_escape) { + this.title_container.text(this.options.title); + } else { + this.title_container.html(this.options.title); + } + if (oldOpts.title === false) { + this.title_container.slideDown(200); + } + } + // Update the text. + if (this.options.text === false) { + this.text_container.slideUp("fast"); + } else if (this.options.text !== oldOpts.text) { + if (this.options.text_escape) { + this.text_container.text(this.options.text); + } else { + this.text_container.html(this.options.insert_brs ? String(this.options.text).replace(/\n/g, "
") : this.options.text); + } + if (oldOpts.text === false) { + this.text_container.slideDown(200); + } + } + // Change the notice type. + if (this.options.type !== oldOpts.type) + this.container.removeClass( + this.styles.error+" "+this.styles.notice+" "+this.styles.success+" "+this.styles.info + ).addClass(this.options.type === "error" ? + this.styles.error : + (this.options.type === "info" ? + this.styles.info : + (this.options.type === "success" ? + this.styles.success : + this.styles.notice + ) + ) + ); + if (this.options.icon !== oldOpts.icon || (this.options.icon === true && this.options.type !== oldOpts.type)) { + // Remove any old icon. + this.container.find("div.ui-pnotify-icon").remove(); + if (this.options.icon !== false) { + // Build the new icon. + $("
", {"class": "ui-pnotify-icon"}) + .append($("", {"class": this.options.icon === true ? (this.options.type === "error" ? this.styles.error_icon : (this.options.type === "info" ? this.styles.info_icon : (this.options.type === "success" ? this.styles.success_icon : this.styles.notice_icon))) : this.options.icon})) + .prependTo(this.container); + } + } + // Update the width. + if (this.options.width !== oldOpts.width) { + this.elem.animate({width: this.options.width}); + } + // Update the minimum height. + if (this.options.min_height !== oldOpts.min_height) { + this.container.animate({minHeight: this.options.min_height}); + } + // Update the timed hiding. + if (!this.options.hide) { + this.cancelRemove(); + } else if (!oldOpts.hide) { + this.queueRemove(); + } + this.queuePosition(true); + + // Run the modules. + this.runModules('update', oldOpts); + return this; + }, + + // Display the notice. + open: function(){ + this.state = "opening"; + // Run the modules. + this.runModules('beforeOpen'); + + var that = this; + // If the notice is not in the DOM, append it. + if (!this.elem.parent().length) { + this.elem.appendTo(this.options.stack.context ? this.options.stack.context : body); + } + // Try to put it in the right position. + if (this.options.stack.push !== "top") { + this.position(true); + } + this.animateIn(function(){ + that.queuePosition(true); + + // Now set it to hide. + if (that.options.hide) { + that.queueRemove(); + } + + that.state = "open"; + + // Run the modules. + that.runModules('afterOpen'); + }); + + return this; + }, + + // Remove the notice. + remove: function(timer_hide) { + this.state = "closing"; + this.timerHide = !!timer_hide; // Make sure it's a boolean. + // Run the modules. + this.runModules('beforeClose'); + + var that = this; + if (this.timer) { + root.clearTimeout(this.timer); + this.timer = null; + } + this.animateOut(function(){ + that.state = "closed"; + // Run the modules. + that.runModules('afterClose'); + that.queuePosition(true); + // If we're supposed to remove the notice from the DOM, do it. + if (that.options.remove) { + that.elem.detach(); + } + // Run the modules. + that.runModules('beforeDestroy'); + // Remove object from PNotify.notices to prevent memory leak (issue #49) + // unless destroy is off + if (that.options.destroy) { + if (PNotify.notices !== null) { + var idx = $.inArray(that,PNotify.notices); + if (idx !== -1) { + PNotify.notices.splice(idx,1); + } + } + } + // Run the modules. + that.runModules('afterDestroy'); + }); + + return this; + }, + + // === Class Methods === + + // Get the DOM element. + get: function(){ + return this.elem; + }, + + // Put all the options in the right places. + parseOptions: function(options, moreOptions){ + this.options = $.extend(true, {}, PNotify.prototype.options); + // This is the only thing that *should* be copied by reference. + this.options.stack = PNotify.prototype.options.stack; + var optArray = [options, moreOptions], curOpts; + for (var curIndex=0; curIndex < optArray.length; curIndex++) { + curOpts = optArray[curIndex]; + if (typeof curOpts === "undefined") { + break; + } + if (typeof curOpts !== 'object') { + this.options.text = curOpts; + } else { + for (var option in curOpts) { + if (this.modules[option]) { + // Avoid overwriting module defaults. + $.extend(true, this.options[option], curOpts[option]); + } else { + this.options[option] = curOpts[option]; + } + } + } + } + }, + + // Animate the notice in. + animateIn: function(callback){ + // Declare that the notice is animating in. + this.animating = "in"; + var that = this; + callback = (function(){ + if (that.animTimer) { + clearTimeout(that.animTimer); + } + if (that.animating !== "in") { + return; + } + if (that.elem.is(":visible")) { + if (this) { + this.call(); + } + // Declare that the notice has completed animating. + that.animating = false; + } else { + that.animTimer = setTimeout(callback, 40); + } + }).bind(callback); + + if (this.options.animation === "fade") { + this.elem.one('webkitTransitionEnd mozTransitionEnd MSTransitionEnd oTransitionEnd transitionend', callback).addClass("ui-pnotify-in"); + this.elem.css("opacity"); // This line is necessary for some reason. Some notices don't fade without it. + this.elem.addClass("ui-pnotify-fade-in"); + // Just in case the event doesn't fire, call it after 650 ms. + this.animTimer = setTimeout(callback, 650); + } else { + this.elem.addClass("ui-pnotify-in"); + callback(); + } + }, + + // Animate the notice out. + animateOut: function(callback){ + // Declare that the notice is animating out. + this.animating = "out"; + var that = this; + callback = (function(){ + if (that.animTimer) { + clearTimeout(that.animTimer); + } + if (that.animating !== "out") { + return; + } + if (that.elem.css("opacity") == "0" || !that.elem.is(":visible")) { + that.elem.removeClass("ui-pnotify-in"); + if (this) { + this.call(); + } + // Declare that the notice has completed animating. + that.animating = false; + } else { + // In case this was called before the notice finished animating. + that.animTimer = setTimeout(callback, 40); + } + }).bind(callback); + + if (this.options.animation === "fade") { + this.elem.one('webkitTransitionEnd mozTransitionEnd MSTransitionEnd oTransitionEnd transitionend', callback).removeClass("ui-pnotify-fade-in"); + // Just in case the event doesn't fire, call it after 650 ms. + this.animTimer = setTimeout(callback, 650); + } else { + this.elem.removeClass("ui-pnotify-in"); + callback(); + } + }, + + // Position the notice. dont_skip_hidden causes the notice to + // position even if it's not visible. + position: function(dontSkipHidden){ + // Get the notice's stack. + var stack = this.options.stack, + elem = this.elem; + if (typeof stack.context === "undefined") { + stack.context = body; + } + if (!stack) { + return; + } + if (typeof stack.nextpos1 !== "number") { + stack.nextpos1 = stack.firstpos1; + } + if (typeof stack.nextpos2 !== "number") { + stack.nextpos2 = stack.firstpos2; + } + if (typeof stack.addpos2 !== "number") { + stack.addpos2 = 0; + } + var hidden = !elem.hasClass("ui-pnotify-in"); + // Skip this notice if it's not shown. + if (!hidden || dontSkipHidden) { + if (stack.modal) { + if (stack.overlay) { + stack.overlay.show(); + } else { + stack.overlay = createStackOverlay(stack); + } + } + // Add animate class by default. + elem.addClass("ui-pnotify-move"); + var curpos1, curpos2; + // Calculate the current pos1 value. + var csspos1; + switch (stack.dir1) { + case "down": + csspos1 = "top"; + break; + case "up": + csspos1 = "bottom"; + break; + case "left": + csspos1 = "right"; + break; + case "right": + csspos1 = "left"; + break; + } + curpos1 = parseInt(elem.css(csspos1).replace(/(?:\..*|[^0-9.])/g, '')); + if (isNaN(curpos1)) { + curpos1 = 0; + } + // Remember the first pos1, so the first visible notice goes there. + if (typeof stack.firstpos1 === "undefined" && !hidden) { + stack.firstpos1 = curpos1; + stack.nextpos1 = stack.firstpos1; + } + // Calculate the current pos2 value. + var csspos2; + switch (stack.dir2) { + case "down": + csspos2 = "top"; + break; + case "up": + csspos2 = "bottom"; + break; + case "left": + csspos2 = "right"; + break; + case "right": + csspos2 = "left"; + break; + } + curpos2 = parseInt(elem.css(csspos2).replace(/(?:\..*|[^0-9.])/g, '')); + if (isNaN(curpos2)) { + curpos2 = 0; + } + // Remember the first pos2, so the first visible notice goes there. + if (typeof stack.firstpos2 === "undefined" && !hidden) { + stack.firstpos2 = curpos2; + stack.nextpos2 = stack.firstpos2; + } + // Check that it's not beyond the viewport edge. + if ( + (stack.dir1 === "down" && stack.nextpos1 + elem.height() > (stack.context.is(body) ? jwindow.height() : stack.context.prop('scrollHeight')) ) || + (stack.dir1 === "up" && stack.nextpos1 + elem.height() > (stack.context.is(body) ? jwindow.height() : stack.context.prop('scrollHeight')) ) || + (stack.dir1 === "left" && stack.nextpos1 + elem.width() > (stack.context.is(body) ? jwindow.width() : stack.context.prop('scrollWidth')) ) || + (stack.dir1 === "right" && stack.nextpos1 + elem.width() > (stack.context.is(body) ? jwindow.width() : stack.context.prop('scrollWidth')) ) + ) { + // If it is, it needs to go back to the first pos1, and over on pos2. + stack.nextpos1 = stack.firstpos1; + stack.nextpos2 += stack.addpos2 + (typeof stack.spacing2 === "undefined" ? 25 : stack.spacing2); + stack.addpos2 = 0; + } + if (typeof stack.nextpos2 === "number") { + if (!stack.animation) { + elem.removeClass("ui-pnotify-move"); + elem.css(csspos2, stack.nextpos2+"px"); + elem.css(csspos2); + elem.addClass("ui-pnotify-move"); + } else { + elem.css(csspos2, stack.nextpos2+"px"); + } + } + // Keep track of the widest/tallest notice in the column/row, so we can push the next column/row. + switch (stack.dir2) { + case "down": + case "up": + if (elem.outerHeight(true) > stack.addpos2) { + stack.addpos2 = elem.height(); + } + break; + case "left": + case "right": + if (elem.outerWidth(true) > stack.addpos2) { + stack.addpos2 = elem.width(); + } + break; + } + // Move the notice on dir1. + if (typeof stack.nextpos1 === "number") { + if (!stack.animation) { + elem.removeClass("ui-pnotify-move"); + elem.css(csspos1, stack.nextpos1+"px"); + elem.css(csspos1); + elem.addClass("ui-pnotify-move"); + } else { + elem.css(csspos1, stack.nextpos1+"px"); + } + } + // Calculate the next dir1 position. + switch (stack.dir1) { + case "down": + case "up": + stack.nextpos1 += elem.height() + (typeof stack.spacing1 === "undefined" ? 25 : stack.spacing1); + break; + case "left": + case "right": + stack.nextpos1 += elem.width() + (typeof stack.spacing1 === "undefined" ? 25 : stack.spacing1); + break; + } + } + return this; + }, + // Queue the position all function so it doesn't run repeatedly and + // use up resources. + queuePosition: function(animate, milliseconds){ + if (posTimer) { + clearTimeout(posTimer); + } + if (!milliseconds) { + milliseconds = 10; + } + posTimer = setTimeout(function(){ + PNotify.positionAll(animate); + }, milliseconds); + return this; + }, + + + // Cancel any pending removal timer. + cancelRemove: function(){ + if (this.timer) { + root.clearTimeout(this.timer); + } + if (this.animTimer) { + root.clearTimeout(this.animTimer); + } + if (this.state === "closing") { + // If it's animating out, stop it. + this.state = "open"; + this.animating = false; + this.elem.addClass("ui-pnotify-in"); + if (this.options.animation === "fade") { + this.elem.addClass("ui-pnotify-fade-in"); + } + } + return this; + }, + // Queue a removal timer. + queueRemove: function(){ + var that = this; + // Cancel any current removal timer. + this.cancelRemove(); + this.timer = root.setTimeout(function(){ + that.remove(true); + }, (isNaN(this.options.delay) ? 0 : this.options.delay)); + return this; + } + }); + // These functions affect all notices. + $.extend(PNotify, { + // This holds all the notices. + notices: [], + reload: init, + removeAll: function(){ + $.each(PNotify.notices, function(){ + if (this.remove) { + this.remove(false); + } + }); + }, + removeStack: function(stack){ + $.each(PNotify.notices, function(){ + if (this.remove && this.options.stack === stack) { + this.remove(false); + } + }); + }, + positionAll: function(animate){ + // This timer is used for queueing this function so it doesn't run + // repeatedly. + if (posTimer) { + clearTimeout(posTimer); + } + posTimer = null; + // Reset the next position data. + if (PNotify.notices && PNotify.notices.length) { + $.each(PNotify.notices, function(){ + var s = this.options.stack; + if (!s) { + return; + } + if (s.overlay) { + s.overlay.hide(); + } + s.nextpos1 = s.firstpos1; + s.nextpos2 = s.firstpos2; + s.addpos2 = 0; + s.animation = animate; + }); + $.each(PNotify.notices, function(){ + this.position(); + }); + } else { + var s = PNotify.prototype.options.stack; + if (s) { + delete s.nextpos1; + delete s.nextpos2; + } + } + }, + styling: { + brighttheme: { + // Bright Theme doesn't require any UI libraries. + container: "brighttheme", + notice: "brighttheme-notice", + notice_icon: "brighttheme-icon-notice", + info: "brighttheme-info", + info_icon: "brighttheme-icon-info", + success: "brighttheme-success", + success_icon: "brighttheme-icon-success", + error: "brighttheme-error", + error_icon: "brighttheme-icon-error" + }, + jqueryui: { + container: "ui-widget ui-widget-content ui-corner-all", + notice: "ui-state-highlight", + // (The actual jQUI notice icon looks terrible.) + notice_icon: "ui-icon ui-icon-info", + info: "", + info_icon: "ui-icon ui-icon-info", + success: "ui-state-default", + success_icon: "ui-icon ui-icon-circle-check", + error: "ui-state-error", + error_icon: "ui-icon ui-icon-alert" + }, + bootstrap3: { + container: "alert", + notice: "alert-warning", + notice_icon: "glyphicon glyphicon-exclamation-sign", + info: "alert-info", + info_icon: "glyphicon glyphicon-info-sign", + success: "alert-success", + success_icon: "glyphicon glyphicon-ok-sign", + error: "alert-danger", + error_icon: "glyphicon glyphicon-warning-sign" + } + } + }); + /* + * uses icons from http://fontawesome.io/ + * version 4.0.3 + */ + PNotify.styling.fontawesome = $.extend({}, PNotify.styling.bootstrap3); + $.extend(PNotify.styling.fontawesome, { + notice_icon: "fa fa-exclamation-circle", + info_icon: "fa fa-info", + success_icon: "fa fa-check", + error_icon: "fa fa-warning" + }); + + if (root.document.body) { + do_when_ready(); + } else { + $(do_when_ready); + } + return PNotify; + }; + return init(root); +})); diff --git a/public/js/v1.1.3/lib/pnotify/pnotify.nonblock.js b/public/js/v1.1.3/lib/pnotify/pnotify.nonblock.js index 4464f14c..3d0481ce 100644 --- a/public/js/v1.1.3/lib/pnotify/pnotify.nonblock.js +++ b/public/js/v1.1.3/lib/pnotify/pnotify.nonblock.js @@ -1,14 +1,16 @@ // Nonblock -// Uses AMD or browser globals for jQuery. -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as a module. - define('pnotify.nonblock', ['jquery', 'pnotify'], factory); - } else { - // Browser globals - factory(jQuery, PNotify); - } -}(function($, PNotify){ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.nonblock', ['jquery', 'pnotify'], factory); + } else if (typeof exports === 'object' && typeof module !== 'undefined') { + // CommonJS + module.exports = factory(require('jquery'), require('./pnotify')); + } else { + // Browser globals + factory(root.jQuery, root.PNotify); + } +}(this, function($, PNotify){ // Some useful regexes. var re_on = /^on/, re_mouse_events = /^(dbl)?click$|^mouse(move|down|up|over|out|enter|leave)$|^contextmenu$/, @@ -54,11 +56,14 @@ var nonblock_last_elem; // This is used to pass events through the notice if it is non-blocking. var nonblock_pass = function(notice, e, e_name){ - notice.elem.css("display", "none"); + notice.elem.addClass("ui-pnotify-nonblock-hide"); var element_below = document.elementFromPoint(e.clientX, e.clientY); - notice.elem.css("display", "block"); + notice.elem.removeClass("ui-pnotify-nonblock-hide"); var jelement_below = $(element_below); var cursor_style = jelement_below.css("cursor"); + if (cursor_style === "auto" && element_below.tagName === "A") { + cursor_style = "pointer"; + } notice.elem.css("cursor", cursor_style !== "auto" ? cursor_style : "default"); // If the element changed, call mouseenter, mouseleave, etc. if (!nonblock_last_elem || nonblock_last_elem.get(0) != element_below) { @@ -77,75 +82,75 @@ PNotify.prototype.options.nonblock = { // Create a non-blocking notice. It lets the user click elements underneath it. - nonblock: false, - // The opacity of the notice (if it's non-blocking) when the mouse is over it. - nonblock_opacity: .2 + nonblock: false }; PNotify.prototype.modules.nonblock = { - // This lets us update the options available in the closures. - myOptions: null, - init: function(notice, options){ var that = this; - this.myOptions = options; notice.elem.on({ "mouseenter": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); - if (that.myOptions.nonblock) { + if (that.options.nonblock) { + e.stopPropagation(); + } + if (that.options.nonblock) { // If it's non-blocking, animate to the other opacity. - notice.elem.stop().animate({"opacity": that.myOptions.nonblock_opacity}, "fast"); + notice.elem.addClass("ui-pnotify-nonblock-fade"); } }, "mouseleave": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); + if (that.options.nonblock) { + e.stopPropagation(); + } nonblock_last_elem = null; notice.elem.css("cursor", "auto"); // Animate back to the normal opacity. - if (that.myOptions.nonblock && notice.animating !== "out") - notice.elem.stop().animate({"opacity": notice.options.opacity}, "fast"); + if (that.options.nonblock && notice.animating !== "out") { + notice.elem.removeClass("ui-pnotify-nonblock-fade"); + } }, "mouseover": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); + if (that.options.nonblock) { + e.stopPropagation(); + } }, "mouseout": function(e){ - if (that.myOptions.nonblock) e.stopPropagation(); + if (that.options.nonblock) { + e.stopPropagation(); + } }, "mousemove": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); nonblock_pass(notice, e, "onmousemove"); } }, "mousedown": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); e.preventDefault(); nonblock_pass(notice, e, "onmousedown"); } }, "mouseup": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); e.preventDefault(); nonblock_pass(notice, e, "onmouseup"); } }, "click": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); nonblock_pass(notice, e, "onclick"); } }, "dblclick": function(e){ - if (that.myOptions.nonblock) { + if (that.options.nonblock) { e.stopPropagation(); nonblock_pass(notice, e, "ondblclick"); } } }); - }, - update: function(notice, options){ - this.myOptions = options; } }; })); diff --git a/sass/library/pnotify/_pnotify.core.scss b/sass/library/pnotify/_pnotify.core.scss deleted file mode 100644 index d819c564..00000000 --- a/sass/library/pnotify/_pnotify.core.scss +++ /dev/null @@ -1,67 +0,0 @@ -/* -Author : Hunter Perrin -Version : 2.0.1 -Link : http://sciactive.com/pnotify/ -*/ -/* -- Notice */ -.ui-pnotify { - top: 25px; - right: 25px; - position: absolute; - height: auto; - /* Ensures notices are above everything */ - z-index: 9999; -} -/* Hides position: fixed from IE6 */ -html > body > .ui-pnotify { - position: fixed; -} -.ui-pnotify .ui-pnotify-shadow { - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,0.2); - -moz-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0,0,0,0.2); -} -.ui-pnotify-container { - background-position: 0 0; - padding: .8em; - height: 100%; - margin: 0; -} -.ui-pnotify-sharp { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} -.ui-pnotify-title { - display: block; - margin-bottom: .4em; - margin-top: 0; -} -.ui-pnotify-text { - display: block; - font-family: $font-family-bold; -} -.ui-pnotify-icon, .ui-pnotify-icon span { - display: block; - float: left; - margin-right: .2em; -} -/* Alternate stack initial positioning. */ -.ui-pnotify.stack-topleft, .ui-pnotify.stack-bottomleft { - left: 25px; - right: auto; -} -.ui-pnotify.stack-bottomright, .ui-pnotify.stack-bottomleft { - bottom: 25px; - top: auto; -} -.ui-pnotify.stack-bar-top { - right: 0; - top: 0; -} -.ui-pnotify.stack-bar-bottom { - right: auto; - bottom: 0; - top: auto; - left: auto; -} diff --git a/sass/library/pnotify/_pnotify.custom.scss b/sass/library/pnotify/_pnotify.custom.scss new file mode 100644 index 00000000..c0eadd54 --- /dev/null +++ b/sass/library/pnotify/_pnotify.custom.scss @@ -0,0 +1,11 @@ +.ui-pnotify{ + + &.stack-bar-bottom{ + margin-left: 15%; + margin-bottom: 25px; + right: auto; + bottom: 0; + top: auto; + left: auto; + } +} \ No newline at end of file diff --git a/sass/library/pnotify/_pnotify.nonblock.scss b/sass/library/pnotify/_pnotify.nonblock.scss new file mode 100644 index 00000000..40279438 --- /dev/null +++ b/sass/library/pnotify/_pnotify.nonblock.scss @@ -0,0 +1,7 @@ +.ui-pnotify.ui-pnotify-nonblock-fade { + /*transition: opacity .3s ease;*/ + opacity: .2; +} +.ui-pnotify.ui-pnotify-nonblock-hide { + display: none !important; +} \ No newline at end of file diff --git a/sass/library/pnotify/_pnotify.scss b/sass/library/pnotify/_pnotify.scss new file mode 100644 index 00000000..8745b7b8 --- /dev/null +++ b/sass/library/pnotify/_pnotify.scss @@ -0,0 +1,112 @@ +/* +Author : Hunter Perrin +Version : 3.0.0 +Link : http://sciactive.com/pnotify/ +*/ +/* -- Notice */ +.ui-pnotify { + top: 36px; + right: 36px; + position: absolute; + height: auto; + z-index: 2; +} +body > .ui-pnotify { + /* Notices in the body context should be fixed to the viewport. */ + position: fixed; + /* Ensures notices are above everything */ + z-index: 100040; +} +.ui-pnotify-modal-overlay { + background-color: rgba(0, 0, 0, .4); + top: 0; + left: 0; + position: absolute; + height: 100%; + width: 100%; + z-index: 1; +} +body > .ui-pnotify-modal-overlay { + position: fixed; + z-index: 100039; +} +.ui-pnotify.ui-pnotify-in { + display: block !important; +} +.ui-pnotify.ui-pnotify-move { + transition: left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; +} +.ui-pnotify.ui-pnotify-fade-slow { + transition: opacity .6s linear; + opacity: 0; +} +.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move { + transition: opacity .6s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; +} +.ui-pnotify.ui-pnotify-fade-normal { + transition: opacity .4s linear; + opacity: 0; +} +.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move { + transition: opacity .4s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; +} +.ui-pnotify.ui-pnotify-fade-fast { + transition: opacity .2s linear; + opacity: 0; +} +.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move { + transition: opacity .2s linear, left .5s ease, top .5s ease, right .5s ease, bottom .5s ease; +} +.ui-pnotify.ui-pnotify-fade-in { + opacity: 1; +} +.ui-pnotify .ui-pnotify-shadow { + -webkit-box-shadow: 0px 6px 28px 0px rgba(0,0,0,0.1); + -moz-box-shadow: 0px 6px 28px 0px rgba(0,0,0,0.1); + box-shadow: 0px 6px 28px 0px rgba(0,0,0,0.1); +} +.ui-pnotify-container { + background-position: 0 0; + padding: .8em; + height: 100%; + margin: 0; +} +.ui-pnotify-container:after { + content: " "; /* Older browser do not support empty content */ + visibility: hidden; + display: block; + height: 0; + clear: both; +} +.ui-pnotify-container.ui-pnotify-sharp { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.ui-pnotify-title { + display: block; + margin-bottom: .4em; + margin-top: 0; +} +.ui-pnotify-text { + display: block; +} +.ui-pnotify-icon, .ui-pnotify-icon span { + display: block; + float: left; + margin-right: .2em; +} +/* Alternate stack initial positioning. */ +.ui-pnotify.stack-topleft, .ui-pnotify.stack-bottomleft { + left: 25px; + right: auto; +} +.ui-pnotify.stack-bottomright, .ui-pnotify.stack-bottomleft { + bottom: 25px; + top: auto; +} +.ui-pnotify.stack-modal { + left: 50%; + right: auto; + margin-left: -150px; +} diff --git a/sass/pathfinder.scss b/sass/pathfinder.scss index 0200fe0d..6902b7f7 100644 --- a/sass/pathfinder.scss +++ b/sass/pathfinder.scss @@ -28,7 +28,9 @@ @import "library/data-tables/_all"; // DataTables 1.10.12 + extensions @import "library/x-editable/_bootstrap-editable"; // X-editable - v1.5.1 -@import "library/pnotify/_pnotify.core"; // PNotify styles +@import "library/pnotify/_pnotify"; // PNotify styles - v3.0.0 +@import "library/pnotify/_pnotify.nonblock"; +@import "library/pnotify/_pnotify.custom"; // PNotify custom styles @import "library/slidebars/_slidebars"; // Slidebars Navigation @import "library/easy-pie-chart/_easyPieChart"; // Easy Pie Chart 2.1.6 @import "library/drag-to-select/_dragToSelect"; // Drag to Select 1.1