Js achieves the drag effect on the win7 taskbar
At some point, I met a friend. under my guidance, this person set foot on the js Road. the day before yesterday, he asked me how to achieve the drag effect on the Windows 7 taskbar. I told him at will that it was a simple force. after one night of hard work, a piece of code was finally implemented. PS: I am engaged in C ++. js knows a little bit .. the source code is not much to be said. copy code 1 // constant 2 var CELL_WIDTH = 100; 3 var CELL_HEIGHT = 50; 4 5 var Utils = {6 pixelToInt: function (str) 7 {8 return parseInt (str. replace ("px", ""); 9}, 10 getTagLeft: function ($ tag) 11 {12 return this. pixelToInt (tag.css ("left"); 13}, 14 getTagT Op: function ($ tag) 15 {16 return this. pixelToInt (tag.css ("top"); 17}, 18 getTagWidth: function ($ tag) 19 {20 return this. pixelToInt ($tag.css ("width"); 21}, 22 getTagHeight: function ($ tag) 23 {24 return this. pixelToInt ($tag.css ("height"); 25}, 26 setTagLeft: function ($ tag, x) 27 {28 rows tag.css ("left", x + "px "); 29}, 30 setTagTop: function ($ tag, y) 31 {32 using tag.css ("top", y + "px "); 33}, 34 setTagWidth: function ($ tag, width) 35 {36 rows tag.css ("width", width + "px"); 37}, 38 setTagHeight: function ($ tag, height) 39 {40 rows tag.css ("left", height + "px"); 41}, 42 swapNode: function (ary, idx1, idx2) 43 {44 var t = ary [idx1]; 45 ary [idx1] = ary [idx2]; 46 ary [idx2] = t; 47} 48 }; 49 50 function Taskbar () 51 {52 this. _ cells = []; 53 this. _ frameTag = null; 54 this. _ cellWidth = 0; 55 this. _ cellHeight = 0; 56 this. _ selNode = null; 57 this. _ selIndex =-1; 58 59 this. _ swapQueue = []; 60 // consider optimization. 61 this. _ offsetPoint = {"x": 0, "y": 0}; 62} 63 64 Taskbar. prototype. getTag = function () 65 {66 return this. _ frameTag; 67} 68 69 Taskbar. prototype. init = function (x, y, width, height, rgb) 70 {71 this. _ frameTag = $ ("<div> </div>"); 72 this. setPosition (x, y); 73 this. setContentSize (w Idth, height); 74 this. setBackgroundColor (rgb); 75 76 var self = this; 77 this. _ frameTag. bind ("mousedown", {"bar": self}, this. mouseDown); 78 this. _ frameTag. bind ("mouseup", {"bar": self}, this. mouseUp); 79 this. _ frameTag. bind ("mousemove", {"bar": self}, this. mouseMove); 80 // this. _ frameTag. bind ("mouseout", {"bar": self}, this. mouseOut); 81} 82 83 Taskbar. prototype. setPosition = function (x, y) 84 {85 this._frameTag.css ("position", "absolute"); 86 this._frameTag.css ("left", x + "px"); 87 this._frameTag.css ("top ", y + "px"); 88} 89 90 Taskbar. prototype. setContentSize = function (width, height) 91 {92 this._frameTag.css ("width", width + "px"); 93 this._frameTag.css ("height", height + "px "); 94} 95 96 Taskbar. prototype. setBackgroundColor = function (rgb) 97 {98 // rgb => "rgb (0, 0, 0 )". 99 This._frameTag.css ("background", rgb); 100} 101 102 Taskbar. prototype. appendNode = function ($ node) 103 {104 var frameWidth = Utils. getTagWidth (this. _ frameTag); 105 var frameHeight = Utils. getTagHeight (this. _ frameTag); 106 var length = this. _ cells. length + 1; 107 this. _ cellWidth = frameWidth/length; 108 this. _ cellHeight = frameHeight; 109 this. _ cells. push ($ node); 110 $ node. appendTo (this. _ frameTag); 111 112 for (var I = 0; I! = Length; ++ I) 113 {114 Utils. setTagLeft (this. _ cells [I], I * this. _ cellWidth); 115 Utils. setTagWidth (this. _ cells [I], this. _ cellWidth); 116} 117} 118 119 Taskbar. prototype. mouseDown = function (e) 120 {121 var bar = e. data ["bar"]; 122 123 if (bar. _ selNode) 124 {125 return; 126} 127 128 var index = bar. hitTest (e. clientX, e. clientY); 129 if (! Bar. isInvalidIndex (index) 130 {131 // activate. 132 bar. _ selIndex = index; 133 bar. _ selNode = bar. _ cells [index]; 134 bar._selNode.css ("z-index", 99); 135 bar. _ cells [index] = null; 136 137 // Save the offset to keep the mouse dragging. 138 var point = bar. converPoint (e. clientX, e. clientY); 139 bar. _ offsetPoint. x = point. x-index * bar. _ cellWidth; 140 bar. _ offsetPoint. y = point. y; 141 console. log ("down"); 142} 143 144} 145 146 Taskbar. pro Totype. mouseUp = function (e) 147 {148 var bar = e. data ["bar"]; 149 150 if (bar. _ selNode) 151 {152 // Add to the exchange. 153 bar. appendSwap (bar. _ selNode, bar. _ selIndex); 154 155 // After the mouse is raised, reset the selected node. 156 // bar. _ cells [bar. _ selIndex] = bar. _ selNode; 157 bar. _ cells [bar. _ selIndex pai.css ("z-index", 1); 158 bar. _ selIndex =-1; 159 bar. _ selNode = null; 160 console. log ("up"); 161} 162} 163 164 Taskbar. prototype. mouseOut = func Tion (e) 165 {166 var bar = e. data ["bar"]; 167 bar. mouseUp (e); 168 console. log ("mouseout"); 169} 170 171 Taskbar. prototype. mouseMove = function (e) 172 {173 var bar = e. data ["bar"]; 174 if (bar. _ selNode) 175 {176 var point = bar. converPoint (e. clientX, e. clientY); 177 var moveX = point. x-bar. _ offsetPoint. x; 178 179 // prevents location overflow. 180 bar. noOverflow (bar. _ selNode, moveX); 181 182 // squeeze off the float block.183 var cu next to it RX = Utils. getTagLeft (bar. _ selNode), 184 width = Utils. getTagWidth (bar. _ selNode), 185 testX = curX + width/2,186 hitIndex = bar. hitTest (testX, 0); 187 if (bar. _ selIndex! = HitIndex) 188 {189 bar. appendSwap (bar. _ cells [hitIndex], bar. _ selIndex); 190 bar. _ selIndex = hitIndex; 191} 192} 193 194 Taskbar. prototype. appendSwap = function ($ node, index) 196 {197 this. _ cells [index] = $ node; 198 199 this. _ swapQueue. push ({"node": $ node, "index": index}); 200 this. resetNode (); 201} 202 203 Taskbar. prototype. noOverflow = function ($ node, moveX) 204 {205 var width = Utils. getTagWidth ($ Node), 206 frameWidth = Utils. getTagWidth (this. _ frameTag); 207 208 if (moveX <0) 209 moveX = 0; 210 else if (moveX + width> frameWidth) 211 moveX = frameWidth-width; 212 213 Utils. setTagLeft ($ node, moveX); 214} 215 Taskbar. prototype. resetNode = function () 217 {218 var self = this; 219 var call = function ($ node, index) 220 {221 var oldX = Utils. getTagLeft ($ node), 222 newX = index * self. _ cel LWidth, 223 diff = newX-oldX, 224 stepCount = 10,225 step = diff/stepCount, 226 curX = oldX; 227 (228 function call () 229 {230 if (stepCount! = 0) 231 {232 curX + = step; 233 Utils. setTagLeft ($ node, curX); 234 setTimeout (call, 10); 235} 236 else237 {238 slave node.css ("z-index", 0); 239 Utils. setTagLeft ($ node, newX); 240} 241 -- stepCount; 242} 243) (); 244}; 245 246 for (var I in this. _ swapQueue) 247 {248 call (this. _ swapQueue [I]. node, this. _ swapQueue [I]. index); 249} 250 this. _ swapQueue = []; 251} 252 253 Taskbar. prototype. hitTest = function (x, y) 254 {25 5 // The y parameter is completely soy sauce. 256 var point = this. converPoint (x, y); 257 return parseInt (point. x/this. _ cellWidth); 258} 259 260 Taskbar. prototype. converPoint = function (x, y) 261 {262 var frameX = Utils. getTagLeft (this. _ frameTag); 263 frameY = Utils. getTagTop (this. _ frameTag); 264 return {265 "x": x-= frameX, 266 "y": y-= frameY267}; 268} 269 Taskbar. prototype. isInvalidIndex = function (index) 271 {272 retur N index <0 | index> = this. _ cells. length; 273} 274 275 function init () 276 {277 var getCell = function (cls, left, top, name) 278 {279 return $(280 "<div class = '_ cls' name =' _ name' style = 'left: _ leftpx; top: _ toppx; width: _ widthpx; height: _ heightpx; '> </div> "281. replace ("_ cls", cls) 282. replace ("_ left", left) 283. replace ("_ top", top) 284. replace ("_ name", name) 285. replace ("_ width", CELL_WIDTH) 286. Replace ("_ height", CELL_HEIGHT); 287}; 288 289 for (var I = 0; I! = 5; ++ I) 290 {291 var taskbar = new Taskbar (); 292 taskbar. init (0, I * 60,500, 50, "rgb (0, 0, 0)"); 293 taskbar. getTag (). appendTo ($ ("body"); 294 for (var j = 0; j! = I + 5; ++ j) 295 {296 taskbar. appendNode (getCell ("cell", 0, 0, 0); 297} 298} 299 $300 (document ). ready (init); the idea of copying code is actually very simple. create a Taskbar object, which sets coordinates, dimensions, and background color. then appendChild is added to the object, and the child node automatically adapts to the size. we use a Job Queue to save the tasks to be moved. this queue stores the nodes to be moved and the locations to which the nodes are passive. next, an exchange action is triggered. This action is continuous, so we can see that the node moves smoothly. after the down operation, the node location under the down operation is set to null. then we use a _ selNode to save the node. at the same time, use _ selIndex to save the location where the node should belong. (This sentence is hard to describe, but I can't think of it !) Then, in the move operation, determine whether the _ selNode is "exceeding the line". Once the line is crossed, a switch job is pushed. then, as mentioned above, the exchange action is triggered. after the up operation is triggered, you only need to push _ selNode and _ selIndex to the job queue. because all mouse responses are in the background div, the mouse does not respond if it is out of the range .. for example, after I go down, the mouse moves out of the range and then up, the up will not be responded .. I added a judgment in down to solve this bug .. after the range is exceeded and the value is returned to the range, it is still down. html file content copy Code <! DOCTYPE html>