JavaScript DOM高级程序设计 3.6 实例 将HTML代码转换成DOM代码(附源码)--我要坚持到底!
作为一名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代码(附源码)--我要坚持到底!的更多相关文章
- 【JavaScript】使用纯JS实现多张图片的懒加载(附源码)
一.效果图如下 上面的效果图,效果需求如下 1.还没加载图片的时候,默认显示加载图片背景图 2.刚开始进入页面,自动加载第一屏幕的图片 3.下拉界面,当一张图片容器完全显露出屏幕,即刻加载图片,替换背 ...
- C#共享内存实例 附源码
原文 C#共享内存实例 附源码 网上有C#共享内存类,不过功能太简单了,并且写内存每次都从开头写.故对此进行了改进,并做了个小例子,供需要的人参考. 主要改进点: 通过利用共享内存的一部分空间(以下称 ...
- 业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份
业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份 WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多.大家对我做的这个行业 ...
- (转)干货|这篇TensorFlow实例教程文章告诉你GANs为何引爆机器学习?(附源码)
干货|这篇TensorFlow实例教程文章告诉你GANs为何引爆机器学习?(附源码) 该博客来源自:https://mp.weixin.qq.com/s?__biz=MzA4NzE1NzYyMw==& ...
- 超详细的php用户注册页面填写信息完整实例(附源码)
这篇文章主要介绍了一个超详细的php用户注册页面填写信息完整实例,内容包括邮箱自动匹配.密码强度验证以及防止表单重复等,小编特别喜欢这篇文章,推荐给大家. 注册页面是大多数网站必备的页面,所以很有必要 ...
- HTML5与CSS3实例教程(第2版) 附源码 中文pdf扫描版
HTML5和CSS3技术是目前整个网页的基础.<HTML5与CSS3实例教程(第2版)>共分3部分,集中讨论了HTML5和CSS3规范及其技术的使用方法.这一版全面讲解了最新的HTML5和 ...
- JavaScript DOM高级程序设计 2.4-try{}catch{}--我要坚持到底!
先看一段有异常的语句 var sound = 'Roar!'; function myOrneryBeast() { this.style.color='green';//window没有style属 ...
- 客户端哈希加密(Javascript哈希加密,附源码)
摘要 我们很难想象用户在什么样的网络环境使用我们开发的应用,如果用户所处的网络环境不是一个可信任的环境,那么用户的账户安全就可能有威胁,比如用户登陆时提交的账号密码被网络嗅探器窃取:客户端加密数据能有 ...
- 微信公众账号开发教程(三) 实例入门:机器人(附源码) ——转自http://www.cnblogs.com/yank/p/3409308.html
一.功能介绍 通过微信公众平台实现在线客服机器人功能.主要的功能包括:简单对话.查询天气等服务. 这里只是提供比较简单的功能,重在通过此实例来说明公众平台的具体研发过程.只是一个简单DEMO,如果需要 ...
随机推荐
- winform 与 html 交互 简单案例
本文主要简单的记录winform如何与html文件中的信息如何进行交互,即在winform中加载html界面,从而可以进行相互调用. 1.新建一个winform项目,若要在winform中加载html ...
- DataGridView 分页显示
DataGridView 分页显示函数 1.获取当前页的子数据表函数 public static DataTable GetPagedTable(DataTable dt, int PageIndex ...
- C#委托的异步调用1
本文将主要通过“同步调用”.“异步调用”.“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊. 首先,通过代码定义一个委托和下面三个示例将要调用的方法: /*添加的命名空间 u ...
- 数据库(MSSQLServer,Oracle,DB2,MySql)常见语句以及问题
创建数据库表 create table person ( FName varchar(), FAge int, FRemark varchar(), primary key(FName) ) 基本sq ...
- linux centos 安装
本着学习的目的,在自己的电脑上进行 centos 7 安装,记录下这步骤以备忘. 一.Centos 下载 centos 官方(https://www.centos.org/)下载ISO镜像(这是我的下 ...
- Oracle 内核参数
安装Oracle的时候,可以参考Oracle 的安装文档,来设置相关内核参数的值,但是有些参数的值还是需要根据我们自己的情况来进行调整.注:不同系统的参数不同,本篇针对linux. 一.Linux 系 ...
- 阿里云服务器无法远程其他的mysql服务器
1.初始化root密码 进入mysql数据库 1 mysql>update user set password=PASSWORD('123456') where User='root'; 2.允 ...
- IOS 学习参考
IOS 开发 http://code4app.com/ios/%E5%AE%9E%E6%97%B6%E6%9B%B4%E6%96%B0%E7%9A%84%E6%9B%B2%E7%BA%BF%E5%9B ...
- 【iOS】init,loadView,viewDidLoad加载关系
一.loadView 永远不要主动调用这个函数.view controller会在view的property被请求并且当前view值为nil时调用这个函数.如果你手动创建view,你应该重载这个函数. ...
- 微软职位内部推荐-Data Scientist
微软近期Open的职位: Job Description:Extracting accurate, insightful and actionable information from data is ...