Repository: CodeSeven/toastr Branch: master Commit: 50092cc60485 Files: 68 Total size: 243.9 KB Directory structure: gitextract_rvu49o6b/ ├── .gitattributes ├── .gitignore ├── .jscsrc ├── .jshintrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build/ │ └── toastr.css ├── demo.html ├── gulpfile.js ├── karma.conf.js ├── nuget/ │ ├── content/ │ │ ├── content/ │ │ │ ├── toastr.css │ │ │ ├── toastr.less │ │ │ └── toastr.scss │ │ └── scripts/ │ │ └── toastr.js │ ├── toastr.1.0.0.nupkg │ ├── toastr.1.0.0.nuspec │ ├── toastr.1.0.1.nupkg │ ├── toastr.1.0.1.nuspec │ ├── toastr.1.0.2.nupkg │ ├── toastr.1.0.2.nuspec │ ├── toastr.1.0.3.nupkg │ ├── toastr.1.0.3.nuspec │ ├── toastr.1.1.0.nupkg │ ├── toastr.1.1.0.nuspec │ ├── toastr.1.1.1.nupkg │ ├── toastr.1.1.1.nuspec │ ├── toastr.1.1.2.nupkg │ ├── toastr.1.1.2.nuspec │ ├── toastr.1.1.3.nupkg │ ├── toastr.1.1.4.1.nupkg │ ├── toastr.1.1.4.1.nuspec │ ├── toastr.1.1.4.2.nupkg │ ├── toastr.1.1.4.2.nuspec │ ├── toastr.1.1.4.nupkg │ ├── toastr.1.1.4.nuspec │ ├── toastr.1.1.5.nupkg │ ├── toastr.1.1.5.nuspec │ ├── toastr.1.2.0.nupkg │ ├── toastr.1.2.0.nuspec │ ├── toastr.1.2.1.nupkg │ ├── toastr.1.2.1.nuspec │ ├── toastr.1.2.2.nupkg │ ├── toastr.1.2.2.nuspec │ ├── toastr.1.3.0.nupkg │ ├── toastr.1.3.0.nuspec │ ├── toastr.1.3.1.nupkg │ ├── toastr.1.3.1.nuspec │ ├── toastr.2.0.0-rc1.nupkg │ ├── toastr.2.0.0-rc1.nuspec │ ├── toastr.2.0.1.nupkg │ ├── toastr.2.0.1.nuspec │ ├── toastr.2.0.2.nupkg │ ├── toastr.2.0.2.nuspec │ ├── toastr.2.0.3.nupkg │ └── toastr.2.0.3.nuspec ├── package.json ├── release checklist.md ├── tests/ │ ├── qunit/ │ │ ├── qunit.css │ │ └── qunit.js │ ├── toastr-tests.html │ └── unit/ │ ├── qunit-helper.js │ ├── toastr-tests.js │ └── x.js ├── toastr.js ├── toastr.less └── toastr.scss ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Set default behaviour, in case users don't have core.autocrlf set. * text=auto # Explicitly declare text files we want to always be normalized and converted # to native line endings on checkout. *.c text *.h text # Declare files that will always have CRLF line endings on checkout. *.sln text eol=crlf *.csproj text eol=crlf # Denote all files that are truly binary and should not be modified. *.png binary *.jpg binary ================================================ FILE: .gitignore ================================================ node_modules bower_components # Ignore Visual Studio Project # ################### *.config *.user *.csproj *.gpState *.sln *.suo /bin /obj /packages /Properties /Scripts /report /tests/coverage # Compiled source # ################### *.com *.class *.dll *.exe *.o *.so # Packages # ############ # it's better to unpack these files and commit the raw source # git has its own built in compression methods *.7z *.dmg *.gz *.iso *.jar *.rar *.tar *.zip # Logs and databases # ###################### *.log *.sql *.sqlite # OS generated files # ###################### .DS_Store* ehthumbs.db Icon? Thumbs.db # WebStorm # ###################### .idea/ ================================================ FILE: .jscsrc ================================================ { "excludeFiles": ["node_modules/**", "bower_components/**"], "requireCurlyBraces": [ "if", "else", "for", "while", "do", "try", "catch" ], "requireOperatorBeforeLineBreak": true, "requireCamelCaseOrUpperCaseIdentifiers": true, "maximumLineLength": { "value": 80, "allowComments": true, "allowRegex": true }, "validateIndentation": 2, "validateQuoteMarks": "'", "disallowMultipleLineStrings": true, "disallowMixedSpacesAndTabs": true, "disallowTrailingWhitespace": true, "disallowSpaceAfterPrefixUnaryOperators": true, "disallowMultipleVarDecl": null, "requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "return", "try", "catch" ], "requireSpaceBeforeBinaryOperators": [ "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "|=", "^=", "+=", "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", "|", "^", "&&", "||", "===", "==", ">=", "<=", "<", ">", "!=", "!==" ], "requireSpaceAfterBinaryOperators": true, "requireSpacesInConditionalExpression": true, "requireSpaceBeforeBlockStatements": true, "requireLineFeedAtFileEnd": true, "disallowSpacesInsideObjectBrackets": "all", "disallowSpacesInsideArrayBrackets": "all", "disallowSpacesInsideParentheses": true, "validateJSDoc": { "checkParamNames": true, "requireParamTypes": true }, "disallowMultipleLineBreaks": true, "requireLineFeedAtFileEnd": null, "disallowCommaBeforeLineBreak": null, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": null, "disallowMixedSpacesAndTabs": null, "disallowMultipleLineStrings": null, "disallowTrailingComma": null, "disallowTrailingWhitespace": null, "maximumLineLength": null, "requireCamelCaseOrUpperCaseIdentifiers": null, "requireCapitalizedConstructors": null, "requireCommaBeforeLineBreak": null, "requireCurlyBraces": null, "requireDotNotation": null, "requireMultipleVarDecl": null, "requireOperatorBeforeLineBreak": null, "requireParenthesesAroundIIFE": true, "validateIndentation": 4, "validateQuoteMarks": null } ================================================ FILE: .jshintrc ================================================ { "bitwise": true, "camelcase": true, "curly": true, "eqeqeq": true, "es3": false, "forin": true, "freeze": true, "immed": true, "indent": 4, "latedef": "nofunc", "newcap": true, "noarg": true, "noempty": true, "nonbsp": true, "nonew": true, "plusplus": false, "quotmark": "single", "undef": true, "unused": false, "strict": false, "maxparams": 10, "maxdepth": 5, "maxstatements": 40, "maxcomplexity": 8, "maxlen": 120, "asi": false, "boss": false, "debug": false, "eqnull": true, "esnext": false, "evil": false, "expr": false, "funcscope": false, "globalstrict": false, "iterator": false, "lastsemic": false, "laxbreak": false, "laxcomma": false, "loopfunc": true, "maxerr": false, "moz": false, "multistr": false, "notypeof": false, "proto": false, "scripturl": false, "shadow": false, "sub": true, "supernew": false, "validthis": false, "noyield": false, "browser": true, "node": true, "globals": { "angular": false, "$": false, "module": false, "require": false } } ================================================ FILE: .travis.yml ================================================ language: node_js node_js: - "6.12.1" install: - npm install -g gulp karma-cli - npm install script: - npm test cache: directories: - node_modules - travis_phantomjs branches: only: - develop - master before_install: # Upgrade PhantomJS to v2.1.1. - "export PHANTOMJS_VERSION=2.1.1" - "export PATH=$PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin:$PATH" - "if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then rm -rf $PWD/travis_phantomjs; mkdir -p $PWD/travis_phantomjs; fi" - "if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then wget https://github.com/Medium/phantomjs/releases/download/v$PHANTOMJS_VERSION/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -O $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2; fi" - "if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then tar -xvf $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs; fi" - "phantomjs --version" ================================================ FILE: CHANGELOG.md ================================================ # 6454acf14 (2017-12-08) _No official release because there are only CI changes._ - Resolving CI issues by manually merging in JLHwung's fork. (https://github.com/easyops-cn/toastr) # 2.1.4 (2017-12-07) - Same as 2.1.3, except 2.1.4 is on NPM # 2.1.3 (2016-07-22) ## New Features - Right to left text support - Added callbacks for click events on close button ## Bug Fixes - Fixed some CSS that prevented touch events from propagating on iOS devices - Removed role attribute because it duplicated voice over on text-to-speech readers; kept aria-live. - Consistent line-heights for close button to resolve issues with Bootstrap. ## Dev Ops - Removed Plato from gulp # 2.1.2 (2015-08-06) ## New Features - Added HTML escaping (use toastr.options.escapeHTML) - Added more options for overriding animations, specifically to closing a toast - Events are now passed into the onClick handler of the toast ## Bug Fixes - Resolved issue with centered toasts that would override top and bottom margins ## Dev Ops - Removed `module` and `require` from the `.jshintrc` file - Cleaned up the readme - Builds moved to the `builds` folder - Made href calls relative to the transport in the demo - CSS is now built by the included LESS file as part of a `gulp` call - Removed un-used deps # 2.1.1 (2015-02-19) ## New Features - Support for explicitly clearing a toast [jstawski](https://github.com/jstawski) | [PR 226](https://github.com/CodeSeven/toastr/pull/226) ## Dev Ops - Refactor to use gulp # 2.1.0 (2014-10-15) ## New Features - Prevent duplicate sequential toasts [SBero](https://github.com/sbero) | [aa083d8](https://github.com/CodeSeven/toastr/commit/ccb377b6015d557dbb987df74750b97b3aa083d8) - Add support for top-center and bottom-center toasts [showwin](https://github.com/showwin) | [86a4798](https://github.com/CodeSeven/toastr/commit/86a4798e76c7d8516521780b7bd085d6bb4c371b) - Add feature allowing progress bars to be shown for toasts [TravisTX](https://github.com/TravisTX) | [PR 189](https://github.com/CodeSeven/toastr/pull/189) `toastr.options.preventDuplicates = true;` `toastr.options.progressBar = true;` ## Bug Fixes - None ## Breaking Changes - None ## Dev Ops - Add karma test runner - Added Travis CI hooks # 2.0.3 (2014-05-17) ## New Features - None ## Bug Fixes - positionClass changes were not being honored due to 2.0.2 release changes. Refactored getContainer to only get the container, unless a 2nd boolean parameter is passed in in which case it will also create it if the container did not exist [871c2a6](https://github.com/CodeSeven/toastr/commit/871c2a6e438bb6b996cfb80286720604a4cf00fd) ## Breaking Changes - None # 2.0.2 (2014-04-29) ## New Features - Added simple ARIA reader support ([45c6362](https://github.com/CodeSeven/toastr/commit/45c63628476f6b085a6579dc681f4fe61ba5820c)) - Added SASS support (direct port of CSS for now) ([b4c8b34](https://github.com/CodeSeven/toastr/commit/b4c8b3460efb8aa51c730dd38c35ef6b025db2cc)) ## Bug Fixes - Added sourcemap for the min file ([1da4bd1](https://github.com/CodeSeven/toastr/commit/1da4bd1dad21bcfc7fcfe73da1abb185cf2c3f9f)) - IE 8 does not support stopPropagation on the event ([6989573](https://github.com/CodeSeven/toastr/commit/698957325a8e7bf63990f71ee409b911d69bc8ec)) - Media query width fixes ([ea2f5db](https://github.com/CodeSeven/toastr/commit/ea2f5db6e5314dcfe48eb34176583849c177c00e)) - Fix of onHidden firing twice when clicking on it then moving mouse out of toast ([ad613b9](https://github.com/CodeSeven/toastr/commit/ad613b9f18feeec630497590b85ca75c52141ea3) , [#105](https://github.com/CodeSeven/toastr/issues/105)) - Clear all toasts followed by a new toast now displays correctly ([3126a53](https://github.com/CodeSeven/toastr/commit/3126a533e0ab12ec3ff374e155a37fd38bd23bb6) , [#149](https://github.com/CodeSeven/toastr/issues/149) , [#118](https://github.com/CodeSeven/toastr/issues/118)) ## Breaking Changes - None # 2.0.1 (2013-09-01) ## New Features ### Close Button Optionally enable a close button toastr.options.closeButton = true; Optionally override the close button's HTML. toastr.options.closeHtml = ''; You can also override the CSS/LESS for `#toast-container .toast-close-button` ### Callbacks // Define a callback for when the toast is shown/hidden toastr.options.onShown = function() { console.log('hello'); } toastr.options.onHidden = function() { console.log('goodbye'); } ### Animation Options Toastr will supply default animations, so you do not have to provide any of these settings. However you have the option to override the animations if you like. ####Easings Optionally override the animation easing to show or hide the toasts. Default is swing. swing and linear are built into jQuery. toastr.options.showEasing = 'swing'; toastr.options.hideEasing = 'linear'; Using the jQuery Easing plugin (http://www.gsgd.co.uk/sandbox/jquery/easing/) toastr.options.showEasing = 'easeOutBounce'; toastr.options.hideEasing = 'easeInBack'; ####Animation Method Use the jQuery show/hide method of your choice. These default to fadeIn/fadeOut. The methods fadeIn/fadeOut, slideDown/slideUp, and show/hide are built into jQuery. toastr.options.showMethod = 'slideDown'; toastr.options.hideMethod = 'slideUp'; ###Timeouts Control how toastr interacts with users by setting timeouts appropriately. toastr.options.timeout = 30; // How long the toast will display without user interaction toastr.options.extendedTimeOut = 60; // How long the toast will display after a user hovers over it ## Breaking Changes ###Animation Changes The following animations options have been deprecated and should be replaced: - Replace `options.fadeIn` with `options.showDuration` - Replace `options.onFadeIn` with `options.onShown` - Replace `options.fadeOut` with `options.hideDuration` - Replace `options.onFadeOut` with `options.onHidden` # Version 1.3.1 ## Display Sequence Show newest toast at bottom (top is default) toastr.options.newestOnTop = false; ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2017 Toastr Maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # toastr **toastr** is a Javascript library for non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. [![Build Status](https://travis-ci.org/CodeSeven/toastr.svg)](https://travis-ci.org/CodeSeven/toastr) Browser testing provided by BrowserStack. ## Current Version 2.1.4 ## Demo - Demo can be found at http://codeseven.github.io/toastr/demo.html - [Demo using FontAwesome icons with toastr](http://plnkr.co/edit/6W9URNyyp2ItO4aUWzBB?p=preview) ## CDNs [![cdnjs](https://img.shields.io/cdnjs/v/toastr.js.svg)](https://cdnjs.com/libraries/toastr.js) [![jsdelivr](https://data.jsdelivr.com/v1/package/npm/toastr/badge)](https://www.jsdelivr.com/package/npm/toastr) Toastr is hosted at cdnjs and jsdelivr #### Debug - [//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css](//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css) #### Minified - [//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js](//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js) - [//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css](//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css) ## Install #### [NuGet Gallery](http://nuget.org/packages/toastr) ``` Install-Package toastr ``` #### [Bower](http://bower.io/search/?q=toastr) ``` bower install toastr ``` #### [npm](https://www.npmjs.com/package/toastr) ``` npm install --save toastr ``` #### [yarn](https://yarnpkg.com/en/package/toastr) ``` yarn add toastr ``` #### [Ruby on Rails](https://github.com/tylergannon/toastr-rails) ```ruby # Gemfile gem 'toastr-rails' ``` ```coffee # application.coffee #= require toastr ``` ```scss // application.scss @import "toastr"; ``` ## Wiki and Change Log [Wiki including Change Log](https://github.com/CodeSeven/toastr/wiki) ## Breaking Changes #### Animation Changes The following animations options have been deprecated and should be replaced: - Replace `options.fadeIn` with `options.showDuration` - Replace `options.onFadeIn` with `options.onShown` - Replace `options.fadeOut` with `options.hideDuration` - Replace `options.onFadeOut` with `options.onHidden` ## Quick Start ### 3 Easy Steps For other API calls, see the [demo](http://codeseven.github.io/toastr/demo.html). 1. Link to toastr.css `` 2. Link to toastr.js `` 3. use toastr to display a toast for info, success, warning or error ```js // Display an info toast with no title toastr.info('Are you the 6 fingered man?') ``` ### Other Options ```js // Display a warning toast, with no title toastr.warning('My name is Inigo Montoya. You killed my father, prepare to die!') // Display a success toast, with a title toastr.success('Have fun storming the castle!', 'Miracle Max Says') // Display an error toast, with a title toastr.error('I do not think that word means what you think it means.', 'Inconceivable!') // Immediately remove current toasts without using animation toastr.remove() // Remove current toasts using animation toastr.clear() // Override global options toastr.success('We do have the Kapua suite available.', 'Turtle Bay Resort', {timeOut: 5000}) ``` ### Escape HTML characters In case you want to escape HTML characters in title and message toastr.options.escapeHtml = true; ### Close Button Optionally enable a close button ```js toastr.options.closeButton = true; ```` Optionally override the close button's HTML. ```js toastr.options.closeHtml = ''; ``` You can also override the CSS/LESS for `#toast-container .toast-close-button` Optionally override the hide animation when the close button is clicked (falls back to hide configuration). ```js toastr.options.closeMethod = 'fadeOut'; toastr.options.closeDuration = 300; toastr.options.closeEasing = 'swing'; ``` ### Display Sequence Show newest toast at bottom (top is default) ```js toastr.options.newestOnTop = false; ``` ### Callbacks ```js // Define a callback for when the toast is shown/hidden/clicked toastr.options.onShown = function() { console.log('hello'); } toastr.options.onHidden = function() { console.log('goodbye'); } toastr.options.onclick = function() { console.log('clicked'); } toastr.options.onCloseClick = function() { console.log('close button clicked'); } ``` ### Animation Options Toastr will supply default animations, so you do not have to provide any of these settings. However you have the option to override the animations if you like. #### Easings Optionally override the animation easing to show or hide the toasts. Default is swing. swing and linear are built into jQuery. ```js toastr.options.showEasing = 'swing'; toastr.options.hideEasing = 'linear'; toastr.options.closeEasing = 'linear'; ``` Using the jQuery Easing plugin (http://www.gsgd.co.uk/sandbox/jquery/easing/) ```js toastr.options.showEasing = 'easeOutBounce'; toastr.options.hideEasing = 'easeInBack'; toastr.options.closeEasing = 'easeInBack'; ``` #### Animation Method Use the jQuery show/hide method of your choice. These default to fadeIn/fadeOut. The methods fadeIn/fadeOut, slideDown/slideUp, and show/hide are built into jQuery. ```js toastr.options.showMethod = 'slideDown'; toastr.options.hideMethod = 'slideUp'; toastr.options.closeMethod = 'slideUp'; ``` ### Prevent Duplicates Rather than having identical toasts stack, set the preventDuplicates property to true. Duplicates are matched to the previous toast based on their message content. ```js toastr.options.preventDuplicates = true; ``` ### Timeouts Control how toastr interacts with users by setting timeouts appropriately. ```js toastr.options.timeOut = 30; // How long the toast will display without user interaction toastr.options.extendedTimeOut = 60; // How long the toast will display after a user hovers over it ``` ### Prevent from Auto Hiding To prevent toastr from closing based on the timeouts, set the `timeOut` and `extendedTimeOut` options to `0`. The toastr will persist until selected. ```js toastr.options.timeOut = 0; toastr.options.extendedTimeOut = 0; ``` ### Progress Bar Visually indicate how long before a toast expires. ```js toastr.options.progressBar = true; ``` ### rtl Flip the toastr to be displayed properly for right-to-left languages. ```js toastr.options.rtl = true; ``` ## Building Toastr To build the minified and css versions of Toastr you will need [node](http://nodejs.org) installed. (Use Homebrew or Chocolatey.) ``` npm install -g gulp karma-cli npm install ``` At this point the dependencies have been installed and you can build Toastr - Run the analytics `gulp analyze` - Run the test `gulp test` - Run the build `gulp` ## Contributing For a pull request to be considered it must resolve a bug, or add a feature which is beneficial to a large audience. Pull requests must pass existing unit tests, CI processes, and add additional tests to indicate successful operation of a new feature, or the resolution of an identified bug. Requests must be made against the `develop` branch. Pull requests submitted against the `master` branch will not be considered. All pull requests are subject to approval by the repository owners, who have sole discretion over acceptance or denial. ## Authors **John Papa** + [http://twitter.com/John_Papa](http://twitter.com/John_Papa) **Tim Ferrell** + [http://twitter.com/ferrell_tim](http://twitter.com/ferrell_tim) **Hans Fjällemark** + [http://twitter.com/hfjallemark](http://twitter.com/hfjallemark) ## Credits Inspired by https://github.com/Srirangan/notifer.js/. ## Copyright Copyright © 2012-2015 ## License toastr is under MIT license - http://www.opensource.org/licenses/mit-license.php ================================================ FILE: build/toastr.css ================================================ .toast-title { font-weight: bold; } .toast-message { -ms-word-wrap: break-word; word-wrap: break-word; } .toast-message a, .toast-message label { color: #FFFFFF; } .toast-message a:hover { color: #CCCCCC; text-decoration: none; } .toast-close-button { position: relative; right: -0.3em; top: -0.3em; float: right; font-size: 20px; font-weight: bold; color: #FFFFFF; -webkit-text-shadow: 0 1px 0 #ffffff; text-shadow: 0 1px 0 #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); line-height: 1; } .toast-close-button:hover, .toast-close-button:focus { color: #000000; text-decoration: none; cursor: pointer; opacity: 0.4; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); filter: alpha(opacity=40); } .rtl .toast-close-button { left: -0.3em; float: left; right: 0.3em; } /*Additional properties for button version iOS requires the button element instead of an anchor tag. If you want the anchor version, it requires `href="#"`.*/ button.toast-close-button { padding: 0; cursor: pointer; background: transparent; 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; pointer-events: none; /*overrides*/ } #toast-container * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #toast-container > div { position: relative; pointer-events: auto; overflow: hidden; margin: 0 0 6px; padding: 15px 15px 15px 50px; width: 300px; -moz-border-radius: 3px 3px 3px 3px; -webkit-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; background-position: 15px center; background-repeat: no-repeat; -moz-box-shadow: 0 0 12px #999999; -webkit-box-shadow: 0 0 12px #999999; box-shadow: 0 0 12px #999999; color: #FFFFFF; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } #toast-container > div.rtl { direction: rtl; padding: 15px 50px 15px 15px; background-position: right 15px center; } #toast-container > div:hover { -moz-box-shadow: 0 0 12px #000000; -webkit-box-shadow: 0 0 12px #000000; box-shadow: 0 0 12px #000000; opacity: 1; -ms-filter: progid:DXImageTransform.Microsoft.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-top-center > div, #toast-container.toast-bottom-center > div { width: 300px; margin-left: auto; margin-right: auto; } #toast-container.toast-top-full-width > div, #toast-container.toast-bottom-full-width > div { width: 96%; margin-left: auto; margin-right: 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: #000000; opacity: 0.4; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); filter: alpha(opacity=40); } /*Responsive Design*/ @media all and (max-width: 240px) { #toast-container > div { padding: 8px 8px 8px 50px; width: 11em; } #toast-container > div.rtl { padding: 8px 50px 8px 8px; } #toast-container .toast-close-button { right: -0.2em; top: -0.2em; } #toast-container .rtl .toast-close-button { left: -0.2em; right: 0.2em; } } @media all and (min-width: 241px) and (max-width: 480px) { #toast-container > div { padding: 8px 8px 8px 50px; width: 18em; } #toast-container > div.rtl { padding: 8px 50px 8px 8px; } #toast-container .toast-close-button { right: -0.2em; top: -0.2em; } #toast-container .rtl .toast-close-button { left: -0.2em; right: 0.2em; } } @media all and (min-width: 481px) and (max-width: 768px) { #toast-container > div { padding: 15px 15px 15px 50px; width: 25em; } #toast-container > div.rtl { padding: 15px 50px 15px 15px; } } ================================================ FILE: demo.html ================================================ toastr examples

toastr


        
================================================ FILE: gulpfile.js ================================================ /* jshint node:true, camelcase:false */ var gulp = require('gulp'); var karma = require('karma').server; var merge = require('merge-stream'); var plug = require('gulp-load-plugins')(); var paths = { js: './toastr.js', less: './toastr.less', report: './report', build: './build' }; var log = plug.util.log; /** * List the available gulp tasks */ gulp.task('help', plug.taskListing); /** * Lint the code, create coverage report, and a visualizer * @return {Stream} */ gulp.task('analyze', function () { log('Analyzing source with JSHint and JSCS'); var jshint = analyzejshint([paths.js]); var jscs = analyzejscs([paths.js]); return merge(jshint, jscs); }); /** * Minify and bundle the app's JavaScript * @return {Stream} */ gulp.task('js', function () { log('Bundling, minifying, and copying the app\'s JavaScript'); return gulp .src(paths.js) .pipe(plug.sourcemaps.init()) .pipe(plug.bytediff.start()) .pipe(plug.uglify({})) .pipe(plug.bytediff.stop(bytediffFormatter)) .pipe(plug.sourcemaps.write('.')) .pipe(plug.rename(function (path) { if (path.extname === '.js') { path.basename += '.min'; } })) .pipe(gulp.dest(paths.build)); }); /** * Minify and bundle the CSS * @return {Stream} */ gulp.task('css', function () { log('Bundling, minifying, and copying the app\'s CSS'); return gulp.src(paths.less) .pipe(plug.less()) .pipe(gulp.dest(paths.build)) .pipe(plug.bytediff.start()) .pipe(plug.minifyCss({})) .pipe(plug.bytediff.stop(bytediffFormatter)) .pipe(plug.rename('toastr.min.css')) .pipe(gulp.dest(paths.build)); }); /** * Build js and css */ gulp.task('default', ['js', 'css'], function () { log('Analyze, Build CSS and JS'); }); /** * Remove all files from the build folder * One way to run clean before all tasks is to run * from the cmd line: gulp clean && gulp build * @return {Stream} */ gulp.task('clean', function (cb) { log('Cleaning: ' + plug.util.colors.blue(paths.report)); log('Cleaning: ' + plug.util.colors.blue(paths.build)); var delPaths = [paths.build, paths.report]; del(delPaths, cb); }); /** * Run specs once and exit * To start servers and run midway specs as well: * gulp test --startServers * @return {Stream} */ gulp.task('test', function (done) { startTests(true /*singleRun*/, done); }); //////////////// /** * Execute JSHint on given source files * @param {Array} sources * @param {String} overrideRcFile * @return {Stream} */ function analyzejshint(sources, overrideRcFile) { var jshintrcFile = overrideRcFile || './.jshintrc'; log('Running JSHint'); return gulp .src(sources) .pipe(plug.jshint(jshintrcFile)) .pipe(plug.jshint.reporter('jshint-stylish')); } /** * Execute JSCS on given source files * @param {Array} sources * @return {Stream} */ function analyzejscs(sources) { log('Running JSCS'); return gulp .src(sources) .pipe(plug.jscs('./.jscsrc')); } /** * Start the tests using karma. * @param {boolean} singleRun - True means run once and end (CI), or keep running (dev) * @param {Function} done - Callback to fire when karma is done * @return {undefined} */ function startTests(singleRun, done) { karma.start({ configFile: __dirname + '/karma.conf.js', singleRun: !!singleRun }, karmaCompleted); //////////////// function karmaCompleted(exitCode) { if (exitCode === 0) { done(); } else { process.exit(exitCode); } } } /** * Formatter for bytediff to display the size changes after processing * @param {Object} data - byte data * @return {String} Difference in bytes, formatted */ function bytediffFormatter(data) { var difference = (data.savings > 0) ? ' smaller.' : ' larger.'; return data.fileName + ' went from ' + (data.startSize / 1000).toFixed(2) + ' kB to ' + (data.endSize / 1000).toFixed(2) + ' kB' + ' and is ' + formatPercent(1 - data.percent, 2) + '%' + difference; } /** * Format a number as a percentage * @param {Number} num Number to format as a percent * @param {Number} precision Precision of the decimal * @return {Number} Formatted perentage */ function formatPercent(num, precision) { return (num * 100).toFixed(precision); } ================================================ FILE: karma.conf.js ================================================ // Karma configuration // Generated on Thu Sep 04 2014 07:41:43 GMT-0400 (EDT) module.exports = function (config) { config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['qunit'], // list of files / patterns to load in the browser files: [ 'node_modules/jquery/dist/jquery.min.js', 'build/toastr.css', 'toastr.js', 'node_modules/qunitjs/qunit/qunit.js', 'tests/unit/qunit-helper.js', 'tests/unit/toastr-tests.js' ], // list of files to exclude exclude: [], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { 'toastr.js': 'coverage' }, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter reporters: ['progress', 'coverage'], coverageReporter: { type: 'lcov', dir: 'tests/coverage' }, // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file changes autoWatch: false, // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher browsers: ['PhantomJS'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits singleRun: true }); }; ================================================ FILE: nuget/content/content/toastr.css ================================================ /* * Toastr * Copyright 2012-2014 John Papa and Hans Fjällemark. * All Rights Reserved. * Use, reproduction, distribution, and modification of this code is subject to the terms and * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php * * Author: John Papa and Hans Fjällemark * Project: https://github.com/CodeSeven/toastr */ .toast-title { font-weight: bold; } .toast-message { -ms-word-wrap: break-word; word-wrap: break-word; } .toast-message a, .toast-message label { color: #ffffff; } .toast-message a:hover { color: #cccccc; text-decoration: none; } .toast-close-button { position: relative; right: -0.3em; top: -0.3em; float: right; font-size: 20px; font-weight: bold; color: #ffffff; -webkit-text-shadow: 0 1px 0 #ffffff; text-shadow: 0 1px 0 #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } .toast-close-button:hover, .toast-close-button:focus { color: #000000; text-decoration: none; cursor: pointer; opacity: 0.4; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); filter: alpha(opacity=40); } /*Additional properties for button version iOS requires the button element instead of an anchor tag. If you want the anchor version, it requires `href="#"`.*/ button.toast-close-button { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; } .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; /*overrides*/ } #toast-container * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #toast-container > div { margin: 0 0 6px; padding: 15px 15px 15px 50px; width: 300px; -moz-border-radius: 3px 3px 3px 3px; -webkit-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; background-position: 15px center; background-repeat: no-repeat; -moz-box-shadow: 0 0 12px #999999; -webkit-box-shadow: 0 0 12px #999999; box-shadow: 0 0 12px #999999; color: #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } #toast-container > :hover { -moz-box-shadow: 0 0 12px #000000; -webkit-box-shadow: 0 0 12px #000000; box-shadow: 0 0 12px #000000; opacity: 1; -ms-filter: progid:DXImageTransform.Microsoft.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-top-full-width > div, #toast-container.toast-bottom-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; } /*Responsive Design*/ @media all and (max-width: 240px) { #toast-container > div { padding: 8px 8px 8px 50px; width: 11em; } #toast-container .toast-close-button { right: -0.2em; top: -0.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: -0.2em; top: -0.2em; } } @media all and (min-width: 481px) and (max-width: 768px) { #toast-container > div { padding: 15px 15px 15px 50px; width: 25em; } } ================================================ FILE: nuget/content/content/toastr.less ================================================ // Mix-ins .borderRadius(@radius) { -moz-border-radius: @radius; -webkit-border-radius: @radius; border-radius: @radius; } .boxShadow(@boxShadow) { -moz-box-shadow: @boxShadow; -webkit-box-shadow: @boxShadow; box-shadow: @boxShadow; } .opacity(@opacity) { @opacityPercent: @opacity * 100; opacity: @opacity; -ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(Opacity=@{opacityPercent})"; filter: ~"alpha(opacity=@{opacityPercent})"; } .wordWrap(@wordWrap: break-word) { -ms-word-wrap: @wordWrap; word-wrap: @wordWrap; } // Variables @black: #000000; @grey: #999999; @light-grey: #CCCCCC; @white: #FFFFFF; @near-black: #030303; @green: #51A351; @red: #BD362F; @blue: #2F96B4; @orange: #F89406; // Styles .toast-title { font-weight: bold; } .toast-message { .wordWrap(); a, label { color: @white; } a:hover { color: @light-grey; text-decoration: none; } } .toast-close-button { position: relative; right: -0.3em; top: -0.3em; float: right; font-size: 20px; font-weight: bold; color: @white; -webkit-text-shadow: 0 1px 0 rgba(255,255,255,1); text-shadow: 0 1px 0 rgba(255,255,255,1); .opacity(0.8); &:hover, &:focus { color: @black; text-decoration: none; cursor: pointer; .opacity(0.4); } } /*Additional properties for button version iOS requires the button element instead of an anchor tag. If you want the anchor version, it requires `href="#"`.*/ button.toast-close-button { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; } //#endregion .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; * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } > div { margin: 0 0 6px; padding: 15px 15px 15px 50px; width: 300px; .borderRadius(3px 3px 3px 3px); background-position: 15px center; background-repeat: no-repeat; .boxShadow(0 0 12px @grey); color: @white; .opacity(0.8); } > :hover { .boxShadow(0 0 12px @black); .opacity(1); cursor: pointer; } > .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-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-success { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; } > .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; } /*overrides*/ &.toast-top-full-width > div, &.toast-bottom-full-width > div { width: 96%; margin: auto; } } .toast { background-color: @near-black; } .toast-success { background-color: @green; } .toast-error { background-color: @red; } .toast-info { background-color: @blue; } .toast-warning { background-color: @orange; } /*Responsive Design*/ @media all and (max-width: 240px) { #toast-container { > div { padding: 8px 8px 8px 50px; width: 11em; } & .toast-close-button { right: -0.2em; top: -0.2em; } } } @media all and (min-width: 241px) and (max-width: 480px) { #toast-container { > div { padding: 8px 8px 8px 50px; width: 18em; } & .toast-close-button { right: -0.2em; top: -0.2em; } } } @media all and (min-width: 481px) and (max-width: 768px) { #toast-container { > div { padding: 15px 15px 15px 50px; width: 25em; } } } ================================================ FILE: nuget/content/content/toastr.scss ================================================ /* * Toastr * Version 2.0.1 * Copyright 2012 John Papa and Hans Fjällemark. * All Rights Reserved. * Use, reproduction, distribution, and modification of this code is subject to the terms and * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php * * Author: John Papa and Hans Fjällemark * Project: https://github.com/CodeSeven/toastr */ .toast-title { font-weight: bold; } .toast-message { -ms-word-wrap: break-word; word-wrap: break-word; } .toast-message a, .toast-message label { color: #ffffff; } .toast-message a:hover { color: #cccccc; text-decoration: none; } .toast-close-button { position: relative; right: -0.3em; top: -0.3em; float: right; font-size: 20px; font-weight: bold; color: #ffffff; -webkit-text-shadow: 0 1px 0 #ffffff; text-shadow: 0 1px 0 #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } .toast-close-button:hover, .toast-close-button:focus { color: #000000; text-decoration: none; cursor: pointer; opacity: 0.4; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); filter: alpha(opacity=40); } /*Additional properties for button version iOS requires the button element instead of an anchor tag. If you want the anchor version, it requires `href="#"`.*/ button.toast-close-button { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; } .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; /*overrides*/ } #toast-container * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } #toast-container > div { margin: 0 0 6px; padding: 15px 15px 15px 50px; width: 300px; -moz-border-radius: 3px 3px 3px 3px; -webkit-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; background-position: 15px center; background-repeat: no-repeat; -moz-box-shadow: 0 0 12px #999999; -webkit-box-shadow: 0 0 12px #999999; box-shadow: 0 0 12px #999999; color: #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } #toast-container > :hover { -moz-box-shadow: 0 0 12px #000000; -webkit-box-shadow: 0 0 12px #000000; box-shadow: 0 0 12px #000000; opacity: 1; -ms-filter: progid:DXImageTransform.Microsoft.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-top-full-width > div, #toast-container.toast-bottom-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; } /*Responsive Design*/ @media all and (max-width: 239px) { #toast-container > div { padding: 8px 8px 8px 50px; width: 11em; } #toast-container .toast-close-button { right: -0.2em; top: -0.2em; } } @media all and (min-width: 240px) and (max-width: 479px) { #toast-container > div { padding: 8px 8px 8px 50px; width: 18em; } #toast-container .toast-close-button { right: -0.2em; top: -0.2em; } } @media all and (min-width: 480px) and (max-width: 767px) { #toast-container > div { padding: 15px 15px 15px 50px; width: 25em; } } ================================================ FILE: nuget/content/scripts/toastr.js ================================================ /* * Toastr * Copyright 2012-2014 John Papa and Hans Fjällemark. * All Rights Reserved. * Use, reproduction, distribution, and modification of this code is subject to the terms and * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php * * Author: John Papa and Hans Fjällemark * ARIA Support: Greta Krafsig * Project: https://github.com/CodeSeven/toastr */ ; (function (define) { define(['jquery'], function ($) { return (function () { var $container; var listener; var toastId = 0; var toastType = { error: 'error', info: 'info', success: 'success', warning: 'warning' }; var toastr = { clear: clear, remove: remove, error: error, getContainer: getContainer, info: info, options: {}, subscribe: subscribe, success: success, version: '2.0.3', warning: warning }; return toastr; //#region Accessible Methods function error(message, title, optionsOverride) { return notify({ type: toastType.error, iconClass: getOptions().iconClasses.error, message: message, optionsOverride: optionsOverride, title: title }); } function getContainer(options, create) { if (!options) { options = getOptions(); } $container = $('#' + options.containerId); if ($container.length) { return $container; } if(create) { $container = createContainer(options); } return $container; } function info(message, title, optionsOverride) { return notify({ type: toastType.info, iconClass: getOptions().iconClasses.info, message: message, optionsOverride: optionsOverride, title: title }); } function subscribe(callback) { listener = callback; } function success(message, title, optionsOverride) { return notify({ type: toastType.success, iconClass: getOptions().iconClasses.success, message: message, optionsOverride: optionsOverride, title: title }); } function warning(message, title, optionsOverride) { return notify({ type: toastType.warning, iconClass: getOptions().iconClasses.warning, message: message, optionsOverride: optionsOverride, title: title }); } function clear($toastElement) { var options = getOptions(); if (!$container) { getContainer(options); } if (!clearToast($toastElement, options)) { clearContainer(options); } } function remove($toastElement) { var options = getOptions(); if (!$container) { getContainer(options); } if ($toastElement && $(':focus', $toastElement).length === 0) { removeToast($toastElement); return; } if ($container.children().length) { $container.remove(); } } //#endregion //#region Internal Methods function clearContainer(options){ var toastsToClear = $container.children(); for (var i = toastsToClear.length - 1; i >= 0; i--) { clearToast($(toastsToClear[i]), options); }; } function clearToast($toastElement, options){ if ($toastElement && $(':focus', $toastElement).length === 0) { $toastElement[options.hideMethod]({ duration: options.hideDuration, easing: options.hideEasing, complete: function () { removeToast($toastElement); } }); return true; } return false; } function createContainer(options) { $container = $('
') .attr('id', options.containerId) .addClass(options.positionClass) .attr('aria-live', 'polite') .attr('role', 'alert'); $container.appendTo($(options.target)); return $container; } function getDefaults() { return { tapToDismiss: true, toastClass: 'toast', containerId: 'toast-container', debug: false, showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery showDuration: 300, showEasing: 'swing', //swing and linear are built into jQuery onShown: undefined, hideMethod: 'fadeOut', hideDuration: 1000, hideEasing: 'swing', onHidden: undefined, extendedTimeOut: 1000, iconClasses: { error: 'toast-error', info: 'toast-info', success: 'toast-success', warning: 'toast-warning' }, iconClass: 'toast-info', positionClass: 'toast-top-right', timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky titleClass: 'toast-title', messageClass: 'toast-message', target: 'body', closeHtml: '', newestOnTop: true }; } function publish(args) { if (!listener) { return; } listener(args); } function notify(map) { var options = getOptions(), iconClass = map.iconClass || options.iconClass; if (typeof (map.optionsOverride) !== 'undefined') { options = $.extend(options, map.optionsOverride); iconClass = map.optionsOverride.iconClass || iconClass; } toastId++; $container = getContainer(options, true); var intervalId = null, $toastElement = $('
'), $titleElement = $('
'), $messageElement = $('
'), $closeElement = $(options.closeHtml), response = { toastId: toastId, state: 'visible', startTime: new Date(), options: options, map: map }; if (map.iconClass) { $toastElement.addClass(options.toastClass).addClass(iconClass); } if (map.title) { $titleElement.append(map.title).addClass(options.titleClass); $toastElement.append($titleElement); } if (map.message) { $messageElement.append(map.message).addClass(options.messageClass); $toastElement.append($messageElement); } if (options.closeButton) { $closeElement.addClass('toast-close-button').attr("role", "button"); $toastElement.prepend($closeElement); } $toastElement.hide(); if (options.newestOnTop) { $container.prepend($toastElement); } else { $container.append($toastElement); } $toastElement[options.showMethod]( { duration: options.showDuration, easing: options.showEasing, complete: options.onShown } ); if (options.timeOut > 0) { intervalId = setTimeout(hideToast, options.timeOut); } $toastElement.hover(stickAround, delayedHideToast); if (!options.onclick && options.tapToDismiss) { $toastElement.click(hideToast); } if (options.closeButton && $closeElement) { $closeElement.click(function (event) { if( event.stopPropagation ) { event.stopPropagation(); } else if( event.cancelBubble !== undefined && event.cancelBubble !== true ) { event.cancelBubble = true; } hideToast(true); }); } if (options.onclick) { $toastElement.click(function () { options.onclick(); hideToast(); }); } publish(response); if (options.debug && console) { console.log(response); } return $toastElement; function hideToast(override) { if ($(':focus', $toastElement).length && !override) { return; } return $toastElement[options.hideMethod]({ duration: options.hideDuration, easing: options.hideEasing, complete: function () { removeToast($toastElement); if (options.onHidden && response.state !== 'hidden') { options.onHidden(); } response.state = 'hidden'; response.endTime = new Date(); publish(response); } }); } function delayedHideToast() { if (options.timeOut > 0 || options.extendedTimeOut > 0) { intervalId = setTimeout(hideToast, options.extendedTimeOut); } } function stickAround() { clearTimeout(intervalId); $toastElement.stop(true, true)[options.showMethod]( { duration: options.showDuration, easing: options.showEasing } ); } } function getOptions() { return $.extend({}, getDefaults(), toastr.options); } function removeToast($toastElement) { if (!$container) { $container = getContainer(); } if ($toastElement.is(':visible')) { return; } $toastElement.remove(); $toastElement = null; if ($container.children().length === 0) { $container.remove(); } } //#endregion })(); }); }(typeof define === 'function' && define.amd ? define : function (deps, factory) { if (typeof module !== 'undefined' && module.exports) { //Node module.exports = factory(require('jquery')); } else { window['toastr'] = factory(window['jQuery']); } })); ================================================ FILE: nuget/toastr.1.0.0.nuspec ================================================ 1.0.0 John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr toastr toastr false 3 Easy Steps: 1) Link to toastr.css and toastr-responsive.css 2) Link to toastr.js 3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.0.3.nuspec ================================================  toastr 1.0.2 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr false 3 Easy Steps: 1) Link to toastr.css and toastr-responsive.css 2) Link to toastr.js 3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Minor updates for long unbroken string going outside toast and new feature to keep the toast around after hover-off for an extended timeout. Set extendedTimeOut and timeOut to 0 to avoid toastr from fading away. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.0.nuspec ================================================  toastr 1.1.0 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added AMD support (and backwards compat with non AMD), toastr.clear() method, optionsOverride API to be able to override options for each toast, added onclick callback option which fires when a user clicks the toast. Also cleaned CSS, merged CSS files into 1 file, and reduced jQuery dependency to v1.6.3 Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.1.nuspec ================================================  toastr 1.1.1 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added AMD support (and backwards compat with non AMD), toastr.clear() method, optionsOverride API to be able to override options for each toast, added onclick callback option which fires when a user clicks the toast. Also cleaned CSS, merged CSS files into 1 file, and reduced jQuery dependency to v1.6.3 Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.2.nuspec ================================================  toastr 1.1.2 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added AMD support (and backwards compat with non AMD), toastr.clear() method clears 1 or all toasts, optionsOverride API to be able to override options for each toast, added onclick callback option which fires when a user clicks the toast. Also cleaned CSS, merged CSS files into 1 file, and reduced jQuery dependency to v1.6.3 Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.4.1.nuspec ================================================  toastr 1.1.4.1 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added AMD support (and backwards compat with non AMD), toastr.clear() method clears 1 or all toasts, optionsOverride API to be able to override options for each toast, added onclick callback option which fires when a user clicks the toast. Also cleaned CSS, merged CSS files into 1 file, and reduced jQuery dependency to v1.6.3 Fix to the toastr.min.js file Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.4.2.nuspec ================================================  toastr 1.1.4.2 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added AMD support (and backwards compat with non AMD), toastr.clear() method clears 1 or all toasts, optionsOverride API to be able to override options for each toast, added onclick callback option which fires when a user clicks the toast. Also cleaned CSS, merged CSS files into 1 file, and reduced jQuery dependency to v1.6.3 Fix to the toastr.min.js file Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.4.nuspec ================================================  toastr 1.1.4 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added AMD support (and backwards compat with non AMD), toastr.clear() method clears 1 or all toasts, optionsOverride API to be able to override options for each toast, added onclick callback option which fires when a user clicks the toast. Also cleaned CSS, merged CSS files into 1 file, and reduced jQuery dependency to v1.6.3 Fix to the toastr.min.js file Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.1.5.nuspec ================================================  toastr 1.1.5 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Now using SemVer for JavaScript files. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.2.0.nuspec ================================================  toastr 1.2.0 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added getContainer(). Fixed clear() bug. Removed semver from file name. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.2.1.nuspec ================================================  toastr 1.2.1 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added getContainer(). Fixed clear() bug. Removed semver from file name. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.2.2.nuspec ================================================  toastr 1.2.2 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added getContainer(). Fixed clear() bug. Removed semver from file name. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.3.0.nuspec ================================================  toastr 1.3.0 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Added onFadeIn and onFadeOut callbacks. toastr.options.onFadeIn = function() { console.log('hello'); } Added option <code>newestOnTop</code> to show toasts in oldest or newest first order. toastr.options.newestOnTop = false; Fixed margins on full width toasts Added LESS file. Added min file for JS and CSS Added missing vendor prefixes in CSS. Various minor bug fixes. Added unit tests for new features. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.1.3.1.nuspec ================================================  toastr 1.3.1 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php https://github.com/CodeSeven/toastr http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo toastr is a Javascript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. v.1.3.1 Added new API for toastr.subscribe so you can be alerted when toasts appear and disappear. toastr.subscribe(function (args) { // args contains the toast options and data } Added support for glimpse.toastr.js plugin. https://github.com/johnpapa/glimpse.toastr Added toastId, state (visible/hidden), startTime and endTime to the toastr info response (available in the coneol, glimpse.toastr plugin, or via the subscribe callback). Fixed bug with stacking toasts when clear all toasts occurs first. v1.2.2 Added onFadeIn and onFadeOut callbacks. toastr.options.onFadeIn = function() { console.log('hello'); } Added option <code>newestOnTop</code> to show toasts in oldest or newest first order. toastr.options.newestOnTop = false; Fixed margins on full width toasts Added LESS file. Added min file for JS and CSS Added missing vendor prefixes in CSS. Various minor bug fixes. Added unit tests for new features. Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.2.0.0-rc1.nuspec ================================================  toastr 2.0.0-rc1 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php http://toastrjs.com/ http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo Toastr is a JavaScript library for non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. The following animations options have been deprecated and should be replaced: Replace options.fadeIn with options.showDuration Replace options.onFadeIn with options.onShown Replace options.fadeOut with options.hideDuration Replace options.onFadeOut with options.onHidden Optional 'close' button, bug fixes, and improved responsive design. For other changes, see http://toastrjs.com Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.2.0.1.nuspec ================================================  toastr 2.0.1 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php http://toastrjs.com/ http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo Toastr is a JavaScript library for non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. The following animations options have been deprecated and should be replaced: Replace options.fadeIn with options.showDuration Replace options.onFadeIn with options.onShown Replace options.fadeOut with options.hideDuration Replace options.onFadeOut with options.onHidden Optional 'close' button, bug fixes, and improved responsive design. For other changes, see http://toastrjs.com Copyright © 2012 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.2.0.2.nuspec ================================================  toastr 2.0.2 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php http://toastrjs.com/ http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo Toastr is a JavaScript library for non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Change log: https://github.com/CodeSeven/toastr/blob/master/CHANGELOG.md Copyright © 2012-2014 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: nuget/toastr.2.0.3.nuspec ================================================  toastr 2.0.3 toastr John Papa,Hans Fjällemark John Papa,Hans Fjällemark http://www.opensource.org/licenses/mit-license.php http://toastrjs.com/ http://johnpapa.net/wp-content/images/toastr-icon.png false 3 Easy Steps: (1) Link to toastr.css (2) Link to toastr.js (3) Use toastr to display a toast for info, success, warning or error // Display an info toast with no title toastr.info('Are you the 6 fingered man?') *** For other API calls, see the demo Toastr is a JavaScript library for non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended. Change log: https://github.com/CodeSeven/toastr/blob/master/CHANGELOG.md Copyright © 2012-2014 Hans Fjällemark & John Papa. en-US toastr, toast, notification, dialog, jquery ================================================ FILE: package.json ================================================ { "name": "toastr", "filename": "build/toastr.min.js", "main": "toastr.js", "style": "build/toastr.min.css", "version": "2.1.4", "description": "ToastrJS is a JavaScript library for Gnome / Growl type non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended.", "homepage": "http://www.toastrjs.com", "keywords": [ "Toastr", "ToastrJS", "toastr.js" ], "maintainers": [ { "name": "John Papa", "web": "http://www.johnpapa.net", "twitter": "@john_papa" }, { "name": "Tim Ferrell", "web": "https://twitter.com/ferrell_tim", "twitter": "@ferrell_tim" } ], "repository": { "type": "git", "url": "git://github.com/CodeSeven/toastr.git" }, "bugs": "http://stackoverflow.com/questions/tagged/toastr", "licenses": [ { "type": "MIT", "url": "http://www.opensource.org/licenses/mit-license.php" } ], "dependencies": { "jquery": ">=1.12.0" }, "devDependencies": { "gulp": "^3.8.10", "gulp-bytediff": "^0.2.0", "gulp-jscs": "^1.3.0", "gulp-jshint": "^1.9.0", "gulp-less": "^3.0.3", "gulp-load-plugins": "^0.7.1", "gulp-load-utils": "0.0.4", "gulp-minify-css": "^0.3.11", "gulp-rename": "^1.2.0", "gulp-sourcemaps": "^1.2.8", "gulp-task-listing": "^0.3.0", "gulp-uglify": "^1.0.1", "gulp-util": "^3.0.1", "jquery": ">=1.12.0", "jshint-stylish": "^1.0.0", "karma": "^1.7.0", "karma-coverage": "^1.1.1", "karma-phantomjs-launcher": "^1.0.4", "karma-qunit": "^0.1.3", "merge-stream": "^0.1.6", "phantomjs-prebuilt": "^2.1.14", "plato": "^1.2.2", "qunitjs": "~1.14.0" }, "scripts": { "test": "gulp test" } } ================================================ FILE: release checklist.md ================================================ Toastr Release Checklist 1. Update Toastr Version * toastr.js * bower.json (toastr-bower repo) * package.json * nuget versions and dependency versions * readme file for github repo * Consider HotTowel VSIX 2. Gulp * run main demo * `gulp analyze` * `gulp test` * `gulp` 3. Nuget * Copy new files in * Build * Test 4. CDNJS * Update CDNJS 5. Update Website with New Downloads 6. Publish Bower * Include License and Readme * Test Locally * Update Github repo toastr-bower * Github tag * Register with Bower 7. Publish Nugets 8. Release on Github * Tag with semver * Attach all artifacts 9. Blog post ================================================ FILE: tests/qunit/qunit.css ================================================ /** * QUnit v1.12.0 - A JavaScript Unit Testing Framework * * http://qunitjs.com * * Copyright 2012 jQuery Foundation and other contributors * Released under the MIT license. * http://jquery.org/license */ /** Font Family and Sizes */ #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; } #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } #qunit-tests { font-size: smaller; } /** Resets */ #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { margin: 0; padding: 0; } /** Header */ #qunit-header { padding: 0.5em 0 0.5em 1em; color: #8699a4; background-color: #0d3349; font-size: 1.5em; line-height: 1em; font-weight: normal; border-radius: 5px 5px 0 0; -moz-border-radius: 5px 5px 0 0; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px; } #qunit-header a { text-decoration: none; color: #c2ccd1; } #qunit-header a:hover, #qunit-header a:focus { color: #fff; } #qunit-testrunner-toolbar label { display: inline-block; padding: 0 .5em 0 .1em; } #qunit-banner { height: 5px; } #qunit-testrunner-toolbar { padding: 0.5em 0 0.5em 2em; color: #5E740B; background-color: #eee; overflow: hidden; } #qunit-userAgent { padding: 0.5em 0 0.5em 2.5em; background-color: #2b81af; color: #fff; text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; } #qunit-modulefilter-container { float: right; } /** Tests: Pass/Fail */ #qunit-tests { list-style-position: inside; } #qunit-tests li { padding: 0.4em 0.5em 0.4em 2.5em; border-bottom: 1px solid #fff; list-style-position: inside; } #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { display: none; } #qunit-tests li strong { cursor: pointer; } #qunit-tests li a { padding: 0.5em; color: #c2ccd1; text-decoration: none; } #qunit-tests li a:hover, #qunit-tests li a:focus { color: #000; } #qunit-tests li .runtime { float: right; font-size: smaller; } .qunit-assert-list { margin-top: 0.5em; padding: 0.5em; background-color: #fff; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; } .qunit-collapsed { display: none; } #qunit-tests table { border-collapse: collapse; margin-top: .2em; } #qunit-tests th { text-align: right; vertical-align: top; padding: 0 .5em 0 0; } #qunit-tests td { vertical-align: top; } #qunit-tests pre { margin: 0; white-space: pre-wrap; word-wrap: break-word; } #qunit-tests del { background-color: #e0f2be; color: #374e0c; text-decoration: none; } #qunit-tests ins { background-color: #ffcaca; color: #500; text-decoration: none; } /*** Test Counts */ #qunit-tests b.counts { color: black; } #qunit-tests b.passed { color: #5E740B; } #qunit-tests b.failed { color: #710909; } #qunit-tests li li { padding: 5px; background-color: #fff; border-bottom: none; list-style-position: inside; } /*** Passing Styles */ #qunit-tests li li.pass { color: #3c510c; background-color: #fff; border-left: 10px solid #C6E746; } #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } #qunit-tests .pass .test-name { color: #366097; } #qunit-tests .pass .test-actual, #qunit-tests .pass .test-expected { color: #999999; } #qunit-banner.qunit-pass { background-color: #C6E746; } /*** Failing Styles */ #qunit-tests li li.fail { color: #710909; background-color: #fff; border-left: 10px solid #EE5757; white-space: pre; } #qunit-tests > li:last-child { border-radius: 0 0 5px 5px; -moz-border-radius: 0 0 5px 5px; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px; } #qunit-tests .fail { color: #000000; background-color: #EE5757; } #qunit-tests .fail .test-name, #qunit-tests .fail .module-name { color: #000000; } #qunit-tests .fail .test-actual { color: #EE5757; } #qunit-tests .fail .test-expected { color: green; } #qunit-banner.qunit-fail { background-color: #EE5757; } /** Result */ #qunit-testresult { padding: 0.5em 0.5em 0.5em 2.5em; color: #2b81af; background-color: #D2E0E6; border-bottom: 1px solid white; } #qunit-testresult .module-name { font-weight: bold; } /** Fixture */ #qunit-fixture { position: absolute; top: -10000px; left: -10000px; width: 1000px; height: 1000px; } ================================================ FILE: tests/qunit/qunit.js ================================================ /** * QUnit v1.12.0 - A JavaScript Unit Testing Framework * * http://qunitjs.com * * Copyright 2013 jQuery Foundation and other contributors * Released under the MIT license. * https://jquery.org/license/ */ (function( window ) { var QUnit, assert, config, onErrorFnPrev, testId = 0, fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""), toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, // Keep a local reference to Date (GH-283) Date = window.Date, setTimeout = window.setTimeout, defined = { setTimeout: typeof window.setTimeout !== "undefined", sessionStorage: (function() { var x = "qunit-test-string"; try { sessionStorage.setItem( x, x ); sessionStorage.removeItem( x ); return true; } catch( e ) { return false; } }()) }, /** * Provides a normalized error string, correcting an issue * with IE 7 (and prior) where Error.prototype.toString is * not properly implemented * * Based on http://es5.github.com/#x15.11.4.4 * * @param {String|Error} error * @return {String} error message */ errorString = function( error ) { var name, message, errorString = error.toString(); if ( errorString.substring( 0, 7 ) === "[object" ) { name = error.name ? error.name.toString() : "Error"; message = error.message ? error.message.toString() : ""; if ( name && message ) { return name + ": " + message; } else if ( name ) { return name; } else if ( message ) { return message; } else { return "Error"; } } else { return errorString; } }, /** * Makes a clone of an object using only Array or Object as base, * and copies over the own enumerable properties. * * @param {Object} obj * @return {Object} New object with only the own properties (recursively). */ objectValues = function( obj ) { // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392. /*jshint newcap: false */ var key, val, vals = QUnit.is( "array", obj ) ? [] : {}; for ( key in obj ) { if ( hasOwn.call( obj, key ) ) { val = obj[key]; vals[key] = val === Object(val) ? objectValues(val) : val; } } return vals; }; function Test( settings ) { extend( this, settings ); this.assertions = []; this.testNumber = ++Test.count; } Test.count = 0; Test.prototype = { init: function() { var a, b, li, tests = id( "qunit-tests" ); if ( tests ) { b = document.createElement( "strong" ); b.innerHTML = this.nameHtml; // `a` initialized at top of scope a = document.createElement( "a" ); a.innerHTML = "Rerun"; a.href = QUnit.url({ testNumber: this.testNumber }); li = document.createElement( "li" ); li.appendChild( b ); li.appendChild( a ); li.className = "running"; li.id = this.id = "qunit-test-output" + testId++; tests.appendChild( li ); } }, setup: function() { if ( // Emit moduleStart when we're switching from one module to another this.module !== config.previousModule || // They could be equal (both undefined) but if the previousModule property doesn't // yet exist it means this is the first test in a suite that isn't wrapped in a // module, in which case we'll just emit a moduleStart event for 'undefined'. // Without this, reporters can get testStart before moduleStart which is a problem. !hasOwn.call( config, "previousModule" ) ) { if ( hasOwn.call( config, "previousModule" ) ) { runLoggingCallbacks( "moduleDone", QUnit, { name: config.previousModule, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, total: config.moduleStats.all }); } config.previousModule = this.module; config.moduleStats = { all: 0, bad: 0 }; runLoggingCallbacks( "moduleStart", QUnit, { name: this.module }); } config.current = this; this.testEnvironment = extend({ setup: function() {}, teardown: function() {} }, this.moduleTestEnvironment ); this.started = +new Date(); runLoggingCallbacks( "testStart", QUnit, { name: this.testName, module: this.module }); /*jshint camelcase:false */ /** * Expose the current test environment. * * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead. */ QUnit.current_testEnvironment = this.testEnvironment; /*jshint camelcase:true */ if ( !config.pollution ) { saveGlobal(); } if ( config.notrycatch ) { this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert ); return; } try { this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert ); } catch( e ) { QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) ); } }, run: function() { config.current = this; var running = id( "qunit-testresult" ); if ( running ) { running.innerHTML = "Running:
" + this.nameHtml; } if ( this.async ) { QUnit.stop(); } this.callbackStarted = +new Date(); if ( config.notrycatch ) { this.callback.call( this.testEnvironment, QUnit.assert ); this.callbackRuntime = +new Date() - this.callbackStarted; return; } try { this.callback.call( this.testEnvironment, QUnit.assert ); this.callbackRuntime = +new Date() - this.callbackStarted; } catch( e ) { this.callbackRuntime = +new Date() - this.callbackStarted; QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); // else next test will carry the responsibility saveGlobal(); // Restart the tests if they're blocking if ( config.blocking ) { QUnit.start(); } } }, teardown: function() { config.current = this; if ( config.notrycatch ) { if ( typeof this.callbackRuntime === "undefined" ) { this.callbackRuntime = +new Date() - this.callbackStarted; } this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert ); return; } else { try { this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert ); } catch( e ) { QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) ); } } checkPollution(); }, finish: function() { config.current = this; if ( config.requireExpects && this.expected === null ) { QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack ); } else if ( this.expected !== null && this.expected !== this.assertions.length ) { QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack ); } else if ( this.expected === null && !this.assertions.length ) { QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack ); } var i, assertion, a, b, time, li, ol, test = this, good = 0, bad = 0, tests = id( "qunit-tests" ); this.runtime = +new Date() - this.started; config.stats.all += this.assertions.length; config.moduleStats.all += this.assertions.length; if ( tests ) { ol = document.createElement( "ol" ); ol.className = "qunit-assert-list"; for ( i = 0; i < this.assertions.length; i++ ) { assertion = this.assertions[i]; li = document.createElement( "li" ); li.className = assertion.result ? "pass" : "fail"; li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" ); ol.appendChild( li ); if ( assertion.result ) { good++; } else { bad++; config.stats.bad++; config.moduleStats.bad++; } } // store result when possible if ( QUnit.config.reorder && defined.sessionStorage ) { if ( bad ) { sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad ); } else { sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName ); } } if ( bad === 0 ) { addClass( ol, "qunit-collapsed" ); } // `b` initialized at top of scope b = document.createElement( "strong" ); b.innerHTML = this.nameHtml + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; addEvent(b, "click", function() { var next = b.parentNode.lastChild, collapsed = hasClass( next, "qunit-collapsed" ); ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" ); }); addEvent(b, "dblclick", function( e ) { var target = e && e.target ? e.target : window.event.srcElement; if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) { target = target.parentNode; } if ( window.location && target.nodeName.toLowerCase() === "strong" ) { window.location = QUnit.url({ testNumber: test.testNumber }); } }); // `time` initialized at top of scope time = document.createElement( "span" ); time.className = "runtime"; time.innerHTML = this.runtime + " ms"; // `li` initialized at top of scope li = id( this.id ); li.className = bad ? "fail" : "pass"; li.removeChild( li.firstChild ); a = li.firstChild; li.appendChild( b ); li.appendChild( a ); li.appendChild( time ); li.appendChild( ol ); } else { for ( i = 0; i < this.assertions.length; i++ ) { if ( !this.assertions[i].result ) { bad++; config.stats.bad++; config.moduleStats.bad++; } } } runLoggingCallbacks( "testDone", QUnit, { name: this.testName, module: this.module, failed: bad, passed: this.assertions.length - bad, total: this.assertions.length, duration: this.runtime }); QUnit.reset(); config.current = undefined; }, queue: function() { var bad, test = this; synchronize(function() { test.init(); }); function run() { // each of these can by async synchronize(function() { test.setup(); }); synchronize(function() { test.run(); }); synchronize(function() { test.teardown(); }); synchronize(function() { test.finish(); }); } // `bad` initialized at top of scope // defer when previous test run passed, if storage is available bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName ); if ( bad ) { run(); } else { synchronize( run, true ); } } }; // Root QUnit object. // `QUnit` initialized at top of scope QUnit = { // call on start of module test to prepend name to all tests module: function( name, testEnvironment ) { config.currentModule = name; config.currentModuleTestEnvironment = testEnvironment; config.modules[name] = true; }, asyncTest: function( testName, expected, callback ) { if ( arguments.length === 2 ) { callback = expected; expected = null; } QUnit.test( testName, expected, callback, true ); }, test: function( testName, expected, callback, async ) { var test, nameHtml = "" + escapeText( testName ) + ""; if ( arguments.length === 2 ) { callback = expected; expected = null; } if ( config.currentModule ) { nameHtml = "" + escapeText( config.currentModule ) + ": " + nameHtml; } test = new Test({ nameHtml: nameHtml, testName: testName, expected: expected, async: async, callback: callback, module: config.currentModule, moduleTestEnvironment: config.currentModuleTestEnvironment, stack: sourceFromStacktrace( 2 ) }); if ( !validTest( test ) ) { return; } test.queue(); }, // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through. expect: function( asserts ) { if (arguments.length === 1) { config.current.expected = asserts; } else { return config.current.expected; } }, start: function( count ) { // QUnit hasn't been initialized yet. // Note: RequireJS (et al) may delay onLoad if ( config.semaphore === undefined ) { QUnit.begin(function() { // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first setTimeout(function() { QUnit.start( count ); }); }); return; } config.semaphore -= count || 1; // don't start until equal number of stop-calls if ( config.semaphore > 0 ) { return; } // ignore if start is called more often then stop if ( config.semaphore < 0 ) { config.semaphore = 0; QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) ); return; } // A slight delay, to avoid any current callbacks if ( defined.setTimeout ) { setTimeout(function() { if ( config.semaphore > 0 ) { return; } if ( config.timeout ) { clearTimeout( config.timeout ); } config.blocking = false; process( true ); }, 13); } else { config.blocking = false; process( true ); } }, stop: function( count ) { config.semaphore += count || 1; config.blocking = true; if ( config.testTimeout && defined.setTimeout ) { clearTimeout( config.timeout ); config.timeout = setTimeout(function() { QUnit.ok( false, "Test timed out" ); config.semaphore = 1; QUnit.start(); }, config.testTimeout ); } } }; // `assert` initialized at top of scope // Assert helpers // All of these must either call QUnit.push() or manually do: // - runLoggingCallbacks( "log", .. ); // - config.current.assertions.push({ .. }); // We attach it to the QUnit object *after* we expose the public API, // otherwise `assert` will become a global variable in browsers (#341). assert = { /** * Asserts rough true-ish result. * @name ok * @function * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); */ ok: function( result, msg ) { if ( !config.current ) { throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) ); } result = !!result; msg = msg || (result ? "okay" : "failed" ); var source, details = { module: config.current.module, name: config.current.testName, result: result, message: msg }; msg = "" + escapeText( msg ) + ""; if ( !result ) { source = sourceFromStacktrace( 2 ); if ( source ) { details.source = source; msg += "
Source:
" + escapeText( source ) + "
"; } } runLoggingCallbacks( "log", QUnit, details ); config.current.assertions.push({ result: result, message: msg }); }, /** * Assert that the first two arguments are equal, with an optional message. * Prints out both actual and expected values. * @name equal * @function * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); */ equal: function( actual, expected, message ) { /*jshint eqeqeq:false */ QUnit.push( expected == actual, actual, expected, message ); }, /** * @name notEqual * @function */ notEqual: function( actual, expected, message ) { /*jshint eqeqeq:false */ QUnit.push( expected != actual, actual, expected, message ); }, /** * @name propEqual * @function */ propEqual: function( actual, expected, message ) { actual = objectValues(actual); expected = objectValues(expected); QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); }, /** * @name notPropEqual * @function */ notPropEqual: function( actual, expected, message ) { actual = objectValues(actual); expected = objectValues(expected); QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); }, /** * @name deepEqual * @function */ deepEqual: function( actual, expected, message ) { QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); }, /** * @name notDeepEqual * @function */ notDeepEqual: function( actual, expected, message ) { QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); }, /** * @name strictEqual * @function */ strictEqual: function( actual, expected, message ) { QUnit.push( expected === actual, actual, expected, message ); }, /** * @name notStrictEqual * @function */ notStrictEqual: function( actual, expected, message ) { QUnit.push( expected !== actual, actual, expected, message ); }, "throws": function( block, expected, message ) { var actual, expectedOutput = expected, ok = false; // 'expected' is optional if ( typeof expected === "string" ) { message = expected; expected = null; } config.current.ignoreGlobalErrors = true; try { block.call( config.current.testEnvironment ); } catch (e) { actual = e; } config.current.ignoreGlobalErrors = false; if ( actual ) { // we don't want to validate thrown error if ( !expected ) { ok = true; expectedOutput = null; // expected is a regexp } else if ( QUnit.objectType( expected ) === "regexp" ) { ok = expected.test( errorString( actual ) ); // expected is a constructor } else if ( actual instanceof expected ) { ok = true; // expected is a validation function which returns true is validation passed } else if ( expected.call( {}, actual ) === true ) { expectedOutput = null; ok = true; } QUnit.push( ok, actual, expectedOutput, message ); } else { QUnit.pushFailure( message, null, "No exception was thrown." ); } } }; /** * @deprecated since 1.8.0 * Kept assertion helpers in root for backwards compatibility. */ extend( QUnit, assert ); /** * @deprecated since 1.9.0 * Kept root "raises()" for backwards compatibility. * (Note that we don't introduce assert.raises). */ QUnit.raises = assert[ "throws" ]; /** * @deprecated since 1.0.0, replaced with error pushes since 1.3.0 * Kept to avoid TypeErrors for undefined methods. */ QUnit.equals = function() { QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" ); }; QUnit.same = function() { QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" ); }; // We want access to the constructor's prototype (function() { function F() {} F.prototype = QUnit; QUnit = new F(); // Make F QUnit's constructor so that we can add to the prototype later QUnit.constructor = F; }()); /** * Config object: Maintain internal state * Later exposed as QUnit.config * `config` initialized at top of scope */ config = { // The queue of tests to run queue: [], // block until document ready blocking: true, // when enabled, show only failing tests // gets persisted through sessionStorage and can be changed in UI via checkbox hidepassed: false, // by default, run previously failed tests first // very useful in combination with "Hide passed tests" checked reorder: true, // by default, modify document.title when suite is done altertitle: true, // when enabled, all tests must call expect() requireExpects: false, // add checkboxes that are persisted in the query-string // when enabled, the id is set to `true` as a `QUnit.config` property urlConfig: [ { id: "noglobals", label: "Check for Globals", tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings." }, { id: "notrycatch", label: "No try-catch", tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings." } ], // Set of all modules. modules: {}, // logging callback queues begin: [], done: [], log: [], testStart: [], testDone: [], moduleStart: [], moduleDone: [] }; // Export global variables, unless an 'exports' object exists, // in that case we assume we're in CommonJS (dealt with on the bottom of the script) if ( typeof exports === "undefined" ) { extend( window, QUnit.constructor.prototype ); // Expose QUnit object window.QUnit = QUnit; } // Initialize more QUnit.config and QUnit.urlParams (function() { var i, location = window.location || { search: "", protocol: "file:" }, params = location.search.slice( 1 ).split( "&" ), length = params.length, urlParams = {}, current; if ( params[ 0 ] ) { for ( i = 0; i < length; i++ ) { current = params[ i ].split( "=" ); current[ 0 ] = decodeURIComponent( current[ 0 ] ); // allow just a key to turn on a flag, e.g., test.html?noglobals current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; urlParams[ current[ 0 ] ] = current[ 1 ]; } } QUnit.urlParams = urlParams; // String search anywhere in moduleName+testName config.filter = urlParams.filter; // Exact match of the module name config.module = urlParams.module; config.testNumber = parseInt( urlParams.testNumber, 10 ) || null; // Figure out if we're running the tests from a server or not QUnit.isLocal = location.protocol === "file:"; }()); // Extend QUnit object, // these after set here because they should not be exposed as global functions extend( QUnit, { assert: assert, config: config, // Initialize the configuration options init: function() { extend( config, { stats: { all: 0, bad: 0 }, moduleStats: { all: 0, bad: 0 }, started: +new Date(), updateRate: 1000, blocking: false, autostart: true, autorun: false, filter: "", queue: [], semaphore: 1 }); var tests, banner, result, qunit = id( "qunit" ); if ( qunit ) { qunit.innerHTML = "

" + escapeText( document.title ) + "

" + "

" + "
" + "

" + "
    "; } tests = id( "qunit-tests" ); banner = id( "qunit-banner" ); result = id( "qunit-testresult" ); if ( tests ) { tests.innerHTML = ""; } if ( banner ) { banner.className = ""; } if ( result ) { result.parentNode.removeChild( result ); } if ( tests ) { result = document.createElement( "p" ); result.id = "qunit-testresult"; result.className = "result"; tests.parentNode.insertBefore( result, tests ); result.innerHTML = "Running...
     "; } }, // Resets the test setup. Useful for tests that modify the DOM. /* DEPRECATED: Use multiple tests instead of resetting inside a test. Use testStart or testDone for custom cleanup. This method will throw an error in 2.0, and will be removed in 2.1 */ reset: function() { var fixture = id( "qunit-fixture" ); if ( fixture ) { fixture.innerHTML = config.fixture; } }, // Trigger an event on an element. // @example triggerEvent( document.body, "click" ); triggerEvent: function( elem, type, event ) { if ( document.createEvent ) { event = document.createEvent( "MouseEvents" ); event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); elem.dispatchEvent( event ); } else if ( elem.fireEvent ) { elem.fireEvent( "on" + type ); } }, // Safe object type checking is: function( type, obj ) { return QUnit.objectType( obj ) === type; }, objectType: function( obj ) { if ( typeof obj === "undefined" ) { return "undefined"; // consider: typeof null === object } if ( obj === null ) { return "null"; } var match = toString.call( obj ).match(/^\[object\s(.*)\]$/), type = match && match[1] || ""; switch ( type ) { case "Number": if ( isNaN(obj) ) { return "nan"; } return "number"; case "String": case "Boolean": case "Array": case "Date": case "RegExp": case "Function": return type.toLowerCase(); } if ( typeof obj === "object" ) { return "object"; } return undefined; }, push: function( result, actual, expected, message ) { if ( !config.current ) { throw new Error( "assertion outside test context, was " + sourceFromStacktrace() ); } var output, source, details = { module: config.current.module, name: config.current.testName, result: result, message: message, actual: actual, expected: expected }; message = escapeText( message ) || ( result ? "okay" : "failed" ); message = "" + message + ""; output = message; if ( !result ) { expected = escapeText( QUnit.jsDump.parse(expected) ); actual = escapeText( QUnit.jsDump.parse(actual) ); output += ""; if ( actual !== expected ) { output += ""; output += ""; } source = sourceFromStacktrace(); if ( source ) { details.source = source; output += ""; } output += "
    Expected:
    " + expected + "
    Result:
    " + actual + "
    Diff:
    " + QUnit.diff( expected, actual ) + "
    Source:
    " + escapeText( source ) + "
    "; } runLoggingCallbacks( "log", QUnit, details ); config.current.assertions.push({ result: !!result, message: output }); }, pushFailure: function( message, source, actual ) { if ( !config.current ) { throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) ); } var output, details = { module: config.current.module, name: config.current.testName, result: false, message: message }; message = escapeText( message ) || "error"; message = "" + message + ""; output = message; output += ""; if ( actual ) { output += ""; } if ( source ) { details.source = source; output += ""; } output += "
    Result:
    " + escapeText( actual ) + "
    Source:
    " + escapeText( source ) + "
    "; runLoggingCallbacks( "log", QUnit, details ); config.current.assertions.push({ result: false, message: output }); }, url: function( params ) { params = extend( extend( {}, QUnit.urlParams ), params ); var key, querystring = "?"; for ( key in params ) { if ( hasOwn.call( params, key ) ) { querystring += encodeURIComponent( key ) + "=" + encodeURIComponent( params[ key ] ) + "&"; } } return window.location.protocol + "//" + window.location.host + window.location.pathname + querystring.slice( 0, -1 ); }, extend: extend, id: id, addEvent: addEvent, addClass: addClass, hasClass: hasClass, removeClass: removeClass // load, equiv, jsDump, diff: Attached later }); /** * @deprecated: Created for backwards compatibility with test runner that set the hook function * into QUnit.{hook}, instead of invoking it and passing the hook function. * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here. * Doing this allows us to tell if the following methods have been overwritten on the actual * QUnit object. */ extend( QUnit.constructor.prototype, { // Logging callbacks; all receive a single argument with the listed properties // run test/logs.html for any related changes begin: registerLoggingCallback( "begin" ), // done: { failed, passed, total, runtime } done: registerLoggingCallback( "done" ), // log: { result, actual, expected, message } log: registerLoggingCallback( "log" ), // testStart: { name } testStart: registerLoggingCallback( "testStart" ), // testDone: { name, failed, passed, total, duration } testDone: registerLoggingCallback( "testDone" ), // moduleStart: { name } moduleStart: registerLoggingCallback( "moduleStart" ), // moduleDone: { name, failed, passed, total } moduleDone: registerLoggingCallback( "moduleDone" ) }); if ( typeof document === "undefined" || document.readyState === "complete" ) { config.autorun = true; } QUnit.load = function() { runLoggingCallbacks( "begin", QUnit, {} ); // Initialize the config, saving the execution queue var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter, numModules = 0, moduleNames = [], moduleFilterHtml = "", urlConfigHtml = "", oldconfig = extend( {}, config ); QUnit.init(); extend(config, oldconfig); config.blocking = false; len = config.urlConfig.length; for ( i = 0; i < len; i++ ) { val = config.urlConfig[i]; if ( typeof val === "string" ) { val = { id: val, label: val, tooltip: "[no tooltip available]" }; } config[ val.id ] = QUnit.urlParams[ val.id ]; urlConfigHtml += ""; } for ( i in config.modules ) { if ( config.modules.hasOwnProperty( i ) ) { moduleNames.push(i); } } numModules = moduleNames.length; moduleNames.sort( function( a, b ) { return a.localeCompare( b ); }); moduleFilterHtml += ""; // `userAgent` initialized at top of scope userAgent = id( "qunit-userAgent" ); if ( userAgent ) { userAgent.innerHTML = navigator.userAgent; } // `banner` initialized at top of scope banner = id( "qunit-header" ); if ( banner ) { banner.innerHTML = "" + banner.innerHTML + " "; } // `toolbar` initialized at top of scope toolbar = id( "qunit-testrunner-toolbar" ); if ( toolbar ) { // `filter` initialized at top of scope filter = document.createElement( "input" ); filter.type = "checkbox"; filter.id = "qunit-filter-pass"; addEvent( filter, "click", function() { var tmp, ol = document.getElementById( "qunit-tests" ); if ( filter.checked ) { ol.className = ol.className + " hidepass"; } else { tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; ol.className = tmp.replace( / hidepass /, " " ); } if ( defined.sessionStorage ) { if (filter.checked) { sessionStorage.setItem( "qunit-filter-passed-tests", "true" ); } else { sessionStorage.removeItem( "qunit-filter-passed-tests" ); } } }); if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) { filter.checked = true; // `ol` initialized at top of scope ol = document.getElementById( "qunit-tests" ); ol.className = ol.className + " hidepass"; } toolbar.appendChild( filter ); // `label` initialized at top of scope label = document.createElement( "label" ); label.setAttribute( "for", "qunit-filter-pass" ); label.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." ); label.innerHTML = "Hide passed tests"; toolbar.appendChild( label ); urlConfigCheckboxesContainer = document.createElement("span"); urlConfigCheckboxesContainer.innerHTML = urlConfigHtml; urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input"); // For oldIE support: // * Add handlers to the individual elements instead of the container // * Use "click" instead of "change" // * Fallback from event.target to event.srcElement addEvents( urlConfigCheckboxes, "click", function( event ) { var params = {}, target = event.target || event.srcElement; params[ target.name ] = target.checked ? true : undefined; window.location = QUnit.url( params ); }); toolbar.appendChild( urlConfigCheckboxesContainer ); if (numModules > 1) { moduleFilter = document.createElement( "span" ); moduleFilter.setAttribute( "id", "qunit-modulefilter-container" ); moduleFilter.innerHTML = moduleFilterHtml; addEvent( moduleFilter.lastChild, "change", function() { var selectBox = moduleFilter.getElementsByTagName("select")[0], selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value); window.location = QUnit.url({ module: ( selectedModule === "" ) ? undefined : selectedModule, // Remove any existing filters filter: undefined, testNumber: undefined }); }); toolbar.appendChild(moduleFilter); } } // `main` initialized at top of scope main = id( "qunit-fixture" ); if ( main ) { config.fixture = main.innerHTML; } if ( config.autostart ) { QUnit.start(); } }; addEvent( window, "load", QUnit.load ); // `onErrorFnPrev` initialized at top of scope // Preserve other handlers onErrorFnPrev = window.onerror; // Cover uncaught exceptions // Returning true will suppress the default browser handler, // returning false will let it run. window.onerror = function ( error, filePath, linerNr ) { var ret = false; if ( onErrorFnPrev ) { ret = onErrorFnPrev( error, filePath, linerNr ); } // Treat return value as window.onerror itself does, // Only do our handling if not suppressed. if ( ret !== true ) { if ( QUnit.config.current ) { if ( QUnit.config.current.ignoreGlobalErrors ) { return true; } QUnit.pushFailure( error, filePath + ":" + linerNr ); } else { QUnit.test( "global failure", extend( function() { QUnit.pushFailure( error, filePath + ":" + linerNr ); }, { validTest: validTest } ) ); } return false; } return ret; }; function done() { config.autorun = true; // Log the last module results if ( config.currentModule ) { runLoggingCallbacks( "moduleDone", QUnit, { name: config.currentModule, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, total: config.moduleStats.all }); } delete config.previousModule; var i, key, banner = id( "qunit-banner" ), tests = id( "qunit-tests" ), runtime = +new Date() - config.started, passed = config.stats.all - config.stats.bad, html = [ "Tests completed in ", runtime, " milliseconds.
    ", "", passed, " assertions of ", config.stats.all, " passed, ", config.stats.bad, " failed." ].join( "" ); if ( banner ) { banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" ); } if ( tests ) { id( "qunit-testresult" ).innerHTML = html; } if ( config.altertitle && typeof document !== "undefined" && document.title ) { // show ✖ for good, ✔ for bad suite result in title // use escape sequences in case file gets loaded with non-utf-8-charset document.title = [ ( config.stats.bad ? "\u2716" : "\u2714" ), document.title.replace( /^[\u2714\u2716] /i, "" ) ].join( " " ); } // clear own sessionStorage items if all tests passed if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) { // `key` & `i` initialized at top of scope for ( i = 0; i < sessionStorage.length; i++ ) { key = sessionStorage.key( i++ ); if ( key.indexOf( "qunit-test-" ) === 0 ) { sessionStorage.removeItem( key ); } } } // scroll back to top to show results if ( window.scrollTo ) { window.scrollTo(0, 0); } runLoggingCallbacks( "done", QUnit, { failed: config.stats.bad, passed: passed, total: config.stats.all, runtime: runtime }); } /** @return Boolean: true if this test should be ran */ function validTest( test ) { var include, filter = config.filter && config.filter.toLowerCase(), module = config.module && config.module.toLowerCase(), fullName = (test.module + ": " + test.testName).toLowerCase(); // Internally-generated tests are always valid if ( test.callback && test.callback.validTest === validTest ) { delete test.callback.validTest; return true; } if ( config.testNumber ) { return test.testNumber === config.testNumber; } if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) { return false; } if ( !filter ) { return true; } include = filter.charAt( 0 ) !== "!"; if ( !include ) { filter = filter.slice( 1 ); } // If the filter matches, we need to honour include if ( fullName.indexOf( filter ) !== -1 ) { return include; } // Otherwise, do the opposite return !include; } // so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions) // Later Safari and IE10 are supposed to support error.stack as well // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack function extractStacktrace( e, offset ) { offset = offset === undefined ? 3 : offset; var stack, include, i; if ( e.stacktrace ) { // Opera return e.stacktrace.split( "\n" )[ offset + 3 ]; } else if ( e.stack ) { // Firefox, Chrome stack = e.stack.split( "\n" ); if (/^error$/i.test( stack[0] ) ) { stack.shift(); } if ( fileName ) { include = []; for ( i = offset; i < stack.length; i++ ) { if ( stack[ i ].indexOf( fileName ) !== -1 ) { break; } include.push( stack[ i ] ); } if ( include.length ) { return include.join( "\n" ); } } return stack[ offset ]; } else if ( e.sourceURL ) { // Safari, PhantomJS // hopefully one day Safari provides actual stacktraces // exclude useless self-reference for generated Error objects if ( /qunit.js$/.test( e.sourceURL ) ) { return; } // for actual exceptions, this is useful return e.sourceURL + ":" + e.line; } } function sourceFromStacktrace( offset ) { try { throw new Error(); } catch ( e ) { return extractStacktrace( e, offset ); } } /** * Escape text for attribute or text content. */ function escapeText( s ) { if ( !s ) { return ""; } s = s + ""; // Both single quotes and double quotes (for attributes) return s.replace( /['"<>&]/g, function( s ) { switch( s ) { case "'": return "'"; case "\"": return """; case "<": return "<"; case ">": return ">"; case "&": return "&"; } }); } function synchronize( callback, last ) { config.queue.push( callback ); if ( config.autorun && !config.blocking ) { process( last ); } } function process( last ) { function next() { process( last ); } var start = new Date().getTime(); config.depth = config.depth ? config.depth + 1 : 1; while ( config.queue.length && !config.blocking ) { if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) { config.queue.shift()(); } else { setTimeout( next, 13 ); break; } } config.depth--; if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { done(); } } function saveGlobal() { config.pollution = []; if ( config.noglobals ) { for ( var key in window ) { if ( hasOwn.call( window, key ) ) { // in Opera sometimes DOM element ids show up here, ignore them if ( /^qunit-test-output/.test( key ) ) { continue; } config.pollution.push( key ); } } } } function checkPollution() { var newGlobals, deletedGlobals, old = config.pollution; saveGlobal(); newGlobals = diff( config.pollution, old ); if ( newGlobals.length > 0 ) { QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") ); } deletedGlobals = diff( old, config.pollution ); if ( deletedGlobals.length > 0 ) { QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") ); } } // returns a new Array with the elements that are in a but not in b function diff( a, b ) { var i, j, result = a.slice(); for ( i = 0; i < result.length; i++ ) { for ( j = 0; j < b.length; j++ ) { if ( result[i] === b[j] ) { result.splice( i, 1 ); i--; break; } } } return result; } function extend( a, b ) { for ( var prop in b ) { if ( hasOwn.call( b, prop ) ) { // Avoid "Member not found" error in IE8 caused by messing with window.constructor if ( !( prop === "constructor" && a === window ) ) { if ( b[ prop ] === undefined ) { delete a[ prop ]; } else { a[ prop ] = b[ prop ]; } } } } return a; } /** * @param {HTMLElement} elem * @param {string} type * @param {Function} fn */ function addEvent( elem, type, fn ) { // Standards-based browsers if ( elem.addEventListener ) { elem.addEventListener( type, fn, false ); // IE } else { elem.attachEvent( "on" + type, fn ); } } /** * @param {Array|NodeList} elems * @param {string} type * @param {Function} fn */ function addEvents( elems, type, fn ) { var i = elems.length; while ( i-- ) { addEvent( elems[i], type, fn ); } } function hasClass( elem, name ) { return (" " + elem.className + " ").indexOf(" " + name + " ") > -1; } function addClass( elem, name ) { if ( !hasClass( elem, name ) ) { elem.className += (elem.className ? " " : "") + name; } } function removeClass( elem, name ) { var set = " " + elem.className + " "; // Class name may appear multiple times while ( set.indexOf(" " + name + " ") > -1 ) { set = set.replace(" " + name + " " , " "); } // If possible, trim it for prettiness, but not necessarily elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, ""); } function id( name ) { return !!( typeof document !== "undefined" && document && document.getElementById ) && document.getElementById( name ); } function registerLoggingCallback( key ) { return function( callback ) { config[key].push( callback ); }; } // Supports deprecated method of completely overwriting logging callbacks function runLoggingCallbacks( key, scope, args ) { var i, callbacks; if ( QUnit.hasOwnProperty( key ) ) { QUnit[ key ].call(scope, args ); } else { callbacks = config[ key ]; for ( i = 0; i < callbacks.length; i++ ) { callbacks[ i ].call( scope, args ); } } } // Test for equality any JavaScript type. // Author: Philippe Rathé QUnit.equiv = (function() { // Call the o related callback with the given arguments. function bindCallbacks( o, callbacks, args ) { var prop = QUnit.objectType( o ); if ( prop ) { if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) { return callbacks[ prop ].apply( callbacks, args ); } else { return callbacks[ prop ]; // or undefined } } } // the real equiv function var innerEquiv, // stack to decide between skip/abort functions callers = [], // stack to avoiding loops from circular referencing parents = [], parentsB = [], getProto = Object.getPrototypeOf || function ( obj ) { /*jshint camelcase:false */ return obj.__proto__; }, callbacks = (function () { // for string, boolean, number and null function useStrictEquality( b, a ) { /*jshint eqeqeq:false */ if ( b instanceof a.constructor || a instanceof b.constructor ) { // to catch short annotation VS 'new' annotation of a // declaration // e.g. var i = 1; // var j = new Number(1); return a == b; } else { return a === b; } } return { "string": useStrictEquality, "boolean": useStrictEquality, "number": useStrictEquality, "null": useStrictEquality, "undefined": useStrictEquality, "nan": function( b ) { return isNaN( b ); }, "date": function( b, a ) { return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf(); }, "regexp": function( b, a ) { return QUnit.objectType( b ) === "regexp" && // the regex itself a.source === b.source && // and its modifiers a.global === b.global && // (gmi) ... a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.sticky === b.sticky; }, // - skip when the property is a method of an instance (OOP) // - abort otherwise, // initial === would have catch identical references anyway "function": function() { var caller = callers[callers.length - 1]; return caller !== Object && typeof caller !== "undefined"; }, "array": function( b, a ) { var i, j, len, loop, aCircular, bCircular; // b could be an object literal here if ( QUnit.objectType( b ) !== "array" ) { return false; } len = a.length; if ( len !== b.length ) { // safe and faster return false; } // track reference to avoid circular references parents.push( a ); parentsB.push( b ); for ( i = 0; i < len; i++ ) { loop = false; for ( j = 0; j < parents.length; j++ ) { aCircular = parents[j] === a[i]; bCircular = parentsB[j] === b[i]; if ( aCircular || bCircular ) { if ( a[i] === b[i] || aCircular && bCircular ) { loop = true; } else { parents.pop(); parentsB.pop(); return false; } } } if ( !loop && !innerEquiv(a[i], b[i]) ) { parents.pop(); parentsB.pop(); return false; } } parents.pop(); parentsB.pop(); return true; }, "object": function( b, a ) { /*jshint forin:false */ var i, j, loop, aCircular, bCircular, // Default to true eq = true, aProperties = [], bProperties = []; // comparing constructors is more strict than using // instanceof if ( a.constructor !== b.constructor ) { // Allow objects with no prototype to be equivalent to // objects with Object as their constructor. if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) || ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) { return false; } } // stack constructor before traversing properties callers.push( a.constructor ); // track reference to avoid circular references parents.push( a ); parentsB.push( b ); // be strict: don't ensure hasOwnProperty and go deep for ( i in a ) { loop = false; for ( j = 0; j < parents.length; j++ ) { aCircular = parents[j] === a[i]; bCircular = parentsB[j] === b[i]; if ( aCircular || bCircular ) { if ( a[i] === b[i] || aCircular && bCircular ) { loop = true; } else { eq = false; break; } } } aProperties.push(i); if ( !loop && !innerEquiv(a[i], b[i]) ) { eq = false; break; } } parents.pop(); parentsB.pop(); callers.pop(); // unstack, we are done for ( i in b ) { bProperties.push( i ); // collect b's properties } // Ensures identical properties name return eq && innerEquiv( aProperties.sort(), bProperties.sort() ); } }; }()); innerEquiv = function() { // can take multiple arguments var args = [].slice.apply( arguments ); if ( args.length < 2 ) { return true; // end transition } return (function( a, b ) { if ( a === b ) { return true; // catch the most you can } else if ( a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b) ) { return false; // don't lose time with error prone cases } else { return bindCallbacks(a, callbacks, [ b, a ]); } // apply transition with (1..n) arguments }( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) ); }; return innerEquiv; }()); /** * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | * http://flesler.blogspot.com Licensed under BSD * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008 * * @projectDescription Advanced and extensible data dumping for Javascript. * @version 1.0.0 * @author Ariel Flesler * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} */ QUnit.jsDump = (function() { function quote( str ) { return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\""; } function literal( o ) { return o + ""; } function join( pre, arr, post ) { var s = jsDump.separator(), base = jsDump.indent(), inner = jsDump.indent(1); if ( arr.join ) { arr = arr.join( "," + s + inner ); } if ( !arr ) { return pre + post; } return [ pre, inner + arr, base + post ].join(s); } function array( arr, stack ) { var i = arr.length, ret = new Array(i); this.up(); while ( i-- ) { ret[i] = this.parse( arr[i] , undefined , stack); } this.down(); return join( "[", ret, "]" ); } var reName = /^function (\w+)/, jsDump = { // type is used mostly internally, you can fix a (custom)type in advance parse: function( obj, type, stack ) { stack = stack || [ ]; var inStack, res, parser = this.parsers[ type || this.typeOf(obj) ]; type = typeof parser; inStack = inArray( obj, stack ); if ( inStack !== -1 ) { return "recursion(" + (inStack - stack.length) + ")"; } if ( type === "function" ) { stack.push( obj ); res = parser.call( this, obj, stack ); stack.pop(); return res; } return ( type === "string" ) ? parser : this.parsers.error; }, typeOf: function( obj ) { var type; if ( obj === null ) { type = "null"; } else if ( typeof obj === "undefined" ) { type = "undefined"; } else if ( QUnit.is( "regexp", obj) ) { type = "regexp"; } else if ( QUnit.is( "date", obj) ) { type = "date"; } else if ( QUnit.is( "function", obj) ) { type = "function"; } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) { type = "window"; } else if ( obj.nodeType === 9 ) { type = "document"; } else if ( obj.nodeType ) { type = "node"; } else if ( // native arrays toString.call( obj ) === "[object Array]" || // NodeList objects ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) ) ) { type = "array"; } else if ( obj.constructor === Error.prototype.constructor ) { type = "error"; } else { type = typeof obj; } return type; }, separator: function() { return this.multiline ? this.HTML ? "
    " : "\n" : this.HTML ? " " : " "; }, // extra can be a number, shortcut for increasing-calling-decreasing indent: function( extra ) { if ( !this.multiline ) { return ""; } var chr = this.indentChar; if ( this.HTML ) { chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); } return new Array( this.depth + ( extra || 0 ) ).join(chr); }, up: function( a ) { this.depth += a || 1; }, down: function( a ) { this.depth -= a || 1; }, setParser: function( name, parser ) { this.parsers[name] = parser; }, // The next 3 are exposed so you can use them quote: quote, literal: literal, join: join, // depth: 1, // This is the list of parsers, to modify them, use jsDump.setParser parsers: { window: "[Window]", document: "[Document]", error: function(error) { return "Error(\"" + error.message + "\")"; }, unknown: "[Unknown]", "null": "null", "undefined": "undefined", "function": function( fn ) { var ret = "function", // functions never have name in IE name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1]; if ( name ) { ret += " " + name; } ret += "( "; ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" ); return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" ); }, array: array, nodelist: array, "arguments": array, object: function( map, stack ) { /*jshint forin:false */ var ret = [ ], keys, key, val, i; QUnit.jsDump.up(); keys = []; for ( key in map ) { keys.push( key ); } keys.sort(); for ( i = 0; i < keys.length; i++ ) { key = keys[ i ]; val = map[ key ]; ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) ); } QUnit.jsDump.down(); return join( "{", ret, "}" ); }, node: function( node ) { var len, i, val, open = QUnit.jsDump.HTML ? "<" : "<", close = QUnit.jsDump.HTML ? ">" : ">", tag = node.nodeName.toLowerCase(), ret = open + tag, attrs = node.attributes; if ( attrs ) { for ( i = 0, len = attrs.length; i < len; i++ ) { val = attrs[i].nodeValue; // IE6 includes all attributes in .attributes, even ones not explicitly set. // Those have values like undefined, null, 0, false, "" or "inherit". if ( val && val !== "inherit" ) { ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" ); } } } ret += close; // Show content of TextNode or CDATASection if ( node.nodeType === 3 || node.nodeType === 4 ) { ret += node.nodeValue; } return ret + open + "/" + tag + close; }, // function calls it internally, it's the arguments part of the function functionArgs: function( fn ) { var args, l = fn.length; if ( !l ) { return ""; } args = new Array(l); while ( l-- ) { // 97 is 'a' args[l] = String.fromCharCode(97+l); } return " " + args.join( ", " ) + " "; }, // object calls it internally, the key part of an item in a map key: quote, // function calls it internally, it's the content of the function functionCode: "[code]", // node calls it internally, it's an html attribute value attribute: quote, string: quote, date: quote, regexp: literal, number: literal, "boolean": literal }, // if true, entities are escaped ( <, >, \t, space and \n ) HTML: false, // indentation unit indentChar: " ", // if true, items in a collection, are separated by a \n, else just a space. multiline: true }; return jsDump; }()); // from jquery.js function inArray( elem, array ) { if ( array.indexOf ) { return array.indexOf( elem ); } for ( var i = 0, length = array.length; i < length; i++ ) { if ( array[ i ] === elem ) { return i; } } return -1; } /* * Javascript Diff Algorithm * By John Resig (http://ejohn.org/) * Modified by Chu Alan "sprite" * * Released under the MIT license. * * More Info: * http://ejohn.org/projects/javascript-diff-algorithm/ * * Usage: QUnit.diff(expected, actual) * * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" */ QUnit.diff = (function() { /*jshint eqeqeq:false, eqnull:true */ function diff( o, n ) { var i, ns = {}, os = {}; for ( i = 0; i < n.length; i++ ) { if ( !hasOwn.call( ns, n[i] ) ) { ns[ n[i] ] = { rows: [], o: null }; } ns[ n[i] ].rows.push( i ); } for ( i = 0; i < o.length; i++ ) { if ( !hasOwn.call( os, o[i] ) ) { os[ o[i] ] = { rows: [], n: null }; } os[ o[i] ].rows.push( i ); } for ( i in ns ) { if ( hasOwn.call( ns, i ) ) { if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) { n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] }; o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] }; } } } for ( i = 0; i < n.length - 1; i++ ) { if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && n[ i + 1 ] == o[ n[i].row + 1 ] ) { n[ i + 1 ] = { text: n[ i + 1 ], row: n[i].row + 1 }; o[ n[i].row + 1 ] = { text: o[ n[i].row + 1 ], row: i + 1 }; } } for ( i = n.length - 1; i > 0; i-- ) { if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && n[ i - 1 ] == o[ n[i].row - 1 ]) { n[ i - 1 ] = { text: n[ i - 1 ], row: n[i].row - 1 }; o[ n[i].row - 1 ] = { text: o[ n[i].row - 1 ], row: i - 1 }; } } return { o: o, n: n }; } return function( o, n ) { o = o.replace( /\s+$/, "" ); n = n.replace( /\s+$/, "" ); var i, pre, str = "", out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ), oSpace = o.match(/\s+/g), nSpace = n.match(/\s+/g); if ( oSpace == null ) { oSpace = [ " " ]; } else { oSpace.push( " " ); } if ( nSpace == null ) { nSpace = [ " " ]; } else { nSpace.push( " " ); } if ( out.n.length === 0 ) { for ( i = 0; i < out.o.length; i++ ) { str += "" + out.o[i] + oSpace[i] + ""; } } else { if ( out.n[0].text == null ) { for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) { str += "" + out.o[n] + oSpace[n] + ""; } } for ( i = 0; i < out.n.length; i++ ) { if (out.n[i].text == null) { str += "" + out.n[i] + nSpace[i] + ""; } else { // `pre` initialized at top of scope pre = ""; for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) { pre += "" + out.o[n] + oSpace[n] + ""; } str += " " + out.n[i].text + nSpace[i] + pre; } } } return str; }; }()); // for CommonJS environments, export everything if ( typeof exports !== "undefined" ) { extend( exports, QUnit.constructor.prototype ); } // get at whatever the global object is, like window in browsers }( (function() {return this;}.call()) )); ================================================ FILE: tests/toastr-tests.html ================================================ toastr QUnit Tests

    toastr QUnit Tests

      test markup, will be hidden
      ================================================ FILE: tests/unit/qunit-helper.js ================================================ /** * Hack to expose spec count from QUnit to Karma */ var testCount = 0; var qunitTest = QUnit.test; QUnit.test = window.test = function () { testCount += 1; qunitTest.apply(this, arguments); }; QUnit.begin(function (args) { args.totalTests = testCount; }); ================================================ FILE: tests/unit/toastr-tests.js ================================================ /// /// (function () { var iconClasses = { error: 'toast-error', info: 'toast-info', success: 'toast-success', warning: 'toast-warning' }; var positionClasses = { topRight: 'toast-top-right', bottomRight: 'toast-bottom-right', bottomLeft: 'toast-bottom-left', topLeft: 'toast-top-left', topCenter: 'toast-top-center', bottomCenter: 'toast-bottom-center' }; var sampleMsg = 'I don\'t think they really exist'; var sampleTitle = 'TEST'; var selectors = { container: 'div#toast-container', toastInfo: 'div#toast-container > div.toast-info', toastWarning: 'div#toast-container > div.toast-success', toastError: 'div#toast-container > div.toast-error', toastSuccess: 'div#toast-container > div.toast-success' }; toastr.options = { timeOut: 2000, extendedTimeOut: 0, fadeOut: 0, fadeIn: 0, showDuration: 0, hideDuration: 0, debug: false }; var delay = toastr.options.timeOut + 500; // 'Clears' must go first module('clear'); asyncTest('clear - show 3 toasts, clear the 2nd', 1, function () { //Arrange var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); $toast[2] = toastr.info(sampleMsg, sampleTitle + '-3'); var $container = toastr.getContainer(); //Act toastr.clear($toast[1]); //Assert setTimeout(function () { ok($container && $container.children().length === 2); //Teardown resetContainer(); start(); }, 1000); }); asyncTest('clear - show 3 toasts, clear all 3, 0 left', 1, function () { //Arrange var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); $toast[2] = toastr.info(sampleMsg, sampleTitle + '-3'); var $container = toastr.getContainer(); //Act toastr.clear(); //Assert setTimeout(function () { ok($container && $container.children().length === 0); //Teardown resetContainer(); start(); }, delay); }); test('clear - after clear with force option toast with focus disappears', 1, function () { //Arrange var $toast; var msg = sampleMsg + '

      '; //Act $toast = toastr.info(msg, sampleTitle + '-1'); $toast.find('button').focus(); toastr.clear($toast, { force: true }); var $container = toastr.getContainer(); //Assert ok($container && $container.children().length === 0, 'Focused toast after a clear with force is not visible'); //Teardown resetContainer(); }); asyncTest('clear and show - show 2 toasts, clear both, then show 1 more', 2, function () { //Arrange var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); var $container = toastr.getContainer(); toastr.clear(); //Act setTimeout(function () { $toast[2] = toastr.info(sampleMsg, sampleTitle + '-3-Visible'); //Assert equal($toast[2].find('div.toast-title').html(), sampleTitle + '-3-Visible', 'Finds toast after a clear'); ok($toast[2].is(':visible'), 'Toast after a clear is visible'); //Teardown resetContainer(); start(); }, delay); }); asyncTest('clear and show - clear removes toast container', 2, function () { //Arrange var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); var $container = toastr.getContainer(); toastr.clear(); //Act setTimeout(function () { //Assert equal($(selectors.container).length, 0, 'Toast container does not exist'); ok(!$toast[1].is(':visible'), 'Toast after a clear is visible'); //Teardown resetContainer(); start(); }, delay); }); asyncTest('clear and show - after clear new toast creates container', 1, function () { //Arrange var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); var $container = toastr.getContainer(); toastr.clear(); //Act setTimeout(function () { $toast[2] = toastr.info(sampleMsg, sampleTitle + '-3-Visible'); //Assert equal($(selectors.container).find('div.toast-title').html(), sampleTitle + '-3-Visible', 'Finds toast after a clear'); //Teardown resetContainer(); start(); }, delay); }); asyncTest('clear and show - clear toast after hover', 1, function () { //Arrange var $toast = toastr.info(sampleMsg, sampleTitle); var $container = toastr.getContainer(); $toast.trigger("mouseout"); //Act setTimeout(function () { //Assert ok($container.find('div.toast-title').length === 0, 'Toast clears after a mouse hover'); //Teardown resetContainer(); start(); }, 500); }); asyncTest('clear and show - do not clear toast after hover', 1, function () { //Arrange var $toast = toastr.info(sampleMsg, sampleTitle, { closeOnHover: false }); var $container = toastr.getContainer(); $toast.trigger("mouseout"); //Act setTimeout(function () { //Assert ok($container.find('div.toast-title').length === 1, 'Toast does not clear after a mouse hover'); //Teardown resetContainer(); start(); }, 500); }); test('clear and show - after clear all toasts new toast still appears', 1, function () { //Arrange var $toast = []; //Act $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); toastr.clear(); $toast[2] = toastr.info(sampleMsg, sampleTitle + '-3-Visible'); //Assert ok($toast[2].is(':visible'), 'Toast after a clear is visible'); //Teardown resetContainer(); }); module('info'); test('info - pass title and message', 3, function () { //Arrange //Act var $toast = toastr.info(sampleMsg, sampleTitle); //Assert equal($toast.find('div.toast-title').html(), sampleTitle, 'Sets title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.info), 'Sets info icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('info - pass message, but no title', 3, function () { //Arrange //Act var $toast = toastr.info(sampleMsg); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets null title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.info), 'Sets info icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('info - pass no message nor title', 3, function () { //Arrange //Act var $toast = toastr.info(); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets null title'); equal($toast.find('div.toast-message').html(), null, 'Sets message'); ok($toast.hasClass(iconClasses.info), 'Sets info icon'); //Teardown $toast.remove(); clearContainerChildren(); }); module('warning'); test('warning - pass message and title', 3, function () { //Arrange //Act var $toast = toastr.warning(sampleMsg, sampleTitle); //Assert equal($toast.find('div.toast-title').html(), sampleTitle, 'Sets title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.warning), 'Sets warning icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('warning - pass message, but no title', 3, function () { //Arrange //Act var $toast = toastr.warning(sampleMsg); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets empty title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.warning), 'Sets warning icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('warning - no message nor title', 3, function () { //Arrange //Act var $toast = toastr.warning(''); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets null title'); equal($toast.find('div.toast-message').length, 0, 'Sets empty message'); ok($toast.hasClass(iconClasses.warning), 'Sets warning icon'); //Teardown $toast.remove(); clearContainerChildren(); }); module('error'); test('error - pass message and title', 3, function () { //Arrange //Act var $toast = toastr.error(sampleMsg, sampleTitle); //Assert equal($toast.find('div.toast-title').html(), sampleTitle, 'Sets title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.error), 'Sets error icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('error - pass message, but no title', 3, function () { //Arrange //Act var $toast = toastr.error(sampleMsg); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets empty title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.error), 'Sets error icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('error - no message nor title', 3, function () { //Arrange //Act var $toast = toastr.error(''); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets empty title'); equal($toast.find('div.toast-message').length, 0, 'Sets empty message'); ok($toast.hasClass(iconClasses.error), 'Sets error icon'); //Teardown $toast.remove(); clearContainerChildren(); }); module('success'); test('success - pass message and title', 3, function () { //Arrange //Act var $toast = toastr.success(sampleMsg, sampleTitle); //Assert equal($toast.find('div.toast-title').html(), sampleTitle, 'Sets title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.success), 'Sets success icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('success - pass message, but no title', 3, function () { //Arrange //Act var $toast = toastr.success(sampleMsg); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets empty title'); equal($toast.find('div.toast-message').html(), sampleMsg, 'Sets message'); ok($toast.hasClass(iconClasses.success), 'Sets success icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('success - no message nor title', 3, function () { //Arrange //Act var $toast = toastr.success(''); //Assert equal($toast.find('div.toast-title').length, 0, 'Sets null title'); equal($toast.find('div.toast-message').length, 0, 'Sets empty message'); ok($toast.hasClass(iconClasses.success), 'Sets success icon'); //Teardown $toast.remove(); clearContainerChildren(); }); module('escape html', { teardown: function () { toastr.options.escapeHtml = false; } }); test('info - escape html', 2, function () { //Arrange toastr.options.escapeHtml = true; //Act var $toast = toastr.info('html message', 'html title'); //Assert equal($toast.find('div.toast-title').html(), 'html <u>title</u>', 'Title is escaped'); equal($toast.find('div.toast-message').html(), 'html <strong>message</strong>', 'Message is escaped'); //Teardown $toast.remove(); clearContainerChildren(); }); test('warning - escape html', 2, function () { //Arrange toastr.options.escapeHtml = true; //Act var $toast = toastr.warning('html message', 'html title'); //Assert equal($toast.find('div.toast-title').html(), 'html <u>title</u>', 'Title is escaped'); equal($toast.find('div.toast-message').html(), 'html <strong>message</strong>', 'Message is escaped'); //Teardown $toast.remove(); clearContainerChildren(); }); test('error - escape html', 2, function () { //Arrange toastr.options.escapeHtml = true; //Act var $toast = toastr.error('html message', 'html title'); //Assert equal($toast.find('div.toast-title').html(), 'html <u>title</u>', 'Title is escaped'); equal($toast.find('div.toast-message').html(), 'html <strong>message</strong>', 'Message is escaped'); //Teardown $toast.remove(); clearContainerChildren(); }); test('success - escape html', 2, function () { //Arrange toastr.options.escapeHtml = true; //Act var $toast = toastr.success('html message', 'html title'); //Assert equal($toast.find('div.toast-title').html(), 'html <u>title</u>', 'Title is escaped'); equal($toast.find('div.toast-message').html(), 'html <strong>message</strong>', 'Message is escaped'); //Teardown $toast.remove(); clearContainerChildren(); }); module('closeButton', { teardown: function () { toastr.options.closeButton = false; } }); test('close button disabled', 1, function () { //Arrange toastr.options.closeButton = false; //Act var $toast = toastr.success(''); //Assert equal($toast.find('button.toast-close-button').length, 0, 'close button should not exist with closeButton=false'); //Teardown $toast.remove(); clearContainerChildren(); }); test('close button enabled', 1, function () { //Arrange toastr.options.closeButton = true; //Act var $toast = toastr.success(''); //Assert equal($toast.find('button.toast-close-button').length, 1, 'close button should exist with closeButton=true'); //Teardown $toast.remove(); clearContainerChildren(); }); test('close button has type=button', 1, function () { //Arrange toastr.options.closeButton = true; //Act var $toast = toastr.success(''); //Assert equal($toast.find('button[type="button"].toast-close-button').length, 1, 'close button should have type=button'); //Teardown $toast.remove(); clearContainerChildren(); }); asyncTest('close button duration', 1, function () { //Arrange toastr.options.closeButton = true; toastr.options.closeDuration = 0; toastr.options.hideDuration = 2000; var $container = toastr.getContainer(); //Act var $toast = toastr.success(''); $toast.find('button.toast-close-button').click(); setTimeout(function () { //Assert ok($container && $container.children().length === 0, 'close button should support own hide animation'); //Teardown toastr.options.hideDuration = 0; resetContainer(); start(); }, 500); }); module('progressBar', { teardown: function () { toastr.options.progressBar = false; } }); test('progress bar disabled', 1, function () { //Arrange toastr.options.progressBar = false; //Act var $toast = toastr.success(''); //Assert equal($toast.find('div.toast-progress').length, 0, 'progress bar should not exist with progressBar=false'); //Teardown $toast.remove(); clearContainerChildren(); }); test('progress bar enabled', 1, function () { //Arrange toastr.options.progressBar = true; //Act var $toast = toastr.success(''); //Assert equal($toast.find('div.toast-progress').length, 1, 'progress bar should exist with progressBar=true'); //Teardown $toast.remove(); clearContainerChildren(); }); module('rtl', { teardown: function () { toastr.options.rtl = false; } }); test('toastr is ltr by default', 1, function () { //Arrange //Act //Assert toastr.subscribe(function(response) { equal(response.options.rtl, false, 'ltr by default (i.e. rtl=false)'); }); var $toast = toastr.success(''); //Teardown toastr.subscribe(null); $toast.remove(); clearContainerChildren(); }); test('ltr toastr does not have .rtl class', 1, function () { //Arrange //Act var $toast = toastr.success(''); //Assert ok($toast.hasClass('rtl') === false, 'ltr div container does not have .rtl class'); //Teardown $toast.remove(); clearContainerChildren(); }); test('rtl toastr has .rtl class', 1, function () { //Arrange toastr.options.rtl = true; //Act var $toast = toastr.success(''); //Assert ok($toast.hasClass('rtl'), 'rtl div container has .rtl class'); //Teardown $toast.remove(); clearContainerChildren(); }); module('accessibility'); test('toastr success has aria polite',1,function() { // Arrange var $toast = toastr.success(''); // Act ok($toast.attr('aria-live')==='polite', 'success toast has aria-live of polite'); // Teardown $toast.remove(); clearContainerChildren(); }); test('toastr info has aria polite',1,function() { // Arrange var $toast = toastr.info(''); // Act ok($toast.attr('aria-live')==='polite', 'info toast has aria-live of polite'); // Teardown $toast.remove(); clearContainerChildren(); }); test('toastr warning has aria assertive',1,function() { // Arrange var $toast = toastr.warning(''); // Act ok($toast.attr('aria-live')==='assertive', 'warning toast has aria-live of assertive'); // Teardown $toast.remove(); clearContainerChildren(); }); test('toastr error has aria assertive',1,function() { // Arrange var $toast = toastr.error(''); // Act ok($toast.attr('aria-live')==='assertive', 'error toast has aria-live of assertive'); // Teardown $toast.remove(); clearContainerChildren(); }); module('event', { teardown: function () { toastr.options.closeButton = false; toastr.options.hideDuration = 0; } }); asyncTest('event - onShown is executed', 1, function () { // Arrange var run = false; var onShown = function () { run = true; }; toastr.options.onShown = onShown; // Act var $toast = toastr.success(sampleMsg, sampleTitle); setTimeout(function () { // Assert ok(run); //Teardown $toast.remove(); clearContainerChildren(); start(); }, delay); }); asyncTest('event - onHidden is executed', 1, function () { //Arrange var run = false; var onHidden = function () { run = true; }; toastr.options.onHidden = onHidden; toastr.options.timeOut = 1; //Act var $toast = toastr.success(sampleMsg, sampleTitle); setTimeout(function () { // Assert ok(run); //Teardown $toast.remove(); clearContainerChildren(); start(); }, delay); }); asyncTest('event - onShown and onHidden are both executed', 2, function () { //Arrange var onShowRun = false; var onHideRun = false; var onShow = function () { onShowRun = true; }; var onHide = function () { onHideRun = true; }; toastr.options.onShown = onShow; toastr.options.onHidden = onHide; toastr.options.timeOut = 1; //Act var $toast = toastr.success(sampleMsg, sampleTitle); setTimeout(function () { // Assert ok(onShowRun); ok(onHideRun); //Teardown $toast.remove(); clearContainerChildren(); start(); }, delay); }); asyncTest('event - onCloseClick is executed', 1, function () { //Arrange var run = false; toastr.options.closeButton = true; toastr.options.closeDuration = 0; toastr.options.hideDuration = 2000; var onCloseClick = function () { run = true; }; toastr.options.onCloseClick = onCloseClick; toastr.options.timeOut = 1; //Act var $toast = toastr.success(sampleMsg, sampleTitle); $toast.find('button.toast-close-button').click(); setTimeout(function () { // Assert ok(run); //Teardown $toast.remove(); clearContainerChildren(); start(); }, delay); }); test('event - message appears when no show or hide method functions provided', 1, function () { //Arrange //Act var $toast = toastr.success(sampleMsg, sampleTitle); //Assert ok($toast.hasClass(iconClasses.success), 'Sets success icon'); //Teardown $toast.remove(); clearContainerChildren(); }); test('event - prevent duplicate sequential toasts.', 1, function(){ toastr.options.preventDuplicates = true; var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle); $toast[1] = toastr.info(sampleMsg, sampleTitle); $toast[2] = toastr.info(sampleMsg + " 1", sampleTitle); $toast[3] = toastr.info(sampleMsg, sampleTitle); var $container = toastr.getContainer(); ok($container && $container.children().length === 3); clearContainerChildren(); }); test('event - prevent duplicate sequential toasts, but allow previous after clear.', 1, function(){ toastr.options.preventDuplicates = true; var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle); $toast[1] = toastr.info(sampleMsg, sampleTitle); clearContainerChildren(); $toast[3] = toastr.info(sampleMsg, sampleTitle); var $container = toastr.getContainer(); ok($container && $container.children().length === 1); clearContainerChildren(); }); test('event - allow duplicate sequential toasts.', 1, function(){ toastr.options.preventDuplicates = false; var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle); $toast[1] = toastr.info(sampleMsg, sampleTitle); $toast[1] = toastr.info(sampleMsg, sampleTitle); var $container = toastr.getContainer(); ok($container && $container.children().length === 3); clearContainerChildren(); }); test('event - allow preventDuplicates option to be overridden.', 1, function() { var $toast = []; $toast[0] = toastr.info(sampleMsg, sampleTitle, { preventDuplicates: true }); $toast[1] = toastr.info(sampleMsg, sampleTitle, { preventDuplicates: true }); $toast[2] = toastr.info(sampleMsg, sampleTitle); var $container = toastr.getContainer(); ok($container && $container.children().length === 2); clearContainerChildren(); }); module('subscription'); asyncTest('subscribe - triggers 2 visible and 2 hidden response notifications while clicking on a toast', 1, function () { //Arrange var $toast = []; var expectedReponses = []; //Act toastr.subscribe(function(response) { if(response.options.testId) { expectedReponses.push(response); } }) $toast[0] = toastr.info(sampleMsg, sampleTitle, {testId : 1}); $toast[1] = toastr.info(sampleMsg, sampleTitle, {testId : 2}); $toast[1].click() setTimeout(function () { // Assert ok(expectedReponses.length === 4); //Teardown clearContainerChildren(); toastr.subscribe(null); start(); }, delay); }); module('order of appearance'); test('Newest toast on top', 1, function () { //Arrange resetContainer(); toastr.options.newestOnTop = true; //Act var $first = toastr.success("First toast"); var $second = toastr.success("Second toast"); //Assert var containerHtml = toastr.getContainer().html(); ok(containerHtml.indexOf("First toast") > containerHtml.indexOf("Second toast"), 'Newest toast is on top'); //Teardown $first.remove(); $second.remove(); resetContainer(); }); test('Oldest toast on top', 1, function () { //Arrange resetContainer(); toastr.options.newestOnTop = false; //Act var $first = toastr.success("First toast"); var $second = toastr.success("Second toast"); //Assert var containerHtml = toastr.getContainer().html(); ok(containerHtml.indexOf("First toast") < containerHtml.indexOf("Second toast"), 'Oldest toast is on top'); //Teardown $first.remove(); $second.remove(); resetContainer(); }); // These must go last module('positioning'); test('Container - position top-right', 1, function () { //Arrange resetContainer(); toastr.options.positionClass = positionClasses.topRight; //Act var $toast = toastr.success(sampleMsg); var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.topRight), 'Has position top right'); //Teardown $toast.remove(); resetContainer(); }); test('Container - position bottom-right', 1, function () { //Arrange resetContainer(); toastr.options.positionClass = positionClasses.bottomRight; //Act var $toast = toastr.success(sampleMsg); var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.bottomRight), 'Has position bottom right'); //Teardown $toast.remove(); resetContainer(); }); test('Container - position bottom-left', 1, function () { //Arrange resetContainer(); //$(selectors.container).remove() toastr.options.positionClass = positionClasses.bottomLeft; //Act var $toast = toastr.success(sampleMsg); var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.bottomLeft), 'Has position bottom left'); //Teardown $toast.remove(); resetContainer(); }); test('Container - position top-left', 1, function () { //Arrange resetContainer(); toastr.options.positionClass = positionClasses.topLeft; //Act var $toast = toastr.success(sampleMsg); var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.topLeft), 'Has position top left'); //Teardown $toast.remove(); resetContainer(); }); test('Container - position top-center', 1, function () { //Arrange resetContainer(); toastr.options.positionClass = positionClasses.topCenter; //Act var $toast = toastr.success(sampleMsg); var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.topCenter), 'Has position top center'); //Teardown $toast.remove(); resetContainer(); }); test('Container - position bottom-center', 1, function () { //Arrange resetContainer(); toastr.options.positionClass = positionClasses.bottomCenter; //Act var $toast = toastr.success(sampleMsg); var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.bottomCenter), 'Has position bottom center'); //Teardown $toast.remove(); resetContainer(); }); function resetContainer() { var $container = toastr.getContainer(); if ($container) { $container.remove(); } $(selectors.container).remove(); clearContainerChildren(); } function clearContainerChildren() { toastr.clear(); } })(); ================================================ FILE: tests/unit/x.js ================================================ test('test test', 1, function () { ok(1 === 1, '1 equals 1'); }); ================================================ FILE: toastr.js ================================================ /* * Toastr * Copyright 2012-2015 * Authors: John Papa, Hans Fjällemark, and Tim Ferrell. * All Rights Reserved. * Use, reproduction, distribution, and modification of this code is subject to the terms and * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php * * ARIA Support: Greta Krafsig * * Project: https://github.com/CodeSeven/toastr */ /* global define */ (function (define) { define(['jquery'], function ($) { return (function () { var $container; var listener; var toastId = 0; var toastType = { error: 'error', info: 'info', success: 'success', warning: 'warning' }; var toastr = { clear: clear, remove: remove, error: error, getContainer: getContainer, info: info, options: {}, subscribe: subscribe, success: success, version: '2.1.4', warning: warning }; var previousToast; return toastr; //////////////// function error(message, title, optionsOverride) { return notify({ type: toastType.error, iconClass: getOptions().iconClasses.error, message: message, optionsOverride: optionsOverride, title: title }); } function getContainer(options, create) { if (!options) { options = getOptions(); } $container = $('#' + options.containerId); if ($container.length) { return $container; } if (create) { $container = createContainer(options); } return $container; } function info(message, title, optionsOverride) { return notify({ type: toastType.info, iconClass: getOptions().iconClasses.info, message: message, optionsOverride: optionsOverride, title: title }); } function subscribe(callback) { listener = callback; } function success(message, title, optionsOverride) { return notify({ type: toastType.success, iconClass: getOptions().iconClasses.success, message: message, optionsOverride: optionsOverride, title: title }); } function warning(message, title, optionsOverride) { return notify({ type: toastType.warning, iconClass: getOptions().iconClasses.warning, message: message, optionsOverride: optionsOverride, title: title }); } function clear($toastElement, clearOptions) { var options = getOptions(); if (!$container) { getContainer(options); } if (!clearToast($toastElement, options, clearOptions)) { clearContainer(options); } } function remove($toastElement) { var options = getOptions(); if (!$container) { getContainer(options); } if ($toastElement && $(':focus', $toastElement).length === 0) { removeToast($toastElement); return; } if ($container.children().length) { $container.remove(); } } // internal functions function clearContainer (options) { var toastsToClear = $container.children(); for (var i = toastsToClear.length - 1; i >= 0; i--) { clearToast($(toastsToClear[i]), options); } } function clearToast ($toastElement, options, clearOptions) { var force = clearOptions && clearOptions.force ? clearOptions.force : false; if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { $toastElement[options.hideMethod]({ duration: options.hideDuration, easing: options.hideEasing, complete: function () { removeToast($toastElement); } }); return true; } return false; } function createContainer(options) { $container = $('
      ') .attr('id', options.containerId) .addClass(options.positionClass); $container.appendTo($(options.target)); return $container; } function getDefaults() { return { tapToDismiss: true, toastClass: 'toast', containerId: 'toast-container', debug: false, showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery showDuration: 300, showEasing: 'swing', //swing and linear are built into jQuery onShown: undefined, hideMethod: 'fadeOut', hideDuration: 1000, hideEasing: 'swing', onHidden: undefined, closeMethod: false, closeDuration: false, closeEasing: false, closeOnHover: true, extendedTimeOut: 1000, iconClasses: { error: 'toast-error', info: 'toast-info', success: 'toast-success', warning: 'toast-warning' }, iconClass: 'toast-info', positionClass: 'toast-top-right', timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky titleClass: 'toast-title', messageClass: 'toast-message', escapeHtml: false, target: 'body', closeHtml: '', closeClass: 'toast-close-button', newestOnTop: true, preventDuplicates: false, progressBar: false, progressClass: 'toast-progress', rtl: false }; } function publish(args) { if (!listener) { return; } listener(args); } function notify(map) { var options = getOptions(); var iconClass = map.iconClass || options.iconClass; if (typeof (map.optionsOverride) !== 'undefined') { options = $.extend(options, map.optionsOverride); iconClass = map.optionsOverride.iconClass || iconClass; } if (shouldExit(options, map)) { return; } toastId++; $container = getContainer(options, true); var intervalId = null; var $toastElement = $('
      '); var $titleElement = $('
      '); var $messageElement = $('
      '); var $progressElement = $('
      '); var $closeElement = $(options.closeHtml); var progressBar = { intervalId: null, hideEta: null, maxHideTime: null }; var response = { toastId: toastId, state: 'visible', startTime: new Date(), options: options, map: map }; personalizeToast(); displayToast(); handleEvents(); publish(response); if (options.debug && console) { console.log(response); } return $toastElement; function escapeHtml(source) { if (source == null) { source = ''; } return source .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } function personalizeToast() { setIcon(); setTitle(); setMessage(); setCloseButton(); setProgressBar(); setRTL(); setSequence(); setAria(); } function setAria() { var ariaValue = ''; switch (map.iconClass) { case 'toast-success': case 'toast-info': ariaValue = 'polite'; break; default: ariaValue = 'assertive'; } $toastElement.attr('aria-live', ariaValue); } function handleEvents() { if (options.closeOnHover) { $toastElement.hover(stickAround, delayedHideToast); } if (!options.onclick && options.tapToDismiss) { $toastElement.click(hideToast); } if (options.closeButton && $closeElement) { $closeElement.click(function (event) { if (event.stopPropagation) { event.stopPropagation(); } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { event.cancelBubble = true; } if (options.onCloseClick) { options.onCloseClick(event); } hideToast(true); }); } if (options.onclick) { $toastElement.click(function (event) { options.onclick(event); hideToast(); }); } } function displayToast() { $toastElement.hide(); $toastElement[options.showMethod]( {duration: options.showDuration, easing: options.showEasing, complete: options.onShown} ); if (options.timeOut > 0) { intervalId = setTimeout(hideToast, options.timeOut); progressBar.maxHideTime = parseFloat(options.timeOut); progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; if (options.progressBar) { progressBar.intervalId = setInterval(updateProgress, 10); } } } function setIcon() { if (map.iconClass) { $toastElement.addClass(options.toastClass).addClass(iconClass); } } function setSequence() { if (options.newestOnTop) { $container.prepend($toastElement); } else { $container.append($toastElement); } } function setTitle() { if (map.title) { var suffix = map.title; if (options.escapeHtml) { suffix = escapeHtml(map.title); } $titleElement.append(suffix).addClass(options.titleClass); $toastElement.append($titleElement); } } function setMessage() { if (map.message) { var suffix = map.message; if (options.escapeHtml) { suffix = escapeHtml(map.message); } $messageElement.append(suffix).addClass(options.messageClass); $toastElement.append($messageElement); } } function setCloseButton() { if (options.closeButton) { $closeElement.addClass(options.closeClass).attr('role', 'button'); $toastElement.prepend($closeElement); } } function setProgressBar() { if (options.progressBar) { $progressElement.addClass(options.progressClass); $toastElement.prepend($progressElement); } } function setRTL() { if (options.rtl) { $toastElement.addClass('rtl'); } } function shouldExit(options, map) { if (options.preventDuplicates) { if (map.message === previousToast) { return true; } else { previousToast = map.message; } } return false; } function hideToast(override) { var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; var duration = override && options.closeDuration !== false ? options.closeDuration : options.hideDuration; var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; if ($(':focus', $toastElement).length && !override) { return; } clearTimeout(progressBar.intervalId); return $toastElement[method]({ duration: duration, easing: easing, complete: function () { removeToast($toastElement); clearTimeout(intervalId); if (options.onHidden && response.state !== 'hidden') { options.onHidden(); } response.state = 'hidden'; response.endTime = new Date(); publish(response); } }); } function delayedHideToast() { if (options.timeOut > 0 || options.extendedTimeOut > 0) { intervalId = setTimeout(hideToast, options.extendedTimeOut); progressBar.maxHideTime = parseFloat(options.extendedTimeOut); progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; } } function stickAround() { clearTimeout(intervalId); progressBar.hideEta = 0; $toastElement.stop(true, true)[options.showMethod]( {duration: options.showDuration, easing: options.showEasing} ); } function updateProgress() { var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; $progressElement.width(percentage + '%'); } } function getOptions() { return $.extend({}, getDefaults(), toastr.options); } function removeToast($toastElement) { if (!$container) { $container = getContainer(); } if ($toastElement.is(':visible')) { return; } $toastElement.remove(); $toastElement = null; if ($container.children().length === 0) { $container.remove(); previousToast = undefined; } } })(); }); }(typeof define === 'function' && define.amd ? define : function (deps, factory) { if (typeof module !== 'undefined' && module.exports) { //Node module.exports = factory(require('jquery')); } else { window.toastr = factory(window.jQuery); } })); ================================================ FILE: toastr.less ================================================ // Mix-ins .borderRadius(@radius) { -moz-border-radius: @radius; -webkit-border-radius: @radius; border-radius: @radius; } .boxShadow(@boxShadow) { -moz-box-shadow: @boxShadow; -webkit-box-shadow: @boxShadow; box-shadow: @boxShadow; } .opacity(@opacity) { @opacityPercent: (@opacity * 100); opacity: @opacity; -ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(Opacity=@{opacityPercent})"; filter: ~"alpha(opacity=@{opacityPercent})"; } .wordWrap(@wordWrap: break-word) { -ms-word-wrap: @wordWrap; word-wrap: @wordWrap; } // Variables @black: #000000; @grey: #999999; @light-grey: #CCCCCC; @white: #FFFFFF; @near-black: #030303; @green: #51A351; @red: #BD362F; @blue: #2F96B4; @orange: #F89406; @default-container-opacity: .8; // Styles .toast-title { font-weight: bold; } .toast-message { .wordWrap(); a, label { color: @white; } a:hover { color: @light-grey; text-decoration: none; } } .toast-close-button { position: relative; right: -0.3em; top: -0.3em; float: right; font-size: 20px; font-weight: bold; color: @white; -webkit-text-shadow: 0 1px 0 rgba(255,255,255,1); text-shadow: 0 1px 0 rgba(255,255,255,1); .opacity(0.8); line-height: 1; &:hover, &:focus { color: @black; text-decoration: none; cursor: pointer; .opacity(0.4); } } .rtl .toast-close-button { left: -0.3em; float: left; right: 0.3em; } /*Additional properties for button version iOS requires the button element instead of an anchor tag. If you want the anchor version, it requires `href="#"`.*/ button.toast-close-button { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; } //#endregion .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; // The container should not be clickable. pointer-events: none; * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } > div { position: relative; // The toast itself should be clickable. pointer-events: auto; overflow: hidden; margin: 0 0 6px; padding: 15px 15px 15px 50px; width: 300px; .borderRadius(3px 3px 3px 3px); background-position: 15px center; background-repeat: no-repeat; .boxShadow(0 0 12px @grey); color: @white; .opacity(@default-container-opacity); } > div.rtl { direction: rtl; padding: 15px 50px 15px 15px; background-position: right 15px center; } > div:hover { .boxShadow(0 0 12px @black); .opacity(1); cursor: pointer; } > .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-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-success { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; } > .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; } /*overrides*/ &.toast-top-center > div, &.toast-bottom-center > div { width: 300px; margin-left: auto; margin-right: auto; } &.toast-top-full-width > div, &.toast-bottom-full-width > div { width: 96%; margin-left: auto; margin-right: auto; } } .toast { background-color: @near-black; } .toast-success { background-color: @green; } .toast-error { background-color: @red; } .toast-info { background-color: @blue; } .toast-warning { background-color: @orange; } .toast-progress { position: absolute; left: 0; bottom: 0; height: 4px; background-color: @black; .opacity(0.4); } /*Responsive Design*/ @media all and (max-width: 240px) { #toast-container { > div { padding: 8px 8px 8px 50px; width: 11em; } > div.rtl { padding: 8px 50px 8px 8px; } & .toast-close-button { right: -0.2em; top: -0.2em; } & .rtl .toast-close-button { left: -0.2em; right: 0.2em; } } } @media all and (min-width: 241px) and (max-width: 480px) { #toast-container { > div { padding: 8px 8px 8px 50px; width: 18em; } > div.rtl { padding: 8px 50px 8px 8px; } & .toast-close-button { right: -0.2em; top: -0.2em; } & .rtl .toast-close-button { left: -0.2em; right: 0.2em; } } } @media all and (min-width: 481px) and (max-width: 768px) { #toast-container { > div { padding: 15px 15px 15px 50px; width: 25em; } > div.rtl { padding: 15px 50px 15px 15px; } } } ================================================ FILE: toastr.scss ================================================ .toast-title { font-weight: bold; } .toast-message { -ms-word-wrap: break-word; word-wrap: break-word; } .toast-message a, .toast-message label { color: #ffffff; } .toast-message a:hover { color: #cccccc; text-decoration: none; } .toast-close-button { position: relative; right: -0.3em; top: -0.3em; float: right; font-size: 20px; font-weight: bold; color: #ffffff; -webkit-text-shadow: 0 1px 0 #ffffff; text-shadow: 0 1px 0 #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } .toast-close-button:hover, .toast-close-button:focus { color: #000000; text-decoration: none; cursor: pointer; opacity: 0.4; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); filter: alpha(opacity=40); } /*Additional properties for button version iOS requires the button element instead of an anchor tag. If you want the anchor version, it requires `href="#"`.*/ button.toast-close-button { padding: 0; cursor: pointer; background: transparent; 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; /*overrides*/ } #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 3px 3px 3px; -webkit-border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px; background-position: 15px center; background-repeat: no-repeat; -moz-box-shadow: 0 0 12px #999999; -webkit-box-shadow: 0 0 12px #999999; box-shadow: 0 0 12px #999999; color: #ffffff; opacity: 0.8; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); filter: alpha(opacity=80); } #toast-container > div:hover { -moz-box-shadow: 0 0 12px #000000; -webkit-box-shadow: 0 0 12px #000000; box-shadow: 0 0 12px #000000; opacity: 1; -ms-filter: progid:DXImageTransform.Microsoft.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-top-center > div, #toast-container.toast-bottom-center > div { width: 300px; margin-left: auto; margin-right: auto; } #toast-container.toast-top-full-width > div, #toast-container.toast-bottom-full-width > div { width: 96%; margin-left: auto; margin-right: 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: #000000; opacity: 0.4; -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); filter: alpha(opacity=40); } /*Responsive Design*/ @media all and (max-width: 240px) { #toast-container > div { padding: 8px 8px 8px 50px; width: 11em; } #toast-container .toast-close-button { right: -0.2em; top: -0.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: -0.2em; top: -0.2em; } } @media all and (min-width: 481px) and (max-width: 768px) { #toast-container > div { padding: 15px 15px 15px 50px; width: 25em; } }