美文网首页
做一个仿360工具箱的web页面(完结篇,可以跑起来的工具箱)

做一个仿360工具箱的web页面(完结篇,可以跑起来的工具箱)

作者: 淡淡紫色 | 来源:发表于2018-10-12 14:51 被阅读0次

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

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

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

    在全部工具页面:

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

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

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

    在我的工具页面:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    div.tool-my
        div.img
        div.text    小清新日历
        div.edit-img.displayNONE
    
    

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

    div.tool-foot
        div.img
        div.text    系统急救箱
        div.edit-img.displayNONE
    

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

    div.BigTool
        span.img
        span.mask
        div.text
            div.title
            div.description
        div.Button.add  添 加
        div.Button.cancel.displayNONE   取 消
    
    

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

    div.normalTool
        div.img
        div.text
            div.title
            div.description
        div.Button.add  添 加
        div.Button.cancel.displayNONE   取 消
    

    另附2个新增的CSS样式:

    .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 {
        position: absolute;
        right: 14px;
        top: 10px;
        width: 18px;
        height: 17px;
        background-image: url(../img/toolbox.png);
        background-position: -80px -50px;
    }
    

    然后是样式修改:

    显示大图标的:

    把原来的addButton拆分成Button、add和cancel

    .back .contentbox .toolbox-all .firstRow .BigTool .Button {
        display: none;
        position: absolute;
        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 {
        display: block;
    }
    

    另外一个类似

    .back .contentbox .commonRow .normalTool .Button {
        display: none;
        position: absolute;
        top: 7px;
        right: 15px;
        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 .commonRow .normalTool .add {
        background-image: linear-gradient(rgb(98, 227, 25) 0%, rgb(68, 208, 27) 100%);
        border: 1px solid rgb(65, 199, 36);
        color: white;
    }
     
    .back .contentbox .commonRow .normalTool .cancel {
        background-image: linear-gradient(#f3f3f3 0%, #dfdfdf 100%);
        color: black;
        border: 1px solid #b6b6b6;
        display: block;
     
    }
     
    .back .contentbox .commonRow .normalTool:hover .add {
        display: block;
    }
    

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

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

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

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

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

    重构Tool类:
    他分为以下几个部分:

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

    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类里调用),一个是公有的(会在外面调用),所以声明方式不同:

    //获取DOM
    var getDomInAllTools = function () {
        return BigImgDom ? BigImgDom : NormalToolDom;   //因为只有一个存在
    };
    this.getDomInMyTools = function () {
        return InMyToolDom;
    };
    

    ③创建图标

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

    //全部工具页面
    //  大按钮
    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>' +
            '<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>';
        NormalToolDom = $(str);
        addButton = NormalToolDom.find(".add");
        cancelButton = NormalToolDom.find(".cancel");
        DomClickEvent = callback;
        setClickEvent();
        return getDomInAllTools();
    };
     
    //我的工具页面
    //  创建普通的dom
    var createInMyToolDom = function () {
        var str = '<div class="tool-my">' +
            '<div class="img" style="background-position: ' + obj.commonImg.ImgPosition.x + ' ' + obj.commonImg.ImgPosition.y + '"></div>' +
            '<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>' +
            '<div class="text">' + obj.title + '</div>' +
            '<div class="edit-img displayNONE"></div>' +
            '</div>';
        var node = $(str);
        return node;
    };
    

    注:

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

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

    ④响应逻辑:

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

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

    //  设置全部工具里的点击事件
    var setClickEvent = function () {
        var node = BigImgDom ? BigImgDom : NormalToolDom;
        node.click(function (event) {
            if (state) {
                DomClickEvent();
            } else if (state === 0) {
                self.addDomToMyTools();
            }
        });
    };
    

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

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

    //将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】点击事件:

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

    //  设置我的工具页面的两种按钮的点击事件
    var setMyToolClickEvent = function (node) {
        node.click(function (event) {
            if (!editing) {
                DomClickEvent();
            }
        });
    };
    

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

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

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

    //我的工具大图标的移动函数
    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();
                return;
            }
            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) {
            if (move) {
                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();
                    }
                }
            }
        })
    };
    

    解释:

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

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

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

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

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

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

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

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

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

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

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

    this.InMyToolDomEndMoving = function () {
        if (!SmallToolDom) {
            SmallToolDom = createSmallTool();
            //setMyToolClickEvent(SmallToolDom);
            editButtonInSmallToolDom = SmallToolDom.find(".edit-img");
            setSmallEditEvent(editButtonInSmallToolDom);
            setSmallToolDomMoveEvent();
        }
        return SmallToolDom;
    };
    

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

    绑定事件有:

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

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

    //  设置小的dom的编辑按钮的点击事件
    var setSmallEditEvent = function (editNode) {
        editNode.click(function (event) {
            self.removeSmallTool();
            editButtonInSmallToolDom.addClass("displayNONE");
            SmallToolDom.detach();
            event.stopPropagation();
        })
    };
    

    《3》移动事件;

    var setSmallToolDomMoveEvent = function () {
        var mouseX = null;
        var mouseY = null;
        var startLeft = null;
        var startTop = null;
        var placeHholderDom = $('<div class="tool-foot placeholder SmallToolHolder">' +
            '<div class="placeholder-img"></div>' +
            '<div class="text">拖拽到此</div>' +
            '</div>');
        SmallToolDom.mousedown(function (evt) {
            if (evt.button != 0) {
                return;
            }
            if (editing & $(evt.target)[0] == editButtonInSmallToolDom[0]) {
                event.stopPropagation();
                return;
            }
            mouseX = evt.clientX;   //这里的值是鼠标坐标
            mouseY = evt.clientY;
            var position = SmallToolDom.position();
            startLeft = position.left;  //没有px
            startTop = position.top;
            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();
            }
        });
        $(".toolbox-my").mousemove(function (evt) {
            if (!evt.buttons & SmallIconMove) {  //只有不在按,且当前是true的时候,才触发
                SmallIconMove = false;
                placeHholderDom.before(SmallToolDom);
                placeHholderDom.remove();
                SmallToolDom.css("position", "relative");
                SmallToolDom.css("left", "0");
                SmallToolDom.css("top", "0");
                $(".SmallToolHolder").remove();
                if (mouseX == evt.clientX & mouseY == evt.clientY) {
                    if (!editing) {
                        DomClickEvent();
                    }
                }
            }
            if (SmallIconMove) {
                self.SmallToolDomMoving([placeHholderDom, evt]);
                var offsetX = evt.clientX - mouseX;
                var offsetY = evt.clientY - mouseY;
                SmallToolDom.css("left", offsetX + startLeft + "px");
                SmallToolDom.css("top", offsetY + startTop + "px");
                if ($(".SmallToolHolder").length > 1) {
                    $(".SmallToolHolder")[1].remove();
                }
            }
        });
        SmallToolDom.mouseup(function (evt) {
            if (SmallIconMove) {
                SmallIconMove = false;
                placeHholderDom.before(SmallToolDom);
                placeHholderDom.remove();
                SmallToolDom.css("position", "relative");
                SmallToolDom.css("left", "0");
                SmallToolDom.css("top", "0");
                $(".SmallToolHolder").remove();
                if (mouseX == evt.clientX & mouseY == evt.clientY) {
                    if (!editing) {
                        DomClickEvent();
                    }
                }
            }
        })
    }
    

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

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

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

    //移动时会触发这个方法
    this.InMyToolDomMoving = function (arr) {
        return arr;
    };
     
    this.InMyToolDomEndMoving = function () {
        if (!SmallToolDom) {
            SmallToolDom = createSmallTool();
            //setMyToolClickEvent(SmallToolDom);
            editButtonInSmallToolDom = SmallToolDom.find(".edit-img");
            setSmallEditEvent(editButtonInSmallToolDom);
            setSmallToolDomMoveEvent();
        }
        return SmallToolDom;
    };
     
    this.SmallToolDomMoving = function (arr) {
        return arr;
    };
    

    ⑤其他事件:

    //设置编辑或者结束编辑
    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");
        editButtonInMyToolDom.addClass("displayNONE");
        if (editButtonInSmallToolDom) {
            editButtonInSmallToolDom.addClass("displayNONE");
        }
        state = 0;  //设置其状态为未添加
    }
    

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

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

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

    重写ToolsConfigJsonLoad函数:
    这个函数做了这些事情:

    ①读取json;

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

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

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

    声明这个函数:

    var ToolsConfigJsonLoad = function (InMyToolArray, url) {
        this.url = url ? url : "data/tools.json";
    

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

    this.load = function () {
        var self = this;
        $.ajax({
            url: self.url,
            dataType: "json",
            type: "GET",
            success: function (data) {
                addToolsInToolbox_all(data);
     
            }
        })
    };
    

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

    //将内容添加到全部工具页面中
    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);
            }
            var tool = new Tool(obj);
            var mixin = new MixinTool(obj);
            var callback = mixin.mixin()
            listenToolEvent(tool);
            $(".commonRow." + obj.type).append(tool.createNormalToolDom(callback));
        })
        addPlaceHolderWhenOnlyTwoToolsInToolbox_All(type);
        addDottedLineInToolbox_All();
    };
    

    监听事件先略过;

    添加分割线:

    // 这个目的是为了给全部工具中的多行工具之间添加分割线
    var addDottedLineInToolbox_All = function () {
        $(".commonRow .normalTool:nth-child(3n+4)").before('<div class="dotted"></div>');
    };
    

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

    // 这个目的是当某一行只有两个图标时,创造一个占位的图标
    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>'));
            }
        })
    };
    

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

    //参数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类的实例。

    //监听事件
    var listenToolEvent = function (tool) {
    

    他包含以下方法:

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

    runAfter(tool, "addDomToMyTools", function () {
        InMyToolArray.push(tool);
    });
    

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

    runAfter(tool, "setStateToUnadd", function () {
        var MyToolIndex = InMyToolArray.indexOf(tool);
        InMyToolArray.splice(MyToolIndex, 1);
    });
    

    ③还需要一个占位图标,用于图标在移动时占位:

    var placeHolderInSmall = $('<div class="tool-foot placeholder">' +
        '<div class="placeholder-img"></div>' +
        '<div class="text">拖拽到此</div>' +
        '</div>')
    

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

    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");
        }
    });
    
    

    ⑤当图标停止移动时,需要决定他是否被移动到一个新位置,或者是添加到快捷入口那里;

     var sign = false;
        $(".tool-foot").toArray().forEach(function (node, index) {
            if ($(node)[0] == placeHolderInSmall[0]) {
                sign = true;
            }
        })
        if (sign) {
            if (node.hasClass("displayNONE")) {
                node.removeClass("displayNONE");
            }
            placeHolderInSmall.before(node);
            placeHolderInSmall.remove();
        }
        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) {
        var placeHolder = result[0];
        var event = result[1];
        $(".tool-foot").toArray().forEach(function (node) {
            var position = $(node).offset(); //获取相对于文档的位置
            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);
                    } else {
                        $(node).after(placeHolder);
                    }
                }
            }
        });
    });
    

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

    让工具箱运行起来:

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

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

    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 {
                InMyToolArray.forEach(function (item) {
                    item.setEditing();
                })
                //设置编辑按钮的样式变更
                $(this).addClass("editing");
                var text = $(this).find(".text");
                text.text("退出编辑");
                text.css("width", "52px");
                text.css("margin-left", "-10px");
            }
        });
    }
    

    这个函数干了两件事:

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

    ②设置编辑按钮的事件。

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

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

    js全部代码:

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

    css全部代码:

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

    相关文章

      网友评论

          本文标题:做一个仿360工具箱的web页面(完结篇,可以跑起来的工具箱)

          本文链接:https://www.haomeiwen.com/subject/gthgaftx.html