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

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

  

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

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

  

  点击查看DEMO:打开

  1. <!--
  2. //设置内容;
  3. window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1111},{"name":2222}]}}' ) ;
  4.  
  5. //设置内容, 对应的item对象如果active为true为激活态;
  6. window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1000},{"name":1111},{"name":2222},{"name":3333,"active":true}]}}' ) ;
  7.  
  8. //设置某个第n个位置的item;
  9. window.onWebMessage('{"type":"setItem","data":[2,{ "name" : "add-item"}]}');
  10.  
  11. //激活第三个锚链接为选中态;
  12. window.onWebMessage( '{"type":"active","data":2}' )
  13.  
  14. //获取目前的数据:
  15. window.onWebMessage( '{"type":"getItem"}' );
  16. -->
  17.  
  18. <html>
  19. <head>
  20. <meta charset="utf-8" />
  21. <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
  22. </head>
  23. <style>
  24. /*初始的reset样式*/
  25. *{
  26. margin:0;
  27. padding:0;
  28. }
  29. .time-line-wrap{
  30. position: relative;
  31. width: 400px;
  32. margin:0 auto;
  33. }
  34. ul{
  35. list-style: none;
  36. }
  37. body,html{
  38. height: 100%;
  39. }
  40. body{
  41. -webkit-user-select: none;
  42. -moz-user-select: none;
  43. -ms-user-select: none;
  44. user-select: none;
  45. }
  46.  
  47. /*样式开始*/
  48. .scroll-time-line{
  49. height:100%;
  50. overflow: hidden;
  51. }
  52. .time-line-wrap{
  53. position: relative;
  54. }
  55. .time-line-ul{
  56. position: relative;
  57. }
  58. /**
  59. 时间轴的轴用伪类实现;
  60. */
  61. .time-line-ul::before{
  62. display: block;
  63. position:absolute;
  64. content:"";
  65. height:100%;
  66. width:1;
  67. left:27px;
  68. top:0;
  69. background: #eee;
  70. }
  71. .time-line-ul li{
  72. padding:14px;
  73. position: relative;
  74. }
  75. .time-line-ul input {
  76. vertical-align: super;
  77. border-radius: 4px;
  78. border:1px solid #eee;
  79. padding:4px;
  80. line-height: 22px;
  81. margin-left:10px;
  82. }
  83. /**
  84. 使用after和before伪类实现input前面的三角形;
  85. */
  86. .time-line-ul li::before{
  87. position: absolute;
  88. content: "";
  89. display: block;
  90. top: 21px;
  91. left: 40px;
  92. width: 0px;
  93. height: 0px;
  94. border: 10px solid rgba(0, 0, 0, 0);
  95. border-right: 10px solid #EEE;
  96. }
  97. .time-line-ul li::after{
  98. position: absolute;
  99. content: "";
  100. display: block;
  101. top: 21px;
  102. left: 41px;
  103. width: 0px;
  104. height: 0px;
  105. border: 10px solid rgba(0, 0, 0, 0);
  106. border-right: 10px solid #fff;
  107. }
  108. /**
  109. 默认时间轴锚链接的样式
  110. */
  111. .time-line-icon{
  112. width: 26px;
  113. height: 28px;
  114. display: inline-block;
  115. background: url(http://images0.cnblogs.com/blog2015/497865/201507/131424386411828.png);
  116. }
  117. /**
  118. 鼠标移动上来,或者锚链接有active时候的背景图样式
  119. */
  120. .time-line-icon.active,.time-line-icon:hover{
  121. background-position: 0px 28px;
  122. }
  123. </style>
  124.  
  125. <!--模板,勿删!-->
  126. <script type="text/tempate" id="li-tpl">
  127. <% for(var i=0; i<items.length; i++ ) {%>
  128. <li class="li-<%=i%>">
  129. <a href="###" class="time-line-icon <% if(items[i].active){ %> <%="active"%> <%}%> "></a>
  130. <input type="text" value="<%=items[i].name%>"/>
  131. </li>
  132. <% } %>
  133. </script>
  134.  
  135. <body>
  136. <!--
  137. 滚动出现在这个div里面
  138. -->
  139. <div class="scroll-time-line">
  140.  
  141. <!---
  142. 时间轴相关的html结构
  143. -->
  144. <div class="time-line-wrap">
  145. <ul class="time-line-ul">
  146. <li>
  147. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  148. </li>
  149. <li>
  150. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  151. </li>
  152. <li>
  153. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  154. </li>
  155. <li>
  156. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  157. </li>
  158. <li>
  159. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  160. </li>
  161. <li>
  162. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  163. </li>
  164. <li>
  165. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  166. </li>
  167. <li>
  168. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  169. </li>
  170. <li>
  171. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  172. </li>
  173. <li>
  174. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  175. </li>
  176. <li>
  177. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  178. </li>
  179. <li>
  180. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  181. </li>
  182. <li>
  183. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  184. </li>
  185. <li>
  186. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  187. </li>
  188. <li>
  189. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  190. </li>
  191. <li>
  192. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  193. <li>
  194. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  195. </li>
  196. <li>
  197. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  198. </li>
  199. <li>
  200. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  201. </li>
  202. <li>
  203. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  204. </li>
  205. <li>
  206. <a href="###" class="time-line-icon"></a> <input type="text" value="2015"/>
  207. </li>
  208. </ul>
  209. </div>
  210. <!---
  211. 时间轴相关的html结构结束
  212. -->
  213. </div>
  214. <script>
  215. //模板引擎的代码
  216. (function () {
  217. //underscore抄的模板引擎;
  218. var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  219.  
  220. var escapes = {
  221. "'": "'",
  222. '\\': '\\',
  223. '\r': 'r',
  224. '\n': 'n',
  225. '\t': 't',
  226. '\u2028': 'u2028',
  227. '\u2029': 'u2029'
  228. };
  229.  
  230. $.templateSettings = {
  231. evaluate : /<%([\s\S]+?)%>/g,
  232. interpolate : /<%=([\s\S]+?)%>/g,
  233. escape : /<%-([\s\S]+?)%>/g
  234. }
  235. $.template = function(text, data, settings) {
  236. var render;
  237. settings = $.extend({}, settings, $.templateSettings);
  238.  
  239. // Combine delimiters into one regular expression via alternation.
  240. var matcher = new RegExp([
  241. (settings.escape || noMatch).source,
  242. (settings.interpolate || noMatch).source,
  243. (settings.evaluate || noMatch).source
  244. ].join('|') + '|$', 'g');
  245.  
  246. // Compile the template source, escaping string literals appropriately.
  247. var index = 0;
  248. var source = "__p+='";
  249. text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
  250. source += text.slice(index, offset)
  251. .replace(escaper, function(match) { return '\\' + escapes[match]; });
  252.  
  253. if (escape) {
  254. source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
  255. }
  256. if (interpolate) {
  257. source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
  258. }
  259. if (evaluate) {
  260. source += "';\n" + evaluate + "\n__p+='";
  261. }
  262. index = offset + match.length;
  263. return match;
  264. });
  265. source += "';\n";
  266.  
  267. // If a variable is not specified, place data values in local scope.
  268. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  269.  
  270. source = "var __t,__p='',__j=Array.prototype.join," +
  271. "print=function(){__p+=__j.call(arguments,'');};\n" +
  272. source + "return __p;\n";
  273.  
  274. try {
  275. render = new Function(settings.variable || 'obj', '_', source);
  276. } catch (e) {
  277. e.source = source;
  278. throw e;
  279. }
  280.  
  281. if (data) return render(data, _);
  282. var template = function(data) {
  283. return render.call(this, data);
  284. };
  285.  
  286. // Provide the compiled function source as a convenience for precompilation.
  287. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
  288.  
  289. return template;
  290. };
  291. })();
  292.  
  293. (function( fn ) {
  294.  
  295. $( fn.call( $ ,$) );
  296.  
  297. })(function ($) {
  298.  
  299. $.timeLineSetting = {
  300. offsetTop : 100
  301. };
  302. $.extend($.fn, {
  303. timeLine : function() {
  304. $.each(this, function() {
  305.  
  306. var _this = this;
  307.  
  308. $(this).delegate(".time-line-ul>li", "click", function( ev ) {
  309.  
  310. $(".time-line-icon.active").removeClass("active");
  311.  
  312. $(this).find(".time-line-icon").addClass("active");
  313.  
  314. $(_this).animate({scrollTop: this.offsetTop - $.timeLineSetting.offsetTop},300);
  315.  
  316. ev.preventDefault();
  317.  
  318. });
  319. });
  320. }
  321. });
  322. });
  323. $(function() {
  324. var compile= $.template( $("#li-tpl").html() || "");
  325.  
  326. //与客户端的交互事件;
  327. var orginalData = {};
  328. window.onWebMessage = function( msg ) {
  329. msg = JSON.parse(msg);
  330. switch( msg.type ) {
  331. case "setItems" :
  332. $(".time-line-ul").html( compile(msg.data) );
  333. //结构化复制;
  334. orginalData = JSON.parse(JSON.stringify(msg.data));
  335. break;
  336.  
  337. case "setItem" :
  338. orginalData.items&&orginalData.items.splice(msg.data[0],0,msg.data[1]);
  339. $(".time-line-ul").html( compile(orginalData) );
  340. break;
  341.  
  342. case "getItem" :
  343. alert(JSON.stringify( orginalData ));
  344. break;
  345.  
  346. case "active" :
  347. $(".time-line-icon.active").removeClass("active");
  348. $(".time-line-ul>li").eq( msg.data).find(".time-line-icon").addClass("active")
  349. break;
  350.  
  351. };
  352.  
  353. };
  354.  
  355. //启用插件;
  356. $(".scroll-time-line").timeLine();
  357. })
  358. </script>
  359. </body>
  360. </html>

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

  1. //模板引擎的代码
  2. (function () {
  3. //underscore抄的模板引擎;
  4. var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  5.  
  6. var escapes = {
  7. "'": "'",
  8. '\\': '\\',
  9. '\r': 'r',
  10. '\n': 'n',
  11. '\t': 't',
  12. '\u2028': 'u2028',
  13. '\u2029': 'u2029'
  14. };
  15.  
  16. $.templateSettings = {
  17. evaluate : /<%([\s\S]+?)%>/g,
  18. interpolate : /<%=([\s\S]+?)%>/g,
  19. escape : /<%-([\s\S]+?)%>/g
  20. }
  21. $.template = function(text, data, settings) {
  22. var render;
  23. settings = $.extend({}, settings, $.templateSettings);
  24.  
  25. // Combine delimiters into one regular expression via alternation.
  26. var matcher = new RegExp([
  27. (settings.escape || noMatch).source,
  28. (settings.interpolate || noMatch).source,
  29. (settings.evaluate || noMatch).source
  30. ].join('|') + '|$', 'g');
  31.  
  32. // Compile the template source, escaping string literals appropriately.
  33. var index = 0;
  34. var source = "__p+='";
  35. text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
  36. source += text.slice(index, offset)
  37. .replace(escaper, function(match) { return '\\' + escapes[match]; });
  38.  
  39. if (escape) {
  40. source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
  41. }
  42. if (interpolate) {
  43. source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
  44. }
  45. if (evaluate) {
  46. source += "';\n" + evaluate + "\n__p+='";
  47. }
  48. index = offset + match.length;
  49. return match;
  50. });
  51. source += "';\n";
  52.  
  53. // If a variable is not specified, place data values in local scope.
  54. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  55.  
  56. source = "var __t,__p='',__j=Array.prototype.join," +
  57. "print=function(){__p+=__j.call(arguments,'');};\n" +
  58. source + "return __p;\n";
  59.  
  60. try {
  61. render = new Function(settings.variable || 'obj', '_', source);
  62. } catch (e) {
  63. e.source = source;
  64. throw e;
  65. }
  66.  
  67. if (data) return render(data, _);
  68. var template = function(data) {
  69. return render.call(this, data);
  70. };
  71.  
  72. // Provide the compiled function source as a convenience for precompilation.
  73. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
  74.  
  75. return template;
  76. };
  77. })();

  

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

  1. <html>
  2. <head>
  3. <body>
  4. <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
  5. <script>
  6. //模板引擎的代码
  7. (function () {
  8. //underscore抄的模板引擎;
  9. var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  10.  
  11. var escapes = {
  12. "'": "'",
  13. '\\': '\\',
  14. '\r': 'r',
  15. '\n': 'n',
  16. '\t': 't',
  17. '\u2028': 'u2028',
  18. '\u2029': 'u2029'
  19. };
  20.  
  21. $.templateSettings = {
  22. evaluate : /<%([\s\S]+?)%>/g,
  23. interpolate : /<%=([\s\S]+?)%>/g,
  24. escape : /<%-([\s\S]+?)%>/g
  25. }
  26. $.template = function(text, data, settings) {
  27. var render;
  28. settings = $.extend({}, settings, $.templateSettings);
  29.  
  30. // Combine delimiters into one regular expression via alternation.
  31. var matcher = new RegExp([
  32. (settings.escape || noMatch).source,
  33. (settings.interpolate || noMatch).source,
  34. (settings.evaluate || noMatch).source
  35. ].join('|') + '|$', 'g');
  36.  
  37. // Compile the template source, escaping string literals appropriately.
  38. var index = 0;
  39. var source = "__p+='";
  40. text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
  41. source += text.slice(index, offset)
  42. .replace(escaper, function(match) { return '\\' + escapes[match]; });
  43.  
  44. if (escape) {
  45. source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
  46. }
  47. if (interpolate) {
  48. source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
  49. }
  50. if (evaluate) {
  51. source += "';\n" + evaluate + "\n__p+='";
  52. }
  53. index = offset + match.length;
  54. return match;
  55. });
  56. source += "';\n";
  57.  
  58. // If a variable is not specified, place data values in local scope.
  59. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  60.  
  61. source = "var __t,__p='',__j=Array.prototype.join," +
  62. "print=function(){__p+=__j.call(arguments,'');};\n" +
  63. source + "return __p;\n";
  64.  
  65. try {
  66. render = new Function(settings.variable || 'obj', '_', source);
  67. } catch (e) {
  68. e.source = source;
  69. throw e;
  70. }
  71.  
  72. if (data) return render(data, _);
  73. var template = function(data) {
  74. return render.call(this, data);
  75. };
  76.  
  77. // Provide the compiled function source as a convenience for precompilation.
  78. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
  79.  
  80. return template;
  81. };
  82. })();
  83. </script>
  84. <script>
  85. //会输出 <div>haahah</div>;
  86. console.log( $.template('<div><%=data%></div>')( {data:"haahah"} ) );
  87. </script>
  88. </body>
  89. </head>
  90. </html>

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

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8"/>
  5. <style type="text/css">
  6. #div1 {width:488px;height:70px;padding:10px;border:1px solid #aaaaaa;}
  7. </style>
  8. <script type="text/javascript">
  9. //当元素dragover时候一定要阻止默认事件, 否则把当前拖拽的元素就无法drop;
  10. function dragover(ev)
  11. {
  12. console.log(ev);
  13. ev.preventDefault();
  14. }
  15.  
  16. //对于拖拽事件最重要的一个事件属性就是dataTransfer;
  17. function drag(ev)
  18. {
  19. console.log(ev);
  20. ev.dataTransfer.setData("Text",ev.target.id);
  21. }
  22.  
  23. function drop(ev)
  24. {
  25. console.log(ev);
  26. var data=ev.dataTransfer.getData("Text");
  27. ev.target.appendChild(document.getElementById(data));
  28. }
  29. </script>
  30. </head>
  31. <body>
  32.  
  33. <p>请把图片拖放到矩形中:</p>
  34.  
  35. <div id="div1" ondrop="drop(event)" ondragover="dragover(event)"></div>
  36. <br />
  37. <img id="drag1" src="http://images0.cnblogs.com/news/24442/201507/081152502219706.gif" draggable="true" ondragstart="drag(event)" />
  38.  
  39. </body>
  40. </html>

  另外一个DEMO:

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8"/>
  5. <style type="text/css">
  6. </style>
  7. </head>
  8. <body>
  9. <p>What fruits do you like?</p>
  10. <ol ondragstart="dragStartHandler(event)">
  11. <li draggable="true" data-value="fruit-apple">Apples</li>
  12. <li draggable="true" data-value="fruit-orange">Oranges</li>
  13. <li draggable="true" data-value="fruit-pear">Pears</li>
  14. </ol>
  15. <script>
  16. var internalDNDType = 'text/x-example'; // set this to something specific to your site
  17. function dragStartHandler(event) {
  18. if (event.target instanceof HTMLLIElement) {
  19. // use the element's data-value="" attribute as the value to be moving:
  20. event.dataTransfer.setData(internalDNDType, event.target.dataset.value);
  21. event.dataTransfer.effectAllowed = 'move'; // only allow moves
  22. } else {
  23. event.preventDefault(); // don't allow selection to be dragged
  24. }
  25. }
  26. </script>
  27.  
  28. <p>Drop your favorite fruits below:</p>
  29. <ol ondrop="dropHandler(event)" ondragover="dragover(event)">
  30. <!-- don't forget to change the "text/x-example" type to something
  31. specific to your site -->
  32. <li>drop</li>
  33. </ol>
  34. <script>
  35. var internalDNDType = 'text/x-example'; // set this to something specific to your site
  36. function dropHandler(event) {
  37. var li = document.createElement('li');
  38. var data = event.dataTransfer.getData(internalDNDType);
  39. if (data == 'fruit-apple') {
  40. li.textContent = 'Apples';
  41. } else if (data == 'fruit-orange') {
  42. li.textContent = 'Oranges';
  43. } else if (data == 'fruit-pear') {
  44. li.textContent = 'Pears';
  45. } else {
  46. li.textContent = 'Unknown Fruit';
  47. }
  48. event.target.appendChild(li);
  49. };
  50. function dragover(ev) {
  51. ev.preventDefault();
  52. };
  53. </script>
  54. </body>
  55. </html>

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

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8"/>
  5. <style type="text/css">
  6. </style>
  7. </head>
  8. <body>
  9. <div id="div0" ondragover="dragover(event)" ondrop="drop(event)">
  10. drop拖放文件进来
  11. </div>
  12. <script>
  13. function dragover(ev) {
  14. ev.preventDefault();
  15. };
  16. function drop(ev) {
  17. var reader = new FileReader();
  18. reader.onload = function ( ev ) {
  19. var oDiv = document.createElement("div");
  20. oDiv.innerHTML = ev.target.result;
  21. document.body.appendChild( oDiv );
  22. };
  23. reader.readAsText( ev.dataTransfer.files[0] );
  24. ev.preventDefault();
  25. }
  26. </script>
  27. </body>
  28. </html>

  插件效果图:

  最后完成的插件代码:

  1. <!--
  2. //设置内容;
  3. window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1111,"type":"doc"},{"name":2222,"type":"doc"}]}}' ) ;
  4.  
  5. window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":"文档类型","type":"doc"},{"name":"音频类型","type":"audio","active":true},{"name":"视频类型","type":"video"},{"name":"单元测试","type":"test"},{"name":"图片类型","type":"pic"}]}}' ) ;
  6.  
  7. //设置内容, 对应的item对象如果active为true为激活态;
  8. window.onWebMessage( '{"type":"setItems","data":{"items":[{"name":1111,"type":"doc"},{"name":2222,"type":"doc","active":true}]}}' ) ;
  9.  
  10. //设置某个第n个位置的item;
  11. window.onWebMessage('{"type":"setItem","data":[2,{ "name" : "add-item", "type":"doc"}]}');
  12.  
  13. //激活第三个锚链接为选中态;
  14. window.onWebMessage( '{"type":"active","data":2}' )
  15.  
  16. //获取目前的数据:
  17. window.onWebMessage( '{"type":"getItem"}' )
  18. -->
  19.  
  20. <html>
  21. <head>
  22. <meta charset="utf-8" />
  23. <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.js"></script>
  24. </head>
  25. <style>
  26. /*初始的reset样式*/
  27. *{
  28. margin:0;
  29. padding:0;
  30. }
  31. .time-line-wrap{
  32. position: relative;
  33. width: 400px;
  34. margin:0 auto;
  35. }
  36. ul{
  37. list-style: none;
  38. }
  39. body,html{
  40. height: 100%;
  41. }
  42. body{
  43. background:#303030;
  44. -webkit-user-select: none;
  45. -moz-user-select: none;
  46. -ms-user-select: none;
  47. user-select: none;
  48. }
  49.  
  50. /*样式开始*/
  51. .scroll-time-line{
  52. height:100%;
  53. overflow: hidden;
  54. }
  55. .time-line-wrap{
  56. position: relative;
  57. }
  58. .time-line-wrap::before{
  59. display: block;
  60. content: "";
  61. position: absolute;
  62. border: 2px solid #616161;
  63. width: 7px;
  64. background: #303030;
  65. height: 7px;
  66. z-index: 2;
  67. border-radius: 100%;
  68. left: 12px;
  69. top: 0;
  70. }
  71. .time-line-wrap::after{
  72. display: block;
  73. content: "";
  74. position: absolute;
  75. border: 2px solid #616161;
  76. width: 7px;
  77. background: #303030;
  78. height: 7px;
  79. z-index: 2;
  80. border-radius: 100%;
  81. left: 12px;
  82. bottom:0;
  83. }
  84. .time-line-ul{
  85. position: relative;
  86. }
  87. /**
  88. 时间轴的轴用伪类实现;
  89. */
  90. .time-line-ul::before{
  91. display: block;
  92. position:absolute;
  93. content:"";
  94. height:100%;
  95. width:1px;
  96. left:17px;
  97. top:0;
  98. background: #616161;
  99. }
  100.  
  101. .time-line-ul li{
  102. padding: 14px;
  103. position: relative;
  104. color: #FFF;
  105. height: 26px;
  106. }
  107. .time-line-ul li>* {
  108. vertical-align: middle;
  109. display: inline-block;
  110. }
  111.  
  112. /**
  113. 为了更好的维护hover的样式, 背景图片通过js进行管理
  114. hover start;
  115. */
  116. .time-line-ul li b{
  117. width: 32px;
  118. height: 32px;
  119. }
  120. .time-line-ul li b.active{
  121. display: none;
  122. }
  123. .time-line-ul li:hover b{
  124. display: none;
  125. }
  126. .time-line-ul li:hover .active{
  127. display: inline-block;
  128. }
  129. /**
  130. 当li被点击的时候添加的类,优先级
  131. */
  132. .time-line-ul li b.show{
  133. display: none;
  134. }
  135. .time-line-ul li b.active.show{
  136. display: inline-block;
  137. }
  138. /**
  139. hover end
  140. */
  141.  
  142. .time-line-ul li span{
  143. display: inline-block;
  144. white-space: nowrap;
  145. word-wrap: normal;
  146. width: 100px;
  147. text-overflow: ellipsis;
  148. overflow: hidden;
  149. }
  150. /**
  151. 当拖拽LI到某个LI上面,这个LI变透明
  152. */
  153. .over{
  154. opacity: 0.4;
  155. }
  156. /**
  157. 占位DIV;
  158. */
  159. .blank{
  160. display: block;
  161. height:50px;
  162. line-height: 50px;
  163. }
  164.  
  165. /**
  166. 默认时间轴锚链接的样式
  167. */
  168. .time-line-icon{
  169. width: 7px;
  170. height: 7px;
  171. display: inline-block;
  172. background: #616161;
  173. border-radius: 100%;
  174. }
  175. /**
  176. 鼠标移动上来,或者锚链接有active时候的背景图样式
  177. */
  178. .time-line-icon.active,.time-line-icon:hover{
  179. background: #fff;
  180. }
  181. </style>
  182.  
  183. <!--模板,勿删!-->
  184. <script type="text/tempate" id="li-tpl">
  185. <% for(var i=0; i<items.length; i++ ) {%>
  186. <li class="li-<%=i%>" draggable="true">
  187. <a href="###" class="time-line-icon <% if(items[i].active){ %> <%="active"%> <%}%> "></a>
  188. <b class="">
  189. <img src="imgs/<%=items[i].type%>.png" />
  190. </b>
  191. <b class="active">
  192. <img src="imgs/<%=items[i].type%>1.png" />
  193. </b>
  194. <span>
  195. <%=items[i].name%>
  196. </span>
  197. </li>
  198. <% } %>
  199. </script>
  200.  
  201. <body>
  202. <!--
  203. 滚动出现在这个div里面
  204. -->
  205. <div class="scroll-time-line">
  206.  
  207. <!---
  208. 时间轴相关的html结构
  209. -->
  210. <div class="time-line-wrap">
  211. <ul class="time-line-ul">
  212.  
  213. <!----假数据--->
  214. <li class="li-0" draggable="true">
  215. <a href="###" class="time-line-icon "></a>
  216. <b class="">
  217. <img src="imgs/doc.png">
  218. </b>
  219. <b class="active">
  220. <img src="imgs/doc1.png">
  221. </b>
  222. <span>
  223. 文档类型
  224. </span>
  225. </li>
  226.  
  227. <li class="li-2" draggable="true">
  228. <a href="###" class="time-line-icon "></a>
  229. <b class="">
  230. <img src="imgs/video.png">
  231. </b>
  232. <b class="active">
  233. <img src="imgs/video1.png">
  234. </b>
  235. <span>
  236. 视频类型
  237. </span>
  238. </li>
  239.  
  240. <li class="li-3" draggable="true">
  241. <a href="###" class="time-line-icon "></a>
  242. <b class="">
  243. <img src="imgs/test.png">
  244. </b>
  245. <b class="active">
  246. <img src="imgs/test1.png">
  247. </b>
  248. <span>
  249. 单元测试
  250. </span>
  251. </li><li class="li-1" draggable="true">
  252. <a href="###" class="time-line-icon active "></a>
  253. <b class="">
  254. <img src="imgs/audio.png">
  255. </b>
  256. <b class="active">
  257. <img src="imgs/audio1.png">
  258. </b>
  259. <span>
  260. 音频类型
  261. </span>
  262. </li>
  263.  
  264. <li class="li-4" draggable="true">
  265. <a href="###" class="time-line-icon "></a>
  266. <b class="">
  267. <img src="imgs/pic.png">
  268. </b>
  269. <b class="active">
  270. <img src="imgs/pic1.png">
  271. </b>
  272. <span>
  273. 图片类型
  274. </span>
  275. </li>
  276.  
  277. <li class="li-0" draggable="true">
  278. <a href="###" class="time-line-icon "></a>
  279. <b class="">
  280. <img src="imgs/doc.png">
  281. </b>
  282. <b class="active">
  283. <img src="imgs/doc1.png">
  284. </b>
  285. <span>
  286. 文档类型
  287. </span>
  288. </li>
  289.  
  290. <li class="li-2" draggable="true">
  291. <a href="###" class="time-line-icon "></a>
  292. <b class="">
  293. <img src="imgs/video.png">
  294. </b>
  295. <b class="active">
  296. <img src="imgs/video1.png">
  297. </b>
  298. <span>
  299. 视频类型
  300. </span>
  301. </li>
  302.  
  303. <li class="li-3" draggable="true">
  304. <a href="###" class="time-line-icon "></a>
  305. <b class="">
  306. <img src="imgs/test.png">
  307. </b>
  308. <b class="active">
  309. <img src="imgs/test1.png">
  310. </b>
  311. <span>
  312. 单元测试
  313. </span>
  314. </li><li class="li-1" draggable="true">
  315. <a href="###" class="time-line-icon active "></a>
  316. <b class="">
  317. <img src="imgs/audio.png">
  318. </b>
  319. <b class="active">
  320. <img src="imgs/audio1.png">
  321. </b>
  322. <span>
  323. 音频类型
  324. </span>
  325. </li>
  326.  
  327. <li class="li-4" draggable="true">
  328. <a href="###" class="time-line-icon "></a>
  329. <b class="">
  330. <img src="imgs/pic.png">
  331. </b>
  332. <b class="active">
  333. <img src="imgs/pic1.png">
  334. </b>
  335. <span>
  336. 图片类型
  337. </span>
  338. </li>
  339.  
  340. <li class="li-0" draggable="true">
  341. <a href="###" class="time-line-icon "></a>
  342. <b class="">
  343. <img src="imgs/doc.png">
  344. </b>
  345. <b class="active">
  346. <img src="imgs/doc1.png">
  347. </b>
  348. <span>
  349. 文档类型
  350. </span>
  351. </li>
  352.  
  353. <li class="li-2" draggable="true">
  354. <a href="###" class="time-line-icon "></a>
  355. <b class="">
  356. <img src="imgs/video.png">
  357. </b>
  358. <b class="active">
  359. <img src="imgs/video1.png">
  360. </b>
  361. <span>
  362. 视频类型
  363. </span>
  364. </li>
  365.  
  366. <li class="li-3" draggable="true">
  367. <a href="###" class="time-line-icon "></a>
  368. <b class="">
  369. <img src="imgs/test.png">
  370. </b>
  371. <b class="active">
  372. <img src="imgs/test1.png">
  373. </b>
  374. <span>
  375. 单元测试
  376. </span>
  377. </li><li class="li-1" draggable="true">
  378. <a href="###" class="time-line-icon active "></a>
  379. <b class="">
  380. <img src="imgs/audio.png">
  381. </b>
  382. <b class="active">
  383. <img src="imgs/audio1.png">
  384. </b>
  385. <span>
  386. 音频类型
  387. </span>
  388. </li>
  389.  
  390. <li class="li-4" draggable="true">
  391. <a href="###" class="time-line-icon "></a>
  392. <b class="">
  393. <img src="imgs/pic.png">
  394. </b>
  395. <b class="active">
  396. <img src="imgs/pic1.png">
  397. </b>
  398. <span>
  399. 图片类型
  400. </span>
  401. </li>
  402.  
  403. <li class="li-0" draggable="true">
  404. <a href="###" class="time-line-icon "></a>
  405. <b class="">
  406. <img src="imgs/doc.png">
  407. </b>
  408. <b class="active">
  409. <img src="imgs/doc1.png">
  410. </b>
  411. <span>
  412. 文档类型
  413. </span>
  414. </li>
  415.  
  416. <li class="li-2" draggable="true">
  417. <a href="###" class="time-line-icon "></a>
  418. <b class="">
  419. <img src="imgs/video.png">
  420. </b>
  421. <b class="active">
  422. <img src="imgs/video1.png">
  423. </b>
  424. <span>
  425. 视频类型
  426. </span>
  427. </li>
  428.  
  429. <li class="li-3" draggable="true">
  430. <a href="###" class="time-line-icon "></a>
  431. <b class="">
  432. <img src="imgs/test.png">
  433. </b>
  434. <b class="active">
  435. <img src="imgs/test1.png">
  436. </b>
  437. <span>
  438. 单元测试
  439. </span>
  440. </li><li class="li-1" draggable="true">
  441. <a href="###" class="time-line-icon active "></a>
  442. <b class="">
  443. <img src="imgs/audio.png">
  444. </b>
  445. <b class="active">
  446. <img src="imgs/audio1.png">
  447. </b>
  448. <span>
  449. 音频类型
  450. </span>
  451. </li>
  452.  
  453. <li class="li-4" draggable="true">
  454. <a href="###" class="time-line-icon "></a>
  455. <b class="">
  456. <img src="imgs/pic.png">
  457. </b>
  458. <b class="active">
  459. <img src="imgs/pic1.png">
  460. </b>
  461. <span>
  462. 图片类型
  463. </span>
  464. </li>
  465.  
  466. <li class="li-0" draggable="true">
  467. <a href="###" class="time-line-icon "></a>
  468. <b class="">
  469. <img src="imgs/doc.png">
  470. </b>
  471. <b class="active">
  472. <img src="imgs/doc1.png">
  473. </b>
  474. <span>
  475. 文档类型
  476. </span>
  477. </li>
  478.  
  479. <li class="li-2" draggable="true">
  480. <a href="###" class="time-line-icon "></a>
  481. <b class="">
  482. <img src="imgs/video.png">
  483. </b>
  484. <b class="active">
  485. <img src="imgs/video1.png">
  486. </b>
  487. <span>
  488. 视频类型
  489. </span>
  490. </li>
  491.  
  492. <!---假数据end--->
  493.  
  494. </ul>
  495. </div>
  496. <!---
  497. 时间轴相关的html结构结束
  498. -->
  499. </div>
  500. <script>
  501. //模板引擎的代码
  502. (function () {
  503. //underscore抄的模板引擎;
  504. var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
  505.  
  506. var escapes = {
  507. "'": "'",
  508. '\\': '\\',
  509. '\r': 'r',
  510. '\n': 'n',
  511. '\t': 't',
  512. '\u2028': 'u2028',
  513. '\u2029': 'u2029'
  514. };
  515.  
  516. $.templateSettings = {
  517. evaluate : /<%([\s\S]+?)%>/g,
  518. interpolate : /<%=([\s\S]+?)%>/g,
  519. escape : /<%-([\s\S]+?)%>/g
  520. }
  521. $.template = function(text, data, settings) {
  522. var render;
  523. settings = $.extend({}, settings, $.templateSettings);
  524.  
  525. // Combine delimiters into one regular expression via alternation.
  526. var matcher = new RegExp([
  527. (settings.escape || noMatch).source,
  528. (settings.interpolate || noMatch).source,
  529. (settings.evaluate || noMatch).source
  530. ].join('|') + '|$', 'g');
  531.  
  532. // Compile the template source, escaping string literals appropriately.
  533. var index = 0;
  534. var source = "__p+='";
  535. text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
  536. source += text.slice(index, offset)
  537. .replace(escaper, function(match) { return '\\' + escapes[match]; });
  538.  
  539. if (escape) {
  540. source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
  541. }
  542. if (interpolate) {
  543. source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
  544. }
  545. if (evaluate) {
  546. source += "';\n" + evaluate + "\n__p+='";
  547. }
  548. index = offset + match.length;
  549. return match;
  550. });
  551. source += "';\n";
  552.  
  553. // If a variable is not specified, place data values in local scope.
  554. if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  555.  
  556. source = "var __t,__p='',__j=Array.prototype.join," +
  557. "print=function(){__p+=__j.call(arguments,'');};\n" +
  558. source + "return __p;\n";
  559.  
  560. try {
  561. render = new Function(settings.variable || 'obj', '_', source);
  562. } catch (e) {
  563. e.source = source;
  564. throw e;
  565. }
  566.  
  567. if (data) return render(data, _);
  568. var template = function(data) {
  569. return render.call(this, data);
  570. };
  571.  
  572. // Provide the compiled function source as a convenience for precompilation.
  573. template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
  574.  
  575. return template;
  576. };
  577. })();
  578.  
  579. (function( fn ) {
  580.  
  581. $( fn.call( $ ,$) );
  582.  
  583. })(function ($) {
  584.  
  585. $.timeLineSetting = {
  586. offsetTop : 100
  587. };
  588.  
  589. $.extend($.fn, {
  590. timeLine : function() {
  591. $.each(this, function() {
  592.  
  593. var _this = this,
  594. eleDrag;
  595. $(this).delegate(".time-line-ul>li", "click", function( ev ) {
  596. $(".time-line-icon.active").removeClass("active");
  597. $(this).find(".time-line-icon").addClass("active");
  598. $("b").removeClass("show");
  599. $(this).find("b").addClass("show");
  600. $(_this).animate({scrollTop: this.offsetTop - $.timeLineSetting.offsetTop},300);
  601. ev.preventDefault();
  602. }).delegate(".time-line-ul>li","dragstart" , function(ev) {
  603. //不允许img和a的拖拽;
  604. if( ev.target&&ev.target.tagName.toLocaleLowerCase() === "img" || ev.target.tagName.toLocaleLowerCase() === "a") {
  605. return false;
  606. };
  607. /*拖拽开始*/
  608. //拖拽效果
  609. ev.originalEvent.dataTransfer.effectAllowed = "move";
  610. eleDrag = ev.originalEvent.target;
  611. return true;
  612. }).delegate(".time-line-ul>li","dragenter" , function(ev) {
  613. return true;
  614. }).delegate(".time-line-ul>li", "dragover" , function(ev) {
  615. $(".time-line-ul>li.over").removeClass("over");
  616. $(this).addClass("over");
  617. $(".blank").remove();
  618. var $blank = $("<li class='blank' draggable='true'></li>");
  619. $(this).after( $blank );
  620. /*拖拽元素在目标元素头上移动的时候*/
  621. ev.preventDefault();
  622. return true;
  623. });
  624. $(".time-line-ul").bind("drop" , function(ev) {
  625. if(ev.target.tagName.toLocaleLowerCase() === "li") {
  626. $(ev.target).after( eleDrag );
  627. };
  628. $(".blank").remove();
  629. $(".time-line-ul>li.over").removeClass("over");
  630. return false;
  631. });
  632. });
  633. }
  634. });
  635. });
  636.  
  637. $(function() {
  638. var compile= $.template( $("#li-tpl").html() || "");
  639.  
  640. //与客户端的交互事件;
  641. var orginalData = {};
  642. window.onWebMessage = function( msg ) {
  643. msg = JSON.parse(msg);
  644. switch( msg.type ) {
  645. case "setItems" :
  646. $(".time-line-ul").html( compile(msg.data) );
  647. //结构化复制;
  648. orginalData = JSON.parse(JSON.stringify(msg.data));
  649. break;
  650.  
  651. case "setItem" :
  652. orginalData.items&&orginalData.items.splice(msg.data[0],0,msg.data[1]);
  653. $(".time-line-ul").html( compile(orginalData) );
  654. break;
  655.  
  656. case "getItem" :
  657. var result = [];
  658. var lis = $(".time-line-ul li");
  659. for(var i=0; i<lis.length; i++) {
  660. result.push( {
  661. index : i,
  662. src : $(lis[i]).find("img").attr("src"),
  663. name : $(lis[i]).find("span").text()
  664. });
  665. };
  666. alert(JSON.stringify( result ));
  667. break;
  668.  
  669. case "active" :
  670. $(".time-line-icon.active").removeClass("active");
  671. $(".time-line-ul>li").eq( msg.data).find(".time-line-icon").addClass("active")
  672. break;
  673.  
  674. };
  675.  
  676. };
  677.  
  678. //启用插件;
  679. $(".scroll-time-line").timeLine();
  680. })
  681. </script>
  682. </body>
  683. </html>

  FileReader的API

  FILE的API

  HTML拖拽API

作者: NONO
出处:http://www.cnblogs.com/diligenceday/

QQ:287101329

jQ插件--时间线插件和拖拽API的更多相关文章

  1. 基于html5拖拽api实现列表的拖拽排序

    基于html5拖拽api实现列表的拖拽排序 html代码: <ul ondrop="drop_handler(event);" ondragover="dragov ...

  2. div/dom元素拖拽缩放插件,纯js实现拖拽缩放,不依赖jQuery~

    产品需求,需要用到对div(dom)进行拖拽缩放操作,看到有好多插件,要么依赖jQuery,要么文件太大. 封装了一个插件,不压缩状态下5KB. html <!DOCTYPE html> ...

  3. DragVideo,一种在播放视频时,可以任意拖拽的方案

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53638896 前言 项目已开源到 ...

  4. Html5 拖拽api

    拖拽要有两个元素,一个是要拖动的元素,一个是要放置到的元素. 1, 在默认情况下, 只有图片和文字是可以拖拽的,其它元素都不可以.因此要想使一个元素可拖动,必须设置它的draggable 属性为tru ...

  5. 强大的jQuery幻灯片播放插件 支持全拼、拖拽和下载等功能

    在线演示 本地下载

  6. 不断优化,重构我的代码-----拖拽jquery插件

    最近学东西学的有点太散了,歇一阵子,重新完善之前的JQ插件,今天先上拖拽吧 // JavaScript Document (function($){ var defaults = { actionEl ...

  7. JQuery之拖拽插件

    一直以来,都对JS获取元素的位置感到非常的困惑:一会client.一会offset.一会scroll. 再加上各大浏览器之间的不兼容,唉,搞得哥晕晕乎乎的. 而很多页面效果都要用到这些位置.不得已,得 ...

  8. 一步一步实现JS拖拽插件

    js拖拽是常见的网页效果,本文将从零开始实现一个简单的js插件. 一.js拖拽插件的原理 常见的拖拽操作是什么样的呢?整过过程大概有下面几个步骤: 1.用鼠标点击被拖拽的元素 2.按住鼠标不放,移动鼠 ...

  9. div拖拽缩放jquery插件编写——带8个控制点

    项目中需要对div进行拖拽缩放,需要有控制面板8个控制点的那种,原以为这么常见的效果应该能搜索到很多相关插件,然而可以完成拖拽的实繁,却找不到我想要的,还是自己动手丰衣足食吧 效果预览(只支持pc端) ...

随机推荐

  1. 分享一例测试环境下nginx+tomcat的视频业务部署记录

    需求说明:在测试环境下(192.168.1.28)部署一套公司某业务环境,其中:该业务前台访问地址: http://testhehe.wangshibo.com该业务后台访问地址: http://te ...

  2. 2055 [ZJOI2009]假期的宿舍

    P2055 [ZJOI2009]假期的宿舍 题目描述 学校放假了 · · · · · · 有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如 A 和 B 都是学校的学生,A ...

  3. Java集合系列:-----------05LinkedList的底层实现

    前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类--LinkedList.和学习ArrayList一样,接下来呢,我们先对LinkedList ...

  4. 表单验证——JavaScript和Jquery版

    1.轻量级的JavaScript表单验证 在应用中引用 validator.min.js 文件 <script type="text/javascript" src=&quo ...

  5. 启动PPT的时候一直配置vs2013的问题解决

    前几天装了VS2013,结果发现每次启动powerpoint都要配置vs2013,虽然时间花的不多,可我看的就是碍眼,我都想把VS2013卸载来解决了.后来抱着试下的态度竟然在google上找到了解决 ...

  6. There is no ‘Animation’ attached to the “Player” game object

    There is no ‘Animation’ attached to the “Player” game object 在照着龚老师的Unity3D投篮游戏视频教程练习时,遇到这个错误提示. 我知道 ...

  7. 在linux下运行java工程

    在linux 服务器上运行JAVA工程需注意.1: 在linux 上: /etc/profile  设置classpath 配置正确的jar 路径.2:  把本地JAVA工程做成一个jar包.如:1. ...

  8. 让 HTML5 来为你定位

    Geolocation HTML5 的 geolocation 是一个令人兴奋的 API,通过这套 API,Javascript 代码就能够访问到用户的当前位置.当然,访问之前必须得到用户的明确认可, ...

  9. [转]Linux系统中‘dmesg’命令处理故障和收集系统信息的7种用法

    'dmesg'命令显示linux内核的环形缓冲区信息,我们可以从中获得诸如系统架构.cpu.挂载的硬件,RAM等多个运行级别的大量的系统信息.当计算机启动时,系统内核(操作系统的核心部分)将会被加载到 ...

  10. AngularJS中实现无限级联动菜单(使用demo)

    昨天没来得及贴几个使用demo,今天补上,供有兴趣的同学参考 :) 1. 同步加载子选项demo2. 异步加载子选项demo3. 初始值回填demo4. 倒金字塔依赖demo directive的源代 ...