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 相关文章推荐
javaScript对象和属性的创建方法
Jan 15 Javascript
深入探讨JavaScript、JQuery屏蔽网页鼠标右键菜单及禁止选择复制
Jun 10 Javascript
jquery delay()介绍及使用指南
Sep 02 Javascript
jQuery使用cookie与json简单实现购物车功能
Apr 15 Javascript
node.js连接mongoDB数据库 快速搭建自己的web服务
Apr 17 Javascript
Bootstrap学习系列之使用 Bootstrap Typeahead 组件实现百度下拉效果
Jul 07 Javascript
elementui之el-tebs浏览器卡死的问题和使用报错未注册问题
Jul 06 Javascript
ES6 Class中实现私有属性的一些方法总结
Jul 08 Javascript
vue子传父关于.sync与$emit的实现
Nov 05 Javascript
JS倒计时两种实现方式代码实例
Jul 27 Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
Aug 31 Javascript
JS获取一个字符串中指定字符串第n次出现的位置
Feb 10 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.ini中文版(1)
2006/10/09 PHP
php preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
php文件操作之小型留言本实例
2015/06/20 PHP
PHP获取音频文件的相关信息
2015/06/22 PHP
定义select的边框颜色
2008/04/28 Javascript
JS 无限级 Select效果实现代码(json格式)
2011/08/30 Javascript
Uglifyjs(JS代码优化工具)入门 安装使用
2020/04/13 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
Javascript 修改String 对象 增加去除空格功能(示例代码)
2013/11/30 Javascript
js动态移动滚动条至底部示例代码
2014/04/24 Javascript
javascript下拉列表中显示树形菜单的实现方法
2015/11/17 Javascript
jQuery实现Table表格隔行变色及高亮显示当前选择行效果示例
2017/02/14 Javascript
利用JS实现简单的瀑布流加载图片效果
2017/04/22 Javascript
vue购物车插件编写代码
2017/11/27 Javascript
基于滚动条位置判断的简单实例
2017/12/14 Javascript
vue全局使用axios的方法实例详解
2018/11/22 Javascript
详解使用Nuxt.js快速搭建服务端渲染(SSR)应用
2019/03/13 Javascript
详解vue-cli@2.x项目迁移日志
2019/06/06 Javascript
jquery.tagsinput.js实现记录checkbox勾选的顺序
2019/09/21 jQuery
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
2020/07/21 Javascript
js实现点击按钮随机生成背景颜色
2020/09/05 Javascript
Echarts.js无法引入问题解决方案
2020/10/30 Javascript
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
[52:26]完美世界DOTA2联赛决赛 FTD vs Phoenix 第一场 11.08
2020/11/11 DOTA
使用Python中的cookielib模拟登录网站
2015/04/09 Python
Request的中断和ErrorHandler实例解析
2018/02/12 Python
Python图像处理之图片文字识别功能(OCR)
2019/07/30 Python
python如何将两个txt文件内容合并
2019/10/18 Python
h5移动端调用支付宝、微信支付的实现
2020/06/08 HTML / CSS
创建文明城市标语
2014/06/16 职场文书
欢迎领导标语
2014/06/27 职场文书
批评与自我批评发言稿
2014/10/15 职场文书
十岁生日答谢词
2015/01/05 职场文书
毕业论文致谢格式模板
2015/05/14 职场文书
PHP中strval()函数实例用法
2021/06/07 PHP
MySQL的表级锁,行级锁,排它锁和共享锁
2022/07/15 MySQL