'use strict'; (function() { var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1], 10); function indexOf(array, obj) { if (array.indexOf) return array.indexOf(obj); for ( var i = 0; i < array.length; i++) { if (obj === array[i]) return i; } return -1; } /** * Triggers a browser event. Attempts to choose the right event if one is * not specified. * * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement * @param {string} eventType Optional event type * @param {Object=} eventData An optional object which contains additional event data (such as x,y * coordinates, keys, etc...) that are passed into the event when triggered */ window.browserTrigger = function browserTrigger(element, eventType, eventData) { if (element && !element.nodeName) element = element[0]; if (!element) return; eventData = eventData || {}; var keys = eventData.keys; var x = eventData.x; var y = eventData.y; var inputType = (element.type) ? element.type.toLowerCase() : null, nodeName = element.nodeName.toLowerCase(); if (!eventType) { eventType = { 'text': 'change', 'textarea': 'change', 'hidden': 'change', 'password': 'change', 'button': 'click', 'submit': 'click', 'reset': 'click', 'image': 'click', 'checkbox': 'click', 'radio': 'click', 'select-one': 'change', 'select-multiple': 'change', '_default_': 'click' }[inputType || '_default_']; } if (nodeName == 'option') { element.parentNode.value = element.value; element = element.parentNode; eventType = 'change'; } keys = keys || []; function pressed(key) { return indexOf(keys, key) !== -1; } if (msie < 9) { if (inputType == 'radio' || inputType == 'checkbox') { element.checked = !element.checked; } // WTF!!! Error: Unspecified error. // Don't know why, but some elements when detached seem to be in inconsistent state and // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error) // forcing the browser to compute the element position (by reading its CSS) // puts the element in consistent state. element.style.posLeft; // TODO(vojta): create event objects with pressed keys to get it working on IE<9 var ret = element.fireEvent('on' + eventType); if (inputType == 'submit') { while(element) { if (element.nodeName.toLowerCase() == 'form') { element.fireEvent('onsubmit'); break; } element = element.parentNode; } } return ret; } else { var evnt; if(/transitionend/.test(eventType)) { if(window.WebKitTransitionEvent) { evnt = new WebKitTransitionEvent(eventType, eventData); evnt.initEvent(eventType, false, true); } else { try { evnt = new TransitionEvent(eventType, eventData); } catch(e) { evnt = document.createEvent('TransitionEvent'); evnt.initTransitionEvent(eventType, null, null, null, eventData.elapsedTime || 0); } } } else if(/animationend/.test(eventType)) { if(window.WebKitAnimationEvent) { evnt = new WebKitAnimationEvent(eventType, eventData); evnt.initEvent(eventType, false, true); } else { try { evnt = new AnimationEvent(eventType, eventData); } catch(e) { evnt = document.createEvent('AnimationEvent'); evnt.initAnimationEvent(eventType, null, null, null, eventData.elapsedTime || 0); } } } else { evnt = document.createEvent('MouseEvents'); x = x || 0; y = y || 0; evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'), pressed('alt'), pressed('shift'), pressed('meta'), 0, element); } /* we're unable to change the timeStamp value directly so this * is only here to allow for testing where the timeStamp value is * read */ evnt.$manualTimeStamp = eventData.timeStamp; if(!evnt) return; var originalPreventDefault = evnt.preventDefault, appWindow = element.ownerDocument.defaultView, fakeProcessDefault = true, finalProcessDefault, angular = appWindow.angular || {}; // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208 angular['ff-684208-preventDefault'] = false; evnt.preventDefault = function() { fakeProcessDefault = false; return originalPreventDefault.apply(evnt, arguments); }; element.dispatchEvent(evnt); finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault); delete angular['ff-684208-preventDefault']; return finalProcessDefault; } }; }());