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 相关文章推荐
百度Popup.js弹出框进化版 拖拽小框架发布 兼容IE6/7/8,Firefox,Chrome
Apr 13 Javascript
javascript实现的元素拖动函数宿主为浏览器
Jul 21 Javascript
JS 获取鼠标左右键的键值方法
Oct 11 Javascript
理解JavaScript中worker事件api
Dec 25 Javascript
利用jQuery中的ajax分页实现代码
Feb 25 Javascript
js捕捉键盘事件和按键键值的方法
Oct 10 Javascript
全面解析node 表单的图片上传
Nov 21 Javascript
jQuery简介_动力节点Java学院整理
Jul 04 jQuery
Vue Spa切换页面时更改标题的实例代码
Jul 15 Javascript
微信小程序云开发如何使用云函数生成二维码
May 18 Javascript
js实现查询商品案例
Jul 22 Javascript
js实现自动锁屏功能
Jun 02 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
使用php4加速网络传输
2006/10/09 PHP
zf框架的registry(注册表)使用示例
2014/03/13 PHP
Linux中用PHP判断程序运行状态的2个方法
2014/05/04 PHP
php实例化一个类的具体方法
2019/09/19 PHP
Prototype最新版(1.5 rc2)使用指南(1)
2007/01/10 Javascript
为超链接加上disabled后的故事
2010/12/10 Javascript
jqgrid 表格数据导出实例
2013/11/21 Javascript
判断日期是否能跨月查询的js代码
2014/07/25 Javascript
Angularjs实现mvvm式的选项卡示例代码
2016/09/08 Javascript
如何通过非数字与字符的方式实现PHP WebShell详解
2017/07/02 Javascript
Element-ui table中过滤条件变更表格内容的方法
2018/03/02 Javascript
利用Promise自定义一个GET请求的函数示例代码
2019/03/20 Javascript
微信打开网址添加在浏览器中打开提示的办法
2019/05/20 Javascript
vue cli3.0打包上线静态资源找不到路径的解决操作
2020/08/03 Javascript
Vuex实现购物车小功能
2020/08/17 Javascript
[01:08]DOTA2次级职业联赛 - Shield战队宣传片
2014/12/01 DOTA
[01:46]2020完美世界全国高校联赛秋季赛报名开启
2020/10/15 DOTA
利用Python演示数型数据结构的教程
2015/04/03 Python
python利用多种方式来统计词频(单词个数)
2019/05/27 Python
PyQt5实现简易电子词典
2019/06/25 Python
pandas中的series数据类型详解
2019/07/06 Python
html5各种页面切换效果和模态对话框用法总结
2014/12/15 HTML / CSS
德国百年厨具品牌WMF美国站:WMF美国
2016/09/12 全球购物
美国顶级水上运动专业店:Marine Products
2018/04/15 全球购物
进程的查看和调度分别使用什么命令
2013/12/14 面试题
安全教育实施方案
2014/03/02 职场文书
2014年十一国庆向国旗敬礼寄语
2014/04/11 职场文书
《爱如茉莉》教后反思
2014/04/12 职场文书
员工考核评语大全
2014/04/26 职场文书
选秀节目策划方案
2014/06/06 职场文书
小学秋季运动会报道稿
2014/09/30 职场文书
高中运动会广播稿
2015/08/19 职场文书
社区干部培训心得体会
2016/01/06 职场文书
个人房屋租赁合同(标准范本)
2019/09/16 职场文书
java项目构建Gradle的使用教程
2022/03/24 Java/Android
Spring Cloud OpenFeign模版化客户端
2022/06/25 Java/Android