jQuery时间轴插件使用详解

前端技术 2023/09/09 JavaScript

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

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

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

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

<!--
//设置内容;
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>

  插件效果图:

  最后完成的插件代码:

<!--
//设置内容;
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>

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

本文地址:https://www.stayed.cn/item/25134

转载请注明出处。

本站部分内容来源于网络,如侵犯到您的权益,请 联系我

我的博客

人生若只如初见,何事秋风悲画扇。