1/* 2 * jQuery dragscrollable Plugin 3 * version: 1.0 (25-Jun-2009) 4 * Copyright (c) 2009 Miquel Herrera 5 * 6 * Portions Copyright (c) 2010 Reg Braithwaite 7 * Copyright (c) 2010 Internet Archive / Michael Ang 8 * 9 * Dual licensed under the MIT and GPL licenses: 10 * http://www.opensource.org/licenses/mit-license.php 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 */ 14;(function($){ // secure $ jQuery alias 15 16/** 17 * Adds the ability to manage elements scroll by dragging 18 * one or more of its descendant elements. Options parameter 19 * allow to specifically select which inner elements will 20 * respond to the drag events. 21 * 22 * options properties: 23 * ------------------------------------------------------------------------ 24 * dragSelector | jquery selector to apply to each wrapped element 25 * | to find which will be the dragging elements. 26 * | Defaults to '>:first' which is the first child of 27 * | scrollable element 28 * ------------------------------------------------------------------------ 29 * acceptPropagatedEvent| Will the dragging element accept propagated 30 * | events? default is yes, a propagated mouse event 31 * | on a inner element will be accepted and processed. 32 * | If set to false, only events originated on the 33 * | draggable elements will be processed. 34 * ------------------------------------------------------------------------ 35 * preventDefault | Prevents the event to propagate further effectivey 36 * | dissabling other default actions. Defaults to true 37 * ------------------------------------------------------------------------ 38 * scrollWindow | Scroll the window rather than the element 39 * | Defaults to false 40 * ------------------------------------------------------------------------ 41 * 42 * usage examples: 43 * 44 * To add the scroll by drag to the element id=viewport when dragging its 45 * first child accepting any propagated events 46 * $('#viewport').dragscrollable(); 47 * 48 * To add the scroll by drag ability to any element div of class viewport 49 * when dragging its first descendant of class dragMe responding only to 50 * evcents originated on the '.dragMe' elements. 51 * $('div.viewport').dragscrollable({dragSelector:'.dragMe:first', 52 * acceptPropagatedEvent: false}); 53 * 54 * Notice that some 'viewports' could be nested within others but events 55 * would not interfere as acceptPropagatedEvent is set to false. 56 * 57 */ 58 59var append_namespace = function (string_of_events, ns) { 60 61 /* IE doesn't have map 62 return string_of_events 63 .split(' ') 64 .map(function (name) { return name + ns; }) 65 .join(' '); 66 */ 67 var pieces = string_of_events.split(' '); 68 var ret = new Array(); 69 for (var i = 0; i < pieces.length; i++) { 70 ret.push(pieces[i] + ns); 71 } 72 return ret.join(' '); 73}; 74 75var left_top = function(event) { 76 77 var x; 78 var y; 79 if (typeof(event.clientX) != 'undefined') { 80 x = event.clientX; 81 y = event.clientY; 82 } 83 else if (typeof(event.screenX) != 'undefined') { 84 x = event.screenX; 85 y = event.screenY; 86 } 87 else if (typeof(event.targetTouches) != 'undefined') { 88 x = event.targetTouches[0].pageX; 89 y = event.targetTouches[0].pageY; 90 } 91 else if (typeof(event.originalEvent) == 'undefined') { 92 var str = ''; 93 for (i in event) { 94 str += ', ' + i + ': ' + event[i]; 95 } 96 console.error("don't understand x and y for " + event.type + ' event: ' + str); 97 } 98 else if (typeof(event.originalEvent.clientX) != 'undefined') { 99 x = event.originalEvent.clientX; 100 y = event.originalEvent.clientY; 101 } 102 else if (typeof(event.originalEvent.screenX) != 'undefined') { 103 x = event.originalEvent.screenX; 104 y = event.originalEvent.screenY; 105 } 106 else if (typeof(event.originalEvent.targetTouches) != 'undefined') { 107 x = event.originalEvent.targetTouches[0].pageX; 108 y = event.originalEvent.targetTouches[0].pageY; 109 } 110 111 return {left: x, top:y}; 112}; 113 114$.fn.dragscrollable = function( options ) { 115 116 var handling_element = $(this); 117 118 var settings = $.extend( 119 { 120 dragSelector:'>:first', 121 acceptPropagatedEvent: true, 122 preventDefault: true, 123 dragstart: 'mousedown touchstart',
124 dragcontinue: 'mousemove touchmove', 125 dragend: 'mouseup mouseleave touchend', 126 dragMinDistance: 5, 127 namespace: '.ds', 128 scrollWindow: false 129 },options || {}); 130 131 settings.dragstart = append_namespace(settings.dragstart, settings.namespace); 132 settings.dragcontinue = append_namespace(settings.dragcontinue, settings.namespace); 133 settings.dragend = append_namespace(settings.dragend, settings.namespace); 134 135 var dragscroll= { 136 dragStartHandler : function(event) { 137 // console.log('dragstart'); 138 139 // mousedown, left click, check propagation 140 if (event.which > 1 || 141 (!event.data.acceptPropagatedEvent && event.target != this)){ 142 return false; 143 } 144 145 event.data.firstCoord = left_top(event); 146 // Initial coordinates will be the last when dragging 147 event.data.lastCoord = event.data.firstCoord; 148 149 handling_element 150 .bind(settings.dragcontinue, event.data, dragscroll.dragContinueHandler) 151 .bind(settings.dragend, event.data, dragscroll.dragEndHandler); 152 153 if (event.data.preventDefault) { 154 event.preventDefault(); 155 return false; 156 } 157 }, 158 dragContinueHandler : function(event) { // User is dragging 159 // console.log('drag continue'); 160 161 var lt = left_top(event); 162 163 // How much did the mouse move? 164 var delta = {left: (lt.left - event.data.lastCoord.left), 165 top: (lt.top - event.data.lastCoord.top)}; 166 167 /* 168 console.log(event.data.scrollable); 169 console.log('delta.left - ' + delta.left); 170 console.log('delta.top - ' + delta.top); 171 */ 172 173 var scrollTarget = event.data.scrollable; 174 if (event.data.scrollWindow) { 175 scrollTarget = $(window); 176 } 177 // Set the scroll position relative to what ever the scroll is now 178 scrollTarget.scrollLeft( scrollTarget.scrollLeft() - delta.left ); 179 scrollTarget.scrollTop( scrollTarget.scrollTop() - delta.top ); 180 181 // Save where the cursor is 182 event.data.lastCoord = lt; 183 184 if (event.data.preventDefault) { 185 event.preventDefault(); 186 return false; 187 } 188 189 }, 190 dragEndHandler : function(event) { // Stop scrolling 191 // console.log('drag END'); 192 193 handling_element 194 .unbind(settings.dragcontinue) 195 .unbind(settings.dragend); 196 197 // How much did the mouse move total? 198 var delta = {left: Math.abs(event.data.lastCoord.left - event.data.firstCoord.left), 199 top: Math.abs(event.data.lastCoord.top - event.data.firstCoord.top)}; 200 var distance = Math.max(delta.left, delta.top); 201 202 // Trigger 'tap' if did not meet drag distance 203 // $$$ does not differentiate single vs multi-touch 204 if (distance < settings.dragMinDistance) { 205 //$(event.originalEvent.target).trigger('tap'); 206 $(event.target).trigger('tap'); // $$$ always the right target? 207 } 208 209 // Allow event to propage if min distance was not achieved 210 if (event.data.preventDefault && distance > settings.dragMinDistance) { 211 event.preventDefault(); 212 return false; 213 } 214 } 215 } 216 217 // set up the initial events 218 return this.each(function() { 219 // closure object data for each scrollable element 220 var data = {scrollable : $(this), 221 acceptPropagatedEvent : settings.acceptPropagatedEvent, 222 preventDefault : settings.preventDefault, 223 scrollWindow : settings.scrollWindow } 224 // Set mouse initiating event on the desired descendant 225 $(this).find(settings.dragSelector). 226 bind(settings.dragstart, data, dragscroll.dragStartHandler); 227 }); 228}; //end plugin dragscrollable 229 230$.fn.removedragscrollable = function (namespace) { 231 if (typeof(namespace) == 'undefined') 232 namespace = '.ds'; 233 return this.each(function() { 234 var x = $(document).find('*').andSelf().unbind(namespace); 235 }); 236}; 237 238})( jQuery ); // confine scope
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.