1// packager build Mobile/Swipe 2/* 3--- 4 5name: Element.defineCustomEvent 6 7description: Allows to create custom events based on other custom events. 8 9authors: Christoph Pojer (@cpojer) 10 11license: MIT-style license. 12 13requires: [Core/Element.Event] 14 15provides: Element.defineCustomEvent 16 17... 18*/ 19 20(function(){ 21 22[Element, Window, Document].invoke('implement', {hasEvent: function(event){ 23 var events = this.retrieve('events'), 24 list = (events && events[event]) ? events[event].values : null; 25 if (list){ 26 var i = list.length; 27 while (i--) if (i in list){ 28 return true; 29 } 30 } 31 return false; 32}}); 33 34var wrap = function(custom, method, extended){ 35 method = custom[method]; 36 extended = custom[extended]; 37 38 return function(fn, name){ 39 if (extended && !this.hasEvent(name)) extended.call(this, fn, name); 40 if (method) method.call(this, fn, name); 41 }; 42}; 43 44var inherit = function(custom, base, method){ 45 return function(fn, name){ 46 base[method].call(this, fn, name); 47 custom[method].call(this, fn, name); 48 }; 49}; 50 51var events = Element.Events; 52 53Element.defineCustomEvent = function(name, custom){ 54 var base = events[custom.base]; 55 56 custom.onAdd = wrap(custom, 'onAdd', 'onSetup'); 57 custom.onRemove = wrap(custom, 'onRemove', 'onTeardown'); 58 59 events[name] = base ? Object.append({}, custom, { 60 61 base: base.base, 62 63 condition: function(event, name){ 64 return (!base.condition || base.condition.call(this, event, name)) && 65 (!custom.condition || custom.condition.call(this, event, name)); 66 }, 67 68 onAdd: inherit(custom, base, 'onAdd'), 69 onRemove: inherit(custom, base, 'onRemove') 70 71 }) : custom; 72 73 return this; 74}; 75 76Element.enableCustomEvents = function(){ 77 Object.each(events, function(event, name){ 78 if (event.onEnable) event.onEnable.call(event, name); 79 }); 80}; 81 82Element.disableCustomEvents = function(){ 83 Object.each(events, function(event, name){ 84 if (event.onDisable) event.onDisable.call(event, name); 85 }); 86}; 87 88})(); 89 90 91/* 92--- 93 94name: Browser.Features.Touch 95 96description: Checks whether the used Browser has touch events 97 98authors: Christoph Pojer (@cpojer) 99 100license: MIT-style license. 101 102requires: [Core/Browser] 103 104provides: Browser.Features.Touch 105 106... 107*/ 108 109Browser.Features.Touch = (function(){ 110 try { 111 document.createEvent('TouchEvent').initTouchEvent('touchstart'); 112 return true; 113 } catch (exception){} 114 115 return false; 116})(); 117 118// Android doesn't have a touch delay and dispatchEvent does not fire the handler 119Browser.Features.iOSTouch = (function(){ 120 var name = 'cantouch', // Name does not matter 121 html = document.html, 122 hasTouch = false; 123 124 if (!html.addEventListener) return false; 125 126 var handler = function(){ 127 html.removeEventListener(name, handler, true); 128 hasTouch = true; 129 }; 130 131 try { 132 html.addEventListener(name, handler, true); 133 var event = document.createEvent('TouchEvent'); 134 event.initTouchEvent(name); 135 html.dispatchEvent(event); 136 return hasTouch; 137 } catch (exception){} 138 139 handler(); // Remove listener 140 return false; 141})(); 142 143 144/* 145--- 146 147name: Swipe 148 149description: Provides a custom swipe event for touch devices 150 151authors: Christopher Beloch (@C_BHole), Christoph Pojer (@cpojer), Ian Collins (@3n) 152 153license: MIT-style license. 154 155requires: [Core/Element.Event, Custom-Event/Element.defineCustomEvent, Browser.Features.Touch] 156 157provides: Swipe 158 159... 160*/ 161 162(function(){ 163 164var name = 'swipe', 165 distanceKey = name + ':distance', 166 cancelKey = name + ':cancelVertical', 167 dflt = 50; 168 169var start = {}, disabled, active; 170 171var clean = function(){ 172 active = false; 173}; 174 175var events = { 176 177 touchstart: function(event){ 178 if (event.touches.length > 1) return; 179 180 var touch = event.touches[0]; 181 active = true; 182 start = {x: touch.pageX, y: touch.pageY}; 183 }, 184 185 touchmove: function(event){ 186 if (disabled || !active) return; 187 188 var touch = event.changedTouches[0], 189 end = {x: touch.pageX, y: touch.pageY}; 190 if (this.retrieve(cancelKey) && Math.abs(start.y - end.y) > 10){ 191 active = false; 192 return; 193 } 194 195 var distance = this.retrieve(distanceKey, dflt), 196 delta = end.x - start.x, 197 isLeftSwipe = delta < -distance, 198 isRightSwipe = delta > distance; 199 200 if (!isRightSwipe && !isLeftSwipe) 201 return; 202 203 event.preventDefault(); 204 active = false;
205 event.direction = (isLeftSwipe ? 'left' : 'right'); 206 event.start = start; 207 event.end = end; 208 209 this.fireEvent(name, event); 210 }, 211 212 touchend: clean, 213 touchcancel: clean 214 215}; 216 217Element.defineCustomEvent(name, { 218 219 onSetup: function(){ 220 this.addEvents(events); 221 }, 222 223 onTeardown: function(){ 224 this.removeEvents(events); 225 }, 226 227 onEnable: function(){ 228 disabled = false; 229 }, 230 231 onDisable: function(){ 232 disabled = true; 233 clean(); 234 } 235 236}); 237 238})(); 239
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.