1. ;(function(){
  2. var Test=function(opt){
  3. // console.log(opt.a)
  4. }
  5. Test.prototype={
  6. };
  7. window.Test=Test;
  8. })();
  9. var test=new Test({a:'1',b:'2'});

JSON字符串转对象 -> JSON.parse()

html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>TodoList</title>
  8. <link href="https://netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  9. <link rel="stylesheet" href="./css/common.css">
  10. <link rel="stylesheet" href="./css/index.css">
  11. </head>
  12. <body>
  13. <div class="wrap">
  14. <div class="list-hd">
  15. <h2>TodoList</h2>
  16. <a href="javascript:;" class="j-plus-btn fa fa-plus"></a>
  17. </div>
  18. <div class="input-wrap">
  19. <div class="input-bd text-input">
  20. <input type="text" id="itemContent"/>
  21. </div>
  22. <div class="btn-bd add-btn">
  23. <button class="j-add-item">增加项目</button>
  24. </div>
  25. </div>
  26. <div class="list-wrap">
  27. <ul class="item-list"></ul>
  28. </div>
  29. </div>
  30. <script src="./js/untils.js"></script>
  31. <script src="./js/index.js"></script>
  32. </body>
  33. </html>

common.css

  1. body{
  2. margin: 0;
  3. }
  4. a{
  5. text-decoration: none;
  6. }
  7. ul{
  8. padding: 0;
  9. margin: 0;
  10. list-style: none;
  11. }
  12. h1,
  13. h2,
  14. h3,
  15. h4,
  16. h5,
  17. h6,
  18. p{
  19. margin: 0;
  20. font-weight: bold;
  21. }
  22. h1{
  23. margin: 0;
  24. font-weight: bold;
  25. }
  26. div{
  27. box-sizing: border-box;
  28. }
  29. input,button{
  30. outline: none;
  31. box-sizing: border-box;
  32. border: none;
  33. }

index.css

  1. .wrap{
  2. position: relative;
  3. width: 500px;
  4. height: 500px;
  5. margin: 50px auto;
  6. box-shadow: 0 0 5px #999;
  7. border-radius: 10px;
  8. overflow: hidden;
  9. }
  10. .list-hd{
  11. position: absolute;
  12. top: 0;
  13. left:0;
  14. height: 44px;
  15. width: 100%;
  16. background-color: #000;
  17. color: #fff;
  18. text-align: center;
  19. line-height: 44px;
  20. }
  21. .list-hd .fa-plus{
  22. position: absolute;
  23. top: 15px;
  24. right: 15px;
  25. color: #fff;
  26. }
  27. .input-wrap{
  28. display: none;
  29. position: relative;
  30. top: 44px;
  31. left: 0;
  32. width: 100%;
  33. height: 40px;
  34. border-bottom: 1px solid #ddd;
  35. }
  36. .input-wrap .text-input{
  37. float: left;
  38. width: 410px;
  39. height: 100%;
  40. padding: 5px 5px 5px 10px;
  41. }
  42. .input-wrap .input-bd input{
  43. width: 100%;
  44. height: 100%;
  45. border: 1px solid #ddd;
  46. }
  47. .input-wrap .btn-bd{
  48. float: left;
  49. width: 90px;
  50. height: 100%;
  51. padding: 5px 5px 5px 10px;
  52. }
  53. .input-wrap .btn-bd button{
  54. width: 100%;
  55. height: 100%;
  56. border: 1px solid #ddd;
  57. background-color: #fff;
  58. }
  59. .list-wrap{
  60. height: 456px;
  61. margin-top: 44px;
  62. overflow: auto;
  63. }
  64. .list-wrap .item{
  65. height: 50px;
  66. position: relative;
  67. }
  68. .list-wrap .item:nth-child(odd),
  69. .list-wrap .item:hover{
  70. background-color: #eee;
  71. }
  72. .list-wrap .item.active{
  73. background-color: #dff0d8;
  74. }
  75. .list-wrap .item .item-content{
  76. position: absolute;
  77. left: 0;
  78. top: 0;
  79. width: 400px;
  80. height: 100%;
  81. line-height: 50px;
  82. text-indent: 15px;
  83. }
  84. .list-wrap .item .btn-group{
  85. height: 100%;
  86. margin-left: 400px;
  87. line-height: 50px;
  88. }
  89. .list-wrap .item .btn-group a{
  90. margin-left: 15px;
  91. }
  92. .list-wrap .item .btn-group .edit-btn{
  93. color: green;
  94. }
  95. .list-wrap .item .btn-group .remove-btn{
  96. color: red;
  97. }

untils.js

  1. // 添加事件
  2. function addEvent(el,type,fn) {
  3. if(el.addEventListener){
  4. el.addEventListener(type,fn,false);
  5. }else if(el.attachEvent){
  6. el.attachEvent('on'+type,function () {
  7. fn.call(el);
  8. })
  9. }else{
  10. el['on'+type] = fn;
  11. }
  12. }
  13. // 获取滚动坐标
  14. function getScrollOffset(){
  15. if(window.pageXOffset){
  16. return{
  17. left:window.pageXOffset,
  18. top:window.pageYOffset
  19. }
  20. }else{
  21. return{
  22. left:document.body.scrollLeft + document.documentElement.scrollLeft,
  23. top:document.body.scrollTop + document.documentElement.scrollTop
  24. }
  25. }
  26. }
  27. // 封装可视窗口尺寸
  28. function getViewportSize(){
  29. if(window.innerWidth){
  30. return{
  31. width:window.innerWidth,
  32. height:window.innerHeight
  33. }
  34. }else{
  35. if(document.compatMode==='BackCompat'){
  36. return{
  37. width:document.body.clientWidth,
  38. height:document.body.clientHeight
  39. }
  40. }else{
  41. return {
  42. width:document.documentElement.clientWidth,
  43. height:document.documentElement.clientHeight
  44. }
  45. }
  46. }
  47. }
  48. //获取body大小
  49. function getScrollSize(){
  50. if(document.body.scrollWidth){
  51. return {
  52. width:document.body.scrollWidth,
  53. height:document.body.scrollHeight
  54. }
  55. }else{
  56. return {
  57. width:document.documentElement.scrollWidth,
  58. height:document.documentElement.scrollHeight
  59. }
  60. }
  61. }
  62. // 获取子元素
  63. function elemChildren(node){
  64. var temp = {
  65. 'length': 0,
  66. 'push': Array.prototype.push,
  67. 'splice': Array.prototype.splice
  68. },
  69. len = node.childNodes.length;
  70. for(var i = 0;i<len;i++){
  71. var childItem = node.childNodes[i];
  72. if(childItem.nodeType === 1){
  73. temp[temp['length']] = childItem;
  74. temp['length']++;
  75. // temp.push(childItem); push方法
  76. }
  77. }
  78. return temp;
  79. }
  80. // 获取祖先元素
  81. function elemParent(node,n){
  82. var type = typeof(n);
  83. if(type==='undefined'){
  84. return node.parentNode;
  85. }else if(n<=0|| type !=='number'){
  86. return undefined;
  87. }
  88. while(n){
  89. node = node.parentNode;
  90. n--;
  91. }
  92. return node;
  93. }

index.js

  1. ;(function(node){
  2. var TodoList = function(){
  3. var _self = this;
  4. this.node = node;
  5. this.inputShow = false;
  6. this.isEdit = false;
  7. this.curIdx = null;
  8. this.dConfig = {
  9. "plusBtn":"",
  10. "inputArea":"",
  11. "addBtn":"",
  12. "list":"",
  13. "itemClass":""
  14. }
  15. this.config = this.getConfig();
  16. this.itemClass = this.config.itemClass;
  17. for(var key in this.dConfig){
  18. if(!this.config.hasOwnProperty(key)){
  19. console.log(errorInfo(key));
  20. return;
  21. }
  22. }
  23. this.setConfig();
  24. addEvent(this.plusBtn,'click',function(){
  25. _self.showInput.call(_self);
  26. });
  27. addEvent(this.addBtn,'click',function(){
  28. _self.addBtnClick.call(_self);
  29. });
  30. addEvent(this.oList,'click',function(e){
  31. var e = e || window.event,
  32. tar = e.target || e.srcElement;
  33. _self.listClick.call(_self,tar);
  34. });
  35. }
  36. TodoList.prototype = {
  37. getConfig:function(){
  38. console.log(this.node.getAttribute('data-config'))
  39. return JSON.parse(this.node.getAttribute('data-config'))
  40. },
  41. setConfig:function(){
  42. var config = this.config,
  43. node = this.node;
  44. this.inputArea = node.getElementsByClassName(config.inputArea)[0];
  45. this.addBtn = this.inputArea.getElementsByClassName(config.addBtn)[0];
  46. this.plusBtn = node.getElementsByClassName(config.plusBtn)[0];
  47. this.oList = node.getElementsByClassName(config.list)[0];
  48. this.content = this.inputArea.getElementsByClassName('content')[0];
  49. console.log(this);
  50. console.log(this.plusBtn);
  51. },
  52. showInput:function(){
  53. console.log('1');
  54. var _self = this;
  55. if(this.inputShow){
  56. setInputShow.call(_self,'close');
  57. }else{
  58. setInputShow.call(_self,'open');
  59. }
  60. },
  61. addBtnClick:function(){
  62. var _self = this,
  63. content = this.content.value,
  64. contentLen = content.length,
  65. oItems = this.oList.getElementsByClassName('item'),
  66. itemLen = oItems.length,
  67. text;
  68. if(contentLen<=0){
  69. return;
  70. }
  71. if(itemLen>0){
  72. for(var i = 0;i<itemLen;i++){
  73. text = elemChildren(oItems[i])[0].innerText;
  74. if(text===content){
  75. alert('已存在该项');
  76. return;
  77. }
  78. }
  79. }
  80. if(this.isEdit){
  81. elemChildren(oItems[this.curIdx])[0].innerText = content;
  82. setInputStatus.call(_self,[oItems,null,'add']);
  83. }else{
  84. var oLi = document.createElement('li');
  85. oLi.className = this.itemClass;
  86. oLi.innerHTML = itemTpl(content);
  87. this.oList.appendChild(oLi);
  88. }
  89. setInputShow.call(_self,'close');
  90. },
  91. listClick:function(tar){
  92. var _self = this,
  93. className = tar.className,
  94. oParent = elemParent(tar,2),
  95. oItems = this.oList.getElementsByClassName('item'),
  96. itemLen = oItems.length,
  97. item;
  98. if(className === 'edit-btn fa fa-edit'){
  99. // console.log('edit');
  100. for(var i = 0;i<itemLen;i++){
  101. item = oItems[i];
  102. item.className ='item';
  103. }
  104. oParent.className += ' active';
  105. setInputShow.call(_self,'open');
  106. setInputStatus.apply(_self,[oItems,oParent,'edit']);
  107. }else if(className === 'remove-btn fa fa-times'){
  108. // console.log('remove');
  109. oParent.remove();
  110. }
  111. }
  112. }
  113. function setInputShow(action) {
  114. // console.log('2');
  115. var oItems = this.oList.getElementsByClassName('item');
  116. if(action === 'open'){
  117. this.inputArea.style.display = 'block';
  118. this.inputShow = true;
  119. }else if(action === 'close'){
  120. this.inputArea.style.display = 'none';
  121. this.inputShow = false;
  122. this.content.value = '';
  123. setInputStatus(oItems,null,status);
  124. }
  125. }
  126. function setInputStatus(oItems,target,status){
  127. if(status === 'edit'){
  128. var idx = Array.prototype.indexOf.call(oItems,target),
  129. text = elemChildren(target)[0].innerText;
  130. this.addBtn.innerText = '编辑第'+(idx+1)+'项';
  131. this.isEdit = true;
  132. this.curIdx = idx;
  133. this.content.value = text;
  134. }else if(status === 'add'){
  135. var itemLen = oItems.length,
  136. item;
  137. for(var i = 0;i<itemLen;i++){
  138. item = oItems[i];
  139. item.className = 'item';
  140. this.addBtn.innerText ='增加项目';
  141. this.isEdit = false;
  142. this.curIdx = null;
  143. }
  144. }
  145. }
  146. function errorInfo(key){
  147. return new Error(
  148. '您没有配置参数' + key + '\n'+
  149. '必须配置的参数列表如下: \n'+
  150. '打开输入按钮元素类名:plusBtn\n' +
  151. '输入框区域元素类名:inputArea\n' +
  152. '增加项目按钮元素类名:addBtn\n' +
  153. '列表承载元素类名:list\n' +
  154. '列表项承载元素类名:itemClass'
  155. );
  156. }
  157. function itemTpl(text) {
  158. return (
  159. '<p class="item-content">' + text + '</p>' +
  160. '<div class="btn-group">' +
  161. '<a href="javascript:;" class="edit-btn fa fa-edit"></a>' +
  162. '<a href="javascript:;" class="remove-btn fa fa-times"></a>' +
  163. '</div>'
  164. )
  165. }
  166. new TodoList();
  167. }(document.getElementsByClassName('todo-wrap')[0]));

index2

  1. // ;(function(){
  2. // var Test=function(opt){
  3. // // console.log(opt.a)
  4. // }
  5. // Test.prototype={
  6. // };
  7. // window.Test=Test;
  8. // })();
  9. // var test=new Test({a:'1',b:'2'});
  10. (function (node) {
  11. var TodoList = function () {
  12. var _self = this;
  13. console.log(_self); //直接打印可以看到挂载到对象上的元素是否正确,而不用总是打印
  14. this.node = node;
  15. this.inputShow = false; //打开关闭的状态
  16. // console.log(this.getConfig())
  17. this.dConfig = {
  18. plusBtn: "",
  19. inputArea: "",
  20. addBtn: "",
  21. list: "",
  22. itemClass: "",
  23. };
  24. this.config = this.getConfig();
  25. this.itemClass = this.config.itemClass;
  26. // this.config = this.getConfig();
  27. for (var key in this.dConfig) {
  28. if (!this.config.hasOwnProperty(key)) {
  29. return; //结束函数
  30. }
  31. }
  32. this.setConfig();
  33. //这里this是plusBtn,应该把this变成TodoList
  34. addEvent(this.plusBtn, "click", function () {
  35. _self.showInput.call(_self); //改变showInput的this指向 得改变2次
  36. // _self.showInput()
  37. }),
  38. addEvent(this.addBtn, "click", function () {
  39. // console.log('addBtn')
  40. _self.addBtnClick.call(_self);
  41. });
  42. addEvent(this.oList, "click", function (e) {
  43. var e = e || window.event,
  44. tar = e.target || e.srcElement;
  45. _self.listClick.call(_self, tar);
  46. });
  47. };
  48. TodoList.prototype = {
  49. getConfig: function () {
  50. // var config=
  51. // console.log(this.node);
  52. // var config=JSON.parse(this.node.getAttribute('data-config'));
  53. // // var config=this.node.dataset.config;
  54. // // console.log(config)
  55. // return config;
  56. return JSON.parse(this.node.getAttribute("data-config"));
  57. },
  58. setConfig: function () {
  59. var config = this.config,
  60. node = this.node;
  61. this.inputArea = node.getElementsByClassName(config.inputArea)[0];
  62. this.addBtn = this.inputArea.getElementsByClassName(config.addBtn)[0];
  63. //效率更高,比从node上获取
  64. this.plusBtn = node.getElementsByClassName(config.plusBtn)[0];
  65. this.oList = node.getElementsByClassName(config.list)[0];
  66. this.content = this.inputArea.getElementsByClassName("content")[0];
  67. // this.plusBtn=node.getElementsByClassName(config.plusBtn)[0];
  68. // this.oList=node.getElementsByClassName(config.list)[0];
  69. // console.log(this);
  70. // console.log(this.plusBtn);
  71. },
  72. //点击+展示输入框
  73. showInput: function () {
  74. // console.log(this)
  75. var _self = this;
  76. if (this.inputShow) {
  77. //封装显示输入框的方法
  78. setInputShow.call(_self, "close");
  79. } else {
  80. setInputShow.call(_self, "open");
  81. }
  82. },
  83. //输入数据
  84. addBtnClick: function () {
  85. var _self = this,
  86. content = this.content.value,
  87. contentLen = content.length,
  88. oItems = this.oList.getElementsByClassName("item"),
  89. itemLen = oItems.length,
  90. text;
  91. if (contentLen <= 0) {
  92. return;
  93. }
  94. if (itemLen > 0) {
  95. for (var i = 0; i < itemLen; i++) {
  96. text = elemChildren(oItems[i])[0].innerText;
  97. if (text === content) {
  98. alert("已存在该项");
  99. return;
  100. }
  101. }
  102. }
  103. if (this.isEdit) {
  104. elemChildren(oItems[this.curIdx])[0].innerText = content;
  105. setInputStatus.call(_self, [oItems, null, "add"]);
  106. } else {
  107. var oLi = document.createElement("li");
  108. oLi.className = this.itemClass;
  109. oLi.innerHTML = itemTpl(content);
  110. this.oList.appendChild(oLi);
  111. }
  112. setInputShow.call(_self, "close");
  113. },
  114. listClick: function (tar) {
  115. var _self = this,
  116. className = tar.className,
  117. oParent = elemParent(tar, 2),
  118. oItems = this.oList.getElementsByClassName("item"),
  119. itemLen = oItems.length,
  120. item;
  121. if (className === "edit-btn fa fa-edit") {
  122. // console.log('edit');
  123. for (var i = 0; i < itemLen; i++) {
  124. item = oItems[i];
  125. item.className = "item";
  126. }
  127. oParent.className += " active";
  128. setInputShow.call(_self, "open");
  129. setInputStatus.apply(_self, [oItems, oParent, "edit"]);
  130. } else if (className === "remove-btn fa fa-times") {
  131. // console.log('remove');
  132. oParent.remove();
  133. }
  134. },
  135. };
  136. function setInputShow(action) {
  137. // console.log(2,this)
  138. if (action === "open") {
  139. this.inputArea.style.display = "block";
  140. this.inputShow = true;
  141. } else if (action === "close") {
  142. this.inputArea.style.display = "none";
  143. this.inputShow = false;
  144. }
  145. }
  146. function setInputShow(action) {
  147. // console.log('2');
  148. var oItems = this.oList.getElementsByClassName("item");
  149. if (action === "open") {
  150. this.inputArea.style.display = "block";
  151. this.inputShow = true;
  152. } else if (action === "close") {
  153. this.inputArea.style.display = "none";
  154. this.inputShow = false;
  155. this.content.value = "";
  156. setInputStatus(oItems, null, status);
  157. }
  158. }
  159. function setInputStatus(oItems, target, status) {
  160. if (status === "edit") {
  161. var idx = Array.prototype.indexOf.call(oItems, target),
  162. text = elemChildren(target)[0].innerText;
  163. this.addBtn.innerText = "编辑第" + (idx + 1) + "项";
  164. this.isEdit = true;
  165. this.curIdx = idx;
  166. this.content.value = text;
  167. } else if (status === "add") {
  168. var itemLen = oItems.length,
  169. item;
  170. for (var i = 0; i < itemLen; i++) {
  171. item = oItems[i];
  172. item.className = "item";
  173. this.addBtn.innerText = "增加项目";
  174. this.isEdit = false;
  175. this.curIdx = null;
  176. }
  177. }
  178. }
  179. function errorInfo(key) {
  180. return new Error(
  181. "您没有配置参数" +
  182. key +
  183. "\n" +
  184. "必须配置的参数列表如下: \n" +
  185. "打开输入按钮元素类名:plusBtn\n" +
  186. "输入框区域元素类名:inputArea\n" +
  187. "增加项目按钮元素类名:addBtn\n" +
  188. "列表承载元素类名:list\n" +
  189. "列表项承载元素类名:itemClass"
  190. );
  191. }
  192. function itemTpl(text) {
  193. return (
  194. '<p class="item-content">' +
  195. text +
  196. "</p>" +
  197. '<div class="btn-group">' +
  198. '<a href="javascript:;" class="edit-btn fa fa-edit"></a>' +
  199. '<a href="javascript:;" class="remove-btn fa fa-times"></a>' +
  200. "</div>"
  201. );
  202. }
  203. new TodoList();
  204. })(document.getElementsByClassName("todo-wrap")[0]);