├── .gitignore ├── Gruntfile.js ├── LICENSE.txt ├── README.md ├── bower.json ├── demo.html ├── dist ├── ng-modal.css ├── ng-modal.js └── ng-modal.min.js ├── karma.conf.coffee ├── package.json ├── screenshot.png ├── spec └── ng-modal-specs.coffee ├── src ├── ng-modal.coffee └── ng-modal.less └── vendor └── browserTrigger.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | bower_components 3 | .DS_Store 4 | node_modules 5 | build 6 | spec/build 7 | ng-modal.zip 8 | dist/ng-modal.zip 9 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | // Project configuration. 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON('package.json'), 6 | coffee: { 7 | compile: { 8 | files: { 9 | "spec/build/specs.js": ["spec/*.coffee"], 10 | "dist/ng-modal.js": ["src/*.coffee"] 11 | } 12 | } 13 | }, 14 | uglify: { 15 | my_target: { 16 | files: { 17 | "dist/ng-modal.min.js": "dist/ng-modal.js" 18 | } 19 | } 20 | }, 21 | less: { 22 | compile: { 23 | files: { 24 | "dist/ng-modal.css": ["src/ng-modal.less"] 25 | } 26 | } 27 | }, 28 | watch: { 29 | scripts: { 30 | files: ['**/*.coffee', '**/*.less'], 31 | tasks: ['coffee', 'uglify', 'less'], 32 | options: { 33 | debounceDelay: 250, 34 | }, 35 | } 36 | }, 37 | zip: { 38 | 'package': { 39 | cwd: 'dist/', 40 | src: ['dist/*.js', 'dist/*.css'], 41 | dest: 'dist/ng-modal.zip' 42 | } 43 | } 44 | }); 45 | 46 | grunt.loadNpmTasks('grunt-contrib-coffee'); 47 | grunt.loadNpmTasks('grunt-contrib-uglify'); 48 | grunt.loadNpmTasks('grunt-contrib-less'); 49 | grunt.loadNpmTasks('grunt-contrib-watch'); 50 | grunt.loadNpmTasks('grunt-zip'); 51 | 52 | grunt.registerTask('default', ['coffee', 'uglify', 'less', 'watch']); 53 | grunt.registerTask('package', ['coffee', 'uglify', 'less', 'zip']); 54 | }; 55 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2013 Adam Albrecht and other contributors 2 | http://adamalbrecht.com 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ngModal 2 | 3 | ngModal is very simple [Angular.js](http://angularjs.org/) modal dialog directive. 4 | 5 | 6 | ![ngModal Screenshot](https://raw.github.com/adamalbrecht/ngModal/master/screenshot.png) 7 | 8 | 9 | ## Download 10 | 11 | * [Version 1.2.2](https://github.com/adamalbrecht/ngModal/archive/1.2.2.zip) - Compatible with Angular 1.2.x. 12 | 13 | You can also install the package using [Bower](http://bower.io). 14 | 15 | ```sh 16 | bower install ngModal 17 | ``` 18 | 19 | Or add it to your bower.json file: 20 | 21 | ```javascript 22 | dependencies: { 23 | "ngModal": "~1.2.0" 24 | } 25 | ``` 26 | 27 | ## The Basics 28 | To use the library, add the JS file and CSS file, and then include the module in your app: 29 | 30 | ```javascript 31 | app = angular.module("myApp", ["ngModal"]) 32 | ``` 33 | 34 | The directive itself is called *modal-dialog*. The only required attribute is `show`, which should reference a boolean variable that controls whether or not the dialog is shown. Inside, you can put whatever HTML content you'd like. 35 | 36 | ```html 37 | 38 |

Dialog content goes in here

39 |
40 | ``` 41 | 42 | ## Inline Options 43 | 44 | There are a few options that be configured inline with attributes. 45 | 46 | | Option | Default | Description | 47 | | -------------- | ------- | ----------------------------------------------------------------- | 48 | | dialog-title | null | Title placed in the header of the modal dialog. | 49 | | width | 50% | Width of the dialog. Can be specified in px or %. | 50 | | height | 50% | Height of the dialog. Can be specified in px or %. | 51 | | on-close | null | Call a function when the dialog is closed. Ex: `on-close='foo()'` | 52 | 53 | **Example:** 54 | 55 | ```html 56 | 57 |

Dialog content goes in here

58 |
59 | ``` 60 | 61 | ## Configuration Options 62 | 63 | You can also pre-configure some options during your app's configuration phase. 64 | 65 | ```javascript 66 | app.config(function(ngModalDefaultsProvider) { 67 | ngModalDefaultsProvider.set('option', 'value'); 68 | // Or with a hash 69 | ngModalDefaultsProvider.set({option: 'value', option2: 'value2'}); 70 | }) 71 | ``` 72 | 73 | | Option | Default | Description | 74 | | ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------- | 75 | | closeButtonHtml | 'X' | By default, the close button is just an X character. But you can set it to any HTML. For example, if you're using font-awesome, you could set it to `` | 76 | 77 | 78 | ## Browser Support 79 | 80 | So far, it has only been tested in Chrome. There is some CSS that is not compatible with with older browsers, including IE9. 81 | 82 | ## Contributing 83 | 84 | Contributions are welcome. Whenever possible, please include test coverage with your contribution. 85 | 86 | 1. Fork it 87 | 2. Create your feature branch (`git checkout -b my-new-feature`) 88 | 3. Commit your changes (`git commit -am 'Add some feature'`) 89 | 4. Push to the branch (`git push origin my-new-feature`) 90 | 5. Create new Pull Request 91 | 92 | To get the project running, you'll need [NPM](https://npmjs.org/) and [Bower](http://bower.io/). Run `npm install` and `bower install` to install all dependencies. Then run `grunt` in the project directory to watch and compile changes. And you can run `karma start` to watch for changes and auto-execute unit tests. 93 | 94 | ## Potential Features Down the Road 95 | 96 | * Ability to integrate easily with [UI-Router](https://github.com/angular-ui/ui-router). This may be possible already, but it needs to be explored. 97 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngModal", 3 | "version": "1.2.2", 4 | "main": ["dist/ng-modal.js", "dist/ng-modal.css"], 5 | "ignore": [ 6 | ".gitignore", 7 | "bower_components", 8 | "node_modules", 9 | "spec", 10 | "src", 11 | "vendor", 12 | "demo.html", 13 | "Gruntfile.js", 14 | "karma.conf.coffee", 15 | "package.json", 16 | "screenshot.png" 17 | ], 18 | "dependencies": {}, 19 | "devDependencies": { 20 | "angular": "~1.2.4", 21 | "angular-mocks": "~1.2.4", 22 | "jasmine": "~1.3.1", 23 | "karma-jasmine": "~0.1.3", 24 | "jquery": "~2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ngQuickDate Demo 5 | 6 | 7 | 12 | 13 | 14 |
15 | 16 |

This is some html content

17 |

18 | 19 | 20 |

21 |

22 | 23 | 24 |

25 | 26 |
27 | 28 |
29 |
30 |
31 |

Shown? {{myData.modalShown}}

32 |

Hello: {{myData.hello}}

33 |

Foo: {{myData.foo}}

34 |
35 | 36 | 37 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /dist/ng-modal.css: -------------------------------------------------------------------------------- 1 | .ng-modal { 2 | position: fixed; 3 | z-index: 9999; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | } 9 | .ng-modal-overlay { 10 | position: absolute; 11 | z-index: 9999; 12 | top: 0; 13 | left: 0; 14 | width: 100%; 15 | height: 100%; 16 | background-color: #000000; 17 | opacity: 0.8; 18 | } 19 | .ng-modal-dialog { 20 | z-index: 10000; 21 | position: absolute; 22 | top: 50%; 23 | left: 50%; 24 | width: 50%; 25 | transform: translate(-50%, -50%); 26 | -webkit-transform: translate(-50%, -50%); 27 | -moz-transform: translate(-50%, -50%); 28 | -ms-transform: translate(-50%, -50%); 29 | -o-transform: translate(-50%, -50%); 30 | background-color: #fff; 31 | box-shadow: 4px 4px 80px #000; 32 | -webkit-box-shadow: 4px 4px 80px #000; 33 | -moz-box-shadow: 4px 4px 80px #000; 34 | -ms-box-shadow: 4px 4px 80px #000; 35 | -o-box-shadow: 4px 4px 80px #000; 36 | padding: 10px; 37 | } 38 | .ng-modal-dialog-content { 39 | overflow: hidden; 40 | height: 100%; 41 | } 42 | .ng-modal-close { 43 | position: absolute; 44 | top: 3px; 45 | right: 5px; 46 | cursor: pointer; 47 | font-size: 120%; 48 | padding: 5px; 49 | display: inline-block; 50 | } 51 | .ng-modal-close-x { 52 | font-weight: bold; 53 | font-family: Arial, sans-serif; 54 | } 55 | .ng-modal-title { 56 | font-weight: bold; 57 | font-size: 200%; 58 | display: block; 59 | margin-bottom: 10px; 60 | padding-bottom: 7px; 61 | border-bottom: solid 1px #999; 62 | } 63 | -------------------------------------------------------------------------------- /dist/ng-modal.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var app; 3 | 4 | app = angular.module("ngModal", []); 5 | 6 | app.provider("ngModalDefaults", function() { 7 | return { 8 | options: { 9 | closeButtonHtml: "X" 10 | }, 11 | $get: function() { 12 | return this.options; 13 | }, 14 | set: function(keyOrHash, value) { 15 | var k, v, _results; 16 | if (typeof keyOrHash === 'object') { 17 | _results = []; 18 | for (k in keyOrHash) { 19 | v = keyOrHash[k]; 20 | _results.push(this.options[k] = v); 21 | } 22 | return _results; 23 | } else { 24 | return this.options[keyOrHash] = value; 25 | } 26 | } 27 | }; 28 | }); 29 | 30 | app.directive('modalDialog', [ 31 | 'ngModalDefaults', '$sce', function(ngModalDefaults, $sce) { 32 | return { 33 | restrict: 'E', 34 | scope: { 35 | show: '=', 36 | dialogTitle: '@', 37 | onClose: '&?' 38 | }, 39 | replace: true, 40 | transclude: true, 41 | link: function(scope, element, attrs) { 42 | var setupCloseButton, setupStyle; 43 | setupCloseButton = function() { 44 | return scope.closeButtonHtml = $sce.trustAsHtml(ngModalDefaults.closeButtonHtml); 45 | }; 46 | setupStyle = function() { 47 | scope.dialogStyle = {}; 48 | if (attrs.width) { 49 | scope.dialogStyle['width'] = attrs.width; 50 | } 51 | if (attrs.height) { 52 | return scope.dialogStyle['height'] = attrs.height; 53 | } 54 | }; 55 | scope.hideModal = function() { 56 | return scope.show = false; 57 | }; 58 | scope.$watch('show', function(newVal, oldVal) { 59 | if (newVal && !oldVal) { 60 | document.getElementsByTagName("body")[0].style.overflow = "hidden"; 61 | } else { 62 | document.getElementsByTagName("body")[0].style.overflow = ""; 63 | } 64 | if ((!newVal && oldVal) && (scope.onClose != null)) { 65 | return scope.onClose(); 66 | } 67 | }); 68 | setupCloseButton(); 69 | return setupStyle(); 70 | }, 71 | template: "
\n
\n
\n \n
\n
\n
\n
\n
\n
" 72 | }; 73 | } 74 | ]); 75 | 76 | }).call(this); 77 | -------------------------------------------------------------------------------- /dist/ng-modal.min.js: -------------------------------------------------------------------------------- 1 | (function(){var a;a=angular.module("ngModal",[]),a.provider("ngModalDefaults",function(){return{options:{closeButtonHtml:"X"},$get:function(){return this.options},set:function(a,b){var c,d,e;if("object"==typeof a){e=[];for(c in a)d=a[c],e.push(this.options[c]=d);return e}return this.options[a]=b}}}),a.directive("modalDialog",["ngModalDefaults","$sce",function(a,b){return{restrict:"E",scope:{show:"=",dialogTitle:"@",onClose:"&?"},replace:!0,transclude:!0,link:function(c,d,e){var f,g;return f=function(){return c.closeButtonHtml=b.trustAsHtml(a.closeButtonHtml)},g=function(){return c.dialogStyle={},e.width&&(c.dialogStyle.width=e.width),e.height?c.dialogStyle.height=e.height:void 0},c.hideModal=function(){return c.show=!1},c.$watch("show",function(a,b){return document.getElementsByTagName("body")[0].style.overflow=a&&!b?"hidden":"",!a&&b&&null!=c.onClose?c.onClose():void 0}),f(),g()},template:"
\n
\n
\n \n
\n
\n
\n
\n
\n
"}}])}).call(this); -------------------------------------------------------------------------------- /karma.conf.coffee: -------------------------------------------------------------------------------- 1 | # an example karma.conf.coffee 2 | module.exports = (config) -> 3 | config.set 4 | autoWatch: true 5 | frameworks: ['jasmine'] 6 | browsers: ['PhantomJS'] 7 | preprocessors: { 8 | '**/*.coffee': ['coffee'], 9 | } 10 | coffeePreprocessor: { 11 | options: { 12 | bare: true, 13 | sourceMap: false 14 | } 15 | transformPath: (path) -> path.replace(/\.js$/, '.coffee') 16 | } 17 | files: [ 18 | 'bower_components/angular/angular.js' 19 | 'bower_components/angular-mocks/angular-mocks.js' 20 | 'bower_components/jquery/jquery.js' 21 | 'vendor/*.js' 22 | 'src/*.coffee' 23 | 'spec/*.coffee' 24 | ] 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngModal", 3 | "version": "1.2.2", 4 | "devDependencies": { 5 | "grunt": "~0.4.1", 6 | "grunt-contrib-coffee": "~0.7", 7 | "grunt-contrib-watch": "~0.5", 8 | "grunt-contrib-uglify": "~0.2", 9 | "karma": "~0.10", 10 | "karma-coffee-preprocessor": "~0.1", 11 | "grunt-contrib-less": "~0.8.2", 12 | "grunt-zip": "~0.12.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamalbrecht/ngModal/7f374086275dc66f1fd0183c664698c8b8111204/screenshot.png -------------------------------------------------------------------------------- /spec/ng-modal-specs.coffee: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | describe "ngModal", -> 4 | beforeEach angular.mock.module("ngModal") 5 | describe 'modal-dialog', -> 6 | element = undefined 7 | $scope = undefined 8 | describe 'Given a basic modal dialog', -> 9 | beforeEach angular.mock.inject(($compile, $rootScope) -> 10 | $scope = $rootScope 11 | $scope.shown = false 12 | element = $compile("

My Content

")($scope) 13 | ) 14 | 15 | it 'is hidden by default since shown is false' 16 | describe 'and the shown variable is set to true', -> 17 | beforeEach -> 18 | $scope.shown = true 19 | 20 | it 'is displayed' 21 | it 'is hidden when the close button is clicked' 22 | it 'is hidden when the overlay is clicked' 23 | -------------------------------------------------------------------------------- /src/ng-modal.coffee: -------------------------------------------------------------------------------- 1 | # 2 | # ngModal 3 | # by Adam Albrecht 4 | # http://adamalbrecht.com 5 | # 6 | # Source Code: https://github.com/adamalbrecht/ngModal 7 | # 8 | # Compatible with Angular 1.2.x 9 | # 10 | 11 | app = angular.module("ngModal", []) 12 | 13 | app.provider "ngModalDefaults", -> 14 | options: { 15 | closeButtonHtml: "X" 16 | } 17 | $get: -> 18 | @options 19 | 20 | set: (keyOrHash, value) -> 21 | if typeof(keyOrHash) == 'object' 22 | for k, v of keyOrHash 23 | @options[k] = v 24 | else 25 | @options[keyOrHash] = value 26 | 27 | app.directive 'modalDialog', ['ngModalDefaults', '$sce', (ngModalDefaults, $sce) -> 28 | restrict: 'E' 29 | scope: 30 | show: '=' 31 | dialogTitle: '@' 32 | onClose: '&?' 33 | replace: true 34 | transclude: true 35 | link: (scope, element, attrs) -> 36 | setupCloseButton = -> 37 | scope.closeButtonHtml = $sce.trustAsHtml(ngModalDefaults.closeButtonHtml) 38 | 39 | setupStyle = -> 40 | scope.dialogStyle = {} 41 | scope.dialogStyle['width'] = attrs.width if attrs.width 42 | scope.dialogStyle['height'] = attrs.height if attrs.height 43 | 44 | scope.hideModal = -> 45 | scope.show = false 46 | 47 | scope.$watch('show', (newVal, oldVal) -> 48 | if newVal && !oldVal 49 | document.getElementsByTagName("body")[0].style.overflow = "hidden"; 50 | else 51 | document.getElementsByTagName("body")[0].style.overflow = ""; 52 | if (!newVal && oldVal) && scope.onClose? 53 | scope.onClose() 54 | ) 55 | 56 | setupCloseButton() 57 | setupStyle() 58 | 59 | template: """ 60 |
61 |
62 |
63 | 64 |
65 |
66 |
67 |
68 |
69 |
70 | """ 71 | ] 72 | -------------------------------------------------------------------------------- /src/ng-modal.less: -------------------------------------------------------------------------------- 1 | .ng-modal { 2 | position: fixed; 3 | z-index: 9999; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | } 9 | .ng-modal-overlay { 10 | position:absolute; 11 | z-index:9999; 12 | top:0; 13 | left:0; 14 | width:100%; 15 | height:100%; 16 | background-color:#000000; 17 | opacity: 0.8; 18 | } 19 | .ng-modal-dialog { 20 | z-index:10000; 21 | position: absolute; 22 | top: 50%; 23 | left: 50%; 24 | width: 50%; 25 | transform: translate(-50%, -50%); 26 | -webkit-transform: translate(-50%, -50%); 27 | -moz-transform: translate(-50%, -50%); 28 | -ms-transform: translate(-50%, -50%); 29 | -o-transform: translate(-50%, -50%); 30 | 31 | background-color: #fff; 32 | box-shadow: 4px 4px 80px #000; 33 | -webkit-box-shadow: 4px 4px 80px #000; 34 | -moz-box-shadow: 4px 4px 80px #000; 35 | -ms-box-shadow: 4px 4px 80px #000; 36 | -o-box-shadow: 4px 4px 80px #000; 37 | padding: 10px; 38 | } 39 | .ng-modal-dialog-content { 40 | overflow: hidden; 41 | height: 100%; 42 | } 43 | .ng-modal-close { 44 | position: absolute; 45 | top: 3px; 46 | right: 5px; 47 | cursor: pointer; 48 | font-size: 120%; 49 | padding: 5px; 50 | display: inline-block; 51 | } 52 | .ng-modal-close-x { 53 | font-weight: bold; 54 | font-family: Arial, sans-serif; 55 | } 56 | .ng-modal-title { 57 | font-weight: bold; 58 | font-size: 200%; 59 | display: block; 60 | margin-bottom: 10px; 61 | padding-bottom: 7px; 62 | border-bottom: solid 1px #999; 63 | } 64 | -------------------------------------------------------------------------------- /vendor/browserTrigger.js: -------------------------------------------------------------------------------- 1 | // https://github.com/angular/angular.js/blob/master/src/ngScenario/browserTrigger.js 2 | 3 | 'use strict'; 4 | 5 | (function() { 6 | var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1], 10); 7 | 8 | function indexOf(array, obj) { 9 | if (array.indexOf) return array.indexOf(obj); 10 | 11 | for ( var i = 0; i < array.length; i++) { 12 | if (obj === array[i]) return i; 13 | } 14 | return -1; 15 | } 16 | 17 | 18 | 19 | /** 20 | * Triggers a browser event. Attempts to choose the right event if one is 21 | * not specified. 22 | * 23 | * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement 24 | * @param {string} eventType Optional event type 25 | * @param {Object=} eventData An optional object which contains additional event data (such as x,y 26 | * coordinates, keys, etc...) that are passed into the event when triggered 27 | */ 28 | window.browserTrigger = function browserTrigger(element, eventType, eventData) { 29 | if (element && !element.nodeName) element = element[0]; 30 | if (!element) return; 31 | 32 | eventData = eventData || {}; 33 | var keys = eventData.keys; 34 | var x = eventData.x; 35 | var y = eventData.y; 36 | 37 | var inputType = (element.type) ? element.type.toLowerCase() : null, 38 | nodeName = element.nodeName.toLowerCase(); 39 | 40 | if (!eventType) { 41 | eventType = { 42 | 'text': 'change', 43 | 'textarea': 'change', 44 | 'hidden': 'change', 45 | 'password': 'change', 46 | 'button': 'click', 47 | 'submit': 'click', 48 | 'reset': 'click', 49 | 'image': 'click', 50 | 'checkbox': 'click', 51 | 'radio': 'click', 52 | 'select-one': 'change', 53 | 'select-multiple': 'change', 54 | '_default_': 'click' 55 | }[inputType || '_default_']; 56 | } 57 | 58 | if (nodeName == 'option') { 59 | element.parentNode.value = element.value; 60 | element = element.parentNode; 61 | eventType = 'change'; 62 | } 63 | 64 | keys = keys || []; 65 | function pressed(key) { 66 | return indexOf(keys, key) !== -1; 67 | } 68 | 69 | if (msie < 9) { 70 | if (inputType == 'radio' || inputType == 'checkbox') { 71 | element.checked = !element.checked; 72 | } 73 | 74 | // WTF!!! Error: Unspecified error. 75 | // Don't know why, but some elements when detached seem to be in inconsistent state and 76 | // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error) 77 | // forcing the browser to compute the element position (by reading its CSS) 78 | // puts the element in consistent state. 79 | element.style.posLeft; 80 | 81 | // TODO(vojta): create event objects with pressed keys to get it working on IE<9 82 | var ret = element.fireEvent('on' + eventType); 83 | if (inputType == 'submit') { 84 | while(element) { 85 | if (element.nodeName.toLowerCase() == 'form') { 86 | element.fireEvent('onsubmit'); 87 | break; 88 | } 89 | element = element.parentNode; 90 | } 91 | } 92 | return ret; 93 | } else { 94 | var evnt; 95 | if(/transitionend/.test(eventType)) { 96 | if(window.WebKitTransitionEvent) { 97 | evnt = new WebKitTransitionEvent(eventType, eventData); 98 | evnt.initEvent(eventType, false, true); 99 | } 100 | else { 101 | try { 102 | evnt = new TransitionEvent(eventType, eventData); 103 | } 104 | catch(e) { 105 | evnt = document.createEvent('TransitionEvent'); 106 | evnt.initTransitionEvent(eventType, null, null, null, eventData.elapsedTime || 0); 107 | } 108 | } 109 | } 110 | else if(/animationend/.test(eventType)) { 111 | if(window.WebKitAnimationEvent) { 112 | evnt = new WebKitAnimationEvent(eventType, eventData); 113 | evnt.initEvent(eventType, false, true); 114 | } 115 | else { 116 | try { 117 | evnt = new AnimationEvent(eventType, eventData); 118 | } 119 | catch(e) { 120 | evnt = document.createEvent('AnimationEvent'); 121 | evnt.initAnimationEvent(eventType, null, null, null, eventData.elapsedTime || 0); 122 | } 123 | } 124 | } 125 | else { 126 | evnt = document.createEvent('MouseEvents'); 127 | x = x || 0; 128 | y = y || 0; 129 | evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'), 130 | pressed('alt'), pressed('shift'), pressed('meta'), 0, element); 131 | } 132 | 133 | /* we're unable to change the timeStamp value directly so this 134 | * is only here to allow for testing where the timeStamp value is 135 | * read */ 136 | evnt.$manualTimeStamp = eventData.timeStamp; 137 | 138 | if(!evnt) return; 139 | 140 | var originalPreventDefault = evnt.preventDefault, 141 | appWindow = element.ownerDocument.defaultView, 142 | fakeProcessDefault = true, 143 | finalProcessDefault, 144 | angular = appWindow.angular || {}; 145 | 146 | // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208 147 | angular['ff-684208-preventDefault'] = false; 148 | evnt.preventDefault = function() { 149 | fakeProcessDefault = false; 150 | return originalPreventDefault.apply(evnt, arguments); 151 | }; 152 | 153 | element.dispatchEvent(evnt); 154 | finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault); 155 | 156 | delete angular['ff-684208-preventDefault']; 157 | 158 | return finalProcessDefault; 159 | } 160 | }; 161 | }()); 162 | --------------------------------------------------------------------------------