diff --git a/src/3rdparty/angular-ui-notification.css b/src/3rdparty/angular-ui-notification.css new file mode 100644 index 000000000..759db0936 --- /dev/null +++ b/src/3rdparty/angular-ui-notification.css @@ -0,0 +1,85 @@ +/** + * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating + * @author Alex_Crack + * @version v0.3.6 + * @link https://github.com/alexcrack/angular-ui-notification + * @license MIT + */ +.ui-notification +{ + position: fixed; + z-index: 9999; + + width: 300px; + + -webkit-transition: all ease .5s; + -o-transition: all ease .5s; + transition: all ease .5s; + + color: #fff; + border-radius: 0; + background: #337ab7; + box-shadow: 5px 5px 10px rgba(0, 0, 0, .3); +} +.ui-notification.clickable +{ + cursor: pointer; +} +.ui-notification.clickable:hover +{ + opacity: .7; +} +.ui-notification.killed +{ + -webkit-transition: opacity ease 1s; + -o-transition: opacity ease 1s; + transition: opacity ease 1s; + + opacity: 0; +} +.ui-notification > h3 +{ + font-size: 14px; + font-weight: bold; + + display: block; + + margin: 10px 10px 0 10px; + padding: 0 0 5px 0; + + text-align: left; + + border-bottom: 1px solid rgba(255, 255, 255, .3); +} +.ui-notification a +{ + color: #fff; +} +.ui-notification a:hover +{ + text-decoration: underline; +} +.ui-notification > .message +{ + margin: 10px 10px 10px 10px; +} +.ui-notification.warning +{ + color: #fff; + background: #f0ad4e; +} +.ui-notification.error +{ + color: #fff; + background: #d9534f; +} +.ui-notification.success +{ + color: #fff; + background: #5cb85c; +} +.ui-notification.info +{ + color: #fff; + background: #5bc0de; +} diff --git a/src/3rdparty/angular-ui-notification.min.css b/src/3rdparty/angular-ui-notification.min.css deleted file mode 100644 index a055ef4f0..000000000 --- a/src/3rdparty/angular-ui-notification.min.css +++ /dev/null @@ -1,8 +0,0 @@ -/** - * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating - * @author Alex_Crack - * @version v0.3.5 - * @link https://github.com/alexcrack/angular-ui-notification - * @license MIT - */ -.ui-notification{position:fixed;z-index:9999;width:300px;-webkit-transition:all ease .5s;-o-transition:all ease .5s;transition:all ease .5s;color:#fff;border-radius:0;background:#337ab7;box-shadow:5px 5px 10px rgba(0,0,0,.3)}.ui-notification.clickable{cursor:pointer}.ui-notification.clickable:hover{opacity:.7}.ui-notification.killed{-webkit-transition:opacity ease 1s;-o-transition:opacity ease 1s;transition:opacity ease 1s;opacity:0}.ui-notification>h3{font-size:14px;font-weight:700;display:block;margin:10px 10px 0;padding:0 0 5px;text-align:left;border-bottom:1px solid rgba(255,255,255,.3)}.ui-notification a{color:#fff}.ui-notification a:hover{text-decoration:underline}.ui-notification>.message{margin:10px}.ui-notification.warning{color:#fff;background:#f0ad4e}.ui-notification.error{color:#fff;background:#d9534f}.ui-notification.success{color:#fff;background:#5cb85c}.ui-notification.info{color:#fff;background:#5bc0de} \ No newline at end of file diff --git a/src/3rdparty/js/angular-ui-notification.js b/src/3rdparty/js/angular-ui-notification.js new file mode 100644 index 000000000..7c9cbddae --- /dev/null +++ b/src/3rdparty/js/angular-ui-notification.js @@ -0,0 +1,271 @@ +/** + * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating + * @author Alex_Crack + * @version v0.3.6 + * @link https://github.com/alexcrack/angular-ui-notification + * @license MIT + */ +angular.module('ui-notification', []); + +angular.module('ui-notification').provider('Notification', function () { + + this.options = { + delay: 5000, + startTop: 10, + startRight: 10, + verticalSpacing: 10, + horizontalSpacing: 10, + positionX: 'right', + positionY: 'top', + replaceMessage: false, + templateUrl: 'angular-ui-notification.html', + onClose: undefined, + onClick: undefined, + closeOnClick: true, + maxCount: 0, // 0 - Infinite + container: 'body', + priority: 10 + }; + + this.setOptions = function (options) { + if (!angular.isObject(options)) throw new Error("Options should be an object!"); + this.options = angular.extend({}, this.options, options); + }; + + this.$get = ["$timeout", "$http", "$compile", "$templateCache", "$rootScope", "$injector", "$sce", "$q", "$window", function ($timeout, $http, $compile, $templateCache, $rootScope, $injector, $sce, $q, $window) { + var options = this.options; + + var startTop = options.startTop; + var startRight = options.startRight; + var verticalSpacing = options.verticalSpacing; + var horizontalSpacing = options.horizontalSpacing; + var delay = options.delay; + + var messageElements = []; + var isResizeBound = false; + + var notify = function (args, t) { + var deferred = $q.defer(); + + if (typeof args !== 'object' || args === null) { + args = {message: args}; + } + + args.scope = args.scope ? args.scope : $rootScope; + args.template = args.templateUrl ? args.templateUrl : options.templateUrl; + args.delay = !angular.isUndefined(args.delay) ? args.delay : delay; + args.type = t || args.type || options.type || ''; + args.positionY = args.positionY ? args.positionY : options.positionY; + args.positionX = args.positionX ? args.positionX : options.positionX; + args.replaceMessage = args.replaceMessage ? args.replaceMessage : options.replaceMessage; + args.onClose = args.onClose ? args.onClose : options.onClose; + args.onClick = args.onClick ? args.onClick : options.onClick; + args.closeOnClick = (args.closeOnClick !== null && args.closeOnClick !== undefined) ? args.closeOnClick : options.closeOnClick; + args.container = args.container ? args.container : options.container; + args.priority = args.priority ? args.priority : options.priority; + + var template = $templateCache.get(args.template); + + if (template) { + processNotificationTemplate(template); + } else { + // load it via $http only if it isn't default template and template isn't exist in template cache + // cache:true means cache it for later access. + $http.get(args.template, {cache: true}) + .then(function (response) { + processNotificationTemplate(response.data); + }) + .catch(function (data) { + throw new Error('Template (' + args.template + ') could not be loaded. ' + data); + }); + } + + + function processNotificationTemplate(template) { + + var scope = args.scope.$new(); + scope.message = $sce.trustAsHtml(args.message); + scope.title = $sce.trustAsHtml(args.title); + scope.t = args.type.substr(0, 1); + scope.delay = args.delay; + scope.onClose = args.onClose; + scope.onClick = args.onClick; + + var priorityCompareTop = function (a, b) { + return a._priority - b._priority; + }; + + var priorityCompareBtm = function (a, b) { + return b._priority - a._priority; + }; + + var reposite = function () { + var j = 0; + var k = 0; + var lastTop = startTop; + var lastRight = startRight; + var lastPosition = []; + + if (args.positionY === 'top') { + messageElements.sort(priorityCompareTop); + } else if (args.positionY === 'bottom') { + messageElements.sort(priorityCompareBtm); + } + + for (var i = messageElements.length - 1; i >= 0; i--) { + var element = messageElements[i]; + if (args.replaceMessage && i < messageElements.length - 1) { + element.addClass('killed'); + continue; + } + var elHeight = parseInt(element[0].offsetHeight); + var elWidth = parseInt(element[0].offsetWidth); + var position = lastPosition[element._positionY + element._positionX]; + + if ((top + elHeight) > window.innerHeight) { + position = startTop; + k++; + j = 0; + } + + var top = (lastTop = position ? (j === 0 ? position : position + verticalSpacing) : startTop); + var right = lastRight + (k * (horizontalSpacing + elWidth)); + + element.css(element._positionY, top + 'px'); + if (element._positionX === 'center') { + element.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px'); + } else { + element.css(element._positionX, right + 'px'); + } + + lastPosition[element._positionY + element._positionX] = top + elHeight; + + if (options.maxCount > 0 && messageElements.length > options.maxCount && i === 0) { + element.scope().kill(true); + } + + j++; + } + }; + + var templateElement = $compile(template)(scope); + templateElement._positionY = args.positionY; + templateElement._positionX = args.positionX; + templateElement._priority = args.priority; + templateElement.addClass(args.type); + + var closeEvent = function (e) { + e = e.originalEvent || e; + if (e.type === 'click' || e.propertyName === 'opacity' && e.elapsedTime >= 1) { + + if (scope.onClose) { + scope.$apply(scope.onClose(templateElement)); + } + + if (e.type === 'click') + if (scope.onClick) { + scope.$apply(scope.onClick(templateElement)); + } + + templateElement.remove(); + messageElements.splice(messageElements.indexOf(templateElement), 1); + scope.$destroy(); + reposite(); + } + }; + + if (args.closeOnClick) { + templateElement.addClass('clickable'); + templateElement.bind('click', closeEvent); + } + + templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', closeEvent); + + if (angular.isNumber(args.delay)) { + $timeout(function () { + templateElement.addClass('killed'); + }, args.delay); + } + + setCssTransitions('none'); + + angular.element(document.querySelector(args.container)).append(templateElement); + var offset = -(parseInt(templateElement[0].offsetHeight) + 50); + templateElement.css(templateElement._positionY, offset + "px"); + messageElements.push(templateElement); + + if (args.positionX == 'center') { + var elWidth = parseInt(templateElement[0].offsetWidth); + templateElement.css('left', parseInt(window.innerWidth / 2 - elWidth / 2) + 'px'); + } + + $timeout(function () { + setCssTransitions(''); + }); + + function setCssTransitions(value) { + ['-webkit-transition', '-o-transition', 'transition'].forEach(function (prefix) { + templateElement.css(prefix, value); + }); + } + + scope._templateElement = templateElement; + + scope.kill = function (isHard) { + if (isHard) { + if (scope.onClose) { + scope.$apply(scope.onClose(scope._templateElement)); + } + + messageElements.splice(messageElements.indexOf(scope._templateElement), 1); + scope._templateElement.remove(); + scope.$destroy(); + $timeout(reposite); + } else { + scope._templateElement.addClass('killed'); + } + }; + + $timeout(reposite); + + if (!isResizeBound) { + angular.element($window).bind('resize', function (e) { + $timeout(reposite); + }); + isResizeBound = true; + } + + deferred.resolve(scope); + + } + + return deferred.promise; + }; + + notify.primary = function (args) { + return this(args, 'primary'); + }; + notify.error = function (args) { + return this(args, 'error'); + }; + notify.success = function (args) { + return this(args, 'success'); + }; + notify.info = function (args) { + return this(args, 'info'); + }; + notify.warning = function (args) { + return this(args, 'warning'); + }; + + notify.clearAll = function () { + angular.forEach(messageElements, function (element) { + element.addClass('killed'); + }); + }; + + return notify; + }]; +}); + +angular.module("ui-notification").run(["$templateCache", function($templateCache) {$templateCache.put("angular-ui-notification.html","