作为一名Web开发者,最讨厌的事情就是重复性任务,摆脱乏味的日常重复性事物的一种方法,是借助可重用的对象或者说与你现在建立的ADS库类似的库,另外一种让事情变得有意思,且能够加速开发进程的方式是编写能够创建代码的代码。

本节讲的工具,就是它可以在快速生成要的DOM代码是用来取代使用innerHTML字符串

HTML代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DOM Generation</title>
<title>AdvancED DOM Scripting Sample Document</title>
<!-- inclue some CSS style sheet to make everything look a little nicer -->
<link rel="stylesheet" type="text/css" href="../../shared/source.css" />
<link rel="stylesheet" type="text/css" href="../chapter.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <!-- Your ADS library with the common JavaScript objects -->
<script type="text/javascript" src="../../ADS-final-verbose.js"></script>
<!-- Log object from Chapter 2 -->
<script type="text/javascript" src="../../chapter2/myLogger-final/myLogger.js"></script>
<!-- The DOM generation file -->
<script type="text/javascript" src="generateDOM.js"></script>
<!-- The load script -->
<script type="text/javascript" src="load.js"></script>
</head>
<body>
<h1>DOM Generation</h1>
<div id="content">
<form id="generator" action="">
<fieldset>
<h2>Source</h2>
<label for="source">Enter an HTML document fragment</label>
<textarea id="source" cols="30" rows="15">
</textarea>
<input id="generate" type="button" value="↓ generate ↓" />
<h2>DOM Code</h2>
<label for="result">and voila! DOM goodness:</label>
<textarea id="result" cols="30" rows="15"></textarea>
</fieldset>
</form>
</div>
</body> </html>

页面包含一个generateDOM.js文件和一个调用generateDOM()方法,转换HTML代码的非常简单的load.js脚本

//向页面中添加载入事件,注册事件侦听器
ADS.addEvent(window,'load',function(){
//在按钮上注册一个单机时间侦听器
ADS.addEvent('generate','click',function(W3CEvent){
//取得HTML源代码
var source=ADS.$('source').value;
//将HTML转换成DOM并放到#result文本区
ADS.$('result').value=generateDOM(source);
});
});

在构建generateDOM对象的框架之前,还需要想ADS.js添加几个方法

/*把对原型的修改放在ADS命名控件之外,是为了提醒你对内部String对象的prototype
的修改会影响到整个脚本中的每个字符串,而不仅仅是在ADS.generateDOM对象内部有影响
//重复一个字符串
if (!String.repeat)
{
String.prototype.repeat=function(s)
{
return new Array(s+1).join(this);
}
}
//var example='a'.repeat(5);
//example现在是aaaaa
//清除结尾 和开头处的空白符
if (!String.trim)
{
String.prototype.trim=function(){
retun this.replace(/^\s+|\s+$/g,'');
}
}
*/

在ADS.js库中添加一下代码

//把word-word转换为wordWord
//用于处理嵌入式样式的属性。
function camelize(s)
{
return s.replace(/-(\w/)/g,function(strMatch,p1){
return p1.toUpperCase();
});
}
window['ADS']['camelize']=camelize;

下面剩下唯一意见事就是在generateDOM.js文件中创建generateDOM对象了。框架以创建一个新的命名空间开始,人后包含了一些辅助方法和属性,最后是为window方法复制的代码:

//generateDOM对象的新命名空间
(function () { //保证字符串是一个安全的js字符串,因为转换工具生成的字符串会包含在单引号中
//所以只需要转移反斜杠、单引号和换行符即可
function encode(str) {
if (!str) {
return null;
}
str = str.replace(/\\/g, '\\\\');
str = str.replace(/';/g, "\\'"); str = str.replace(/\s+^/mg, "\\n");
return str;
}
//查找所有节点中那些特殊的$var字符串。并对他们进行处理
//检查是否存在美元符号,如果是,则返回一个带引号的字符串或者一个变量名称
//而且还会把变量声明添加到requiredVariables字符串中。
function checkForVariable(v) {
if (v.indexOf('$') == -1) {
v = '\'' + v + '\'';
}
else {
//因MSIE会添加锚完整路径故需要取得该字符串从$到结尾出的子字符串
v = v.substring(v.indexOf('$') + 1);
requiredVariables += 'var' + v + ';\n'
}
return v;
} var domCode = '';
var nodeNameCounters = [];
var requiredVariables = '';
var newVariables = ''; //借助如下代码,了解他内部工作过程
function generate(strHTML, strRoot) {
//将HTML代码添加到页面的主题中以便能遍历相应的DOM树
var domRoot = document.createElement('DIV');
//因为你可以控制在那个浏览器运行这个工具,所有innerHTML是可以使用的
domRoot.innerHTML = strHTML; //重置变量
domCode = '';
nodeNameCounters = [];
requireVariables = '';
newVariables = ''; //使用processNode()处理domRoot中的所有子节点
var node = domRoot.firstChild;
while (node) {
ADS.walkTheDOMRecursive(processNode, node, 0, strRoot);
node = node.nextSibling;
} //输出生成的代码
domCode =
'/*requiredVariables in this code\n' + requiredVariables + '*/\n\n'
+ domCode + '\n\n' + '/* new objects in this code\n' + newVariables + '*/\n\n';
return domCode;
} //循环遍历子节点
function processNode(tabCount, refParent) {
//根据树的深度级别重复制表符以便对每一行进行适当的缩进,代码更清晰,更容易理解
var tabs = (tabCount ? '\t'.repeat(parseInt(tabCount)) : ''); //确定节点类型并处理元素和文本节点
switch (this.nodeType) {
//处理元素节点
case ADS.node.ELEMENT_NODE:
//计数器加1并创建一个使用标签和计数器的值表示的新变量,例如a1,a2,a3
if (nodeNameCounters[this.nodeName]) {
++nodeNameCounters[this.nodeName];
}
else {
nodeNameCounters[this.nodeName]=1
} var ref = this.nodeName.toLowerCase() + nodeNameCounters[this.nodeName];
//添加创建这个元素的DOM代码航
domCode += tabs + 'var ' + ref + ' =document.createElement(\''
+ this.nodeName + '\');\n'; //将新变量添加到列表中以便在结束中报告他们
newVariables += '' + ref + ';\n'; //检测是否存在属性,如果是则循环遍历这些属性,并使用processAttribute()
//遍历他们的DOM树
if (this.attributes) {
for (var i = 0; i < this.attributes.length; i++) {
ADS.walkTheDOMRecursive(processAttribute, this.attributes[i], tabCount, ref);
}
}
break;
//处理文本节点
case ADS.node.TEXT_NODE:
//检测文本节点中除了空白符之外的值
var value = (this.nodeValue ? encode(this.nodeValue.trim()) : '');
if (value) {
//计数器加1并创建一个使用txt和计数器的值
//表示的新变量,例如txt1,txt2...
if (nodeNameCounters['txt']) {
++nodeNameCounters['txt'];
}
else {
nodeNameCounters['txt'] = 1;
}
var ref = 'txt' + nodeNameCounters['txt']; //检查是不是$var格式的值
value = checkForVariable(value); //添加创建这个元素的DOM代码
domCode += tabs + 'var' + ref + ' =document.createTextNode(' + value + ');\n';
//将新变量添加到列表中以便在结果中报告它们
newVariables += '' + ref + ';\n'; }
else {
//如果不存在值(或者只是空白符)则返回
//即这个节点将不会被添加到父节点中
return;
}
break;
default:
//忽略其他情况
break;
}
//添加将这个节点添加到父节点的代码
if (refParent) {
domCode += tabs + refParent + '.appendChild(' + ref + ');\n';
}
return ref;
} function processAttribute(tabCount, refParent) {
//跳过文本节点
if (this.nodeType != ADS.node.ATTRIBUTE_NODE) {
return;
}
//取得属性值
var attrValue = (this.nodeValue ? encode(this.nodeValue.trim()) : '');
if (this.nodeName == 'cssText') {
alert('true');
}
//如果没有值返回
if (!attrValue) {
return;
}
//确定缩进级别
var tabs = (tabCount ? '\t'.repeat(parseInt(tabCount)) : '');
//根据nodeName进行判断,除了class和style需要特殊注意以外,所有类型都可以按常规来处理
switch (this.nodeName) {
default:
if (this.nodeName.substring(0, 2) == 'on') {
//如果属性名称以‘on’开头,说明是一个嵌入事件属性,
//也就需要重新创建一个给该属性复制的函数
domCode += tabs + refParent + '.' + this.nodeName + '=function(){' + attrValue + '}\n'; } else {
//对于其他情况则使用setAttribute
domCode += tabs + refParent + '.setAttribute(\'' + this.nodeName + '\'.' + checkForVariable(attrValue)
+ ');\n';
}
break;
case 'class':
//使用className属性为class赋值
domCode += tabs + refParent + '.className=' + checkForVariable(attrValue)
+ ';\n';
break;
case 'style':
//使用增则表达式基于;和临近的空格符来分割样式属性的值
var style = attrValue.split(/\s*;\s*/);
if (style) {
for (pair in style) {
if (!style[pair]) {
continue;
}
//使用增则表达式基于;和临近的空格符来分割样式属性的值
var prop = style[pair].split(/\s*:\s*/);
if (!prop[1]) {
continue;
}
//将css-property格式的css属性转换为cssProperty格式
prop[0] = ADS.camelize(prop[0]);
var propValue = checkForVariable(prop[1]);
if (prop[0] == 'float') {
//float是保留字,因此属特殊情况,cssFloat是标准属性
//styleFloat是ie使用的属性
domCode += tabs + refParent + '.style.cssFloat=' + propValue + ';\n';
domCode += tabs + refParent + '.style.styleFloat=' + propValue + ';\n'; }
else {
domCode += tabs + refParent + '.style=' + propValue + ';\n';
} }
}
break;
}
} window['generateDOM'] = generate;
})();

demo:http://vdisk.weibo.com/s/Da3Hr

JavaScript DOM高级程序设计 3.6 实例 将HTML代码转换成DOM代码(附源码)--我要坚持到底!的更多相关文章

  1. 【JavaScript】使用纯JS实现多张图片的懒加载(附源码)

    一.效果图如下 上面的效果图,效果需求如下 1.还没加载图片的时候,默认显示加载图片背景图 2.刚开始进入页面,自动加载第一屏幕的图片 3.下拉界面,当一张图片容器完全显露出屏幕,即刻加载图片,替换背 ...

  2. C#共享内存实例 附源码

    原文 C#共享内存实例 附源码 网上有C#共享内存类,不过功能太简单了,并且写内存每次都从开头写.故对此进行了改进,并做了个小例子,供需要的人参考. 主要改进点: 通过利用共享内存的一部分空间(以下称 ...

  3. 业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份

    业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份 WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多.大家对我做的这个行业 ...

  4. (转)干货|这篇TensorFlow实例教程文章告诉你GANs为何引爆机器学习?(附源码)

    干货|这篇TensorFlow实例教程文章告诉你GANs为何引爆机器学习?(附源码) 该博客来源自:https://mp.weixin.qq.com/s?__biz=MzA4NzE1NzYyMw==& ...

  5. 超详细的php用户注册页面填写信息完整实例(附源码)

    这篇文章主要介绍了一个超详细的php用户注册页面填写信息完整实例,内容包括邮箱自动匹配.密码强度验证以及防止表单重复等,小编特别喜欢这篇文章,推荐给大家. 注册页面是大多数网站必备的页面,所以很有必要 ...

  6. HTML5与CSS3实例教程(第2版) 附源码 中文pdf扫描版

    HTML5和CSS3技术是目前整个网页的基础.<HTML5与CSS3实例教程(第2版)>共分3部分,集中讨论了HTML5和CSS3规范及其技术的使用方法.这一版全面讲解了最新的HTML5和 ...

  7. JavaScript DOM高级程序设计 2.4-try{}catch{}--我要坚持到底!

    先看一段有异常的语句 var sound = 'Roar!'; function myOrneryBeast() { this.style.color='green';//window没有style属 ...

  8. 客户端哈希加密(Javascript哈希加密,附源码)

    摘要 我们很难想象用户在什么样的网络环境使用我们开发的应用,如果用户所处的网络环境不是一个可信任的环境,那么用户的账户安全就可能有威胁,比如用户登陆时提交的账号密码被网络嗅探器窃取:客户端加密数据能有 ...

  9. 微信公众账号开发教程(三) 实例入门:机器人(附源码) ——转自http://www.cnblogs.com/yank/p/3409308.html

    一.功能介绍 通过微信公众平台实现在线客服机器人功能.主要的功能包括:简单对话.查询天气等服务. 这里只是提供比较简单的功能,重在通过此实例来说明公众平台的具体研发过程.只是一个简单DEMO,如果需要 ...

随机推荐

  1. C#基础(八)——C#数据类型的转换

    C#数据类型的转换主要有以下几种方式: 1.强制转换 注意:char类型不能强制转换成int,如果使用强制转化,得到的是原整数的ASCII码值. 2.class.parse(string类型的变量), ...

  2. <script type="text/html"></script> js模版使用

    <div></div> <script type="text/html" id="javascript_template"> ...

  3. Div 内部所有元素 全部垂直对齐

    http://stackoverflow.com/questions/7273338/how-to-vertically-align-an-image-inside-div How it works: ...

  4. html实现层叠加

    <div id="canvasesdiv" style="position:relative; width:400px; height:300px"> ...

  5. const和#define的区别

    在刷题的时候经常遇到定义全局常量我一般都是用#define(可能是因为很少接触const的原因) 在昨天做到51nod1082时照常暴力用#define定义最大.可是提交超时..... 后来看他人写的 ...

  6. Java语法糖

    1.创建数组:String[] s = new String[]{"1","2","3"};//这种方法可以在不指定数组元素数量的情况下生成 ...

  7. 【转】O'Reilly Java系列书籍建议阅读顺序(转自蔡学庸)

    Learning Java the O'Reilly's Way (Part I) Java 技术可以说是越来越重要了,不但可以用在计算机上,甚至连电视等家电用品,行动电话.个人数字助理(PDA)等电 ...

  8. easy ui 异步上传文件,跨域

    easy ui 跨域上传文件,代码如下: 1.html代码:(这段代码是个win窗体,我在点击上传图片按钮然后弹出一个上传图片的窗体,选择图片再进行上传,这样在form提交时,提交的参数会少一点.) ...

  9. Google面试题

    今天早上在Quora上看到的一个题目,很不错的!最直观的是枚举n^3,但稍微进步一点的观察是找出3个数,然后最大的减去最小的2倍的结果,然后就有了线性扫一遍就OK. Given three array ...

  10. win7下以兼容模式安装oracle10g

    在win7系统装Oracle时经常会遇到一个“Oracle 10g 出现程序异常终止,发生内部错误!请将以下文件提供给 Oracle技术部门“未知”“未知”“未知””这样一个错误,百度了下,才知道原来 ...