diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index e206d70d..00000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 1162f438..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 65468647..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.idea/umeditor.iml b/.idea/umeditor.iml deleted file mode 100644 index 6b8184f8..00000000 --- a/.idea/umeditor.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index c80f2198..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/README.md b/README.md old mode 100755 new mode 100644 index f9276d49..51c75b31 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ UMeditor,简称UM,是 [ueditor](http://ueditor.baidu.com) 的简版。是为 2. **加载速度更快**: 放弃了使用传统的iframe模式,采用了div的加载方式,以达到更快的加载速度和零加载失败率。 2. **可定制**: 配置项完善,可定制程度高。 2. **可扩展**: 代码层次拆分清晰,功能以插件形式挂接,可灵活定制需要的功能。 -3. **多后台支持**: 支持php、asp、jsp、.net四种后台部署代码 +3. **多后台支持**: 支持php、asp、jsp、net四中后台部署代码 4. **功能丰富**: 支持插入公式、粘贴QQ截屏、拖放上传图片、插入地图、草稿箱功能 ## 入门部署和体验 ## diff --git a/net/getContent.ashx b/_examples/server/getContent.ashx similarity index 100% rename from net/getContent.ashx rename to _examples/server/getContent.ashx diff --git a/asp/getContent.asp b/_examples/server/getContent.asp similarity index 53% rename from asp/getContent.asp rename to _examples/server/getContent.asp index 64b1a087..dd56ab90 100644 --- a/asp/getContent.asp +++ b/_examples/server/getContent.asp @@ -1,7 +1,7 @@ <% @LANGUAGE="VBSCRIPT" CODEPAGE="65001" %> - - - + + + <% Dim content diff --git a/jsp/getContent.jsp b/_examples/server/getContent.jsp similarity index 64% rename from jsp/getContent.jsp rename to _examples/server/getContent.jsp index 6aee0c09..cd133c79 100644 --- a/jsp/getContent.jsp +++ b/_examples/server/getContent.jsp @@ -1,7 +1,7 @@ <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> - - - + + + <% request.setCharacterEncoding("utf-8"); diff --git a/php/getContent.php b/_examples/server/getContent.php similarity index 61% rename from php/getContent.php rename to _examples/server/getContent.php index 89b19724..64f3a612 100755 --- a/php/getContent.php +++ b/_examples/server/getContent.php @@ -1,6 +1,6 @@ - - - + + + ".htmlspecialchars_decode($content).""; +?> diff --git a/_examples/submitFormDemo.html b/_examples/submitFormDemo.html index e74402dd..210ac3bd 100644 --- a/_examples/submitFormDemo.html +++ b/_examples/submitFormDemo.html @@ -37,13 +37,13 @@

UMEDITOR 提交示例

form=doc.getElementById("form"); if(version.match(/php/)){ - form.action="../php/getContent.php"; + form.action="./server/getContent.php"; }else if(version.match(/net/)){ - form.action="../net/getContent.ashx"; + form.action="./server/getContent.ashx"; }else if(version.match(/jsp/)){ - form.action="../jsp/getContent.jsp"; + form.action="./server/getContent.jsp"; }else if(version.match(/asp/)){ - form.action="../asp/getContent.asp"; + form.action="./server/getContent.asp"; } diff --git a/_src/adapter/adapter.js b/_src/adapter/adapter.js index f249ac1b..fa08d972 100644 --- a/_src/adapter/adapter.js +++ b/_src/adapter/adapter.js @@ -20,7 +20,7 @@ registerUI: function (name, fn) { utils.each(name.split(/\s+/), function (uiname) { _editorUI[uiname] = fn; - }) + }); }, setEditor : function(editor){ @@ -43,7 +43,7 @@ } }, getWidgetData : function(name){ - return _widgetData[name] + return _widgetData[name]; }, setWidgetBody : function(name,$widget,editor){ if(!editor._widgetData){ @@ -56,10 +56,10 @@ getWidgetCallback : function(widgetName){ var me = this; return function(){ - return _widgetCallBack[widgetName].apply(me,[me,$widget].concat(Array.prototype.slice.call(arguments,0))) - } + return _widgetCallBack[widgetName].apply(me,[me,$widget].concat(Array.prototype.slice.call(arguments,0))); + }; } - }) + }); } var pro = _widgetData[name]; @@ -102,7 +102,7 @@ }, clearCache : function(id){ if ( _editors[id]) { - delete _editors[id] + delete _editors[id]; } }, delEditor: function (id) { @@ -131,9 +131,13 @@ }); var options = editor.options; if(options.initialFrameWidth){ - options.minFrameWidth = options.initialFrameWidth + options.minFrameWidth = options.initialFrameWidth; }else{ options.minFrameWidth = options.initialFrameWidth = editor.$body.width() || UM.defaultWidth; + var styleWidth = editor.$body[0].style.width; + if(styleWidth.match(/%$/)) { + options.initialFrameWidth = styleWidth; + } } $container.css({ @@ -151,7 +155,7 @@ $.eduitooltip && $.eduitooltip('attachTo', $("[data-original-title]",$container)).css('z-index',editor.getOpt('zIndex')+1); $container.find('a').click(function(evt){ - evt.preventDefault() + evt.preventDefault(); }); editor.fireEvent("afteruiready"); @@ -212,12 +216,12 @@ btns.length && toolbar.appendToBtnmenu(btns); }); } else { - $toolbar.find('.edui-btn-toolbar').remove() + $toolbar.find('.edui-btn-toolbar').remove(); } return $toolbar; } - }) + }); })(); diff --git a/_src/adapter/dialog.js b/_src/adapter/dialog.js index b3538c2c..abe3bc09 100644 --- a/_src/adapter/dialog.js +++ b/_src/adapter/dialog.js @@ -1,4 +1,4 @@ -UM.registerUI('link image video map formula',function(name){ +UM.registerUI('link image video map',function(name){ var me = this, currentRange, $dialog, opt = { @@ -26,8 +26,8 @@ UM.registerUI('link image video map formula',function(name){ opt.oklabel = ok.label || me.getLang('ok'); if(ok.exec){ opt.okFn = function(){ - return $.proxy(ok.exec,null,me,$dialog)() - } + return $.proxy(ok.exec,null,me,$dialog)(); + }; } } var cancel = data.buttons.cancel; @@ -35,8 +35,8 @@ UM.registerUI('link image video map formula',function(name){ opt.cancellabel = cancel.label || me.getLang('cancel'); if(cancel.exec){ opt.cancelFn = function(){ - return $.proxy(cancel.exec,null,me,$dialog)() - } + return $.proxy(cancel.exec,null,me,$dialog)(); + }; } } } @@ -51,7 +51,7 @@ UM.registerUI('link image video map formula',function(name){ $dialog.edui().on('beforehide',function () { var rng = me.selection.getRange(); if (rng.equals(currentRange)) { - rng.select() + rng.select(); } }).on('beforeshow', function () { var $root = this.root(), @@ -81,21 +81,19 @@ UM.registerUI('link image video map formula',function(name){ UM.setWidgetBody(name,$dialog,me); UM.setTopEditor(me); }).on('afterbackdrop',function(){ - this.$backdrop.css('zIndex',me.getOpt('zIndex')+1).appendTo(me.$container.find('.edui-dialog-container')) - $dialog.css('zIndex',me.getOpt('zIndex')+2) + this.$backdrop.css('zIndex',me.getOpt('zIndex')+1).appendTo(me.$container.find('.edui-dialog-container')); + $dialog.css('zIndex',me.getOpt('zIndex')+2); }).on('beforeok',function(){ try{ - currentRange.select() + currentRange.select(); }catch(e){} - }).attachTo($btn) + }).attachTo($btn); }); - - me.addListener('selectionchange', function () { var state = this.queryCommandState(name); - $btn.edui().disabled(state == -1).active(state == 1) + $btn.edui().disabled(state == -1).active(state == 1); }); return $btn; }); \ No newline at end of file diff --git a/_src/core/Editor.js b/_src/core/Editor.js index dcd095c1..42d36bb6 100755 --- a/_src/core/Editor.js +++ b/_src/core/Editor.js @@ -39,7 +39,7 @@ } textarea.value = editor.hasContents() ? (editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true)) : - '' + ''; } function loadPlugins(me){ //初始化插件 @@ -55,7 +55,7 @@ } function checkCurLang(I18N){ for(var lang in I18N){ - return lang + return lang; } } /** @@ -105,7 +105,7 @@ if(!utils.isEmptyObject(UM.I18N)){ //修改默认的语言类型 me.options.lang = checkCurLang(UM.I18N); - loadPlugins(me) + loadPlugins(me); }else{ utils.loadFile(document, { src: me.options.langPath + me.options.lang + "/" + me.options.lang + ".js", @@ -113,7 +113,7 @@ type: "text/javascript", defer: "defer" }, function () { - loadPlugins(me) + loadPlugins(me); }); } @@ -145,14 +145,14 @@ setOpt: function (key, val) { var obj = {}; if (utils.isString(key)) { - obj[key] = val + obj[key] = val; } else { obj = key; } utils.extend(this.options, obj, true); }, getOpt:function(key){ - return this.options[key] || '' + return this.options[key] || ''; }, /** * 销毁编辑器实例对象 @@ -163,16 +163,13 @@ var me = this; me.fireEvent('destroy'); - var container = me.container.parentNode; - if(container === document.body){ - container = me.container; - } + var container = me.container; var textarea = me.textarea; if (!textarea) { textarea = document.createElement('textarea'); container.parentNode.insertBefore(textarea, container); } else { - textarea.style.display = '' + textarea.style.display = ''; } textarea.style.width = me.body.offsetWidth + 'px'; @@ -248,15 +245,14 @@ container.className += ' edui-body-container'; if(options.initialFrameWidth){ - options.minFrameWidth = options.initialFrameWidth + options.minFrameWidth = options.initialFrameWidth; }else{ //都没给值,先写死了 options.minFrameWidth = options.initialFrameWidth = $(container).width() || UM.defaultWidth; } if(options.initialFrameHeight){ - options.minFrameHeight = options.initialFrameHeight + options.minFrameHeight = options.initialFrameHeight; }else{ - options.initialFrameHeight = options.minFrameHeight = $(container).height() || UM.defaultHeight; } @@ -273,7 +269,7 @@ container.style.setExpression('height', 'this.scrollHeight <= ' + height + ' ? "' + height + 'px" : "auto"'); } }else{ - $(container).height(height) + $(container).height(height); } container.style.zIndex = options.zIndex; this._setup(container); @@ -312,11 +308,11 @@ if(me.options.autoSyncData){ $(cont).on('blur',function(){ setValue(form,me); - }) + }); }else{ $(form).on('submit', function () { setValue(this, me); - }) + }); } break; } @@ -365,7 +361,8 @@ } } else { try { - me._bakRange && nSel.addRange(me._bakRange) + nSel.removeAllRanges(); + me._bakRange && nSel.addRange(me._bakRange); } catch (e) { } me._bakRange = null; @@ -392,7 +389,7 @@ var me = this, form = formId ? document.getElementById(formId) : domUtils.findParent(me.body.parentNode, function (node) { - return node.tagName == 'FORM' + return node.tagName == 'FORM'; }, true); form && setValue(form, me); }, @@ -412,7 +409,7 @@ this.container.style.setExpression('height', 'this.scrollHeight <= ' + height + ' ? "' + height + 'px" : "auto"'); } }else{ - $(this.body).height(height) + $(this.body).height(height); } this.fireEvent('resize'); }, @@ -429,11 +426,11 @@ addshortcutkey: function (cmd, keys) { var obj = {}; if (keys) { - obj[cmd] = keys + obj[cmd] = keys; } else { obj = cmd; } - utils.extend(this.shortcutkeys, obj) + utils.extend(this.shortcutkeys, obj); }, _bindshortcutKeys: function () { var me = this, shortcutkeys = this.shortcutkeys; @@ -638,7 +635,7 @@ blur:function(){ var sel = this.selection.getNative(); sel.empty ? sel.empty() : sel.removeAllRanges(); - this.fireEvent('blur') + this.fireEvent('blur'); }, /** * 判断编辑器当前是否获得了焦点 @@ -764,9 +761,9 @@ if(!this.isFocus()){ var bakRange = this.selection._bakRange; if(bakRange){ - bakRange.select() + bakRange.select(); }else{ - this.focus(true) + this.focus(true); } } @@ -790,7 +787,7 @@ me.__hasEnterExecCommand = false; } else { result = this._callCmdFn('execCommand', arguments); - (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange') + (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me.fireEvent('contentchange'); } (!me.__hasEnterExecCommand && !cmd.ignoreContentChange && !me._ignoreContentChange) && me._selectionChange(); return result; @@ -808,7 +805,7 @@ try{ return this._callCmdFn('queryCommandState', arguments); }catch(e){ - return 0 + return 0; } }, @@ -822,7 +819,7 @@ try{ return this._callCmdFn('queryCommandValue', arguments); }catch(e){ - return null + return null; } }, /** @@ -845,7 +842,7 @@ } } if (!domUtils.isEmptyBlock(this.body)) { - return true + return true; } //随时添加,定义的特殊标签如果存在,不能认为是空 tags = ['div']; @@ -884,9 +881,9 @@ range = me.selection.getRange(); try { range.moveToBookmark(me.lastBk); - delete me.lastBk + delete me.lastBk; } catch (e) { - range.setStartAtFirst(me.body).collapse(true) + range.setStartAtFirst(me.body).collapse(true); } range.select(true); } @@ -939,9 +936,7 @@ /* 备份并墙原生事件 */ if(!keepDomEvent && !me._bkproxyDomEvent) { me._bkproxyDomEvent = me._proxyDomEvent; - me._proxyDomEvent = function () { - return false; - }; + me._proxyDomEvent = function () {}; } /* 触发事件 */ @@ -974,7 +969,7 @@ setTimeout(function () { me.focus(); me._selectionChange(); - }, 0) + }, 0); } } @@ -983,7 +978,7 @@ me.body.innerHTML = '

' + cont + '

'; me.addListener('firstBeforeExecCommand focus', clear); - } + }; }(), /** * show方法的兼容版本 @@ -996,9 +991,9 @@ //有可能内容丢失了 try { range.moveToBookmark(me.lastBk); - delete me.lastBk + delete me.lastBk; } catch (e) { - range.setStartAtFirst(me.body).collapse(true) + range.setStartAtFirst(me.body).collapse(true); } //ie下focus实效,所以做了个延迟 setTimeout(function () { @@ -1026,7 +1021,7 @@ if (!me.lastBk) { me.lastBk = me.selection.getRange().createBookmark(true); } - me.container.style.display = 'none' + me.container.style.display = 'none'; }, /** * 隐藏编辑器 @@ -1082,19 +1077,19 @@ if(isUndoLoad && ci.ignoreUndo){ continue; } - ci.call(this, root) + ci.call(this, root); } }, addOutputRule: function (rule,ignoreUndo) { rule.ignoreUndo = ignoreUndo; - this.outputRules.push(rule) + this.outputRules.push(rule); }, filterOutputRule: function (root,isUndoLoad) { for (var i = 0, ci; ci = this.outputRules[i++];) { if(isUndoLoad && ci.ignoreUndo){ continue; } - ci.call(this, root) + ci.call(this, root); } } }; diff --git a/_src/core/Selection.js b/_src/core/Selection.js index 1ebbe50f..bf59ea1f 100755 --- a/_src/core/Selection.js +++ b/_src/core/Selection.js @@ -145,7 +145,7 @@ }else{ rng = _getIERange(this); } - return this.rangeInBody(rng); + return rng && this.rangeInBody(rng); }, /** * 获取原生seleciton对象 @@ -179,7 +179,7 @@ return ieRange; }, rangeInBody : function(rng,txtRange){ - var node = browser.ie9below || txtRange ? rng.item ? rng.item() : rng.parentElement() : rng.startContainer; + var node = browser.ie9below || txtRange ? rng && rng.item ? rng.item() : rng.parentElement() : rng.startContainer; return node === this.body || domUtils.inDoc(node,this.body); }, diff --git a/_src/core/domUtils.js b/_src/core/domUtils.js index ac8c1018..14ceb438 100755 --- a/_src/core/domUtils.js +++ b/_src/core/domUtils.js @@ -630,7 +630,8 @@ var domUtils = dom.domUtils = { break; case 'style': node.style.cssText = ''; - !browser.ie && node.removeAttributeNode(node.getAttributeNode('style')) + var val = node.getAttributeNode('style'); + !browser.ie && val && node.removeAttributeNode(val); } node.removeAttribute(ci); } diff --git a/_src/editor.js b/_src/editor.js index 9c165b96..8f30c2c6 100755 --- a/_src/editor.js +++ b/_src/editor.js @@ -7,7 +7,7 @@ window.UM = { I18N : {}, - version : "1.2.2" + version : "1.2.3" }; var dom = UM.dom = {}; \ No newline at end of file diff --git a/_src/plugins/autoupload.js b/_src/plugins/autoupload.js index e817ed11..70cc007f 100755 --- a/_src/plugins/autoupload.js +++ b/_src/plugins/autoupload.js @@ -45,8 +45,7 @@ UM.plugins['autoupload'] = function () { me.addListener('ready', function () { if (window.FormData && window.FileReader) { var autoUploadHandler = function (e) { - var hasImg = false, - items; + var items; //获取粘贴板文件列表或者拖放文件列表 items = e.type == 'paste' ? getPasteImage(e.originalEvent) : getDropImage(e.originalEvent); if (items) { @@ -57,10 +56,8 @@ UM.plugins['autoupload'] = function () { if (file.getAsFile) file = file.getAsFile(); if (file && file.size > 0 && /image\/\w+/i.test(file.type)) { sendAndInsertImage(file, me); - hasImg = true; } } - if (hasImg) return false; } }; @@ -70,10 +67,48 @@ UM.plugins['autoupload'] = function () { //取消拖放图片时出现的文字光标位置提示 me.$body.on('dragover', function (e) { if (e.originalEvent.dataTransfer.types[0] == 'Files') { - return false; + e.preventDefault(); } }); } }); + // 转存 base64 图片 + me.addListener('transferBase64Image', function () { + utils.each(me.document.getElementsByTagName('img'), function (img, i){ + var options = {}, base64, id; + if (base64 = getBase64ImageData(img)) { + id = img.id = 'base64img_' + (+new Date()); + options['base64'] = true; + options[me.getOpt('imageFieldName')] = base64; + $.post(me.getOpt('imageUrl'), options, function(r){ + var json = eval('('+r+')'), + $img = $('#' + id), + link; + if (json.state == 'SUCCESS' && json.url) { + link = me.getOpt('imagePath') + json.url; + $img.attr('src', link); + $img.attr('_src', link); + } + }); + } + }); + }); + + me.addListener('ready', function () { + function transferHandler(){ + setTimeout(function (){ + me.fireEvent('transferBase64Image'); + }); + } + me.$body.on('paste drop', transferHandler); + }); + + function getBase64ImageData(img){ + var src = img.src, arr; + if (src.length > 60 && (arr = src.match(/^(data:[^;]*;base64,)/))) { + return src.substring(arr[1].length); + } + } + }; \ No newline at end of file diff --git a/_src/plugins/basestyle.js b/_src/plugins/basestyle.js index 3e096135..ab849c7e 100755 --- a/_src/plugins/basestyle.js +++ b/_src/plugins/basestyle.js @@ -42,20 +42,29 @@ UM.plugins['basestyle'] = function(){ $.each(basestyles,function(i,cmd){ me.commands[cmd] = { execCommand : function( cmdName ) { - var rng = this.selection.getRange(); - if(rng.collapsed && this.queryCommandState(cmdName) != 1){ - var node = this.document.createElement({ - 'bold':'strong', - 'underline':'u', - 'superscript':'sup', - 'subscript':'sub', - 'italic':'em', - 'strikethrough':'strike' - }[cmdName]); - rng.insertNode(node).setStart(node,0).setCursor(false); - return true; + var node, rng = this.selection.getRange(); + if(rng.collapsed) { + if (this.queryCommandState(cmdName) == 1) { + node = this.document.createElement('span'); + node.appendChild(this.document.createTextNode(domUtils.fillChar)); + rng.insertNode(node); + rng.selectNode(node).select(); + this.document.execCommand(cmdName); + return true; + } else if (this.queryCommandState(cmdName) != 1) { + node = this.document.createElement({ + 'bold':'strong', + 'underline':'u', + 'superscript':'sup', + 'subscript':'sub', + 'italic':'em', + 'strikethrough':'strike' + }[cmdName]); + rng.insertNode(node).setStart(node,0).setCursor(false); + return true; + } }else{ - return this.document.execCommand(cmdName) + return this.document.execCommand(cmdName); } }, @@ -103,7 +112,7 @@ UM.plugins['basestyle'] = function(){ } break; } - }) + }); return result } }; diff --git a/_src/plugins/font.js b/_src/plugins/font.js index 193c314b..2eb76779 100755 --- a/_src/plugins/font.js +++ b/_src/plugins/font.js @@ -43,57 +43,69 @@ UM.plugins['font'] = function () { { name: 'timesNewRoman', val: 'times new roman'}, { name: 'sans-serif',val:'sans-serif'} ], - 'fontsize': [10, 12, 16, 18,24, 32,48] + 'fontsize': [10, 12, 14, 16, 18,24, 32,48] }); - me.addOutputRule(function (root) { - utils.each(root.getNodesByTagName('font'), function (node) { - if (node.tagName == 'font') { - var cssStyle = []; - for (var p in node.attrs) { - switch (p) { - case 'size': - var val = node.attrs[p]; - $.each({ - '10':'1', - '12':'2', - '16':'3', - '18':'4', - '24':'5', - '32':'6', - '48':'7' - },function(k,v){ - if(v == val){ - val = k; - return false; - } - }); - cssStyle.push('font-size:' + val + 'px'); - break; - case 'color': - cssStyle.push('color:' + node.attrs[p]); - break; - case 'face': - cssStyle.push('font-family:' + node.attrs[p]); - break; - case 'style': - cssStyle.push(node.attrs[p]); - } + function font2span(node){ + if (node.tagName == 'font') { + var cssStyle = []; + for (var p in node.attrs) { + switch (p) { + case 'size': + var val = node.attrs[p]; + $.each({ + '10':'1', + '12':'2', + '14':'3', + '16':'4', + '18':'5', + '24':'6', + '32':'7', + '48':'8' + },function(k,v){ + if(v == val){ + val = k; + return false; + } + }); + cssStyle.push('font-size:' + val + 'px'); + break; + case 'color': + cssStyle.push('color:' + node.attrs[p]); + break; + case 'face': + cssStyle.push('font-family:' + node.attrs[p]); + break; + case 'style': + cssStyle.push(node.attrs[p]); } - node.attrs = { - 'style': cssStyle.join(';') - }; } - node.tagName = 'span'; - if(node.parentNode.tagName == 'span' && node.parentNode.children.length == 1){ - $.each(node.attrs,function(k,v){ + node.attrs = { + 'style': cssStyle.join(';') + ';' + }; + } + node.tagName = 'span'; + if(node.parentNode.tagName == 'span' && node.parentNode.children.length == 1){ + $.each(node.attrs,function(k,v){ - node.parentNode.attrs[k] = k == 'style' ? node.parentNode.attrs[k] + v : v; - }) - node.parentNode.removeChild(node,true); - } + node.parentNode.attrs[k] = k == 'style' ? node.parentNode.attrs[k] + v : v; + }); + node.parentNode.removeChild(node,true); + } + } + + me.addInputRule(function (root) { + utils.each(root.getNodesByTagName('font'), function (node) { + font2span(node); }); }); + + me.addOutputRule(function (root) { + utils.each(root.getNodesByTagName('font'), function (node) { + font2span(node); + }); + }); + for(var p in fonts){ (function (cmd) { me.commands[cmd] = { @@ -103,21 +115,41 @@ UM.plugins['font'] = function () { } var rng = this.selection.getRange(); if(rng.collapsed){ - var span = $('').css(cmdNameToStyle[cmdName],value)[0]; + var span = $('').css(cmdNameToStyle[cmdName],size)[0]; rng.insertNode(span).setStart(span,0).setCursor(); }else{ if(cmdName == 'fontsize'){ - value = { + /* fontsize额外处理 */ + var size = { '10':'1', '12':'2', - '16':'3', - '18':'4', - '24':'5', - '32':'6', - '48':'7' - }[(value+"").replace(/px/,'')] + '14':'3', + '16':'4', + '18':'5', + '24':'6', + '32':'7', + '48':'8' + }[(value+"").replace(/px/,'')] || 1; + + this.document.execCommand(fonts[cmdName],false, size); + var $fonts = $('font[size=' + size + ']', this.body).attr('size', null).css('font-size', value + 'px'); + + // 处理ff原生fontsize命令不判断style上的fontsize的bug + if (browser.gecko) { + $fonts.find('*').each(function(i, ele){ + var $ele = $(ele), + fontSize = parseInt($ele.css('font-size')); + if (fontSize && fontSize != value) { + $ele.css('font-size', ''); + } + }); + } + + } else { + this.document.execCommand(fonts[cmdName],false, value); } - this.document.execCommand(fonts[cmdName],false, value); + + if(browser.gecko){ $.each(this.$body.find('a'),function(i,a){ var parent = a.parentNode; @@ -156,6 +188,10 @@ UM.plugins['font'] = function () { if(val === undefined){ val = $(start).attr(cmdNameToAttr[cmdName]) } + + if(val.indexOf('px') != -1 && start.indexOf('px') != -1 && start.style.fontSize != val) { + val = start.style.fontSize; + } return val ? utils.fixColor(cmdName,val).replace(/px/,'') : ''; }, queryCommandState: function (cmdName) { @@ -164,4 +200,4 @@ UM.plugins['font'] = function () { }; })(p); } -}; \ No newline at end of file +}; diff --git a/_src/plugins/link.js b/_src/plugins/link.js index e935352e..c7b84165 100755 --- a/_src/plugins/link.js +++ b/_src/plugins/link.js @@ -58,7 +58,7 @@ UM.plugins['link'] = function(){ this.addOutputRule(function(root){ $.each(root.getNodesByTagName('a'),function(i,a){ var _href = utils.html(a.getAttr('_href')); - if(!/^(ftp|https?|\/|file)/.test(_href)){ + if(!/^(ftp|tel|https?|\/|file)/.test(_href)){ _href = 'http://' + _href; } a.setAttr('href', _href); @@ -84,7 +84,7 @@ UM.plugins['link'] = function(){ $(start).attr(opt); rng.selectNode(start).select() }else{ - rng.insertNode($('' +opt.href+'').attr(opt)[0]).select() + rng.insertNode($('').text(opt.href).attr(opt)[0]).select(); } @@ -123,4 +123,4 @@ UM.plugins['link'] = function(){ this.document.execCommand('unlink'); } }; -}; \ No newline at end of file +}; diff --git a/_src/ui/combobox.js b/_src/ui/combobox.js index c0fc4c22..e5996a31 100644 --- a/_src/ui/combobox.js +++ b/_src/ui/combobox.js @@ -85,7 +85,7 @@ var me = this, labelClass = "."+labelClassName; - me.root().delegate('.' + itemClassName, 'click', function(){ + me.root().delegate('.' + itemClassName, 'click', function(evt){ var $li = $(this), index = $li.attr('data-item-index'); @@ -98,7 +98,7 @@ me.hide(); - return false; + evt.preventDefault(); }); diff --git a/_src/ui/menu.js b/_src/ui/menu.js index 683bc15b..55d8b1db 100755 --- a/_src/ui/menu.js +++ b/_src/ui/menu.js @@ -1,7 +1,6 @@ //menu 类 UM.ui.define('menu',{ show : function($obj,dir,fnname,topOffset,leftOffset){ - fnname = fnname || 'position'; if(this.trigger('beforeshow') === false){ return; @@ -9,7 +8,7 @@ UM.ui.define('menu',{ this.root().css($.extend({display:'block'},$obj ? { top : $obj[fnname]().top + ( dir == 'right' ? 0 : $obj.outerHeight()) - (topOffset || 0), left : $obj[fnname]().left + (dir == 'right' ? $obj.outerWidth() : 0) - (leftOffset || 0) - }:{})) + }:{})); this.trigger('aftershow'); } }, @@ -32,12 +31,12 @@ UM.ui.define('menu',{ if(!$obj.data('$mergeObj')){ $obj.data('$mergeObj',me.root()); $obj.on('wrapclick',function(evt){ - me.show() + me.show(); }); me.register('click',$obj,function(evt){ - me.hide() + me.hide(); }); - me.data('$mergeObj',$obj) + me.data('$mergeObj',$obj); } } }); \ No newline at end of file diff --git a/_src/ui/scale.js b/_src/ui/scale.js index 9dbda4c9..895b145d 100644 --- a/_src/ui/scale.js +++ b/_src/ui/scale.js @@ -24,7 +24,7 @@ UM.ui.define('scale', { return this; }, initStyle: function () { - utils.cssRule('edui-style-scale', '.edui-scale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;}' + + utils.cssRule('edui-style-scale', '.edui-scale{display:none;position:absolute;border:1px solid #38B2CE;cursor:hand;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}' + '.edui-scale span{position:absolute;left:0;top:0;width:7px;height:7px;overflow:hidden;font-size:0px;display:block;background-color:#3C9DD0;}' + '.edui-scale .edui-scale-hand0{cursor:nw-resize;top:0;margin-top:-4px;left:0;margin-left:-4px;}' + '.edui-scale .edui-scale-hand1{cursor:n-resize;top:0;margin-top:-4px;left:50%;margin-left:-4px;}' @@ -72,8 +72,10 @@ UM.ui.define('scale', { updateTargetElement: function () { var me = this, $root = me.root(), - $target = me.data('$scaleTarget'); - $target.css({width: $root.width(), height: $root.height()}); + $target = me.data('$scaleTarget'), + w = $root.width(), + h = $root.height(); + $target.attr('width', w).attr('height', h).css({width: w, height: h}); me.attachTo($target); }, updateContainerStyle: function (dir, offset) { diff --git a/_test/adapter/adapter.js b/_test/adapter/adapter.js deleted file mode 100644 index e226ae1f..00000000 --- a/_test/adapter/adapter.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: xuheng - * Date: 13-8-21 - * Time: 上午10:49 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.adapter' ); - -test('getEditor',function(){ - var div = document.createElement('div'); - div.id='editor'; - var con=document.createElement('div'); - con.id="contest"; - con.appendChild(div); - document.body.appendChild(con); - var ue7=UM.getEditor('editor'); - var ue8=UM.getEditor('editor'); - - stop(); - ue8.ready(function(){ - equal(ue8.uid,ue7.uid,''); - setTimeout(function(){ - UM.delEditor('editor'); - var editor=document.getElementById('editor'); - editor.parentNode.removeChild(editor); - start(); - },100) - }); -}); - -test('delEditor',function(){ - var div = document.createElement('div'); - div.id='editor'; - document.body.appendChild(div); - var ue=UM.getEditor('editor'); - stop(); - ue.ready(function(){ - setTimeout(function(){ - UM.delEditor('editor'); - equal(document.getElementById('editor').tagName.toLowerCase(),'textarea'); - var div=document.getElementById("editor") - div.parentNode.removeChild(div); - start(); - },100) - }); -}); - -test( 'trace 3623 render没有内容时,显示initialContent', function() { - var sc4 = document.createElement("script"); - sc4.id="sc4"; - sc4.style.width ="800px"; -// sc4.height = "100px"; - document.body.appendChild(sc4); - var ue4=UM.getEditor('sc4'); - stop(); - ue4.ready(function(){ - equal(ue4.getContent().toLowerCase(),ue4.options.initialContent.toLowerCase(),'标签没有内容,显示initialContent'); - setTimeout(function(){ - UM.delEditor('sc4'); - var editor=document.getElementById('sc4'); - editor.parentNode.removeChild(editor); - start(); - },200) - }); -} ); - -test( '判断render有内容时,显示render内容(script)', function() { - var sc3 = document.createElement("script"); - sc3.id="sc3"; - sc3.type="text/plain"; - sc3.style.width ="800px"; - - sc3.text= 'renderinnerhtml'; - document.body.appendChild(sc3); - var ue3=UM.getEditor('sc3'); - stop(); - ue3.ready(function(){ - equal(ue3.body.firstChild.innerHTML.toLowerCase(),"renderinnerhtml",'标签有内容,显示标签内容'); - - setTimeout(function(){ - UM.delEditor('sc3'); - var editor=document.getElementById('sc3'); - editor.parentNode.removeChild(editor); - start(); - },100) - }); -}); \ No newline at end of file diff --git a/_test/adapter/autofloat.js b/_test/adapter/autofloat.js deleted file mode 100644 index 663baea7..00000000 --- a/_test/adapter/autofloat.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-19 - * Time: 下午4:33 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.autofloat' ); -test( '检查toolbar是否浮动在页面顶端', function() { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var me = UM.getEditor(sc.id, {autoFloatEnabled:true,initialFrameWidth:800,initialFrameHeight:100,autoHeightEnabled:true}); - stop(); - me.ready(function(){ - me.setContent('














































sdf

'); - var screenX = window.screenX || window.screenLeft;//不同浏览器兼容 - var screenY = window.screenY || window.screenTop; - setTimeout(function () { - var range = new UM.dom.Range(me.document,me.body); - range.setStart(me.body.firstChild, 1).collapse(1).select(); - me.focus(); - setTimeout(function () { - window.scrollBy(screenX, screenY + $(document.body).height()); - setTimeout(function () { - var $eduiToolbar = me.$container.find('.edui-toolbar'), - getScrollTop = function(){ - return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;//不同浏览器兼容 - }; - - if(ua.browser.ie != 6) { //ie6下,工具栏浮动不到正确位置 - equal(getScrollTop(), $eduiToolbar.offset().top, '检查toolbar是否在页面顶端'); - } - window.scrollTo(screenX, screenY - $(document.body).height()); - setTimeout(function () { - equal(me.$container.children()[0].className, me.$container.find('.edui-toolbar')[0].className, 'toolbar是第一个元素'); - document.getElementById('sc').parentNode.removeChild(document.getElementById('sc')); - start(); - }, 500); - }, 500); - }, 200); - }, 200); - }); -}); \ No newline at end of file diff --git a/_test/adapter/button.js b/_test/adapter/button.js deleted file mode 100644 index 74a6e8b8..00000000 --- a/_test/adapter/button.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-19 - * Time: 下午5:17 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.button' ); - -test( '判断有没有触发fullscreenchanged事件', function () { - var editor = te.obj[0]; - var div = te.dom[0]; - - editor.ready(function(){ - var $btn = editor.$container.find('.edui-btn-bold'); - equal($btn.edui().disabled(), editor.queryCommandState('bold') == -1, '判断初始化后ui对象disable状态是否正常'); - equal($btn.edui().active(), editor.queryCommandState('bold') == 1, '判断初始化后ui对象active状态是否正常'); - editor.focus(); - $btn.click();//直接用$btn.click()在ie8下,模拟有问题,要先focus,不然document找不对 - setTimeout(function(){ - equal($btn.edui().disabled(), editor.queryCommandState('bold') == -1, '判断点击加粗后ui对象disable状态是否正常'); - equal($btn.edui().active(), editor.queryCommandState('bold') == 1, '判断点击加粗后ui对象active状态是否正常'); - start(); - },200); - }); - stop(); -}); \ No newline at end of file diff --git a/_test/adapter/combobox.js b/_test/adapter/combobox.js deleted file mode 100644 index a400510d..00000000 --- a/_test/adapter/combobox.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-19 - * Time: 下午4:33 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.combobox' ); -test( '检测combobox的控制否正常', function() { - var editor = te.obj[0]; - stop(); - editor.ready(function(){ - setTimeout(function () { - var editor = te.obj[0], - components = [ "paragraph", "fontfamily", "fontsize" ], - $body = $(document.body), - colors = [ "forecolor", "backcolor" ]; - - for ( var i = 0, component; component = components[ i ]; i++ ) { - - $( ".edui-btn-name-" + component, editor.container).trigger("click"); - - equal( $( ".edui-combobox-" + component , editor.container ).css("display"), "block", component+' combobox打开正常' ); - - $body.trigger("click"); - - equal( $( ".edui-combobox-" + component , editor.container ).css("display"), "none", component+' combobox关闭正常' ); - - } - - for ( var i = 0, color; color = colors[ i ]; i++ ) { - - $( ".edui-splitbutton-"+ color +" .edui-dropdown-toggle", editor.container).trigger("click"); - - equal( $( ".edui-colorpicker-" + color , editor.container).parents(".edui-popup").css("display"), "block", color+' combobox打开正常' ); - - $body.trigger("click"); - - equal( $( ".edui-colorpicker-" + color , editor.container).parents(".edui-popup").css("display"), "none", color+' combobox关闭正常' ); - - } - - start(); - - }, 200); - }); - -}); - diff --git a/_test/adapter/dialog.js b/_test/adapter/dialog.js deleted file mode 100644 index e9a6674d..00000000 --- a/_test/adapter/dialog.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 上午10:47 - * To change this template use File | Settings | File Templates. - */ - -module('ui.dialog'); -test('检查video的按钮和弹出的dialog面板是否正常显示', function () { - var editor = te.obj[0]; - setTimeout(function () {//这句本身没有用,但是当用例自动执行下一个时,时序上可能有问题,所以在这儿先等一下 - var $vedioBtn = editor.$container.find('.edui-btn-video'); - ok($vedioBtn.data('$mergeObj').parent()[0] === undefined, '判断点击按钮前dialog是否未插入到dom树里面'); - editor.focus(); - $vedioBtn.click(); - ok($vedioBtn.data('$mergeObj').parent()[0] !== undefined, '判断点击按钮后dialog是否已插入到dom树里面'); - $vedioBtn.click(); - equal($vedioBtn.edui().disabled(), editor.queryCommandState('video') == -1, '判断初始化后btn对象disable状态是否正常'); - equal($vedioBtn.edui().active(), editor.queryCommandState('video') == 1, '判断初始化后btn对象active状态是否正常'); - editor.setContent(''); - setTimeout(function () { - editor.execCommand('selectall'); - setTimeout(function () { - equal($vedioBtn.edui().disabled(), editor.queryCommandState('video') == -1, '判断点击按钮后btn对象disable状态是否正常'); - equal($vedioBtn.edui().active(), editor.queryCommandState('video') == 1, '判断点击按钮后btn对象active状态是否正常'); - start(); - }, 100); - }, 100); - }, 100); - stop(); -}); \ No newline at end of file diff --git a/_test/adapter/fullscreen.js b/_test/adapter/fullscreen.js deleted file mode 100644 index f2088348..00000000 --- a/_test/adapter/fullscreen.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-19 - * Time: 下午4:33 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.fullscreen' ); -test( '检测全屏操作是否正常', function() { - stop(); - setTimeout(function () { - var editor = te.obj[0]; - if(ua.browser.ie==8){//todo trace 3628 focus有问题,select代替 - var range = new UM.dom.Range( editor.document ,editor.body); - range.setStart(editor.body,0).collapse(true).select(); - } - var oldState = { //切换前的状态 - width: editor.$container.innerWidth(), - height: editor.$container.innerHeight() - }, - //切换之后的新状态 - newState = {}, - $fullscreenBtn = $( ".edui-btn-fullscreen", editor.$container ); - - //切换至全屏 - $fullscreenBtn.trigger("click"); - - newState = { - width: editor.$container.innerWidth(), - height: editor.$container.innerHeight() - }; - - equal( newState.width, $( window ).width(), '切换至全屏状态后宽度正常' ); - equal( newState.height, $( window ).height(), '切换至全屏状态后高度正常' ); - - equal( $fullscreenBtn.hasClass( "edui-active" ), true, '切换至全屏状态后按钮状态正常' ); - - //模拟resize - $( window ).trigger( "resize" ); - equal( newState.width, $( window ).width(), 'resize后宽度正常' ); - equal( newState.height, $( window ).height(), 'resize后高度正常' ); - - - //退出全屏 - $fullscreenBtn.trigger("click"); - - newState = { - width: editor.$container.innerWidth(), - height: editor.$container.innerHeight() - }; - - equal( newState.width, oldState.width, '退出全屏状态后宽度正常' ); - equal( newState.height, oldState.height, '退出全屏状态后高度正常' ); - - equal( $fullscreenBtn.hasClass( "active" ), false, '退出全屏状态后按钮状态正常' ); - - //模拟resize - $( window ).trigger( "resize" ); - equal( newState.width, oldState.width, 'resize后宽度未改变' ); - equal( newState.height, oldState.height, 'resize后高度未改变' ); - start(); - }, 500); -}); - diff --git a/_test/adapter/imagescale.js b/_test/adapter/imagescale.js deleted file mode 100644 index 887ddf9d..00000000 --- a/_test/adapter/imagescale.js +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: dongyancen - * Date: 13-8-1 - * Time: 下午3:41 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.imagescale' ); - -test( 'webkit下图片可以被选中并出现八个角', function() { - if ( ua.browser.webkit ) { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var editor = UM.getEditor(sc.id, {initialFrameWidth:800,initialFrameHeight:320,autoHeightEnabled:true}); - editor.ready(function () { - editor.setContent( '

修正webkit下图片选择的问题修正webkit下图片选择的问题

' ); - var img = editor.body.getElementsByTagName( 'img' )[0]; - var p = editor.body.firstChild; - ua.click( img ); - var range = editor.selection.getRange(); - ua.checkResult( range, p, p, 1, 2, false, '检查当前的range是否为img' ); - var scale = editor.$container.find('.edui-scale')[0]; - ok(scale && scale.style.display!='none', "检查八个角是否已出现"); - ok($(img).width() == $(scale).width() && $(img).height() == $(scale).height(), "检查八个角和图片宽高度是否相等"); - setTimeout(function(){ - UM.clearCache(sc.id); - domUtils.remove(editor.container); - start(); - },100); - }); - stop(); - } -} ); - -test( '鼠标点击图片外的其他区域时,八个角消失', function() { - if ( ua.browser.webkit ) { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var editor = UM.getEditor(sc.id, {initialFrameWidth:800,initialFrameHeight:320,autoHeightEnabled:true}); - editor.ready(function () { - editor.setContent( '

修正webkit下图片选择的问题修正webkit下图片选择的问题

' ); - var img = editor.body.getElementsByTagName( 'img' )[0]; - var p = editor.body.firstChild; - ua.click( img ); - var scale = editor.$container.find('.edui-scale')[0]; - ok(scale && scale.style.display!='none', "检查八个角是否已出现"); - ua.mousedown( editor.$container[0], {clientX: 100, clientY: 100} ); - ok(scale && scale.style.display=='none', "检查八个角是否已消失"); - setTimeout(function(){ - UM.clearCache(sc.id); - domUtils.remove(editor.container); - start(); - },100); - }); - stop(); - } -} ); - -test( '键盘有操作时,八个角消失', function() { - if ( ua.browser.webkit ) { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var editor = UM.getEditor(sc.id, {initialFrameWidth:800,initialFrameHeight:320,autoHeightEnabled:true}); - editor.ready(function () { - editor.setContent( '

修正webkit下图片选择的问题修正webkit下图片选择的问题

' ); - var img = editor.body.getElementsByTagName( 'img' )[0]; - var p = editor.body.firstChild; - ua.click( img ); - var scale = editor.$container.find('.edui-scale')[0]; - ok(scale && scale.style.display!='none', "检查八个角是否已出现"); - ua.keydown( editor.$container[0] ); - ok(scale && scale.style.display=='none', "检查八个角是否已消失"); - setTimeout(function(){ - UM.clearCache(sc.id); - domUtils.remove(editor.container); - start(); - },100); - }); - stop(); - } -} ); - -test( '八个角显示时,鼠标快速按下然、放开,八个角不消失', function() { - if ( ua.browser.webkit ) { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var editor = UM.getEditor(sc.id, {initialFrameWidth:800,initialFrameHeight:320,autoHeightEnabled:true}); - editor.ready(function () { - editor.setContent( '

修正webkit下图片选择的问题修正webkit下图片选择的问题

' ); - var img = editor.body.getElementsByTagName( 'img' )[0]; - var p = editor.body.firstChild; - ua.click( img ); - var scale = editor.$container.find('.edui-scale')[0]; - ok(scale && scale.style.display!='none', "检查八个角是否已出现"); - ua.mousedown( scale ); - setTimeout(function(){ - ua.mouseup( scale ); - },10); - setTimeout(function(){ - ok(scale && scale.style.display!='none', "检查八个角是否正常显示"); - setTimeout(function(){ - UM.clearCache(sc.id); - domUtils.remove(editor.container); - start(); - },100); - },400); - - }); - stop(); - } -} ); - -test( '八个角显示时,鼠标快速按下然、放开,八个角不消失', function() { - if ( ua.browser.webkit ) { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var editor = UM.getEditor(sc.id, {initialFrameWidth:800,initialFrameHeight:320,autoHeightEnabled:true}); - editor.ready(function () { - editor.setContent( '

修正webkit下图片选择的问题修正webkit下图片选择的问题

' ); - var img = editor.body.getElementsByTagName( 'img' )[0]; - var p = editor.body.firstChild; - ua.click( img ); - var scale = editor.$container.find('.edui-scale')[0]; - ok(scale && scale.style.display!='none', "检查八个角是否已出现"); - ua.mousedown( scale ); - setTimeout(function(){ - ua.mouseup( scale ); - },400); - setTimeout(function(){ - ok(scale && scale.style.display=='none', "检查八个角是否消失"); - setTimeout(function(){ - UM.clearCache(sc.id); - domUtils.remove(editor.container); - start(); - },100); - },500); - }); - stop(); - } -} ); \ No newline at end of file diff --git a/_test/adapter/popup.js b/_test/adapter/popup.js deleted file mode 100644 index 7121ed2f..00000000 --- a/_test/adapter/popup.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-20 - * Time: 下午7:13 - * To change this template use File | Settings | File Templates. - */ -module('ui.popup'); -test('检查表情的pupop显示是否正常', function () { - var editor = te.obj[0]; - setTimeout(function () {//这句本身没有用,但是当用例自动执行下一个时,时序上可能有问题,所以在这儿先等一下 - var $emotionBtn = editor.$container.find('.edui-btn-emotion'); - ok($emotionBtn.data('$mergeObj').parent()[0] === undefined, '判断点击按钮前pupop是否未插入到dom树里面'); - editor.focus(); - $emotionBtn.click(); - ok($emotionBtn.data('$mergeObj').parent()[0] !== undefined, '判断点击按钮后pupop是否已插入到dom树里面'); - - equal($emotionBtn.edui().disabled(), editor.queryCommandState('emotion') == -1, '判断初始化后btn对象disable状态是否正常'); - equal($emotionBtn.edui().active(), editor.queryCommandState('emotion') == 1, '判断初始化后btn对象active状态是否正常'); - editor.focus(); - $emotionBtn.click(); - setTimeout(function () { - equal($emotionBtn.edui().disabled(), editor.queryCommandState('emotion') == -1, '判断点击按钮后btn对象disable状态是否正常'); - equal($emotionBtn.edui().active(), editor.queryCommandState('emotion') == 1, '判断点击按钮后btn对象active状态是否正常'); - start(); - }, 100); - }, 50); - stop(); -}); \ No newline at end of file diff --git a/_test/adapter/source.js b/_test/adapter/source.js deleted file mode 100644 index f9369c12..00000000 --- a/_test/adapter/source.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-19 - * Time: 下午5:17 - * To change this template use File | Settings | File Templates. - */ -module( 'adapter.source' ); - -test( '判断有没有触发fullscreenchanged事件', function () { - var editor = te.obj[0]; - editor.focus(); - editor.execCommand('source'); - setTimeout(function () { - var $textarea = editor.$container.find('textarea'); - editor.fireEvent('fullscreenchanged'); - setTimeout(function () { - equal($textarea.width(), editor.$body.width() - 10, "textarea的宽是否正确"); - equal($textarea.height(), editor.$body.height(), "textarea的高是否正确"); - start(); - }, 100); - }, 100); - stop(); -}); \ No newline at end of file diff --git a/_test/adapter/tools.js b/_test/adapter/tools.js deleted file mode 100644 index 05f178f1..00000000 --- a/_test/adapter/tools.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - - */ -(function () { - function mySetup() { - for (var config in window.UMDITOR_CONFIG) { - if (typeof(window.UMDITOR_CONFIG[config]) == 'string') - window.UMDITOR_CONFIG[config] = window.UMDITOR_CONFIG[config].replace('_test/tools/br/', ''); - } - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc').attr('id', 'testeditor'); - var editor = UM.getEditor(div.id, {'initialContent':'

欢迎使用umeditor

', 'autoFloatEnabled':false,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); - var ue = new UM.Editor({'UEDITOR_HOME_URL':'../../../', 'autoFloatEnabled':true,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); - QUnit.readyFlag =0; - stop(); - setTimeout(function(){ - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - te.dom.push(div); - te.obj.push(editor); - te.obj.push(range); - te.obj.push(ue); - QUnit.readyFlag =1; - }); - },50); - document.getElementsByClassName = function (eleClassName) { - var getEleClass = [];//定义一个数组 - var myclass = new RegExp("\\b" + eleClassName + "\\b");//创建一个正则表达式对像 - var elem = this.getElementsByTagName("*");//获取文档里所有的元素 - for (var h = 0; h < elem.length; h++) { - var classes = elem[h].className;//获取class对像 - if (myclass.test(classes)) getEleClass.push(elem[h]);//正则比较,取到想要的CLASS对像 - } - return getEleClass;//返回数组 - } - } - - var _d = function () { - UM.clearCache('testeditor'); - te.dom.push(te.obj[0].container); - document.getElementById('testeditor')&&te.dom.push(document.getElementById('testeditor')); - if (te) { - if (te.dom && te.dom.length) { - for (var i = 0; i < te.dom.length; i++) { - if (te.dom[i] && te.dom[i].parentNode) - te.dom[i].parentNode.removeChild(te.dom[i]); - } - - } - } - te.dom = []; - te.obj = []; - } - var s = QUnit.testStart, d = QUnit.testDone; - QUnit.testStart = function () { - s.apply(this, arguments); - mySetup(); - }; - QUnit.testDone = function () { - _d(); - d.apply(this, arguments); - } -})(); \ No newline at end of file diff --git a/_test/build_run.xml b/_test/build_run.xml deleted file mode 100644 index d13c10b2..00000000 --- a/_test/build_run.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/_test/build_run_core.xml b/_test/build_run_core.xml deleted file mode 100644 index 5a6bafad..00000000 --- a/_test/build_run_core.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/_test/build_run_plugin.xml b/_test/build_run_plugin.xml deleted file mode 100644 index c6af6d49..00000000 --- a/_test/build_run_plugin.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/_test/build_run_ui.xml b/_test/build_run_ui.xml deleted file mode 100644 index d53f1b49..00000000 --- a/_test/build_run_ui.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/_test/core/Editor.js b/_test/core/Editor.js deleted file mode 100644 index 8910fec4..00000000 --- a/_test/core/Editor.js +++ /dev/null @@ -1,674 +0,0 @@ -module("core.Editor"); -//test('', function () { -// stop() -//}); -var pluginsList = { - 'autosave': ['clearlocaldata', 'getlocaldata', 'drafts'], - 'basestyle': ['bold', 'underline', 'superscript', 'subscript', 'italic', 'strikethrough'], - 'font': ['forecolor', 'backcolor', 'fontsize', 'fontfamily'], - 'formula': ['formula'], - 'horizontal': ['horizontal'], - 'justify': ['justifyleft', 'justifyright', 'justifycenter' , 'justifyfull'], - 'link': ['link', 'unlink'], - 'list': ['insertorderedlist', 'insertunorderedlist'], - 'paragraph': ['paragraph'], - 'removeformat': ['removeformat'], - 'selectall': ['selectall'], - 'source': ['source'], - 'undo': ['undo', 'redo'], - 'video': ['insertvideo'] - // 'autoupload':[], - // 'cleardoc':['cleardoc'], -// 'enterkey':[], - // 'paste':[], -// 'preview':['preview'], -// 'print':['print'], -// 'image':['insertimage'], -// 'inserthtml':['inserthtml'], -}; - -test('某一个插件不加载', function () { - if(ua.browser.ie)return; - var i = 0; - for (var p in pluginsList) { - var e = new UM.Editor({excludePlugins: p}); - e.addListener("langReady", function () { - var flag = true; - var msg = ''; - for (var p2 in pluginsList) { - if (p2 == e.options['excludePlugins']) - continue; - for (var c in pluginsList[p2]) { - if (e.commands[pluginsList[p2][c]] === undefined) { - flag = false; - msg += pluginsList[p2][c] + ' '; - } - } - } - equal(flag, true, 'exclude' + p + '未加载:' + msg); - i++; - if (i == Object.keys(pluginsList).length) { - start(); - } - }); - //todo ie下这里需要个延迟 加 e = null; - } - stop(); -}); -test("autoSyncData:true,textarea容器(由setcontent触发的)", function () { - var div = document.body.appendChild(document.createElement('div')); - div.innerHTML = '
'; - var editor_a = UM.getEditor('myEditor'); - stop(); - editor_a.ready(function () { - editor_a.setContent('

设置内容autoSyncData 1

'); - setTimeout(function () { - var textarea = document.getElementById('myEditor'); - equal(textarea.value, '

设置内容autoSyncData 1

', 'textarea内容正确'); - te.dom.push(editor_a.container); - document.getElementById('form').parentNode.removeChild(document.getElementById('form')); - document.getElementById('test1') && te.dom.push(document.getElementById('test1')); - setTimeout(function () { - start(); - }, 100); - }, 100); - }); -}); -test("autoSyncData:true(由blur触发的)", function () { - //todo ie8里事件触发有问题,暂用手动测 - if (ua.browser.ie > 8 || !ua.browser.ie) { - var div = document.body.appendChild(document.createElement('div')); - div.innerHTML = '
'; - var editor_a = UM.getEditor('myEditor_autoSyncData_blur'); - stop(); - editor_a.ready(function () { - editor_a.body.innerHTML = '

设置内容autoSyncData 2

'; - equal(document.getElementsByTagName('textarea').length, 0, '内容空没有textarea'); - ua.blur(editor_a.body); - stop(); - setTimeout(function () { - var form = document.getElementById('form'); - var textarea = form.lastChild; - if (textarea.tagName.toLowerCase() == 'textarea') { - equal(textarea.value, '

设置内容autoSyncData 2

', 'textarea内容正确'); - } - else { - ok(false, '没有textarea'); - } - te.dom.push(editor_a.container); - - form && form.parentNode.removeChild(form); - start(); - - }, 100); - }); - } -}); -test("sync", function () { - var div = document.body.appendChild(document.createElement('div')); - div.innerHTML = '
'; - var editor_a = UM.getEditor('myEditor_sync'); - stop(); - editor_a.ready(function () { - editor_a.body.innerHTML = '

hello

'; - editor_a.sync("form"); - setTimeout(function () { - var textarea = document.getElementById('myEditor_sync'); - equal(textarea.value, '

hello

', '同步内容正确'); - te.dom.push(editor_a.container); - start(); - - }, 100); - }); -}); - -test('默认加载全部插件', function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - var flag = true; - var msg = ''; - editor.ready(function () { - for (var p in pluginsList) { - for (var c in pluginsList[p]) { - if (editor.commands[pluginsList[p][c]] === undefined) { - flag = false; - msg += pluginsList[p][c] + ' '; - } - } - } - equal(flag, true, '未加载:' + msg); - start(); - }); - stop(); -}); -test('多个插件不加载', function () { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ex'; - var editor = UM.getEditor('ex',{excludePlugins: 'font undo source'}); - editor.ready( function () { - var flag = true; - var msg = ''; - for (var p in pluginsList) { - if (editor.options['excludePlugins'].indexOf(p) > -1) - continue; - for (var c in pluginsList[p]) { - if (editor.commands[pluginsList[p][c]] === undefined) { - flag = false; - msg += pluginsList[p][c] + ' '; - } - } - } - equal(flag, true, 'exclude' + p + '未加载:' + msg); - UM.delEditor('ex'); - document.getElementById('ex')&&document.getElementById('ex').parentNode.removeChild(document.getElementById('ex')); - start(); - }); - stop(); -}); -test("hide,show", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - editor.ready(function () { - equal(editor.body.getElementsByTagName('span').length, 0, '初始没有书签'); - editor.hide(); - setTimeout(function () { - equal($(editor.container).css('display'), 'none', '隐藏编辑器'); - equal(editor.body.getElementsByTagName('span').length, 1, '插入书签'); - ok(/_baidu_bookmark_start/.test(editor.body.getElementsByTagName('span')[0].id), '书签'); - editor.show(); - setTimeout(function () { - equal($(te.dom[0]).css('display'), 'block', '显示编辑器'); - var br = ua.browser.ie ? '' : '
'; - equal(ua.getChildHTML(editor.body), '

' + br + '

', '删除书签'); - start(); - }, 200); - }, 200); - }); - stop(); -}); - -test("_setDefaultContent--focus", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - editor.ready(function () { - editor._setDefaultContent('hello'); - editor.fireEvent('focus'); - setTimeout(function () { - var br = ua.browser.ie ? '' : '
'; - equal(ua.getChildHTML(editor.body), '

' + br + '

', 'focus'); - start(); - }, 200); - }); - stop(); -}); - -test("_setDefaultContent--firstBeforeExecCommand", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - editor.ready(function () { - editor._setDefaultContent('hello'); - editor.fireEvent('firstBeforeExecCommand'); - var br = ua.browser.ie ? '' : '
'; - equal(ua.getChildHTML(editor.body), '

' + br + '

', 'firstBeforeExecCommand'); - start(); - }); - stop(); -}); -test("trace 3610 setDisabled,setEnabled", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - editor.ready(function () { - editor.setContent('

欢迎使用umeditor!

'); - editor.focus(); - if (ua.browser.ie && ua.browser.ie < 9) {//trace 3628 ie8 focus 设置无效,手动设range - var range = new UM.dom.Range(editor.document, editor.body); - range.setStart(editor.body.firstChild, 0).collapse(true).select(); - } - setTimeout(function () { - if (ua.browser.ie && ua.browser.ie < 9) {//trace 3628 ie8 focus 设置无效,手动设range - ua.manualDeleteFillData(editor.body); - } - var startContainer = editor.selection.getRange().startContainer.outerHTML; - var startOffset = editor.selection.getRange().startOffset; - var collapse = editor.selection.getRange().collapsed; - editor.setDisabled(); - setTimeout(function () { - equal(editor.body.contentEditable, 'false', 'setDisabled'); - equal(editor.body.firstChild.firstChild.tagName.toLowerCase(), 'span', '插入书签'); - equal($(editor.body.firstChild.firstChild).css('display'), 'none', '检查style'); - equal($(editor.body.firstChild.firstChild).css('line-height'), '0px', '检查style'); - ok(/_baidu_bookmark_start/.test(editor.body.firstChild.firstChild.id), '书签');///_baidu_bookmark_start/.test() - editor.setEnabled(); - setTimeout(function () { - equal(editor.body.contentEditable, 'true', 'setEnabled'); - equal(ua.getChildHTML(editor.body), '

欢迎使用umeditor!

', '内容恢复'); - if (!ua.browser.ie || ua.browser.ie < 9) {//todo ie9,10改range 之后,ie9,10这里的前后range不一致,focus时是text,setEnabled后是p - equal(editor.selection.getRange().startContainer.outerHTML, startContainer, '检查range'); - } - equal(editor.selection.getRange().startOffset, startOffset, '检查range'); - equal(editor.selection.getRange().collapsed, collapse, '检查range'); - start(); - }, 50); - }, 50); - }, 50); - }); - stop(); -}); -test("render-- options", function () { - var options = {'initialContent': 'xxx
xxx

', 'UEDITOR_HOME_URL': '../../../', autoClearinitialContent: false, 'autoFloatEnabled': false}; - var editor = new UM.Editor(options); - - var div = document.body.appendChild(document.createElement('div')); - editor.render(div); - /*会自动用p标签包围*/ -// var space = UM.browser.ie ? ' ' : '
'; - stop(); - editor.ready(function () { - equal(ua.getChildHTML(editor.body), '

xxx

xxx

', 'check initialContent'); - te.dom.push(div); - start(); - }); -}); - -test('destroy', function () { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'edu'; - var editor = UM.getEditor('edu'); - editor.ready(function () { - editor.destroy(); - equal(document.getElementById('edu').tagName.toLowerCase(), 'textarea', '容器被删掉了'); - UM.clearCache('edu'); - document.getElementById('edu') && te.dom.push(document.getElementById('edu')); - }); -}); - -test("getContent--转换空格,nbsp与空格相间显示", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - setTimeout(function () { - editor.focus(); - var innerHTML = '
x x x    x    
'; - editor.setContent(innerHTML); - - equal(editor.getContent(), '
x  x   x    x     
', "转换空格,nbsp与空格相间显示,原nbsp不变"); - start(); - }, 100); - }); -}); - -test('getContent--参数为函数', function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - setTimeout(function () { - editor.focus(); - editor.setContent("


dd

"); - equal(editor.getContent(), "


dd

", 'hasContents判断不为空'); - equal(editor.getContent(function () { - return false - }), "", '为空'); - - start(); - }, 50); -}); - -test('getContent--2个参数,第一个参数为参数为函数', function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - setTimeout(function () { - editor.focus(); - editor.setContent("


dd

"); - equal(editor.getContent(), "


dd

", 'hasContents判断不为空'); - equal(editor.getContent("", function () { - return false - }), "", '为空'); - start(); - }, 50); -}); - -test("setContent", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - expect(2); - editor.addListener("beforesetcontent", function () { - ok(true, "beforesetcontent"); - }); - editor.addListener("aftersetcontent", function () { - ok(true, "aftersetcontent"); - }); - var html = 'xxem
xxxx
'; - editor.setContent(html); - var div_new = document.createElement('div'); - div_new.innerHTML = '

xxem

xxxx
'; - var div2 = document.createElement('div'); - div2.innerHTML = editor.body.innerHTML; - ua.haveSameAllChildAttribs(div2, div_new, 'check contents'); - setTimeout(function () { - start(); - }, 1000); - }); -}); - -test("setContent 追加", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - expect(2); - editor.addListener("beforesetcontent", function () { - ok(true, "beforesetcontent"); - }); - editor.addListener("aftersetcontent", function () { - ok(true, "aftersetcontent"); - }); - var html = 'xxem
xxxx
'; - editor.setContent(html); - var div_new = document.createElement('div'); - div_new.innerHTML = '

xxem

xxxx
'; - var div2 = document.createElement('div'); - div2.innerHTML = editor.body.innerHTML; - ua.haveSameAllChildAttribs(div2, div_new, 'check contents'); - start(); - }); -}); - -test("focus(false)", function () { - if (ua.browser.ie && ua.browser.ie < 9)return;//trace 3628 ie8 focus - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.setContent("

hello1

hello2

"); - editor.focus(false); - setTimeout(function () { - var rng = editor.selection.getRange(); - var start = rng.startContainer; - if(start.nodeName == 'P' && rng.startOffset == 0){ - if(start = start.childNodes[rng.startOffset]){ - if(start.nodeType == 3){ - rng.setStart(start,0).collapse(true); - } - } - } - equal(rng.collapsed,true); - equal(rng.startContainer,editor.body.firstChild.firstChild,"focus(false)焦点在最前面"); - equal(rng.startOffset,0,"focus(false)焦点在最前面"); - - }, 100); - start(); - }); -}); - -test("focus(true)", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - - stop(); - editor.ready(function () { - editor.setContent("

hello1

hello2

"); - editor.focus(true); - var rng = editor.selection.getRange(); - var start = rng.startContainer; - if(start.nodeName == 'P' && rng.startOffset == start.childNodes.length){ - if(start = start.lastChild){ - if(start.nodeType == 3){ - rng.setStartAtLast(start).collapse(true); - } - } - } - equal(rng.collapsed,true); - equal(rng.startContainer,editor.body.lastChild.lastChild,"focus( true)焦点在最后面"); - equal(rng.endOffset, editor.body.lastChild.lastChild.nodeValue.length, "focus( true)焦点在最后面"); - - }); - start(); -}); - -/*按钮高亮、正常和灰色*/ -test("queryCommandState", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent("

xxxxxx

"); - var p = editor.document.getElementsByTagName('p')[0]; - var r = new UM.dom.Range(editor.document, editor.body); - r.setStart(p.firstChild, 0).setEnd(p.firstChild, 1).select(); - equal(editor.queryCommandState('bold'), 1, '加粗状态为1'); - r.setStart(p, 1).setEnd(p, 2).select(); - equal(editor.queryCommandState('bold'), 0, '加粗状态为0'); - start(); - }); -}); -test("trace 3581 queryCommandValue", function () { - if (ua.browser.gecko)return;//todo trace 3581 - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent('

xxx

'); - var range = new UM.dom.Range(editor.document, editor.body); - var p = editor.document.getElementsByTagName("p")[0]; - range.selectNode(p).select(); - editor.execCommand('justifyleft'); - equal(editor.queryCommandValue('justifyleft'), 'left', 'text align is left'); - start(); - }); -}); -test("execCommand", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent("

xx

xxx

"); - var doc = editor.document; - var range = new UM.dom.Range(doc, editor.body); - var p = doc.getElementsByTagName('p')[1]; - range.setStart(p, 0).setEnd(p, 1).select(); - editor.execCommand('justifyright'); - if (ua.browser.gecko) - equal($(p).css('text-align'), '-moz-right', 'execCommand align'); - else - equal($(p).css('text-align'), 'right', 'execCommand align'); - range.selectNode(p).select(); - editor.execCommand("forecolor", "red"); - var font = doc.getElementsByTagName('font')[0]; - equal(ua.formatColor(font.color), "#ff0000", 'check execCommand color'); - var html = '

xx

xxx

'; - var html_1 = "

xx

xxx

"; - ua.checkSameHtml(editor.body.innerHTML, ua.browser.webkit ? html : html_1, 'check style') - start(); - }); -}); - -test("hasContents", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent(''); - ok(!editor.hasContents(), "have't content"); - editor.setContent("xxx"); - ok(editor.hasContents(), "has contents"); - editor.setContent('


'); - ok(!editor.hasContents(), '空p认为是空'); - start(); - }); -}); - - -/*参数是对原有认为是空的标签的一个扩展,即原来的dtd认为br为空,加上这个参数可以认为br存在时body也不是空*/ -test("hasContents--有参数", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent('

你好

  1. ddd

'); - ok(editor.hasContents(['ol', 'li', 'table']), "有ol和li"); - ok(editor.hasContents(['td', 'li', 'table']), "有li"); - editor.setContent('


'); - ok(!editor.hasContents(['']), "为空"); - ok(editor.hasContents(['br']), "不为空"); - start(); - }); -}); - -test('trace 1964 getPlainTxt--得到有格式的编辑器的纯文本内容', function () { - if (ua.browser.ie > 0 && ua.browser.ie < 9)return;//TODO 1.2.6 - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent('

 

  hell\no
hello

'); - equal(editor.getPlainTxt(), "\n hello\nhello\n", '得到编辑器的纯文本内容,但会保留段落格式'); - start(); - }); -}); - -test('getContentTxt--文本前后的空格,&nbs p转成空格', function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - editor.setContent('  你 好   '); - equal(editor.getContentTxt(), ' 你 好 '); - equal(editor.getContentTxt().length, 8, '8个字符,空格不被过滤'); - start(); - }); -}); -test('getAllHtml', function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - var html = editor.getAllHtml(); - ok(/umeditor.css/.test(html), '引入样式'); - start(); - }); -}); -test('2个实例采用2个配置文件', function () { - var head = document.getElementsByTagName('head')[0]; - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = '../../editor_config.js'; - head.appendChild(script); - expect(6); - stop(); - /*动态加载js需要时间,用这个umeditor.config.js覆盖默认的配置文件*/ - setTimeout(function () { - var div1 = document.body.appendChild(document.createElement('div')); - div1.id = 'div1'; - div1.style.height = '200px'; - var div2 = document.body.appendChild(document.createElement('div')); - div2.id = 'div2'; - var editor1 = UM.getEditor('div1', {'UEDITOR_HOME_URL': '../../../', 'initialContent': '欢迎使用umeditor', 'autoFloatEnabled': false}); - editor1.ready(function () { - var editor2 = UM.getEditor('div2', UMEDITOR_CONFIG2); - editor2.ready(function () { - equal(editor1.body.style.minHeight, '200px', '编辑器高度为200px'); - equal(editor2.body.style.minHeight, '400px', '自定义div高度为400px'); - var html = UMEDITOR_CONFIG2.initialContent; - ua.checkHTMLSameStyle(html, editor2.document, editor2.body.firstChild, '初始内容为自定制的'); - equal(editor2.options.enterTag, 'br', 'enterTag is br'); - html = '欢迎使用umeditor'; - equal(html, editor1.body.firstChild.innerHTML, '内容和umeditor.config一致'); - equal(editor1.options.enterTag, 'p', 'enterTag is p'); - te.dom.push(editor1.container); - te.dom.push(editor2.container); - document.getElementById('div1') && te.dom.push(document.getElementById('div1')); - document.getElementById('div2') && te.dom.push(document.getElementById('div2')); - start(); - }); - }); - }, 300); -}); -test("_initEvents,_proxyDomEvent--click", function () { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - expect(1); - stop(); - editor.addListener('click', function () { - ok(true, 'click event dispatched'); - - start(); - }); - ua.click(editor.body); - }); -}); -test('绑定事件', function () { - document.onmouseup = function (event) { - ok(true, "mouseup is fired"); - }; - document.onmousedown = function (event) { - ok(true, "mousedown is fired"); - }; -// document.onmouseover = function (event) { -// ok(true, "mouseover is fired"); -// }; - document.onkeydown = function (event) { - ok(true, "keydown is fired"); - }; - document.onkeyup = function (event) { - ok(true, "keyup is fired"); - }; - var editor = new UM.Editor({'autoFloatEnabled': false}); - var div = document.body.appendChild(document.createElement('div')); - div.id = 'event'; - editor.render('event'); - expect(4); - editor.ready(function () { - setTimeout(function () { - editor.focus(); - ua.mousedown(document.body); - ua.mouseup(document.body); -// ua.mouseover(document.body); - ua.keydown(document.body, {'keyCode': 13}); - ua.keyup(document.body, {'keyCode': 13}); - setTimeout(function () { - document.getElementById('event') && te.dom.push(document.getElementById('event')); - start(); - }, 1000); - }, 50); - }); - stop(); -}); - diff --git a/_test/core/EventBase.js b/_test/core/EventBase.js deleted file mode 100644 index 5a404d0a..00000000 --- a/_test/core/EventBase.js +++ /dev/null @@ -1,102 +0,0 @@ -module( "EventBase" ); - -test( "addListener,fireEvent", function() { - var editor = te.obj[1]; - var div = te.dom[0]; - expect(6); - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - - editor.addListener("event1", function () { - ok(true, "listener1 is fired"); - }); - editor.addListener("event2", function () { - ok(true, "listener2 is fired"); - }); - editor.fireEvent("event1"); - editor.fireEvent("event2"); - - editor.fireEvent("event1 event2"); - var fun = function (type) { - ok(true, type + " is fired"); - }; - editor.addListener("event3 event4 ", fun); - editor.fireEvent("event3 event4 "); - start(); - }); -} ); - -test( "addListener,fireEvent --同一个侦听器绑定多个事件", function() { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render( div ); - expect( 2 ); - stop(); - editor.ready(function () { - editor.focus(); - editor.addListener( "event1", function() { - ok( true, "listener1 is fired" ); - } ); - editor.addListener( "event1", function() { - ok( true, "listener2 is fired" ); - } ); - editor.fireEvent( "event1" ); - start(); - }); -} ); - -test( "removeListener", function() { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render( div); - expect(3); - stop(); - editor.ready(function () { - editor.focus(); - function fun1() { - ok(true, "listener1 is fired"); - } - - function fun2() { - ok(true, "listener2 is fired"); - } - - editor.addListener("event1", fun1); - editor.addListener("event1", fun2); - editor.fireEvent("event1"); - - editor.removeListener("event1", fun1); - editor.fireEvent("event1"); - - function fun(type) { - ok(true, type + " is fired"); - } - - editor.addListener("event3 event4 ", fun); - editor.removeListener("event3 event4 ", fun); - editor.fireEvent("event3 event4 "); - start(); - }); -} ); - - -test( "fireEvent--nolisteners", function() { - var editor = te.obj[1]; - var div = te.dom[0]; - editor.render(div); - stop(); - editor.ready(function () { - editor.focus(); - function fun1() { - ok(true, "listener1 is fired"); - } - - editor.fireEvent("event1");//no listener is fired - editor.addListener("event1", fun1); - editor.fireEvent("event1");//listener1 and listener2 are both fired - start(); - }); -} ); - diff --git a/_test/core/Range.js b/_test/core/Range.js deleted file mode 100644 index 40764b23..00000000 --- a/_test/core/Range.js +++ /dev/null @@ -1,776 +0,0 @@ -module('core.Range'); - -//test('', function () { -// stop() -//});/* -var checkBookmark = function (bookmark, pre, latter, id) { - same(bookmark['start'], pre, '检查start返回值'); - same(bookmark['end'], latter, '检查end返回值'); - equal(bookmark['id'], id, '检查id'); -}; - -test('init', function () { - expect(6); - var div = te.dom[2]; - var range = new UM.dom.Range(document); - ua.checkResult(range, null, null, null, null, true, 'for init range'); - same(range.document, document, 'check current document of range'); -}); - -/* 删除当前选区范围中的所有内容*/ -test('deleteContents--删除空', function () { - var div = te.dom[2]; - - var range = new UM.dom.Range(document); - div.innerHTML = '

p_text

'; - var p_text = div.firstChild.firstChild; - range.setStart(p_text, 2).setEnd(p_text, 2); - range.deleteContents(); - ua.checkResult(range, p_text, p_text, 2, 2, true, '删除空'); - equal(ua.getHTML(div), '

p_text

', 'div的innerHTML没有改变 '); -}); - -test('deleteContents--删除相邻节点之间的内容', function () { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function(){ - var div = te.dom[2]; - var html = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - div.innerHTML = html; - var r = new UM.dom.Range(editor.document); - var two = document.getElementById('two'); - var last = document.getElementById('last'); - r.setStart(two, 1).setEnd(last, 2); - r.deleteContents(); - ua.checkSameHtml(ua.getHTML(div), '

first strong strong second em strong.

bar

some textem textmore text

1abc

'); - - ua.checkResult(r, div, div, 4, 4, true, '删除相邻节点的内容'); - - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - - }); - stop(); -}); - - -test('deleteContents--删除子节点', function () { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function(){ - var div = te.dom[2]; - var html = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - div.innerHTML = html; - var r = new UM.dom.Range(document); - - r.setStart(div, 0).setEnd(div, 2); - r.deleteContents(); - ua.checkSameHtml(ua.getHTML(r.startContainer), '

some textem textmore text

1abc
34

textabcspan

'); - - ua.checkResult(r, div, div, 0, 0, true, '删除子节点的内容'); - - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - - }); - stop(); -}); - - -test('deleteContents--删除同一文本节点内容', function () { - var div = te.dom[2]; - var html = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - div.innerHTML = html; - var r = new UM.dom.Range(document); - var p = div.firstChild; - var strong_text = document.getElementById('strong').firstChild; - r.setStart(strong_text, 0).setEnd(strong_text, 2); - r.deleteContents(); - equals(ua.getHTML(r.startContainer), 'rong'); - - ua.checkSameHtml(ua.getHTML(div), '

first strong rong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'); - ua.checkResult(r, strong_text, strong_text, 0, 0, true, '删除子节点的内容'); -}); - -test('deleteContents--startContainer是endContainer父亲', function () { - var div = te.dom[2]; - var r = new UM.dom.Range(document); - div.innerHTML = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - r.setStart(div, 0); - r.setEnd(document.getElementById('traverse'), 2); - r.deleteContents(); - ua.checkSameHtml(ua.getHTML(div), '

more text

1abc
34

textabcspan

'); - ua.checkResult(r, div, div, 0, 0, true, 'startContainer是endContainer父亲'); -}); - -test('deleteContents--startContainer和endContainer为不同文本节点', function () { - var div = te.dom[2]; - var html = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - div.innerHTML = html; - var r = new UM.dom.Range(document); - var first = document.getElementById('first'); - r.setStart(first.firstChild, 1).setEnd(first.lastChild, 4); - var p = div.firstChild; - r.deleteContents(); - equals(ua.getHTML(r.startContainer), '

fong.

'); - ua.checkResult(r, p, p, 1, 1, true, 'startContainer和endContainer为文本节点内容'); - ua.checkSameHtml(ua.getHTML(div), '

fong.

bar

some textem textmore text

1abc
34

textabcspan

'); - equals(ua.getHTML(r.endContainer), '

fong.

'); -}); - - -test('deleteContents--startContainer是endContainer后代', function () { - var div = te.dom[2]; - var html = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - div.innerHTML = html; - var r = new UM.dom.Range(document); - var em = document.getElementById('em'); - r.setStart(em, 1).setEnd(div, 3); - r.deleteContents(); - ua.checkSameHtml(ua.getHTML(r.startContainer), '

first strong strong second em

1abc
34

textabcspan

'); - ua.checkResult(r, div, div, 1, 1, true, 'startContainer是endContainer后代'); -}); - -test('deleteContents--startContainer是文本,endContainer的nodeType=1', function () { - var div = te.dom[2]; - var html = '

first strong strong second em strong.

bar

some textem textmore text

1abc
34

textabcspan

'; - div.innerHTML = html; - var r = new UM.dom.Range(document); - var em = document.getElementById('em').firstChild; - var two = document.getElementById('two'); - r.setStart(em, 1).setEnd(two, 0); - r.deleteContents(); - ua.checkSameHtml(ua.getHTML(r.startContainer), '

first strong strong second e

abc
34

textabcspan

'); - ua.checkResult(r, div, div, 1, 1, true, 'startContainer是文本,endContainer的nodeType=1'); -}); - -test('setStart/startEnd 自闭合元素', function () { - var range = new UM.dom.Range(document); - var div = te.dom[2]; - var img = document.createElement('img'); - div.appendChild(img); - range.setStart(img, 0); - ua.checkResult(range, div, div, 0, 0, true, "endContainer is null"); - range.setEnd(img, 0); - ua.checkResult(range, div, div, 0, 1, false, "startContainer is not null"); - range.startContainer = null; - range.setEnd(img, 0); - ua.checkResult(range, div, div, 1, 1, true, "startContainer is null"); - range.setStart(img, 0); - ua.checkResult(range, div, div, 0, 1, false, "endContainer is not null"); -}); - -test('setStart/startEnd--nodeType不为1', function () { - var range = new UM.dom.Range(document); - var div = te.dom[2]; - var text = document.createTextNode("text"); - div.appendChild(text); - range.setStart(text, 0); - ua.checkResult(range, text, text, 0, 0, true, "endContainer is null"); - range.setEnd(text, 1); - ua.checkResult(range, text, text, 0, 1, false, "startContainer is not null"); -}); - -test('setStart/setEnd--nodeType为1', function () { - var range = new UM.dom.Range(document); - var div = te.dom[2]; - range.setStart(div, 0); - ua.checkResult(range, div, div, 0, 0, true, "endContainer is null"); - range.setEnd(div, 1); - ua.checkResult(range, div, div, 0, 1, false, "startContainer is not null"); -}); -/* -* 测的内容比较多,updateCollapse,setEndPoint,setStart,setEnd,collapse -* 因为updateCollapse和setEndPoint无法通过Range对象获取, 必须间接调用验证 -*/ -test('setStartAfter,setStartBefore', function () { - var div = te.dom[2]; - div.innerHTML = '
'; - var span = div.firstChild; - var a = div.lastChild; - var range = new UM.dom.Range(document); - range.setStartAfter(a); - equal(range.startOffset, 2, 'check startOffset for setStartAfter--boundary testing'); - range.setStartAfter(span); - equal(range.startOffset, 1, 'check startOffset for setStartAfter'); - range.setStartBefore(span); - equal(range.startOffset, 0, 'check startOffset for setStartBefore--boundary testing'); - range.setStartBefore(a); - equal(range.startOffset, 1, 'check startOffset for setStartBefore'); - var txtNode = document.createTextNode("text"); - div.innerHTML = ""; - div.appendChild(txtNode); - range.setStartBefore(txtNode); - equal(range.startOffset, 0, 'check startOffset in text node'); -}); - -test('setEndAfter,setEndBefore', function () { - var div = te.dom[2]; - div.innerHTML = ''; - var span = div.firstChild; - var a = div.lastChild; - var range = new UM.dom.Range(document); - range.setEndAfter(a); - equal(range.endOffset, 2, 'check startOffset for setEndAfter--boundary testing'); - range.setEndAfter(span); - equal(range.endOffset, 1, 'check startOffset for setEndAfter'); - range.setEndBefore(span); - equal(range.endOffset, 0, 'check startOffset for setEndBefore--boundary testing'); - range.setEndBefore(a); - equal(range.endOffset, 1, 'check startOffset for setEndBefore'); -}); - -/* 校验collapse方法 */ -test('collapse', function () { - var text = document.createTextNode('TextNode'); - te.dom[2].appendChild(text); - var range = new UM.dom.Range(document); - range.setStart(text, 1); -// ua.checkResult(range.endContainer,range.startContainer,0) - ok(range.collapsed, 'check collapse method true--setStart'); - equal(range.startContainer, range.endContainer, 'compare startContainer and endContainer--setStart'); - range.startContainer = null; - range.setEnd(text, 0); - equal(range.startContainer, range.endContainer, 'compare startContainer and endContainer--setEnd'); - equal(range.startOffset, range.endOffset, 'compare startOffset and endOffset--setEnd'); - ok(range.collapsed, 'check collapsed is true--setEnd'); - var img = document.createElement("img"); - range.insertNode(img).selectNode(img); - equal(range.startContainer, range.endContainer, "img startContainer and endContainer is same,but startOffset and endOffset is not same"); -}); - -//TODO 空节点
- -test('selectNode', function () { - var div = te.dom[2]; - div.innerHTML = "text!"; - div.id = 'div_id'; - var range = new UM.dom.Range(document); - range.selectNode(div); - var index = ua.getIndex(div); - ua.checkResult(range, document.body, document.body, index, index + 1, false, 'check selectNode'); -}); - -test('selectNode--空节点', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - range.selectNode(div); - var index = ua.getIndex(div); - ua.checkResult(range, document.body, document.body, index, index + 1, false, 'check selectNode'); -}); - -test('selectNode--空文本节点', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - var textNode = document.createTextNode(''); - div.appendChild(textNode); - range.selectNode(div); - var index = ua.getIndex(div); - ua.checkResult(range, document.body, document.body, index, index + 1, false, 'check selectNode'); -}); - -test('selectNodeContents', function () { - expect(15); - var div = te.dom[2]; - div.innerHTML = '
text
'; - var text = div.firstChild.firstChild; - var range = new UM.dom.Range(document); - range = range.selectNodeContents(div); - ua.checkResult(range, div, div, 0, 2, false, 'selectNodeContents'); - /*textNode*/ - range = range.selectNodeContents((text)); - ua.checkResult(range, text, text, 0, 4, false, 'selectNodeContents for textNode'); - div.innerHTML = 'xxxxxxxxx'; - range = new UM.dom.Range(document); - range = range.selectNodeContents(div.firstChild); - ua.checkResult(range, div.firstChild, div.firstChild, 0, 3, false, 'selectNodeContents'); - -}); - - -test('cloneRange', function () { - expect(5); - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = '
cloneRange
'; - range.setStart(div, 0); - range.setEnd(div, 1); - var cloneRange = range.cloneRange(range); - ua.checkResult(range, cloneRange.startContainer, cloneRange.endContainer, - cloneRange.startOffset, cloneRange.endOffset, false, 'cloneRange'); -}); - - -/*循环缩进子节点,直到子节点元素类型不为1或为自闭合元素*/ -test('shrinkBoundary--not ignore end', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); -// $('#test').css('background','red'); - div.innerHTML = '
div1_text
a_text
span_textdiv3_text
'; - - var a = div.firstChild.nextSibling; - var div_2 = div.lastChild; - range.setStart(div, 1).setEnd(div, 3); - range.shrinkBoundary(); - ua.checkResult(range, a, div_2, 0, 2, false, 'shrinkBoundary--not ignore end'); -}); - -test('shrinkBoundary--ignoreEnd', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = "

p_text

"; - var div_child = div.firstChild; - var p = div_child.firstChild; - range.setStart(div_child, 0).setEnd(div_child, 0); - //TODO - range.shrinkBoundary(true); - ua.checkResult(range, p, p, 0, 0, true, '检查前后闭合是否一致'); -}); -test('shrinkBonudaryl', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'xxxxxxxxxxx'; - /*ignoreEnd=true*/ - range.selectNodeContents(div).shrinkBoundary(true); - - var i = div.firstChild.firstChild; - ua.checkResult(range, i, div, 0, 1, false, 'shrinkBoundary--ignoreEnd'); - /*ignoreEnd = null*/ - var b = div.firstChild; - range.selectNodeContents(div).shrinkBoundary(); - ua.checkResult(range, i, b, 0, b.childNodes.length, false, 'shrinkBoundary--not ignoreEnd'); - - div.innerHTML = 'xxxxssss'; - var u = div.getElementsByTagName('u')[0]; - range.selectNode(div.getElementsByTagName('b')[0]).shrinkBoundary(); - ua.checkResult(range, u, u, 0, 0, true, '初始startContainer和endContainer相同'); - - div.innerHTML = '
sssss
'; - var td = div.getElementsByTagName('td')[0]; - var table = div.firstChild; - range.setStart(table, 0).setEnd(table.getElementsByTagName('tr')[0], 1).shrinkBoundary(); - ua.checkResult(range, td, td, 0, 1, false, '初始startContainer和endContainer不同'); - - div.innerHTML = ''; - range.setStart(div, 0).setEnd(div, 1).shrinkBoundary(); - ua.checkResult(range, div, div, 0, 1, false, '子节点为自闭合元素,未能进入函数内部的逻辑'); - - div.innerHTML = 'text'; - var text = div.firstChild; - range.setStart(text, 1).setEnd(text, 4).shrinkBoundary(); - ua.checkResult(range, text, text, 1, 4, false, '节点为文本节点,未能进入函数内部的逻辑'); - - range.setStart(div, 0).setEnd(div, 1).shrinkBoundary(); - ua.checkResult(range, div, div, 0, 1, false, '子节点为文本节点,未能进入函数内部的逻辑'); - - range.setStart(div, 0).setEnd(div, 0).shrinkBoundary(); - ua.checkResult(range, div, div, 0, 0, true, '元素collapsed'); - - range.setStart(div, 0).setEnd(text, 4).shrinkBoundary(); - ua.checkResult(range, div, text, 0, 4, false, 'endContainer为文本节点'); -}); - - -/*调整边界,针对TextNode*/ -test('txtToElmBoundary', function () { - var div = te.dom[2]; - div.innerHTML = 'text_node'; - var range = new UM.dom.Range(document); - var text = div.firstChild; - /*endOffset大于text的长度*/ - range.setStart(text, 0).setEnd(text, 10); - range.txtToElmBoundary(); - ua.checkResult(range, div, div, 0, 1, false, 'endOffset大于text的长度'); - /*endOffset小于text的长度*/ - range.setStart(text, 1).setEnd(text, 4).txtToElmBoundary(); - ua.checkResult(range, text, text, 1, 4, false, 'endOffset小于text长度'); - range.setStart(text, 1).setEnd(text, 10).txtToElmBoundary(); - ua.checkResult(range, text, div, 1, 1, false, 'startOffset不为0,endOffset大于text长度'); - /*startOffset和endOffset都大于text长度*/ - range.setStart(text, 10).setEnd(text, 11).txtToElmBoundary(); - ua.checkResult(range, div, div, 1, 1, true, 'endOffset和startOffset大于text长度'); - /*startOffset和endOffset都等于0*/ - range.setStart(text, 0).setEnd(text, 0).txtToElmBoundary(); - ua.checkResult(range, text, text, 0, 0, true, 'startOffset和endOffset为0'); -}); - -/*切分文本节点*/ -test('trimBonudary', function () { - var div = te.dom[2]; - div.innerHTML = '
td_xxxxu_text
'; - var range = new UM.dom.Range(document,document.body); - var td = div.getElementsByTagName('td')[0]; - var td_text = td.firstChild; - /*startOffset为0,在第一个孩子节点前插入*/ - range.setStart(td_text, 0).setEnd(td_text, 5); - - range.trimBoundary(); - ua.checkResult(range, td, td, 0, 1, false, '切分文本节点'); - /*text_node被切分为2个文本节点*/ - equal(td_text.data, "td_xx", "check text of tr"); - - var u = div.getElementsByTagName('u')[0]; - var u_text = u.firstChild; - - /*startOffset=0 && collapsed=true,则不对后面的文本节点进行操作*/ - range.setStart(u_text, 0).setEnd(u_text, 0); - range.trimBoundary(); - ua.checkResult(range, u, u, 0, 0, true, 'startOffset=endOffset=0'); - - /*endOffset大于text的长度,从左边切'*/ - range.setStart(u_text, 3).setEnd(u_text, 10); - range.trimBoundary().select(); - ua.checkResult(range, u, u, 1, 2, false, 'endOffset大于text的长度'); - equal(u_text.data, 'u_t', '从左边切分textNode'); - - /*endOffset大小于text的长度,从中间切'*/ - range.setStart(u_text, 1).setEnd(u_text, 2); - range.trimBoundary(); - ua.checkResult(range, u, u, 1, 2, false, 'endOffset小于text的长度'); - equal(u_text.data, 'u', '从中间切分textNode'); - - div.innerHTML = '123456'; - range.setStart(div.firstChild, 2).setEnd(div.firstChild, 4).trimBoundary(true); - ua.checkResult(range, div, div.lastChild, 1, 2, false, 'ignoreEnd'); -}); - -/*前面尽可能往右边跳,后面尽可能往左边跳*/ -test('adjustmentBoundary--startContainer为文本节点', function () { - //adjustmentBoundary用到isbody,需要渲染编辑器才能用 - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

span_text

div_text2

p_textem_text

'); - var span_text = document.getElementById('span').firstChild; - var p = document.getElementById('p'); - range.setStart(span_text, 9).setEnd(p, 0); - range.adjustmentBoundary(); - ua.checkResult(range, editor.body, editor.body, 1, 2, false, 'startContainer为文本节点'); - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }); - stop(); -}); - -//TODO -test('adjustmentBoundary--非文本节点', function () { - var range = new UM.dom.Range(document); - var div = te.dom[2]; - div.innerHTML = 'div_text

span_text

div_text2

p_textem_text

'; - var span = document.getElementById('span'); - var p = document.getElementById('p'); - range.setStart(span, 1).setEnd(p, 0); - range.adjustmentBoundary(); - ua.checkResult(range, div, div, 2, 3, false, 'startContainer为非文本节点'); - -}); -test('selectNodeContents', function () { - var div = te.dom[2]; - div.innerHTML = 'xxxxdiv_text'; - var range = new UM.dom.Range(document); - /*选中非文本节点*/ - range.selectNodeContents(div); - ua.checkResult(range, div, div, 0, 2, false, 'selectNodeContents'); - /*选中文本节点*/ - range.selectNodeContents(div.lastChild); - ua.checkResult(range, div.lastChild, div.lastChild, 0, 8, false, 'selectNodeContents--'); -}); - -test('insertNode--文本中插入', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'div_text1

p_text

xxxem_textxxxxxxxxxxx|xxx

bbbbb

text2_div'; - var p_text = div.firstChild.nextSibling.firstChild; - range.setStart(p_text, 1).setEnd(p_text, 2); - /*插入块元素*/ - var new_div = document.createElement('div'); - range.insertNode(new_div); - - ua.checkResult(range, p_text.parentNode, new_div.nextSibling, 1, 1, false, '插入div'); - - /*插入文本节点,原来闭合*/ - var em_text = div.getElementsByTagName('em')[0].firstChild; - range.setStart(em_text, 0).setEnd(em_text, 0); - range.insertNode(document.createTextNode('new_text')); - ua.checkResult(range, em_text.parentNode, em_text.parentNode, 0, 1, false, '闭合情况下插入文本'); - /*插入inline元素*/ - range.setStart(div.firstChild, 1).setEnd(div.lastChild, 1); - range.insertNode(document.createElement('i')); - ua.checkResult(range, div, div.lastChild, 1, 1, false, '插入inline元素'); -}); - -test('inserNode--块元素中插入', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'div_text1

p_text

xxxem_textxxxxxxxxxxx|xxx

bbbbb

text2_div'; -// var p_text = div.firstChild.nextSibling.firstChild; - range.setStart(div, 1).setEnd(div.lastChild, 2); - /*插入块元素*/ - var new_div = document.createElement('div'); - range.insertNode(new_div); - - ua.checkResult(range, div, div.lastChild, 1, 2, false, '插入div'); - -}); - -test('insertNode--插入的节点为endContainer孩子', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'xxx

xxxxx

xxxxxxxxxxxxxxxxx|xxx

bbbbb

xx'; - var length = div.childNodes.length; - range.setStart(div, 1).setEnd(div, length); - var new_div = document.createElement('div'); - new_div.innerHTML = 'xxxx
div_text
i_textem_textxxxx'; - range.insertNode(new_div); - ua.checkResult(range, div, div, 1, length + 1, false, '插入节点为endContainer的孩子'); - equal(ua.getHTML(div), '
xxx
xxxx
div_text
i_textem_textxxxx

xxxxx

xxxxxxxxxxxxxxxxx|xxx

bbbbb

xx
') -}); - -test('insertNode--插入的fragment为endContainer孩子', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - var frag = document.createDocumentFragment(); - - div.innerHTML = 'xxx

xxxxx

xxxxxxxxxxxxxxxxx|xxx

bbbbb

xx'; - var length = div.childNodes.length; - range.setStart(div, 1).setEnd(div, div.childNodes.length); - var new_div = document.createElement('div'); - frag.appendChild(new_div); - frag.appendChild(document.createTextNode('text')); - frag.appendChild(document.createElement('span')); - range.insertNode(frag); - ua.checkResult(range, div, div, 1, length + 3, false, '插入fragment为endContainer的孩子'); - equal(ua.getHTML(div), '
xxx
text

xxxxx

xxxxxxxxxxxxxxxxx|xxx

bbbbb

xx
', '比较innerHTML'); -}); - -test('createBookmark/moveToBookmark--元素不闭合', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'first_texti_textxxxxxxxspan_text

em_textp_text

'; - var bookmark = range.selectNode(div).createBookmark(); - ua.checkResult(range, document.body, document.body, ua.getIndex(div), ua.getIndex(div) + 1, false, "元素不闭合,创建书签"); - ok(/_baidu_bookmark_start_/.test(div.previousSibling.id), '检查div的前一个兄弟'); - ok(/_baidu_bookmark_end_/.test(div.nextSibling.id), '检查div的后一个兄弟'); - /*moveToBookmark*/ - range.moveToBookmark(bookmark); - ua.checkResult(range, document.body, document.body, ua.getIndex(div), ua.getIndex(div) + 1, false, "元素不闭合,删除书签"); - ok(!/_baidu_bookmark_start_/.test(div.previousSibling.id), '检查div的前面书签是否被删除'); - - range.setStart(div, 2).setEnd(div, 3); - var bookmark = range.createBookmark(true); - ua.checkResult(range, div, div, 3, 4, false, "元素不闭合,插入span"); - var preId = document.getElementById('span').previousSibling.id; - var latterId = document.getElementById('span').nextSibling.id; - var reg = /_baidu_bookmark_start_/; - ok(/_baidu_bookmark_start_/.test(preId), '检查前面span的id'); - ok(/_baidu_bookmark_end_/.test(latterId), '检查后面span的id'); - checkBookmark(bookmark, preId, latterId, true); - - range.moveToBookmark(bookmark); - ua.checkResult(range, div, div, 2, 3, false, 'moveToBookmark'); - equal(ua.getHTML(div), '
first_texti_textxxxxxxxspan_text

em_textp_text

'); - -}); -test('createBookmark/moveToBookmark--span嵌套', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'first_texti_textxxxxxxxspan_text

em_textp_text

'; - var span = document.getElementById('span'); - range.setStart(span, 0).setEnd(span, 1); - var bookmark = range.createBookmark(); - var pre = span.firstChild; - var latter = span.lastChild; - ua.checkResult(range, span, span, 1, 2, false, 'span嵌套'); - ok(/_baidu_bookmark_start_/.test(pre.id), '检查前面span的id'); - ok(/_baidu_bookmark_end_/.test(latter.id), '检查后面span的id'); - checkBookmark(bookmark, pre, latter, undefined); -}); - -test('createBookmark/moveToBookmark--元素闭合', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'first_texti_textxxxxxxxspan_text

em_textp_text

'; - var em_text = document.getElementById('em').firstChild; - var em = em_text.parentNode; - range.setStart(em_text, 1).setEnd(em_text, 1); - var bookmark = range.createBookmark(true, true); - ua.checkResult(range, em, em, 2, 2, true, '元素闭合'); - var pre = em.firstChild.nextSibling; - checkBookmark(bookmark, pre.id, null, true); - equal('_baidu_bookmark_start_', pre.id, '检查前面span的id'); - -}); -test('getClosedNode', function () { - var div = te.dom[2]; - var range = new UM.dom.Range(document); - div.innerHTML = 'xxxxxxxxxx'; - range.setStart(div, 2).setEnd(div, 3); - same(range.getClosedNode(), div.lastChild.previousSibling, 'check result is img'); - - range.setStart(div, 2).collapse(true); - equal(range.getClosedNode(), null, 'check null return result'); - - range.setStart(div, 0).setEnd(div, 1); - equal(range.getClosedNode(), null, 'get null result'); - -}); -test('b节点取range', function () { - var div = te.dom[2]; - var editor = new UM.Editor({'autoFloatEnabled':false}); - stop(); - editor.render(div); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

hellohello1hello2

'); - range.setStart(editor.body.firstChild.lastChild, 0).collapse(1).select(); - range = editor.selection.getRange(); - if ((ua.browser.ie &&ua.browser.ie < 9) || ua.browser.webkit) - ua.checkResult(range, editor.body.firstChild.lastChild.previousSibling, editor.body.firstChild.lastChild.previousSibling, 1, 1, true, '节点后--check range'); - else if(ua.browser.ie &&ua.browser.ie > 8)//todo ie9,10改range - ua.checkResult(range, editor.body.firstChild, editor.body.firstChild, 3, 3, true, '节点后--check range'); - else - ua.checkResult(range, editor.body.firstChild.lastChild.previousSibling, editor.body.firstChild.lastChild.previousSibling, 0, 0, true, '节点后--check range'); - - range.setStart(editor.body.firstChild.firstChild.nextSibling, 0).collapse(1) - range.select(); - range = editor.selection.getRange(); - if (ua.browser.webkit) - ua.checkResult(range, editor.body.firstChild.firstChild.nextSibling.firstChild, editor.body.firstChild.firstChild.nextSibling.firstChild, 1, 1, true, '节点内文本节点前--check range'); - else if (ua.browser.ie&&ua.browser.ie < 9) - ua.checkResult(range, editor.body.firstChild.childNodes[1].childNodes[1], editor.body.firstChild.childNodes[1].childNodes[1], 0, 0, true, '节点内文本节点前--check range'); - else if(ua.browser.ie &&ua.browser.ie > 8)//todo ie9,10改range - ua.checkResult(range, editor.body.firstChild.childNodes[1], editor.body.firstChild.childNodes[1], 1, 1, true, '节点内文本节点前--check range'); - else - ua.checkResult(range, editor.body.firstChild.firstChild.nextSibling.firstChild, editor.body.firstChild.firstChild.nextSibling.firstChild, 0, 0, true, '节点内文本节点前--check range'); - - range.setStart(editor.body.firstChild.childNodes[1], 0).collapse(1).select(); - range = editor.selection.getRange(); - if (ua.browser.webkit) - ua.checkResult(range, editor.body.firstChild.childNodes[1].firstChild, editor.body.firstChild.childNodes[1].firstChild, 1, 1, true, 'b节点--check range'); - else if (ua.browser.ie&&ua.browser.ie < 9) - ua.checkResult(range, editor.body.firstChild.childNodes[1].childNodes[1], editor.body.firstChild.childNodes[1].childNodes[1], 0, 0, true, '节点内文本节点前--check range'); - else if(ua.browser.ie &&ua.browser.ie > 8)//todo ie9,10改range - ua.checkResult(range, editor.body.firstChild.childNodes[1], editor.body.firstChild.childNodes[1], 1, 1, true, '节点内文本节点前--check range'); - else - ua.checkResult(range, editor.body.firstChild.childNodes[1].firstChild, editor.body.firstChild.childNodes[1].firstChild, 0, 0, true, 'b节点--check range'); - start(); - }); -}); - -test('文本节点中间取range', function () { - var div = te.dom[2]; - var editor = new UM.Editor({'autoFloatEnabled':false}); - stop(); - editor.render(div); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

hello2

'); - range.setStart(editor.body.firstChild.firstChild, 2).collapse(1).select(); - range = editor.selection.getRange(); if (ua.browser.ie&&ua.browser.ie < 9) - ua.checkResult(range, editor.body.firstChild.lastChild, editor.body.firstChild.lastChild, 0, 0, true, 'check range'); - else if(ua.browser.ie &&ua.browser.ie > 8)//todo ie9,10改range - ua.checkResult(range, editor.body.firstChild, editor.body.firstChild, 2, 2, true, 'check range'); - else - ua.checkResult(range, editor.body.firstChild.lastChild, editor.body.firstChild.lastChild, 2, 2, true, 'check range'); - start(); - }); -}); - -//test( 'select--closedNode', function() { -// var div = te.dom[2]; -// var range = new UM.dom.Range( document ); -// div.innerHTML = 'div_textspan_textdiv2_textem_text'; -//// range.setStart(div.getElementsBytagName('img'),0).setEnd(div.) -//// var span = div.firstChild.nextSibling; -//// range.setStart(span,1).setEnd(div,4); -//// range.select(); -//// -//// ua.checkResult(range,span,div,1,4,false,'check range'); -//// range.insertNode(document.createTextNode('aa')); -//// var selection = new UM.dom.Selection( document ); -//// var nativeRange = selection.getRange(); -// //TODO -//} ); - -test('range.createAddress,range.moveAddress', function () { - function equalRange(rngA, rngB) { - return rngA.startContainer === rngB.startContainer && rngA.startOffset === rngB.startOffset - && rngA.endContainer === rngB.endContainer && rngA.endOffset === rngB.endOffset - - } - - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.body,editor.body); - editor.setContent('xxxx'); - var addr = range.setStart(editor.body.firstChild.firstChild, 0).collapse(true).createAddress(true); - var range1 = new UM.dom.Range(editor.body,editor.body); - range1.moveToAddress(addr); - ok(equalRange(range, range1)); - editor.setContent('aaa'); - editor.body.appendChild(document.createTextNode('aaa')); - editor.body.appendChild(document.createTextNode('aaa')); - addr = range.setStart(editor.body.lastChild, 0).setEnd(editor.body.lastChild, editor.body.lastChild.nodeValue.length).createAddress(); - range1.moveToAddress(addr); - ok(equalRange(range, range1)); - - editor.focus(); - addr = range.setStart(div.lastChild, 0).setEnd(div.lastChild, div.lastChild.nodeValue.length).createAddress(false, true); - editor.body.innerHTML = 'aaaaaabbb'; - range1.moveToAddress(addr); - - editor.body.innerHTML = 'aaaaaabbbsss'; - if(div.lastChild.nodeName == '#text' && domUtils.isWhitespace(div.lastChild)){ - domUtils.remove(div.lastChild) - } - addr = range.setStartAfter(div.lastChild.firstChild).collapse(true).createAddress(false); - range1.moveToAddress(addr); - ok(equalRange(range, range1)); - editor.body.innerHTML = ''; - editor.body.appendChild(document.createTextNode(domUtils.fillChar)); - editor.body.appendChild(document.createTextNode('aaa')); - addr = range.setStartAtLast(div).collapse(true).createAddress(false, true); - editor.body.innerHTML = 'aaa'; - range1.moveToAddress(addr); - range.setStartAtLast(div).collapse(true); - ok(equalRange(range, range1)); - editor.body.innerHTML = 'aaasss'; - editor.body.appendChild(document.createTextNode(domUtils.fillChar)); - addr = range.setStartAtLast(div).collapse(true).createAddress(false, true); - editor.body.innerHTML = 'aaasss'; - range1.moveToAddress(addr); - range.setStartAtLast(div).collapse(true); - ok(equalRange(range, range1)); - editor.body.innerHTML = 'aaa'; - editor.body.appendChild(document.createTextNode(domUtils.fillChar)); - editor.body.appendChild(document.createTextNode('aaa')); - //空节点有占位 - addr = range.setStart(div.firstChild.nextSibling, 0).collapse(true).createAddress(false, true); - editor.body.innerHTML = 'aaaaaa'; - range1.moveToAddress(addr); - range.setStart(div.firstChild, 3).collapse(true); - ok(equalRange(range, range1)); - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }); - stop(); -}); - -test('equals', function () { - var div = te.dom[2]; - var rng = new UM.dom.Range(document); - div.innerHTML = 'xxxx'; - rng.setStart(div.firstChild, 0).collapse(true); - var rng2 = rng.cloneRange(); - ok(rng.equals(rng2)) -}); \ No newline at end of file diff --git a/_test/core/Selection.js b/_test/core/Selection.js deleted file mode 100644 index 78ed9dc9..00000000 --- a/_test/core/Selection.js +++ /dev/null @@ -1,145 +0,0 @@ -module("core.Selection"); - -test('getRange--闭合选区的边界情况', function () { - var div_new = document.createElement('div'); - document.body.appendChild(div_new); - var editor = new UM.Editor({'autoFloatEnabled': false}); - stop(); - setTimeout(function () { - editor.render(div_new); - editor.ready(function () { - setTimeout(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

xxx

'); - range.setStart(editor.body.firstChild.firstChild, 0).collapse(true).select(); - range = editor.selection.getRange(); - var strong = editor.body.firstChild.firstChild; - if(ua.browser.ie&&ua.browser.ie>8){//todo ie9,10改range - ok(range.startContainer === strong,'startContainer是strong'); - ok(range.startOffset == 1,'startOffset是1') - } - else{ - ok(range.startContainer.nodeType == 3, 'startContainer是文本节点'); - /*startContainer:ie is xxx,others are strong.firstChild*/ - ok(( range.startContainer === strong.firstChild) && strong.firstChild.length == 1 || (range.startContainer.nodeValue.length == 3 && range.startContainer === strong.lastChild), 'startContainer是xxx左边的占位符或者xxx'); - } - ua.manualDeleteFillData(editor.body); - range.setStart(editor.body.firstChild.firstChild, 1).collapse(true).select(); - /*去掉占位符*/ - range = editor.selection.getRange(); - /*可能为(strong,1)或者(xxx,3)*/ - ok(( range.startContainer === strong) || ( range.startContainer === strong.lastChild) && strong.lastChild.length == 1 || (range.startContainer.nodeValue.length == 3 && range.startContainer === strong.firstChild), 'startContainer是xxx或者xxx右边的占位符'); -// ok( range.startContainer.nodeType == 1 ? range.startContainer.tagName.toLowerCase() == 'strong' && range.startOffset == 1 : range.startContainer.data == 'xxx' && range.startOffset == 3, 'strong,1或xxx,3' ); - - ua.manualDeleteFillData(editor.body); - /*p,0*/ - range.setStart(editor.body.firstChild, 0).collapse(true).select(); - range = editor.selection.getRange(); - /*startContainer:ie is xxx,ff is p, chrome is strong*/ -// ok( ( range.startContainer === strong.parentNode.firstChild)&& strong.parentNode.firstChild.length == 1 || (range.startContainer.nodeValue.length == 3 && range.startContainer === strong.firstChild.nextSibling), 'startContainer是第一个占位符或者xxx' ); -// ua.manualDeleteFillData( editor.body ); -// range.setStart( editor.body.firstChild, 1 ).collapse( true ).select(); -// equal( range.startContainer.tagName.toLowerCase(), 'p', 'p,1' ); - - - te.dom.push(div_new); - te.obj.push(editor); - start(); - }, 50); - }); - }, 50); -}); - -test('trace 3628 isFocus', function () { - if(ua.browser.ie==8)return; //todo trace 3628 - if (!ua.browser.opera) { - var div1 = document.createElement('div'); - var div2 = document.createElement('div'); - document.body.appendChild(div1); - document.body.appendChild(div2); - var editor1 = new UM.Editor({'initialContent': 'hello', 'autoFloatEnabled': false}); - var editor2 = new UM.Editor({'initialContent': 'hello', 'autoFloatEnabled': false}); - editor1.render(div1); - stop(); - editor1.ready(function () { - editor2.render(div2); - editor2.ready(function () { - editor1.focus(); - ok(editor1.selection.isFocus(), '设editor内容是 editor1 is focused'); - ok(!editor2.selection.isFocus(), '设editor内容是 editor2 is not focused'); - editor2.focus(); - ok(editor2.selection.isFocus(), '设editor内容是 editor2 is focused'); - ok(!editor1.selection.isFocus(), '设editor内容是 editor1 is not focused'); - div1.parentNode.removeChild(div1); - div2.parentNode.removeChild(div2); - - var div3 = document.createElement('div'); - var div4 = document.createElement('div'); - document.body.appendChild(div3); - document.body.appendChild(div4); - var editor3 = new UM.Editor({'initialContent': '

hello

', 'autoFloatEnabled': false}); - var editor4 = new UM.Editor({'initialContent': '

hello

', 'autoFloatEnabled': false}); - editor3.render(div3); - editor3.ready(function () { - editor4.render(div4); - editor4.ready(function () { - editor3.focus(); - ok(editor3.selection.isFocus(), '设editor内容是

editor1 is focused'); - ok(!editor4.selection.isFocus(), '设editor内容是

editor2 is not focused'); - editor4.focus(); - ok(editor4.selection.isFocus(), '设editor内容是

editor2 is focused'); - ok(!editor3.selection.isFocus(), '设editor内容是

editor1 is not focused'); - setTimeout(function () { - div3.parentNode.removeChild(div3); - div4.parentNode.removeChild(div4); - start(); - }, 50); - }); - }); - }); - }); - } -}); - -test( 'getText', function() { - stop(); - setTimeout( function() { - var doc = te.dom[1].contentWindow.document; - var range = new UM.dom.Range( doc ,doc.body); - var div = doc.createElement( 'div' ); - doc.body.appendChild( div ); - div.innerHTML = 'spanTextfirstsecond'; - range.setStart( div.firstChild, 0 ).setEnd( div.lastChild, 1 ).select(); - var selection = new UM.dom.Selection( doc,doc.body ); - var text = selection.getText(); - equal( text, 'spanTextfirsts', 'check getText function' ); - start(); - }, 20 ); -} ); - - - -test('hasNativeRange', function () { - - var div_new = document.createElement('div'); - document.body.appendChild(div_new); - var editor = new UM.Editor({'autoFloatEnabled': false}); - stop(); - setTimeout(function () { - editor.render(div_new); - editor.ready(function () { - setTimeout(function () { - editor.focus(); - if(ua.browser.ie==8){//todo trace 3628 focus有问题,select代替 - var range = new UM.dom.Range( editor.document ,editor.body); - range.setStart(editor.body,0).collapse(true).select(); - } - ok(editor.selection.hasNativeRange()); - var rng = new UM.dom.Range(document,document.body); - rng.setStart(document.body,0).setCursor(); - ok(!editor.selection.hasNativeRange()); - start(); - }, 50); - }); - }, 50); -}); \ No newline at end of file diff --git a/_test/core/browser.js b/_test/core/browser.js deleted file mode 100644 index da67e06c..00000000 --- a/_test/core/browser.js +++ /dev/null @@ -1,70 +0,0 @@ -module( "core.browser" ); - - -test( 'browser', function() { - var browser = UM.browser; - /*ie*/ - if ( browser.ie ) { - ok(true, 'is ie' ); - var version = ua.browser.ie; - if(browser.version == 11){ - equal( browser.version, ua.browser.ie, 'check ie version' ); - } - if ( browser.version < 7 ) { - ok( browser.ie6Compat, 'ie6 compat mode' ); - equal( version, browser.version, 'check ie version' ); - } - if ( browser.version == 7 ) { - ok( browser.ie7Compat, 'ie7 compat mode' ); - equal( version, browser.version, 'check ie version' ); - ok( browser.isCompatible, 'is compatible' ); - } - switch ( document.documentMode ) { - case 7: - ok( browser.ie7Compat, 'ie7 document Mode' ); - equal( version, browser.version, 'check ie version' ); - ok( browser.isCompatible, 'is compatible' ); - break; - case 8: - ok( browser.ie8Compat, 'ie8 document Mode' ); - equal( version, browser.version, 'check ie version' ); - ok( browser.isCompatible, 'is compatible' ); - break; - case 9: - ok( browser.ie9Compat, 'ie9 document Mode' ); - equal( version, browser.version, 'check ie version' ); - ok( browser.isCompatible, 'is compatible' ); - break; - } - } - /*opera*/ - if ( browser.opera ) { - ok( ua.browser.opera, 'is opera' ); - equal( browser.version, ua.browser.opera, 'check opera version' ); - } - /*webKit*/ - if ( browser.webkit ) { - ok( ua.browser.webkit, 'is webkit' ); - equal( browser.webkit, ua.browser.webkit>0, 'check webkit version' ); - } - /*gecko*/ - if ( browser.gecko ) { - ok( ua.browser.gecko, 'is gecko' ); - equal( browser.gecko, !!ua.browser.gecko, 'check gecko version' ); - } -// /*air*/ -// if ( browser.air ) { -// ok( ua.browser.air, 'is air' ); -// equal( browser.air, ua.browser.air>0, 'check air version' ); -// } -// /*mac*/ -// if ( browser.mac ) { -// ok( ua.browser.air, 'is air' ); -// equal( ua.browser.os, 'macintosh', 'check air version' ); -// } - /*quirks*/ - if ( browser.quirks ) { - equal( document.compatMode, 'BackCompat', 'is quirks mode' ); - equal( browser.version, 6, 'ie version is 6' ); - } -} ); diff --git a/_test/core/domUtils.js b/_test/core/domUtils.js deleted file mode 100644 index 43e4ea97..00000000 --- a/_test/core/domUtils.js +++ /dev/null @@ -1,771 +0,0 @@ -module( 'core.domUtils' ); - -//test('', function () { -// stop() -//}); -test( 'getPosition--A和B是同一个节点', function() { - var div = te.dom[2]; - div.innerHTML = "spanbbbxxx"; - var span_text = div.firstChild.firstChild; - var domUtils = te.obj[3]; - equal( domUtils.getPosition( span_text, span_text ), 0, 'identical node' ); -} ); - - -test( 'getPosition--A和B是兄弟节点', function() { - var div = te.dom[2]; - div.innerHTML = "spanbbbxxx"; - var span_text = div.firstChild.firstChild; - var div_text = div.lastChild; - var domUtils = te.obj[3]; - /*span_text在div_text前面*/ - equal( domUtils.getPosition( span_text, div_text ), domUtils.POSITION_PRECEDING, 'preceding node' ); - /*div_text在span_text后面*/ - equal( domUtils.getPosition( div_text, span_text ), domUtils.POSITION_FOLLOWING, 'following node' ); -} ); - - -test( 'getPosition--A是B的祖先', function() { - var div = te.dom[2]; - div.innerHTML = "spanbbbxxx"; - var span_text = div.firstChild.firstChild; - var domUtils = te.obj[3]; - /*A是B的祖先*/ - equal( domUtils.getPosition( div, span_text ), domUtils.POSITION_CONTAINS + domUtils.POSITION_PRECEDING, 'preceding node' ); - /*A是B的子孙*/ - equal( domUtils.getPosition( span_text, div ), domUtils.POSITION_IS_CONTAINED + domUtils.POSITION_FOLLOWING, 'following node' ); -} ); - -test( 'getPosition--A和B在不同dom树上', function() { - stop(); - expect( 1 ); - var div = te.dom[2]; - div.innerHTML = "spanbbbxxx"; - var iframe = te.dom[1]; - setTimeout( function() { - var frame_doc = iframe.contentWindow.document || iframe.contentDocument; - var frame_div = frame_doc.createElement( 'div' ); - frame_doc.body.appendChild( frame_div ); - var domUtils = te.obj[3]; - /*A和B在不同dom树上*/ - equal( domUtils.getPosition( div, frame_div ) & 1, 1, 'A和B不在同一个dom树上' ); - start(); - }, 50 ); - -} ); - -test( 'getNodeIndex', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - div.innerHTML = 'dddddxxxxx


dddd

'; - var comment = div.firstChild.nextSibling.nextSibling; - equal( domUtils.getNodeIndex( comment ), 2, 'check commnet index' ); - var td_text = document.getElementById( 'table' ).firstChild.firstChild.firstChild; - equal( domUtils.getNodeIndex( td_text ), 0, 'check textNode index' ); - equal( domUtils.getNodeIndex( div.firstChild ), 0, 'check strong label index' ); - equal( domUtils.getNodeIndex( (document.getElementById( 'p' )) ), 5, 'check p label index' ); -} ); - -test( 'findParent--body', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var domUtils = UM.dom.domUtils; - equal(domUtils.findParent(editor.body), null, 'find parent for body'); - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }); - stop(); -} ); - -/*找符合条件的上一个节点,如果条件为空则找父节点*/ -test( 'findParent--tester为空', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = 'dddddspanxxxxx


dddd

'; - var span_text = document.getElementById( 'span' ).firstChild; - same( domUtils.findParent( span_text ), span_text.parentNode, 'find parent' ); -} ); - -test( 'findParent--tester不为空', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = 'dddddspanxxxxx


dddd

'; - var span_text = document.getElementById( 'span' ).firstChild; - var div1 = domUtils.findParent( span_text, function( node ) { - if ( node.id == "test" ) - return true; - return false; - } ); - same( div1, div, 'find parent' ); -} ); - - -/*不考虑includeSelf的时候取body的parent的情况*/ -test( 'findParentByTagName--body', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - same( domUtils.findParentByTagName( document.body, 'body' ), null, 'parent is self' ); -} ); - - -test( 'findParentByTagName--tagName为字符串', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = 'dddddspanxxxxx


dddd

'; - var br = document.getElementById( 'p' ).firstChild; - same( domUtils.findParentByTagName( br, 'div' ), div, 'tagName为字符串' ); - same( domUtils.findParentByTagName( br, 'em' ), null, 'tagName为字符串返回null' ); -} ); - -test( 'findParentByTagName--tagName为字符串数组', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = 'dddddspanxxxxx


dddd

'; - var br = document.getElementById( 'p' ).firstChild; - var tagName = ['em','p','div']; - same( domUtils.findParentByTagName( br, tagName ), document.getElementById( 'p' ), 'tagName为字符串数组,找出第一个符合条件的父节点' ); -} ); - - -test( 'findParentByTagName--文本节点', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = 'dddddspanxxxxx


dddd

'; - var span_text = document.getElementById( 'span' ).firstChild; - var tagName = ['em','p','div']; - same( domUtils.findParentByTagName( span_text, tagName ), div, '文本节点' ); -} ); - -test( 'findParents', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var domUtils = UM.dom.domUtils; - var div = editor.body; - div.innerHTML = 'dddddspanxxxxx


dddd

'; - var span_text = document.getElementById('span').firstChild; - /*includeSelf*/ - var parents = domUtils.findParents(span_text, true); - equal(parents.length, 3, 'check parent count'); - same(parents[0], editor.body, 'first parent is body'); - same(parents[1], document.getElementById('span'), 'second parent is div'); - same(parents[2], span_text, 'last parent is self'); - /*不逆序存放祖先节点,closerFirst=false*/ - parents = domUtils.findParents(span_text, false, null, true); - equal(parents.length, 2, 'check parent count'); - same(parents[0], document.getElementById('span'), 'first parent is span'); - same(parents[1], editor.body, 'last parent is body'); - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }); - stop(); -} ); - - -test( 'findParents--tester', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var domUtils = UM.dom.domUtils; - var div = editor.body; - div.innerHTML = '


dddd

'; - var img = document.getElementById('img'); - var parents = domUtils.findParents(img, false, function (node) { - if (node.tagName.toLowerCase() == 'div' || node.tagName.toLowerCase() == 'body') - return false; - return true; - }); - equal(parents.length, 1, 'check parent count'); - same(parents[0], div.firstChild.firstChild, 'first parent is p'); - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }); - stop(); -} ); - -test( 'insertAfter', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - var textNode = document.createTextNode( 'text' ); - domUtils.insertAfter( div, textNode ); - te.dom.push( textNode ); - equal( textNode, div.nextSibling, 'insertAfter' ); -} ); - -test( 'remove--not keep children', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = "

xxxxxxxxxxx

xxxx
"; - var text = div.firstChild.firstChild; - var p = div.firstChild; - /*删除文本节点*/ - var node = domUtils.remove( text ); - equal( ua.getChildHTML( div ), '

xxxxxxxx

xxxx
' ); - same( text, node, 'check removed textNode' ); - /*删除有孩子的节点*/ - node = domUtils.remove( p ); - equal( ua.getChildHTML( div ), '
xxxx
' ); - same( node, p, 'check removed p' ); -} ); - -test( 'remove-- keep children', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - div.innerHTML = '

xxxxxxxxxxx

xxxx
'; - var text = div.firstChild.firstChild; - var p = div.firstChild; - /*删除文本节点*/ - var node = domUtils.remove( text, true ); - equal( ua.getChildHTML( div ), '

xxxxxxxx

xxxx
' ); - same( text, node, 'check removed textNode' ); - /*删除有孩子的节点*/ - node = domUtils.remove( p, true ); - equal( ua.getChildHTML( div ), 'xxxxxxxx
xxxx
' ); - same( node.id, p.id, 'check removed p' ); -} ); - -test( 'isBookmarkNode', function() { - var domUtils = te.obj[3]; - var div = te.dom[2]; - var range = te.obj[2]; - div.innerHTML = 'xxxxxxxx
xxxx
'; - range.setStart( div, 0 ).setEnd( div, 1 ); - range.createBookmark(); - ok( domUtils.isBookmarkNode( div.firstChild ), 'is BookmarkNode' ); - ok( !domUtils.isBookmarkNode( div.firstChild.nextSibling ), 'not BookmarkNode' ); - -} ); - -test( 'getWindow', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - var w = domUtils.getWindow( div ); - ok( w === self.window, 'check window' ); -} ); - -test( 'getWindow--iframe', function() { - var f = te.dom[1]; - var domUtils = te.obj[3]; - expect( 1 ); - var frame_doc = f.contentWindow.document || f.contentDocument; - stop(); - setTimeout( function() { - var frame_div = frame_doc.createElement( 'div' ); - frame_doc.body.appendChild( frame_div ); - var w = domUtils.getWindow( frame_div ); - ok( f.contentWindow === w, 'same window' ); - start(); - } ); - -} ); - -test( 'isWhitespace', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - div.innerHTML = "aaa\ufeff\u200B\t\t\n\r"; - ok( !domUtils.isWhitespace( div.firstChild ), 'not whiteSpace' ); - div.innerHTML = UM.browser.ie && UM.browser.version == '6' ? '\ufeff' : '\u200B' + '\t\t\n\r'; - ok( domUtils.isWhitespace( div.firstChild ), 'is whiteSpace' ); -} ); - -test( 'split--offset正常', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - div.innerHTML = 'span >'; - var span = div.firstChild; - domUtils.split( span.firstChild, 2 ); - equal( span.childNodes.length, 2, 'check child count' ); - equal( span.childNodes[0].data, 'sp', 'check firstChild' ); - equal( span.childNodes[1].data, 'an', 'check secondChild' ); -} ); - -test( 'split--offset=0', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - div.innerHTML = 'span >'; - var span = div.firstChild; - domUtils.split( span.firstChild, 0 ); - equal( span.childNodes.length, 2, 'check child count' ); - equal( span.childNodes[0].data, '', 'check firstChild' ); - equal( span.childNodes[1].data, 'span', 'check secondChild' ); -} ); - -test( 'split--offset=data.length', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - div.innerHTML = 'span >'; - var span = div.firstChild; - domUtils.split( span.firstChild, 4 ); - equal( span.childNodes.length, 2, 'check child count' ); - equal( span.childNodes[0].data, 'span', 'check firstChild' ); - equal( span.childNodes[1].data, '', 'check secondChild' ); -} ); - -/*求相对视窗的位置而不是实际位置*/ -//test( 'getXY', function() { -// var div = te.dom[2]; -// var domUtils = te.obj[3]; -// equal( domUtils.getXY( div )['x'], ua.findPosition( div )[0] - document.documentElement.scrollLeft, 'check X' ); -// equal( domUtils.getXY( div )['y'], ua.findPosition( div )[1] - document.documentElement.scrollTop, 'check Y' ); -// -//} ); - -// -//test( 'on--跨iframe加载', function() { -// expect( 1 ); -// var domUtils = te.obj[3]; -// var op = { -// onafterstart : function( f ) { -// domUtils.on( f, 'load', function() { -// ok( true, 'on load of iframe success' ); -// } ); -// }, -// ontest : function() { -// this.finish(); -// } -// }; -// ua.frameExt( op ); -//} ); -// - -//test( 'on- 给不同的dom元素绑定相同的事件', function() { -// var domUtils = te.obj[3]; -// expect( 2 ); -// var div2 = document.body.appendChild( document.createElement( 'div' ) ); -// div2.id = 'test2'; -// te.dom.push( div2 ); -// var handle = function( e ) { -// ok( true, e.type + ' event triggered' ); -// }; -// domUtils.on( te.dom[2], 'mouseover', handle); -// domUtils.on( te.dom[1], 'mouseover', handle ); -// -// ua.mouseover( te.dom[2] ); -// ua.mouseover( te.dom[1] ); -//} ); -//test( 'un- 给不同的dom元素绑定相同的事件,解除一个,另一个仍然有效', function() { -// var domUtils = te.obj[3]; -// expect( 1 ); -// var div2 = document.body.appendChild( document.createElement( 'div' ) ); -// div2.id = 'test2'; -// te.dom.push( div2 ); -// var handle = function( e ) { -// ok( true, e.type + ' event triggered' ); -// }; -// domUtils.on( te.dom[2], 'mouseover', handle); -// domUtils.on( te.dom[1], 'mouseover', handle ); -// domUtils.un( te.dom[2],'mouseover', handle ); -// ua.mouseover( te.dom[2] ); -// ua.mouseover( te.dom[1] ); -//} ); -///*绑定多个事件*/ -//test( 'on', function() { -// var domUtils = te.obj[3]; -// expect( 2 ); -// domUtils.on( te.dom[2], ['mouseover','keypress'], function( e ) { -// ok( true, e.type + ' event triggered' ); -// } ); -// ua.mouseover( te.dom[2] ); -// ua.keypress( te.dom[2] ); -//} ); -//test( "test case sensitive", function() { -// var div = te.dom[2]; -// var domUtils = te.obj[3]; -// if ( ua.browser.ie ) { -// ok( true, 'IE下不支持诸如DOMNodeInserted等mutation事件' ); -// return; -// } -// // ok(false, 'TODO: 添加大小写敏感事件的on绑定和un取消用例,比如DOMMouseScroll'); -// expect( 2 ); -// domUtils.on( div, 'DOMNodeInserted', function() { -// ok( true, '用DOMNodeInserted测试大小写敏感事件的on绑定' ); -// domUtils.un( div, 'DOMNodeInserted' ); -// } ); -// div.appendChild( document.createElement( 'div' ) ); -// div.appendChild( document.createElement( 'div' ) ); -//} ); -// -//test( "un--取消注册unload事件", function() { -// expect( 1 ); -// var domUtils = te.obj[3]; -// var div = te.dom[2]; -// var handle_a = function() { -// ok( true, "check unload" ); -// }; -// domUtils.on( div, "click", handle_a ); -// /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ -// ua.click( div ); -// domUtils.un( div, "click", handle_a ); -// ua.click( div ); -//} ); -// -// -//test( "un--同一个回调注册多个事件,后面事件会将第一个事件dhandler覆盖掉", function() { -// expect( 1 ); -// var domUtils = te.obj[3]; -// var div = te.dom[2]; -// var handle_a = function() { -// ok( true, "应当只会执行一次" ); -// }; -// /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ -// domUtils.on( div, "click", handle_a ); -// domUtils.on(div,'dbclick',handle_a); -// ua.click( div ); -// domUtils.un( div, "click", handle_a ); -// ua.click( div ); -//} ); -// -//test( "un--同一个回调同一个事件注册2次", function() { -// expect( 1 ); -// var domUtils = te.obj[3]; -// var div = te.dom[2]; -// var handle_a = function() { -// ok( true, "check unload" ); -// }; -// /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ -// domUtils.on( div, "click", handle_a ); -// domUtils.on(div,'click',handle_a); -// ua.click( div ); -// domUtils.un( div, "click", handle_a ); -// ua.click( div ); -//} ); -// -//test( "un--同一个事件取消注册三次", function() { -// expect( 1 ); -// var domUtils = te.obj[3]; -// var div = te.dom[2]; -// var handle_a = function() { -// ok( true, "check unload" ); -// }; -// /* 直接调用ua提供的接口跨浏览器接口,屏蔽浏览器之间的差异 */ -// domUtils.on( div, "click", handle_a ); -// ua.click( div ); -// domUtils.un( div, "click", handle_a ); -// domUtils.un( div, "click", handle_a ); -// domUtils.un( div, "click", handle_a ); -// ua.click( div ); -//} ); - -test( 'isBlockElm', function() { - var div = te.dom[2]; - var domUtils = te.obj[3]; - /*isindex,noframes是特例,在这里不做验证*/ - var blockElms = ['address','blockquote','center','dir','div','dl','fieldset','form','h1','h2','h3','h4','h5','h6','hr','menu','ol','p','pre','table','ul']; - var k = blockElms.length; - while ( k ) { - var elm = document.createElement( blockElms[k - 1] ); - div.appendChild( elm ); - ok( domUtils.isBlockElm( elm ), elm.tagName + ' is block elm' ); - k--; - } - blockElms = ['a','abbr','acronym','b','bdo','big','br','cite','code','dfn','em','font','i','img','input','kbd','label','q','s','samp','select','small','span','strike','strong','sub','sp','textarea','tt','u','noscript' ]; - k = blockElms.length; - while ( k ) { - var elm = document.createElement( blockElms[k - 1] ); - div.appendChild( elm ); - ok( !domUtils.isBlockElm( elm ), elm.tagName + ' is not block elm' ); - k--; - } -} ); - -test( 'isbody', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var domUtils = UM.dom.domUtils; - ok(domUtils.isBody(editor.body), 'is body'); - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }); - stop(); -} ); - -test( 'getElementsByTagName', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '

xxxxuitext

xxxx

xxxx

'; - var elms = domUtils.getElementsByTagName( div, 'p' ); - equal( elms.length, 2, 'check elem count' ); - equal( elms[0].innerHTML.toLowerCase(), 'xxxxuitext
', 'check first p' ); - equal( elms[1].innerHTML, 'xxxx', 'check second p' ); -} ); - -test( 'unselectable--检查赋值是否成功', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '

xxxxxxxxxxx

dddd

aaaa

'; - domUtils.unSelectable( div ); - if ( UM.browser.gecko || UM.browser.webkit || (UM.browser.ie &&UM.browser.version==11) ) { - equal( div.style.MozUserSelect || div.style.KhtmlUserSelect || div.style.MSUserSelect, 'none', 'webkit or gecko unselectable' ); - } else { - equal( div.unselectable, 'on', '检查unselectable属性' ); - for ( var i = 0,ci; ci = div.all[i++]; ) { - equal( ci.unselectable, 'on', '检查子节点unselectable属性' ); - } - } -} ); - -test( 'unselectable--检查是否真的不能选中', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '

xxx

'; - //TODO ie下如何选中文本节点需要重新想一想,用程序选择文本貌似不会考虑unselectable属性,都是可以选中的 - if ( ! ua.browser.ie && !ua.browser.opera) { -// var rng = document.body.createTextRange(); -// domUtils.unselectable( div ); -// rng.moveToElementText( div ) -// /*开始位置处向前移动一个字符,结束位置处向后移动一个字符*/ -// rng.moveEnd( 'character', 1 ); -// rng.moveStart( 'character', -1 ); -// rng.select(); -// equal( rng.text, '', 'after unselectable' ); -// } else { - var r = te.obj[2]; - r.selectNode( div.firstChild ).select(); - equal( ua.getSelectedText(), 'xxx', 'before unselectable' ); - /*禁止选中*/ - domUtils.unSelectable( div ); - r.selectNode( div.firstChild ).select(); - equal( ua.getSelectedText(), '', 'after unselectable' ); - } -} ); - -/*不支持第二个参数为字符串,必须为数组*/ -//test( 'removeAttributes--删除一个属性', function() { -// var div = te.dom[2]; -// div.innerHTML = '
'; -// var domUtils = UM.dom.domUtils; -// domUtils.removeAttributes( div.firstChild, 'class' ); -// equal( ua.getChildHTML( div ), '
' ); -//} ); - -test( 'removeAttributes--删除多个属性,包括style', function() { - var div = te.dom[2]; - div.innerHTML = '
'; - var domUtils = UM.dom.domUtils; - /*诡异模式下className可以删除,而非诡异模式下不能删除*/ - domUtils.removeAttributes( div.firstChild, ['class','name','style'] ); - equal( ua.getChildHTML( div ), '
' ); -} ); - -test( 'setAttributes--设置class,style', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
'; - domUtils.setAttributes( div.firstChild, {'class':'div_class','id':'div_id','style':'color:red;font-size:12px;'} ); - var div_new = document.createElement( 'div' ); - div_new.id = 'test'; - div_new.innerHTML = '
'; - ok( ua.haveSameAllChildAttribs( div, div_new ), 'check attributes' ); -} ); - -test( 'getComputedStyle', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
'; - equal( domUtils.getComputedStyle( div.firstChild, 'font-size' ), '12px' ); - equal( domUtils.getComputedStyle( div.firstChild, 'display' ), 'block' ); - equal( domUtils.getComputedStyle( div.lastChild, 'display' ), 'inline' ); - equal( domUtils.getComputedStyle( div.firstChild, 'width' ),div.firstChild.offsetWidth + 'px'); - div.innerHTML = '
'; - equal( domUtils.getComputedStyle( div.firstChild, 'width' ),'30px'); -} ); - -test( 'getComputedStyle--获取默认的背景色', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
hello
'; - /*chrome下不作特殊处理得到的结果是rgba(0,0,0,0),处理后是结果是“”*/ - var result = UM.browser.webkit ? "" : "transparent"; - equal( domUtils.getComputedStyle( div, 'background-color' ), result, '默认背景色为透明色' ); -} ); - -test( 'trace 3629 getComputedStyle-border', function() { - if(ua.browser.ie==9)return;//todo trace 3629 - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
'; - var s =( (ua.browser.ie&&ua.browser.ie>8)||ua.browser.gecko)?'left-':''; - equal( domUtils.getComputedStyle( div.firstChild, 'border-'+s+'width' ), '5px' ); - equal( domUtils.getComputedStyle( div.lastChild, 'border-'+s+'style' ), 'solid' ); - equal( ua.formatColor(domUtils.getComputedStyle( div.lastChild, 'border-'+s+'color' )).toUpperCase(), "#FF0000" ); -} ); -//修复ie下的一个bug,如果在body上强制设了字体大小,h1的字体大小就会继承body的字体,而没有办法取到真是的字体大小 -test( 'getComputedStyle-在body上设置字体大小', function() { - var domUtils = UM.dom.domUtils; - var editor = new UM.Editor({'autoFloatEnabled':false}); - var div = document.body.appendChild( document.createElement( 'div' ) ); - editor.render( div ); - stop(); - editor.ready(function(){ - var body = editor.body; - var range = new UM.dom.Range( editor.document ); - var h1 = body.appendChild( editor.document.createElement( 'h1' ) ); -// editor.body.style['fontSize'] = '10px'; -// h1的字体大小不是10px - var fontSize = '32px'; - equal( domUtils.getComputedStyle( h1, 'font-size' ), fontSize, 'body的fontSize属性不应当覆盖p的fontSize属性' ); -// editor.setContent( '

这是h2的文本这是一个超链接

' ); - start(); - }); -} ); - -test( "preventDefault", function() { - expect( 1 ); - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - /*img用来撑大页面*/ - var img = document.createElement( 'img' ); - img.src = upath + 'test.jpg'; - img.style.height = "2000px"; - div.appendChild( img ); - document.body.appendChild( div ); - var a = document.createElement( 'a' ); - a.setAttribute( "href", "#" ); - a.innerHTML = 'ToTop'; - a.target = '_self'; - document.body.appendChild( a ); - window.scrollTo( 0, document.body.scrollHeight ); - -// UserAction.beforedispatch = function( e ) { -// e = e || window.event; -// domUtils.preventDefault( e ); -// }; - a.onclick = function( e ) { - domUtils.preventDefault( e ); - } - UserAction.click( a ); - var top = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; - ok( top != 0, "preventDefault" ); - document.body.removeChild( a ); -} ); - -test( 'getStyle--color is red', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
'; - equal( domUtils.getStyle( div.firstChild, 'color' ), 'red', 'check color' ); - equal( domUtils.getStyle( div.firstChild, 'font-size' ), '12px', 'check font size' ); - equal( domUtils.getStyle( div.firstChild, 'top' ), '13px', 'check top' ); -} ); - -test( 'getStyle--color is rgb', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
'; - equal( domUtils.getStyle( div.firstChild, 'color' ), '#FF0000', 'check color' ); - equal( domUtils.getStyle( div.firstChild, 'font-size' ), '12px', 'check font size' ); - equal( domUtils.getStyle( div.firstChild, 'top' ), '13px', 'check top' ); -} ); - -test( 'getStyle--color is #ff0000', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
'; - equal( domUtils.getStyle( div.firstChild, 'color' ).toUpperCase(), '#FF0000', 'check color' ); - equal( domUtils.getStyle( div.firstChild, 'font-size' ), '12px', 'check font size' ); - equal( domUtils.getStyle( div.firstChild, 'top' ), '13px', 'check top' ); -} ); - - -//test( 'getStyle--border', function() { -// var div = te.dom[2]; -// div.innerHTML = '
'; -//} ); -test( 'removeDirtyAttr', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '
xxx
xx'; - $( div ).attr( '_moz_dirty', 'xxxx' ); - for ( var i = 0,ci,nodes = div.getElementsByTagName( '*' ); ci = nodes[i++]; ) { - $( ci ).attr( '_moz_dirty', 'xxx' ); - } - domUtils.removeDirtyAttr( div ); - - for ( var i = 0,ci,nodes = div.getElementsByTagName( '*' ); ci = nodes[i++]; ) { - equal( $( ci ).attr( '_moz_dirty' ), undefined, 'check dirty attr ' ); - } - equal( $( div ).attr( '_moz_dirty' ), undefined, 'check dirty attr' ); -} ); - -test( 'getChildCount', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '

xxx

xxxxxxxxxx
'; - var divChild = div.firstChild; - equal( domUtils.getChildCount( div ), 1, 'one childNode' ); - equal( domUtils.getChildCount( divChild ), 5, '5 childs' ); - equal( domUtils.getChildCount( divChild.firstChild.firstChild ), 2, 'inline span' ); - equal( domUtils.getChildCount( divChild.lastChild ), 0, 'text node have no child' ); - equal( domUtils.getChildCount( divChild.lastChild.previousSibling ), 0, 'img have no child' ); - -} ); - -test( 'setStyle', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = '

'; - /*修改float值*/ - domUtils.setStyle( div.firstChild, 'float', 'right' ); - equal( $( div.firstChild ).css( 'float' ), 'right', '浮动方式改为了right' ); - domUtils.setStyle( div.firstChild.firstChild, 'text-indent', '10px' ); - equal( $( div.firstChild.lastChild ).css( 'text-indent' ), '10px', '设置了缩进样式' ); -} ); - -//zhuwenxuan add -test( 'isEmptyNode', function() { - var div = te.dom[2]; - var domUtils = UM.dom.domUtils; - div.innerHTML = " \t\t\n\r"; - ok(domUtils.isEmptyNode(div)); - div.innerHTML = '
dasdf
'; - equal(false,domUtils.isEmptyNode(div)); -} ); - -//zhuwenxuan add -test( 'isBr', function() { - var domUtils = UM.dom.domUtils; - var div = te.dom[2]; - div.innerHTML = "
"; - equal(true,domUtils.isBr(div.firstChild)); -} ); - -//zhuwenxuan add -test( 'isFillChar', function() { - var domUtils = UM.dom.domUtils; - var div = te.dom[2]; - domUtils.fillNode(document,div); - if(ua.browser.ie){ - ok(domUtils.isFillChar(div.lastChild)); - } -} ); - - -//zhuwenxuan add -test( 'isEmptyBlock', function() { - var domUtils = UM.dom.domUtils; - var div = te.dom[2]; - domUtils.fillNode(document,div); - ok(domUtils.isEmptyBlock(div)); - var span = document.createElement("span"); - equal(1,domUtils.isEmptyBlock(span)); - span.innerHTML = "asdf"; - equal(0,domUtils.isEmptyBlock(span)); -} ); - -//zhuwenxuan add -test( 'fillNode', function() { - var domUtils = UM.dom.domUtils; - var div = te.dom[2]; - domUtils.fillNode(document,div); - ok(div.innerHTML.length>0); -} ); \ No newline at end of file diff --git a/_test/core/filternode.js b/_test/core/filternode.js deleted file mode 100644 index ffc2a2af..00000000 --- a/_test/core/filternode.js +++ /dev/null @@ -1,178 +0,0 @@ -module( 'core.filternode' ); - -test( '过滤掉整个标签', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdfsdf

sdf
'); - UM.filterNode(node,{ - 'p':{}, - 'b':'-' - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdf

sdf
','保留p,过滤b'); - - node.innerHTML('

sdfs





'); - UM.filterNode(node,{ - 'p':{}, - 'br':'-' - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdfs

','保留p,过滤br'); -}); - -test( '过滤标签全部属性', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdfsdf

sdf
'); - node.innerHTML('

sdfssdfs

sdfasdf
'); - UM.filterNode(node,{ - 'p':{$:{}} - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdfssdfs

sdfasdf
','过滤p全部属性'); - - node.innerHTML('
asdlkfj
'); - UM.filterNode(node,{ - 'h6':function(node){ - node.tagName = 'p'; - node.setAttr(); - }, - '-':'b i', - 'p':{} - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

asd

','同时过滤多个标签属性'); -}); - -test( '过滤标签部分属性', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdfsdf

sdf
'); - node.innerHTML('

sdfasdf
'); - UM.filterNode(node,{ - 'p':{$:{ - style:['color'] - }}, - 'td':{} - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdfasdf
','保留p的color属性'); - - node.innerHTML('

sdfssdfs

'); - UM.filterNode(node,{ - 'p':{$:{ - style:['line-height'] - }}, - 'span':{$:{}}, - 'strong':'-' - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdfs

','过滤span全部属性,保留p部分属性,过滤strong标签'); - - node.innerHTML('

sdfssdfssdfssdfs

'); - UM.filterNode(node,{ - 'p':{}, - 'u':{$:{ - 'class':['ad'] - }}, - 'sub':{$:{}}, - 'i':'-' - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdfssdfs

','过滤sub全部属性,保留u部分属性,过滤i标签'); -}); - -test( '标签替换过滤', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdfsdf

sdf
'); - node.innerHTML('

sdfssdfs

sdfasdf
'); - UM.filterNode(node,{ - 'p':{$:{ - style:['color'] - }}, - 'tr':function(node){ - node.tagName = 'p'; - node.setAttr(); - }, - 'td':function(node){ - node.parentNode.removeChild(node,true) - } - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

sdfssdfs

sdfasdf
','tr替换为p,过滤掉td'); - - node.innerHTML('
aldkfj
adf
lkj
'); - UM.filterNode(node,{ - 'img':{$:{ - src:[''] - }}, - 'table':{}, - 'tbody':{}, - 'tr':{$:{}}, - 'td':{$:{}}, - 'th':function(node){ - var txt = !!node.innerText(); - if(txt){ - node.parentNode.insertAfter(UM.uNode.createText('    '),node); - } - node.parentNode.removeChild(node,node.innerText()) - } - }); - ua.checkSameHtml(node.toHtml().replace(/[ ]+>/g,'>'),'
aldkfjadf    
lkj
','th按文本内容替换,保留img部分属性'); -}); - -test( '保留标签全部属性', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdfsdf

sdf
'); - node.innerHTML('
  1. sdf
    • a
    • b
    • c
  2. jkl
'); - UM.filterNode(node,{ - 'ol':{}, - 'ul':{$:{}}, - 'li':{} - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'
  1. sdf
    • a
    • b
    • c
  2. jkl
','保留ol、li全部属性,过滤ul全部属性'); -}); - -test( '过滤规则为空', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdfsdf

sdf
'); - node.innerHTML('

asd

sdfasdf
'); - UM.filterNode(node,{}); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

asd

sdfasdf
','过滤规则为空'); -}); - -test( '特殊规则过滤', function() { - var uNode = UM.uNode; - var node = uNode.createElement('

sdf

sdf
'); - node.innerHTML(''); - UM.filterNode(node,{ - 'b':'-' - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'
','过滤规则中包含html中不存在的标签'); - - node.innerHTML('

'); - UM.filterNode(node,{ - 'p':{} - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'

','innerHTML中包含注释'); -}); - -test( '只有white list--滤除属性', function () { - var uNode = UM.uNode; - var node = uNode.createElement('

sdf

sdf
'); - node.innerHTML('
hellotable

hellodiv

hellospan'); - UM.filterNode(node,{ - div:{ - $:{ - id:{}, - 'class':{} - } - }, - table:{}, - span:{} - }); - ua.checkSameHtml(node.toHtml().replace(/[ ]+>/g,'>'), '
hellotable
hellodiv
hellospan
', '滤除属性'); -} ); - -test( '只有black list', function () { - var uNode = UM.uNode; - var node = uNode.createElement('

sdf

sdf
'); - node.innerHTML('
hello1hello2
'); - UM.filterNode(node,{ - span:'-', - em:'-', - '#comment':'-', - script:'-', - style:'-' - }); - equals(node.toHtml().replace(/[ ]+>/g,'>'),'
hello2
','过滤规则中包含html中不存在的标签'); -} ); \ No newline at end of file diff --git a/_test/core/filterword.js b/_test/core/filterword.js deleted file mode 100644 index ba911f64..00000000 --- a/_test/core/filterword.js +++ /dev/null @@ -1,40 +0,0 @@ -module( "core.filterword" ); - - -test( "office2010 word", function () { - stop(); - ua.readTxt('test1_1.txt',function(str){ - var txt = '

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

1. 欢迎使用umeditor!

2. 欢迎使用umeditor!

l 欢迎使用umeditor!

l 欢迎使用umeditor!

'; - equal(UM.filterWord(str),txt,'字体、字号、颜色、基本样式、列表'); - ua.readTxt('test1_2.txt',function(str){ - txt ='

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

'; - equal(UM.filterWord(str),txt,'段落样式、word样式、缩进'); - ua.readTxt('test1_3.txt',function(str){ - txt = '

欢迎使用umeditor!

 

 

 

 

欢迎使用umeditor!

www.baidu.com

'; - equal(UM.filterWord(str),txt,'表格、图片、超链接'); - start(); - }); - }); - }); -} ); -test( "wps word", function () { - stop(); - ua.readTxt('test2_1.txt',function(str){ - var txt='

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

一、欢迎使用umeditor!

二、欢迎使用umeditor!

l 欢迎使用umeditor!

l 欢迎使用umeditor!

'; - equal(UM.filterWord(str),txt,'字体、字号、颜色、基本样式、列表'); - ua.readTxt('test2_2.txt',function(str){ - txt= '

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

欢迎使用umeditor!

'; - equal(UM.filterWord(str),txt,'缩进、段落样式、word样式'); - ua.readTxt('test2_3.txt',function(str){ - txt='

欢迎使用umeditor!

欢迎使用umeditor!

www.baidu.com

'; - equal(UM.filterWord(str),txt,'表格、图片、超链接'); - start(); - }); - }); - }); -} ); -test( "word 补充 ", function () { - var str = '

'; - var txt = '

'; - ua.checkSameHtml(UM.filterWord(str),txt,'word 补充'); -}); diff --git a/_test/core/htmlparser.js b/_test/core/htmlparser.js deleted file mode 100644 index c169a1e3..00000000 --- a/_test/core/htmlparser.js +++ /dev/null @@ -1,209 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: luqiong - * Date: 13-3-14 - * Time: 下午2:31 - * To change this template use File | Settings | File Templates. - */ -module( 'core.htmlparser' ); - -test( '普通标签处理', function() { - var root = UM.htmlparser('sdfsdfsdfsf'); - equals(root.toHtml(),'sdfsdfsdfsf','单个普通标签'); - root = UM.htmlparser('sdfsdfsdsdfsdfsf'); - equals(root.toHtml(),'sdfsdfsdsdfsdfsf','多个普通标签'); - root = UM.htmlparser('sdf'); - ua.checkSameHtml(root.toHtml(),'sdf','添加属性的标签'); - root = UM.htmlparser(''); - ua.checkSameHtml(root.toHtml(),'','img标签'); -}); - -test( '特殊标签处理', function() { - var root = UM.htmlparser('sdf'); - ua.checkSameHtml(root.toHtml(),'sdf','包含注释'); - root = UM.htmlparser(''); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'','script标签'); - root = UM.htmlparser('


'); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'


','br标签'); - root = UM.htmlparser('
  • sdfsdfsdf
  • sdfsdfsdfsdf'); - equals(root.toHtml(),'
    • sdfsdfsdf
    • sdfsdfsdfsdf
    ','以文本结束的html'); -}); - -//test( '补全不完整table', function() {//TODO 1.2.6 -// var root = UM.htmlparser('

    '); -// equals(root.toHtml(),'

    ','td完整,补全table'); -// root = UM.htmlparser('

    sdfsdfsdf

    '); -// equals(root.toHtml(),'

    sdfsdfsdf

    ','td不完整,补全table'); -// root = UM.htmlparser('' + '\n\r' + ''); -// equals(root.toHtml(),'
    ','包含\n,补全table'); -// root = UM.htmlparser(''); -// equals( root.toHtml().toLowerCase(), '
    ', '--不补孩子' ); -// /*补parent*/ -// root = UM.htmlparser('hello'); -// equals( root.toHtml().toLowerCase(), '
    '); -// equals( root.toHtml().toLowerCase(), '
    ', '
    --补父亲' ); -// /*补parent和child*/ -// root = UM.htmlparser('
    hello
    ', 'hello--补父亲不补孩子' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '
    123
    ', '123--文本放在table里' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123
    ', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); -// -// /*补充为2个td*/ -//// root = UM.htmlparser('123'); -//// equals( root.toHtml().toLowerCase(), '
    123
    ', '123--tr和td之间有文字' );//TODO 1.2.6 -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); -// -// /*补2个table*/ -//// root = UM.htmlparser('123132'); -//// equals( root.toHtml().toLowerCase(), '
    123
    132
    ', '123132--补全2个table' );//TODO 1.2.6 -// -// /*开标签、文本与闭标签混合*/ -//// root = UM.htmlparser('123'); -//// equals( root.toHtml().toLowerCase(), '
    123', '123--tr和td之间有文字' );//TODO 1.2.6 -// -//// root = UM.htmlparser('123'); -//// equals( root.toHtml().toLowerCase(), '
    123', '123--td闭标签后面有文字' );//TODO 1.2.6 -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123
    ', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '
    123
    ', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123
    ', '123' ); -// /*闭标签、文本与闭标签混合*/ -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123
    ', '123', '123' ); -// -// /*补前面的标签*/ -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123', '123' ); -// -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123', '123' ); -// /*补全tr前面的标签*/ -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123', '123--删除tr前后的标签,前面有文本' ); -// /*补全table前面的标签*/ -// root = UM.htmlparser('123'); -// equals( root.toHtml().toLowerCase(), '123', '123--删除table前后的标签,前面有文本' ); -// /*复杂结构*/ -// root = UM.htmlparser('456'); -// equals( root.toHtml().toLowerCase(), '
    123
    123
    456
    ', '456' ); -// -// root = UM.htmlparser(''); -// equals( root.toHtml().toLowerCase(), '
    123
    hello1hello2
    hello1hello2
    ', '解析hello1hello2' ); -// -// root = UM.htmlparser(''); -// equals( root.toHtml().toLowerCase(), '
    hello1hello2
    hello1hello2
    ', '解析' ); -// -// root = UM.htmlparser('
    hello1hello2
    123'); -// equals( root.toHtml().toLowerCase(), '
    123', '123' ); -//}); - -test( '补全不完整li', function() { - var root = UM.htmlparser('
    1. sdf
    2. sdfsdf
    '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
    2. sdfsdf
    ','补全u,em'); - root = UM.htmlparser('
    1. sdf
      • a
      • b
      • c
    2. jkl
    '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
      • a
      • b
      • c
    2. jkl
    ','补全li'); - root = UM.htmlparser('
  • 123'); - equals(root.toHtml().replace(/[ ]+>/g,'>'), '
    • 123
    ', '
  • 123--补全li的parent--ul,前面有文本' ); - /*补ul的child*/ - root = UM.htmlparser('
      123'); - equals(root.toHtml().replace(/[ ]+>/g,'>'), '
      • 123
      ', '
        123--补全ul的child--li,前面有文本' ); - /*补li开始标签*/ - root = UM.htmlparser('123'); - equals(root.toHtml().replace(/[ ]+>/g,'>'), '123', '123--删掉标签' ); -}); - -test( '属性引号问题', function() { - var root = UM.htmlparser(''); - equals(root.toHtml().replace(/[ ]+>/g,'>'),''); - root = UM.htmlparser(""); - equals(root.toHtml().replace(/[ ]+>/g,'>'),''); - root = UM.htmlparser(''); - equals(root.toHtml().replace(/[ ]+>/g,'>'),''); -}); - -test( '大小写', function() { - var root = UM.htmlparser('

  • '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'

    '); - root = UM.htmlparser('
    1. sdf
    2. sdfsdf
    '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    1. sdf
    2. sdfsdf
    ','补全u,em'); - root = UM.htmlparser(''); - equals(root.toHtml().replace(/[ ]+>/g,'>'),''); -}); - -test( '裸字', function() { - var root = UM.htmlparser('sdfasdfasdf'); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'sdfasdfasdf'); -}); - -test( '只有结束标签的情况', function() { - var root = UM.htmlparser('

    hello1

    hello2

    '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'

    hello1

    hello2

    '); -}); - -test( '开始标签与后面文本的空格过滤,其他不过滤inline节点之间的空格,过滤block节点之间的空格', function () { - /*inline节点之间的空格要留着*/ - var root = UM.htmlparser('baidu hello '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'baidu hello '); - root = UM.htmlparser(' hello he llo2 hello '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),' hello he llo2 hello ' ); - /*block节点之间的空格不要留着 这个太纠结,不必了。会把ol拆开,后面的变成ul*/ -// html = '
    1. li_test
    2. li test2
    '; -// node = serialize.parseHTML( html ); -// node = serialize.filter( node ); -// equal( serialize.toHTML( node ), '
    1. li_test 
    2. li test2 
     ' ); -} ); - -/*特殊字符需要转义*/ -test( '文本包含特殊字符,如尖括号', function () { - var root = UM.htmlparser(''); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'<td  hello', '字符转义' ); -} ); - -test( 'br', function () { - var root = UM.htmlparser('
    '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    ', '对br不操作'); - root = UM.htmlparser('
    '); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'
    ', '补充br后面的斜杠'); -} ); - -/*考察标签之间嵌套关系*/ -test( '复杂标签嵌套', function() { - var root = UM.htmlparser('hello1

    hello2

    hello3

    hello4'); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'hello1

    hello2

    hello3

    hello4

    '); -} ); - -test( 'trace 1727:过滤超链接后面的空格', function () { - var root = UM.htmlparser('baidu ddd'); - equals(root.toHtml().replace(/[ ]+>/g,'>'),'baidu  ddd','过滤超链接后面的空格'); -} ); - -//test( '转换img标签', function () { -// var root = UM.htmlparser(''); -// var spa=ua.browser.ie==6?' orgSrc="'+te.obj[1].options.UEDITOR_HOME_URL+'themes/default/images/spacer.gif"':''; -// equals(root.toHtml().replace(/[ ]+>/g,'>'), '' , '转换img标签'); -//} ); \ No newline at end of file diff --git a/_test/core/node.js b/_test/core/node.js deleted file mode 100644 index e65e99b8..00000000 --- a/_test/core/node.js +++ /dev/null @@ -1,215 +0,0 @@ -module( 'core.node' ); - -test( 'createElement', function() { - var uNode = UM.uNode; - var node = uNode.createElement('div'); - equals(node.tagName,'div','空div ——tagname'); - equals(node.type,'element','空div ——节点类型'); - node = uNode.createElement('
    sdfadf
    '); - equals(node.tagName,'div','非空div——tagname'); - equals(node.children[0].data,'sdfadf','非空div——数据内容'); -}); - -test( 'getNodeById', function() { - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - node = node.getNodeById('bb'); - equals(node.getAttr('id'),'bb','获取标签id'); - node = uNode.createElement('
    sdfadf
    '); - node = node.getNodeById('cc'); - equals(node.getAttr('id'),'cc','获取标签id'); -}); - -test( 'getNodesByTagName', function() { - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - var nodelist = node.getNodesByTagName('div'); - equals(nodelist.length,2,'div节点列表长度'); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'
    sdfadf','innerHTML内容'); -}); - -test( 'innerHTML', function() { - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - node.innerHTML('
    '); - var nodelist =node.getNodesByTagName('div'); - equals(nodelist.length,3,'div节点列表长度'); - for(var i= 0,ci;ci=nodelist[i++];){ - ci.tagName = 'p'; - } - equals(node.innerHTML(),'

    ','innerHTML内容'); - node = uNode.createElement('
    '); - node.innerHTML('asdf'); - equals(node.innerHTML(),'asdf','innerHTML内容'); -}); - -test( 'innerText', function() { - var tmp = new UM.uNode.createElement('area'); - tmp.innerHTML('

    '); - equals(tmp.innerText(),tmp,'标签类型特殊'); - tmp = new UM.uNode.createText(''); - tmp.innerHTML('

    '); - equals(tmp.innerText(),tmp,'对象类型不为element'); - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - node.innerHTML('

    dfsdfsdfeeesdf

    '); - equals(node.innerText(),'dfsdfsdfeeesdf','获取标签中纯文本'); - node.innerText('sdf'); - equals(node.innerHTML(),'sdf','设置文本节点'); -}); - -test( 'getData', function() { - var tmp = new UM.uNode.createElement('div'); - equals(tmp.getData(),'','element元素'); - tmp = new UM.uNode.createText('askdj'); - equals(tmp.getData(),"askdj",'其他类型'); -}); - -test( 'appendChild && insertBefore', function() { - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - node.innerHTML('

    '); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','补全html标签'); - var tmp = uNode.createElement('div'); - node.appendChild(tmp); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','appendChild'); - node.insertBefore(tmp,node.firstChild()); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','insertBefore'); - node.appendChild(tmp); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','appendChild'); -}); - -test( 'replaceChild && setAttr', function() { - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - node.innerHTML('

    '); - var tmp = uNode.createElement('p'); - tmp.setAttr({'class':'test','id':'aa'}); - node.insertBefore(tmp,node.lastChild()); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','setAttr不为空'); - node.replaceChild(uNode.createElement('div'),tmp); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','replaceChild'); - - node.removeChild(node.lastChild(),true); - tmp = uNode.createElement('p'); - tmp.setAttr(); - node.insertAfter(tmp,node.lastChild()); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','setAttr为空'); - node.innerHTML('

    '); - tmp = uNode.createElement('div'); - node.appendChild(tmp); - node.replaceChild(node.firstChild(),tmp); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','replaceChild'); -}); - -test( 'insertAfter', function() { - var uNode = UM.uNode; - var node = uNode.createElement('
    sdfadf
    '); - node.innerHTML('

    '); - var tmp = uNode.createElement('div'); - node.appendChild(tmp); - node.insertAfter(tmp,node.firstChild()); - equals(node.innerHTML().replace(/[ ]+>/g,'>'),'

    ','在第一个子节点后插入'); -}); - -test( 'getStyle', function() { - var uNode = UM.uNode; - var node = uNode.createElement('div'); - node.innerHTML('
    '); - node = node.firstChild(); - equals(node.getStyle(''),'','空cssStyle'); - node.innerHTML('
    '); - node = node.firstChild(); - equals(node.getStyle('border'),'1px solid #ccc','有border,取border样式'); - node.innerHTML('
    '); - node = node.firstChild(); - equals(node.getStyle('color'),'','无color样式,取color样式'); - node.innerHTML('
    '); - node = node.firstChild(); - equals(node.getStyle('border'),'1px solid #ccc','有2个样式,取其一'); -}); - -test( 'setStyle', function() { - var uNode = UM.uNode; - var node = uNode.createElement('div'); - node.innerHTML('
    '); - node = node.firstChild(); - node.setStyle('border','2px solid #ccc'); - equals(node.getAttr('style'),'border:2px solid #ccc;color:#ccc','修改样式中的一个'); - node.setStyle({ - 'font':'12px', - 'background':'#ccc' - }); - equals(node.getAttr('style'),'background:#ccc;font:12px;border:2px solid #ccc;color:#ccc','添加新样式'); - node.setStyle({ - 'font':'', - 'background':'', - 'border':'', - 'color':'' - }); - equals(node.getAttr('style'),undefined,'清空样式'); - node.setStyle('border',''); - equals(node.getAttr('style'),"border:<script>alert("")</script>;",'脚本'); - equals(node.toHtml(),'
    ','脚本转html'); - node.innerHTML('
    asdfasdfsdf
    '); - node.removeChild(node.firstChild(),true); - equals(node.toHtml(),'
    asdfasdfsdf
    ','移除子节点'); - node.innerHTML('
    '); - node.firstChild().setStyle('border'); - equals(node.firstChild().toHtml(),'
    ','删除分号'); - node.innerHTML('
    '); - equals(node.firstChild().toHtml(),'
    '); - - node.innerHTML('
    '); - node.firstChild().setStyle('border'); - - equals(node.firstChild().toHtml(),'
    '); - node.innerHTML('
    '); - node.firstChild().setStyle('border'); - equals(node.firstChild().toHtml(),'
    '); - -}); - -test( 'getIndex', function() { - var uNode = UM.uNode; - var node = uNode.createElement('div'); - node.innerHTML('
    asdfasdfsdf
    ') - node.removeChild(node.firstChild(),true); - var tmp = new UM.uNode.createElement('div'); - node.appendChild(tmp); - equals(tmp.getIndex(),2,'节点索引'); -}); - -test( 'traversal', function() { - var uNode = UM.uNode; - var node = uNode.createElement('div'); - node.innerHTML('
    asdfasdfsdf
    ') - var count = 0; - node.traversal(function(node){ - count++; - }); - equals(count,4); - count = 0; - node.traversal(function(node){ - if(node.type == 'text'){ - count++ - } - }); - equals(count,2); - node.traversal(function(node){ - if(node.type == 'text'){ - - node.parentNode.removeChild(node) - } - }); - equals(node.toHtml(),'
    '); - node.innerHTML('
    asdfasdfsdf
    '); - node.traversal(function(node){ - if(node.type == 'text'){ - var span = uNode.createElement('span'); - node.parentNode.insertBefore(span,node); - span.appendChild(node); - } - }); - equals(node.toHtml(),'
    asdfasdfsdf
    '); -}); \ No newline at end of file diff --git a/_test/core/tools.js b/_test/core/tools.js deleted file mode 100644 index bddd995b..00000000 --- a/_test/core/tools.js +++ /dev/null @@ -1,50 +0,0 @@ -(function () { - function mySetup() { - for (var config in window.UMDITOR_CONFIG) { - if (typeof(window.UMDITOR_CONFIG[config]) == 'string') - window.UMDITOR_CONFIG[config] = window.UMDITOR_CONFIG[config].replace('_test/tools/br/', ''); - } - - var div = document.body.appendChild(document.createElement('div')); - div.id = 'test1'; - var utils = UM.utils; - var editor = new UM.Editor({'UEDITOR_HOME_URL':'../../../', 'autoFloatEnabled':false}); - var iframe = document.createElement('iframe'); - document.body.appendChild(iframe); - iframe.id = 'iframe'; - var range = new UM.dom.Range(document,document.body); - var domUtils = UM.dom.domUtils; - var div_dom = document.body.appendChild(document.createElement('div')); - div_dom.id = 'test'; - te.dom.push(div); - te.dom.push(iframe); - te.dom.push(div_dom); - te.obj.push(utils); - te.obj.push(editor); - te.obj.push(range); - te.obj.push(domUtils); - } - var _d = function () { - - if (te) { - if (te.dom && te.dom.length) { - for (var i = 0; i < te.dom.length; i++) { - if (te.dom[i] && te.dom[i].parentNode) - te.dom[i].parentNode.removeChild(te.dom[i]); - } - - } - } - te.dom = []; - te.obj = []; - }; - var s = QUnit.testStart, d = QUnit.testDone; - QUnit.testStart = function () { - s.apply(this, arguments); - mySetup(); - }; - QUnit.testDone = function () { - _d(); - d.apply(this, arguments); - }; -})() \ No newline at end of file diff --git a/_test/core/utils.js b/_test/core/utils.js deleted file mode 100644 index 09f954e1..00000000 --- a/_test/core/utils.js +++ /dev/null @@ -1,324 +0,0 @@ -module( "core.utils" ); - - -test( "makeInstance", function () { - var utils = te.obj[0]; - var obj = { - s:1, - str:"makeInstance" - }, str = "makeInstance"; - var ins = utils.makeInstance( obj ); - var ins1 = utils.makeInstance( str ); - equals( ins.s, 1, "ins.s" ); - equals( ins.str, "makeInstance", "ins.str" ); - same( ins1, {}, "null" ); - same( utils.makeInstance( null ), {}, "null" ); -} ); -test( "isArray--普通对象", function () { - var utils = te.obj[0]; - var arr = [ '1', '2' ], ob = {}, str = "array", fun = function () { - }; - var div = te.dom[0]; - ok( utils.isArray( arr ), 'arr is a array' ); - ok( !utils.isArray( ob ), 'ob is not a array' ); - ok( !utils.isArray( str ), 'str is not a array' ); - ok( !utils.isArray( fun ), 'fun is not a array' ); - ok( !utils.isArray( null ), 'null is not a array' ); - ok( !utils.isArray( div ), 'dom element is not a array' ); -} ); - -test( "isArray--类数组对象", function () { - var utils = te.obj[0]; - var arrayLike = { - 0:'0', - 1:'1', - 2:'2', - length:3 - }; - var div = te.dom[0]; - div.innerHTML = 'xxxxx

    '; - ok( !utils.isArray( arrayLike ), '类数组对象不是数组' ); - ok( !utils.isArray( div.childNodes ), 'nodeList 不是数组' ); - -} ); - -test( "inherits", function () { - var utils = te.obj[0]; - var superClass = function () { - }; - var subClass = function () { - }; - expect( 4 ); - var index = 0; - superClass.prototype.name = "superClass"; - superClass.prototype.methodSuper = function () { - ok( true, "method in superClass is called" ); - }; - superClass.prototype.method = function () { - ok( false, "I am in superClass" ); - }; - subClass.prototype.name = "subClass"; - subClass.prototype.methodSub = function () { - ok( true, "method in subClass is called" ); - }; - subClass.prototype.method = function () { - ok( true, "I am in subClass" ); - }; - utils.inherits( subClass, superClass ); - var sub = new subClass(); - /*子类自己的名字,父类的被覆盖*/ - equal( sub.name, "subClass", "the name of subClass" ); - /*从父类中继承的方法*/ - sub.methodSuper(); - /*子类自己的方法*/ - sub.methodSub(); - /*覆盖父类中的method方法*/ - sub.method(); -} ); - - -test( "bind", function () { - var utils = te.obj[0]; - var first_object = { num:4 }; - var second_object = { num:2 }; - - function multiply( mult ) { - return this.num * mult; - } - - var first_multiply = utils.bind( multiply, first_object ); - equal( first_multiply( 5 ), 20, "first_object" ); // returns 4 * 5 - var second_multiply = utils.bind( multiply, second_object ); - equal( second_multiply( 5 ), 10, "second_object" ); -} ); - -test( 'defer--一个defer', function () { - var utils = te.obj[0]; - var delay = 100; - expect( 1 ); - stop(); - /*defer返回一个闭包,算defer不准,chrome下会 相差300多ms,没办法判断延时是否准确*/ - var stime = +new Date(); - utils.defer( function () { - ok( 1, '检查回调函数是否触发' ); - start(); - }, delay )(); -} ); - -test( 'defer--多个defer', function () { - var utils = te.obj[0]; - var delay = 40; - stop(); - expect( 2 ); - utils.defer( function () { - ok( true, '第一个触发' ); - }, delay )(); - - utils.defer( function () { - ok( true, '第二个触发' ); - start(); - }, delay )(); -} ); - -/*若互斥,则前一个注册的setTimeout事件被删除*/ -test( 'defer--考虑互斥', function () { - var utils = te.obj[0]; - var delay = 20; - stop(); - expect( 1 ); - /*exclusion=true*/ - var defer = utils.defer( function () { - ok( 1, '检查回调函数是否在规定的时间内触发' ); - }, delay, true ); - defer(); - //第一个defer会被删掉 - defer(); - setTimeout( function () { - start(); - }, 100 ); -} ); - -test( "extend--true", function () { - var utils = te.obj[0]; - var obj1 = {a:3, b:"str", fun:function () { - ok( true, "fun" ); - }, n:null}; - var obj2 = {a:2, c:1}; - utils.extend( obj2, obj1, true ); - equal( obj2.a, 2, "obj2 a" ); - equal( obj2.b, "str", "obj2 str" ); - equal( obj2.c, 1, "obj2 c" ); - obj2.fun(); - equal( obj2.n, null, "obj2 n null" ); -} ); -test( "extend--false", function () { - var utils = te.obj[0]; - var obj1 = {a:3, b:"str", fun:function () { - ok( true, "fun" ); - }, n:null}; - var obj2 = {a:2, c:1}; - utils.extend( obj2, obj1, false ); - equal( obj2.a, 3, "obj2 a" ); - equal( obj2.b, "str", "obj2 str" ); - equal( obj2.c, 1, "obj2 c" ); - obj2.fun(); - equal( obj2.n, null, "obj2 n null" ); -} ); -test( 'indexOf', function () { - var utils = te.obj[0]; - var s = [ 1, 2, 3, 4, 5 ]; - equals( utils.indexOf( s, 3 ), 2 ); - equals( utils.indexOf( s, 6 ), -1 ); - equals( utils.indexOf( s, 5 ), 4 ); - equals( utils.indexOf( s, 3, 3 ), -1 ); - equals(utils.indexOf( s, 3 ,3), -1); -} ); -test( 'removeItem&&itemexist', function () { - var utils = te.obj[0]; - var s = [ 1, 2, 3, 4, 5 , 4, 3]; - equal( s[5], 4, "before remove 4" ); - utils.removeItem( s, 4 ); - equal( s.length, 5, "4 be removed" ); - equal( s[4], 3, "4 be removed" ); -} ); - -test( 'removeItem&&itemnotexist', function () { - var utils = te.obj[0]; - var s = [ 1, 2, 3, 4, 5 , 4]; - utils.removeItem( s, 6 ); - equal( s.length, 6, "itemnotexist" ); -} ); - -test( "trim", function () { - var utils = te.obj[0]; - var s = ' sss '; - equals( utils.trim( s ), 'sss', "两端有空格" ); - s = " xxx "; - equal( utils.trim( s ), ' xxx', "包含 " );// 不能被捕获 - s = "string"; - equal( utils.trim( s ), "string", '没有 和空格' ); -} ); -test( 'listToMap', function () { - var utils = te.obj[0]; - var s = "listToMap"; - var re = utils.listToMap( s ); - equal( re.listToMap, 1, "listToMap" ); -} ); -test( 'list,To,Map', function () { - var utils = te.obj[0]; - var s = "list,To,Map"; - var re = utils.listToMap( s ); - equal( re.list, 1, "list" ); - equal( re.To, 1, "list" ); - equal( re.Map, 1, "Map" ); -} ); -test( 'listToMap ""', function () { - var utils = te.obj[0]; - var s = ""; - var re = utils.listToMap( s ); - equal( re.toString(), {}, "{}" ); -} ); -test( 'listToMap null', function () { - var utils = te.obj[0]; - var s = null; - var re = utils.listToMap( s ); - equal( re.toString(), {}, "{}" ); -} ); -test( 'listToMap numstring', function () { - var utils = te.obj[0]; - var s = "123333"; - var re = utils.listToMap( s ); - equal( re[123333], 1, "num" ); -} ); -test('unhtml 字符转义', function(){ - var utils=te.obj[0]; - var str='

    "as&cd"

    '; - var str_html=utils.unhtml(str); - equal(str_html,'<p>"as&cd"</p>','转义字符成功'); - str = 'border:<script>alert("")</script>"' - equal(utils.unhtml(str),'border:<script>alert("")</script>"','转义字符成功'); - str = "'"; - equal(utils.unhtml(str),''') -}); -test('html 反转义', function(){ - var utils=te.obj[0]; - var str_html='<p>"as&cd"</p>'; - var str=utils.html(str_html); - equal(str,'

    "as&cd"

    ','反转义成功'); -}); -test( 'unhtml null ""', function () { - var utils = te.obj[0]; - var s = null; - equal( utils.unhtml( s ), "", "unhtml null" ); - s = ''; - equal( utils.unhtml( s ), "", "unhtml null" ); -} ); -test( 'cssStyleToDomStyle', function () { - var utils = te.obj[0]; - equal( utils.cssStyleToDomStyle( "cssFloat" ).toLowerCase(), "cssfloat", "cssFloat" ); - if ( ua.browser.ie&&ua.browser.ie<9) { - equal( utils.cssStyleToDomStyle( "float" ).toLowerCase(), "stylefloat", "float" ); - } else{ - equal( utils.cssStyleToDomStyle( "float" ).toLowerCase(), "cssfloat", "float" ); - } - equal( utils.cssStyleToDomStyle( "styleFloat" ).toLowerCase(), "stylefloat", "styleFloat" ); -} ); - -//zhuwenxuan add -test( "isEmptyObject", function () { - var utils = te.obj[0]; - var obj = { - n:1 - }; - equal( false, utils.isEmptyObject( obj ) ); - equal( true, utils.isEmptyObject( [] ) ); - equal( true, utils.isEmptyObject( "" ) ); -} ); -//dong -test( "fixColor", function () { - var utils = te.obj[0]; - equal( '#953734', utils.fixColor("color", 'rgb(149, 55, 52)' ),'fixColor' ); -} ); -test( 'each 遍历方法', function () { - var div = te.dom[0]; - div.innerHTML = ''; - UM.utils.each(div.getElementsByTagName('span'),function(node,i){ - equal(node.tagName,'SPAN','遍历nodelist'); - }); - var count = 0; - UM.utils.each(div.getElementsByTagName('span'),function(node,i){ - count++; - if(node.id =='a') - return false - }); - equal(count,3); - UM.utils.each(['a','b'],function(v,i){ - equal(v,['a','b'][i],'遍历数组'); - }); - UM.utils.each({a:1,b:2},function(v,k){ - equal(v,{a:1,b:2}[k],'遍历对象'); - }); -} ) ; -test( 'clone 转换', function () { - var obj = {a:1}; - var obj1= UM.utils.clone({a:1}); - obj.a = 2; - equal(obj1.a,1); - obj = { - a:{ - b:1 - }, - c:[1,2] - } - obj1 = UM.utils.clone(obj); - obj.a.b = 2; - equal(obj1.a.b,1); - obj.c[1] = 3; - equal(obj1.c[1],2); - - -} ) ; -test( 'transUnitToPx 转换', function () { - equal(UM.utils.transUnitToPx('20pt'),'27px'); - equal(UM.utils.transUnitToPx('0pt'),'0'); -} ) ; diff --git a/_test/editor_config.js b/_test/editor_config.js deleted file mode 100644 index 278fe23f..00000000 --- a/_test/editor_config.js +++ /dev/null @@ -1,276 +0,0 @@ -/** - * umeditor完整配置项 - * 可以在这里配置整个编辑器的特性 - */ -var UMEDITOR_CONFIG2 = { - UMEDITOR_HOME_URL: '../../../', //这里你可以配置成umeditor目录在您网站的绝对路径 - toolbars: [ - ['FullScreen','Source','|','Undo','Redo','|', - 'Bold','Italic','Underline','StrikeThrough','Superscript','Subscript','RemoveFormat','FormatMatch','|', - 'BlockQuote','|', - 'PastePlain','|', - 'ForeColor','BackColor','InsertOrderedList','InsertUnorderedList','|', - 'Paragraph','RowSpacing','FontFamily','FontSize','|', - 'DirectionalityLtr','DirectionalityRtl','|','','Indent','Outdent','|', - 'JustifyLeft','JustifyCenter','JustifyRight','JustifyJustify','|', - 'Link','Unlink','Anchor','Image','MultiMenu','Video','Map','GMap','Code', '|', - 'Horizontal','Date','Time','Spechars','|', - 'InsertTable','DeleteTable','InsertParagraphBeforeTable','InsertRow','DeleteRow','InsertCol','DeleteCol','MergeCells','MergeRight','MergeDown','SplittoCells','SplittoRows','SplittoCols','|', - 'SelectAll','ClearDoc','SearchReplace','Print','Preview','PageBreak','Help'] - ],autoFloatEnabled:false, - labelMap: { - 'anchor':'锚点', - 'undo': '撤销', - 'redo': '重做', - 'bold': '加粗', - 'indent':'首行缩进', - 'outdent':'取消缩进', - 'italic': '斜体', - 'underline': '下划线', - 'strikethrough': '删除线', - 'subscript': '下标', - 'superscript': '上标', - 'formatmatch': '格式刷', - 'source': '源代码', - 'blockquote': '引用', - 'pasteplain': '纯文本粘贴模式', - 'selectall': '全选', - 'print': '打印', - 'preview': '预览', - 'horizontal': '分隔线', - 'removeformat': '清除格式', - 'time': '时间', - 'date': '日期', - 'unlink': '取消链接', - 'insertrow': '前插入行', - 'insertcol': '前插入列', - 'mergeright': '右合并单元格', - 'mergedown': '下合并单元格', - 'deleterow': '删除行', - 'deletecol': '删除列', - 'splittorows': '拆分成行', - 'splittocols': '拆分成列', - 'splittocells': '完全拆分单元格', - 'mergecells': '合并多个单元格', - 'deletetable': '删除表格', -// 'tablesuper': '表格高级设置', - 'insertparagraphbeforetable': '表格前插行', - 'cleardoc': '清空文档', - 'fontfamily': '字体', - 'fontsize': '字号', - 'paragraph': '格式', - 'image': '图片', - 'inserttable': '表格', - 'link': '超链接', - 'emoticon': '表情', - 'spechars': '特殊字符', - 'searchreplace': '查询替换', - 'map': 'Baidu地图', - 'gmap': 'Google地图', - 'video': '视频', - 'help': '帮助', - 'justifyleft':'居左对齐', - 'justifyright':'居右对齐', - 'justifycenter':'居中对齐', - 'justifyjustify':'两端对齐', - 'forecolor' : '字体颜色', - 'backcolor' : '背景色', - 'insertorderedlist' : '有序列表', - 'insertunorderedlist' : '无序列表', - 'fullscreen' : '全屏', - 'directionalityltr' : '从左向右输入', - 'directionalityrtl' : '从右向左输入', - 'rowspacing' : '行间距', - 'code' : '插入代码', - 'pagebreak':'分页' - }, - iframeUrlMap: { - 'anchor': '~/dialogs/anchor/anchor.html', - 'image': '~/dialogs/image/image.html', - 'inserttable': '~/dialogs/table/table.html', - 'link': '~/dialogs/link/link.html', - 'emoticon': '~/dialogs/emoticon/emoticon.html', - 'spechars': '~/dialogs/spechars/spechars.html', - 'searchreplace': '~/dialogs/searchreplace/searchreplace.html', - 'map': '~/dialogs/map/map.html', - 'gmap': '~/dialogs/gmap/gmap.html', - 'video': '~/dialogs/video/video.html', - 'help': '~/dialogs/help/help.html', - 'code' : '~/dialogs/code/code.html', - 'multimenu': '~/dialogs/menu-emoticon/emoticon.html' - }, - listMap: { - 'fontfamily': ['宋体', '楷体', '隶书', '黑体','andale mono','arial','arial black','comic sans ms','impact','times new roman'], - 'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36], - 'underline':['none','overline','line-through','underline'], - 'paragraph': ['p:Paragraph', 'h1:Heading 1', 'h2:Heading 2', 'h3:Heading 3', 'h4:Heading 4', 'h5:Heading 5', 'h6:Heading 6'], - 'rowspacing' : ['1.0:0','1.5:15','2.0:20','2.5:25','3.0:30'] - }, - fontMap: { - '宋体': ['宋体', 'SimSun'], - '楷体': ['楷体', '楷体_GB2312', 'SimKai'], - '黑体': ['黑体', 'SimHei'], - '隶书': ['隶书', 'SimLi'], - 'andale mono' : ['andale mono'], - 'arial' : ['arial','helvetica','sans-serif'], - 'arial black' : ['arial black','avant garde'], - 'comic sans ms' : ['comic sans ms'], - 'impact' : ['impact','chicago'], - 'times new roman' : ['times new roman'] - }, - contextMenu: [ - { - label : '删除', - cmdName : 'delete' - - }, - { - label : '全选', - cmdName : 'selectall' - - },{ - label : '清空文档', - cmdName : 'cleardoc', - exec : function(){ - if(confirm('确定清空文档吗?')){ - this.execCommand('cleardoc'); - } - } - },'-',{ - label : '取消链接', - cmdName : 'unlink' - },'-',{ - group : '段落格式', - icon : 'justifyjustify', - subMenu : [ - { - label: '居左对齐', - cmdName : 'justify', - value : 'left' - }, - { - label: '居右对齐', - cmdName : 'justify', - value : 'right' - },{ - label: '居中对齐', - cmdName : 'justify', - value : 'center' - },{ - label: '两端对齐', - cmdName : 'justify', - value : 'justify' - } - ] - },'-',{ - group : '表格', - icon : 'table', - subMenu : [ - { - label: '删除表格', - cmdName : 'deletetable' - }, - { - label: '表格前插行', - cmdName : 'insertparagraphbeforetable' - }, - '-', - { - label: '删除行', - cmdName : 'deleterow' - }, - { - label: '删除列', - cmdName : 'deletecol' - }, - '-', - { - label: '前插入行', - cmdName : 'insertrow' - }, - { - label: '前插入列', - cmdName : 'insertcol' - }, - '-', - { - label: '右合并单元格', - cmdName : 'mergeright' - }, - { - label: '下合并单元格', - cmdName : 'mergedown' - }, - '-', - { - label: '拆分成行', - cmdName : 'splittorows' - }, - { - label: '拆分成列', - cmdName : 'splittocols' - }, - { - label: '合并多个单元格', - cmdName : 'mergecells' - }, - { - label: '完全拆分单元格', - cmdName : 'splittocells' - } - ] - } - ], - theme:'default', - initialStyle: '', //编辑器内部样式 - initialContent: '欢迎光临编辑器', //初始化编辑器的内容 - autoClearinitialContent :true, //是否自动清除编辑器初始内容 - iframeCssUrl :'../../../themes/default/iframe.css', //要引入css的url - removeFormatTags : 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var', //配置格式刷删除的标签 - removeFormatAttributes : 'class,style,lang,width,height,align,hspace,valign', //配置格式刷删除的属性 - enterTag : 'br', //编辑器回车标签。p或br - maxUndoCount : 20, //最多可以回退的次数 - maxInputCount : 20, //当输入的字符数超过该值时,保存一次现场 - selectedTdClass : 'selectTdClass', //设定选中td的样式名称 - pasteplain : 0, //是否纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 - textarea : 'editorValue', //提交表单时,服务器端接收编辑器内容的名字 - focus : false, //初始化时,是否让编辑器获得焦点true或false - indentValue : '2em', //初始化时,首行缩进距离 - pageBreakTag : '_baidu_page_break_tag_', //分页符 - initialFrameHeight: 400, //最小高度 - autoHeightEnabled: true, //是否自动长高 - elementPathEnabled : false, //是否启用elementPath - serialize : function(){ //配置过滤标签 - function X( t, s, b ) { - var o = {}; - for(var i=0,ai;ai=arguments[i++];){ - for(var k in ai){ - o[k] = ai[k] - } - } - - return o; - } - var inline = {strong:1,em:1,b:1,i:1,u:1,span:1,a:1,img:1}; - var block = X(inline, {p:1,div:1,blockquote:1,$:{style:1,dir:1}}); - return { - blackList: {style:1,script:1,form:1,input:1,textarea:1,iframe:1,"#comment":1} -// , -// whiteList: { -// br: {$:{}}, -// span: X(inline, {$:{style:1,id:1}}), -// strong: inline, -// em:inline, -// b: inline, -// a: X(inline,{$:{href:1,'target':1,title:1}}), -// u: inline, -// div: block, -// p: block, -// ul: {li:1,$:{style:1}}, -// ol: {li:1,$:{style:1}}, -// li: block, -// img: {$:{style:1,width:1,height:1,src:1,alt:1,title:1}} -// } - }; - }() -}; \ No newline at end of file diff --git a/_test/editor_config_src.js b/_test/editor_config_src.js deleted file mode 100644 index ac6671f8..00000000 --- a/_test/editor_config_src.js +++ /dev/null @@ -1,285 +0,0 @@ -/** - * umeditor完整配置项 - * 可以在这里配置整个编辑器的特性 - */ -var UMEDITOR_CONFIG = { - UMEDITOR_HOME_URL: '../', //这里你可以配置成umeditor目录在您网站的绝对路径 - toolbars: [ - ['FullScreen','Source','|','Undo','Redo','|', - 'Bold','Italic','Underline','StrikeThrough','Superscript','Subscript','RemoveFormat','FormatMatch','|', - 'BlockQuote','|', - 'PastePlain','|', - 'ForeColor','BackColor','InsertOrderedList','InsertUnorderedList','|', - 'Paragraph','RowSpacing','FontFamily','FontSize','|', - 'DirectionalityLtr','DirectionalityRtl','|','','Indent','Outdent','|', - 'JustifyLeft','JustifyCenter','JustifyRight','JustifyJustify','|', - 'Link','Unlink','Anchor','Image','MultiMenu','Video','Map','GMap','Code', '|', - 'Horizontal','Date','Time','Spechars','|', - 'InsertTable','DeleteTable','InsertParagraphBeforeTable','InsertRow','DeleteRow','InsertCol','DeleteCol','MergeCells','MergeRight','MergeDown','SplittoCells','SplittoRows','SplittoCols','|', - 'SelectAll','ClearDoc','SearchReplace','Print','Preview','PageBreak','Help','AutoSave','InsertFrame'] - ], - labelMap: { - 'anchor':'锚点', - 'undo': '撤销', - 'redo': '重做', - 'bold': '加粗', - 'indent':'首行缩进', - 'outdent':'取消缩进', - 'italic': '斜体', - 'underline': '下划线', - 'strikethrough': '删除线', - 'subscript': '下标', - 'superscript': '上标', - 'formatmatch': '格式刷', - 'source': '源代码', - 'blockquote': '引用', - 'pasteplain': '纯文本粘贴模式', - 'selectall': '全选', - 'print': '打印', - 'preview': '预览', - 'horizontal': '分隔线', - 'removeformat': '清除格式', - 'time': '时间', - 'date': '日期', - 'unlink': '取消链接', - 'insertrow': '前插入行', - 'insertcol': '前插入列', - 'mergeright': '右合并单元格', - 'mergedown': '下合并单元格', - 'deleterow': '删除行', - 'deletecol': '删除列', - 'splittorows': '拆分成行', - 'splittocols': '拆分成列', - 'splittocells': '完全拆分单元格', - 'mergecells': '合并多个单元格', - 'deletetable': '删除表格', -// 'tablesuper': '表格高级设置', - 'insertparagraphbeforetable': '表格前插行', - 'cleardoc': '清空文档', - 'fontfamily': '字体', - 'fontsize': '字号', - 'paragraph': '格式', - 'image': '图片', - 'inserttable': '表格', - 'link': '超链接', - 'emoticon': '表情', - 'spechars': '特殊字符', - 'searchreplace': '查询替换', - 'map': 'Baidu地图', - 'gmap': 'Google地图', - 'video': '视频', - 'help': '帮助', - 'justifyleft':'居左对齐', - 'justifyright':'居右对齐', - 'justifycenter':'居中对齐', - 'justifyjustify':'两端对齐', - 'forecolor' : '字体颜色', - 'backcolor' : '背景色', - 'insertorderedlist' : '有序列表', - 'insertunorderedlist' : '无序列表', - 'fullscreen' : '全屏', - 'directionalityltr' : '从左向右输入', - 'directionalityrtl' : '从右向左输入', - 'rowspacing' : '行间距', - 'code' : '插入代码', - 'pagebreak':'分页', - 'insertframe':'插入Iframe' - }, - iframeUrlMap: { - 'anchor': '../../../dialogs/anchor/anchor.html', - 'image': '../../../dialogs/image/image.html', - 'inserttable': '../../../dialogs/table/table.html', - 'link': '../../../dialogs/link/link.html', - 'emoticon': '../../../dialogs/emoticon/emoticon.html', - 'spechars': '../../../dialogs/spechars/spechars.html', - 'searchreplace': '../../../dialogs/searchreplace/searchreplace.html', - 'map': '../../../dialogs/map/map.html', - 'gmap': '../../../dialogs/gmap/gmap.html', - 'video': '../../../dialogs/video/video.html', - 'help': '../../../dialogs/help/help.html', - 'code' : '../../../dialogs/code/code.html', - 'multimenu': '../../../dialogs/menu-emoticon/emoticon.html', - 'insertframe': '../../../dialogs/insertframe/insertframe.html' - }, - listMap: { - 'fontfamily': ['宋体', '楷体', '隶书', '黑体','andale mono','arial','arial black','comic sans ms','impact','times new roman'], - 'fontsize': [10, 11, 12, 14, 16, 18, 20, 24, 36], - 'underline':['none','overline','line-through','underline'], - 'paragraph': ['p:Paragraph', 'h1:Heading 1', 'h2:Heading 2', 'h3:Heading 3', 'h4:Heading 4', 'h5:Heading 5', 'h6:Heading 6'], - 'rowspacing' : ['1.0:0','1.5:15','2.0:20','2.5:25','3.0:30'] - }, - fontMap: { - '宋体': ['宋体', 'SimSun'], - '楷体': ['楷体', '楷体_GB2312', 'SimKai'], - '黑体': ['黑体', 'SimHei'], - '隶书': ['隶书', 'SimLi'], - 'andale mono' : ['andale mono'], - 'arial' : ['arial','helvetica','sans-serif'], - 'arial black' : ['arial black','avant garde'], - 'comic sans ms' : ['comic sans ms'], - 'impact' : ['impact','chicago'], - 'times new roman' : ['times new roman'] - }, - contextMenu: [ - { - label : '删除', - cmdName : 'delete' - - }, - { - label : '全选', - cmdName : 'selectall' - - },{ - label : '删除代码', - cmdName : 'highlightcode' - - },{ - label : '清空文档', - cmdName : 'cleardoc', - exec : function(){ - if(confirm('确定清空文档吗?')){ - this.execCommand('cleardoc'); - } - } - },'-',{ - label : '取消链接', - cmdName : 'unlink' - },'-',{ - group : '段落格式', - icon : 'justifyjustify', - subMenu : [ - { - label: '居左对齐', - cmdName : 'justify', - value : 'left' - }, - { - label: '居右对齐', - cmdName : 'justify', - value : 'right' - },{ - label: '居中对齐', - cmdName : 'justify', - value : 'center' - },{ - label: '两端对齐', - cmdName : 'justify', - value : 'justify' - } - ] - },'-',{ - group : '表格', - icon : 'table', - subMenu : [ - { - label: '删除表格', - cmdName : 'deletetable' - }, - { - label: '表格前插行', - cmdName : 'insertparagraphbeforetable' - }, - '-', - { - label: '删除行', - cmdName : 'deleterow' - }, - { - label: '删除列', - cmdName : 'deletecol' - }, - '-', - { - label: '前插入行', - cmdName : 'insertrow' - }, - { - label: '前插入列', - cmdName : 'insertcol' - }, - '-', - { - label: '右合并单元格', - cmdName : 'mergeright' - }, - { - label: '下合并单元格', - cmdName : 'mergedown' - }, - '-', - { - label: '拆分成行', - cmdName : 'splittorows' - }, - { - label: '拆分成列', - cmdName : 'splittocols' - }, - { - label: '合并多个单元格', - cmdName : 'mergecells' - }, - { - label: '完全拆分单元格', - cmdName : 'splittocells' - } - ] - } - ], - initialStyle: '', //编辑器内部样式 - initialContent: 'hello', //初始化编辑器的内容 - autoClearinitialContent :true, //是否自动清除编辑器初始内容 - iframeCssUrl :'../../../themes/default/iframe.css', //要引入css的url - removeFormatTags : 'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var', //配置格式刷删除的标签 - removeFormatAttributes : 'class,style,lang,width,height,align,hspace,valign', //配置格式刷删除的属性 - enterTag : 'p', //编辑器回车标签。p或br - maxUndoCount : 20, //最多可以回退的次数 - maxInputCount : 20, //当输入的字符数超过该值时,保存一次现场 - selectedTdClass : 'selectTdClass', //设定选中td的样式名称 - pasteplain : 0, //是否纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 - textarea : 'editorValue', //提交表单时,服务器端接收编辑器内容的名字 - focus : false, //初始化时,是否让编辑器获得焦点true或false - indentValue : '2em', //初始化时,首行缩进距离 - pageBreakTag : '_baidu_page_break_tag_', //分页符 - autoSave:true, //是否开启自动保存 - autoSavePath:this.UMEDITOR_HOME_URL+'auto-save.php', //自动保存的地址 - autoSaveFrequency:5, //自动保存频率 - minFrameHeight: 320, //最小高度 - autoHeightEnabled: true, //是否自动长高 - autoFloatEnabled: true, //是否保持toolbar的位置不动 - elementPathEnabled : true, //是否启用elementPath - serialize : function(){ //配置过滤标签 - function X( t, s, b ) { - var o = {}; - for(var i=0,ai;ai=arguments[i++];){ - for(var k in ai){ - o[k] = ai[k] - } - } - - return o; - } - var inline = {strong:1,em:1,b:1,i:1,u:1,span:1,a:1,img:1}; - var block = X(inline, {p:1,div:1,blockquote:1,$:{style:1,dir:1}}); - return { - blackList: {style:1,script:1,form:1,input:1,textarea:1,"#comment":1} -// , -// whiteList: { -// br: {$:{}}, -// span: X(inline, {$:{style:1,id:1}}), -// strong: inline, -// em:inline, -// b: inline, -// a: X(inline,{$:{href:1,'target':1,title:1}}), -// u: inline, -// div: block, -// p: block, -// ul: {li:1,$:{style:1}}, -// ol: {li:1,$:{style:1}}, -// li: block, -// img: {$:{style:1,width:1,height:1,src:1,alt:1,title:1}} -// } - }; - }() -}; \ No newline at end of file diff --git a/_test/import.js b/_test/import.js deleted file mode 100644 index e034d1ed..00000000 --- a/_test/import.js +++ /dev/null @@ -1,70 +0,0 @@ - -///import editor; - -///import core/browser; -///import core/utils; -///import core/EventBase; -///import core/dtd; -///import core/domUtils; -///import core/Range; -///import core/Selection; -///import core/Editor; -///import core/filterword; -///import core/node; -///import core/htmlparser; -///import core/filternode; - - -///import plugins/removeformat; -///import plugins/font; -///import plugins/justify; -///import plugins/inserthtml; -///import plugins/link; -///import plugins/horizontal; -///import plugins/image; -///import plugins/selectall; -///import plugins/paragraph; -///import plugins/cleardoc; -///import plugins/preview; -///import plugins/print; -///import plugins/basestyle; -///import plugins/undo; -///import plugins/paste; -///import plugins/source; -///import plugins/enterkey; -///import plugins/keystrokes; -///import plugins/list; -///import plugins/video; -///import plugins/dropfile; -///import plugins/autosave; -///import plugins/formula; - -///import adapter/adapter; -///import adapter/autofloat; -///import adapter/autoheight; -///import adapter/button; -///import adapter/dialog; -///import adapter/combobox; -///import adapter/fullscreen; -///import adapter/popup; -///import adapter/imagescale; -///import adapter/source; - - -///import ui/widget; -///import ui/button; -///import ui/menu; -///import ui/dropmenu; -///import ui/splitbutton; -///import ui/colorsplitbutton; -///import ui/popup; -///import ui/scale; -///import ui/colorpicker; -///import ui/combobox; -///import ui/buttoncombobox; -///import ui/modal; -///import ui/tooltip; -///import ui/tab; -///import ui/separator; -///import ui/toolbar; - diff --git a/_test/index.php b/_test/index.php deleted file mode 100644 index 8dc8f7d4..00000000 --- a/_test/index.php +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/_test/plugins/autosave.js b/_test/plugins/autosave.js deleted file mode 100644 index 496d49d2..00000000 --- a/_test/plugins/autosave.js +++ /dev/null @@ -1,101 +0,0 @@ -module( "plugins.autosave" ); - -test('自动保存', function () { - - var count = 0; - UM.clearCache('testDefault'); - $('.edui-body-container')[0].parentNode.removeChild($('.edui-body-container')[0]); - var container = document.createElement("div"); - container.id = "container"; - document.body.appendChild(container); - - editor = UM.getEditor("container", { - initialContent: "", - //无限制 - saveInterval: 0 - }); - - - editor.addListener("beforeautosave", function (type, data) { - - data.content = data.content.toLowerCase(); - equal(true, true, "成功触发beforeautosave事件"); - equal(data.content === "

    http://www.baidu.com

    " || data.content === "

    disable

    ", true, "事件携带数据正确"); - }); - - editor.addListener("beforeautosave", function (type, data) { - data.content = data.content.toLowerCase(); - if (data.content === "

    disable

    ") { - return false; - } - - count++; - - }); - - editor.addListener("afterautosave", function (type, data) { - - data.content = data.content.toLowerCase(); - equal(data.content, "

    http://www.baidu.com

    ", "成功触发afterautosave事件"); - window.setTimeout(function () { - equal(editor.execCommand("getlocaldata") !== null, true, "getlocaldata命令正常"); - editor.execCommand("clearlocaldata"); - equal(editor.execCommand("getlocaldata") === "", true, "clearlocaldata命令正常"); - }, 50); - }); - - stop(); - window.setTimeout(function () { - - editor.setContent('

    disable

    '); - - - window.setTimeout(function () { - - editor.setContent('

    http://www.baidu.com

    '); - - window.setTimeout(function () { - - equal(count, 1, "触发事件次数"); - UM.delEditor("container"); - document.getElementById('container') && document.getElementById('container').parentNode.removeChild(document.getElementById('container')); - start(); - }, 500); - - }, 50); - - }, 500); - -}); -test('重建编辑器,加载草稿箱', function () { - if(ua.browser.ie<9)return;//延迟问题,手动过 - UM.clearCache('testDefault'); - $('.edui-body-container')[0].parentNode.removeChild($('.edui-body-container')[0]); - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue', {saveInterval: 0}); - setTimeout(function () { - var content = '

    内容

    '; - editor.setContent(content); - setTimeout(function () { - UM.delEditor('ue'); - document.getElementById('ue') && document.getElementById('ue').parentNode.removeChild(document.getElementById('ue')); - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor2 = UM.getEditor('ue'); - setTimeout(function () { - equal(editor2.queryCommandState('drafts'), 0, '草稿箱可用'); - editor2.execCommand('drafts'); - ua.checkSameHtml(editor2.body.innerHTML, content, '内容加载正确'); - setTimeout(function () { - - UM.delEditor('ue'); - document.getElementById('ue') && document.getElementById('ue').parentNode.removeChild(document.getElementById('ue')); - start(); - }, 2000); - - }, 500); - }, 200); - }, 500); - stop(); -}); \ No newline at end of file diff --git a/_test/plugins/basestyle.js b/_test/plugins/basestyle.js deleted file mode 100644 index aa3ee19a..00000000 --- a/_test/plugins/basestyle.js +++ /dev/null @@ -1,334 +0,0 @@ -module( "plugins.basestyle" ); - -//test( 'bold-在已加粗文本中间去除加粗', function () {//原生问题不修了 -// var editor = te.obj[0]; -// var body = editor.body; -// var range = te.obj[1]; -// editor.setContent( 'hellossss' ); -// range.setStart( body.firstChild.firstChild, 0 ).collapse( true ).select(); -// editor.execCommand( 'bold' ); -// -// //range = editor.selection.getRange(); -// equal( editor.queryCommandState( 'bold' ), 0, " 被去掉" ); -//// range.insertNode( range.document.createTextNode( 'aa' ) ); /*在当前的range选区插入文本节点*/ -//// ua.manualDeleteFillData( editor.body ); -//// equal( ua.getChildHTML( body.firstChild ), "aahellossss", "新文本节点没有加粗" ); -//} ); - - -test('trace:3886:多实例插入图片',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent("

    123

    "); - var text = body.firstChild.firstChild; - range.setStart(text,'0').collapse(true).select(); - var div2 = document.body.appendChild(document.createElement('div')); - $(div2).css('width', '500px').css('height', '200px').css('border', '1px solid #ccc'); - div2.id = 'testDefault2'; - te.obj[2].render(div2); - editor.execCommand('insertimage',{ - src:'http://img.baidu.com/hi/jx2/j_0001.gif', - width:50, - height:52 - }); - te.obj[2].execCommand('insertimage',{ - src:'http://img.baidu.com/hi/jx2/j_0002.gif', - width:50, - height:52 - }); - equal($('img')[0].src,'http://img.baidu.com/hi/jx2/j_0001.gif','实例1,插入图片成功'); - equal($('img')[1].src,'http://img.baidu.com/hi/jx2/j_0002.gif','实例2,插入图片成功'); - $(div2).remove(); -}); - -test('trace:3941:超链接设置标题',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent('

    university

    '); - var text = body.firstChild.firstChild; - range.setStart(text,0).setEnd(text,10).select(); - editor.execCommand('link',{ - url:'www.baidu.com', - title:'myUniversity'}); - var title = $('a').attr('title'); - equal(title,'myUniversity','设置超链接标题'); -}); - -test('trace:3881:输入空行,内容不可编辑',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent('



    123

    '); - var text = body.firstChild.lastChild.firstChild; - range.setStart(text,0).collapse(1).select(); - editor.execCommand('formula','\\int{x}{y}'); - editor.setDisabled(); - var t = $('div').find('br').length; - equal(t,3,'不可编辑状态显示正确'); -}); - -test('trace:3880:插入公式',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent('
    1. x
    2. hello2
    3. hello3
    '); - var text = body.firstChild.firstChild.firstChild; - range.setStart(text,0).collapse(true).select(); - editor.execCommand('formula','\\int{x}{y}'); - var text3 = $(".mathquill-embedded-latex").attr("data-latex"); - equal(text3,'\\int{x}{y}','公式插入成功'); -}); - -test('trace:3873:无序列表转换',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent('
    1. hello1
    2. hello2
    3. hello3
    '); - var text = body.firstChild.firstChild.nextSibling.firstChild; - range.setStart(text,1).collapse(true).select(); - editor.execCommand('insertunorderedlist'); - var text2 = body.children; - if(text2.length==1){ - ok(false,'列表转换失败,影响到其他行的状态'); - }else{ - var f = body.firstChild; - equal(f.tagName,'OL','检测一:有序列表的某一行转无序,未影响其它行'); - var fff = body.firstChild.nextSibling; - equal(fff.tagName,'UL','检测三:有序列表的某一行转无序,未影响其它行'); - var ff = body.lastChild; - equal(ff.tagName,'OL','检测二:有序列表的某一行转无序,未影响其它行'); - } -}); - -test('trace:3869:多次切换源码,保留选区',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent('

    This is a test word

    '); - var text = body.firstChild.firstChild; - range.setStart(text,0).setEnd(text,4).select(); - var text2 = editor.selection.getText(); - editor.execCommand('bold');//加粗 - editor.execCommand('italic');//字体倾斜 - editor.execCommand('source');//切换到源码状态 - stop(); - setTimeout(function(){ - editor.execCommand('source'); - var text3 = editor.selection.getText(); - editor.execCommand('source');//第二次切换到源码状态 - editor.execCommand('source');//第二次从源码切换到编辑状态 - var text4 = editor.selection.getText(); - equal(text2,text4,'源码和编辑状态切换,保留选区'); - start(); - },100); -}); - -test('removeformat-清除格式',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent( '
    hello1
    hello2
    ' ); - var tttt = body.firstChild.firstChild.firstChild.firstChild; - range.selectNode(tttt).select(); - editor.execCommand('removeformat');//清除格式 - equal( ua.getChildHTML( tttt ), 'hello1' ,'不闭合光标,清除格式');//不闭合光标 - editor.execCommand('bold'); - range.setStart(tttt,0).collapse(true).select(); //闭合光标 - editor.execCommand('removeformat');//清除格式 - var tar='hello1'; - if(ua.browser.ie){ - tar = 'hello1'; - } - equal( ua.getChildHTML(tttt),tar,'闭合光标,清除格式'); -}); - -test( 'trace:3940:bold-加粗图标状态',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent('

    This is a test word

    '); - var text = body.firstChild.firstChild; - range.setStart(text,0).collapse(true).select();//闭合选择 - editor.execCommand('bold');//第一次加粗 - equal(editor.queryCommandState( 'bold' ), 1, '闭合选择,加粗高亮' ); - editor.execCommand('bold');//第二次加粗 - equal(editor.queryCommandState( 'bold' ), 0,'闭合选择,取消加粗高亮' ); - editor.setContent('

    This is a test word

    '); - text = body.firstChild.firstChild; - range.setStart(text,0).setEnd(text,1).select();//不闭合选择 - editor.execCommand('bold');//第一次加粗 - equal(editor.queryCommandState( 'bold' ), 1, '不闭合选择,加粗高亮' ); - editor.execCommand('bold');//第二次加粗 - equal(editor.queryCommandState( 'bold' ), 0,'不闭合选择,取消加粗高亮' ); -}); - -test( 'bold-加粗状态反射', function () { - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent( '

    This is a dog

    ' ); - stop(); - setTimeout( function () { - range.selectNode( body.firstChild ).select(); - editor.execCommand( 'bold' ); - range.setStart( body.firstChild.firstChild.firstChild, 2 ).collapse( true ).select(); - equal( editor.queryCommandState( 'bold' ), 1, '闭合选择,加粗高亮' ); - ua.manualDeleteFillData( editor.body ); - range.setStart( body.firstChild.firstChild.firstChild, 0 ).setEnd( body.firstChild.firstChild.lastChild, 4 ).select(); - equal( editor.queryCommandState( 'bold' ), 1, '不闭合选择,加粗高亮' ); - start(); - }, 100 ) -} ); - -test( 'bold-连续加粗2次', function () { - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent( '

    this is a dog

    ' ); - var text = body.firstChild.firstChild; - range.setStart( text, 0 ).setEnd( text, 3 ).select(); - editor.execCommand( 'bold' ); /*第一次加粗*/ - equal( editor.queryCommandState( 'bold' ), 1, '加粗按钮高亮' ); - text = body.firstChild.lastChild; - range.setStart( text, 1 ).setEnd( text, 3 ).select(); /*不闭合选区文本*/ - equal( editor.queryCommandState( 'bold' ), 0, '不闭合选择,加粗不高亮' ); - ua.manualDeleteFillData( editor.body ); - editor.execCommand( 'bold' ); /*第二次加粗*/ - stop(); - setTimeout( function () { - equal( editor.queryCommandState( 'bold' ), 1, '加粗高亮' ); - start(); - }, 100 ) -} ); - -test( 'bold-2个单词,中间有空格第一个单词加粗,第二个单词加粗再去加粗', function () { - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - body.innerHTML = '

    hello world

    '; //用setContent复现不了这个问题 - var text = body.firstChild.firstChild; - range.setStart( text, 0 ).setEnd( text, 5 ).select(); - editor.execCommand( 'bold' ); - text = body.firstChild.lastChild; - range.setStart( text, 1 ).setEnd( text, 6 ).select(); - editor.execCommand( 'bold' ); - editor.execCommand( 'bold' ); - ok( body.firstChild.childNodes.length==3&&body.firstChild.childNodes[1].length ==1, '空格保留'); -} ); - -test( '测试 userAction.manualdeleteFilldata', function () { - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent( '

    ' ); - var fillData = editor.document.createTextNode( domUtils.fillChar ); // 在ie 6,7下,使用appendChild时,需要body先加载,必须将上句document前加editor,否则出错 - body.appendChild( fillData ); - var space = ua.browser.ie ? ' ' : '
    ';//getContent()结果:‘
    ’,innerHTML结果:
    - notEqual( body.innerHTML.toLowerCase(), '

    ' + space + '

    ', '清除不可见字符前不相等' ); - ua.manualDeleteFillData( body ); - //equal( body.innerHTML.toLowerCase(), '

    ' + space + '

    ', '清除不可见字符后相等' ); - equal(body.innerHTML.toLowerCase(),'

    ','清除不可见字符后相等'); //断言合理性待定 -} ); - -test( 'trace 1884:单击B再单击I ', function () { - if(ua.browser.ie==8)return ;//todo 测试机上有问题,自己的虚拟机上没问题 - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent( '' ); - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'bold' ); - equal( editor.queryCommandState( 'bold' ), 1, 'b高亮' ); - editor.execCommand( 'italic' ); - equal( editor.queryCommandState( 'italic' ), 1, 'b高亮' ); -} ); - -test( 'ctrl+i', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - var body = editor.body; - editor.setContent( '

    没有加粗的文本

    ' ); - range.selectNode( body.firstChild ).select(); - var p = body.firstChild; - editor.focus(); - setTimeout( function() { - ua.keydown(editor.body,{'keyCode':73,'ctrlKey':true}); - editor.focus(); - setTimeout( function() { - if(ua.browser.ie ) - equal( ua.getChildHTML( p ), '没有加粗的文本' ); - else - equal(ua.getChildHTML(p),'没有加粗的文本'); - te.dom.push(editor.container); - //UM.delEditor('ue'); - start(); - }, 150 ); - }, 100 ); - }); - stop(); -} ); - - -test( 'ctrl+b', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue1'; - var editor = UM.getEditor('ue1'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - var body = editor.body; - editor.setContent( '

    没有加粗的文本

    ' ); - range.selectNode( body.firstChild ).select(); - var p = body.firstChild; - editor.focus(); - setTimeout( function() { - ua.keydown(editor.body,{'keyCode':66,'ctrlKey':true}); - editor.focus(); - setTimeout( function() { - if(!ua.browser.ie) - { - equal( ua.getChildHTML( p ), '没有加粗的文本' ); - - } - else - { - equal(ua.getChildHTML( p ),'没有加粗的文本'); - - } - te.dom.push(editor.container); - //UM.delEditor('ue'); - start(); - }, 150 ); - }, 100 ); - }); - stop(); -} ); -test( 'ctrl+u', function() { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue2'; - var editor = UM.getEditor('ue2'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - var body = editor.body; - - editor.setContent( '

    没有加粗的文本

    ' ); - setTimeout( function() { - range.selectNode( body.firstChild ).select(); - editor.focus(); - setTimeout( function() { - var html = '没有加粗的文本'; - ua.checkHTMLSameStyle( html, editor.document, body.firstChild, '文本被添加了下划线' ); - //equal(editor.body.firstChild.firstChild.style.textDecoration,'underline'); - //UM.delEditor('ue'); - te.dom.push(editor.container); - start(); - }, 150 ); - ua.keydown(editor.body,{'keyCode':85,'ctrlKey':true}); - }, 150 ); - }); - stop(); -} ); \ No newline at end of file diff --git a/_test/plugins/cleardoc.js b/_test/plugins/cleardoc.js deleted file mode 100644 index d0c9cd3b..00000000 --- a/_test/plugins/cleardoc.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Created by JetBrains PhpStorm. - * User: shenlixia01 - * Date: 11-8-15 - * Time: 下午3:47 - * To change this template use File | Settings | File Templates. - */ -module( 'plugins.cleardoc' ); - -test( '取得焦点后清空后查看range', function () { - var editor = te.obj[0]; - editor.setContent( '
    1. hello1
    2. 你好

    hello1

    hello2
    ' ); - editor.focus(); - var body = editor.body; - editor.execCommand( 'cleardoc' ); - ua.manualDeleteFillData( editor.body ); - if ( UM.browser.ie ) { - equal( ua.getChildHTML( body ), '

    ' ); //目前ie清空文档后不放空格占位符 - } - else { - equal( ua.getChildHTML( body ), '


    ', '清空文档' ); - } -} ); - -test( '编辑器没有焦点,清空', function () { - var editor = te.obj[0]; - editor.setContent( '

    hello

    hello1

    hello2
    ' ); - var body = editor.body; - editor.execCommand( 'cleardoc' ); - ua.manualDeleteFillData( editor.body ); - if ( UM.browser.ie ) { - equal( ua.getChildHTML( body ), '

    ' ); - } - else { - equal( ua.getChildHTML( body ), '


    ', '清空文档' ); - } -} ); - -test('选中文本,清空',function(){ - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent('

    hello

    hello1

    ') - range.selectNode(editor.body.firstChild).select(); - editor.execCommand('cleardoc'); - var br = ua.browser.ie?'':'
    '; - equal(ua.getChildHTML(editor.body),'

    '+br+'

    ',''); -}); - -test( '全选后删除', function() { - var editor = te.obj[0]; - if ( UM.browser.ie ) - editor.setContent( '

    dsafds 

     

     

     

     

     

     

    ' ); - else - editor.setContent( '




    d






    ' ); - setTimeout(function() { - editor.focus(); - editor.execCommand( 'selectall' ); - editor.execCommand( 'cleardoc' ); - ua.manualDeleteFillData(editor.body); - equal( editor.body.childNodes.length, 1, '删除后只剩一个bolock元素' ); - equal( editor.body.firstChild.tagName.toLowerCase(), 'p', '删除后只剩一个p' ); - if ( !ua.browser.ie ) - equal( editor.body.lastChild.innerHTML, '
    ', '内容被删除了' ); - else - equal( editor.body.lastChild.innerHTML, '', '内容被删除了' ); - start(); - },50); - stop(); -} ); \ No newline at end of file diff --git a/_test/plugins/dropfile.js b/_test/plugins/dropfile.js deleted file mode 100644 index f59f7688..00000000 --- a/_test/plugins/dropfile.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: dongyancen - * Date: 13-8-19 - * Time: 下午3:11 - * To change this template use File | Settings | File Templates. - */ -module("plugins.dropfile"); -test( 'dropfile', function () { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var fileList = [ - {type: "image/jpeg", size: 42466, name: "cc50ddfcc3cec3fdd59d8becd688d43f8694274d.jpg"} - ] - var originalEvent = {dataTransfer: {files: fileList}}; - editor.$body.trigger( {type:"drop",originalEvent: originalEvent}); - setTimeout(function () { - UM.clearCache('ue'); - te.dom.push(editor.container); - start(); - }, 600); - }); - stop(); -} ); \ No newline at end of file diff --git a/_test/plugins/enterkey.js b/_test/plugins/enterkey.js deleted file mode 100644 index eb58f1be..00000000 --- a/_test/plugins/enterkey.js +++ /dev/null @@ -1,65 +0,0 @@ -module( 'plugins.enterkey' ); - -///*不作处理chrome会产生div*/ -test( 'chrome删除div', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - if(ua.browser.chrome){ - editor.body.innerHTML = '

    一级标题


    '; - range.setStart( body.firstChild.firstChild, 4 ).collapse( 1 ).select(); - ua.keydown(editor.body,{'keyCode':13}); - range.selectNode(body.lastChild).select(); - var index = editor.undoManger.index; - var br = ua.browser.ie ? '' : '
    '; - ua.keyup(editor.body,{'keyCode':13}); - equal(editor.undoManger.list.length,2,'保存现场'); - setTimeout( function () { - equal( body.childNodes.length, 2, '2个子节点' ); - equal(body.lastChild.tagName.toLowerCase(),'p','div转成p'); - equal(ua.getChildHTML(body),'

    一级标题


    ','检查内容'); - start(); - }, 60 ); - stop(); - }else{ - } -} ); -test( 'formatBlock', function () { - if(ua.browser.ie) return ;//ie时没有做处理 - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '
    hello1
    hello2
    ' ); - var tds = editor.body.getElementsByTagName('td'); - range.setStart(tds[0].firstChild,6).collapse(true).select(); - ua.keydown(editor.body,{'keyCode':13}); - setTimeout( function () { - ua.keyup(editor.body,{'keyCode':13}); - setTimeout( function () { - var td = editor.body.getElementsByTagName('td')[0]; - if(!ua.browser.ie){ - equal(td.firstChild&&td.firstChild.tagName.toLowerCase(),'p','加上p'); - equal(td.firstChild.innerHTML,'hello1','hello1'); - } - else - equal(ua.getChildHTML(td),'hello1','try'); - start(); - }, 60 ); - }, 60 ); - stop(); -} ); - -test( '跨td不删', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '
    hello1
    hello2
    ' ); - var tds = editor.body.getElementsByTagName('td'); - range.setStart(tds[0],0).setEnd(tds[2],1).select(); - editor.addListener("keydown", function (type, evt) { - setTimeout( function () { - ok(evt.defaultPrevented||!evt.returnValue, "keydown"); - start(); - }, 60 ); - }); - ua.keydown(editor.body,{'keyCode':13}); - stop(); -} ); \ No newline at end of file diff --git a/_test/plugins/font.js b/_test/plugins/font.js deleted file mode 100644 index d171e8c5..00000000 --- a/_test/plugins/font.js +++ /dev/null @@ -1,430 +0,0 @@ -module("plugins.font"); -test('trace 3606 3625 设置超链接前景色,背景色', function () { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    hellobaidu

    '); - range.selectNode(editor.body.firstChild).select(); - editor.execCommand('foreColor', 'rgb(255,0,0)'); - editor.execCommand('backColor', 'rgb(0,255,0)'); - //var html = 'hellobaidu';todo 1.2.6.1 样式复制了一次 - //var html = 'hellobaidu'; - // - var forecolor = ua.browser.ie?"rgb(255,0,0)":"#ff0000"; - var html = 'hellobaidu'; - if(ua.browser.gecko){ - html='hellobaidu' - } - else if(ua.browser.ie){ - html = 'hellobaidu' - } - ua.checkSameHtml(editor.body.firstChild.innerHTML,html,''); - setTimeout(function () { - div.parentNode.removeChild(div); - start(); - }, 100); - }); -}); - -test('underline and linethrough', function () { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('hellobaidutest'); - setTimeout(function () { - if (!ua.browser.opera) { - editor.focus(); - } - var body = editor.body; - ua.manualDeleteFillData(editor.body); - range.selectNode(body.firstChild.firstChild.nextSibling).select(); - //equal(editor.queryCommandValue('underline'), 'underline', 'query command value is underline'); - //equal(editor.queryCommandValue('strikethrough'), 'underline', 'query command value is not strike'); -// ok(editor.queryCommandState('underline'), 'query underline state'); - editor.execCommand('strikethrough'); - //var html = 'hellobaidutest'; - //ua.checkHTMLSameStyle(html, editor.document, body.firstChild, 'check results'); - if(ua.browser.webkit||ua.browser.ie) - { - var html = 'hellobaidutest'; - equal(editor.body.firstChild.innerHTML.toLowerCase(),html,'超链接也可以添加删除线'); - ua.checkHTMLSameStyle(html, editor.document, body.firstChild, 'check results'); - } - else - { - var html = 'hellobaidutest'; - equal(editor.body.firstChild.innerHTML.toLowerCase(),html,'超链接也可以添加删除线'); - ua.checkHTMLSameStyle(html, editor.document, body.firstChild, 'check results'); - } - setTimeout(function () { - div.parentNode.removeChild(div); - start(); - }, 100); - }, 50); - }); -}); - - - -test('字体的状态反射', function () { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    欢迎你回来

    '); - var p = editor.body.firstChild; - range.selectNode(p).select(); - editor.execCommand('underline'); - var p1 = document.createElement('p'); - //p1.innerHTML = '欢迎你回来'; - p1.innerHTML = '欢迎你回来'; - var html = '

    欢迎你回来

    '; - if (!ua.browser.opera) { - ok(ua.haveSameAllChildAttribs(p, p1), '检查是否添加了下划线'); - equal(editor.getContent('p'),html,'检查是否添加了下划线'); - } - range.setStart(p.firstChild.firstChild, 3).setEnd(p.firstChild.firstChild, 4).select(); - editor.execCommand('fontfamily', '楷体'); - if (ua.browser.webkit || ua.browser.ie ||ua.browser.gecko) - var txt = '楷体'; - else - if(ua.browser.opera) - txt = '\"楷体\"'; - else - txt = 'sans-serif'; - equal(editor.queryCommandValue('fontfamily'), txt, '检查字体的状态反射'); - setTimeout(function () { - div.parentNode.removeChild(div); - start(); - }, 50); - }); -}); - - - -test('选中文本设置前景色',function(){//ie8不执行 - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent('

    我是mini

    '); - range.selectNode(editor.body.firstChild).select(); - if(!ua.browser.ie) - editor.execCommand('forecolor','rgb(255,0,0)');//ie8下去掉execCommand(),竟然结果是正确的,待定 - if(ua.browser.chrome) - { - var html = '

    我是mini

    '; - ua.checkSameHtml(html,editor.body.firstChild.outerHTML,'设置文本前景色为红色'); - } - else - { - var html ='

    我是mini

    '; - ua.checkHTMLSameStyle(html,editor.document,editor.body, '设置文本前景色为红色'); - } - -}); - - -test('闭合时改变前景色和删除线,再输入文本', function () { - if (!ua.browser.opera) { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    你好

    '); - var p = editor.body.firstChild; - range.setStart(p.firstChild, 1).collapse(true).select(); - editor.execCommand('forecolor', 'rgb(0,255,0)'); - //range = editor.selection.getRange(); - editor.execCommand('underline'); - range = editor.selection.getRange(); - range.insertNode(editor.document.createTextNode('hey')); - var p1 = editor.document.createElement('p'); - //p1.innerHTML = '你好​hey';//chrome、ff、ie8下手动操作是正确的,用例无法模拟添加下划线操作 - p1.innerHTML = '你好hey'; - ua.manualDeleteFillData(editor.body); - /*ff下会自动加一个空的设置了style的span,比较时不作考虑*/ - if (UM.dom.domUtils.isEmptyNode(editor.body.firstChild.lastChild) && UM.browser.gecko) - editor.body.firstChild.removeChild(editor.body.firstChild.lastChild); - //ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '检查新输入的文本下划线和颜色是否正确'); - - ua.checkSameHtml( p1.innerHTML,editor.body.firstChild.innerHTML, '检查新输入的文本下划线和颜色是否正确'); - //equal(editor.body.firstChild.innerHTML,p1.innerHTML,'try'); - setTimeout(function () { - div.parentNode.removeChild(div); - start(); - }, 50); - }); - } -}); - -//test('trace 805:切换删除线和下划线,前景色没了', function () { -// var editor = te.obj[2]; -// var div = document.body.appendChild(document.createElement('div')); -// $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); -// editor.render(div); -// stop(); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// editor.setContent('

    你好早安

    '); -// var text = editor.body.firstChild.firstChild.firstChild; -// range.selectNode(text).select(); -// editor.execCommand('forecolor', 'rgb(255,0,0)'); -// range.setStart(text, 0).setEnd(text, 2).select(); -// editor.execCommand('underline'); -// range.setStart(text, 0).setEnd(text, 2).select(); -// editor.execCommand('strikethrough'); -// var p1 = editor.document.createElement('p'); -// p1.innerHTML = '你好早安'; -// ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '查看前景色是不是还在'); -// setTimeout(function () { -// div.parentNode.removeChild(div); -// start(); -// }, 50); -// }); -//}); - - -//test(':对字体设置前景色,然后进行下划线和删除线操作,前景色不消失',function(){//ie8不执行 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// editor.setContent('

    你好北京

    '); -// var text = editor.body.firstChild.firstChild.firstChild; -// //range.selectNode(text).select(); -// range.setStart(text,0).setEnd(text,4).select(); -// editor.execCommand('forecolor','rgb(255,0,0)'); -// range.setStart(text,0).setEnd(text,2).select();//选中的是‘你好’ -// editor.execCommand('underline'); -// range.setStart(text,0).setEnd(text,2).select();//选中的是‘北京’ -// editor.execCommand('strikethrough'); -// var p1 = editor.document.createElement('p'); -// p1.innerHTML = '你好北京'; -// var html = '

    你好北京

    '; -// equal(ua.getChildHTML(editor.body).toLowerCase(),p1.outerHTML,'前景色不消失'); -// equal(editor.getContent(editor.body),html,'try'); -//}); - -test('为设置了字体的文本添加删除线', function () { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    你好早安

    '); - var text = editor.body.firstChild.firstChild.firstChild; - range.setStart(text, 0).setEnd(text, 2).select(); - editor.execCommand('strikethrough'); - var p1 = editor.document.createElement('p'); -// p1.innerHTML = '你好早安'; -// ok(ua.haveSameAllChildAttribs(editor.body.firstChild, p1), '检查删除线是否正确'); - p1.innerHTML = '你好早安'; - equal(editor.body.firstChild.innerHTML,p1.innerHTML,'删除线存在'); - editor.execCommand('fontfamily', '隶书'); - editor.focus(); - var txt = '隶书'; - if (ua.browser.opera) - txt = '\"隶书\"'; - equal(editor.queryCommandValue('fontfamily'), txt); - setTimeout(function () { - div.parentNode.removeChild(div); - start(); - }, 50); - }); -}); - -test('设置超链接背景色后切换到源码再切回来', function () { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    hellobaidu

    '); - range.selectNode(editor.body.firstChild).select(); - editor.execCommand('backcolor', 'rgb(255,0,0)'); - var html = '

    hellobaidu

    '; - var html_ie = "

    hellobaidu

    "; - - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - - ua.checkSameHtml(editor.body.innerHTML,ua.browser.ie?html_ie:html,'切换后html代码不变'); -// /*切换源码前后代码应当相同*/ - div.parentNode.removeChild(div); - start(); - }, 50); - }, 50); - }); -}); - - -//test('trace 740:设置左右字为红色,修改部分字颜色为蓝色,再修改所有字体', function () {//在ff下 有东西没删干净 -// var editor = te.obj[2]; -// var div = document.body.appendChild(document.createElement('div')); -// $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); -// editor.render(div); -// stop(); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// editor.setContent('

    你好早安

    '); -// range.selectNode(editor.body.firstChild).select(); -// editor.execCommand('forecolor', 'rgb(255,0,0)'); -// var text = editor.body.firstChild.firstChild.firstChild; -// range.setStart(text, 2).setEnd(text, 4).select(); -// editor.execCommand('forecolor', 'rgb(0,255,0)'); -// range.setStart(editor.body.firstChild, 0).setEnd(editor.body.firstChild, 1).select(); -// editor.execCommand('fontfamily', ' 楷体, 楷体_GB2312, SimKai'); -// //editor.execCommand('fontfamily','楷体'); -// setTimeout(function () { -// //todo 1.2.6.1 去掉多余的复制样式 -// var html = '你好早安'; -// ua.checkSameHtml(html,editor.body.firstChild.innerHTML, '查看字体和颜色是否正确'); -// div.parentNode.removeChild(div); -// start(); -// }, 50); -// }); -//}); - -//test('trace 740:设置左右字为红色,修改部分字颜色为蓝色,再修改所有字体----', function () {//ie8不能执行 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// editor.setContent('

    你好早安

    '); -// range.selectNode(editor.body.firstChild).select(); -// editor.execCommand('forecolor', 'rgb(255,0,0)'); -// var text = editor.body.firstChild.firstChild.firstChild; -// range.setStart(text, 2).setEnd(text, 4).select(); -// editor.execCommand('forecolor', 'rgb(0,255,0)'); -// range.setStart(editor.body.firstChild, 0).setEnd(editor.body.firstChild, 1).select(); -// editor.execCommand('fontfamily', ' 楷体, 楷体_GB2312, SimKai '); -// stop(); -// setTimeout(function () { -// //todo 1.2.6.1 去掉多余的复制样式 -// //var html = '你好早安'; -// if(ua.browser.chrome) -// { -// -// var html = '你好早安'; -// ua.checkSameHtml(html,editor.body.firstChild.innerHTML, '查看字体和颜色是否正确'); -// } -// else -// { -// //var html1 = '

    你好早安

    '; -// var html1 = '

    你好早安

    '; -// equal(editor.getContent(editor.body),html1,'查看字体和颜色是否正确'); -// } -// start(); -// }, 50); -//}); - -test('预先设置字体颜色,再输入文本,查看文本颜色', function () { - if (!ua.browser.opera) { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - editor.render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('


    '); - range.setStart(editor.body.firstChild, 0).collapse(true).select(); - editor.execCommand('forecolor', 'rgb(255,0,0)'); - range = editor.selection.getRange(); - range.insertNode(editor.document.createTextNode('hello')); - ua.manualDeleteFillData(editor.body); - var html = 'hello
    '; - ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '查看文本颜色是否与设置的字体颜色一致'); - setTimeout(function () { - div.parentNode.removeChild(div); - start(); - }, 50); - }); - } -}); -test('font不转span', function () { - var editor = te.obj[0]; - editor.focus(); - editor.setContent('hellohello'); - var html = 'hellohello'; - var html = 'hellohello'; - ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '不转换font标签'); - editor.setContent('hello'); - //html = 'hello'; - html = 'hello'; - ua.checkHTMLSameStyle(html, editor.document, editor.body.firstChild, '不转换font标签'); - -}); - -test('font标签不发生转换', function () { - var editor = te.obj[0]; - editor.setContent('x'); -// if(ua.browser.chrome){ -// var html = 'x'; -// equal(editor.body.firstChild.innerHTML.toLowerCase(),html,'font不转换标签'); -// } -// else{ -// var html = 'x'; -// equal(editor.body.firstChild.innerHTML.toLowerCase(),html,'font不转换标签'); -// } - var html1 = '

    x

    '; - ua.checkSameHtml(editor.getContent(editor.body),html1,'确认一下确实是正确的'); - editor.setContent('x'); - html = 'x'; - //equal(editor.body.firstChild.innerHTML.toLowerCase(),html,'font不转换标签');//ff和chrome下都是正确的,ie下报错,但是错误的提示中,可以看到期待的和实际得到的也是一样的 不知道为何报错 - ua.checkSameHtml(editor.body.firstChild.innerHTML.toLowerCase(),html,'font不转换标签'); -}); - - -test('background--不同字号', function () { - if (!ua.browser.opera) { - var editor = te.obj[2]; - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - te.obj[2].render(div); - stop(); - editor.ready(function () { - var range = new UM.dom.Range(te.obj[2].document,te.obj[2].body); - te.obj[2].setContent('你好'); - editor.focus(); - //var body = editor.document.body; - var body = editor.body; - ua.manualDeleteFillData(editor.body); - range.selectNode(body.firstChild.firstChild).select(); - editor.execCommand('backcolor', 'rgb(255,0,0)'); - range.setStart(body.firstChild.firstChild, 1).collapse(1).select(); - editor.execCommand('fontsize', '30px'); - range = editor.selection.getRange(); - range.insertNode(editor.document.createTextNode('hello')); - setTimeout(function () { - //ua.manualDeleteFillData(editor.body); - //去掉空白字符 - //var color = ua.browser.ie && ua.browser.ie < 9 ? 'background-color: #ff0000;' : 'background-color: rgb(255, 0, 0); '; - //var html = '你好hello'; - if(ua.browser.ie) - var html = '你好hello'; - else - var html = '你好hello'; - ua.checkSameHtml(editor.body.firstChild.innerHTML,html,'检查不同字号的文本背景色是否一致'); - div.parentNode.removeChild(div); - start(); - }, 50); - }); - } -}); - diff --git a/_test/plugins/formula.js b/_test/plugins/formula.js deleted file mode 100644 index 11c34ebe..00000000 --- a/_test/plugins/formula.js +++ /dev/null @@ -1,41 +0,0 @@ -module("plugins.formula"); -/** - * 插入公式 - * 更新公式 - */ -test( '插入公式', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '


    ' ); - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - - editor.execCommand( 'formula', '\\frac{x}{y}' ); - - var $iframe = $('iframe', editor.body); - equal($iframe.length, 1, '正常插入公式'); - equal($iframe.hasClass('mathquill-embedded-latex'), true, '公式classname正常'); - equal($iframe.attr('data-latex'), "\\frac{x}{y}", '公式latex值设置正确'); - equal(editor.getContent(), '

    \\frac{x}{y}

    ', '正常设置内容'); -} ); - -test( '更新公式', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '


    ' ); - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - - editor.execCommand( 'formula', '\\frac{x}{y}' ); - var $iframe = $('iframe', editor.body); - $iframe.addClass('edui-formula-active'); - - setTimeout(function(){ - editor.execCommand( 'formula', '\\frac{z1}{z2}' ); - equal($iframe.attr('data-latex'), "\\frac{x}{y}\\frac{z1}{z2}", '公式latex值更新正确'); - equal($( editor.getContent() ).find('.mathquill-embedded-latex').text(), '\\frac{x}{y}\\frac{z1}{z2}', '正常获取公式latex内容'); - - start(); - }, 200); - stop(); -} ); diff --git a/_test/plugins/horizontal.js b/_test/plugins/horizontal.js deleted file mode 100644 index 82aab4f0..00000000 --- a/_test/plugins/horizontal.js +++ /dev/null @@ -1,39 +0,0 @@ -module( "plugins.horizontal" ); - -//normal -test( 'trace 3587 3614:horizontal', function() { - if(ua.browser.ie)return;//todo ie下有问题 - var editor = te.obj[0]; - var d = editor.document; - var range = te.obj[1]; - var db = editor.body; - - editor.setContent( '

    hello

    top

    bottom

    ' ); - setTimeout(function(){ - range.setStart( d.getElementsByTagName( 'i' )[0].firstChild, 0 ).setEnd( db.lastChild.firstChild, 5 ).select(); - editor.execCommand( 'horizontal' ); - //

    hello


    m - if(ua.browser.gecko) - equal( ua.getChildHTML( db ), '

    hello


    m', "horizontal" ); - else - equal( ua.getChildHTML( db ), '

    hello


    m

    ', "horizontal" ); - start(); - },50); - stop(); -} ); - -test( 'horizontal&&collapsed', function() {//ie8下待确定 - if(ua.browser.ie)return;//todo ie下有问题 - var editor = te.obj[0]; - var range = te.obj[1]; - var db = editor.body; - editor.setContent( 'top

    bottom

    ' ); - range.setStart( db.lastChild.firstChild, 0 ).collapse( true ).select(); - editor.execCommand( 'horizontal' ); - ua.manualDeleteFillData(db); - var spase = ua.browser.chrome?'

    ':''; - if(ua.browser.ie) - equal( ua.getChildHTML( db ), '

    top

    '+spase+'


    bottom

    ', "边界不在table里" ); - else - equal( ua.getChildHTML( db ), '

    top

    '+spase+'

    bottom

    ', "边界不在table里" ); -} ); diff --git a/_test/plugins/image.js b/_test/plugins/image.js deleted file mode 100644 index f94c4b1d..00000000 --- a/_test/plugins/image.js +++ /dev/null @@ -1,208 +0,0 @@ -module( 'plugins.image' ); -/** - * 插入视频 - * 插入图像 - * 选区闭合和不闭合 - * 表格中插入图像 - */ -test( '插入新图像', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '


    ' ); - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:52} ); - ua.manualDeleteFillData( editor.body ); - var img = body.getElementsByTagName( 'img' )[0]; - equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); - equal( img.getAttribute( 'width' ), '50', '比较width' ); - equal( img.getAttribute( 'height' ), '52', '比较height' ); -} ); - -test( '不设宽高,插入图片', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '


    ' ); - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif'} ); - ua.manualDeleteFillData( editor.body ); - var img = body.getElementsByTagName( 'img' )[0]; - equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); -} ); - -//test( '插入对齐方式为居中对齐的图像,新建一个p,在p上设置居中对齐', function () {//三个浏览器都不可以 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// var body = editor.body; -// editor.setContent( '

    hello

    ' ); -// range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); -// editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:51, floatStyle:'center'} ); -// ua.manualDeleteFillData( editor.body ); -// -// var img = body.getElementsByTagName( 'img' )[0]; -// equal( body.childNodes.length, 2, '2个p' ); -// var p = body.firstChild; -// equal( p.style['textAlign'], 'center', '居中对齐' ); -// ok( p.nextSibling.innerHTML.indexOf( 'hello' ) > -1, '第二个p里面是hello' ); //1.2版本在FF中,hello前有不可见字符 -// if ( UM.browser.ie ) -// equal( img.style['styleFloat'], '', 'float为空' ); -// else -// equal( img.style['cssFloat'], '', 'float为空' ); -// equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); -// equal( img.getAttribute( 'width' ), '50', '比较width' ); -// equal( img.getAttribute( 'height' ), '51', '比较height' ); -//} ); - - -test( 'trace:3600 修改已有图片的属性', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello

    ' ); - setTimeout(function(){ - //range.selectNode( body.firstChild.firstChild).select();//ie8下,无法单独选中图片节点, - range.setStart(body.firstChild.firstChild,0).setEnd(body.firstChild.childNodes[1],2).select(); - editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0018.gif'} ); - equal( ua.getChildHTML( body.firstChild ), 'llo', '检查插入的图像地址' ); - equal( body.firstChild.childNodes.length, 3, '2个img孩子' ); - start(); - },50); - stop(); -} ); - -//test( 'trace3574 替换图片', function () { //这个用例的问题 应该是像是没有给用例足够的时间执行一样 所以得到的是undefined,当我一步一步调试的时候,chrome下是通过的 -// if(ua.browser.ie>8)return;//todo trace3574 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// var body = editor.body; -// editor.setContent( '


    ' ); -// //range.setStart( body.firstChild, 0 ).collapse( 1 ).select();//当有这句话的时候 在ie8下会被卡住 -// editor.execCommand( 'insertimage', {src:'../data/test.JPG'} ); -// ua.manualDeleteFillData( editor.body ); -// range.selectNode( body.firstChild.firstChild ).select(); -// editor.execCommand( 'insertimage', {src:'../data/test.JPG', width:50, height:80} ); -// var img = body.getElementsByTagName( 'img' )[0]; -// equal(img.getAttribute('width'),'50','比较width'); -// equal(img.getAttribute('height'),'80','比较width'); -// ok(/data\/test\.JPG/.test( img.getAttribute( 'src' )), '比较src' ); -//} ); - - -test( '选区不闭合插入图像', function () { - - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello1

    hello2

    ' ); - setTimeout(function(){ - range.setStart( body.firstChild.firstChild, 2 ).setEnd( body.lastChild, 2 ).select(); - editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0016.gif', width:'100', height:'100'} ); - ua.manualDeleteFillData( editor.body ); - equal( body.childNodes.length, 1, '只有一个p' ); - ua.clearWhiteNode(body.firstChild); - var img = body.getElementsByTagName('img')[0]; - equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0016.gif', '比较src' ); - equal( img.getAttribute( 'width' ), '100', '比较width' ); - equal( img.getAttribute( 'height' ), '100', '比较height' ); - start(); - },50); - stop(); -} ); - -test( '一次插入多张图片', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '


    ' ); - setTimeout(function(){ - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'insertimage', [{src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:52}, - {src:'http://img.baidu.com/hi/jx2/j_0002.gif', width:51, height:52}, - {src:'http://img.baidu.com/hi/jx2/j_0003.gif', width:52, height:53} ] ); - ua.manualDeleteFillData( editor.body ); - var img = body.getElementsByTagName( 'img' )[0]; - equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0001.gif', '比较src' ); - equal( img.getAttribute( 'width' ), '50', '比较width' ); - equal( img.getAttribute( 'height' ), '52', '比较height' ); - img = body.getElementsByTagName( 'img' )[1]; - equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0002.gif', '比较src' ); - equal( img.getAttribute( 'width' ), '51', '比较width' ); - equal( img.getAttribute( 'height' ), '52', '比较height' ); - img = body.getElementsByTagName( 'img' )[2]; - equal( img.getAttribute( 'src' ), 'http://img.baidu.com/hi/jx2/j_0003.gif', '比较src' ); - equal( img.getAttribute( 'width' ), '52', '比较width' ); - equal( img.getAttribute( 'height' ), '53', '比较height' ); - start(); - },50); - stop(); -} ); - - -//test( '图像设置左右浮动', function () {//mini中已经取消了execCommand('imagefloat')函数入口 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// var body = editor.body; -// editor.setContent( '

    hello1

    hello2

    ' ); -// range.selectNode( body.lastChild.lastChild ).select(); -// editor.execCommand( 'imagefloat', 'left' ); -// equal( body.getElementsByTagName( 'img' )[0].style['cssFloat'] || body.getElementsByTagName( 'img' )[0].style['styleFloat'], 'left', '左浮动' ); -// equal( body.getElementsByTagName( 'img' )[0].style['floatStyle'], 'left', '左浮动2' ); -// equal( editor.queryCommandValue( 'imagefloat' ), 'left' ); -// -// editor.execCommand( 'imagefloat', 'right' ); -// equal( body.getElementsByTagName( 'img' )[0].style['cssFloat'] || body.getElementsByTagName( 'img' )[0].style['styleFloat'], 'right', '右浮动' ); -// equal( editor.queryCommandValue( 'imagefloat' ), 'right' ); -// equal( editor.queryCommandState( 'imagefloat' ), 0, '图片被选中,因此图片菜单高亮' ); -// range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); -// equal( editor.queryCommandState( 'imagefloat' ), -1, '光标闭合,因此图片菜单高不高亮' ); -// equal( editor.queryCommandValue( 'justify' ), 'left', '段落的对齐方式为左对齐' ); -// equal( editor.queryCommandValue( 'imagefloat' ), 'none', '图片对齐方式在闭合情况获取为空' ) -// range.selectNode( body.firstChild.firstChild ).select(); -// equal( editor.queryCommandValue( 'imagefloat' ), 'none', '选中文本,因此图片菜单高不高亮' ); -//} ); - -//test( '左浮动变为默认的样式和居中', function () {//三个都有问题 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// var body = editor.body; -// editor.setContent( '

    hello1

    hello2

    ' ); -// range.selectNode( body.lastChild.lastChild ).select(); -// editor.execCommand( 'imagefloat', 'none' ); -// equal( ua.getFloatStyle( body.getElementsByTagName( 'img' )[0] ), '', '没有浮动方式' ); -// equal( editor.queryCommandValue( 'imagefloat' ), 'none' ); -// $( body.getElementsByTagName( 'img' )[0] ).css( 'float' ); -// range.selectNode( body.getElementsByTagName( 'img' )[0] ).select(); -// editor.execCommand( 'imagefloat', 'center' ); -// equal( editor.queryCommandValue( 'imagefloat' ), 'center' ); -// equal( body.childNodes.length, 3, '3个p,image被切出一个p出来了' ); -// var p = body.childNodes[2]; -// equal( p.tagName.toLowerCase(), 'p', '第2个是p' ); -// equal( p.firstChild.tagName.toLowerCase(), 'img', 'p的孩子为image' ); -// equal( ua.getFloatStyle( p.firstChild ), '', 'image对齐方式float为空' ); -// equal( editor.queryCommandValue( 'justify' ), 'center', '段落的对齐方式为居中' ); -//} ); - -//test( ' 默认样式切换到居中再切换回默认,会把居中导致的3个p合并', function () {//三个都有问题 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// var body = editor.body; -// editor.setContent( '

    hello2hello3

    ' ); -// setTimeout( function () { -// range.selectNode( body.getElementsByTagName( 'a' )[0] ).select(); -// editor.execCommand( 'imagefloat', 'center' ); -// var p = body.childNodes[1]; -// equal( p.firstChild.tagName.toLowerCase(), 'a', 'p的孩子为a' ); -// equal( ua.getFloatStyle( p.firstChild ), '', 'image对齐方式float为空' ); -// equal( editor.queryCommandValue( 'justify' ), 'center', '段落的对齐方式为居中' ); -// editor.execCommand( 'imagefloat', 'none' ); -// equal( body.childNodes.length, 1, '3个p合并为1个' ); -// -// var a = body.firstChild.firstChild.nextSibling; -// equal( a.tagName.toLowerCase(), 'a', 'p的孩子为a' ); -// equal( a.firstChild.tagName.toLowerCase(), 'img', 'a的孩子是img' ); -// equal( ua.getFloatStyle( a.firstChild ), '', 'image对齐方式float为空' ); -// start(); -// }, 50 ); -// stop(); -//} ); \ No newline at end of file diff --git a/_test/plugins/inserthtml.js b/_test/plugins/inserthtml.js deleted file mode 100644 index 19f59325..00000000 --- a/_test/plugins/inserthtml.js +++ /dev/null @@ -1,35 +0,0 @@ -module( "plugins.inserthtml" ); - -test( '闭合方式插入文本', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '


    ' ); - range.setStart( body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'inserthtml', 'hello2' ); - equal( ua.getChildHTML( body ), '

    hello2

    ', '插入文本节点' ); -} ); - -//刘表中插入img -test( '列表中插入img', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent('
    '); - var lis = editor.body.getElementsByTagName('li'); - range.setStart( lis[0], 0 ).collapse(true).select(); - editor.execCommand( 'insertimage', {src:'http://img.baidu.com/hi/jx2/j_0001.gif', width:50, height:51} ); - stop(); - setTimeout(function(){ - equal(lis.length,1,'列表长度没有变化'); - ua.manualDeleteFillData(lis[0]); - if(ua.browser.ie&&ua.browser.ie<11){ - equal(lis[0].firstChild.firstChild.tagName.toLowerCase(),'img','列表中插入img'); - equal(lis[0].firstChild.firstChild.attributes['src'].nodeValue,'http://img.baidu.com/hi/jx2/j_0001.gif','列表中插入img'); - } - else{ - equal(lis[0].firstChild.tagName.toLowerCase(),'img','列表中插入img'); - equal(lis[0].firstChild.attributes['src'].nodeValue,'http://img.baidu.com/hi/jx2/j_0001.gif','列表中插入img'); - } - start(); - },50); -}); \ No newline at end of file diff --git a/_test/plugins/justify.js b/_test/plugins/justify.js deleted file mode 100644 index 2a1db08d..00000000 --- a/_test/plugins/justify.js +++ /dev/null @@ -1,80 +0,0 @@ -module( "plugins.justify" ); - -test( '闭合在段落中设置对齐方式', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.focus(); - editor.setContent( '

    hello1

    ' ); - if(ua.browser.gecko){ - range.setStart(editor.body.firstChild.firstChild,0).collapse(true).select(); - } - editor.execCommand( 'justifycenter' ); - setTimeout(function(){ - range.setStart( body.firstChild.firstChild.firstChild, 3 ).collapse( true ).select(); - if(ua.browser.webkit) - equal( body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); - else - equal(editor.body.firstChild.align,'center','p对齐方式为居中对齐'); - start(); - },50); - stop(); -} ); - -test( '不闭合在段落中设置对齐方式', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello1

    hello2hello3

    ' ); - setTimeout(function(){ - range.selectNode( body.firstChild.firstChild.firstChild ).select(); - editor.execCommand( 'justifycenter' ); - if(ua.browser.chrome) - equal( body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); - else - equal(body.firstChild.align,'center','p对齐方式为居中对齐'); - - range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 1 ).select(); - editor.execCommand( 'justifyright' ); - if(ua.browser.chrome){ - equal( body.firstChild.style['textAlign'], 'right', 'p对齐方式为右对齐' ); - equal( body.lastChild.style['textAlign'], 'right', 'p对齐方式为右对齐' ); - } - else{ - equal( body.firstChild.align, 'right', 'p对齐方式为右对齐' ); - equal( body.lastChild.align, 'right', 'p对齐方式为右对齐' ); - } - range.setStart( body.firstChild.firstChild.firstChild, 3 ).collapse( true ).select(); - editor.execCommand( 'justifycenter' ); - if(ua.browser.chrome) - equal( body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); - else - equal(body.firstChild.align,'center', 'p对齐方式为居中对齐' ); - start(); - },50); - stop(); -} ); - -test( '连续2次设置对齐方式', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '

    tell

    ' ); - setTimeout(function(){ - range.setStart( editor.body.firstChild.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'justifyright' ); - //equal( editor.queryCommandValue( 'justifyright' ), 'right', 'querycommand value' ); - if(ua.browser.chrome) - equal( editor.body.firstChild.style['textAlign'], 'right', 'p对齐方式为右对齐' ); - else - equal( editor.body.firstChild.align, 'right', 'p对齐方式为右对齐' ); - range.setStart( editor.body.firstChild.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'justifycenter' ); - //equal( editor.queryCommandValue( 'justify' ), 'center', 'querycommand value' ); - if(ua.browser.chrome) - equal( editor.body.firstChild.style['textAlign'], 'center', 'p对齐方式为居中对齐' ); - else - equal(editor.body.firstChild.align,'center', 'p对齐方式为居中对齐' ); - start(); - },50); - stop(); -} ); diff --git a/_test/plugins/keystrokes.js b/_test/plugins/keystrokes.js deleted file mode 100644 index af351c3d..00000000 --- a/_test/plugins/keystrokes.js +++ /dev/null @@ -1,293 +0,0 @@ -/** - * Created by JetBrains PhpStorm. - * User: dongyancen - * Date: 12-10-9 - * Time: 下午6:52 - * To change this template use File | Settings | File Templates. - */ -module( "plugins.keystrokes" ); - -//test('跨节点输入tab键',function(){//删掉的 -// //todo ie9,10改range bug trace -// var editor = te.obj[0]; -// editor.setContent( '

    hello

    heoll

    ' ); -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStart( editor.body.lastChild.firstChild,0 ).setEnd(editor.body.lastChild.firstChild.nextSibling,1).select(); -// ua.keydown(editor.body,{'keyCode':9}); -// ua.keyup(editor.body,{'keyCode':9}); -// setTimeout(function(){ -// equal(te.obj[0].undoManger.list.length,2,''); -// var html = '

    hello

        heoll

    '; -// equal(ua.getChildHTML(te.obj[0].body),html,'跨节点输入tab键'); -// start(); -// },20); -// },20); -// stop(); -//}); - -test('trace 3613 删除br标签',function(){ - var editor = te.obj[0]; - editor.setContent('


    hello1

    '); - var range = te.obj[1]; - setTimeout(function(){ - range.setStart( editor.body.firstChild,2 ).collapse(true).select(); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - equal(ua.getChildHTML(te.obj[0].body),'

    hello1

    ','删除br标签'); - start(); - },20); - stop(); -}); - - -test('删除块元素,块元素在后',function(){ - var editor = te.obj[0]; - editor.setContent( '

    hello

    ' ); - var range = te.obj[1]; - setTimeout(function(){ - range.setStart( editor.body.lastChild.lastChild,0 ).setEnd(editor.body.lastChild.lastChild,1).select(); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - setTimeout(function(){ - equal(te.obj[0].undoManger.index,1,''); - var html = '

    hello

    '; - if(!ua.browser.opera) - equal(ua.getChildHTML(te.obj[0].body),html,'删除块元素'); - start(); - },20); - },20); - stop(); -}); - -test('删除块元素,块元素在前',function(){ - var editor = te.obj[0]; - editor.setContent( '

    hello

    ' ); - var range = te.obj[1]; - setTimeout(function(){ - range.setStart( editor.body.firstChild,0 ).setEnd(editor.body.firstChild,1).select(); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - setTimeout(function(){ - equal(te.obj[0].undoManger.index,1,''); - var html = '

    hello

    '; - equal(ua.getChildHTML(te.obj[0].body),html,'删除块元素'); - start(); - },20); - },20); - stop(); -}); - -//test('普通情况,选中一个节点,输入tab键',function(){//删掉的 -// var editor = te.obj[0]; -// editor.setContent( '

    hello

    heoll

    ' ); -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStart( editor.body.lastChild,1 ).setEnd(editor.body.lastChild,2).select(); -// ua.keydown(editor.body,{'keyCode':9}); -// ua.keyup(editor.body,{'keyCode':9}); -// setTimeout(function(){ -// equal(te.obj[0].undoManger.list.length,1,''); -// var html = '

    hello

    he    oll

    '; -// equal(ua.getChildHTML(te.obj[0].body),html,'普通情况,选中一个节点,输入tab键'); -// start(); -// },20); -// },20); -// stop(); -//}); - -test('删除自闭合标签',function(){ - var editor = te.obj[0]; - editor.setContent( '

    hello

    heoll

    ' ); - var range = te.obj[1]; - setTimeout(function(){ - range.setStart( editor.body.lastChild,1 ).setEnd(editor.body.lastChild,2).select(); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - setTimeout(function(){ - equal(te.obj[0].undoManger.index,1,''); - var html = '

    hello

    heoll

    '; - equal(ua.getChildHTML(te.obj[0].body),html,'删除自闭合标签'); - start(); - },20); - },20); - stop(); -}); - -test('全选后,退格,剩下空p',function(){ - var editor = te.obj[0]; - editor.setContent( 'hello' ); - var range = te.obj[1]; - range.selectNode( editor.body.firstChild ).select(); - editor.execCommand( 'bold' ); - editor.execCommand('selectall'); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - stop(); - setTimeout(function(){ - var br = ua.browser.ie?'':'
    '; - equal(ua.getChildHTML(te.obj[0].body),'

    '+br+'

    ','全选后,退格,剩下空p'); - start(); - },20); -}); -//TODO 1.2.6 -//test('针对ff下在列表首行退格,不能删除空格行的问题 ',function(){ -// if(ua.browser.gecko){ -// var editor = te.obj[0]; -// editor.body.innerHTML = '

    欢迎使用umeditor!


    '; -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStartAtFirst(editor.body.firstChild).collapse(true); -// ua.keyup(te.obj[0].body,{'keyCode':8}); -// setTimeout(function(){ -// equal(ua.getChildHTML(editor.body),'

    欢迎使用umeditor!

    ','删除空行 '); -// start(); -// },20); -// },20); -// stop(); -// } -//}); - -//test('在列表中,跨行选中第2,3行,输入tab键',function(){//删掉的 -// var editor = te.obj[0]; -// editor.setContent( '
    1. 欢迎使用

    2. umeditor

    3. umeditor

    ' ); -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStart( editor.body.childNodes[0].childNodes[1].firstChild.firstChild,1 ).setEnd(editor.body.childNodes[0].childNodes[2].firstChild.firstChild,1 ).select(); -// ua.keydown(editor.body,{'keyCode':9}); -// ua.keyup(editor.body,{'keyCode':9}); -// setTimeout(function(){ -// ua.manualDeleteFillData(te.obj[0].body); -// equal(te.obj[0].body.firstChild.tagName.toLowerCase(),'ol','原列表'); -// equal($(te.obj[0].body.firstChild).css('list-style-type'),'decimal','原列表类型'); -// equal(ua.getChildHTML(te.obj[0].body.firstChild.firstChild),'

    欢迎使用

    ','第一行保持原来的列表样式'); -// equal(te.obj[0].body.firstChild.lastChild.tagName.toLowerCase(),'ol','后两行变成第二层列表'); -// equal($(te.obj[0].body.firstChild.lastChild).css('list-style-type'),'lower-alpha','第二层列表类型'); -// equal(ua.getChildHTML(te.obj[0].body.firstChild.lastChild),'
  • umeditor

  • umeditor

  • ','检查内容'); -// start(); -// },20); -// },50); -// stop(); -//}); - -//todo 这个检查存在问题,如何检查 evt.preventDefault();? -test('在h1内输入del',function(){ - var editor = te.obj[0]; - editor.setContent( '


    hello

    ' ); - var range = te.obj[1]; - setTimeout(function(){ - range.setStart(editor.body.childNodes[0],0).collapse(true).select(true); - ua.keydown(te.obj[0].body,{'keyCode':46}); - ua.keyup(te.obj[0].body,{'keyCode':46}); - setTimeout(function(){ - equal(ua.getChildHTML(te.obj[0].body),'


    hello

    ','在h1内输入del'); - start(); - },20); - },20); - stop(); -}); - -//test('在列表中,跨行选中,输入tab键',function(){//删掉的 -// var editor = te.obj[0]; -// editor.setContent( '
    1. 欢迎使用

    2. umeditor

    3. umeditor

    ' ); -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStart( editor.body.firstChild.firstChild.firstChild.firstChild,1 ).setEnd(editor.body.firstChild.childNodes[1].firstChild.firstChild,1 ).select(); -// ua.keydown(editor.body,{'keyCode':9}); -// ua.keyup(editor.body,{'keyCode':9}); -// setTimeout(function(){ -// equal(te.obj[0].undoManger.index,1,'undoManger.index'); -// ua.manualDeleteFillData(te.obj[0].body); -// equal(te.obj[0].body.firstChild.tagName.toLowerCase(),'ol','外面套了一层ol'); -// equal(te.obj[0].body.firstChild.childNodes.length,2,''); -// equal(te.obj[0].body.firstChild.firstChild.tagName.toLowerCase(),'ol','原列表'); -// equal($(te.obj[0].body.firstChild).css('list-style-type'),'decimal','原列表类型'); -// equal(ua.getChildHTML(te.obj[0].body.firstChild.firstChild),'
  • 欢迎使用

  • umeditor

  • ','检查内容'); -// start(); -// },20); -// },50); -// stop(); -//}); - -//test(' 光标定位到列表前,输入tab键',function(){//删掉的 -// var editor = te.obj[0]; -// editor.setContent( '
    1. 欢迎使用

    2. umeditor

    ' ); -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStart( editor.body.firstChild.firstChild.firstChild,0 ).collapse(true).select(); -// ua.keydown(editor.body,{'keyCode':9}); -// ua.keyup(editor.body,{'keyCode':9}); -// setTimeout(function(){ -// equal(te.obj[0].undoManger.list.length,1,'undoManger.index'); -// ua.manualDeleteFillData(te.obj[0].body); -// equal($(te.obj[0].body.firstChild).css('list-style-type'),'decimal','原列表类型'); -// equal(te.obj[0].body.firstChild.childNodes.length,2,'列表有两个子节点'); -// equal($(te.obj[0].body.firstChild.firstChild).css('list-style-type'),'lower-alpha','第一个节点是另一类型的列表'); -// equal(ua.getChildHTML(te.obj[0].body.firstChild.firstChild),'
  • 欢迎使用

  • ','检查内容'); -// equal(te.obj[0].body.firstChild.lastChild.tagName.toLowerCase(),'li','第一个节点是原列表的li'); -// equal(ua.getChildHTML(te.obj[0].body.firstChild.lastChild),'

    umeditor

    ','检查内容'); -// start(); -// },20); -// },50); -// stop(); -//}); - -test( '删除inline的标签', function() { - var editor = te.obj[0]; - editor.setContent( '

    hello worldwasai

    ' ); - var range = te.obj[1]; - setTimeout(function(){ - var strong = editor.body.firstChild.firstChild; - range.selectNode( strong ).select(); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - setTimeout(function(){ - ua.manualDeleteFillData( editor.body ); - equal( editor.body.firstChild.tagName.toLowerCase(), 'p', 'strong 以及子inline节点都被删除' ); - if ( !ua.browser.ie ) - equal( editor.body.lastChild.innerHTML, '
    ', '内容被删除了' ); - else - equal( editor.body.lastChild.innerHTML, '', '内容被删除了' ); - start(); - },20); - },20); - stop(); -} ); - -/*trace 1089*/ -test( '跨行选择2个块元素', function() { - var editor = te.obj[0]; - editor.setContent( '

    hello worldwasai

    hello 2
    ' ); - var range = te.obj[1]; - setTimeout(function(){ - var body = editor.body; - range.setStart( body.firstChild, 0 ).setEnd( body.lastChild,1 ).select(); - ua.keydown(editor.body,{'keyCode':8}); - ua.keyup(editor.body,{'keyCode':8}); - setTimeout(function(){ - ua.manualDeleteFillData( editor.body ); - range = editor.selection.getRange(); - equal( body.childNodes.length, 1, 'div被删除,保留p' ); - var br = ua.browser.ie?"":"
    "; - equal( ua.getChildHTML( body ), '

    '+br+'

    ' ); - start(); - },20); - },20); - stop(); -} ); - -//test('删除空节点 ',function(){ -// var editor = te.obj[0]; -// editor.setContent('


    ') ; -// var range = te.obj[1]; -// setTimeout(function(){ -// range.setStartAtFirst(editor.body.getElementsByTagName('span')[0]).collapse(true).select(true); -// ua.keyup(te.obj[0].body,{'keyCode':8}); -// setTimeout(function(){ -// var br = ua.browser.ie?'':'
    '; -// equal(ua.getChildHTML(editor.body),'

    '+br+'

    ','删除空节点'); -// start(); -// },20); -// },20); -// stop(); -//}); \ No newline at end of file diff --git a/_test/plugins/link.js b/_test/plugins/link.js deleted file mode 100644 index 251ffce2..00000000 --- a/_test/plugins/link.js +++ /dev/null @@ -1,90 +0,0 @@ -module( "plugins.link" ); - -/*trace 879*/ -test( '同时去多个超链接', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '

    hellofirstsecond

    thirdsina

    baidu
    ' ); - stop(); - setTimeout(function () { - range.selectNodeContents( editor.body ).select(); - editor.execCommand( 'unlink' ); - equal( editor.body.firstChild.innerHTML, 'hellofirstsecond', '第一段去掉超链接' ); - equal( editor.body.firstChild.nextSibling.innerHTML, 'thirdsina', '第二段去掉超链接' ); - start(); - }, 100); -} ); - -test( '光标闭合且没有超链接', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '

    hello

    ' ); - range.setStart( editor.body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( 'unlink' ); - equal( ua.getChildHTML( editor.body ), '

    hello

    ', '没有超链接什么都不做' ); -} ); - - -//test( '给图片添加超链接', function () {//ie8下无法选中 单个图像节点 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// editor.setContent( '

    hello

    ' ); -// range.selectNode( editor.body.firstChild.firstChild ).select(); -// editor.execCommand( 'link', {href:'http://www.baidu.com/'} ); -// //var html = 'hello'; -// var html1 = 'hello'; -// if(ua.browser.ie) -// ua.checkHTMLSameStyle( html1, editor.document, editor.body.firstChild, '给图片添加超链接' ); -// else -// equal(editor.body.firstChild.innerHTML.toLowerCase(),html1,'给图片添加超链接'); -//} ); - -test( '去除链接--选中区域包含超链接和非超链接', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello

    hello2famfouhello3

    ' ); - range.setStart( body.firstChild, 0 ).setEnd( body.lastChild, 3 ).select(); - editor.execCommand('unlink'); - var html = '

    hello

    hello2famfouhello3

    '; - equal(editor.getContent(editor.body),html,'去掉选中区域中的超链接'); -} ); - - -test( '插入超链接', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '

    hello

    ' ); - range.setStart( editor.body.firstChild, 1 ).collapse( 1 ).select(); - editor.execCommand( 'link', {href:'www.baidu.com'} ); - var a = editor.body.getElementsByTagName( 'a' )[0]; - range.selectNode( a ).select(); - range = editor.selection.getRange(); - same( editor.queryCommandValue( 'link' ), a, 'link value is a' ); - equal( ua.getChildHTML( editor.body ), '

    hellowww.baidu.com

    ' ); - equal( editor.queryCommandState( 'unlink' ), 0, 'link state is 0' ); -} ); - -test( '对现有的超链接修改超链接地址', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    http://www.baidu.comhellogoogle

    ' ); - var a1 = body.firstChild.firstChild; - range.selectNode( a1 ).select(); - - editor.execCommand( 'link', {href:'ueditor.baidu.com'} ); - a1 = body.firstChild.firstChild; - equal( a1.getAttribute( 'href' ), 'ueditor.baidu.com', 'check href' ); - //equal( a1.innerHTML, 'umeditor.baidu.com', 'innerHTML也相应变化' ); //ff下的超链接和取消都不好用 显示演示的是会改变 ie和chrome的是不会改变(有问题,要确认一下) - - var a2 = body.firstChild.getElementsByTagName( 'a' )[1]; - range.selectNode( a2 ).select(); - editor.execCommand( 'link', {href:'mp3.baidu.com'} ); - a2 = body.firstChild.getElementsByTagName( 'a' )[1]; - - equal( a2.getAttribute( 'href' ), 'mp3.baidu.com', 'check href for second a link' ); - equal( a2.innerHTML, 'google', 'innerHTML不变' ); -} ); - - diff --git a/_test/plugins/list.js b/_test/plugins/list.js deleted file mode 100644 index 208439f9..00000000 --- a/_test/plugins/list.js +++ /dev/null @@ -1,561 +0,0 @@ -module("plugins.list"); -/* - *
  • 有序列表切换到无序 - *
  • 无序列表切换到有序 - *
  • 有序之间相互切换 - *
  • 无序之间相互切换 - *
  • 先引用后列表 - *
  • 表格中插入列表 - *
  • h1套列表 - *
  • 去除链接 - * - * */ - - -test('列表复制粘贴', function () { - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - editor.setContent('
    1. a
    2. b
    • a
    • b
    '); - ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); - ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); - /*ctrl+c*/ - - setTimeout(function () { - var html = {html:editor.body.innerHTML}; - editor.fireEvent('beforepaste', html); - /*粘贴*/ -// range.setStart(editor.body,1).collapse(true).select(); -// editor.fireEvent("paste"); -// ua.manualDeleteFillData(editor.body); -// equal(editor.body.innerHTML,'


    ','编辑器清空'); - editor.setContent('
    1. a
    2. b
    • a
    • b
    '); - ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); - ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); - /*ctrl+c*/ - html = {html:editor.body.innerHTML}; - editor.fireEvent('beforepaste', html); - /*粘贴*/ - editor.setContent('
      1. a
      2. b
      • a
      • b
    '); - ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); - ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); - /*ctrl+c*/ - html = {html:editor.body.innerHTML}; - editor.fireEvent('beforepaste', html); - /*粘贴*/ - editor.setContent('
      1. a
      2. b
      • a
      • b
    '); - ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); - ua.keydown(editor.body, {'keyCode':67, 'ctrlKey':true}); - /*ctrl+c*/ - html = {html:editor.body.innerHTML}; - setTimeout(function () { - editor.fireEvent('beforepaste', html); - /*粘贴*/ - te.dom.push(editor.container); - start() - }, 50); - }, 50); - - }); - stop(); -}); - - -test('修改列表再删除列表', function () { - if ((ua.browser.safari && !ua.browser.chrome))return 0; - var editor = te.obj[0]; - var range = te.obj[1]; - var br = UM.browser.chrome ? "
    " : ""; - editor.setContent('
      hello1
    '); -// range.setStart(editor.body.firstChild, 0).collapse(true).select();//如果是闭合选区的话 只有ie8是正确的 chrome和ff都是有些问题的 - range.selectNode(editor.body.firstChild).select(); - editor.execCommand('insertunorderedlist'); - ua.manualDeleteFillData(editor.body); - equal(editor.body.firstChild.tagName.toLowerCase(), 'ul', '查询列表的类型'); - equal(editor.getContent(editor.body),'
    • hello1
    '); - range.setStart(editor.body.lastChild, 0).setEnd(editor.body.lastChild, 1).select(); - editor.execCommand('insertunorderedlist'); - ua.manualDeleteFillData(editor.body); - if(ua.browser.ie) - equal(editor.getContent(editor.body),'

    hello1

    ','没有列表格式'); - else - equal(editor.getContent(editor.body),'hello1'+ br,'没有列表格式'); - -}); - -//test('列表内没有列表标号的项后退', function () {//ie8下无法运行 -// if (ua.browser.safari)return; -// var div = document.body.appendChild(document.createElement('div')); -// div.id = 'ue'; -// var editor = UM.getEditor('ue'); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// var lis; -// var br = ua.browser.ie ? '
    ' : '
    '; -// editor.setContent('
    1. hello

      www.baidu.com

    '); -// range.setStart(editor.body.firstChild.firstChild.lastChild.lastChild, 0).collapse(true).select(); -// ua.manualDeleteFillData(editor.body); -// ua.keydown(editor.body, {keyCode:8}); -// -// setTimeout(function () { -// lis = editor.body.getElementsByTagName('li'); -// equal(lis.length, '1', '列表长度不变'); -// ua.checkSameHtml(ua.getChildHTML(editor.body), '
    1. hello

    www.baidu.com

    ', 'p在列表外'); -// te.dom.push(editor.container); -// start() -// }, 200); -// }); -// stop(); -//}); - -test('多个p,选中其中几个变为列表', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('

    hello1

    hello2

    hello3

    hello4

    '); - setTimeout(function () { - range.setStart(body.firstChild, 0).setEnd(body.firstChild.nextSibling, 1).select(); - editor.execCommand('insertorderedlist'); - - //var space = ua.browser.webkit?'
    ':''; - if(ua.browser.webkit) - equal(editor.getContent(editor.body.firstChild), '
    1. hello1

    2. hello2

    hello3

    hello4

    ', '检查列表的内容'); - else - equal(editor.getContent(editor.body.firstChild), '
    1. hello1
    2. hello2

    hello3

    hello4

    ', '检查列表的内容'); - equal(body.firstChild.tagName.toLowerCase(), 'ol', '检查列表的类型'); - equal(body.childNodes.length, 3, '3个孩子'); - equal(body.lastChild.tagName.toLowerCase(), 'p', '后面的p没有变为列表'); - equal(body.lastChild.innerHTML.toLowerCase(), 'hello4', 'p里的文本'); - start(); - }, 50); - stop(); -}); - - - -test('去除无序列表', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('

    '); - range.setStart(body.firstChild, 0).collapse(1).select(); - editor.execCommand('insertunorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ul', 'insert an unordered list'); - equal(body.childNodes.length, 1, 'body只有一个孩子'); - ok(editor.queryCommandState('insertunorderedlist'), 'state是1'); - /*去除列表*/ - editor.execCommand('insertunorderedlist'); - ua.manualDeleteFillData(editor.body); - //equal(body.firstChild.tagName.toLowerCase(), 'p', '去除列表');//这句话ff运行不通过 因为此时ff下认为body没有孩子了 所以报错 - equal(body.childNodes.length, ua.browser.gecko?0:1, 'body只有一个孩子'); - ok(!editor.queryCommandState('insertunorderedlist'), 'state是0'); -}); - -test('闭合方式有序和无序列表之间的切换', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('

    '); - range.setStart(body.firstChild, 0).collapse(1).select(); - editor.execCommand('insertunorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ul', 'insert an unordered list'); - equal(body.childNodes.length, 1, 'body只有一个孩子'); - equal(editor.queryCommandValue('insertorderedlist'), null, '有序列表查询结果为null'); - /*切换为有序列表*/ - editor.execCommand('insertorderedlist'); - ua.manualDeleteFillData(editor.body); - equal(body.firstChild.tagName.toLowerCase(), 'ol', '变为有序列表'); - equal(body.childNodes.length, 1, 'body只有一个孩子'); - equal(editor.queryCommandValue('insertunorderedlist'), null, '无序列表查询结果为null'); -}); - -test('非闭合方式切换有序和无序列表', function () {//原本是有序列表,非闭合方式进行切换,chrome下就是对的了,外层没有

    了 - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - /*如果只选中hello然后切换有序无序的话,不同浏览器下表现不一样*/ - editor.setContent('
    1. hello
    2. hello3

    hello2

    '); - range.selectNode(body.firstChild).select(); - editor.execCommand('insertunorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ul', '有序列表变为无序列表'); - equal(ua.getChildHTML(body.firstChild), '
  • hello
  • hello3
  • ', 'innerHTML 不变'); - /*切换为有序列表*/ - editor.execCommand('insertorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ol', '无序列表变为有序列表'); - equal(ua.getChildHTML(body.firstChild), '
  • hello
  • hello3
  • ', '变为有序列表后innerHTML 不变'); -}); - -test('trace:3591:将列表下的文本合并到列表中', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - var br = UM.browser.chrome ? "
    " : ""; - editor.setContent('
    • hello1

    是的

    '); - setTimeout(function () { - range.setStart(body.firstChild, 0).setEnd(body.lastChild, 1).select(); - /*将无序的变为有序,文本也相应变成无序列表的一部分*/ - editor.execCommand('insertorderedlist'); - ua.manualDeleteFillData(editor.body); - equal(body.firstChild.tagName.toLowerCase(), 'ol', 'ul变为了ol'); - equal(ua.getChildHTML(body.firstChild), '
  • hello1
  • 是的'+br+'
  • '); - equal(body.childNodes.length, 1, '只有一个孩子是ol'); - start(); - }, 50); - stop(); -}); - -test('多个列表', function () { - if(ua.browser.gecko)return;//trace 3591 不修 - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('
    1. hello1
    • hello2
    '); - range.selectNode(body.lastChild).select(); - /*将无序的变为有序*/ - editor.execCommand('insertorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ol', '仍然是ol'); - equal(body.childNodes.length, 1, 'body只有1个孩子ol'); - equal(body.firstChild.childNodes.length, 2, '下面的列表合并到上面'); - equal(ua.getChildHTML(body.lastChild), '
  • hello1
  • hello2
  • ', '2个li子节点'); -}); - -test('修改列表中间某一段列表为另一种列表', function () {//ie下'childNodes.1.tagName' 为空或不是对象 - if(!ua.browser.ie){ - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - var br = UM.browser.chrome ? "
    " : ""; - editor.setContent('
    1. hello
    2. hello2
    3. hello3
    4. hello4
    '); - //var lis = body.firstChild.getElementsByTagName('li'); - // range.setStart(lis[1], 0).setEnd(lis[2], 1).select(); - range.setStart(body.firstChild.firstChild.nextSibling,0).setEnd(body.firstChild.firstChild.nextSibling.nextSibling,1).select(); - editor.execCommand('insertunorderedlist'); - equal(body.childNodes.length, 3, '3个列表'); - equal(ua.getChildHTML(body.firstChild), '
  • hello
  • ', '第一个列表只有一个li'); - equal(ua.getChildHTML(body.lastChild), '
  • hello4
  • ', '最后一个列表只有一个li'); - equal(body.childNodes[1].tagName.toLowerCase(), 'ul', '第二个孩子是无序列表'); - equal(ua.getChildHTML(body.childNodes[1]), '
  • hello2'+br+'
  • hello3'+br+'
  • ', '检查第二个列表的内容'); - } -}); - -//ff和ie下是bug -test('trace:3567:两个有序列表,一个无序列表,将无序列表与第二个有序列表合并', function () { - if(ua.browser.ie||ua.browser.gecko)return;//won't fix - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('
    1. hello3
    1. hello1
    • hello2
    '); - range.selectNode(body.lastChild).select(); - /*将无序的变为有序,有序上面的有序不会合并在一起了*/ - editor.execCommand('insertorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ol', '仍然是ol'); - equal(body.childNodes.length, 2, 'body有两个孩子ol'); - equal(body.lastChild.childNodes.length, 2, '无序列表合并到第二个有序列表中了'); -}); - -test('列表下的文本合并到列表中', function () { - if(ua.browser.gecko)return;//trace 3591 不修 - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - var br = UM.browser.chrome ? "
    " : ""; - editor.setContent('
    1. hello3
    2. hello1

    文本1

    文本2

    '); - range.setStart(body, 1).setEnd(body, 3).select(); - /*选中文本变为有序列表,和上面的列表合并了*/ - editor.execCommand('insertorderedlist'); - var ol = body.firstChild; - equal(body.childNodes.length, 1, '所有合并为一个列表'); - equal(ol.tagName.toLowerCase(), 'ol', '仍然是ol'); - equal(ol.childNodes.length, 4, '普通文本与上面的有序列表合并为一个了'); - equal(ua.getChildHTML(body.firstChild), '
  • hello3
  • hello1
  • 文本1'+br+'
  • 文本2'+br+'
  • ', '4个li子节点'); -}); - -test('trace 3586 :2个相同类型的列表合并', function () { - if(ua.browser.ie||ua.browser.gecko)return;//won't fix - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('
    1. hello3
    2. hello1
    1. 文本1

    2. 文本2

    '); - range.setStart(body.firstChild,0).setEnd(body.lastChild,2).select(); - editor.execCommand('insertorderedlist'); - if(ua.browser.ie){ - var ol = body.firstChild; - equal(body.childNodes.length, 1, '所有合并为一个列表'); - equal(ol.tagName.toLowerCase(), 'ol', '仍然是ol'); - equal(ol.childNodes.length, 4, '下面和上面的列表合并到上面去了'); - equal(ua.getChildHTML(body.firstChild), '
  • hello3
  • hello1
  • 文本1
  • 文本2
  • ', '4个li子节点'); - } - else{ - equal(ua.getChildHTML(body),'hello3
    hello1
    文本1
    文本2
    ','列表形式被取消'); - } -}); -// -/*test('列表内后退', function () { - *//*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*//* - if ((ua.browser.safari && !ua.browser.chrome)) - return 0; - var div = document.body.appendChild(document.createElement('div')); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document); - var lis; - var br = ua.browser.ie ? '
    ' : '
    '; -//////标签空格的处理 - editor.setContent('

    1. hello2


    2. hello3
    3. hello4

    4. hello5

    '); -// editor.setContent('

    1. hello2

    2. hello3
    3. hello4

    4. hello5

    '); - range.setStart(editor.body.firstChild.lastChild.firstChild.firstChild, 0).collapse(1).select(); - ua.manualDeleteFillData(editor.body); - ua.keydown(editor.body, {keyCode:8}); - - var ol = editor.body.getElementsByTagName('ol'); - lis = editor.body.getElementsByTagName('li'); - equal(lis.length, '5', '变成5个列表项'); - equal(ua.getChildHTML(editor.body.firstChild), '
  • ' + br + '

  • hello2

  • ' + br + '

  • hello3
  • hello4

    hello5

  • ', '最后一个列表项'); - range.setStart(lis[0].firstChild, 0).collapse(1).select(); - ua.keydown(editor.body, {keyCode:8}); - - lis = editor.body.getElementsByTagName('li'); - equal(lis.length, '4', '变成4个列表项'); - equal(ua.getChildHTML(editor.body.lastChild), '
  • hello2

  • ' + br + '

  • hello3
  • hello4

    hello5

  • ', '第一个列表项且为空行'); - range.setStart(lis[1].firstChild, 0).collapse(1).select(); - ua.keydown(editor.body, {keyCode:8}); - - lis = editor.body.getElementsByTagName('li'); - equal(lis.length, '3', '变成3个列表项'); - equal(ua.getChildHTML(editor.body.lastChild), '
  • hello2

    ' + br + '

  • hello3
  • hello4

    hello5

  • ', '中间列表项且为空行'); - if (!ua.browser.ie) { - range.setStart(lis[1].firstChild.firstChild, 0).collapse(1).select(); - ua.manualDeleteFillData(editor.body); - ua.keydown(editor.body, {keyCode:8}); -//TODO 1.2.6不严重bug注释 空style未删除 -// equal(ua.getChildHTML(editor.body),'


    1. hello2


      hello3
    2. hello4

      hello5

    ','自定义标签后退'); - } - te.dom.push(editor.container); - start() - }); - stop(); -});*/ - -//test('列表内回车', function () {//ie8下 用例不通过 ff和chrome下各种问题,比较乱 待定 -// var div = document.body.appendChild(document.createElement('div')); -// div.id = 'ue'; -// var editor = UM.getEditor('ue'); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// var lis; -// var br = ua.browser.ie ? ' ' : '
    '; -// editor.setContent('
    '); -// lis = editor.body.getElementsByTagName('li'); -// range.setStart(lis[0], 0).collapse(1).select(); -// ua.keydown(editor.body, {keyCode:13}); -// var spa = ua.browser.opera ? '
    ' : ''; -// equal(ua.getChildHTML(editor.body), '

    ' + br + '

    ', '空列表项回车--无列表'); -// -// editor.setContent('
    1. hello1

      hello2

    ');//mini中应该是没有回车 增加列表项的功能 -// lis = editor.body.getElementsByTagName('li'); -// range.setStart(lis[0].lastChild, 0).collapse(1).select(); -// ua.keydown(editor.body, {keyCode:13}); -// //equal(ua.getChildHTML(editor.body.firstChild), '
  • hello1

  • hello2

  • ', '单个列表项内回车'); -// equal(ua.getChildHTML(editor.body),'
    1. hello1

      hello2

    '); -// //标签空格的处理 -// editor.setContent('

    1. hello5



    '); -// lis = editor.body.getElementsByTagName('li'); -// range.setStart(lis[2].firstChild.firstChild, 0).setEnd(lis[2].lastChild.firstChild, 0).select(); -// ua.keydown(editor.body, {keyCode:13}); -// //trace 2652 -// range.setStart(editor.body.firstChild.firstChild.firstChild, 0).collapse(1).select(); -// ua.keydown(editor.body, {keyCode:13}); -// // trace 2653 -// editor.setContent('
    1. hello2

    2. hello3


    3. hello5

    '); -// lis = editor.body.getElementsByTagName('li'); -// range.setStart(lis[0].firstChild.firstChild, 2).setEnd(lis[1].firstChild.firstChild, 4).select(); -// ua.keydown(editor.body, {keyCode:13}); -// equal(ua.getChildHTML(editor.body.firstChild), '
  • he

  • o3


  • hello5

  • ', '非闭合回车'); -// -// editor.setContent('
    1. hello

      hello4

    2. hello5

    '); -// lis = editor.body.getElementsByTagName('li'); -// range.setStart(lis[0].lastChild.firstChild, 1).setEnd(lis[0].lastChild.firstChild, 2).select(); -// ua.keydown(editor.body, {keyCode:13}); -// equal(ua.getChildHTML(editor.body.firstChild), '
  • hello

    h

  • llo4

  • hello5

  • ', '一个列表项内两行'); -// te.dom.push(editor.container); -// start() -// }); -// stop(); -//}); - -//test('回车后产生新的li-选区闭合', function () { -// var div = document.body.appendChild(document.createElement('div')); -// div.id = 'ue'; -// var editor = UM.getEditor('ue'); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// var body = editor.body; -// editor.setContent('

    hello1

    hello2

    '); -// setTimeout(function () { -// range.setStart(body.firstChild, 0).setEnd(body.firstChild.nextSibling, 1).select(); -// editor.execCommand('insertorderedlist'); -// var lastLi = body.firstChild.lastChild.firstChild.firstChild; -// //var lastLi = body.firstChild.lastChild.firstChild; -// range.setStart(lastLi, lastLi.length).collapse(1).select(); -// setTimeout(function () { -// ua.keydown(editor.body, {'keyCode':13}); -// equal(body.firstChild.childNodes.length, 3, '回车后产生新的li'); -// equal(body.firstChild.lastChild.tagName.toLowerCase(), 'li', '回车后产生新的li'); -// var br = ua.browser.ie ? '' : '
    '; -// equal(ua.getChildHTML(body.firstChild), '
  • hello1

  • hello2

  • ' + br + '

  • ', '检查内容'); -// var lastLi = body.firstChild.lastChild.firstChild.firstChild; -// range.setStart(lastLi, lastLi.length).collapse(1).select(); -// setTimeout(function () { -// ua.keydown(editor.body, {'keyCode':13}); -// equal(body.firstChild.childNodes.length, 2, '空li后回车,删除此行li'); -// equal(body.lastChild.tagName.toLowerCase(), 'p', '产生p'); -// br = ua.browser.ie ? '' : '
    '; -// ua.manualDeleteFillData(body.lastChild); -// equal(body.lastChild.innerHTML.toLowerCase().replace(/\r\n/ig, ''), br, '检查内容'); -// te.dom.push(editor.container); -// start() -// }, 20); -// }, 20); -// }, 50); -// }); -// stop(); -//}); - -//test('trace 3117:列表内后退两次', function () { -// // 实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现 -// if ((ua.browser.safari && !ua.browser.chrome))return 0; -// var div = document.body.appendChild(document.createElement('div')); -// div.id = 'ue'; -// var editor = UM.getEditor('ue'); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// var br = ua.browser.ie ? '
    ' : '
    '; -// editor.setContent('
    1. hello

    '); -// -// range.setStart(editor.body.firstChild.lastChild.firstChild, 0).collapse(1).select(); -// ua.manualDeleteFillData(editor.body); -// ua.keydown(editor.body, {keyCode:8}); -// var ol = editor.body.getElementsByTagName('ol'); -// var lis = editor.body.getElementsByTagName('li'); -// equal(lis.length, '1', '变成1个列表项'); -// equal(ua.getChildHTML(editor.body.firstChild), '
  • hello

    ' + br + '

  • ', '检查列表内容'); -////TODO 1.2.6不严重bug注释 空style未删除 -//// range.setStart(lis[0].lastChild,0).collapse(1).select(); -//// ua.keydown(editor.body,{keyCode:8}); -//// equal(ua.getChildHTML(editor.body),'
    1. hello

    '+br+'

    ','检查body内容'); -// //模拟不到光标跳到上一行? -//// range.setStart(editor.body.lastChild,0).collapse(1).select(); -//// ua.keydown(editor.body,{keyCode:8}); -//// equal(ua.getChildHTML(editor.body),'
    1. hello

    ','检查body内容'); -// te.dom.push(editor.container); -// start() -// }); -// stop(); -//}); - -/*trace 3136*/ -//test('trace 3118:全选后backspace', function () {//跟单行backspace 是一样的问题 -// /*实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现*/ -// if ((ua.browser.safari && !ua.browser.chrome))return 0; -// var div = document.body.appendChild(document.createElement('div')); -// div.id = 'ue'; -// var editor = UM.getEditor('ue'); -// editor.ready(function () { -// -// var br = ua.browser.ie ? '' : '
    '; -// editor.setContent('
    1. hello

    '); -// ua.keydown(editor.body, {'keyCode':65, 'ctrlKey':true}); -// ua.keydown(editor.body, {'keyCode':8}); -// equal(ua.getChildHTML(editor.body), '

    ' + br + '

    ', ''); -// ok(!editor.queryCommandState('insertorderedlist'), 'state是0'); -// te.dom.push(editor.container); -// start() -// }); -// stop(); -//}); - -//test('trace 3132:单行列表backspace', function () { -// //实际操作没问题,取range时会在将文本节点分为两个节点,后退操作无法实现 -// if ((ua.browser.safari && !ua.browser.chrome))return 0; -// if (ua.browser.ie == 9)return 0;//TODO 1.2.6 -// var div = document.body.appendChild(document.createElement('div')); -// div.id = 'ue'; -// var editor = UM.getEditor('ue'); -// editor.ready(function () { -// var range = new UM.dom.Range(editor.document); -// editor.setContent('

    '); -// range.selectNode(editor.body.firstChild.firstChild.firstChild.firstChild).select(); -// ua.keydown(editor.body, {keyCode:8}); -// equal(ua.getChildHTML(editor.body), '


    ', ''); -// te.dom.push(editor.container); -// start() -// }); -// stop(); -//}); - - -//test('trace 3118:全选后backspace',function(){ //写的用例,为什么看不到TT 想确定一下为什么的 -// if ((ua.browser.safari && !ua.browser.chrome))return 0; -// var editor = te.obj[0]; -// var range = te.obj[1]; -// // var body = editor.body; -// var br = ua.browser.chrome ? '
    ' : ''; -// editor.setContent('
    1. hello

    '); -// range.selectNode(editor.body.firstChild).select(); -// setTimeout(function(){ -// ua.keydown(editor.body,{'keyCode':65,'ctrlKey':true}); -// ua.keydown(editor.body,{keycode:8}); -// equal(ua.getChildHTML(editor.body),'

    ' + br + '

    ','全部清空'); -// ok(!editor.queryCommandState('insertorderedlist'), 'state是0'); -// start(); -// },200) -// stop(); -//}); - - - - -test('添加列表,取消列表', function () { - var editor = te.obj[0]; - var body = editor.body; - var br = ua.browser.ie ? '' : '
    '; - editor.setContent('

    hello1

    hello2

    hello3

    hello4

    '); - editor.execCommand('selectAll'); - editor.execCommand('insertunorderedlist'); - - equal(body.firstChild.tagName.toLowerCase(),'ul','检查无序列表'); - ok(editor.queryCommandState('insertunorderedlist'), 'state是1'); - editor.execCommand('selectAll'); - editor.execCommand('insertunorderedlist'); - if(ua.browser.ie) - ua.checkHTMLSameStyle('

    hello1

    hello2

    hello3

    hello4

    ', editor.document, editor.body, '取消列表'); - else{ - if(ua.browser.gecko) - equal(ua.getChildHTML(editor.body),'hello1
    hello2
    hello3
    hello4','取消列表'); - else - equal(ua.getChildHTML(editor.body),'hello1
    hello2
    hello3
    hello4
    ','取消列表'); - } - equal(editor.queryCommandValue('insertunorderedlist'), null, '查询取消无序列表的结果'); - ok(!editor.queryCommandState('insertunorderedlist'), 'state是0'); -}); - -test('去掉列表外边的p', function () { - var editor = te.obj[0]; - var body = editor.body; - //var range = te.obj[1]; - var br = ua.browser.ie ? '' : '
    '; - editor.setContent('

    hello1

    hello2

    hello3

    hello4

    '); - editor.execCommand('selectAll'); - //range.selectNode(body.lastChild).select(); - editor.execCommand('insertunorderedlist'); - var count = 0; - editor.$body.find('ol,ul').each(function(i,n){ - var p = n.parentNode; - if(p!==editor.body){ - count++ - } - }) - equal(count,0) -}); \ No newline at end of file diff --git a/_test/plugins/map.js b/_test/plugins/map.js deleted file mode 100644 index d70a3da1..00000000 --- a/_test/plugins/map.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Created by dongyancen on 14-1-20. - */ -/*test('', function () { - stop(); - UM.clearCache('testDefault'); - $('.edui-body-container')[0].parentNode.removeChild($('.edui-body-container')[0]); - var div = document.body.appendChild(document.createElement('div')); - div.id = 'map'; - var editor = UM.getEditor('map'); - setTimeout(function () { - var i = editor.$container.find($(".edui-btn-map")); -// i.trigger('click'); - editor.$container.find($('.edui-map-dynamic')).eq(1).attr("checked","checked"); - var dialog = editor.$container.find($('.edui-dialog-map')) -// edui-dialog-map -// dialog.find($('.edui-btn-primary')).eq(1).attr("checked","checked"); - dialog.find($('.edui-btn-primary')).trigger('click'); - //edui-btn-primary - }, 200) - -});*/ - - -test('trace:3878:地图dialog显示',function(){ - var editor = te.obj[0]; - var body = editor.body; - var range = te.obj[1]; - editor.setContent("

    123

    "); - var text = body.firstChild.firstChild; - range.setStart(text,'0').collapse(true).select(); - var div = document.body.appendChild(document.createElement('div')); - div.id = 'xe'; - var editor2 = UM.getEditor('xe'); - editor2.ready(function(){ - var range2 = new UM.dom.Range(editor2.document,editor2.body); - var body2 = editor2.body; - editor2.setContent( '

    123

    ' ); - range2.selectNode( body2.firstChild ).select(); - setTimeout(function () { - var i = editor2.$container.find($(".edui-btn-map")); - i.trigger('click'); - var map_body = String($('.edui-map-city')[0].value); - i.trigger('click'); - equal(map_body,'北京','地图dialog正常显示'); - $(div).remove(); - start(); - }, 200); - }); - stop(); -}); \ No newline at end of file diff --git a/_test/plugins/paragraph.js b/_test/plugins/paragraph.js deleted file mode 100644 index f9bf5216..00000000 --- a/_test/plugins/paragraph.js +++ /dev/null @@ -1,65 +0,0 @@ -module( "plugins.paragraph" ); -/** - * h1和p之间的转换 - * 表格中添加p和h1 - * 列表里加h1 - * 传入2个参数,style和attrs - */ - -test( 'trace:3595:不闭合h1和p之间的转换', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('

    hello

    '); - setTimeout(function () { - range.selectNode(body.firstChild.firstChild).select(); - /*p===>h1*/ - var block = ua.browser.ie ? '标题 1' : 'h1'; - editor.execCommand('paragraph', 'h1'); - equal(ua.getChildHTML(body), '

    hello

    '); - equal(editor.queryCommandValue('paragraph'), block, '当前的block元素为h1'); - /*h1===>p*/ - range.selectNode(body.firstChild.firstChild).select(); - editor.execCommand('paragraph', 'p'); - equal(ua.getChildHTML(body), '

    hello

    '); - /*多个段落的部分文本*/ - var block = ua.browser.ie ? '标题 3' : 'h3'; - editor.setContent('

    hello

    hello2

    '); - setTimeout(function () { - range.setStart(body.firstChild.firstChild, 2).setEnd(body.lastChild.firstChild, 1).select(); - editor.execCommand('paragraph', 'h3'); - if (ua.browser.webkit) - equal(ua.getChildHTML(body), '

    hello
    hello2

    '); - else - equal(ua.getChildHTML(body), '

    hello

    hello2

    '); - range.setStart(body.firstChild.firstChild, 2).collapse(true).select(); - equal(editor.queryCommandValue('paragraph'), block, '当前的block元素为h3'); - start(); - }, 50); - }, 50); - stop(); -} ); - -test( '闭合h1和p之间的转换', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello

    hello2

    ' ); - setTimeout(function(){ - range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select(); - /*p===>h1*/ - editor.execCommand( 'paragraph', 'h1' ); - equal( ua.getChildHTML( body ), '

    hello

    hello2

    ' ); - /*h1===>p*/ - var block = ua.browser.ie?'普通':'p'; - range.setStart( body.firstChild.firstChild, 1 ).collapse( 1 ).select(); - editor.execCommand( 'paragraph', 'p' ); - equal( ua.getChildHTML( body ), '

    hello

    hello2

    ' ); - range.setStart(body.lastChild.firstChild,0).collapse(1).select(); - equal( editor.queryCommandValue( 'paragraph' ), block, '当前的block元素为p' ); - start(); - },50); - -stop(); -} ); - diff --git a/_test/plugins/paste.js b/_test/plugins/paste.js deleted file mode 100644 index e40ba0b8..00000000 --- a/_test/plugins/paste.js +++ /dev/null @@ -1,29 +0,0 @@ -module( 'plugins.paste' ); - -//不能模拟出真实的粘贴效果,此用例用于检查中间值 -test( '粘贴', function() { - if(ua.browser.ie || ua.browser.opera)return; - var div = document.body.appendChild( document.createElement( 'div' ) ); - $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); - var me = te.obj[2]; - me.render(div); - stop(); - me.ready(function(){ - var range = new UM.dom.Range( te.obj[2].document ,te.obj[2].body); - me.focus(); - me.setContent('

    hello

    '); - range.setStart(me.body.firstChild,0).collapse(true).select(); - ua.keydown(me.body,{'keyCode':65,'ctrlKey':true}); - ua.keydown(me.body,{'keyCode':67,'ctrlKey':true}); - setTimeout(function(){ - me.focus(); - range.setStart(me.body.firstChild,0).collapse(true).select(); - ua.paste(me.body,{'keyCode':86,'ctrlKey':true}); - equal(me.body.lastChild.id,'baidu_pastebin','检查id'); - equal(me.body.lastChild.style.position,'absolute','检查style'); - div.parentNode.removeChild(div); - start(); - },50); - stop(); - }); -} ); diff --git a/_test/plugins/preview.js b/_test/plugins/preview.js deleted file mode 100644 index 33708052..00000000 --- a/_test/plugins/preview.js +++ /dev/null @@ -1,23 +0,0 @@ -module('plugins.preview'); - -//test('设置内容后后预览',function(){ -// var editor = te.obj[0]; -// var body = editor.body; -// var html = '
    1.  function addSpace(linenum){
    2.          if(linenum<10){
    3.              return "&nbsp;&nbsp;";
    4.          }else if(linenum>=10 && linenum<100){
    5.              return "&nbsp;";
    6.          }else if(linenum>=100 && linenum<1000){
    7.              return "";
    8.          }
    9.      }
    '; -// editor.setContent(html); -// editor.execCommand('preview'); -// ua.checkSameHtml(body.innerHTML,html,'预览不会对页面代码产生影响'); -//}); - - -test('设置内容后后预览',function(){ - if(ua.browser.gecko)return;//ff总不停打开窗口,实际操作没问题 - var editor = te.obj[0]; - var body = editor.body; - var html = '

    你好,我亲爱的朋

    '; - var html_ie10 ="

    你好,我亲爱的朋

    "; - editor.setContent(html); - editor.focus(); - editor.execCommand('preview'); - ua.checkSameHtml(body.innerHTML,(ua.browser.ie>8)?html_ie10:html,'预览不会对页面代码产生影响'); -}); \ No newline at end of file diff --git a/_test/plugins/removeformat.js b/_test/plugins/removeformat.js deleted file mode 100644 index ba25d764..00000000 --- a/_test/plugins/removeformat.js +++ /dev/null @@ -1,83 +0,0 @@ -module( "plugins.removeformat" ); - -/*trace 3570*/ -test( 'trace 3570:对包含超链接的文本清除样式', function () { - if(ua.browser.gecko||ua.browser.ie)return;//todo trace 3570 - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '

    hellobaidu

    ' ); - range.selectNode(editor.body.firstChild).select(); - editor.execCommand( 'removeformat' ); - equal(ua.getChildHTML(editor.body), '

    hellobaidu

    ', '对包含超链接的文本去除样式' ); -} ); - -test( 'trace 3612 清除超链接的颜色', function () { - var editor = te.obj[2]; - var div = document.body.appendChild( document.createElement( 'div' ) ); - $( div ).css( 'width', '500px' ).css( 'height', '500px' ).css( 'border', '1px solid #ccc' ); - editor.render(div); - stop(); - setTimeout(function(){ - var range = new UM.dom.Range( te.obj[2].document,te.obj[2].body ); - editor.setContent('baidu'); - range.selectNode(editor.body.firstChild).select(); - editor.execCommand( 'forecolor', 'rgb(255,0,0)' ); - //var html = 'baidu';//editor里得到的是这个结果,mini不是 - //ua.checkHTMLSameStyle( html, editor.document, editor.body.firstChild, '查看加了颜色后超链接的样式' ); - //

    baidu

    - if(ua.browser.ie||ua.browser.gecko){ - var html = '

    baidu

    '; - equal(editor.getContent(editor.body),html,'查看加了颜色后的超链接样式'); - } - else{ - var html = '

    baidu

    '; - equal(editor.getContent(editor.body),html,'查看加了颜色后的超链接样式'); - } - editor.execCommand( 'removeformat' ); - var cl = ua.browser.ie && ua.browser.ie == 8 ? 'class=\"\"' : ""; - html = '

    baidu

    '; - equal(ua.getChildHTML(editor.body),html,'查看清除样式后超链接的样式'); - div.parentNode.removeChild(div); - start(); - },500); -} ); - -test( 'trace 3605 3624 清除样式的区域有多个inline元素嵌套', function () { - if(ua.browser.ie)return;//todo trace 3624 - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello1

    hello2

    ' ); - var strs = body.getElementsByTagName( 'strong' ); - range.setStart( strs[0].firstChild, 2 ).setEnd( strs[1].firstChild.lastChild, 3 ).select(); - editor.execCommand( 'removeformat' ); - var trace = (ua.browser.ie>9)?'lo2':'lo2';//trace 3624 fix in future - equal( ua.getChildHTML( body ), '

    hello1

    hel'+trace+'

    ' ); -} ); - - - -//test( '指定删除某一个span', function () {//不闭合选择chrome下可以,ff下是清除了所有样式,但是手动操作,ff无反应,ie下是样式完全不改变 -// var editor = te.obj[0]; -// var range = te.obj[1]; -// var body = editor.body; -// editor.setContent( '

    hello2

    ' ); -// range.selectNode(body.firstChild).select(); -// editor.execCommand( 'removeformat'); -// // ua.checkHTMLSameStyle('hello2',editor.document,body.firstChild,'清除span corlor'); -// //equal(editor.getContent(editor.body),'

    hello2

    ','清除'); -// equal(ua.getChildHTML(body),'

    hello2

    '); -//} ); - - - -test( '不闭合方式清除样式', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    hello1

    hello2

    ' ); - //range.setStart( body.firstChild.firstChild, 0 ).collapse( 1 ).select(); - range.selectNode(body.firstChild.firstChild).select(); - editor.execCommand( 'removeformat' ); - equal( ua.getChildHTML( body ), '

    hello1

    hello2

    ' ); -} ); \ No newline at end of file diff --git a/_test/plugins/selectall.js b/_test/plugins/selectall.js deleted file mode 100644 index e1f6a609..00000000 --- a/_test/plugins/selectall.js +++ /dev/null @@ -1,62 +0,0 @@ -module( "plugins.selectall" ); -test( 'selectall', function () { - var editor = te.obj[0], db = editor.body; - editor.setContent( '

    xxxx

    ssss' ); - editor.focus(); - editor.execCommand( 'selectAll' ); - editor.execCommand( "bold" ); - if(ua.browser.gecko) - equal(editor.getContent(db),"

    xxxx

    ssss

    ","after calling selectall command"); - else - equal(editor.getContent(db),"

    xxxx

    ssss

    ","after calling selectall command"); -} ); - -test( 'a part of the content is selected', function () { - var editor = te.obj[0], range = te.obj[1], db = editor.body; - //var d = editor.document; - editor.setContent( '

    xxxx

    ssss' ); - range.selectNode( db.lastChild.firstChild ).select(); - editor.execCommand( "bold" ); - equal( editor.getContent(db), "

    xxxx

    ssss

    ", "before calling selectAll command" ); - editor.execCommand( 'selectAll' ); - editor.execCommand( "bold" ); - if(ua.browser.gecko) - equal( editor.getContent(db), "

    xxxx

    ssss

    ", "after calling selectAll command" ); - else - equal( editor.getContent(db), "

    xxxx

    ssss

    ", "after calling selectAll command" ); -} ); - -test( 'content is null', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '


    ' ); - //TODO 现在必须先focus再selectall,trace1743 - editor.focus(); - range.setStart(editor.body.firstChild,0).collapse(true).select(); - editor.execCommand( 'selectAll' ); - equal( ua.getChildHTML( editor.body ), "


    ", "content is null" ); - //equal(UM.plugins['selectall'].notNeedUndo, 1, "notNeedUndo==1" ); - range.setStart( editor.body.firstChild, 0 ).collapse( 1 ).select(); - editor.execCommand( "bold" ); - ua.manualDeleteFillData( editor.body ); - equal( ua.getChildHTML( editor.body ), "


    ", "after calling command bold" ); -} ); - -test( 'ctrl+a', function() { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent( '

    全选的文本1

    全选的文本2

    ' ); - range.selectNode( body.firstChild ).select(); - var p = body.firstChild; - ua.keydown(editor.body,{'keyCode':65,'ctrlKey':true}); - setTimeout( function() { - var range = editor.selection.getRange(); - if ( ua.browser.gecko ) - ua.checkResult( range, body, body, 0, 2, false, '查看全选后的range' ); - else - ua.checkResult( range, body.firstChild.firstChild, body.lastChild.firstChild, 0, 6, false, '查看全选后的range' ); - start(); - }, 150 ); - stop(); -} ); \ No newline at end of file diff --git a/_test/plugins/source.js b/_test/plugins/source.js deleted file mode 100644 index 3c8816d6..00000000 --- a/_test/plugins/source.js +++ /dev/null @@ -1,271 +0,0 @@ -module('plugins.source'); - - - -//test('', function () { -// stop() -//}); -test('插入表格,切源码再切回来',function(){ - var editor = te.obj[0]; - var div = te.dom[0]; - editor.focus(); - editor.setContent('
    hello1
    hello2
    '); - //source 包含超时操作,ie下必须有同步操作,否则会报错 - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - var content = editor.getContent(); - equal(content, '
    hello1
    hello2
    '); - start(); - }, 20); - }, 20); - stop(); -}); -test('设定range,切源码再切回来',function(){//trace 3647 - var editor = te.obj[0]; - var div = te.dom[0]; - editor.focus(); - editor.setContent('

    这里我可以写一些输入提示

    '); - var range = te.obj[1]; - setTimeout(function () { - range.selectNode(editor.body.firstChild).select(); -// range.setStart(editor.body.firstChild.firstChild,0).setEnd(editor.body.firstChild.firstChild,2).select(); - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - if (ua.browser.gecko) {//todo range 判断 - ua.checkResult(editor.selection.getRange(), editor.body, editor.body, 0, 1, false, '选区不变'); - } else { - ua.checkResult(editor.selection.getRange(), editor.body.firstChild.firstChild, editor.body.firstChild.firstChild, 0, 12, false, '选区不变'); - } - start(); - }, 20); - }, 20); - stop(); -}); -test('chrome删除后切换源码再切换回来,光标没了', function () { - //opera 取不到range值 - if (ua.browser.opera) return 0; - var editor = te.obj[0]; - var div = te.dom[0]; - editor.render(div); - editor.setContent('hello'); - var range = editor.selection.getRange(); - range.selectNode(editor.body.firstChild).select(); - editor.execCommand('cleardoc'); - stop(); - expect(2); - //source 包含超时操作,ie下必须有同步操作,否则会报错 - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - start(); - }, 20); - }, 20); - range = editor.selection.getRange(); - equal(range.startContainer.nodeType, 1, '光标定位在p里'); - equal(range.startContainer.tagName.toLowerCase(), 'p', 'startContainer为p'); - te.dom.push(div); -}); - -test('切换源码,源码中多处空行', function () { - var editor = te.obj[0]; - editor.setContent('

    hellobaidu

    '); - stop(); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - var html = editor.getContent(); - equal(html, '

    hellobaidu

    '); - start(); - }, 100); - }, 100); - }, 100); - - // var html = '

    \nhello\n\tbaidu\n\n

    '; - //无奈的验证,有不可见字符 - //多余不可见字符的的bug已经修改了,现在用例字符串长度:53 - - // ok(html.length>=58&&html.length<=60,'切换源码不会多空行'); -}); -test('设置源码内容没有p标签,切换源码后会自动添加', function () { - var editor = te.obj[0]; - editor.setContent('helloworld你好啊大家好,你在干嘛呢。谢谢,不用谢~~%199

    hello

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - var childs = editor.body.childNodes; - ok(childs.length, 3, '3个p'); - for (var index = 0; index < 3; index++) { - equal(childs[0].tagName.toLowerCase(), 'p', '第' + index + '个孩子为p'); - } - start(); - }, 100); - }, 100); - }, 100); - }, 100); - stop(); -}); - -test('切换源码不会去掉空的span', function () { - var editor = te.obj[0]; - editor.setContent('

    切换源码去掉空的span

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - start(); - }, 100); - }, 100); - stop(); - equal(editor.getContent(), '

    切换源码去掉空的span

    '); -}); - -test('b,i标签,切换源码后自动转换成strong和em', function () { - var editor = te.obj[0]; - editor.setContent('

    加粗的内容斜体的内容加粗且斜体

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - start(); - }, 100); - }, 100); - stop(); - equal(editor.getContent(), '

    加粗的内容斜体的内容加粗且斜体

    '); -}); - -test(' range的更新/特殊符号的转换', function () { - var editor = te.obj[0]; - editor.setContent('

    "<>

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - equal(editor.getContent(), '

    "<>

    '); - editor.setContent("

    '

    "); -// var range = te.obj[1]; -// range.setStart(editor.body.firstChild,0).collapse(1).select(); - setTimeout(function () { -// var label = ua.browser.gecko ? 'html' : 'body'; - var label = 'html'; - ua.manualDeleteFillData(editor.body); - if (ua.browser.ie && ua.browser.ie > 8)//todo ie9,10改range - equal(editor.selection.getRange().startContainer.parentNode.parentNode.tagName.toLowerCase(), label, 'range的更新'); - else - equal(editor.selection.getRange().startContainer.parentNode.parentNode.parentNode.tagName.toLowerCase(), label, 'range的更新'); - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - equal(editor.getContent(), "

    '

    "); - start(); - }, 100); - }, 100); - }, 100); - }, 100); - stop(); -}); - -test('默认插入的占位符', function () { - var editor = te.obj[0]; - editor.setContent(''); - equal(editor.getContent(), ''); -}); - -test('不以http://开头的超链接绝对路径网址', function () { - if (ua.browser.ie == 9)return 0;//TODO - var editor = te.obj[0]; - editor.setContent('

    绝对路径网址

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - equal(editor.getContent(), '

    绝对路径网址

    '); - start(); - }, 100); - }, 100); - stop(); -}); - -test('插入超链接后再插入空格,空格不能被删除', function () { - var editor = te.obj[0]; - editor.setContent('

    绝对路径网址 ddd

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - var html = '

    绝对路径网址  ddd

    '; - ua.manualDeleteFillData(editor.body) - equal(editor.body.innerHTML.toLowerCase(), html, '查看空格是否被删除'); - //equal(editor.body.firstChild.innerHTML.toLowerCase(),'绝对路径网址  ddd','空格仍然存在'); - equal(editor.body.innerHTML.toLowerCase().length, html.length, '查看空格是否被删除'); - start(); - }, 100); - }, 100); - stop(); -}); - -//自动转换标签 -test('在font,b,i标签中输入,会自动转换标签 ', function () { -// if(!ua.browser.gecko){ - var editor = te.obj[0]; - editor.body.innerHTML = '

    x

    '; - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - equal(editor.body.firstChild.firstChild.tagName.toLowerCase(), 'span', 'font转换成span'); - if (ua.browser.gecko || ua.browser.ie) - equal($(editor.body.firstChild.firstChild).css('font-size'), '16px', '检查style'); - else - equal($(editor.body.firstChild.firstChild).css('font-size'), '16px', '检查style'); - var EMstyle = $(editor.body.firstChild.firstChild).css('color'); //dollar符号的使用 - ok(EMstyle == 'rgb(255, 0, 0)' || EMstyle == 'red' || EMstyle == '#ff0000', '检查style'); - equal(ua.getChildHTML(editor.body.firstChild.firstChild), 'x', 'b转成strong,i转成em '); - start(); - }, 20); - }, 20); - stop(); -// } -}); -test('img和a之间不会产生多余空格', function () { - var editor = te.obj[0]; - editor.setContent('

    http://www.baidu.com

    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - ua.manualDeleteFillData(editor.body); -// var html = '

    http://www.baidu.com

    '; -// ua.checkSameHtml(editor.body.innerHTML.toLowerCase(), html, '查看img和a之间是否会产生多余空格'); - ua.checkSameHtml(editor.body.firstChild.innerHTML.toLowerCase(),'http://www.baidu.com','img和a之间不会产生多余空格'); - start(); - }, 20); - }, 20); - }, 20); - stop(); -}); - -test('带颜色的span切到源码再切回,不会丢失span', function () { - var editor = te.obj[0]; - editor.setContent('


    '); - setTimeout(function () { - editor.execCommand('source'); - setTimeout(function () { - editor.execCommand('source'); - ua.checkSameHtml(editor.body.innerHTML, '


    ','span不丢失'); - start(); - }, 20); - }, 20); - stop(); -}); \ No newline at end of file diff --git a/_test/plugins/tools.js b/_test/plugins/tools.js deleted file mode 100644 index d0374ade..00000000 --- a/_test/plugins/tools.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - - */ -(function () { - function mySetup() { - for (var config in window.UMDITOR_CONFIG) { - if (typeof(window.UMDITOR_CONFIG[config]) == 'string') - window.UMDITOR_CONFIG[config] = window.UMDITOR_CONFIG[config].replace('_test/tools/br/', ''); - } - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc'); - var editor = new UM.Editor({'initialContent':'

    欢迎使用umeditor

    ', 'autoFloatEnabled':false,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); - div.id = "testDefault"; - var ue = new UM.Editor({'UEDITOR_HOME_URL':'../../../', 'autoFloatEnabled':true,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); - QUnit.readyFlag =0; - editor.render(div); - stop(); - setTimeout(function(){ - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - te.dom.push(div); - te.obj.push(editor); - te.obj.push(range); - te.obj.push(ue); - QUnit.readyFlag =1; - }); - },50); - document.getElementsByClassName = function (eleClassName) { - var getEleClass = [];//定义一个数组 - var myclass = new RegExp("\\b" + eleClassName + "\\b");//创建一个正则表达式对像 - var elem = this.getElementsByTagName("*");//获取文档里所有的元素 - for (var h = 0; h < elem.length; h++) { - var classes = elem[h].className;//获取class对像 - if (myclass.test(classes)) getEleClass.push(elem[h]);//正则比较,取到想要的CLASS对像 - } - return getEleClass;//返回数组 - } - } - - var _d = function () { - if (te) { - if (te.dom && te.dom.length) { - for (var i = 0; i < te.dom.length; i++) { - if (te.dom[i] && te.dom[i].parentNode) - te.dom[i].parentNode.removeChild(te.dom[i]); - } - - } - } - te.dom = []; - te.obj = []; - } - var s = QUnit.testStart, d = QUnit.testDone; - QUnit.testStart = function () { - s.apply(this, arguments); - mySetup(); - }; - QUnit.testDone = function () { - _d(); - d.apply(this, arguments); - } -})(); \ No newline at end of file diff --git a/_test/plugins/undo.js b/_test/plugins/undo.js deleted file mode 100644 index 21bab09a..00000000 --- a/_test/plugins/undo.js +++ /dev/null @@ -1,176 +0,0 @@ -module("plugins.undo"); -//test('', function () { -// stop() -//}); -test( 'trace 3643 更改部分内容,点击 undo,redo,undo,这时redo按钮高亮', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('

    hello1

    '); - setTimeout(function () { - range.selectNode(editor.body.firstChild).select(); - editor.execCommand('underline'); - equal(editor.queryCommandState('undo'), 0, 'undo按钮高亮'); - equal(editor.queryCommandState('redo'), -1, 'redo按钮高亮'); - editor.execCommand('Undo'); - equal(editor.queryCommandState('undo'), -1, 'undo按钮高亮'); - equal(editor.queryCommandState('redo'), 0, 'redo按钮高亮'); - editor.execCommand('redo'); - equal(editor.queryCommandState('undo'), 0, 'undo按钮高亮'); - equal(editor.queryCommandState('redo'), -1, 'redo按钮高亮'); - editor.execCommand('Undo'); - equal(editor.queryCommandState('undo'), -1, 'undo按钮高亮'); - equal(editor.queryCommandState('redo'), 0, 'redo按钮高亮'); - start(); - }, 50); - stop(); -} ); - -test( 'trace 3645 设置一段文本为有序列表,再设成无序列表,undo', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - var body = editor.body; - editor.setContent('

    hello1

    hello2

    '); - setTimeout(function () { - range.setStart(body.firstChild, 0).setEnd(body.lastChild, 1).select(); - editor.execCommand('insertorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ol', 'insertorderedlist-检查列表的类型'); - equal(body.firstChild.childNodes.length, 2, '2个孩子'); - editor.execCommand('insertunorderedlist'); - equal(body.firstChild.tagName.toLowerCase(), 'ul', 'insertunorderedlist-检查列表的类型'); - equal(body.firstChild.childNodes.length, 2, '2个孩子'); - editor.execCommand('Undo'); - //这个trace 出现问题的时候,undo之后,列表会变成4行 - equal(body.firstChild.tagName.toLowerCase(), 'ol', 'Undo-检查列表的类型'); - equal(body.firstChild.childNodes.length, 2, '2个孩子'); - start(); - }, 50); - stop(); -} ); - -function getDiv(){ - var div = document.body.appendChild(document.createElement('div')); - return div.appendChild(document.createElement('div')); -} - -test('输入文本后撤销按钮不亮', function () { - var div = getDiv(); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    '); - range.setStart(editor.body.firstChild, 0).collapse(true).select(); - ua.keydown(editor.body); - range.insertNode(editor.document.createTextNode('hello')); - ua.keydown(editor.body); - setTimeout(function () { - equal(editor.queryCommandState('undo'), 0, '模拟输入文本后撤销按钮应当高亮'); - UM.delEditor('ue'); - div&&te.dom.push(div); - start(); - }, 500); - }); - stop(); -}); - -test('插入文本、分割线、文本,撤销2次,撤销掉分割线', function () { - var div = getDiv(); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - editor.setContent('

    '); - - //输入文本 - range.setStart(editor.body.firstChild, 0).collapse(true).select(); - ua.keydown(editor.body); - range.insertNode(editor.document.createTextNode('hello')); - if (!ua.browser.ie) - ua.compositionstart(editor.body); - ua.keyup(editor.body); - //输入分割符 - range.setStartAfter(editor.body.lastChild).collapse(true).select(); - editor.execCommand('Horizontal'); - //输入文本 - range.setStartAfter(editor.body.lastChild).collapse(true).select(); - ua.keydown(editor.body); - range.insertNode(editor.document.createTextNode('hello')); - if (!ua.browser.ie) - ua.compositionend(editor.body); - ua.keyup(editor.body); - - editor.execCommand('Undo'); - editor.execCommand('Undo'); - equal(editor.body.getElementsByTagName('hr').length, 0, '分割线已删除'); - setTimeout(function () { - UM.delEditor('ue'); - div&&te.dom.push(div); - start() - }, 500); - }); - stop(); -}); - -test('undo--redo', function () { - //todo 分别插入文本,img,list,link,再undo,redo -}); -test('ctrl+z/y', function () { - var div = getDiv(); - div.id = 'ue'; - var editor = UM.getEditor('ue'); - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - var body = editor.body; - editor.setContent('

    没有加粗的文本

    '); - range.selectNode(body.firstChild).select(); - var p = body.firstChild; - editor.focus(); - setTimeout(function () { - ua.keydown(editor.body, {'keyCode':66, 'ctrlKey':true}); - setTimeout(function () { - if(ua.browser.ie) - equal(ua.getChildHTML(p),'没有加粗的文本'); - else - equal(ua.getChildHTML(p), '没有加粗的文本'); - ua.keydown(editor.body, {'keyCode':90, 'ctrlKey':true}); - setTimeout(function () { - editor.focus(); - equal(ua.getChildHTML(body.firstChild), '没有加粗的文本'); - ua.keydown(editor.body, {'keyCode':89, 'ctrlKey':true}); - editor.focus(); - setTimeout(function () { - equal(ua.getChildHTML(body.firstChild), '没有加粗的文本'); - UM.delEditor('ue'); - div&&te.dom.push(div); - start(); - },500); - }, 100); - }, 150); - }, 100); - }); - stop(); -}); - -test('reset,index', function () { - var editor = te.obj[0]; - var br = (ua.browser.ie&&ua.browser.ie<9)? ' ': ''; - var range = te.obj[1]; - editor.setContent('

    '); - range.setStart(editor.body.firstChild,0).collapse(true).select(); - editor.execCommand('horizontal'); - var listLength = editor.undoManger.list.length; - ok(listLength>0,'检查undoManger.list'); - equal(editor.undoManger.index,1,'检查undoManger.index'); - editor.undoManger.undo(); - equal(editor.undoManger.list.length,listLength,'undo操作,undoManger.list不变'); - equal(editor.undoManger.index,0,'undo操作,undoManger.index-1'); - equal(ua.getChildHTML(editor.body), '

    ', '检查内容'); - editor.reset(); - equal(editor.undoManger.list.length,0,'reset,undoManger.list清空'); - equal(editor.undoManger.index,0,'reset,undoManger.index清空'); - editor.undoManger.redo(); - ua.manualDeleteFillData(editor.body); - equal(ua.getChildHTML(editor.body), '

    '+br+'

    ','检查内容'); - -}); \ No newline at end of file diff --git a/_test/plugins/video.js b/_test/plugins/video.js deleted file mode 100644 index 951b8da0..00000000 --- a/_test/plugins/video.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Administrator - * Date: 13-5-15 - * Time: 下午7:15 - * To change this template use File | Settings | File Templates. - */ -module( 'plugins.video' ); - -test( '视频', function () { - var editor = te.obj[0]; - var range = te.obj[1]; - editor.setContent( '

    hello

    ' ); - range.setStart(editor.body.firstChild,0).collapse(true).select(); - var videoObject ={url: "http://player.youku.com/player.php/Type/Folder/Fid/19275705/Ob/1/sid/XNTU3Mjk4NzQ4/v.swf", width: "500", height: "400", align: "right"}; - editor.execCommand( 'insertvideo',videoObject); - stop(); - setTimeout(function(){ - var img = editor.body.getElementsByTagName('img'); - equal(img.length,1,'插入img'); - equal(img[0].width,"500"); - equal(img[0].height,"400"); - equal(img[0].src,editor.options.UMEDITOR_HOME_URL+'themes/default/images/spacer.gif'); - equal(ua.getFloatStyle(img[0]),'right');//trace 3653 - if(ua.browser.gecko||ua.browser.ie>8){ - ok(img[0].style.background.indexOf('url(\"'+editor.options.UMEDITOR_HOME_URL+'themes/default/images/videologo.gif\")') > -1); - } - else - { - ok(img[0].style.background.indexOf("url("+editor.options.UMEDITOR_HOME_URL+"themes/default/images/videologo.gif)") > -1); - } - start(); - },100); -} ); \ No newline at end of file diff --git a/_test/qunit/jquery-1.5.1.js b/_test/qunit/jquery-1.5.1.js deleted file mode 100644 index fa52d75b..00000000 --- a/_test/qunit/jquery-1.5.1.js +++ /dev/null @@ -1,8316 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Check for digits - rdigit = /\d/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // Has the ready events already been bound? - readyBound = false, - - // The deferred used on DOM ready - readyList, - - // Promise methods - promiseMethods = "then done fail isResolved isRejected promise".split( " " ), - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = "body"; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return (context || rootjQuery).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.5.1", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + (this.selector ? " " : "") + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.done( fn ); - - return this; - }, - - eq: function( i ) { - return i === -1 ? - this.slice( i ) : - this.slice( i, +i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - // A third-party is pushing the ready event forwards - if ( wait === true ) { - jQuery.readyWait--; - } - - // Make sure that the DOM is not already loaded - if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).unbind( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyBound ) { - return; - } - - readyBound = true; - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent("onreadystatechange", DOMContentLoaded); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNaN: function( obj ) { - return obj == null || !rdigit.test( obj ) || isNaN( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw msg; - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test(data.replace(rvalidescape, "@") - .replace(rvalidtokens, "]") - .replace(rvalidbraces, "")) ) { - - // Try to use the native JSON parser first - return window.JSON && window.JSON.parse ? - window.JSON.parse( data ) : - (new Function("return " + data))(); - - } else { - jQuery.error( "Invalid JSON: " + data ); - } - }, - - // Cross-browser xml parsing - // (xml & tmp used internally) - parseXML: function( data , xml , tmp ) { - - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - - tmp = xml.documentElement; - - if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { - jQuery.error( "Invalid XML: " + data ); - } - - return xml; - }, - - noop: function() {}, - - // Evalulates a script in a global context - globalEval: function( data ) { - if ( data && rnotwhite.test(data) ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, - script = document.createElement( "script" ); - - if ( jQuery.support.scriptEval() ) { - script.appendChild( document.createTextNode( data ) ); - } else { - script.text = data; - } - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction(object); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type(array); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var ret = [], value; - - // Go through the array, translating each of the items to their - // new value (or values). - for ( var i = 0, length = elems.length; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - proxy: function( fn, proxy, thisObject ) { - if ( arguments.length === 2 ) { - if ( typeof proxy === "string" ) { - thisObject = fn; - fn = thisObject[ proxy ]; - proxy = undefined; - - } else if ( proxy && !jQuery.isFunction( proxy ) ) { - thisObject = proxy; - proxy = undefined; - } - } - - if ( !proxy && fn ) { - proxy = function() { - return fn.apply( thisObject || this, arguments ); - }; - } - - // Set the guid of unique handler to the same of original handler, so it can be removed - if ( fn ) { - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - } - - // So proxy can be declared as an argument - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can be optionally by executed if its a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return (new Date()).getTime(); - }, - - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - // We have to add a catch block for - // IE prior to 8 or else the finally - // block will never get executed - catch (e) { - throw e; - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - var i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; - } - return obj; - } - } ); - // Make sure only one callback list will be used - deferred.done( failDeferred.cancel ).fail( deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( object ) { - var lastIndex = arguments.length, - deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? - object : - jQuery.Deferred(), - promise = deferred.promise(); - - if ( lastIndex > 1 ) { - var array = slice.call( arguments, 0 ), - count = lastIndex, - iCallback = function( index ) { - return function( value ) { - array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( promise, array ); - } - }; - }; - while( ( lastIndex-- ) ) { - object = array[ lastIndex ]; - if ( object && jQuery.isFunction( object.promise ) ) { - object.promise().then( iCallback(lastIndex), deferred.reject ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( promise, array ); - } - } else if ( deferred !== object ) { - deferred.resolve( object ); - } - return promise; - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySubclass( selector, context ) { - return new jQuerySubclass.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySubclass, this ); - jQuerySubclass.superclass = this; - jQuerySubclass.fn = jQuerySubclass.prototype = this(); - jQuerySubclass.fn.constructor = jQuerySubclass; - jQuerySubclass.subclass = this.subclass; - jQuerySubclass.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { - context = jQuerySubclass(context); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); - }; - jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; - var rootjQuerySubclass = jQuerySubclass(document); - return jQuerySubclass; - }, - - browser: {} -}); - -// Create readyList deferred -readyList = jQuery._Deferred(); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -if ( indexOf ) { - jQuery.inArray = function( elem, array ) { - return indexOf.call( array, elem ); - }; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -// Expose jQuery to the global object -return jQuery; - -})(); - - -(function() { - - jQuery.support = {}; - - var div = document.createElement("div"); - - div.style.display = "none"; - div.innerHTML = "
    a"; - - var all = div.getElementsByTagName("*"), - a = div.getElementsByTagName("a")[0], - select = document.createElement("select"), - opt = select.appendChild( document.createElement("option") ), - input = div.getElementsByTagName("input")[0]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return; - } - - jQuery.support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: div.firstChild.nodeType === 3, - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText insted) - style: /red/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: a.getAttribute("href") === "/a", - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55$/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: input.value === "on", - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Will be defined later - deleteExpando: true, - optDisabled: false, - checkClone: false, - noCloneEvent: true, - noCloneChecked: true, - boxModel: null, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableHiddenOffsets: true - }; - - input.checked = true; - jQuery.support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as diabled) - select.disabled = true; - jQuery.support.optDisabled = !opt.disabled; - - var _scriptEval = null; - jQuery.support.scriptEval = function() { - if ( _scriptEval === null ) { - var root = document.documentElement, - script = document.createElement("script"), - id = "script" + jQuery.now(); - - try { - script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); - } catch(e) {} - - root.insertBefore( script, root.firstChild ); - - // Make sure that the execution of code works by injecting a script - // tag with appendChild/createTextNode - // (IE doesn't support this, fails, and uses .text instead) - if ( window[ id ] ) { - _scriptEval = true; - delete window[ id ]; - } else { - _scriptEval = false; - } - - root.removeChild( script ); - // release memory in IE - root = script = id = null; - } - - return _scriptEval; - }; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - - } catch(e) { - jQuery.support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent("onclick", function click() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - jQuery.support.noCloneEvent = false; - div.detachEvent("onclick", click); - }); - div.cloneNode(true).fireEvent("onclick"); - } - - div = document.createElement("div"); - div.innerHTML = ""; - - var fragment = document.createDocumentFragment(); - fragment.appendChild( div.firstChild ); - - // WebKit doesn't clone checked state correctly in fragments - jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; - - // Figure out if the W3C box model works as expected - // document.body must exist before we can do this - jQuery(function() { - var div = document.createElement("div"), - body = document.getElementsByTagName("body")[0]; - - // Frameset documents with no body should not run this code - if ( !body ) { - return; - } - - div.style.width = div.style.paddingLeft = "1px"; - body.appendChild( div ); - jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; - - if ( "zoom" in div.style ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
    "; - jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; - } - - div.innerHTML = "
    t
    "; - var tds = div.getElementsByTagName("td"); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; - - tds[0].style.display = ""; - tds[1].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE < 8 fail this test) - jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; - div.innerHTML = ""; - - body.removeChild( div ).style.display = "none"; - div = tds = null; - }); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ - var eventSupported = function( eventName ) { - var el = document.createElement("div"); - eventName = "on" + eventName; - - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( !el.attachEvent ) { - return true; - } - - var isSupported = (eventName in el); - if ( !isSupported ) { - el.setAttribute(eventName, "return;"); - isSupported = typeof el[eventName] === "function"; - } - el = null; - - return isSupported; - }; - - jQuery.support.submitBubbles = eventSupported("submit"); - jQuery.support.changeBubbles = eventSupported("change"); - - // release memory in IE - div = all = a = null; -})(); - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the pagebreak - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ jQuery.expando ] = id = ++jQuery.uuid; - } else { - id = jQuery.expando; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); - } else { - cache[ id ] = jQuery.extend(cache[ id ], name); - } - } - - thisCache = cache[ id ]; - - // Internal jQuery data is stored in a separate object inside the object's data - // cache in order to avoid key collisions between internal data and user-defined - // data - if ( pvt ) { - if ( !thisCache[ internalKey ] ) { - thisCache[ internalKey ] = {}; - } - - thisCache = thisCache[ internalKey ]; - } - - if ( data !== undefined ) { - thisCache[ name ] = data; - } - - // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should - // not attempt to inspect the internal events object using jQuery.data, as this - // internal data object is undocumented and subject to change. - if ( name === "events" && !thisCache[name] ) { - return thisCache[ internalKey ] && thisCache[ internalKey ].events; - } - - return getByName ? thisCache[ name ] : thisCache; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; - - if ( thisCache ) { - delete thisCache[ name ]; - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !isEmptyDataObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( pvt ) { - delete cache[ id ][ internalKey ]; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - var internalCache = cache[ id ][ internalKey ]; - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - if ( jQuery.support.deleteExpando || cache != window ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the entire user cache at once because it's faster than - // iterating through each key, but we need to continue to persist internal - // data if it existed - if ( internalCache ) { - cache[ id ] = {}; - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - - cache[ id ][ internalKey ] = internalCache; - - // Otherwise, we need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - } else if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ jQuery.expando ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( jQuery.expando ); - } else { - elem[ jQuery.expando ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 ) { - var attr = this[0].attributes, name; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = name.substr( 5 ); - dataAttr( this[0], name, data[ name ] ); - } - } - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var $this = jQuery( this ), - args = [ parts[0], value ]; - - $this.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - $this.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - data = elem.getAttribute( "data-" + key ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - !jQuery.isNaN( data ) ? parseFloat( data ) : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON -// property to be considered empty objects; this property always exists in -// order to make sure JSON.stringify does not expose internal metadata -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -jQuery.extend({ - queue: function( elem, type, data ) { - if ( !elem ) { - return; - } - - type = (type || "fx") + "queue"; - var q = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( !data ) { - return q || []; - } - - if ( !q || jQuery.isArray(data) ) { - q = jQuery._data( elem, type, jQuery.makeArray(data) ); - - } else { - q.push( data ); - } - - return q; - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(); - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift("inprogress"); - } - - fn.call(elem, function() { - jQuery.dequeue(elem, type); - }); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue", true ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function( i ) { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; - type = type || "fx"; - - return this.queue( type, function() { - var elem = this; - setTimeout(function() { - jQuery.dequeue( elem, type ); - }, time ); - }); - }, - - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspaces = /\s+/, - rreturn = /\r/g, - rspecialurl = /^(?:href|src|style)$/, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rradiocheck = /^(?:radio|checkbox)$/i; - -jQuery.props = { - "for": "htmlFor", - "class": "className", - readonly: "readOnly", - maxlength: "maxLength", - cellspacing: "cellSpacing", - rowspan: "rowSpan", - colspan: "colSpan", - tabindex: "tabIndex", - usemap: "useMap", - frameborder: "frameBorder" -}; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name, fn ) { - return this.each(function(){ - jQuery.attr( this, name, "" ); - if ( this.nodeType === 1 ) { - this.removeAttribute( name ); - } - }); - }, - - addClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.addClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( value && typeof value === "string" ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className ) { - elem.className = value; - - } else { - var className = " " + elem.className + " ", - setClass = elem.className; - - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { - setClass += " " + classNames[c]; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.removeClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - var className = (" " + elem.className + " ").replace(rclass, " "); - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[c] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspaces ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " "; - for ( var i = 0, l = this.length; i < l; i++ ) { - if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - if ( !arguments.length ) { - var elem = this[0]; - - if ( elem ) { - if ( jQuery.nodeName( elem, "option" ) ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - } - - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { - return elem.getAttribute("value") === null ? "on" : elem.value; - } - - // Everything else, we just grab the value - return (elem.value || "").replace(rreturn, ""); - - } - - return undefined; - } - - var isFunction = jQuery.isFunction(value); - - return this.each(function(i) { - var self = jQuery(this), val = value; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call(this, i, self.val()); - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray(val) ) { - val = jQuery.map(val, function (value) { - return value == null ? "" : value + ""; - }); - } - - if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { - this.checked = jQuery.inArray( self.val(), val ) >= 0; - - } else if ( jQuery.nodeName( this, "select" ) ) { - var values = jQuery.makeArray(val); - - jQuery( "option", this ).each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - this.selectedIndex = -1; - } - - } else { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { - return undefined; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery(elem)[name](value); - } - - var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), - // Whether we are setting (or getting) - set = value !== undefined; - - // Try to normalize/fix the name - name = notxml && jQuery.props[ name ] || name; - - // Only do all the following if this is a node (faster for style) - if ( elem.nodeType === 1 ) { - // These attributes require special treatment - var special = rspecialurl.test( name ); - - // Safari mis-reports the default selected property of an option - // Accessing the parent's selectedIndex property fixes it - if ( name === "selected" && !jQuery.support.optSelected ) { - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - - // If applicable, access the attribute via the DOM 0 way - // 'in' checks fail in Blackberry 4.7 #6931 - if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { - if ( set ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } - - if ( value === null ) { - if ( elem.nodeType === 1 ) { - elem.removeAttribute( name ); - } - - } else { - elem[ name ] = value; - } - } - - // browsers index elements by id/name on forms, give priority to attributes. - if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { - return elem.getAttributeNode( name ).nodeValue; - } - - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - if ( name === "tabIndex" ) { - var attributeNode = elem.getAttributeNode( "tabIndex" ); - - return attributeNode && attributeNode.specified ? - attributeNode.value : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - - return elem[ name ]; - } - - if ( !jQuery.support.style && notxml && name === "style" ) { - if ( set ) { - elem.style.cssText = "" + value; - } - - return elem.style.cssText; - } - - if ( set ) { - // convert the value to a string (all browsers do this but IE) see #1070 - elem.setAttribute( name, "" + value ); - } - - // Ensure that missing attributes return undefined - // Blackberry 4.7 returns "" from getAttribute #6938 - if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { - return undefined; - } - - var attr = !jQuery.support.hrefNormalized && notxml && special ? - // Some attributes require a special call on IE - elem.getAttribute( name, 2 ) : - elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return attr === null ? undefined : attr; - } - // Handle everything which isn't a DOM element node - if ( set ) { - elem[ name ] = value; - } - return elem[ name ]; - } -}); - - - - -var rnamespaces = /\.(.*)$/, - rformElems = /^(?:textarea|input|select)$/i, - rperiod = /\./g, - rspace = / /g, - rescape = /[^\w\s.|`]/g, - fcleanup = function( nm ) { - return nm.replace(rescape, "\\$&"); - }; - -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function( elem, types, handler, data ) { - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6) - // Minor release fix for bug #8018 - try { - // For whatever reason, IE has trouble passing the window object - // around, causing it to be cloned in the process - if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { - elem = window; - } - } - catch ( e ) {} - - if ( handler === false ) { - handler = returnFalse; - } else if ( !handler ) { - // Fixes bug #7229. Fix recommended by jdalton - return; - } - - var handleObjIn, handleObj; - - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure - var elemData = jQuery._data( elem ); - - // If no elemData is found then we must be trying to bind to one of the - // banned noData elements - if ( !elemData ) { - return; - } - - var events = elemData.events, - eventHandle = elemData.handle; - - if ( !events ) { - elemData.events = events = {}; - } - - if ( !eventHandle ) { - elemData.handle = eventHandle = function() { - // Handle the second event of a trigger and when - // an event is called after a pagebreak has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? - jQuery.event.handle.apply( eventHandle.elem, arguments ) : - undefined; - }; - } - - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native events in IE. - eventHandle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = types.split(" "); - - var type, i = 0, namespaces; - - while ( (type = types[ i++ ]) ) { - handleObj = handleObjIn ? - jQuery.extend({}, handleObjIn) : - { handler: handler, data: data }; - - // Namespaced event handlers - if ( type.indexOf(".") > -1 ) { - namespaces = type.split("."); - type = namespaces.shift(); - handleObj.namespace = namespaces.slice(0).sort().join("."); - - } else { - namespaces = []; - handleObj.namespace = ""; - } - - handleObj.type = type; - if ( !handleObj.guid ) { - handleObj.guid = handler.guid; - } - - // Get the current list of functions bound to this event - var handlers = events[ type ], - special = jQuery.event.special[ type ] || {}; - - // Init the event handler queue - if ( !handlers ) { - handlers = events[ type ] = []; - - // Check for a special event handler - // Only use addEventListener/attachEvent if the special - // events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add the function to the element's handler list - handlers.push( handleObj ); - - // Keep track of which events have been used, for global triggering - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, pos ) { - // don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } - - var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - events = elemData && elemData.events; - - if ( !elemData || !events ) { - return; - } - - // types is actually an event object here - if ( types && types.type ) { - handler = types.handler; - types = types.type; - } - - // Unbind all events for the element - if ( !types || typeof types === "string" && types.charAt(0) === "." ) { - types = types || ""; - - for ( type in events ) { - jQuery.event.remove( elem, type + types ); - } - - return; - } - - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(" "); - - while ( (type = types[ i++ ]) ) { - origType = type; - handleObj = null; - all = type.indexOf(".") < 0; - namespaces = []; - - if ( !all ) { - // Namespaced event handlers - namespaces = type.split("."); - type = namespaces.shift(); - - namespace = new RegExp("(^|\\.)" + - jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - eventType = events[ type ]; - - if ( !eventType ) { - continue; - } - - if ( !handler ) { - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( all || namespace.test( handleObj.namespace ) ) { - jQuery.event.remove( elem, origType, handleObj.handler, j ); - eventType.splice( j--, 1 ); - } - } - - continue; - } - - special = jQuery.event.special[ type ] || {}; - - for ( j = pos || 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( handler.guid === handleObj.guid ) { - // remove the given handler for the given type - if ( all || namespace.test( handleObj.namespace ) ) { - if ( pos == null ) { - eventType.splice( j--, 1 ); - } - - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - - if ( pos != null ) { - break; - } - } - } - - // remove generic event handler if no more handlers exist - if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - ret = null; - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - var handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - delete elemData.events; - delete elemData.handle; - - if ( jQuery.isEmptyObject( elemData ) ) { - jQuery.removeData( elem, undefined, true ); - } - } - }, - - // bubbling is internal - trigger: function( event, data, elem /*, bubbling */ ) { - // Event object or event type - var type = event.type || event, - bubbling = arguments[3]; - - if ( !bubbling ) { - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - jQuery.extend( jQuery.Event(type), event ) : - // Just the event type (string) - jQuery.Event(type); - - if ( type.indexOf("!") >= 0 ) { - event.type = type = type.slice(0, -1); - event.exclusive = true; - } - - // Handle a global trigger - if ( !elem ) { - // Don't bubble custom events when global (to avoid too much overhead) - event.stopPropagation(); - - // Only trigger if we've ever bound an event for it - if ( jQuery.event.global[ type ] ) { - // XXX This code smells terrible. event.js should not be directly - // inspecting the data cache - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - } - } - - // Handle triggering a single element - - // don't do events on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { - return undefined; - } - - // Clean up in case it is reused - event.result = undefined; - event.target = elem; - - // Clone the incoming data, if any - data = jQuery.makeArray( data ); - data.unshift( event ); - } - - event.currentTarget = elem; - - // Trigger the event, it is assumed that "handle" is a function - var handle = jQuery._data( elem, "handle" ); - - if ( handle ) { - handle.apply( elem, data ); - } - - var parent = elem.parentNode || elem.ownerDocument; - - // Trigger an inline bound script - try { - if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { - if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { - event.result = false; - event.preventDefault(); - } - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (inlineError) {} - - if ( !event.isPropagationStopped() && parent ) { - jQuery.event.trigger( event, data, parent, true ); - - } else if ( !event.isDefaultPrevented() ) { - var old, - target = event.target, - targetType = type.replace( rnamespaces, "" ), - isClick = jQuery.nodeName( target, "a" ) && targetType === "click", - special = jQuery.event.special[ targetType ] || {}; - - if ( (!special._default || special._default.call( elem, event ) === false) && - !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { - - try { - if ( target[ targetType ] ) { - // Make sure that we don't accidentally re-trigger the onFOO events - old = target[ "on" + targetType ]; - - if ( old ) { - target[ "on" + targetType ] = null; - } - - jQuery.event.triggered = true; - target[ targetType ](); - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (triggerError) {} - - if ( old ) { - target[ "on" + targetType ] = old; - } - - jQuery.event.triggered = false; - } - } - }, - - handle: function( event ) { - var all, handlers, namespaces, namespace_re, events, - namespace_sort = [], - args = jQuery.makeArray( arguments ); - - event = args[0] = jQuery.event.fix( event || window.event ); - event.currentTarget = this; - - // Namespaced event handlers - all = event.type.indexOf(".") < 0 && !event.exclusive; - - if ( !all ) { - namespaces = event.type.split("."); - event.type = namespaces.shift(); - namespace_sort = namespaces.slice(0).sort(); - namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.namespace = event.namespace || namespace_sort.join("."); - - events = jQuery._data(this, "events"); - - handlers = (events || {})[ event.type ]; - - if ( events && handlers ) { - // Clone the handlers to prevent manipulation - handlers = handlers.slice(0); - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - - // Filter the functions by class - if ( all || namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - } - - return event.result; - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ) { - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) { - // Fixes #1925 where srcElement might not be defined either - event.target = event.srcElement || document; - } - - // check if target is a textnode (safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) { - event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; - } - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var doc = document.documentElement, - body = document.body; - - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add which for key events - if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { - event.which = event.charCode != null ? event.charCode : event.keyCode; - } - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) { - event.metaKey = event.ctrlKey; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button !== undefined ) { - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - } - - return event; - }, - - // Deprecated, use jQuery.guid instead - guid: 1E8, - - // Deprecated, use jQuery.proxy instead - proxy: jQuery.proxy, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady, - teardown: jQuery.noop - }, - - live: { - add: function( handleObj ) { - jQuery.event.add( this, - liveConvert( handleObj.origType, handleObj.selector ), - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); - }, - - remove: function( handleObj ) { - jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); - } - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src ) { - // Allow instantiation without the 'new' keyword - if ( !this.preventDefault ) { - return new jQuery.Event( src ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.timeStamp = jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function( event ) { - // Check if mouse(over|out) are still within the same parent element - var parent = event.relatedTarget; - - // Firefox sometimes assigns relatedTarget a XUL element - // which we cannot access the parentNode property of - try { - - // Chrome does something similar, the parentNode property - // can be accessed but is null. - if ( parent !== document && !parent.parentNode ) { - return; - } - // Traverse up the tree - while ( parent && parent !== this ) { - parent = parent.parentNode; - } - - if ( parent !== this ) { - // set the correct event type - event.type = event.data; - - // handle event if we actually just moused on to a non sub-element - jQuery.event.handle.apply( this, arguments ); - } - - // assuming we've left the element since we most likely mousedover a xul element - } catch(e) { } -}, - -// In case of event delegation, we only need to rename the event.type, -// liveHandler will take care of the rest. -delegate = function( event ) { - event.type = event.data; - jQuery.event.handle.apply( this, arguments ); -}; - -// Create mouseenter and mouseleave events -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - setup: function( data ) { - jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); - }, - teardown: function( data ) { - jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); - } - }; -}); - -// submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function( data, namespaces ) { - if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { - jQuery.event.add(this, "click.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - trigger( "submit", this, arguments ); - } - }); - - jQuery.event.add(this, "keypress.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { - trigger( "submit", this, arguments ); - } - }); - - } else { - return false; - } - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialSubmit" ); - } - }; - -} - -// change delegation, happens here so we have bind. -if ( !jQuery.support.changeBubbles ) { - - var changeFilters, - - getVal = function( elem ) { - var type = elem.type, val = elem.value; - - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; - - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; - - } else if ( elem.nodeName.toLowerCase() === "select" ) { - val = elem.selectedIndex; - } - - return val; - }, - - testChange = function testChange( e ) { - var elem = e.target, data, val; - - if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { - return; - } - - data = jQuery._data( elem, "_change_data" ); - val = getVal(elem); - - // the current data will be also retrieved by beforeactivate - if ( e.type !== "focusout" || elem.type !== "radio" ) { - jQuery._data( elem, "_change_data", val ); - } - - if ( data === undefined || val === data ) { - return; - } - - if ( data != null || val ) { - e.type = "change"; - e.liveFired = undefined; - jQuery.event.trigger( e, arguments[1], elem ); - } - }; - - jQuery.event.special.change = { - filters: { - focusout: testChange, - - beforedeactivate: testChange, - - click: function( e ) { - var elem = e.target, type = elem.type; - - if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { - testChange.call( this, e ); - } - }, - - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = elem.type; - - if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - testChange.call( this, e ); - } - }, - - // Beforeactivate happens also before the previous element is blurred - // with this event you can't trigger a change event, but you can store - // information - beforeactivate: function( e ) { - var elem = e.target; - jQuery._data( elem, "_change_data", getVal(elem) ); - } - }, - - setup: function( data, namespaces ) { - if ( this.type === "file" ) { - return false; - } - - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); - } - - return rformElems.test( this.nodeName ); - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialChange" ); - - return rformElems.test( this.nodeName ); - } - }; - - changeFilters = jQuery.event.special.change.filters; - - // Handle when the input is .focus()'d - changeFilters.focus = changeFilters.beforeactivate; -} - -function trigger( type, elem, args ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - // Don't pass args or remember liveFired; they apply to the donor event. - var event = jQuery.extend( {}, args[ 0 ] ); - event.type = type; - event.originalEvent = {}; - event.liveFired = undefined; - jQuery.event.handle.call( elem, event ); - if ( event.isDefaultPrevented() ) { - args[ 0 ].preventDefault(); - } -} - -// Create "bubbling" focus and blur events -if ( document.addEventListener ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - jQuery.event.special[ fix ] = { - setup: function() { - this.addEventListener( orig, handler, true ); - }, - teardown: function() { - this.removeEventListener( orig, handler, true ); - } - }; - - function handler( e ) { - e = jQuery.event.fix( e ); - e.type = fix; - return jQuery.event.handle.call( this, e ); - } - }); -} - -jQuery.each(["bind", "one"], function( i, name ) { - jQuery.fn[ name ] = function( type, data, fn ) { - // Handle object literals - if ( typeof type === "object" ) { - for ( var key in type ) { - this[ name ](key, data, type[key], fn); - } - return this; - } - - if ( jQuery.isFunction( data ) || data === false ) { - fn = data; - data = undefined; - } - - var handler = name === "one" ? jQuery.proxy( fn, function( event ) { - jQuery( this ).unbind( event, handler ); - return fn.apply( this, arguments ); - }) : fn; - - if ( type === "unload" && name !== "one" ) { - this.one( type, data, fn ); - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.add( this[i], type, handler, data ); - } - } - - return this; - }; -}); - -jQuery.fn.extend({ - unbind: function( type, fn ) { - // Handle object literals - if ( typeof type === "object" && !type.preventDefault ) { - for ( var key in type ) { - this.unbind(key, type[key]); - } - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.remove( this[i], type, fn ); - } - } - - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.live( types, data, fn, selector ); - }, - - undelegate: function( selector, types, fn ) { - if ( arguments.length === 0 ) { - return this.unbind( "live" ); - - } else { - return this.die( types, null, fn, selector ); - } - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - - triggerHandler: function( type, data ) { - if ( this[0] ) { - var event = jQuery.Event( type ); - event.preventDefault(); - event.stopPropagation(); - jQuery.event.trigger( event, data, this[0] ); - return event.result; - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - i = 1; - - // link all the functions, so any of them can unbind this click handler - while ( i < args.length ) { - jQuery.proxy( fn, args[ i++ ] ); - } - - return this.click( jQuery.proxy( fn, function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - })); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -var liveMap = { - focus: "focusin", - blur: "focusout", - mouseenter: "mouseover", - mouseleave: "mouseout" -}; - -jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { - var type, i = 0, match, namespaces, preType, - selector = origSelector || this.selector, - context = origSelector ? this : jQuery( this.context ); - - if ( typeof types === "object" && !types.preventDefault ) { - for ( var key in types ) { - context[ name ]( key, data, types[key], selector ); - } - - return this; - } - - if ( jQuery.isFunction( data ) ) { - fn = data; - data = undefined; - } - - types = (types || "").split(" "); - - while ( (type = types[ i++ ]) != null ) { - match = rnamespaces.exec( type ); - namespaces = ""; - - if ( match ) { - namespaces = match[0]; - type = type.replace( rnamespaces, "" ); - } - - if ( type === "hover" ) { - types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); - continue; - } - - preType = type; - - if ( type === "focus" || type === "blur" ) { - types.push( liveMap[ type ] + namespaces ); - type = type + namespaces; - - } else { - type = (liveMap[ type ] || type) + namespaces; - } - - if ( name === "live" ) { - // bind live handler - for ( var j = 0, l = context.length; j < l; j++ ) { - jQuery.event.add( context[j], "live." + liveConvert( type, selector ), - { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); - } - - } else { - // unbind live handler - context.unbind( "live." + liveConvert( type, selector ), fn ); - } - } - - return this; - }; -}); - -function liveHandler( event ) { - var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, - elems = [], - selectors = [], - events = jQuery._data( this, "events" ); - - // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) - if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { - return; - } - - if ( event.namespace ) { - namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.liveFired = this; - - var live = events.live.slice(0); - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { - selectors.push( handleObj.selector ); - - } else { - live.splice( j--, 1 ); - } - } - - match = jQuery( event.target ).closest( selectors, event.currentTarget ); - - for ( i = 0, l = match.length; i < l; i++ ) { - close = match[i]; - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { - elem = close.elem; - related = null; - - // Those two events require additional checking - if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { - event.type = handleObj.preType; - related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; - } - - if ( !related || related !== elem ) { - elems.push({ elem: elem, handleObj: handleObj, level: close.level }); - } - } - } - } - - for ( i = 0, l = elems.length; i < l; i++ ) { - match = elems[i]; - - if ( maxLevel && match.level > maxLevel ) { - break; - } - - event.currentTarget = match.elem; - event.data = match.handleObj.data; - event.handleObj = match.handleObj; - - ret = match.handleObj.origHandler.apply( match.elem, arguments ); - - if ( ret === false || event.isPropagationStopped() ) { - maxLevel = match.level; - - if ( ret === false ) { - stop = false; - } - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - return stop; -} - -function liveConvert( type, selector ) { - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); -} - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.bind( name, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } -}); - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var match, - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - var found, item, - filter = Expr.filter[ type ], - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw "Syntax error, unrecognized expression: " + msg; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return "text" === elem.getAttribute( 'type' ); - }, - radio: function( elem ) { - return "radio" === elem.type; - }, - - checkbox: function( elem ) { - return "checkbox" === elem.type; - }, - - file: function( elem ) { - return "file" === elem.type; - }, - password: function( elem ) { - return "password" === elem.type; - }, - - submit: function( elem ) { - return "submit" === elem.type; - }, - - image: function( elem ) { - return "image" === elem.type; - }, - - reset: function( elem ) { - return "reset" === elem.type; - }, - - button: function( elem ) { - return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - var first = match[2], - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // If the nodes are siblings (or identical) we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Utility function for retreiving the text value of an array of DOM nodes -Sizzle.getText = function( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += Sizzle.getText( elem.childNodes ); - } - } - - return ret; -}; - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

    "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - if ( matches ) { - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - return matches.call( node, expr ); - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
    "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var ret = this.pushStack( "", "find", selector ), - length = 0; - - for ( var i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( var n = length; n < ret.length; n++ ) { - for ( var r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && jQuery.filter( selector, this ).length > 0; - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - if ( jQuery.isArray( selectors ) ) { - var match, selector, - matches = {}, - level = 1; - - if ( cur && selectors.length ) { - for ( i = 0, l = selectors.length; i < l; i++ ) { - selector = selectors[i]; - - if ( !matches[selector] ) { - matches[selector] = jQuery.expr.match.POS.test( selector ) ? - jQuery( selector, context || this.context ) : - selector; - } - } - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( selector in matches ) { - match = matches[selector]; - - if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { - ret.push({ selector: selector, elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - } - - return ret; - } - - var pos = POS.test( selectors ) ? - jQuery( selectors, context || this.context ) : null; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique(ret) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - if ( !elem || typeof elem === "string" ) { - return jQuery.inArray( this[0], - // If it receives a string, the selector is used - // If it receives nothing, the siblings are used - elem ? jQuery( elem ) : this.parent().children() ); - } - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ), - // The variable 'args' was introduced in - // https://github.com/jquery/jquery/commit/52a0238 - // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. - // http://code.google.com/p/v8/issues/detail?id=1050 - args = slice.call(arguments); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, args.join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return (elem === qualifier) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return (jQuery.inArray( elem, qualifier ) >= 0) === keep; - }); -} - - - - -var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
    ", "
    " ], - thead: [ 1, "", "
    " ], - tr: [ 2, "", "
    " ], - td: [ 3, "", "
    " ], - col: [ 2, "", "
    " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }; - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and "); -// } diff --git a/_test/testDesign/Manual regression cases.xmind b/_test/testDesign/Manual regression cases.xmind deleted file mode 100644 index 91ed117d..00000000 Binary files a/_test/testDesign/Manual regression cases.xmind and /dev/null differ diff --git a/_test/testDesign/Range.mm b/_test/testDesign/Range.mm deleted file mode 100644 index a2320126..00000000 --- a/_test/testDesign/Range.mm +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/_test/testDesign/UeditorMini_1.0.0_\346\265\213\350\257\225\346\212\245\345\221\212.docx" "b/_test/testDesign/UeditorMini_1.0.0_\346\265\213\350\257\225\346\212\245\345\221\212.docx" deleted file mode 100644 index f136bf41..00000000 Binary files "a/_test/testDesign/UeditorMini_1.0.0_\346\265\213\350\257\225\346\212\245\345\221\212.docx" and /dev/null differ diff --git "a/_test/testDesign/UeditorMini_1.0.0_\346\265\213\350\257\225\350\256\241\345\210\222.docx" "b/_test/testDesign/UeditorMini_1.0.0_\346\265\213\350\257\225\350\256\241\345\210\222.docx" deleted file mode 100644 index 360031ab..00000000 Binary files "a/_test/testDesign/UeditorMini_1.0.0_\346\265\213\350\257\225\350\256\241\345\210\222.docx" and /dev/null differ diff --git a/_test/testDesign/config.xmind b/_test/testDesign/config.xmind deleted file mode 100644 index b171b5ce..00000000 Binary files a/_test/testDesign/config.xmind and /dev/null differ diff --git a/_test/testDesign/core.xmind b/_test/testDesign/core.xmind deleted file mode 100644 index 9be7cc13..00000000 Binary files a/_test/testDesign/core.xmind and /dev/null differ diff --git a/_test/testDesign/domUtils.xmind b/_test/testDesign/domUtils.xmind deleted file mode 100644 index 38cdd2b7..00000000 Binary files a/_test/testDesign/domUtils.xmind and /dev/null differ diff --git a/_test/testDesign/image revelant.xmind b/_test/testDesign/image revelant.xmind deleted file mode 100644 index d7f0b23e..00000000 Binary files a/_test/testDesign/image revelant.xmind and /dev/null differ diff --git a/_test/testDesign/pluginsAutoCaseListBase.docx b/_test/testDesign/pluginsAutoCaseListBase.docx deleted file mode 100644 index 27e6ec90..00000000 Binary files a/_test/testDesign/pluginsAutoCaseListBase.docx and /dev/null differ diff --git a/_test/testDesign/regression testing.xmind b/_test/testDesign/regression testing.xmind deleted file mode 100644 index 2a8b42a2..00000000 Binary files a/_test/testDesign/regression testing.xmind and /dev/null differ diff --git a/_test/testDesign/test list for 1.2.xmind b/_test/testDesign/test list for 1.2.xmind deleted file mode 100644 index 34d06a9f..00000000 Binary files a/_test/testDesign/test list for 1.2.xmind and /dev/null differ diff --git a/_test/tools/br/analysis.php b/_test/tools/br/analysis.php deleted file mode 100644 index c0a57732..00000000 --- a/_test/tools/br/analysis.php +++ /dev/null @@ -1,112 +0,0 @@ -circle)) return array();//如果已经被分析过则直接返回 - array_push($this->circle, $domain); - - $include = array(); - $cnts = self::get_src_cnt($domain); - $is = $cnts['i']; - if(sizeof($is) > 0) - foreach($is as $d){ - if($recurse) - $include = array_merge($include, $this->get_import_srcs($d)); - else - $include[$d] = self::$_cache[$d]; - } - - //因为依赖关系的前后联系,最后在include中加入当前domain - if($recurse) - $include[$domain] = $cnts['c']; - return $include; - } - - - /** - * 读取源文件内容,支持缓存,支持覆盖率文件读取,覆盖率路径在Config中配置 - * @param string $domain - * @see Config::$COVERAGE_PATH - */ - static function get_src_cnt($domain){ - new Analysis(); - if(!array_key_exists($domain, self::$_cache)){ - $cnt =''; $covcnt = ''; - //$path = join('/', explode('.', $domain)).'.js'; //为了支持xx.xx.js类型的文件名而修改 田丽丽 - //文件在当前项目存在则取当前项目,否则取tangram项目 - require_once 'config.php'; - foreach(Config::$SOURCE_PATH as $i=>$d){ - if(Config::$DEBUG) - var_dump($d.$path); - if(file_exists($d.$path)){ - $cnt = file_get_contents($d.$path); - $cnt.="\n";//读取文件内容必须加个回车 - break; - } - } - //尝试读取cov目录下的文件,如果不存在则忽略 - $covpath = Config::$COVERAGE_PATH.$path; - if(file_exists($covpath)){ - if(Config::$DEBUG)var_dump($covpath); - $covcnt = file_get_contents($covpath); - } - else $covcnt = $cnt; - if($cnt == ''){ - if(Config::$DEBUG) - print "fail read file : ".$path; - return array('', array(), ''); - } - - if(Config::$DEBUG) - print "start read file $domain
    "; - - $is = array(); - //正则匹配,提取所有(///import xxx;)中的xxx - preg_match_all('/\/\/\/import\s+([^;]+);?/ies', $cnt, $is, PREG_PATTERN_ORDER); - - //移除//,顺便移除空行 - // $cnt = preg_replace('/\/\/.*/m', '', $cnt);TODO:正则处理出现在“”或者正则中的//时出现问题 - //移除/**/ - // $cnt = preg_replace('/\/\*.*\*\//sU', '', $cnt); - - self::$_cache[$domain] = array('c'=>$cnt, 'i'=>$is[1], 'cc'=>$covcnt); - } - return self::$_cache[$domain]; - } -} -?> diff --git a/_test/tools/br/batchrun.sh b/_test/tools/br/batchrun.sh deleted file mode 100644 index f88256c1..00000000 --- a/_test/tools/br/batchrun.sh +++ /dev/null @@ -1,10 +0,0 @@ -/home/work/.bash_profile -cd /home/work/repos/Tangram-base -/home/work/soft/git-1.7.3.5/bin-wrappers/git pull -sh release/output.sh -rm -rf test/tools/br/report -wget -q -O /tmp/tmp.php http://10.32.34.115:8000/Tangram-base/test/tools/br/runall.php?clearreport=true&cov=true -sleep 3m -rm -rf test/tools/br/report -wget -q -O /tmp/tmp.php http://10.32.34.115:8000/Tangram-base/test/tools/br/runall.php?release=true&clearreport=true -cd - \ No newline at end of file diff --git a/_test/tools/br/case.class.php b/_test/tools/br/case.class.php deleted file mode 100644 index c4b31edb..00000000 --- a/_test/tools/br/case.class.php +++ /dev/null @@ -1,194 +0,0 @@ -projroot = $projroot; - $this->name = $name; - - $this->ext = $ext; - if ( strlen( $ext ) > 0 ) { - $ns = explode( '.' , $name ); - - $n = array_pop( $ns ); - array_push( $ns , $ext , $n ); - $path = implode( '/' , $ns ); - } else { - //$path = implode( '/' , explode( '.' , $name ) ); - $path = $name; //为了支持xx.xx.js类型的文件名而修改 田丽丽 - } -// $dir = explode('/',$path); -// if($dir[0]=='dialogs') -// $this->path = $this->projroot . '_test/' . $path . '.html'; -// else - $this->path = $this->projroot . '_test/' . $path . '.js'; - if ( filesize( $this->path ) < 20 ) { - $this->empty = true; - return; - } - $this->case_id = 'id_case_' . join( '_' , explode( '.' , $name ) ); - } - - - public function print_js( $cov, $release = false ) - { - - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - print '' . "\n"; - - print '' . "\n"; - - - /* load case source*/ - $importurl = "{$this->projroot}_test/tools/br/import.php?f=$this->name"; - if ( $cov ) $importurl .= '^&cov=true'; - print "\n"; - - /* load case and case dependents*/ - //$ps = explode( '.' , $this->name ); - $ps = explode( '/' , $this->name ); //为了支持xx.xx.js类型的文件名而修改 田丽丽 - array_pop( $ps ); - array_push( $ps , 'tools' ); - - if ( file_exists( $this->projroot . '_test/' . implode( '/' , $ps ) . '.js' ) ) //没有就不加载了 - print '' . "\n"; - print '' . "\n"; - - - } - public function match( $matcher ) - { - if ( $matcher == '*' ) - return true; - $len = strlen( $matcher ); - - /** - * 处理多选分支,有一个成功则成功,filter后面参数使用|切割 - * @var unknown_type - */ - $ms = explode( ',' , $matcher ); - if ( sizeof( $ms ) > 1 ) { - foreach ( $ms as $matcher1 ) { - if ( $this->match( $matcher1 ) ) - return true; - } - return false; - } - - /** - * 处理反向选择分支 - */ - if ( substr( $matcher , 0 , 1 ) == '!' ) { - $m = substr( $matcher , 1 ); - if ( substr( $this->name , 0 , strlen( $m ) ) == $m ) - return false; - return true; - } - - if ( $len > strlen( $this->name ) ) { - return false; - } - return substr( $this->name , 0 , $len ) == $matcher; - } - - public static function listcase( $matcher = "*" , $projroot = '../../../' ) - { - $srcpath = $projroot . '_src/'; - $testpath = $projroot . '_test/'; - require_once 'filehelper.php'; - $caselist = getSameFile( $srcpath , $testpath , '' );//默认取src和test下的同名文件 - foreach(Config::$special_Case as $s_caseitem => $s_source){//设置在源码路径下没有同名文件对应的测试文件 - array_push($caselist,$s_caseitem); - } sort($caselist,SORT_STRING); - foreach ( $caselist as $caseitem ) { - /*将文件名替换为域名方式,替换/为.,移除.js*/ - //$name = str_replace( '/' , '.' , substr( $caseitem , 0 , -3 ) ); - $name = substr( $caseitem , 0 , -3 ); //为了支持xx.xx.js类型的文件名而修改 田丽丽 - $c = new Kiss( $projroot , $name ); - if ( $c->empty ) - continue; - if ( $c->match( $matcher ) ) { - $newName = explode( '\\.' , $name ); - $newName = $newName[ count( $newName ) - 1 ]; - print( "case_id\" class=\"jsframe_qunit\" target=\"_blank\" title=\"$name\" onclick=\"run('$name');\$('#id_rerun').html('$name');return false;\">" - /*过长的时候屏蔽超出20的部分,因为隐藏的处理,所有用例不能直接使用标签a中的innerHTML,而应该使用title*/ - . $newName . "\n" ); - } - } - - } - - public static function listSrcOnly( $print = true , $projroot = '../../../' ) - { - $srcpath = $projroot . '_src/'; - $testpath = $projroot . '_test/'; - require_once 'filehelper.php'; - $caselist = getSameFile( $srcpath , $testpath , '' ); - $srclist = getSrcOnlyFile( $srcpath , $testpath , '' ); - $srcList = array(); - foreach ( $srclist as $case ) { - if ( in_array( $case , $caselist ) ) - continue; - $name = str_replace( '/' , '.' , substr( $case , 0 , -3 ) ); - $tag = "" . ( strlen( $name ) > 20 ? substr( $name , 6 ) - : $name ) . ""; - array_push( $srcList , $tag ); - if ( $print ) - echo $tag; - } - return $srcList; - } -} - -?> \ No newline at end of file diff --git a/_test/tools/br/config.php b/_test/tools/br/config.php deleted file mode 100644 index 4dc39d95..00000000 --- a/_test/tools/br/config.php +++ /dev/null @@ -1,73 +0,0 @@ - array( '10.94.26.96' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ), - 'ie11' => array( '10.81.96.46' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ), - 'firefox' => array( '10.94.26.95' , "C:\\Program Files\\mozilla firefox\\firefox.exe" ) -// 'firefox' => array( '10.81.96.46@8500' , "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe" ) -// , '360ie8' => array('10.81.58.64@8500',"C:\\Program Files\\360\\360se\\360SE.exe") -// , '360ie7' => array( '10.81.58.87@8500' , "C:\\Program Files\\360\\360se\\360SE.exe" ) - -// -// , 'ie6' => array( '10.81.58.86@8500' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) - - , 'chrome' => array( '10.94.26.95' , "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" ) -// , 'ie7' => array( '10.81.58.87@8500' , "C:\\Program Files\\Internet Explorer\\iexplore.exe" ) -// , 'opera' => array( '10.81.58.64@8500' , "C:\\Program Files\\Opera\\opera.exe" ) -// , 'safari' => array( '10.81.58.63@8500' , "C:\\Program Files\\Safari\\Safari.exe" ) - ); - - public static $DEBUG = false; - - public static $HISTORY_REPORT_PATH = '/report'; - - public static function getBrowserSet($browsers){ - if(strcmp($browsers,'')==0){ - return Config::$BROWSERS; - } - $selectedBrowsers =array(); - $browserName = explode('_',$browsers); - foreach($browserName as $s){ - if(array_key_exists($s,Config::$BROWSERS));{ - $selectedBrowsers[$s] =Config::$BROWSERS[$s]; - } - } - return $selectedBrowsers; - } - - public static function StopAll() - { - $hostarr = array(); - foreach ( Config::$BROWSERS as $b => $h ) { - $host = $h[ 0 ]; - if ( array_search( $host , $hostarr ) ) - continue; - array_push( $hostarr , $host ); - require_once 'lib/Staf.php'; - Staf::process_stop( '' , $host , true ); - Staf::process( "free all" ); - } - } - - /** - * 源码路径配置,会在所有位置寻找源码 - * @var ArrayIterator::String - */ - public static $SOURCE_PATH = array( "../../../_src/" ); - - public static $test_PATH = "../../../_test/"; - - /** - * 覆盖率相关源码所在路径,如果路径中没有找到会回到$SOURCH_PATH中查找 - * @var string - */ - public static $COVERAGE_PATH = "../../coverage/"; - /** - * 设置在源码路径下没有同名文件对应的测试文件 - * @var array - */ - public static $special_Case = array('plugins/map.js'=>''); - } - -?> \ No newline at end of file diff --git a/_test/tools/br/coverage/jscov.php b/_test/tools/br/coverage/jscov.php deleted file mode 100644 index ebff23bd..00000000 --- a/_test/tools/br/coverage/jscov.php +++ /dev/null @@ -1,61 +0,0 @@ - \ No newline at end of file diff --git a/_test/tools/br/coverage/jscoverage-highlight.css b/_test/tools/br/coverage/jscoverage-highlight.css deleted file mode 100644 index d2ad01da..00000000 --- a/_test/tools/br/coverage/jscoverage-highlight.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - jscoverage-highlight.css - JSCoverage syntax highlighting style sheet - Copyright (C) 2008, 2009, 2010 siliconforks.com - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -/* keyword, type, symbol, cbracket */ -#sourceTable .k { - font-weight: bold; -} - -/* string, regexp, number */ -#sourceTable .s { - color: #006400; -} - -/* specialchar */ -#sourceTable .t { - color: #2e8b57; -} - -/* comment */ -#sourceTable .c { - font-style: italic; -} diff --git a/_test/tools/br/coverage/jscoverage-ie.css b/_test/tools/br/coverage/jscoverage-ie.css deleted file mode 100644 index 05cad2af..00000000 --- a/_test/tools/br/coverage/jscoverage-ie.css +++ /dev/null @@ -1,108 +0,0 @@ -/* - jscoverage-ie.css - JSCoverage style sheet for Internet Explorer - Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#headingDiv { - position: static; - margin-left: 10px; - margin-right: 10px; - padding-top: 0.5em; -} - -#tabs { - clear: all; - position: static; - top: auto; - left: auto; - right: auto; - height: auto; - margin-left: 10px; - margin-right: 10px; -} - -#tabs div { - position: relative; - height: auto; - line-height: normal; - padding-top: 5px; - padding-bottom: 5px; -} - -#tabs div.selected { - padding-bottom: 6px; - z-index: 2; -} - -.TabPage { - position: relative; - top: -1px; - left: auto; - right: auto; - bottom: auto; - clear: left; - margin-left: 10px; - margin-right: 10px; - padding: 10px; - z-index: 1; -} - -#locationDiv { - margin-bottom: 10px; -} - -#iframeDiv { - position: static; - width: 100%; -} - -#summaryDiv { - position: static; - width: 100%; -} - -#fileDiv { - margin-bottom: 10px; -} - -#sourceDiv { - position: static; - width: 100%; -} - -#storeDiv { - position: static; - width: 100%; -} - -/* some defaults */ - -.TabPage { - height: 650px; -} - -#iframeDiv { - height: 600px; -} - -#summaryDiv { - height: 600px; -} - -#sourceDiv { - height: 600px; -} diff --git a/_test/tools/br/coverage/jscoverage-throbber.gif b/_test/tools/br/coverage/jscoverage-throbber.gif deleted file mode 100644 index f13c0b4e..00000000 Binary files a/_test/tools/br/coverage/jscoverage-throbber.gif and /dev/null differ diff --git a/_test/tools/br/coverage/jscoverage.css b/_test/tools/br/coverage/jscoverage.css deleted file mode 100644 index 9866fd70..00000000 --- a/_test/tools/br/coverage/jscoverage.css +++ /dev/null @@ -1,355 +0,0 @@ -/* - jscoverage.css - code coverage for JavaScript - Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -body { - background-color: #bfffbf; - font-family: sans-serif; - font-size: 100%; - margin: 0; -} - -#mainDiv { - font-size: 0.8125em; -} - -#headingDiv { - position: absolute; - top: 0.5em; - left: 1.5em; - right: 1.5em; - bottom: 0; - line-height: 1.5em; -} - -h1 { - float: left; - margin: 0; - padding-bottom: 0.5em; - font-size: 1.3em; -} - -.ProgressBar { - float: left; - visibility: hidden; -} - -.ProgressPercentage { - display: block; - float: left; - width: 5em; - text-align: right; -} - -.ProgressGraph { - float: left; - width: 100px; - height: 10px; - border: 1px solid black; - margin-top: 0.3em; - background-color: #d4d0c8; - overflow: hidden; -} - -.ProgressCovered { - /* windows system color ActiveCaption or Highlight */ - background-color: #0a246a; - width: 0; - height: 10px; - overflow: hidden; -} - -#progressLabel { - display: block; - float: left; - padding-left: 0.3em; -} - -#warningDiv { - display: none; - float: right; - background-color: #FFBFBF; - border: 1px solid red; - padding-left: 2px; - padding-right: 2px; -} - -.WarningDialog { - display: none; - background-color: #FFBFBF; - position: absolute; - z-index: 10; - top: 20%; - left: 20%; - width: 50%; - padding: 5%; - border: 1px solid red; -} - -.WarningDialog button { - display: block; - margin-left: auto; - margin-right: auto; -} - -/******************************************************************************* -browser tab -*/ - -input#location, button { - border: 1px solid black; - margin-left: 1px; - margin-right: 1px; -} - -#iframeDiv { - position: absolute; - top: 3.5em; - left: 1em; - right: 1em; - bottom: 1em; -} - -iframe { - width: 100%; - height: 100%; -} - -/******************************************************************************* -summary tab -*/ - -#summaryDiv { - position: absolute; - top: 3em; - left: 1em; - right: 1em; - bottom: 1em; - overflow: auto; -} - -table#summaryTable { - width: 100%; - margin-left: 0px; - margin-right: 0px; - border-collapse: collapse; - font-size: small; -} - -table#summaryTable th, table#summaryTable td { - border-left: 1px solid #d9d9d9; -} - -table#summaryTable th.leftColumn, table#summaryTable td.leftColumn { - border-left-width: 0px; -} - -table#summaryTable th, table#summaryTable td { - padding: 2px; -} - -th { - background-color: #e6ffe6; -} - -td.numeric { - text-align: right; -} - -abbr { - cursor: help; -} - -tr#summaryTotals td.leftColumn span { - float: right; -} -tr#summaryTotals td.leftColumn span.title { - float: left; - font-weight: bold; -} -tr#summaryTotals td { - background-color: #ffd; -} -td.coverage { - width: 150px; -} -td.coverage span { - float: right; - margin-right: 5px; -} -.pctGraph { - width: 100px; - height: 10px; - float: right; - border: 1px solid #000; - background-color: #e00000; - overflow: hidden; - margin-top: 4px; -} -.pctGraph .covered { - background-color: #00f000; - width: 0; - height: 10px; -} -.pctGraph .skipped { - background-color: #d4d0c8; - width: 100px; - height: 10px; -} -tbody#summaryTbody tr.even td { - background-color: #e6ffe6; -} - -/******************************************************************************* -source tab -*/ - -#fileDiv { - font-size: large; - font-weight: bold; -} - -#sourceDiv { - position: absolute; - top: 3em; - left: 1em; - right: 1em; - bottom: 1em; - overflow: auto; -} - -table#sourceTable { - border: 0px; - border-collapse: collapse; - font-size: small; -} - -/* -IE default behavior is to make
     smaller than surrounding text.  Because
    -the table already has font-size small, this would make the font-size within the
    -
     x-small.  So we don't rely on the default.
    -*/
    -table#sourceTable pre {
    -  font-size: medium;
    -}
    -
    -table#sourceTable td {
    -  border: 0px;
    -  padding-top: 0px;
    -  padding-bottom: 0px;
    -  padding-left: 10px;
    -  padding-right: 10px;
    -}
    -
    -table#sourceTable pre {
    -  border: 0px;
    -  margin: 0px;
    -}
    -
    -.g {
    -  background-color: #bfffbf;
    -}
    -
    -.y {
    -  background-color: #ffffbf;
    -}
    -
    -.r {
    -  background-color: #ffbfbf;
    -}
    -
    -/*******************************************************************************
    -store tab
    -*/
    -
    -#storeDiv {
    -  position: absolute;
    -  top: 3em;
    -  left: 1em;
    -  right: 1em;
    -  bottom: 1em;
    -  overflow: auto;
    -}
    -
    -/*******************************************************************************
    -about tab
    -*/
    -
    -p {
    -  margin-top: 0;
    -}
    -
    -/*******************************************************************************
    -tabs
    -*/
    -
    -#tabs {
    -  position: absolute;
    -  top: 3em;
    -  left: 1.5em;
    -  right: 1.5em;
    -  height: 2em;
    -}
    -
    -#tabs div {
    -  background-color: white;
    -  position: relative;
    -  float: left;
    -  border: 1px solid black;
    -  border-bottom-width: 0;
    -  cursor: pointer;
    -  margin-left: 0.5em;
    -  margin-right: 0.5em;
    -  padding-left: 0.5em;
    -  padding-right: 0.5em;
    -  height: 2em;
    -  z-index: 1;
    -  line-height: 1.8em;
    -}
    -
    -#tabs div.selected {
    -  z-index: 3;
    -  cursor: default;
    -}
    -
    -#tabs div.disabled {
    -  /* windows system color GrayText */
    -  color: #808080;
    -  cursor: default; 
    -}
    -
    -.TabPage {
    -  background-color: white;
    -  border: 1px solid black;
    -  position: absolute;
    -  top: 5em;
    -  left: 1.5em;
    -  right: 1.5em;
    -  bottom: 1.5em;
    -  z-index: 2;
    -  padding: 1em;
    -  display: none;
    -}
    -
    -#tabPages div.selected {
    -  display: block;
    -}
    -
    -img {
    -  visibility: hidden;
    -}
    diff --git a/_test/tools/br/coverage/jscoverage.html b/_test/tools/br/coverage/jscoverage.html
    deleted file mode 100644
    index e6288fce..00000000
    --- a/_test/tools/br/coverage/jscoverage.html
    +++ /dev/null
    @@ -1,168 +0,0 @@
    -
    -
    -
    -
    -
    -
    -JSCoverage
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - -
    -

    -Recent web browsers tend to place significant security restrictions on the use -of file: URLs. These restrictions can prevent JSCoverage from -working properly. To avoid problems, it is recommended that you do either of the -following: -

    -
      -
    • If you are using the jscoverage program to instrument your -JavaScript code, install the instrumented files on a web server.
    • -
    • Use the jscoverage-server program (which itself acts as a web -server).
    • -
    -

    -See the -manual -for further details. -

    - -
    - -
    -

    -Recent web browsers tend to place significant security restrictions on the use -of file: URLs. These restrictions can prevent JSCoverage from -working properly. To avoid problems, it is recommended that you view coverage -reports stored to the filesystem by serving them from a web server. -

    -

    -See the -manual -for further details. -

    - -
    - -
    - -
    Summary
    -
    Source
    -
    Store
    -
    About
    -
    -
    - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - -
    FileStatementsExecutedCoverage
    - Total: - 0 - 00 -
    -
    -
    - 0% -
    -
    -
    -
    -
    -
    -
    -
    - - loading... -
    -
    -
    -

    - This is version 0.5.1 of JSCoverage, a program that calculates code - coverage statistics for JavaScript. -

    -

    - See http://siliconforks.com/jscoverage/ for more information. -

    -

    - Copyright © 2007, 2008, 2009, 2010 siliconforks.com -

    -
    -
    -
    - - diff --git a/_test/tools/br/coverage/jscoverage.js b/_test/tools/br/coverage/jscoverage.js deleted file mode 100644 index 4233615a..00000000 --- a/_test/tools/br/coverage/jscoverage.js +++ /dev/null @@ -1,1176 +0,0 @@ -/* - jscoverage.js - code coverage for JavaScript - Copyright (C) 2007, 2008, 2009, 2010 siliconforks.com - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -function jscoverage_openWarningDialog() { - var id; - if (jscoverage_isReport) { - id = 'reportWarningDialog'; - } - else { - id = 'warningDialog'; - } - var dialog = document.getElementById(id); - dialog.style.display = 'block'; -} - -function jscoverage_closeWarningDialog() { - var id; - if (jscoverage_isReport) { - id = 'reportWarningDialog'; - } - else { - id = 'warningDialog'; - } - var dialog = document.getElementById(id); - dialog.style.display = 'none'; -} - -/** -Initializes the _$jscoverage object in a window. This should be the first -function called in the page. -@param w this should always be the global window object -*/ -function jscoverage_init(w) { - try { - // in Safari, "import" is a syntax error - Components.utils['import']('resource://app/modules/jscoverage.jsm'); - jscoverage_isInvertedMode = true; - return; - } - catch (e) {} - - // check if we are in inverted mode - if (w.opener) { - try { - if (w.opener.top._$jscoverage) { - jscoverage_isInvertedMode = true; - if (! w._$jscoverage) { - w._$jscoverage = w.opener.top._$jscoverage; - } - } - else { - jscoverage_isInvertedMode = false; - } - } - catch (e) { - try { - if (w.opener._$jscoverage) { - jscoverage_isInvertedMode = true; - if (! w._$jscoverage) { - w._$jscoverage = w.opener._$jscoverage; - } - } - else { - jscoverage_isInvertedMode = false; - } - } - catch (e2) { - jscoverage_isInvertedMode = false; - } - } - } - else { - jscoverage_isInvertedMode = false; - } - - if (! jscoverage_isInvertedMode) { - if (! w._$jscoverage) { - w._$jscoverage = {}; - } - } -} - -var jscoverage_currentFile = null; -var jscoverage_currentLine = null; - -var jscoverage_inLengthyOperation = false; - -/* -Possible states: - isInvertedMode isServer isReport tabs -normal false false false Browser -inverted true false false -server, normal false true false Browser, Store -server, inverted true true false Store -report false false true -*/ -var jscoverage_isInvertedMode = false; -var jscoverage_isServer = false; -var jscoverage_isReport = false; - -jscoverage_init(window); - -function jscoverage_createRequest() { - // Note that the IE7 XMLHttpRequest does not support file URL's. - // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html - // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx -//#JSCOVERAGE_IF - if (window.ActiveXObject) { - return new ActiveXObject("Microsoft.XMLHTTP"); - } - else { - return new XMLHttpRequest(); - } -} - -// http://www.quirksmode.org/js/findpos.html -function jscoverage_findPos(obj) { - var result = 0; - do { - result += obj.offsetTop; - obj = obj.offsetParent; - } - while (obj); - return result; -} - -// http://www.quirksmode.org/viewport/compatibility.html -function jscoverage_getViewportHeight() { -//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent) - if (self.innerHeight) { - // all except Explorer - return self.innerHeight; - } - else if (document.documentElement && document.documentElement.clientHeight) { - // Explorer 6 Strict Mode - return document.documentElement.clientHeight; - } - else if (document.body) { - // other Explorers - return document.body.clientHeight; - } - else { - throw "Couldn't calculate viewport height"; - } -//#JSCOVERAGE_ENDIF -} - -/** -Indicates visually that a lengthy operation has begun. The progress bar is -displayed, and the cursor is changed to busy (on browsers which support this). -*/ -function jscoverage_beginLengthyOperation() { - jscoverage_inLengthyOperation = true; - - var progressBar = document.getElementById('progressBar'); - progressBar.style.visibility = 'visible'; - ProgressBar.setPercentage(progressBar, 0); - var progressLabel = document.getElementById('progressLabel'); - progressLabel.style.visibility = 'visible'; - - /* blacklist buggy browsers */ -//#JSCOVERAGE_IF - if (! /Opera|WebKit/.test(navigator.userAgent)) { - /* - Change the cursor style of each element. Note that changing the class of the - element (to one with a busy cursor) is buggy in IE. - */ - var tabs = document.getElementById('tabs').getElementsByTagName('div'); - var i; - for (i = 0; i < tabs.length; i++) { - tabs.item(i).style.cursor = 'wait'; - } - } -} - -/** -Removes the progress bar and busy cursor. -*/ -function jscoverage_endLengthyOperation() { - var progressBar = document.getElementById('progressBar'); - ProgressBar.setPercentage(progressBar, 100); - setTimeout(function() { - jscoverage_inLengthyOperation = false; - progressBar.style.visibility = 'hidden'; - var progressLabel = document.getElementById('progressLabel'); - progressLabel.style.visibility = 'hidden'; - progressLabel.innerHTML = ''; - - var tabs = document.getElementById('tabs').getElementsByTagName('div'); - var i; - for (i = 0; i < tabs.length; i++) { - tabs.item(i).style.cursor = ''; - } - }, 50); -} - -function jscoverage_setSize() { -//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent) - var viewportHeight = jscoverage_getViewportHeight(); - - /* - border-top-width: 1px - padding-top: 10px - padding-bottom: 10px - border-bottom-width: 1px - margin-bottom: 10px - ---- - 32px - */ - var tabPages = document.getElementById('tabPages'); - var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px'; - var nodeList = tabPages.childNodes; - var length = nodeList.length; - for (var i = 0; i < length; i++) { - var node = nodeList.item(i); - if (node.nodeType !== 1) { - continue; - } - node.style.height = tabPageHeight; - } - - var iframeDiv = document.getElementById('iframeDiv'); - // may not exist if we have removed the first tab - if (iframeDiv) { - iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px'; - } - - var summaryDiv = document.getElementById('summaryDiv'); - summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px'; - - var sourceDiv = document.getElementById('sourceDiv'); - sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px'; - - var storeDiv = document.getElementById('storeDiv'); - if (storeDiv) { - storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px'; - } -//#JSCOVERAGE_ENDIF -} - -/** -Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off', -and '0' (upper or lower case) are false. -@param s the string -@return a boolean value -*/ -function jscoverage_getBooleanValue(s) { - s = s.toLowerCase(); - if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') { - return false; - } - return true; -} - -function jscoverage_removeTab(id) { - var tab = document.getElementById(id + 'Tab'); - tab.parentNode.removeChild(tab); - var tabPage = document.getElementById(id + 'TabPage'); - tabPage.parentNode.removeChild(tabPage); -} - -function jscoverage_isValidURL(url) { - // RFC 3986 - var matches = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(url); - if (matches === null) { - return false; - } - var scheme = matches[1]; - if (typeof scheme === 'string') { - scheme = scheme.toLowerCase(); - return scheme === '' || scheme === 'file:' || scheme === 'http:' || scheme === 'https:'; - } - return true; -} - -/** -Initializes the contents of the tabs. This sets the initial values of the -input field and iframe in the "Browser" tab and the checkbox in the "Summary" -tab. -@param queryString this should always be location.search -*/ -function jscoverage_initTabContents(queryString) { - var showMissingColumn = false; - var url = null; - var windowURL = null; - var parameters, parameter, i, index, name, value; - if (queryString.length > 0) { - // chop off the question mark - queryString = queryString.substring(1); - parameters = queryString.split(/&|;/); - for (i = 0; i < parameters.length; i++) { - parameter = parameters[i]; - index = parameter.indexOf('='); - if (index === -1) { - // still works with old syntax - url = decodeURIComponent(parameter); - } - else { - name = parameter.substr(0, index); - value = decodeURIComponent(parameter.substr(index + 1)); - if (name === 'missing' || name === 'm') { - showMissingColumn = jscoverage_getBooleanValue(value); - } - else if (name === 'url' || name === 'u' || name === 'frame' || name === 'f') { - url = value; - } - else if (name === 'window' || name === 'w') { - windowURL = value; - } - } - } - } - - var checkbox = document.getElementById('checkbox'); - checkbox.checked = showMissingColumn; - if (showMissingColumn) { - jscoverage_appendMissingColumn(); - } - - var isValidURL = function (url) { - var result = jscoverage_isValidURL(url); - if (! result) { - alert('Invalid URL: ' + url); - } - return result; - }; - - if (url !== null && isValidURL(url)) { - // this will automatically propagate to the input field - frames[0].location = url; - } - else if (windowURL !== null && isValidURL(windowURL)) { - window.open(windowURL); - } - - // if the browser tab is absent, we have to initialize the summary tab - if (! document.getElementById('browserTab')) { - jscoverage_recalculateSummaryTab(); - } -} - -function jscoverage_body_load() { - // check if this is a file: URL - if (window.location && window.location.href && /^file:/i.test(window.location.href)) { - var warningDiv = document.getElementById('warningDiv'); - warningDiv.style.display = 'block'; - } - - var progressBar = document.getElementById('progressBar'); - ProgressBar.init(progressBar); - - function reportError(e) { - jscoverage_endLengthyOperation(); - var summaryThrobber = document.getElementById('summaryThrobber'); - summaryThrobber.style.visibility = 'hidden'; - var div = document.getElementById('summaryErrorDiv'); - div.innerHTML = 'Error: ' + e; - } - - if (jscoverage_isReport) { - jscoverage_beginLengthyOperation(); - var summaryThrobber = document.getElementById('summaryThrobber'); - summaryThrobber.style.visibility = 'visible'; - var request = jscoverage_createRequest(); - try { - request.open('GET', 'jscoverage.json', true); - request.onreadystatechange = function (event) { - if (request.readyState === 4) { - try { - if (request.status !== 0 && request.status !== 200) { - throw request.status; - } - var response = request.responseText; - if (response === '') { - throw 404; - } - - var json; - if (window.JSON && window.JSON.parse) { - json = window.JSON.parse(response); - } - else { - json = eval('(' + response + ')'); - } - - var file; - for (file in json) { - if (! json.hasOwnProperty(file)) { - continue; - } - - var fileCoverage = json[file]; - _$jscoverage[file] = fileCoverage.coverage; - _$jscoverage[file].source = fileCoverage.source; - } - jscoverage_recalculateSummaryTab(); - summaryThrobber.style.visibility = 'hidden'; - } - catch (e) { - reportError(e); - } - } - }; - request.send(null); - } - catch (e) { - reportError(e); - } - - jscoverage_removeTab('browser'); - jscoverage_removeTab('store'); - } - else { - if (jscoverage_isInvertedMode) { - jscoverage_removeTab('browser'); - } - - if (! jscoverage_isServer) { - jscoverage_removeTab('store'); - } - } - - jscoverage_initTabControl(); - - jscoverage_initTabContents(location.search); -} - -function jscoverage_body_resize() { - if (/MSIE/.test(navigator.userAgent)) { - jscoverage_setSize(); - } -} - -// ----------------------------------------------------------------------------- -// tab 1 - -function jscoverage_updateBrowser() { - var input = document.getElementById("location"); - frames[0].location = input.value; -} - -function jscoverage_openWindow() { - var input = document.getElementById("location"); - var url = input.value; - window.open(url); -} - -function jscoverage_input_keypress(e) { - if (e.keyCode === 13) { - if (e.shiftKey) { - jscoverage_openWindow(); - } - else { - jscoverage_updateBrowser(); - } - } -} - -function jscoverage_openInFrameButton_click() { - jscoverage_updateBrowser(); -} - -function jscoverage_openInWindowButton_click() { - jscoverage_openWindow(); -} - -function jscoverage_browser_load() { - /* update the input box */ - var input = document.getElementById("location"); - - /* sometimes IE seems to fire this after the tab has been removed */ - if (input) { - input.value = frames[0].location; - } -} - -// ----------------------------------------------------------------------------- -// tab 2 - -function jscoverage_createHandler(file, line) { - return function () { - jscoverage_get(file, line); - return false; - }; -} - -function jscoverage_createLink(file, line) { - var link = document.createElement("a"); - link.href = '#'; - link.onclick = jscoverage_createHandler(file, line); - - var text; - if (line) { - text = line.toString(); - } - else { - text = file; - } - - link.appendChild(document.createTextNode(text)); - - return link; -} - -function jscoverage_recalculateSummaryTab(cc) { - var checkbox = document.getElementById('checkbox'); - var showMissingColumn = checkbox.checked; - - if (! cc) { - cc = window._$jscoverage; - } - if (! cc) { -//#JSCOVERAGE_IF 0 - throw "No coverage information found."; -//#JSCOVERAGE_ENDIF - } - - var tbody = document.getElementById("summaryTbody"); - while (tbody.hasChildNodes()) { - tbody.removeChild(tbody.firstChild); - } - - var totals = { files:0, statements:0, executed:0 }; - - var file; - var files = []; - for (file in cc) { - if (! cc.hasOwnProperty(file)) { - continue; - } - - files.push(file); - } - files.sort(); - - var rowCounter = 0; - for (var f = 0; f < files.length; f++) { - file = files[f]; - var lineNumber; - var num_statements = 0; - var num_executed = 0; - var missing = []; - var fileCC = cc[file]; - var length = fileCC.length; - var currentConditionalEnd = 0; - var conditionals = null; - if (fileCC.conditionals) { - conditionals = fileCC.conditionals; - } - for (lineNumber = 0; lineNumber < length; lineNumber++) { - var n = fileCC[lineNumber]; - - if (lineNumber === currentConditionalEnd) { - currentConditionalEnd = 0; - } - else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) { - currentConditionalEnd = conditionals[lineNumber]; - } - - if (currentConditionalEnd !== 0) { - continue; - } - - if (n === undefined || n === null) { - continue; - } - - if (n === 0) { - missing.push(lineNumber); - } - else { - num_executed++; - } - num_statements++; - } - - var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) ); - - var row = document.createElement("tr"); - row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" ); - - var cell = document.createElement("td"); - cell.className = 'leftColumn'; - var link = jscoverage_createLink(file); - cell.appendChild(link); - - row.appendChild(cell); - - cell = document.createElement("td"); - cell.className = 'numeric'; - cell.appendChild(document.createTextNode(num_statements)); - row.appendChild(cell); - - cell = document.createElement("td"); - cell.className = 'numeric'; - cell.appendChild(document.createTextNode(num_executed)); - row.appendChild(cell); - - // new coverage td containing a bar graph - cell = document.createElement("td"); - cell.className = 'coverage'; - var pctGraph = document.createElement("div"), - covered = document.createElement("div"), - pct = document.createElement("span"); - pctGraph.className = "pctGraph"; - if( num_statements === 0 ) { - covered.className = "skipped"; - pct.appendChild(document.createTextNode("N/A")); - } else { - covered.className = "covered"; - covered.style.width = percentage + "px"; - pct.appendChild(document.createTextNode(percentage + '%')); - } - pct.className = "pct"; - pctGraph.appendChild(covered); - cell.appendChild(pctGraph); - cell.appendChild(pct); - row.appendChild(cell); - - if (showMissingColumn) { - cell = document.createElement("td"); - for (var i = 0; i < missing.length; i++) { - if (i !== 0) { - cell.appendChild(document.createTextNode(", ")); - } - link = jscoverage_createLink(file, missing[i]); - - // group contiguous missing lines; e.g., 10, 11, 12 -> 10-12 - var j, start = missing[i]; - for (;;) { - j = 1; - while (i + j < missing.length && missing[i + j] == missing[i] + j) { - j++; - } - var nextmissing = missing[i + j], cur = missing[i] + j; - if (isNaN(nextmissing)) { - break; - } - while (cur < nextmissing && ! fileCC[cur]) { - cur++; - } - if (cur < nextmissing || cur >= length) { - break; - } - i += j; - } - if (start != missing[i] || j > 1) { - i += j - 1; - link.innerHTML += "-" + missing[i]; - } - - cell.appendChild(link); - } - row.appendChild(cell); - } - - tbody.appendChild(row); - - totals['files'] ++; - totals['statements'] += num_statements; - totals['executed'] += num_executed; - - // write totals data into summaryTotals row - var tr = document.getElementById("summaryTotals"); - if (tr) { - var tds = tr.getElementsByTagName("td"); - tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files']; - tds[1].firstChild.nodeValue = totals['statements']; - tds[2].firstChild.nodeValue = totals['executed']; - - var coverage = parseInt(100 * totals['executed'] / totals['statements']); - if( isNaN( coverage ) ) { - coverage = 0; - } - tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%'; - tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px'; - } - - } - jscoverage_endLengthyOperation(); -} - -function jscoverage_appendMissingColumn() { - var headerRow = document.getElementById('headerRow'); - var missingHeader = document.createElement('th'); - missingHeader.id = 'missingHeader'; - missingHeader.innerHTML = 'Missing'; - headerRow.appendChild(missingHeader); - var summaryTotals = document.getElementById('summaryTotals'); - var empty = document.createElement('td'); - empty.id = 'missingCell'; - summaryTotals.appendChild(empty); -} - -function jscoverage_removeMissingColumn() { - var missingNode; - missingNode = document.getElementById('missingHeader'); - missingNode.parentNode.removeChild(missingNode); - missingNode = document.getElementById('missingCell'); - missingNode.parentNode.removeChild(missingNode); -} - -function jscoverage_checkbox_click() { - if (jscoverage_inLengthyOperation) { - return false; - } - jscoverage_beginLengthyOperation(); - var checkbox = document.getElementById('checkbox'); - var showMissingColumn = checkbox.checked; - setTimeout(function() { - if (showMissingColumn) { - jscoverage_appendMissingColumn(); - } - else { - jscoverage_removeMissingColumn(); - } - jscoverage_recalculateSummaryTab(); - }, 50); - return true; -} - -// ----------------------------------------------------------------------------- -// tab 3 - -function jscoverage_makeTable() { - var coverage = _$jscoverage[jscoverage_currentFile]; - var lines = coverage.source; - - // this can happen if there is an error in the original JavaScript file - if (! lines) { - lines = []; - } - - var rows = ['']; - var i = 0; - var progressBar = document.getElementById('progressBar'); - var tableHTML; - var currentConditionalEnd = 0; - - function joinTableRows() { - tableHTML = rows.join(''); - ProgressBar.setPercentage(progressBar, 60); - /* - This may be a long delay, so set a timeout of 100 ms to make sure the - display is updated. - */ - setTimeout(appendTable, 100); - } - - function appendTable() { - var sourceDiv = document.getElementById('sourceDiv'); - sourceDiv.innerHTML = tableHTML; - ProgressBar.setPercentage(progressBar, 80); - setTimeout(jscoverage_scrollToLine, 0); - } - - while (i < lines.length) { - var lineNumber = i + 1; - - if (lineNumber === currentConditionalEnd) { - currentConditionalEnd = 0; - } - else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) { - currentConditionalEnd = coverage.conditionals[lineNumber]; - } - - var row = ''; - row += ''; - var timesExecuted = coverage[lineNumber]; - if (timesExecuted !== undefined && timesExecuted !== null) { - if (currentConditionalEnd !== 0) { - row += ''; - } - else { - row += ''; - } - row += ''; - row += ''; - row += '\n'; - rows[lineNumber] = row; - i++; - } - rows[i + 1] = '
    ' + lineNumber + ''; - } - else if (timesExecuted === 0) { - row += ''; - } - else { - row += ''; - } - row += timesExecuted; - row += '
    ' + lines[i] + '
    '; - ProgressBar.setPercentage(progressBar, 40); - setTimeout(joinTableRows, 0); -} - -function jscoverage_scrollToLine() { - jscoverage_selectTab('sourceTab'); - if (! window.jscoverage_currentLine) { - jscoverage_endLengthyOperation(); - return; - } - var div = document.getElementById('sourceDiv'); - if (jscoverage_currentLine === 1) { - div.scrollTop = 0; - } - else { - var cell = document.getElementById('line-' + jscoverage_currentLine); - - // this might not be there if there is an error in the original JavaScript - if (cell) { - var divOffset = jscoverage_findPos(div); - var cellOffset = jscoverage_findPos(cell); - div.scrollTop = cellOffset - divOffset; - } - } - jscoverage_currentLine = 0; - jscoverage_endLengthyOperation(); -} - -/** -Loads the given file (and optional line) in the source tab. -*/ -function jscoverage_get(file, line) { - if (jscoverage_inLengthyOperation) { - return; - } - jscoverage_beginLengthyOperation(); - setTimeout(function() { - var sourceDiv = document.getElementById('sourceDiv'); - sourceDiv.innerHTML = ''; - jscoverage_selectTab('sourceTab'); - if (file === jscoverage_currentFile) { - jscoverage_currentLine = line; - jscoverage_recalculateSourceTab(); - } - else { - if (jscoverage_currentFile === null) { - var tab = document.getElementById('sourceTab'); - tab.className = ''; - tab.onclick = jscoverage_tab_click; - } - jscoverage_currentFile = file; - jscoverage_currentLine = line || 1; // when changing the source, always scroll to top - var fileDiv = document.getElementById('fileDiv'); - fileDiv.innerHTML = jscoverage_currentFile; - jscoverage_recalculateSourceTab(); - return; - } - }, 50); -} - -/** -Calculates coverage statistics for the current source file. -*/ -function jscoverage_recalculateSourceTab() { - if (! jscoverage_currentFile) { - jscoverage_endLengthyOperation(); - return; - } - var progressLabel = document.getElementById('progressLabel'); - progressLabel.innerHTML = 'Calculating coverage ...'; - var progressBar = document.getElementById('progressBar'); - ProgressBar.setPercentage(progressBar, 20); - setTimeout(jscoverage_makeTable, 0); -} - -// ----------------------------------------------------------------------------- -// tabs - -/** -Initializes the tab control. This function must be called when the document is -loaded. -*/ -function jscoverage_initTabControl() { - var tabs = document.getElementById('tabs'); - var i; - var child; - var tabNum = 0; - for (i = 0; i < tabs.childNodes.length; i++) { - child = tabs.childNodes.item(i); - if (child.nodeType === 1) { - if (child.className !== 'disabled') { - child.onclick = jscoverage_tab_click; - } - tabNum++; - } - } - jscoverage_selectTab(0); -} - -/** -Selects a tab. -@param tab the integer index of the tab (0, 1, 2, or 3) - OR - the ID of the tab element - OR - the tab element itself -*/ -function jscoverage_selectTab(tab) { - if (typeof tab !== 'number') { - tab = jscoverage_tabIndexOf(tab); - } - var tabs = document.getElementById('tabs'); - var tabPages = document.getElementById('tabPages'); - var nodeList; - var tabNum; - var i; - var node; - - nodeList = tabs.childNodes; - tabNum = 0; - for (i = 0; i < nodeList.length; i++) { - node = nodeList.item(i); - if (node.nodeType !== 1) { - continue; - } - - if (node.className !== 'disabled') { - if (tabNum === tab) { - node.className = 'selected'; - } - else { - node.className = ''; - } - } - tabNum++; - } - - nodeList = tabPages.childNodes; - tabNum = 0; - for (i = 0; i < nodeList.length; i++) { - node = nodeList.item(i); - if (node.nodeType !== 1) { - continue; - } - - if (tabNum === tab) { - node.className = 'selected TabPage'; - } - else { - node.className = 'TabPage'; - } - tabNum++; - } -} - -/** -Returns an integer (0, 1, 2, or 3) representing the index of a given tab. -@param tab the ID of the tab element - OR - the tab element itself -*/ -function jscoverage_tabIndexOf(tab) { - if (typeof tab === 'string') { - tab = document.getElementById(tab); - } - var tabs = document.getElementById('tabs'); - var i; - var child; - var tabNum = 0; - for (i = 0; i < tabs.childNodes.length; i++) { - child = tabs.childNodes.item(i); - if (child.nodeType === 1) { - if (child === tab) { - return tabNum; - } - tabNum++; - } - } -//#JSCOVERAGE_IF 0 - throw "Tab not found"; -//#JSCOVERAGE_ENDIF -} - -function jscoverage_tab_click(e) { - if (jscoverage_inLengthyOperation) { - return; - } - var target; -//#JSCOVERAGE_IF - if (e) { - target = e.target; - } - else if (window.event) { - // IE - target = window.event.srcElement; - } - if (target.className === 'selected') { - return; - } - jscoverage_beginLengthyOperation(); - setTimeout(function() { - if (target.id === 'summaryTab') { - var tbody = document.getElementById("summaryTbody"); - while (tbody.hasChildNodes()) { - tbody.removeChild(tbody.firstChild); - } - } - else if (target.id === 'sourceTab') { - var sourceDiv = document.getElementById('sourceDiv'); - sourceDiv.innerHTML = ''; - } - jscoverage_selectTab(target); - if (target.id === 'summaryTab') { - jscoverage_recalculateSummaryTab(); - } - else if (target.id === 'sourceTab') { - jscoverage_recalculateSourceTab(); - } - else { - jscoverage_endLengthyOperation(); - } - }, 50); -} - -// ----------------------------------------------------------------------------- -// progress bar - -var ProgressBar = { - init: function(element) { - element._percentage = 0; - - /* doing this via JavaScript crashes Safari */ -/* - var pctGraph = document.createElement('div'); - pctGraph.className = 'pctGraph'; - element.appendChild(pctGraph); - var covered = document.createElement('div'); - covered.className = 'covered'; - pctGraph.appendChild(covered); - var pct = document.createElement('span'); - pct.className = 'pct'; - element.appendChild(pct); -*/ - - ProgressBar._update(element); - }, - setPercentage: function(element, percentage) { - element._percentage = percentage; - ProgressBar._update(element); - }, - _update: function(element) { - var pctGraph = element.getElementsByTagName('div').item(0); - var covered = pctGraph.getElementsByTagName('div').item(0); - var pct = element.getElementsByTagName('span').item(0); - pct.innerHTML = element._percentage.toString() + '%'; - covered.style.width = element._percentage + 'px'; - } -}; - -// ----------------------------------------------------------------------------- -// reports - -function jscoverage_pad(s) { - return '0000'.substr(s.length) + s; -} - -function jscoverage_quote(s) { - return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) { - switch (c) { - case '\b': - return '\\b'; - case '\f': - return '\\f'; - case '\n': - return '\\n'; - case '\r': - return '\\r'; - case '\t': - return '\\t'; - // IE doesn't support this - /* - case '\v': - return '\\v'; - */ - case '"': - return '\\"'; - case '\\': - return '\\\\'; - default: - return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16)); - } - }) + '"'; -} - -function jscoverage_serializeCoverageToJSON() { - var json = []; - for (var file in _$jscoverage) { - if (! _$jscoverage.hasOwnProperty(file)) { - continue; - } - - var coverage = _$jscoverage[file]; - - var array = []; - var length = coverage.length; - for (var line = 0; line < length; line++) { - var value = coverage[line]; - if (value === undefined || value === null) { - value = 'null'; - } - array.push(value); - } - - var source = coverage.source; - var lines = []; - length = source.length; - for (var line = 0; line < length; line++) { - lines.push(jscoverage_quote(source[line])); - } - - json.push(jscoverage_quote(file) + ':{"coverage":[' + array.join(',') + '],"source":[' + lines.join(',') + ']}'); - } - return '{' + json.join(',') + '}'; -} - -function jscoverage_storeButton_click() { - if (jscoverage_inLengthyOperation) { - return; - } - - jscoverage_beginLengthyOperation(); - var img = document.getElementById('storeImg'); - img.style.visibility = 'visible'; - - var request = jscoverage_createRequest(); - request.open('POST', '/jscoverage-store', true); - request.onreadystatechange = function (event) { - if (request.readyState === 4) { - var message; - try { - if (request.status !== 200 && request.status !== 201 && request.status !== 204) { - throw request.status; - } - message = request.responseText; - } - catch (e) { - if (e.toString().search(/^\d{3}$/) === 0) { - message = e + ': ' + request.responseText; - } - else { - message = 'Could not connect to server: ' + e; - } - } - - jscoverage_endLengthyOperation(); - var img = document.getElementById('storeImg'); - img.style.visibility = 'hidden'; - - var div = document.getElementById('storeDiv'); - div.appendChild(document.createTextNode(new Date() + ': ' + message)); - div.appendChild(document.createElement('br')); - } - }; - request.setRequestHeader('Content-Type', 'application/json'); - var json = jscoverage_serializeCoverageToJSON(); - request.setRequestHeader('Content-Length', json.length.toString()); - request.send(json); -} diff --git a/_test/tools/br/coverage/readCoverage.js b/_test/tools/br/coverage/readCoverage.js deleted file mode 100644 index fbd43732..00000000 --- a/_test/tools/br/coverage/readCoverage.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * - */ -///import source -function creatJscoverage(){ - try { - if (typeof top === 'object' && top !== null && typeof top.opener === 'object' && top.opener !== null) { - // this is a browser window that was opened from another window - if (! top.opener._$jscoverage) { - top.opener._$jscoverage = {}; - } - } - } - - catch (e) {} - try { - if (typeof top === 'object' && top !== null) { - // this is a browser window - try { - if (typeof top.opener === 'object' && top.opener !== null && top.opener._$jscoverage) { - top._$jscoverage = top.opener._$jscoverage; - } - } - catch (e) {} - - if (! top._$jscoverage) { - top._$jscoverage = {}; - } - } - } - catch (e) {} - - try { - if (typeof top === 'object' && top !== null && top._$jscoverage) { - _$jscoverage = top._$jscoverage; - } - } - catch (e) {} - if (typeof _$jscoverage !== 'object') { - _$jscoverage = {}; - } -} - -(function(){ - var xmlDoc; - if (window.ActiveXObject) - { - xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); - if(xmlDoc != null) - { - xmlDoc.async=true; - xmlDoc.load("../HTML_Report/report.xml"); - } - } - else if(document.implementation && document.implementation.createDocument) - { - var xmlHttp=new window.XMLHttpRequest(); - xmlHttp.open("GET","../HTML_Report/report.xml",false); - xmlHttp.send(null); - xmlDoc = xmlHttp.responseXML; - }else{ - xmlDom=null; - } - function readCoverage(){ - creatJscoverage(); - var nodeNumber=xmlDoc.getElementsByTagName("testsuite").length; - for(i=0;i li:last-child { - border-radius: 0 0 15px 15px; - -moz-border-radius: 0 0 15px 15px; - -webkit-border-bottom-right-radius: 15px; - -webkit-border-bottom-left-radius: 15px; -} - -#qunit-tests .fail { color: #000000; background-color: #EE5757; } -#qunit-tests .fail .test-name, -#qunit-tests .fail .module-name { color: #000000; } - -#qunit-tests .fail .test-actual { color: #EE5757; } -#qunit-tests .fail .test-expected { color: green; } - -#qunit-banner.qunit-fail { background-color: #EE5757; } - - -/** Result */ - -#qunit-testresult { - padding: 0.5em 0.5em 0.5em 2.5em; - - color: #2b81af; - background-color: #D2E0E6; - - border-bottom: 1px solid white; -} - -/** Fixture */ - -#qunit-fixture { - position: absolute; - top: -10000px; - left: -10000px; -} diff --git a/_test/tools/br/css/tangramtest.css b/_test/tools/br/css/tangramtest.css deleted file mode 100644 index cd306e13..00000000 --- a/_test/tools/br/css/tangramtest.css +++ /dev/null @@ -1,173 +0,0 @@ -* { - margin: 0; - padding: 0; -} - -html { - border: 0; - height: 100%; -} - -body { - font: 12px/1.5 Lucida Grande, Helvetica, Arial, sans-serif; - background: #F3F1F1; - color: #41464D; -} - -body,#container { - width: 100%; - height: 100%; -} - -.clear { /* generic container (i.e. div) for floating buttons */ - overflow: hidden; - width: 100%; -} - -a { - text-decoration: none; - overflow: hidden; -} - -#title { - top: 0; - left: 0; - width: 100%; - padding: 5px 0; - background: #aaa; - background: #41464D; - color: #F3F1F1; - height: 30px; -} - -a:link,a:visited { - color: #528CE0; -} - -a:hover,a:active { - color: #41464D !important; - cursor: pointer !important; -} - -#title h1 { - height: 30px; - font: 25px/1.1 Arial, sans-serif; - font-weight: bolder; - float: left; - margin: 1px 0 2px 20px; - text-shadow: 0 2px 2px rgba(0, 0, 0, 0.4); -} - -h3 { - font-size: 14px; - padding: 3px 5px 1px; -} - -.control { - background: #d5ded7; - width: 99%; -} - -.testlist { - max-height: 200px; - overflow-y: scroll; - border-style: double; -} - -.testlist a { - display: block; - width: 150px; - color: #657528; - background: #d5dea7; - border: 1px solid #c8dc7b; - margin: 5px 0 0 5px; - text-indent: 5px; - line-height: 24px; - font-size: 14px; - float: left; -} - -a.button { - background: transparent url('bg_button_a.gif') no-repeat scroll top - right; - color: #444; - display: block; - float: left; - font: normal 12px arial, sans-serif; - height: 24px; - margin-right: 6px; - padding-right: 18px; /* sliding doors padding */ - text-decoration: none; -} - -a.button span { - background: transparent url('bg_button_span.gif') no-repeat; - display: block; - line-height: 14px; - padding: 5px 0 5px 18px; -} - -a.button:active { - background-position: bottom right; - color: #000; - outline: none; /* hide dotted outline in Firefox */ -} - -a.button:active span { - background-position: bottom left; - padding: 6px 0 4px 18px; /* push text down 1px */ -} - -.testlist a:link { - -} - -.testlist a:visited { - -} - -.testlist a:hover { - background: #c8dc7b; -} - -.testlist a.jsframe_jsspec { - background: #DDDDDD -} - -.testlist a.running_case { - color: yellow; -} - -.testlist a.fail_case { - color: red; -} - -.testlist a.pass_case { - color: green; -} - -.runningarea { - height: 60%; -} - -.runningmaindiv { - height: 99%; -} - -.runningframe { - height: 99.99%; - width: 99.99%; -} - -.runningstatus { - clear: both; - height: 10%; - border: solid -} - -.reportarea { - padding: 10px; - border: 10px blue; - max-height: 200px; - overflow-y: scroll; -} \ No newline at end of file diff --git a/_test/tools/br/css/testsuite.css b/_test/tools/br/css/testsuite.css deleted file mode 100644 index 5714bf4a..00000000 --- a/_test/tools/br/css/testsuite.css +++ /dev/null @@ -1,119 +0,0 @@ - -ol#qunit-tests { - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - margin:0; - padding:0; - list-style-position:inside; - - font-size: smaller; -} -ol#qunit-tests li{ - padding:0.4em 0.5em 0.4em 2.5em; - border-bottom:1px solid #fff; - font-size:small; - list-style-position:inside; -} -ol#qunit-tests li ol{ - box-shadow: inset 0px 2px 13px #999; - -moz-box-shadow: inset 0px 2px 13px #999; - -webkit-box-shadow: inset 0px 2px 13px #999; - margin-top:0.5em; - margin-left:0; - padding:0.5em; - background-color:#fff; - border-radius:15px; - -moz-border-radius: 15px; - -webkit-border-radius: 15px; -} -ol#qunit-tests li li{ - border-bottom:none; - margin:0.5em; - background-color:#fff; - list-style-position: inside; - padding:0.4em 0.5em 0.4em 0.5em; -} - -ol#qunit-tests li li.pass{ - border-left:26px solid #C6E746; - background-color:#fff; - color:#5E740B; - } -ol#qunit-tests li li.fail{ - border-left:26px solid #EE5757; - background-color:#fff; - color:#710909; -} -ol#qunit-tests li.pass{ - background-color:#D2E0E6; - color:#528CE0; -} -ol#qunit-tests li.fail{ - background-color:#EE5757; - color:#000; -} -ol#qunit-tests li strong { - cursor:pointer; -} -h1#qunit-header{ - background-color:#0d3349; - margin:0; - padding:0.5em 0 0.5em 1em; - color:#fff; - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - border-top-right-radius:15px; - border-top-left-radius:15px; - -moz-border-radius-topright:15px; - -moz-border-radius-topleft:15px; - -webkit-border-top-right-radius:15px; - -webkit-border-top-left-radius:15px; - text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px; -} -h2#qunit-banner{ - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - height:5px; - margin:0; - padding:0; -} -h2#qunit-banner.qunit-pass{ - background-color:#C6E746; -} -h2#qunit-banner.qunit-fail, #qunit-testrunner-toolbar { - background-color:#EE5757; -} -#qunit-testrunner-toolbar { - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - padding:0; - /*width:80%;*/ - padding:0em 0 0.5em 2em; - font-size: small; -} -h2#qunit-userAgent { - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - background-color:#2b81af; - margin:0; - padding:0; - color:#fff; - font-size: small; - padding:0.5em 0 0.5em 2.5em; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} -p#qunit-testresult{ - font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial; - margin:0; - font-size: small; - color:#2b81af; - border-bottom-right-radius:15px; - border-bottom-left-radius:15px; - -moz-border-radius-bottomright:15px; - -moz-border-radius-bottomleft:15px; - -webkit-border-bottom-right-radius:15px; - -webkit-border-bottom-left-radius:15px; - background-color:#D2E0E6; - padding:0.5em 0.5em 0.5em 2.5em; -} -strong b.fail{ - color:#710909; - } -strong b.pass{ - color:#5E740B; - } diff --git a/_test/tools/br/filehelper.php b/_test/tools/br/filehelper.php deleted file mode 100644 index d7c2ec8e..00000000 --- a/_test/tools/br/filehelper.php +++ /dev/null @@ -1,57 +0,0 @@ - \ No newline at end of file diff --git a/_test/tools/br/geneHTML.php b/_test/tools/br/geneHTML.php deleted file mode 100644 index 79fadd0d..00000000 --- a/_test/tools/br/geneHTML.php +++ /dev/null @@ -1,209 +0,0 @@ -来设置css是因为有的邮件客户端会过滤这样的信息 - * - * ***/ -function geneHTML($caseList, $name=''){ - date_default_timezone_set('PRC'); -// $url = (isset ($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') . $_SERVER['PHP_SELF']; - $url =""; - $html = " -
    -

    自动化用例测试结果".date('Y-m-d H:i:s')."

    -网页版 - -".getTrCase($caseList,true,1)."
    fail的用例统计
    用例名称


    - -".getTrCase($caseList,false,1)."".getTrCase($caseList,false,0)."
    全部用例统计
    用例名称
    未覆盖到的用例
    "; -// .""._srcOnlyList()."" - return $html; -} - -/** - * 创建遗漏用例列表 - * FIXME: 需要过滤package类型,考虑使用js名称同名目录存在进行过滤或者白名单 - */ -function _srcOnlyList(){ - require 'case.class.php'; - $list = Kiss::listSrcOnly(false); - $len = sizeof($list); - $flag="
    遗漏列表:总计$len,未过滤无需用例的package类型
    "; - $flag.=implode("
    ", $list); - $flag.="
    "; - return $flag; -} - -/** - * - * 根据实际浏览器书目确认生成表头 - * @param unknown_type $caseList - */ -function getThBrowser($caseList){ - //创建浏览器相关单元格 - $thBrowser = ''; - $count = 0; - foreach ($caseList as $casename => $casedetail) { - //每一个用例 - foreach ($casedetail as $b => $info) { - $thBrowser .= "$b"; - $count++; - } - $thBrowser .=""; - break;//遍历一次就知道所有浏览器的信息 - } - for($index = 0; $index < $count; $index++) { - $thBrowser .= "covfailtotal"; - } - - return $thBrowser.""; -} - -/** - * - * 根据执行结果生成单元格信息 - * @param unknown_type $caseList - */ -function getTrCase($caseList,$onlyFail,$onlyCoverd){ -//$onlyFail 为真时,只显示 fail 的用例 - //$onlyCoverd 为0时,只显示全浏览器覆盖率为0的用例;为1时,只显示全浏览器覆盖率不为0的用例;为其他时,显示所有的用例 - //创建case名对应的单元格 - $totalTrCase = ''; - require_once 'config.php'; - $rowColor = '#B0E0E6';//标记行的颜色,单双数行显示的背景颜色不同 - $numBro = count(Config::getBrowserSet($configBrowserSet)); - $averageCov = 0;//所有用例的全浏览器覆盖率的平均值(全浏览器覆盖率为0的不计) - $numCov = 0;//全浏览器覆盖率不为0的用例数量 - foreach ($caseList as $casename => $caseDetail) { - //每一个用例 - $ifFail = false; - $cnurl = implode('.', explode('_', $casename)); - $trCase = ''; - $totalCov = calTotalCov($caseDetail,$numBro); - $averageCov +=$totalCov; - $numCov = $totalCov==0?$numCov:$numCov+1; - if(($onlyCoverd==0&&$totalCov!=0)||($onlyCoverd==1&&$totalCov==0))//$onlyCoverd 为0时,只显示全浏览器覆盖率为0的用例;为1时,只显示全浏览器覆盖率不为0的用例; - continue; - if(!$onlyFail){//对于展示 fail 的用例的列表,不显示全浏览器覆盖率 - $trCase .= "".$totalCov.($totalCov=="_"?"":"%").""; - } - foreach ($caseDetail as $br => $infos) { - //$b为browser名字,$info为详细信息 - $fail = $infos['fail']; - $ifFail = $fail==0?$ifFail:true; - $total = $infos['total']; - $cov = $infos['cov']; - $color = $fail == 0 ? $rowColor : '#CD5C5C'; - $PercentSign = $cov=='_'?'':'%'; - $trCase .= "".$cov.$PercentSign."".$fail."".$total.""; - } - $trCase ="运行$casename".$trCase.""; - if(!$onlyFail||$ifFail){ - $totalTrCase =$totalTrCase.$trCase; - $rowColor = $rowColor=='#F0FFFF'?'#B0E0E6':'#F0FFFF'; - } - else; - } - $averageCov = number_format($averageCov/$numCov,1); - if($onlyCoverd==0) - $tableContent = $totalTrCase; - elseif(!$onlyFail) - $tableContent = "总覆盖率
    (平均值:".$averageCov."%)".getThBrowser($caseList).$totalTrCase; - else - $tableContent = getThBrowser($caseList).$totalTrCase; - return $tableContent; -} - -/** - * - * 计算总覆盖率信息 - * @param unknown_type $caseDetail - * @param unknown_type $brcount - */ -function calTotalCov($caseDetail,$brcount){ - $length = -1; - $num_statements = 0; - $num_executed = 0; - $totalInfo = null;//数组,记录全浏览器的覆盖情况,对文件中的每一行:覆盖为1,没覆盖为0,不计数为2 - $flag = 1;//$flag==-1时,各个浏览器覆盖率记录的文件信息有冲突,不能计算出全浏览器覆盖率(统计的文件长度不同/标记为2的不计入统计的行信息不同) - foreach ($caseDetail as $caseInfo){ - //如果recordCovForBrowser为空,跳过这个$caseInfo - if($caseInfo['recordCovForBrowser']==''){ - continue; - } - $infos = explode(',',$caseInfo['recordCovForBrowser']); - - $length = ($length==-1||$length==count($infos))?count($infos):-1; - if($length==-1||$length!=count($infos)) - break;//统计的文件长度不同 - else - ; - if($totalInfo==null){ -// if(count($infos)==1){ -// $flag = 0;//没有覆盖率信息 -// break; -// } - for($i=0;$i \ No newline at end of file diff --git a/_test/tools/br/geneHistory.php b/_test/tools/br/geneHistory.php deleted file mode 100644 index 3c32d90a..00000000 --- a/_test/tools/br/geneHistory.php +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/_test/tools/br/geneXML.php b/_test/tools/br/geneXML.php deleted file mode 100644 index 24cfad90..00000000 --- a/_test/tools/br/geneXML.php +++ /dev/null @@ -1,82 +0,0 @@ -testsuite as $testsuite){ - foreach ($testsuite->testcase as $testResult) { - // $totalCov = 0; - $browser = $testResult['browserInfo']; - $host = $testResult['hostInfo']; - $caseName = $testResult['name']; //得到用例名称 - settype($caseName, "string"); //$caseName本来类型为object,需要做转换 - $fail = $testResult['failNumber']; - $total = $testResult['totalNumber']; - $cov = $testResult['cov']; - settype($browser, "string"); - settype($host, "string"); - settype($fail, "string"); - settype($total, "string"); - settype($cov, "float"); - - if (!array_key_exists($caseName, $caseList)) { //如果这个用例不存在 - $caseInfo = array ( - 'hostInfo' => $host, - 'fail' => $fail, - 'total' => $total, - 'cov' => $cov - ); - // $totalCov += $cov; - $caseList[$caseName] = array ( - $browser => $caseInfo//, - // 'totalCov'=>$totalCov - ); - - // $caseList['totalCov'] = $totalCov; - } else { //否则添加到相应的用例中去 - $foundCase = $caseList[$caseName]; //找到用例名称对应的array,$caseName为key - if (!array_key_exists($browser, $foundCase)) { //如果没有该浏览器信息,则添加 - // $totalCov += $cov; - $caseList[$caseName][$browser] = array ( - 'hostInfo' => $host, - 'fail' => $fail, - 'total' => $total, - 'cov' => $cov - ); - // $caseList[$caseName]['totalCov'] = $totalCov; - } else { - $foundBrowser = $foundCase[$browser]; //有这个浏览器 - array_push($foundBrowser, array ( - 'hostInfo' => $host, - 'fail' => $fail, - 'total' => $total, - 'cov' => $cov - )); - } - } - - } - } - - //根据需求添加仅记录失败情况的接口 - if($onlyfails){//如果仅考虑失败情况,此处根据用例情况过滤 - foreach($caseList as $name => $info){ - $all_success = true;//记录当前用例是否全部运行成功 - foreach($info as $b => $result){ - if($result['fail'] > 0) - $all_success = false;//如果有失败情况则终止循环并进入下一个用例分析 - break; - } - //if($all_success) //如果全部通过则从记录中移除 - //unset($caseList[$name]); - } - } - return $caseList; -} -?> \ No newline at end of file diff --git a/_test/tools/br/import.php b/_test/tools/br/import.php deleted file mode 100644 index f4457d40..00000000 --- a/_test/tools/br/import.php +++ /dev/null @@ -1,68 +0,0 @@ -$d){ -// if(preg_match("/editorui/",$dd)){ -// echo "*************".file_get_contents($d.$path)."************"; -// } - if(file_exists($d.$path)){ - $source.= file_get_contents($d.$path); - $source.="\n";//读取文件内容必须加个回车 - break; - } - } - } - } - return $source; -} -//update by bell 2011-03-25, 更新覆盖率相关逻辑 -echo importSrc($cov); -?> \ No newline at end of file diff --git a/_test/tools/br/js/UserAction manual.rar b/_test/tools/br/js/UserAction manual.rar deleted file mode 100644 index 75853cb9..00000000 Binary files a/_test/tools/br/js/UserAction manual.rar and /dev/null differ diff --git a/_test/tools/br/js/UserAction.js b/_test/tools/br/js/UserAction.js deleted file mode 100644 index 2dd10838..00000000 --- a/_test/tools/br/js/UserAction.js +++ /dev/null @@ -1,1852 +0,0 @@ -/** - * 测试用例库文件,提供如event mock、iframe封装等各种常用功能 部分方法来源于YUI测试框架 - */ -UserAction = { - beforedispatch:null, -// flag : true, - isf /* is function ? */:function (value) { - return value && (typeof value == 'function'); - }, - isb /* is boolean? */:function (value) { - return value && (typeof value == 'boolean'); - }, - iso /* is object? */:function (value) { - return value && (typeof value == 'object'); - }, - iss /* is string? */:function (value) { - return value && (typeof value == 'string'); - }, - isn /* is number? */:function (value) { - return value && (typeof value == 'number'); - }, - // -------------------------------------------------------------------------- - // Generic event methods - // -------------------------------------------------------------------------- - - /** - * Simulates a key event using the given event information to populate the - * generated event object. This method does browser-equalizing calculations - * to account for differences in the DOM and IE event models as well as - * different browser quirks. Note: keydown causes Safari 2.x to crash. - * - * @method simulateKeyEvent - * @private - * @static - * @param {HTMLElement} - * target The target of the given event. - * @param {String} - * type The type of event to fire. This can be any one of the - * following: keyup, keydown, and keypress. - * @param {Boolean} - * bubbles (Optional) Indicates if the event can be bubbled up. - * DOM Level 3 specifies that all key events bubble by default. - * The default is true. - * @param {Boolean} - * cancelable (Optional) Indicates if the event can be canceled - * using preventDefault(). DOM Level 3 specifies that all key - * events can be cancelled. The default is true. - * @param {Window} - * view (Optional) The view containing the target. This is - * typically the window object. The default is window. - * @param {Boolean} - * ctrlKey (Optional) Indicates if one of the CTRL keys is - * pressed while the event is firing. The default is false. - * @param {Boolean} - * altKey (Optional) Indicates if one of the ALT keys is pressed - * while the event is firing. The default is false. - * @param {Boolean} - * shiftKey (Optional) Indicates if one of the SHIFT keys is - * pressed while the event is firing. The default is false. - * @param {Boolean} - * metaKey (Optional) Indicates if one of the META keys is - * pressed while the event is firing. The default is false. - * @param {int} - * keyCode (Optional) The code for the key that is in use. The - * default is 0. - * @param {int} - * charCode (Optional) The Unicode code for the character - * associated with the key being used. The default is 0. - */ - simulateKeyEvent:function (target /* :HTMLElement */, type /* :String */, bubbles /* :Boolean */, cancelable /* :Boolean */, view /* :Window */, ctrlKey /* :Boolean */, altKey /* :Boolean */, shiftKey /* :Boolean */, metaKey /* :Boolean */, keyCode /* :int */, charCode /* :int */) /* :Void */ { - // check target - target = typeof target == 'string' ? document.getElementById(target) - : target; - if (!target) { - throw new Error("simulateKeyEvent(): Invalid target."); - } - - // check event type - if (typeof type == 'string') { - type = type.toLowerCase(); - switch (type) { - case "compositionend": - case "compositionstart": - case "paste": - case "cut": - case "keyup": - case "keydown": - case "keypress": - break; - case "textevent": // DOM Level 3 - type = "keypress"; - break; - // @TODO was the fallthrough intentional, if so throw error - default: - throw new Error("simulateKeyEvent(): Event type '" + type - + "' not supported."); - } - } else { - throw new Error("simulateKeyEvent(): Event type must be a string."); - } - - // setup default values - if (!this.isb(bubbles)) { - bubbles = true; // all key events bubble - } - if (!this.isb(cancelable)) { - cancelable = true; // all key events can be cancelled - } - if (!this.iso(view)) { - view = window; // view is typically window - } - if (!this.isb(ctrlKey)) { - ctrlKey = false; - } - if (!this.isb(typeof altKey == 'boolean')) { - altKey = false; - } - if (!this.isb(shiftKey)) { - shiftKey = false; - } - if (!this.isb(metaKey)) { - metaKey = false; - } - if (!(typeof keyCode == 'number')) { - keyCode = 0; - } - if (!(typeof charCode == 'number')) { - charCode = 0; - } - - // try to create a mouse event - var customEvent /* :MouseEvent */ = null; - - // check for DOM-compliant browsers first - if (this.isf(document.createEvent)) { - - try { - - // try to create key event - customEvent = document.createEvent("KeyEvents"); - - /* - * Interesting problem: Firefox implemented a non-standard - * version of initKeyEvent() based on DOM Level 2 specs. Key - * event was removed from DOM Level 2 and re-introduced in DOM - * Level 3 with a different interface. Firefox is the only - * browser with any implementation of Key Events, so for now, - * assume it's Firefox if the above line doesn't error. - */ - // TODO: Decipher between Firefox's implementation and a correct - // one. - customEvent.initKeyEvent(type, bubbles, cancelable, view, - ctrlKey, altKey, shiftKey, metaKey, keyCode, charCode); - - } catch (ex /* :Error */) { - - /* - * If it got here, that means key events aren't officially - * supported. Safari/WebKit is a real problem now. WebKit 522 - * won't let you set keyCode, charCode, or other properties if - * you use a UIEvent, so we first must try to create a generic - * event. The fun part is that this will throw an error on - * Safari 2.x. The end result is that we need another - * try...catch statement just to deal with this mess. - */ - try { - - // try to create generic event - will fail in Safari 2.x - customEvent = document.createEvent("Events"); - - } catch (uierror /* :Error */) { - - // the above failed, so create a UIEvent for Safari 2.x - customEvent = document.createEvent("UIEvents"); - - } finally { - - customEvent.initEvent(type, bubbles, cancelable); - - // initialize - customEvent.view = view; - customEvent.altKey = altKey; - customEvent.ctrlKey = ctrlKey; - customEvent.shiftKey = shiftKey; - customEvent.metaKey = metaKey; - customEvent.keyCode = keyCode; - customEvent.charCode = charCode; - - } - - } - - // before dispatch - if (this.beforedispatch && typeof this.beforedispatch == 'function') - this.beforedispatch(customEvent); - this.beforedispatch = null; - - // fire the event - target.dispatchEvent(customEvent); - - } else if (this.iso(document.createEventObject)) { // IE - - // create an IE event object - customEvent = document.createEventObject(); - - // assign available properties - customEvent.bubbles = bubbles; - customEvent.cancelable = cancelable; - customEvent.view = view; - customEvent.ctrlKey = ctrlKey; - customEvent.altKey = altKey; - customEvent.shiftKey = shiftKey; - customEvent.metaKey = metaKey; - - /* - * IE doesn't support charCode explicitly. CharCode should take - * precedence over any keyCode value for accurate representation. - */ - customEvent.keyCode = (charCode > 0) ? charCode : keyCode; - - // before dispatch - if (this.beforedispatch && typeof this.beforedispatch == 'function') - this.beforedispatch(customEvent); - this.beforedispatch = null; - - // fire the event - target.fireEvent("on" + type, customEvent); - - } else { - throw new Error( - "simulateKeyEvent(): No event simulation framework present."); - } - - this.beforedispatch = null; - }, - - /** - * Simulates a mouse event using the given event information to populate the - * generated event object. This method does browser-equalizing calculations - * to account for differences in the DOM and IE event models as well as - * different browser quirks. - * - * @method simulateMouseEvent - * @private - * @static - * @param {HTMLElement} - * target The target of the given event. - * @param {String} - * type The type of event to fire. This can be any one of the - * following: click, dblclick, mousedown, mouseup, mouseout, - * mouseover, and mousemove. - * @param {Boolean} - * bubbles (Optional) Indicates if the event can be bubbled up. - * DOM Level 2 specifies that all mouse events bubble by default. - * The default is true. - * @param {Boolean} - * cancelable (Optional) Indicates if the event can be canceled - * using preventDefault(). DOM Level 2 specifies that all mouse - * events except mousemove can be cancelled. The default is true - * for all events except mousemove, for which the default is - * false. - * @param {Window} - * view (Optional) The view containing the target. This is - * typically the window object. The default is window. - * @param {int} - * detail (Optional) The number of times the mouse button has - * been used. The default value is 1. - * @param {int} - * screenX (Optional) The x-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {int} - * screenY (Optional) The y-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {int} - * clientX (Optional) The x-coordinate on the client at which - * point the event occured. The default is 0. - * @param {int} - * clientY (Optional) The y-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Boolean} - * ctrlKey (Optional) Indicates if one of the CTRL keys is - * pressed while the event is firing. The default is false. - * @param {Boolean} - * altKey (Optional) Indicates if one of the ALT keys is pressed - * while the event is firing. The default is false. - * @param {Boolean} - * shiftKey (Optional) Indicates if one of the SHIFT keys is - * pressed while the event is firing. The default is false. - * @param {Boolean} - * metaKey (Optional) Indicates if one of the META keys is - * pressed while the event is firing. The default is false. - * @param {int} - * button (Optional) The button being pressed while the event is - * executing. The value should be 0 for the primary mouse button - * (typically the left button), 1 for the terciary mouse button - * (typically the middle button), and 2 for the secondary mouse - * button (typically the right button). The default is 0. - * @param {HTMLElement} - * relatedTarget (Optional) For mouseout events, this is the - * element that the mouse has moved to. For mouseover events, - * this is the element that the mouse has moved from. This - * argument is ignored for all other events. The default is null. - */ - simulateMouseEvent:function (target /* :HTMLElement */, type /* :String */, bubbles /* :Boolean */, cancelable /* :Boolean */, view /* :Window */, detail /* :int */, screenX /* :int */, screenY /* :int */, clientX /* :int */, clientY /* :int */, ctrlKey /* :Boolean */, altKey /* :Boolean */, shiftKey /* :Boolean */, metaKey /* :Boolean */, button /* :int */, relatedTarget /* :HTMLElement */) /* :Void */ { - - // check target - target = typeof target == 'string' ? document.getElementById(target) - : target; - if (!target) { - throw new Error("simulateMouseEvent(): Invalid target."); - } - - // check event type - if (this.iss(type)) { - type = type.toLowerCase(); - switch (type) { - case "mouseover": - case "mouseout": - case "mousedown": - case "mouseup": - case "click": - case "dblclick": - case "mousemove": - case "mouseenter":// 非标准支持,仅为测试提供,该项仅IE下work - case "mouseleave": - case "contextmenu": - case "dragend": - case "blur": - break; - default: - throw new Error("simulateMouseEvent(): Event type '" + type - + "' not supported."); - } - } else { - throw new Error( - "simulateMouseEvent(): Event type must be a string."); - } - - // setup default values - if (!this.isb(bubbles)) { - bubbles = true; // all mouse events bubble - } - if (!this.isb(cancelable)) { - cancelable = (type != "mousemove"); // mousemove is the only one - // that can't be cancelled - } - if (!this.iso(view)) { - view = window; // view is typically window - } - if (!this.isn(detail)) { - detail = 1; // number of mouse clicks must be at least one - } - if (!this.isn(screenX)) { - screenX = 0; - } - if (!this.isn(screenY)) { - screenY = 0; - } - if (!this.isn(clientX)) { - clientX = 0; - } - if (!this.isn(clientY)) { - clientY = 0; - } - if (!this.isb(ctrlKey)) { - ctrlKey = false; - } - if (!this.isb(altKey)) { - altKey = false; - } - if (!this.isb(shiftKey)) { - shiftKey = false; - } - if (!this.isb(metaKey)) { - metaKey = false; - } - if (!this.isn(button)) { - button = 0; - } - - // try to create a mouse event - var customEvent /* :MouseEvent */ = null; - - // check for DOM-compliant browsers first - if (this.isf(document.createEvent)) { - - customEvent = document.createEvent("MouseEvents"); - - // Safari 2.x (WebKit 418) still doesn't implement initMouseEvent() - if (this.browser.ie !== 9 && customEvent.initMouseEvent) { - customEvent.initMouseEvent(type, bubbles, cancelable, view, - detail, screenX, screenY, clientX, clientY, ctrlKey, - altKey, shiftKey, metaKey, button, relatedTarget); - } else { // Safari - - // the closest thing available in Safari 2.x is UIEvents - customEvent = document.createEvent("UIEvents"); - customEvent.initEvent(type, bubbles, cancelable); - customEvent.view = view; - customEvent.detail = detail; - customEvent.screenX = screenX; - customEvent.screenY = screenY; - customEvent.clientX = clientX; - customEvent.clientY = clientY; - customEvent.ctrlKey = ctrlKey; - customEvent.altKey = altKey; - customEvent.metaKey = metaKey; - customEvent.shiftKey = shiftKey; - customEvent.button = button; - customEvent.relatedTarget = relatedTarget; - } - - /* - * Check to see if relatedTarget has been assigned. Firefox versions - * less than 2.0 don't allow it to be assigned via initMouseEvent() - * and the property is readonly after event creation, so in order to - * keep YAHOO.util.getRelatedTarget() working, assign to the IE - * proprietary toElement property for mouseout event and fromElement - * property for mouseover event. - */ - if (relatedTarget && !customEvent.relatedTarget) { - if (type == "mouseout") { - customEvent.toElement = relatedTarget; - } else if (type == "mouseover") { - customEvent.fromElement = relatedTarget; - } - } - - // before dispatch - if (this.beforedispatch && typeof this.beforedispatch == 'function') - this.beforedispatch(customEvent); - this.beforedispatch = null; - - // fire the event - target.dispatchEvent(customEvent); - - } else if (this.iso(document.createEventObject)) { // IE - - // create an IE event object - customEvent = document.createEventObject(); - - // assign available properties - customEvent.bubbles = bubbles; - customEvent.cancelable = cancelable; - customEvent.view = view; - customEvent.detail = detail; - customEvent.screenX = screenX; - customEvent.screenY = screenY; - customEvent.clientX = clientX; - customEvent.clientY = clientY; - customEvent.ctrlKey = ctrlKey; - customEvent.altKey = altKey; - customEvent.metaKey = metaKey; - customEvent.shiftKey = shiftKey; - - // fix button property for IE's wacky implementation - switch (button) { - case 0: - customEvent.button = 1; - break; - case 1: - customEvent.button = 4; - break; - case 2: - // leave as is - break; - default: - customEvent.button = 0; - } - - /* - * Have to use relatedTarget because IE won't allow assignment to - * toElement or fromElement on generic events. This keeps - * YAHOO.util.customEvent.getRelatedTarget() functional. - */ - customEvent.relatedTarget = relatedTarget; - - // before dispatch - if (this.beforedispatch && typeof this.beforedispatch == 'function') - this.beforedispatch(customEvent); - this.beforedispatch = null; - // fire the event - target.fireEvent("on" + type, customEvent); - - } else { - throw new Error( - "simulateMouseEvent(): No event simulation framework present."); - } - }, - - // -------------------------------------------------------------------------- - // Mouse events - // -------------------------------------------------------------------------- - - /** - * Simulates a mouse event on a particular element. - * - * @param {HTMLElement} - * target The element to click on. - * @param {String} - * type The type of event to fire. This can be any one of the - * following: click, dblclick, mousedown, mouseup, mouseout, - * mouseover, and mousemove. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method mouseEvent - * @static - */ - fireMouseEvent:function (target /* :HTMLElement */, type /* :String */, options /* :Object */) /* :Void */ { - options = options || {}; - this.simulateMouseEvent(target, type, options.bubbles, - options.cancelable, options.view, options.detail, - options.screenX, options.screenY, options.clientX, - options.clientY, options.ctrlKey, options.altKey, - options.shiftKey, options.metaKey, options.button, - options.relatedTarget); - }, - - /** - * Simulates a click on a particular element. - * - * @param {HTMLElement} - * target The element to click on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method click - * @static - */ - click:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireMouseEvent(target, "click", options); - }, - - /** - * Simulates a double click on a particular element. - * - * @param {HTMLElement} - * target The element to double click on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method dblclick - * @static - */ - dblclick:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireMouseEvent(target, "dblclick", options); - }, - - /** - * Simulates a mousedown on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method mousedown - * @static - */ - mousedown:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mousedown", options); - }, - - /** - * Simulates a mousemove on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method mousemove - * @static - */ - mousemove:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mousemove", options); - }, - - /** - * Simulates a mouseout event on a particular element. Use "relatedTarget" - * on the options object to specify where the mouse moved to. Quirks: - * Firefox less than 2.0 doesn't set relatedTarget properly, so toElement is - * assigned in its place. IE doesn't allow toElement to be be assigned, so - * relatedTarget is assigned in its place. Both of these concessions allow - * YAHOO.util.Event.getRelatedTarget() to work correctly in both browsers. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method mouseout - * @static - */ - mouseout:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mouseout", options); - }, - - /** - * Simulates a mouseover event on a particular element. Use "relatedTarget" - * on the options object to specify where the mouse moved from. Quirks: - * Firefox less than 2.0 doesn't set relatedTarget properly, so fromElement - * is assigned in its place. IE doesn't allow fromElement to be be assigned, - * so relatedTarget is assigned in its place. Both of these concessions - * allow YAHOO.util.Event.getRelatedTarget() to work correctly in both - * browsers. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method mouseover - * @static - */ - mouseover:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mouseover", options); - }, - - /** - * Simulates a mouseup on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method mouseup - * @static - */ - mouseup:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mouseup", options); - }, - mouseenter:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mouseenter", options); - }, - mouseleave:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireMouseEvent(target, "mouseleave", options); - }, - /** - * Simulates a contextmenu on a particular element. - * - * @param {HTMLElement} - * target The element to show contextmenu. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method contextmenu - * @static - */ - contextmenu:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireMouseEvent(target, "contextmenu", options); - }, - /** - * Simulates a dragend on a particular element. - * - * @param {HTMLElement} - * target The element to show dragend. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method dragend - * @static - */ - dragend:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireMouseEvent(target, "dragend", options); - }, - /** - * Simulates a blur on a particular element. - * - * @param {HTMLElement} - * target The element to show blur. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method blur - * @static - */ - blur:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireMouseEvent(target, "blur", options); - }, - dragto:function (target, options) { - var me = this; - me.mousemove(target, { - clientX:options.startX, - clientY:options.startY - }); - setTimeout(function () { - me.mousedown(target, { - clientX:options.startX, - clientY:options.startY - }); - setTimeout(function () { - me.mousemove(target, { - clientX:options.endX, - clientY:options.endY - }); - setTimeout(function () { - me.mouseup(target, { - clientX:options.endX, - clientY:options.endY - }); - if (options.callback) - options.callback(); - }, options.aftermove || 20); - }, options.beforemove || 20); - }, options.beforestart || 50); - }, - - // -------------------------------------------------------------------------- - // Key events - // -------------------------------------------------------------------------- - - /** - * Fires an event that normally would be fired by the keyboard (keyup, - * keydown, keypress). Make sure to specify either keyCode or charCode as an - * option. - * - * @private - * @param {String} - * type The type of event ("keyup", "keydown" or "keypress"). - * @param {HTMLElement} - * target The target of the event. - * @param {Object} - * options Options for the event. Either keyCode or charCode are - * required. - * @method fireKeyEvent - * @static - */ - fireKeyEvent:function (type /* :String */, target /* :HTMLElement */, options /* :Object */) /* :Void */ { - options = options || {}; - this.simulateKeyEvent(target, type, options.bubbles, - options.cancelable, options.view, options.ctrlKey, - options.altKey, options.shiftKey, options.metaKey, - options.keyCode, options.charCode); - }, - - /** - * Simulates a cut event on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method cut - * @static - */ - cut:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireKeyEvent("cut", target, options); - }, - - /** - * Simulates a paste event on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method paste - * @static - */ - paste:function ( target /* :HTMLElement */, options /* :Object */ ) /* :Void */ { - this.fireKeyEvent( "paste", target, options ); - }, - - /** - * Simulates a keydown event on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method keydown - * @static - */ - keydown:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireKeyEvent("keydown", target, options); - }, - - /** - * Simulates a keypress on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method keypress - * @static - */ - keypress:function (target /* :HTMLElement */, options /* :Object */) /* :Void */ { - this.fireKeyEvent("keypress", target, options); - }, - - /** - * Simulates a keyup event on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method keyup - * @static - */ - keyup:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireKeyEvent("keyup", target, options); - }, - - /** - * Simulates a compositionstart event on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method compositionstart - * @static - */ - compositionstart:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireKeyEvent("compositionstart", target, options); - }, - - /** - * Simulates a compositionstart event on a particular element. - * - * @param {HTMLElement} - * target The element to act on. - * @param {Object} - * options Additional event options (use DOM standard names). - * @method compositionstart - * @static - */ - compositionend:function (target /* :HTMLElement */, options /* Object */) /* :Void */ { - this.fireKeyEvent("compositionend", target, options); - }, - - /** - * 提供iframe扩展支持,用例测试需要独立场景的用例,由于异步支持,通过finish方法触发start - *
  • 事件绑定在frame上,包括afterfinish和jsloaded - * - * @param op.win - * @param op.nojs - * 不加载额外js - * @param op.ontest - * 测试步骤 - * @param op.onbeforestart - * 测试启动前处理步骤,默认为QUnit.stop(); - * @param op.onafterfinish - * 测试完毕执行步骤,默认为QUnit.start() - * - */ - frameExt:function (op) { - stop(); - op = typeof op == 'function' ? { - ontest:op - } : op; - var pw = op.win || window, w, f, url = '', id = typeof op.id == 'undefined' ? 'f' - : op.id, fid = 'iframe#' + id; - - op.finish = function () { - pw.$(fid).unbind(); - setTimeout(function () { - pw.$('div#div' + id).remove(); - start(); - }, 20); - }; - - if (pw.$(fid).length == 0) { - /* 添加frame,部分情况下,iframe没有边框,为了可以看到效果,添加一个带边框的div */ - pw.$(pw.document.body).append('
    '); - pw.$('div#div' + id).append(''); - } - op.onafterstart && op.onafterstart($('iframe#f')[0]); - pw.$('script').each(function () { - if (this.src && this.src.indexOf('import.php') >= 0) { - url = this.src.split('import.php')[1]; - } - }); - pw.$(fid).one('load', - function (e) { - var w = e.target.contentWindow; - var h = setInterval(function () { - if (w.baidu) {// 等待加载完成,IE6下这地方总出问题 - clearInterval(h); - op.ontest(w, w.frameElement); - } - }, 20); - // 找到当前操作的iframe,然后call ontest - }).attr('src', cpath + 'frame.php' + url); - }, - - /** - * - * 判断2个数组是否相等 - * - * @static - */ - isEqualArray:function (array1, array2) { - if ('[object Array]' != Object.prototype.toString.call(array1) - || '[object Array]' != Object.prototype.toString.call(array2)) - return (array1 === array2); - else if (array1.length != array2.length) - return false; - else { - for (var i in array1) { - if (array1[i] != array2[i]) - return false; - } - return true; - } - }, - - /*************************************************************************** - * - * 通用数据模块 - * - * @static - * - **************************************************************************/ - commonData:{// 针对测试文件的路径而不是UserAction的路径 - "testdir":'../../', - datadir:(function () { - return location.href.split("/_test/")[0] + "/_test/tools/data/"; - })(), - currentPath:function () { - var params = location.search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i]; - if (p.split('=')[0] == 'case') { - var casepath = p.split('=')[1].split('.').join('/'); - return location.href.split('/_test/')[0] + '/_test/' - + casepath.substring(0, casepath.lastIndexOf('/')) - + '/'; - } - } - return ""; - } - }, - - importsrc:function (src, callback, matcher, exclude, win) { - win = win || window; - var doc = win.document; - - var srcpath = location.href.split("/_test/")[0] - + "/_test/tools/br/import.php"; - var param0 = src; - var ps = { - f:src - }; - if (exclude) - ps.e = exclude; - var param1 = exclude || ""; - /** - * IE下重复载入会出现无法执行情况 - */ - if (win.execScript) { - $.get(srcpath, ps, function (data) { - win.execScript(data); - }); - } else { - var head = doc.getElementsByTagName('head')[0]; - var sc = doc.createElement('script'); - sc.type = 'text/javascript'; - sc.src = srcpath + "?f=" + param0 + "&e=" + param1; - head.appendChild(sc); - } - - matcher = matcher || src; - var mm = matcher.split(",")[0].split("."); - var h = setInterval(function () { - var p = win; - for (var i = 0; i < mm.length; i++) { - if (typeof (p[mm[i]]) == 'undefined') { - // console.log(mm[i]); - return; - } - p = p[mm[i]]; - } - clearInterval(h); - if (callback && 'function' == typeof callback) - callback(); - }, 20); - }, - - /* 用于加载css文件,如果没有加载完毕则不执行回调函数 */ - loadcss:function (url, callback, classname, style, value) { - var links = document.getElementsByTagName('link'); - for (var link in links) { - if (link.href == url) { - callback(); - return; - } - } - var head = document.getElementsByTagName('head')[0]; - var link = head.appendChild(document.createElement('link')); - link.setAttribute("rel", "stylesheet"); - link.setAttribute("type", "text/css"); - link.setAttribute("href", url); - var div = document.body.appendChild(document.createElement("div")); - $(document).ready( - function () { - div.className = classname || 'cssloaded'; - var h = setInterval(function () { - if ($(div).css(style || 'width') == value - || $(div).css(style || 'width') == '20px') { - clearInterval(h); - document.body.removeChild(div); - setTimeout(callback, 20); - } - }, 20); - }); - }, - - /** - * options supported - */ - delayhelper:function (oncheck, onsuccess, onfail, timeout) { - onsuccess = onsuccess || oncheck.onsuccess; - onfail = onfail || oncheck.onfail || function () { - window.QUnit.fail('timeout wait for timeout : ' + timeout + 'ms'); - start(); - }; - timeout = timeout || oncheck.timeout || 10000; - - oncheck = (typeof oncheck == 'function') ? oncheck : oncheck.oncheck; - var h1 = setInterval(function () { - if (!oncheck()) - return; - else { - clearInterval(h1); - clearTimeout(h2); - typeof onsuccess == "function" && onsuccess(); - } - }, 20); - var h2 = setTimeout(function () { - clearInterval(h1); - clearTimeout(h2); - onfail(); - }, timeout); - }, - - browser:(function () { - var win = window; - var numberify = function (s) { - var c = 0; - return parseFloat(s.replace(/\./g, function () { - return (c++ == 1) ? '' : '.'; - })); - }, - - nav = win && win.navigator, - - o = { - - /** - * Internet Explorer version number or 0. Example: 6 - * - * @property ie - * @type float - * @static - */ - ie:0, - - /** - * Opera version number or 0. Example: 9.2 - * - * @property opera - * @type float - * @static - */ - opera:0, - - /** - * Gecko engine revision number. Will evaluate to 1 if Gecko is - * detected but the revision could not be found. Other browsers will - * be 0. Example: 1.8 - * - *
    -                 * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
    -                 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
    -                 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
    -                 * Firefox 3.0   <-- 1.9
    -                 * Firefox 3.5   <-- 1.91
    -                 * 
    - * - * @property gecko - * @type float - * @static - */ - gecko:0, - - /** - * AppleWebKit version. KHTML browsers that are not WebKit browsers - * will evaluate to 1, other browsers 0. Example: 418.9 - * - *
    -                 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
    -                 *                                   latest available for Mac OSX 10.3.
    -                 * Safari 2.0.2:         416     <-- hasOwnProperty introduced
    -                 * Safari 2.0.4:         418     <-- preventDefault fixed
    -                 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
    -                 *                                   different versions of webkit
    -                 * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
    -                 *                                   updated, but not updated
    -                 *                                   to the latest patch.
    -                 * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native SVG
    -                 *                                   and many major issues fixed).
    -                 * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic update
    -                 *                                   from 2.x via the 10.4.11 OS patch
    -                 * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
    -                 *                                   yahoo.com user agent hack removed.
    -                 * 
    - * - * http://en.wikipedia.org/wiki/Safari_version_history - * - * @property webkit - * @type float - * @static - */ - webkit:0, - - /** - * Chrome will be detected as webkit, but this property will also be - * populated with the Chrome version number - * - * @property chrome - * @type float - * @static - */ - chrome:0, - - safari:0, - - firefox:0, - - maxthon:0, - maxthonIE:0, - - /** - * The mobile property will be set to a string containing any - * relevant user agent information when a modern mobile browser is - * detected. Currently limited to Safari on the iPhone/iPod Touch, - * Nokia N-series devices with the WebKit-based browser, and Opera - * Mini. - * - * @property mobile - * @type string - * @static - */ - mobile:null, - - /** - * Adobe AIR version number or 0. Only populated if webkit is - * detected. Example: 1.0 - * - * @property air - * @type float - */ - air:0, - - /** - * Google Caja version number or 0. - * - * @property caja - * @type float - */ - caja:nav && nav.cajaVersion, - - /** - * Set to true if the pagebreak appears to be in SSL - * - * @property secure - * @type boolean - * @static - */ - secure:false, - - /** - * The operating system. Currently only detecting windows or - * macintosh - * - * @property os - * @type string - * @static - */ - os:null - - }, - - ua = nav && nav.userAgent, - - loc = win && win.location, - - href = loc && loc.href, - - m; - - o.secure = href && (href.toLowerCase().indexOf("https") === 0); - - if (ua) { - - if ((/windows|win32/i).test(ua)) { - o.os = 'windows'; - } else if ((/macintosh/i).test(ua)) { - o.os = 'macintosh'; - } else if ((/rhino/i).test(ua)) { - o.os = 'rhino'; - } - - // Modern KHTML browsers should qualify as Safari X-Grade - if ((/KHTML/).test(ua)) { - o.webkit = 1; - } - if (window.external && /(\d+\.\d)/.test(external.max_version)) { - - o.maxthon = parseFloat(RegExp['\x241']); - if (/MSIE/.test(ua)) { - o.maxthonIE = 1; - o.maxthon = 0; - } - - } - // Modern WebKit browsers are at least X-Grade - m = ua.match(/AppleWebKit\/([^\s]*)/); - if (m && m[1]) { - o.webkit = numberify(m[1]); - - // Mobile browser check - if (/ Mobile\//.test(ua)) { - o.mobile = "Apple"; // iPhone or iPod Touch - } else { - m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/); - if (m) { - o.mobile = m[0]; // Nokia N-series, Android, webOS, - // ex: - // NokiaN95 - } - } - - var m1 = ua.match(/Safari\/([^\s]*)/); - if (m1 && m1[1]) // Safari - o.safari = numberify(m1[1]); - m = ua.match(/Chrome\/([^\s]*)/); - if (o.safari && m && m[1]) { - o.chrome = numberify(m[1]); // Chrome - } else { - m = ua.match(/AdobeAIR\/([^\s]*)/); - if (m) { - o.air = m[0]; // Adobe AIR 1.0 or better - } - } - } - - if (!o.webkit) { // not webkit - // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; - // fi; U; - // try get firefox and it's ver - // ssr) - m = ua.match(/Opera[\s\/]([^\s]*)/); - if (m && m[1]) { - m = ua.match(/Version[\s\/]([^\s]*)/); - o.opera = numberify(m[1]); - m = ua.match(/Opera Mini[^;]*/); - if (m) { - o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 - } - } else { // not opera or webkit - m = ua.match(/MSIE\s([^;]*)/); - if (m && m[1]) { - o.ie = numberify(m[1]); - }else if (ua.match(/Gecko([^\s]*)/)&&ua.match(/rv:11/)){//todo - o.ie = 11; - } else { // not opera, webkit, or ie - m = ua.match(/Gecko\/([^\s]*)/); - if (m) { - o.gecko = 1; // Gecko detected, look for revision - m = ua.match(/rv:([^\s\)]*)/); - if (m && m[1]) { - o.gecko = numberify(m[1]); - } - } - } - } - } - } - - return o; - }) - (), - - /** - * 提供队列方式执行用例的方案,接口包括start、add、next,方法全部执行完毕时会启动用例继续执行 - */ - functionListHelper:function () { - var check = { - list:[], - start:function () { - var self = this; - $(this).bind('next', function () { - setTimeout(function () {// 避免太深的堆栈 - if (self.list.length == 0) - start(); - else - self.list.shift()(); - }, 0); - }); - self.next(); - }, - add:function (func) { - this.list.push(func); - }, - next:function (delay) { - var self = this; - if (delay) { - setTimeout(function () { - $(self).trigger('next'); - }, delay); - } else - $(this).trigger('next'); - } - }; - return check; - }, - getHTML:function (co) { - var div = document.createElement('div'), h; - if (!co) - return 'null'; - div.appendChild(co.cloneNode(true)); - h = div.innerHTML.toLowerCase(); - - h = h.replace(/[\r\n\t\u200b\ufeff]/g, ''); // Remove line feeds and tabs - h = h.replace(/ (\w+)=([^\"][^\s>]*)/gi, ' $1="$2"'); // Restore - // attribs on IE - return h; - }, - getChildHTML:function (co) { - - var h = co.innerHTML.toLowerCase(); - - h = h.replace(/[\r\n\t\u200b\ufeff]/g, ''); // Remove line feeds and tabs - h = h.replace(/ (\w+)=([^\"][^\s>]*)/gi, ' $1="$2"'); // Restore attribs on IE - - return h.replace(/\u200B/g, ''); - }, - getIndex:function (node) { - var childNodes = node.parentNode.childNodes, i = 0; - while (childNodes[i] !== node) - i++; - return i; - }, - checkResult:function (range, sc, ec, so, eo, collapsed, descript) { - descript = descript ? descript : ''; - equal(range.collapsed, collapsed, "check collapsed --" + descript); - ok(range.startContainer === sc, "check startContainer--" + descript); - ok(range.endContainer === ec, "check endContainer--" + descript); - equal(range.startOffset, so, "check startOffset--" + descript); - equal(range.endOffset, eo, "check endOffset--" + descript); - }, - isSameRange:function (rangeA, rangeB, descript) { - descript = descript ? descript : ''; - equal(rangeA.collapsed, rangeB.collapsed, "check collapsed --" + descript); - ok(rangeA.document === rangeB.document, "check document--" + descript); - ok(rangeA.startContainer === rangeB.startContainer, "check startContainer--" + descript); - ok(rangeA.endContainer === rangeB.endContainer, "check endContainer--" + descript); - equal(rangeA.startOffset, rangeB.startOffset, "check startOffset--" + descript); - equal(rangeA.endOffset, rangeB.endOffset, "check endOffset--" + descript); - }, - manualDeleteFillData:function (node) { - var childs = node.childNodes; - for (var i = 0; i < childs.length; i++) { - var fillData = childs[i]; - if ((fillData.nodeType == 3) && ( fillData.data == domUtils.fillChar )) { - domUtils.remove(fillData); - fillData = null; - - } - else - this.manualDeleteFillData(fillData); - } - - - }, - cssStyleToDomStyle:function (cssName) { - var test = document.createElement('div').style, - cssFloat = test.cssFloat != undefined ? 'cssFloat' - : test.styleFloat != undefined ? 'styleFloat' - : 'float', - cache = { 'float':cssFloat }; - - function replacer(match) { - return match.charAt(1).toUpperCase(); - } - -// return function( cssName ) { - return cache[cssName] || (cache[cssName] = cssName.replace(/-./g, replacer) ); -// }; - }, - isSameStyle:function (elementA, elementB) { -// var styleA = elementA.style.cssText, -// styleB = elementB.style.cssText; -// if ( this.browser.ie && this.browser.version == 6 ) { -// styleA = styleA.toLowerCase(); -// styleB = styleB.toLowerCase(); -// } -// if ( !styleA && !styleB ) { -// return true; -// } else if ( !styleA || !styleB ) { -// return false; -// } -// var styleNameMap = {}, -// record = [], -// exit = {}; -// styleA.replace( /[\w-]+\s*(?=:)/g, function ( name ) { -// styleNameMap[name] = record.push( name ); -// } ); -// try { -// styleB.replace( /[\w-]+\s*(?=:)/g, function ( name ) { -// var index = styleNameMap[name]; -// if ( index ) { -//// name = this.cssStyleToDomStyle( name ); -// if ( elementA.style[name] !== elementB.style[name] ) { -// throw exit; -// } -// record[index - 1] = ''; -// } else { -// throw exit; -// } -// } ); -// } catch ( ex ) { -// if ( ex === exit ) { -// return false; -// } -// } -// return !record.join( '' ); - function indexOf(array, item, at) { - for (var i = at || 0, l = array.length; i < l; i++) { - if (array[i] === item) { - return i; - } - } - return -1; - } - - var styleA = elementA.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'), - styleB = elementB.style.cssText.replace(/( ?; ?)/g, ';').replace(/( ?: ?)/g, ':'); - if (browser.opera) { - styleA = elementA.style; - styleB = elementB.style; - if (styleA.length != styleB.length) - return 0; - for (var p in styleA) { - if (/^(\d+|csstext)$/i.test(p)) - continue; - if (styleA[p] != styleB[p]) - return 0; - } - return 1; - } - - - if (!styleA || !styleB) { - return styleA == styleB ? 1 : 0; - } - styleA = styleA.split(';'); - styleB = styleB.split(';'); - - if (styleA.length != styleB.length) - return 0; - for (var j = 0; j < styleB.length; j++) { - if (styleB[j].toLowerCase().indexOf("color") > -1 && styleB[j].toLowerCase().indexOf("rgb") > -1) { - var color = this.formatColor(styleB[j].substr(styleB[j].indexOf("rgb"), styleB[j].length)); - styleB[j] = styleB[j].replace(styleB[j].substr(styleB[j].indexOf("rgb"), styleB[j].length), color); - } - } - for (var i = 0, ci; ci = styleA[i++];) { - if (ci.toLowerCase().indexOf("color") > -1 && ci.toLowerCase().indexOf("rgb") > -1) { - var color = this.formatColor(ci.substr(ci.indexOf("rgb"), ci.length)); - ci = ci.replace(ci.substr(ci.indexOf("rgb"), ci.length), color); - } - if (indexOf(styleB, ci) == -1) { - - return 0; - - }//styleA[0].substr(styleA[0].indexOf("rga"),styleA[0].length) - } - return 1; - }, - - - formatColor:function (color) { - var reg1 = /^\#[\da-f]{6}$/i, - reg2 = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/, - keyword = { - black:'#000000', - silver:'#c0c0c0', - gray:'#808080', - white:'#ffffff', - maroon:'#800000', - red:'#ff0000', - purple:'#800080', - fuchsia:'#ff00ff', - green:'#008000', - lime:'#00ff00', - olive:'#808000', - yellow:'#ffff0', - navy:'#000080', - blue:'#0000ff', - teal:'#008080', - aqua:'#00ffff' - }; - if (reg1.test(color)) { - // #RRGGBB 直接返回 - return color; - } else if (reg2.test(color)) { - // 非IE中的 rgb(0, 0, 0) - for (var s, i = 1, color = "#"; i < 4; i++) { - s = parseInt(RegExp["\x24" + i]).toString(16); - color += ("00" + s).substr(s.length); - } - return color; - } else if (/^\#[\da-f]{3}$/.test(color)) { - // 简写的颜色值: #F00 - var s1 = color.charAt(1), - s2 = color.charAt(2), - s3 = color.charAt(3); - return "#" + s1 + s1 + s2 + s2 + s3 + s3; - } else if (keyword[color]) - return keyword[color]; - - return ""; - - }, - hasSameAttrs:function (nodeA, nodeB) { - if (nodeA.tagName != nodeB.tagName) - return 0; - var thisAttribs = nodeA.attributes, - otherAttribs = nodeB.attributes; - if (thisAttribs.length != otherAttribs.length) - return 0; - if (thisAttribs.length == 0) - return 1; - var attrA, attrB; - for (var i = 0; attrA = thisAttribs[i++];) { - if (attrA.nodeName == 'style') { - if (this.isSameStyle(nodeA, nodeB)) { - continue - } else { - return 0; - } - } - if (!ua.browser.ie || attrA.specified) { - attrB = nodeB.attributes[attrA.nodeName]; - if (!attrB) { - return 0; - } - } - return 1; - } - return 1; - }, - /** - *清除空Text节点 - */ - - clearWhiteNode:function (node) { - for (var i = 0; i < node.childNodes.length; i++) { - var tmpNode = node.childNodes[i]; - if (tmpNode.nodeType == 3 && !tmpNode.length) { - tmpNode.parentNode.removeChild(tmpNode); - i--; - } - } - }, - /** - *检查两个节点(包含所有子节点)是否具有相同的属性 - */ - flag:true, - checkAllChildAttribs:function (nodeA, nodeB) { - var k = nodeA.childNodes.length; - if (k != nodeB.childNodes.length) { - if (ua.browser.opera) { - this.clearWhiteNode(nodeA); - k = nodeA.childNodes.length; - if (k != nodeB.childNodes.length) - this.flag = false; - } - else - this.flag = false; - } - if (!this.flag) - return this.flag; - while (k) { - var tmpNodeA = nodeA.childNodes[k - 1]; - var tmpNodeB = nodeB.childNodes[k - 1]; - k--; - - if (tmpNodeA.nodeType == 3 || tmpNodeB.nodeType == 3 || tmpNodeA.nodeType == 8 || tmpNodeB.nodeType == 8) - continue; - if (!this.hasSameAttrs(tmpNodeA, tmpNodeB)) { - this.flag = false; - break; - - } - - this.checkAllChildAttribs(tmpNodeA, tmpNodeB); - } - return this.flag; - }, - haveSameAllChildAttribs:function (nodeA, nodeB) { - this.flag = true; - return this.checkAllChildAttribs(nodeA, nodeB); - }, - /*查看传入的html是否与传入的元素ele具有相同的style*/ - checkHTMLSameStyle:function (html, doc, ele, descript) { - var tagEle = doc.createElement(ele.tagName); - tagEle.innerHTML = html; - /*会有一些不可见字符,在比较前提前删掉*/ - this.manualDeleteFillData(ele); - ok(this.haveSameAllChildAttribs(ele, tagEle), descript); -// ok(this.equalsNode(ele.innerHMTL,html),descript); - }, - - - equalsNode:function (na, nb) { - function compare(nodeA, nodeB) { - if (nodeA.nodeType != nodeB.nodeType) { - return 0; - } - if (nodeA.nodeType == 3) { - return nodeA.nodeValue == nodeB.nodeValue - } - if (domUtils.isSameElement(nodeA, nodeB)) { - if (!nodeA.firstChild && !nodeB.firstChild) { - return 1; - } - if (nodeA.firstChild && !nodeB.firstChild || !nodeA.firstChild && nodeB.firstChild) { - return 0 - } - for (var i = 0, ai, bi; ai = nodeA.childNodes[i], bi = nodeB.childNodes[i++];) { - - if (!compare(ai, bi)) { - return 0 - } - } - return 1; - } else { - return 0; - } - } - - return compare(domUtils.createElement(document, 'div', { - 'innerHTML':na - }), domUtils.createElement(document, 'div', { - 'innerHTML':nb - })); - }, - - - getSelectedText:function () { - if (window.getSelection) { - // This technique is the most likely to be standardized. - // getSelection() returns a Selection object, which we do not document. - return window.getSelection().toString(); - } - else if (document.getSelection) { - // This is an older, simpler technique that returns a string - return document.getSelection(); - } - else if (document.selection) { - // This is the IE-specific technique. - // We do not document the IE selection property or TextRange objects. - return document.selection.createRange().text; - } - }, - findPosition:function (oElement) { - var x2 = 0; - var y2 = 0; - var width = oElement.offsetWidth; - var height = oElement.offsetHeight; - if (typeof( oElement.offsetParent ) != 'undefined') { - for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) { - posX += oElement.offsetLeft; - posY += oElement.offsetTop; - } - x2 = posX + width; - y2 = posY + height; - return [ posX, posY , x2, y2]; - - } else { - x2 = oElement.x + width; - y2 = oElement.y + height; - return [ oElement.x, oElement.y, x2, y2]; - } - }, - - checkElementPath:function (arr1, arr2, descript) { - if (!descript) - descript = ''; - var index = arr1.length; - if (index != arr2.length) - ok(false, '路径深度不相同'); - else { - - while (index > 0) - equal(arr1[--index ], arr2[index ], descript + '---第' + index + '个元素' + arr1[index]); - } - }, - getBrowser:function () { - var browser = ""; - if (this.browser.ie == 6) - browser = 'ie6'; - if (this.browser.ie == 7) - browser = 'ie7'; - if (this.browser.ie == 8) - browser = 'ie8'; - if (this.browser.ie == 9) - browser = 'ie9'; - if (this.browser.safari) - browser = 'safari'; - if (this.browser.firefox) - browser = 'firefox'; - if (this.browser.chrome) - browser = 'chrome'; - if (this.browser.maxthon) { - browser = 'maxthon'; - } - if (this.browser.maxthonIE) - browser = 'maxIE'; - if (this.browser.opera) - browser = 'opera'; - return browser; - }, - getFloatStyle:function (ele) { - if (this.browser.ie) - return ele.style['styleFloat']; - else - return ele.style['cssFloat']; - }, - - readTxt:function (name, f) { - var args = {}; - args['name'] = './txt/' + name; - $.ajax({ - url:'read.php', - type:'post', - data:args, - success:function (msg) { - f(msg); - }, - error:function (xhr, msg) { - f(null); - } - }); - }, checkLowerCase:function (stringA, stringB) { - if (!(stringA || stringB)) - return true; - else if (!stringA || !stringB) - return false; - else { - return stringA.toLowerCase() == stringB.toLowerCase(); - } - }, removeEndSemicolon:function (styleValue) { - if (styleValue.length - 1 == styleValue.lastIndexOf(';')) - styleValue = styleValue.substring(0, styleValue.length - 1); - return styleValue; - }, checkNodeStyle:function (nodeA, nodeB) { - var nodeAStyle = this.removeEndSemicolon(nodeA.getAttr("style").replace(/\s+/g, "")).replace(/"/g,'').split(";"); - var nodeBStyle = this.removeEndSemicolon(nodeB.getAttr("style").replace(/\s+/g, "")).replace(/"/g,'').split(";"); - var lengthA = nodeAStyle.length; - var lengthB = nodeBStyle.length; - if (!(lengthA && lengthB)) - return true; - else if (lengthA != lengthB) - return false; - else { - for (var i = 0; i < lengthA; i++) { - if (nodeAStyle[i].match(/\w+\s*:/)) { - var styleName = nodeAStyle[i].match(/\w+\s*:/)[0].replace(/\s*:/, ""); - nodeA.attrs.style = nodeA.attrs.style.replace(/"/g,''); - nodeB.attrs.style = nodeB.attrs.style.replace(/"/g,''); - if (nodeA.getStyle(styleName).toLowerCase().replace(/\s+/g, "") != nodeB.getStyle(styleName).toLowerCase().replace(/\s+/g, "")) - return false; - } - } - } - return true; - }, getPropertyCount:function (o) { - var n, count = 0; - for (n in o) { - if (o.hasOwnProperty(n)) { - count++; - } - } - return count; - },formHref:function(str){ - if(str.lastIndexOf('/')== str.length-1){ - str = str.substring(0,str.length-1); - } - return str; - },checkSameNodeAttrs:function (nodeA, nodeB) { - var lengthA = this.getPropertyCount(nodeA.attrs); - var lengthB = this.getPropertyCount(nodeB.attrs); - if (!(lengthA && lengthB)) - return true; - else if (lengthA != lengthB) - return false; - else { - for (var p in nodeA.attrs) { - if(!nodeB.getAttr(p)&&!nodeA.getAttr(p)) - return true; - else if (!nodeB.getAttr(p)||!nodeA.getAttr(p)) - return false; - else if (p.toLowerCase() == "style") { - if (!this.checkNodeStyle(nodeA, nodeB)) - return false; - } - else if(p.toLowerCase() == "href"){ - if (this.formHref(nodeA.getAttr(p).toLowerCase()) != this.formHref(nodeB.getAttr(p).toLowerCase())) - return false; - } - else { - if (nodeA.getAttr(p).toLowerCase() != nodeB.getAttr(p).toLowerCase()) - return false; - } - } - } - return true; - - }, checkChildren:function (nodeA, nodeB) { - if (!(nodeA.children || nodeB.children)) - return true; - else if (!(nodeA.children && nodeB.children)) - return false; - else if (nodeA.children.length != nodeB.children.length) - return false; - else { - var lengthA = nodeA.children.length; - for (var i = 0; i < lengthA; i++) { - if (!this.checkSameNode(nodeA.children[i], nodeB.children[i])) - return false; - } - } - return true; - }, checkSameNode:function (nodeA, nodeB) { - if (!this.checkSameNodeAttrs(nodeA, nodeB)) - return false; - else if (!this.checkChildren(nodeA, nodeB)) - return false; - else if (nodeA.data != nodeB.data) - return false; - else if (!this.checkLowerCase(nodeA.tagName, nodeB.tagName)) - return false; - else if (!this.checkLowerCase(nodeA.type, nodeB.type)) - return false; - else - return true; - }, checkSameHtml:function (stringA, stringB, scholium) { - ok(this.checkSameNode(UM.htmlparser(stringA), UM.htmlparser(stringB)), scholium); - } -}; -var ua = UserAction; -var upath = ua.commonData.currentPath(); -var cpath = ua.commonData.datadir; \ No newline at end of file diff --git a/_test/tools/br/js/ext_qunit.js b/_test/tools/br/js/ext_qunit.js deleted file mode 100644 index 3e83821a..00000000 --- a/_test/tools/br/js/ext_qunit.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 重载QUnit部分接口实现批量执行控制功能 - */ -(function() { - if (!QUnit) - return; - var ms = QUnit.moduleStart, d = QUnit.done; - - function _d(args /* failures, total */) { - //默认展开失败用例 - $('li.fail ol').toggle(); - if (parent && parent.brtest) { - parent.$(parent.brtest).trigger('done', [ new Date().getTime(), { - failed : args[0], - passed : args[1], - detail:args[2] - }, window._$jscoverage || null ]); - } - } - QUnit.moduleStart = function() { - stop(); - /* 为批量执行等待import.php正确返回 */ - var h = setInterval(function() { - if (window && window['UM']) { - clearInterval(h); - ms.apply(this, arguments); - start(); - } - }, 20); - }; - QUnit.done = function() { - _d(arguments); - d.apply(this, arguments); - }; -})(); diff --git a/_test/tools/br/js/jquery-1.5.1.js b/_test/tools/br/js/jquery-1.5.1.js deleted file mode 100644 index fa52d75b..00000000 --- a/_test/tools/br/js/jquery-1.5.1.js +++ /dev/null @@ -1,8316 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Check for digits - rdigit = /\d/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // Has the ready events already been bound? - readyBound = false, - - // The deferred used on DOM ready - readyList, - - // Promise methods - promiseMethods = "then done fail isResolved isRejected promise".split( " " ), - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = "body"; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return (context || rootjQuery).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.5.1", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + (this.selector ? " " : "") + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.done( fn ); - - return this; - }, - - eq: function( i ) { - return i === -1 ? - this.slice( i ) : - this.slice( i, +i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - // A third-party is pushing the ready event forwards - if ( wait === true ) { - jQuery.readyWait--; - } - - // Make sure that the DOM is not already loaded - if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).unbind( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyBound ) { - return; - } - - readyBound = true; - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent("onreadystatechange", DOMContentLoaded); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNaN: function( obj ) { - return obj == null || !rdigit.test( obj ) || isNaN( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw msg; - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test(data.replace(rvalidescape, "@") - .replace(rvalidtokens, "]") - .replace(rvalidbraces, "")) ) { - - // Try to use the native JSON parser first - return window.JSON && window.JSON.parse ? - window.JSON.parse( data ) : - (new Function("return " + data))(); - - } else { - jQuery.error( "Invalid JSON: " + data ); - } - }, - - // Cross-browser xml parsing - // (xml & tmp used internally) - parseXML: function( data , xml , tmp ) { - - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - - tmp = xml.documentElement; - - if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { - jQuery.error( "Invalid XML: " + data ); - } - - return xml; - }, - - noop: function() {}, - - // Evalulates a script in a global context - globalEval: function( data ) { - if ( data && rnotwhite.test(data) ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, - script = document.createElement( "script" ); - - if ( jQuery.support.scriptEval() ) { - script.appendChild( document.createTextNode( data ) ); - } else { - script.text = data; - } - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction(object); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type(array); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var ret = [], value; - - // Go through the array, translating each of the items to their - // new value (or values). - for ( var i = 0, length = elems.length; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - proxy: function( fn, proxy, thisObject ) { - if ( arguments.length === 2 ) { - if ( typeof proxy === "string" ) { - thisObject = fn; - fn = thisObject[ proxy ]; - proxy = undefined; - - } else if ( proxy && !jQuery.isFunction( proxy ) ) { - thisObject = proxy; - proxy = undefined; - } - } - - if ( !proxy && fn ) { - proxy = function() { - return fn.apply( thisObject || this, arguments ); - }; - } - - // Set the guid of unique handler to the same of original handler, so it can be removed - if ( fn ) { - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - } - - // So proxy can be declared as an argument - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can be optionally by executed if its a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return (new Date()).getTime(); - }, - - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - // We have to add a catch block for - // IE prior to 8 or else the finally - // block will never get executed - catch (e) { - throw e; - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - var i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; - } - return obj; - } - } ); - // Make sure only one callback list will be used - deferred.done( failDeferred.cancel ).fail( deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( object ) { - var lastIndex = arguments.length, - deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? - object : - jQuery.Deferred(), - promise = deferred.promise(); - - if ( lastIndex > 1 ) { - var array = slice.call( arguments, 0 ), - count = lastIndex, - iCallback = function( index ) { - return function( value ) { - array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( promise, array ); - } - }; - }; - while( ( lastIndex-- ) ) { - object = array[ lastIndex ]; - if ( object && jQuery.isFunction( object.promise ) ) { - object.promise().then( iCallback(lastIndex), deferred.reject ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( promise, array ); - } - } else if ( deferred !== object ) { - deferred.resolve( object ); - } - return promise; - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySubclass( selector, context ) { - return new jQuerySubclass.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySubclass, this ); - jQuerySubclass.superclass = this; - jQuerySubclass.fn = jQuerySubclass.prototype = this(); - jQuerySubclass.fn.constructor = jQuerySubclass; - jQuerySubclass.subclass = this.subclass; - jQuerySubclass.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { - context = jQuerySubclass(context); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); - }; - jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; - var rootjQuerySubclass = jQuerySubclass(document); - return jQuerySubclass; - }, - - browser: {} -}); - -// Create readyList deferred -readyList = jQuery._Deferred(); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -if ( indexOf ) { - jQuery.inArray = function( elem, array ) { - return indexOf.call( array, elem ); - }; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -// Expose jQuery to the global object -return jQuery; - -})(); - - -(function() { - - jQuery.support = {}; - - var div = document.createElement("div"); - - div.style.display = "none"; - div.innerHTML = "
    a"; - - var all = div.getElementsByTagName("*"), - a = div.getElementsByTagName("a")[0], - select = document.createElement("select"), - opt = select.appendChild( document.createElement("option") ), - input = div.getElementsByTagName("input")[0]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return; - } - - jQuery.support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: div.firstChild.nodeType === 3, - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText insted) - style: /red/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: a.getAttribute("href") === "/a", - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55$/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: input.value === "on", - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Will be defined later - deleteExpando: true, - optDisabled: false, - checkClone: false, - noCloneEvent: true, - noCloneChecked: true, - boxModel: null, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableHiddenOffsets: true - }; - - input.checked = true; - jQuery.support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as diabled) - select.disabled = true; - jQuery.support.optDisabled = !opt.disabled; - - var _scriptEval = null; - jQuery.support.scriptEval = function() { - if ( _scriptEval === null ) { - var root = document.documentElement, - script = document.createElement("script"), - id = "script" + jQuery.now(); - - try { - script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); - } catch(e) {} - - root.insertBefore( script, root.firstChild ); - - // Make sure that the execution of code works by injecting a script - // tag with appendChild/createTextNode - // (IE doesn't support this, fails, and uses .text instead) - if ( window[ id ] ) { - _scriptEval = true; - delete window[ id ]; - } else { - _scriptEval = false; - } - - root.removeChild( script ); - // release memory in IE - root = script = id = null; - } - - return _scriptEval; - }; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - - } catch(e) { - jQuery.support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent("onclick", function click() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - jQuery.support.noCloneEvent = false; - div.detachEvent("onclick", click); - }); - div.cloneNode(true).fireEvent("onclick"); - } - - div = document.createElement("div"); - div.innerHTML = ""; - - var fragment = document.createDocumentFragment(); - fragment.appendChild( div.firstChild ); - - // WebKit doesn't clone checked state correctly in fragments - jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; - - // Figure out if the W3C box model works as expected - // document.body must exist before we can do this - jQuery(function() { - var div = document.createElement("div"), - body = document.getElementsByTagName("body")[0]; - - // Frameset documents with no body should not run this code - if ( !body ) { - return; - } - - div.style.width = div.style.paddingLeft = "1px"; - body.appendChild( div ); - jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; - - if ( "zoom" in div.style ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
    "; - jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; - } - - div.innerHTML = "
    t
    "; - var tds = div.getElementsByTagName("td"); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; - - tds[0].style.display = ""; - tds[1].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE < 8 fail this test) - jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; - div.innerHTML = ""; - - body.removeChild( div ).style.display = "none"; - div = tds = null; - }); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ - var eventSupported = function( eventName ) { - var el = document.createElement("div"); - eventName = "on" + eventName; - - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( !el.attachEvent ) { - return true; - } - - var isSupported = (eventName in el); - if ( !isSupported ) { - el.setAttribute(eventName, "return;"); - isSupported = typeof el[eventName] === "function"; - } - el = null; - - return isSupported; - }; - - jQuery.support.submitBubbles = eventSupported("submit"); - jQuery.support.changeBubbles = eventSupported("change"); - - // release memory in IE - div = all = a = null; -})(); - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the pagebreak - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ jQuery.expando ] = id = ++jQuery.uuid; - } else { - id = jQuery.expando; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); - } else { - cache[ id ] = jQuery.extend(cache[ id ], name); - } - } - - thisCache = cache[ id ]; - - // Internal jQuery data is stored in a separate object inside the object's data - // cache in order to avoid key collisions between internal data and user-defined - // data - if ( pvt ) { - if ( !thisCache[ internalKey ] ) { - thisCache[ internalKey ] = {}; - } - - thisCache = thisCache[ internalKey ]; - } - - if ( data !== undefined ) { - thisCache[ name ] = data; - } - - // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should - // not attempt to inspect the internal events object using jQuery.data, as this - // internal data object is undocumented and subject to change. - if ( name === "events" && !thisCache[name] ) { - return thisCache[ internalKey ] && thisCache[ internalKey ].events; - } - - return getByName ? thisCache[ name ] : thisCache; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; - - if ( thisCache ) { - delete thisCache[ name ]; - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !isEmptyDataObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( pvt ) { - delete cache[ id ][ internalKey ]; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - var internalCache = cache[ id ][ internalKey ]; - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - if ( jQuery.support.deleteExpando || cache != window ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the entire user cache at once because it's faster than - // iterating through each key, but we need to continue to persist internal - // data if it existed - if ( internalCache ) { - cache[ id ] = {}; - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - - cache[ id ][ internalKey ] = internalCache; - - // Otherwise, we need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - } else if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ jQuery.expando ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( jQuery.expando ); - } else { - elem[ jQuery.expando ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 ) { - var attr = this[0].attributes, name; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = name.substr( 5 ); - dataAttr( this[0], name, data[ name ] ); - } - } - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var $this = jQuery( this ), - args = [ parts[0], value ]; - - $this.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - $this.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - data = elem.getAttribute( "data-" + key ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - !jQuery.isNaN( data ) ? parseFloat( data ) : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON -// property to be considered empty objects; this property always exists in -// order to make sure JSON.stringify does not expose internal metadata -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -jQuery.extend({ - queue: function( elem, type, data ) { - if ( !elem ) { - return; - } - - type = (type || "fx") + "queue"; - var q = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( !data ) { - return q || []; - } - - if ( !q || jQuery.isArray(data) ) { - q = jQuery._data( elem, type, jQuery.makeArray(data) ); - - } else { - q.push( data ); - } - - return q; - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(); - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift("inprogress"); - } - - fn.call(elem, function() { - jQuery.dequeue(elem, type); - }); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue", true ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function( i ) { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; - type = type || "fx"; - - return this.queue( type, function() { - var elem = this; - setTimeout(function() { - jQuery.dequeue( elem, type ); - }, time ); - }); - }, - - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspaces = /\s+/, - rreturn = /\r/g, - rspecialurl = /^(?:href|src|style)$/, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rradiocheck = /^(?:radio|checkbox)$/i; - -jQuery.props = { - "for": "htmlFor", - "class": "className", - readonly: "readOnly", - maxlength: "maxLength", - cellspacing: "cellSpacing", - rowspan: "rowSpan", - colspan: "colSpan", - tabindex: "tabIndex", - usemap: "useMap", - frameborder: "frameBorder" -}; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name, fn ) { - return this.each(function(){ - jQuery.attr( this, name, "" ); - if ( this.nodeType === 1 ) { - this.removeAttribute( name ); - } - }); - }, - - addClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.addClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( value && typeof value === "string" ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className ) { - elem.className = value; - - } else { - var className = " " + elem.className + " ", - setClass = elem.className; - - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { - setClass += " " + classNames[c]; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.removeClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - var className = (" " + elem.className + " ").replace(rclass, " "); - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[c] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspaces ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " "; - for ( var i = 0, l = this.length; i < l; i++ ) { - if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - if ( !arguments.length ) { - var elem = this[0]; - - if ( elem ) { - if ( jQuery.nodeName( elem, "option" ) ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - } - - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { - return elem.getAttribute("value") === null ? "on" : elem.value; - } - - // Everything else, we just grab the value - return (elem.value || "").replace(rreturn, ""); - - } - - return undefined; - } - - var isFunction = jQuery.isFunction(value); - - return this.each(function(i) { - var self = jQuery(this), val = value; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call(this, i, self.val()); - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray(val) ) { - val = jQuery.map(val, function (value) { - return value == null ? "" : value + ""; - }); - } - - if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { - this.checked = jQuery.inArray( self.val(), val ) >= 0; - - } else if ( jQuery.nodeName( this, "select" ) ) { - var values = jQuery.makeArray(val); - - jQuery( "option", this ).each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - this.selectedIndex = -1; - } - - } else { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { - return undefined; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery(elem)[name](value); - } - - var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), - // Whether we are setting (or getting) - set = value !== undefined; - - // Try to normalize/fix the name - name = notxml && jQuery.props[ name ] || name; - - // Only do all the following if this is a node (faster for style) - if ( elem.nodeType === 1 ) { - // These attributes require special treatment - var special = rspecialurl.test( name ); - - // Safari mis-reports the default selected property of an option - // Accessing the parent's selectedIndex property fixes it - if ( name === "selected" && !jQuery.support.optSelected ) { - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - - // If applicable, access the attribute via the DOM 0 way - // 'in' checks fail in Blackberry 4.7 #6931 - if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { - if ( set ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } - - if ( value === null ) { - if ( elem.nodeType === 1 ) { - elem.removeAttribute( name ); - } - - } else { - elem[ name ] = value; - } - } - - // browsers index elements by id/name on forms, give priority to attributes. - if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { - return elem.getAttributeNode( name ).nodeValue; - } - - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - if ( name === "tabIndex" ) { - var attributeNode = elem.getAttributeNode( "tabIndex" ); - - return attributeNode && attributeNode.specified ? - attributeNode.value : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - - return elem[ name ]; - } - - if ( !jQuery.support.style && notxml && name === "style" ) { - if ( set ) { - elem.style.cssText = "" + value; - } - - return elem.style.cssText; - } - - if ( set ) { - // convert the value to a string (all browsers do this but IE) see #1070 - elem.setAttribute( name, "" + value ); - } - - // Ensure that missing attributes return undefined - // Blackberry 4.7 returns "" from getAttribute #6938 - if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { - return undefined; - } - - var attr = !jQuery.support.hrefNormalized && notxml && special ? - // Some attributes require a special call on IE - elem.getAttribute( name, 2 ) : - elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return attr === null ? undefined : attr; - } - // Handle everything which isn't a DOM element node - if ( set ) { - elem[ name ] = value; - } - return elem[ name ]; - } -}); - - - - -var rnamespaces = /\.(.*)$/, - rformElems = /^(?:textarea|input|select)$/i, - rperiod = /\./g, - rspace = / /g, - rescape = /[^\w\s.|`]/g, - fcleanup = function( nm ) { - return nm.replace(rescape, "\\$&"); - }; - -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function( elem, types, handler, data ) { - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6) - // Minor release fix for bug #8018 - try { - // For whatever reason, IE has trouble passing the window object - // around, causing it to be cloned in the process - if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { - elem = window; - } - } - catch ( e ) {} - - if ( handler === false ) { - handler = returnFalse; - } else if ( !handler ) { - // Fixes bug #7229. Fix recommended by jdalton - return; - } - - var handleObjIn, handleObj; - - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure - var elemData = jQuery._data( elem ); - - // If no elemData is found then we must be trying to bind to one of the - // banned noData elements - if ( !elemData ) { - return; - } - - var events = elemData.events, - eventHandle = elemData.handle; - - if ( !events ) { - elemData.events = events = {}; - } - - if ( !eventHandle ) { - elemData.handle = eventHandle = function() { - // Handle the second event of a trigger and when - // an event is called after a pagebreak has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? - jQuery.event.handle.apply( eventHandle.elem, arguments ) : - undefined; - }; - } - - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native events in IE. - eventHandle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = types.split(" "); - - var type, i = 0, namespaces; - - while ( (type = types[ i++ ]) ) { - handleObj = handleObjIn ? - jQuery.extend({}, handleObjIn) : - { handler: handler, data: data }; - - // Namespaced event handlers - if ( type.indexOf(".") > -1 ) { - namespaces = type.split("."); - type = namespaces.shift(); - handleObj.namespace = namespaces.slice(0).sort().join("."); - - } else { - namespaces = []; - handleObj.namespace = ""; - } - - handleObj.type = type; - if ( !handleObj.guid ) { - handleObj.guid = handler.guid; - } - - // Get the current list of functions bound to this event - var handlers = events[ type ], - special = jQuery.event.special[ type ] || {}; - - // Init the event handler queue - if ( !handlers ) { - handlers = events[ type ] = []; - - // Check for a special event handler - // Only use addEventListener/attachEvent if the special - // events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add the function to the element's handler list - handlers.push( handleObj ); - - // Keep track of which events have been used, for global triggering - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, pos ) { - // don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } - - var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - events = elemData && elemData.events; - - if ( !elemData || !events ) { - return; - } - - // types is actually an event object here - if ( types && types.type ) { - handler = types.handler; - types = types.type; - } - - // Unbind all events for the element - if ( !types || typeof types === "string" && types.charAt(0) === "." ) { - types = types || ""; - - for ( type in events ) { - jQuery.event.remove( elem, type + types ); - } - - return; - } - - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(" "); - - while ( (type = types[ i++ ]) ) { - origType = type; - handleObj = null; - all = type.indexOf(".") < 0; - namespaces = []; - - if ( !all ) { - // Namespaced event handlers - namespaces = type.split("."); - type = namespaces.shift(); - - namespace = new RegExp("(^|\\.)" + - jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - eventType = events[ type ]; - - if ( !eventType ) { - continue; - } - - if ( !handler ) { - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( all || namespace.test( handleObj.namespace ) ) { - jQuery.event.remove( elem, origType, handleObj.handler, j ); - eventType.splice( j--, 1 ); - } - } - - continue; - } - - special = jQuery.event.special[ type ] || {}; - - for ( j = pos || 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( handler.guid === handleObj.guid ) { - // remove the given handler for the given type - if ( all || namespace.test( handleObj.namespace ) ) { - if ( pos == null ) { - eventType.splice( j--, 1 ); - } - - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - - if ( pos != null ) { - break; - } - } - } - - // remove generic event handler if no more handlers exist - if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - ret = null; - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - var handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - delete elemData.events; - delete elemData.handle; - - if ( jQuery.isEmptyObject( elemData ) ) { - jQuery.removeData( elem, undefined, true ); - } - } - }, - - // bubbling is internal - trigger: function( event, data, elem /*, bubbling */ ) { - // Event object or event type - var type = event.type || event, - bubbling = arguments[3]; - - if ( !bubbling ) { - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - jQuery.extend( jQuery.Event(type), event ) : - // Just the event type (string) - jQuery.Event(type); - - if ( type.indexOf("!") >= 0 ) { - event.type = type = type.slice(0, -1); - event.exclusive = true; - } - - // Handle a global trigger - if ( !elem ) { - // Don't bubble custom events when global (to avoid too much overhead) - event.stopPropagation(); - - // Only trigger if we've ever bound an event for it - if ( jQuery.event.global[ type ] ) { - // XXX This code smells terrible. event.js should not be directly - // inspecting the data cache - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - } - } - - // Handle triggering a single element - - // don't do events on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { - return undefined; - } - - // Clean up in case it is reused - event.result = undefined; - event.target = elem; - - // Clone the incoming data, if any - data = jQuery.makeArray( data ); - data.unshift( event ); - } - - event.currentTarget = elem; - - // Trigger the event, it is assumed that "handle" is a function - var handle = jQuery._data( elem, "handle" ); - - if ( handle ) { - handle.apply( elem, data ); - } - - var parent = elem.parentNode || elem.ownerDocument; - - // Trigger an inline bound script - try { - if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { - if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { - event.result = false; - event.preventDefault(); - } - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (inlineError) {} - - if ( !event.isPropagationStopped() && parent ) { - jQuery.event.trigger( event, data, parent, true ); - - } else if ( !event.isDefaultPrevented() ) { - var old, - target = event.target, - targetType = type.replace( rnamespaces, "" ), - isClick = jQuery.nodeName( target, "a" ) && targetType === "click", - special = jQuery.event.special[ targetType ] || {}; - - if ( (!special._default || special._default.call( elem, event ) === false) && - !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { - - try { - if ( target[ targetType ] ) { - // Make sure that we don't accidentally re-trigger the onFOO events - old = target[ "on" + targetType ]; - - if ( old ) { - target[ "on" + targetType ] = null; - } - - jQuery.event.triggered = true; - target[ targetType ](); - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (triggerError) {} - - if ( old ) { - target[ "on" + targetType ] = old; - } - - jQuery.event.triggered = false; - } - } - }, - - handle: function( event ) { - var all, handlers, namespaces, namespace_re, events, - namespace_sort = [], - args = jQuery.makeArray( arguments ); - - event = args[0] = jQuery.event.fix( event || window.event ); - event.currentTarget = this; - - // Namespaced event handlers - all = event.type.indexOf(".") < 0 && !event.exclusive; - - if ( !all ) { - namespaces = event.type.split("."); - event.type = namespaces.shift(); - namespace_sort = namespaces.slice(0).sort(); - namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.namespace = event.namespace || namespace_sort.join("."); - - events = jQuery._data(this, "events"); - - handlers = (events || {})[ event.type ]; - - if ( events && handlers ) { - // Clone the handlers to prevent manipulation - handlers = handlers.slice(0); - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - - // Filter the functions by class - if ( all || namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - } - - return event.result; - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ) { - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) { - // Fixes #1925 where srcElement might not be defined either - event.target = event.srcElement || document; - } - - // check if target is a textnode (safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) { - event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; - } - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var doc = document.documentElement, - body = document.body; - - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add which for key events - if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { - event.which = event.charCode != null ? event.charCode : event.keyCode; - } - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) { - event.metaKey = event.ctrlKey; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button !== undefined ) { - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - } - - return event; - }, - - // Deprecated, use jQuery.guid instead - guid: 1E8, - - // Deprecated, use jQuery.proxy instead - proxy: jQuery.proxy, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady, - teardown: jQuery.noop - }, - - live: { - add: function( handleObj ) { - jQuery.event.add( this, - liveConvert( handleObj.origType, handleObj.selector ), - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); - }, - - remove: function( handleObj ) { - jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); - } - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src ) { - // Allow instantiation without the 'new' keyword - if ( !this.preventDefault ) { - return new jQuery.Event( src ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.timeStamp = jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function( event ) { - // Check if mouse(over|out) are still within the same parent element - var parent = event.relatedTarget; - - // Firefox sometimes assigns relatedTarget a XUL element - // which we cannot access the parentNode property of - try { - - // Chrome does something similar, the parentNode property - // can be accessed but is null. - if ( parent !== document && !parent.parentNode ) { - return; - } - // Traverse up the tree - while ( parent && parent !== this ) { - parent = parent.parentNode; - } - - if ( parent !== this ) { - // set the correct event type - event.type = event.data; - - // handle event if we actually just moused on to a non sub-element - jQuery.event.handle.apply( this, arguments ); - } - - // assuming we've left the element since we most likely mousedover a xul element - } catch(e) { } -}, - -// In case of event delegation, we only need to rename the event.type, -// liveHandler will take care of the rest. -delegate = function( event ) { - event.type = event.data; - jQuery.event.handle.apply( this, arguments ); -}; - -// Create mouseenter and mouseleave events -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - setup: function( data ) { - jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); - }, - teardown: function( data ) { - jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); - } - }; -}); - -// submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function( data, namespaces ) { - if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { - jQuery.event.add(this, "click.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - trigger( "submit", this, arguments ); - } - }); - - jQuery.event.add(this, "keypress.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { - trigger( "submit", this, arguments ); - } - }); - - } else { - return false; - } - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialSubmit" ); - } - }; - -} - -// change delegation, happens here so we have bind. -if ( !jQuery.support.changeBubbles ) { - - var changeFilters, - - getVal = function( elem ) { - var type = elem.type, val = elem.value; - - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; - - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; - - } else if ( elem.nodeName.toLowerCase() === "select" ) { - val = elem.selectedIndex; - } - - return val; - }, - - testChange = function testChange( e ) { - var elem = e.target, data, val; - - if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { - return; - } - - data = jQuery._data( elem, "_change_data" ); - val = getVal(elem); - - // the current data will be also retrieved by beforeactivate - if ( e.type !== "focusout" || elem.type !== "radio" ) { - jQuery._data( elem, "_change_data", val ); - } - - if ( data === undefined || val === data ) { - return; - } - - if ( data != null || val ) { - e.type = "change"; - e.liveFired = undefined; - jQuery.event.trigger( e, arguments[1], elem ); - } - }; - - jQuery.event.special.change = { - filters: { - focusout: testChange, - - beforedeactivate: testChange, - - click: function( e ) { - var elem = e.target, type = elem.type; - - if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { - testChange.call( this, e ); - } - }, - - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = elem.type; - - if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - testChange.call( this, e ); - } - }, - - // Beforeactivate happens also before the previous element is blurred - // with this event you can't trigger a change event, but you can store - // information - beforeactivate: function( e ) { - var elem = e.target; - jQuery._data( elem, "_change_data", getVal(elem) ); - } - }, - - setup: function( data, namespaces ) { - if ( this.type === "file" ) { - return false; - } - - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); - } - - return rformElems.test( this.nodeName ); - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialChange" ); - - return rformElems.test( this.nodeName ); - } - }; - - changeFilters = jQuery.event.special.change.filters; - - // Handle when the input is .focus()'d - changeFilters.focus = changeFilters.beforeactivate; -} - -function trigger( type, elem, args ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - // Don't pass args or remember liveFired; they apply to the donor event. - var event = jQuery.extend( {}, args[ 0 ] ); - event.type = type; - event.originalEvent = {}; - event.liveFired = undefined; - jQuery.event.handle.call( elem, event ); - if ( event.isDefaultPrevented() ) { - args[ 0 ].preventDefault(); - } -} - -// Create "bubbling" focus and blur events -if ( document.addEventListener ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - jQuery.event.special[ fix ] = { - setup: function() { - this.addEventListener( orig, handler, true ); - }, - teardown: function() { - this.removeEventListener( orig, handler, true ); - } - }; - - function handler( e ) { - e = jQuery.event.fix( e ); - e.type = fix; - return jQuery.event.handle.call( this, e ); - } - }); -} - -jQuery.each(["bind", "one"], function( i, name ) { - jQuery.fn[ name ] = function( type, data, fn ) { - // Handle object literals - if ( typeof type === "object" ) { - for ( var key in type ) { - this[ name ](key, data, type[key], fn); - } - return this; - } - - if ( jQuery.isFunction( data ) || data === false ) { - fn = data; - data = undefined; - } - - var handler = name === "one" ? jQuery.proxy( fn, function( event ) { - jQuery( this ).unbind( event, handler ); - return fn.apply( this, arguments ); - }) : fn; - - if ( type === "unload" && name !== "one" ) { - this.one( type, data, fn ); - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.add( this[i], type, handler, data ); - } - } - - return this; - }; -}); - -jQuery.fn.extend({ - unbind: function( type, fn ) { - // Handle object literals - if ( typeof type === "object" && !type.preventDefault ) { - for ( var key in type ) { - this.unbind(key, type[key]); - } - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.remove( this[i], type, fn ); - } - } - - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.live( types, data, fn, selector ); - }, - - undelegate: function( selector, types, fn ) { - if ( arguments.length === 0 ) { - return this.unbind( "live" ); - - } else { - return this.die( types, null, fn, selector ); - } - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - - triggerHandler: function( type, data ) { - if ( this[0] ) { - var event = jQuery.Event( type ); - event.preventDefault(); - event.stopPropagation(); - jQuery.event.trigger( event, data, this[0] ); - return event.result; - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - i = 1; - - // link all the functions, so any of them can unbind this click handler - while ( i < args.length ) { - jQuery.proxy( fn, args[ i++ ] ); - } - - return this.click( jQuery.proxy( fn, function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - })); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -var liveMap = { - focus: "focusin", - blur: "focusout", - mouseenter: "mouseover", - mouseleave: "mouseout" -}; - -jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { - var type, i = 0, match, namespaces, preType, - selector = origSelector || this.selector, - context = origSelector ? this : jQuery( this.context ); - - if ( typeof types === "object" && !types.preventDefault ) { - for ( var key in types ) { - context[ name ]( key, data, types[key], selector ); - } - - return this; - } - - if ( jQuery.isFunction( data ) ) { - fn = data; - data = undefined; - } - - types = (types || "").split(" "); - - while ( (type = types[ i++ ]) != null ) { - match = rnamespaces.exec( type ); - namespaces = ""; - - if ( match ) { - namespaces = match[0]; - type = type.replace( rnamespaces, "" ); - } - - if ( type === "hover" ) { - types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); - continue; - } - - preType = type; - - if ( type === "focus" || type === "blur" ) { - types.push( liveMap[ type ] + namespaces ); - type = type + namespaces; - - } else { - type = (liveMap[ type ] || type) + namespaces; - } - - if ( name === "live" ) { - // bind live handler - for ( var j = 0, l = context.length; j < l; j++ ) { - jQuery.event.add( context[j], "live." + liveConvert( type, selector ), - { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); - } - - } else { - // unbind live handler - context.unbind( "live." + liveConvert( type, selector ), fn ); - } - } - - return this; - }; -}); - -function liveHandler( event ) { - var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, - elems = [], - selectors = [], - events = jQuery._data( this, "events" ); - - // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) - if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { - return; - } - - if ( event.namespace ) { - namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.liveFired = this; - - var live = events.live.slice(0); - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { - selectors.push( handleObj.selector ); - - } else { - live.splice( j--, 1 ); - } - } - - match = jQuery( event.target ).closest( selectors, event.currentTarget ); - - for ( i = 0, l = match.length; i < l; i++ ) { - close = match[i]; - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { - elem = close.elem; - related = null; - - // Those two events require additional checking - if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { - event.type = handleObj.preType; - related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; - } - - if ( !related || related !== elem ) { - elems.push({ elem: elem, handleObj: handleObj, level: close.level }); - } - } - } - } - - for ( i = 0, l = elems.length; i < l; i++ ) { - match = elems[i]; - - if ( maxLevel && match.level > maxLevel ) { - break; - } - - event.currentTarget = match.elem; - event.data = match.handleObj.data; - event.handleObj = match.handleObj; - - ret = match.handleObj.origHandler.apply( match.elem, arguments ); - - if ( ret === false || event.isPropagationStopped() ) { - maxLevel = match.level; - - if ( ret === false ) { - stop = false; - } - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - return stop; -} - -function liveConvert( type, selector ) { - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); -} - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.bind( name, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } -}); - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var match, - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - var found, item, - filter = Expr.filter[ type ], - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw "Syntax error, unrecognized expression: " + msg; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return "text" === elem.getAttribute( 'type' ); - }, - radio: function( elem ) { - return "radio" === elem.type; - }, - - checkbox: function( elem ) { - return "checkbox" === elem.type; - }, - - file: function( elem ) { - return "file" === elem.type; - }, - password: function( elem ) { - return "password" === elem.type; - }, - - submit: function( elem ) { - return "submit" === elem.type; - }, - - image: function( elem ) { - return "image" === elem.type; - }, - - reset: function( elem ) { - return "reset" === elem.type; - }, - - button: function( elem ) { - return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - var first = match[2], - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // If the nodes are siblings (or identical) we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Utility function for retreiving the text value of an array of DOM nodes -Sizzle.getText = function( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += Sizzle.getText( elem.childNodes ); - } - } - - return ret; -}; - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

    "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - if ( matches ) { - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - return matches.call( node, expr ); - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
    "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var ret = this.pushStack( "", "find", selector ), - length = 0; - - for ( var i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( var n = length; n < ret.length; n++ ) { - for ( var r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && jQuery.filter( selector, this ).length > 0; - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - if ( jQuery.isArray( selectors ) ) { - var match, selector, - matches = {}, - level = 1; - - if ( cur && selectors.length ) { - for ( i = 0, l = selectors.length; i < l; i++ ) { - selector = selectors[i]; - - if ( !matches[selector] ) { - matches[selector] = jQuery.expr.match.POS.test( selector ) ? - jQuery( selector, context || this.context ) : - selector; - } - } - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( selector in matches ) { - match = matches[selector]; - - if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { - ret.push({ selector: selector, elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - } - - return ret; - } - - var pos = POS.test( selectors ) ? - jQuery( selectors, context || this.context ) : null; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique(ret) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - if ( !elem || typeof elem === "string" ) { - return jQuery.inArray( this[0], - // If it receives a string, the selector is used - // If it receives nothing, the siblings are used - elem ? jQuery( elem ) : this.parent().children() ); - } - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ), - // The variable 'args' was introduced in - // https://github.com/jquery/jquery/commit/52a0238 - // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. - // http://code.google.com/p/v8/issues/detail?id=1050 - args = slice.call(arguments); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, args.join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return (elem === qualifier) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return (jQuery.inArray( elem, qualifier ) >= 0) === keep; - }); -} - - - - -var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
    ", "
    " ], - thead: [ 1, "", "
    " ], - tr: [ 2, "", "
    " ], - td: [ 3, "", "
    " ], - col: [ 2, "", "
    " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }; - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and "); -// } diff --git a/_test/tools/br/lib/Staf.php b/_test/tools/br/lib/Staf.php deleted file mode 100644 index 4420c7bc..00000000 --- a/_test/tools/br/lib/Staf.php +++ /dev/null @@ -1,58 +0,0 @@ -]] COMMAND [PARMS ] - * @param $path - * @param $params - * @param $host - */ - public static function process_start($path, $params, $host='local', $wait=false){ - $cmd = "start shell command \\\"\"$path\"\\\" parms \\\"\"$params\"\\\""; - if($wait){ - $cmd.=" wait returnstdout returnstderr"; - } - return self::process($cmd, $host); - } - - /** - * STOP | HANDLE > [USING ] - * @param unknown_type $handle - * @param unknown_type $host - */ - public static function process_stop($handle, $host='local', $all=0){ - $cmd = $all ? "STOP ALL CONFIRM":"STOP HANDLE $handle"; - return self::process($cmd, $host); - } - - public static function queryHandle($browser){ - $filename = "temp\\$browser"; - if(file_exists($filename)){ - $handle = file_get_contents($filename); - delete($filename); - return $handle; - } - return false; - } - - public static function saveHandle($browser){ - $filename = "temp\\$browser"; - $fp = fopen($filename, 'w'); - fwrite($fp, 'test'); - fclose($fp); - } -} -?> \ No newline at end of file diff --git a/_test/tools/br/lib/StafResult.php b/_test/tools/br/lib/StafResult.php deleted file mode 100644 index 6942dd16..00000000 --- a/_test/tools/br/lib/StafResult.php +++ /dev/null @@ -1,20 +0,0 @@ -rc = $rc; - $this->info = $info; - } - - public function __toString() - { - return "return code : ".$rc.", return info : ".$info."\n"; - } - - public static function parse($result){ - return new StafResult(0, $result); - } -}?> \ No newline at end of file diff --git a/_test/tools/br/list.php b/_test/tools/br/list.php deleted file mode 100644 index f67b5f27..00000000 --- a/_test/tools/br/list.php +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - Ueditor Test Index Page - - - - - - - - - -
    -

    Ueditor Test Index Page

    - -

    - umeditor -

    -
    - - -
    - - - -
    - -
    - 自动下一个出错时终止 -
    - -
    -
    -
    - -
    -
    - - -
    - - - diff --git a/_test/tools/br/log.php b/_test/tools/br/log.php deleted file mode 100644 index cf43ba0c..00000000 --- a/_test/tools/br/log.php +++ /dev/null @@ -1,45 +0,0 @@ - \ No newline at end of file diff --git a/_test/tools/br/mail.php b/_test/tools/br/mail.php deleted file mode 100644 index 07b2fbc2..00000000 --- a/_test/tools/br/mail.php +++ /dev/null @@ -1,113 +0,0 @@ - - * @version $Id: mail.php 156323 2011-11-28 02:57:21Z peng.shan $ - */ -class Mail { - function send_mail($to,$subject = "",$body = "") { - //error_reporting(E_STRICT); - date_default_timezone_set("Asia/Shanghai");//设定时区东八区 - require_once('../libs/phpmailer/class.phpmailer.php'); - include("../libs/phpmailer/class.pop3.php"); - $mail = new PHPMailer(); //new一个PHPMailer对象出来 - $body = str_replace("[\]",'',$body); //对邮件内容进行必要的过滤 - $mail->CharSet ="UTF-8";//设定邮件编码,默认ISO-8859-1,如果发中文此项必须设置,否则乱码 -// $mail->IsSMTP(); // 设定使用SMTP服务 -// $mail->SMTPDebug = 1; // 启用SMTP调试功能 - // 1 = errors and messages - // 2 = messages only - $mail->SMTPAuth = true; // 启用 SMTP 验证功能 - $mail->SMTPSecure = "ssl"; // 安全协议 - $mail->Host = "MAILBOX03.internal.baidu.com"; // SMTP 服务器 - $mail->Port = 465; // SMTP服务器的端口号 - $mail->Username = "zhuwemxuan"; // SMTP服务器用户名 - $mail->Password = "Zwx19840818"; // SMTP服务器密码 - $mail->SetFrom('zhuewnxuan@baidu.com', '朱文轩'); - $mail->AddReplyTo("zhuwenxuan@baidu.com","邮件回复人的名称"); - $mail->Subject = $subject; - $mail->AltBody = "To view the message, please use an HTML compatible email viewer! - From www.jiucool.com"; // optional, comment out and test - $mail->MsgHTML($body); - $address = $to; - $mail->AddAddress($address, "收件人名称"); - if(!$mail->Send()) { - echo "Mailer Error: " . $mail->ErrorInfo; - } else { - echo "Message sent!恭喜,邮件发送成功!"; - } - } - function new_send_mail(){ - mail("zhuwenxuan@baidu.com","asdfasdf","asdfasdf"); -// require_once('../libs/phpmailer/class.phpmailer.php'); -// $mail = new PHPMailer(); -// $body = "asdfdsf"; -// $body = str_replace("[\]",'',$body); -// $mail->SMTPAuth = true; // 启用 SMTP 验证功能 -// $mail->SMTPSecure = "ssl"; // 安全协议 -// $mail->IsSMTP(); -// $mail->CharSet='UTF-8'; -// $mail->SMTPDebug = 2; -// $mail->Host = 'smtp.baidu.com'; -// $mail->Port = 25; -// $mail->Username = "zhuwenxuan@baidu.com"; -// $mail->Password = "Zwx19840818"; -// $mail->SetFrom('zhuwenxuan@baidu.com', 'First Last'); -// -// $mail->AddReplyTo("zhuwen_xuan@126.com","First Last"); -// -// $mail->Subject = "PHPMailer Test Subject via POP before SMTP, basic"; -// -// $mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test -// -// $mail->MsgHTML($body); -// -// $address = "zhuwen_xuan@126.com"; -// $mail->AddAddress($address, "John Doe"); -// if(!$mail->Send()) { -// echo "Mailer Error: " . $mail->ErrorInfo; -// } else { -// echo "Message sent!"; -// } - } - - function sendMain126(){ - require_once('../libs/phpmailer/class.phpmailer.php'); - $mail = new PHPMailer(); - $body = "asdfdsf"; - $body = str_replace("[\]",'',$body); - $mail->SMTPAuth = true; // 启用 SMTP 验证功能 - $mail->SMTPSecure = "ssl"; // 安全协议 - $mail->IsSMTP(); - $mail->CharSet='UTF-8'; - $mail->SMTPDebug = 2; - $mail->Host = 'smtp.126.com'; - $mail->Port = 465; - $mail->Username = "zhuwen_xuan@126.com"; - $mail->Password = "zwx19840818"; - $mail->SetFrom('zhuwen_xuan@126.com', 'First Last'); - - $mail->AddReplyTo("zhuwenxuan@baidu.com","First Last"); - - $mail->Subject = "PHPMailer Test Subject via POP before SMTP, basic"; - - $mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test - - $mail->MsgHTML($body); - - $address = "zhuwenxuan@baidu.com"; - $mail->AddAddress($address, "John Doe"); - if(!$mail->Send()) { - echo "Mailer Error: " . $mail->ErrorInfo; - } else { - echo "Message sent!"; - } - } - -} -$m = new Mail(); -$m->new_send_mail(); - - - - - \ No newline at end of file diff --git a/_test/tools/br/read.php b/_test/tools/br/read.php deleted file mode 100644 index 082ef2b1..00000000 --- a/_test/tools/br/read.php +++ /dev/null @@ -1,12 +0,0 @@ - \ No newline at end of file diff --git a/_test/tools/br/record.php b/_test/tools/br/record.php deleted file mode 100644 index 8d3a15cb..00000000 --- a/_test/tools/br/record.php +++ /dev/null @@ -1,95 +0,0 @@ -testsuite as $testsuite){ - foreach ($testsuite->testcase as $testResult) { - // $totalCov = 0; - $browser =strval( $testResult['browserInfo']); - $host = strval($testResult['hostInfo']); - $caseName = strval($testResult['name']); - $fail = strval($testResult['failNumber']); - $total = strval($testResult['totalNumber']); - $cov = strval($testResult['cov']); - $recordCovForBrowser = strval($testResult['recordCovForBrowser']); - if (!array_key_exists($caseName, $caseList)) { //如果这个用例不存在 - $caseInfo = array ( - 'hostInfo' => $host, - 'fail' => $fail, - 'total' => $total, - 'cov' => $cov, - 'recordCovForBrowser' => $recordCovForBrowser - ); - // $totalCov += $cov; - $caseList[$caseName] = array ( - $browser => $caseInfo//, - // 'totalCov'=>$totalCov - ); - // $caseList['totalCov'] = $totalCov; - } else { //否则添加到相应的用例中去 - $foundCase = $caseList[$caseName]; //找到用例名称对应的array,$caseName为key - if (!array_key_exists($browser, $foundCase)) { //如果没有该浏览器信息,则添加 - // $totalCov += $cov; - $caseList[$caseName][$browser] = array ( - 'hostInfo' => $host, - 'fail' => $fail, - 'total' => $total, - 'cov' => $cov, - 'recordCovForBrowser' => $recordCovForBrowser - ); - // $caseList[$caseName]['totalCov'] = $totalCov; - } else { - $foundBrowser = $foundCase[$browser]; //有这个浏览器 - array_push($foundBrowser, array ( - 'hostInfo' => $host, - 'fail' => $fail, - 'total' => $total, - 'cov' => $cov, - 'recordCovForBrowser' => $recordCovForBrowser - )); - } - } - - } - } - - //根据需求添加仅记录失败情况的接口 - if($onlyfails){//如果仅考虑失败情况,此处根据用例情况过滤 - foreach($caseList as $name => $info){ - $all_success = true;//记录当前用例是否全部运行成功 - foreach($info as $b => $result){ - if($result['fail'] > 0) - $all_success = false;//如果有失败情况则终止循环并进入下一个用例分析 - break; - } - //if($all_success) //如果全部通过则从记录中移除 - //unset($caseList[$name]); - } - } - return $caseList; -} - -function record() -{ -// require_once 'geneXML.php'; - /*如果全部运行完毕,发送邮件*/ - $kissList = interXML(false); - require_once 'geneHTML.php'; - if (sizeof($kissList) > 0) { - //针对kissList过滤,移除全部正确用例 - $html = geneHTML($kissList); - $report = 'report.html'; - $handle = fopen("$report", "w"); - fwrite($handle, $html); - fclose($handle); -// require_once 'geneHistory.php'; -// geneHistory($html); - } -} -?> diff --git a/_test/tools/br/report.php b/_test/tools/br/report.php deleted file mode 100644 index cc0ebceb..00000000 --- a/_test/tools/br/report.php +++ /dev/null @@ -1,108 +0,0 @@ -"; - return; -} - -function report() -{ - /** - * for junit report - */ - $dom = new DOMDocument('1.0', 'utf-8'); - $suite = $dom->appendChild($dom->createElement('testsuite')); - $cfg = preg_split('/[&=]/', $_POST['config']); - $config = array(); - for ($i = 0; $i < sizeof($cfg); $i += 2) { - // echo "{$cfg[$i]} {$cfg[$i+1]}\r\n
    "; - $config[$cfg[$i]] = $cfg[$i + 1]; - $p = $suite->appendChild($dom->createElement("property")); - - $p->setAttribute('name', $cfg[$i]); - $p->setAttribute('value', $cfg[$i + 1]); - - } - $suite->setAttribute("name", $config['browser']); - $errors = 0; - $failures = 0; - $tests = 0; - $time = 0; - $filter = $config['filter']; - foreach ($_POST as $key => $value) { - if ($key == 'config') - continue; - $info = explode(";", $value); - if ($filter!='' && (substr_count($key, $filter) == 0 || strpos($key, $filter) > 0)) - continue; - //errornum + ',' + allnum + ','+ kissPerc || 0 + ',' + wb.kissstart + ','+ wb.kissend; - $casetime = ($info[4] - $info[3]) / 1000; - $time += $casetime; - $tests++; - $failure = (int)($info[0]); - $case = $suite->appendChild($dom->createElement('testcase')); - $case->setAttribute("name", $key); - $case->setAttribute("time", $casetime); - $case->setAttribute("cov", $info[2]); - $case->setAttribute('failNumber', $info[0]); - $case->setAttribute('totalNumber', $info[1]); - $case->setAttribute('recordCovForBrowser',$info[5]); - $case->setAttribute('browserInfo', $config['browser']); - $case->setAttribute('hostInfo', Config::$BROWSERS[$config['browser']][0]); - // covHtml( $config[ 'browser' ] . '/' . $key , $info[ 2 ] ); - if ($failure > 0) { - $failures++; - $failinfo = $case->appendChild($dom->createElement('failure')); - $failinfo->setAttribute('type', 'junit.framework.AssertionFailedError'); - //FROM php.net, You cannot simply overwrite $textContent, to replace the text content of a DOMNode, as the missing readonly flag suggests. - $kiss = join(".", split("/", $key)); - // $failinfo->appendChild( new DOMText( $value ) ); - $failinfo->appendChild(new DOMText("run")); - } - //TODO add more case info in xml - } - - $suite->setAttribute('time', $time); - $suite->setAttribute('failures', $failures); - $suite->setAttribute('tests', $tests); - - if (!is_dir("report_{$config['filter']}")) - mkdir("report_{$config['filter']}"); - $dom->save("report_{$config['filter']}/{$config['browser']}.xml"); -} -include 'config.php'; -$config; -$configs = preg_split('/[&=]/', $_POST['config']); -for ($j = 0; $j < sizeof($configs); $j += 2) { - // echo "{$cfg[$i]} {$cfg[$i+1]}\r\n
    "; -// if(strcmp($configs[$j],'browserSet')==0){ - $config[$configs[$j]] = $configs[$j + 1]; -// } - -} -report(); - -$dom = new DOMDocument('1.0', 'utf-8'); -$testsuites = $dom->appendChild($dom->createElement('testsuites')); - -foreach (Config::getBrowserSet($configBrowserSet) as $key => $value) { - $file = "report_{$config['filter']}/$key.xml"; - if (!file_exists($file)) { - echo "wait for report : $file\r\n
    "; - return; - } - $xmlDoc = new DOMDocument('1.0', 'utf-8'); - $xmlDoc->load($file); - $xmlDom = $xmlDoc->documentElement; - //echo $xmlDom->nodeName; - $testsuites->appendChild($dom->importNode($xmlDom, true)); -} -$dom->save("report.xml"); -$browserNum = count(Config::getBrowserSet($configBrowserSet)); -require_once 'record.php'; -record(); - -Config::StopAll(); -?> \ No newline at end of file diff --git a/_test/tools/br/run.php b/_test/tools/br/run.php deleted file mode 100644 index c84b4d5a..00000000 --- a/_test/tools/br/run.php +++ /dev/null @@ -1,46 +0,0 @@ -'; -} -; -require_once "case.class.php"; -$c = new Kiss( '../../../' , $_GET[ 'case' ] ); -$title = $c->name; -$cov = array_key_exists( 'cov' , $_GET ); -?> - - - - <?php print( "run case $title" );?> - print_js( $cov ); ?> - - -

    name );?>

    - -

    - -

    -
      - -
      - - - -
      - - \ No newline at end of file diff --git a/_test/tools/br/runC.php b/_test/tools/br/runC.php deleted file mode 100644 index 3671cbb8..00000000 --- a/_test/tools/br/runC.php +++ /dev/null @@ -1,46 +0,0 @@ -'; -} -; -require_once "case.class.php"; -$c = new Kiss( '../../../' , $_GET[ 'case' ] ); -$title = $c->name; -$cov = array_key_exists( 'cov' , $_GET ); -?> - - - - <?php print( "run case $title" );?> - print_all_js( $cov ); ?> - - -

      name );?>

      - -

      - -

      -
        - -
        - - - -
        - - \ No newline at end of file diff --git a/_test/tools/br/runall.php b/_test/tools/br/runall.php deleted file mode 100644 index e8da4637..00000000 --- a/_test/tools/br/runall.php +++ /dev/null @@ -1,111 +0,0 @@ -\n"; - } - } - } - closedir( $handle ); - if ( rmdir( $dirName ) ) echo "成功删除目录: $dirName
        \n"; - } -} - -if ( array_key_exists( 'clear' , $_GET ) ) { - print 'debug - clear report'; - //Config::StopAll(); - if ( file_exists( 'report' ) ) - delDirAndFile( 'report' ); -} -$reportfile = "report_{$_GET['filter']}"; -if ( file_exists( $reportfile ) ) { - // rmdir('report'); - $reports = scandir( $reportfile ); - /*自己和父节点*/ - print 'on batch run, please waiting : ' . ( sizeof( $reports ) - 2 ); - return; -} else { - mkdir( $reportfile ); -} - -if ( file_exists( "./coverage/source.js" ) ) { - if ( unlink( "./coverage/source.js" ) ) echo "成功删除文件:source.js"; -} -source(); - -if ( file_exists( "covreport.html" ) ) { - if ( unlink( "covreport.html" ) ) echo "成功删除覆盖率报告文件: covreport.html
        \n"; -} -if ( file_exists( "jshintReport.html" ) ) { - if ( unlink( "jshintReport.html" ) ) echo "成功删除: jshintReport.html
        \n"; -} -exec("python ../lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py jshintReport.html ../../../_src", $back); -echo "jshint: ".$back."
        \n"; -/*记录运行时信息*/ -$b = array_key_exists( 'browser' , $_GET ) ? $_GET[ 'browser' ] : 'all'; - -//if ( array_key_exists( 'cov' , $_GET ) ){ - - -if ( $b != 'all' ) { - run( $b , true ); -} else { - Config::StopAll(); //添加启动前结束浏览器步骤 - $browsers = array_key_exists( 'browserSet' , $_GET )?Config::getBrowserSet($_GET[ 'browserSet' ]):Config::$BROWSERS; - foreach ( $browsers as $b => $i ) { - run( $b ); - sleep(30); - } -} -?> \ No newline at end of file diff --git a/_test/tools/br/txt/test1_1.txt b/_test/tools/br/txt/test1_1.txt deleted file mode 100644 index f587a369..00000000 --- a/_test/tools/br/txt/test1_1.txt +++ /dev/null @@ -1,76 +0,0 @@ -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - -

        -

        - 欢迎使用umeditor! - - -

        -

        - -

        -

        - 欢迎使用umeditor! - - -

        -

        - -

        -

        - 1. -欢迎使用umeditor! - - -

        -

        - 2. -欢迎使用umeditor! - - -

        -

        - -

        -

        - l 欢迎使用umeditor! - - -

        -

        - l 欢迎使用umeditor! - - -

        -

        \ No newline at end of file diff --git a/_test/tools/br/txt/test1_2.txt b/_test/tools/br/txt/test1_2.txt deleted file mode 100644 index 7615dbdd..00000000 --- a/_test/tools/br/txt/test1_2.txt +++ /dev/null @@ -1,38 +0,0 @@ -

        -

        - -

        -

        - 欢迎使用umeditor! - - -

        -

        - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        \ No newline at end of file diff --git a/_test/tools/br/txt/test1_3.txt b/_test/tools/br/txt/test1_3.txt deleted file mode 100644 index 4f765937..00000000 --- a/_test/tools/br/txt/test1_3.txt +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - -
        -

        欢迎使用umeditor!

        -
        -

         

        -
        -

         

        -
        -

         

        -
        -

         

        -
        -

        欢迎使用umeditor!

        -
        - -

        - -

        www.baidu.com

        \ No newline at end of file diff --git a/_test/tools/br/txt/test2_1.txt b/_test/tools/br/txt/test2_1.txt deleted file mode 100644 index d9fe6ea3..00000000 --- a/_test/tools/br/txt/test2_1.txt +++ /dev/null @@ -1,57 +0,0 @@ -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 一、欢迎使用umeditor! - - -

        -

        - 二、欢迎使用umeditor! - - -

        -

        - l 欢迎使用umeditor! - - -

        -

        - l 欢迎使用umeditor! - - -

        -

        \ No newline at end of file diff --git a/_test/tools/br/txt/test2_2.txt b/_test/tools/br/txt/test2_2.txt deleted file mode 100644 index 22c6c807..00000000 --- a/_test/tools/br/txt/test2_2.txt +++ /dev/null @@ -1,32 +0,0 @@ -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        - 欢迎使用umeditor! - - -

        -

        \ No newline at end of file diff --git a/_test/tools/br/txt/test2_3.txt b/_test/tools/br/txt/test2_3.txt deleted file mode 100644 index b4c11e87..00000000 --- a/_test/tools/br/txt/test2_3.txt +++ /dev/null @@ -1,156 +0,0 @@ -

        -

        -

        - -

        - - - - - -
        - - - - - - - - - -
        - - - - - -

        - 欢迎使用umeditor! - - -

        - -
        - -
        - - -

        - -

        - -
        - - - - - - - -
        - - -

        - -

        - -
        - - - - - - - -
        -
        - - - - - - - - -
        - - - - - -

        - -

        - -
        - - - - - - - -
        - - -

        - -

        - -
        - - - - - - - -
        - - -

        - 欢迎使用umeditor! - - -

        - -
        - - - - - - - -
        -
        -

        - - - -

        www.baidu.com
        -

        -

        \ No newline at end of file diff --git a/_test/tools/br/txt/test3_1.txt b/_test/tools/br/txt/test3_1.txt deleted file mode 100644 index c7f7ea43..00000000 --- a/_test/tools/br/txt/test3_1.txt +++ /dev/null @@ -1,131 +0,0 @@ - - -

        欢迎使用umeditor!

        - -

        欢迎使用umeditor!

        - -

         

        - -

        欢迎使用umeditor!

        - -

        欢迎使用umeditor!

        - - - - - - - - - - - - -
        -

        欢迎使用umeditor!

        -
        -

         

        -
        -

         

        -
        -

         

        -
        -

         

        -
        -

        欢迎使用umeditor!

        -
        - -

         

        \ No newline at end of file diff --git a/_test/tools/coverage/cov.bat b/_test/tools/coverage/cov.bat deleted file mode 100644 index 3bc2d3f2..00000000 --- a/_test/tools/coverage/cov.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -jscoverage.exe --encoding=UTF-8 ../../../_src ../../coverage \ No newline at end of file diff --git a/_test/tools/coverage/jscoverage.exe b/_test/tools/coverage/jscoverage.exe deleted file mode 100644 index 1151644a..00000000 Binary files a/_test/tools/coverage/jscoverage.exe and /dev/null differ diff --git a/_test/tools/data/frame.html b/_test/tools/data/frame.html deleted file mode 100644 index d5f7c5a3..00000000 --- a/_test/tools/data/frame.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/_test/tools/data/frame.php b/_test/tools/data/frame.php deleted file mode 100644 index b5ec9a2f..00000000 --- a/_test/tools/data/frame.php +++ /dev/null @@ -1,16 +0,0 @@ - - - - -"; -else -print ""; -?> - - - - diff --git a/_test/tools/data/test.JPG b/_test/tools/data/test.JPG deleted file mode 100644 index 68343f2d..00000000 Binary files a/_test/tools/data/test.JPG and /dev/null differ diff --git a/_test/tools/data/test.html b/_test/tools/data/test.html deleted file mode 100644 index ff34eec4..00000000 --- a/_test/tools/data/test.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/_test/tools/data/testReady.html b/_test/tools/data/testReady.html deleted file mode 100644 index 27dcb3f1..00000000 --- a/_test/tools/data/testReady.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/_test/tools/lib/ant_tangram_ext.jar b/_test/tools/lib/ant_tangram_ext.jar deleted file mode 100644 index 4cd595a1..00000000 Binary files a/_test/tools/lib/ant_tangram_ext.jar and /dev/null differ diff --git a/_test/tools/lib/js.jar b/_test/tools/lib/js.jar deleted file mode 100644 index 2369f99a..00000000 Binary files a/_test/tools/lib/js.jar and /dev/null differ diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/check.cfg b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/check.cfg deleted file mode 100644 index 912719b8..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/check.cfg +++ /dev/null @@ -1,117 +0,0 @@ -[option] -asi = true -#if automatic semicolon insertion should be tolerated -bitwise = false -#if bitwise operators should not be allowed -boss = true -# if advanced usage of assignments should be allowed -browser= true -# if the standard browser globals should be predefined -couch = true -# if CouchDB globals should be predefined -curly = false -# if curly braces around all blocks should be required -debug = false -# if debugger statements should be allowed -devel = false -# if logging globals should be predefined (console,alertetc.) -dojo = false -# if Dojo Toolkit globals should be predefined -eqeqeq = false -# if === should be required -eqnull = false -# if == null comparisons should be tolerated -es5 = false -# if ES5 syntax should be allowed -esnext = false -# if es.next specific syntax should be allowed -evil = true -# if eval should be allowed -expr = true -# if ExpressionStatement should be allowed as Programs -forin = true -# if for in statements must filter -funcscope = true -# if only function scope should be used for scope tests -globalstrict = true -# if global "use strict"; should be allowed (also enables 'strict') -immed = false -# if immediate invocations must be wrapped in parents -iterator = true -# if the `__iterator__` property should be allowed -jquery = true -# if jQuery globals should be predefined -lastsemic = true -# if semicolons may be ommitted for the trailing statements inside of a one-line blocks. -latedef= true -# if the use before definition should not be tolerated -laxbreak = true -# if line breaks should not be checked -loopfunc = true -# if functions should be allowed to be defined within loops -mootools = true -# if MooTools globals should be predefined -multistr = true -# allow multiline strings -newcap = false -# if constructor names must be capitalized -noarg = false -# if arguments.caller and arguments.callee should be disallowed -node = false -# if the Node.js environment globals should be predefined -noempty= false -# if empty blocks should be disallowed -nonew = true -# if using `new` for side-effects should be disallowed -nonstandard = true -# if non-standard (but widely adopted) globals should be predefined -nomen = false -# if names should be checked -onevar = true -# if only one var statement per function should be allowed -onecase= true -# if one case switch statements should be allowed -passfail = false -# if the scan should stop on first error -plusplus = false -# if increment/decrement should not be allowed -proto = true -# if the `__proto__` property should be allowed -prototypejs = true -# if Prototype and Scriptaculous globals should be predefined -regexdash = true -# if unescaped first/last dash (-) inside brackets should be tolerated -regexp = false -# if the . should not be allowed in regexp literals -rhino = true -# if the Rhino environment globals should be predefined -undef = false -# if variables should be declared before used -scripturl = true -# if script-targeted URLs should be tolerated -shadow = true -# if variable shadowing should be tolerated -strict = false -# require the "use strict"; pragma -sub = true -# if all forms of subscript notation are tolerated -supernew = true -# if `new function () { ... };` and `new Object;` should be tolerated -trailing = false -# if trailing whitespace rules apply -validthis = true -# if 'this' inside a non-constructor function is valid. This is a function scoped option only. -white = false -# if strict whitespace rules apply -wsh = true -# if the Windows Scripting Host environment globals should be predefined -[predef] -baidu = true -nuit = true -Ext = true -ko = true -_ = true -noah = true -Noah = true -Backbone = true -WdatePicker = true diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/custcheck.conf b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/custcheck.conf deleted file mode 100644 index 85cda0c4..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/custcheck.conf +++ /dev/null @@ -1 +0,0 @@ -[command] diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/ignore.list b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/ignore.list deleted file mode 100644 index 503cb641..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/ignore.list +++ /dev/null @@ -1,14 +0,0 @@ -#there 3 level:ignore warning error -[level] -Unsafe character=ignore -Mixed spaces and tabs=warning -Too many var statements=ignore -Unclosed string=ignore -Missing semicolon=error -Unexpected dangling=ignore -to compare with=ignore -is not defined=ignore -Unexpected dangling=ignore -A constructor name should start with an uppercase letter=warning -Expected an assignment or function call and instead saw an expression=warning -Mixed spaces and tabs=ignore diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/omitfiles.conf b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/omitfiles.conf deleted file mode 100644 index 2b6f42ee..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/conf/omitfiles.conf +++ /dev/null @@ -1,4 +0,0 @@ -#[config format]:REGULAR:true|false,true means set filtering enabeld and false means not -#notice:REGULAR will be set in the command "find /top/dir -name REGULAR" -[omitfils] -*data*:true diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/customcheck/cust.sh b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/customcheck/cust.sh deleted file mode 100644 index 7c5482ff..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/customcheck/cust.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -echo $1'***222***444***555***666' diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/js.jar b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/js.jar deleted file mode 100644 index c081d16b..00000000 Binary files a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/js.jar and /dev/null differ diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/jshint-rhino.js b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/jshint-rhino.js deleted file mode 100644 index c7c9b2ec..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/jshint/jshint-rhino.js +++ /dev/null @@ -1,89 +0,0 @@ -/*jshint boss: true, rhino: true */ -/*globals JSHINT*/ - - - -(function (args) { - var filenames = [], - optstr, // arg1=val1,arg2=val2,... - predef, // global1=override,global2,global3,... - opts = { rhino: true }, - retval = 0; - load(args[0]+"jshint.js"); - - for(var i=1;i ' + (err.evidence || '').replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")); - //print(''); - //print("==========="); - //print(err.evidence); - //print(err.raw); - //print(err.a); - //print("==========="); - //var myReport = JSHINT.report(false); - //print(myReport); - } - retval = 1; - } - }); - - quit(retval); -}(arguments)); diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/htmlpart.html b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/htmlpart.html deleted file mode 100644 index 51de2a62..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/htmlpart.html +++ /dev/null @@ -1,15 +0,0 @@ - - -
        {$title}
        -
        - - - - - - - - - [---to be replaced 2---] - -
        \ No newline at end of file diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/toggle_tpl.html b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/toggle_tpl.html deleted file mode 100644 index ce857cd1..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/core/tpl/toggle_tpl.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - -JsHunter Check Report - - - - - - - - - -
        JSHunter Report
        -
        - -
        -
        - - - - - - - - - - - - - - - - - - - - - - -
        TOTAL PROBLEM:{$pnumber}
        IGNORED:{$ignumber}
        ERROR:{$errnumber}
        WARNING:{$warnumber}
        DATA TIME:{$timeData}
        -
        -

         

        -
        -
        - [---to be replace 1---] -
        - - diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/editor.js b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/editor.js deleted file mode 100644 index a27b8236..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/editor.js +++ /dev/null @@ -1,22 +0,0 @@ -UMDITOR_CONFIG = window.UMDITOR_CONFIG || {}; - -var baidu = window.baidu || {}; - -window.baidu = baidu; - -window.UM = UM = {}; - -UM.plugins = {}; - -UM.commands = {}; - -UM.instants = {}; - -UM.I18N = {}; - -console.log("console"); -alert("alert"); - -UM.version = "1.2.3.0"; - -var dom = UM.dom = {}; \ No newline at end of file diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py deleted file mode 100644 index cd9b718d..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/hint.py +++ /dev/null @@ -1,425 +0,0 @@ -#!/usr/bin/python -#encoding=utf-8 -import sys,os -import ConfigParser -import commands -import time -import codecs - -htmlMap = {} -def processHtml(filename): - f = open(filename,"r") - if f is None: - raise Exception('open %s error!' % (filename)) - newName = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1]) + os.sep + "core" + os.sep + "data"+os.sep+os.path.basename(filename) + "." + str(time.time()) - #print newName - tmp = "" - flag=False - orig_num = 0 - new_num = 0 - for ln in f: - orig_num += 1 - if ln.find("") == -1: - flag=True - continue - if ln.find("") != -1: - flag=False - continue - if ln.find("") == -1: - flag=True - continue - if ln.find("") != -1: - flag=False - continue - if ln.find("") != -1: - flag=False - continue - if flag == True: - tmp += ln - new_num += 1 - htmlMap[filename+os.sep+str(orig_num)]=newName + os.sep + str(new_num) - if tmp == "": - print ('[WARNING]file %s not contain js code' % (filename)) - return "" - outfile = open(newName,"w") - if outfile is None: - raise Exception('open %s error!' % (newName)) - outfile.write(tmp) - #print htmlMap - return newName - -def clearTmpFiles(): - dels=[] - for key in htmlMap.keys(): - fn = os.sep.join(htmlMap[key].split(os.sep)[:-1]) - if not fn in dels: - dels.append(fn) - #print dels - for item in dels: - os.remove(item) -def isHiddenFile(path): - itms = path.split(os.sep) - for itm in itms: - if itm != "" and itm != "." and itm != ".." and itm[0]==".": - return True - return False -''' -@input -a file (or a top dir) to be checked -@process -recuresively read all the files of a dir.only support .html and .js. -if it is a html file then we only check the code between -if it is a js file then we check all the code -@return -file(or folder) to be checked -''' -def getFiles(paths): - #print paths - ret = [] - omitpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "omitfiles.conf" - for path in paths: - path = path.rstrip(os.sep) - if not os.path.isdir(path): - omitfiles = getOmitedFiles(omitpath,os.sep.join(path.split(os.sep)[:-1])+os.sep) - if (os.path.getsize(path)==0) or (path in omitfiles): - continue - if path.find(".js") != -1 and isHiddenFile(path)==False: - ret.append(path) - elif path.find(".html") != -1 and isHiddenFile(path)==False: - np = processHtml(path) - if np != "": - ret.append(np) - else: - omitfiles = getOmitedFiles(omitpath,path) - for root, dirs, files in os.walk(path): - for f in files: - if (os.path.getsize(root + os.sep + f)==0) or ((root + os.sep + f) in omitfiles): - continue - if f.find(".js") != -1 and isHiddenFile(root + os.sep + f) == False: - ret.append(root + os.sep + f) - elif f.find(".html") != -1 and isHiddenFile(root + os.sep + f) == False: - np=processHtml(root + os.sep + f) - if np != "": - ret.append(np) - else: - continue - return ret - - -def getopt(path): - _opt=[] - _predef=[] - conf = ConfigParser.ConfigParser() - conf.read(path) - for item in conf.options('option'): - _opt.append("%s=%s"%(item,conf.get('option',item))) - for item in conf.options('predef'): - _predef.append("%s=%s"%(item,conf.get('predef',item))) - return "%s %s"%(",".join(_opt),",".join(_predef)) - -def getBlackList(path): - lst={} - conf = ConfigParser.ConfigParser() - conf.read(path) - for item in conf.options('level'): - lst[item]=conf.get('level',item) - return lst - -def printReport(rptstr): - if rptstr=="": - return - array = rptstr.split('\n') - for ln in array: - items = ln.split("***") - if items[1].find("Stopping") != -1: - print items[1] - else: - print "文件:%s\t错误原因:%s\t错误位置:第%s行\t错误语句:%s"%(items[0],items[1],items[2],items[4]) -def processItem(item,blacklst,hp): - itm = item - for key in hp.keys(): - if item[0]+os.sep+item[2] == hp[key]: - itm[0]=os.sep.join(key.split(os.sep)[:-1]) - itm[2]=key.split(os.sep)[-1] - #print "====",itm,"======" - itm.append("error") - for err in blacklst.keys(): - if itm[1].lower().find(err.lower())!=-1: - itm[5] = blacklst[err] - break - return itm -''' -parse jshint output -''' -def splitOutput(rptstr,blacklist,mp): - if rptstr=="": - return - array = rptstr.split('\n') - lst=[] - parsecnt = 0; - parsetotal=len(array) - for ln in array: - #print ln - if ln.find("***") == -1: - continue - items = processItem(ln.split("***"),blacklist,mp) - if items[1].find("Stopping") != -1: - print items[1] - else: - lst.append(items) - parsecnt = parsecnt + 1 - return (lst,parsecnt,parsetotal) -''' -get the table body according to the result-list -''' -def getBody(lst): - files={} - error=0 - warning=0 - ignore=0; - count=0 - for item in lst: - count = count + 1 - if len(item)<6: - continue - if not files.has_key(item[0]): - if item[5] == "ignore": - ignore = ignore + 1 - elif item[5] == "error": - error = error + 1 - files[item[0]] = getLine(item,count) - else: - files[item[0]] = getLine(item,count) - warning = warning + 1 - else: - if item[5] == "ignore": - ignore = ignore + 1 - elif item[5] == "error": - error = error + 1 - files[item[0]] = files[item[0]] + getLine(item,count) - else: - files[item[0]] = files[item[0]] + getLine(item,count) - warning = warning + 1 - return (files,ignore,warning,error) - -def generateHtml(rptstr,outfile,blacklst,mp): - print "start parsing jshint output..." - (lst,parsecnt,parsetotal) = splitOutput(rptstr,blacklst,mp) - print "prepare main tpl..." - tpl="" - tplPath=os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1])+os.sep+"core"+os.sep+"tpl"+os.sep+"toggle_tpl.html" - if not os.path.exists(tplPath): - raise Exception('%s file does not exists!'%(tplPath)) - f=open(tplPath,"r") - if f is None: - raise Exception('open %s error!' % (tplPath)) - for ln in f: - tpl+=ln - strStartTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) - tpl=tpl.replace("{$pnumber}",str(len(lst))) - tpl=tpl.replace("{$timeData}",strStartTime) - f.close() - print "blacklist filtering..." - (files,ignore,warning,error) = getBody(lst) - tpl=tpl.replace("{$ignumber}","%s(%5.1f%%)"%(str(ignore),(float(ignore)/len(lst)*100))) - tpl=tpl.replace("{$errnumber}","%s(%5.1f%%)"%(str(error),(float(error)/len(lst)*100))) - tpl=tpl.replace("{$warnumber}","%s(%5.1f%%)"%(str(warning),(float(warning)/len(lst)*100))) - print "prepare body" - bodys="" - for key in files: - tblPath=os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1])+os.sep+"core"+os.sep+"tpl"+os.sep+"htmlpart.html" - if not os.path.exists(tblPath): - raise Exception('%s file does not exists!'%(tblPath)) - f=open(tblPath,"r") - body='''''' - for ln in f: - body += ln - body = body.replace("{$title}",key) - body = body.replace("{$fname}",key) - f.close() - body = body.replace("[---to be replaced 2---]",files[key]) - bodys = bodys + body - if bodys=="": - #raise Exception('no report generated') - bodys = "no informatin maybe they are filtered" - tpl=tpl.replace("[---to be replace 1---]",bodys) - ts=str(int(time.time())) - resf=open(outfile,"w") - if resf is None: - raise Exception('open %s error!' % (outfile)) - resf.write(tpl) - resf.close() - print "generate html file %s OK!"%(outfile) - return ts - -def getLine(item,no): - #print item - text = '''%s%s%s%s%s'''%(str(no),item[5],item[1],item[2],item[4].replace("<","<").replace(">",">")) - return text - -def genReport(status,output,blackpath,outfile,htmlMap): - #if status == 0: - # print "[WARNING][NO ERROR DETECTED BY JSHUNTER]" - #else: - if output.find("open file") != -1: - raise Exception("File Not Found Error!") - print "[ERROR DETECTED BY JSHUNTER]" - blacklist = getBlackList(blackpath) - ts = generateHtml(output,outfile,blacklist,htmlMap) - return ts - -def checkJavaExist(): - cmd="java" - (status,output) = commands.getstatusoutput(cmd) - if status != 0: - raise Exception("jshunter depend on java enviroment.please make sure your java is OK") -def checkPythonExist(): - cmd="python -h" - (status,output) = commands.getstatusoutput(cmd) - if status != 0: - raise Exception("jshunter depend on python enviroment.please make sure your python is OK") - -def getCustomerCheckFiles(paths): - omitpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "omitfiles.conf" - ret = [] - for path in paths: - path = path.rstrip(os.sep) - if not os.path.isdir(path): - omitfiles = getOmitedFiles(omitpath,os.sep.join(path.split(os.sep)[:-1])+os.sep) - if ((os.path.getsize(path)==0) or (path in omitfiles)): - continue - ret.append(path) - else: - omitfiles = getOmitedFiles(omitpath,path) - for root, dirs, files in os.walk(path): - for f in files: - if (os.path.getsize(root + os.sep + f)==0) or ((root + os.sep + f) in omitfiles): - continue - else: - ret.append(root + os.sep + f) - return ret -def getOmitedFiles(confpath,topdir): - _res = [] - _opt = [] - conf = ConfigParser.ConfigParser() - conf.read(confpath) - for item in conf.options('omitfils'): - if conf.get('omitfils',item) == "true": - _opt.append(item) - if (not os.path.isdir(topdir)) and (len(_opt) > 0): - return [] - for item in _opt: - cmd = 'find %s -name "%s"'%(topdir,item) - #print cmd - (status,output) = commands.getstatusoutput(cmd) - if status != 0: - raise Exception("[FATAL]cmd failed!%s"%(cmd)) - #print output - for ln in output.split("\n"): - _res.append(ln) - return _res - -def usage(): - print "====================================================================================================================" - print "[Usage]\n./hint outpath.html fileToCheck.js\t\t检查fileToCheck.js这个文件" - print "./hint outpath.html folderToCheck\t\t检查folderToCheck这个目录内的所有js文件和html文件(递归检查)" - print "./hint outpath.html folderToCheck/*.js\t\t检查folderToCheck一级目录下的所有js文件和html文件(忽略目录)" - print "[Notice]使用时请确保当前目录中包含jshint.js文件,建议cd到jshunter的目录中执行./hint.py" - print "[Contact] pankai01@baidu.com liulanying01@baidu.com" - print "====================================================================================================================" - -def doJsHint(_path): - fileToCheck=getFiles(_path) - step = 50 - javapath = "java" - jsjar = os.path.dirname(__file__) + os.sep + "core" + os.sep + "jshint" + os.sep + "js.jar" - rhino = os.path.dirname(__file__) + os.sep + "core" + os.sep + "jshint" + os.sep + "jshint-rhino.js" - confpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "check.cfg" - blackpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "ignore.list" - opt = getopt(confpath) - sz = len(fileToCheck) - if sz <= 0: - print "[WARNING]no file to be checked in doJsHint" - return "" - print "Files to be checked Number: %d"%(sz) - for i in range(0,sz): - print (i+1),":",fileToCheck[i] - output="" - if sz <= step: - opt = "%s %s"%(getopt(confpath)," ".join(fileToCheck[:])) - cmd = "%s -jar %s %s %s %s"%(javapath,jsjar,rhino,os.path.dirname(__file__) + os.sep,opt) - (status,output) = commands.getstatusoutput(cmd) - else: - rd=sz/step+1 - for j in range(0,rd): - if (j+1)*step>sz: - opt = "%s %s"%(getopt(confpath)," ".join(fileToCheck[j*step:sz])) - else: - opt = "%s %s"%(getopt(confpath)," ".join(fileToCheck[j*step:(j+1)*step])) - cmd = "%s -jar %s %s %s %s"%(javapath,jsjar,rhino,os.path.dirname(__file__) + os.sep,opt) - (status,output_tmp)=commands.getstatusoutput(cmd) - if status != 0 and output_tmp.find("open file") != -1: - raise Exception("File Not Found Error.ERRMSG:%s\n"%(output_tmp)) - else: - output = output + output_tmp - print "Finish %5.1f%%"%((j+1)*float(str(step))/sz*100.0) - return output - -def doCustomerCheck(_path): - confpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "custcheck.conf" - custpath = os.path.dirname(__file__) + os.sep + "core" + os.sep + "customcheck" + os.sep - ops = getCustCheckOpt(confpath) - fileToCheck = getCustomerCheckFiles(_path) - sz = len(fileToCheck) - if sz == 0: - print "[WARNING]no file to be checked in doCustomerCheck" - return "" - custout = '' - #print ops - for item in ops: - for i in range(0,sz): - cmd = "%s %s"%(custpath+item,fileToCheck[i]) - #print cmd - (status,output_tmp)=commands.getstatusoutput(cmd) - for ln in output_tmp.split("\n"): - #print ln - if ln.find("***") != -1: - custout += (ln+"\n") - - #print custout - return custout - -def getCustCheckOpt(path): - _opt=[] - conf = ConfigParser.ConfigParser() - conf.read(path) - for item in conf.options('command'): - if conf.get('command',item) == "true": - _opt.append(item) - return _opt - -if __name__ == "__main__": - try: - #checkJavaExist() - #checkPythonExist() - #print "check enviroment ok" - if len(sys.argv) < 3: - usage() - raise Exception("arg number error!") - outfile=sys.argv[1] - if os.path.exists(outfile): - raise Exception('%s already exist!In order to avoid overwrite the file,please change a none-exist file!'%(outfile)) - blackpath = os.path.dirname(__file__) + os.sep + "conf" + os.sep + "ignore.list" - filepath = sys.argv[2:] - output1 = doJsHint(filepath) - output2 = doCustomerCheck(filepath) - output = output1 + output2 - if output != "": - ts = genReport(0,output,blackpath,outfile,htmlMap) - else: - print "[WARNING]%s"%("no error detected") - clearTmpFiles() - except Exception,err: - print "[FATAL]%s"%(err) - clearTmpFiles() - sys.exit(1) diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/jshint.js b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/jshint.js deleted file mode 100644 index 9b08c0df..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/jshint.js +++ /dev/null @@ -1,4278 +0,0 @@ -/*! - * JSHint, by JSHint Community. - * - * Licensed under the same slightly modified MIT license that JSLint is. - * It stops evil-doers everywhere. - * - * JSHint is a derivative work of JSLint: - * - * Copyright (c) 2002 Douglas Crockford (www.JSLint.com) - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * The Software shall be used for Good, not Evil. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * JSHint was forked from 2010-12-16 edition of JSLint. - * - */ - -/* - JSHINT is a global function. It takes two parameters. - - var myResult = JSHINT(source, option); - - The first parameter is either a string or an array of strings. If it is a - string, it will be split on '\n' or '\r'. If it is an array of strings, it - is assumed that each string represents one line. The source can be a - JavaScript text or a JSON text. - - The second parameter is an optional object of options which control the - operation of JSHINT. Most of the options are booleans: They are all - optional and have a default value of false. One of the options, predef, - can be an array of names, which will be used to declare global variables, - or an object whose keys are used as global names, with a boolean value - that determines if they are assignable. - - If it checks out, JSHINT returns true. Otherwise, it returns false. - - If false, you can inspect JSHINT.errors to find out the problems. - JSHINT.errors is an array of objects containing these members: - - { - line : The line (relative to 0) at which the lint was found - character : The character (relative to 0) at which the lint was found - reason : The problem - evidence : The text line in which the problem occurred - raw : The raw message before the details were inserted - a : The first detail - b : The second detail - c : The third detail - d : The fourth detail - } - - If a fatal error was found, a null will be the last element of the - JSHINT.errors array. - - You can request a Function Report, which shows all of the functions - and the parameters and vars that they use. This can be used to find - implied global variables and other problems. The report is in HTML and - can be inserted in an HTML . - - var myReport = JSHINT.report(limited); - - If limited is true, then the report will be limited to only errors. - - You can request a data structure which contains JSHint's results. - - var myData = JSHINT.data(); - - It returns a structure with this form: - - { - errors: [ - { - line: NUMBER, - character: NUMBER, - reason: STRING, - evidence: STRING - } - ], - functions: [ - name: STRING, - line: NUMBER, - last: NUMBER, - param: [ - STRING - ], - closure: [ - STRING - ], - var: [ - STRING - ], - exception: [ - STRING - ], - outer: [ - STRING - ], - unused: [ - STRING - ], - global: [ - STRING - ], - label: [ - STRING - ] - ], - globals: [ - STRING - ], - member: { - STRING: NUMBER - }, - unuseds: [ - { - name: STRING, - line: NUMBER - } - ], - implieds: [ - { - name: STRING, - line: NUMBER - } - ], - urls: [ - STRING - ], - json: BOOLEAN - } - - Empty arrays will not be included. - -*/ - -/*jshint - evil: false, nomen: false, onevar: true, regexp: false, strict: false, boss: true, eqeqeq : false,bitwise: false,newcap: false,white: false, asi: true,trailing: false,funcscope: false,noarg:true,sub:true,loopfunc:true, -onevar: true, esnext: true,debug: false,laxbreak: trueundef: true, maxlen: 100, indent:4 -*/ - -/*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)", - "(breakage)", "(context)", "(error)", "(global)", "(identifier)", "(last)", - "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)", - "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==", - "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax, - __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio, - Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas, - CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date, - Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag, - E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event, - Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form, - FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey, - HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement, - HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement, - HTMLDivElement, HTMLDListElement, HTMLFieldSetElement, - HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement, - HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement, - HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement, - HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement, - HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement, - HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement, - HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement, - HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement, - HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement, - HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement, - HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement - Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array, - Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E, - MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native, - NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI, - POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError, - Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation, - SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion, - ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller, - Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables, - SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template, - Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL, - VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, - XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a, - addEventListener, address, alert, apply, applicationCache, arguments, arity, - asi, b, bitwise, block, blur, boolOptions, boss, browser, c, call, callee, - caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout, - close, closed, closure, comment, condition, confirm, console, constructor, - content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI, - decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document, - dojo, dijit, dojox, define, edition, else, emit, encodeURI, encodeURIComponent, - entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil, - ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus, - forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions, - g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict, - hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include, - indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray, - isDigit, isFinite, isNaN, iterator, java, join, jshint, - JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, - latedef, lbp, led, left, length, line, load, loadClass, localStorage, location, - log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy, - moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen, - nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus, - onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param, - parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt, - proto, prototype, prototypejs, push, quit, range, raw, reach, reason, regexp, - readFile, readUrl, regexdash, removeEventListener, replace, report, require, - reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right, - runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, - send, serialize, sessionStorage, setInterval, setTimeout, shift, slice, sort,spawn, - split, stack, status, start, strict, sub, substr, supernew, shadow, supplant, sum, - sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, type, - typeOf, Uint16Array, Uint32Array, Uint8Array, undef, unused, urls, validthis, value, valueOf, - var, version, WebSocket, white, window, Worker, wsh*/ - -/*global exports: false */ - -// We build the application inside a function so that we produce only a single -// global variable. That function will be invoked immediately, and its return -// value is the JSHINT function itself. - -var JSHINT = (function () { - "use strict"; - - var anonname, // The guessed name for anonymous functions. - -// These are operators that should not be used with the ! operator. - - bang = { - '<' : true, - '<=' : true, - '==' : true, - '===': true, - '!==': true, - '!=' : true, - '>' : true, - '>=' : true, - '+' : true, - '-' : true, - '*' : true, - '/' : true, - '%' : true - }, - - // These are the JSHint boolean options. - boolOptions = { - asi : true, // if automatic semicolon insertion should be tolerated - bitwise : true, // if bitwise operators should not be allowed - boss : true, // if advanced usage of assignments should be allowed - browser : true, // if the standard browser globals should be predefined - couch : true, // if CouchDB globals should be predefined - curly : true, // if curly braces around all blocks should be required - debug : true, // if debugger statements should be allowed - devel : true, // if logging globals should be predefined (console, - // alert, etc.) - dojo : true, // if Dojo Toolkit globals should be predefined - eqeqeq : true, // if === should be required - eqnull : true, // if == null comparisons should be tolerated - es5 : true, // if ES5 syntax should be allowed - esnext : true, // if es.next specific syntax should be allowed - evil : true, // if eval should be allowed - expr : true, // if ExpressionStatement should be allowed as Programs - forin : true, // if for in statements must filter - funcscope : true, // if only function scope should be used for scope tests - globalstrict: true, // if global "use strict"; should be allowed (also - // enables 'strict') - immed : true, // if immediate invocations must be wrapped in parens - iterator : true, // if the `__iterator__` property should be allowed - jquery : true, // if jQuery globals should be predefined - lastsemic : true, // if semicolons may be ommitted for the trailing - // statements inside of a one-line blocks. - latedef : true, // if the use before definition should not be tolerated - laxbreak : true, // if line breaks should not be checked - loopfunc : true, // if functions should be allowed to be defined within - // loops - mootools : true, // if MooTools globals should be predefined - multistr : true, // allow multiline strings - newcap : true, // if constructor names must be capitalized - noarg : true, // if arguments.caller and arguments.callee should be - // disallowed - node : true, // if the Node.js environment globals should be - // predefined - noempty : true, // if empty blocks should be disallowed - nonew : true, // if using `new` for side-effects should be disallowed - nonstandard : true, // if non-standard (but widely adopted) globals should - // be predefined - nomen : true, // if names should be checked - onevar : true, // if only one var statement per function should be - // allowed - onecase : true, // if one case switch statements should be allowed - passfail : true, // if the scan should stop on first error - plusplus : true, // if increment/decrement should not be allowed - proto : true, // if the `__proto__` property should be allowed - prototypejs : true, // if Prototype and Scriptaculous globals should be - // predefined - regexdash : true, // if unescaped first/last dash (-) inside brackets - // should be tolerated - regexp : true, // if the . should not be allowed in regexp literals - rhino : true, // if the Rhino environment globals should be predefined - undef : true, // if variables should be declared before used - scripturl : true, // if script-targeted URLs should be tolerated - shadow : true, // if variable shadowing should be tolerated - strict : true, // require the "use strict"; pragma - sub : true, // if all forms of subscript notation are tolerated - supernew : true, // if `new function () { ... };` and `new Object;` - // should be tolerated - trailing : true, // if trailing whitespace rules apply - validthis : true, // if 'this' inside a non-constructor function is valid. - // This is a function scoped option only. - white : true, // if strict whitespace rules apply - wsh : true // if the Windows Scripting Host environment globals - // should be predefined - }, - - // browser contains a set of global names which are commonly provided by a - // web browser environment. - browser = { - ArrayBuffer : false, - ArrayBufferView : false, - Audio : false, - addEventListener : false, - applicationCache : false, - blur : false, - clearInterval : false, - clearTimeout : false, - close : false, - closed : false, - DataView : false, - defaultStatus : false, - document : false, - event : false, - FileReader : false, - Float32Array : false, - Float64Array : false, - FormData : false, - focus : false, - frames : false, - getComputedStyle : false, - HTMLElement : false, - HTMLAnchorElement : false, - HTMLBaseElement : false, - HTMLBlockquoteElement : false, - HTMLBodyElement : false, - HTMLBRElement : false, - HTMLButtonElement : false, - HTMLCanvasElement : false, - HTMLDirectoryElement : false, - HTMLDivElement : false, - HTMLDListElement : false, - HTMLFieldSetElement : false, - HTMLFontElement : false, - HTMLFormElement : false, - HTMLFrameElement : false, - HTMLFrameSetElement : false, - HTMLHeadElement : false, - HTMLHeadingElement : false, - HTMLHRElement : false, - HTMLHtmlElement : false, - HTMLIFrameElement : false, - HTMLImageElement : false, - HTMLInputElement : false, - HTMLIsIndexElement : false, - HTMLLabelElement : false, - HTMLLayerElement : false, - HTMLLegendElement : false, - HTMLLIElement : false, - HTMLLinkElement : false, - HTMLMapElement : false, - HTMLMenuElement : false, - HTMLMetaElement : false, - HTMLModElement : false, - HTMLObjectElement : false, - HTMLOListElement : false, - HTMLOptGroupElement : false, - HTMLOptionElement : false, - HTMLParagraphElement : false, - HTMLParamElement : false, - HTMLPreElement : false, - HTMLQuoteElement : false, - HTMLScriptElement : false, - HTMLSelectElement : false, - HTMLStyleElement : false, - HTMLTableCaptionElement : false, - HTMLTableCellElement : false, - HTMLTableColElement : false, - HTMLTableElement : false, - HTMLTableRowElement : false, - HTMLTableSectionElement : false, - HTMLTextAreaElement : false, - HTMLTitleElement : false, - HTMLUListElement : false, - HTMLVideoElement : false, - history : false, - Int16Array : false, - Int32Array : false, - Int8Array : false, - Image : false, - length : false, - localStorage : false, - location : false, - moveBy : false, - moveTo : false, - name : false, - navigator : false, - onbeforeunload : true, - onblur : true, - onerror : true, - onfocus : true, - onload : true, - onresize : true, - onunload : true, - open : false, - openDatabase : false, - opener : false, - Option : false, - parent : false, - print : false, - removeEventListener : false, - resizeBy : false, - resizeTo : false, - screen : false, - scroll : false, - scrollBy : false, - scrollTo : false, - sessionStorage : false, - setInterval : false, - setTimeout : false, - SharedWorker : false, - status : false, - top : false, - Uint16Array : false, - Uint32Array : false, - Uint8Array : false, - WebSocket : false, - window : false, - Worker : false, - XMLHttpRequest : false, - XPathEvaluator : false, - XPathException : false, - XPathExpression : false, - XPathNamespace : false, - XPathNSResolver : false, - XPathResult : false - }, - - couch = { - "require" : false, - respond : false, - getRow : false, - emit : false, - send : false, - start : false, - sum : false, - log : false, - exports : false, - module : false - }, - - devel = { - alert : false, - confirm : false, - console : false, - Debug : false, - opera : false, - prompt : false - }, - - dojo = { - dojo : false, - dijit : false, - dojox : false, - define : false, - "require" : false - }, - - escapes = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '/' : '\\/', - '\\': '\\\\' - }, - - funct, // The current function - - functionicity = [ - 'closure', 'exception', 'global', 'label', - 'outer', 'unused', 'var' - ], - - functions, // All of the functions - - global, // The global scope - implied, // Implied globals - inblock, - indent, - jsonmode, - - jquery = { - '$' : false, - jQuery : false - }, - - lines, - lookahead, - member, - membersOnly, - - mootools = { - '$' : false, - '$$' : false, - Assets : false, - Browser : false, - Chain : false, - Class : false, - Color : false, - Cookie : false, - Core : false, - Document : false, - DomReady : false, - DOMReady : false, - Drag : false, - Element : false, - Elements : false, - Event : false, - Events : false, - Fx : false, - Group : false, - Hash : false, - HtmlTable : false, - Iframe : false, - IframeShim : false, - InputValidator : false, - instanceOf : false, - Keyboard : false, - Locale : false, - Mask : false, - MooTools : false, - Native : false, - Options : false, - OverText : false, - Request : false, - Scroller : false, - Slick : false, - Slider : false, - Sortables : false, - Spinner : false, - Swiff : false, - Tips : false, - Type : false, - typeOf : false, - URI : false, - Window : false - }, - - nexttoken, - - node = { - __filename : false, - __dirname : false, - Buffer : false, - console : false, - exports : false, - GLOBAL : false, - global : false, - module : false, - process : false, - require : false, - setTimeout : false, - clearTimeout : false, - setInterval : false, - clearInterval : false - }, - - noreach, - option, - predefined, // Global variables defined by option - prereg, - prevtoken, - - prototypejs = { - '$' : false, - '$$' : false, - '$A' : false, - '$F' : false, - '$H' : false, - '$R' : false, - '$break' : false, - '$continue' : false, - '$w' : false, - Abstract : false, - Ajax : false, - Class : false, - Enumerable : false, - Element : false, - Event : false, - Field : false, - Form : false, - Hash : false, - Insertion : false, - ObjectRange : false, - PeriodicalExecuter: false, - Position : false, - Prototype : false, - Selector : false, - Template : false, - Toggle : false, - Try : false, - Autocompleter : false, - Builder : false, - Control : false, - Draggable : false, - Draggables : false, - Droppables : false, - Effect : false, - Sortable : false, - SortableObserver : false, - Sound : false, - Scriptaculous : false - }, - - rhino = { - defineClass : false, - deserialize : false, - gc : false, - help : false, - importPackage: false, - "java" : false, - load : false, - loadClass : false, - print : false, - quit : false, - readFile : false, - readUrl : false, - runCommand : false, - seal : false, - serialize : false, - spawn : false, - sync : false, - toint32 : false, - version : false - }, - - scope, // The current scope - src, - stack, - - // standard contains the global names that are provided by the - // ECMAScript standard. - standard = { - Array : false, - Boolean : false, - Date : false, - decodeURI : false, - decodeURIComponent : false, - encodeURI : false, - encodeURIComponent : false, - Error : false, - 'eval' : false, - EvalError : false, - Function : false, - hasOwnProperty : false, - isFinite : false, - isNaN : false, - JSON : false, - Math : false, - Number : false, - Object : false, - parseInt : false, - parseFloat : false, - RangeError : false, - ReferenceError : false, - RegExp : false, - String : false, - SyntaxError : false, - TypeError : false, - URIError : false - }, - - // widely adopted global names that are not part of ECMAScript standard - nonstandard = { - escape : false, - unescape : false - }, - - standard_member = { - E : true, - LN2 : true, - LN10 : true, - LOG2E : true, - LOG10E : true, - MAX_VALUE : true, - MIN_VALUE : true, - NEGATIVE_INFINITY : true, - PI : true, - POSITIVE_INFINITY : true, - SQRT1_2 : true, - SQRT2 : true - }, - - directive, - syntax = {}, - tab, - token, - urls, - useESNextSyntax, - warnings, - - wsh = { - ActiveXObject : true, - Enumerator : true, - GetObject : true, - ScriptEngine : true, - ScriptEngineBuildVersion : true, - ScriptEngineMajorVersion : true, - ScriptEngineMinorVersion : true, - VBArray : true, - WSH : true, - WScript : true, - XDomainRequest : true - }; - - // Regular expressions. Some of these are stupidly long. - var ax, cx, tx, nx, nxg, lx, ix, jx, ft; - (function () { - /*jshint maxlen:300 */ - - // unsafe comment or string - ax = /@cc|<\/?|script|\]\s*\]|<\s*!|</i; - - // unsafe characters that are silently deleted by one or more browsers - cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; - - // token - tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/; - - // characters in strings that need escapement - nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; - nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; - - // star slash - lx = /\*\/|\/\*/; - - // identifier - ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; - - // javascript url - jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i; - - // catches /* falls through */ comments - ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/; - }()); - - function F() {} // Used by Object.create - - function is_own(object, name) { - -// The object.hasOwnProperty method fails when the property under consideration -// is named 'hasOwnProperty'. So we have to use this more convoluted form. - - return Object.prototype.hasOwnProperty.call(object, name); - } - -// Provide critical ES5 functions to ES3. - - if (typeof Array.isArray !== 'function') { - Array.isArray = function (o) { - return Object.prototype.toString.apply(o) === '[object Array]'; - }; - } - - if (typeof Object.create !== 'function') { - Object.create = function (o) { - F.prototype = o; - return new F(); - }; - } - - if (typeof Object.keys !== 'function') { - Object.keys = function (o) { - var a = [], k; - for (k in o) { - if (is_own(o, k)) { - a.push(k); - } - } - return a; - }; - } - -// Non standard methods - - if (typeof String.prototype.entityify !== 'function') { - String.prototype.entityify = function () { - return this - .replace(/&/g, '&') - .replace(//g, '>'); - }; - } - - if (typeof String.prototype.isAlpha !== 'function') { - String.prototype.isAlpha = function () { - return (this >= 'a' && this <= 'z\uffff') || - (this >= 'A' && this <= 'Z\uffff'); - }; - } - - if (typeof String.prototype.isDigit !== 'function') { - String.prototype.isDigit = function () { - return (this >= '0' && this <= '9'); - }; - } - - if (typeof String.prototype.supplant !== 'function') { - String.prototype.supplant = function (o) { - return this.replace(/\{([^{}]*)\}/g, function (a, b) { - var r = o[b]; - return typeof r === 'string' || typeof r === 'number' ? r : a; - }); - }; - } - - if (typeof String.prototype.name !== 'function') { - String.prototype.name = function () { - -// If the string looks like an identifier, then we can return it as is. -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can simply slap some quotes around it. -// Otherwise we must also replace the offending characters with safe -// sequences. - - if (ix.test(this)) { - return this; - } - if (nx.test(this)) { - return '"' + this.replace(nxg, function (a) { - var c = escapes[a]; - if (c) { - return c; - } - return '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4); - }) + '"'; - } - return '"' + this + '"'; - }; - } - - - function combine(t, o) { - var n; - for (n in o) { - if (is_own(o, n)) { - t[n] = o[n]; - } - } - } - - function assume() { - if (option.couch) { - combine(predefined, couch); - } - - if (option.rhino) { - combine(predefined, rhino); - } - - if (option.prototypejs) { - combine(predefined, prototypejs); - } - - if (option.node) { - combine(predefined, node); - } - - if (option.devel) { - combine(predefined, devel); - } - - if (option.dojo) { - combine(predefined, dojo); - } - - if (option.browser) { - combine(predefined, browser); - } - - if (option.nonstandard) { - combine(predefined, nonstandard); - } - - if (option.jquery) { - combine(predefined, jquery); - } - - if (option.mootools) { - combine(predefined, mootools); - } - - if (option.wsh) { - combine(predefined, wsh); - } - - if (option.esnext) { - useESNextSyntax(); - } - - if (option.globalstrict && option.strict !== false) { - option.strict = true; - } - } - - - // Produce an error warning. - function quit(message, line, chr) { - var percentage = Math.floor((line / lines.length) * 100); - - throw { - name: 'JSHintError', - line: line, - character: chr, - message: message + " (" + percentage + "% scanned)." - }; - } - - function warning(m, t, a, b, c, d) { - var ch, l, w; - t = t || nexttoken; - if (t.id === '(end)') { // `~ - t = token; - } - l = t.line || 0; - ch = t.from || 0; - w = { - id: '(error)', - raw: m, - evidence: lines[l - 1] || '', - line: l, - character: ch, - a: a, - b: b, - c: c, - d: d - }; - w.reason = m.supplant(w); - JSHINT.errors.push(w); - if (option.passfail) { - quit('Stopping. ', l, ch); - } - warnings += 1; - if (warnings >= option.maxerr) { - quit("Too many errors.", l, ch); - } - return w; - } - - function warningAt(m, l, ch, a, b, c, d) { - return warning(m, { - line: l, - from: ch - }, a, b, c, d); - } - - function error(m, t, a, b, c, d) { - var w = warning(m, t, a, b, c, d); - } - - function errorAt(m, l, ch, a, b, c, d) { - return error(m, { - line: l, - from: ch - }, a, b, c, d); - } - - - -// lexical analysis and token construction - - var lex = (function lex() { - var character, from, line, s; - -// Private lex methods - - function nextLine() { - var at, - tw; // trailing whitespace check - - if (line >= lines.length) - return false; - - character = 1; - s = lines[line]; - line += 1; - at = s.search(/ \t|\t /); - - if (at >= 0) - warningAt("Mixed spaces and tabs.", line, at + 1); - - s = s.replace(/\t/g, tab); - at = s.search(cx); - - if (at >= 0) - warningAt("Unsafe character.", line, at); - - if (option.maxlen && option.maxlen < s.length) - warningAt("Line too long.", line, s.length); - - // Check for trailing whitespaces - tw = /\s+$/.test(s); - if (option.trailing && tw && !/^\s+$/.test(s)) { - warningAt("Trailing whitespace.", line, tw); - } - return true; - } - -// Produce a token object. The token inherits from a syntax symbol. - - function it(type, value) { - var i, t; - if (type === '(color)' || type === '(range)') { - t = {type: type}; - } else if (type === '(punctuator)' || - (type === '(identifier)' && is_own(syntax, value))) { - t = syntax[value] || syntax['(error)']; - } else { - t = syntax[type]; - } - t = Object.create(t); - if (type === '(string)' || type === '(range)') { - if (!option.scripturl && jx.test(value)) { - warningAt("Script URL.", line, from); - } - } - if (type === '(identifier)') { - t.identifier = true; - if (value === '__proto__' && !option.proto) { - warningAt("The '{a}' property is deprecated.", - line, from, value); - } else if (value === '__iterator__' && !option.iterator) { - warningAt("'{a}' is only available in JavaScript 1.7.", - line, from, value); - } else if (option.nomen && (value.charAt(0) === '_' || - value.charAt(value.length - 1) === '_')) { - if (!option.node || token.id == '.' || - (value != '__dirname' && value != '__filename')) { - warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value); - } - } - } - t.value = value; - t.line = line; - t.character = character; - t.from = from; - i = t.id; - if (i !== '(endline)') { - prereg = i && - (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || - i === 'return' || - i === 'case'); - } - return t; - } - - // Public lex methods - return { - init: function (source) { - if (typeof source === 'string') { - lines = source - .replace(/\r\n/g, '\n') - .replace(/\r/g, '\n') - .split('\n'); - } else { - lines = source; - } - - // If the first line is a shebang (#!), make it a blank and move on. - // Shebangs are used by Node scripts. - if (lines[0] && lines[0].substr(0, 2) == '#!') - lines[0] = ''; - - line = 0; - nextLine(); - from = 1; - }, - - range: function (begin, end) { - var c, value = ''; - from = character; - if (s.charAt(0) !== begin) { - errorAt("Expected '{a}' and instead saw '{b}'.", - line, character, begin, s.charAt(0)); - } - for (;;) { - s = s.slice(1); - character += 1; - c = s.charAt(0); - switch (c) { - case '': - errorAt("Missing '{a}'.", line, character, c); - break; - case end: - s = s.slice(1); - character += 1; - return it('(range)', value); - case '\\': - warningAt("Unexpected '{a}'.", line, character, c); - } - value += c; - } - - }, - - - // token -- this is called by advance to get the next token - token: function () { - var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange; - - function match(x) { - var r = x.exec(s), r1; - if (r) { - l = r[0].length; - r1 = r[1]; - c = r1.charAt(0); - s = s.substr(l); - from = character + l - r1.length; - character += l; - return r1; - } - } - - function string(x) { - var c, j, r = '', allowNewLine = false; - - if (jsonmode && x !== '"') { - warningAt("Strings must use doublequote.", - line, character); - } - - function esc(n) { - var i = parseInt(s.substr(j + 1, n), 16); - j += n; - if (i >= 32 && i <= 126 && - i !== 34 && i !== 92 && i !== 39) { - warningAt("Unnecessary escapement.", line, character); - } - character += n; - c = String.fromCharCode(i); - } - j = 0; - for (;;) { - while (j >= s.length) { - j = 0; - if (allowNewLine) { - allowNewLine = false; - } else { - warningAt("Unclosed string.", line, from); - } - if (!nextLine()) { - errorAt("Unclosed string.", line, from); - } - } - c = s.charAt(j); - if (c === x) { - character += 1; - s = s.substr(j + 1); - return it('(string)', r, x); - } - if (c < ' ') { - if (c === '\n' || c === '\r') { - break; - } - warningAt("Control character in string: {a}.", - line, character + j, s.slice(0, j)); - } else if (c === '\\') { - j += 1; - character += 1; - c = s.charAt(j); - switch (c) { - case '\\': - case '"': - case '/': - break; - case '\'': - if (jsonmode) { - warningAt("Avoid \\'.", line, character); - } - break; - case 'b': - c = '\b'; - break; - case 'f': - c = '\f'; - break; - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'u': - esc(4); - break; - case 'v': - if (jsonmode) { - warningAt("Avoid \\v.", line, character); - } - c = '\v'; - break; - case 'x': - if (jsonmode) { - warningAt("Avoid \\x-.", line, character); - } - esc(2); - break; - case '': - // last character is escape character - // always allow new line if escaped, but show - // warning if option is not set - allowNewLine = true; - if (option.multistr) { - if (jsonmode) { - warningAt("Avoid EOL escapement.", line, character); - } - c = ''; - character -= 1; - break; - } - warningAt("Bad escapement of EOL. Use option multistr if needed.", - line, character); - break; - default: - warningAt("Bad escapement.", line, character); - } - } - r += c; - character += 1; - j += 1; - } - } - - for (;;) { - if (!s) { - return it(nextLine() ? '(endline)' : '(end)', ''); - } - t = match(tx); - if (!t) { - t = ''; - c = ''; - while (s && s < '!') { - s = s.substr(1); - } - if (s) { - errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1)); - } - } else { - - // identifier - - if (c.isAlpha() || c === '_' || c === '$') { - return it('(identifier)', t); - } - - // number - - if (c.isDigit()) { - if (!isFinite(Number(t))) { - warningAt("Bad number '{a}'.", - line, character, t); - } - if (s.substr(0, 1).isAlpha()) { - warningAt("Missing space after '{a}'.", - line, character, t); - } - if (c === '0') { - d = t.substr(1, 1); - if (d.isDigit()) { - if (token.id !== '.') { - warningAt("Don't use extra leading zeros '{a}'.", - line, character, t); - } - } else if (jsonmode && (d === 'x' || d === 'X')) { - warningAt("Avoid 0x-. '{a}'.", - line, character, t); - } - } - if (t.substr(t.length - 1) === '.') { - warningAt( -"A trailing decimal point can be confused with a dot '{a}'.", line, character, t); - } - return it('(number)', t); - } - switch (t) { - - // string - - case '"': - case "'": - return string(t); - - // // comment - - case '//': - if (src) { - warningAt("Unexpected comment.", line, character); - } - s = ''; - token.comment = true; - break; - - // /* comment - - case '/*': - if (src) { - warningAt("Unexpected comment.", line, character); - } - for (;;) { - i = s.search(lx); - if (i >= 0) { - break; - } - if (!nextLine()) { - errorAt("Unclosed comment.", line, character); - } - } - character += i + 2; - if (s.substr(i, 1) === '/') { - errorAt("Nested comment.", line, character); - } - s = s.substr(i + 2); - token.comment = true; - break; - - // /*members /*jshint /*global - - case '/*members': - case '/*member': - case '/*jshint': - case '/*jslint': - case '/*global': - case '*/': - return { - value: t, - type: 'special', - line: line, - character: character, - from: from - }; - - case '': - break; - // / - case '/': - if (token.id === '/=') { - errorAt( -"A regular expression literal can be confused with '/='.", line, from); - } - if (prereg) { - depth = 0; - captures = 0; - l = 0; - for (;;) { - b = true; - c = s.charAt(l); - l += 1; - switch (c) { - case '': - errorAt("Unclosed regular expression.", - line, from); - return; - case '/': - if (depth > 0) { - warningAt("Unescaped '{a}'.", - line, from + l, '/'); - } - c = s.substr(0, l - 1); - q = { - g: true, - i: true, - m: true - }; - while (q[s.charAt(l)] === true) { - q[s.charAt(l)] = false; - l += 1; - } - character += l; - s = s.substr(l); - q = s.charAt(0); - if (q === '/' || q === '*') { - errorAt("Confusing regular expression.", - line, from); - } - return it('(regexp)', c); - case '\\': - c = s.charAt(l); - if (c < ' ') { - warningAt( -"Unexpected control character in regular expression.", line, from + l); - } else if (c === '<') { - warningAt( -"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); - } - l += 1; - break; - case '(': - depth += 1; - b = false; - if (s.charAt(l) === '?') { - l += 1; - switch (s.charAt(l)) { - case ':': - case '=': - case '!': - l += 1; - break; - default: - warningAt( -"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); - } - } else { - captures += 1; - } - break; - case '|': - b = false; - break; - case ')': - if (depth === 0) { - warningAt("Unescaped '{a}'.", - line, from + l, ')'); - } else { - depth -= 1; - } - break; - case ' ': - q = 1; - while (s.charAt(l) === ' ') { - l += 1; - q += 1; - } - if (q > 1) { - warningAt( -"Spaces are hard to count. Use {{a}}.", line, from + l, q); - } - break; - case '[': - c = s.charAt(l); - if (c === '^') { - l += 1; - if (option.regexp) { - warningAt("Insecure '{a}'.", - line, from + l, c); - } else if (s.charAt(l) === ']') { - errorAt("Unescaped '{a}'.", - line, from + l, '^'); - } - } - if (c === ']') { - warningAt("Empty class.", line, - from + l - 1); - } - isLiteral = false; - isInRange = false; -klass: do { - c = s.charAt(l); - l += 1; - switch (c) { - case '[': - case '^': - warningAt("Unescaped '{a}'.", - line, from + l, c); - if (isInRange) { - isInRange = false; - } else { - isLiteral = true; - } - break; - case '-': - if (isLiteral && !isInRange) { - isLiteral = false; - isInRange = true; - } else if (isInRange) { - isInRange = false; - } else if (s.charAt(l) === ']') { - isInRange = true; - } else { - if (option.regexdash !== (l === 2 || (l === 3 && - s.charAt(2) === '^'))) { - warningAt("Unescaped '{a}'.", - line, from + l - 1, '-'); - } - isLiteral = true; - } - break; - case ']': - if (isInRange && !option.regexdash) { - warningAt("Unescaped '{a}'.", - line, from + l - 1, '-'); - } - break klass; - case '\\': - c = s.charAt(l); - if (c < ' ') { - warningAt( -"Unexpected control character in regular expression.", line, from + l); - } else if (c === '<') { - warningAt( -"Unexpected escaped character '{a}' in regular expression.", line, from + l, c); - } - l += 1; - - // \w, \s and \d are never part of a character range - if (/[wsd]/i.test(c)) { - if (isInRange) { - warningAt("Unescaped '{a}'.", - line, from + l, '-'); - isInRange = false; - } - isLiteral = false; - } else if (isInRange) { - isInRange = false; - } else { - isLiteral = true; - } - break; - case '/': - warningAt("Unescaped '{a}'.", - line, from + l - 1, '/'); - - if (isInRange) { - isInRange = false; - } else { - isLiteral = true; - } - break; - case '<': - if (isInRange) { - isInRange = false; - } else { - isLiteral = true; - } - break; - default: - if (isInRange) { - isInRange = false; - } else { - isLiteral = true; - } - } - } while (c); - break; - case '.': - if (option.regexp) { - warningAt("Insecure '{a}'.", line, - from + l, c); - } - break; - case ']': - case '?': - case '{': - case '}': - case '+': - case '*': - warningAt("Unescaped '{a}'.", line, - from + l, c); - } - if (b) { - switch (s.charAt(l)) { - case '?': - case '+': - case '*': - l += 1; - if (s.charAt(l) === '?') { - l += 1; - } - break; - case '{': - l += 1; - c = s.charAt(l); - if (c < '0' || c > '9') { - warningAt( -"Expected a number and instead saw '{a}'.", line, from + l, c); - } - l += 1; - low = +c; - for (;;) { - c = s.charAt(l); - if (c < '0' || c > '9') { - break; - } - l += 1; - low = +c + (low * 10); - } - high = low; - if (c === ',') { - l += 1; - high = Infinity; - c = s.charAt(l); - if (c >= '0' && c <= '9') { - l += 1; - high = +c; - for (;;) { - c = s.charAt(l); - if (c < '0' || c > '9') { - break; - } - l += 1; - high = +c + (high * 10); - } - } - } - if (s.charAt(l) !== '}') { - warningAt( -"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); - } else { - l += 1; - } - if (s.charAt(l) === '?') { - l += 1; - } - if (low > high) { - warningAt( -"'{a}' should not be greater than '{b}'.", line, from + l, low, high); - } - } - } - } - c = s.substr(0, l - 1); - character += l; - s = s.substr(l); - return it('(regexp)', c); - } - return it('(punctuator)', t); - - // punctuator - - case '#': - return it('(punctuator)', t); - default: - return it('(punctuator)', t); - } - } - } - } - }; - }()); - - - function addlabel(t, type) { - - if (t === 'hasOwnProperty') { - warning("'hasOwnProperty' is a really bad name."); - } - -// Define t in the current function in the current scope. - - if (is_own(funct, t) && !funct['(global)']) { - if (funct[t] === true) { - if (option.latedef) - warning("'{a}' was used before it was defined.", nexttoken, t); - } else { - if (!option.shadow) - warning("'{a}' is already defined.", nexttoken, t); - } - } - - funct[t] = type; - if (funct['(global)']) { - global[t] = funct; - if (is_own(implied, t)) { - if (option.latedef) - warning("'{a}' was used before it was defined.", nexttoken, t); - delete implied[t]; - } - } else { - scope[t] = funct; - } - } - - - function doOption() { - var b, obj, filter, o = nexttoken.value, t, v; - switch (o) { - case '*/': - error("Unbegun comment."); - break; - case '/*members': - case '/*member': - o = '/*members'; - if (!membersOnly) { - membersOnly = {}; - } - obj = membersOnly; - break; - case '/*jshint': - case '/*jslint': - obj = option; - filter = boolOptions; - break; - case '/*global': - obj = predefined; - break; - default: - error("What?"); - } - t = lex.token(); -loop: for (;;) { - for (;;) { - if (t.type === 'special' && t.value === '*/') { - break loop; - } - if (t.id !== '(endline)' && t.id !== ',') { - break; - } - t = lex.token(); - } - if (t.type !== '(string)' && t.type !== '(identifier)' && - o !== '/*members') { - error("Bad option.", t); - } - v = lex.token(); - if (v.id === ':') { - v = lex.token(); - if (obj === membersOnly) { - error("Expected '{a}' and instead saw '{b}'.", - t, '*/', ':'); - } - if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.white = true; - obj.indent = b; - } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.maxerr = b; - } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) { - b = +v.value; - if (typeof b !== 'number' || !isFinite(b) || b <= 0 || - Math.floor(b) !== b) { - error("Expected a small integer and instead saw '{a}'.", - v, v.value); - } - obj.maxlen = b; - } else if (t.value == 'validthis') { - if (funct['(global)']) { - error("Option 'validthis' can't be used in a global scope."); - } else { - if (v.value === 'true' || v.value === 'false') - obj[t.value] = v.value === 'true'; - else - error("Bad option value.", v); - } - } else if (v.value === 'true') { - obj[t.value] = true; - } else if (v.value === 'false') { - obj[t.value] = false; - } else { - error("Bad option value.", v); - } - t = lex.token(); - } else { - if (o === '/*jshint' || o === '/*jslint') { - error("Missing option value.", t); - } - obj[t.value] = false; - t = v; - } - } - if (filter) { - assume(); - } - } - - -// We need a peek function. If it has an argument, it peeks that much farther -// ahead. It is used to distinguish -// for ( var i in ... -// from -// for ( var i = ... - - function peek(p) { - var i = p || 0, j = 0, t; - - while (j <= i) { - t = lookahead[j]; - if (!t) { - t = lookahead[j] = lex.token(); - } - j += 1; - } - return t; - } - - - -// Produce the next token. It looks for programming errors. - - function advance(id, t) { - switch (token.id) { - case '(number)': - if (nexttoken.id === '.') { - warning("A dot following a number can be confused with a decimal point.", token); - } - break; - case '-': - if (nexttoken.id === '-' || nexttoken.id === '--') { - warning("Confusing minusses."); - } - break; - case '+': - if (nexttoken.id === '+' || nexttoken.id === '++') { - warning("Confusing plusses."); - } - break; - } - - if (token.type === '(string)' || token.identifier) { - anonname = token.value; - } - - if (id && nexttoken.id !== id) { - if (t) { - if (nexttoken.id === '(end)') { - warning("Unmatched '{a}'.", t, t.id); - } else { - warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", - nexttoken, id, t.id, t.line, nexttoken.value); - } - } else if (nexttoken.type !== '(identifier)' || - nexttoken.value !== id) { - warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, id, nexttoken.value); - } - } - - prevtoken = token; - token = nexttoken; - for (;;) { - nexttoken = lookahead.shift() || lex.token(); - if (nexttoken.id === '(end)' || nexttoken.id === '(error)') { - return; - } - if (nexttoken.type === 'special') { - doOption(); - } else { - if (nexttoken.id !== '(endline)') { - break; - } - } - } - } - - -// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it -// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is -// like .nud except that it is only used on the first token of a statement. -// Having .fud makes it much easier to define statement-oriented languages like -// JavaScript. I retained Pratt's nomenclature. - -// .nud Null denotation -// .fud First null denotation -// .led Left denotation -// lbp Left binding power -// rbp Right binding power - -// They are elements of the parsing method called Top Down Operator Precedence. - - function expression(rbp, initial) { - var left, isArray = false; - - if (nexttoken.id === '(end)') - error("Unexpected early end of program.", token); - - advance(); - if (initial) { - anonname = 'anonymous'; - funct['(verb)'] = token.value; - } - if (initial === true && token.fud) { - left = token.fud(); - } else { - if (token.nud) { - left = token.nud(); - } else { - if (nexttoken.type === '(number)' && token.id === '.') { - warning("A leading decimal point can be confused with a dot: '.{a}'.", - token, nexttoken.value); - advance(); - return token; - } else { - error("Expected an identifier and instead saw '{a}'.", - token, token.id); - } - } - while (rbp < nexttoken.lbp) { - isArray = token.value == 'Array'; - advance(); - if (isArray && token.id == '(' && nexttoken.id == ')') - warning("Use the array literal notation [].", token); - if (token.led) { - left = token.led(left); - } else { - error("Expected an operator and instead saw '{a}'.", - token, token.id); - } - } - } - return left; - } - - -// Functions for conformance of style. - - function adjacent(left, right) { - left = left || token; - right = right || nexttoken; - if (option.white) { - if (left.character !== right.from && left.line === right.line) { - warning("Unexpected space after '{a}'.", right, left.value); - } - } - } - - function nobreak(left, right) { - left = left || token; - right = right || nexttoken; - if (option.white && (left.character !== right.from || left.line !== right.line)) { - warning("Unexpected space before '{a}'.", right, right.value); - } - } - - function nospace(left, right) { - left = left || token; - right = right || nexttoken; - if (option.white && !left.comment) { - if (left.line === right.line) { - adjacent(left, right); - } - } - } - - function nonadjacent(left, right) { - if (option.white) { - left = left || token; - right = right || nexttoken; - if (left.line === right.line && left.character === right.from) { - left.from += (left.character - left.from); - warning("Missing space after '{a}'.", - left, left.value); - } - } - } - - function nobreaknonadjacent(left, right) { - left = left || token; - right = right || nexttoken; - if (!option.laxbreak && left.line !== right.line) { - warning("Bad line breaking before '{a}'.", right, right.id); - } else if (option.white) { - left = left || token; - right = right || nexttoken; - if (left.character === right.from) { - left.from += (left.character - left.from); - warning("Missing space after '{a}'.", - left, left.value); - } - } - } - - function indentation(bias) { - var i; - if (option.white && nexttoken.id !== '(end)') { - i = indent + (bias || 0); - if (nexttoken.from !== i) { - warning( -"Expected '{a}' to have an indentation at {b} instead at {c}.", - nexttoken, nexttoken.value, i, nexttoken.from); - } - } - } - - function nolinebreak(t) { - t = t || token; - if (t.line !== nexttoken.line) { - warning("Line breaking error '{a}'.", t, t.value); - } - } - - - function comma() { - if (token.line !== nexttoken.line) { - if (!option.laxbreak) { - warning("Bad line breaking before '{a}'.", token, nexttoken.id); - } - } else if (token.character !== nexttoken.from && option.white) { - warning("Unexpected space after '{a}'.", nexttoken, token.value); - } - advance(','); - nonadjacent(token, nexttoken); - } - - -// Functional constructors for making the symbols that will be inherited by -// tokens. - - function symbol(s, p) { - var x = syntax[s]; - if (!x || typeof x !== 'object') { - syntax[s] = x = { - id: s, - lbp: p, - value: s - }; - } - return x; - } - - - function delim(s) { - return symbol(s, 0); - } - - - function stmt(s, f) { - var x = delim(s); - x.identifier = x.reserved = true; - x.fud = f; - return x; - } - - - function blockstmt(s, f) { - var x = stmt(s, f); - x.block = true; - return x; - } - - - function reserveName(x) { - var c = x.id.charAt(0); - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - x.identifier = x.reserved = true; - } - return x; - } - - - function prefix(s, f) { - var x = symbol(s, 150); - reserveName(x); - x.nud = (typeof f === 'function') ? f : function () { - this.right = expression(150); - this.arity = 'unary'; - if (this.id === '++' || this.id === '--') { - if (option.plusplus) { - warning("Unexpected use of '{a}'.", this, this.id); - } else if ((!this.right.identifier || this.right.reserved) && - this.right.id !== '.' && this.right.id !== '[') { - warning("Bad operand.", this); - } - } - return this; - }; - return x; - } - - - function type(s, f) { - var x = delim(s); - x.type = s; - x.nud = f; - return x; - } - - - function reserve(s, f) { - var x = type(s, f); - x.identifier = x.reserved = true; - return x; - } - - - function reservevar(s, v) { - return reserve(s, function () { - if (typeof v === 'function') { - v(this); - } - return this; - }); - } - - - function infix(s, f, p, w) { - var x = symbol(s, p); - reserveName(x); - x.led = function (left) { - if (!w) { - nobreaknonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - } - if (typeof f === 'function') { - return f(left, this); - } else { - this.left = left; - this.right = expression(p); - return this; - } - }; - return x; - } - - - function relation(s, f) { - var x = symbol(s, 100); - x.led = function (left) { - nobreaknonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - var right = expression(100); - if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { - warning("Use the isNaN function to compare with NaN.", this); - } else if (f) { - f.apply(this, [left, right]); - } - if (left.id === '!') { - warning("Confusing use of '{a}'.", left, '!'); - } - if (right.id === '!') { - warning("Confusing use of '{a}'.", left, '!'); - } - this.left = left; - this.right = right; - return this; - }; - return x; - } - - - function isPoorRelation(node) { - return node && - ((node.type === '(number)' && +node.value === 0) || - (node.type === '(string)' && node.value === '') || - (node.type === 'null' && !option.eqnull) || - node.type === 'true' || - node.type === 'false' || - node.type === 'undefined'); - } - - - function assignop(s, f) { - symbol(s, 20).exps = true; - return infix(s, function (left, that) { - var l; - that.left = left; - if (predefined[left.value] === false && - scope[left.value]['(global)'] === true) { - warning("Read only.", left); - } else if (left['function']) { - warning("'{a}' is a function.", left, left.value); - } - if (left) { - if (option.esnext && funct[left.value] === 'const') { - warning("Attempting to override '{a}' which is a constant", left, left.value); - } - if (left.id === '.' || left.id === '[') { - if (!left.left || left.left.value === 'arguments') { - warning('Bad assignment.', that); - } - that.right = expression(19); - return that; - } else if (left.identifier && !left.reserved) { - if (funct[left.value] === 'exception') { - warning("Do not assign to the exception parameter.", left); - } - that.right = expression(19); - return that; - } - if (left === syntax['function']) { - warning( -"Expected an identifier in an assignment and instead saw a function invocation.", - token); - } - } - error("Bad assignment.", that); - }, 20); - } - - - function bitwise(s, f, p) { - var x = symbol(s, p); - reserveName(x); - x.led = (typeof f === 'function') ? f : function (left) { - if (option.bitwise) { - warning("Unexpected use of '{a}'.", this, this.id); - } - this.left = left; - this.right = expression(p); - return this; - }; - return x; - } - - - function bitwiseassignop(s) { - symbol(s, 20).exps = true; - return infix(s, function (left, that) { - if (option.bitwise) { - warning("Unexpected use of '{a}'.", that, that.id); - } - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - if (left) { - if (left.id === '.' || left.id === '[' || - (left.identifier && !left.reserved)) { - expression(19); - return that; - } - if (left === syntax['function']) { - warning( -"Expected an identifier in an assignment, and instead saw a function invocation.", - token); - } - return that; - } - error("Bad assignment.", that); - }, 20); - } - - - function suffix(s, f) { - var x = symbol(s, 150); - x.led = function (left) { - if (option.plusplus) { - warning("Unexpected use of '{a}'.", this, this.id); - } else if ((!left.identifier || left.reserved) && - left.id !== '.' && left.id !== '[') { - warning("Bad operand.", this); - } - this.left = left; - return this; - }; - return x; - } - - - // fnparam means that this identifier is being defined as a function - // argument (see identifier()) - function optionalidentifier(fnparam) { - if (nexttoken.identifier) { - advance(); - if (token.reserved && !option.es5) { - // `undefined` as a function param is a common pattern to protect - // against the case when somebody does `undefined = true` and - // help with minification. More info: https://gist.github.com/315916 - if (!fnparam || token.value != 'undefined') { - warning("Expected an identifier and instead saw '{a}' (a reserved word).", - token, token.id); - } - } - return token.value; - } - } - - // fnparam means that this identifier is being defined as a function - // argument - function identifier(fnparam) { - var i = optionalidentifier(fnparam); - if (i) { - return i; - } - if (token.id === 'function' && nexttoken.id === '(') { - warning("Missing name in function declaration."); - } else { - error("Expected an identifier and instead saw '{a}'.", - nexttoken, nexttoken.value); - } - } - - - function reachable(s) { - var i = 0, t; - if (nexttoken.id !== ';' || noreach) { - return; - } - for (;;) { - t = peek(i); - if (t.reach) { - return; - } - if (t.id !== '(endline)') { - if (t.id === 'function') { - warning( -"Inner functions should be listed at the top of the outer function.", t); - break; - } - warning("Unreachable '{a}' after '{b}'.", t, t.value, s); - break; - } - i += 1; - } - } - - - function statement(noindent) { - var i = indent, r, s = scope, t = nexttoken; - -// We don't like the empty statement. - - if (t.id === ';') { - warning("Unnecessary semicolon.", t); - advance(';'); - return; - } - -// Is this a labelled statement? - - if (t.identifier && !t.reserved && peek().id === ':') { - advance(); - advance(':'); - scope = Object.create(s); - addlabel(t.value, 'label'); - if (!nexttoken.labelled) { - warning("Label '{a}' on {b} statement.", - nexttoken, t.value, nexttoken.value); - } - if (jx.test(t.value + ':')) { - warning("Label '{a}' looks like a javascript url.", - t, t.value); - } - nexttoken.label = t.value; - t = nexttoken; - } - -// Parse the statement. - - if (!noindent) { - indentation(); - } - r = expression(0, true); - - // Look for the final semicolon. - if (!t.block) { - if (!option.expr && (!r || !r.exps)) { - warning("Expected an assignment or function call and instead saw an expression.", - token); - } else if (option.nonew && r.id === '(' && r.left.id === 'new') { - warning("Do not use 'new' for side effects."); - } - - if (nexttoken.id !== ';') { - if (!option.asi) { - // If this is the last statement in a block that ends on - // the same line *and* option lastsemic is on, ignore the warning. - // Otherwise, complain about missing semicolon. - if (!option.lastsemic || nexttoken.id != '}' || - nexttoken.line != token.line) { - warningAt("Missing semicolon.", token.line, token.from + - token.value.length); - } - } - } else { - adjacent(token, nexttoken); - advance(';'); - nonadjacent(token, nexttoken); - } - } - -// Restore the indentation. - - indent = i; - scope = s; - return r; - } - - - function statements(startLine) { - var a = [], f, p; - - while (!nexttoken.reach && nexttoken.id !== '(end)') { - if (nexttoken.id === ';') { - warning("Unnecessary semicolon."); - advance(';'); - } else { - a.push(statement(startLine === nexttoken.line)); - } - } - return a; - } - - - /* - * read all directives - * recognizes a simple form of asi, but always - * warns, if it is used - */ - function directives() { - var i, p, pn; - - for (;;) { - if (nexttoken.id === "(string)") { - p = peek(0); - if (p.id === "(endline)") { - i = 1; - do { - pn = peek(i); - i = i + 1; - } while (pn.id === "(endline)"); - - if (pn.id !== ";") { - if (pn.id !== "(string)" && pn.id !== "(number)" && - pn.id !== "(regexp)" && pn.identifier !== true && - pn.id !== "}") { - break; - } - warning("Missing semicolon.", nexttoken); - } else { - p = pn; - } - } else if (p.id === "}") { - // directive with no other statements, warn about missing semicolon - warning("Missing semicolon.", p); - } else if (p.id !== ";") { - break; - } - - indentation(); - advance(); - if (directive[token.value]) { - warning("Unnecessary directive \"{a}\".", token, token.value); - } - - if (token.value === "use strict") { - option.newcap = true; - option.undef = true; - } - - // there's no directive negation, so always set to true - directive[token.value] = true; - - if (p.id === ";") { - advance(";"); - } - continue; - } - break; - } - } - - - /* - * Parses a single block. A block is a sequence of statements wrapped in - * braces. - * - * ordinary - true for everything but function bodies and try blocks. - * stmt - true if block can be a single statement (e.g. in if/for/while). - * isfunc - true if block is a function body - */ - function block(ordinary, stmt, isfunc) { - var a, - b = inblock, - old_indent = indent, - m, - s = scope, - t, - line, - d; - - inblock = ordinary; - if (!ordinary || !option.funcscope) scope = Object.create(scope); - nonadjacent(token, nexttoken); - t = nexttoken; - - if (nexttoken.id === '{') { - advance('{'); - line = token.line; - if (nexttoken.id !== '}') { - indent += option.indent; - while (!ordinary && nexttoken.from > indent) { - indent += option.indent; - } - - if (isfunc) { - m = {}; - for (d in directive) { - if (is_own(directive, d)) { - m[d] = directive[d]; - } - } - directives(); - - if (option.strict && funct['(context)']['(global)']) { - if (!m["use strict"] && !directive["use strict"]) { - warning("Missing \"use strict\" statement."); - } - } - } - - a = statements(line); - - if (isfunc) { - directive = m; - } - - indent -= option.indent; - if (line !== nexttoken.line) { - indentation(); - } - } else if (line !== nexttoken.line) { - indentation(); - } - advance('}', t); - indent = old_indent; - } else if (!ordinary) { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); - } else { - if (!stmt || option.curly) - warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); - - noreach = true; - indent += option.indent; - // test indentation only if statement is in new line - a = [statement(nexttoken.line === token.line)]; - indent -= option.indent; - noreach = false; - } - funct['(verb)'] = null; - if (!ordinary || !option.funcscope) scope = s; - inblock = b; - if (ordinary && option.noempty && (!a || a.length === 0)) { - warning("Empty block."); - } - return a; - } - - - function countMember(m) { - if (membersOnly && typeof membersOnly[m] !== 'boolean') { - warning("Unexpected /*member '{a}'.", token, m); - } - if (typeof member[m] === 'number') { - member[m] += 1; - } else { - member[m] = 1; - } - } - - - function note_implied(token) { - var name = token.value, line = token.line, a = implied[name]; - if (typeof a === 'function') { - a = false; - } - if (!a) { - a = [line]; - implied[name] = a; - } else if (a[a.length - 1] !== line) { - a.push(line); - } - } - - - // Build the syntax table by declaring the syntactic elements of the language. - - type('(number)', function () { - return this; - }); - - type('(string)', function () { - return this; - }); - - syntax['(identifier)'] = { - type: '(identifier)', - lbp: 0, - identifier: true, - nud: function () { - var v = this.value, - s = scope[v], - f; - - if (typeof s === 'function') { - // Protection against accidental inheritance. - s = undefined; - } else if (typeof s === 'boolean') { - f = funct; - funct = functions[0]; - addlabel(v, 'var'); - s = funct; - funct = f; - } - - // The name is in scope and defined in the current function. - if (funct === s) { - // Change 'unused' to 'var', and reject labels. - switch (funct[v]) { - case 'unused': - funct[v] = 'var'; - break; - case 'unction': - funct[v] = 'function'; - this['function'] = true; - break; - case 'function': - this['function'] = true; - break; - case 'label': - warning("'{a}' is a statement label.", token, v); - break; - } - } else if (funct['(global)']) { - // The name is not defined in the function. If we are in the global - // scope, then we have an undefined variable. - // - // Operators typeof and delete do not raise runtime errors even if - // the base object of a reference is null so no need to display warning - // if we're inside of typeof or delete. - if (anonname != 'typeof' && anonname != 'delete' && - option.undef && typeof predefined[v] !== 'boolean') { - warning("'{a}' is not defined.", token, v); - } - note_implied(token); - } else { - // If the name is already defined in the current - // function, but not as outer, then there is a scope error. - - switch (funct[v]) { - case 'closure': - case 'function': - case 'var': - case 'unused': - warning("'{a}' used out of scope.", token, v); - break; - case 'label': - warning("'{a}' is a statement label.", token, v); - break; - case 'outer': - case 'global': - break; - default: - // If the name is defined in an outer function, make an outer entry, - // and if it was unused, make it var. - if (s === true) { - funct[v] = true; - } else if (s === null) { - warning("'{a}' is not allowed.", token, v); - note_implied(token); - } else if (typeof s !== 'object') { - // Operators typeof and delete do not raise runtime errors even - // if the base object of a reference is null so no need to - // display warning if we're inside of typeof or delete. - if (anonname != 'typeof' && anonname != 'delete' && option.undef) { - warning("'{a}' is not defined.", token, v); - } else { - funct[v] = true; - } - note_implied(token); - } else { - switch (s[v]) { - case 'function': - case 'unction': - this['function'] = true; - s[v] = 'closure'; - funct[v] = s['(global)'] ? 'global' : 'outer'; - break; - case 'var': - case 'unused': - s[v] = 'closure'; - funct[v] = s['(global)'] ? 'global' : 'outer'; - break; - case 'closure': - case 'parameter': - funct[v] = s['(global)'] ? 'global' : 'outer'; - break; - case 'label': - warning("'{a}' is a statement label.", token, v); - } - } - } - } - return this; - }, - led: function () { - error("Expected an operator and instead saw '{a}'.", - nexttoken, nexttoken.value); - } - }; - - type('(regexp)', function () { - return this; - }); - - -// ECMAScript parser - - delim('(endline)'); - delim('(begin)'); - delim('(end)').reach = true; - delim(''); - delim('(error)').reach = true; - delim('}').reach = true; - delim(')'); - delim(']'); - delim('"').reach = true; - delim("'").reach = true; - delim(';'); - delim(':').reach = true; - delim(','); - delim('#'); - delim('@'); - reserve('else'); - reserve('case').reach = true; - reserve('catch'); - reserve('default').reach = true; - reserve('finally'); - reservevar('arguments', function (x) { - if (directive['use strict'] && funct['(global)']) { - warning("Strict violation.", x); - } - }); - reservevar('eval'); - reservevar('false'); - reservevar('Infinity'); - reservevar('NaN'); - reservevar('null'); - reservevar('this', function (x) { - if (directive['use strict'] && !option.validthis && ((funct['(statement)'] && - funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) { - warning("Possible strict violation.", x); - } - }); - reservevar('true'); - reservevar('undefined'); - assignop('=', 'assign', 20); - assignop('+=', 'assignadd', 20); - assignop('-=', 'assignsub', 20); - assignop('*=', 'assignmult', 20); - assignop('/=', 'assigndiv', 20).nud = function () { - error("A regular expression literal can be confused with '/='."); - }; - assignop('%=', 'assignmod', 20); - bitwiseassignop('&=', 'assignbitand', 20); - bitwiseassignop('|=', 'assignbitor', 20); - bitwiseassignop('^=', 'assignbitxor', 20); - bitwiseassignop('<<=', 'assignshiftleft', 20); - bitwiseassignop('>>=', 'assignshiftright', 20); - bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); - infix('?', function (left, that) { - that.left = left; - that.right = expression(10); - advance(':'); - that['else'] = expression(10); - return that; - }, 30); - - infix('||', 'or', 40); - infix('&&', 'and', 50); - bitwise('|', 'bitor', 70); - bitwise('^', 'bitxor', 80); - bitwise('&', 'bitand', 90); - relation('==', function (left, right) { - var eqnull = option.eqnull && (left.value == 'null' || right.value == 'null'); - - if (!eqnull && option.eqeqeq) - warning("Expected '{a}' and instead saw '{b}'.", this, '===', '=='); - else if (isPoorRelation(left)) - warning("Use '{a}' to compare with '{b}'.", this, '===', left.value); - else if (isPoorRelation(right)) - warning("Use '{a}' to compare with '{b}'.", this, '===', right.value); - - return this; - }); - relation('==='); - relation('!=', function (left, right) { - var eqnull = option.eqnull && - (left.value == 'null' || right.value == 'null'); - - if (!eqnull && option.eqeqeq) { - warning("Expected '{a}' and instead saw '{b}'.", - this, '!==', '!='); - } else if (isPoorRelation(left)) { - warning("Use '{a}' to compare with '{b}'.", - this, '!==', left.value); - } else if (isPoorRelation(right)) { - warning("Use '{a}' to compare with '{b}'.", - this, '!==', right.value); - } - return this; - }); - relation('!=='); - relation('<'); - relation('>'); - relation('<='); - relation('>='); - bitwise('<<', 'shiftleft', 120); - bitwise('>>', 'shiftright', 120); - bitwise('>>>', 'shiftrightunsigned', 120); - infix('in', 'in', 120); - infix('instanceof', 'instanceof', 120); - infix('+', function (left, that) { - var right = expression(130); - if (left && right && left.id === '(string)' && right.id === '(string)') { - left.value += right.value; - left.character = right.character; - if (!option.scripturl && jx.test(left.value)) { - warning("JavaScript URL.", left); - } - return left; - } - that.left = left; - that.right = right; - return that; - }, 130); - prefix('+', 'num'); - prefix('+++', function () { - warning("Confusing pluses."); - this.right = expression(150); - this.arity = 'unary'; - return this; - }); - infix('+++', function (left) { - warning("Confusing pluses."); - this.left = left; - this.right = expression(130); - return this; - }, 130); - infix('-', 'sub', 130); - prefix('-', 'neg'); - prefix('---', function () { - warning("Confusing minuses."); - this.right = expression(150); - this.arity = 'unary'; - return this; - }); - infix('---', function (left) { - warning("Confusing minuses."); - this.left = left; - this.right = expression(130); - return this; - }, 130); - infix('*', 'mult', 140); - infix('/', 'div', 140); - infix('%', 'mod', 140); - - suffix('++', 'postinc'); - prefix('++', 'preinc'); - syntax['++'].exps = true; - - suffix('--', 'postdec'); - prefix('--', 'predec'); - syntax['--'].exps = true; - prefix('delete', function () { - var p = expression(0); - if (!p || (p.id !== '.' && p.id !== '[')) { - warning("Variables should not be deleted."); - } - this.first = p; - return this; - }).exps = true; - prefix('console', function () { - if (!option.debug) { - warning("All 'console' statements should be removed."); - } - return this; - }).exps = true; - prefix('alert', function () { - if (!option.debug) { - warning("All 'alert' statements should be removed."); - } - return this; - }).exps = true; - prefix('~', function () { - if (option.bitwise) { - warning("Unexpected '{a}'.", this, '~'); - } - expression(150); - return this; - }); - - prefix('!', function () { - this.right = expression(150); - this.arity = 'unary'; - if (bang[this.right.id] === true) { - warning("Confusing use of '{a}'.", this, '!'); - } - return this; - }); - prefix('typeof', 'typeof'); - prefix('new', function () { - var c = expression(155), i; - if (c && c.id !== 'function') { - if (c.identifier) { - c['new'] = true; - switch (c.value) { - case 'Object': - warning("Use the object literal notation {}.", token); - break; - case 'Number': - case 'String': - case 'Boolean': - case 'Math': - case 'JSON': - warning("Do not use {a} as a constructor.", token, c.value); - break; - case 'Function': - if (!option.evil) { - warning("The Function constructor is eval."); - } - break; - case 'Date': - case 'RegExp': - break; - default: - if (c.id !== 'function') { - i = c.value.substr(0, 1); - if (option.newcap && (i < 'A' || i > 'Z')) { - warning("A constructor name should start with an uppercase letter.", - token); - } - } - } - } else { - if (c.id !== '.' && c.id !== '[' && c.id !== '(') { - warning("Bad constructor.", token); - } - } - } else { - if (!option.supernew) - warning("Weird construction. Delete 'new'.", this); - } - adjacent(token, nexttoken); - if (nexttoken.id !== '(' && !option.supernew) { - warning("Missing '()' invoking a constructor."); - } - this.first = c; - return this; - }); - syntax['new'].exps = true; - - prefix('void').exps = true; - - infix('.', function (left, that) { - adjacent(prevtoken, token); - nobreak(); - var m = identifier(); - if (typeof m === 'string') { - countMember(m); - } - that.left = left; - that.right = m; - if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) { - if (option.noarg) - warning("Avoid arguments.{a}.", left, m); - else if (directive['use strict']) - error('Strict violation.'); - } else if (!option.evil && left && left.value === 'document' && - (m === 'write' || m === 'writeln')) { - warning("document.write can be a form of eval.", left); - } - if (!option.evil && (m === 'eval' || m === 'execScript')) { - warning('eval is evil.'); - } - return that; - }, 160, true); - - infix('(', function (left, that) { - if (prevtoken.id !== '}' && prevtoken.id !== ')') { - nobreak(prevtoken, token); - } - nospace(); - if (option.immed && !left.immed && left.id === 'function') { - warning("Wrap an immediate function invocation in parentheses " + - "to assist the reader in understanding that the expression " + - "is the result of a function, and not the function itself."); - } - var n = 0, - p = []; - if (left) { - if (left.type === '(identifier)') { - if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { - if (left.value !== 'Number' && left.value !== 'String' && - left.value !== 'Boolean' && - left.value !== 'Date') { - if (left.value === 'Math') { - warning("Math is not a function.", left); - } else if (option.newcap) { - warning( -"Missing 'new' prefix when invoking a constructor.", left); - } - } - } - } - } - if (nexttoken.id !== ')') { - for (;;) { - p[p.length] = expression(10); - n += 1; - if (nexttoken.id !== ',') { - break; - } - comma(); - } - } - advance(')'); - nospace(prevtoken, token); - if (typeof left === 'object') { - if (left.value === 'parseInt' && n === 1) { - warning("Missing radix parameter.", left); - } - if (!option.evil) { - if (left.value === 'eval' || left.value === 'Function' || - left.value === 'execScript') { - warning("eval is evil.", left); - } else if (p[0] && p[0].id === '(string)' && - (left.value === 'setTimeout' || - left.value === 'setInterval')) { - warning( - "Implied eval is evil. Pass a function instead of a string.", left); - } - } - if (!left.identifier && left.id !== '.' && left.id !== '[' && - left.id !== '(' && left.id !== '&&' && left.id !== '||' && - left.id !== '?') { - warning("Bad invocation.", left); - } - } - that.left = left; - return that; - }, 155, true).exps = true; - - prefix('(', function () { - nospace(); - if (nexttoken.id === 'function') { - nexttoken.immed = true; - } - var v = expression(0); - advance(')', this); - nospace(prevtoken, token); - if (option.immed && v.id === 'function') { - if (nexttoken.id === '(') { - warning( -"Move the invocation into the parens that contain the function.", nexttoken); - } else { - warning( -"Do not wrap function literals in parens unless they are to be immediately invoked.", - this); - } - } - return v; - }); - - infix('[', function (left, that) { - nobreak(prevtoken, token); - nospace(); - var e = expression(0), s; - if (e && e.type === '(string)') { - if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) { - warning("eval is evil.", that); - } - countMember(e.value); - if (!option.sub && ix.test(e.value)) { - s = syntax[e.value]; - if (!s || !s.reserved) { - warning("['{a}'] is better written in dot notation.", - e, e.value); - } - } - } - advance(']', that); - nospace(prevtoken, token); - that.left = left; - that.right = e; - return that; - }, 160, true); - - prefix('[', function () { - var b = token.line !== nexttoken.line; - this.first = []; - if (b) { - indent += option.indent; - if (nexttoken.from === indent + option.indent) { - indent += option.indent; - } - } - while (nexttoken.id !== '(end)') { - while (nexttoken.id === ',') { - warning("Extra comma."); - advance(','); - } - if (nexttoken.id === ']') { - break; - } - if (b && token.line !== nexttoken.line) { - indentation(); - } - this.first.push(expression(10)); - if (nexttoken.id === ',') { - comma(); - if (nexttoken.id === ']' && !option.es5) { - warning("Extra comma.", token); - break; - } - } else { - break; - } - } - if (b) { - indent -= option.indent; - indentation(); - } - advance(']', this); - return this; - }, 160); - - - function property_name() { - var id = optionalidentifier(true); - if (!id) { - if (nexttoken.id === '(string)') { - id = nexttoken.value; - advance(); - } else if (nexttoken.id === '(number)') { - id = nexttoken.value.toString(); - advance(); - } - } - return id; - } - - - function functionparams() { - var i, t = nexttoken, p = []; - advance('('); - nospace(); - if (nexttoken.id === ')') { - advance(')'); - nospace(prevtoken, token); - return; - } - for (;;) { - i = identifier(true); - p.push(i); - addlabel(i, 'parameter'); - if (nexttoken.id === ',') { - comma(); - } else { - advance(')', t); - nospace(prevtoken, token); - return p; - } - } - } - - - function doFunction(i, statement) { - var f, - oldOption = option, - oldScope = scope; - - option = Object.create(option); - scope = Object.create(scope); - - funct = { - '(name)' : i || '"' + anonname + '"', - '(line)' : nexttoken.line, - '(context)' : funct, - '(breakage)' : 0, - '(loopage)' : 0, - '(scope)' : scope, - '(statement)': statement - }; - f = funct; - token.funct = funct; - functions.push(funct); - if (i) { - addlabel(i, 'function'); - } - funct['(params)'] = functionparams(); - - block(false, false, true); - scope = oldScope; - option = oldOption; - funct['(last)'] = token.line; - funct = funct['(context)']; - return f; - } - - - (function (x) { - x.nud = function () { - var b, f, i, j, p, seen = {}, t; - - b = token.line !== nexttoken.line; - if (b) { - indent += option.indent; - if (nexttoken.from === indent + option.indent) { - indent += option.indent; - } - } - for (;;) { - if (nexttoken.id === '}') { - break; - } - if (b) { - indentation(); - } - if (nexttoken.value === 'get' && peek().id !== ':') { - advance('get'); - if (!option.es5) { - error("get/set are ES5 features."); - } - i = property_name(); - if (!i) { - error("Missing property name."); - } - t = nexttoken; - adjacent(token, nexttoken); - f = doFunction(); - if (!option.loopfunc && funct['(loopage)']) { - warning("Don't make functions within a loop.", t); - } - p = f['(params)']; - if (p) { - warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i); - } - adjacent(token, nexttoken); - advance(','); - indentation(); - advance('set'); - j = property_name(); - if (i !== j) { - error("Expected {a} and instead saw {b}.", token, i, j); - } - t = nexttoken; - adjacent(token, nexttoken); - f = doFunction(); - p = f['(params)']; - if (!p || p.length !== 1 || p[0] !== 'value') { - warning("Expected (value) in set {a} function.", t, i); - } - } else { - i = property_name(); - if (typeof i !== 'string') { - break; - } - advance(':'); - nonadjacent(token, nexttoken); - expression(10); - } - if (seen[i] === true) { - warning("Duplicate member '{a}'.", nexttoken, i); - } - seen[i] = true; - countMember(i); - if (nexttoken.id === ',') { - comma(); - if (nexttoken.id === ',') { - warning("Extra comma.", token); - } else if (nexttoken.id === '}' && !option.es5) { - warning("Extra comma.", token); - } - } else { - break; - } - } - if (b) { - indent -= option.indent; - indentation(); - } - advance('}', this); - return this; - }; - x.fud = function () { - error("Expected to see a statement and instead saw a block.", token); - }; - }(delim('{'))); - -// This Function is called when esnext option is set to true -// it adds the `const` statement to JSHINT - - useESNextSyntax = function () { - var conststatement = stmt('const', function (prefix) { - var id, name, value; - - this.first = []; - for (;;) { - nonadjacent(token, nexttoken); - id = identifier(); - if (funct[id] === "const") { - warning("const '" + id + "' has already been declared"); - } - if (funct['(global)'] && predefined[id] === false) { - warning("Redefinition of '{a}'.", token, id); - } - addlabel(id, 'const'); - if (prefix) { - break; - } - name = token; - this.first.push(token); - - if (nexttoken.id !== "=") { - warning("const " + - "'{a}' is initialized to 'undefined'.", token, id); - } - - if (nexttoken.id === '=') { - nonadjacent(token, nexttoken); - advance('='); - nonadjacent(token, nexttoken); - if (nexttoken.id === 'undefined') { - warning("It is not necessary to initialize " + - "'{a}' to 'undefined'.", token, id); - } - if (peek(0).id === '=' && nexttoken.identifier) { - error("Constant {a} was not declared correctly.", - nexttoken, nexttoken.value); - } - value = expression(0); - name.first = value; - } - - if (nexttoken.id !== ',') { - break; - } - comma(); - } - return this; - }); - conststatement.exps = true; - }; - - var varstatement = stmt('var', function (prefix) { - // JavaScript does not have block scope. It only has function scope. So, - // declaring a variable in a block can have unexpected consequences. - var id, name, value; - - if (funct['(onevar)'] && option.onevar) { - warning("Too many var statements."); - } else if (!funct['(global)']) { - funct['(onevar)'] = true; - } - this.first = []; - for (;;) { - nonadjacent(token, nexttoken); - id = identifier(); - if (option.esnext && funct[id] === "const") { - warning("const '" + id + "' has already been declared"); - } - if (funct['(global)'] && predefined[id] === false) { - warning("Redefinition of '{a}'.", token, id); - } - addlabel(id, 'unused'); - if (prefix) { - break; - } - name = token; - this.first.push(token); - if (nexttoken.id === '=') { - nonadjacent(token, nexttoken); - advance('='); - nonadjacent(token, nexttoken); - if (nexttoken.id === 'undefined') { - warning("It is not necessary to initialize '{a}' to 'undefined'.", token, id); - } - if (peek(0).id === '=' && nexttoken.identifier) { - error("Variable {a} was not declared correctly.", - nexttoken, nexttoken.value); - } - value = expression(0); - name.first = value; - } - if (nexttoken.id !== ',') { - break; - } - comma(); - } - return this; - }); - varstatement.exps = true; - - blockstmt('function', function () { - if (inblock) { - warning("Function declarations should not be placed in blocks. " + - "Use a function expression or move the statement to the top of " + - "the outer function.", token); - - } - var i = identifier(); - if (option.esnext && funct[i] === "const") { - warning("const '" + i + "' has already been declared"); - } - adjacent(token, nexttoken); - addlabel(i, 'unction'); - doFunction(i, true); - if (nexttoken.id === '(' && nexttoken.line === token.line) { - error( -"Function declarations are not invocable. Wrap the whole function invocation in parens."); - } - return this; - }); - - prefix('function', function () { - var i = optionalidentifier(); - if (i) { - adjacent(token, nexttoken); - } else { - nonadjacent(token, nexttoken); - } - doFunction(i); - if (!option.loopfunc && funct['(loopage)']) { - warning("Don't make functions within a loop."); - } - return this; - }); - - blockstmt('if', function () { - var t = nexttoken; - advance('('); - nonadjacent(this, t); - nospace(); - expression(20); - if (nexttoken.id === '=') { - if (!option.boss) - warning("Expected a conditional expression and instead saw an assignment."); - advance('='); - expression(20); - } - advance(')', t); - nospace(prevtoken, token); - block(true, true); - if (nexttoken.id === 'else') { - nonadjacent(token, nexttoken); - advance('else'); - if (nexttoken.id === 'if' || nexttoken.id === 'switch') { - statement(true); - } else { - block(true, true); - } - } - return this; - }); - - blockstmt('try', function () { - var b, e, s; - - block(false); - if (nexttoken.id === 'catch') { - advance('catch'); - nonadjacent(token, nexttoken); - advance('('); - s = scope; - scope = Object.create(s); - e = nexttoken.value; - if (nexttoken.type !== '(identifier)') { - warning("Expected an identifier and instead saw '{a}'.", - nexttoken, e); - } else { - addlabel(e, 'exception'); - } - advance(); - advance(')'); - block(false); - b = true; - scope = s; - } - if (nexttoken.id === 'finally') { - advance('finally'); - block(false); - return; - } else if (!b) { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'catch', nexttoken.value); - } - return this; - }); - - blockstmt('while', function () { - var t = nexttoken; - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - advance('('); - nonadjacent(this, t); - nospace(); - expression(20); - if (nexttoken.id === '=') { - if (!option.boss) - warning("Expected a conditional expression and instead saw an assignment."); - advance('='); - expression(20); - } - advance(')', t); - nospace(prevtoken, token); - block(true, true); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; - return this; - }).labelled = true; - - reserve('with'); - - blockstmt('switch', function () { - var t = nexttoken, - g = false; - funct['(breakage)'] += 1; - advance('('); - nonadjacent(this, t); - nospace(); - this.condition = expression(20); - advance(')', t); - nospace(prevtoken, token); - nonadjacent(token, nexttoken); - t = nexttoken; - advance('{'); - nonadjacent(token, nexttoken); - indent += option.indent; - this.cases = []; - for (;;) { - switch (nexttoken.id) { - case 'case': - switch (funct['(verb)']) { - case 'break': - case 'case': - case 'continue': - case 'return': - case 'switch': - case 'throw': - break; - default: - // You can tell JSHint that you don't use break intentionally by - // adding a comment /* falls through */ on a line just before - // the next `case`. - if (!ft.test(lines[nexttoken.line - 2])) { - warning( - "Expected a 'break' statement before 'case'.", - token); - } - } - indentation(-option.indent); - advance('case'); - this.cases.push(expression(20)); - g = true; - advance(':'); - funct['(verb)'] = 'case'; - break; - case 'default': - switch (funct['(verb)']) { - case 'break': - case 'continue': - case 'return': - case 'throw': - break; - default: - if (!ft.test(lines[nexttoken.line - 2])) { - warning( - "Expected a 'break' statement before 'default'.", - token); - } - } - indentation(-option.indent); - advance('default'); - g = true; - advance(':'); - break; - case '}': - indent -= option.indent; - indentation(); - advance('}', t); - if (this.cases.length === 1 || this.condition.id === 'true' || - this.condition.id === 'false') { - if (!option.onecase) - warning("This 'switch' should be an 'if'.", this); - } - funct['(breakage)'] -= 1; - funct['(verb)'] = undefined; - return; - case '(end)': - error("Missing '{a}'.", nexttoken, '}'); - return; - default: - if (g) { - switch (token.id) { - case ',': - error("Each value should have its own case label."); - return; - case ':': - g = false; - statements(); - break; - default: - error("Missing ':' on a case clause.", token); - return; - } - } else { - if (token.id === ':') { - advance(':'); - error("Unexpected '{a}'.", token, ':'); - statements(); - } else { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'case', nexttoken.value); - return; - } - } - } - } - }).labelled = true; - - stmt('debugger', function () { - if (!option.debug) { - warning("All 'debugger' statements should be removed."); - } - return this; - }).exps = true; -// stmt('alert', function () { -// if (!option.debug) { -// warning("All 'alert' statements should be removed."); -// } -// return this; -// }).exps = true; -// stmt('console', function () { -// if (!option.debug) { -// warning("All 'console' statements should be removed."); -// } -// return this; -// }).exps = true; - - (function () { - var x = stmt('do', function () { - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - this.first = block(true); - advance('while'); - var t = nexttoken; - nonadjacent(token, t); - advance('('); - nospace(); - expression(20); - if (nexttoken.id === '=') { - if (!option.boss) - warning("Expected a conditional expression and instead saw an assignment."); - advance('='); - expression(20); - } - advance(')', t); - nospace(prevtoken, token); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; - return this; - }); - x.labelled = true; - x.exps = true; - }()); - - blockstmt('for', function () { - var s, t = nexttoken; - funct['(breakage)'] += 1; - funct['(loopage)'] += 1; - advance('('); - nonadjacent(this, t); - nospace(); - if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { - if (nexttoken.id === 'var') { - advance('var'); - varstatement.fud.call(varstatement, true); - } else { - switch (funct[nexttoken.value]) { - case 'unused': - funct[nexttoken.value] = 'var'; - break; - case 'var': - break; - default: - warning("Bad for in variable '{a}'.", - nexttoken, nexttoken.value); - } - advance(); - } - advance('in'); - expression(20); - advance(')', t); - s = block(true, true); - if (option.forin && (s.length > 1 || typeof s[0] !== 'object' || - s[0].value !== 'if')) { - warning("The body of a for in should be wrapped in an if statement to filter " + - "unwanted properties from the prototype.", this); - } - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; - return this; - } else { - if (nexttoken.id !== ';') { - if (nexttoken.id === 'var') { - advance('var'); - varstatement.fud.call(varstatement); - } else { - for (;;) { - expression(0, 'for'); - if (nexttoken.id !== ',') { - break; - } - comma(); - } - } - } - nolinebreak(token); - advance(';'); - if (nexttoken.id !== ';') { - expression(20); - if (nexttoken.id === '=') { - if (!option.boss) - warning("Expected a conditional expression and instead saw an assignment."); - advance('='); - expression(20); - } - } - nolinebreak(token); - advance(';'); - if (nexttoken.id === ';') { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, ')', ';'); - } - if (nexttoken.id !== ')') { - for (;;) { - expression(0, 'for'); - if (nexttoken.id !== ',') { - break; - } - comma(); - } - } - advance(')', t); - nospace(prevtoken, token); - block(true, true); - funct['(breakage)'] -= 1; - funct['(loopage)'] -= 1; - return this; - } - }).labelled = true; - - - stmt('break', function () { - var v = nexttoken.value; - - if (funct['(breakage)'] === 0) - warning("Unexpected '{a}'.", nexttoken, this.value); - - if (!option.asi) - nolinebreak(this); - - if (nexttoken.id !== ';') { - if (token.line === nexttoken.line) { - if (funct[v] !== 'label') { - warning("'{a}' is not a statement label.", nexttoken, v); - } else if (scope[v] !== funct) { - warning("'{a}' is out of scope.", nexttoken, v); - } - this.first = nexttoken; - advance(); - } - } - reachable('break'); - return this; - }).exps = true; - - - stmt('continue', function () { - var v = nexttoken.value; - - if (funct['(breakage)'] === 0) - warning("Unexpected '{a}'.", nexttoken, this.value); - - if (!option.asi) - nolinebreak(this); - - if (nexttoken.id !== ';') { - if (token.line === nexttoken.line) { - if (funct[v] !== 'label') { - warning("'{a}' is not a statement label.", nexttoken, v); - } else if (scope[v] !== funct) { - warning("'{a}' is out of scope.", nexttoken, v); - } - this.first = nexttoken; - advance(); - } - } else if (!funct['(loopage)']) { - warning("Unexpected '{a}'.", nexttoken, this.value); - } - reachable('continue'); - return this; - }).exps = true; - - - stmt('return', function () { - if (this.line === nexttoken.line) { - if (nexttoken.id === '(regexp)') - warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator."); - - if (nexttoken.id !== ';' && !nexttoken.reach) { - nonadjacent(token, nexttoken); - this.first = expression(0); - } - } else if (!option.asi) { - nolinebreak(this); // always warn (Line breaking error) - } - reachable('return'); - return this; - }).exps = true; - - - stmt('throw', function () { - nolinebreak(this); - nonadjacent(token, nexttoken); - this.first = expression(20); - reachable('throw'); - return this; - }).exps = true; - -// Superfluous reserved words - - reserve('class'); - reserve('const'); - reserve('enum'); - reserve('export'); - reserve('extends'); - reserve('import'); - reserve('super'); - - reserve('let'); - reserve('yield'); - reserve('implements'); - reserve('interface'); - reserve('package'); - reserve('private'); - reserve('protected'); - reserve('public'); - reserve('static'); - - -// Parse JSON - - function jsonValue() { - - function jsonObject() { - var o = {}, t = nexttoken; - advance('{'); - if (nexttoken.id !== '}') { - for (;;) { - if (nexttoken.id === '(end)') { - error("Missing '}' to match '{' from line {a}.", - nexttoken, t.line); - } else if (nexttoken.id === '}') { - warning("Unexpected comma.", token); - break; - } else if (nexttoken.id === ',') { - error("Unexpected comma.", nexttoken); - } else if (nexttoken.id !== '(string)') { - warning("Expected a string and instead saw {a}.", - nexttoken, nexttoken.value); - } - if (o[nexttoken.value] === true) { - warning("Duplicate key '{a}'.", - nexttoken, nexttoken.value); - } else if ((nexttoken.value === '__proto__' && - !option.proto) || (nexttoken.value === '__iterator__' && - !option.iterator)) { - warning("The '{a}' key may produce unexpected results.", - nexttoken, nexttoken.value); - } else { - o[nexttoken.value] = true; - } - advance(); - advance(':'); - jsonValue(); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - advance('}'); - } - - function jsonArray() { - var t = nexttoken; - advance('['); - if (nexttoken.id !== ']') { - for (;;) { - if (nexttoken.id === '(end)') { - error("Missing ']' to match '[' from line {a}.", - nexttoken, t.line); - } else if (nexttoken.id === ']') { - warning("Unexpected comma.", token); - break; - } else if (nexttoken.id === ',') { - error("Unexpected comma.", nexttoken); - } - jsonValue(); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - advance(']'); - } - - switch (nexttoken.id) { - case '{': - jsonObject(); - break; - case '[': - jsonArray(); - break; - case 'true': - case 'false': - case 'null': - case '(number)': - case '(string)': - advance(); - break; - case '-': - advance('-'); - if (token.character !== nexttoken.from) { - warning("Unexpected space after '-'.", token); - } - adjacent(token, nexttoken); - advance('(number)'); - break; - default: - error("Expected a JSON value.", nexttoken); - } - } - - -// The actual JSHINT function itself. - - var itself = function (s, o, g) { - var a, i, k; - JSHINT.errors = []; - predefined = Object.create(standard); - combine(predefined, g || {}); - if (o) { - a = o.predef; - if (a) { - if (Array.isArray(a)) { - for (i = 0; i < a.length; i += 1) { - predefined[a[i]] = true; - } - } else if (typeof a === 'object') { - k = Object.keys(a); - for (i = 0; i < k.length; i += 1) { - predefined[k[i]] = !!a[k[i]]; - } - } - } - option = o; - } else { - option = {}; - } - option.indent = option.indent || 4; - option.maxerr = option.maxerr || 5000000; - - tab = ''; - for (i = 0; i < option.indent; i += 1) { - tab += ' '; - } - indent = 1; - global = Object.create(predefined); - scope = global; - funct = { - '(global)': true, - '(name)': '(global)', - '(scope)': scope, - '(breakage)': 0, - '(loopage)': 0 - }; - functions = [funct]; - urls = []; - src = false; - stack = null; - member = {}; - membersOnly = null; - implied = {}; - inblock = false; - lookahead = []; - jsonmode = false; - warnings = 0; - lex.init(s); - prereg = true; - directive = {}; - - prevtoken = token = nexttoken = syntax['(begin)']; - assume(); - - // combine the passed globals after we've assumed all our options - combine(predefined, g || {}); - - try { - advance(); - switch (nexttoken.id) { - case '{': - case '[': - option.laxbreak = true; - jsonmode = true; - jsonValue(); - break; - default: - directives(); - if (directive["use strict"] && !option.globalstrict) { - warning("Use the function form of \"use strict\".", prevtoken); - } - - statements(); - } - advance('(end)'); - } catch (e) { - if (e) { - JSHINT.errors.push({ - reason : e.message, - line : e.line || nexttoken.line, - character : e.character || nexttoken.from - }, null); - } - } - return JSHINT.errors.length === 0; - }; - - // Data summary. - itself.data = function () { - - var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j, - members = [], n, unused = [], v; - if (itself.errors.length) { - data.errors = itself.errors; - } - - if (jsonmode) { - data.json = true; - } - - for (n in implied) { - if (is_own(implied, n)) { - implieds.push({ - name: n, - line: implied[n] - }); - } - } - if (implieds.length > 0) { - data.implieds = implieds; - } - - if (urls.length > 0) { - data.urls = urls; - } - - globals = Object.keys(scope); - if (globals.length > 0) { - data.globals = globals; - } - - for (i = 1; i < functions.length; i += 1) { - f = functions[i]; - fu = {}; - for (j = 0; j < functionicity.length; j += 1) { - fu[functionicity[j]] = []; - } - for (n in f) { - if (is_own(f, n) && n.charAt(0) !== '(') { - v = f[n]; - if (v === 'unction') { - v = 'unused'; - } - if (Array.isArray(fu[v])) { - fu[v].push(n); - if (v === 'unused') { - unused.push({ - name: n, - line: f['(line)'], - 'function': f['(name)'] - }); - } - } - } - } - for (j = 0; j < functionicity.length; j += 1) { - if (fu[functionicity[j]].length === 0) { - delete fu[functionicity[j]]; - } - } - fu.name = f['(name)']; - fu.param = f['(params)']; - fu.line = f['(line)']; - fu.last = f['(last)']; - data.functions.push(fu); - } - - if (unused.length > 0) { - data.unused = unused; - } - - members = []; - for (n in member) { - if (typeof member[n] === 'number') { - data.member = member; - break; - } - } - - return data; - }; - - itself.report = function (option) { - var data = itself.data(); - - var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s; - - function detail(h, array) { - var b, i, singularity; - if (array) { - o.push('
        ' + h + ' '); - array = array.sort(); - for (i = 0; i < array.length; i += 1) { - if (array[i] !== singularity) { - singularity = array[i]; - o.push((b ? ', ' : '') + singularity); - b = true; - } - } - o.push('
        '); - } - } - - - if (data.errors || data.implieds || data.unused) { - err = true; - o.push('
        Error:'); - if (data.errors) { - for (i = 0; i < data.errors.length; i += 1) { - c = data.errors[i]; - if (c) { - e = c.evidence || ''; - o.push('

        Problem' + (isFinite(c.line) ? ' at line ' + - c.line + ' character ' + c.character : '') + - ': ' + c.reason.entityify() + - '

        ' + - (e && (e.length > 80 ? e.slice(0, 77) + '...' : - e).entityify()) + '

        '); - } - } - } - - if (data.implieds) { - s = []; - for (i = 0; i < data.implieds.length; i += 1) { - s[i] = '' + data.implieds[i].name + ' ' + - data.implieds[i].line + ''; - } - o.push('

        Implied global: ' + s.join(', ') + '

        '); - } - - if (data.unused) { - s = []; - for (i = 0; i < data.unused.length; i += 1) { - s[i] = '' + data.unused[i].name + ' ' + - data.unused[i].line + ' ' + - data.unused[i]['function'] + ''; - } - o.push('

        Unused variable: ' + s.join(', ') + '

        '); - } - if (data.json) { - o.push('

        JSON: bad.

        '); - } - o.push('
        '); - } - - if (!option) { - - o.push('
        '); - - if (data.urls) { - detail("URLs
        ", data.urls, '
        '); - } - - if (data.json && !err) { - o.push('

        JSON: good.

        '); - } else if (data.globals) { - o.push('
        Global ' + - data.globals.sort().join(', ') + '
        '); - } else { - o.push('
        No new global variables introduced.
        '); - } - - for (i = 0; i < data.functions.length; i += 1) { - f = data.functions[i]; - - o.push('
        ' + f.line + '-' + - f.last + ' ' + (f.name || '') + '(' + - (f.param ? f.param.join(', ') : '') + ')
        '); - detail('Unused', f.unused); - detail('Closure', f.closure); - detail('Variable', f['var']); - detail('Exception', f.exception); - detail('Outer', f.outer); - detail('Global', f.global); - detail('Label', f.label); - } - - if (data.member) { - a = Object.keys(data.member); - if (a.length) { - a = a.sort(); - m = '
        /*members ';
        -                    l = 10;
        -                    for (i = 0; i < a.length; i += 1) {
        -                        k = a[i];
        -                        n = k.name();
        -                        if (l + n.length > 72) {
        -                            o.push(m + '
        '); - m = ' '; - l = 1; - } - l += n.length + 2; - if (data.member[k] === 1) { - n = '' + n + ''; - } - if (i < a.length - 1) { - n += ', '; - } - m += n; - } - o.push(m + '
        */
        '); - } - o.push('
        '); - } - } - return o.join(''); - }; - - itself.jshint = itself; - itself.edition = '2011-04-16'; - - return itself; -}()); - -// Make JSHINT a Node module, if possible. -if (typeof exports == 'object' && exports) - exports.JSHINT = JSHINT; diff --git a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/version b/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/version deleted file mode 100644 index 93b9d970..00000000 --- a/_test/tools/lib/jshunter_1.2.0.1/jshunter_dev/jshunter/version +++ /dev/null @@ -1,22 +0,0 @@ -#beta version -version:1.2.0.1 - -[changelog] -1.��ָ��������ļ��Ѿ�������ܾ���飬�Է���Դ�ļ������ǵ���� -2.֧�ֵݹ���Ŀ¼�ڵ������ļ� -3.֧�ּ��html�ļ��е�js���루��ȡ��ͬһ��ʱ������ѭ����һ��bug -5.�޸���isHidden�����ж��ϼ�Ŀ¼..ʱ�����bug -6.�޸������·����bug -7.�����˱�Ҫ��debug��� -8.�޸���Ŀ¼�ṹ��������confĿ¼��core/data/Ŀ¼ -9.�����˷�������ɨ��Ĺ��� -10.������html�ļ���ʽ��������⣨֮ǰ��������Ĵ����ļ�������<��>����Ҫת�壬����������룩 -11.������ɨ����� -12.�����˺����������������ִ��󼶱�error,warning,ignore����ignore����� -13.�����еĺ�����֣�������ά�� -14.���������������warning��error�ĸ����Ͱٷֱ� -15.�޸��˴�����ļ��б�Ϊ��δ������� -16.[1.2.0]�������ļ�������˹��� -17.[1.2.0]�����û��Զ��������ù��� -18.[1.2.0.1]ȥ���˻�����鲽�� diff --git a/_test/tools/lib/jslint4java-2.0.2.jar b/_test/tools/lib/jslint4java-2.0.2.jar deleted file mode 100644 index 71055164..00000000 Binary files a/_test/tools/lib/jslint4java-2.0.2.jar and /dev/null differ diff --git a/_test/tools/lib/jslint4java-ant-1.4.2.jar b/_test/tools/lib/jslint4java-ant-1.4.2.jar deleted file mode 100644 index 5f6bd7ec..00000000 Binary files a/_test/tools/lib/jslint4java-ant-1.4.2.jar and /dev/null differ diff --git a/_test/tools/lib/npPlugintest.dll b/_test/tools/lib/npPlugintest.dll deleted file mode 100644 index 07df0b3e..00000000 Binary files a/_test/tools/lib/npPlugintest.dll and /dev/null differ diff --git a/_test/ui/buttoncombobox.js b/_test/ui/buttoncombobox.js deleted file mode 100644 index b0c90658..00000000 --- a/_test/ui/buttoncombobox.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-8-19 - * Time: 下午4:33 - * To change this template use File | Settings | File Templates. - */ -module( 'ui.buttoncombobox' ); -test( '检测buttoncombobox行为是否正确', function() { - var editor = te.obj[0]; - stop(); - editor.ready(function(){ - setTimeout(function () { - - var editor = te.obj[0], - coboboxOptions = { - label: 'test', - title: 'test', - comboboxName: 'test', - recordStack: [ 'h2', 'h4' ], - items: [ 'p', 'h1', 'h2', 'h3', 'h4', 'h5' ], - value: [ 'p', 'h1', 'h2', 'h3', 'h4', 'h5' ], - autowidthitem: [ 'p', 'h1', 'h2', 'h3', 'h4', 'h5' ], - autoRecord: true - }, - $combox = null, - $btn = null, - $item = null, - oldIE6 = $.IE6; - - $.IE6 = true; - $combox = $.eduibuttoncombobox( coboboxOptions ); - $.IE6 = oldIE6; - $btn = $combox.edui().button(); - - - $combox.appendTo( editor.$container.find('.edui-dialog-container') ); - $( ".edui-btn-toolbar", editor.$container ).append( $btn.addClass("edui-combobox") ); - - window.setTimeout( function () { - - //测试弹出层位置是否正常 - $btn.trigger( "click" ); - - window.setTimeout( function () { - - equal( Math.abs( $combox.position().left - $btn.position().left ) < 3, true , '弹出层的左边界对齐正常' ); - equal( Math.abs($combox.position().top-($btn.position().top + $btn.outerHeight())) < 2,true , '弹出层的上边界对齐正常' ); - - //hover背景改变 - $item = $(".edui-combobox-item:first", $combox ); - - $item.addClass( "edui-combobox-item-hover" ); - equal( ua.formatColor($item.css("backgroundColor")), "#d5e1f2" , 'hover in 背景色正常' ); - $item.removeClass( "edui-combobox-item-hover" ); - equal( $item.css("backgroundColor") !== "rgb(213, 225, 242)", true , 'hover out 背景色正常' ); - - //选中第一个 - $item.trigger("click"); - equal( $( ".edui-button-label", $btn ).text(), "p", "标签选择之后, 按钮文字正常" ); - - $item = $(".edui-combobox-item:first", $combox ); - - equal( $item.hasClass("edui-combobox-checked"), true, "标签选择之后, 标签已添加选中状态class" ); - - equal( $(".edui-combobox-item-separator", $combox).length, 1, "历史记录的分割线正常出现" ); - - equal( $(".edui-combobox-item", $combox ).length, coboboxOptions.items.length+1, "历史记录条数正确" ); - - //选中历史记录 - $item.trigger("click"); - equal( $( ".edui-button-label", $btn ).text(), "p", "选择历史记录之后, 按钮文字正常" ); - - equal( $(".edui-combobox-item", $combox ).length, coboboxOptions.items.length+1, "历史记录条数正确" ); - - //根据label选择 - $combox.edui().selectItemByLabel( 'h3' ); - equal( $( ".edui-button-label", $btn ).text(), "h3", "根据label选择后, 按钮文字正常" ); - - equal( $(".edui-combobox-item", $combox ).length, coboboxOptions.items.length+2, "历史记录条数正确" ); - - start(); - - }, 500 ); - - }, 500 ); - - }, 500); - }); - -}); - diff --git a/_test/ui/colorpicker.js b/_test/ui/colorpicker.js deleted file mode 100644 index 04eaf835..00000000 --- a/_test/ui/colorpicker.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: xuheng - * Date: 13-8-20 - * Time: 下午7:02 - * To change this template use File | Settings | File Templates. - */ -module( 'ui.colorpicker' ); - -test( 'colorpicker--初始化', function() { - var div = document.body.appendChild( document.createElement( 'div' ) ); - $(div).attr('id','test'); - - $colorPickerWidget = $.eduicolorpicker({ - lang_clearColor:'清除', - lang_themeColor: '主题', - lang_standardColor: '标准' - }).appendTo(div); - - var $btn=$.eduibutton({ - icon : "bold", - title: "测试" - }).appendTo(div); - - stop(); - setTimeout(function(){ - $colorPickerWidget.edui().show($btn); - - var isshow=$colorPickerWidget.css("display")!="none"; - equal(isshow,true,'检查菜单是否显示'); - - $colorPickerWidget.edui().hide(); - var ishide=$colorPickerWidget.css("display")=="none"; - equal(ishide,true,'检查菜单是否隐藏'); - - var ele=$colorPickerWidget.find("table .edui-colorpicker-colorcell")[0]; - var color=$(ele).data('color'); - - $colorPickerWidget.on('pickcolor',function(evt,value){ - equal(value,color,'检查菜单点击颜色是否正确'); - - div.parentNode.removeChild(div); - start(); - }); - - ua.click(ele); - - }); -} ); \ No newline at end of file diff --git a/_test/ui/dropmenu.js b/_test/ui/dropmenu.js deleted file mode 100644 index ad750e19..00000000 --- a/_test/ui/dropmenu.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午1:28 - * To change this template use File | Settings | File Templates. - */ -module('ui.dropmenu'); - -test('dropmenu--初始化', function () { - UM.delEditor('testeditor'); - document.getElementById('testeditor')&&document.getElementById('testeditor').parentNode.removeChild(document.getElementById('testeditor')); - - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var item, value, - $dropMenuWidget = $.eduidropmenu({data:[ - {"value":"decimal","label":"1,2,3..."}, - {"value":"lower-alpha","label":"a,b,c..."}, - {"value":"lower-roman","label":"i,ii,iii..."}, - {"value":"upper-alpha","label":"A,B,C..."}, - {"value":"upper-roman","label":"I,II,III..."} - ],click:function(evt, val){ - equal(value, val, '检查菜单点击的value是否正确'); - div.parentNode.removeChild(div); - - $dropMenuWidget.edui().val('upper-alpha'); - equal($dropMenuWidget.edui().val(), 'upper-alpha', '检查设置菜单值是否正常'); - - $dropMenuWidget.edui().disabled(true); - equal($dropMenuWidget.find("li").hasClass('edui-disabled'), true, '检查选项失效后,菜单项是否有disabled的class'); - - $dropMenuWidget.edui().disabled(false); - equal($dropMenuWidget.find("li").hasClass('edui-disabled'), false, '检查选项失效后,菜单项是否没有disabled的class'); - var $subMenuWidget = $.eduidropmenu({data:[ - {"value":"decimal","label":"1,2,3..."}, - {"value":"lower-alpha","label":"a,b,c..."}, - {"value":"lower-roman","label":"i,ii,iii..."}, - {"value":"upper-alpha","label":"A,B,C..."}, - {"value":"upper-roman","label":"I,II,III..."} - ]}); - $dropMenuWidget.edui().addSubmenu('subMenu', $subMenuWidget, 5); - equal($dropMenuWidget.find(".edui-dropdown-menu").length!=0, true, '检查是否已插入子节点'); - $(div).remove(); - start(); - }}).appendTo(div); - - var $btn = $.eduibutton({ - icon: "paragraph", - title: "测试" - }).appendTo(div); - - $dropMenuWidget.edui().show($btn); - $item = $dropMenuWidget.find("li").eq(0); - value = $item.data('value'); - - - $item.trigger('click'); - - stop(); -}); \ No newline at end of file diff --git a/_test/ui/menu.js b/_test/ui/menu.js deleted file mode 100644 index 77a59ba8..00000000 --- a/_test/ui/menu.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午5:17 - * To change this template use File | Settings | File Templates. - */ -module('ui.menu'); - -test('menu--初始化', function () { - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var $dropMenuWidget = $.eduidropmenu({data:[ - {"value":"decimal","label":"1,2,3..."}, - {"value":"lower-alpha","label":"a,b,c..."}, - {"value":"lower-roman","label":"i,ii,iii..."}, - {"value":"upper-alpha","label":"A,B,C..."}, - {"value":"upper-roman","label":"I,II,III..."} - ]}).appendTo(div); - - var $btn = $.eduibutton({ - icon: "paragraph", - title: "测试" - }).appendTo(div); - - equal($btn.data('$mergeObj')==undefined, true, 'attachTo方法执行之前,按钮没有data("$mergeObj")'); - $dropMenuWidget.edui().attachTo($btn); - equal($btn.data('$mergeObj')!=undefined, true, 'attachTo方法执行之后,按钮有data("$mergeObj")'); - - var $subMenuWidget = $.eduidropmenu({data:[ - {"value":"decimal","label":"1,2,3..."}, - {"value":"lower-alpha","label":"a,b,c..."}, - {"value":"lower-roman","label":"i,ii,iii..."}, - {"value":"upper-alpha","label":"A,B,C..."}, - {"value":"upper-roman","label":"I,II,III..."} - ]}); - //插入子菜单 - $dropMenuWidget.edui().addSubmenu('subMenu', $subMenuWidget, 5); - - ua.click($btn[0]); - - setTimeout(function(){ - - var isshow = $dropMenuWidget.css("display") != "none"; - equal(isshow, true, '检查菜单是否显示'); - - ua.click($dropMenuWidget.find('li')[0]); - setTimeout(function(){ - var ishide = $dropMenuWidget.css("display") == "none"; - equal(ishide, true, '检查菜单是否隐藏'); - - $(div).remove(); - start(); - },0); - - },100); - stop(); -}); \ No newline at end of file diff --git a/_test/ui/modal.js b/_test/ui/modal.js deleted file mode 100644 index 18264138..00000000 --- a/_test/ui/modal.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: xuheng - * Date: 13-8-1 - * Time: 下午3:41 - * To change this template use File | Settings | File Templates. - */ -module( 'ui.modal' ); - -test( 'modal--初始化', function() { - var div = document.body.appendChild( document.createElement( 'div' ) ); - $(div).attr('id','test'); - stop(); - setTimeout(function(){ - var $dialog=$.eduimodal({ - title: "titletest", - width: 300, - height: 400, - oklabel:'oktest', - cancellabel:'canceltest' - }).appendTo(div); - - var title=$('.edui-title',$dialog).text(); - equal(title,'titletest','检查dialog标题'); - - var oklabel=$('[data-ok="modal"]',$dialog).text(); - equal(oklabel,'oktest','检查dialog确定按钮文本'); - - var cancellabel=$('.edui-modal-footer [data-hide="modal"]',$dialog).text(); - equal(cancellabel,'canceltest','检查dialog取消按钮文本'); - - var wt=$dialog.width(); - equal(wt,300,'检查dialog宽度'); - - var ht=$('.edui-modal-body',$dialog).height(); - equal(ht,400,'检查dialog高度'); - - div.parentNode.removeChild(div); - start(); - }); -} ); - - -test( 'modal--显示 隐藏', function() { - var div = document.body.appendChild( document.createElement( 'div' ) ); - $(div).attr('id','test'); - stop(); - setTimeout(function(){ - var $dialog=$.eduimodal({ - width: 300, - height: 400 - }).appendTo(div); - - $dialog.edui().toggle(); - var isshow=($dialog.css('display')=="none"); - equal(isshow,false,'检查dialog是否显示'); - - $dialog.edui().toggle(); - var ishide=($dialog.css('display')=="none"); - equal(ishide,true,'检查dialog是否隐藏'); - - div.parentNode.removeChild(div); - start(); - }); -} ); diff --git a/_test/ui/popup.js b/_test/ui/popup.js deleted file mode 100644 index a65c17c3..00000000 --- a/_test/ui/popup.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午5:18 - * To change this template use File | Settings | File Templates. - */ -/** - * Created by JetBrains PhpStorm. - * User: dongyancen - * Date: 12-4-12 - * Time: 下午4:47 - * To change this template use File | Settings | File Templates. - */ -module( 'ui.popup' ); - -test('popup--初始化', function () { - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var $btn = $.eduibutton({ - icon: "bold", - title: "测试" - }).appendTo(div); - - var $popupWidget = $.eduipopup({ - subtpl: 'popup text', - width: '100', - height: '100' - }); - - $popupWidget.edui().show($btn,{ - offsetTop:-5, - offsetLeft:10, - caretLeft:11, - caretTop:-8 - }); - - ; - equal($popupWidget.edui().getBodyContainer()!=null, true, '检查getBodyContaine是否正常'); - - setTimeout(function(){ - - var isshow = $popupWidget.css("display") != "none"; - equal(isshow, true, '检查popup是否显示'); - - $popupWidget.edui().hide(); - var ishide = $popupWidget.css("display") == "none"; - equal(ishide, true, '检查popup是否隐藏'); - - start(); - $(div).remove(); - },100); - stop(); -}); \ No newline at end of file diff --git a/_test/ui/scale.js b/_test/ui/scale.js deleted file mode 100644 index ee92ece8..00000000 --- a/_test/ui/scale.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: dongyancen - * Date: 13-8-1 - * Time: 下午3:41 - * To change this template use File | Settings | File Templates. - */ -module( 'ui.scale' ); - -test( '鼠标在八个角上拖拽改变图片大小', function() { - if ( ua.browser.webkit ) { - var sc = document.createElement("script"); - sc.id="sc"; - sc.type = "text/plain"; - document.body.appendChild(sc); - var editor = UM.getEditor(sc.id, {initialFrameWidth:800,initialFrameHeight:320,autoHeightEnabled:true}); - editor.ready(function () { - editor.setContent( '

        修正webkit下图片选择的问题修正webkit下图片选择的问题

        ' ); - var img = editor.body.getElementsByTagName( 'img' )[0]; - - var $scale = $.eduiscale({'$wrap':editor.$container}).css('zIndex', editor.options.zIndex); - editor.$container.append($scale); - $scale.edui().show($(img)); - ok($scale.css('display')!='none', "检查八个角是否已出现"); - - var width = $scale.width(), - height = $scale.height(); - - ua.mousedown( $scale.find('.edui-scale-hand0')[0], {clientX: 322, clientY: 281} ); - ua.mousemove( document, {clientX: 352, clientY: 301} ); - equal(width-$scale.width(), 30, "检查鼠标拖拽中图片宽度是否正确 --"); - equal(height-$scale.height(), 20, "检查鼠标拖拽中图片高度是否正确 --"); - - ua.mousemove( document, {clientX: 382, clientY: 321} ); - ua.mouseup( document, {clientX: 382, clientY: 321} ); - equal(width-$scale.width(), 60, "检查鼠标拖拽完毕图片高度是否正确 --"); - equal(height-$scale.height(), 40, "检查鼠标拖拽完毕图片高度是否正确 --"); - ok($(img).width() == $scale.width() && $(img).height() == $scale.height(), "检查八个角和图片宽高度是否相等"); - - $scale.edui().hide(); - ok($scale.css('display')=='none', "检查八个角是否已消失"); - domUtils.remove(editor.container); - start(); - }); - stop(); - } -} ); \ No newline at end of file diff --git a/_test/ui/separator.js b/_test/ui/separator.js deleted file mode 100644 index 2cb6f6a0..00000000 --- a/_test/ui/separator.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午5:18 - * To change this template use File | Settings | File Templates. - */ - -module('ui.separator'); - -test('separator--初始化', function () { - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var $separatorWidget = $.eduiseparator().appendTo(div); - equal($separatorWidget.parent()!=null,true, '判断ui是否已插入到dom上'); - equal($separatorWidget.hasClass('edui-separator'),true, '判断ui的html内容是否正确'); - $separatorWidget.parent(); - $(div).remove(); -}); diff --git a/_test/ui/splitbutton.js b/_test/ui/splitbutton.js deleted file mode 100644 index 484902f8..00000000 --- a/_test/ui/splitbutton.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午5:18 - * To change this template use File | Settings | File Templates. - */ - -module('ui.splitbutton'); - -test('splitbutton--初始化', function () { - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var $btn = $.eduisplitbutton({ - "icon":"forecolor", - "caret":true, - "name":"forecolor", - "title":"字体颜色", - "click":function(){ - this.root().addClass('afterBtnClick'); - } - }).appendTo(div); - $btn.edui().disabled(true); - equal($btn.hasClass('edui-disabled'), true, '检查是否有disabled的class'); - $btn.edui().disabled(false); - equal($btn.hasClass('edui-disabled'), false, '检查是否没有disabled的class'); - - $btn.edui().active(true); - equal($btn.edui().active(), true, '检查是否有disabled的class'); - $btn.edui().active(false); - equal($btn.edui().active(), false, '检查是否有disabled的class'); - - $popup = $.eduipopup({ - subtpl: 'popup text', - width: '100', - height: '100' - }); - equal($popup.edui().data('$mergeObj')==null, true, '检查是否没有disabled的class'); - $btn.edui().mergeWith($popup); - equal($popup.edui().data('$mergeObj')!=null, true, '检查是否有disabled的class'); - - $btn.find('.edui-btn:first').trigger('click'); - $btn.find('.edui-dropdown-toggle').trigger('click'); - setTimeout(function(){ - equal($btn.hasClass('afterBtnClick'), true, '判断点击是否触发设定好的监听函数'); - equal($popup.css('display')!='none', true, '判断是否已出现颜色选择面板'); - start(); - }, 50); - - $(div).remove(); - stop(); -}); diff --git a/_test/ui/tab.js b/_test/ui/tab.js deleted file mode 100644 index 8003cc4e..00000000 --- a/_test/ui/tab.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: xuheng - * Date: 13-8-1 - * Time: 下午3:41 - * To change this template use File | Settings | File Templates. - */ -module('ui.tab'); - -test('tab--初始化 操作', function () { - var div = document.body.appendChild(document.createElement('div')); - div.innerHTML = '
          ' + - '
        • 1
        • ' + - '
        • 2
        • ' + - '
        ' + - '
        ' + - '
        1个
        ' + - '
        2个
        ' + - '
        '; - $(div).attr('id', 'edui-test'); - stop(); - setTimeout(function () { - $tab = $.eduitab({selector: "#edui-test"}) - .edui(); - - var index=$tab.activate(); - equal(index,0,'检查tab初始化时应该显示第一个tab'); - - var $tgt=$('[href="#edui-test2"]',$tab.root()); - ua.click($tgt[0]); - var index2=$tab.activate(); - equal(index2,1,'检查点击第2个tab时应该显示第2个tab'); - - div.parentNode.removeChild(div); - start(); - }); -}); diff --git a/_test/ui/toolbar.js b/_test/ui/toolbar.js deleted file mode 100644 index cd90a71e..00000000 --- a/_test/ui/toolbar.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午5:19 - * To change this template use File | Settings | File Templates. - */ - -module('ui.toolbar'); - -test('toolbar--初始化', function () { - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var $toolbarWidget = $.eduitoolbar().appendTo(div); - equal($toolbarWidget.parent()!=null,true, '判断ui是否已插入到dom上'); - equal($toolbarWidget.hasClass('edui-toolbar'),true, '判断ui的html内容是否正确'); - - var $btn = $.eduibutton({ - icon: "bold", - title: "测试按钮" - }); - - $toolbarWidget.edui().appendToBtnmenu([$btn]); - equal($toolbarWidget.html().indexOf('测试按钮')!=-1,true, '判断按钮是否已插入到toolbar'); - - $(div).remove(); -}); diff --git a/_test/ui/tools.js b/_test/ui/tools.js deleted file mode 100644 index d700fa7b..00000000 --- a/_test/ui/tools.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - - */ -(function () { - function mySetup() { - for (var config in window.UMDITOR_CONFIG) { - if (typeof(window.UMDITOR_CONFIG[config]) == 'string') - window.UMDITOR_CONFIG[config] = window.UMDITOR_CONFIG[config].replace('_test/tools/br/', ''); - } - var div = document.body.appendChild(document.createElement('div')); - $(div).css('width', '500px').css('height', '500px').css('border', '1px solid #ccc').attr('id', 'testeditor'); - var editor = UM.getEditor(div.id, {'initialContent':'

        欢迎使用umeditor

        ', 'autoFloatEnabled':false,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); - var ue = new UM.Editor({'UEDITOR_HOME_URL':'../../../', 'autoFloatEnabled':true,webAppKey:'Qr0M9yTEoLIiUSXXQTtq7yFt'}); - QUnit.readyFlag =0; - stop(); - setTimeout(function(){ - editor.ready(function () { - var range = new UM.dom.Range(editor.document,editor.body); - te.dom.push(div); - te.obj.push(editor); - te.obj.push(range); - te.obj.push(ue); - QUnit.readyFlag =1; - }); - },50); - document.getElementsByClassName = function (eleClassName) { - var getEleClass = [];//定义一个数组 - var myclass = new RegExp("\\b" + eleClassName + "\\b");//创建一个正则表达式对像 - var elem = this.getElementsByTagName("*");//获取文档里所有的元素 - for (var h = 0; h < elem.length; h++) { - var classes = elem[h].className;//获取class对像 - if (myclass.test(classes)) getEleClass.push(elem[h]);//正则比较,取到想要的CLASS对像 - } - return getEleClass;//返回数组 - } - } - - var _d = function () { - UM.delEditor('testeditor'); - te.dom.push(te.obj[0].container); - document.getElementById('testeditor')&&te.dom.push(document.getElementById('testeditor')); - if (te) { - if (te.dom && te.dom.length) { - for (var i = 0; i < te.dom.length; i++) { - if (te.dom[i] && te.dom[i].parentNode) - te.dom[i].parentNode.removeChild(te.dom[i]); - } - - } - } - te.dom = []; - te.obj = []; - } - var s = QUnit.testStart, d = QUnit.testDone; - QUnit.testStart = function () { - s.apply(this, arguments); - mySetup(); - }; - QUnit.testDone = function () { - _d(); - d.apply(this, arguments); - } -})(); \ No newline at end of file diff --git a/_test/ui/tooltip.js b/_test/ui/tooltip.js deleted file mode 100644 index 0689b831..00000000 --- a/_test/ui/tooltip.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: xuheng - * Date: 13-8-20 - * Time: 下午4:19 - * To change this template use File | Settings | File Templates. - */ -module('ui.tooltip'); - -test('tooltip', function () { - var div = document.body.appendChild(document.createElement('div')); - var $btn=$.eduibutton({ - icon : "bold", - title: "测试" - }).appendTo(div); - - $(div).attr('id', 'edui-test'); - $.eduitooltip('attachTo',$btn); - - setTimeout(function () { - if(browser.ie){ - ua.mouseenter($btn[0]); - }else{ - ua.mouseover($btn[0]); - } - var isshow=$(".edui-tooltip",$btn).css("display")!="none"; - equal(isshow,true,"检查按钮提示是否显示"); - - ua.click($btn[0]); - - var ishide=$(".edui-tooltip",$btn).css("display")=="none"; - - equal(ishide,true,"检查按钮提示是否隐藏"); - - - $btn.edui().disabled(true); - if(browser.ie){ - ua.mouseenter($btn[0]); - }else{ - ua.mouseover($btn[0]); - } - isHide=$(".edui-tooltip",$btn).css("display")=="none"; - equal(isHide,true,"检查不可用的按钮不应该有提示"); - - div.parentNode.removeChild(div); - - start(); - }); - stop(); -}); \ No newline at end of file diff --git a/_test/ui/widget.js b/_test/ui/widget.js deleted file mode 100644 index ada3dbb5..00000000 --- a/_test/ui/widget.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Created with JetBrains PhpStorm. - * User: Jinqn - * Date: 13-9-2 - * Time: 下午5:19 - * To change this template use File | Settings | File Templates. - */ -module('ui.widget'); -test('widget--初始化',function(){ - var div = document.body.appendChild(document.createElement('div')); - $(div).attr('id', 'test'); - - var $widget = $.eduibutton({ - icon: "bold", - title: "测试" - }).appendTo(div), - widgetedui = $widget.edui(), - AddClassHandler = function(){ - $widget.addClass('testWidget'); - }; - equal($widget.parent()!=null, true, '判断ui是否已插入到dom上'); - - //测试on和trigger方法 - widgetedui.on('click', AddClassHandler); - widgetedui.trigger('click'); - equal($widget.hasClass('testWidget'), true, '判断是否已设置testWidget的class'); - - $widget.removeClass('testWidget'); - equal($widget.hasClass('testWidget'), false, '判断是已去除testWidget的class'); - - //测试off和trigger方法 - widgetedui.off('click', AddClassHandler); - widgetedui.trigger('click'); - equal($widget.hasClass('testWidget'), false, '判断是否没有testWidget的class'); - - //测试root和register方法 - widgetedui.register('click', widgetedui.root(), function(){ - $widget.addClass('registerClick'); - }); - equal($widget.hasClass('registerClick'), false, '判断是否未设置registerClick的class'); - $widget.parent().trigger('click'); - equal($widget.hasClass('registerClick'), true, '判断是否已设置registerClick的class'); - - //测试data方法 - widgetedui.data('testdata', '123456'); - equal(widgetedui.data('testdata'), '123456', '判断是否data数据是否设置正常'); -}); diff --git "a/_test/\345\205\263\351\224\256\345\255\227.txt" "b/_test/\345\205\263\351\224\256\345\255\227.txt" deleted file mode 100644 index 9faca2ce..00000000 --- "a/_test/\345\205\263\351\224\256\345\255\227.txt" +++ /dev/null @@ -1,25 +0,0 @@ -1.2.5 -��������ơ� -���������� -������ճ���� -����ʽ�� -���ַ��߿� -���߼���ɫ�� -��ͼƬ��ק�� -�Ϲ��ܣ� -�������� -���Զ��Ű桿 -��undo�� -��soure�� -��insertcode�� -������ -������������ -��Editor�� -��ճ���� -��URL·���� -��Ԥ���� -�������ύ�� -��ͼƬ�� -�������滻�� - - diff --git a/changelog.md b/changelog.md index 73db1cc6..1efd7a06 100755 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,16 @@ # UMeditor Change List +## 1.2.3 + +### 功能更新 +1. **添加插入数学公式** +2. 支持插入动态地图 +3. 支持复制图片、截屏图片的粘贴 +4. 添加自动保存插件,支持草稿箱功能 +5. 支持拖放图片上传并插入 +6. 优化了对IE11的支持 +7. 支持asp后台 + ## 1.2.2 ### 功能更新 diff --git a/dialogs/image/image.js b/dialogs/image/image.js index b6222df1..9e9e7a3b 100755 --- a/dialogs/image/image.js +++ b/dialogs/image/image.js @@ -141,9 +141,8 @@ uploadTpl: '
        ' + '' + '
        ' + - '' + + '' + '
        ' + - '
        ', init: function (editor, $w) { var me = this; @@ -169,7 +168,7 @@ render: function (sel, t) { var me = this; - $(sel, me.dialog).append($(me.uploadTpl.replace(/%%/g, t))); + $(sel, me.dialog).append($(me.uploadTpl.replace(/%fieldName%/, me.editor.getOpt('imageFieldName')).replace(/%%/g, t))); return me; }, @@ -206,7 +205,8 @@ } $('').insertBefore(me.dialog).on('load', function(){ - var r = this.contentWindow.document.body.innerHTML; + var body = (this.contentDocument || this.contentWindow.document).body, + r = body.innerText || body.textContent || ''; if(r == '')return; me.uploadComplete(r); $(this).unbind('load'); @@ -261,7 +261,7 @@ Base.createImgBase64(img, f, me.dialog); var xhr = new XMLHttpRequest(); - xhr.open("post", me.editor.getOpt('imageUrl') + "?type=ajax", true); + xhr.open("post", me.editor.getOpt('imageUrl'), true); xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); //模拟数据 diff --git a/dialogs/map/map.js b/dialogs/map/map.js index 6f898c4a..7a3317b8 100755 --- a/dialogs/map/map.js +++ b/dialogs/map/map.js @@ -1,4 +1,4 @@ -(function () { +(function(){ var widgetName = 'map'; @@ -183,8 +183,7 @@ } else { me.map.centerAndZoom(points[0], 13); } - point = me.map.getCenter(); - me.marker.setPoint(point); + me.marker.setPosition(me.map.getCenter()); } else { alert(me.lang.errorMsg); } @@ -231,7 +230,7 @@ center = widget.map.getCenter(), zoom = widget.map.getZoom(), size = widget.map.getSize(), - point = widget.marker.P; + point = widget.marker.getPosition(); if (widget.root().find(".edui-map-dynamic")[0].checked) { var URL = editor.getOpt('UMEDITOR_HOME_URL'), diff --git a/dialogs/video/video.css b/dialogs/video/video.css index e046d8c0..fffe2d79 100755 --- a/dialogs/video/video.css +++ b/dialogs/video/video.css @@ -34,7 +34,10 @@ -.edui-dialog-video #eduiVideoPreview{width: 420px; margin-left: 10px; _margin-left:5px; height: 280px;background-color: #ddd;float: left} +.edui-dialog-video #eduiVideoPreview{position: relative;width: 420px;padding:0;overflow: hidden; margin-left: 10px; _margin-left:5px; height: 280px;background-color: #ddd;float: left} +.edui-dialog-video #eduiVideoPreview .previewMsg {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;background-color: #666;} +.edui-dialog-video #eduiVideoPreview .previewMsg span{display:block;margin: 125px auto 0 auto;text-align:center;font-size:18px;color:#fff;} +.edui-dialog-video #eduiVideoPreview .previewVideo {position:absolute;top:0;margin:0;padding:0;height:280px;width:100%;} .edui-dialog-video #eduiVideoInfo {width: 120px;float: left;margin-left: 10px;_margin-left:7px;} .edui-dialog-video .edui-video-wrapper fieldset{ border: 1px solid #ddd; diff --git a/dialogs/video/video.js b/dialogs/video/video.js index 64a47eca..21b2e7e2 100644 --- a/dialogs/video/video.js +++ b/dialogs/video/video.js @@ -1,7 +1,8 @@ - (function(){ - var domUtils = UM.dom.domUtils; - var widgetName = 'video'; + + var utils = UM.utils, + domUtils = UM.dom.domUtils, + widgetName = 'video'; UM.registerWidget( widgetName,{ @@ -93,16 +94,13 @@ lang = me.lang, conUrl = me.convert_url(url); - if(!me.endWith(conUrl,[".swf",".flv",".wmv"])){ - $("#eduiVideoPreview", me.$widget).html( lang.urlError ); - return; - } - $("#eduiVideoPreview", me.$widget)[0].innerHTML = ''+lang.urlError+''+ + ''; - + ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >' + + ''); }, /** * 将单个视频信息插入编辑器中 @@ -126,31 +124,25 @@ }, /** - * URL转换 + * URL转换规则 */ convert_url: function(url){ + if ( !url ) return ''; - var matches = url.match(/youtu.be\/(\w+)$/) || - url.match(/youtube\.com\/watch\?v=(\w+)/) || - url.match(/youtube.com\/v\/(\w+)/), - youku = url.match(/youku\.com\/v_show\/id_(\w+)/), - youkuPlay = /player\.youku\.com/ig.test(url); + url = utils.trim(url) + .replace(/v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/i, 'player.youku.com/player.php/sid/$1/v.swf') + .replace(/(www\.)?youtube\.com\/watch\?v=([\w\-]+)/i, "www.youtube.com/v/$2") + .replace(/youtu.be\/(\w+)$/i, "www.youtube.com/v/$1") + .replace(/v\.ku6\.com\/.+\/([\w\.]+)\.html.*$/i, "player.ku6.com/refer/$1/v.swf") + .replace(/www\.56\.com\/u\d+\/v_([\w\-]+)\.html/i, "player.56.com/v_$1.swf") + .replace(/www.56.com\/w\d+\/play_album\-aid\-\d+_vid\-([^.]+)\.html/i, "player.56.com/v_$1.swf") + .replace(/v\.pps\.tv\/play_([\w]+)\.html.*$/i, "player.pps.tv/player/sid/$1/v.swf") + .replace(/www\.letv\.com\/ptv\/vplay\/([\d]+)\.html.*$/i, "i7.imgs.letv.com/player/swfPlayer.swf?id=$1&autoplay=0") + .replace(/www\.tudou\.com\/programs\/view\/([\w\-]+)\/?/i, "www.tudou.com/v/$1") + .replace(/v\.qq\.com\/cover\/[\w]+\/[\w]+\/([\w]+)\.html/i, "static.video.qq.com/TPout.swf?vid=$1") + .replace(/v\.qq\.com\/.+[\?\&]vid=([^&]+).*$/i, "static.video.qq.com/TPout.swf?vid=$1") + .replace(/my\.tv\.sohu\.com\/[\w]+\/[\d]+\/([\d]+)\.shtml.*$/i, "share.vrs.sohu.com/my/v.swf&id=$1"); - if(youkuPlay){ - url = url.replace(/\?f=.*/, ""); - } else if (matches){ - url = "https://www.youtube.com/v/" + matches[1] + "?version=3&feature=player_embedded"; - }else if(youku){ - url = "http://player.youku.com/player.php/sid/"+youku[1]+"/v.swf" - } else { - url = url.replace(/http:\/\/www\.tudou\.com\/programs\/view\/([\w\-]+)\/?/i, "http://www.tudou.com/v/$1") - .replace(/http:\/\/www\.youtube\.com\/watch\?v=([\w\-]+)/i, "http://www.youtube.com/v/$1") - .replace(/http:\/\/v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/i, "http://player.youku.com/player.php/sid/$1") - .replace(/http:\/\/www\.56\.com\/u\d+\/v_([\w\-]+)\.html/i, "http://player.56.com/v_$1.swf") - .replace(/http:\/\/www.56.com\/w\d+\/play_album\-aid\-\d+_vid\-([^.]+)\.html/i, "http://player.56.com/v_$1.swf") - .replace(/http:\/\/v\.ku6\.com\/.+\/([^.]+)\.html/i, "http://player.ku6.com/refer/$1/v.swf") - .replace(/\?f=.*/, ""); - } return url; }, /** @@ -251,6 +243,7 @@ * 末尾字符检测 */ endWith: function(str,endStrArr){ + // str = str.replace(/\?.*$/, ''); for(var i=0,len = endStrArr.length;i "upload/" , //存储文件夹 @@ -14,8 +17,7 @@ //背景保存在临时目录中 $config[ "savePath" ] = $Path; - $up = new Uploader( "upfile" , $config ); - $type = $_REQUEST['type']; + $up = new Uploader("upfile", $config, $base64); $callback=$_GET['callback']; $info = $up->getFileInfo(); @@ -27,3 +29,4 @@ } else { echo json_encode($info); } +?> \ No newline at end of file diff --git a/themes/default/_css/combobox.css b/themes/default/_css/combobox.css index 0863fb18..11ee4e5e 100644 --- a/themes/default/_css/combobox.css +++ b/themes/default/_css/combobox.css @@ -10,9 +10,9 @@ vertical-align: top; *display: inline ; *zoom:1; - width:60px; - height:20px; - line-height: 20px; + width:50px; + height:16px; + line-height: 18px; padding: 2px; margin: 0; font-size: 12px; diff --git a/themes/default/_css/comboboxmenu.css b/themes/default/_css/comboboxmenu.css index 229552df..e99c3d4a 100644 --- a/themes/default/_css/comboboxmenu.css +++ b/themes/default/_css/comboboxmenu.css @@ -6,7 +6,8 @@ list-style: none; text-decoration: none; margin: 0; - padding:5px; + margin-left: 2px; + padding:3px; background-color: #ffffff; border: 1px solid #ccc; font-size: 12px; @@ -26,7 +27,7 @@ display: inline-block; _display: inline; _zoom: 1; - margin-left: 10px; + margin-left: 3px; } .edui-combobox-menu .edui-combobox-item:hover, .edui-combobox-menu .edui-combobox-stack-item:hover, .edui-combobox-menu .edui-combobox-item-hover { @@ -39,7 +40,7 @@ display: inline-block; *zoom: 1; *display: inline; - width: 24px; + width: 20px; height: 25px; background: red; vertical-align: bottom; @@ -47,12 +48,12 @@ } .edui-combobox-menu .edui-combobox-checked .edui-combobox-icon { - background-position: 10px 7px; + background-position: 5px 7px; } .edui-combobox-menu .edui-combobox-item-separator { - min-width: 160px; + min-width: 150px; height: 1px; line-height: 1px; overflow: hidden; @@ -64,19 +65,19 @@ /* 字体样式校正 */ .edui-combobox-fontsize .edui-combobox-item-0.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 7px; + background-position: 5px 7px; } .edui-combobox-fontsize .edui-combobox-item-1.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 7px; + background-position: 5px 7px; } .edui-combobox-fontsize .edui-combobox-item-2.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 7px; + background-position: 5px 7px; } .edui-combobox-fontsize .edui-combobox-item-3.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 7px; + background-position: 5px 7px; } /* 24 */ @@ -86,7 +87,7 @@ } .edui-combobox-fontsize .edui-combobox-item-4.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 5px; + background-position: 5px 5px; } /* 32 */ @@ -96,7 +97,7 @@ } .edui-combobox-fontsize .edui-combobox-item-5.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 4px; + background-position: 5px 4px; } @@ -112,7 +113,7 @@ /*}*/ /*.edui-combobox-fontsize .edui-combobox-item-6.edui-combobox-checked .edui-combobox-icon {*/ - /*background-position: 10px 7px;*/ + /*background-position: 5px 7px;*/ /*}*/ @@ -130,7 +131,7 @@ } .edui-combobox-paragraph .edui-combobox-item-1.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 7px; + background-position: 5px 7px; } /* h2 */ @@ -145,7 +146,7 @@ } .edui-combobox-paragraph .edui-combobox-item-2.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 10px; + background-position: 5px 10px; } /* h3 */ @@ -161,7 +162,7 @@ } .edui-combobox-paragraph .edui-combobox-item-3.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 11px; + background-position: 5px 11px; } /* h4 */ @@ -172,7 +173,7 @@ } .edui-combobox-paragraph .edui-combobox-item-4.edui-combobox-checked .edui-combobox-icon { - background-position: 10px 6px; + background-position: 5px 6px; } /* h5 */ diff --git a/themes/default/_css/reset.css b/themes/default/_css/reset.css new file mode 100755 index 00000000..c43ca348 --- /dev/null +++ b/themes/default/_css/reset.css @@ -0,0 +1,5 @@ +.edui-container .edui-editor-body .edui-body-container em{ + font-style: italic; +} + +/* TODO 有待添加完整的重置样式 */ \ No newline at end of file diff --git a/themes/default/_css/umeditor.css b/themes/default/_css/umeditor.css index 315a0321..8268b7c7 100755 --- a/themes/default/_css/umeditor.css +++ b/themes/default/_css/umeditor.css @@ -1,4 +1,5 @@ @import "editor.css"; +@import "reset.css"; @import "button.css"; @import "buttonicon.css"; @import "splitbutton.css"; @@ -10,4 +11,4 @@ @import "tab.css"; @import "tooltip.css"; @import "colorpicker.css"; -@import "separator.css"; +@import "separator.css"; \ No newline at end of file diff --git a/third-party/jquery-1.10.2.min.map b/third-party/jquery-1.10.2.min.map new file mode 100644 index 00000000..4dc4920b --- /dev/null +++ b/third-party/jquery-1.10.2.min.map @@ -0,0 +1 @@ +{"version":3,"file":"jquery-1.10.2.min.js","sources":["jquery-1.10.2.js"],"names":["window","undefined","readyList","rootjQuery","core_strundefined","location","document","docElem","documentElement","_jQuery","jQuery","_$","$","class2type","core_deletedIds","core_version","core_concat","concat","core_push","push","core_slice","slice","core_indexOf","indexOf","core_toString","toString","core_hasOwn","hasOwnProperty","core_trim","trim","selector","context","fn","init","core_pnum","source","core_rnotwhite","rtrim","rquickExpr","rsingleTag","rvalidchars","rvalidbraces","rvalidescape","rvalidtokens","rmsPrefix","rdashAlpha","fcamelCase","all","letter","toUpperCase","completed","event","addEventListener","type","readyState","detach","ready","removeEventListener","detachEvent","prototype","jquery","constructor","match","elem","this","charAt","length","exec","find","merge","parseHTML","nodeType","ownerDocument","test","isPlainObject","isFunction","attr","getElementById","parentNode","id","makeArray","toArray","call","get","num","pushStack","elems","ret","prevObject","each","callback","args","promise","done","apply","arguments","first","eq","last","i","len","j","map","end","sort","splice","extend","src","copyIsArray","copy","name","options","clone","target","deep","isArray","expando","Math","random","replace","noConflict","isReady","readyWait","holdReady","hold","wait","body","setTimeout","resolveWith","trigger","off","obj","Array","isWindow","isNumeric","isNaN","parseFloat","isFinite","String","key","e","support","ownLast","isEmptyObject","error","msg","Error","data","keepScripts","parsed","scripts","createElement","buildFragment","remove","childNodes","parseJSON","JSON","parse","Function","parseXML","xml","tmp","DOMParser","parseFromString","ActiveXObject","async","loadXML","getElementsByTagName","noop","globalEval","execScript","camelCase","string","nodeName","toLowerCase","value","isArraylike","text","arr","results","Object","inArray","max","second","l","grep","inv","retVal","arg","guid","proxy","access","chainable","emptyGet","raw","bulk","now","Date","getTime","swap","old","style","Deferred","attachEvent","top","frameElement","doScroll","doScrollCheck","split","cachedruns","Expr","getText","isXML","compile","outermostContext","sortInput","setDocument","documentIsHTML","rbuggyQSA","rbuggyMatches","matches","contains","preferredDoc","dirruns","classCache","createCache","tokenCache","compilerCache","hasDuplicate","sortOrder","a","b","strundefined","MAX_NEGATIVE","hasOwn","pop","push_native","booleans","whitespace","characterEncoding","identifier","attributes","pseudos","RegExp","rcomma","rcombinators","rsibling","rattributeQuotes","rpseudo","ridentifier","matchExpr","ID","CLASS","TAG","ATTR","PSEUDO","CHILD","bool","needsContext","rnative","rinputs","rheader","rescape","runescape","funescape","_","escaped","escapedWhitespace","high","fromCharCode","els","Sizzle","seed","m","groups","nid","newContext","newSelector","getElementsByClassName","qsa","tokenize","getAttribute","setAttribute","toSelector","join","querySelectorAll","qsaError","removeAttribute","select","keys","cache","cacheLength","shift","markFunction","assert","div","removeChild","addHandle","attrs","handler","attrHandle","siblingCheck","cur","diff","sourceIndex","nextSibling","createInputPseudo","createButtonPseudo","createPositionalPseudo","argument","matchIndexes","node","doc","parent","defaultView","className","appendChild","createComment","innerHTML","firstChild","getById","getElementsByName","filter","attrId","getAttributeNode","tag","input","matchesSelector","webkitMatchesSelector","mozMatchesSelector","oMatchesSelector","msMatchesSelector","disconnectedMatch","compareDocumentPosition","adown","bup","compare","sortDetached","aup","ap","bp","unshift","expr","elements","val","specified","uniqueSort","duplicates","detectDuplicates","sortStable","textContent","nodeValue","selectors","createPseudo","relative",">","dir"," ","+","~","preFilter","excess","unquoted","nodeNameSelector","pattern","operator","check","result","what","simple","forward","ofType","outerCache","nodeIndex","start","useCache","lastChild","pseudo","setFilters","idx","matched","not","matcher","unmatched","has","innerText","lang","elemLang","hash","root","focus","activeElement","hasFocus","href","tabIndex","enabled","disabled","checked","selected","selectedIndex","empty","header","button","even","odd","lt","gt","radio","checkbox","file","password","image","submit","reset","filters","parseOnly","tokens","soFar","preFilters","cached","addCombinator","combinator","base","checkNonElements","doneName","dirkey","elementMatcher","matchers","condense","newUnmatched","mapped","setMatcher","postFilter","postFinder","postSelector","temp","preMap","postMap","preexisting","multipleContexts","matcherIn","matcherOut","matcherFromTokens","checkContext","leadingRelative","implicitRelative","matchContext","matchAnyContext","matcherFromGroupMatchers","elementMatchers","setMatchers","matcherCachedRuns","bySet","byElement","superMatcher","expandContext","setMatched","matchedCount","outermost","contextBackup","dirrunsUnique","group","contexts","token","div1","defaultValue","unique","isXMLDoc","optionsCache","createOptions","object","flag","Callbacks","firing","memory","fired","firingLength","firingIndex","firingStart","list","stack","once","fire","stopOnFalse","self","disable","add","index","lock","locked","fireWith","func","tuples","state","always","deferred","fail","then","fns","newDefer","tuple","action","returned","resolve","reject","progress","notify","pipe","stateString","when","subordinate","resolveValues","remaining","updateFunc","values","progressValues","notifyWith","progressContexts","resolveContexts","fragment","opt","eventName","isSupported","cssText","getSetAttribute","leadingWhitespace","tbody","htmlSerialize","hrefNormalized","opacity","cssFloat","checkOn","optSelected","enctype","html5Clone","cloneNode","outerHTML","inlineBlockNeedsLayout","shrinkWrapBlocks","pixelPosition","deleteExpando","noCloneEvent","reliableMarginRight","boxSizingReliable","noCloneChecked","optDisabled","radioValue","createDocumentFragment","appendChecked","checkClone","click","change","focusin","backgroundClip","clearCloneStyle","container","marginDiv","tds","divReset","offsetHeight","display","reliableHiddenOffsets","zoom","boxSizing","offsetWidth","getComputedStyle","width","marginRight","rbrace","rmultiDash","internalData","pvt","acceptData","thisCache","internalKey","isNode","toJSON","internalRemoveData","isEmptyDataObject","cleanData","noData","applet","embed","hasData","removeData","_data","_removeData","dataAttr","queue","dequeue","startLength","hooks","_queueHooks","next","stop","setter","delay","time","fx","speeds","timeout","clearTimeout","clearQueue","count","defer","nodeHook","boolHook","rclass","rreturn","rfocusable","rclickable","ruseDefault","getSetInput","removeAttr","prop","removeProp","propFix","addClass","classes","clazz","proceed","removeClass","toggleClass","stateVal","classNames","hasClass","valHooks","set","option","one","optionSet","nType","attrHooks","propName","attrNames","for","class","notxml","propHooks","tabindex","parseInt","getter","setAttributeNode","createAttribute","coords","contenteditable","rformElems","rkeyEvent","rmouseEvent","rfocusMorph","rtypenamespace","returnTrue","returnFalse","safeActiveElement","err","global","types","events","t","handleObjIn","special","eventHandle","handleObj","handlers","namespaces","origType","elemData","handle","triggered","dispatch","delegateType","bindType","namespace","delegateCount","setup","mappedTypes","origCount","teardown","removeEvent","onlyHandlers","ontype","bubbleType","eventPath","Event","isTrigger","namespace_re","noBubble","parentWindow","isPropagationStopped","preventDefault","isDefaultPrevented","_default","fix","handlerQueue","delegateTarget","preDispatch","currentTarget","isImmediatePropagationStopped","stopPropagation","postDispatch","sel","originalEvent","fixHook","fixHooks","mouseHooks","keyHooks","props","srcElement","metaKey","original","which","charCode","keyCode","eventDoc","fromElement","pageX","clientX","scrollLeft","clientLeft","pageY","clientY","scrollTop","clientTop","relatedTarget","toElement","load","blur","beforeunload","returnValue","simulate","bubble","isSimulated","defaultPrevented","getPreventDefault","timeStamp","cancelBubble","stopImmediatePropagation","mouseenter","mouseleave","orig","related","submitBubbles","form","_submit_bubble","changeBubbles","propertyName","_just_changed","focusinBubbles","attaches","on","origFn","triggerHandler","isSimple","rparentsprev","rneedsContext","guaranteedUnique","children","contents","prev","targets","winnow","is","closest","pos","prevAll","addBack","sibling","parents","parentsUntil","until","nextAll","nextUntil","prevUntil","siblings","contentDocument","contentWindow","reverse","n","r","qualifier","createSafeFragment","nodeNames","safeFrag","rinlinejQuery","rnoshimcache","rleadingWhitespace","rxhtmlTag","rtagName","rtbody","rhtml","rnoInnerhtml","manipulation_rcheckableType","rchecked","rscriptType","rscriptTypeMasked","rcleanScript","wrapMap","legend","area","param","thead","tr","col","td","safeFragment","fragmentDiv","optgroup","tfoot","colgroup","caption","th","append","createTextNode","domManip","manipulationTarget","prepend","insertBefore","before","after","keepData","getAll","setGlobalEval","dataAndEvents","deepDataAndEvents","html","replaceWith","allowIntersection","hasScripts","iNoClone","disableScript","restoreScript","_evalUrl","content","refElements","cloneCopyEvent","dest","oldData","curData","fixCloneNodeIssues","defaultChecked","defaultSelected","appendTo","prependTo","insertAfter","replaceAll","insert","found","fixDefaultChecked","destElements","srcElements","inPage","selection","wrap","safe","nodes","url","ajax","dataType","throws","wrapAll","wrapInner","unwrap","iframe","getStyles","curCSS","ralpha","ropacity","rposition","rdisplayswap","rmargin","rnumsplit","rnumnonpx","rrelNum","elemdisplay","BODY","cssShow","position","visibility","cssNormalTransform","letterSpacing","fontWeight","cssExpand","cssPrefixes","vendorPropName","capName","origName","isHidden","el","css","showHide","show","hidden","css_defaultDisplay","styles","hide","toggle","cssHooks","computed","cssNumber","columnCount","fillOpacity","lineHeight","order","orphans","widows","zIndex","cssProps","float","extra","_computed","minWidth","maxWidth","getPropertyValue","currentStyle","left","rs","rsLeft","runtimeStyle","pixelLeft","setPositiveNumber","subtract","augmentWidthOrHeight","isBorderBox","getWidthOrHeight","valueIsBorderBox","actualDisplay","write","close","$1","visible","margin","padding","border","prefix","suffix","expand","expanded","parts","r20","rbracket","rCRLF","rsubmitterTypes","rsubmittable","serialize","serializeArray","traditional","s","encodeURIComponent","ajaxSettings","buildParams","v","hover","fnOver","fnOut","bind","unbind","delegate","undelegate","ajaxLocParts","ajaxLocation","ajax_nonce","ajax_rquery","rhash","rts","rheaders","rlocalProtocol","rnoContent","rprotocol","rurl","_load","prefilters","transports","allTypes","addToPrefiltersOrTransports","structure","dataTypeExpression","dataTypes","inspectPrefiltersOrTransports","originalOptions","jqXHR","inspected","seekingTransport","inspect","prefilterOrFactory","dataTypeOrTransport","ajaxExtend","flatOptions","params","response","responseText","complete","status","active","lastModified","etag","isLocal","processData","contentType","accepts","*","json","responseFields","converters","* text","text html","text json","text xml","ajaxSetup","settings","ajaxPrefilter","ajaxTransport","cacheURL","responseHeadersString","timeoutTimer","fireGlobals","transport","responseHeaders","callbackContext","globalEventContext","completeDeferred","statusCode","requestHeaders","requestHeadersNames","strAbort","getResponseHeader","getAllResponseHeaders","setRequestHeader","lname","overrideMimeType","mimeType","code","abort","statusText","finalText","success","method","crossDomain","hasContent","ifModified","headers","beforeSend","send","nativeStatusText","responses","isSuccess","modified","ajaxHandleResponses","ajaxConvert","rejectWith","getJSON","getScript","firstDataType","ct","finalDataType","conv2","current","conv","dataFilter","script","text script","head","scriptCharset","charset","onload","onreadystatechange","isAbort","oldCallbacks","rjsonp","jsonp","jsonpCallback","originalSettings","callbackName","overwritten","responseContainer","jsonProp","xhrCallbacks","xhrSupported","xhrId","xhrOnUnloadAbort","createStandardXHR","XMLHttpRequest","createActiveXHR","xhr","cors","username","open","xhrFields","firefoxAccessException","unload","fxNow","timerId","rfxtypes","rfxnum","rrun","animationPrefilters","defaultPrefilter","tweeners","tween","createTween","unit","scale","maxIterations","createFxNow","animation","collection","Animation","properties","stopped","tick","currentTime","startTime","duration","percent","tweens","run","opts","specialEasing","originalProperties","Tween","easing","gotoEnd","propFilter","timer","anim","tweener","prefilter","oldfire","dataShow","unqueued","overflow","overflowX","overflowY","eased","step","cssFn","speed","animate","genFx","fadeTo","to","optall","doAnimation","finish","stopQueue","timers","includeWidth","height","slideDown","slideUp","slideToggle","fadeIn","fadeOut","fadeToggle","linear","p","swing","cos","PI","interval","setInterval","clearInterval","slow","fast","animated","offset","setOffset","win","box","getBoundingClientRect","getWindow","pageYOffset","pageXOffset","curElem","curOffset","curCSSTop","curCSSLeft","calculatePosition","curPosition","curTop","curLeft","using","offsetParent","parentOffset","scrollTo","Height","Width","defaultExtra","funcName","size","andSelf","module","exports","define","amd"],"mappings":"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"} \ No newline at end of file diff --git a/umeditor.config.js b/umeditor.config.js index 212dc8e9..13b2596e 100755 --- a/umeditor.config.js +++ b/umeditor.config.js @@ -147,7 +147,7 @@ 'insertorderedlist insertunorderedlist | selectall cleardoc paragraph | fontfamily fontsize' , '| justifyleft justifycenter justifyright justifyjustify |', 'link unlink | emotion image video | map', - '| horizontal print preview fullscreen', 'drafts', 'formula' + '| horizontal print preview fullscreen', 'drafts', 'formula' ] //语言配置项,默认是zh-cn。有需要的话也可以使用如下这样的方式来自动多语言切换,当然,前提条件是lang文件夹下存在对应的语言文件: