前端的小玩意(9.5)——做一个仿360工具箱的web页面(完结篇,可以跑起来的工具箱)

简介:

DEMO网址:

http://jianwangsan.cn/toolbox


(五)添加、点击和移动的逻辑

我反思了一下,在(四)中我写的并不好,事实上,无论是大按钮,还是被添加到我的工具,或者是添加到常用工具栏,他都是一个按钮,因此,应该共享状态,即他们属于同一个tool实例,并能互相影响。

 

需求分析:

在重写Tool类之前,需要明确分析按钮的逻辑。

在全部工具页面:

①当按钮未被添加时,鼠标移动上去会有添加按钮显示;

②当按钮未被添加时,鼠标无论点击按钮本身还是点击添加按钮,都执行添加逻辑,将添加按钮显示为取消,执行一次添加动画,添加完成后,按钮隐藏;

③当按钮已被添加时,鼠标点击会启用按钮本身的逻辑(比如打开软件);

 

在我的工具页面:

①当按钮未被添加时,不显示;

②当按钮被添加时,显示按钮;

③点击按钮时,点击会启用按钮本身的逻辑(比如打开软件);

④长按按钮,可以拖动按钮,原有按钮位置不被占用,显示为空白;

⑤按钮拖动中时,若经过某个已有按钮的位置,原按钮位置不再被占用,经过的位置被空白占用,相当于把空白占位符从DOM中的原位置挪到了DOM树中的新位置;

⑥按钮拖动时,可以离开工具箱的页面显示范围,但不会显示出来(类似overflow:hidden)的效果;

⑦当按钮拖动到主界面快捷入口的四个图标范围时,若原位置有图标,再该位置图标及右侧所有图标依次向右移动一位;当离开这个位置时,原有图标立刻返回原位置;

⑧主界面快捷入口最多有四个图标,假如新插入一个,那么原本最右边的将被移除;

⑨点击编辑按钮时,所有图标右上角都会出现一个红叉符号;

(10)当编辑状态时,点击主界面快捷入口的四个图标的红叉时,将移除被点击的那个图标;

(11)当编辑状态时,点击我的工具的图标的红叉,将删除该图标(全部工具里的添加按钮恢复);若该图标在快捷入口也存在时,快捷入口的该图标也被删除。

因此,这个Tool类也能满足以上功能;


更新模板和样式;

①要有四种状态的图标,依次为全部工具页面的大图标、普通图标,我的工具页面的普通图标、快捷入口图标;

②并且,要能创建这些图标,并且,由于之前没有设计全部工具页面的取消按钮、我的工具页面里的编辑按钮,因此要添上;

我的工具里图标的html模板:,编辑按钮默认为不显示:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. div.tool-my  
  2.     div.img  
  3.     div.text    小清新日历  
  4.     div.edit-img.displayNONE  

 

快捷入口的按钮的html模板:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. div.tool-foot  
  2.     div.img  
  3.     div.text    系统急救箱  
  4.     div.edit-img.displayNONE  

取消按钮添加后的大图标:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. div.BigTool  
  2.     span.img  
  3.     span.mask  
  4.     div.text  
  5.         div.title  
  6.         div.description  
  7.     div.Button.add  添 加  
  8.     div.Button.cancel.displayNONE   取 消  

取消按钮添加后的html模板:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. div.normalTool  
  2.     div.img  
  3.     div.text  
  4.         div.title  
  5.         div.description  
  6.     div.Button.add  添 加  
  7.     div.Button.cancel.displayNONE   取 消  


另附2个新增的CSS样式:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .back .contentbox .toolbox-my .toolbox-content .tool-my .edit-img {  
  2.     position: absolute;  
  3.     right: 14px;  
  4.     top: 13px;  
  5.     width: 18px;  
  6.     height: 17px;  
  7.     background-image: url(../img/toolbox.png);  
  8.     background-position: -80px -50px;  
  9. }  
  10. .back .contentbox .toolbox-my .toolbox-foot .edit-img {  
  11.     position: absolute;  
  12.     right: 14px;  
  13.     top: 10px;  
  14.     width: 18px;  
  15.     height: 17px;  
  16.     background-image: url(../img/toolbox.png);  
  17.     background-position: -80px -50px;  
  18. }  

然后是样式修改:

显示大图标的:

把原来的addButton拆分成Buttonaddcancel

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .back .contentbox .toolbox-all .firstRow .BigTool .Button {  
  2.     display: none;  
  3.     position: absolute;  
  4.     bottom: 10px;  
  5.     right: 12px;  
  6.     width: 60px;  
  7.     height: 22px;  
  8.     font-size: 12px;  
  9.     text-align: center;  
  10.     line-height: 20px;  
  11.     -webkit-border-radius: 1px;  
  12.     -moz-border-radius: 1px;  
  13.     border-radius: 1px;  
  14. }  
  15.   
  16. .back .contentbox .toolbox-all .firstRow .BigTool .Button.add {  
  17.     background-image: linear-gradient(rgb(98, 227, 25) 0%, rgb(68, 208, 27) 100%);  
  18.     color: white;  
  19.     border: 1px solid rgb(65, 199, 36);  
  20. }  
  21.   
  22. .back .contentbox .toolbox-all .firstRow .BigTool .Button.cancel {  
  23.     background-image: linear-gradient(#f3f3f3 0%, #dfdfdf 100%);  
  24.     color: black;  
  25.     border: 1px solid #b6b6b6;  
  26.     display: block;  
  27. }  
  28.   
  29. .back .contentbox .toolbox-all .firstRow .BigTool:hover .add {  
  30.     display: block;  
  31. }  

 

另外一个类似

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. .back .contentbox .commonRow .normalTool .Button {  
  2.     display: none;  
  3.     position: absolute;  
  4.     top: 7px;  
  5.     right: 15px;  
  6.     width: 60px;  
  7.     height: 22px;  
  8.     font-size: 12px;  
  9.     text-align: center;  
  10.     line-height: 20px;  
  11.     -webkit-border-radius: 1px;  
  12.     -moz-border-radius: 1px;  
  13.     border-radius: 1px;  
  14. }  
  15.   
  16. .back .contentbox .commonRow .normalTool .add {  
  17.     background-image: linear-gradient(rgb(98, 227, 25) 0%, rgb(68, 208, 27) 100%);  
  18.     border: 1px solid rgb(65, 199, 36);  
  19.     color: white;  
  20. }  
  21.   
  22. .back .contentbox .commonRow .normalTool .cancel {  
  23.     background-image: linear-gradient(#f3f3f3 0%, #dfdfdf 100%);  
  24.     color: black;  
  25.     border: 1px solid #b6b6b6;  
  26.     display: block;  
  27.   
  28. }  
  29.   
  30. .back .contentbox .commonRow .normalTool:hover .add {  
  31.     display: block;  
  32. }  

为了符合实际需求,我们需要做以下工作:

①重构Tool类(之前实在太简陋了);

②需要一个函数,专用进行操作;

③需要一个runAfter函数,他的效果是,监听某个对象的某个方法,在该方法执行完后执行runAfter的回调函数;

④然后利用这个runAfter监听一些函数,并在该函数触发时做一些事情。

 

 

重构Tool类:

他分为以下几个部分:

①变量声明(私有变量):

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var Tool = function (obj, myToolDom) {  
  2.     var self = this;  
  3.     var obj = obj;  
  4.   
  5.     // 0表示未加载到我的工具,1表示加载到我的工具,-1表示添加中(未使用)  
  6.     var state = 0;  
  7.     var BigImgDom = null;   //全部工具大图标  
  8.     var NormalToolDom = null;   //全部工具小图标  
  9.     var addButton = null;   //确认按钮  
  10.     var cancelButton = null;    //取消按钮(有,但是实际未使用)  
  11.     var InMyToolDom = null//我的工具大图标  
  12.     var editButtonInMyToolDom = null;  //我的工具页面的编辑红叉按钮  
  13.     var SmallToolDom = null;    //快捷入口图标  
  14.     var editButtonInSmallToolDom = null;    //快捷入口图标的编辑按钮  
  15.   
  16.     var DomClickEvent = null;    //这个是该dom点击事件的回调函数  
  17.     var editing = false;    //编辑状态  
  18.     var move = false;   //我的工具大图标移动状态  
  19.     var SmallIconMove = false;  //我的工具小图标移动状态  
  20.   
  21.     //如果有传参则用传参,如果没有则用默认值  
  22.     var MyToolDom = myToolDom ? myToolDom : $(".toolbox-my .toolbox-content");  

注意,以上四种图标,最多只会存在三种(所有工具的大图标和小图标只能存在一种状态)

 

 

dom获取

根据实际需求,我们有时候需要获取dom,其中一个是私有的(只在tool类里调用),一个是公有的(会在外面调用),所以声明方式不同:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //获取DOM  
  2. var getDomInAllTools = function () {  
  3.     return BigImgDom ? BigImgDom : NormalToolDom;   //因为只有一个存在  
  4. };  
  5. this.getDomInMyTools = function () {  
  6.     return InMyToolDom;  
  7. };  

③创建图标

我们自然需要创建图标,四种图标都需要一个函数(因为他们的dom结构不同);

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //全部工具页面  
  2. //  大按钮  
  3. this.createBigImgDom = function (callback) {  
  4.     var str = '<div class="BigTool">' +  
  5.         '<span class="img" style="background-position: ' + obj.bigImg.ImgPosition.x + ' ' + obj.bigImg.ImgPosition.y + '"></span>' +  
  6.         '<span class="mask"></span>' +  
  7.         '<div class="text">' +  
  8.         '<div class="title">' + obj.title + '</div>' +  
  9.         '<div class="description">' + obj.description + '</div>' +  
  10.         '</div>' +  
  11.         '<div class="Button add">添 加</div>' +  
  12.         '<div class="Button cancel displayNONE">取 消</div>' +  
  13.         '</div>';  
  14.     BigImgDom = $(str);  
  15.     addButton = BigImgDom.find(".add");  
  16.     cancelButton = BigImgDom.find(".cancel");  
  17.     DomClickEvent = callback;  
  18.     setClickEvent();  
  19.     return getDomInAllTools();  
  20. };  
  21.   
  22. //  普通按钮  
  23. this.createNormalToolDom = function (callback) {  
  24.     var str = '<div class="normalTool">' +  
  25.         '<div class="img" style="background-position: ' + obj.commonImg.ImgPosition.x + ' ' + obj.commonImg.ImgPosition.y + '"></div>' +  
  26.         '<div class="text">' +  
  27.         '<div class="title">' + obj.title + '</div>' +  
  28.         '<div class="description">' + obj.description + '</div>' +  
  29.         '</div>' +  
  30.         '<div class="Button add">添 加</div>' +  
  31.         '<div class="Button cancel displayNONE">取 消</div>' +  
  32.         '</div>';  
  33.     NormalToolDom = $(str);  
  34.     addButton = NormalToolDom.find(".add");  
  35.     cancelButton = NormalToolDom.find(".cancel");  
  36.     DomClickEvent = callback;  
  37.     setClickEvent();  
  38.     return getDomInAllTools();  
  39. };  
  40.   
  41. //我的工具页面  
  42. //  创建普通的dom  
  43. var createInMyToolDom = function () {  
  44.     var str = '<div class="tool-my">' +  
  45.         '<div class="img" style="background-position: ' + obj.commonImg.ImgPosition.x + ' ' + obj.commonImg.ImgPosition.y + '"></div>' +  
  46.         '<div class="text">' + obj.title + '</div>' +  
  47.         '<div class="edit-img displayNONE"></div>' +  
  48.         '</div>'  
  49.     var node = $(str);  
  50.     return node;  
  51. }  
  52.   
  53. //  创建小的dom  
  54. var createSmallTool = function () {  
  55.     var position_x = parseInt(obj.commonImg.ImgPosition.x) * 0.615 + "px";  
  56.     var position_y = parseInt(obj.commonImg.ImgPosition.y) * 0.615 + "px";  
  57.     var str = '<div class="tool-foot">' +  
  58.         '<div class="img"  style="background-position: ' + position_x + ' ' + position_y + '"></div>' +  
  59.         '<div class="text">' + obj.title + '</div>' +  
  60.         '<div class="edit-img displayNONE"></div>' +  
  61.         '</div>';  
  62.     var node = $(str);  
  63.     return node;  
  64. };  

注:

1)以上四个创建图标,在全部工具里的两种还额外获取了编辑按钮;

2)创建全部工具的图标时,顺便获取了响应函数

 

 

④响应逻辑:

图标创建了必然需要对她设置事件,

1)比如全部工具里图标的点击事件:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //  设置全部工具里的点击事件  
  2. var setClickEvent = function () {  
  3.     var node = BigImgDom ? BigImgDom : NormalToolDom;  
  4.     node.click(function (event) {  
  5.         if (state) {  
  6.             DomClickEvent();  
  7.         } else if (state === 0) {  
  8.             self.addDomToMyTools();  
  9.         }  
  10.     });  
  11. };  

2)以上点击事件又分为两种,已添加时,触发正常的响应逻辑(在创建图标时作为参数传进来的回调函数);

未添加时,用于添加到我的工具里的函数:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //将dom添加到我的工具里  
  2. this.addDomToMyTools = function () {  
  3.     addButton.addClass("displayNONE");  
  4.     state = 1;  //设置其状态为已添加  
  5.     //现在是在mytools里添加  
  6.     if (!InMyToolDom) {  
  7.         InMyToolDom = createInMyToolDom();  
  8.         editButtonInMyToolDom = InMyToolDom.find(".edit-img");  
  9.         //setMyToolEditEvent(editButtonInMyToolDom);    //废弃,同下被整合  
  10.         //setMyToolClickEvent(InMyToolDom);   //废弃,被整合进移动按钮的逻辑中  
  11.         setMyToolsDomMoveEvent();  
  12.     }  
  13.     MyToolDom.append(InMyToolDom);  
  14. };  

3)这个添加事件又分为:

设置添加按钮为隐藏,设置添加状态为已添加;

没有dom的时候,创建dom并为其绑定事件,绑定的事件有:

1】点击事件:

(但事实上这个已废弃,因为后面涉及到移动按钮的函数,被整合在那里了)

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //  设置我的工具页面的两种按钮的点击事件  
  2. var setMyToolClickEvent = function (node) {  
  3.     node.click(function (event) {  
  4.         if (!editing) {  
  5.             DomClickEvent();  
  6.         }  
  7.     });  
  8. };  

2】编辑按钮点击事件:

(同样已废弃,因为后面涉及到移动按钮的函数,被整合在那里了)

 

3】设置按钮的移动函数,包括以上两个被整合的事件:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //我的工具大图标的移动函数  
  2. var setMyToolsDomMoveEvent = function () {  
  3.     var mouseX = null;  
  4.     var mouseY = null;  
  5.     var startLeft = null;  
  6.     var startTop = null;  
  7.     var placeHholderDom = $('<div class="tool-my .ItsplaceHolder"></div>');  
  8.     InMyToolDom.mousedown(function (evt) {  
  9.         if (evt.button != 0) {  
  10.             return;  
  11.         }  
  12.         if (editing & $(evt.target)[0] == editButtonInMyToolDom[0]) {  
  13.             self.setStateToUnadd();  
  14.             InMyToolDom.detach();  
  15.             if ($(".shortcut .tool-foot").filter(placeHholderDom[0])) {  
  16.                 SmallToolDom.detach();  
  17.                 $(".shortcut").append('<div class="tool-foot placeholder">' +  
  18.                     '<div class="placeholder-img"></div>' +  
  19.                     '<div class="text">拖拽到此</div>' +  
  20.                     '</div>')  
  21.             }  
  22.             event.stopPropagation();  
  23.             return;  
  24.         }  
  25.         mouseX = evt.clientX;   //这里的值是鼠标坐标  
  26.         mouseY = evt.clientY;  
  27.         var position = InMyToolDom.position();  
  28.         startLeft = position.left;  //没有px  
  29.         startTop = position.top;  
  30.         InMyToolDom.css("position""absolute");  
  31.         InMyToolDom.css("left", startLeft + "px");  
  32.         InMyToolDom.css("top", startTop + "px");  
  33.         InMyToolDom.after(placeHholderDom);  
  34.         move = true;  
  35.     });  
  36.     $(".toolbox-my").mousemove(function (evt) {  
  37.         if (!evt.buttons & move) {  //只有不在按,且当前是true的时候,才触发  
  38.             move = false;  
  39.             placeHholderDom.after(InMyToolDom);  
  40.             placeHholderDom.remove();  
  41.             InMyToolDom.css("position""relative");  
  42.             InMyToolDom.css("left""0");  
  43.             InMyToolDom.css("top""0");  
  44.             self.InMyToolDomEndMoving();  
  45.             if (mouseX == evt.clientX & mouseY == evt.clientY) {  
  46.                 if (!editing) {  
  47.                     DomClickEvent();  
  48.                 }  
  49.             }  
  50.         }  
  51.         if (move) {  
  52.             self.InMyToolDomMoving([placeHholderDom, evt]);  
  53.             var offsetX = evt.clientX - mouseX;  
  54.             var offsetY = evt.clientY - mouseY;  
  55.             InMyToolDom.css("left", offsetX + startLeft + "px");  
  56.             InMyToolDom.css("top", offsetY + startTop + "px");  
  57.         }  
  58.     });  
  59.     InMyToolDom.mouseup(function (evt) {  
  60.         if (move) {  
  61.             move = false;  
  62.             placeHholderDom.after(InMyToolDom);  
  63.             placeHholderDom.remove();  
  64.             InMyToolDom.css("position""relative");  
  65.             InMyToolDom.css("left""0");  
  66.             InMyToolDom.css("top""0");  
  67.             self.InMyToolDomEndMoving();  
  68.             if (mouseX == evt.clientX & mouseY == evt.clientY) {  
  69.                 if (!editing) {  
  70.                     DomClickEvent();  
  71.                 }  
  72.             }  
  73.         }  
  74.     })  
  75. };  

解释:

以上这个函数干了以下事:

1》只有鼠标左键按下才有效;

2》编辑状态时,按编辑按钮是有效的;(因此我们需要一个设置编辑状态的函数)

3》编辑状态时点击编辑按钮,会删除当前按钮,并用一个空白的按钮替代;

4》这个dom移除,为了不移除他的事件,因此用的是jquerydetach()方法,并阻止该按钮事件的冒泡;

5》非编辑状态时,可以移动按钮,原理是设置该按钮的定位为绝对定位,并用一个空白按钮放在该按钮的DOM后起到占位作用,并设置该按钮可移动;

6》由于代码本身写的并不是很好,因此移动状态被取消时,计算移动距离,如果没有位移偏差,且非编辑状态,触发该按钮的点击事件;(如果要写的好的话,该按钮的移动状态设置,应该在移动位置有偏差之后才设置position为绝对定位);

7》移动时触发一个InMyToolDomMoving方法,这个要被runAfter方法所监视,返回值是空白dom和鼠标移动时触发的event事件。该事件会决定该按钮和其他按钮的互动;

8》移动结束后,会触发一个InMyToolDomEndMoving方法,该方法同样被监视。并且设置移动结束后的鼠标弹起事件(同移动中的那个)。

9》移动结束后,把图标放在占位图标之前(注意,该占位图标的位置可能移动),并解除移动状态,取消绝对定位,移除占位图标;

 

 

4】然后是我的工具的大图标的移动中事件:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. this.InMyToolDomEndMoving = function () {  
  2.     if (!SmallToolDom) {  
  3.         SmallToolDom = createSmallTool();  
  4.         //setMyToolClickEvent(SmallToolDom);  
  5.         editButtonInSmallToolDom = SmallToolDom.find(".edit-img");  
  6.         setSmallEditEvent(editButtonInSmallToolDom);  
  7.         setSmallToolDomMoveEvent();  
  8.     }  
  9.     return SmallToolDom;  
  10. };  

他会返回小图标,如果没有小图标则创建,并为他绑定事件。

绑定事件有:

1》点击事件(整合进移动相关函数);

2》编辑按钮点击事件:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //  设置小的dom的编辑按钮的点击事件  
  2. var setSmallEditEvent = function (editNode) {  
  3.     editNode.click(function (event) {  
  4.         self.removeSmallTool();  
  5.         editButtonInSmallToolDom.addClass("displayNONE");  
  6.         SmallToolDom.detach();  
  7.         event.stopPropagation();  
  8.     })  
  9. };  

3》移动事件;

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var setSmallToolDomMoveEvent = function () {  
  2.     var mouseX = null;  
  3.     var mouseY = null;  
  4.     var startLeft = null;  
  5.     var startTop = null;  
  6.     var placeHholderDom = $('<div class="tool-foot placeholder SmallToolHolder">' +  
  7.         '<div class="placeholder-img"></div>' +  
  8.         '<div class="text">拖拽到此</div>' +  
  9.         '</div>');  
  10.     SmallToolDom.mousedown(function (evt) {  
  11.         if (evt.button != 0) {  
  12.             return;  
  13.         }  
  14.         if (editing & $(evt.target)[0] == editButtonInSmallToolDom[0]) {  
  15.             event.stopPropagation();  
  16.             return;  
  17.         }  
  18.         mouseX = evt.clientX;   //这里的值是鼠标坐标  
  19.         mouseY = evt.clientY;  
  20.         var position = SmallToolDom.position();  
  21.         startLeft = position.left;  //没有px  
  22.         startTop = position.top;  
  23.         SmallToolDom.css("position""absolute");  
  24.         SmallToolDom.css("left", startLeft + "px");  
  25.         SmallToolDom.css("top", startTop + "px");  
  26.         SmallToolDom.after(placeHholderDom);  
  27.         SmallIconMove = true;  
  28.         if ($(".SmallToolHolder").length > 1) {  
  29.             $(".SmallToolHolder")[1].remove();  
  30.         }  
  31.     });  
  32.     $(".toolbox-my").mousemove(function (evt) {  
  33.         if (!evt.buttons & SmallIconMove) {  //只有不在按,且当前是true的时候,才触发  
  34.             SmallIconMove = false;  
  35.             placeHholderDom.before(SmallToolDom);  
  36.             placeHholderDom.remove();  
  37.             SmallToolDom.css("position""relative");  
  38.             SmallToolDom.css("left""0");  
  39.             SmallToolDom.css("top""0");  
  40.             $(".SmallToolHolder").remove();  
  41.             if (mouseX == evt.clientX & mouseY == evt.clientY) {  
  42.                 if (!editing) {  
  43.                     DomClickEvent();  
  44.                 }  
  45.             }  
  46.         }  
  47.         if (SmallIconMove) {  
  48.             self.SmallToolDomMoving([placeHholderDom, evt]);  
  49.             var offsetX = evt.clientX - mouseX;  
  50.             var offsetY = evt.clientY - mouseY;  
  51.             SmallToolDom.css("left", offsetX + startLeft + "px");  
  52.             SmallToolDom.css("top", offsetY + startTop + "px");  
  53.             if ($(".SmallToolHolder").length > 1) {  
  54.                 $(".SmallToolHolder")[1].remove();  
  55.             }  
  56.         }  
  57.     });  
  58.     SmallToolDom.mouseup(function (evt) {  
  59.         if (SmallIconMove) {  
  60.             SmallIconMove = false;  
  61.             placeHholderDom.before(SmallToolDom);  
  62.             placeHholderDom.remove();  
  63.             SmallToolDom.css("position""relative");  
  64.             SmallToolDom.css("left""0");  
  65.             SmallToolDom.css("top""0");  
  66.             $(".SmallToolHolder").remove();  
  67.             if (mouseX == evt.clientX & mouseY == evt.clientY) {  
  68.                 if (!editing) {  
  69.                     DomClickEvent();  
  70.                 }  
  71.             }  
  72.         }  
  73.     })  
  74. }  

由于和大图标的移动按钮事件类似,就不细说了

总之,他在移动的时候,会触发一个SmallToolDomMoving方法,runAfter会监视他。

 


5】下来是两个按钮移动时触发的事件和移动结束后触发的事件:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //移动时会触发这个方法  
  2. this.InMyToolDomMoving = function (arr) {  
  3.     return arr;  
  4. };  
  5.   
  6. this.InMyToolDomEndMoving = function () {  
  7.     if (!SmallToolDom) {  
  8.         SmallToolDom = createSmallTool();  
  9.         //setMyToolClickEvent(SmallToolDom);  
  10.         editButtonInSmallToolDom = SmallToolDom.find(".edit-img");  
  11.         setSmallEditEvent(editButtonInSmallToolDom);  
  12.         setSmallToolDomMoveEvent();  
  13.     }  
  14.     return SmallToolDom;  
  15. };  
  16.   
  17. this.SmallToolDomMoving = function (arr) {  
  18.     return arr;  
  19. };  

⑤其他事件:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //设置编辑或者结束编辑  
  2. this.setEditing = function () {  
  3.     editing = true;  
  4.     editButtonInMyToolDom ? editButtonInMyToolDom.removeClass("displayNONE") : "";  
  5.     editButtonInSmallToolDom ? editButtonInSmallToolDom.removeClass("displayNONE") : "";  
  6. };  
  7.   
  8. this.cancelEditing = function () {  
  9.     editing = false;  
  10.     editButtonInMyToolDom.addClass("displayNONE");  
  11.     editButtonInSmallToolDom ? editButtonInSmallToolDom.addClass("displayNONE") : "";  
  12. }  
  13. //设置dom为未添加状态  
  14. this.setStateToUnadd = function () {  
  15.     addButton.removeClass("displayNONE");  
  16.     editButtonInMyToolDom.addClass("displayNONE");  
  17.     if (editButtonInSmallToolDom) {  
  18.         editButtonInSmallToolDom.addClass("displayNONE");  
  19.     }  
  20.     state = 0;  //设置其状态为未添加  
  21. }  

编辑状态的两个方法用于设置可编辑或者不可编辑;

另一个用于在删除按钮时调用;

 

 

——————————————————————————

 

重写ToolsConfigJsonLoad函数:

这个函数做了这些事情:

①读取json

②把json转化为Tool类的数据来源;

③创建Tool类实例,并监听其事件;

④在创建图标的时候,添加分割线、或者创建占位图标等;


声明这个函数:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var ToolsConfigJsonLoad = function (InMyToolArray, url) {  
  2.     this.url = url ? url : "data/tools.json";  

这个函数只有一个公有方法,那就是读取json

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. this.load = function () {  
  2.     var self = this;  
  3.     $.ajax({  
  4.         url: self.url,  
  5.         dataType: "json",  
  6.         type: "GET",  
  7.         success: function (data) {  
  8.             addToolsInToolbox_all(data);  
  9.   
  10.         }  
  11.     })  
  12. };  

读取json成功之后调用的函数:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //将内容添加到全部工具页面中  
  2. var addToolsInToolbox_all = function (data) {  
  3.     var type = [];  
  4.     data[0].BigImg.forEach(function (obj) {  
  5.         var tool = new Tool(obj);  
  6.         var mixin = new MixinTool(obj);  
  7.         var callback = mixin.mixin()  
  8.         listenToolEvent(tool);  
  9.         $(".firstRow").append(tool.createBigImgDom(callback));  
  10.     })  
  11.     data[0].CommonImg.forEach(function (obj) {  
  12.         if (type.indexOf(obj.type) < 0) {  
  13.             type.push(obj.type);  
  14.         }  
  15.         var tool = new Tool(obj);  
  16.         var mixin = new MixinTool(obj);  
  17.         var callback = mixin.mixin()  
  18.         listenToolEvent(tool);  
  19.         $(".commonRow." + obj.type).append(tool.createNormalToolDom(callback));  
  20.     })  
  21.     addPlaceHolderWhenOnlyTwoToolsInToolbox_All(type);  
  22.     addDottedLineInToolbox_All();  
  23. };  

监听事件先略过;

 

添加分割线:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // 这个目的是为了给全部工具中的多行工具之间添加分割线  
  2. var addDottedLineInToolbox_All = function () {  
  3.     $(".commonRow .normalTool:nth-child(3n+4)").before('<div class="dotted"></div>');  
  4. };  

为保证美观,添加占位图标:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. // 这个目的是当某一行只有两个图标时,创造一个占位的图标  
  2. var addPlaceHolderWhenOnlyTwoToolsInToolbox_All = function (type) {  
  3.     type.forEach(function (obj) {  
  4.         var length = $(".commonRow." + obj + " > *").length;  
  5.         if (length % 3 == 2) {  
  6.             $(".commonRow." + obj).append($('<div class="normalToolHolder" style="cursor:default"></div>'));  
  7.         }  
  8.     })  
  9. };  

下来事件监听函数的原型:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //参数1是对象,参数2是方法名(字符串),参数三是该方法执行后执行的函数  
  2. var runAfter = function (obj, runEvent, AfterEvent) {  
  3.     var temp = obj[runEvent];  
  4.     obj[runEvent] = function (arguments) {  
  5.         var result = temp(arguments);  
  6.         AfterEvent(obj, result);  
  7.     }  
  8. }  

类似dojoaspect.after方法

 

最后是利用runAfter函数进行事件监听,调用它时只需要传递Tool类的实例。

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //监听事件  
  2. var listenToolEvent = function (tool) {  

他包含以下方法:

①当图标添加进我的工具时,将实例添加到一个数组中:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. runAfter(tool, "addDomToMyTools"function () {  
  2.     InMyToolArray.push(tool);  
  3. });  

②或者是删除我的工具里的按钮时,移除这个实例:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. runAfter(tool, "setStateToUnadd"function () {  
  2.     var MyToolIndex = InMyToolArray.indexOf(tool);  
  3.     InMyToolArray.splice(MyToolIndex, 1);  
  4. });  

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><p>③还需要一个占位图标,用于图标在移动时占位:</p><pre name="code" class="javascript">var placeHolderInSmall = $('<div class="tool-foot placeholder">' +  
  2.     '<div class="placeholder-img"></div>' +  
  3.     '<div class="text">拖拽到此</div>' +  
  4.     '</div>')  

④监听图标移动时的方法,他涉及到我的工具页面里大图标的互动,和快捷入口小图标的互动:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. runAfter(tool, "InMyToolDomMoving"function (obj, result) {  
  2.     var placeHolder = result[0];  
  3.     var event = result[1];  
  4.     InMyToolArray.forEach(function (tool) {  
  5.         var node = tool.getDomInMyTools();  
  6.         if (node.css("position") !== "absolute") {  
  7.             var position = node.offset(); //获取相对于文档的位置  
  8.             if (event.clientY > position.top & event.clientY < position.top + 100 & event.clientX > position.left & event.clientX < position.left + 100) {  
  9.                 if (node.index() < placeHolder.index()) {    //根据索引决定放在前还是后面  
  10.                     node.before(placeHolder);  
  11.                 } else {  
  12.                     node.after(placeHolder);  
  13.                 }  
  14.             }  
  15.         }  
  16.     });  
  17.   
  18.     var theNodeInSmallTools = false;    //是否重合  
  19.     $(".tool-foot").toArray().forEach(function (node, index) {  
  20.         var position = $(node).offset(); //获取相对于文档的位置  
  21.         if (event.clientY > position.top & event.clientY < position.top + 70 & event.clientX > position.left & event.clientX < position.left + 76) {  
  22.             theNodeInSmallTools = true;  
  23.             if ($(node) != placeHolderInSmall) {  
  24.                 $(node).before(placeHolderInSmall);  
  25.             }  
  26.         }  
  27.     });  
  28.     //如果重合  
  29.     if (theNodeInSmallTools) {  
  30.         $(".shortcut .tool-foot:last-child").addClass("displayNONE");  
  31.     }   //如果不重合  
  32.     else {  
  33.         placeHolderInSmall.remove();  
  34.         $(".shortcut .tool-foot.displayNONE").removeClass("displayNONE");  
  35.     }  
  36. });  

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><p>⑤当图标停止移动时,需要决定他是否被移动到一个新位置,或者是添加到快捷入口那里;</p><pre name="code" class="javascript">runAfter(tool, "InMyToolDomEndMoving"function (obj, node) {  
  2.     var sign = false;  
  3.     $(".tool-foot").toArray().forEach(function (node, index) {  
  4.         if ($(node)[0] == placeHolderInSmall[0]) {  
  5.             sign = true;  
  6.         }  
  7.     })  
  8.     if (sign) {  
  9.         if (node.hasClass("displayNONE")) {  
  10.             node.removeClass("displayNONE");  
  11.         }  
  12.         placeHolderInSmall.before(node);  
  13.         placeHolderInSmall.remove();  
  14.     }  
  15.     if ($(".tool-foot").length < 4) {  
  16.         var temp = '<div class="tool-foot placeholder">' +  
  17.             '<div class="placeholder-img"></div>' +  
  18.             '<div class="text">拖拽到此</div>' +  
  19.             '</div>';  
  20.         $(".shortcut").append(temp);  
  21.     } else if ($(".tool-foot").length > 4) {  
  22.         $(".tool-foot")[4].remove(); //移除第五个  
  23.     } else {  
  24.         $(".tool-foot.displayNONE").removeClass("displayNONE");  
  25.     }  
  26.     $(".shortcut").append($(".tool-foot.placeholder"));  
  27. })  
  28.   
  29.   
  30. ⑥还有小图标移动时,需要和小图标互动,例如可能需要交换位置:  
  31. runAfter(tool, "SmallToolDomMoving"function (obj, result) {  
  32.     var placeHolder = result[0];  
  33.     var event = result[1];  
  34.     $(".tool-foot").toArray().forEach(function (node) {  
  35.         var position = $(node).offset(); //获取相对于文档的位置  
  36.         if ($(node).css("position") !== "absolute") {  
  37.             if (event.clientY > position.top & event.clientY < position.top + 70 & event.clientX > position.left & event.clientX < position.left + 76) {  
  38.                 if ($(node).index() < placeHolder.index()) {    //根据索引决定放在前还是后面  
  39.                     $(node).before(placeHolder);  
  40.                 } else {  
  41.                     $(node).after(placeHolder);  
  42.                 }  
  43.             }  
  44.         }  
  45.     });  
  46. });  

 

——————————————————————

让工具箱运行起来:

以上代码,只涉及到工具箱页面各个图标的交互逻辑,但是并没有真正运行起来(例如,没有显式调用load()方法),并且也没有编辑图标的逻辑。

因此,我们需要一个函数补全剩下的部分:

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var ToolBoxEvent = function () {  
  2.     var InMyToolArray = [];  
  3.     var jsonLoad = new ToolsConfigJsonLoad(InMyToolArray);  
  4.     jsonLoad.load();  
  5.   
  6.     $("#edit").click(function () {  
  7.         //编辑中  
  8.         if ($(this).hasClass("editing")) {  
  9.             InMyToolArray.forEach(function (item) {  
  10.                 item.cancelEditing();  
  11.             })  
  12.             //设置编辑按钮的样式变更  
  13.             $(this).removeClass("editing");  
  14.             var text = $(this).find(".text");  
  15.             text.text("编辑");  
  16.             text.css("width""32px");  
  17.             text.css("margin-left""0px");  
  18.         } else {  
  19.             InMyToolArray.forEach(function (item) {  
  20.                 item.setEditing();  
  21.             })  
  22.             //设置编辑按钮的样式变更  
  23.             $(this).addClass("editing");  
  24.             var text = $(this).find(".text");  
  25.             text.text("退出编辑");  
  26.             text.css("width""52px");  
  27.             text.css("margin-left""-10px");  
  28.         }  
  29.     });  
  30. }  
save_snippets.png

这个函数干了两件事:

①声明一个ToolsConfigJsonLoad类的实例,并调用它的load方法(加载工具箱);

②设置编辑按钮的事件。

 

这样的话,工具箱就可以正常跑起来了。

当然,还有一些小BUG,需要被修复,不过这并不影响整体功能的运转,作为一个DEMO来说,程度是足够了,如果真要跑生产环境,那么这些BUG必须被fix


js全部代码:

http://jianwangsan.cn/javascripts/toolboxes.js

css全部代码:

http://jianwangsan.cn/stylesheets/toolboxes.css

目录
相关文章
|
17天前
|
编解码 前端开发 JavaScript
构建高效响应式Web界面:现代前端框架的比较
【4月更文挑战第9天】在移动设备和多样屏幕尺寸盛行的时代,构建能够适应不同视口的响应式Web界面变得至关重要。本文深入探讨了几种流行的前端框架——Bootstrap、Foundation和Tailwind CSS,分析它们在创建响应式设计中的优势与局限。通过对比这些框架的栅格系统、组件库和定制化能力,开发者可以更好地理解如何选择合适的工具来优化前端开发流程,并最终实现高性能、跨平台兼容的用户界面。
|
17天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
18天前
|
编解码 前端开发 JavaScript
Web 前端开发中的最佳实践
本文将介绍 Web 前端开发中的最佳实践,包括代码组织、性能优化、响应式设计和用户体验等方面。通过遵循这些实践,开发人员可以提高开发效率,优化用户体验,并减少潜在的问题和错误。
|
1天前
|
前端开发 JavaScript UED
Web前端开发:探索技术与艺术的交融
Web前端开发:探索技术与艺术的交融
8 1
|
1天前
|
前端开发 JavaScript Java
前端与后端:构建现代Web应用的双翼
前端与后端:构建现代Web应用的双翼
|
11天前
|
前端开发 搜索推荐 数据安全/隐私保护
HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
18 1
|
11天前
|
前端开发 JavaScript vr&ar
前端新技术探索:WebAssembly、Web Components与WebVR/AR
【4月更文挑战第12天】WebAssembly、Web Components和WebVR/AR正重塑Web应用的未来。WebAssembly允许C/C++等语言在Web上高效运行,提供接近原生的性能,如游戏引擎。Web Components通过Custom Elements和Shadow DOM实现可复用的自定义UI组件,提升模块化开发。WebVR/AR(现WebXR)则让VR/AR体验无需额外应用,直接在浏览器中实现。掌握这些技术对前端开发者至关重要。
16 3
|
XML Web App开发 JavaScript
前端入门教程(二)Web前端与HTML简介
一 web1.0时代的网页制作 网页制作是web1.0时代的产物,那个时候的网页主要是静态网页,所谓的静态网页就是没有与用户进行交互而仅仅供读者浏览的网页,我们当时称为“牛皮癣”网页。 例如一篇QQ日志、一篇博文等展示性文章。
2498 0
|
22天前
|
监控 JavaScript 前端开发
《理解 WebSocket:Java Web 开发的实时通信技术》
【4月更文挑战第4天】WebSocket是Java Web实时通信的关键技术,提供双向持久连接,实现低延迟、高效率的实时交互。适用于聊天应用、在线游戏、数据监控和即时通知。开发涉及服务器端实现、客户端连接及数据协议定义,注意安全、错误处理、性能和兼容性。随着实时应用需求增加,WebSocket在Java Web开发中的地位将更加重要。
|
1月前
|
Web App开发 前端开发 开发工具
介绍Web开发的基础知识
介绍Web开发的基础知识
29 7