上移下移扩展版 【总结】

需求

上移下移
需求:
1)点击上移就将当前的按钮的父级上移一位

2)当点击第一个时候将当前按钮的父级移动到最后一位

3)当点击最后一个时候将当前按钮的父级移动到首位

4)带过渡动画

需求分析:

下移:剪切所点击的条目插入到下一条目后面

上移:剪切所点击的条目插入到上一条目前面

过渡效果实现:CSS3的transition 或 js实现

实现思路:

transition实现方法,先在CSS里设置好transition: 1s top; 这个样式,然后鼠标点击修改top值触发过渡效果。

需要用js给每一个li设置top值,因为insertBefore会中断transition所以还必须设个定时器,等到过渡结束再执行DOM层面的剪切

难点:

边界的判断:当第一项点击上移是应该移动到最下面其他都上移一层

      当最后一项点击下移时应该移动到最上面其他都下移一层

insertBefore为什么会中断transition的执行???

难点解决方案:

前两项都可以解决

最后一项想不通!!!???

涉及的新知识:

element.priviousSibling

element.nextSibling

element.parentNode

element.nodeType

parentNode.insertBefore( newEle , targetEle );

优化方向:

不用定时器也能实现DOM层面和视觉层面一起上移下移且有过渡动画

修复连续点击的bug

封装成一个函数

备注:

写完这个,稍微有点懂得【视觉层】和【行为层】分开的意义了,也稍微感觉到了一点React的数据驱动视图了。其实页面上看到的天花乱坠,DOM里可能啥都每变,看起来div在那个div的上门,其实是用css强行改变它们的默认排列的,所以要从DOM的视角看问题。

最后:为什么insertBefore会中断transition????

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>

<style>
    a{ text-decoration: none; }
    a:hover{ text-decoration: underline; }

ul{ position: relative; }

li{
    position: absolute;
    transition: .5s top;
}

</style>

</head>
<body>

<!--
上移下移
    需求:
        1)点击上移就将当前的按钮的父级上移一位

        2)当点击第一个时候将当前按钮的父级移动到最后一位

        3)当点击最后一个时候将当前按钮的父级移动到首位

    跨展板:
        移动时带动画
 -->

<ul id="oUl">
    <li>第一项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li>
    <li>第二项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li>
    <li>第三项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li>
    <li>第四项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li>
    <li>第五项 <a href="javascript:;">上移</a> <a href="javascript:;">下移</a></li>
</ul>

<script src="getId.js"></script>
<script src="doMove.js"></script>
<script src="main.js"></script>

</body>
</html>
var oUl = $(‘oUl‘);
var oLi = oUl.getElementsByTagName(‘li‘);

for(var i=0, oLen=oLi.length; i<oLen; i++){

    oLi[i].style.top = (i*16 + i*6) + ‘px‘;

    //****上移按钮
    oLi[i].getElementsByTagName(‘a‘)[0].onclick = function(){

        var oldTop = null,
            nextTop = null,
            nextItem = getSiEle( this.parentNode , -1 );

        //点击第一项要做的事
        if( !nextItem ){

            nextTop = oUl.children[oUl.children.length-1].style.top;

            //2~5项向上移1格
            for( var j=oUl.children.length-1; j>0; j--  ){
                oLi[j].style.top = oLi[j-1].style.top;
            }

            this.parentNode.style.top = nextTop;

        }else{
            //如果不是最后一项就两两对换
            oldTop = this.parentNode.style.top;
            nextTop = getSiEle( this.parentNode , -1 ).style.top;
            this.parentNode.style.top = nextTop;
            getSiEle( this.parentNode , -1 ).style.top = oldTop;
        }

        //等0.5s的transition结束后在执行DOM剪切操作
        var _this = this;
        setTimeout(function(){
            if( !moveUp( _this.parentNode ) ){
                oUl.appendChild( _this.parentNode )
            }
        },500);

    }
    //****上移按钮结束****//

    //****下移按钮开始
    oLi[i].getElementsByTagName(‘a‘)[1].onclick = function(){

        var oldTop = null,
            nextTop = null,
            nextItem = getSiEle( this.parentNode , 1 );

        //点击最后第一项要做的事
        if( !nextItem ){

            nextTop = oUl.children[0].style.top;

            //1~4项的位置下降“1格”
            for(var j=0,oLen=oUl.children.length; j<oLen-1; j++  ){
                oLi[j].style.top = oLi[j+1].style.top
            }

            //点击项升到顶端
            this.parentNode.style.top = nextTop;

        }else{
            //如果不是最后一项就两两对换
            oldTop = this.parentNode.style.top;
            nextTop = getSiEle( this.parentNode , 1 ).style.top;
            this.parentNode.style.top = nextTop;
            getSiEle( this.parentNode , 1 ).style.top = oldTop;
        }

        //等0.5s的transition结束后在执行DOM剪切操作
        var _this = this;
        setTimeout(function(){
            if( !moveDown( _this.parentNode ) ){
                insertBefore( _this.parentNode , oUl.children[0] );
            }
        },500);

    }
    //****下移按钮结束****//

}
function $( v ){
    if(typeof v === ‘function‘){
        window.onload = v;
    }else if(typeof v === ‘string‘){
        return document.getElementById( v );
    }else if(typeof v === ‘object‘){
        return v;
    }
}

function getStyle( obj,attr ){
    var arr = ‘‘;
    for(var i=0; i<attr.length; i++){
        if(attr[i] != ‘ ‘)
            arr += attr[i];
    }

    return obj.currentStyle ? obj.currentStyle[arr] : getComputedStyle(obj)[arr];
} 

function $class(typeEle,attr){
    var oChild = document.getElementsByTagName(typeEle);
    var arr = [];
    for(var i=0; i<oChild.length; i++){
        if( oChild[i].className == attr ){
            arr.push(oChild[i]);
        }

    }

    return arr;

}

function getSiEle( ele , v ){

    //-1代表查找前一个兄弟元素,1代表查找后一个兄弟元素
    //开始查找前判断本元素是不是第一个元素或最后一个元素,如果是返回false
    //开始查找

    if( v === -1 ){
        v = ‘previousSibling‘; 

        if( ele.parentNode.children[0] == ele ){
            return false;
        }

    }

    if( v === 1 ){
        v = ‘nextSibling‘;

        if( ele == ele.parentNode.children[ ele.parentNode.children.length-1 ] ){
            return false;
        }

    }

    var theParent = ele[v];
    while( theParent.nodeType != 1 ){
        theParent = theParent[v];
    }
    return theParent;

}

//重新包装一下
function insertBefore( newEle , targetEle ){

    targetEle.parentNode.insertBefore( newEle , targetEle );

}

//向targetEle后面插入一个元素节点
function insertAfter( newEle , targetEle ){

    var tNextSibling = targetEle.nextSibling;
    var targetEleParent = targetEle.parentNode;

    if( tNextSibling ){
        targetEleParent.insertBefore( newEle , tNextSibling );
    }else{
        targetEleParent.appendChild( newEle );
    }

}

//上移
function moveUp( ele ){
    var tSiEle = getSiEle( ele , -1 );

    if( !tSiEle ){
        return false;
    }

    ele.parentNode.insertBefore( ele , tSiEle );
    return true;

}

//下移
function moveDown( ele ){
    var tSiEle = getSiEle( ele , 1 );

    if( !tSiEle ){
        return false;
    }

    insertAfter( ele , tSiEle );
    console.log(555);
    return true;

}

/*

while(true){
    if( oDiv[oDiv.length-1] != 400 ){
        FdoMove(400);
    }else{
        FdoMove(0);
    }
}

function FdoMove(endStep){

    document.onclick = function(){
        clearInterval(attrs.timer);
        attrs.timer = setInterval(function(){

            if(endStep != 0){

                if(  parseInt(oDiv[attrs.i].style.top) == endStep )
                    attrs.i++;

                if( attrs.i < oDiv.length ){
                    doMove( oDiv[attrs.i], ‘top‘, 90, endStep );
                }else{
                    clearInterval(attrs.timer);
                    attrs.timer = null;
                }

            }else{

                if(  parseInt(oDiv[attrs.lastNum].style.top) == endStep )
                    attrs.lastNum--;

                if( attrs.lastNum >= endStep ){
                    doMove( oDiv[attrs.lastNum], ‘top‘, 90, endStep );
                }else{
                    clearInterval(attrs.timer);
                    attrs.timer = null;
                }

            }

        },90);

    }

}*/

原文地址:https://www.cnblogs.com/mflnhg/p/9503309.html

时间: 2024-10-08 12:28:32

上移下移扩展版 【总结】的相关文章

扩展版瀑布流

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>瀑布流-扩展版02</title> <style type="text/css"> * { margin: 0; padding: 0; } #list { list-style: none; position: relative; margin: 0 auto; }

AngularJS实现数据列表的增加、删除和上移下移等功能实例

转: http://www.jb51.net/article/91991.htm 这篇文章给大家分享了AngularJS循环实现数据列表的增加.删除和上移下移等基础功能,对大家学习AngularJS具有一定的参考借鉴价值,有需要的朋友可以看看. 效果图 实例代码 <!DOCTYPE html> <html lang="en" ng-app="myapp" ng-controller="myCtrl"> <head&g

利用jQuery操作select列表选项的上移下移示例

导读:本文实现了一个简单的select列表选项的上移下移操作,可帮助读者了解jQuery选择器,节点操作的一些常用方法 实现的效果: 分享代码: 1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="MoveNode_Default" %> 2 3 <!DOCTYPE html PUBLIC &

用PC浏览器模拟手机浏览器(一):无扩展版

想浏览手机版,打开对应网址却跳转到PC版?怎么办? 下面咱们来说下在只是安装了浏览器,无需其他安装操作的情况下来怎么用PC浏览器模拟手机浏览器,然后访问手机站点. 浏览器众多,IE系列的咱就不考虑了,相信你也不用他浏览手机站点,否侧太没品位了,那咱今天就说说其他的:Chrome和Safari两个浏览器,在无任何扩展的情况下怎么来模拟手机浏览器. 其实,还是如前言里说的,就是修改浏览器的User Agent,来让那些以User Agent为判断标准的站点认为你当前的浏览器为手机浏览器,从而呈现手机

js 上移下移行

function up_tr(sender) {                            var tr = $(sender).parent().parent();                            var table = tr.parent();                            var first = $("tr:first", table);                            if (tr.html() =

JS移动li行数据,点击上移下移(是位置的互换,不是top的偏移量改变)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta content="text/html; cha

jquery行上移下移删除

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Typ

php修改排序,上移下移

php修改排序,上移下移 /**  $UpDown //移动方向,up或down  $table //表名  $id //当前移动的ID  $id_col //ID字段的名称  $oc_col //排序字段的名称  $where //条件 */ function MoveUpDown($UpDown,$table,$id,$id_col='id',$oc_col='OrderColumn',$where='')  {    if($UpDown=='up'){$op='<';$desc='des

TcxTreeList 节点 上移 下移 代码

if not Assigned(cxDBTreeList1.FocusedNode) then Exit; // 上移方法: with cxDBTreeList1 do FocusedNode.MoveTo(FocusedNode.getPrevSibling, tlamInsert); // 下移方法: with cxDBTreeList1 do FocusedNode.getNextSibling.MoveTo(FocusedNode, tlamInsert); TcxTreeList 节点