如何获取对HTML对象的跨浏览器 引用

分享于 

16分钟阅读

Web开发

  繁體 雙語

介绍

本文演示了如何使用我的DHTML API中的一个JavaScript类。 你可以在以下位置看到该 API:

但是,这些站点和文档都在土耳其语中:(

如果你考虑使用 API,那么代码是在'creative Commons Attribution-NonCommercial-Share同样 2.0'许可下分发的。 如果你给我信用卡和更新的代码( 电子邮件),那么说明它的非商业用途是免费的: volkan.ozcelik@gmail.com ;

像任何开发人员一样,当使用我的代码以后,我会很高兴的。 但我最想要的是共享知识,帮助别人改进,听别人的评论,以便我能改善自己。

我打算制作一个本网站的英文版本。 但我还有其他更高优先级的问题。

本文的目

在本文中,我们将创建一个对象,该对象将返回对HTML页面中元素的跨浏览器 引用。

我们将以面向对象的方式编写 JavaScript。 我们将看到函数Prototype的示例。 我们将看到,JavaScript函数并不是简单的过程。 在JavaScript中,为了更加技术化,函数可以被看作是对象。 它们可以有自己的方法,成员变量 等等。

骨架

让我们从对象的Prototype模型开始。 我们将 NAME CBObject 作为 跨浏览器 对象的缩写。

function CBObject(elmID) {
. . .
}
CBObject.prototype.exists = function() {
. . .
};
CBObject.prototype.getObject = function() {
. . .
};
CBObject.prototype.getValidator = function() {
. . .
};
CBObject.prototype.getID = function() {
. . .
};

可以将 CBObject(elmID) 视为构造函数。 它将HTML页面( elmID ) 上对象的ID作为字符串,并查找页面以检查是否存在这样的对象。

  • 方法 exists 返回 true 如果发现了这样的物体 false 否则。
  • 方法 getObject 返回对该对象的引用。
  • 不用担心 getValidator,它将返回一个 Validator 对象的引用,我稍后会解释。
  • 然后 getID 返回对象的ID,你可以猜测。

交换代码

现在让我们交换一下:

var g_blnCBObjectProtoCalled = false;function CBObject(elmID) {
 if(!g_blnCBObjectProtoCalled) {
 g_blnCBObjectProtoCalled = true;
 var _this = CBObject.prototype;
 _this.prototype.exists = function() {
. . .
 };
 _this.getObject = function() {
. . .
 };
 _this.getValidator = function() {
. . .
 };
 _this.getID = function() {
. . .
 };
 }//if prototype not called}//CBObject

以这种方式修改代码是我的设计偏好。 在我看来,它有两个优点。

  • 首先,代码更像一个类。
  • 第二,如果 CBObject 不是用 新建 原型将不会被附加到对象,因为它们出现在函数体之外,它们与函数体之外的代码相对应。

我们使用变量 g_blnCBObjectProtoCalled 来确保Prototype只附加一次,而且只有一次(。例如,当第一次构造对象时)。

验证器

Validator 对象是用于验证对象的实用工具类。 以下是它包含的方法的完整列表:

isDefined(x) // returns true if x is not undefined.isEmpty(x) // returns true if x is an empty string.isEmail(x) // does a regexp check to see if x represents a valid e-mail.isInteger(x) // returns true if x represents an integer.isFloat(x) // returns true if x can be parsed as float.isString(x) // returns true if x is an instance of a String.isDate(intYear, intMonth, intDay) // returns true if the parameters represent// a valid date.getStatusCode() // returns 0 if the former validation is OK.// returns a non-zero number otherwise.

你可以在源代码中找到整个代码。 我们将对以下两种具体方法感兴趣:

function Validator() {
. . . truncated.. .
 _this.isDefined = function(x) {
 if(typeof(x) == "undefined") {returnfalse;}
 returntrue;
 };
 _this.isString = function(x) {
 if(!this.isDefined(x)) {returnfalse;}
 if(typeof(x) == "string") {returntrue;}
 returnfalse;
 };
. . . truncated.. .
}

字符串Prototype助手

Validator 类使用几个 String Prototype。 我给他们的是完整的。

var _spt = String.prototype;
_spt.trim = function(blnIgnoreCarriage, blnIgnoreInnerWhiteSpace) {
 var temp = this.replace(/^s*/,"");
 temp = temp.replace(/s*$/,"");
 blnIgnoreCarriage = blnIgnoreCarriage? true : false;
 blnIgnoreInnerWhiteSpace = blnIgnoreInnerWhiteSpace? true : false;
 if(blnIgnoreCarriage && blnIgnoreInnerWhiteSpace) {;}
 elseif(blnIgnoreCarriage&&!blnIgnoreInnerWhiteSpace) {
 temp = temp.replace(/t+/g,"");
 temp = temp.replace(/+/g,"");
 }
 elseif(!blnIgnoreCarriage && blnIgnoreInnerWhiteSpace) {
 temp=temp.replace(/(nr)+/g,"");
 }
 elseif(!blnIgnoreCarriage &&!blnIgnoreInnerWhiteSpace) {
 temp=temp.replace(/s+/g,"");
 }
 if(temp=="") { temp=""; }
 return temp;
};
_spt.match = function(strRegExp, strOption) {
 var regEx = new RegExp(strRegExp, strOption? strOption : "g");
 returnthis.match(regEx);
};
_spt.remove = function(strRegExp, strOption) {
 var temp = this;
 var regEx = new RegExp(strRegExp, strOption? strOption : "g");
 temp = temp.replace(regEx, "");
 return temp;
};
_spt.removeTags = function() {
 var regEx =/<[/]?([a-zA-Z0-9]+)[^>^<]*>/ig; /*any tag*/returnthis.replace(regEx,"");
}
_spt.test = function(strRegExp, strOption) {
 var regEx = new RegExp(strRegExp, strOption? strOption : "g");
 return regEx.test(this);
};

如何查找对象引用

根据 上面 描述,我们现在可以把注意力集中在 CBObject 上了。

让我们先初始化 CBObject的成员变量:

function CBObject(elmID) {
 if(!g_blnCBObjectProtoCalled) {
. . . truncated.. . 
 }
 this._val = new Validator();
 this._obj = this._getObject(elmID);
}

我使用的符号是下划线。 对于不应该在对象外使用的方法,我用下划线将它们前缀。 也就是说,以下划线( _ ) 开头的方法名只能在对象中使用。 ( 可以说它们是对象的private 方法,以下划线开头的变量名是 private 成员。)

code代码 上面 变量 _val_obj,以及方法 _getObject are private 到 CBObject

方差 _val 是对内部 Validator 对象的引用。 _obj 是一个元素的引用,该元素包含在HTML主体中存在的ID elmID

下面是完成大部分工作的结构的核心:

_this._getObject = function(elmID) {
 var v = this.getValidator();
 if(!v.isString(elmID)) {return elmID;}
 if(document.getElementById) {elmID = document.getElementById(elmID);}
 elseif(document.all) {elmID = document.all[elmID];}
 elseif(document.layers) {elmID = this._getLayer(elmID);}
 elseif(document.forms) {
 if(document.forms[elmID]) {elmID = document.forms[elmID];}
 else {
 for(var i=0; i<document.forms.length; i++) {
 if(document.forms[i][elmID]) {
 elmID = document.forms[i][elmID];
 break;
 }
 }
 }
 }
 else {elmID = null;}
 return elmID;
};

方法 getValidator 只返回成员 Validator 实例 _val,该实例包含几个段落 上面。

让我来解释 _getObject 一步一步来做什么:

  • 如果 elmID 不是字符串,那么假定它是一个对象引用并立即返回它。
  • 其他尝试以 跨浏览器 方式获取与 W3C DOM函数 getElementById 相关的引用。 大多数浏览器的最新版本支持 getElementById
  • 它的他方法是使用只有 IE 理解的document.all 才能获得 IE 方法。
  • 如果仍然没有得到对象引用,尝试遍历文档的层次,这仅仅是 Netscape ( 例如 ) 中的旧版本。 NS4- ) 理解这里处,_getLayer 函数扫描所有层以查看 elmID 是否存在于它的中一个。

由于层可以包含其他层,所以应该递归调用 _getLayer 方法。 以下是完成操作的方法:

_this._getLayer = function(elmID,objRoot) {
 var i = 0;
 var objLayer = null;
 var objFound = null;
 if(!objRoot) {objRoot = window;}
 for(i=0; i<objRoot.document.layers.length; i++) {
 objLayer = objRoot.document.layers[i];
 if(objLayer.id==elmID) {return objLayer;}
 if(objLayer.document.layers.length) { 
 objFound = this._getLayer(elmID,objLayer);
 }
 if(objFound) {return objFound;}
 }
 returnnull;
};

尽管 _getLayer 方法永远不会被使用,但我想应该检查递归是如何实现的。

如果 上面 步骤中没有找到对象,则该对象可以是 窗体 因此,对于最后一个希望,我们迭代 forms Collection。 如果我们还是找不到任何东西

测试我们所做

源zip捆绑的TestCBObject.html 包含一个简单的测试用例。

以下是文档头部的内容:

<script type="text/javascript" src="String.js"></script>
<script type="text/javascript" src="Validator.js"></script>
<script type="text/javascript" src="CBObject.js"></script>
<script type="text/javascript">function checkForObjects() {
 var MyLayer = new CBObject("MyLayer");
 var FormInput1 = new CBObject("FormInput1");
 var FormInput2 = new CBObject("FormInput2");
 var NonExistent = new CBObject("NonExistent");
 if(MyLayer.exists()) {
 MyLayer.getObject().style.backgroundColor = "#cc0000";
 }
 else {
 alert("MyLayer does not exist");
 }
 if(FormInput1.exists()) {
 FormInput1.getObject().style.backgroundColor = "#cc0000";
 }
 else {
 alert("FormInput1 does not exist");
 }
 if(FormInput2.exists()) {
 FormInput2.getObject().style.backgroundColor = "#cc0000";
 }
 else {
 alert("FormInput2 does not exist");
 }
 if(NonExistent.exists()) {
 NonExistent.getObject().style.backgroundColor = "#cc0000";
 }
 else {
 alert("NonExistent does not exist");
 }
}
</script>

这就是尸体:

<divid="MyLayer">My Layer</div><formid="MyFirstForm"method="post"action="#"onsubmit="return false;"><fieldset><legend>first form</legend><inputname="FormInput1"/></fieldset></form><formid="MySecondForm"method="post"action="#"onsubmit="return false;"><fieldset><legend>second form</legend><inputname="FormInput2"/></fieldset></form><formid="ActionForm"><div><inputtype="button"value="click me"onclick="checkForObjects();"/></div></form>

单击按钮后,checkForObjects() 将被执行。 它将检查若干个对象存在,如果找到一个对象,它将改变该对象的background 颜色。 如果找不到它就会通知我们。

结束语

在本文中,我们试图检索对 HTML DOM对象的跨浏览器 引用,同时我们看看原型如何实现。 我希望在讨论期间我没有跳到这里。

编写 跨浏览器 JavaScript可能会非常困难,如果你在大量的目标浏览器和平台上。 在这个世界上仍然有用户使用历史时代(。NS3实例)的浏览器。 当然,他们有这样做的理由。

请注意读者

说实话,编写这个 跨浏览器 代码使API变得太复杂和臃肿。

由于几乎所有版本 4 + 浏览器都支持 W3C DOM,所以我决定从API中删除预先创建的DOM支持,并决定添加新的使用DOM的小部件。

我意识到支持flintstone浏览器最好的范围是开关I jambo和一个I 代码,甚至发现自己失去了。

因此,我决定不为那些不理解DOM的浏览器编写代码。 可能是一个根本的改变,但它的时间已经到来了。

如果我们选择了该操作过程,请查看 上面 混乱 _getObject 如何简化:

_this._getObject = function(elmID) {
 if(!new Validator().isString(elmID)) {return elmID;}
 else {return document.getElementById(elmID);}
};

25行代码( 包含 _getLayer 内容)" if "," 其它 - if and" for junk简单地减少到两行 ! 它很简单,它是快速的,它是一致的,它是可以理解的,并且是followable的标准方法。 总之,让你的代码尽可能 jumpy。 我不说"仅为IEv7+编写代码"。 我只是说,不支持旧浏览器只是为了炫耀。

你可能认为一个支持全球所有version2+浏览器的结构是所有时代最优雅的编码 Manifest。 但我只是把它当作一堆垃圾。 ( 我也很感激你对我的决定,TIA。)

历史记录

  • 2005-03-05
    • 已经创建文章。
  • 2005-03-07
    • 方法 _getLayer 稍微改变一下。 文章相应更改。
  • 2005-03-22
    • "注释 to part added。

bro  对象  浏览  REF  Refer  跨浏览器  
相关文章