jQuery时间轴插件使用详解


Posted in Javascript onJuly 16, 2015

这个时间轴是工作上用到的,自己写了一个, qq空间有时间轴的控件, 百度文库也有时间轴的控件;

百度的时间轴大概是这样的:

jQuery时间轴插件使用详解

用户点击对应的锚链接,  那个三角会滚动, 然后左侧的界面也会滚动;

实际的效果如下图,用户点击左侧的按钮或者右侧的input,滚动条都会主动滚动, 这里有个小技巧就是用after和before伪类生成三角形, 用户点击按钮的滚动效果直接用jq的animate方法:

jQuery时间轴插件使用详解

<!--
//设置内容;
window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1111},{"name":2222}]}}' ) ;

//设置内容, 对应的item对象如果active为true为激活态;
window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1000},{"name":1111},{"name":2222},{"name":3333,"active":true}]}}' ) ;

//设置某个第n个位置的item;
window.onWebMessage('{"type":"setItem","data":[2,{ "name" : "add-item"}]}');

//激活第三个锚链接为选中态;
window.onWebMessage( '{"type":"active","data":2}' )

//获取目前的数据:
window.onWebMessage( '{"type":"getItem"}' );
-->

<html>
  <head>
    <meta charset="utf-8" />
    <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
  </head>
  <style>
    /*初始的reset样式*/
    *{
      margin:0;
      padding:0;
    }
    .time-line-wrap{
      position: relative;
      width: 400px;
      margin:0 auto;
    }
    ul{
      list-style: none;
    }
    body,html{
      height: 100%;
    }
    body{
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }


    /*样式开始*/
    .scroll-time-line{
      height:100%;
      overflow: hidden;
    }
    .time-line-wrap{
      position: relative;
    }
    .time-line-ul{
      position: relative;
    }
    /**
    时间轴的轴用伪类实现;
    */
    .time-line-ul::before{
      display: block;
      position:absolute;
      content:"";
      height:100%;
      width:1;
      left:27px;
      top:0;
      background: #eee;
    }
    .time-line-ul li{
      padding:14px;
      position: relative;
    }
    .time-line-ul input {
      vertical-align: super;
      border-radius: 4px;
      border:1px solid #eee;
      padding:4px;
      line-height: 22px;
      margin-left:10px;
    }
    /**
    使用after和before伪类实现input前面的三角形;
    */
    .time-line-ul li::before{
      position: absolute;
      content: "";
      display: block;
      top: 21px;
      left: 40px;
      width: 0px;
      height: 0px;
      border: 10px solid rgba(0, 0, 0, 0);
      border-right: 10px solid #EEE;
    }
    .time-line-ul li::after{
      position: absolute;
      content: "";
      display: block;
      top: 21px;
      left: 41px;
      width: 0px;
      height: 0px;
      border: 10px solid rgba(0, 0, 0, 0);
      border-right: 10px solid #fff;
    }
    /**
    默认时间轴锚链接的样式
    */
    .time-line-icon{
      width: 26px;
      height: 28px;
      display: inline-block;
      background: url(http://images0.cnblogs.com/blog2015/497865/201507/131424386411828.png);
    }
    /**
    鼠标移动上来,或者锚链接有active时候的背景图样式
    */
    .time-line-icon.active,.time-line-icon:hover{
      background-position: 0px 28px;
    }
  </style>

  <!--模板,勿删!-->
  <script type="text/tempate" id="li-tpl">
    <% for(var i=0; i<items.length; i++ ) {%>
      <li class="li-<%=i%>">
        <a href="###" class="time-line-icon <% if(items[i].active){ %> <%="active"%> <%}%> "></a>
        <input type="text" value="<%=items[i].name%>"/>
      </li>
    <% } %>
  </script>

  <body>
    <!--
    滚动出现在这个div里面
    -->
    <div class="scroll-time-line">

      <!---
      时间轴相关的html结构
      -->
      <div class="time-line-wrap">
        <ul class="time-line-ul">
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
          <li>
            <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
          </li>
        </ul>
      </div>
      <!---
      时间轴相关的html结构结束
      -->
    </div>
    <script>
      //模板引擎的代码
      (function () {
        //underscore抄的模板引擎;
        var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;

        var escapes = {
          "'":   "'",
          '\\':   '\\',
          '\r':   'r',
          '\n':   'n',
          '\t':   't',
          '\u2028': 'u2028',
          '\u2029': 'u2029'
        };

        $.templateSettings = {
          evaluate  : /<%([\s\S]+?)%>/g,
          interpolate : /<%=([\s\S]+?)%>/g,
          escape   : /<%-([\s\S]+?)%>/g
        }
        $.template = function(text, data, settings) {
          var render;
          settings = $.extend({}, settings, $.templateSettings);

          // Combine delimiters into one regular expression via alternation.
          var matcher = new RegExp([
            (settings.escape || noMatch).source,
            (settings.interpolate || noMatch).source,
            (settings.evaluate || noMatch).source
          ].join('|') + '|$', 'g');

          // Compile the template source, escaping string literals appropriately.
          var index = 0;
          var source = "__p+='";
          text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
            source += text.slice(index, offset)
                .replace(escaper, function(match) { return '\\' + escapes[match]; });

            if (escape) {
              source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
            }
            if (interpolate) {
              source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
            }
            if (evaluate) {
              source += "';\n" + evaluate + "\n__p+='";
            }
            index = offset + match.length;
            return match;
          });
          source += "';\n";

          // If a variable is not specified, place data values in local scope.
          if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

          source = "var __t,__p='',__j=Array.prototype.join," +
              "print=function(){__p+=__j.call(arguments,'');};\n" +
              source + "return __p;\n";

          try {
            render = new Function(settings.variable || 'obj', '_', source);
          } catch (e) {
            e.source = source;
            throw e;
          }

          if (data) return render(data, _);
          var template = function(data) {
            return render.call(this, data);
          };

          // Provide the compiled function source as a convenience for precompilation.
          template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';

          return template;
        };
      })();

      (function( fn ) {

        $( fn.call( $ ,$) );

      })(function ($) {

        $.timeLineSetting = {
          offsetTop : 100
        };
        $.extend($.fn, {
          timeLine : function() {
            $.each(this, function() {

              var _this = this;

              $(this).delegate(".time-line-ul>li", "click", function( ev ) {

                $(".time-line-icon.active").removeClass("active");

                $(this).find(".time-line-icon").addClass("active");

                $(_this).animate({scrollTop: this.offsetTop - $.timeLineSetting.offsetTop},300);

                ev.preventDefault();

              });
            });
          }
        });
      });
      $(function() {
        var compile= $.template( $("#li-tpl").html() || "");

        //与客户端的交互事件;
        var orginalData = {};
        window.onWebMessage = function( msg ) {
          msg = JSON.parse(msg);
          switch( msg.type ) {
            case "setItems" :
              $(".time-line-ul").html( compile(msg.data) );
              //结构化复制;
              orginalData = JSON.parse(JSON.stringify(msg.data));
              break;

            case "setItem" :
              orginalData.items&&orginalData.items.splice(msg.data[0],0,msg.data[1]);
              $(".time-line-ul").html( compile(orginalData) );
              break;

            case "getItem" :
                alert(JSON.stringify( orginalData ));
              break;

            case "active" :
              $(".time-line-icon.active").removeClass("active");
              $(".time-line-ul>li").eq( msg.data).find(".time-line-icon").addClass("active")
              break;

          };

        };

        //启用插件;
        $(".scroll-time-line").timeLine();
      })
    </script>
  </body>
</html>

 

模板用了underscore,tempate方法挂到了$下, 作为$的工具方法(依赖于jQuery),模板的js代码直接放这里方便一些小项目直接用:

//模板引擎的代码
      (function () {
        //underscore抄的模板引擎;
        var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;

        var escapes = {
          "'":   "'",
          '\\':   '\\',
          '\r':   'r',
          '\n':   'n',
          '\t':   't',
          '\u2028': 'u2028',
          '\u2029': 'u2029'
        };

        $.templateSettings = {
          evaluate  : /<%([\s\S]+?)%>/g,
          interpolate : /<%=([\s\S]+?)%>/g,
          escape   : /<%-([\s\S]+?)%>/g
        }
        $.template = function(text, data, settings) {
          var render;
          settings = $.extend({}, settings, $.templateSettings);

          // Combine delimiters into one regular expression via alternation.
          var matcher = new RegExp([
            (settings.escape || noMatch).source,
            (settings.interpolate || noMatch).source,
            (settings.evaluate || noMatch).source
          ].join('|') + '|$', 'g');

          // Compile the template source, escaping string literals appropriately.
          var index = 0;
          var source = "__p+='";
          text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
            source += text.slice(index, offset)
                .replace(escaper, function(match) { return '\\' + escapes[match]; });

            if (escape) {
              source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
            }
            if (interpolate) {
              source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
            }
            if (evaluate) {
              source += "';\n" + evaluate + "\n__p+='";
            }
            index = offset + match.length;
            return match;
          });
          source += "';\n";

          // If a variable is not specified, place data values in local scope.
          if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

          source = "var __t,__p='',__j=Array.prototype.join," +
              "print=function(){__p+=__j.call(arguments,'');};\n" +
              source + "return __p;\n";

          try {
            render = new Function(settings.variable || 'obj', '_', source);
          } catch (e) {
            e.source = source;
            throw e;
          }

          if (data) return render(data, _);
          var template = function(data) {
            return render.call(this, data);
          };

          // Provide the compiled function source as a convenience for precompilation.
          template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';

          return template;
        };
      })();

模板的使用的DEMO如下, 也可以参考官方的文档:http://underscorejs.org/#template:

<html>
  <head>
    <body>
      <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
      <script>
      //模板引擎的代码
      (function () {
        //underscore抄的模板引擎;
        var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;

        var escapes = {
          "'":   "'",
          '\\':   '\\',
          '\r':   'r',
          '\n':   'n',
          '\t':   't',
          '\u2028': 'u2028',
          '\u2029': 'u2029'
        };

        $.templateSettings = {
          evaluate  : /<%([\s\S]+?)%>/g,
          interpolate : /<%=([\s\S]+?)%>/g,
          escape   : /<%-([\s\S]+?)%>/g
        }
        $.template = function(text, data, settings) {
          var render;
          settings = $.extend({}, settings, $.templateSettings);

          // Combine delimiters into one regular expression via alternation.
          var matcher = new RegExp([
            (settings.escape || noMatch).source,
            (settings.interpolate || noMatch).source,
            (settings.evaluate || noMatch).source
          ].join('|') + '|$', 'g');

          // Compile the template source, escaping string literals appropriately.
          var index = 0;
          var source = "__p+='";
          text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
            source += text.slice(index, offset)
                .replace(escaper, function(match) { return '\\' + escapes[match]; });

            if (escape) {
              source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
            }
            if (interpolate) {
              source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
            }
            if (evaluate) {
              source += "';\n" + evaluate + "\n__p+='";
            }
            index = offset + match.length;
            return match;
          });
          source += "';\n";

          // If a variable is not specified, place data values in local scope.
          if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

          source = "var __t,__p='',__j=Array.prototype.join," +
              "print=function(){__p+=__j.call(arguments,'');};\n" +
              source + "return __p;\n";

          try {
            render = new Function(settings.variable || 'obj', '_', source);
          } catch (e) {
            e.source = source;
            throw e;
          }

          if (data) return render(data, _);
          var template = function(data) {
            return render.call(this, data);
          };

          // Provide the compiled function source as a convenience for precompilation.
          template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';

          return template;
        };
      })();
      </script>
      <script>
      //会输出 <div>haahah</div>;
      console.log( $.template('<div><%=data%></div>')( {data:"haahah"} ) );
      </script>
    </body>
  </head>
</html>

修改了时间轴的样式, 又为这个插件添加了拖拽的方法,代码一下变得好乱, 顺便普及一下拖拽的事件, ondrop, ondragover,ondrag, 如果要让元素可以拖拽, 就要为要拖拽的元素添加draggable="true",   元素可以拖拽以后 , 要为可以拖放到的的DIV或者其他块元素,绑定一个dragover方法, 这个方法就做一件事, ev.preventDefault(), 看代码撒:

运行下面代码

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8"/>
  <style type="text/css">
    #div1 {width:488px;height:70px;padding:10px;border:1px solid #aaaaaa;}
  </style>
  <script type="text/javascript">
    //当元素dragover时候一定要阻止默认事件, 否则把当前拖拽的元素就无法drop;
    function dragover(ev)
    {
      console.log(ev);
      ev.preventDefault();
    }

    //对于拖拽事件最重要的一个事件属性就是dataTransfer;
    function drag(ev)
    {
      console.log(ev);
      ev.dataTransfer.setData("Text",ev.target.id);
    }

    function drop(ev)
    {
      console.log(ev);
      var data=ev.dataTransfer.getData("Text");
      ev.target.appendChild(document.getElementById(data));
    }
  </script>
</head>
<body>

<p>请把图片拖放到矩形中:</p>

<div id="div1" ondrop="drop(event)" ondragover="dragover(event)"></div>
<br />
<img id="drag1" src="http://images0.cnblogs.com/news/24442/201507/081152502219706.gif" draggable="true" ondragstart="drag(event)" />

</body>
</html>

另外一个DEMO:

运行下面代码

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8"/>
  <style type="text/css">
  </style>
</head>
<body>
  <p>What fruits do you like?</p>
  <ol ondragstart="dragStartHandler(event)">
    <li draggable="true" data-value="fruit-apple">Apples</li>
    <li draggable="true" data-value="fruit-orange">Oranges</li>
    <li draggable="true" data-value="fruit-pear">Pears</li>
  </ol>
  <script>
    var internalDNDType = 'text/x-example'; // set this to something specific to your site
    function dragStartHandler(event) {
      if (event.target instanceof HTMLLIElement) {
        // use the element's data-value="" attribute as the value to be moving:
        event.dataTransfer.setData(internalDNDType, event.target.dataset.value);
        event.dataTransfer.effectAllowed = 'move'; // only allow moves
      } else {
        event.preventDefault(); // don't allow selection to be dragged
      }
    }
  </script>

  <p>Drop your favorite fruits below:</p>
  <ol ondrop="dropHandler(event)" ondragover="dragover(event)">
    <!-- don't forget to change the "text/x-example" type to something
    specific to your site -->
    <li>drop</li>
  </ol>
  <script>
    var internalDNDType = 'text/x-example'; // set this to something specific to your site
    function dropHandler(event) {
      var li = document.createElement('li');
      var data = event.dataTransfer.getData(internalDNDType);
      if (data == 'fruit-apple') {
        li.textContent = 'Apples';
      } else if (data == 'fruit-orange') {
        li.textContent = 'Oranges';
      } else if (data == 'fruit-pear') {
        li.textContent = 'Pears';
      } else {
        li.textContent = 'Unknown Fruit';
      }
      event.target.appendChild(li);
    };
    function dragover(ev) {
      ev.preventDefault();
    };
  </script>
</body>
</html>

 

HTML5的拖拽提供了 setDragImage ,  effectAllowed , setData.... 等很多便捷的方法给开发者,  通过FileReader读取File, 然后就可以用ajax与后台进行交互, 和前端DOM操作:

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8"/>
  <style type="text/css">
  </style>
</head>
<body>
  <div id="div0" ondragover="dragover(event)" ondrop="drop(event)">
    drop拖放文件进来
  </div>
  <script>
    function dragover(ev) {
      ev.preventDefault();
    };
    function drop(ev) {
      var reader = new FileReader();
      reader.onload = function ( ev ) {
        var oDiv = document.createElement("div");
        oDiv.innerHTML = ev.target.result;
        document.body.appendChild( oDiv );
      };
      reader.readAsText( ev.dataTransfer.files[0] );
      ev.preventDefault();
    }
  </script>
</body>
</html>

插件效果图:

jQuery时间轴插件使用详解

最后完成的插件代码:

<!--
//设置内容;
window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1111,"type":"doc"},{"name":2222,"type":"doc"}]}}' ) ;

window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":"文档类型","type":"doc"},{"name":"音频类型","type":"audio","active":true},{"name":"视频类型","type":"video"},{"name":"单元测试","type":"test"},{"name":"图片类型","type":"pic"}]}}' ) ;

//设置内容, 对应的item对象如果active为true为激活态;
window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1111,"type":"doc"},{"name":2222,"type":"doc","active":true}]}}' ) ;

//设置某个第n个位置的item;
window.onWebMessage('{"type":"setItem","data":[2,{ "name" : "add-item", "type":"doc"}]}');

//激活第三个锚链接为选中态;
window.onWebMessage( '{"type":"active","data":2}' )

//获取目前的数据:
window.onWebMessage( '{"type":"getItem"}' )
-->

<html>
  <head>
    <meta charset="utf-8" />
    <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
  </head>
  <style>
    /*初始的reset样式*/
    *{
      margin:0;
      padding:0;
    }
    .time-line-wrap{
      position: relative;
      width: 400px;
      margin:0 auto;
    }
    ul{
      list-style: none;
    }
    body,html{
      height: 100%;
    }
    body{
      background:#303030;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
    }


    /*样式开始*/
    .scroll-time-line{
      height:100%;
      overflow: hidden;
    }
    .time-line-wrap{
      position: relative;
    }
    .time-line-wrap::before{
      display: block;
      content: "";
      position: absolute;
      border: 2px solid #616161;
      width: 7px;
      background: #303030;
      height: 7px;
      z-index: 2;
      border-radius: 100%;
      left: 12px;
      top: 0;
    }
    .time-line-wrap::after{
      display: block;
      content: "";
      position: absolute;
      border: 2px solid #616161;
      width: 7px;
      background: #303030;
      height: 7px;
      z-index: 2;
      border-radius: 100%;
      left: 12px;
      bottom:0;
    }
    .time-line-ul{
      position: relative;
    }
    /**
    时间轴的轴用伪类实现;
    */
    .time-line-ul::before{
      display: block;
      position:absolute;
      content:"";
      height:100%;
      width:1px;
      left:17px;
      top:0;
      background: #616161;
    }

    .time-line-ul li{
      padding: 14px;
      position: relative;
      color: #FFF;
      height: 26px;
    }
    .time-line-ul li>* {
      vertical-align: middle;
      display: inline-block;
    }

    /**
    为了更好的维护hover的样式, 背景图片通过js进行管理
    hover start;
    */
    .time-line-ul li b{
      width: 32px;
      height: 32px;
    }
    .time-line-ul li b.active{
      display: none;
    }
    .time-line-ul li:hover b{
      display: none;
    }
    .time-line-ul li:hover .active{
      display: inline-block;
    }
    /**
      当li被点击的时候添加的类,优先级
    */
    .time-line-ul li b.show{
      display: none;
    }
    .time-line-ul li b.active.show{
      display: inline-block;
    }
    /**
    hover end
    */

    .time-line-ul li span{
      display: inline-block;
      white-space: nowrap;
      word-wrap: normal;
      width: 100px;
      text-overflow: ellipsis;
      overflow: hidden;
    }
    /**
    当拖拽LI到某个LI上面,这个LI变透明
    */
    .over{
      opacity: 0.4;
    }
    /**
    占位DIV;
    */
    .blank{
      display: block;
      height:50px;
      line-height: 50px;
    }

    /**
    默认时间轴锚链接的样式
    */
    .time-line-icon{
      width: 7px;
      height: 7px;
      display: inline-block;
      background: #616161;
      border-radius: 100%;
    }
    /**
    鼠标移动上来,或者锚链接有active时候的背景图样式
    */
    .time-line-icon.active,.time-line-icon:hover{
      background: #fff;
    }
  </style>

  <!--模板,勿删!-->
  <script type="text/tempate" id="li-tpl">
    <% for(var i=0; i<items.length; i++ ) {%>
      <li class="li-<%=i%>" draggable="true">
        <a href="###" class="time-line-icon <% if(items[i].active){ %> <%="active"%> <%}%> "></a>
        <b class="">
          <img src="imgs/<%=items[i].type%>.png" />
        </b>
        <b class="active">
          <img src="imgs/<%=items[i].type%>1.png" />
        </b>
        <span>
          <%=items[i].name%>
        </span>
      </li>
    <% } %>
  </script>

  <body>
    <!--
    滚动出现在这个div里面
    -->
    <div class="scroll-time-line">

      <!---
      时间轴相关的html结构
      -->
      <div class="time-line-wrap">
        <ul class="time-line-ul">

          <!----假数据--->
          <li class="li-0" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/doc.png">
            </b>
            <b class="active">
              <img src="imgs/doc1.png">
            </b>
            <span>
              文档类型
            </span>
          </li>

          <li class="li-2" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/video.png">
            </b>
            <b class="active">
              <img src="imgs/video1.png">
            </b>
            <span>
              视频类型
            </span>
          </li>


          <li class="li-3" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/test.png">
            </b>
            <b class="active">
              <img src="imgs/test1.png">
            </b>
            <span>
              单元测试
            </span>
          </li><li class="li-1" draggable="true">
          <a href="###" class="time-line-icon active "></a>
          <b class="">
            <img src="imgs/audio.png">
          </b>
          <b class="active">
            <img src="imgs/audio1.png">
          </b>
          <span>
            音频类型
          </span>
        </li>

          <li class="li-4" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/pic.png">
            </b>
            <b class="active">
              <img src="imgs/pic1.png">
            </b>
          <span>
            图片类型
          </span>
          </li>

          <li class="li-0" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/doc.png">
            </b>
            <b class="active">
              <img src="imgs/doc1.png">
            </b>
            <span>
              文档类型
            </span>
          </li>

          <li class="li-2" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/video.png">
            </b>
            <b class="active">
              <img src="imgs/video1.png">
            </b>
            <span>
              视频类型
            </span>
          </li>


          <li class="li-3" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/test.png">
            </b>
            <b class="active">
              <img src="imgs/test1.png">
            </b>
            <span>
              单元测试
            </span>
          </li><li class="li-1" draggable="true">
          <a href="###" class="time-line-icon active "></a>
          <b class="">
            <img src="imgs/audio.png">
          </b>
          <b class="active">
            <img src="imgs/audio1.png">
          </b>
          <span>
            音频类型
          </span>
        </li>

          <li class="li-4" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/pic.png">
            </b>
            <b class="active">
              <img src="imgs/pic1.png">
            </b>
            <span>
              图片类型
            </span>
          </li>

          <li class="li-0" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/doc.png">
            </b>
            <b class="active">
              <img src="imgs/doc1.png">
            </b>
            <span>
              文档类型
            </span>
          </li>

          <li class="li-2" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/video.png">
            </b>
            <b class="active">
              <img src="imgs/video1.png">
            </b>
            <span>
              视频类型
            </span>
          </li>


          <li class="li-3" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/test.png">
            </b>
            <b class="active">
              <img src="imgs/test1.png">
            </b>
            <span>
              单元测试
            </span>
          </li><li class="li-1" draggable="true">
          <a href="###" class="time-line-icon active "></a>
          <b class="">
            <img src="imgs/audio.png">
          </b>
          <b class="active">
            <img src="imgs/audio1.png">
          </b>
          <span>
            音频类型
          </span>
        </li>

          <li class="li-4" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/pic.png">
            </b>
            <b class="active">
              <img src="imgs/pic1.png">
            </b>
            <span>
              图片类型
            </span>
          </li>

          <li class="li-0" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/doc.png">
            </b>
            <b class="active">
              <img src="imgs/doc1.png">
            </b>
            <span>
              文档类型
            </span>
          </li>

          <li class="li-2" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/video.png">
            </b>
            <b class="active">
              <img src="imgs/video1.png">
            </b>
            <span>
              视频类型
            </span>
          </li>


          <li class="li-3" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/test.png">
            </b>
            <b class="active">
              <img src="imgs/test1.png">
            </b>
            <span>
              单元测试
            </span>
          </li><li class="li-1" draggable="true">
            <a href="###" class="time-line-icon active "></a>
            <b class="">
              <img src="imgs/audio.png">
            </b>
            <b class="active">
              <img src="imgs/audio1.png">
            </b>
            <span>
              音频类型
            </span>
          </li>

          <li class="li-4" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/pic.png">
            </b>
            <b class="active">
              <img src="imgs/pic1.png">
            </b>
            <span>
              图片类型
            </span>
          </li>

          <li class="li-0" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/doc.png">
            </b>
            <b class="active">
              <img src="imgs/doc1.png">
            </b>
            <span>
              文档类型
            </span>
          </li>

          <li class="li-2" draggable="true">
            <a href="###" class="time-line-icon "></a>
            <b class="">
              <img src="imgs/video.png">
            </b>
            <b class="active">
              <img src="imgs/video1.png">
            </b>
            <span>
              视频类型
            </span>
          </li>


          <!---假数据end--->

        </ul>
      </div>
      <!---
      时间轴相关的html结构结束
      -->
    </div>
    <script>
      //模板引擎的代码
      (function () {
        //underscore抄的模板引擎;
        var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;

        var escapes = {
          "'":   "'",
          '\\':   '\\',
          '\r':   'r',
          '\n':   'n',
          '\t':   't',
          '\u2028': 'u2028',
          '\u2029': 'u2029'
        };

        $.templateSettings = {
          evaluate  : /<%([\s\S]+?)%>/g,
          interpolate : /<%=([\s\S]+?)%>/g,
          escape   : /<%-([\s\S]+?)%>/g
        }
        $.template = function(text, data, settings) {
          var render;
          settings = $.extend({}, settings, $.templateSettings);

          // Combine delimiters into one regular expression via alternation.
          var matcher = new RegExp([
            (settings.escape || noMatch).source,
            (settings.interpolate || noMatch).source,
            (settings.evaluate || noMatch).source
          ].join('|') + '|$', 'g');

          // Compile the template source, escaping string literals appropriately.
          var index = 0;
          var source = "__p+='";
          text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
            source += text.slice(index, offset)
                .replace(escaper, function(match) { return '\\' + escapes[match]; });

            if (escape) {
              source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
            }
            if (interpolate) {
              source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
            }
            if (evaluate) {
              source += "';\n" + evaluate + "\n__p+='";
            }
            index = offset + match.length;
            return match;
          });
          source += "';\n";

          // If a variable is not specified, place data values in local scope.
          if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';

          source = "var __t,__p='',__j=Array.prototype.join," +
              "print=function(){__p+=__j.call(arguments,'');};\n" +
              source + "return __p;\n";

          try {
            render = new Function(settings.variable || 'obj', '_', source);
          } catch (e) {
            e.source = source;
            throw e;
          }

          if (data) return render(data, _);
          var template = function(data) {
            return render.call(this, data);
          };

          // Provide the compiled function source as a convenience for precompilation.
          template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';

          return template;
        };
      })();

      (function( fn ) {

        $( fn.call( $ ,$) );

      })(function ($) {

        $.timeLineSetting = {
          offsetTop : 100
        };

        $.extend($.fn, {
          timeLine : function() {
            $.each(this, function() {

              var _this = this,
                  eleDrag;
              $(this).delegate(".time-line-ul>li", "click", function( ev ) {
                $(".time-line-icon.active").removeClass("active");
                $(this).find(".time-line-icon").addClass("active");
                $("b").removeClass("show");
                $(this).find("b").addClass("show");
                $(_this).animate({scrollTop: this.offsetTop - $.timeLineSetting.offsetTop},300);
                ev.preventDefault();
              }).delegate(".time-line-ul>li","dragstart" , function(ev) {
                //不允许img和a的拖拽;
                if( ev.target&&ev.target.tagName.toLocaleLowerCase() === "img" || ev.target.tagName.toLocaleLowerCase() === "a") {
                  return false;
                };
                /*拖拽开始*/
                //拖拽效果
                ev.originalEvent.dataTransfer.effectAllowed = "move";
                eleDrag = ev.originalEvent.target;
                return true;
              }).delegate(".time-line-ul>li","dragenter" , function(ev) {
                return true;
              }).delegate(".time-line-ul>li", "dragover" , function(ev) {
                $(".time-line-ul>li.over").removeClass("over");
                $(this).addClass("over");
                $(".blank").remove();
                var $blank = $("<li class='blank' draggable='true'></li>");
                $(this).after( $blank );
                /*拖拽元素在目标元素头上移动的时候*/
                ev.preventDefault();
                return true;
              });
              $(".time-line-ul").bind("drop" , function(ev) {
                if(ev.target.tagName.toLocaleLowerCase() === "li") {
                  $(ev.target).after( eleDrag );
                };
                $(".blank").remove();
                $(".time-line-ul>li.over").removeClass("over");
                return false;
              });
            });
          }
        });
      });

      $(function() {
        var compile= $.template( $("#li-tpl").html() || "");

        //与客户端的交互事件;
        var orginalData = {};
        window.onWebMessage = function( msg ) {
          msg = JSON.parse(msg);
          switch( msg.type ) {
            case "setItems" :
              $(".time-line-ul").html( compile(msg.data) );
              //结构化复制;
              orginalData = JSON.parse(JSON.stringify(msg.data));
              break;

            case "setItem" :
              orginalData.items&&orginalData.items.splice(msg.data[0],0,msg.data[1]);
              $(".time-line-ul").html( compile(orginalData) );
              break;

            case "getItem" :
                var result = [];
                var lis = $(".time-line-ul li");
                for(var i=0; i<lis.length; i++) {
                  result.push( {
                    index : i,
                    src : $(lis[i]).find("img").attr("src"),
                    name : $(lis[i]).find("span").text()
                  });
                };
                alert(JSON.stringify( result ));
              break;

            case "active" :
              $(".time-line-icon.active").removeClass("active");
              $(".time-line-ul>li").eq( msg.data).find(".time-line-icon").addClass("active")
              break;

          };

        };

        //启用插件;
        $(".scroll-time-line").timeLine();
      })
    </script>
  </body>
</html>

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
jquery 无限级联菜单案例分享
Mar 26 Javascript
利用webqq协议使用python登录qq发消息源码参考
Apr 08 Javascript
变量声明时命名与变量作为对象属性时命名的区别解析
Dec 06 Javascript
jQuery根据ID获取input、checkbox、radio、select的示例
Aug 11 Javascript
javascript常用函数归纳整理
Oct 31 Javascript
实现非常简单的js双向数据绑定
Nov 06 Javascript
js实现上一页下一页的效果【附代码】
Mar 10 Javascript
JS实现仿百度文库评分功能
Jan 12 Javascript
bootstrap轮播图示例代码分享
May 17 Javascript
Node.js JSON模块用法实例分析
Jan 04 Javascript
React学习之JSX与react事件实例分析
Jan 06 Javascript
vue中js判断长时间不操作界面自动退出登录(推荐)
Jan 22 Javascript
jQuery实现定时读取分析xml文件的方法
Jul 16 #Javascript
Javascript函数的参数
Jul 16 #Javascript
Javascript简单改变表单元素背景的方法
Jul 15 #Javascript
JavaScript基于ajax编辑信息用法实例
Jul 15 #Javascript
JavaScript实现对下拉列表值进行排序的方法
Jul 15 #Javascript
jQuery简单实现验证邮箱格式
Jul 15 #Javascript
JavaScript截断字符串的方法
Jul 15 #Javascript
You might like
php debug 安装技巧
2011/04/30 PHP
PHP使用Face++接口开发微信公众平台人脸识别系统的方法
2015/04/17 PHP
PHP对XML内容进行修改和删除实例代码
2016/10/26 PHP
PHPUnit测试私有属性和方法功能示例
2018/06/12 PHP
Laravel中错误与异常处理的用法示例
2018/09/16 PHP
PHP token验证生成原理实例分析
2019/06/05 PHP
php使用redis的几种常见操作方式和用法示例
2020/02/20 PHP
轻轻松松学习JavaScript
2007/02/25 Javascript
JS 的应用开发初探(mootools)
2009/12/19 Javascript
XMLHTTPRequest的属性和方法简介
2010/11/23 Javascript
jquery.ui.draggable中文文档(原文翻译)
2013/11/15 Javascript
如何减少浏览器的reflow和repaint
2015/02/26 Javascript
详解Matlab中 sort 函数用法
2016/03/20 Javascript
jQuery实例—选项卡的简单实现(js源码和jQuery)
2016/06/14 Javascript
Ubuntu 16.04 64位中搭建Node.js开发环境教程
2016/10/19 Javascript
初探JavaScript 面向对象(推荐)
2017/09/03 Javascript
详解如何让InstantClick兼容MathJax、百度统计等
2017/09/12 Javascript
EasyUI Tree树组件无限循环的解决方法
2017/09/27 Javascript
vuejs前后端数据交互之从后端请求数据的实例
2018/08/11 Javascript
Vue Prop属性功能与用法实例详解
2019/02/23 Javascript
基于vue和websocket的多人在线聊天室
2020/02/01 Javascript
Vue 实现对quill-editor组件中的工具栏添加title
2020/08/03 Javascript
Python学习笔记(二)基础语法
2014/06/06 Python
Python多线程编程(八):使用Event实现线程间通信
2015/04/05 Python
使用Python进行二进制文件读写的简单方法(推荐)
2016/09/12 Python
python自动化测试无法启动谷歌浏览器问题
2019/10/10 Python
浅谈python输出列表元素的所有排列形式
2020/02/26 Python
python使用paramiko实现ssh的功能详解
2020/03/06 Python
jupyter实现重新加载模块
2020/04/16 Python
PyCharm 2020.2.2 x64 下载并安装的详细教程
2020/10/15 Python
CSS3 实现时间轴动画
2020/11/25 HTML / CSS
delegate与普通函数的区别
2014/01/22 面试题
个人简历自荐信
2013/12/05 职场文书
2015教师个人师德工作总结
2015/10/23 职场文书
python实战之用emoji表情生成文字
2021/05/08 Python
解读Vue组件注册方式
2021/05/15 Vue.js