jquery.event.ue

Jquery plugin for unified mouse and touch events

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/6421/24600/jqueryeventue.js

  1. /*
  2. * Jquery plugin for unified mouse and touch events
  3. *
  4. * Copyright (c) 2013 Michael S. Mikowski
  5. * (mike[dot]mikowski[at]gmail[dotcom])
  6. *
  7. * Dual licensed under the MIT or GPL Version 2
  8. * http://jquery.org/license
  9. *
  10. * Versions
  11. * 0.3.0 - Initial jQuery plugin site release
  12. * - Replaced scrollwheel zoom with drag motion.
  13. * This resolved a conflict with scrollable areas.
  14. * 0.3.1 - Change for jQuery plugins site
  15. * 0.3.2 - Updated to jQuery 1.9.1.
  16. * Confirmed 1.7.0-1.9.1 compatibility.
  17. *
  18. */
  19.  
  20. /*jslint browser : true, continue : true,
  21. devel : true, indent : 2, maxerr : 50,
  22. newcap : true, plusplus : true, regexp : true,
  23. sloppy : true, vars : true, white : true
  24. */
  25. /*global jQuery, sl */
  26.  
  27. (function ( $ ) {
  28. //---------------- BEGIN MODULE SCOPE VARIABLES --------------
  29. var
  30. $Special = $.event.special, // shortcut for special event
  31. motionMapMap = {}, // map of pointer motions by cursor
  32. isMoveBound = false, // flag if move handlers bound
  33. pxPinchZoom = -1, // distance between pinch-zoom points
  34. optionKey = 'ue_bound', // data key for storing options
  35. doDisableMouse = false, // flag to discard mouse input
  36. defaultOptMap = { // Default option hash
  37. bound_ns_map : {}, // namspace hash e.g. bound_ns_map.utap.fred
  38. wheel_ratio : 15, // multiplier for mousewheel delta
  39. px_radius : 3, // 'distance' dragged before dragstart
  40. ignore_class : ':input', // 'not' suppress matching elements
  41. tap_time : 200, // millisecond max time to consider tap
  42. held_tap_time : 300 // millisecond min time to consider taphold
  43. },
  44. callbackList = [], // global callback stack
  45. zoomMouseNum = 1, // multiplier for mouse zoom
  46. zoomTouchNum = 4, // multiplier for touch zoom
  47.  
  48. boundList, Ue,
  49. motionDragId, motionHeldId, motionDzoomId,
  50. motion1ZoomId, motion2ZoomId,
  51.  
  52. checkMatchVal, removeListVal, pushUniqVal, makeListPlus,
  53. fnHeld, fnMotionStart, fnMotionMove,
  54. fnMotionEnd, onMouse, onTouch,
  55. onMousewheel
  56. ;
  57. //----------------- END MODULE SCOPE VARIABLES ---------------
  58.  
  59. //------------------- BEGIN UTILITY METHODS ------------------
  60. // Begin utiltity /makeListPlus/
  61. // Returns an array with much desired methods:
  62. // * remove_val(value) : remove element that matches
  63. // the provided value. Returns number of elements
  64. // removed.
  65. // * match_val(value) : shows if a value exists
  66. // * push_uniq(value) : pushes a value onto the stack
  67. // iff it does not already exist there
  68. // Note: the reason I need this is to compare objects to
  69. // objects (perhaps jQuery has something similar?)
  70. checkMatchVal = function ( data ) {
  71. var match_count = 0, idx;
  72. for ( idx = this.length; idx; 0 ) {
  73. if ( this[--idx] === data ) { match_count++; }
  74. }
  75. return match_count;
  76. };
  77. removeListVal = function ( data ) {
  78. var removed_count = 0, idx;
  79. for ( idx = this.length; idx; 0 ) {
  80. if ( this[--idx] === data ) {
  81. this.splice(idx, 1);
  82. removed_count++;
  83. idx++;
  84. }
  85. }
  86. return removed_count;
  87. };
  88. pushUniqVal = function ( data ) {
  89. if ( checkMatchVal.call(this, data ) ) { return false; }
  90. this.push( data );
  91. return true;
  92. };
  93. // primary utility
  94. makeListPlus = function ( input_list ) {
  95. if ( input_list && $.isArray(input_list) ) {
  96. if ( input_list.remove_val ) {
  97. console.warn( 'The array appears to already have listPlus capabilities' );
  98. return input_list;
  99. }
  100. }
  101. else {
  102. input_list = [];
  103. }
  104. input_list.remove_val = removeListVal;
  105. input_list.match_val = checkMatchVal;
  106. input_list.push_uniq = pushUniqVal;
  107.  
  108. return input_list;
  109. };
  110. // End utility /makeListPlus/
  111. //-------------------- END UTILITY METHODS -------------------
  112.  
  113. //--------------- BEGIN JQUERY SPECIAL EVENTS ----------------
  114. // Unique array for bound objects
  115. boundList = makeListPlus();
  116.  
  117. // Begin define special event handlers
  118. Ue = {
  119. setup : function( data, a_names, fn_bind ) {
  120. var
  121. elem_this = this,
  122. $to_bind = $(elem_this),
  123. seen_map = {},
  124. option_map, idx, namespace_key, ue_namespace_code, namespace_list
  125. ;
  126.  
  127. // if previous related event bound do not rebind, but do add to
  128. // type of event bound to this element, if not already noted
  129. if ( $.data( this, optionKey ) ) { return; }
  130.  
  131. option_map = {};
  132. $.extend( true, option_map, defaultOptMap );
  133. $.data( elem_this, optionKey, option_map );
  134.  
  135. namespace_list = makeListPlus(a_names.slice(0));
  136. if ( ! namespace_list.length
  137. || namespace_list[0] === ""
  138. ) { namespace_list = ["000"]; }
  139.  
  140. NSPACE_00:
  141. for ( idx = 0; idx < namespace_list.length; idx++ ) {
  142. namespace_key = namespace_list[idx];
  143.  
  144. if ( ! namespace_key ) { continue NSPACE_00; }
  145. if ( seen_map.hasOwnProperty(namespace_key) ) { continue NSPACE_00; }
  146.  
  147. seen_map[namespace_key] = true;
  148.  
  149. ue_namespace_code = '.__ue' + namespace_key;
  150.  
  151. $to_bind.bind( 'mousedown' + ue_namespace_code, onMouse );
  152. $to_bind.bind( 'touchstart' + ue_namespace_code, onTouch );
  153. $to_bind.bind( 'mousewheel' + ue_namespace_code, onMousewheel );
  154. }
  155.  
  156. boundList.push_uniq( elem_this ); // record as bound element
  157.  
  158. if ( ! isMoveBound ) {
  159. // console.log('first element bound - adding global binds');
  160. $(document).bind( 'mousemove.__ue', onMouse );
  161. $(document).bind( 'touchmove.__ue', onTouch );
  162. $(document).bind( 'mouseup.__ue' , onMouse );
  163. $(document).bind( 'touchend.__ue' , onTouch );
  164. isMoveBound = true;
  165. }
  166. },
  167.  
  168. // arg_map.type = string - name of event to bind
  169. // arg_map.data = poly - whatever (optional) data was passed when binding
  170. // arg_map.namespace = string - A sorted, dot-delimited list of namespaces
  171. // specified when binding the event
  172. // arg_map.handler = fn - the event handler the developer wishes to be bound
  173. // to the event. This function should be called whenever the event
  174. // is triggered
  175. // arg_map.guid = number - unique ID for event handler, provided by jQuery
  176. // arg_map.selector = string - selector used by 'delegate' or 'live' jQuery
  177. // methods. Only available when these methods are used.
  178. //
  179. // this - the element to which the event handler is being bound
  180. // this always executes immediate after setup (if first binding)
  181. add : function ( arg_map ) {
  182. var
  183. elem_this = this,
  184. option_map = $.data( elem_this, optionKey ),
  185. namespace_str = arg_map.namespace,
  186. event_type = arg_map.type,
  187. bound_ns_map, namespace_list, idx, namespace_key
  188. ;
  189. if ( ! option_map ) { return; }
  190.  
  191. bound_ns_map = option_map.bound_ns_map;
  192.  
  193. if ( ! bound_ns_map[event_type] ) {
  194. // this indicates a non-namespaced entry
  195. bound_ns_map[event_type] = {};
  196. }
  197.  
  198. if ( ! namespace_str ) { return; }
  199.  
  200. namespace_list = namespace_str.split('.');
  201.  
  202. for ( idx = 0; idx < namespace_list.length; idx++ ) {
  203. namespace_key = namespace_list[idx];
  204. bound_ns_map[event_type][namespace_key] = true;
  205. }
  206. },
  207.  
  208. remove : function ( arg_map ) {
  209. var
  210. elem_bound = this,
  211. option_map = $.data( elem_bound, optionKey ),
  212. bound_ns_map = option_map.bound_ns_map,
  213. event_type = arg_map.type,
  214. namespace_str = arg_map.namespace,
  215. namespace_list, idx, namespace_key
  216. ;
  217.  
  218. if ( ! bound_ns_map[event_type] ) { return; }
  219.  
  220. // No namespace(s) provided:
  221. // Remove complete record for custom event type (e.g. utap)
  222. if ( ! namespace_str ) {
  223. delete bound_ns_map[event_type];
  224. return;
  225. }
  226.  
  227. // Namespace(s) provided:
  228. // Remove namespace flags from each custom event typei (e.g. utap)
  229. // record. If all claimed namespaces are removed, remove
  230. // complete record.
  231. namespace_list = namespace_str.split('.');
  232.  
  233. for ( idx = 0; idx < namespace_list.length; idx++ ) {
  234. namespace_key = namespace_list[idx];
  235. if (bound_ns_map[event_type][namespace_key]) {
  236. delete bound_ns_map[event_type][namespace_key];
  237. }
  238. }
  239.  
  240. if ( $.isEmptyObject( bound_ns_map[event_type] ) ) {
  241. delete bound_ns_map[event_type];
  242. }
  243. },
  244.  
  245. teardown : function( a_names ) {
  246. var
  247. elem_bound = this,
  248. $bound = $(elem_bound),
  249. option_map = $.data( elem_bound, optionKey ),
  250. bound_ns_map = option_map.bound_ns_map,
  251. idx, namespace_key, ue_namespace_code, namespace_list
  252. ;
  253.  
  254. // do not tear down if related handlers are still bound
  255. if ( ! $.isEmptyObject( bound_ns_map ) ) { return; }
  256.  
  257. namespace_list = makeListPlus(a_names);
  258. namespace_list.push_uniq('000');
  259.  
  260. NSPACE_01:
  261. for ( idx = 0; idx < namespace_list.length; idx++ ) {
  262. namespace_key = namespace_list[idx];
  263.  
  264. if ( ! namespace_key ) { continue NSPACE_01; }
  265.  
  266. ue_namespace_code = '.__ue' + namespace_key;
  267. $bound.unbind( 'mousedown' + ue_namespace_code );
  268. $bound.unbind( 'touchstart' + ue_namespace_code );
  269. $bound.unbind( 'mousewheel' + ue_namespace_code );
  270. }
  271.  
  272. $.removeData( elem_bound, optionKey );
  273.  
  274. // Unbind document events only after last element element is removed
  275. boundList.remove_val(this);
  276. if ( boundList.length === 0 ) {
  277. // console.log('last bound element removed - removing global binds');
  278. $(document).unbind( 'mousemove.__ue');
  279. $(document).unbind( 'touchmove.__ue');
  280. $(document).unbind( 'mouseup.__ue');
  281. $(document).unbind( 'touchend.__ue');
  282. isMoveBound = false;
  283. }
  284. }
  285. };
  286. // End define special event handlers
  287. //--------------- BEGIN JQUERY SPECIAL EVENTS ----------------
  288.  
  289. //------------------ BEGIN MOTION CONTROLS -------------------
  290. // Begin motion control /fnHeld/
  291. fnHeld = function ( arg_map ) {
  292. var
  293. timestamp = +new Date(),
  294. motion_id = arg_map.motion_id,
  295. motion_map = arg_map.motion_map,
  296. bound_ns_map = arg_map.bound_ns_map,
  297. event_ue
  298. ;
  299.  
  300. delete motion_map.idto_tapheld;
  301.  
  302. if ( ! motion_map.do_allow_tap ) { return; }
  303.  
  304. motion_map.px_end_x = motion_map.px_start_x;
  305. motion_map.px_end_y = motion_map.px_start_y;
  306. motion_map.ms_timestop = timestamp;
  307. motion_map.ms_elapsed = timestamp - motion_map.ms_timestart;
  308.  
  309. if ( bound_ns_map.uheld ) {
  310. event_ue = $.Event('uheld');
  311. $.extend( event_ue, motion_map );
  312. $(motion_map.elem_bound).trigger(event_ue);
  313. }
  314.  
  315. // remove tracking, as we want no futher action on this motion
  316. if ( bound_ns_map.uheldstart ) {
  317. event_ue = $.Event('uheldstart');
  318. $.extend( event_ue, motion_map );
  319. $(motion_map.elem_bound).trigger(event_ue);
  320. motionHeldId = motion_id;
  321. }
  322. else {
  323. delete motionMapMap[motion_id];
  324. }
  325. };
  326. // End motion control /fnHeld/
  327.  
  328.  
  329. // Begin motion control /fnMotionStart/
  330. fnMotionStart = function ( arg_map ) {
  331. var
  332. motion_id = arg_map.motion_id,
  333. event_src = arg_map.event_src,
  334. request_dzoom = arg_map.request_dzoom,
  335.  
  336. option_map = $.data( arg_map.elem, optionKey ),
  337. bound_ns_map = option_map.bound_ns_map,
  338. $target = $(event_src.target ),
  339. do_zoomstart = false,
  340. motion_map, cb_map, do_allow_tap, event_ue
  341. ;
  342.  
  343. // this should never happen, but it does
  344. if ( motionMapMap[ motion_id ] ) { return; }
  345.  
  346. if ( request_dzoom && ! bound_ns_map.uzoomstart ) { return; }
  347.  
  348. // :input selector includes text areas
  349. if ( $target.is( option_map.ignore_class ) ) { return; }
  350.  
  351. do_allow_tap = bound_ns_map.utap
  352. || bound_ns_map.uheld || bound_ns_map.uheldstart
  353. ? true : false;
  354.  
  355. cb_map = callbackList.pop();
  356.  
  357. while ( cb_map ) {
  358. if ( $target.is( cb_map.selector_str )
  359. || $( arg_map.elem ).is( cb_map.selector_str )
  360. ) {
  361. if ( cb_map.callback_match ) {
  362. cb_map.callback_match( arg_map );
  363. }
  364. }
  365. else {
  366. if ( cb_map.callback_nomatch ) {
  367. cb_map.callback_nomatch( arg_map );
  368. }
  369. }
  370. cb_map = callbackList.pop();
  371. }
  372.  
  373. motion_map = {
  374. do_allow_tap : do_allow_tap,
  375. elem_bound : arg_map.elem,
  376. elem_target : event_src.target,
  377. ms_elapsed : 0,
  378. ms_timestart : event_src.timeStamp,
  379. ms_timestop : undefined,
  380. option_map : option_map,
  381. orig_target : event_src.target,
  382. px_current_x : event_src.clientX,
  383. px_current_y : event_src.clientY,
  384. px_end_x : undefined,
  385. px_end_y : undefined,
  386. px_start_x : event_src.clientX,
  387. px_start_y : event_src.clientY,
  388. timeStamp : event_src.timeStamp
  389. };
  390.  
  391. motionMapMap[ motion_id ] = motion_map;
  392.  
  393. if ( bound_ns_map.uzoomstart ) {
  394. if ( request_dzoom ) {
  395. motionDzoomId = motion_id;
  396. }
  397. else if ( ! motion1ZoomId ) {
  398. motion1ZoomId = motion_id;
  399. }
  400. else if ( ! motion2ZoomId ) {
  401. motion2ZoomId = motion_id;
  402. event_ue = $.Event('uzoomstart');
  403. do_zoomstart = true;
  404. }
  405.  
  406. if ( do_zoomstart ) {
  407. event_ue = $.Event( 'uzoomstart' );
  408. motion_map.px_delta_zoom = 0;
  409. $.extend( event_ue, motion_map );
  410. $(motion_map.elem_bound).trigger(event_ue);
  411. return;
  412. }
  413. }
  414.  
  415. if ( bound_ns_map.uheld || bound_ns_map.uheldstart ) {
  416. motion_map.idto_tapheld = setTimeout(
  417. function() {
  418. fnHeld({
  419. motion_id : motion_id,
  420. motion_map : motion_map,
  421. bound_ns_map : bound_ns_map
  422. });
  423. },
  424. option_map.held_tap_time
  425. );
  426. }
  427. };
  428. // End motion control /fnMotionStart/
  429.  
  430. // Begin motion control /fnMotionMove/
  431. fnMotionMove = function ( arg_map ) {
  432. var
  433. motion_id = arg_map.motion_id,
  434. event_src = arg_map.event_src,
  435. do_zoommove = false,
  436. motion_map, option_map, bound_ns_map,
  437. event_ue, px_pinch_zoom, px_delta_zoom,
  438. mzoom1_map, mzoom2_map
  439. ;
  440.  
  441. if ( ! motionMapMap[motion_id] ) { return; }
  442.  
  443. motion_map = motionMapMap[motion_id];
  444. option_map = motion_map.option_map;
  445. bound_ns_map = option_map.bound_ns_map;
  446.  
  447. motion_map.timeStamp = event_src.timeStamp;
  448. motion_map.elem_target = event_src.target;
  449. motion_map.ms_elapsed = event_src.timeStamp - motion_map.ms_timestart;
  450.  
  451. motion_map.px_delta_x = event_src.clientX - motion_map.px_current_x;
  452. motion_map.px_delta_y = event_src.clientY - motion_map.px_current_y;
  453.  
  454. motion_map.px_current_x = event_src.clientX;
  455. motion_map.px_current_y = event_src.clientY;
  456.  
  457. // native event object override
  458. motion_map.timeStamp = event_src.timeStamp;
  459.  
  460. // disallow tap if outside of zone or time elapsed
  461. // we use this for other events, so we do it every time
  462. if ( motion_map.do_allow_tap ) {
  463. if ( Math.abs(motion_map.px_delta_x) > option_map.px_radius
  464. || Math.abs(motion_map.pd_delta_y) > option_map.px_radius
  465. || motion_map.ms_elapsed > option_map.tap_time
  466. ) { motion_map.do_allow_tap = false; }
  467. }
  468.  
  469. if ( motion1ZoomId && motion2ZoomId
  470. && ( motion_id === motion1ZoomId
  471. || motion_id === motion2ZoomId
  472. )) {
  473. motionMapMap[motion_id] = motion_map;
  474. mzoom1_map = motionMapMap[motion1ZoomId];
  475. mzoom2_map = motionMapMap[motion2ZoomId];
  476.  
  477. px_pinch_zoom = Math.floor(
  478. Math.sqrt(
  479. Math.pow((mzoom1_map.px_current_x - mzoom2_map.px_current_x),2)
  480. + Math.pow((mzoom1_map.px_current_y - mzoom2_map.px_current_y),2)
  481. ) +0.5
  482. );
  483.  
  484. if ( pxPinchZoom === -1 ) { px_delta_zoom = 0; }
  485. else { px_delta_zoom = ( px_pinch_zoom - pxPinchZoom ) * zoomTouchNum;}
  486.  
  487. // save value for next iteration delta comparison
  488. pxPinchZoom = px_pinch_zoom;
  489. do_zoommove = true;
  490. }
  491. else if ( motionDzoomId === motion_id ) {
  492. if ( bound_ns_map.uzoommove ) {
  493. px_delta_zoom = motion_map.px_delta_y * zoomMouseNum;
  494. do_zoommove = true;
  495. }
  496. }
  497.  
  498. if ( do_zoommove ){
  499. event_ue = $.Event('uzoommove');
  500. motion_map.px_delta_zoom = px_delta_zoom;
  501. $.extend( event_ue, motion_map );
  502. $(motion_map.elem_bound).trigger(event_ue);
  503. return;
  504. }
  505.  
  506. if ( motionHeldId === motion_id ) {
  507. if ( bound_ns_map.uheldmove ) {
  508. event_ue = $.Event('uheldmove');
  509. $.extend( event_ue, motion_map );
  510. $(motion_map.elem_bound).trigger(event_ue);
  511. event_src.preventDefault();
  512. }
  513. }
  514. else if ( motionDragId === motion_id ) {
  515. if ( bound_ns_map.udragmove ) {
  516. event_ue = $.Event('udragmove');
  517. $.extend( event_ue, motion_map );
  518. $(motion_map.elem_bound).trigger(event_ue);
  519. event_src.preventDefault();
  520. }
  521. }
  522.  
  523. if ( ! motionDragId
  524. && ! motionHeldId
  525. && bound_ns_map.udragstart
  526. && motion_map.do_allow_tap === false
  527. ) {
  528. motionDragId = motion_id;
  529. event_ue = $.Event('udragstart');
  530. $.extend( event_ue, motion_map );
  531. $(motion_map.elem_bound).trigger(event_ue);
  532. event_src.preventDefault();
  533.  
  534. if ( motion_map.idto_tapheld ) {
  535. clearTimeout(motion_map.idto_tapheld);
  536. delete motion_map.idto_tapheld;
  537. }
  538. }
  539. };
  540. // End motion control /fnMotionMove/
  541.  
  542. // Begin motion control /fnMotionEnd/
  543. fnMotionEnd = function ( arg_map ) {
  544. var
  545. motion_id = arg_map.motion_id,
  546. event_src = arg_map.event_src,
  547. do_zoomend = false,
  548. motion_map, option_map, bound_ns_map, event_ue
  549. ;
  550.  
  551. doDisableMouse = false;
  552.  
  553. if ( ! motionMapMap[motion_id] ) { return; }
  554.  
  555. motion_map = motionMapMap[motion_id];
  556. option_map = motion_map.option_map;
  557. bound_ns_map = option_map.bound_ns_map;
  558.  
  559. motion_map.elem_target = event_src.target;
  560. motion_map.ms_elapsed = event_src.timeStamp - motion_map.ms_timestart;
  561. motion_map.ms_timestop = event_src.timeStamp;
  562.  
  563. if ( motion_map.px_current_x ) {
  564. motion_map.px_delta_x = event_src.clientX - motion_map.px_current_x;
  565. motion_map.px_delta_y = event_src.clientY - motion_map.px_current_y;
  566. }
  567.  
  568. motion_map.px_current_x = event_src.clientX;
  569. motion_map.px_current_y = event_src.clientY;
  570.  
  571. motion_map.px_end_x = event_src.clientX;
  572. motion_map.px_end_y = event_src.clientY;
  573.  
  574. // native event object override
  575. motion_map.timeStamp = event_src.timeStamp
  576. ;
  577.  
  578. // clear-out any long-hold tap timer
  579. if ( motion_map.idto_tapheld ) {
  580. clearTimeout(motion_map.idto_tapheld);
  581. delete motion_map.idto_tapheld;
  582. }
  583.  
  584. // trigger utap
  585. if ( bound_ns_map.utap
  586. && motion_map.ms_elapsed <= option_map.tap_time
  587. && motion_map.do_allow_tap
  588. ) {
  589. event_ue = $.Event('utap');
  590. $.extend( event_ue, motion_map );
  591. $(motion_map.elem_bound).trigger(event_ue);
  592. }
  593.  
  594. // trigger udragend
  595. if ( motion_id === motionDragId ) {
  596. if ( bound_ns_map.udragend ) {
  597. event_ue = $.Event('udragend');
  598. $.extend( event_ue, motion_map );
  599. $(motion_map.elem_bound).trigger(event_ue);
  600. event_src.preventDefault();
  601. }
  602. motionDragId = undefined;
  603. }
  604.  
  605. // trigger heldend
  606. if ( motion_id === motionHeldId ) {
  607. if ( bound_ns_map.uheldend ) {
  608. event_ue = $.Event('uheldend');
  609. $.extend( event_ue, motion_map );
  610. $(motion_map.elem_bound).trigger(event_ue);
  611. }
  612. motionHeldId = undefined;
  613. }
  614.  
  615. // trigger uzoomend
  616. if ( motion_id === motionDzoomId ) {
  617. do_zoomend = true;
  618. motionDzoomId = undefined;
  619. }
  620.  
  621. // cleanup zoom info
  622. else if ( motion_id === motion1ZoomId ) {
  623. if ( motion2ZoomId ) {
  624. motion1ZoomId = motion2ZoomId;
  625. motion2ZoomId = undefined;
  626. do_zoomend = true;
  627. }
  628. else { motion1ZoomId = undefined; }
  629. pxPinchZoom = -1;
  630. }
  631. if ( motion_id === motion2ZoomId ) {
  632. motion2ZoomId = undefined;
  633. pxPinchZoom = -1;
  634. do_zoomend = true;
  635. }
  636.  
  637. if ( do_zoomend && bound_ns_map.uzoomend ) {
  638. event_ue = $.Event('uzoomend');
  639. motion_map.px_delta_zoom = 0;
  640. $.extend( event_ue, motion_map );
  641. $(motion_map.elem_bound).trigger(event_ue);
  642. }
  643. // remove pointer from consideration
  644. delete motionMapMap[motion_id];
  645. };
  646. // End motion control /fnMotionEnd/
  647. //------------------ END MOTION CONTROLS -------------------
  648.  
  649. //------------------- BEGIN EVENT HANDLERS -------------------
  650. // Begin event handler /onTouch/ for all touch events.
  651. // We use the 'type' attribute to dispatch to motion control
  652. onTouch = function ( event ) {
  653. var
  654. elem_this = this,
  655. timestamp = +new Date(),
  656. o_event = event.originalEvent,
  657. a_touches = o_event.changedTouches || [],
  658. idx, touch_event, motion_id,
  659. handler_fn
  660. ;
  661.  
  662. doDisableMouse = true;
  663.  
  664. event.timeStamp = timestamp;
  665.  
  666. switch ( event.type ) {
  667. case 'touchstart' : handler_fn = fnMotionStart; break;
  668. case 'touchmove' :
  669. handler_fn = fnMotionMove;
  670. break;
  671. case 'touchend' : handler_fn = fnMotionEnd; break;
  672. default : handler_fn = null;
  673. }
  674.  
  675. if ( ! handler_fn ) { return; }
  676.  
  677. for ( idx = 0; idx < a_touches.length; idx++ ) {
  678. touch_event = a_touches[idx];
  679.  
  680. motion_id = 'touch' + String(touch_event.identifier);
  681.  
  682. event.clientX = touch_event.clientX;
  683. event.clientY = touch_event.clientY;
  684. handler_fn({
  685. elem : elem_this,
  686. motion_id : motion_id,
  687. event_src : event
  688. });
  689. }
  690. };
  691. // End event handler /onTouch/
  692.  
  693.  
  694. // Begin event handler /onMouse/ for all mouse events
  695. // We use the 'type' attribute to dispatch to motion control
  696. onMouse = function ( event ) {
  697. var
  698. elem_this = this,
  699. motion_id = 'mouse' + String(event.button),
  700. request_dzoom = false,
  701. handler_fn
  702. ;
  703.  
  704. if ( doDisableMouse ) {
  705. event.stopImmediatePropagation();
  706. return;
  707. }
  708.  
  709. if ( event.shiftKey ) { request_dzoom = true; }
  710.  
  711. // skip left or middle clicks
  712. if ( event.type !== 'mousemove' ) {
  713. if ( event.button !== 0 ) { return true; }
  714. }
  715.  
  716. switch ( event.type ) {
  717. case 'mousedown' : handler_fn = fnMotionStart; event.preventDefault(); break;
  718. case 'mouseup' : handler_fn = fnMotionEnd; break;
  719. case 'mousemove' :
  720. handler_fn = fnMotionMove;
  721. event.preventDefault();
  722. break;
  723. default : handler_fn = null;
  724. }
  725.  
  726. if ( ! handler_fn ) { return; }
  727.  
  728. handler_fn({
  729. elem : elem_this,
  730. event_src : event,
  731. request_dzoom : request_dzoom,
  732. motion_id : motion_id
  733. });
  734. };
  735. // End event handler /onMouse/
  736. //-------------------- END EVENT HANDLERS --------------------
  737.  
  738.  
  739. // Export special events through jQuery API
  740. $Special.ue
  741. = $Special.utap = $Special.uheld
  742. = $Special.uzoomstart = $Special.uzoommove = $Special.uzoomend
  743. = $Special.udragstart = $Special.udragmove = $Special.udragend
  744. = $Special.uheldstart = $Special.uheldmove = $Special.uheldend
  745. = Ue
  746. ;
  747. $.ueSetGlobalCb = function ( selector_str, callback_match, callback_nomatch ) {
  748. callbackList.push( {
  749. selector_str : selector_str || '',
  750. callback_match : callback_match || null,
  751. callback_nomatch : callback_nomatch || null
  752. });
  753. };
  754.  
  755. }(jQuery));
  756.