建模一个可以拖动层并通过 XML HTTP加载动态内容

分享于 

18分钟阅读

Web开发

  繁體

介绍

首先,请注意,本文展示了一个高级的面向对象的基于Prototype的JavaScript编程。 如果你不熟悉面向对象的JavaScript,你可能需要阅读我以前的文章或者 baker baker baker baker,它展示了概念的概念。

在本文中,我们将尝试生成一个弹出文件来加载外部文件。

我想到这样一个解决方案就是增加了弹出阻塞器的使用。

在实现解决方案时,弹出窗口将永远不会被阻止。 因为它不会是一个真正的弹出来。 实际上,它将是一个DHTML层。 所以没有弹出窗口阻止程序将能够 block: )

这里实现具有一些优点和缺点:

  • 优点
    • 解决方案是 跨浏览器 ( 最新版本的Netscape。Mozilla。Opera 和 IE 支持它)。
  • 缺点
    • 这项技术是相对的。 因此旧的浏览器版本将不支持它。

我们将在五个步骤中进行总结:

  • 设计一个看起来像弹出来的图层。
  • 使我们的图层可以拖动。
  • 为 nasty <select>的解决方案找到一个解决方案,其中包括我们的伪弹。
  • 查看我们的对象 Prototype,如有必要,添加/重新设计方法。
  • 从外部URL中异步更改弹出的内部内容,不刷新浏览器( 这就是 XMLHttp 对象进场的地方)。

正如我一直在这篇文章中,我将尝试使它尽可以能多的跨浏览器 和面向对象。

我向你保证会很有趣的。

你可能希望在继续操作之前,查看结果。

图层

这是件容易的事情。 虽然可以用表格轻松制作,但我更喜欢使用基于css的布局。

<divid="PopupMasterContainer"><divid="PopupTopHandle"><divid="PopupTopButtons"><imgsrc="images/close.gif"id="IcnClose"alt="closes the pop-up"/></div><divid="PopupTopTitle">Title Goes Here</div></div><divid="PopupContent"></div></div>

用一些 CSS,它看起来就像是一个弹出的屏幕。

移动它 !

周围有几十个移动和拖动层脚本。 所以你不用用我的版本。

关键是,如果你使用一些脚本,你最好知道它做什么,而不是仅仅复制和粘贴。 这样你就可以找到一种方法来扩展它。

就像我在介绍中提到的,我们将尝试编写面向对象。 我们将观察多层次继承,方法隐藏,方法重写的例子。

不,我们不会编写 C#: ) Javascript可以比我们想象的更面向对象。

我已经包含了一个简化版本的,只添加拖放相关部分,使我们的弹出层可以拖动。

你可以用不同的方式检查完整版本的用法。 或者下载整个 API。 ( 页面是土耳其语;API在非商业共享的情况下分布在license许可中。 )。

不要偏离主题,我不会深入了解拖动功能是如何实现的。 就像我所说的,任何拖放API都。

想尝试使用拖放支持弹出? 拖动顶部手柄时,会看到它移动。

下面是执行该操作的JavaScript代码:

1. var lyr = new DraggableLayer("PopupMasterContainer",null,null,true);2. lyr.ignoreLayer("PopupContent");

脚本将" PopupMasterContainer"转换为可以拖动的不可调整的层;并告诉它在第 2行忽略层" PopupContent"上的任何拖动动作。

如果你注释出第 2行,你会看到不仅是顶部的句柄,而且底部的内容层将激活拖动操作。

这就是我喜欢面向对象编程的内容: 封装 !

一旦正确设计对象,很少需要修改它。 你所需要做的就是知道如何使用接口方法。 你不需要关心后面的代码。

我不解释代码如何做它所做的事情。 否则我就会out-of-scope了。 如果你有任何查询 给我一个 E-mail 地址。 我一有时间就会尽快回复。

模拟弹出

现在,让我们坚持我们的旧model-view-controller范例,并创建一个模型来控制视图( 例如。 弹出)。

我们模型的骨架很可能是这样的:

function PopupLayer(elmID,strTitle) {}
PopupLayer.prototype.show=function() {}
PopupLayer.prototype.hide=function() {}
PopupLayer.prototype._closeBtn_Click=function(evt) {}

在这个窗口中,PopupLayer(elmID,strTitle) 构造函数将创建一个可以拖动的弹出窗口;show 将使它可见;hide 将使它消失;将在右上角处理关闭图像;它将在对象构造过程中被附加。

然后,当我们检查API时,我们看到对象 DynamicLayer 有一些方法可以使生活更容易。 下面是它的public 方法的List:

.moveTo(intLeft,intTop) //moves the layer to given coordinates. .resizeTo(intWidth,intHeight)// changes width and height of the layer.[intLeft]. getLeft()// gets the left distance from the container..setLeft(intLeft)//sets the left distance to the container.[intTop]. getTop()// gets the top distance from the container..setTop(intTop)// sets the top distance to the container.[intHeight]. getHeight() // gets the height of the layer..setHeight(intHeight) // sets the height of the layer. [intWidth]. getWidth() // gets the width of the layer..setWidth(intWidth) // sets the width of the layer.[bln]. isVisible() // return true if the layer is visible..show() // makes layer visible..hide() // makes layer invisible..collapse() // sets layer's display to 'none'.expand() // sets layer's display to 'block'.changeContent(strNewHTML) // changes the contet of the layer..addContentBefore(strHTML) // adds content before..addContentAfter(strHTML) // adds content after.[bln]. exists() // returns true if such a layer actually exists.[obj]. getObject() // returns the object reference to the layer.[strID]. getID() // returns the id of the layer.

对象已经定义了 showhide 方法。 此外,它还有一个完整的附加方法: 以 moveTo 为例,以编程方式将页面的任意位置移动到页面上;或者 resizeTo 将改变图层的大小。

DynamicLayer 包含了我们最初Prototype的大多数方法,但不是全部。 此外,它有一组有用的方法,我们在最初的设计中没有考虑到。

因此,我们认为 PopupLayerDynamicLayer 都不能完全满足我们的需求。

你不需要是Oracle来表示"嘿PopupLayer应该扩展 DynamicLayer":)。

那我们来吧 !

扩展 PopupLayer

添加 PopupLayer.prototype = new DynamicLayer(); 使 PopupLayer 成为 DynamicLayer 就够了。 现在 DynamicLayer的任何方法都是 PopupLayer的一种方法。

这里是新的原型,有一些附加评论,以了解我们将要做什么:

PopupLayer.prototype = new DynamicLayer();
_this = PopupLayer.prototype;function PopupLayer(elmID,strTitle) {
 /* create a draggable - non resizable layer. *//* set the title text *//* attach event handler to close button *//* override necessary methods */}
_this._closeBtn_Click=function(evt) {}/* override necessary methods */

我们的目标是探测容器的各个部分,我们在HTML中添加了独特的类。

<divid="PopupMasterContainer"><divid="PopupTopHandle"class="popupDragBar"><divid="PopupTopButtons"class="popupButtonContainer"><imgsrc="images/close.gif"class="popupCloseIcon"id="IcnClose"alt="closes the pop-up"/></div><divid="PopupTopTitle"class="popupWindowTitle">Title Goes Here</div></div><divid="PopupContent"class="popupConsole"></div></div>

构造函数将迭代DOM层次结构,添加事件监听器,并借助这些类名进行必要的更改。

下面是构造函数中代码的截断版本,用于描述它所做的事情:

function PopupLayer(elmID,strTitle) {
 /* Create a draggable - non resizable layer. */var pop = new DraggableLayer(elmID,null,null,true);
 /* Find the top container. */var objPop = pop.getObject();
 var children = objPop.childNodes;
 for (var i=0;i <children.length;i++ ) {
 if(children[i].className) {
 /* Find console. *//* Find drag bar. */if(children[i].className=="popupDragBar") {
 for(var j=0;j <dragBarChildren.length;j++) {
 if(dragBarChildren[j].className) {
 /* Find and attach close event to close button. *//* Find and set title. */ }
 }//for }//if }//if }//for}//constructor

创建构造函数后,让我们重写并扩展必需的部分:

重写方法

为了使我们的弹出层工作,需要重写一些继承的方法 上面,即 changeContentaddContentBeforeaddContentAfter

这三种方法改变了整个层的innerHTML。 但是,我们只想更改控制台的内容( 例如。 类" popupConsole")。

此外,我们还需要重写 showhide,因为我们将在( 在所有问题的顶部选择:) 中检查一个呈现。

覆盖前三个是很容易的部分:

PopupLayer.prototype = new DynamicLayer();
_this = PopupLayer.prototype;function PopupLayer(elmID,strTitle) {
. . . constructor logic.. .
}/** overridden method */_this.changeContent = function(strNewHTML) {
. . .code goes here...
};/** overridden method */_this.addContentBefore = function(strHTML) {
. . .code goes here...
};/** overridden method */_this.addContentAfter = function(strHTML) {
. . .code goes here...
}

重写 showhide 有点棘手,因为我们不能直接掩蔽对象的父 showhide 方法。 我们还需要调用对象的父方法。

以下是我们要做的:

/** overridden show method*/PopupLayer.prototype.show=function() {
 /* Hide nasty selects. *//* Call parent object's show method. */}/** overridden hide method*/PopupLayer.prototype.hide=function() {
 /* Show the selects. *//* Call parent object's show method. */}

由于我们没有 base,或者JavaScript中的parent 关键字,我们应用了一个技巧: 我们将对象的父方法的引用复制为成员变量。

我认为显示代码比键入代码有很多解释:

PopupLayer.prototype = new DynamicLayer();
_this = PopupLayer.prototype;function PopupLayer(elmID,strTitle) {
. . . constructor logic.. .
 this._parent_show = this.show;
 this._parent_hide = this.hide;
 /** Override show method. */this.show=function() {
 /* Hide dropdowns. *//* Call parent object's show method. */this._parent_show();
 }
 /** Override hide method. */this.hide=function() {
 /* Show dropdowns. *//* Call parent object's show method. */this._parent_hide();
 }
}

隐藏/显示下拉框

很可能你在其他地方看到过这样的场景。

nasty selects

出现这种呈现异常,因为 HTML 选择 s 被呈现在页面的顶部。 因为我们的弹出文件位于页面中,所以这并不例外。

为防止这种情况,我们将在打开弹出时隐藏页面中的所有下拉框,并在弹出时再次显示它们。

gues,我们将创建一个对象来执行它:)

var _this=DOMManager.prototype;function DOMManager() {}
_this.hideCombos = function() {
 var arCombo = document.getElementsByTagName("select");
 for(var i=0;i <arCombo.length;i++) {
 arCombo[i].style.visibility="hidden";
 }
}
_this.showCombos = function() {
 var arCombo = document.getElementsByTagName("select");
 for(var i=0;i <arCombo.length;i++) {
 arCombo[i].style.visibility="inherit";
 }
}

那么简单 !

当你需要隐藏组合时,你可以打电话给 new DOMManager().hideCombos();,当你想显示你所呼叫的组合时。

添加其他部件

客户机的一个常见请求是"我想把我的pop放在page的中间"。 和客户永远是正确的:)

下面是将弹出位置放置在页面中央的附加方法:

_this.center = function() {
 /* 
 * quick and dirty way to get 
 * cross-browser width and height -- not fully tested 
 */var windowHeight = self.innerHeight?
 self.innerHeight:document.body.clientHeight;
 var windowWidth = self.innerWidth?
 self.innerWidth:document.body.clientWidth;
 this.moveTo(
 ((windowWidth)/2-g_popup.getWidth()/2)-17
, 
 ((windowHeight)/2-g_popup.getHeight()/2)-17
 );
};

在这里,我们看到为什么继承是一个我们总是要保存在我们的工具箱中的工具:

moveTo 方法是 PopupLayer的父对象的一种方法。 通过继承,我们可以轻松地调用它,让我们的弹出。

对外部文件的HTTP请求

这是我们之前做的,直到这一点。

我们有一个可以拖曳的层,我们可以拖动,关闭,显示。 但这跟真正的弹出来并不一样。 因为,真正的pop从外部URL加载 HTML。

然而我们的伪菜单只显示 static 内容。

我们将按以下两个步骤处理这里问题:

  • 设计一个 跨浏览器 对象,它可以使HTTP连接到外部世界。
  • 将对象与我们的PopupLayer 集成。

让我们从简单的部分开始。 借助 XMLHTTPRequest,几行代码可以完成我们的工作。 我们只需要为它编写一个 跨浏览器 包装器:

_this = XHRequest.prototype;function XHRequest(){}
_this.getObject = function() {
 if (window.XMLHttpRequest) {
 returnnew XMLHttpRequest();
 }
 elseif (window.ActiveXObject) {
 returnnew ActiveXObject("Microsoft.XMLHTTP");
 }
 else {
 alert("XML HTTP Request support cannot be found!");
 returnnull;
 }
};

创建对象后,第二部分是简单的。 我们为弹出的up创建一个 open 方法。 它建立到 url的异步连接,隐藏弹出并在请求完成时显示它。

_this.open = function(url,title) {
 if(title&&this._title) {
 /* _title is a private reference to the title layer. */this._title.innerHTML = title;
 }
 /*hide pop-up*/this.hide();
 /*open an HTTP request to the url*/var request = new XHRequest().getObject();
 request.open("GET",url);
 var eventSource = this;
 request.onreadystatechange = function() {
 if(request.readyState == 4) {
 eventSource.changeContent(request.responseText);
 }
 eventSource.show();
 }
 request.send(null);
};

那就是所有的人 !

结束语

最后,我们建立了一个可以拖动的浏览器来建立一个到外部文件的HTTP连接;我们做了一些 跨浏览器 编码和( 希望),我们有有趣的功能。

开心编码!

历史记录

  • 2005-05-28

    已经创建文章。


模式  HTTP  动态  Layer  拖动  dynamic-c