PageSourceSearch

https://s-textile.ru/vendors/toaster/toaster.js

js s-textile.ru collected 2026-10-08 11:37:26 UTC 24,396 bytes, 460 lines download raw bytes

1/* global angular */
2(function (window, document) {
3    'use strict';
4
5    /*
6     * AngularJS Toaster
7     * Version: 0.4.15
8     *
9     * Copyright 2013-2015 Jiri Kavulak.
10     * All Rights Reserved.
11     * Use, reproduction, distribution, and modification of this code is subject to the terms and
12     * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
13     *
14     * Author: Jiri Kavulak
15     * Related to project of John Papa, Hans Fjällemark and Nguyễn Thiện Hùng (thienhung1989)
16     */
17
18    angular.module('toaster', []).constant(
19        'toasterConfig', {
20            'limit': 0,                   // limits max number of toasts
21            'tap-to-dismiss': true,
22
23            /* Options:
24             - Boolean false/true
25             'close-button': true
26             - object if not a boolean that allows you to
27             override showing the close button for each
28             icon-class value
29             'close-button': { 'toast-error': true, 'toast-info': false }
30             */
31            'close-button': false,
32            'newest-on-top': true, 
33            //'fade-in': 1000,            // done in css
34            //'on-fade-in': undefined,    // not implemented
35            //'fade-out': 1000,           // done in css
36            //'on-fade-out': undefined,   // not implemented
37            //'extended-time-out': 1000,  // not implemented
38            'time-out': 15000, //5000 Set timeOut and extendedTimeout to 0 to make it sticky
39            'icon-classes': {
40                error: 'toast-error',
41                info: 'toast-info',
42                wait: 'toast-wait',
43                success: 'toast-success',
44                warning: 'toast-warning'
45            },
46            'body-output-type': '', // Options: '', 'trustedHtml', 'template', 'templateWithData', 'directive'
47            'body-template': 'toasterBodyTmpl.html',
48            'icon-class': 'toast-info',
49            'position-class': 'toast-top-right', // Options (see CSS):
50            // 'toast-top-full-width', 'toast-bottom-full-width', 'toast-center',
51            // 'toast-top-left', 'toast-top-center', 'toast-top-right',
52            // 'toast-bottom-left', 'toast-bottom-center', 'toast-bottom-right',
53            'title-class': 'toast-title',
54            'message-class': 'toast-message',
55            'prevent-duplicates': false,
56            'mouseover-timer-stop': true // stop timeout on mouseover and restart timer on mouseout
57        }
58        ).service(
59        'toaster', [
60            '$rootScope', 'toasterConfig', function ($rootScope, toasterConfig) {
61                this.pop = function (type, title, body, timeout, bodyOutputType, clickHandler, toasterId, showCloseButton, toastId, onHideCallback) {
62                    if (angular.isObject(type)) {
63                        var params = type; // Enable named parameters as pop argument
64                        this.toast = {
65                            type: params.type,
66                            title: params.title,
67                            body: params.body,
68                            timeout: params.timeout,
69                            bodyOutputType: params.bodyOutputType,
70                            clickHandler: params.clickHandler,
71                            showCloseButton: params.showCloseButton,
72                            uid: params.toastId,
73                            onHideCallback: params.onHideCallback
74                        };
75                        toastId = params.toastId;
76                        toasterId = params.toasterId;
77                    } else {
78                        this.toast = {
79                            type: type,
80                            title: title,
81                            body: body,
82                            timeout: timeout,
83                            bodyOutputType: bodyOutputType,
84                            clickHandler: clickHandler,
85                            showCloseButton: showCloseButton,
86                            uid: toastId,
87                            onHideCallback: onHideCallback
88                        };
89                    }
90                    $rootScope.$emit('toaster-newToast', toasterId, toastId);
91                };
92
93                this.clear = function (toasterId, toastId) {
94                    $rootScope.$emit('toaster-clearToasts', toasterId, toastId);
95                };
96
97                // Create one method per icon class, to allow to call toaster.info() and similar
98                for (var type in toasterConfig['icon-classes']) {
99                    this[type] = createTypeMethod(type);
100                }
101
102                function createTypeMethod(toasterType) {
103                    return function (title, body, timeout, bodyOutputType, clickHandler, toasterId, showCloseButton, toastId, onHideCallback) {
104                        if (angular.isString(title)) {
105                            this.pop(
106                                toasterType,
107                                title,
108                                body,
109                                timeout,
110                                bodyOutputType,
111                                clickHandler,
112                                toasterId,
113                                showCloseButton,
114                                toastId,
115                                onHideCallback
116                                );
117                        } else { // 'title' is actually an object with options
118                            this.pop(angular.extend(title, { type: toasterType }));
119                        }
120                    };
121                }
122            }]
123        ).factory(
124        'toasterEventRegistry', [
125            '$rootScope', function ($rootScope) {
126                var deregisterNewToast = null, deregisterClearToasts = null, newToastEventSubscribers = [], clearToastsEventSubscribers = [], toasterFactory;
127
128                toasterFactory = {
129                    setup: function () {
130                        if (!deregisterNewToast) {
131                            deregisterNewToast = $rootScope.$on(
132                                'toaster-newToast', function (event, toasterId, toastId) {
133                                    for (var i = 0, len = newToastEventSubscribers.length; i < len; i++) {
134                                        newToastEventSubscribers[i](event, toasterId, toastId);
135                                    }
136                                }
137                                );
138                        }
139
140                        if (!deregisterClearToasts) {
141                            deregisterClearToasts = $rootScope.$on(
142                                'toaster-clearToasts', function (event, toasterId, toastId) {
143                                    for (var i = 0, len = clearToastsEventSubscribers.length; i < len; i++) {
144                                        clearToastsEventSubscribers[i](event, toasterId, toastId);
145                                    }
146                                }
147                                );
148                        }
149                    },
150
151                    subscribeToNewToastEvent: function (onNewToast) {
152                        newToastEventSubscribers.push(onNewToast);
153                    },
154                    subscribeToClearToastsEvent: function (onClearToasts) {
155                        clearToastsEventSubscribers.push(onClearToasts);
156                    },
157                    unsubscribeToNewToastEvent: function (onNewToast) {
158                        var index = newToastEventSubscribers.indexOf(onNewToast);
159                        if (index >= 0) {
160                            newToastEventSubscribers.splice(index, 1);
161                        }
162
163                        if (newToastEventSubscribers.length === 0) {
164                            deregisterNewToast();
165                            deregisterNewToast = null;
166                        }
167                    },
168                    unsubscribeToClearToastsEvent: function (onClearToasts) {
169                        var index = clearToastsEventSubscribers.indexOf(onClearToasts);
170                        if (index >= 0) {
171                            clearToastsEventSubscribers.splice(index, 1);
172                        }
173
174                        if (clearToastsEventSubscribers.length === 0) {
175                            deregisterClearToasts();
176                            deregisterClearToasts = null;
177                        }
178                    }
179                };
180                return {
181                    setup: toasterFactory.setup,
182                    subscribeToNewToastEvent: toasterFactory.subscribeToNewToastEvent,
183                    subscribeToClearToastsEvent: toasterFactory.subscribeToClearToastsEvent,
184                    unsubscribeToNewToastEvent: toasterFactory.unsubscribeToNewToastEvent,
185                    unsubscribeToClearToastsEvent: toasterFactory.unsubscribeToClearToastsEvent
186                };
187            }]
188        )
189        .directive('directiveTemplate', ['$compile', function($compile) {
190            return {
191                restrict: 'A',
192                scope: {
193                    directiveName: '@directiveName'
194                },
195                replace: true,   
196                link: function (scope, elm, attrs) {
197                    scope.$watch('directiveName', function (directiveName) {
198                        var template = $compile('<div ' + directiveName + '></div>')(scope);
199                        elm.append(template);
200                    });
201                }
202            }
203        }])
204        .directive(
205        'toasterContainer', [
206            '$parse', '$rootScope', '$interval', '$sce', 'toasterConfig', 'toaster', 'toasterEventRegistry',
207            function ($parse, $rootScope, $interval, $sce, toasterConfig, toaster, toasterEventRegistry) {
208                return {
209                    replace: true,
210                    restrict: 'EA',
211                    scope: true, // creates an internal scope for this directive (one per directive instance)
212                    link: function (scope, elm, attrs) {
213                        var id = 0, mergedConfig;
214
215                        // Merges configuration set in directive with default one
216                        mergedConfig = angular.extend({}, toasterConfig, scope.$eval(attrs.toasterOptions));
217
218                        scope.config = {
219                            toasterId: mergedConfig['toaster-id'],
220                            position: mergedConfig['position-class'],
221                            title: mergedConfig['title-class'],
222                            message: mergedConfig['message-class'],
223                            tap: mergedConfig['tap-to-dismiss'],
224                            closeButton: mergedConfig['close-button'],
225                            animation: mergedConfig['animation-class'],
226                            mouseoverTimer: mergedConfig['mouseover-timer-stop']
227                        };
228
229                        scope.$on(
230                            "$destroy", function () {
231                                toasterEventRegistry.unsubscribeToNewToastEvent(scope._onNewToast);
232                                toasterEventRegistry.unsubscribeToClearToastsEvent(scope._onClearToasts);
233                            }
234                            );
235
236                        function setTimeout(toast, time) {
237                            toast.timeoutPromise = $interval(
238                                function () {
239                                    scope.removeToast(toast.id);
240                                }, time, 1
241                                );
242                        }
243
244                        scope.configureTimer = function (toast) {
245                            var timeout = angular.isNumber(toast.timeout) ? toast.timeout : mergedConfig['time-out'];
246                            if (typeof timeout === "object") timeout = timeout[toast.type];
247                            if (timeout > 0) {
248                                setTimeout(toast, timeout);
249                            }
250                        };
251
252                        function addToast(toast, toastId) {
253                            toast.type = mergedConfig['icon-classes'][toast.type];
254                            if (!toast.type) {
255                                toast.type = mergedConfig['icon-class'];
256                            }
257
258                            if (mergedConfig['prevent-duplicates'] === true) {
259                                // Prevent adding duplicate toasts if it's set
260                                if (isUndefinedOrNull(toastId)) {
261                                    if (scope.toasters.length > 0 && scope.toasters[scope.toasters.length - 1].body === toast.body) {
262                                        return;
263                                    }
264                                } else {
265                                    var i, len;
266                                    for (i = 0, len = scope.toasters.length; i < len; i++) {
267                                        if (scope.toasters[i].uid === toastId) {
268                                            removeToast(i);
269                                            // update loop
270                                            i--;
271                                            len = scope.toasters.length;
272                                        }
273                                    }
274                                }
275                            }
276
277                            toast.id = ++id;
278                            // Sure uid defined
279                            if (!isUndefinedOrNull(toastId)) {
280                                toast.uid = toastId;
281                            }
282
283                            // set the showCloseButton property on the toast so that
284                            // each template can bind directly to the property to show/hide
285                            // the close button
286                            var closeButton = mergedConfig['close-button'];
287
288                            // if toast.showCloseButton is a boolean value,
289                            // it was specifically overriden in the pop arguments
290                            if (typeof toast.showCloseButton === "boolean") {
291
292                            } else if (typeof closeButton === "boolean") {
293                                toast.showCloseButton = closeButton;
294                            } else if (typeof closeButton === "object") {
vendor: 6,722 bytes, lines 295-416
295                                var closeButtonForType = closeButton[toast.type];
296
297                                if (typeof closeButtonForType !== "undefined" && closeButtonForType !== null) {
298                                    toast.showCloseButton = closeButtonForType;
299                                }
300                            } else {
301                                // if an option was not set, default to false.
302                                toast.showCloseButton = false;
303                            }
304
305                            // Set the toast.bodyOutputType to the default if it isn't set
306                            toast.bodyOutputType = toast.bodyOutputType || mergedConfig['body-output-type'];
307                            switch (toast.bodyOutputType) {
308                                case 'trustedHtml':
309                                    toast.html = $sce.trustAsHtml(toast.body);
310                                    break;
311                                case 'template':
312                                    toast.bodyTemplate = toast.body || mergedConfig['body-template'];
313                                    break;
314                                case 'templateWithData':
315                                    var fcGet = $parse(toast.body || mergedConfig['body-template']);
316                                    var templateWithData = fcGet(scope);
317                                    toast.bodyTemplate = templateWithData.template;
318                                    toast.data = templateWithData.data;
319                                    break;
320                                case 'directive':
321                                    toast.html = toast.body;
322                                    break;
323                            }
324
325                            scope.configureTimer(toast);
326                            if (mergedConfig['newest-on-top'] === true) {
327                                scope.toasters.unshift(toast);
328                                if (mergedConfig['limit'] > 0 && scope.toasters.length > mergedConfig['limit']) {
329                                    scope.toasters.pop();
330                                }
331                            } else {
332                                scope.toasters.push(toast);
333                                if (mergedConfig['limit'] > 0 && scope.toasters.length > mergedConfig['limit']) {
334                                    scope.toasters.shift();
335                                }
336                            }
337                        }
338
339                        scope.removeToast = function (id) {
340                            var i, len;
341                            for (i = 0, len = scope.toasters.length; i < len; i++) {
342                                if (scope.toasters[i].id === id) {
343                                    removeToast(i);
344                                    break;
345                                }
346                            }
347                        };
348
349                        function removeToast(toastIndex) {
350                            var toast = scope.toasters[toastIndex];
351                            if (toast) {
352                                if (toast.timeoutPromise) {
353                                    $interval.cancel(toast.timeoutPromise);
354                                }
355                                scope.toasters.splice(toastIndex, 1);
356
357                                if (angular.isFunction(toast.onHideCallback)) {
358                                    toast.onHideCallback();
359                                }
360                            }
361                        }
362
363                        function removeAllToasts(toastId) {
364                            for (var i = scope.toasters.length - 1; i >= 0; i--) {
365                                if (isUndefinedOrNull(toastId)) {
366                                    removeToast(i);
367                                } else {
368                                    if (scope.toasters[i].uid == toastId) {
369                                        removeToast(i);
370                                    }
371                                }
372                            }
373                        }
374
375                        scope.toasters = [];
376
377                        function isUndefinedOrNull(val) {
378                            return angular.isUndefined(val) || val === null;
379                        }
380
381                        scope._onNewToast = function (event, toasterId, toastId) {
382                            // Compatibility: if toaster has no toasterId defined, and if call to display
383                            // hasn't either, then the request is for us
384
385                            if ((isUndefinedOrNull(scope.config.toasterId) && isUndefinedOrNull(toasterId)) || (!isUndefinedOrNull(scope.config.toasterId) && !isUndefinedOrNull(toasterId) && scope.config.toasterId == toasterId)) {
386                                addToast(toaster.toast, toastId);
387                            }
388                        };
389                        scope._onClearToasts = function (event, toasterId, toastId) {
390                            // Compatibility: if toaster has no toasterId defined, and if call to display
391                            // hasn't either, then the request is for us
392                            if (toasterId == '*' || (isUndefinedOrNull(scope.config.toasterId) && isUndefinedOrNull(toasterId)) || (!isUndefinedOrNull(scope.config.toasterId) && !isUndefinedOrNull(toasterId) && scope.config.toasterId == toasterId)) {
393                                removeAllToasts(toastId);
394                            }
395                        };
396
397                        toasterEventRegistry.setup();
398
399                        toasterEventRegistry.subscribeToNewToastEvent(scope._onNewToast);
400                        toasterEventRegistry.subscribeToClearToastsEvent(scope._onClearToasts);
401                    },
402                    controller: [
403                        '$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
404                            // Called on mouseover
405                            $scope.stopTimer = function (toast) {
406                                if ($scope.config.mouseoverTimer === true) {
407                                    if (toast.timeoutPromise) {
408                                        $interval.cancel(toast.timeoutPromise);
409                                        toast.timeoutPromise = null;
410                                    }
411                                }
412                            };
413
414                            // Called on mouseout
415                            $scope.restartTimer = function (toast) {
416                                if ($scope.config.mouseoverTimer === true) {
417                                    if (!toast.timeoutPromise) {
418                                        $scope.configureTimer(toast);
419                                    }
420                                } else if (toast.timeoutPromise === null) {
421                                    $scope.removeToast(toast.id);
422                                }
423                            };
424
425                            $scope.click = function (toast, isCloseButton) {
426                                if ($scope.config.tap === true || (toast.showCloseButton === true && isCloseButton === true)) {
427                                    var removeToast = true;
428                                    if (toast.clickHandler) {
429                                        if (angular.isFunction(toast.clickHandler)) {
430                                            removeToast = toast.clickHandler(toast, isCloseButton);
431                                        } else if (angular.isFunction($scope.$parent.$eval(toast.clickHandler))) {
432                                            removeToast = $scope.$parent.$eval(toast.clickHandler)(toast, isCloseButton);
433                                        } else {
434                                            console.log("TOAST-NOTE: Your click handler is not inside a parent scope of toaster-container.");
435                                        }
436                                    }
437                                    if (removeToast) {
438                                        $scope.removeToast(toast.id);
439                                    }
440                                }
441                            };
442                        }],
443                    template: 
444                        '<div id="toast-container" ng-class="[config.position, config.animation]">' + 
445                            '<div ng-repeat="toaster in toasters" class="toast" ng-class="toaster.type" ng-click="click(toaster)" ng-mouseover="stopTimer(toaster)" ng-mouseout="restartTimer(toaster)">' + 
446                                '<button type="button" class="toast-close-button" ng-show="toaster.showCloseButton" ng-click="click(toaster, true)">&times;</button>' + 
447                                '<div ng-class="config.title">{{toaster.title}}</div>' + 
448                                '<div ng-class="config.message" ng-switch on="toaster.bodyOutputType">' + 
449                                    '<div ng-switch-when="trustedHtml" ng-bind-html="toaster.html"></div>' + 
450                                    '<div ng-switch-when="template"><div ng-include="toaster.bodyTemplate"></div></div>' + 
451                                    '<div ng-switch-when="templateWithData"><div ng-include="toaster.bodyTemplate"></div></div>' +
452                                    '<div ng-switch-when="directive"><div directive-template directive-name="{{toaster.html}}"></div></div>' + 
453                                    '<div ng-switch-default >{{toaster.body}}</div>' + 
454                                '</div>' + 
455                            '</div>' + 
456                        '</div>'
457                };
458            }]
459        );
460})(window, document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.