[
  {
    "path": ".gitignore",
    "content": "node_modules\ndemo"
  },
  {
    "path": "README.md",
    "content": "![logo](./images/logo.png)\n# Medit v2.0.0\n\n***\n\nmedit新版本正在daily/3.0.0分支上进行开发，如有问题或者3.0版本开发建议可以提交issue\n\n***\n\nA creative WYSIWYG rich text editor for mobile device by javascript.\n\n一个创新型的移动端所见即所得富文本编辑器。\n\nWebsite Address : [https://medit.js.org](https://medit.js.org)\n\nDemo: [Medit Demo](https://medit.js.org/demo.html)\n\n##### 为了更专注做一个更具价值和体验的移动端富文本编辑器，所以Medit目前不支持Pc端使用，仅支持移动端。\n\n***\n### Medit2.0.0 较上一版本更新内容\n\n1. 更易用的内容选择方式，目前已支持选取内容块后手势左右滑动选择、通过手机原生自带长按选择进行编辑操作。\n2. 优化编辑器样式，把原有的图标、弹层和编辑器内部标识都进行了优化。\n3. 开放功能扩展接口Medit.extend，可以通过这个接口来扩展更加丰富的内容。\n4. 开放内置功能配置接口Medit.nativeSetting，开放内置弹层调用接口Medit.settingPage。\n5. 工具条目前不在限制于页面顶部，用户可以对工具条进行自定义配置。\n\n  \n***\n### 如何使用：\n\n+ 第一步，引入medit.js文件，如果不下载使用icon包的话可能会导致部分功能性icon无法显示，icon存放于 __github/medit/build/images__ 下\n```html\n<script src=\"https://medit.js.org/build/medit.min.js\"></script>\n```\n> 在第一步和第二步之间可以选择性的引入medit插件，也可以自己来书写medit插件，medit提供了两个方法，一个是 __medit.extend__ 方法来配置扩展插件，另外还有一个 __medit.nativeSetting__ 方法来配置内部功能，详情请看下面的 medit类方法。\n\n+ 第二步，创建medit实例\n```html\n<script>\n/*\n * var meditObj = medit(editerContainerNode [, toolBarContainer]);\n *\n * 这里的medit方法内部实现了自动new，所以可以使用new medit，也可以直接使用medit。\n *\n * editerContainerNode：这是必须的，代表的是编辑框的node结点。\n * toolBarContainer： 这是可选的参数，可以传入一个node结点来配置工具条位置，如果不传入那么就会固定在页面顶部。\n *\n * 下面是一个实例\n */\n var meditObj = medit(document.getElementById(\"medit\"), document.getElementById(\"meditToolBar\"));\n</script>\n```\n+ 经过上面两步之后一个medit富文本编辑器就可以使用了。\n\n***\n### Medit实例方法\n\n通过上面创建好的medit实例meditObj可以调用medit的方法来实现你想要的功能。\n\n+ meditObj.getContent()\n  获取medit编辑器中所编辑的内容结果。\n\n+ meditObj.clear()\n  清除medit编辑器的内容和自动保存在客户端浏览器中的内容。\n\n+ meditObj.autoSave(name, callBack(content, time))\n  配置medit自动保存，需要传入两个参数：\n  + name：为了保证在同一页面引入两个编辑器后自动保存的效果，所以需要手动传入一个自动保存的字段名称，需要在页面中保持唯一性。\n  + callBack(content, time)：这是自动保存的回调函数，每次medit自动保存后都会调用这个回调函数，并传入当前保存的编辑器内容content和当前时间戳time。\n\n+ meditObj.image(option) || meditObj.imageUpload(option)\n  medit图片上传配置，option是配置参数\n  ```javascript\n  { // 默认图片上传设置\n\t\tpath:'https://sm.ms/api/upload', // 图片上传路径\n\t\tname:'smfile', // 图片上传文件参数\n\t\tsize:0, // 大小限制，0为不限制大小\n\t\ttimeout:0, // 上传超时时间，0为不限制\n\t\text:[\"jpg\",\"jpeg\",\"png\",\"gif\",\"bmp\"], // 上传文件格式限制\n\t\tsuccess:function(){}, // 上传成功回调\n\t\terror:function(){} // 上传失败回调\n\t}\n  ```\n\n***\n\n### medit类方法\n\n目前有三个medit类方法，所谓类方法就是直接通过medit类进行调用而不是通过medit实例进行调用。\n\n+ medit.extend(config) \n  功能扩展方法，可以通过这个方法实现medit插件和功能扩展。\n  config是一个对象，其中必须包括 __图标: icon__ 、 __其它类型模块转换为此类型模块时动作: doWhat__ 、 __模块得到焦点时动作: focus__ 、__模块失去焦点时动作: blur__ 和 __模块名称: name__ 这五个属性。其中icon可以是远程url，也可以是dataURL；name必须保持唯一，不能与内置功能名称产生冲突。\n\n 下面是一个功能模块的完整配置属性：\n ```javscript \n /* \n    icon: [String] 类型选择icon url\n    name: [String] 类型名称\n    isMerge: [Bollean] 是否开启相同内容自动合并\n    notDisplay: [Bollean] 在选择模式的时候不显示,\n    emptyNotDelete: [Bollean] 如果当前块只存在一个子节点并且这个子节点要删除的时候是否开启递归删除\n    \n    doWhat: [Function] 转换到此类型时会自动做哪些转换\n    focus：[Function] 点击或此模块获取焦点时自动触发的函数\n    blur：[Function] 此模块失去焦点时自动触发的函数\n    empty: [Function] 什么时候当前模块为空\n    selecting：[Function] 选择当前模块并且手指在屏幕上移动时触发的操作\n    selected：[Function] 手指移动结束执行的操作\n    setting: [Array(Object)] 当前模块可以进行哪些操作\n     --\tname: [String] 操作名称\n     --\ticon: [String] 操作按钮icon url\n     --\tdoWhat: [Function/Array] 点击此操作按钮执行什么，或者是存在更深层次操作\n */\n ```\n+ medit.nativeSetting(callBack(config, name))\n  内部功能配置方法，会循环调用callBack，然后把内置功能的配置和名称传入，返回值应该是一个修改后的config，然后medit就会应用这个config，如果没有返回值那么medit也就不会做任何改动。\n\n+ medit.settingPage(title, contentHTML, callBack)\n  打开medit内置弹层，title是配置弹层顶部Title，contentHTML可以传入一段html文本作为弹层的内容，callBack是在弹层的ok按钮点击之后触发。\n\n下面是一段应用medit类方法的实例：\n```html\n<script>\nmedit.extend({\n\tname: 'time',\n\ticon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAClklEQVRYR8WXjW0VQQyExxUAHUAFJBWQVACpgFABoQJCBZAKgAqSVECogKQCSAVABUZf8B73s393QXorPa2ebs87Httjn2nHy3Z8v1YBcPfHkp5JeiHpYfzw4Vf8LiR9NbMfvY51AXD3A0lvJbH3rCtJ78yMvbqqANwdL99LOh5ZuZGEp3PjgIOZp6OznHtlZjCUXUUA7r4n6aMkdtZnSactegP0B0kv473rAMG+WFkAcfmXiPEtnplZ1kDJs7DxKRiBgcOcjQWA8IDL8Ry6D0oURlKqxErYIlSEBQcAMQlHDgCooQ/P92rxc3eHATOrhZI8SiAuzOxozNrkxaDtWxzYb9HeAwBbM7uwMCTwHABZ+5yEM7Nx5mdD3QsgQCRmr8zsMBkcAES8fsaDJ61sD6PNEKSLIl++x/9HKbRjAHhM2d2YWSq9qoisYSAAk4gkJNoAI/+k2N2p3dehYKd1/fr7dAMA7KKoQ4jHDJAY6PyArgViAwCU8jz6xZ2s5wBMsrQGIgFAITPnqHc8Heo+egoac21m+/8TQAnnGzMjtClkeA0AOmaRgclLDQYoW4SmtI7H1eTu1RCkJDwzs5NW/Lc8d/dqEqYyHOKz5ZIGY9UyhMpVQrQGYFOIoq6TXC6axprLcmfdPdm+NDNy4W7NewEzX5LL7nJsgZs1o4nM59pxSkbql47YPWAWPCe0OMW+aHKlgWQ8RBxtBdEz3JRGMtDi+YMYtwHRnHDHDITqIbvY+h3DzYLN3kkG24gOIlUNSWQ7DSfNE4x1zJTZ93rGcsSDLpkWhgDDngZV2jcJTHazp3UWk/T6sXxGJ0YBkkbtVuJ3jfCLMmxZjaSiieDx/CuJHIERRq6ix/M7uj7NWsDu83znAP4A8SpJMGG4znIAAAAASUVORK5CYII=',\n\tdoWhat: function(node) {\n\t\tnode.innerHTML = \"this is time node\";\n\t\treturn node;\n\t},\n\tsetting: [{\n\t\tname: 'time',\n\t\ticon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAClklEQVRYR8WXjW0VQQyExxUAHUAFJBWQVACpgFABoQJCBZAKgAqSVECogKQCSAVABUZf8B73s393QXorPa2ebs87Httjn2nHy3Z8v1YBcPfHkp5JeiHpYfzw4Vf8LiR9NbMfvY51AXD3A0lvJbH3rCtJ78yMvbqqANwdL99LOh5ZuZGEp3PjgIOZp6OznHtlZjCUXUUA7r4n6aMkdtZnSactegP0B0kv473rAMG+WFkAcfmXiPEtnplZ1kDJs7DxKRiBgcOcjQWA8IDL8Ry6D0oURlKqxErYIlSEBQcAMQlHDgCooQ/P92rxc3eHATOrhZI8SiAuzOxozNrkxaDtWxzYb9HeAwBbM7uwMCTwHABZ+5yEM7Nx5mdD3QsgQCRmr8zsMBkcAES8fsaDJ61sD6PNEKSLIl++x/9HKbRjAHhM2d2YWSq9qoisYSAAk4gkJNoAI/+k2N2p3dehYKd1/fr7dAMA7KKoQ4jHDJAY6PyArgViAwCU8jz6xZ2s5wBMsrQGIgFAITPnqHc8Heo+egoac21m+/8TQAnnGzMjtClkeA0AOmaRgclLDQYoW4SmtI7H1eTu1RCkJDwzs5NW/Lc8d/dqEqYyHOKz5ZIGY9UyhMpVQrQGYFOIoq6TXC6axprLcmfdPdm+NDNy4W7NewEzX5LL7nJsgZs1o4nM59pxSkbql47YPWAWPCe0OMW+aHKlgWQ8RBxtBdEz3JRGMtDi+YMYtwHRnHDHDITqIbvY+h3DzYLN3kkG24gOIlUNSWQ7DSfNE4x1zJTZ93rGcsSDLpkWhgDDngZV2jcJTHazp3UWk/T6sXxGJ0YBkkbtVuJ3jfCLMmxZjaSiieDx/CuJHIERRq6ix/M7uj7NWsDu83znAP4A8SpJMGG4znIAAAAASUVORK5CYII=',\n\t\tdoWhat: function(node){\n\t\t\tmedit.settingPage(\"时间插件测试\",\"Time test\",function(){ console.log(\"ok点击了\")});\n\t\t}\n\t}],\n\tfocus: function(node){\n\t\tnode.setAttribute(\"class\",\"medit-editing\");\n\t},\n\tblur: function(node) {\n\t\tnode.removeAttribute(\"class\");\n\t}\n})\n\nmedit.nativeSetting(function(mode, modeName){\n\tconsole.log(mode, modeName);\n});\n</script>\n```\n***\n\n© MIT License\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"medit\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A creative WYSIWYG rich text editor for mobile device.\",\n  \"main\": \"medit.js\",\n  \"scripts\": {\n    \"dev\": \"webpack --config webpack.config.dev.js --watch\",\n    \"build\": \"webpack --config webpack.config.min.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/echosoar/medit.git\"\n  },\n  \"keywords\": [\n    \"WYSIWYG\",\n    \"mobile\",\n    \"rich\",\n    \"text\",\n    \"editor\"\n  ],\n  \"author\": \"echosoar\",\n  \"license\": \"ISC\",\n  \"bugs\": {\n    \"url\": \"https://github.com/echosoar/medit/issues\"\n  },\n  \"homepage\": \"https://medit.js.org\",\n  \"devDependencies\": {\n    \"babel-plugin-transform-es2015-classes\": \"^6.18.0\",\n    \"copy-webpack-plugin\": \"^4.0.1\",\n    \"eslint\": \"~3.4.0\",\n    \"eslint-plugin-babel\": \"^3.2.0\",\n    \"eslint-plugin-react\": \"~4.2.3\",\n    \"optimist\": \"^0.6.1\",\n    \"resolve-url-loader\": \"^1.6.1\",\n    \"url-loader\": \"~0.5.7\",\n    \"webpack\": \"~1.12.14\"\n  },\n  \"dependencies\": {\n    \"autoprefixer\": \"~6.3.4\",\n    \"babel-core\": \"^6.14.0\",\n    \"babel-eslint\": \"^6.1.2\",\n    \"babel-loader\": \"~6.2.4\",\n    \"babel-plugin-transform-object-rest-spread\": \"~6.6.5\",\n    \"babel-polyfill\": \"^6.3.14\",\n    \"babel-preset-es2015\": \"^6.14.0\",\n    \"css-loader\": \"~0.23.1\",\n    \"file-loader\": \"~0.8.5\",\n    \"less\": \"~2.6.1\",\n    \"less-loader\": \"~2.2.2\",\n    \"loader-utils\": \"~0.2.12\",\n    \"md5\": \"~2.0.0\",\n    \"node-sass\": \"^3.6.0\",\n    \"postcss-loader\": \"~0.8.2\",\n    \"precss\": \"~1.4.0\",\n    \"sass-loader\": \"^3.2.0\",\n    \"style-loader\": \"~0.13.0\"\n  }\n}\n"
  },
  {
    "path": "src/medit.css",
    "content": "#medit {\n\tfont-family:微软雅黑,黑体,Helvetica,华文黑体;\n\tfont-size: 14px;\n\tword-break:break-all;\n}\n#medit * {\n\toutline:none;\n}\n#medit span {\n\tposition: relative;\n\toutline:none;\n}\n.medit-editing{\n\toutline:none;\n\tpadding: 0 20px;\n\tbackground: #eeddff;\n\t\n}\n\n#medit-tool {\n\tposition:fixed;\n\tdisplay: none;\n\tz-index:100;\n\twidth:100%;\n\tleft: 0;\n\ttop: 0;\n\theight:40px;\n\twhite-space: nowrap;\n\toverflow:auto;\n\tbackground:#428bca;\n\ttext-align: left;\n\tfont-family:微软雅黑,黑体,Helvetica,华文黑体;\n}\n\n#medit-tool.medit-tool-inner {\n\tposition:relative;\n}\n\n#medit [data-meditMode=br] {\n\theight: 14px;\n\twidth: 20px;\n\tmargin:10px 0;\n\tborder-radius: 3px;\n\tbackground:url(\"./images/icon-br.png\") no-repeat center;\n\tbackground-size: 14px;\n}\n\n.medit-tool-button {\n\twidth:40px;\n\tdisplay:inline-block;\n\theight:40px;\n\tline-height: 40px;\n\ttext-align:center;\n\tfont-size:13px;\n\tcursor: pointer;\n\tcolor:#fff;\n\tfont-weight:bold;\n}\n\n.medit-tool-addLeft {\n\tbackground:url(\"./images/add-left.png\") no-repeat center center;\n\tbackground-size: 24px;\n}\n.medit-tool-addRight {\n\tbackground:url(\"./images/add-right.png\") no-repeat center center;\n\tbackground-size: 24px;\n}\n.medit-tool-delete {\n\tbackground:url(\"./images/close.png\") no-repeat center center;\n\tbackground-size: 24px;\n}\n\n.medit-tool-mode {\n\tbackground:url(\"./images/mode.png\") no-repeat center center;\n\tbackground-size: 24px;\n}\n.medit-tool-ok {\n\tbackground:url(\"./images/ok.png\") no-repeat center center;\n\tbackground-size: 24px;\n}\n\n.medit-tool-return {\n\tbackground:url(\"./images/return.png\") no-repeat center center;\n\tbackground-size: 24px;\n}\n\n.medit-tool-button{\n\tborder-right: 1px solid #357ebd;\n\tbackground-color: #428bca;\n}\n\n/* text */\n.medit-text-select {\n\tposition:relative;\n\tbackground:#9cf;\n}\n\n/* Link */\n.medit-link {\n\tbackground: #def;\n\tborder-bottom:1px dashed #709;\n}\n#medit a {\n\tposition: relative;\n\toutline:none;\n\tpadding: 0 20px;\n\t\n}\n#medit a:before {\n\tcontent: \" \";\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 20px;\n\theight:20px;\n\tbackground:url(\"./images/link/link-left.png\") no-repeat center center;\n\tbackground-size: 20px;\n}\n#medit a:after {\n\tcontent: \" \";\n\tposition: absolute;\n\tbottom: 0;\n\twidth: 20px;\n\theight:12px;\n\tbackground:url(\"./images/link/link-right.png\") no-repeat center center;\n\tbackground-size: 20px;\n}\n\n/* setting page */\n\n#medit-settingPage{\n\tdisplay: none;\n\tposition:fixed;\n\tz-index:101;\n\ttop:0;\n\tleft:0;\n\twidth:100%;\n\theight:100%;\n\tbackground:rgba(0,0,0,.6);\n\tfont-size:14px;\n\tfont-family:微软雅黑,黑体,Helvetica,华文黑体;\n\t\n}\n\n#medit-settingPage input {\n\tfont-family:微软雅黑,黑体,Helvetica,华文黑体;\n}\n\n#medit-settingPage-main{\n\tposition:absolute;\n\ttop:50%;\n\tleft:10%;\n\ttransform:translateY(-50%);\n\twidth:80%;\n\tbackground:#fff;\n\tborder-radius:3px;\n\tborder:1px solid #666;\n}\n#medit-settingPage-title {\n\tpadding:0 10px;\n\tfont-size:12px;\n\tcolor:#000;\n\theight:36px;\n\tline-height:36px;\n\tborder-bottom:1px solid #ddd;\n}\n#medit-settingPage-content {\n\tborder-radius: 3px;\n}\n\n#medit-settingPage-content .medit-list-mode-style-innerTitle{\n\tpadding: 0 5px;\n\tfont-size:12px;\n\tmargin:10px;\n\tborder-left: 3px solid #f96;\n}\n\n#medit-settingPage-content input[type=text] {\n\twidth:100%;\n\tbox-sizing:border-box;\n\tpadding:0 10px;\n\theight:40px;\n\tline-height:40px;\n\tmargin-top:15px;\n\tborder:1px solid #eee;\n\tborder-left:0;\n\tborder-right:0;\n\toutline:none;\n\tmargin-bottom:15px;\n\tfont-size:12px;\n}\n#medit-settingPage-content .medit-settingPage-image-dataInfo {\n\t\n}\n#medit-settingPage-content .medit-settingPage-image-dataInfo span {\n\tdisplay:block;\n\tfont-size:12px;\n\tpadding:15px;\n}\n#medit-settingPage-content .medit-settingPage-image-dataInfo input[type=text] {\n\tdisplay:block;\n\tmargin:0;\n}\n\n#medit-settingPage-content label{\n\tdisplay:block;\n\tmargin-left:10px;\n}\n\n#medit-settingPage-content input[type=radio], #medit-settingPage-content input[type=checkbox] {\n\tdisplay:none;\n}\n#medit-settingPage-content input[type=radio] + span, #medit-settingPage-content input[type=checkbox] + span {\n\tposition:relative;\n\tdisplay:inline-block;\n\theight:24px;\n\tline-height:24px;\n\tpadding-left:30px;\n\tfont-size:12px;\n}\n#medit-settingPage-content input[type=radio] + span:before, #medit-settingPage-content input[type=checkbox] + span:before{\n\tcontent:' ';\n\tposition:absolute;\n\tleft:0;\n\ttop:4px;\n\twidth:16px;\n\theight:16px;\n\tbackground:#fff;\n\tborder-radius:100%;\n\tborder:2px solid #9cf;\n}\n#medit-settingPage-content input[type=radio]:checked + span:before, #medit-settingPage-content input[type=checkbox]:checked + span:before  {\n\tbackground:#39f url(\"./images/ok.png\") no-repeat center center;\n\tbackground-size: 16px;\n\tborder:2px solid #39f;\n}\n#medit-settingPage-button{\n\theight:36px;\n\tmargin-top:15px;\n}\n\n#medit-settingPage-button-ok {\n\tdisplay: block;\n\tfont-style:normal;\n\theight:36px;\n\tline-height:36px;\n\ttext-align:center;\n\tcolor:#fff;\n\toverflow:hidden;\n\tbackground:#69f;\n\t\n}\n#medit-settingPage-button-cancel {\n\tbackground:#69f url(\"./images/close2.png\") no-repeat center center;\n\tbackground-size: 24px;\n\tposition:absolute;\n\ttop:-15px;\n\tright:-15px;\n\twidth:30px;\n\theight:30px;\n\tborder-radius:50%;\n}\n.medit-image{\n\tposition:relative;\n}\nimg:after {\n\tcontent:\" \";\n\tposition:absolute;\n\twidth:200px;\n\theight:200px;\n\tright:0;\n\tbottom:0;\n\tcolor:#fff;\n\tbackground:#333;\n}\n\n\n#medit [data-meditMode=image] {\n\tbackground-color:#e5e5e5;\n}\n\n#medit-image-upload-select-btn {\n\twidth:70%;\n\toverflow:hidden;\n\twhite-space:nowrap;\n\tpadding: 0 5%;\n\tmargin:20px auto;\n\theight:32px;\n\tline-height:32px;\n\tcolor:#fff;\n\tbackground:#3c9;\n\tborder-radius:3px;\n\ttext-align:center;\n}\n\n#medit-image-upload-file {\n\tposition:absolute;\n\tleft:-500px;\n\twidth:200px;\n\t\n}\n#medit-settingPage-content-img-uploading{\n\tpadding: 20px 10px;\n\tline-height:24px;\n}\n#medit-settingPage-content-img-uploading-progress {\n\tdisplay:block;\n\theight:4px;\n\tbackground:#c33;\n\tborder-radius:2px;\n\tmargin:10px 0;\n}\n\n#medit ul, #medit ol {\n\tposition:relative;\n\tpadding: 5px 0;\n\tmargin:5px 0;\n\tborder-left:20px solid #eee;\n\tmin-height:30px;\n}\n#medit ul:before, #medit ol:before {\n\tcontent: \"Li st\";\n\tposition:absolute;\n\theight:12px;\n\tline-height:12px;\n\tleft:-17px;\n\tcolor:#333;\n\twidth:15px;\n\tfont-size: 10px;\n\ttop:2px;\n}\n.medit-list {\n\tbackground:#ddd;\n}\n#medit li {\n\tposition:relative;\n\tmargin:0;\n\tpadding:0;\n\tlist-style:none;\n\tpadding:5px;\n\tmin-height:20px;\n\tmargin:3px;\n\tborder-left:20px solid #eee;\n}\n#medit li:before{\n\tcontent: \"li\";\n\tposition:absolute;\n\theight:20px;\n\tline-height:20px;\n\tleft:-20px;\n\tcolor:#333;\n\ttext-align:center;\n\twidth:20px;\n\tfont-size: 10px;\n\ttop:0px;\n}"
  },
  {
    "path": "src/medit.js",
    "content": "require(\"./medit.css\");\n\nvar obj = window;\n\nvar meditToolImage = obj.meditToolImage || \"./\";// 工具条图片位置\n\nvar meditId = null;\n\nvar container = [];\n\nvar regNodeId = /medit\\-(\\d+)\\-(\\d+)$/;\n\nvar regContent = /\\s(class|id|contenteditable)(=\".*?\")?/g; // 获得内容时去除id，class和可编辑状态\n\nvar regIsNotContentEmpty = /^<.*?>$/; // 获得内容时检测是否是纯文本\n\nvar regNormalStyle = /(font\\-style\\s*:\\s*normal\\s*;)|(font\\-weight\\s*:\\s*normal\\s*;)|(color:\\s*rgb\\(0,\\s*0,\\s*0\\);)|(\\s*)/ig; // 正常的样式需要剔除\n\nvar selectTextReg = /<span class=\"medit\\-text\\-select\">(.*?)<\\/span>/i;\n\nvar isToolMove = false;\n\nvar toolBarCatch = null;\n\nvar isContainMove = false;\n\nvar mainTouchPoint = {};\n\nvar nowNode = null; // 当前选择的可编辑结点\n\nvar nodeFocusTimeout = null; // nodeFocus延时 \n\nvar globalSelectionContent = null; // 缓存长按选择区域\nvar globalSelectionHandle = null;\n\nvar commonImageType = {\n\t\"jpeg\":\"image/jpeg\",\n\t\"jpg\":\"image/jpeg\",\n\t\"gif\":\"image/gif\",\n\t\"png\":\"image/png\",\n\t\"bmp\":\"image/bmp\"\n}\n\nvar getNodeById = function(id){\n\treturn document.getElementById(id);\n}\n\nvar fun_deep_clone = function (parent, child) {\n\tchild = child || {};\n\tfor(var i in parent) {\n\t\tif(parent.hasOwnProperty(i)) {\n\t\t\tif(typeof parent[i] === \"object\") {\n\t\t\t\tchild[i] = (Object.prototype.toString.call(parent[i]) === \"[object Array]\") ? [] : {};\n\t\t\t\tfun_deep_clone(parent[i], child[i]);\n\t\t\t} else {\n\t\t\t\tchild[i] = parent[i];\n\t\t\t}\n\t\t}\n\t}\n\treturn child;\n}\n\nvar returnButtonHtml = function(from){\n\treturn '<span id=\"medit-tool-button-'+from+'\" class=\"medit-tool-button  medit-tool-return\" data-meditToolStyle=\"return\" data-meditToolDegree=\"1\">&nbsp;</span>';\n}\n\nvar toArray = function(obj){\n\treturn [].slice.call(obj);\n}\n\t\nvar getXhr = function(){\n\tif(window.XMLHttpRequest){\n\t\tvar xhr=new XMLHttpRequest();\n\t}else{\n\t\ttry{\n\t\t\tvar xhr=new ActiveXObject(\"Msxml2.XMLHTTP\");\n\t\t}catch(e){\n\t\t\ttry{\n\t\t\t\tvar xhr=new ActiveXObject(\"Microsoft.XMLHTTP\");\n\t\t\t}catch(e){\n\t\t\t\tthrow new TypeError('Unsupport XMLHttpRequest');\n\t\t\t}\n\t\t}\n\t}\n\treturn xhr;\n}\n\nvar mainButton = [\"addLeft\",\"delete\",\"setting\",\"mode\",\"ok\",\"addRight\"];\n\nvar nowMode = \"text\";\n/*\nmode 属性：\n\nicon: [String] 类型选择icon url\n\nisMerge: [Bollean] 是否开启相同内容自动合并\nnotDisplay: [Bollean] 在选择模式的时候不显示,\nemptyNotDelete: [Bollean] 如果当前块只存在一个子节点并且这个子节点要删除的时候是否开启递归删除\n\ndoWhat: [Function] 转换到此类型时会自动做哪些转换\nfocus：[Function] 点击或此模块获取焦点时自动触发的函数\nblur：[Function] 此模块失去焦点时自动触发的函数\nempty: [Function] 什么时候当前模块为空\nselecting：[Function] 选择当前模块并且手指在屏幕上移动时触发的操作\nselected：[Function] 手指移动结束执行的操作\nsetting: [Array(Object)] 当前模块可以进行哪些操作\n --\tname: [String] 操作名称\n --\ticon: [String] 操作按钮icon url\n --\tdoWhat: [Function/Array] 点击此操作按钮执行什么，或者是存在更深层次操作\n\t\n\n*/\nvar nativeMode = [\"text\", \"br\", \"link\", \"image\", \"list\", \"li\"];\nvar mode = {\n\t\"text\": {\n\t\ticon: meditToolImage + 'images/mode/text.png',\n\t\tdoWhat: function(node){\n\t\t\tmode[node.getAttribute(\"data-meditmode\")].blur(node);\n\t\t\tvar temNode = document.createElement(\"span\");\n\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\ttemNode.setAttribute(\"data-meditmode\", \"text\");\n\t\t\tnode.parentNode.insertBefore(temNode,node);\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tmode[\"text\"].focus(temNode);\n\t\t\tnodeFocus(temNode);\n\t\t\tnowNode = temNode;\n\t\t\ttoolBarModeSetting(\"text\",mode[\"text\"].setting);\n\t\t\tcontainer[meditId].updateId();\n\t\t\tnowMode = \"text\";\n\t\t},\n\t\tisMerge: true,\n\t\tfocus:function(node) {\n\t\t\tnode.setAttribute(\"contentEditable\",\"true\");\n\t\t\tnode.setAttribute(\"class\",\"medit-editing\");\n\t\t},\n\t\tblur:function(node) {\n\t\t\tnode.innerHTML = node.innerHTML.replace(selectTextReg,\"$1\");\n\t\t\tnode.removeAttribute(\"contentEditable\");\n\t\t\tnode.removeAttribute(\"class\");\n\t\t},\n\t\tempty:function(node) {\n\t\t\treturn node.innerHTML == \"\";\n\t\t},\n\t\tsetting:[\n\t\t\t{\n\t\t\t\tname:\"bold\",\n\t\t\t\ticon: meditToolImage + \"images/text/bold.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tvar style = node.getAttribute(\"style\");\n\t\t\t\t\tvar reg = /font\\-weight\\s*:\\s*(.*?)\\s*;/i;\n\t\t\t\t\tif(reg.test(style)){\n\t\t\t\t\t\tvar regRes = reg.exec(style);\n\t\t\t\t\t\tif(regRes[1] == \"bold\"){\n\t\t\t\t\t\t\tnode.style.fontWeight = \"normal\";\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnode.style.fontWeight = \"bold\";\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:\"italic\",\n\t\t\t\ticon: meditToolImage + \"images/text/italic.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tvar style = node.getAttribute(\"style\");\n\t\t\t\t\tvar reg = /font\\-style\\s*:\\s*(.*?)\\s*;/i;\n\t\t\t\t\tif(reg.test(style)){\n\t\t\t\t\t\tvar regRes = reg.exec(style);\n\t\t\t\t\t\tif(regRes[1] == \"italic\"){\n\t\t\t\t\t\t\tnode.style.fontStyle = \"normal\";\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnode.style.fontStyle = \"italic\";\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:\"underline\",\n\t\t\t\ticon: meditToolImage + \"images/text/underline.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tvar style = node.getAttribute(\"style\");\n\t\t\t\t\tvar reg = /text\\-decoration\\s*:\\s*(.*?)\\s*;/i;\n\t\t\t\t\tif(reg.test(style)){\n\t\t\t\t\t\tvar regRes = reg.exec(style);\n\t\t\t\t\t\tif(regRes[1] == \"underline\"){\n\t\t\t\t\t\t\tnode.style.textDecoration = \"none\";\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnode.style.textDecoration = \"underline\";\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:\"size\",\n\t\t\t\ticon: meditToolImage + \"images/text/size.png\",\n\t\t\t\tdoWhat:[\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"fontSizeBig\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/sizeBigger.png\",\n\t\t\t\t\t\tdoWhat: function(node) {\n\t\t\t\t\t\t\tvar style = node.getAttribute(\"style\");\n\t\t\t\t\t\t\tvar displaySize = getNodeById(\"medit-tool-button-text-setting-3-doWhat-1\");\n\t\t\t\t\t\t\tvar reg = /font\\-size\\s*:\\s*(\\d*)\\s*(?:.*?)\\s*;/i;\n\t\t\t\t\t\t\tvar size = 15;\n\t\t\t\t\t\t\tif(reg.test(style)){\n\t\t\t\t\t\t\t\tvar regRes = reg.exec(style);\n\t\t\t\t\t\t\t\tsize = ++regRes[1];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(displaySize){\n\t\t\t\t\t\t\t\tdisplaySize.innerHTML = size;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnode.style.fontSize = size + \"px\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"fontSizeValue\",\n\t\t\t\t\t\ticon: \"\",\n\t\t\t\t\t\tdefaultValue: \"size\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"fontSizeSmall\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/sizeSmaller.png\",\n\t\t\t\t\t\tdoWhat: function(node) {\n\t\t\t\t\t\t\tvar style = node.getAttribute(\"style\");\n\t\t\t\t\t\t\tvar displaySize = getNodeById(\"medit-tool-button-text-setting-3-doWhat-1\");\n\t\t\t\t\t\t\tvar reg = /font\\-size\\s*:\\s*(\\d*)\\s*(?:.*?)\\s*;/i;\n\t\t\t\t\t\t\tvar size = 13;\n\t\t\t\t\t\t\tif(reg.test(style)){\n\t\t\t\t\t\t\t\tvar regRes = reg.exec(style);\n\t\t\t\t\t\t\t\tsize = --regRes[1];\n\t\t\t\t\t\t\t\tif(size<12)size=12;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(displaySize){\n\t\t\t\t\t\t\t\tdisplaySize.innerHTML = size;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnode.style.fontSize = size + \"px\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"color\",\n\t\t\t\ticon: meditToolImage + \"images/text/color.png\",\n\t\t\t\tdoWhat:[\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"black\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/colorBlack.png\",\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.color = \"#000000\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"red\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/colorRed.png\",\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.color = \"#ff0000\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"green\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/colorGreen.png\",\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.color = \"#00ff00\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"blue\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/colorBlue.png\",\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.color = \"#0000ff\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"yellow\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/colorYellow.png\",\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.color = \"#ffff00\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"pink\",\n\t\t\t\t\t\ticon: meditToolImage + \"images/text/colorPink.png\",\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.color = \"#ff00ff\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\tselecting : function(node, isAdd){\n\t\t\tvar selectReg = selectTextReg;\n\t\t\tif(selectReg.test(node.innerHTML)){\n\t\t\t\tvar regRes = node.innerHTML.split(selectReg);\n\t\t\t\tif(isAdd){\n\t\t\t\t\tif(regRes[1].length>1){\n\t\t\t\t\t\tif(/^&nbsp;|^<(.*?)\\s(.*?)>(.*?)<\\/(.*?)>/.test(regRes[1])){\n\t\t\t\t\t\t\tvar innerTagReg = /^&nbsp;|^<(.*?)\\s(.*?)>(.*?)<\\/(.*?)>/.exec(regRes[1]);\n\t\t\t\t\t\t\tvar replaceHTML = innerTagReg[0];\n\t\t\t\t\t\t\tregRes[0] += replaceHTML;\n\t\t\t\t\t\t\tregRes[1] = regRes[1].replace(/^&nbsp;|^<(.*?)\\s(.*?)>(.*?)<\\/(.*?)>/, \"\");\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tregRes[0] = regRes[0] + regRes[1].slice(0, 1);\n\t\t\t\t\t\t\tregRes[1] = regRes[1].slice(1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tif(regRes[1].length>1){\n\t\t\t\t\t\tif(/<(.*?)\\s(.*?)>(.*?)<\\/(.*?)>$|&nbsp;$/.test(regRes[1])){\n\t\t\t\t\t\t\tvar innerTagReg = /<(.*?)\\s(.*?)>(.*?)<\\/(.*?)>$|&nbsp;$/.exec(regRes[1]);\n\t\t\t\t\t\t\tvar replaceHTML = innerTagReg[0];\n\t\t\t\t\t\t\tregRes[2] = replaceHTML + regRes[2];\n\t\t\t\t\t\t\tregRes[1] = regRes[1].replace(/<(.*?)\\s(.*?)>(.*?)<\\/(.*?)>$|&nbsp;$/, \"\");\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tregRes[2] = regRes[1].slice(-1) + regRes[2];\n\t\t\t\t\t\t\tregRes[1] = regRes[1].slice(0, -1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tnode.innerHTML = regRes[0] + '<span class=\"medit-text-select\">' + regRes[1] + '</span>' + regRes[2];\n\t\t\t}else{\n\t\t\t\tnode.innerHTML = '<span class=\"medit-text-select\">' + node.innerHTML + '</span>';\n\t\t\t}\n\t\t},\n\t\tselected: function(thisNode){\n\t\t\tvar selectReg = selectTextReg;\n\t\t\tvar newNode;\n\t\t\tvar contain = container[meditId];\n\t\t\tif(selectReg.test(thisNode.innerHTML)) {\n\t\t\t\tvar thisId = regNodeId.exec(thisNode.getAttribute(\"id\"))[1];\n\t\t\t\tvar regRes = thisNode.innerHTML.split(selectReg);\n\t\t\t\tvar style = thisNode.getAttribute(\"style\");\n\t\t\t\tif(regRes[0]!==''){\n\t\t\t\t\tvar spanPre =document.createElement(\"span\");\n\t\t\t\t\tspanPre.setAttribute(\"data-medit\",\"true\");\n\t\t\t\t\tspanPre.setAttribute(\"data-meditMode\",\"text\");\n\t\t\t\t\tspanPre.setAttribute(\"id\",\"medit-\" + thisId + \"-\" + meditId );\n\t\t\t\t\tspanPre.setAttribute(\"style\",style);\n\t\t\t\t\tspanPre.innerHTML = regRes[0];\n\t\t\t\t\tthisNode.parentNode.insertBefore(spanPre, thisNode);\n\t\t\t\t\tthisId++;\n\t\t\t\t}\n\t\t\t\tif(regRes[2]!==''){\n\t\t\t\t\tthisNode.innerHTML = regRes[2];\n\t\t\t\t\tvar span =document.createElement(\"span\");\n\t\t\t\t\tspan.setAttribute(\"data-medit\",\"true\");\n\t\t\t\t\tspan.setAttribute(\"data-meditMode\",\"text\");\n\t\t\t\t\tspan.setAttribute(\"id\",\"medit-\" + thisId + \"-\" + meditId );\n\t\t\t\t\tspan.setAttribute(\"contentEditable\",\"true\");\n\t\t\t\t\tspan.setAttribute(\"class\",\"medit-editing\");\n\t\t\t\t\tspan.setAttribute(\"style\",style);\n\t\t\t\t\tspan.innerHTML = regRes[1];\n\t\t\t\t\tthis.blur(thisNode);\n\t\t\t\t\tthisNode.parentNode.insertBefore(span, thisNode);\n\t\t\t\t\tnewNode = thisNode.previousSibling;\n\t\t\t\t}else{\n\t\t\t\t\tthisNode.innerHTML = regRes[1];\n\t\t\t\t\tnewNode = thisNode;\n\t\t\t\t}\n\t\t\t\tcontain.updateId();\n\t\t\t\tcontain.nowNodeId = thisId;\n\t\t\t\tnodeFocus(newNode);\n\t\t\t}else{\n\t\t\t\tnewNode = thisNode;\n\t\t\t}\n\t\t\treturn newNode;\n\t\t}\n\t},\n\t\"br\":{\n\t\ticon:  meditToolImage + 'images/mode/br.png',\n\t\tdoWhat: function(node) {\n\t\t\tmode[node.getAttribute(\"data-meditmode\")].blur(node);\n\t\t\tvar temNode = document.createElement(\"span\");\n\t\t\ttemNode.style.display = \"block\";\n\t\t\ttemNode.innerHTML = \" \";\n\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\ttemNode.setAttribute(\"data-meditmode\", \"br\");\n\t\t\tnode.parentNode.insertBefore(temNode,node);\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tmode[\"br\"].focus(temNode);\n\t\t\tnodeFocus(temNode);\n\t\t\tnowNode = temNode;\n\t\t\ttoolBarModeSetting(\"br\",[]);\n\t\t\tcontainer[meditId].updateId();\n\t\t\tnowMode = \"br\";\n\t\t},\n\t\tfocus:function(node) {\n\t\t\tnode.style.backgroundColor = \"#e5e5e5\";\n\t\t},\n\t\tblur:function(node) {\n\t\t\tnode.style.backgroundColor = \"\";\n\t\t}\n\t},\n\t\"link\":{\n\t\ticon:  meditToolImage + 'images/mode/link.png',\n\t\tdoWhat: function(node) {\n\t\t\t\n\t\t\tvar parent = node;\n\t\t\twhile(parent.parentNode.getAttribute(\"data-medit\")){\n\t\t\t\tparent = parent.parentNode;\n\t\t\t}\n\t\t\tif(parent.nodeName.toLowerCase() == \"a\"){\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar linkNode = document.createElement(\"a\");\n\t\t\tlinkNode.setAttribute(\"data-medit\",\"true\");\n\t\t\tlinkNode.setAttribute(\"data-meditmode\",\"link\");\n\t\t\tmode[node.getAttribute(\"data-meditmode\")].blur(node);\n\t\t\tnode.parentNode.insertBefore(linkNode,node);\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tlinkNode.appendChild(node);\n\t\t\ttoolBarModeSetting(\"link\",mode['link'].setting);\n\t\t\tmode[\"link\"].focus(linkNode);\n\t\t\tcontainer[meditId].updateId();\n\t\t\tcontainer[meditId].nowNodeId = regNodeId.exec(linkNode.getAttribute(\"id\"))[1];\n\t\t\tnowMode = \"link\";\n\t\t\tclearTimeout(nodeFocusTimeout);\n\t\t\tnowNode = linkNode;\n\t\t},\n\t\tsetting: [\n\t\t\t{\n\t\t\t\tname: \"setting\",\n\t\t\t\ticon:  meditToolImage + \"images/link/setting.png\",\n\t\t\t\tdoWhat: function(node){\n\t\t\t\t\tvar href = node.getAttribute(\"data-meditHref\");\n\t\t\t\t\tvar hrefHtml = '';\n\t\t\t\t\tif(href){\n\t\t\t\t\t\threfHtml = ' value=\"'+href+'\"';\n\t\t\t\t\t}\n\t\t\t\t\tvar target = node.getAttribute(\"target\");\n\t\t\t\t\tif(target && target != \"_blank\"){\n\t\t\t\t\t\ttarget = \"\";\n\t\t\t\t\t}else{\n\t\t\t\t\t\ttarget = \" checked\";\n\t\t\t\t\t}\n\n\t\t\t\t\tvar html = '<input type=\"text\" id=\"medit-settingPage-input-link\"'+hrefHtml+' placeholder=\"链接地址 Link Address\"/><label><input type=\"checkbox\" id=\"medit-settingPage-check-link\"'+target+'><span>新窗口打开 Open in a new window</span></label>';\n\t\t\t\t\tsettingPageDisplay('超链接设置 Link Setting',html,function(){\n\t\t\t\t\t\tvar href = getNodeById(\"medit-settingPage-input-link\");\n\t\t\t\t\t\tif(href){\n\t\t\t\t\t\t\tnode.setAttribute(\"data-meditHref\", href.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar checkbox = getNodeById(\"medit-settingPage-check-link\");\n\t\t\t\t\t\tif(checkbox.checked){\n\t\t\t\t\t\t\tnode.setAttribute(\"target\", \"_blank\");\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tnode.removeAttribute(\"target\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsettingPage.style.display = \"none\";\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"cancellink\",\n\t\t\t\ticon:  meditToolImage + \"images/link/cancel-link.png\",\n\t\t\t\tdoWhat: function(node){\n\t\t\t\t\tvar childs = toArray(node.children);\n\t\t\t\t\tvar temNode = childs[0];\n\t\t\t\t\tvar temMode = temNode.getAttribute(\"data-meditmode\");\n\t\t\t\t\tchilds.forEach(function(child){\n\t\t\t\t\t\tnode.parentNode.insertBefore(child, node);\n\t\t\t\t\t});\n\t\t\t\t\tnode.parentNode.removeChild(node);\n\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\ttoolBarModeSetting(temMode,mode[temMode].setting);\n\t\t\t\t\tmode[temMode].focus(temNode);\n\t\t\t\t\tnowNode = temNode;\n\t\t\t\t\tnodeFocus(temNode);\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\tfocus: function(node){\n\t\t\tgetNodeById(\"medit-tool-button-mode\").style.display = \"none\";\n\t\t\tnode.setAttribute(\"class\",\"medit-link\");\n\t\t},\n\t\tblur:function(node){\n\t\t\tnode.removeAttribute(\"class\");\n\t\t}\n\t},\n\t\"image\":{\n\t\ticon:  meditToolImage + \"images/mode/image.png\",\n\t\tdoWhat:function(node){\n\t\t\tmode[node.getAttribute(\"data-meditmode\")].blur(node);\n\t\t\tvar temNode = document.createElement(\"img\");\n\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\ttemNode.setAttribute(\"data-meditmode\", \"image\");\n\t\t\ttemNode.setAttribute(\"src\", mode[\"image\"].icon);\n\t\t\ttemNode.setAttribute(\"width\",\"32\");\n\t\t\ttemNode.setAttribute(\"height\",\"32\");\n\t\t\tnode.parentNode.insertBefore(temNode,node);\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tmode[\"image\"].focus(temNode);\n\t\t\tnodeFocus(temNode);\n\t\t\tnowNode = temNode;\n\t\t\ttoolBarModeSetting(\"image\",mode[\"image\"].setting);\n\t\t\tcontainer[meditId].updateId();\n\t\t\tnowMode = \"image\";\n\t\t},\n\t\tfocus: function(node){\n\t\t\tnode.setAttribute(\"class\",\"medit-image\");\n\t\t},\n\t\tblur:function(node){\n\t\t\tnode.removeAttribute(\"class\");\n\t\t},\n\t\tsetting:[\n\t\t\t{\n\t\t\t\tname:\"setting\",\n\t\t\t\ticon: meditToolImage + \"images/image/setting.png\",\n\t\t\t\tdoWhat: function(node) {\n\t\t\t\t\tvar width = node.getAttribute(\"width\");\n\t\t\t\t\tvar height = node.getAttribute(\"height\");\n\t\t\t\t\tvar address = node.getAttribute(\"src\");\n\t\t\t\t\tvar html = '<div class=\"medit-settingPage-image-dataInfo\"><span>宽度 Width:</span><input type=\"text\" id=\"medit-settingPage-image-width\" value=\"'+width+'\"><span>高度 Height:</span><input type=\"text\" id=\"medit-settingPage-image-height\" value=\"'+height+'\"><span>图像地址 Address:</span><input type=\"text\" id=\"medit-settingPage-image-address\" value=\"'+address+'\"><div>';\n\t\t\t\t\tsettingPageDisplay('图像设置 Image Setting',html,function(){\n\t\t\t\t\t\tvar width = getNodeById(\"medit-settingPage-image-width\").value;\n\t\t\t\t\t\tif(width && width>0){\n\t\t\t\t\t\t\tnode.setAttribute(\"width\",width);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar height = getNodeById(\"medit-settingPage-image-height\").value;\n\t\t\t\t\t\tif(height && height>0){\n\t\t\t\t\t\t\tnode.setAttribute(\"height\",height);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar newAddress = getNodeById(\"medit-settingPage-image-address\").value;\n\t\t\t\t\t\tif(address != newAddress){ // 传入网络图片需要进行宽高转换\n\t\t\t\t\t\t\tgetNodeById(\"medit-settingPage-button\").style.display = \"none\";\n\t\t\t\t\t\t\tgetNodeById(\"medit-settingPage-content\").innerHTML = \"Loading Image...\";\n\t\t\t\t\t\t\tvar newImg = new Image();\n\t\t\t\t\t\t\tnewImg.src = newAddress;\n\t\t\t\t\t\t\tnewImg.onload = function(){\n\t\t\t\t\t\t\t\tvar scale = newImg.width/ newImg.height;\n\t\t\t\t\t\t\t\tif(newImg.width>100){\n\t\t\t\t\t\t\t\t\tnewImg.width = 100;\n\t\t\t\t\t\t\t\t\tnewImg.height = 100/scale;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tsettingPage.style.display = \"none\";\n\t\t\t\t\t\t\t\tnode.setAttribute(\"src\",newAddress);\n\t\t\t\t\t\t\t\tnode.setAttribute(\"width\",newImg.width);\n\t\t\t\t\t\t\t\tnode.setAttribute(\"height\",newImg.height);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsettingPage.style.display = \"none\";\n\t\t\t\t\t\t}\t\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"biger\",\n\t\t\t\ticon:  meditToolImage + \"images/image/biger.png\",\n\t\t\t\tdoWhat: function(node){\n\t\t\t\t\tvar width = node.getAttribute(\"width\");\n\t\t\t\t\tvar height = node.getAttribute(\"height\");\n\t\t\t\t\tnode.setAttribute(\"width\",Math.ceil(width*1.1));\n\t\t\t\t\tnode.setAttribute(\"height\",Math.ceil(height*1.1));\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"smaller\",\n\t\t\t\ticon:  meditToolImage + \"images/image/smaller.png\",\n\t\t\t\tdoWhat: function(node){\n\t\t\t\t\tvar width = node.getAttribute(\"width\");\n\t\t\t\t\tvar height = node.getAttribute(\"height\");\n\t\t\t\t\tnode.setAttribute(\"width\",Math.ceil(width/1.1));\n\t\t\t\t\tnode.setAttribute(\"height\",Math.ceil(height/1.1));\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"upload\",\n\t\t\t\ticon:  meditToolImage + \"images/image/upload.png\",\n\t\t\t\tdoWhat: function(node){\n\t\t\t\t\tvar config = container[meditId].imageUpload;\n\t\t\t\t\tvar html = '<form enctype=\"multipart/form-data\" method=\"post\" id=\"medit-image-upload-form\"><input type=\"file\" name=\"'+config.name+'\" id=\"medit-image-upload-file\"/></form><div id=\"medit-image-upload-select-btn\">选择图片 Select Image</div>';\n\t\t\t\t\tsettingPageDisplay('图像上传 Image upload',html,function(){\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar files = getNodeById(\"medit-image-upload-file\");\n\t\t\t\t\t\tif(files.files.length <=0){\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar file = files.files[0];\n\t\t\t\t\t\tvar size = file.size;\n\t\t\t\t\t\tvar name = file.name;\n\t\t\t\t\t\tvar type = file.type;\n\t\t\t\t\t\tvar config = container[meditId].imageUpload;\n\t\t\t\t\t\tvar ext = {};\n\t\t\t\t\t\t\n\t\t\t\t\t\tconfig.ext && config.ext.forEach(function(v){ ext[commonImageType[v]] = true; });\n\n\t\t\t\t\t\tif(config.size == 0 || config.size>=size){\n\t\t\t\t\t\t\tif(!config.ext || ext[type]){\n\t\t\t\t\t\t\t\tvar http = getXhr();\n\t\t\t\t\t\t\t\tvar form = new FormData(getNodeById(\"medit-image-upload-form\"));\n\t\t\t\t\t\t\t\tgetNodeById(\"medit-settingPage-button\").style.display = \"none\";\n\t\t\t\t\t\t\t\tgetNodeById(\"medit-settingPage-content\").innerHTML = '<div id=\"medit-settingPage-content-img-uploading\">图片上传中 Image uploading...</div>';\n\t\t\t\t\t\t\t\thttp.upload.onprogress = function(v){\n\t\t\t\t\t\t\t\t\tvar progress = Math.floor(100*v.loaded/v.total) + \"%\";\n\t\t\t\t\t\t\t\t\tvar success = \"\";\n\t\t\t\t\t\t\t\t\tif(progress == \"100%\") success =\"上传成功，请稍后...<br />upload success,please waiting...\";\n\t\t\t\t\t\t\t\t\tgetNodeById(\"medit-settingPage-content\").innerHTML = '<div id=\"medit-settingPage-content-img-uploading\">图片上传中 Image uploading...'+ progress +'<br /><i id=\"medit-settingPage-content-img-uploading-progress\" style=\"width:' + progress + ';\"></i>'+success+'</div>';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tObject.keys(config.params).map(function(key) {\n\t\t\t\t\t\t\t\t\tform.append(key, config.params[key]);\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\thttp.open(\"POST\",config.path);\n\t\t\t\t\t\t\t\thttp.send(form);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\thttp.onreadystatechange = function(){\n\t\t\t\t\t\t\t\t\tif(http.readyState === 4){\n\t\t\t\t\t\t\t\t\t\tif(http.status === 200 || http.status>200 && http.status<400){\n\t\t\t\t\t\t\t\t\t\t\tvar res = JSON.parse(http.responseText);\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tif(res.code == \"success\"){\n\t\t\t\t\t\t\t\t\t\t\t\tconfig.success(res);\n\t\t\t\t\t\t\t\t\t\t\t\tvar scale = res.data.width/ res.data.height;\n\t\t\t\t\t\t\t\t\t\t\t\tif(res.data.width>100){\n\t\t\t\t\t\t\t\t\t\t\t\t\tres.data.width = 100;\n\t\t\t\t\t\t\t\t\t\t\t\t\tres.data.height = 100/scale;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tsettingPage.style.display = \"none\";\n\t\t\t\t\t\t\t\t\t\t\t\tnode.setAttribute(\"src\",res.data.url);\n\t\t\t\t\t\t\t\t\t\t\t\tnode.setAttribute(\"width\",res.data.width);\n\t\t\t\t\t\t\t\t\t\t\t\tnode.setAttribute(\"height\",res.data.height);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\t\t\tconfig.error(\"http status \" + http.status);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}else{ config.error(\"image type limit \"+config.ext.join(\",\")); }\n\t\t\t\t\t\t}else{ config.error(\"image size limit \"+config.size); }\n\t\t\t\t\t});\n\t\t\t\t\tgetNodeById(\"medit-settingPage-button-ok\").innerHTML = \"上传 Upload\";\n\t\t\t\t\tvar btn = getNodeById(\"medit-image-upload-select-btn\");\n\t\t\t\t\tvar fileInput = getNodeById(\"medit-image-upload-file\");\n\t\t\t\t\t\n\t\t\t\t\tbtn.onclick = function(){\n\t\t\t\t\t\tfileInput.click();\n\t\t\t\t\t}\n\t\t\t\t\tfileInput.onchange = function(e){\n\t\t\t\t\t\t\n\t\t\t\t\t\te = e || window.event;\n\t\t\t\t\t\tvar files=e.target.files||e.srcElement.files;\n\t\t\t\t\t\tvar file = files[0];\n\t\t\t\t\t\tvar size = file.size;\n\t\t\t\t\t\tvar name = file.name;\n\t\t\t\t\t\tvar type = file.type;\n\n\t\t\t\t\t\tvar ext = {};\n\t\t\t\t\t\tconfig.ext && config.ext.forEach(function(v){ ext[commonImageType[v]] = true; });\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (config.size == 0 || config.size>=size){\n\t\t\t\t\t\t\tif (!config.ext || ext[type]){ \n\t\t\t\t\t\t\t\tbtn.innerHTML = name;\n\t\t\t\t\t\t\t} else { \n\t\t\t\t\t\t\t\tconfig.error(\"image type limit \"+config.ext.join(\",\")); \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else { \n\t\t\t\t\t\t\tconfig.error(\"image size limit \"+config.size); \n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'verticalAlign',\n\t\t\t\ticon:  meditToolImage + 'images/image/vertical-align.png',\n\t\t\t\tdoWhat:[\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'top',\n\t\t\t\t\t\ticon:  meditToolImage + 'images/image/top-align.png',\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.verticalAlign = \"top\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'middle',\n\t\t\t\t\t\ticon:  meditToolImage + 'images/image/middle-align.png',\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.verticalAlign = \"middle\";\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'bottom',\n\t\t\t\t\t\ticon:  meditToolImage + 'images/image/bottom-align.png',\n\t\t\t\t\t\tdoWhat:function(node){\n\t\t\t\t\t\t\tnode.style.verticalAlign = \"bottom\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t},\n\t\"list\":{\n\t\temptyNotDelete: true,\n\t\ticon:  meditToolImage + \"images/mode/list.png\",\n\t\tfocus:function(node){\n\t\t\tnode.setAttribute(\"class\",\"medit-list\");\n\t\t\tgetNodeById(\"medit-tool-button-mode\").style.display = \"none\";\n\t\t},\n\t\tblur:function(node){\n\t\t\tnode.removeAttribute(\"class\");\n\t\t},\n\t\tdoWhat:function(node){\n\t\t\tmode[node.getAttribute(\"data-meditmode\")].blur(node);\n\t\t\tvar temNode = document.createElement(\"ul\");\n\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\ttemNode.setAttribute(\"data-meditmode\", \"list\");\n\t\t\ttemNode.setAttribute(\"type\", \"disc\");\n\t\t\tnode.parentNode.insertBefore(temNode,node);\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tnodeFocus(temNode);\n\t\t\tnowNode = temNode;\n\t\t\ttoolBarModeSetting(\"list\",mode[\"list\"].setting);\n\t\t\tmode[\"list\"].focus(temNode);\n\t\t\tcontainer[meditId].updateId();\n\t\t\tnowMode = \"list\";\n\t\t},\n\t\tsetting:[\n\t\t\t{\n\t\t\t\tname:\"setting\",\n\t\t\t\ticon: meditToolImage + \"images/list/setting.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tvar type = node.getAttribute(\"type\").toLowerCase();\n\t\t\t\t\tvar nodeType = node.nodeName.toLowerCase();\n\t\t\t\t\tvar html = '<div class=\"medit-list-mode-style-innerTitle\">无序列表 Unorder List：</div>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ul\" value=\"disc\" name=\"medit-list-mode-style\"'+(type==\"disc\"?\" checked\":\"\")+'><span>disc 实心圆</span></label>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ul\" value=\"circle\" name=\"medit-list-mode-style\"'+(type==\"circle\"?\" checked\":\"\")+'><span>circle 空心圆</span></label>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ul\" value=\"square\" name=\"medit-list-mode-style\"'+(type==\"square\"?\" checked\":\"\")+'><span>square 实心方块</span></label>'+\n\t\t\t\t\t\t'<div class=\"medit-list-mode-style-innerTitle\">有序列表 Order List：</div>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ol\" value=\"1\" name=\"medit-list-mode-style\"'+(type==\"1\"?\" checked\":\"\")+'><span>1、2、3、4</span></label>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ol\" value=\"a\" name=\"medit-list-mode-style\"'+(type==\"a\"?\" checked\":\"\")+'><span>a、b、c、d</span></label>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ol\" value=\"A\" name=\"medit-list-mode-style\"'+(type==\"A\"?\" checked\":\"\")+'><span>A、B、C、D</span></label>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" value=\"i\" class=\"medit-list-mode-style-ol\" name=\"medit-list-mode-style\"'+(type==\"i\"?\" checked\":\"\")+'><span>i, ii, iii, iv</span></label>'+\n\t\t\t\t\t\t'<label><input type=\"radio\" class=\"medit-list-mode-style-ol\" value=\"I\" name=\"medit-list-mode-style\"'+(type==\"I\"?\" checked\":\"\")+'><span>I, II, III, IV</span></label>';\n\t\t\t\t\tsettingPageDisplay('列表类型 List Mode',html,function(){\n\t\t\t\t\t\tvar radio = getNodeById(\"medit-settingPage-content\").getElementsByTagName(\"input\");\n\t\t\t\t\t\tvar input = null;\n\t\t\t\t\t\tfor(var i = 0; i<radio.length; i++){\n\t\t\t\t\t\t\tif(radio[i].checked){\n\t\t\t\t\t\t\t\tinput = radio[i];\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar newType = input.getAttribute(\"class\").split(\"-\").pop();\n\t\t\t\t\t\tif(nodeType == newType){\n\t\t\t\t\t\t\tnode.setAttribute(\"type\",input.value);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tvar temNode = document.createElement(newType);\n\t\t\t\t\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\t\t\t\t\ttemNode.setAttribute(\"data-meditmode\", \"list\");\n\t\t\t\t\t\t\ttemNode.setAttribute(\"type\", input.value);\n\t\t\t\t\t\t\tnode.parentNode.insertBefore(temNode,node);\n\t\t\t\t\t\t\tvar childNode = toArray(node.children);\n\t\t\t\t\t\t\tchildNode.forEach(function(v){\n\t\t\t\t\t\t\t\ttemNode.appendChild(v);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tnode.parentNode.removeChild(node);\n\t\t\t\t\t\t\tnodeFocus(temNode);\n\t\t\t\t\t\t\tnowNode = temNode;\n\t\t\t\t\t\t\tmode[\"list\"].focus(temNode);\n\t\t\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsettingPage.style.display = \"none\";\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:\"newLi\",\n\t\t\t\ticon: meditToolImage + \"images/list/newLi.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tmode[\"list\"].blur(node);\n\t\t\t\t\tvar temNode = document.createElement(\"li\");\n\t\t\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\t\t\ttemNode.setAttribute(\"data-meditmode\", \"li\"); \n\t\t\t\t\tnode.appendChild(temNode);\n\t\t\t\t\t\n\t\t\t\t\tnodeFocus(temNode);\n\t\t\t\t\tnowNode = temNode;\n\t\t\t\t\ttoolBarModeSetting(\"li\",mode[\"li\"].setting);\n\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\tnowMode = \"li\";\n\t\t\t\t\tmode[\"li\"].focus(temNode);\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t},\n\t\"li\":{\n\t\tnotDisplay:true,\n\t\temptyNotDelete: true,\n\t\tfocus:function(node){\n\t\t\tnode.setAttribute(\"class\",\"medit-list\");\n\t\t\tif(!node.children.length){\n\t\t\t\tnode.setAttribute(\"contentEditable\",true);\n\t\t\t}\n\t\t\tgetNodeById(\"medit-tool-button-mode\").style.display = \"none\";\n\t\t\tgetNodeById(\"medit-tool-button-addLeft\").style.display = \"none\";\n\t\t\tgetNodeById(\"medit-tool-button-addRight\").style.display = \"none\";\n\t\t},\n\t\tblur:function(node){\n\t\t\tnode.removeAttribute(\"class\");\n\t\t\tnode.removeAttribute(\"contentEditable\");\n\t\t\tif(!node.children.length){\n\t\t\t\tif(!/^\\s*$/.test(node.innerHTML.replace(/&nbsp;/g,\"\"))){\n\n\t\t\t\t\tvar span =document.createElement(\"span\");\n\t\t\t\t\tspan.setAttribute(\"data-medit\",\"true\");\n\t\t\t\t\tspan.setAttribute(\"data-meditMode\",\"text\");\n\t\t\t\t\tspan.innerHTML = node.innerHTML;\n\t\t\t\t\tnode.innerHTML = \"\";\n\t\t\t\t\tnode.appendChild(span);\n\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\tcontainer[meditId].nowNodeId++;\n\t\t\t\t\treturn span;\n\t\t\t\t}else{\n\t\t\t\t\tnode.innerHTML = \"\";\n\t\t\t\t\treturn {exit:true};\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsetting:[\n\t\t\t{\n\t\t\t\tname:\"addLeft\",\n\t\t\t\ticon: meditToolImage + \"images/list/add-top.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tmode[\"list\"].blur(node);\n\t\t\t\t\tvar temNode = document.createElement(\"li\");\n\t\t\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\t\t\ttemNode.setAttribute(\"data-meditmode\", \"li\"); \n\t\t\t\t\tnode.parentNode.insertBefore(temNode, node);\n\t\t\t\t\tnodeFocus(temNode);\n\t\t\t\t\tnowNode = temNode;\n\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\tmode[\"li\"].focus(temNode);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname:\"addRight\",\n\t\t\t\ticon: meditToolImage + \"images/list/add-bottom.png\",\n\t\t\t\tdoWhat:function(node){\n\t\t\t\t\tmode[\"list\"].blur(node);\n\t\t\t\t\tvar temNode = document.createElement(\"li\");\n\t\t\t\t\ttemNode.setAttribute(\"data-medit\", \"true\");\n\t\t\t\t\ttemNode.setAttribute(\"data-meditmode\", \"li\"); \n\t\t\t\t\tif(node.nextSibling){\n\t\t\t\t\t\tnode.parentNode.insertBefore(temNode, node.nextSibling);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tnode.parentNode.appendChild(temNode);\n\t\t\t\t\t}\n\t\t\t\t\tnodeFocus(temNode);\n\t\t\t\t\tnowNode = temNode;\n\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\tmode[\"li\"].focus(temNode);\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n\nvar isType = function(ele, type){ // 输入一个对象和一个type值，返回这个对象是不是这种type\n\tif(!ele || !type)return false;\n\treturn {}.toString.call(ele).slice(8, -1).toLowerCase() === type.toLowerCase();\n}\n\nvar mergeStyleIsSimilar = function(styleA, styleB){ // 判断合并的两个模块样式是否相同\n\tif(styleA){\n\t\tstyleA = styleA.replace(regNormalStyle, \"\");\n\t}\n\tif(styleB){\n\t\tstyleB = styleB.replace(regNormalStyle, \"\");\n\t}\n\tif(!styleA && !styleB) return true;\n\tif(styleA && !styleB || !styleA && styleB) return false;\n\t\n\tvar styleArrA = styleA.split(\";\").sort();\n\tvar styleArrB = styleB.split(\";\").sort();\n\n\tif(styleArrA.length != styleArrB.length) return false;\n\t\n\tfor(var i=0;i<styleArrA.length;i++){\n\t\tif(styleArrA[i]!==styleArrB[i])return false;\n\t}\n\treturn true;\n}\n\nvar mergeSimilarNextNode = function(node, notFocus){ // 向后合并相似模块结点\n\tvar nowMode = node.getAttribute(\"data-meditMode\");\n\tvar nowStyle = node.getAttribute(\"style\");\n\tvar nextNode = node.nextSibling;\n\tif(!nextNode){\n\t\tif(!notFocus)nodeFocus(node);\n\t\treturn node;\n\t}\n\tvar nextMode = nextNode.getAttribute(\"data-meditMode\");\n\tif(nowMode==nextMode && nextNode && mode[nowMode].isMerge){\n\t\tvar nodeMode = nextNode.getAttribute(\"data-meditMode\");\n\t\tvar nextStyle = nextNode.getAttribute(\"style\");\n\t\tif(mergeStyleIsSimilar(nowStyle, nextStyle) && !!node.innerHTML && !!nextNode.innerHTML){\n\t\t\tnode.innerHTML = node.innerHTML + nextNode.innerHTML;\n\t\t\tnode.parentNode.removeChild(nextNode);\n\t\t\tcontainer[meditId].updateId();\n\t\t\tif(!notFocus)nodeFocus(node);\n\t\t\tif(node.nextSibling){\n\t\t\t\treturn mergeSimilarNextNode(node);\n\t\t\t}\n\t\t}\n\t}\n\treturn node;\n}\n \nvar mergeSimilarPreNode = function(node, notFocus){ // 向前合并相似模块结点\n\t\n\tvar nowMode = node.getAttribute(\"data-meditMode\");\n\tvar nowStyle = node.getAttribute(\"style\");\n\tvar previousNode = node.previousSibling;\n\tif(!previousNode){\n\t\tif(!notFocus)nodeFocus(node);\n\t\treturn node;\n\t}\n\tvar previousMode = previousNode.getAttribute(\"data-meditMode\");\n\tif(previousMode==nowMode && previousNode && mode[nowMode].isMerge){\n\t\tvar nodeMode = previousNode.getAttribute(\"data-meditMode\");\n\t\tvar previousStyle = previousNode.getAttribute(\"style\");\n\t\tif(mergeStyleIsSimilar(nowStyle, previousStyle)){\n\t\t\tvar nowId = regNodeId.exec(previousNode.getAttribute(\"id\"))[1];\n\t\t\tpreviousNode.innerHTML = previousNode.innerHTML + node.innerHTML;\n\t\t\tpreviousNode.parentNode.removeChild(node);\n\t\t\t\n\t\t\tcontainer[meditId].updateId();\n\t\t\tif(!notFocus)nodeFocus(previousNode);\n\t\t\tnode = previousNode;\n\t\t\tif(node.previousSibling){\n\t\t\t\treturn mergeSimilarPreNode(node, notFocus);\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn node;\n}\n\nvar gevent = function (ele,event,func){ // 通用事件处理模块\n\tif(isType(event, \"array\")){\n\t\tevent.forEach(function(v){\n\t\t\tgevent(ele, v, func);\n\t\t});\n\t}else{\n\t\tif(window.addEventListener){\n\t\t\tele.addEventListener(event,func,false);\n\t\t}else if(window.attachEvent){\n\t\t\tele.attachEvent(\"on\"+event,func);\n\t\t}else{\n\t\t\tele[\"on\"+event]=func;\n\t\t}\n\t}\n}\n\nvar initFromData = function(target){ // 如果原来容器内有数据的话，那么根据原来数据进行初始化\n\n\tvar contain = target.parentNode;\t// 获取容器对象\n\t\n\tmeditId = contain.getAttribute(\"data-meditid\"); // 获取容器 meditID\n\t\n\tcontain = container[meditId]; // 由于所有容器对象均存放于container中，通过此ID进行获取\n\n\tcontain.updateId();\n}\n\nvar toolBar = (function(){\n\t\n\tvar temTool = document.createElement(\"div\");\n\ttemTool.setAttribute(\"id\",\"medit-tool\");\n\tdocument.body.appendChild(temTool);\n\t\n\tvar tool = getNodeById(\"medit-tool\");\n\t\n\n\tgevent(tool, [\"touchmove\"], function(e){\n\t\tisToolMove = true;\n\t});\n\tgevent(tool, [\"touchend\"], function(e){\n\t\tif(isToolMove){\n\t\t\tisToolMove=false;\n\t\t\treturn;\n\t\t} \n\t\te = e || window.event;\n\t\tvar target = e.target || e.srcElement;\n\t\t\n\t\tvar type = target.getAttribute(\"data-meditToolStyle\");\n\t\tif(!type) return false;\n\t\t\n\t\tvar degree = target.getAttribute(\"data-meditToolDegree\");\n\t\t\n\t\tmainDo(degree, type, target);\n\t\t\n\t});\n\t\n\treturn tool;\n\t\n})();\n\nvar settingPage = (function(){\n\tvar temSettingPage = document.createElement(\"div\");\n\ttemSettingPage.setAttribute(\"id\",\"medit-settingPage\");\n\ttemSettingPage.innerHTML = '<div id=\"medit-settingPage-main\"></div>';\n\tdocument.body.appendChild(temSettingPage);\n\t\n\tvar setingObj = getNodeById(\"medit-settingPage\");\n\t\n\tgevent(setingObj, [\"touchmove\"], function(e){\n\t\te = e || window.event;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\t\n\tgevent(setingObj, [\"touchend\"], function(e){\n\t\t\n\t\te = e || window.event;\n\t\tvar target = e.target || e.srcElement;\n\t\t\n\t\tvar targetId = target.getAttribute(\"id\");\n\t\t\n\t\tif(targetId === \"medit-settingPage-button-cancel\"){\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tsettingPageOk = null;\n\t\t\tsettingPage.style.display = \"none\";\n\t\t\treturn;\n\t\t}\n\t\tif(targetId === \"medit-settingPage-button-ok\"){\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tsettingPageOk();\n\t\t\treturn;\n\t\t}\n\t\tif(mode[nowMode].settingPage){\n\t\t\tmode[nowMode].settingPage(target);\n\t\t}\n\t\t\n\t});\n\t\n\treturn setingObj;\n})();\n\nvar settingPageOk = null;\n\nvar settingPageDisplay = function(title,content,okCallBack) {\n\n\tvar html = [];\n\thtml.push(title?'<div id=\"medit-settingPage-title\">'+title+'</div>':'');\n\thtml.push('<i id=\"medit-settingPage-button-cancel\"></i>');\n\thtml.push('<div id=\"medit-settingPage-content\">'+content+'</div>');\n\thtml.push('<div id=\"medit-settingPage-button\"><i id=\"medit-settingPage-button-ok\">确定 Ok</i></div>');\n\tgetNodeById(\"medit-settingPage-main\").innerHTML = html.join(\"\");\n\tsettingPageOk = okCallBack;\n\tsettingPage.style.display = \"block\";\n}\n\nvar mainDo = function(degree, type, target) {\n\t\t\n\t\tvar contain = container[meditId];\n\t\tvar thisNode = getNodeById(\"medit-\" + contain.nowNodeId + \"-\" + meditId); // 这里有个已经修复的bug，比如在超链接中，是在当前结点外部包了一层，那么thisNode需要更新到外层结点\n\t\t\n\t\tnowMode = thisNode.getAttribute(\"data-meditMode\");\n\t\t\n\t\tif( mode[nowMode].selected ){\n\t\t\tif(globalSelectionContent && globalSelectionContent.node == thisNode && globalSelectionContent.end!=globalSelectionContent.start ){ // 原生自带文本选择处理\n\t\t\t\tvar html = globalSelectionContent.node.innerHTML.split(\"\");\n\t\t\t\thtml.splice(globalSelectionContent.end,0,'</span>');\n\t\t\t\thtml.splice(globalSelectionContent.start,0,'<span class=\"medit-text-select\">');\n\t\t\t\tglobalSelectionContent.node.innerHTML = html.join(\"\");\n\t\t\t}\n\t\t}\n\t\tif(degree == 1) {\n\t\t\tswitch(type){\n\t\t\t\tcase 'delete':\n\t\t\t\t\tif(mode[nowMode].blur){\n\t\t\t\t\t\tmode[nowMode].blur(thisNode);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\twhile(thisNode.parentNode.getAttribute(\"data-medit\") && thisNode.parentNode.children.length === 1 && !mode[thisNode.parentNode.getAttribute(\"data-meditMode\")].emptyNotDelete){\n\t\t\t\t\t\tthisNode = thisNode.parentNode;\n\t\t\t\t\t}\n\t\t\t\t\tthisNode.parentNode.removeChild(thisNode);\n\t\t\t\t\tcontain.updateId();\n\t\t\t\t\ttoolBarHidden();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ok':\n\t\t\t\t\tif(mode[nowMode].blur){\n\t\t\t\t\t\tmode[nowMode].blur(thisNode);\n\t\t\t\t\t}\n\n\t\t\t\t\tif(mode[nowMode].empty && mode[nowMode].empty(thisNode)) thisNode.parentNode.removeChild(thisNode);\n\t\t\t\t\ttoolBarHidden();\n\t\t\t\t\tcontain.nodeCount++;\n\t\t\t\t\t\n\t\t\t\t\tthisNode = mergeSimilarNextNode(thisNode);\n\t\t\t\t\tmergeSimilarPreNode(thisNode);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'addLeft':\n\t\t\t\t\tif(mode[nowMode].empty && mode[nowMode].empty(thisNode)){\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif(mode[nowMode].blur){\n\t\t\t\t\t\tmode[nowMode].blur(thisNode);\n\t\t\t\t\t}\n\t\t\t\t\tcontain.createSpan(contain.nowNodeId, thisNode, false, true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'addRight':\n\t\t\t\t\tif(mode[nowMode].empty && mode[nowMode].empty(thisNode)){\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif(mode[nowMode].blur){\n\t\t\t\t\t\tmode[nowMode].blur(thisNode);\n\t\t\t\t\t}\n\t\t\t\t\tcontain.createSpan(contain.nowNodeId, thisNode, true, true);\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'mode':\n\t\t\t\t\tvar toolBarRes = [];\n\t\t\t\t\ttoolBarRes.push(returnButtonHtml(nowMode + \"-setting-1\"));\n\t\t\t\t\t\n\t\t\t\t\tfor(var modeType in mode){\n\t\t\t\t\t\tif(mode.hasOwnProperty(modeType) && modeType != nowMode && !mode[modeType].notDisplay){\n\t\t\t\t\t\t\tvar style = mode[modeType].icon?' style=\"background:#428bca url('+ mode[modeType].icon+') no-repeat center center;background-size: 24px;\"':'';\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\ttoolBarRes.push('<span id=\"medit-tool-button-'+modeType+'\" class=\"medit-tool-button\" data-meditToolStyle=\"'+modeType+'\"'+style+' data-meditToolDegree=\"2\">&nbsp;</span>');\n\t\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\ttoolBar.innerHTML = toolBarRes.join(\"\");\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase 'return':\n\t\t\t\t\tvar path = target.getAttribute(\"id\").replace(\"medit-tool-button-\",\"\");\n\t\t\t\t\tvar nodePath = path.split(\"-\");\n\t\t\t\t\tvar doWhat = mode;\n\t\t\t\t\tvar pathMode = null;\n\n\t\t\t\t\tnodePath.pop();\n\t\t\t\t\tpath = path.replace(/\\-[a-zA-Z]*\\-\\d*$/,'');\n\n\t\t\t\t\twhile(pathMode = nodePath.shift()){\n\t\t\t\t\t\tdoWhat = doWhat[pathMode];\n\t\t\t\t\t}\n\t\t\t\t\ttoolBarModeSetting(path, doWhat);\n\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}else{\n\t\t\t\n\t\t\tif( mode[nowMode].selected ){\n\t\t\t\tthisNode = mode[nowMode].selected(thisNode);\n\t\t\t}\n\t\t\t\n\t\t\tvar pathRes =  target.getAttribute(\"id\").replace(\"medit-tool-button-\",\"\");\n\n\t\t\tvar pathArr = pathRes.split(\"-\");\n\t\t\t\n\t\t\tvar pathMode = null;\n\t\t\t\n\t\t\tvar doWhat = mode;\n\t\t\t\n\t\t\twhile(pathMode = pathArr.shift()){\n\t\t\t\tdoWhat = doWhat[pathMode];\n\t\t\t}\n\t\t\t\n\t\t\tdoWhat = doWhat.doWhat;\n\t\t\tif(isType(doWhat, \"array\")){\n\t\t\t\ttoolBarModeSetting(pathRes, doWhat);\n\t\t\t}else{\n\t\t\t\tdoWhat(thisNode);\n\t\t\t}\n\t\t}\n\n\t\tif(!contain.node.children.length) contain.node.innerHTML = contain.preHTML || \"Medit\";\n}\n\nvar toolBarModeSetting = function(path, list){\n\n\tvar pathRes = path.split(\"-\");\n\t\n\tvar toolBarRes = [];\n\t\n\tif(pathRes.length === 1){\n\t\t\n\t\tmainButton.forEach(function(v,index){\n\n\t\t\tif(v === \"setting\"){\n\t\t\t\tif(list){\n\t\t\t\t\tlist.forEach(function(listv, listIndex){\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar defaultValue = listv.defaultValue || \"&nbsp;\";\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar style = listv.icon?' style=\"background:#428bca url('+listv.icon+') no-repeat center center;background-size: 24px;\"':'';\n\t\t\t\t\t\t\n\t\t\t\t\t\ttoolBarRes.push('<span id=\"medit-tool-button-'+path+'-setting-'+listIndex+'\" class=\"medit-tool-button\" data-meditToolStyle=\"'+path+\"-setting-\"+listIndex+'\"'+style+' data-meditToolDegree=\"2\">'+defaultValue+'</span>');\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\ttoolBarRes.push('<span id=\"medit-tool-button-'+v+'\" class=\"medit-tool-button medit-tool-'+v+'\" data-meditToolStyle=\"'+v+'\" data-meditToolDegree=\"1\">&nbsp;</span>');\n\t\t\t}\n\t\t});\n\t\t\n\t}else{\n\t\ttoolBarRes.push(returnButtonHtml(path));\n\t\tif(!!list.length){\n\t\t\tlist.forEach(function(listv, listIndex){\n\t\t\t\t\t\t\n\t\t\t\tvar defaultValue = listv.defaultValue || \"&nbsp;\";\n\t\t\t\t\t\t\n\t\t\t\tvar style = listv.icon?' style=\"background:#428bca url('+listv.icon+') no-repeat center center;background-size: 24px;\"':' style=\"background:#428bca;\"';\n\t\t\t\t\t\t\n\t\t\t\ttoolBarRes.push('<span id=\"medit-tool-button-'+path+'-doWhat-'+listIndex+'\" class=\"medit-tool-button\" data-meditToolStyle=\"'+path+\"-doWhat-\"+listIndex+'\"'+style+' data-meditToolDegree=\"2\">'+defaultValue+'</span>');\n\t\t\t});\n\t\t}\n\t}\n\t\n\ttoolBar.innerHTML = toolBarRes.join(\"\");\n\t\n}\n\nvar toolBarDisplay = function() {\n\tif(toolBarCatch)\n\t\ttoolBar.innerHTML = toolBarCatch;\n\ttoolBar.style.display = \"block\";\n}\n\nvar toolBarHidden = function() {\n\tnowNode = null;\n\ttoolBar.style.display = \"none\";\n}\n\nvar toBr = function(node){\n\tnode.setAttribute(\"style\",\"display:block\");\n\tnode.setAttribute(\"data-meditMode\",\"br\");\n\tnode.setAttribute(\"contentEditable\",\"false\");\n\tnode.setAttribute(\"class\",\"\");\n\tnode.innerHTML = \" \";\n}\n\nvar nodeFocus = function(node){ // 使模块自动获取焦点 使用了很多方法，最后发现这个方法是在移动端最好的\n\tnodeFocusTimeout = setTimeout(function() {\n\t\tnode.focus();\n\t\tcontainer[meditId].nowNodeId = regNodeId.exec(node.getAttribute(\"id\"))[1];\n\t}, 10);\n}\n\nvar selectModeContent = function(isAdd){\n\tif(nowNode){\n\t\tvar nodeMode = nowNode.getAttribute(\"data-meditmode\");\n\t\tvar nodeModeObj = mode[nodeMode];\n\t\tif(nodeModeObj.selecting){\n\t\t\tnodeModeObj.selecting(nowNode, isAdd);\n\t\t}\n\t}\n}\n\t\nvar medit = function(node, toolBarContainer) {\n\tif(!(this instanceof medit)) return new medit(node, toolBarContainer);\n\t\n\tif(!node || node.nodeType != 1)return false;\n\t\n\tif(toolBarContainer && toolBarContainer.nodeType == 1) {\n\t\ttoolBar.parentNode.removeChild(toolBar);\n\t\ttoolBar.setAttribute(\"class\", \"medit-tool-inner\");\n\t\ttoolBarContainer.appendChild(toolBar);\n\t}\n\t\n\tthis.node = node;\n\tthis.nodeCount = 0; // 容器所有子元素数目\n\tthis.nowNodeId = 0;\t// 容器当前子元素ID\n\t\n\tthis.getContent = medit.prototype.getContent;\n\t\n\tthis.node.setAttribute(\"data-meditId\",container.length);\n\t\n\tthis.imageUpload = { // 默认图片上传设置，由于是文件上传，所以在跨域方法仅支持CORS\n\t\tpath:'https://sm.ms/api/upload',\n\t\tparams: {},\n\t\tname:'smfile',\n\t\tsize:0,\n\t\ttimeout:0,\n\t\text:[\"jpg\",\"jpeg\",\"png\",\"gif\",\"bmp\"],\n\t\tsuccess:function(){},\n\t\terror:function(){}\n\t}\n\t\n\tcontainer.push(this);\n\n\tgevent(this.node, [\"touchstart\"], function(e){\n\t\tmainTouchPoint = e.targetTouches[0];\n\t\t\n\t\tif(window.getSelection){ // 原生手势长按选择\n\t\t\tif(globalSelectionHandle)clearTimeout(globalSelectionHandle);\n\t\t\tvar selectionHandle = window.getSelection();\n\t\t\tvar selectionCheckTimeout = function(){\n\t\t\t\tif(selectionHandle && selectionHandle.anchorNode && selectionHandle.anchorNode == selectionHandle.focusNode && selectionHandle.anchorNode.parentNode==nowNode){\n\t\t\t\t\tglobalSelectionContent = {\n\t\t\t\t\t\thandle: selectionHandle,\n\t\t\t\t\t\tnode: selectionHandle.anchorNode.parentNode,\n\t\t\t\t\t\tstart: selectionHandle.anchorOffset<selectionHandle.focusOffset?selectionHandle.anchorOffset:selectionHandle.focusOffset,\n\t\t\t\t\t\tend: selectionHandle.anchorOffset>selectionHandle.focusOffset?selectionHandle.anchorOffset:selectionHandle.focusOffset\n\t\t\t\t\t}\n\t\t\t\t\tglobalSelectionHandle = setTimeout(selectionCheckTimeout, 100);\n\t\t\t\t}else{\n\t\t\t\t\tif(globalSelectionContent){\n\t\t\t\t\t\tglobalSelectionContent.handle.removeAllRanges();\n\t\t\t\t\t\tglobalSelectionContent = null;\n\t\t\t\t\t}\n\t\t\t\t\tif(globalSelectionHandle)clearTimeout(globalSelectionHandle);\n\t\t\t\t}\t\n\t\t\t}\n\t\t\tselectionCheckTimeout();\n\t\t}\n\t});\n\t\n\tgevent(this.node, [\"touchmove\"], function(e){\n\t\n\t\te = e || window.event;\n\t\tvar distance = e.targetTouches[0].clientX - mainTouchPoint.clientX;\n\t\t\n\t\tif(Math.abs(distance) > 50){\n\t\t\tvar isAdd = distance > 0? true: false; \n\t\t\tselectModeContent(isAdd);\n\t\t\tmainTouchPoint = e.targetTouches[0];\n\t\t}\n\t\tisContainMove = true;\n\t});\n\tgevent(this.node, [\"touchend\"], this.editContainFocus);\n\t\n\tgevent(this.node, [\"keydown\"], function(e){\n\t\te = e || window.event;\n\t\tif(e.keyCode == 13){\n\t\t\te.preventDefault();\n\t\t\tvar contain = container[meditId];\n\t\t\tvar thisNode = getNodeById(\"medit-\" + contain.nowNodeId + \"-\" + meditId);\n\t\t\tnowMode = thisNode.getAttribute(\"data-meditMode\");\n\t\t\tif(mode[nowMode].blur){\n\t\t\t\tvar newNode = mode[nowMode].blur(thisNode); // 如果当前按下回车按钮的块需要对内容进行处理，或者是结点进行改变了\n\t\t\t\tif(newNode){\n\t\t\t\t\tif(newNode.exit) return; // 不需要继续创建新的结点了\n\t\t\t\t\tthisNode = newNode;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontain.createSpan(contain.nowNodeId, thisNode, true, true);\n\t\t\t\t\t\n\t\t\tvar brNode = getNodeById(\"medit-\" + contain.nowNodeId + \"-\" + meditId);\n\t\t\ttoBr(brNode);\n\t\t\t\t\t\n\t\t\tcontain.createSpan(contain.nowNodeId, brNode, true, true);\n\t\t}\n\t});\n}\n\nvar returnNextNodeId = function(node){\n\tvar child = node.children;\n\tif(child.length) return returnNextNodeId(child[child.length-1]);\n\treturn Number(regNodeId.exec(node.getAttribute(\"id\"))[1])+1;\n}\n\nmedit.prototype.createSpan = function(nodeId, fromNode, isAfter, isAutoFocus){ // 因为在内部创建span的时候不会自动focus，需要调用一下focus方法\n\t\n\tvar span =document.createElement(\"span\");\n\tspan.setAttribute(\"data-medit\",\"true\");\n\tspan.setAttribute(\"data-meditMode\",\"text\");\n\tspan.setAttribute(\"id\",\"medit-\" + nodeId + \"-\" + meditId );\n\tspan.setAttribute(\"contentEditable\",\"true\");\n\tspan.setAttribute(\"class\",\"medit-editing\");\n\tif(fromNode){\n\t\tif(!isAfter){\n\t\t\tthis.nowNodeId = nodeId;\n\t\t\tfromNode.parentNode.insertBefore(span, fromNode);\n\t\t}else{\n\t\t\tthis.nowNodeId = returnNextNodeId(fromNode);\n\t\t\tif(!fromNode.nextSibling){\n\t\t\t\tfromNode.parentNode.appendChild(span);\n\t\t\t}else{\n\t\t\t\tfromNode.parentNode.insertBefore(span, fromNode.nextSibling); \n\t\t\t}\n\t\t}\n\t\tthis.updateId();\n\t}else{\n\t\tthis.node.appendChild(span);\n\t}\n\tvar editor = getNodeById(\"medit-\" + this.nowNodeId + \"-\" + meditId);\n\tif(nowNode){ // 当创建新的标签的时候把之前/之后的相似结点进行合并\n\t\tif(!isAfter){\n\t\t\tmergeSimilarNextNode(nowNode, true);\n\t\t}else{\n\t\t\tmergeSimilarPreNode(nowNode, true);\n\t\t}\n\t}\n\t\n\tthis.nowNodeId = Number(regNodeId.exec(editor.id)[1]); // 因为合并结点之后要重新更新id， 所以需要重新获取当前结点ID\n\tnowNode = editor;\n\ttoolBarModeSetting(\"text\", mode[\"text\"].setting);\n\t\n\tif(isAutoFocus){\n\t\tnodeFocus(editor);\n\t}\n}\n\nmedit.prototype.updateId = function(nodeId, list) {\n\n\tvar child = list || toArray(this.node.children);\n\tvar index = nodeId || 0;\n\tchild.forEach(function(v){\n\t\tif(v.getAttribute(\"href\")){ // 防止超链接在内部触发\n\t\t\tv.setAttribute(\"data-meditHref\",v.getAttribute(\"href\"));\n\t\t\tv.removeAttribute(\"href\");\n\t\t}\n\t\tv.setAttribute(\"id\",\"medit-\" + (index++) + \"-\" + meditId );\n\t\tvar secondChild = toArray(v.children);\n\t\tif(secondChild.length){\n\t\t\tindex = container[meditId].updateId(index, secondChild);\n\t\t}\n\t});\n\treturn index;\n}\n\nmedit.prototype.getContent = function(isEdit){\n\tisEdit = isEdit || false;\n\tif(!isEdit && toolBar.style.display == \"block\"){\n\t\tmainDo(1, \"ok\");\n\t}\n\tvar html = this.node.innerHTML;\n\tif(regIsNotContentEmpty.test(html)){\n\t\thtml = html.replace(/\\sdata\\-meditHref=\"(.*?)\"/ig,\" href=\\\"$1\\\"\");\n\t\thtml = html.replace(selectTextReg,\"$1\");\n\t\treturn html.replace(regContent, \" \");\n\t\t\n\t}\t\n\treturn \"\";\n}\n\nmedit.prototype.autoSave = function(appId, callBack){// 自动保存 callBack(data, timeStamp),自动恢复已保存数据\n\tif(window.localStorage){\n\t\tthis.appId = appId;\n\t\tvar oldData = localStorage.getItem(\"meditAutosave\"+appId); // repair bug: id is need not exits '-'\n\t\tvar temData = this.getContent(true);\n\t\tif(!regIsNotContentEmpty.test(temData) && oldData){\n\t\t\tmeditId = this.node.getAttribute(\"data-meditid\");\n\t\t\tthis.node.innerHTML = oldData;\n\t\t\tthis.updateId();\n\t\t}\n\t\t\n\t\tclearInterval(this.autoSaveInterval);\n\t\tvar _this = this;\n\t\tthis.autoSaveInterval = setInterval(function(){\n\t\t\tvar nowData = _this.getContent(true);\n\t\t\tlocalStorage.setItem(\"meditAutosave\"+appId,nowData);\n\t\t\tcallBack(nowData, (new Date())-0);\n\t\t},1000);\n\t}\n}\t\n\nmedit.prototype.image = medit.prototype.imageUpload = function(option){ // 图片上传设置\n\tvar meditId = this.node.getAttribute(\"data-meditid\") - 0;\n\tvar contain = container[meditId];\n\tfor(var item in option){\n\t\tif(contain.imageUpload[item] != null){\n\t\t\tcontain.imageUpload[item] = option[item];\n\t\t}\n\t}\n}\n\nmedit.prototype.clear = function(data){\n\tdata = data||\"\";\n\tclearInterval(this.autoSaveInterval);\n\tthis.node.innerHTML = data;\n\tif(this.appId!=null){\n\t\tlocalStorage.removeItem(\"meditAutosave\"+this.appId);\n\t}\n}\n\nmedit.prototype.editContainFocus = function(e) {\n\t\n\te = e || window.event;\n\tvar target = e.target || e.srcElement;\n\t\n\tif(isContainMove){\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tisContainMove = false;\n\t\treturn;\n\t}\n\t\n\ttoolBarDisplay();\n\n\tif(meditId != null) { // 在已经选择某个区块的时候选择其它的，会先调用这个区块的blur\n\t\tvar temObj = container[meditId];\n\t\tvar temNode = getNodeById(\"medit-\" + temObj.nowNodeId + \"-\" + meditId);\n\n\t\tif(temNode){\n\t\t\tvar temNodeMode = temNode.getAttribute(\"data-meditMode\");\n\t\t\tif(mode[temNodeMode].empty && mode[temNodeMode].empty(temNode) && temNode != target){\n\t\t\t\ttemNode.parentNode.removeChild(temNode);\n\t\t\t\ttemObj.updateId();\n\t\t\t}else{\n\t\t\t\tif(mode[temNodeMode].blur){\n\t\t\t\t\tmode[temNodeMode].blur(temNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tvar type = target.getAttribute(\"data-medit\");\n\tif(!type && target.getAttribute(\"data-meditId\")){ // target is container\n\t\tmeditId = target.getAttribute(\"data-meditId\"); // 全局存贮当前medit容器ID\n\t\tvar meditObj = container[ meditId];\n\t\tvar child = target.children;\n\t\tif(!child.length){ // 如果点击了容器发现没有结点，那么就保存原有内容，并且创建新的span\n\t\t\tmeditObj.preHTML = target.innerHTML;\n\t\t\ttarget.innerHTML = \"\";\n\t\t\t\n\t\t\tmeditObj.createSpan(0);\n\t\t\t\n\t\t\ttarget = false;\n\t\t}else{\n\t\t\tvar temTarget = child[child.length-1];\n\t\t\tvar temTargetMode = temTarget.getAttribute(\"data-meditMode\");\n\t\t\tif(!mode[temTargetMode].empty || !mode[temTargetMode].empty(temTarget)){\n\t\t\t\tmeditObj.createSpan(child.length-1,temTarget, true);\n\t\t\t\ttarget = false;\n\t\t\t}else{\n\t\t\t\ttarget = temTarget;\t\t\n\t\t\t\tnowNode = target;\n\t\t\t}\n\t\t\t\t\n\t\t}\n\t}else{ // target is 内部包含结点\n\t\twhile(!target.getAttribute(\"data-medit\")){\n\t\t\ttarget = target.parentNode;\n\t\t}\n\t\tnowNode = target;\n\t}\n\t\n\tif(target){\n\t\tif(!target.id) {\n\t\t\tvar parentNode = target.parentNode;\n\t\t\twhile(!parentNode.getAttribute(\"data-meditid\")){\n\t\t\t\tparentNode = parentNode.parentNode;\n\t\t\t}\n\t\t\tmeditId = parentNode.getAttribute(\"data-meditid\");\n\t\t\tcontainer[meditId].updateId();\n\t\t}\n\t\tvar idExecRes = regNodeId.exec(target.id);\n\t\tmeditId = Number(idExecRes[2]);\n\t\tvar meditObj = container[ meditId];\n\t\tmeditObj.nowNodeId = Number(idExecRes[1]);\t\t\n\t\t\t\n\t\tvar meditNodeMode = target.getAttribute(\"data-meditMode\");\n\t\t\n\t\ttoolBarModeSetting(meditNodeMode, mode[meditNodeMode].setting);\n\t\t\n\t\tif(mode[meditNodeMode].focus){\n\t\t\tmode[meditNodeMode].focus(target);\n\t\t}\n\t}\n}\n\nmedit.settingPage = function(title, content, callBack) {\n\tsettingPageDisplay(title, content, function(){\n\t\tcallBack();\n\t\tsettingPage.style.display = \"none\";\n\t})\n}\n\nmedit.extend = function(obj) { // 扩展方法 会向doWhat方法中传入当前结点，然后需要返回一个新的结点\n\tif(obj && obj.icon && obj.doWhat && obj.focus && obj.blur && obj.name){\n\t\tif(!mode[obj.name]){\n\t\t\tmode[obj.name] = fun_deep_clone(obj);\n\t\t\tmode[obj.name].doWhat = function(node){\n\t\t\t\tmode[node.getAttribute(\"data-meditmode\")].blur(node);\n\t\t\t\tvar newNode = obj.doWhat(node);\n\t\t\t\tif(newNode) {\n\t\t\t\t\tnewNode.setAttribute(\"data-meditmode\", obj.name);\n\t\t\t\t\tnewNode.setAttribute(\"data-medit\", \"true\");\n\t\t\t\t\tmode[obj.name].focus(newNode);\n\t\t\t\t\tnodeFocus(newNode);\n\t\t\t\t\tnowNode = newNode;\n\t\t\t\t\ttoolBarModeSetting(obj.name,obj.setting||[]);\n\t\t\t\t\tcontainer[meditId].updateId();\n\t\t\t\t\tnowMode = obj.name;\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tthrow new Error(obj.name + ' has already exist!');\n\t\t}\n\t}\n}\n\n\nmedit.nativeSetting = function(execFun){ // 原生自带功能配置接口\n\tfor(var i =0; i<nativeMode.length; i++) {\n\t\tvar res = execFun(fun_deep_clone(mode[nativeMode[i]]), nativeMode[i] );\n\t\tif(res){\n\t\t\tmode[nativeMode[i]] = res;\n\t\t}\n\t}\n}\n\t\nobj.Medit = obj.medit = medit;\n\t\nmodule.exports = medit;"
  },
  {
    "path": "test/ajaxImageUpload.html",
    "content": "<form enctype=\"multipart/form-data\" method=\"post\" name=\"fileinfo\">\n<input type=\"file\" id=\"file\" name=\"smfile\"/>\n</form>\n<script>\n\nvar xhr = function(){\n\t\tif(window.XMLHttpRequest){\n\t\t\tvar xhr=new XMLHttpRequest();\n\t\t}else{\n\t\t\ttry{\n\t\t\t\tvar xhr=new ActiveXObject(\"Msxml2.XMLHTTP\");\n\t\t\t}catch(e){\n\t\t\t\ttry{\n\t\t\t\t\tvar xhr=new ActiveXObject(\"Microsoft.XMLHTTP\");\n\t\t\t\t}catch(e){\n\t\t\t\t\tthrow new TypeError('Unsupport XMLHttpRequest');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn xhr;\n\t}\n\n\nvar fileinput = document.getElementById(\"file\");\n\nfileinput.onchange = function(e){\n\te = e || window.event;\n\t\n\tvar  files=e.target.files||e.srcElement.files;\n\tvar file = files[0];\n\tvar form = new FormData(document.forms.namedItem(\"fileinfo\"));\n\tvar http = xhr();\n\thttp.upload.onprogress = function(v){\n\t\tconsole.log(Math.floor(100*v.loaded/v.total) + \"%\");\n\t}\n\thttp.open(\"POST\",\"https://sm.ms/api/upload\");\n\t\n\thttp.send(form);\n\t\n\thttp.onreadystatechange = function(){\n\t\tif(http.readyState === 4){\n\t\t\tif(http.status === 200){\n\t\t\t\tconsole.log(JSON.parse(http.responseText))\n\t\t\t}\n\t\t}\n\t}\n}\n\n</script>"
  },
  {
    "path": "test/contentEditableFocus.html",
    "content": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no, minimal-ui\" />\n\n<style>\n#editable{\n\tdisplay:inline-block;\n\t\n\twidth:300px;\n\tborder:1px solid #ccc;\n}\n</style>\n<span id=\"editable\" contenteditable=\"true\"></span>\n<span onClick=\"contentfocus(document.getElementById('editable'))\">Focus</span>\n<script>\nfunction contentfocus(node){\n\tnode.onfocus = function() {\n    window.setTimeout(function() {\n\t\t\tvar sel, range;\n\t\t\tif (window.getSelection && document.createRange) {\n\t\t\t\trange = document.createRange();\n\t\t\t\trange.selectNodeContents(node);\n\t\t\t\trange.collapse(true);\n\t\t\t\tsel = window.getSelection();\n\t\t\t\tsel.removeAllRanges();\n\t\t\t\tsel.addRange(range);\n\t\t\t} else if (document.body.createTextRange) {\n\t\t\t\trange = document.body.createTextRange();\n\t\t\t\trange.moveToElementText(node);\n\t\t\t\trange.collapse(true);\n\t\t\t\trange.select();\n\t\t\t}\n\t\t}, 1);\n\t};\n\tnode.focus();\n}\n\t\n\n</script>"
  },
  {
    "path": "webpack.config.dev.js",
    "content": "var path = require('path')\nvar webpack = require('webpack')\nvar autoprefixer = require('autoprefixer')\nvar precss = require('precss')\nvar CopyWebpackPlugin = require('copy-webpack-plugin');\n\nmodule.exports = {\n  entry: {\n    \"medit.min\": './src/medit.js'\n  },\n  output: {\n    path: path.join(__dirname, 'build'),\n    filename: '[name].js'\n  },\n  plugins: [],\n  resolve: {\n    alias: {\n      medit: path.resolve(__dirname, 'src')\n    },\n    extensions: ['', '.js', '.jsx']\n  },\n  module: {\n    loaders: [\n      {\n        test: /\\.jsx?$/,\n        loader: 'babel',\n        include: [\n          path.resolve(__dirname, 'src')\n        ]\n      },\n\t  {\ttest   : /\\.css$/, loaders: ['style-loader', 'css-loader', 'resolve-url-loader']},\n      { test: /\\.scss$/, loaders: ['style-loader', 'css-loader?modules&localIdentName=[local]-[hash:base64:5]', 'postcss-loader', 'sass-loader'] },\n      { test: /\\.(ttf|eot|woff|woff2|otf|svg)/, loader: 'file-loader?name=./font/[name].[ext]' },\n      { test: /\\.json$/, loader: 'file-loader?name=./json/[name].json' },\n      { test: /\\.(png|jpg|jpeg|gif)$/, loader: 'url-loader?limit=100000&name=./images/[name].[ext]' }\n    ]\n  },\n  postcss: function () {\n    return [autoprefixer({ browsers: ['> 1%', 'IE 9'] }), precss]\n  },\n  plugins: [\n\t  new CopyWebpackPlugin([{context:'./src/images/', from:'**/*', to:'images'}])\n  ]\n}"
  }
]