天天看点

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

demo网址:

http://jianwangsan.cn/toolbox

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

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

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

在全部工具页面:

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

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

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

在我的工具页面:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

div.tool-my  

    div.img  

    div.text    小清新日历  

    div.edit-img.displaynone  

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

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

div.tool-foot  

    div.text    系统急救箱  

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

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

div.bigtool  

    span.img  

    span.mask  

    div.text  

        div.title  

        div.description  

    div.button.add  添 加  

    div.button.cancel.displaynone   取 消  

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

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

div.normaltool  

另附2个新增的css样式:

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

.back .contentbox .toolbox-my .toolbox-content .tool-my .edit-img {  

    position: absolute;  

    right: 14px;  

    top: 13px;  

    width: 18px;  

    height: 17px;  

    background-image: url(../img/toolbox.png);  

    background-position: -80px -50px;  

}  

.back .contentbox .toolbox-my .toolbox-foot .edit-img {  

    top: 10px;  

然后是样式修改:

显示大图标的:

把原来的addbutton拆分成button、add和cancel

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

.back .contentbox .toolbox-all .firstrow .bigtool .button {  

    display: none;  

    bottom: 10px;  

    right: 12px;  

    width: 60px;  

    height: 22px;  

    font-size: 12px;  

    text-align: center;  

    line-height: 20px;  

    -webkit-border-radius: 1px;  

    -moz-border-radius: 1px;  

    border-radius: 1px;  

.back .contentbox .toolbox-all .firstrow .bigtool .button.add {  

    background-image: linear-gradient(rgb(98, 227, 25) 0%, rgb(68, 208, 27) 100%);  

    color: white;  

    border: 1px solid rgb(65, 199, 36);  

.back .contentbox .toolbox-all .firstrow .bigtool .button.cancel {  

    background-image: linear-gradient(#f3f3f3 0%, #dfdfdf 100%);  

    color: black;  

    border: 1px solid #b6b6b6;  

    display: block;  

.back .contentbox .toolbox-all .firstrow .bigtool:hover .add {  

另外一个类似

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

.back .contentbox .commonrow .normaltool .button {  

    top: 7px;  

    right: 15px;  

.back .contentbox .commonrow .normaltool .add {  

.back .contentbox .commonrow .normaltool .cancel {  

.back .contentbox .commonrow .normaltool:hover .add {  

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

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

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

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

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

他分为以下几个部分:

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

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

var tool = function (obj, mytooldom) {  

    var self = this;  

    var obj = obj;  

    // 0表示未加载到我的工具,1表示加载到我的工具,-1表示添加中(未使用)  

    var state = 0;  

    var bigimgdom = null;   //全部工具大图标  

    var normaltooldom = null;   //全部工具小图标  

    var addbutton = null;   //确认按钮  

    var cancelbutton = null;    //取消按钮(有,但是实际未使用)  

    var inmytooldom = null; //我的工具大图标  

    var editbuttoninmytooldom = null;  //我的工具页面的编辑红叉按钮  

    var smalltooldom = null;    //快捷入口图标  

    var editbuttoninsmalltooldom = null;    //快捷入口图标的编辑按钮  

    var domclickevent = null;    //这个是该dom点击事件的回调函数  

    var editing = false;    //编辑状态  

    var move = false;   //我的工具大图标移动状态  

    var smalliconmove = false;  //我的工具小图标移动状态  

    //如果有传参则用传参,如果没有则用默认值  

    var mytooldom = mytooldom ? mytooldom : $(".toolbox-my .toolbox-content");  

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

②dom获取

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

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

//获取dom  

var getdominalltools = function () {  

    return bigimgdom ? bigimgdom : normaltooldom;   //因为只有一个存在  

};  

this.getdominmytools = function () {  

    return inmytooldom;  

③创建图标

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

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

//全部工具页面  

//  大按钮  

this.createbigimgdom = function (callback) {  

    var str = '<div class="bigtool">' +  

        '<span class="img" style="background-position: ' + obj.bigimg.imgposition.x + ' ' + obj.bigimg.imgposition.y + '"></span>' +  

        '<span class="mask"></span>' +  

        '<div class="text">' +  

        '<div class="title">' + obj.title + '</div>' +  

        '<div class="description">' + obj.description + '</div>' +  

        '</div>' +  

        '<div class="button add">添 加</div>' +  

        '<div class="button cancel displaynone">取 消</div>' +  

        '</div>';  

    bigimgdom = $(str);  

    addbutton = bigimgdom.find(".add");  

    cancelbutton = bigimgdom.find(".cancel");  

    domclickevent = callback;  

    setclickevent();  

    return getdominalltools();  

//  普通按钮  

this.createnormaltooldom = function (callback) {  

    var str = '<div class="normaltool">' +  

        '<div class="img" style="background-position: ' + obj.commonimg.imgposition.x + ' ' + obj.commonimg.imgposition.y + '"></div>' +  

    normaltooldom = $(str);  

    addbutton = normaltooldom.find(".add");  

    cancelbutton = normaltooldom.find(".cancel");  

//我的工具页面  

//  创建普通的dom  

var createinmytooldom = function () {  

    var str = '<div class="tool-my">' +  

        '<div class="text">' + obj.title + '</div>' +  

        '<div class="edit-img displaynone"></div>' +  

        '</div>'  

    var node = $(str);  

    return node;  

//  创建小的dom  

var createsmalltool = function () {  

    var position_x = parseint(obj.commonimg.imgposition.x) * 0.615 + "px";  

    var position_y = parseint(obj.commonimg.imgposition.y) * 0.615 + "px";  

    var str = '<div class="tool-foot">' +  

        '<div class="img"  style="background-position: ' + position_x + ' ' + position_y + '"></div>' +  

注:

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

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

④响应逻辑:

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

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

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

//  设置全部工具里的点击事件  

var setclickevent = function () {  

    var node = bigimgdom ? bigimgdom : normaltooldom;  

    node.click(function (event) {  

        if (state) {  

            domclickevent();  

        } else if (state === 0) {  

            self.adddomtomytools();  

        }  

    });  

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

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

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

//将dom添加到我的工具里  

this.adddomtomytools = function () {  

    addbutton.addclass("displaynone");  

    state = 1;  //设置其状态为已添加  

    //现在是在mytools里添加  

    if (!inmytooldom) {  

        inmytooldom = createinmytooldom();  

        editbuttoninmytooldom = inmytooldom.find(".edit-img");  

        //setmytooleditevent(editbuttoninmytooldom);    //废弃,同下被整合  

        //setmytoolclickevent(inmytooldom);   //废弃,被整合进移动按钮的逻辑中  

        setmytoolsdommoveevent();  

    }  

    mytooldom.append(inmytooldom);  

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

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

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

【1】点击事件:

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

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

//  设置我的工具页面的两种按钮的点击事件  

var setmytoolclickevent = function (node) {  

        if (!editing) {  

【2】编辑按钮点击事件:

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

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

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

//我的工具大图标的移动函数  

var setmytoolsdommoveevent = function () {  

    var mousex = null;  

    var mousey = null;  

    var startleft = null;  

    var starttop = null;  

    var placehholderdom = $('<div class="tool-my .itsplaceholder"></div>');  

    inmytooldom.mousedown(function (evt) {  

        if (evt.button != 0) {  

            return;  

        if (editing & $(evt.target)[0] == editbuttoninmytooldom[0]) {  

            self.setstatetounadd();  

            inmytooldom.detach();  

            if ($(".shortcut .tool-foot").filter(placehholderdom[0])) {  

                smalltooldom.detach();  

                $(".shortcut").append('<div class="tool-foot placeholder">' +  

                    '<div class="placeholder-img"></div>' +  

                    '<div class="text">拖拽到此</div>' +  

                    '</div>')  

            }  

            event.stoppropagation();  

        mousex = evt.clientx;   //这里的值是鼠标坐标  

        mousey = evt.clienty;  

        var position = inmytooldom.position();  

        startleft = position.left;  //没有px  

        starttop = position.top;  

        inmytooldom.css("position", "absolute");  

        inmytooldom.css("left", startleft + "px");  

        inmytooldom.css("top", starttop + "px");  

        inmytooldom.after(placehholderdom);  

        move = true;  

    $(".toolbox-my").mousemove(function (evt) {  

        if (!evt.buttons & move) {  //只有不在按,且当前是true的时候,才触发  

            move = false;  

            placehholderdom.after(inmytooldom);  

            placehholderdom.remove();  

            inmytooldom.css("position", "relative");  

            inmytooldom.css("left", "0");  

            inmytooldom.css("top", "0");  

            self.inmytooldomendmoving();  

            if (mousex == evt.clientx & mousey == evt.clienty) {  

                if (!editing) {  

                    domclickevent();  

                }  

        if (move) {  

            self.inmytooldommoving([placehholderdom, evt]);  

            var offsetx = evt.clientx - mousex;  

            var offsety = evt.clienty - mousey;  

            inmytooldom.css("left", offsetx + startleft + "px");  

            inmytooldom.css("top", offsety + starttop + "px");  

    inmytooldom.mouseup(function (evt) {  

    })  

解释:

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

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

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

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

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

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

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

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

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

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

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

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

this.inmytooldomendmoving = function () {  

    if (!smalltooldom) {  

        smalltooldom = createsmalltool();  

        //setmytoolclickevent(smalltooldom);  

        editbuttoninsmalltooldom = smalltooldom.find(".edit-img");  

        setsmalleditevent(editbuttoninsmalltooldom);  

        setsmalltooldommoveevent();  

    return smalltooldom;  

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

绑定事件有:

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

《2》编辑按钮点击事件:

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

//  设置小的dom的编辑按钮的点击事件  

var setsmalleditevent = function (editnode) {  

    editnode.click(function (event) {  

        self.removesmalltool();  

        editbuttoninsmalltooldom.addclass("displaynone");  

        smalltooldom.detach();  

        event.stoppropagation();  

《3》移动事件;

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

var setsmalltooldommoveevent = function () {  

    var placehholderdom = $('<div class="tool-foot placeholder smalltoolholder">' +  

        '<div class="placeholder-img"></div>' +  

        '<div class="text">拖拽到此</div>' +  

        '</div>');  

    smalltooldom.mousedown(function (evt) {  

        if (editing & $(evt.target)[0] == editbuttoninsmalltooldom[0]) {  

        var position = smalltooldom.position();  

        smalltooldom.css("position", "absolute");  

        smalltooldom.css("left", startleft + "px");  

        smalltooldom.css("top", starttop + "px");  

        smalltooldom.after(placehholderdom);  

        smalliconmove = true;  

        if ($(".smalltoolholder").length > 1) {  

            $(".smalltoolholder")[1].remove();  

        if (!evt.buttons & smalliconmove) {  //只有不在按,且当前是true的时候,才触发  

            smalliconmove = false;  

            placehholderdom.before(smalltooldom);  

            smalltooldom.css("position", "relative");  

            smalltooldom.css("left", "0");  

            smalltooldom.css("top", "0");  

            $(".smalltoolholder").remove();  

        if (smalliconmove) {  

            self.smalltooldommoving([placehholderdom, evt]);  

            smalltooldom.css("left", offsetx + startleft + "px");  

            smalltooldom.css("top", offsety + starttop + "px");  

            if ($(".smalltoolholder").length > 1) {  

                $(".smalltoolholder")[1].remove();  

    smalltooldom.mouseup(function (evt) {  

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

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

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

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

//移动时会触发这个方法  

this.inmytooldommoving = function (arr) {  

    return arr;  

this.smalltooldommoving = function (arr) {  

⑤其他事件:

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

//设置编辑或者结束编辑  

this.setediting = function () {  

    editing = true;  

    editbuttoninmytooldom ? editbuttoninmytooldom.removeclass("displaynone") : "";  

    editbuttoninsmalltooldom ? editbuttoninsmalltooldom.removeclass("displaynone") : "";  

this.cancelediting = function () {  

    editing = false;  

    editbuttoninmytooldom.addclass("displaynone");  

    editbuttoninsmalltooldom ? editbuttoninsmalltooldom.addclass("displaynone") : "";  

//设置dom为未添加状态  

this.setstatetounadd = function () {  

    addbutton.removeclass("displaynone");  

    if (editbuttoninsmalltooldom) {  

    state = 0;  //设置其状态为未添加  

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

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

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

这个函数做了这些事情:

①读取json;

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

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

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

声明这个函数:

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

var toolsconfigjsonload = function (inmytoolarray, url) {  

    this.url = url ? url : "data/tools.json";  

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

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

this.load = function () {  

    $.ajax({  

        url: self.url,  

        datatype: "json",  

        type: "get",  

        success: function (data) {  

            addtoolsintoolbox_all(data);  

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

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

//将内容添加到全部工具页面中  

var addtoolsintoolbox_all = function (data) {  

    var type = [];  

    data[0].bigimg.foreach(function (obj) {  

        var tool = new tool(obj);  

        var mixin = new mixintool(obj);  

        var callback = mixin.mixin()  

        listentoolevent(tool);  

        $(".firstrow").append(tool.createbigimgdom(callback));  

    data[0].commonimg.foreach(function (obj) {  

        if (type.indexof(obj.type) < 0) {  

            type.push(obj.type);  

        $(".commonrow." + obj.type).append(tool.createnormaltooldom(callback));  

    addplaceholderwhenonlytwotoolsintoolbox_all(type);  

    adddottedlineintoolbox_all();  

监听事件先略过;

添加分割线:

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

// 这个目的是为了给全部工具中的多行工具之间添加分割线  

var adddottedlineintoolbox_all = function () {  

    $(".commonrow .normaltool:nth-child(3n+4)").before('<div class="dotted"></div>');  

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

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

// 这个目的是当某一行只有两个图标时,创造一个占位的图标  

var addplaceholderwhenonlytwotoolsintoolbox_all = function (type) {  

    type.foreach(function (obj) {  

        var length = $(".commonrow." + obj + " > *").length;  

        if (length % 3 == 2) {  

            $(".commonrow." + obj).append($('<div class="normaltoolholder" style="cursor:default"></div>'));  

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

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

//参数1是对象,参数2是方法名(字符串),参数三是该方法执行后执行的函数  

var runafter = function (obj, runevent, afterevent) {  

    var temp = obj[runevent];  

    obj[runevent] = function (arguments) {  

        var result = temp(arguments);  

        afterevent(obj, result);  

类似dojo的aspect.after方法

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

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

//监听事件  

var listentoolevent = function (tool) {  

他包含以下方法:

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

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

runafter(tool, "adddomtomytools", function () {  

    inmytoolarray.push(tool);  

});  

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

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

runafter(tool, "setstatetounadd", function () {  

    var mytoolindex = inmytoolarray.indexof(tool);  

    inmytoolarray.splice(mytoolindex, 1);  

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

</pre><p>③还需要一个占位图标,用于图标在移动时占位:</p><pre name="code" class="javascript">var placeholderinsmall = $('<div class="tool-foot placeholder">' +  

    '<div class="placeholder-img"></div>' +  

    '<div class="text">拖拽到此</div>' +  

    '</div>')  

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

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

runafter(tool, "inmytooldommoving", function (obj, result) {  

    var placeholder = result[0];  

    var event = result[1];  

    inmytoolarray.foreach(function (tool) {  

        var node = tool.getdominmytools();  

        if (node.css("position") !== "absolute") {  

            var position = node.offset(); //获取相对于文档的位置  

            if (event.clienty > position.top & event.clienty < position.top + 100 & event.clientx > position.left & event.clientx < position.left + 100) {  

                if (node.index() < placeholder.index()) {    //根据索引决定放在前还是后面  

                    node.before(placeholder);  

                } else {  

                    node.after(placeholder);  

    var thenodeinsmalltools = false;    //是否重合  

    $(".tool-foot").toarray().foreach(function (node, index) {  

        var position = $(node).offset(); //获取相对于文档的位置  

        if (event.clienty > position.top & event.clienty < position.top + 70 & event.clientx > position.left & event.clientx < position.left + 76) {  

            thenodeinsmalltools = true;  

            if ($(node) != placeholderinsmall) {  

                $(node).before(placeholderinsmall);  

    //如果重合  

    if (thenodeinsmalltools) {  

        $(".shortcut .tool-foot:last-child").addclass("displaynone");  

    }   //如果不重合  

    else {  

        placeholderinsmall.remove();  

        $(".shortcut .tool-foot.displaynone").removeclass("displaynone");  

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

</pre><p>⑤当图标停止移动时,需要决定他是否被移动到一个新位置,或者是添加到快捷入口那里;</p><pre name="code" class="javascript">runafter(tool, "inmytooldomendmoving", function (obj, node) {  

    var sign = false;  

        if ($(node)[0] == placeholderinsmall[0]) {  

            sign = true;  

    if (sign) {  

        if (node.hasclass("displaynone")) {  

            node.removeclass("displaynone");  

        placeholderinsmall.before(node);  

    if ($(".tool-foot").length < 4) {  

        var temp = '<div class="tool-foot placeholder">' +  

            '<div class="placeholder-img"></div>' +  

            '<div class="text">拖拽到此</div>' +  

            '</div>';  

        $(".shortcut").append(temp);  

    } else if ($(".tool-foot").length > 4) {  

        $(".tool-foot")[4].remove(); //移除第五个  

    } else {  

        $(".tool-foot.displaynone").removeclass("displaynone");  

    $(".shortcut").append($(".tool-foot.placeholder"));  

})  

⑥还有小图标移动时,需要和小图标互动,例如可能需要交换位置:  

runafter(tool, "smalltooldommoving", function (obj, result) {  

    $(".tool-foot").toarray().foreach(function (node) {  

        if ($(node).css("position") !== "absolute") {  

            if (event.clienty > position.top & event.clienty < position.top + 70 & event.clientx > position.left & event.clientx < position.left + 76) {  

                if ($(node).index() < placeholder.index()) {    //根据索引决定放在前还是后面  

                    $(node).before(placeholder);  

                    $(node).after(placeholder);  

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

让工具箱运行起来:

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

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

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

var toolboxevent = function () {  

    var inmytoolarray = [];  

    var jsonload = new toolsconfigjsonload(inmytoolarray);  

    jsonload.load();  

    $("#edit").click(function () {  

        //编辑中  

        if ($(this).hasclass("editing")) {  

            inmytoolarray.foreach(function (item) {  

                item.cancelediting();  

            })  

            //设置编辑按钮的样式变更  

            $(this).removeclass("editing");  

            var text = $(this).find(".text");  

            text.text("编辑");  

            text.css("width", "32px");  

            text.css("margin-left", "0px");  

        } else {  

                item.setediting();  

            $(this).addclass("editing");  

            text.text("退出编辑");  

            text.css("width", "52px");  

            text.css("margin-left", "-10px");  

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

这个函数干了两件事:

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

②设置编辑按钮的事件。

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

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

js全部代码:

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

css全部代码:

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

继续阅读