touch.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. (function(){
  2. [Element, Window, Document].invoke('implement', {hasEvent: function(event){
  3. var events = this.retrieve('events'),
  4. list = (events && events[event]) ? events[event].values : null;
  5. if (list){
  6. for (var i = list.length; i--;) if (i in list){
  7. return true;
  8. }
  9. }
  10. return false;
  11. }});
  12. var wrap = function(custom, method, extended, name){
  13. method = custom[method];
  14. extended = custom[extended];
  15. return function(fn, customName){
  16. if (!customName) customName = name;
  17. if (extended && !this.hasEvent(customName)) extended.call(this, fn, customName);
  18. if (method) method.call(this, fn, customName);
  19. };
  20. };
  21. var inherit = function(custom, base, method, name){
  22. return function(fn, customName){
  23. base[method].call(this, fn, customName || name);
  24. custom[method].call(this, fn, customName || name);
  25. };
  26. };
  27. var events = Element.Events;
  28. Element.defineCustomEvent = function(name, custom){
  29. var base = events[custom.base];
  30. custom.onAdd = wrap(custom, 'onAdd', 'onSetup', name);
  31. custom.onRemove = wrap(custom, 'onRemove', 'onTeardown', name);
  32. events[name] = base ? Object.append({}, custom, {
  33. base: base.base,
  34. condition: function(event){
  35. return (!base.condition || base.condition.call(this, event)) &&
  36. (!custom.condition || custom.condition.call(this, event));
  37. },
  38. onAdd: inherit(custom, base, 'onAdd', name),
  39. onRemove: inherit(custom, base, 'onRemove', name)
  40. }) : custom;
  41. return this;
  42. };
  43. var loop = function(name){
  44. var method = 'on' + name.capitalize();
  45. Element[name + 'CustomEvents'] = function(){
  46. Object.each(events, function(event, name){
  47. if (event[method]) event[method].call(event, name);
  48. });
  49. };
  50. return loop;
  51. };
  52. loop('enable')('disable');
  53. })();
  54. (function(){
  55. Browser.Device = {
  56. name: 'other'
  57. };
  58. if (Browser.Platform.ios){
  59. var device = navigator.userAgent.toLowerCase().match(/(ip(ad|od|hone))/)[0];
  60. Browser.Device[device] = true;
  61. Browser.Device.name = device;
  62. }
  63. if (this.devicePixelRatio == 2)
  64. Browser.hasHighResolution = true;
  65. Browser.isMobile = !['mac', 'linux', 'win'].contains(Browser.Platform.name);
  66. }).call(this);
  67. Browser.Features.Touch = (function(){
  68. try {
  69. document.createEvent('TouchEvent').initTouchEvent('touchstart');
  70. return true;
  71. } catch (exception){}
  72. return false;
  73. })();
  74. // Android doesn't have a touch delay and dispatchEvent does not fire the handler
  75. Browser.Features.iOSTouch = (function(){
  76. var name = 'cantouch', // Name does not matter
  77. html = document.html,
  78. hasTouch = false;
  79. if (!html.addEventListener) return false;
  80. var handler = function(){
  81. html.removeEventListener(name, handler, true);
  82. hasTouch = true;
  83. };
  84. try {
  85. html.addEventListener(name, handler, true);
  86. var event = document.createEvent('TouchEvent');
  87. event.initTouchEvent(name);
  88. html.dispatchEvent(event);
  89. return hasTouch;
  90. } catch (exception){}
  91. handler(); // Remove listener
  92. return false;
  93. })();
  94. (function(){
  95. var preventDefault = function(event){
  96. if (!event.target || event.target.tagName.toLowerCase() != 'select')
  97. event.preventDefault();
  98. };
  99. var disabled;
  100. Element.defineCustomEvent('touch', {
  101. base: 'touchend',
  102. condition: function(event){
  103. if (disabled || event.targetTouches.length != 0) return false;
  104. var touch = event.changedTouches[0],
  105. target = document.elementFromPoint(touch.clientX, touch.clientY);
  106. do {
  107. if (target == this) return true;
  108. } while (target && (target = target.parentNode));
  109. return false;
  110. },
  111. onSetup: function(){
  112. this.addEvent('touchstart', preventDefault);
  113. },
  114. onTeardown: function(){
  115. this.removeEvent('touchstart', preventDefault);
  116. },
  117. onEnable: function(){
  118. disabled = false;
  119. },
  120. onDisable: function(){
  121. disabled = true;
  122. }
  123. });
  124. })();
  125. if (Browser.Features.iOSTouch) (function(){
  126. var name = 'click';
  127. delete Element.NativeEvents[name];
  128. Element.defineCustomEvent(name, {
  129. base: 'touch'
  130. });
  131. })();