├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE.md ├── README.md ├── composer.json ├── phpunit.xml ├── resources ├── css │ ├── sweetalert │ │ ├── sweetalert.css │ │ └── sweetalert.min.css │ └── toastr │ │ ├── toastr.css │ │ └── toastr.min.css └── js │ ├── bootbox │ ├── bootbox.js │ └── bootbox.min.js │ ├── jquery │ ├── jquery.js │ └── jquery.min.js │ ├── sweetalert │ ├── sweetalert.js │ └── sweetalert.min.js │ └── toastr │ ├── toastr.js │ └── toastr.min.js ├── src ├── Escaping.php ├── LaravelNotifyServiceProvider.php ├── Notifications │ ├── AddsNotifications.php │ ├── Notification.php │ ├── NotificationFacade.php │ ├── NotificationRenderer.php │ └── Renderers │ │ ├── BootboxRenderer.php │ │ ├── NativeRenderer.php │ │ ├── SweetAlertRenderer.php │ │ └── ToastrRenderer.php └── notifications.php └── tests ├── EscapingTest.php └── Notifications ├── AddsNotificationsTest.php ├── NotificationTest.php ├── NotificationsDirectiveTest.php └── Renderers ├── BootboxRendererTest.php ├── NativeRendererTest.php ├── SweetAlertRendererTest.php └── ToastrRendererTest.php /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-vendored 2 | *.css linguist-vendored -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.lock -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.5.9 5 | - 5.5 6 | - 5.6 7 | - 7.0 8 | - hhvm 9 | 10 | env: 11 | global: 12 | - setup=basic 13 | 14 | matrix: 15 | include: 16 | - php: 5.5.9 17 | env: setup=lowest 18 | - php: 5.5.9 19 | env: setup=stable 20 | 21 | sudo: false 22 | 23 | install: 24 | - if [[ $setup = 'basic' ]]; then travis_retry composer install --no-interaction --prefer-source; fi 25 | - if [[ $setup = 'stable' ]]; then travis_retry composer update --prefer-source --no-interaction --prefer-stable; fi 26 | - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-source --no-interaction --prefer-lowest --prefer-stable; fi 27 | 28 | script: vendor/bin/phpunit -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Rob Gloudemans 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Notify 2 | [![Build Status](https://travis-ci.org/Crinsane/LaravelNotify.svg?branch=master)](https://travis-ci.org/Crinsane/LaravelNotify) 3 | [![Total Downloads](https://poser.pugx.org/gloudemans/notify/downloads)](https://packagist.org/packages/gloudemans/notify) 4 | [![License](https://poser.pugx.org/gloudemans/notify/license)](https://packagist.org/packages/gloudemans/notify) 5 | 6 | Some helpful tools for getting handy flash notifications on your website 7 | Out of the box support for: Toastr, SweetAlert, Bootbox and native notifications! 8 | 9 | # Installation 10 | 11 | Install the package through [Composer](http://getcomposer.org/). Require this package with Composer using the following command: 12 | 13 | composer require gloudemans/notify 14 | 15 | Next you need to register the package in Laravel by adding the service provider. 16 | To do this open your `config/app.php` file and add a new line to the `providers` array: 17 | 18 | Gloudemans\Notify\LaravelNotifyServiceProvider::class, 19 | 20 | Now that the package has been registered you can copy the package config file to your local config with the following command: 21 | 22 | artisan vendor:publish --provider="Gloudemans\Notify\LaravelNotifyServiceProvider" --tag="config" 23 | 24 | Now your all set to use the notification package in your Laravel application. 25 | 26 | ### Optional 27 | 28 | If you'd like to use the `Notification` facade, add a new line to the `aliases` array: 29 | 30 | 'Notification' => Gloudemans\Notify\Notifications\NotificationFacade::class, 31 | 32 | # Usage 33 | 34 | Using this package is actually pretty easy. Adding notifications to your application actually only requires two steps. 35 | 36 | ## Adding a notification 37 | First, of course, you need a way to flash the notification to session so they are available on the next request. 38 | If you've injected the `Gloudemans\Notify\Notifications\Notification` class into, for instance, your controller, flashing 39 | the notification to the session is as easy as this: 40 | 41 | $this->notification->add('success', 'Notification message', 'Notification title'); 42 | 43 | And if you're using the facade it's as easy as: 44 | 45 | Notification::add('success', 'Notification message', 'Notification title'); 46 | 47 | - The first parameter is the type of notification, the package understand four types of notification: `success`, `info`, `warning` and `error`. 48 | - The second parameter is the message of the notification. 49 | - The third *(optional)* parameter is the title of the notification. 50 | 51 | To make life even easier there are also four helper methods for different types of notification. So instead of manually supplying 52 | the notification type you can simply call a method with the type as its name: 53 | 54 | ```php 55 | $this->notification->success('Success notification'); 56 | $this->notification->info('Info notification'); 57 | $this->notification->warning('Warning notification'); 58 | $this->notification->error('Error notification'); 59 | ``` 60 | 61 | Finally you can also add the `Gloudemans\Notify\Notifications\AddsNotifications` trait to your class, which will supply you methods 62 | for adding the notifications: 63 | 64 | ```php 65 | 66 | use AddsNotifications; 67 | 68 | public function yourMethod() 69 | { 70 | $this->notify()->success(...); // Also info(), warning(), error() 71 | $this->notifySuccess(...); 72 | $this->notifyInfo(...); 73 | $this->notifyWarning(...); 74 | $this->notifyError(...); 75 | } 76 | 77 | ``` 78 | 79 | ## Displaying the notifications 80 | 81 | The second step is to actually show the notifications on your website. 82 | All notifications can be rendered using the `render()` method on `Gloudemans\Notify\Notifications\Notification`. 83 | 84 | So a possibility is to add something like this to one of your views: 85 | 86 | render(); ?> 87 | 88 | But if you're like me and don't like code like this in your view there's a nice little Blade directive available: 89 | 90 | @notifications 91 | 92 | Adding this Blade directive to one of your views give the package a place to render the JavaScript output for rendering 93 | the notifications. 94 | 95 | *The recommended location for rendering the notifications is at the bottom of your 'master' layout file* 96 | 97 | ## Renderers 98 | 99 | The packages uses dedicated 'renderer' classes for rendering the notifications. 100 | Out of the box you can choose between: `native` (default), `toastr`, `sweetalert` and `bootbox`. 101 | To change the renderer that the package uses, simply update the value of `notifications` in the `notifications.php` config file. 102 | 103 | The native renderer is the only renderer that doesn't require any extra JavaScript libraries as it uses simple `alert()` functions for showing the notification. 104 | 105 | For all the other renderers the necessary scripts and stylesheets are bundled with the package and can be copied to your public directory with the following command: 106 | 107 | artisan vendor:publish --provider="Gloudemans\Notify\LaravelNotifyServiceProvider" --tag="assets" 108 | 109 | But of course you're free to download them manually or pull them in with another service and include them in your asset build sequence. 110 | 111 | *Make sure the scripts are added BEFORE you call the `render()` method* 112 | 113 | # Extending 114 | 115 | If you want to use another library for notifications in your project, that's totally possible! 116 | What you need to do is create your own renderer and change a binding in the service container of Laravel. 117 | 118 | Your custom renderer must implement the `Gloudemans\Notify\Notifications\NotificationRenderer` interface, which forces you to implement one simple method: 119 | 120 | ```php 121 | /** 122 | * Render the notifications as HTML/JavaScript 123 | * 124 | * @param array $notifications 125 | * @return string 126 | */ 127 | public function render(array $notifications); 128 | ``` 129 | 130 | Once you've created your custom renderer you can bind it to the interface like this: 131 | 132 | ```php 133 | $this->app->bind( 134 | 'Gloudemans\Notify\Notifications\NotificationRenderer', 135 | 'App\Renderers\MyCustomRenderer' 136 | ); 137 | ``` 138 | 139 | And that's all you need to do to extend the package with your custom renderer. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gloudemans/notify", 3 | "description": "Laravel Notifications", 4 | "keywords": ["laravel", "notifications", "flashnotifictions", "notify"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Rob Gloudemans", 9 | "email": "robgloudemans@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.5.0", 14 | "illuminate/support": "^5.1", 15 | "illuminate/session": "^5.1", 16 | "illuminate/view": "^5.1" 17 | }, 18 | "require-dev": { 19 | "phpunit/phpunit": "^4.8", 20 | "mockery/mockery": "^0.9.4" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "Gloudemans\\Notify\\": "src" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /resources/css/sweetalert/sweetalert.css: -------------------------------------------------------------------------------- 1 | body.stop-scrolling { 2 | height: 100%; 3 | overflow: hidden; } 4 | 5 | .sweet-overlay { 6 | background-color: black; 7 | /* IE8 */ 8 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; 9 | /* IE8 */ 10 | background-color: rgba(0, 0, 0, 0.4); 11 | position: fixed; 12 | left: 0; 13 | right: 0; 14 | top: 0; 15 | bottom: 0; 16 | display: none; 17 | z-index: 10000; } 18 | 19 | .sweet-alert { 20 | background-color: white; 21 | font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; 22 | width: 478px; 23 | padding: 17px; 24 | border-radius: 5px; 25 | text-align: center; 26 | position: fixed; 27 | left: 50%; 28 | top: 50%; 29 | margin-left: -256px; 30 | margin-top: -200px; 31 | overflow: hidden; 32 | display: none; 33 | z-index: 99999; } 34 | @media all and (max-width: 540px) { 35 | .sweet-alert { 36 | width: auto; 37 | margin-left: 0; 38 | margin-right: 0; 39 | left: 15px; 40 | right: 15px; } } 41 | .sweet-alert h2 { 42 | color: #575757; 43 | font-size: 30px; 44 | text-align: center; 45 | font-weight: 600; 46 | text-transform: none; 47 | position: relative; 48 | margin: 25px 0; 49 | padding: 0; 50 | line-height: 40px; 51 | display: block; } 52 | .sweet-alert p { 53 | color: #797979; 54 | font-size: 16px; 55 | text-align: center; 56 | font-weight: 300; 57 | position: relative; 58 | text-align: inherit; 59 | float: none; 60 | margin: 0; 61 | padding: 0; 62 | line-height: normal; } 63 | .sweet-alert fieldset { 64 | border: none; 65 | position: relative; } 66 | .sweet-alert .sa-error-container { 67 | background-color: #f1f1f1; 68 | margin-left: -17px; 69 | margin-right: -17px; 70 | overflow: hidden; 71 | padding: 0 10px; 72 | max-height: 0; 73 | webkit-transition: padding 0.15s, max-height 0.15s; 74 | transition: padding 0.15s, max-height 0.15s; } 75 | .sweet-alert .sa-error-container.show { 76 | padding: 10px 0; 77 | max-height: 100px; 78 | webkit-transition: padding 0.2s, max-height 0.2s; 79 | transition: padding 0.25s, max-height 0.25s; } 80 | .sweet-alert .sa-error-container .icon { 81 | display: inline-block; 82 | width: 24px; 83 | height: 24px; 84 | border-radius: 50%; 85 | background-color: #ea7d7d; 86 | color: white; 87 | line-height: 24px; 88 | text-align: center; 89 | margin-right: 3px; } 90 | .sweet-alert .sa-error-container p { 91 | display: inline-block; } 92 | .sweet-alert .sa-input-error { 93 | position: absolute; 94 | top: 29px; 95 | right: 26px; 96 | width: 20px; 97 | height: 20px; 98 | opacity: 0; 99 | -webkit-transform: scale(0.5); 100 | transform: scale(0.5); 101 | -webkit-transform-origin: 50% 50%; 102 | transform-origin: 50% 50%; 103 | -webkit-transition: all 0.1s; 104 | transition: all 0.1s; } 105 | .sweet-alert .sa-input-error::before, .sweet-alert .sa-input-error::after { 106 | content: ""; 107 | width: 20px; 108 | height: 6px; 109 | background-color: #f06e57; 110 | border-radius: 3px; 111 | position: absolute; 112 | top: 50%; 113 | margin-top: -4px; 114 | left: 50%; 115 | margin-left: -9px; } 116 | .sweet-alert .sa-input-error::before { 117 | -webkit-transform: rotate(-45deg); 118 | transform: rotate(-45deg); } 119 | .sweet-alert .sa-input-error::after { 120 | -webkit-transform: rotate(45deg); 121 | transform: rotate(45deg); } 122 | .sweet-alert .sa-input-error.show { 123 | opacity: 1; 124 | -webkit-transform: scale(1); 125 | transform: scale(1); } 126 | .sweet-alert input { 127 | width: 100%; 128 | box-sizing: border-box; 129 | border-radius: 3px; 130 | border: 1px solid #d7d7d7; 131 | height: 43px; 132 | margin-top: 10px; 133 | margin-bottom: 17px; 134 | font-size: 18px; 135 | box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.06); 136 | padding: 0 12px; 137 | display: none; 138 | -webkit-transition: all 0.3s; 139 | transition: all 0.3s; } 140 | .sweet-alert input:focus { 141 | outline: none; 142 | box-shadow: 0px 0px 3px #c4e6f5; 143 | border: 1px solid #b4dbed; } 144 | .sweet-alert input:focus::-moz-placeholder { 145 | transition: opacity 0.3s 0.03s ease; 146 | opacity: 0.5; } 147 | .sweet-alert input:focus:-ms-input-placeholder { 148 | transition: opacity 0.3s 0.03s ease; 149 | opacity: 0.5; } 150 | .sweet-alert input:focus::-webkit-input-placeholder { 151 | transition: opacity 0.3s 0.03s ease; 152 | opacity: 0.5; } 153 | .sweet-alert input::-moz-placeholder { 154 | color: #bdbdbd; } 155 | .sweet-alert input:-ms-input-placeholder { 156 | color: #bdbdbd; } 157 | .sweet-alert input::-webkit-input-placeholder { 158 | color: #bdbdbd; } 159 | .sweet-alert.show-input input { 160 | display: block; } 161 | .sweet-alert .sa-confirm-button-container { 162 | display: inline-block; 163 | position: relative; } 164 | .sweet-alert .la-ball-fall { 165 | position: absolute; 166 | left: 50%; 167 | top: 50%; 168 | margin-left: -27px; 169 | margin-top: 4px; 170 | opacity: 0; 171 | visibility: hidden; } 172 | .sweet-alert button { 173 | background-color: #8CD4F5; 174 | color: white; 175 | border: none; 176 | box-shadow: none; 177 | font-size: 17px; 178 | font-weight: 500; 179 | -webkit-border-radius: 4px; 180 | border-radius: 5px; 181 | padding: 10px 32px; 182 | margin: 26px 5px 0 5px; 183 | cursor: pointer; } 184 | .sweet-alert button:focus { 185 | outline: none; 186 | box-shadow: 0 0 2px rgba(128, 179, 235, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.05); } 187 | .sweet-alert button:hover { 188 | background-color: #7ecff4; } 189 | .sweet-alert button:active { 190 | background-color: #5dc2f1; } 191 | .sweet-alert button.cancel { 192 | background-color: #C1C1C1; } 193 | .sweet-alert button.cancel:hover { 194 | background-color: #b9b9b9; } 195 | .sweet-alert button.cancel:active { 196 | background-color: #a8a8a8; } 197 | .sweet-alert button.cancel:focus { 198 | box-shadow: rgba(197, 205, 211, 0.8) 0px 0px 2px, rgba(0, 0, 0, 0.0470588) 0px 0px 0px 1px inset !important; } 199 | .sweet-alert button[disabled] { 200 | opacity: .6; 201 | cursor: default; } 202 | .sweet-alert button.confirm[disabled] { 203 | color: transparent; } 204 | .sweet-alert button.confirm[disabled] ~ .la-ball-fall { 205 | opacity: 1; 206 | visibility: visible; 207 | transition-delay: 0s; } 208 | .sweet-alert button::-moz-focus-inner { 209 | border: 0; } 210 | .sweet-alert[data-has-cancel-button=false] button { 211 | box-shadow: none !important; } 212 | .sweet-alert[data-has-confirm-button=false][data-has-cancel-button=false] { 213 | padding-bottom: 40px; } 214 | .sweet-alert .sa-icon { 215 | width: 80px; 216 | height: 80px; 217 | border: 4px solid gray; 218 | -webkit-border-radius: 40px; 219 | border-radius: 40px; 220 | border-radius: 50%; 221 | margin: 20px auto; 222 | padding: 0; 223 | position: relative; 224 | box-sizing: content-box; } 225 | .sweet-alert .sa-icon.sa-error { 226 | border-color: #F27474; } 227 | .sweet-alert .sa-icon.sa-error .sa-x-mark { 228 | position: relative; 229 | display: block; } 230 | .sweet-alert .sa-icon.sa-error .sa-line { 231 | position: absolute; 232 | height: 5px; 233 | width: 47px; 234 | background-color: #F27474; 235 | display: block; 236 | top: 37px; 237 | border-radius: 2px; } 238 | .sweet-alert .sa-icon.sa-error .sa-line.sa-left { 239 | -webkit-transform: rotate(45deg); 240 | transform: rotate(45deg); 241 | left: 17px; } 242 | .sweet-alert .sa-icon.sa-error .sa-line.sa-right { 243 | -webkit-transform: rotate(-45deg); 244 | transform: rotate(-45deg); 245 | right: 16px; } 246 | .sweet-alert .sa-icon.sa-warning { 247 | border-color: #F8BB86; } 248 | .sweet-alert .sa-icon.sa-warning .sa-body { 249 | position: absolute; 250 | width: 5px; 251 | height: 47px; 252 | left: 50%; 253 | top: 10px; 254 | -webkit-border-radius: 2px; 255 | border-radius: 2px; 256 | margin-left: -2px; 257 | background-color: #F8BB86; } 258 | .sweet-alert .sa-icon.sa-warning .sa-dot { 259 | position: absolute; 260 | width: 7px; 261 | height: 7px; 262 | -webkit-border-radius: 50%; 263 | border-radius: 50%; 264 | margin-left: -3px; 265 | left: 50%; 266 | bottom: 10px; 267 | background-color: #F8BB86; } 268 | .sweet-alert .sa-icon.sa-info { 269 | border-color: #C9DAE1; } 270 | .sweet-alert .sa-icon.sa-info::before { 271 | content: ""; 272 | position: absolute; 273 | width: 5px; 274 | height: 29px; 275 | left: 50%; 276 | bottom: 17px; 277 | border-radius: 2px; 278 | margin-left: -2px; 279 | background-color: #C9DAE1; } 280 | .sweet-alert .sa-icon.sa-info::after { 281 | content: ""; 282 | position: absolute; 283 | width: 7px; 284 | height: 7px; 285 | border-radius: 50%; 286 | margin-left: -3px; 287 | top: 19px; 288 | background-color: #C9DAE1; } 289 | .sweet-alert .sa-icon.sa-success { 290 | border-color: #A5DC86; } 291 | .sweet-alert .sa-icon.sa-success::before, .sweet-alert .sa-icon.sa-success::after { 292 | content: ''; 293 | -webkit-border-radius: 40px; 294 | border-radius: 40px; 295 | border-radius: 50%; 296 | position: absolute; 297 | width: 60px; 298 | height: 120px; 299 | background: white; 300 | -webkit-transform: rotate(45deg); 301 | transform: rotate(45deg); } 302 | .sweet-alert .sa-icon.sa-success::before { 303 | -webkit-border-radius: 120px 0 0 120px; 304 | border-radius: 120px 0 0 120px; 305 | top: -7px; 306 | left: -33px; 307 | -webkit-transform: rotate(-45deg); 308 | transform: rotate(-45deg); 309 | -webkit-transform-origin: 60px 60px; 310 | transform-origin: 60px 60px; } 311 | .sweet-alert .sa-icon.sa-success::after { 312 | -webkit-border-radius: 0 120px 120px 0; 313 | border-radius: 0 120px 120px 0; 314 | top: -11px; 315 | left: 30px; 316 | -webkit-transform: rotate(-45deg); 317 | transform: rotate(-45deg); 318 | -webkit-transform-origin: 0px 60px; 319 | transform-origin: 0px 60px; } 320 | .sweet-alert .sa-icon.sa-success .sa-placeholder { 321 | width: 80px; 322 | height: 80px; 323 | border: 4px solid rgba(165, 220, 134, 0.2); 324 | -webkit-border-radius: 40px; 325 | border-radius: 40px; 326 | border-radius: 50%; 327 | box-sizing: content-box; 328 | position: absolute; 329 | left: -4px; 330 | top: -4px; 331 | z-index: 2; } 332 | .sweet-alert .sa-icon.sa-success .sa-fix { 333 | width: 5px; 334 | height: 90px; 335 | background-color: white; 336 | position: absolute; 337 | left: 28px; 338 | top: 8px; 339 | z-index: 1; 340 | -webkit-transform: rotate(-45deg); 341 | transform: rotate(-45deg); } 342 | .sweet-alert .sa-icon.sa-success .sa-line { 343 | height: 5px; 344 | background-color: #A5DC86; 345 | display: block; 346 | border-radius: 2px; 347 | position: absolute; 348 | z-index: 2; } 349 | .sweet-alert .sa-icon.sa-success .sa-line.sa-tip { 350 | width: 25px; 351 | left: 14px; 352 | top: 46px; 353 | -webkit-transform: rotate(45deg); 354 | transform: rotate(45deg); } 355 | .sweet-alert .sa-icon.sa-success .sa-line.sa-long { 356 | width: 47px; 357 | right: 8px; 358 | top: 38px; 359 | -webkit-transform: rotate(-45deg); 360 | transform: rotate(-45deg); } 361 | .sweet-alert .sa-icon.sa-custom { 362 | background-size: contain; 363 | border-radius: 0; 364 | border: none; 365 | background-position: center center; 366 | background-repeat: no-repeat; } 367 | 368 | /* 369 | * Animations 370 | */ 371 | @-webkit-keyframes showSweetAlert { 372 | 0% { 373 | transform: scale(0.7); 374 | -webkit-transform: scale(0.7); } 375 | 45% { 376 | transform: scale(1.05); 377 | -webkit-transform: scale(1.05); } 378 | 80% { 379 | transform: scale(0.95); 380 | -webkit-transform: scale(0.95); } 381 | 100% { 382 | transform: scale(1); 383 | -webkit-transform: scale(1); } } 384 | 385 | @keyframes showSweetAlert { 386 | 0% { 387 | transform: scale(0.7); 388 | -webkit-transform: scale(0.7); } 389 | 45% { 390 | transform: scale(1.05); 391 | -webkit-transform: scale(1.05); } 392 | 80% { 393 | transform: scale(0.95); 394 | -webkit-transform: scale(0.95); } 395 | 100% { 396 | transform: scale(1); 397 | -webkit-transform: scale(1); } } 398 | 399 | @-webkit-keyframes hideSweetAlert { 400 | 0% { 401 | transform: scale(1); 402 | -webkit-transform: scale(1); } 403 | 100% { 404 | transform: scale(0.5); 405 | -webkit-transform: scale(0.5); } } 406 | 407 | @keyframes hideSweetAlert { 408 | 0% { 409 | transform: scale(1); 410 | -webkit-transform: scale(1); } 411 | 100% { 412 | transform: scale(0.5); 413 | -webkit-transform: scale(0.5); } } 414 | 415 | @-webkit-keyframes slideFromTop { 416 | 0% { 417 | top: 0%; } 418 | 100% { 419 | top: 50%; } } 420 | 421 | @keyframes slideFromTop { 422 | 0% { 423 | top: 0%; } 424 | 100% { 425 | top: 50%; } } 426 | 427 | @-webkit-keyframes slideToTop { 428 | 0% { 429 | top: 50%; } 430 | 100% { 431 | top: 0%; } } 432 | 433 | @keyframes slideToTop { 434 | 0% { 435 | top: 50%; } 436 | 100% { 437 | top: 0%; } } 438 | 439 | @-webkit-keyframes slideFromBottom { 440 | 0% { 441 | top: 70%; } 442 | 100% { 443 | top: 50%; } } 444 | 445 | @keyframes slideFromBottom { 446 | 0% { 447 | top: 70%; } 448 | 100% { 449 | top: 50%; } } 450 | 451 | @-webkit-keyframes slideToBottom { 452 | 0% { 453 | top: 50%; } 454 | 100% { 455 | top: 70%; } } 456 | 457 | @keyframes slideToBottom { 458 | 0% { 459 | top: 50%; } 460 | 100% { 461 | top: 70%; } } 462 | 463 | .showSweetAlert[data-animation=pop] { 464 | -webkit-animation: showSweetAlert 0.3s; 465 | animation: showSweetAlert 0.3s; } 466 | 467 | .showSweetAlert[data-animation=none] { 468 | -webkit-animation: none; 469 | animation: none; } 470 | 471 | .showSweetAlert[data-animation=slide-from-top] { 472 | -webkit-animation: slideFromTop 0.3s; 473 | animation: slideFromTop 0.3s; } 474 | 475 | .showSweetAlert[data-animation=slide-from-bottom] { 476 | -webkit-animation: slideFromBottom 0.3s; 477 | animation: slideFromBottom 0.3s; } 478 | 479 | .hideSweetAlert[data-animation=pop] { 480 | -webkit-animation: hideSweetAlert 0.2s; 481 | animation: hideSweetAlert 0.2s; } 482 | 483 | .hideSweetAlert[data-animation=none] { 484 | -webkit-animation: none; 485 | animation: none; } 486 | 487 | .hideSweetAlert[data-animation=slide-from-top] { 488 | -webkit-animation: slideToTop 0.4s; 489 | animation: slideToTop 0.4s; } 490 | 491 | .hideSweetAlert[data-animation=slide-from-bottom] { 492 | -webkit-animation: slideToBottom 0.3s; 493 | animation: slideToBottom 0.3s; } 494 | 495 | @-webkit-keyframes animateSuccessTip { 496 | 0% { 497 | width: 0; 498 | left: 1px; 499 | top: 19px; } 500 | 54% { 501 | width: 0; 502 | left: 1px; 503 | top: 19px; } 504 | 70% { 505 | width: 50px; 506 | left: -8px; 507 | top: 37px; } 508 | 84% { 509 | width: 17px; 510 | left: 21px; 511 | top: 48px; } 512 | 100% { 513 | width: 25px; 514 | left: 14px; 515 | top: 45px; } } 516 | 517 | @keyframes animateSuccessTip { 518 | 0% { 519 | width: 0; 520 | left: 1px; 521 | top: 19px; } 522 | 54% { 523 | width: 0; 524 | left: 1px; 525 | top: 19px; } 526 | 70% { 527 | width: 50px; 528 | left: -8px; 529 | top: 37px; } 530 | 84% { 531 | width: 17px; 532 | left: 21px; 533 | top: 48px; } 534 | 100% { 535 | width: 25px; 536 | left: 14px; 537 | top: 45px; } } 538 | 539 | @-webkit-keyframes animateSuccessLong { 540 | 0% { 541 | width: 0; 542 | right: 46px; 543 | top: 54px; } 544 | 65% { 545 | width: 0; 546 | right: 46px; 547 | top: 54px; } 548 | 84% { 549 | width: 55px; 550 | right: 0px; 551 | top: 35px; } 552 | 100% { 553 | width: 47px; 554 | right: 8px; 555 | top: 38px; } } 556 | 557 | @keyframes animateSuccessLong { 558 | 0% { 559 | width: 0; 560 | right: 46px; 561 | top: 54px; } 562 | 65% { 563 | width: 0; 564 | right: 46px; 565 | top: 54px; } 566 | 84% { 567 | width: 55px; 568 | right: 0px; 569 | top: 35px; } 570 | 100% { 571 | width: 47px; 572 | right: 8px; 573 | top: 38px; } } 574 | 575 | @-webkit-keyframes rotatePlaceholder { 576 | 0% { 577 | transform: rotate(-45deg); 578 | -webkit-transform: rotate(-45deg); } 579 | 5% { 580 | transform: rotate(-45deg); 581 | -webkit-transform: rotate(-45deg); } 582 | 12% { 583 | transform: rotate(-405deg); 584 | -webkit-transform: rotate(-405deg); } 585 | 100% { 586 | transform: rotate(-405deg); 587 | -webkit-transform: rotate(-405deg); } } 588 | 589 | @keyframes rotatePlaceholder { 590 | 0% { 591 | transform: rotate(-45deg); 592 | -webkit-transform: rotate(-45deg); } 593 | 5% { 594 | transform: rotate(-45deg); 595 | -webkit-transform: rotate(-45deg); } 596 | 12% { 597 | transform: rotate(-405deg); 598 | -webkit-transform: rotate(-405deg); } 599 | 100% { 600 | transform: rotate(-405deg); 601 | -webkit-transform: rotate(-405deg); } } 602 | 603 | .animateSuccessTip { 604 | -webkit-animation: animateSuccessTip 0.75s; 605 | animation: animateSuccessTip 0.75s; } 606 | 607 | .animateSuccessLong { 608 | -webkit-animation: animateSuccessLong 0.75s; 609 | animation: animateSuccessLong 0.75s; } 610 | 611 | .sa-icon.sa-success.animate::after { 612 | -webkit-animation: rotatePlaceholder 4.25s ease-in; 613 | animation: rotatePlaceholder 4.25s ease-in; } 614 | 615 | @-webkit-keyframes animateErrorIcon { 616 | 0% { 617 | transform: rotateX(100deg); 618 | -webkit-transform: rotateX(100deg); 619 | opacity: 0; } 620 | 100% { 621 | transform: rotateX(0deg); 622 | -webkit-transform: rotateX(0deg); 623 | opacity: 1; } } 624 | 625 | @keyframes animateErrorIcon { 626 | 0% { 627 | transform: rotateX(100deg); 628 | -webkit-transform: rotateX(100deg); 629 | opacity: 0; } 630 | 100% { 631 | transform: rotateX(0deg); 632 | -webkit-transform: rotateX(0deg); 633 | opacity: 1; } } 634 | 635 | .animateErrorIcon { 636 | -webkit-animation: animateErrorIcon 0.5s; 637 | animation: animateErrorIcon 0.5s; } 638 | 639 | @-webkit-keyframes animateXMark { 640 | 0% { 641 | transform: scale(0.4); 642 | -webkit-transform: scale(0.4); 643 | margin-top: 26px; 644 | opacity: 0; } 645 | 50% { 646 | transform: scale(0.4); 647 | -webkit-transform: scale(0.4); 648 | margin-top: 26px; 649 | opacity: 0; } 650 | 80% { 651 | transform: scale(1.15); 652 | -webkit-transform: scale(1.15); 653 | margin-top: -6px; } 654 | 100% { 655 | transform: scale(1); 656 | -webkit-transform: scale(1); 657 | margin-top: 0; 658 | opacity: 1; } } 659 | 660 | @keyframes animateXMark { 661 | 0% { 662 | transform: scale(0.4); 663 | -webkit-transform: scale(0.4); 664 | margin-top: 26px; 665 | opacity: 0; } 666 | 50% { 667 | transform: scale(0.4); 668 | -webkit-transform: scale(0.4); 669 | margin-top: 26px; 670 | opacity: 0; } 671 | 80% { 672 | transform: scale(1.15); 673 | -webkit-transform: scale(1.15); 674 | margin-top: -6px; } 675 | 100% { 676 | transform: scale(1); 677 | -webkit-transform: scale(1); 678 | margin-top: 0; 679 | opacity: 1; } } 680 | 681 | .animateXMark { 682 | -webkit-animation: animateXMark 0.5s; 683 | animation: animateXMark 0.5s; } 684 | 685 | @-webkit-keyframes pulseWarning { 686 | 0% { 687 | border-color: #F8D486; } 688 | 100% { 689 | border-color: #F8BB86; } } 690 | 691 | @keyframes pulseWarning { 692 | 0% { 693 | border-color: #F8D486; } 694 | 100% { 695 | border-color: #F8BB86; } } 696 | 697 | .pulseWarning { 698 | -webkit-animation: pulseWarning 0.75s infinite alternate; 699 | animation: pulseWarning 0.75s infinite alternate; } 700 | 701 | @-webkit-keyframes pulseWarningIns { 702 | 0% { 703 | background-color: #F8D486; } 704 | 100% { 705 | background-color: #F8BB86; } } 706 | 707 | @keyframes pulseWarningIns { 708 | 0% { 709 | background-color: #F8D486; } 710 | 100% { 711 | background-color: #F8BB86; } } 712 | 713 | .pulseWarningIns { 714 | -webkit-animation: pulseWarningIns 0.75s infinite alternate; 715 | animation: pulseWarningIns 0.75s infinite alternate; } 716 | 717 | @-webkit-keyframes rotate-loading { 718 | 0% { 719 | transform: rotate(0deg); } 720 | 100% { 721 | transform: rotate(360deg); } } 722 | 723 | @keyframes rotate-loading { 724 | 0% { 725 | transform: rotate(0deg); } 726 | 100% { 727 | transform: rotate(360deg); } } 728 | 729 | /* Internet Explorer 9 has some special quirks that are fixed here */ 730 | /* The icons are not animated. */ 731 | /* This file is automatically merged into sweet-alert.min.js through Gulp */ 732 | /* Error icon */ 733 | .sweet-alert .sa-icon.sa-error .sa-line.sa-left { 734 | -ms-transform: rotate(45deg) \9; } 735 | 736 | .sweet-alert .sa-icon.sa-error .sa-line.sa-right { 737 | -ms-transform: rotate(-45deg) \9; } 738 | 739 | /* Success icon */ 740 | .sweet-alert .sa-icon.sa-success { 741 | border-color: transparent\9; } 742 | 743 | .sweet-alert .sa-icon.sa-success .sa-line.sa-tip { 744 | -ms-transform: rotate(45deg) \9; } 745 | 746 | .sweet-alert .sa-icon.sa-success .sa-line.sa-long { 747 | -ms-transform: rotate(-45deg) \9; } 748 | 749 | /*! 750 | * Load Awesome v1.1.0 (http://github.danielcardoso.net/load-awesome/) 751 | * Copyright 2015 Daniel Cardoso <@DanielCardoso> 752 | * Licensed under MIT 753 | */ 754 | .la-ball-fall, 755 | .la-ball-fall > div { 756 | position: relative; 757 | -webkit-box-sizing: border-box; 758 | -moz-box-sizing: border-box; 759 | box-sizing: border-box; } 760 | 761 | .la-ball-fall { 762 | display: block; 763 | font-size: 0; 764 | color: #fff; } 765 | 766 | .la-ball-fall.la-dark { 767 | color: #333; } 768 | 769 | .la-ball-fall > div { 770 | display: inline-block; 771 | float: none; 772 | background-color: currentColor; 773 | border: 0 solid currentColor; } 774 | 775 | .la-ball-fall { 776 | width: 54px; 777 | height: 18px; } 778 | 779 | .la-ball-fall > div { 780 | width: 10px; 781 | height: 10px; 782 | margin: 4px; 783 | border-radius: 100%; 784 | opacity: 0; 785 | -webkit-animation: ball-fall 1s ease-in-out infinite; 786 | -moz-animation: ball-fall 1s ease-in-out infinite; 787 | -o-animation: ball-fall 1s ease-in-out infinite; 788 | animation: ball-fall 1s ease-in-out infinite; } 789 | 790 | .la-ball-fall > div:nth-child(1) { 791 | -webkit-animation-delay: -200ms; 792 | -moz-animation-delay: -200ms; 793 | -o-animation-delay: -200ms; 794 | animation-delay: -200ms; } 795 | 796 | .la-ball-fall > div:nth-child(2) { 797 | -webkit-animation-delay: -100ms; 798 | -moz-animation-delay: -100ms; 799 | -o-animation-delay: -100ms; 800 | animation-delay: -100ms; } 801 | 802 | .la-ball-fall > div:nth-child(3) { 803 | -webkit-animation-delay: 0ms; 804 | -moz-animation-delay: 0ms; 805 | -o-animation-delay: 0ms; 806 | animation-delay: 0ms; } 807 | 808 | .la-ball-fall.la-sm { 809 | width: 26px; 810 | height: 8px; } 811 | 812 | .la-ball-fall.la-sm > div { 813 | width: 4px; 814 | height: 4px; 815 | margin: 2px; } 816 | 817 | .la-ball-fall.la-2x { 818 | width: 108px; 819 | height: 36px; } 820 | 821 | .la-ball-fall.la-2x > div { 822 | width: 20px; 823 | height: 20px; 824 | margin: 8px; } 825 | 826 | .la-ball-fall.la-3x { 827 | width: 162px; 828 | height: 54px; } 829 | 830 | .la-ball-fall.la-3x > div { 831 | width: 30px; 832 | height: 30px; 833 | margin: 12px; } 834 | 835 | /* 836 | * Animation 837 | */ 838 | @-webkit-keyframes ball-fall { 839 | 0% { 840 | opacity: 0; 841 | -webkit-transform: translateY(-145%); 842 | transform: translateY(-145%); } 843 | 10% { 844 | opacity: .5; } 845 | 20% { 846 | opacity: 1; 847 | -webkit-transform: translateY(0); 848 | transform: translateY(0); } 849 | 80% { 850 | opacity: 1; 851 | -webkit-transform: translateY(0); 852 | transform: translateY(0); } 853 | 90% { 854 | opacity: .5; } 855 | 100% { 856 | opacity: 0; 857 | -webkit-transform: translateY(145%); 858 | transform: translateY(145%); } } 859 | 860 | @-moz-keyframes ball-fall { 861 | 0% { 862 | opacity: 0; 863 | -moz-transform: translateY(-145%); 864 | transform: translateY(-145%); } 865 | 10% { 866 | opacity: .5; } 867 | 20% { 868 | opacity: 1; 869 | -moz-transform: translateY(0); 870 | transform: translateY(0); } 871 | 80% { 872 | opacity: 1; 873 | -moz-transform: translateY(0); 874 | transform: translateY(0); } 875 | 90% { 876 | opacity: .5; } 877 | 100% { 878 | opacity: 0; 879 | -moz-transform: translateY(145%); 880 | transform: translateY(145%); } } 881 | 882 | @-o-keyframes ball-fall { 883 | 0% { 884 | opacity: 0; 885 | -o-transform: translateY(-145%); 886 | transform: translateY(-145%); } 887 | 10% { 888 | opacity: .5; } 889 | 20% { 890 | opacity: 1; 891 | -o-transform: translateY(0); 892 | transform: translateY(0); } 893 | 80% { 894 | opacity: 1; 895 | -o-transform: translateY(0); 896 | transform: translateY(0); } 897 | 90% { 898 | opacity: .5; } 899 | 100% { 900 | opacity: 0; 901 | -o-transform: translateY(145%); 902 | transform: translateY(145%); } } 903 | 904 | @keyframes ball-fall { 905 | 0% { 906 | opacity: 0; 907 | -webkit-transform: translateY(-145%); 908 | -moz-transform: translateY(-145%); 909 | -o-transform: translateY(-145%); 910 | transform: translateY(-145%); } 911 | 10% { 912 | opacity: .5; } 913 | 20% { 914 | opacity: 1; 915 | -webkit-transform: translateY(0); 916 | -moz-transform: translateY(0); 917 | -o-transform: translateY(0); 918 | transform: translateY(0); } 919 | 80% { 920 | opacity: 1; 921 | -webkit-transform: translateY(0); 922 | -moz-transform: translateY(0); 923 | -o-transform: translateY(0); 924 | transform: translateY(0); } 925 | 90% { 926 | opacity: .5; } 927 | 100% { 928 | opacity: 0; 929 | -webkit-transform: translateY(145%); 930 | -moz-transform: translateY(145%); 931 | -o-transform: translateY(145%); 932 | transform: translateY(145%); } } 933 | -------------------------------------------------------------------------------- /resources/css/sweetalert/sweetalert.min.css: -------------------------------------------------------------------------------- 1 | .sweet-alert,.sweet-overlay{position:fixed;display:none}body.stop-scrolling{height:100%;overflow:hidden}.sweet-overlay{background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";background-color:rgba(0,0,0,.4);left:0;right:0;top:0;bottom:0;z-index:10000}.sweet-alert{background-color:#fff;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;width:478px;padding:17px;border-radius:5px;text-align:center;left:50%;top:50%;margin-left:-256px;margin-top:-200px;overflow:hidden;z-index:99999}@media all and (max-width:540px){.sweet-alert{width:auto;margin-left:0;margin-right:0;left:15px;right:15px}}.sweet-alert h2{color:#575757;font-size:30px;text-align:center;font-weight:600;text-transform:none;position:relative;margin:25px 0;padding:0;line-height:40px;display:block}.sweet-alert p{color:#797979;font-size:16px;font-weight:300;position:relative;text-align:inherit;float:none;margin:0;padding:0;line-height:normal}.sweet-alert fieldset{border:none;position:relative}.sweet-alert .sa-error-container{background-color:#f1f1f1;margin-left:-17px;margin-right:-17px;overflow:hidden;padding:0 10px;max-height:0;webkit-transition:padding .15s,max-height .15s;transition:padding .15s,max-height .15s}.sweet-alert .sa-error-container.show{padding:10px 0;max-height:100px;webkit-transition:padding .2s,max-height .2s;transition:padding .25s,max-height .25s}.sweet-alert .sa-error-container .icon{display:inline-block;width:24px;height:24px;border-radius:50%;background-color:#ea7d7d;color:#fff;line-height:24px;text-align:center;margin-right:3px}.sweet-alert .sa-error-container p{display:inline-block}.sweet-alert .sa-input-error{position:absolute;top:29px;right:26px;width:20px;height:20px;opacity:0;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transform-origin:50% 50%;transform-origin:50% 50%;-webkit-transition:all .1s;transition:all .1s}.sweet-alert .sa-input-error::after,.sweet-alert .sa-input-error::before{content:"";width:20px;height:6px;background-color:#f06e57;border-radius:3px;position:absolute;top:50%;margin-top:-4px;left:50%;margin-left:-9px}.sweet-alert .sa-input-error::before{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.sweet-alert .sa-input-error::after{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.sweet-alert .sa-input-error.show{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.sweet-alert input{width:100%;box-sizing:border-box;border-radius:3px;border:1px solid #d7d7d7;height:43px;margin-top:10px;margin-bottom:17px;font-size:18px;box-shadow:inset 0 1px 1px rgba(0,0,0,.06);padding:0 12px;display:none;-webkit-transition:all .3s;transition:all .3s}.sweet-alert input:focus{outline:0;box-shadow:0 0 3px #c4e6f5;border:1px solid #b4dbed}.sweet-alert input:focus::-moz-placeholder{transition:opacity .3s .03s ease;opacity:.5}.sweet-alert input:focus:-ms-input-placeholder{transition:opacity .3s .03s ease;opacity:.5}.sweet-alert input:focus::-webkit-input-placeholder{transition:opacity .3s .03s ease;opacity:.5}.sweet-alert input::-moz-placeholder{color:#bdbdbd}.sweet-alert input:-ms-input-placeholder{color:#bdbdbd}.sweet-alert input::-webkit-input-placeholder{color:#bdbdbd}.sweet-alert.show-input input{display:block}.sweet-alert .sa-confirm-button-container{display:inline-block;position:relative}.sweet-alert .la-ball-fall{position:absolute;left:50%;top:50%;margin-left:-27px;margin-top:4px;opacity:0;visibility:hidden}.sweet-alert button{background-color:#8CD4F5;color:#fff;border:none;box-shadow:none;font-size:17px;font-weight:500;-webkit-border-radius:4px;border-radius:5px;padding:10px 32px;margin:26px 5px 0;cursor:pointer}.sweet-alert button:focus{outline:0;box-shadow:0 0 2px rgba(128,179,235,.5),inset 0 0 0 1px rgba(0,0,0,.05)}.sweet-alert button:hover{background-color:#7ecff4}.sweet-alert button:active{background-color:#5dc2f1}.sweet-alert button.cancel{background-color:#C1C1C1}.sweet-alert button.cancel:hover{background-color:#b9b9b9}.sweet-alert button.cancel:active{background-color:#a8a8a8}.sweet-alert button.cancel:focus{box-shadow:rgba(197,205,211,.8) 0 0 2px,rgba(0,0,0,.0470588) 0 0 0 1px inset!important}.sweet-alert button[disabled]{opacity:.6;cursor:default}.sweet-alert button.confirm[disabled]{color:transparent}.sweet-alert button.confirm[disabled]~.la-ball-fall{opacity:1;visibility:visible;transition-delay:0s}.sweet-alert button::-moz-focus-inner{border:0}.sweet-alert[data-has-cancel-button=false] button{box-shadow:none!important}.sweet-alert[data-has-confirm-button=false][data-has-cancel-button=false]{padding-bottom:40px}.sweet-alert .sa-icon{width:80px;height:80px;border:4px solid gray;-webkit-border-radius:40px;border-radius:50%;margin:20px auto;padding:0;position:relative;box-sizing:content-box}.sweet-alert .sa-icon.sa-error{border-color:#F27474}.sweet-alert .sa-icon.sa-error .sa-x-mark{position:relative;display:block}.sweet-alert .sa-icon.sa-error .sa-line{position:absolute;height:5px;width:47px;background-color:#F27474;display:block;top:37px;border-radius:2px}.sweet-alert .sa-icon.sa-error .sa-line.sa-left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.sweet-alert .sa-icon.sa-error .sa-line.sa-right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}.sweet-alert .sa-icon.sa-warning{border-color:#F8BB86}.sweet-alert .sa-icon.sa-warning .sa-body{position:absolute;width:5px;height:47px;left:50%;top:10px;-webkit-border-radius:2px;border-radius:2px;margin-left:-2px;background-color:#F8BB86}.sweet-alert .sa-icon.sa-warning .sa-dot{position:absolute;width:7px;height:7px;-webkit-border-radius:50%;border-radius:50%;margin-left:-3px;left:50%;bottom:10px;background-color:#F8BB86}.sweet-alert .sa-icon.sa-info::after,.sweet-alert .sa-icon.sa-info::before{position:absolute;content:"";background-color:#C9DAE1}.sweet-alert .sa-icon.sa-info{border-color:#C9DAE1}.sweet-alert .sa-icon.sa-info::before{width:5px;height:29px;left:50%;bottom:17px;border-radius:2px;margin-left:-2px}.sweet-alert .sa-icon.sa-info::after{width:7px;height:7px;border-radius:50%;margin-left:-3px;top:19px}.sweet-alert .sa-icon.sa-success{border-color:#A5DC86}.sweet-alert .sa-icon.sa-success::after,.sweet-alert .sa-icon.sa-success::before{content:'';position:absolute;width:60px;height:120px;background:#fff}.sweet-alert .sa-icon.sa-success::before{-webkit-border-radius:120px 0 0 120px;border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.sweet-alert .sa-icon.sa-success::after{-webkit-border-radius:0 120px 120px 0;border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px}.sweet-alert .sa-icon.sa-success .sa-placeholder{width:80px;height:80px;border:4px solid rgba(165,220,134,.2);-webkit-border-radius:40px;border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.sweet-alert .sa-icon.sa-success .sa-fix{width:5px;height:90px;background-color:#fff;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.sweet-alert .sa-icon.sa-success .sa-line{height:5px;background-color:#A5DC86;display:block;border-radius:2px;position:absolute;z-index:2}.sweet-alert .sa-icon.sa-success .sa-line.sa-tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.sweet-alert .sa-icon.sa-success .sa-line.sa-long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.sweet-alert .sa-icon.sa-custom{background-size:contain;border-radius:0;border:none;background-position:center center;background-repeat:no-repeat}@-webkit-keyframes showSweetAlert{0%{transform:scale(.7);-webkit-transform:scale(.7)}45%{transform:scale(1.05);-webkit-transform:scale(1.05)}80%{transform:scale(.95);-webkit-transform:scale(.95)}100%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes showSweetAlert{0%{transform:scale(.7);-webkit-transform:scale(.7)}45%{transform:scale(1.05);-webkit-transform:scale(1.05)}80%{transform:scale(.95);-webkit-transform:scale(.95)}100%{transform:scale(1);-webkit-transform:scale(1)}}@-webkit-keyframes hideSweetAlert{0%{transform:scale(1);-webkit-transform:scale(1)}100%{transform:scale(.5);-webkit-transform:scale(.5)}}@keyframes hideSweetAlert{0%{transform:scale(1);-webkit-transform:scale(1)}100%{transform:scale(.5);-webkit-transform:scale(.5)}}@-webkit-keyframes slideFromTop{0%{top:0}100%{top:50%}}@keyframes slideFromTop{0%{top:0}100%{top:50%}}@-webkit-keyframes slideToTop{0%{top:50%}100%{top:0}}@keyframes slideToTop{0%{top:50%}100%{top:0}}@-webkit-keyframes slideFromBottom{0%{top:70%}100%{top:50%}}@keyframes slideFromBottom{0%{top:70%}100%{top:50%}}@-webkit-keyframes slideToBottom{0%{top:50%}100%{top:70%}}@keyframes slideToBottom{0%{top:50%}100%{top:70%}}.showSweetAlert[data-animation=pop]{-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s}.showSweetAlert[data-animation=none]{-webkit-animation:none;animation:none}.showSweetAlert[data-animation=slide-from-top]{-webkit-animation:slideFromTop .3s;animation:slideFromTop .3s}.showSweetAlert[data-animation=slide-from-bottom]{-webkit-animation:slideFromBottom .3s;animation:slideFromBottom .3s}.hideSweetAlert[data-animation=pop]{-webkit-animation:hideSweetAlert .2s;animation:hideSweetAlert .2s}.hideSweetAlert[data-animation=none]{-webkit-animation:none;animation:none}.hideSweetAlert[data-animation=slide-from-top]{-webkit-animation:slideToTop .4s;animation:slideToTop .4s}.hideSweetAlert[data-animation=slide-from-bottom]{-webkit-animation:slideToBottom .3s;animation:slideToBottom .3s}@-webkit-keyframes animateSuccessTip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@keyframes animateSuccessTip{0%,54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}}@-webkit-keyframes animateSuccessLong{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@keyframes animateSuccessLong{0%,65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}}@-webkit-keyframes rotatePlaceholder{0%,5%{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}100%,12%{transform:rotate(-405deg);-webkit-transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%,5%{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}100%,12%{transform:rotate(-405deg);-webkit-transform:rotate(-405deg)}}.animateSuccessTip{-webkit-animation:animateSuccessTip .75s;animation:animateSuccessTip .75s}.animateSuccessLong{-webkit-animation:animateSuccessLong .75s;animation:animateSuccessLong .75s}.sa-icon.sa-success.animate::after{-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}@-webkit-keyframes animateErrorIcon{0%{transform:rotateX(100deg);-webkit-transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0);-webkit-transform:rotateX(0);opacity:1}}@keyframes animateErrorIcon{0%{transform:rotateX(100deg);-webkit-transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0);-webkit-transform:rotateX(0);opacity:1}}.animateErrorIcon{-webkit-animation:animateErrorIcon .5s;animation:animateErrorIcon .5s}@-webkit-keyframes animateXMark{0%,50%{transform:scale(.4);-webkit-transform:scale(.4);margin-top:26px;opacity:0}80%{transform:scale(1.15);-webkit-transform:scale(1.15);margin-top:-6px}100%{transform:scale(1);-webkit-transform:scale(1);margin-top:0;opacity:1}}@keyframes animateXMark{0%,50%{transform:scale(.4);-webkit-transform:scale(.4);margin-top:26px;opacity:0}80%{transform:scale(1.15);-webkit-transform:scale(1.15);margin-top:-6px}100%{transform:scale(1);-webkit-transform:scale(1);margin-top:0;opacity:1}}.animateXMark{-webkit-animation:animateXMark .5s;animation:animateXMark .5s}@-webkit-keyframes pulseWarning{0%{border-color:#F8D486}100%{border-color:#F8BB86}}@keyframes pulseWarning{0%{border-color:#F8D486}100%{border-color:#F8BB86}}.pulseWarning{-webkit-animation:pulseWarning .75s infinite alternate;animation:pulseWarning .75s infinite alternate}@-webkit-keyframes pulseWarningIns{0%{background-color:#F8D486}100%{background-color:#F8BB86}}@keyframes pulseWarningIns{0%{background-color:#F8D486}100%{background-color:#F8BB86}}.pulseWarningIns{-webkit-animation:pulseWarningIns .75s infinite alternate;animation:pulseWarningIns .75s infinite alternate}@-webkit-keyframes rotate-loading{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes rotate-loading{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}.sweet-alert .sa-icon.sa-error .sa-line.sa-left{-ms-transform:rotate(45deg)\9}.sweet-alert .sa-icon.sa-error .sa-line.sa-right{-ms-transform:rotate(-45deg)\9}.sweet-alert .sa-icon.sa-success{border-color:transparent\9}.sweet-alert .sa-icon.sa-success .sa-line.sa-tip{-ms-transform:rotate(45deg)\9}.sweet-alert .sa-icon.sa-success .sa-line.sa-long{-ms-transform:rotate(-45deg)\9}/*! 2 | -------------------------------------------------------------------------------- /resources/css/toastr/toastr.css: -------------------------------------------------------------------------------- 1 | .toast-title { 2 | font-weight: bold; 3 | } 4 | .toast-message { 5 | -ms-word-wrap: break-word; 6 | word-wrap: break-word; 7 | } 8 | .toast-message a, 9 | .toast-message label { 10 | color: #ffffff; 11 | } 12 | .toast-message a:hover { 13 | color: #cccccc; 14 | text-decoration: none; 15 | } 16 | .toast-close-button { 17 | position: relative; 18 | right: -0.3em; 19 | top: -0.3em; 20 | float: right; 21 | font-size: 20px; 22 | font-weight: bold; 23 | color: #ffffff; 24 | -webkit-text-shadow: 0 1px 0 #ffffff; 25 | text-shadow: 0 1px 0 #ffffff; 26 | opacity: 0.8; 27 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 28 | filter: alpha(opacity=80); 29 | } 30 | .toast-close-button:hover, 31 | .toast-close-button:focus { 32 | color: #000000; 33 | text-decoration: none; 34 | cursor: pointer; 35 | opacity: 0.4; 36 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 37 | filter: alpha(opacity=40); 38 | } 39 | /*Additional properties for button version 40 | iOS requires the button element instead of an anchor tag. 41 | If you want the anchor version, it requires `href="#"`.*/ 42 | button.toast-close-button { 43 | padding: 0; 44 | cursor: pointer; 45 | background: transparent; 46 | border: 0; 47 | -webkit-appearance: none; 48 | } 49 | .toast-top-center { 50 | top: 0; 51 | right: 0; 52 | width: 100%; 53 | } 54 | .toast-bottom-center { 55 | bottom: 0; 56 | right: 0; 57 | width: 100%; 58 | } 59 | .toast-top-full-width { 60 | top: 0; 61 | right: 0; 62 | width: 100%; 63 | } 64 | .toast-bottom-full-width { 65 | bottom: 0; 66 | right: 0; 67 | width: 100%; 68 | } 69 | .toast-top-left { 70 | top: 12px; 71 | left: 12px; 72 | } 73 | .toast-top-right { 74 | top: 12px; 75 | right: 12px; 76 | } 77 | .toast-bottom-right { 78 | right: 12px; 79 | bottom: 12px; 80 | } 81 | .toast-bottom-left { 82 | bottom: 12px; 83 | left: 12px; 84 | } 85 | #toast-container { 86 | position: fixed; 87 | z-index: 999999; 88 | /*overrides*/ 89 | 90 | } 91 | #toast-container * { 92 | -moz-box-sizing: border-box; 93 | -webkit-box-sizing: border-box; 94 | box-sizing: border-box; 95 | } 96 | #toast-container > div { 97 | position: relative; 98 | overflow: hidden; 99 | margin: 0 0 6px; 100 | padding: 15px 15px 15px 50px; 101 | width: 300px; 102 | -moz-border-radius: 3px 3px 3px 3px; 103 | -webkit-border-radius: 3px 3px 3px 3px; 104 | border-radius: 3px 3px 3px 3px; 105 | background-position: 15px center; 106 | background-repeat: no-repeat; 107 | -moz-box-shadow: 0 0 12px #999999; 108 | -webkit-box-shadow: 0 0 12px #999999; 109 | box-shadow: 0 0 12px #999999; 110 | color: #ffffff; 111 | opacity: 0.8; 112 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 113 | filter: alpha(opacity=80); 114 | } 115 | #toast-container > :hover { 116 | -moz-box-shadow: 0 0 12px #000000; 117 | -webkit-box-shadow: 0 0 12px #000000; 118 | box-shadow: 0 0 12px #000000; 119 | opacity: 1; 120 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); 121 | filter: alpha(opacity=100); 122 | cursor: pointer; 123 | } 124 | #toast-container > .toast-info { 125 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; 126 | } 127 | #toast-container > .toast-error { 128 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; 129 | } 130 | #toast-container > .toast-success { 131 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; 132 | } 133 | #toast-container > .toast-warning { 134 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; 135 | } 136 | #toast-container.toast-top-center > div, 137 | #toast-container.toast-bottom-center > div { 138 | width: 300px; 139 | margin: auto; 140 | } 141 | #toast-container.toast-top-full-width > div, 142 | #toast-container.toast-bottom-full-width > div { 143 | width: 96%; 144 | margin: auto; 145 | } 146 | .toast { 147 | background-color: #030303; 148 | } 149 | .toast-success { 150 | background-color: #51a351; 151 | } 152 | .toast-error { 153 | background-color: #bd362f; 154 | } 155 | .toast-info { 156 | background-color: #2f96b4; 157 | } 158 | .toast-warning { 159 | background-color: #f89406; 160 | } 161 | .toast-progress { 162 | position: absolute; 163 | left: 0; 164 | bottom: 0; 165 | height: 4px; 166 | background-color: #000000; 167 | opacity: 0.4; 168 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 169 | filter: alpha(opacity=40); 170 | } 171 | /*Responsive Design*/ 172 | @media all and (max-width: 240px) { 173 | #toast-container > div { 174 | padding: 8px 8px 8px 50px; 175 | width: 11em; 176 | } 177 | #toast-container .toast-close-button { 178 | right: -0.2em; 179 | top: -0.2em; 180 | } 181 | } 182 | @media all and (min-width: 241px) and (max-width: 480px) { 183 | #toast-container > div { 184 | padding: 8px 8px 8px 50px; 185 | width: 18em; 186 | } 187 | #toast-container .toast-close-button { 188 | right: -0.2em; 189 | top: -0.2em; 190 | } 191 | } 192 | @media all and (min-width: 481px) and (max-width: 768px) { 193 | #toast-container > div { 194 | padding: 15px 15px 15px 50px; 195 | width: 25em; 196 | } 197 | } -------------------------------------------------------------------------------- /resources/css/toastr/toastr.min.css: -------------------------------------------------------------------------------- 1 | .toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#fff}.toast-message a:hover{color:#ccc;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#fff;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:alpha(Opacity=80);filter:alpha(opacity=80)}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:alpha(Opacity=40);filter:alpha(opacity=40)}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#fff;opacity:.8;-ms-filter:alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin:auto}.toast{background-color:#030303}.toast-success{background-color:#51a351}.toast-error{background-color:#bd362f}.toast-info{background-color:#2f96b4}.toast-warning{background-color:#f89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container .toast-close-button{right:-.2em;top:-.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}} -------------------------------------------------------------------------------- /resources/js/bootbox/bootbox.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootbox.js [v4.4.0] 3 | * 4 | * http://bootboxjs.com/license.txt 5 | */ 6 | 7 | // @see https://github.com/makeusabrew/bootbox/issues/180 8 | // @see https://github.com/makeusabrew/bootbox/issues/186 9 | (function (root, factory) { 10 | 11 | "use strict"; 12 | if (typeof define === "function" && define.amd) { 13 | // AMD. Register as an anonymous module. 14 | define(["jquery"], factory); 15 | } else if (typeof exports === "object") { 16 | // Node. Does not work with strict CommonJS, but 17 | // only CommonJS-like environments that support module.exports, 18 | // like Node. 19 | module.exports = factory(require("jquery")); 20 | } else { 21 | // Browser globals (root is window) 22 | root.bootbox = factory(root.jQuery); 23 | } 24 | 25 | }(this, function init($, undefined) { 26 | 27 | "use strict"; 28 | 29 | // the base DOM structure needed to create a modal 30 | var templates = { 31 | dialog: 32 | "", 39 | header: 40 | "", 43 | footer: 44 | "", 45 | closeButton: 46 | "", 47 | form: 48 | "
", 49 | inputs: { 50 | text: 51 | "", 52 | textarea: 53 | "", 54 | email: 55 | "", 56 | select: 57 | "", 58 | checkbox: 59 | "
", 60 | date: 61 | "", 62 | time: 63 | "", 64 | number: 65 | "", 66 | password: 67 | "" 68 | } 69 | }; 70 | 71 | var defaults = { 72 | // default language 73 | locale: "en", 74 | // show backdrop or not. Default to static so user has to interact with dialog 75 | backdrop: "static", 76 | // animate the modal in/out 77 | animate: true, 78 | // additional class string applied to the top level dialog 79 | className: null, 80 | // whether or not to include a close button 81 | closeButton: true, 82 | // show the dialog immediately by default 83 | show: true, 84 | // dialog container 85 | container: "body" 86 | }; 87 | 88 | // our public object; augmented after our private API 89 | var exports = {}; 90 | 91 | /** 92 | * @private 93 | */ 94 | function _t(key) { 95 | var locale = locales[defaults.locale]; 96 | return locale ? locale[key] : locales.en[key]; 97 | } 98 | 99 | function processCallback(e, dialog, callback) { 100 | e.stopPropagation(); 101 | e.preventDefault(); 102 | 103 | // by default we assume a callback will get rid of the dialog, 104 | // although it is given the opportunity to override this 105 | 106 | // so, if the callback can be invoked and it *explicitly returns false* 107 | // then we'll set a flag to keep the dialog active... 108 | var preserveDialog = $.isFunction(callback) && callback.call(dialog, e) === false; 109 | 110 | // ... otherwise we'll bin it 111 | if (!preserveDialog) { 112 | dialog.modal("hide"); 113 | } 114 | } 115 | 116 | function getKeyLength(obj) { 117 | // @TODO defer to Object.keys(x).length if available? 118 | var k, t = 0; 119 | for (k in obj) { 120 | t ++; 121 | } 122 | return t; 123 | } 124 | 125 | function each(collection, iterator) { 126 | var index = 0; 127 | $.each(collection, function(key, value) { 128 | iterator(key, value, index++); 129 | }); 130 | } 131 | 132 | function sanitize(options) { 133 | var buttons; 134 | var total; 135 | 136 | if (typeof options !== "object") { 137 | throw new Error("Please supply an object of options"); 138 | } 139 | 140 | if (!options.message) { 141 | throw new Error("Please specify a message"); 142 | } 143 | 144 | // make sure any supplied options take precedence over defaults 145 | options = $.extend({}, defaults, options); 146 | 147 | if (!options.buttons) { 148 | options.buttons = {}; 149 | } 150 | 151 | buttons = options.buttons; 152 | 153 | total = getKeyLength(buttons); 154 | 155 | each(buttons, function(key, button, index) { 156 | 157 | if ($.isFunction(button)) { 158 | // short form, assume value is our callback. Since button 159 | // isn't an object it isn't a reference either so re-assign it 160 | button = buttons[key] = { 161 | callback: button 162 | }; 163 | } 164 | 165 | // before any further checks make sure by now button is the correct type 166 | if ($.type(button) !== "object") { 167 | throw new Error("button with key " + key + " must be an object"); 168 | } 169 | 170 | if (!button.label) { 171 | // the lack of an explicit label means we'll assume the key is good enough 172 | button.label = key; 173 | } 174 | 175 | if (!button.className) { 176 | if (total <= 2 && index === total-1) { 177 | // always add a primary to the main option in a two-button dialog 178 | button.className = "btn-primary"; 179 | } else { 180 | button.className = "btn-default"; 181 | } 182 | } 183 | }); 184 | 185 | return options; 186 | } 187 | 188 | /** 189 | * map a flexible set of arguments into a single returned object 190 | * if args.length is already one just return it, otherwise 191 | * use the properties argument to map the unnamed args to 192 | * object properties 193 | * so in the latter case: 194 | * mapArguments(["foo", $.noop], ["message", "callback"]) 195 | * -> { message: "foo", callback: $.noop } 196 | */ 197 | function mapArguments(args, properties) { 198 | var argn = args.length; 199 | var options = {}; 200 | 201 | if (argn < 1 || argn > 2) { 202 | throw new Error("Invalid argument length"); 203 | } 204 | 205 | if (argn === 2 || typeof args[0] === "string") { 206 | options[properties[0]] = args[0]; 207 | options[properties[1]] = args[1]; 208 | } else { 209 | options = args[0]; 210 | } 211 | 212 | return options; 213 | } 214 | 215 | /** 216 | * merge a set of default dialog options with user supplied arguments 217 | */ 218 | function mergeArguments(defaults, args, properties) { 219 | return $.extend( 220 | // deep merge 221 | true, 222 | // ensure the target is an empty, unreferenced object 223 | {}, 224 | // the base options object for this type of dialog (often just buttons) 225 | defaults, 226 | // args could be an object or array; if it's an array properties will 227 | // map it to a proper options object 228 | mapArguments( 229 | args, 230 | properties 231 | ) 232 | ); 233 | } 234 | 235 | /** 236 | * this entry-level method makes heavy use of composition to take a simple 237 | * range of inputs and return valid options suitable for passing to bootbox.dialog 238 | */ 239 | function mergeDialogOptions(className, labels, properties, args) { 240 | // build up a base set of dialog properties 241 | var baseOptions = { 242 | className: "bootbox-" + className, 243 | buttons: createLabels.apply(null, labels) 244 | }; 245 | 246 | // ensure the buttons properties generated, *after* merging 247 | // with user args are still valid against the supplied labels 248 | return validateButtons( 249 | // merge the generated base properties with user supplied arguments 250 | mergeArguments( 251 | baseOptions, 252 | args, 253 | // if args.length > 1, properties specify how each arg maps to an object key 254 | properties 255 | ), 256 | labels 257 | ); 258 | } 259 | 260 | /** 261 | * from a given list of arguments return a suitable object of button labels 262 | * all this does is normalise the given labels and translate them where possible 263 | * e.g. "ok", "confirm" -> { ok: "OK, cancel: "Annuleren" } 264 | */ 265 | function createLabels() { 266 | var buttons = {}; 267 | 268 | for (var i = 0, j = arguments.length; i < j; i++) { 269 | var argument = arguments[i]; 270 | var key = argument.toLowerCase(); 271 | var value = argument.toUpperCase(); 272 | 273 | buttons[key] = { 274 | label: _t(value) 275 | }; 276 | } 277 | 278 | return buttons; 279 | } 280 | 281 | function validateButtons(options, buttons) { 282 | var allowedButtons = {}; 283 | each(buttons, function(key, value) { 284 | allowedButtons[value] = true; 285 | }); 286 | 287 | each(options.buttons, function(key) { 288 | if (allowedButtons[key] === undefined) { 289 | throw new Error("button key " + key + " is not allowed (options are " + buttons.join("\n") + ")"); 290 | } 291 | }); 292 | 293 | return options; 294 | } 295 | 296 | exports.alert = function() { 297 | var options; 298 | 299 | options = mergeDialogOptions("alert", ["ok"], ["message", "callback"], arguments); 300 | 301 | if (options.callback && !$.isFunction(options.callback)) { 302 | throw new Error("alert requires callback property to be a function when provided"); 303 | } 304 | 305 | /** 306 | * overrides 307 | */ 308 | options.buttons.ok.callback = options.onEscape = function() { 309 | if ($.isFunction(options.callback)) { 310 | return options.callback.call(this); 311 | } 312 | return true; 313 | }; 314 | 315 | return exports.dialog(options); 316 | }; 317 | 318 | exports.confirm = function() { 319 | var options; 320 | 321 | options = mergeDialogOptions("confirm", ["cancel", "confirm"], ["message", "callback"], arguments); 322 | 323 | /** 324 | * overrides; undo anything the user tried to set they shouldn't have 325 | */ 326 | options.buttons.cancel.callback = options.onEscape = function() { 327 | return options.callback.call(this, false); 328 | }; 329 | 330 | options.buttons.confirm.callback = function() { 331 | return options.callback.call(this, true); 332 | }; 333 | 334 | // confirm specific validation 335 | if (!$.isFunction(options.callback)) { 336 | throw new Error("confirm requires a callback"); 337 | } 338 | 339 | return exports.dialog(options); 340 | }; 341 | 342 | exports.prompt = function() { 343 | var options; 344 | var defaults; 345 | var dialog; 346 | var form; 347 | var input; 348 | var shouldShow; 349 | var inputOptions; 350 | 351 | // we have to create our form first otherwise 352 | // its value is undefined when gearing up our options 353 | // @TODO this could be solved by allowing message to 354 | // be a function instead... 355 | form = $(templates.form); 356 | 357 | // prompt defaults are more complex than others in that 358 | // users can override more defaults 359 | // @TODO I don't like that prompt has to do a lot of heavy 360 | // lifting which mergeDialogOptions can *almost* support already 361 | // just because of 'value' and 'inputType' - can we refactor? 362 | defaults = { 363 | className: "bootbox-prompt", 364 | buttons: createLabels("cancel", "confirm"), 365 | value: "", 366 | inputType: "text" 367 | }; 368 | 369 | options = validateButtons( 370 | mergeArguments(defaults, arguments, ["title", "callback"]), 371 | ["cancel", "confirm"] 372 | ); 373 | 374 | // capture the user's show value; we always set this to false before 375 | // spawning the dialog to give us a chance to attach some handlers to 376 | // it, but we need to make sure we respect a preference not to show it 377 | shouldShow = (options.show === undefined) ? true : options.show; 378 | 379 | /** 380 | * overrides; undo anything the user tried to set they shouldn't have 381 | */ 382 | options.message = form; 383 | 384 | options.buttons.cancel.callback = options.onEscape = function() { 385 | return options.callback.call(this, null); 386 | }; 387 | 388 | options.buttons.confirm.callback = function() { 389 | var value; 390 | 391 | switch (options.inputType) { 392 | case "text": 393 | case "textarea": 394 | case "email": 395 | case "select": 396 | case "date": 397 | case "time": 398 | case "number": 399 | case "password": 400 | value = input.val(); 401 | break; 402 | 403 | case "checkbox": 404 | var checkedItems = input.find("input:checked"); 405 | 406 | // we assume that checkboxes are always multiple, 407 | // hence we default to an empty array 408 | value = []; 409 | 410 | each(checkedItems, function(_, item) { 411 | value.push($(item).val()); 412 | }); 413 | break; 414 | } 415 | 416 | return options.callback.call(this, value); 417 | }; 418 | 419 | options.show = false; 420 | 421 | // prompt specific validation 422 | if (!options.title) { 423 | throw new Error("prompt requires a title"); 424 | } 425 | 426 | if (!$.isFunction(options.callback)) { 427 | throw new Error("prompt requires a callback"); 428 | } 429 | 430 | if (!templates.inputs[options.inputType]) { 431 | throw new Error("invalid prompt type"); 432 | } 433 | 434 | // create the input based on the supplied type 435 | input = $(templates.inputs[options.inputType]); 436 | 437 | switch (options.inputType) { 438 | case "text": 439 | case "textarea": 440 | case "email": 441 | case "date": 442 | case "time": 443 | case "number": 444 | case "password": 445 | input.val(options.value); 446 | break; 447 | 448 | case "select": 449 | var groups = {}; 450 | inputOptions = options.inputOptions || []; 451 | 452 | if (!$.isArray(inputOptions)) { 453 | throw new Error("Please pass an array of input options"); 454 | } 455 | 456 | if (!inputOptions.length) { 457 | throw new Error("prompt with select requires options"); 458 | } 459 | 460 | each(inputOptions, function(_, option) { 461 | 462 | // assume the element to attach to is the input... 463 | var elem = input; 464 | 465 | if (option.value === undefined || option.text === undefined) { 466 | throw new Error("given options in wrong format"); 467 | } 468 | 469 | // ... but override that element if this option sits in a group 470 | 471 | if (option.group) { 472 | // initialise group if necessary 473 | if (!groups[option.group]) { 474 | groups[option.group] = $("").attr("label", option.group); 475 | } 476 | 477 | elem = groups[option.group]; 478 | } 479 | 480 | elem.append(""); 481 | }); 482 | 483 | each(groups, function(_, group) { 484 | input.append(group); 485 | }); 486 | 487 | // safe to set a select's value as per a normal input 488 | input.val(options.value); 489 | break; 490 | 491 | case "checkbox": 492 | var values = $.isArray(options.value) ? options.value : [options.value]; 493 | inputOptions = options.inputOptions || []; 494 | 495 | if (!inputOptions.length) { 496 | throw new Error("prompt with checkbox requires options"); 497 | } 498 | 499 | if (!inputOptions[0].value || !inputOptions[0].text) { 500 | throw new Error("given options in wrong format"); 501 | } 502 | 503 | // checkboxes have to nest within a containing element, so 504 | // they break the rules a bit and we end up re-assigning 505 | // our 'input' element to this container instead 506 | input = $("
"); 507 | 508 | each(inputOptions, function(_, option) { 509 | var checkbox = $(templates.inputs[options.inputType]); 510 | 511 | checkbox.find("input").attr("value", option.value); 512 | checkbox.find("label").append(option.text); 513 | 514 | // we've ensured values is an array so we can always iterate over it 515 | each(values, function(_, value) { 516 | if (value === option.value) { 517 | checkbox.find("input").prop("checked", true); 518 | } 519 | }); 520 | 521 | input.append(checkbox); 522 | }); 523 | break; 524 | } 525 | 526 | // @TODO provide an attributes option instead 527 | // and simply map that as keys: vals 528 | if (options.placeholder) { 529 | input.attr("placeholder", options.placeholder); 530 | } 531 | 532 | if (options.pattern) { 533 | input.attr("pattern", options.pattern); 534 | } 535 | 536 | if (options.maxlength) { 537 | input.attr("maxlength", options.maxlength); 538 | } 539 | 540 | // now place it in our form 541 | form.append(input); 542 | 543 | form.on("submit", function(e) { 544 | e.preventDefault(); 545 | // Fix for SammyJS (or similar JS routing library) hijacking the form post. 546 | e.stopPropagation(); 547 | // @TODO can we actually click *the* button object instead? 548 | // e.g. buttons.confirm.click() or similar 549 | dialog.find(".btn-primary").click(); 550 | }); 551 | 552 | dialog = exports.dialog(options); 553 | 554 | // clear the existing handler focusing the submit button... 555 | dialog.off("shown.bs.modal"); 556 | 557 | // ...and replace it with one focusing our input, if possible 558 | dialog.on("shown.bs.modal", function() { 559 | // need the closure here since input isn't 560 | // an object otherwise 561 | input.focus(); 562 | }); 563 | 564 | if (shouldShow === true) { 565 | dialog.modal("show"); 566 | } 567 | 568 | return dialog; 569 | }; 570 | 571 | exports.dialog = function(options) { 572 | options = sanitize(options); 573 | 574 | var dialog = $(templates.dialog); 575 | var innerDialog = dialog.find(".modal-dialog"); 576 | var body = dialog.find(".modal-body"); 577 | var buttons = options.buttons; 578 | var buttonStr = ""; 579 | var callbacks = { 580 | onEscape: options.onEscape 581 | }; 582 | 583 | if ($.fn.modal === undefined) { 584 | throw new Error( 585 | "$.fn.modal is not defined; please double check you have included " + 586 | "the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ " + 587 | "for more details." 588 | ); 589 | } 590 | 591 | each(buttons, function(key, button) { 592 | 593 | // @TODO I don't like this string appending to itself; bit dirty. Needs reworking 594 | // can we just build up button elements instead? slower but neater. Then button 595 | // can just become a template too 596 | buttonStr += ""; 597 | callbacks[key] = button.callback; 598 | }); 599 | 600 | body.find(".bootbox-body").html(options.message); 601 | 602 | if (options.animate === true) { 603 | dialog.addClass("fade"); 604 | } 605 | 606 | if (options.className) { 607 | dialog.addClass(options.className); 608 | } 609 | 610 | if (options.size === "large") { 611 | innerDialog.addClass("modal-lg"); 612 | } else if (options.size === "small") { 613 | innerDialog.addClass("modal-sm"); 614 | } 615 | 616 | if (options.title) { 617 | body.before(templates.header); 618 | } 619 | 620 | if (options.closeButton) { 621 | var closeButton = $(templates.closeButton); 622 | 623 | if (options.title) { 624 | dialog.find(".modal-header").prepend(closeButton); 625 | } else { 626 | closeButton.css("margin-top", "-10px").prependTo(body); 627 | } 628 | } 629 | 630 | if (options.title) { 631 | dialog.find(".modal-title").html(options.title); 632 | } 633 | 634 | if (buttonStr.length) { 635 | body.after(templates.footer); 636 | dialog.find(".modal-footer").html(buttonStr); 637 | } 638 | 639 | 640 | /** 641 | * Bootstrap event listeners; used handle extra 642 | * setup & teardown required after the underlying 643 | * modal has performed certain actions 644 | */ 645 | 646 | dialog.on("hidden.bs.modal", function(e) { 647 | // ensure we don't accidentally intercept hidden events triggered 648 | // by children of the current dialog. We shouldn't anymore now BS 649 | // namespaces its events; but still worth doing 650 | if (e.target === this) { 651 | dialog.remove(); 652 | } 653 | }); 654 | 655 | /* 656 | dialog.on("show.bs.modal", function() { 657 | // sadly this doesn't work; show is called *just* before 658 | // the backdrop is added so we'd need a setTimeout hack or 659 | // otherwise... leaving in as would be nice 660 | if (options.backdrop) { 661 | dialog.next(".modal-backdrop").addClass("bootbox-backdrop"); 662 | } 663 | }); 664 | */ 665 | 666 | dialog.on("shown.bs.modal", function() { 667 | dialog.find(".btn-primary:first").focus(); 668 | }); 669 | 670 | /** 671 | * Bootbox event listeners; experimental and may not last 672 | * just an attempt to decouple some behaviours from their 673 | * respective triggers 674 | */ 675 | 676 | if (options.backdrop !== "static") { 677 | // A boolean true/false according to the Bootstrap docs 678 | // should show a dialog the user can dismiss by clicking on 679 | // the background. 680 | // We always only ever pass static/false to the actual 681 | // $.modal function because with `true` we can't trap 682 | // this event (the .modal-backdrop swallows it) 683 | // However, we still want to sort of respect true 684 | // and invoke the escape mechanism instead 685 | dialog.on("click.dismiss.bs.modal", function(e) { 686 | // @NOTE: the target varies in >= 3.3.x releases since the modal backdrop 687 | // moved *inside* the outer dialog rather than *alongside* it 688 | if (dialog.children(".modal-backdrop").length) { 689 | e.currentTarget = dialog.children(".modal-backdrop").get(0); 690 | } 691 | 692 | if (e.target !== e.currentTarget) { 693 | return; 694 | } 695 | 696 | dialog.trigger("escape.close.bb"); 697 | }); 698 | } 699 | 700 | dialog.on("escape.close.bb", function(e) { 701 | if (callbacks.onEscape) { 702 | processCallback(e, dialog, callbacks.onEscape); 703 | } 704 | }); 705 | 706 | /** 707 | * Standard jQuery event listeners; used to handle user 708 | * interaction with our dialog 709 | */ 710 | 711 | dialog.on("click", ".modal-footer button", function(e) { 712 | var callbackKey = $(this).data("bb-handler"); 713 | 714 | processCallback(e, dialog, callbacks[callbackKey]); 715 | }); 716 | 717 | dialog.on("click", ".bootbox-close-button", function(e) { 718 | // onEscape might be falsy but that's fine; the fact is 719 | // if the user has managed to click the close button we 720 | // have to close the dialog, callback or not 721 | processCallback(e, dialog, callbacks.onEscape); 722 | }); 723 | 724 | dialog.on("keyup", function(e) { 725 | if (e.which === 27) { 726 | dialog.trigger("escape.close.bb"); 727 | } 728 | }); 729 | 730 | // the remainder of this method simply deals with adding our 731 | // dialogent to the DOM, augmenting it with Bootstrap's modal 732 | // functionality and then giving the resulting object back 733 | // to our caller 734 | 735 | $(options.container).append(dialog); 736 | 737 | dialog.modal({ 738 | backdrop: options.backdrop ? "static": false, 739 | keyboard: false, 740 | show: false 741 | }); 742 | 743 | if (options.show) { 744 | dialog.modal("show"); 745 | } 746 | 747 | // @TODO should we return the raw element here or should 748 | // we wrap it in an object on which we can expose some neater 749 | // methods, e.g. var d = bootbox.alert(); d.hide(); instead 750 | // of d.modal("hide"); 751 | 752 | /* 753 | function BBDialog(elem) { 754 | this.elem = elem; 755 | } 756 | 757 | BBDialog.prototype = { 758 | hide: function() { 759 | return this.elem.modal("hide"); 760 | }, 761 | show: function() { 762 | return this.elem.modal("show"); 763 | } 764 | }; 765 | */ 766 | 767 | return dialog; 768 | 769 | }; 770 | 771 | exports.setDefaults = function() { 772 | var values = {}; 773 | 774 | if (arguments.length === 2) { 775 | // allow passing of single key/value... 776 | values[arguments[0]] = arguments[1]; 777 | } else { 778 | // ... and as an object too 779 | values = arguments[0]; 780 | } 781 | 782 | $.extend(defaults, values); 783 | }; 784 | 785 | exports.hideAll = function() { 786 | $(".bootbox").modal("hide"); 787 | 788 | return exports; 789 | }; 790 | 791 | 792 | /** 793 | * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are 794 | * unlikely to be required. If this gets too large it can be split out into separate JS files. 795 | */ 796 | var locales = { 797 | bg_BG : { 798 | OK : "Ок", 799 | CANCEL : "Отказ", 800 | CONFIRM : "Потвърждавам" 801 | }, 802 | br : { 803 | OK : "OK", 804 | CANCEL : "Cancelar", 805 | CONFIRM : "Sim" 806 | }, 807 | cs : { 808 | OK : "OK", 809 | CANCEL : "Zrušit", 810 | CONFIRM : "Potvrdit" 811 | }, 812 | da : { 813 | OK : "OK", 814 | CANCEL : "Annuller", 815 | CONFIRM : "Accepter" 816 | }, 817 | de : { 818 | OK : "OK", 819 | CANCEL : "Abbrechen", 820 | CONFIRM : "Akzeptieren" 821 | }, 822 | el : { 823 | OK : "Εντάξει", 824 | CANCEL : "Ακύρωση", 825 | CONFIRM : "Επιβεβαίωση" 826 | }, 827 | en : { 828 | OK : "OK", 829 | CANCEL : "Cancel", 830 | CONFIRM : "OK" 831 | }, 832 | es : { 833 | OK : "OK", 834 | CANCEL : "Cancelar", 835 | CONFIRM : "Aceptar" 836 | }, 837 | et : { 838 | OK : "OK", 839 | CANCEL : "Katkesta", 840 | CONFIRM : "OK" 841 | }, 842 | fa : { 843 | OK : "قبول", 844 | CANCEL : "لغو", 845 | CONFIRM : "تایید" 846 | }, 847 | fi : { 848 | OK : "OK", 849 | CANCEL : "Peruuta", 850 | CONFIRM : "OK" 851 | }, 852 | fr : { 853 | OK : "OK", 854 | CANCEL : "Annuler", 855 | CONFIRM : "D'accord" 856 | }, 857 | he : { 858 | OK : "אישור", 859 | CANCEL : "ביטול", 860 | CONFIRM : "אישור" 861 | }, 862 | hu : { 863 | OK : "OK", 864 | CANCEL : "Mégsem", 865 | CONFIRM : "Megerősít" 866 | }, 867 | hr : { 868 | OK : "OK", 869 | CANCEL : "Odustani", 870 | CONFIRM : "Potvrdi" 871 | }, 872 | id : { 873 | OK : "OK", 874 | CANCEL : "Batal", 875 | CONFIRM : "OK" 876 | }, 877 | it : { 878 | OK : "OK", 879 | CANCEL : "Annulla", 880 | CONFIRM : "Conferma" 881 | }, 882 | ja : { 883 | OK : "OK", 884 | CANCEL : "キャンセル", 885 | CONFIRM : "確認" 886 | }, 887 | lt : { 888 | OK : "Gerai", 889 | CANCEL : "Atšaukti", 890 | CONFIRM : "Patvirtinti" 891 | }, 892 | lv : { 893 | OK : "Labi", 894 | CANCEL : "Atcelt", 895 | CONFIRM : "Apstiprināt" 896 | }, 897 | nl : { 898 | OK : "OK", 899 | CANCEL : "Annuleren", 900 | CONFIRM : "Accepteren" 901 | }, 902 | no : { 903 | OK : "OK", 904 | CANCEL : "Avbryt", 905 | CONFIRM : "OK" 906 | }, 907 | pl : { 908 | OK : "OK", 909 | CANCEL : "Anuluj", 910 | CONFIRM : "Potwierdź" 911 | }, 912 | pt : { 913 | OK : "OK", 914 | CANCEL : "Cancelar", 915 | CONFIRM : "Confirmar" 916 | }, 917 | ru : { 918 | OK : "OK", 919 | CANCEL : "Отмена", 920 | CONFIRM : "Применить" 921 | }, 922 | sq : { 923 | OK : "OK", 924 | CANCEL : "Anulo", 925 | CONFIRM : "Prano" 926 | }, 927 | sv : { 928 | OK : "OK", 929 | CANCEL : "Avbryt", 930 | CONFIRM : "OK" 931 | }, 932 | th : { 933 | OK : "ตกลง", 934 | CANCEL : "ยกเลิก", 935 | CONFIRM : "ยืนยัน" 936 | }, 937 | tr : { 938 | OK : "Tamam", 939 | CANCEL : "İptal", 940 | CONFIRM : "Onayla" 941 | }, 942 | zh_CN : { 943 | OK : "OK", 944 | CANCEL : "取消", 945 | CONFIRM : "确认" 946 | }, 947 | zh_TW : { 948 | OK : "OK", 949 | CANCEL : "取消", 950 | CONFIRM : "確認" 951 | } 952 | }; 953 | 954 | exports.addLocale = function(name, values) { 955 | $.each(["OK", "CANCEL", "CONFIRM"], function(_, v) { 956 | if (!values[v]) { 957 | throw new Error("Please supply a translation for '" + v + "'"); 958 | } 959 | }); 960 | 961 | locales[name] = { 962 | OK: values.OK, 963 | CANCEL: values.CANCEL, 964 | CONFIRM: values.CONFIRM 965 | }; 966 | 967 | return exports; 968 | }; 969 | 970 | exports.removeLocale = function(name) { 971 | delete locales[name]; 972 | 973 | return exports; 974 | }; 975 | 976 | exports.setLocale = function(name) { 977 | return exports.setDefaults("locale", name); 978 | }; 979 | 980 | exports.init = function(_$) { 981 | return init(_$ || $); 982 | }; 983 | 984 | return exports; 985 | })); 986 | -------------------------------------------------------------------------------- /resources/js/bootbox/bootbox.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootbox.js v4.4.0 3 | * 4 | * http://bootboxjs.com/license.txt 5 | */ 6 | !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p}); -------------------------------------------------------------------------------- /resources/js/sweetalert/sweetalert.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t,n){"use strict";!function o(e,t,n){function a(s,l){if(!t[s]){if(!e[s]){var i="function"==typeof require&&require;if(!l&&i)return i(s,!0);if(r)return r(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var c=t[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return a(n?n:t)},c,c.exports,o,e,t,n)}return t[s].exports}for(var r="function"==typeof require&&require,s=0;s=0;)n=n.replace(" "+t+" "," ");e.className=n.replace(/^\s+|\s+$/g,"")}},i=function(e){var n=t.createElement("div");return n.appendChild(t.createTextNode(e)),n.innerHTML},u=function(e){e.style.opacity="",e.style.display="block"},c=function(e){if(e&&!e.length)return u(e);for(var t=0;t0?setTimeout(o,t):e.style.display="none"});o()},h=function(n){if("function"==typeof MouseEvent){var o=new MouseEvent("click",{view:e,bubbles:!1,cancelable:!0});n.dispatchEvent(o)}else if(t.createEvent){var a=t.createEvent("MouseEvents");a.initEvent("click",!1,!1),n.dispatchEvent(a)}else t.createEventObject?n.fireEvent("onclick"):"function"==typeof n.onclick&&n.onclick()},g=function(t){"function"==typeof t.stopPropagation?(t.stopPropagation(),t.preventDefault()):e.event&&e.event.hasOwnProperty("cancelBubble")&&(e.event.cancelBubble=!0)};a.hasClass=r,a.addClass=s,a.removeClass=l,a.escapeHtml=i,a._show=u,a.show=c,a._hide=d,a.hide=f,a.isDescendant=p,a.getTopMargin=m,a.fadeIn=v,a.fadeOut=y,a.fireClick=h,a.stopEventPropagation=g},{}],5:[function(t,o,a){Object.defineProperty(a,"__esModule",{value:!0});var r=t("./handle-dom"),s=t("./handle-swal-dom"),l=function(t,o,a){var l=t||e.event,i=l.keyCode||l.which,u=a.querySelector("button.confirm"),c=a.querySelector("button.cancel"),d=a.querySelectorAll("button[tabindex]");if(-1!==[9,13,32,27].indexOf(i)){for(var f=l.target||l.srcElement,p=-1,m=0;m"),i.innerHTML=e.html?e.text:s.escapeHtml(e.text||"").split("\n").join("
"),e.text&&s.show(i),e.customClass)s.addClass(t,e.customClass),t.setAttribute("data-custom-class",e.customClass);else{var d=t.getAttribute("data-custom-class");s.removeClass(t,d),t.setAttribute("data-custom-class","")}if(s.hide(t.querySelectorAll(".sa-icon")),e.type&&!a.isIE8()){var f=function(){for(var o=!1,a=0;ao;o++)n=parseInt(e.substr(2*o,2),16),n=Math.round(Math.min(Math.max(0,n+n*t),255)).toString(16),a+=("00"+n).substr(n.length);return a};o.extend=a,o.hexToRgb=r,o.isIE8=s,o.logStr=l,o.colorLuminance=i},{}]},{},[1]),"function"==typeof define&&define.amd?define(function(){return sweetAlert}):"undefined"!=typeof module&&module.exports&&(module.exports=sweetAlert)}(window,document); -------------------------------------------------------------------------------- /resources/js/toastr/toastr.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Toastr 3 | * Copyright 2012-2015 4 | * Authors: John Papa, Hans Fjällemark, and Tim Ferrell. 5 | * All Rights Reserved. 6 | * Use, reproduction, distribution, and modification of this code is subject to the terms and 7 | * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php 8 | * 9 | * ARIA Support: Greta Krafsig 10 | * 11 | * Project: https://github.com/CodeSeven/toastr 12 | */ 13 | /* global define */ 14 | ; (function (define) { 15 | define(['jquery'], function ($) { 16 | return (function () { 17 | var $container; 18 | var listener; 19 | var toastId = 0; 20 | var toastType = { 21 | error: 'error', 22 | info: 'info', 23 | success: 'success', 24 | warning: 'warning' 25 | }; 26 | 27 | var toastr = { 28 | clear: clear, 29 | remove: remove, 30 | error: error, 31 | getContainer: getContainer, 32 | info: info, 33 | options: {}, 34 | subscribe: subscribe, 35 | success: success, 36 | version: '2.1.1', 37 | warning: warning 38 | }; 39 | 40 | var previousToast; 41 | 42 | return toastr; 43 | 44 | //////////////// 45 | 46 | function error(message, title, optionsOverride) { 47 | return notify({ 48 | type: toastType.error, 49 | iconClass: getOptions().iconClasses.error, 50 | message: message, 51 | optionsOverride: optionsOverride, 52 | title: title 53 | }); 54 | } 55 | 56 | function getContainer(options, create) { 57 | if (!options) { options = getOptions(); } 58 | $container = $('#' + options.containerId); 59 | if ($container.length) { 60 | return $container; 61 | } 62 | if (create) { 63 | $container = createContainer(options); 64 | } 65 | return $container; 66 | } 67 | 68 | function info(message, title, optionsOverride) { 69 | return notify({ 70 | type: toastType.info, 71 | iconClass: getOptions().iconClasses.info, 72 | message: message, 73 | optionsOverride: optionsOverride, 74 | title: title 75 | }); 76 | } 77 | 78 | function subscribe(callback) { 79 | listener = callback; 80 | } 81 | 82 | function success(message, title, optionsOverride) { 83 | return notify({ 84 | type: toastType.success, 85 | iconClass: getOptions().iconClasses.success, 86 | message: message, 87 | optionsOverride: optionsOverride, 88 | title: title 89 | }); 90 | } 91 | 92 | function warning(message, title, optionsOverride) { 93 | return notify({ 94 | type: toastType.warning, 95 | iconClass: getOptions().iconClasses.warning, 96 | message: message, 97 | optionsOverride: optionsOverride, 98 | title: title 99 | }); 100 | } 101 | 102 | function clear($toastElement, clearOptions) { 103 | var options = getOptions(); 104 | if (!$container) { getContainer(options); } 105 | if (!clearToast($toastElement, options, clearOptions)) { 106 | clearContainer(options); 107 | } 108 | } 109 | 110 | function remove($toastElement) { 111 | var options = getOptions(); 112 | if (!$container) { getContainer(options); } 113 | if ($toastElement && $(':focus', $toastElement).length === 0) { 114 | removeToast($toastElement); 115 | return; 116 | } 117 | if ($container.children().length) { 118 | $container.remove(); 119 | } 120 | } 121 | 122 | // internal functions 123 | 124 | function clearContainer (options) { 125 | var toastsToClear = $container.children(); 126 | for (var i = toastsToClear.length - 1; i >= 0; i--) { 127 | clearToast($(toastsToClear[i]), options); 128 | } 129 | } 130 | 131 | function clearToast ($toastElement, options, clearOptions) { 132 | var force = clearOptions && clearOptions.force ? clearOptions.force : false; 133 | if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { 134 | $toastElement[options.hideMethod]({ 135 | duration: options.hideDuration, 136 | easing: options.hideEasing, 137 | complete: function () { removeToast($toastElement); } 138 | }); 139 | return true; 140 | } 141 | return false; 142 | } 143 | 144 | function createContainer(options) { 145 | $container = $('
') 146 | .attr('id', options.containerId) 147 | .addClass(options.positionClass) 148 | .attr('aria-live', 'polite') 149 | .attr('role', 'alert'); 150 | 151 | $container.appendTo($(options.target)); 152 | return $container; 153 | } 154 | 155 | function getDefaults() { 156 | return { 157 | tapToDismiss: true, 158 | toastClass: 'toast', 159 | containerId: 'toast-container', 160 | debug: false, 161 | 162 | showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery 163 | showDuration: 300, 164 | showEasing: 'swing', //swing and linear are built into jQuery 165 | onShown: undefined, 166 | hideMethod: 'fadeOut', 167 | hideDuration: 1000, 168 | hideEasing: 'swing', 169 | onHidden: undefined, 170 | 171 | extendedTimeOut: 1000, 172 | iconClasses: { 173 | error: 'toast-error', 174 | info: 'toast-info', 175 | success: 'toast-success', 176 | warning: 'toast-warning' 177 | }, 178 | iconClass: 'toast-info', 179 | positionClass: 'toast-top-right', 180 | timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky 181 | titleClass: 'toast-title', 182 | messageClass: 'toast-message', 183 | target: 'body', 184 | closeHtml: '', 185 | newestOnTop: true, 186 | preventDuplicates: false, 187 | progressBar: false 188 | }; 189 | } 190 | 191 | function publish(args) { 192 | if (!listener) { return; } 193 | listener(args); 194 | } 195 | 196 | function notify(map) { 197 | var options = getOptions(); 198 | var iconClass = map.iconClass || options.iconClass; 199 | 200 | if (typeof (map.optionsOverride) !== 'undefined') { 201 | options = $.extend(options, map.optionsOverride); 202 | iconClass = map.optionsOverride.iconClass || iconClass; 203 | } 204 | 205 | if (shouldExit(options, map)) { return; } 206 | 207 | toastId++; 208 | 209 | $container = getContainer(options, true); 210 | 211 | var intervalId = null; 212 | var $toastElement = $('
'); 213 | var $titleElement = $('
'); 214 | var $messageElement = $('
'); 215 | var $progressElement = $('
'); 216 | var $closeElement = $(options.closeHtml); 217 | var progressBar = { 218 | intervalId: null, 219 | hideEta: null, 220 | maxHideTime: null 221 | }; 222 | var response = { 223 | toastId: toastId, 224 | state: 'visible', 225 | startTime: new Date(), 226 | options: options, 227 | map: map 228 | }; 229 | 230 | personalizeToast(); 231 | 232 | displayToast(); 233 | 234 | handleEvents(); 235 | 236 | publish(response); 237 | 238 | if (options.debug && console) { 239 | console.log(response); 240 | } 241 | 242 | return $toastElement; 243 | 244 | function personalizeToast() { 245 | setIcon(); 246 | setTitle(); 247 | setMessage(); 248 | setCloseButton(); 249 | setProgressBar(); 250 | setSequence(); 251 | } 252 | 253 | function handleEvents() { 254 | $toastElement.hover(stickAround, delayedHideToast); 255 | if (!options.onclick && options.tapToDismiss) { 256 | $toastElement.click(hideToast); 257 | } 258 | 259 | if (options.closeButton && $closeElement) { 260 | $closeElement.click(function (event) { 261 | if (event.stopPropagation) { 262 | event.stopPropagation(); 263 | } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { 264 | event.cancelBubble = true; 265 | } 266 | hideToast(true); 267 | }); 268 | } 269 | 270 | if (options.onclick) { 271 | $toastElement.click(function () { 272 | options.onclick(); 273 | hideToast(); 274 | }); 275 | } 276 | } 277 | 278 | function displayToast() { 279 | $toastElement.hide(); 280 | 281 | $toastElement[options.showMethod]( 282 | {duration: options.showDuration, easing: options.showEasing, complete: options.onShown} 283 | ); 284 | 285 | if (options.timeOut > 0) { 286 | intervalId = setTimeout(hideToast, options.timeOut); 287 | progressBar.maxHideTime = parseFloat(options.timeOut); 288 | progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; 289 | if (options.progressBar) { 290 | progressBar.intervalId = setInterval(updateProgress, 10); 291 | } 292 | } 293 | } 294 | 295 | function setIcon() { 296 | if (map.iconClass) { 297 | $toastElement.addClass(options.toastClass).addClass(iconClass); 298 | } 299 | } 300 | 301 | function setSequence() { 302 | if (options.newestOnTop) { 303 | $container.prepend($toastElement); 304 | } else { 305 | $container.append($toastElement); 306 | } 307 | } 308 | 309 | function setTitle() { 310 | if (map.title) { 311 | $titleElement.append(map.title).addClass(options.titleClass); 312 | $toastElement.append($titleElement); 313 | } 314 | } 315 | 316 | function setMessage() { 317 | if (map.message) { 318 | $messageElement.append(map.message).addClass(options.messageClass); 319 | $toastElement.append($messageElement); 320 | } 321 | } 322 | 323 | function setCloseButton() { 324 | if (options.closeButton) { 325 | $closeElement.addClass('toast-close-button').attr('role', 'button'); 326 | $toastElement.prepend($closeElement); 327 | } 328 | } 329 | 330 | function setProgressBar() { 331 | if (options.progressBar) { 332 | $progressElement.addClass('toast-progress'); 333 | $toastElement.prepend($progressElement); 334 | } 335 | } 336 | 337 | function shouldExit(options, map) { 338 | if (options.preventDuplicates) { 339 | if (map.message === previousToast) { 340 | return true; 341 | } else { 342 | previousToast = map.message; 343 | } 344 | } 345 | return false; 346 | } 347 | 348 | function hideToast(override) { 349 | if ($(':focus', $toastElement).length && !override) { 350 | return; 351 | } 352 | clearTimeout(progressBar.intervalId); 353 | return $toastElement[options.hideMethod]({ 354 | duration: options.hideDuration, 355 | easing: options.hideEasing, 356 | complete: function () { 357 | removeToast($toastElement); 358 | if (options.onHidden && response.state !== 'hidden') { 359 | options.onHidden(); 360 | } 361 | response.state = 'hidden'; 362 | response.endTime = new Date(); 363 | publish(response); 364 | } 365 | }); 366 | } 367 | 368 | function delayedHideToast() { 369 | if (options.timeOut > 0 || options.extendedTimeOut > 0) { 370 | intervalId = setTimeout(hideToast, options.extendedTimeOut); 371 | progressBar.maxHideTime = parseFloat(options.extendedTimeOut); 372 | progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; 373 | } 374 | } 375 | 376 | function stickAround() { 377 | clearTimeout(intervalId); 378 | progressBar.hideEta = 0; 379 | $toastElement.stop(true, true)[options.showMethod]( 380 | {duration: options.showDuration, easing: options.showEasing} 381 | ); 382 | } 383 | 384 | function updateProgress() { 385 | var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; 386 | $progressElement.width(percentage + '%'); 387 | } 388 | } 389 | 390 | function getOptions() { 391 | return $.extend({}, getDefaults(), toastr.options); 392 | } 393 | 394 | function removeToast($toastElement) { 395 | if (!$container) { $container = getContainer(); } 396 | if ($toastElement.is(':visible')) { 397 | return; 398 | } 399 | $toastElement.remove(); 400 | $toastElement = null; 401 | if ($container.children().length === 0) { 402 | $container.remove(); 403 | previousToast = undefined; 404 | } 405 | } 406 | 407 | })(); 408 | }); 409 | }(typeof define === 'function' && define.amd ? define : function (deps, factory) { 410 | if (typeof module !== 'undefined' && module.exports) { //Node 411 | module.exports = factory(require('jquery')); 412 | } else { 413 | window['toastr'] = factory(window['jQuery']); 414 | } 415 | })); -------------------------------------------------------------------------------- /resources/js/toastr/toastr.min.js: -------------------------------------------------------------------------------- 1 | !function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("
").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:'',newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if("undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),r.preventDuplicates){if(t.message===C)return;C=t.message}T++,v=n(r,!0);var u=null,l=e("
"),c=e("
"),p=e("
"),f=e("
"),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),C=void 0))}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)}); 2 | //# sourceMappingURL=toastr.js.map -------------------------------------------------------------------------------- /src/Escaping.php: -------------------------------------------------------------------------------- 1 | publishes([ 18 | __DIR__.'/notifications.php' => config_path('notifications.php'), 19 | ], 'config'); 20 | 21 | $this->publishes([ 22 | __DIR__.'/../resources/css' => public_path('css'), 23 | __DIR__.'/../resources/js' => public_path('js'), 24 | ], 'assets'); 25 | 26 | $this->getBladeCompiler() 27 | ->directive('notifications', function () { 28 | $expression = 'Gloudemans\Notify\Notifications\Notification'; 29 | 30 | return "render(); ?>"; 31 | }); 32 | } 33 | 34 | /** 35 | * Register the application services. 36 | * 37 | * @return void 38 | */ 39 | public function register() 40 | { 41 | $this->mergeConfigFrom( 42 | __DIR__.'/notifications.php', 'notifications' 43 | ); 44 | 45 | $config = $this->app['config']->get('notifications'); 46 | 47 | $this->bindNotificationRenderer($config['notifications']['renderer']); 48 | } 49 | 50 | /** 51 | * Bind the notification renderer specificed in the configuration 52 | * to the NotificationRenderer interface 53 | * 54 | * @param string $renderer 55 | * @return void 56 | */ 57 | private function bindNotificationRenderer($renderer) 58 | { 59 | $renderer = ucfirst($renderer); 60 | 61 | $this->app->bind( 62 | 'Gloudemans\Notify\Notifications\NotificationRenderer', 63 | "Gloudemans\\Notify\\Notifications\\Renderers\\{$renderer}Renderer" 64 | ); 65 | } 66 | 67 | /** 68 | * Get the blade compiler 69 | * 70 | * @return \Illuminate\View\Compilers\CompilerInterface 71 | */ 72 | private function getBladeCompiler() 73 | { 74 | return $this->app['view'] 75 | ->getEngineResolver() 76 | ->resolve('blade') 77 | ->getCompiler(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Notifications/AddsNotifications.php: -------------------------------------------------------------------------------- 1 | notify()->success($message, $title); 28 | } 29 | 30 | /** 31 | * Add an info notification 32 | * 33 | * @param string $message 34 | * @param string|null $title 35 | * @return void 36 | */ 37 | public function notifyInfo($message, $title = null) 38 | { 39 | return $this->notify()->info($message, $title); 40 | } 41 | 42 | /** 43 | * Add a warning notification 44 | * 45 | * @param string $message 46 | * @param string|null $title 47 | * @return void 48 | */ 49 | public function notifyWarning($message, $title = null) 50 | { 51 | return $this->notify()->warning($message, $title); 52 | } 53 | 54 | /** 55 | * Add an error notification 56 | * 57 | * @param string $message 58 | * @param string|null $title 59 | * @return void 60 | */ 61 | public function notifyError($message, $title = null) 62 | { 63 | return $this->notify()->error($message, $title); 64 | } 65 | } -------------------------------------------------------------------------------- /src/Notifications/Notification.php: -------------------------------------------------------------------------------- 1 | session = $session; 33 | $this->renderer = $renderer; 34 | } 35 | 36 | /** 37 | * Render the notifications 38 | * 39 | * @return string 40 | */ 41 | public function render() 42 | { 43 | $notifications = $this->getNotifications(); 44 | 45 | if (empty($notifications)) { 46 | return; 47 | } 48 | 49 | return $this->renderer->render($notifications); 50 | } 51 | 52 | /** 53 | * Add a new notification to the session 54 | * 55 | * @param string $type 56 | * @param string $message 57 | * @param null $title 58 | * @return void 59 | */ 60 | public function add($type, $message, $title = null) 61 | { 62 | $notifications = $this->getNotifications(); 63 | 64 | $notifications[] = [ 65 | 'type' => $type, 66 | 'message' => $message, 67 | 'title' => $title 68 | ]; 69 | 70 | $this->session->flash(self::SESSION_KEY, $notifications); 71 | } 72 | 73 | /** 74 | * Add a new success notifications 75 | * 76 | * @param string $message 77 | * @param null $title 78 | * @return void 79 | */ 80 | public function success($message, $title = null) 81 | { 82 | $this->add('success', $message, $title); 83 | } 84 | 85 | /** 86 | * Add a new info notifications 87 | * 88 | * @param string $message 89 | * @param null $title 90 | * @return void 91 | */ 92 | public function info($message, $title = null) 93 | { 94 | $this->add('info', $message, $title); 95 | } 96 | 97 | /** 98 | * Add a new warning notifications 99 | * 100 | * @param string $message 101 | * @param null $title 102 | * @return void 103 | */ 104 | public function warning($message, $title = null) 105 | { 106 | $this->add('warning', $message, $title); 107 | } 108 | 109 | /** 110 | * Add a new danger notifications 111 | * 112 | * @param string $message 113 | * @param null $title 114 | * @return void 115 | */ 116 | public function error($message, $title = null) 117 | { 118 | $this->add('error', $message, $title); 119 | } 120 | 121 | /** 122 | * Get the notifications from the session 123 | * 124 | * @return null|array 125 | */ 126 | private function getNotifications() 127 | { 128 | $notifications = $this->session->get(self::SESSION_KEY); 129 | 130 | return $notifications; 131 | } 132 | 133 | } -------------------------------------------------------------------------------- /src/Notifications/NotificationFacade.php: -------------------------------------------------------------------------------- 1 | escapeMessage($notification['message']); 23 | $title = is_null($notification['title']) ? ucfirst($notification['type']) : ucfirst($notification['type']) . ' ' . $this->escapeTitle($notification['title']); 24 | $type = $notification['type'] == 'error' ? 'danger' : $notification['type']; 25 | 26 | $bootboxes = <<renderOutput($bootboxes); 42 | } 43 | 44 | /** 45 | * Render the output 46 | * 47 | * @param string $bootboxes 48 | * @return string 49 | */ 50 | private function renderOutput($bootboxes) 51 | { 52 | $output = << 54 | $bootboxes 55 | 56 | TAG; 57 | 58 | return $output; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Notifications/Renderers/NativeRenderer.php: -------------------------------------------------------------------------------- 1 | generateMessage($notification); 25 | 26 | $alerts .= "alert('{$message}');\n"; 27 | } 28 | 29 | return $this->renderOutput($alerts); 30 | } 31 | 32 | /** 33 | * Render the output 34 | * 35 | * @param string $alerts 36 | * @return string 37 | */ 38 | private function renderOutput($alerts) 39 | { 40 | $output = << 42 | $alerts 43 | 44 | TAG; 45 | 46 | return $output; 47 | } 48 | 49 | /** 50 | * Generate the message for a native alert 51 | * 52 | * @param array $notification 53 | * @return string 54 | */ 55 | private function generateMessage($notification) 56 | { 57 | $message = ucfirst($notification['type']) . '\n\n'; 58 | 59 | if ( ! is_null($notification['title'])) { 60 | $message .= $this->escapeTitle($notification['title']) . '\n\n'; 61 | } 62 | 63 | return $this->escapeMessage($message . $notification['message']); 64 | } 65 | } -------------------------------------------------------------------------------- /src/Notifications/Renderers/SweetAlertRenderer.php: -------------------------------------------------------------------------------- 1 | escapeMessage($notification['message']); 25 | $type = $notification['type']; 26 | $title = is_null($notification['title']) ? ucfirst($type) : $this->escapeTitle($notification['title']); 27 | 28 | $sweetAlerts = <<renderOutput($sweetAlerts); 38 | } 39 | 40 | /** 41 | * Render the output 42 | * 43 | * @param string $sweetAlerts 44 | * @return string 45 | */ 46 | private function renderOutput($sweetAlerts) 47 | { 48 | $output = << 50 | $sweetAlerts 51 | 52 | TAG; 53 | 54 | return $output; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/Notifications/Renderers/ToastrRenderer.php: -------------------------------------------------------------------------------- 1 | escapeMessage($notification['message']); 25 | 26 | $toasts .= "toastr.{$notification['type']}('{$message}'"; 27 | 28 | if ( ! is_null($notification['title'])) { 29 | $title = $this->escapeTitle($notification['title']); 30 | 31 | $toasts .= ", '{$title}'"; 32 | } 33 | 34 | $toasts .= ");\n"; 35 | } 36 | 37 | return $this->renderOutput($toasts); 38 | } 39 | 40 | /** 41 | * Render the output 42 | * 43 | * @param string $toasts 44 | * @return string 45 | */ 46 | private function renderOutput($toasts) 47 | { 48 | $output = << 50 | $toasts 51 | 52 | TAG; 53 | 54 | return $output; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/notifications.php: -------------------------------------------------------------------------------- 1 | [ 6 | 7 | /* 8 | |-------------------------------------------------------------------------- 9 | | Notification Renderer 10 | |-------------------------------------------------------------------------- 11 | | 12 | | Specify which renderer to use to render the notifications 13 | | 14 | | Supported: "native", "toastr", "sweetalert", "bootbox" 15 | | 16 | */ 17 | 'renderer' => 'native' 18 | 19 | ] 20 | 21 | ]; -------------------------------------------------------------------------------- /tests/EscapingTest.php: -------------------------------------------------------------------------------- 1 | escaping = $this->getObjectForTrait('Gloudemans\Notify\Escaping'); 11 | } 12 | 13 | /** @test */ 14 | public function it_can_escape_the_message() 15 | { 16 | $message = "This isn't a title"; 17 | 18 | $escaped = $this->escaping->escapeMessage($message); 19 | 20 | $this->assertEquals("This isn\\'t a title", $escaped); 21 | $this->assertNotEquals("This isn't a title", $escaped); 22 | } 23 | 24 | /** @test */ 25 | public function it_can_escape_the_title() 26 | { 27 | $title = "This isn't a message"; 28 | 29 | $escaped = $this->escaping->escapeMessage($title); 30 | 31 | $this->assertEquals("This isn\\'t a message", $escaped); 32 | $this->assertNotEquals("This isn't a message", $escaped); 33 | } 34 | } -------------------------------------------------------------------------------- /tests/Notifications/AddsNotificationsTest.php: -------------------------------------------------------------------------------- 1 | controller = $this->getObjectForTrait('Gloudemans\Notify\Notifications\AddsNotifications'); 24 | } 25 | 26 | /** @test */ 27 | public function it_has_access_to_a_method_that_returns_an_instance_of_the_notification_class() 28 | { 29 | $notify = $this->controller->notify(); 30 | 31 | $this->assertInstanceOf('Gloudemans\Notify\Notifications\Notification', $notify); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /tests/Notifications/NotificationTest.php: -------------------------------------------------------------------------------- 1 | session = m::mock('Illuminate\Session\SessionManager'); 18 | $this->renderer = m::mock('Gloudemans\Notify\Notifications\NotificationRenderer'); 19 | 20 | $this->notification = new Notification($this->session, $this->renderer); 21 | } 22 | 23 | /** @test */ 24 | public function it_can_add_a_notification_to_the_session() 25 | { 26 | $this->session->shouldReceive('get')->once(); 27 | $this->session->shouldReceive('flash')->once(); 28 | 29 | $this->notification->add('success', 'Notification message', 'Notification title'); 30 | } 31 | 32 | /** @test */ 33 | public function it_can_add_a_notification_without_a_title_to_the_session() 34 | { 35 | $this->session->shouldReceive('get')->once(); 36 | $this->session->shouldReceive('flash')->once(); 37 | 38 | $this->notification->add('success', 'Notification message'); 39 | } 40 | 41 | /** @test */ 42 | public function it_can_add_a_success_notification() 43 | { 44 | $this->addNotification('success'); 45 | } 46 | 47 | /** @test */ 48 | public function it_can_add_an_info_notification() 49 | { 50 | $this->addNotification('info'); 51 | } 52 | 53 | /** @test */ 54 | public function it_can_add_a_warning_notification() 55 | { 56 | $this->addNotification('warning'); 57 | } 58 | 59 | /** @test */ 60 | public function it_can_add_a_error_notification() 61 | { 62 | $this->addNotification('error'); 63 | } 64 | 65 | /** @test */ 66 | public function it_can_render_the_notifications() 67 | { 68 | $notifications = [ 69 | [ 70 | 'type' => 'success', 71 | 'message' => 'Notification message', 72 | 'title' => 'Notification title' 73 | ] 74 | ]; 75 | 76 | $this->session->shouldReceive('get')->once()->andReturn($notifications); 77 | 78 | $this->renderer->shouldReceive('render')->once()->with($notifications)->andReturn($notifications); 79 | 80 | $rendered = $this->notification->render(); 81 | 82 | $this->assertEquals($notifications, $rendered); 83 | } 84 | 85 | /** @test */ 86 | public function it_does_not_render_anything_if_no_notifications_where_set() 87 | { 88 | $this->session->shouldReceive('get')->once()->andReturn(null); 89 | 90 | $this->renderer->shouldReceive('render')->once()->with(null)->andReturn(null); 91 | 92 | $rendered = $this->notification->render(); 93 | 94 | $this->assertNull($rendered); 95 | } 96 | 97 | /** 98 | * Helper method for adding a notification 99 | * 100 | * @param string $type 101 | */ 102 | private function addNotification($type) 103 | { 104 | $message = 'Notification message'; 105 | $title = 'Notification title'; 106 | 107 | $this->session->shouldReceive('get')->once(); 108 | $this->session->shouldReceive('flash')->once()->with(Notification::SESSION_KEY, [[ 109 | 'type' => $type, 110 | 'message' => $message, 111 | 'title' => $title 112 | ]]); 113 | 114 | $this->notification->{$type}($message, $title); 115 | } 116 | } -------------------------------------------------------------------------------- /tests/Notifications/NotificationsDirectiveTest.php: -------------------------------------------------------------------------------- 1 | registerBladeDirective($compiler); 16 | 17 | $result = $compiler->compileString('@notifications'); 18 | $expected = 'render(); ?>'; 19 | 20 | $this->assertEquals($expected, $result); 21 | } 22 | 23 | /** 24 | * Register the custom Blade directive 25 | * 26 | * @param \Illuminate\View\Compilers\BladeCompiler $compiler 27 | */ 28 | private function registerBladeDirective($compiler) 29 | { 30 | $compiler->directive('notifications', function () { 31 | $expression = 'Gloudemans\Notify\Notifications\Notification'; 32 | 33 | return "render(); ?>"; 34 | }); 35 | } 36 | } -------------------------------------------------------------------------------- /tests/Notifications/Renderers/BootboxRendererTest.php: -------------------------------------------------------------------------------- 1 | renderer = new BootboxRenderer(); 18 | } 19 | 20 | /** @test */ 21 | public function it_can_render_a_notification() 22 | { 23 | $expected = << 25 | bootbox.dialog({ 26 | message: 'Notification message', 27 | title: 'Success Notification title', 28 | buttons: { 29 | success: { 30 | label: 'OK', 31 | className: 'btn-success' 32 | } 33 | } 34 | }); 35 | 36 | TAG; 37 | 38 | $rendered = $this->renderer->render([ 39 | [ 40 | 'type' => 'success', 41 | 'message' => 'Notification message', 42 | 'title' => 'Notification title' 43 | ] 44 | ]); 45 | 46 | $this->assertEquals($expected, $rendered); 47 | } 48 | 49 | /** @test */ 50 | public function it_can_render_a_notification_without_a_title() 51 | { 52 | $expected = << 54 | bootbox.dialog({ 55 | message: 'Notification message', 56 | title: 'Success', 57 | buttons: { 58 | success: { 59 | label: 'OK', 60 | className: 'btn-success' 61 | } 62 | } 63 | }); 64 | 65 | TAG; 66 | 67 | $rendered = $this->renderer->render([ 68 | [ 69 | 'type' => 'success', 70 | 'message' => 'Notification message', 71 | 'title' => null 72 | ] 73 | ]); 74 | 75 | $this->assertEquals($expected, $rendered); 76 | } 77 | } -------------------------------------------------------------------------------- /tests/Notifications/Renderers/NativeRendererTest.php: -------------------------------------------------------------------------------- 1 | renderer = new NativeRenderer(); 18 | } 19 | 20 | /** @test */ 21 | public function it_can_render_a_notification() 22 | { 23 | $expected = << 25 | alert('Success\\n\\nNotification title\\n\\nNotification message');\n 26 | 27 | TAG; 28 | 29 | $rendered = $this->renderer->render([ 30 | [ 31 | 'type' => 'success', 32 | 'message' => 'Notification message', 33 | 'title' => 'Notification title' 34 | ] 35 | ]); 36 | 37 | $this->assertEquals($expected, $rendered); 38 | } 39 | 40 | /** @test */ 41 | public function it_can_render_a_notification_without_a_title() 42 | { 43 | $expected = << 45 | alert('Success\\n\\nNotification message');\n 46 | 47 | TAG; 48 | 49 | $rendered = $this->renderer->render([ 50 | [ 51 | 'type' => 'success', 52 | 'message' => 'Notification message', 53 | 'title' => null 54 | ] 55 | ]); 56 | 57 | $this->assertEquals($expected, $rendered); 58 | } 59 | } -------------------------------------------------------------------------------- /tests/Notifications/Renderers/SweetAlertRendererTest.php: -------------------------------------------------------------------------------- 1 | renderer = new SweetAlertRenderer(); 18 | } 19 | 20 | /** @test */ 21 | public function it_can_render_a_notification() 22 | { 23 | $expected = << 25 | swal({ 26 | title: 'Notification title', 27 | text: 'Notification message', 28 | type: 'success' 29 | });\n 30 | 31 | TAG; 32 | 33 | $rendered = $this->renderer->render([ 34 | [ 35 | 'type' => 'success', 36 | 'message' => 'Notification message', 37 | 'title' => 'Notification title' 38 | ] 39 | ]); 40 | 41 | $this->assertEquals($expected, $rendered); 42 | } 43 | 44 | /** @test */ 45 | public function it_can_render_a_notification_without_a_title() 46 | { 47 | $expected = << 49 | swal({ 50 | title: 'Success', 51 | text: 'Notification message', 52 | type: 'success' 53 | });\n 54 | 55 | TAG; 56 | 57 | $rendered = $this->renderer->render([ 58 | [ 59 | 'type' => 'success', 60 | 'message' => 'Notification message', 61 | 'title' => null 62 | ] 63 | ]); 64 | 65 | $this->assertEquals($expected, $rendered); 66 | } 67 | } -------------------------------------------------------------------------------- /tests/Notifications/Renderers/ToastrRendererTest.php: -------------------------------------------------------------------------------- 1 | renderer = new ToastrRenderer(); 18 | } 19 | 20 | /** @test */ 21 | public function it_can_render_a_notification() 22 | { 23 | $expected = << 25 | toastr.success('Notification message', 'Notification title'); 26 | 27 | 28 | TAG; 29 | 30 | $rendered = $this->renderer->render([ 31 | [ 32 | 'type' => 'success', 33 | 'message' => 'Notification message', 34 | 'title' => 'Notification title' 35 | ] 36 | ]); 37 | 38 | $this->assertEquals($expected, $rendered); 39 | } 40 | 41 | /** @test */ 42 | public function it_can_render_a_notification_without_a_title() 43 | { 44 | $expected = << 46 | toastr.success('Notification message');\n 47 | 48 | TAG; 49 | 50 | $rendered = $this->renderer->render([ 51 | [ 52 | 'type' => 'success', 53 | 'message' => 'Notification message', 54 | 'title' => null 55 | ] 56 | ]); 57 | 58 | $this->assertEquals($expected, $rendered); 59 | } 60 | 61 | } --------------------------------------------------------------------------------