一步步教你实现弹出窗口
通常而言,弹出窗口都是居中对齐的,因此我们需要获取浏览器可视区的大小。这里有一个函数,可以帮我们迅速取得结果。
var getBrowserWindowSize = function(){
var de = document.documentElement;
return {
\'width\':(
window.innerWidth
|| (de && de.clientWidth )
|| document.body.clientWidth),
\'height\':(
window.innerHeight
|| (de && de.clientHeight )
|| document.body.clientHeight)
}
}要创建一个弹出窗口,我们需要一些参数,具体可以参考这里。但作为起步,我们不需要面面俱到,现在只要title,width与height这三个就算了。以下是其主体框架:
var Dialog = function(){
var options = arguments[0] || {};
this.title = options.title || "新窗口",
this.width = options.width || 400,
this.height = options.height || 300,
this.contain = document.createElement("div"),
this.id = "id" + (( new Date() * Math.random()) >> 0);
this.init();
}
Dialog.prototype = {
constructor: Dialog,
init: function() {
//*****************
}
}UI控件就难免涉及动态设置样式的问题,通常人们都是这样做:el.style.cssText = “******************”
换言之,就是使用内联样式。但这样做有两个缺点:1,不能使用伪类;2,相同样式容易重复定义。我的一个脚本虽然也用到cssText,但生成的是内部样式,完美地避免了这两个问题。我早期的UI控件都是利用它来设置样式。不过,如你们所见,它的体积比较庞大,而且一下子设置所有样式,需要对UI有够全面的了解,在迭代开发中,恐怕没有人敢保证他现在写的样式就是最后确定用的样式。因此,我又开发另一套动态设置样式规则的方法。IE有一个很好用的方法,createStyleSheet,能生成一个样式表对象。不过有个缺陷,就是一个页面只能使用31次,再多就只能求助于document.createElement(“style”)。IE的样式表对象有两个重要的方法,分别为addRule与removeRule 。我是不推荐用removeRule方法,同理,任何移除节点的方法能不用就不要用。因为IE7中,引入新的DOM元素的回收机制:在离开页面时回收DOM树上的所有元素。换言之,如果所有元素(无论动态创建的还是原来的),只要关闭引页面时,它们都在DOM树上,就不会泄漏,否则肯定泄漏。你不要以为当时移除节点后,IE7会即时回收它,对不起,它很懒,因此内存会一直飙升,直到关闭时才得以喘息。回归正传,标准浏览器肯定没有这些方法,对应方法都是非常不好用,因此我们让它们拥有这种IE风格的方法即可。
if(typeof document.createStyleSheet === \'undefined\') {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\'style\');
element.type = \'text/css\';
document.getElementsByTagName(\'head\')[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length - 1];
if(typeof sheet.addRule === \'undefined\')
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \'undefined\')
index = this.cssRules.length;
this.insertRule(selectorText + \' {\' + cssText + \'}\', index);
};
return sheet;
}
return createStyleSheet;
})();
}然后我们用createStyleSheet创建一个样式表对象,并把作为Dialog的静态属性,
目的让所有Dialog对象都共享这个对象,因为在IE中,这方法在一个页面只能使用31次,
能省就省啊!if(!!Dialog.sheet){
Dialog.sheet.addRule(selector,declaration);
}else{
Dialog.sheet = document.createStyleSheet();
Dialog.sheet.addRule(selector,declaration);
}这有点像单例模式,但上面的写法只能保证创建一个样式表对象,不能防止两个完全一样的样式规则对象的创建。有关样式规则对象等概念,请参考我另一篇博文《再谈动态添加样式规则》。
<mce:script type=”text/javascript”><!–
var Dialog = function(){
var options = arguments[0] || {};
this.title = options.title || “新窗口”,
this.width = options.width || 400,
this.height = options.height || 300,
this.contain = document.createElement(“div”),
this.id = “id” + (( new Date() * Math.random()) >> 0);
this.init();
}
Dialog.prototype = {
constructor: Dialog,
init: function() {
this.css(“body”,”background:#000;”);
this.css(“body”,”color:#fff”);
this.css(“p”,”border:1px solid red”);
},
css:function(selector,declaration){
if(typeof document.createStyleSheet === \’undefined\’) {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\’style\’);
element.type = \’text/css\’;
document.getElementsByTagName(\’head\’)[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length – 1];
if(typeof sheet.addRule === \’undefined\’)
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \’undefined\’)
index = this.cssRules.length;
this.insertRule(selectorText + \’ {\’ + cssText + \’}\’, index);
};
return sheet;
}
return createStyleSheet;
})();
}
if(!!Dialog.sheet){
Dialog.sheet.addRule(selector,declaration);
}else{
Dialog.sheet = document.createStyleSheet();
Dialog.sheet.addRule(selector,declaration);
}
}
};
window.onload = function(){
new Dialog(400,300,”第一个窗口”)
new Dialog(400,300,”第二个窗口”)
}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>样式规则</h2><div id=”parent”></div><b id=”child” >样式规则</b>
<p>https://developer.mozilla.org/cn/Canvas_tutorial</p>
<p>http://www.btinternet.com/~st_rise/main/mainfram.htm?../webplus/vml/vfill.htm</p>
在IE8开发人员工具下,我们可以看到一些样式规则完全一样。我的设想是选择器部分可以重复,但其内容不能重复。因此我们需要设置一个容器来保存与管理这些样式规则。
初步开发了这样一个小东西,类似java的集合,但去掉无关的功能:
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<mce:script type=”text/javascript”><!–
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<l;i++){
if(keys[i] == k){
results.push(values[i])
}
}
return results;
},
exists:function(k,v){
var vs = this.get(k);
for(var i=0,l=vs.length;i<l;i++){
if(vs[i] == v){
return true;
}
}
return false;
},
set : function(k,v){
keys.push(k);
values.push(v);
size++;
},
length :function(){
return size;
}
}
}window.onload = function(){
var m = memory();
m.set(1,”4″);
m.set(“rrr”,”34″);
m.set(“rrr”,”334″);
alert(m.get(“rrr”))
alert(m.exists(“rrr”,”34″))
}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>javascript弹出窗口 by 司徒正美</h2>
我们把它整合到Dialog类中,这样就可以防止冗余重复的CSS代码生成了!
<mce:script type=”text/javascript”><!–
var Dialog = function(){
var options = arguments[0] || {};
this.title = options.title || “新窗口”,
this.width = options.width || 400,
this.height = options.height || 300,
this.contain = document.createElement(“div”),
this.id = “id” + (( new Date() * Math.random()) >> 0);
this.init();
}
Dialog.prototype = {
constructor: Dialog,
init: function() {
this.css(“body”,”background:#000;”);
this.css(“body”,”color:#fff”);
this.css(“p”,”border:1px solid red”);
},
css:function(selector,declaration){
if(typeof document.createStyleSheet === \’undefined\’) {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\’style\’);
element.type = \’text/css\’;
document.getElementsByTagName(\’head\’)[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length – 1];
if(typeof sheet.addRule === \’undefined\’)
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \’undefined\’)
index = this.cssRules.length;
this.insertRule(selectorText + \’ {\’ + cssText + \’}\’, index);
};
return sheet;
}
return createStyleSheet;
})();
}
if(!!Dialog.sheet){
if(!Dialog.memory.exists(selector,declaration)){
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}else{
Dialog.sheet = document.createStyleSheet();
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<l;i++){
if(keys[i] == k){
results.push(values[i])
}
}
return results;
},
exists:function(k,v){
var vs = this.get(k);
for(var i=0,l=vs.length;i<l;i++){
if(vs[i] == v){
return true;
}
}
return false;
},
set : function(k,v){
keys.push(k);
values.push(v);
size++;
},
length :function(){
return size;
}
}
}
Dialog.memory = memory();
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}
};
window.onload = function(){
new Dialog(400,300,”第一个窗口”)
new Dialog(400,300,”第二个窗口”)
}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>样式规则</h2><div id=”parent”></div><b id=”child” >样式规则</b>
<p>https://developer.mozilla.org/cn/Canvas_tutorial</p>
<p>http://www.btinternet.com/~st_rise/main/mainfram.htm?../webplus/vml/vfill.htm</p>
至此,Dialog类的辅助方法就准备得差不多了,下一部分将正式进行开发。
上部分已给出主要辅助方法css了,有了它我们就可以实现类的实例的样式共享。另外,我们的类的实现模式是基于prototype,这样就实现方法共享。现在我们来看看如何渲染它,首先呈上它大体的结构层代码:
<div id="" class="popups" >
<div class="caption"></div>
<form>
<div class="replaceable"></div>
<div class="submitable">
<a class="negative" href="javascript:void(0)">取消</a>
<a class="positive" href="javascript:void(0)">确认</a>
</div>
</form>
<a class="closebtn" href="javascript:void(0)"></a>
</div>这结构层代码比腾讯那个简单得多了,而且没用到table来布局,全凭CSS来处理。虽然元素很少,但如果用W3C那一套操作DOM的API来干活,也要十多行。我们不想一味地createElement然后appendChild的话,就要派innerHTML上场了。一个常识是,当DOM超过十个时,就要考察用字符串拼接实现,这样代码看起来也直观一点。我们再来分析一下这结构层。顶层是一个DIV,不用说,它是弹出层,其他东西都直接构筑在它的上面。考察到一个页面可能存在多个动态生成的弹出窗口,因此我赋给他们一个独一无二的标识,也就是ID。ID在我的样式蓝图中没有用,要实现共享就要用class,我给它一个popups值。接着是标题栏,看上去空荡荡,然后它有一个文本节点,与一张背景图片做icon,还有一个关闭按钮(我把它放到最底层了class=”closebtn”)。这里要用绝对定位。然后是一个表单,表单分两部分,一是替换区(replaceable),为什么这样叫?因为它视alert,prompt,confirm等功能而重写。一个是提交区,有两个按钮。你们可能奇怪了,为什么不用语义化更强、制定性更好的button标签来实现呢?这都怪IE6在拖后腿,只有带href属性的a标签才支持hover伪类。之所以用hover伪类,是因为我不想在它们上面多绑定两个事件(mouseover与mouseout)。而为什么确认按钮放在取消按钮之后呢?因为我们稍后要用到向右浮动。整个提交区是位于form的底部的,这个我们可以用bottom:0来实现。
Dialog.prototype = {
constructor: Dialog,
init: function() {
var container = this.container,width = this.width, height = this.height,
id = this.id,builder = [],
document.body.insertBefore(container,null);
container.id = id;
container.className = "popups";
builder.push(\'
\'+this.title+\'
\');
builder.push(\'
\'); builder.push(\'
\'); builder.push(\'取消\'); builder.push(\'确认\'); builder.push(\'
\');
builder.push(\'\');
container.innerHTML = builder.join(\'\');
}
}这样就创建完成了。我们再来看表现层。要做得好看,得花一些功夫。自已用IE8开发人员工具看生成后的CSS代码吧。它已经使用到CCS3的圆角特征(这在IE8中看不到)。有的人想去掉按下按钮时出现的虚线框,这里给出一个简捷方法:outline:0。
//设置样式
this.css(“.popups”,”position:absolute;width:”+width+”px;height:”+
height+”px;left:”+left+”px;top:”+top+”px;background:#68DFFB”);
this.css(“.popups .caption”,\’position:absolute;top:10px;left:10px;width:\’+
(width-50)+\’px;height:20px;\’+
\’padding-left:30px;font:700 14px/20px “SimSun”,”Times New Roman”;color: #fff;\’+
bg(“o_icon.gif”,”#68DFFB”,”5px”));
this.css(“.popups .closebtn”,\’position:absolute;top:0;right:10px;display:block;width:28px; \’+
\’height:17px;text-decoration:none;\’+ bg(“o_dialog_closebtn.gif”));
this.css(“.popups a.closebtn:hover”,bg(“o_dialog_closebtn_over.gif”));
this.css(“.popups form”,
“position:absolute;top:30px;left:10px;border:3px solid #68DFFB;width:”+
(width-26)+”px;height:”+(height-51)+”px;background:#fff;”);
this.css(“.popups .submitable”,
“position:absolute;bottom:0;border-top:1px solid #c0c0c0;width:100%;height:40px;background:#f9f9f9;”);
var buttoncss = \’display:block;float:right;margin: 0.7em 0.5em;padding:2px 7px;border:1px solid #dedede;\’
+ \’background:#f5f5f5;color:#a9ea00;font:700 12px/130% “SimSun”,”Times New Roman”;text-decoration:none;\’;
this.css(“a.positive”,buttoncss);//IE6有bug,不能动态创建联合选择器
this.css(“a.negative”,buttoncss);
this.css(“a.negative”,”color:#ff5e00;”);
this.css(“a.positive:hover”,”border:1px solid #E6EFC2;background:#E6EFC2;color:#529214;”);
this.css(“a.negative:hover”,”border:1px solid #fbe3e4;background:#fbe3e4;color:#d12f19;”);
this.css(“a.positive:active”,”border:1px solid #529214;background:#529214;color:#fff;”);
this.css(“a.negative:active”,”border:1px solid #d12f19;background:#d12f19;color:#fff;”);
this.css(“a”,”outline: 0;”);
var ff = /a/[-1]==\’a\’;
if(ff){
this.css(“a.positive”,”-moz-border-radius:4px;”);
this.css(“a.negative”,”-moz-border-radius:4px;”);
}else{
this.css(“a.positive”,”-webkit-border-radius:4px;”);
this.css(“a.negative”,”-webkit-border-radius:4px;”);
}
},
getBrowserWindowSize :function(){
var de = document.documentElement;
return {
\’width\’: (de.clientWidth || document.body.clientWidth),
\’height\’:(de.clientHeight || document.body.clientHeight)
}
},
createSVG : function(tag){
return document.createElementNS(“http://www.w3.org/2000/svg”,tag);
},
attr: function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
},
css:function(selector,declaration){
if(typeof document.createStyleSheet === \’undefined\’) {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\’style\’);
element.type = \’text/css\’;
document.getElementsByTagName(\’head\’)[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length – 1];
if(typeof sheet.addRule === \’undefined\’)
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \’undefined\’)
index = this.cssRules.length;
this.insertRule(selectorText + \’ {\’ + cssText + \’}\’, index);
};
return sheet;
}
return createStyleSheet;
})();
}
if(!!Dialog.sheet){
if(!Dialog.memory.exists(selector,declaration)){
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}else{
Dialog.sheet = document.createStyleSheet();
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<l;i++){
if(keys[i] == k){
results.push(values[i])
}
}
return results;
},
exists:function(k,v){
var vs = this.get(k);
for(var i=0,l=vs.length;i<l;i++){
if(vs[i] == v)
return true;
}
return false;
},
set : function(k,v){
keys.push(k);
values.push(v);
size++;
},
length :function(){
return size;
}
}
}
Dialog.memory = memory();
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}
};window.onload = function(){
setTimeout(function(){
new Dialog({width:400,height:300,title:”司徒正美”})
},1000)
}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>一步步教你实现弹出窗口 by 司徒正美</h2><div id=”parent”></div><b id=”child” >样式规则</b>
<pre>
#navigation {
-webkit-box-shadow: 0 0 10px #000;
-moz-box-shadow: 0 0 10px #000;
}
#navigation li a:hover,
#navigation li a:focus {
-webkit-box-shadow: 0 0 5px #111;
-moz-box-shadow: 0 0 5px #111;
}
box-shadow属性可以用多个值:水平偏移、垂直偏移、模糊半径、伸展半径和阴影颜色。水平和垂直偏移和阴影色使用的最多。
在一个div上应用红色阴影,右边和下边偏移4px,无模糊,我们可以使用下面的代码:div {
-moz-box-shadow: 4px 4px 0 #f00;
-webkit-box-shadow: 4px 4px 0 #f00;
box-shadow: 4px 4px 0 #f00;
}
</pre>
<button>测试</button>
<div id=”multi”></div>
<p>http://dev.opera.com/articles/view/svg-evolution-3-applying-polish/</p>
<p>https://developer.mozilla.org/cn/Canvas_tutorial</p>
<p>http://www.btinternet.com/~st_rise/main/mainfram.htm?../webplus/vml/vfill.htm</p>
http://www.svgbasics.com/filters3.html
接着看如何实现圆角与半透明效果与盒阴影。如果不考虑IE与Opera,只需要多添加三行代码:
this.css(".popups","background:rgba(104,223,251,.8)");
this.css(".popups","-moz-border-radius:5px;-moz-box-shadow:10px 10px 5px #c0c0c0;");
this.css(".popups","-webkit-border-radius:5px;-webkit-box-shadow:10px 10px 5px #c0c0c0;");不过要实现兼容IE也不难,就是利用VML生成一个圆角矩形,然后利用二级标记fill与shadow轻易实现上述功能。由于VML元素与HTML元素是位于同一个层的,因此我们插入这些VML时肯定会影响原来的文档流,因此我的弹出层的大多数对象都是定位元素,这样谁都影响不了谁。标准浏览器就有点麻烦了,本来我费了很大劲用canvas实现圆角矩形,但回头发现它不住阴影fillShadow等方法。于是改用SVG。我们可以比较一下动态生成后VML与SVG的代码。
//利用canvas实现圆角矩形
var canvas = document.createElement("canvas");
container.insertBefore(canvas,null);
this.attr(canvas,{width:width,height:height,className:"canvas"});
this.css("#"+this.id +" canvas" ,"position:absolute;");
if(canvas.getContext) {
var ctx = canvas.getContext(\'2d\');
ctx.fillStyle = "rgba(104,223,251,.5)";
roundedRect(ctx,0, 0, width, height,5);
ctx.shadowColor = \'#00f\';
ctx.shadowOffsetX = 16;
ctx.shadowOffsetY = 16;
ctx.shadowBlur = 8;
ctx.shadowColor = \'rgba(0, 0, 255, 0.25)\';
function roundedRect(ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x,y+radius);
ctx.lineTo(x,y+height-radius);
ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
ctx.lineTo(x+width-radius,y+height);
ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
ctx.lineTo(x+width,y+radius);
ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
ctx.lineTo(x+radius,y);
ctx.quadraticCurveTo(x,y,x,y+radius);
ctx.fill();
}
}<vml:roundrect class="vml" style="position: absolute;width:400px;
height:300px;top:0px;left:0px;">
<vml:fill class="vml" opacity="0.8" color="#68DFFB" />
<vml:shadow class="vml" on="t" color="#333" opacity="0.2" offset="10px,10px" />
</vml:roundrect><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="410px" height="310px">
<defs>
<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="1.5" />
<feOffset in="blur-out" result="the-shadow" dx="0" dy="2" />
<feBlend in="SourceGraphic" in2="the-shadow" mode="normal" />
</filter>
</defs>
<rect x="10px" y="10px" width="400px" height="300px" rx="5" fill="#333"
style="opacity:0.2" filter="url(#drop-shadow)"/>
<rect width="400px" height="300px" rx="5" fill="#68DFFB" style="opacity:0.8" />
</svg>var defs = this.createSVG(“defs”);
svg.appendChild(defs);var filter = this.createSVG(“filter”);
defs.appendChild(filter);
this.attr(filter,{id:”filter”+id});var feGaussianBlur = this.createSVG(“feGaussianBlur”);
filter.appendChild(feGaussianBlur)
this.attr(feGaussianBlur,{“in”:”SourceAlpha”,result:”blur-out”,
stdDeviation:1.5});var feOffset = this.createSVG(“feOffset”);
filter.appendChild(feOffset)
this.attr(feOffset,{“in”:”blur-out”,result:”the-shadow”,dx:0,dy:2});var feBlend = this.createSVG(“feBlend”);
filter.appendChild(feBlend)
this.attr(feBlend,{“in”:”SourceGraphic”,”in2″:”the-shadow”,
mode:”normal”});var shadow = this.createSVG(“rect”);
svg.appendChild(shadow);
this.attr(shadow,{x:”10px”,y:”10px”,width:width+”px”,height:height+”px”,
rx:10, fill:”#333″,style:”opacity:0.2″,filter:”url(#filter”+id+”)”});var rect = this.createSVG(“rect”);
svg.appendChild(rect);
this.attr(rect,{width:width+”px”,height:height+”px”,rx:5,
fill:”#68DFFB”,style:”opacity:0.8″});
}},
getBrowserWindowSize :function(){
var de = document.documentElement;
return {
\’width\’: (de.clientWidth || document.body.clientWidth),
\’height\’:(de.clientHeight || document.body.clientHeight)
}
},
createSVG : function(tag){
return document.createElementNS(“http://www.w3.org/2000/svg”,tag);
},
attr: function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
},
css:function(selector,declaration){
if(typeof document.createStyleSheet === \’undefined\’) {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\’style\’);
element.type = \’text/css\’;
document.getElementsByTagName(\’head\’)[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length – 1];
if(typeof sheet.addRule === \’undefined\’)
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \’undefined\’)
index = this.cssRules.length;
this.insertRule(selectorText + \’ {\’ + cssText + \’}\’, index);
};
return sheet;
}
return createStyleSheet;
})();
}
if(!!Dialog.sheet){
if(!Dialog.memory.exists(selector,declaration)){
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}else{
Dialog.sheet = document.createStyleSheet();
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<l;i++){
if(keys[i] == k){
results.push(values[i])
}
}
return results;
},
exists:function(k,v){
var vs = this.get(k);
for(var i=0,l=vs.length;i<l;i++){
if(vs[i] == v)
return true;
}
return false;
},
set : function(k,v){
keys.push(k);
values.push(v);
size++;
},
length :function(){
return size;
}
}
}
Dialog.memory = memory();
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}
};window.onload = function(){
setTimeout(function(){
new Dialog({width:400,height:300,title:”司徒正美”})
},1000)}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>一步步教你实现弹出窗口 by 司徒正美</h2><div id=”parent”></div><b id=”child” >样式规则</b>
<pre>
#navigation {
-webkit-box-shadow: 0 0 10px #000;
-moz-box-shadow: 0 0 10px #000;
}
#navigation li a:hover,
#navigation li a:focus {
-webkit-box-shadow: 0 0 5px #111;
-moz-box-shadow: 0 0 5px #111;
}
box-shadow属性可以用多个值:水平偏移、垂直偏移、模糊半径、伸展半径和阴影颜色。水平和垂直偏移和阴影色使用的最多。
在一个div上应用红色阴影,右边和下边偏移4px,无模糊,我们可以使用下面的代码:div {
-moz-box-shadow: 4px 4px 0 #f00;
-webkit-box-shadow: 4px 4px 0 #f00;
box-shadow: 4px 4px 0 #f00;
}
</pre>
<button>测试</button>
<div id=”multi”></div>
<p>http://dev.opera.com/articles/view/svg-evolution-3-applying-polish/</p>
<p>https://developer.mozilla.org/cn/Canvas_tutorial</p>
<p>http://www.btinternet.com/~st_rise/main/mainfram.htm?../webplus/vml/vfill.htm</p>
http://www.svgbasics.com/filters3.html
接着下来就是绑定事件了,字符串拼接有一个不好处,要获取刚刚生成的DOM对象的引用比较麻烦。不过我打算利用事件代理就另当别论了,因为我们手头上最明确的对象就是那个DIV元素,我们把所有事件都绑定在它上面就是了。这个留在下次说。
这部分的内容是绑定事件,模拟模态窗口与拖动。先从最简单的说起,弹出窗口现在有三个按钮,反正都是点击事件,我们可以利用事件代理以节省侦听器。侦听器放在顶层容器中就是,然后我们再判定冒泡上来的事件的源对象的标签是否为a元素,再根据其类名添加相应的事件。
container.onclick = function(){
var ee = me.getEvent(), node = ee[1],tag = ee[2];
if(tag == "a" ){
switch(node.className){
case "closebtn" :
me.hide();
break;
case "positive" :
me.hide();
//form.submit();
break;
case "negative" :
alert("你点击了取消按钮!");
break;
}
}
}
其中me即为this,Dialog类的实例,因为就这样简单把this暴露在绑定函数中,它对应的是container这个顶层容器,而不是实例。hide方法的功能很简单,隐藏顶层容器。getEvent方法的具体代码可参见我的另一篇博文,用来快捷取得事件,事件源对象以及源对象的标签名。到此,绑定事件部分讲完了。
再看拖放,我以前有两篇博文专门说这问题,可参见这里与这里。现在扼要演实一下如何运用。首先在init()主方法中添加如下代码:
container.onmousedown = function(e){
e = e || event;
container.offset_x = e.clientX - container.offsetLeft;
container.offset_y = e.clientY - container.offsetTop;
document.onmousemove = function(e){
me.drag(e,container)
}
document.onmouseup = function(){
me.dragend(container)
}
}
然后再添加两个原型方法,分别为drag与dragend。
drag:function(e,el){
e = e || event;//获得事件对象
var l = e.clientX - el.offset_x + "px",
t = e.clientY - el.offset_y + "px";
this.incss(el, {cursor:"move",left:l,top:t})
!+"\v1"? document.selection.empty() : window.getSelection().removeAllRanges();
},
dragend:function(el){
el.style.cursor = "";
document.onmouseup = document.onmousemove = null;
}
因为我原来的动态添加样式规则方法css名副其实,就是动态添加,不具备修改能力,因此对于在拖动中频繁修改的CSS属性就无能为力了,于是我又用回内联样式。它的代码很简单,以前我也多次演示过这东西。
incss:function(node,bag){
var str = ";"
for(var i in bag){
if(bag.hasOwnProperty(i))
str += i+":"+bag[i]+";"
}
node.style.cssText = str;
}
如果IE6死掉是多么美好了,基本上就是这样简单。我们在IE6中拖啊拖,遇到select标签了!为了掩住了它,我们需要一个iframe标签,并把它放到顶层容器之前(它与顶层容器是兄弟节点)。由于我们的弹出窗口是有阴影的,因此iframe的大小应该为弹出窗口加阴影的大小,并且其z-index比它顶层容器一点。
if(me.ie6){
me.iframe = document.createElement("");
container.insertAdjacentElement(\'beforeBegin\',me.iframe);
}
在拖动窗口时也拖动iframe。
drag:function(e,me){
e = e || event;//获得事件对象
var el = me.container,
l = e.clientX - el.offset_x + "px",
t = e.clientY - el.offset_y + "px";
this.incss(el, {cursor:"move",left:l,top:t})
if(this.ie6){
with(me.iframe.style){//当用cssText设置iframe的样式时,其display变为inline,就无法掩住select
left=l; //另,当设置iframe的allowTransparency="true" ,也不能掩住select
top=t;
}
}
!+"\v1"? document.selection.empty() : window.getSelection().removeAllRanges();
},
最看模态窗口的实现。现在所有浏览器都支持showModeDialog方法了,即使是火狐。但在首次使用此方法,IE会有提示是否允许执行。若用户以前做够了弹出广告的骚扰,我们再用这方法来实现,恐怕就行不通了。因此我是使用纯DIV来模拟。首先是冻结窗口,把可视区外部分隐藏掉,阻止滚动条出现。其次阻止弹出窗口外的其他部分的右键事件与选择事件。
mode:function(w,h){
var mask = Dialog.mask,me = this;
//IE6的addRule方法存在bug,不支持联合选择器,即html,body{*********}这种形式,只好分开写!
this.css("html","margin:0;border:0;width:100%;height:100%;overflow:hidden;");
this.css("body","margin:0;border:0;width:100%;height:100%;overflow:hidden;");
this.incss(mask,{position:"absolute",background:"#fff",top:0,left:0,
width:w +"px",height:h +"px","-moz-user-select":"none"});
!+"\v1"? (mask.style.filter = "alpha(opacity=0)") : (mask.style.opacity = "0");
mask.onselectstart = function(e){//不允许选择弹出窗口以外的内容
me.stopEvent(e);
}
mask.oncontextmenu = function(e){//不允许在弹出窗口外弹出右键窗口
me.stopEvent(e);
}
},
mode方法我们在show与hide中调用。
hide : function(){
this.container.style.display = "none" ;
if(this.ie6){
this.iframe.style.display = "none";
}
this.mode(0,0);
//下面两行目的是生成 html,body{width:auto;height:auto;overflow:auto;}
this.incss(document.body, {width:"auto",height:"auto",overflow:"auto"});
this.incss(document.documentElement, {width:"auto",height:"auto",overflow:"auto"});
},
show : function(){
this.container.style.display = "block" ;
if(this.ie6){
this.iframe.style.display = "block";
}
var size = this.getBrowserWindowSize();
this.mode(size.width, size.height);
},
stopEvent方法是用来阻止事件冒泡与浏览器的默认事件,一个非常常用的方法。
stopEvent:function(e){
e = e || window.event;
if(e.preventDefault) {
e.preventDefault();
e.stopPropagation();
}else{
e.returnValue = false;
e.cancelBubble = true;
}
},
var divs = container[t](“div”),k = divs.length;
while (–k >= 0) {
if(divs[k].className == “replaceable”){
me.content = divs[k]
break;
}
}//设置样式
me.css(“.popups”,”position:absolute;width:”+width+”px;height:”+
height+”px;left:”+me.left+”px;top:”+me.top+”px;”);//background:#68DFFB
container.style.zIndex = Dialog.zIndex++;
me.css(“.popups .caption”,\’position:absolute;top:10px;left:10px;width:\’+(width-50)+\’px;height:20px;\’+
\’padding-left:30px;font:700 14px/20px “SimSun”,”Times New Roman”;color: #fff;\’+
bg(“o_icon.gif”,”#68DFFB”,”5px”));
me.css(“.popups .closebtn”,\’position:absolute;top:0;right:10px;display:block;width:28px; \’+
\’height:17px;text-decoration:none;\’+ bg(“o_dialog_closebtn.gif”));
me.css(“.popups a.closebtn:hover”,bg(“o_dialog_closebtn_over.gif”));
me.css(“.popups form”,”position:absolute;top:30px;left:10px;border:3px solid #68DFFB;width:”+(width-26)+”px;height:”+(height-51)+”px;background:#fff;”);
me.css(“.popups .submitable”,”position:absolute;bottom:0;border-top:1px solid #c0c0c0;width:100%;height:40px;background:#f9f9f9;”);
var buttoncss = \’display:block;float:right;margin: 0.7em 0.5em;padding:2px 7px;border:1px solid #dedede;\’
+ \’background:#f5f5f5;color:#a9ea00;font:700 12px/130% “SimSun”,”Times New Roman”;text-decoration:none;\’;
me.css(“a.positive”,buttoncss);//IE6有bug,不能动态创建联合选择器
me.css(“a.negative”,buttoncss);
me.css(“a.negative”,”color:#ff5e00;”);
me.css(“a.positive:hover”,”border:1px solid #E6EFC2;background:#E6EFC2;color:#529214;”);
me.css(“a.negative:hover”,”border:1px solid #fbe3e4;background:#fbe3e4;color:#d12f19;”);
me.css(“a.positive:active”,”border:1px solid #529214;background:#529214;color:#fff;”);
me.css(“a.negative:active”,”border:1px solid #d12f19;background:#d12f19;color:#fff;”);
me.css(“a”,”outline: 0;”);
//按钮的圆角
var ff = /a/[-1]==\’a\’;
if(ff){
me.css(“a.positive”,”-moz-border-radius:4px;”);
me.css(“a.negative”,”-moz-border-radius:4px;”);
}else{
me.css(“a.positive”,”-webkit-border-radius:4px;”);
me.css(“a.negative”,”-webkit-border-radius:4px;”);
}
//***************************
if (!+”\v1″ ){
if(!document.namespaces.vml){
document.namespaces.add(\’vml\’, \’urn:schemas-microsoft-com:vml\’);
var vmlobj = document.createElement(“<span class=”mceItemObject” classid=CLSID:10072CEC-8CC1-11D1-986E-00A0C955B42E id=VMLRender>”),
head = document.getElementsByTagName(“head”)[0];
head.appendChild(vmlobj);
document.createStyleSheet().addRule(“.vml”, “behavior: url(#VMLRender); display:inline-block;”);
}
var rect = document.createElement(\'<vml:roundrect class=”vml”>\’);
container.insertBefore(rect,container.firstChild);
rect.style.cssText = “position:absolute;top:0px;left:0px;width:”+width+”px;height:”+height+”px;”;
me.attr(rect,{arcsize:5 /Math.min(width, height),stroked:”f”});
rect.innerHTML = \'<vml:fill class=”vml” opacity=”0.8″ color=”#68DFFB” />\’ +
\'<vml:shadow class=”vml” on=”t” color=”#333″ opacity=”0.2″ offset=”10px,10px” />\’
}else{
var svg = me.createSVG(“svg”);
container.insertBefore(svg,container.firstChild);
me.attr(svg,{width:me.width+10+”px”,height:me.height+10+”px”});var defs = me.createSVG(“defs”);
svg.appendChild(defs);var filter = me.createSVG(“filter”);
defs.appendChild(filter);
me.attr(filter,{id:”filter”+id});var feGaussianBlur = me.createSVG(“feGaussianBlur”);
filter.appendChild(feGaussianBlur)
me.attr(feGaussianBlur,{“in”:”SourceAlpha”,result:”blur-out”,stdDeviation:1.5});var feOffset = me.createSVG(“feOffset”);
filter.appendChild(feOffset)
me.attr(feOffset,{“in”:”blur-out”,result:”the-shadow”,dx:0,dy:2});var feBlend = me.createSVG(“feBlend”);
filter.appendChild(feBlend)
me.attr(feBlend,{“in”:”SourceGraphic”,”in2″:”the-shadow”,mode:”normal”});var shadow = me.createSVG(“rect”);
svg.appendChild(shadow);
me.attr(shadow,{x:”10px”,y:”10px”,width:me.width+”px”,height:me.height+”px”,rx:10,
fill:”#333″,style:”opacity:0.2″,filter:”url(#filter”+id+”)”});var rect = me.createSVG(“rect”);
svg.appendChild(rect);
me.attr(rect,{width:me.width+”px”,height:me.height+”px”,rx:5,fill:”#68DFFB”,style:”opacity:0.8″});
}
//***************************IE6 弹出窗口中遮不住select******************************
if(me.ie6){
me.iframe = document.createElement(“<iframe style=\’position:absolute;left:”+
me.left+”px;top:”+me.top+”px;width:”+(me.width+10)+”px;height:”+
(me.height+10)+”px;z-index:”+(Dialog.zIndex-2)+”;filter:mask();display:none;\’ ></iframe>”);
container.insertAdjacentElement(\’beforeBegin\’,me.iframe);
}//*****************************监听点击**************************
container.onclick = function(){
var ee = me.getEvent(), node = ee[1],tag = ee[2];
if(tag == “a” ){
switch(node.className){
case “closebtn” :
me.hide();
break;
case “positive” :
me.hide();
//form.submit();
break;
case “negative” :
alert(“你点击了取消按钮!”);
break;
}
}
}
container.onmousedown = function(e){
e = e || window.event;
container.offset_x = e.clientX – container.offsetLeft;
container.offset_y = e.clientY – container.offsetTop;
document.onmousemove = function(e){
me.drag(e,me)
}
document.onmouseup = function(){
me.dragend(container)
}
}
},
drag:function(e,me){
e = e || window.event;//获得事件对象
var el = me.container;
var l = e.clientX – el.offset_x + “px”,
t = e.clientY – el.offset_y + “px”;
with(el.style){
left=l;
top=t;
cursor=”move”
}
if(me.ie6){
with(me.iframe.style){
left=l;
top=t;
}
}
!+”\v1″? document.selection.empty() : window.getSelection().removeAllRanges();
},
dragend:function(el){
el.style.cursor = “”;
document.onmouseup = document.onmousemove = null;
},
hide : function(){
this.container.style.display = “none” ;
if(this.ie6){
this.iframe.style.display = “none”;
}
this.mode(0,0);
this.incss(document.body, {width:”auto”,height:”auto”,overflow:”auto”});
this.incss(document.documentElement, {width:”auto”,height:”auto”,overflow:”auto”});
},
show : function(){
this.container.style.display = “block” ;
if(this.ie6){
this.iframe.style.display = “block”;
}
var size = this.getBrowserWindowSize();
this.mode(size.width, size.height);
},
getBrowserWindowSize :function(){
var de = document.documentElement;
return {
\’width\’: (de.clientWidth || document.body.clientWidth),
\’height\’:(de.clientHeight || document.body.clientHeight)
}
},
createSVG : function(tag){
return document.createElementNS(“http://www.w3.org/2000/svg”,tag);
},
attr: function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
},
getEvent : function(e) {
var e = e || window.event;
if (!e) {
var c = this.getEvent.caller;
while (c) {
e = c.arguments[0];
if (e && (Event == e.constructor || MouseEvent == e.constructor)) {
break;
}
c = c.caller;
}
}
var target = e.srcElement ? e.srcElement : e.target,
currentN = target.nodeName.toLowerCase(),
parentN = target.parentNode.nodeName.toLowerCase(),
grandN = target.parentNode.parentNode.nodeName.toLowerCase();
return [e,target,currentN,parentN,grandN];
},
mode:function(w,h){
var mask = Dialog.mask,me = this;
this.incss(document.body, {width:”100%”,height:”100%”,overflow:”hidden”});
this.incss(document.documentElement, {width:”100%”,height:”100%”,overflow:”hidden”});
this.incss(mask,{position:”absolute”,background:”#fff”,top:0,left:0,
width:w +”px”,height:h +”px”,”-moz-user-select”:”none”});
!+”\v1″? (mask.style.filter = “alpha(opacity=0)”) : (mask.style.opacity = “0”);
mask.onselectstart = function(e){
me.stopEvent(e);
}
mask.oncontextmenu = function(e){
me.stopEvent(e);
}
},
stopEvent:function(e){
e = e || window.event;
if(e.preventDefault) {
e.preventDefault();
e.stopPropagation();
}else{
e.returnValue = false;
e.cancelBubble = true;
}
},
incss:function(node,bag){
var str = “;”
for(var i in bag){
if(bag.hasOwnProperty(i))
str += i+”:”+bag[i]+”;”
}
node.style.cssText = str;
},
css:function(selector,declaration){
if(typeof document.createStyleSheet === \’undefined\’) {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\’style\’);
element.type = \’text/css\’;
document.getElementsByTagName(\’head\’)[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length – 1];
if(typeof sheet.addRule === \’undefined\’)
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \’undefined\’)
index = this.cssRules.length;
this.insertRule(selectorText + \’ {\’ + cssText + \’}\’, index);
};
return sheet;
}
return createStyleSheet;
})();
}
if(!!Dialog.sheet){
if(!Dialog.memory.exists(selector,declaration)){
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}else{
Dialog.sheet = document.createStyleSheet();
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<l;i++){
if(keys[i] == k){
results.push(values[i])
}
}
return results;
},
exists:function(k,v){
var vs = this.get(k);
for(var i=0,l=vs.length;i<l;i++){
if(vs[i] == v)
return true;
}
return false;
},
set : function(k,v){
keys.push(k);
values.push(v);
size++;
},
length :function(){
return size;
}
}
}
Dialog.memory = memory();
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
Dialog.mask = document.createElement(“div”);
document.body.insertBefore(Dialog.mask,this.container);
}
}
};window.onload = function(){
var dialog;
setTimeout(function(){ //定时器是为了能在我运行框中正常运行,项目中没有必须放到里面去!dialog = new Dialog({width:400,height:300,title:”司徒正美”});
dialog.hide();},0)
var bn = document.getElementById(“test”);
bn.onclick = function(){dialog.show();
dialog.content.innerHTML = “弹出窗口中间的部分可以用dialog.content.innerHTML重写!”
}
}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>一步步教你实现弹出窗口 by 司徒正美</h2><div id=”parent”></div><b id=”child” >样式规则</b>
<p style=”color:red” mce_style=”color:red”>在chrome中好像没办法用width:100%,height:100%,overflow:hidden冻结窗口,只能隐藏滚动条。</p>
<pre>
#navigation {
-webkit-box-shadow: 0 0 10px #000;
-moz-box-shadow: 0 0 10px #000;
}
#navigation li a:hover,
#navigation li a:focus {
-webkit-box-shadow: 0 0 5px #111;
-moz-box-shadow: 0 0 5px #111;
}
box-shadow属性可以用多个值:水平偏移、垂直偏移、模糊半径、伸展半径和阴影颜色。水平和垂直偏移和阴影色使用的最多。
在一个div上应用红色阴影,右边和下边偏移4px,无模糊,我们可以使用下面的代码:div {
-moz-box-shadow: 4px 4px 0 #f00;
-webkit-box-shadow: 4px 4px 0 #f00;
box-shadow: 4px 4px 0 #f00;
}
</pre>
<select name=”select1″>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
</select>
<select name=”select1″>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
</select><button id=”test”>测试</button>
<div id=”multi”></div>
<p>http://dev.opera.com/articles/view/svg-evolution-3-applying-polish/</p>
<p>https://developer.mozilla.org/cn/Canvas_tutorial</p>
<p>http://www.btinternet.com/~st_rise/main/mainfram.htm?../webplus/vml/vfill.htm</p>
http://www.svgbasics.com/filters3.html
ar callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf(“function”) + 8, callerFunc.indexOf(“(“)) || “anoynmous”)
<pre>
<p>通过正则表达式将查询字符串转化为对象</p>
function getQuery(s){
var arr = s.split(\’?\’);
var param = arr[1].split(\’&\’);
var obj = {};
for(var i =0 ; i<span .length; i++){
var p = param[i].split(\’=\’);
obj[p[0]] = p[1];
}
return obj;
}
</pre class=”mceItemParam”></span>
var divs = container[t](“div”),k = divs.length;
while (–k >= 0) {
if(divs[k].className == “replaceable”){
me.content = divs[k]
break;
}
}//设置样式
me.css(“.popups”,”position:absolute;width:”+width+”px;height:”+
height+”px;left:”+me.left+”px;top:”+me.top+”px;”);//background:#68DFFB
container.style.zIndex = Dialog.zIndex++;
me.css(“.popups .caption”,\’position:absolute;top:10px;left:10px;width:\’+(width-50)+\’px;height:20px;\’+
\’padding-left:30px;font:700 14px/20px “SimSun”,”Times New Roman”;color: #fff;\’+
bg(“o_icon.gif”,”#68DFFB”,”5px”));
me.css(“.popups .closebtn”,\’position:absolute;top:0;right:10px;display:block;width:28px; \’+
\’height:17px;text-decoration:none;\’+ bg(“o_dialog_closebtn.gif”));
me.css(“.popups a.closebtn:hover”,bg(“o_dialog_closebtn_over.gif”));
me.css(“.popups form”,”position:absolute;top:30px;left:10px;border:3px solid #68DFFB;width:”+(width-26)+”px;height:”+(height-51)+”px;background:#fff;”);
me.css(“.popups .submitable”,”position:absolute;bottom:0;border-top:1px solid #c0c0c0;width:100%;height:40px;background:#f9f9f9;”);
var buttoncss = \’display:block;float:right;margin: 0.7em 0.5em;padding:2px 7px;border:1px solid #dedede;\’
+ \’background:#f5f5f5;color:#a9ea00;font:700 12px/130% “SimSun”,”Times New Roman”;text-decoration:none;\’;
me.css(“a.positive”,buttoncss);//IE6有bug,不能动态创建联合选择器
me.css(“a.negative”,buttoncss);
me.css(“a.negative”,”color:#ff5e00;”);
me.css(“a.positive:hover”,”border:1px solid #E6EFC2;background:#E6EFC2;color:#529214;”);
me.css(“a.negative:hover”,”border:1px solid #fbe3e4;background:#fbe3e4;color:#d12f19;”);
me.css(“a.positive:active”,”border:1px solid #529214;background:#529214;color:#fff;”);
me.css(“a.negative:active”,”border:1px solid #d12f19;background:#d12f19;color:#fff;”);
me.css(“a”,”outline: 0;”);
//按钮的圆角
var ff = /a/[-1]==\’a\’;
if(ff){
me.css(“a.positive”,”-moz-border-radius:4px;”);
me.css(“a.negative”,”-moz-border-radius:4px;”);
}else{
me.css(“a.positive”,”-webkit-border-radius:4px;”);
me.css(“a.negative”,”-webkit-border-radius:4px;”);
}
//***************************
if (!+”\v1″ ){
if(!document.namespaces.vml){
document.namespaces.add(\’vml\’, \’urn:schemas-microsoft-com:vml\’);
var vmlobj = document.createElement(“<span class=”mceItemObject” classid=CLSID:10072CEC-8CC1-11D1-986E-00A0C955B42E id=VMLRender>”),
head = document.getElementsByTagName(“head”)[0];
head.appendChild(vmlobj);
document.createStyleSheet().addRule(“.vml”, “behavior: url(#VMLRender); display:inline-block;”);
}
var rect = document.createElement(\'<vml:roundrect class=”vml”>\’);
container.insertBefore(rect,container.firstChild);
rect.style.cssText = “position:absolute;top:0px;left:0px;width:”+width+”px;height:”+height+”px;”;
me.attr(rect,{arcsize:5 /Math.min(width, height),stroked:”f”});
rect.innerHTML = \'<vml:fill class=”vml” opacity=”0.8″ color=”#68DFFB” />\’ +
\'<vml:shadow class=”vml” on=”t” color=”#333″ opacity=”0.2″ offset=”10px,10px” />\’
}else{
var svg = me.createSVG(“svg”);
container.insertBefore(svg,container.firstChild);
me.attr(svg,{width:me.width+10+”px”,height:me.height+10+”px”});var defs = me.createSVG(“defs”);
svg.appendChild(defs);var filter = me.createSVG(“filter”);
defs.appendChild(filter);
me.attr(filter,{id:”filter”+id});var feGaussianBlur = me.createSVG(“feGaussianBlur”);
filter.appendChild(feGaussianBlur)
me.attr(feGaussianBlur,{“in”:”SourceAlpha”,result:”blur-out”,stdDeviation:1.5});var feOffset = me.createSVG(“feOffset”);
filter.appendChild(feOffset)
me.attr(feOffset,{“in”:”blur-out”,result:”the-shadow”,dx:0,dy:2});var feBlend = me.createSVG(“feBlend”);
filter.appendChild(feBlend)
me.attr(feBlend,{“in”:”SourceGraphic”,”in2″:”the-shadow”,mode:”normal”});var shadow = me.createSVG(“rect”);
svg.appendChild(shadow);
me.attr(shadow,{x:”10px”,y:”10px”,width:me.width+”px”,height:me.height+”px”,rx:10,
fill:”#333″,style:”opacity:0.2″,filter:”url(#filter”+id+”)”});var rect = me.createSVG(“rect”);
svg.appendChild(rect);
me.attr(rect,{width:me.width+”px”,height:me.height+”px”,rx:5,fill:”#68DFFB”,style:”opacity:0.8″});
}
//***************************IE6 弹出窗口中遮不住select******************************
if(me.ie6){
me.iframe = document.createElement(“<iframe style=\’position:absolute;left:”+
me.left+”px;top:”+me.top+”px;width:”+(me.width+10)+”px;height:”+
(me.height+10)+”px;z-index:”+(Dialog.zIndex-2)+”;filter:mask();display:none;\’ ></iframe>”);
container.insertAdjacentElement(\’beforeBegin\’,me.iframe);
}//*****************************监听点击**************************
container.onclick = function(){
var ee = me.getEvent(), node = ee[1],tag = ee[2];
if(tag == “a” ){
switch(node.className){
case “closebtn” :
me.hide();
break;
case “positive” :
me.hide();
//form.submit();
break;
case “negative” :
alert(“你点击了取消按钮!”);
break;
}
}
}
container.onmousedown = function(e){
e = e || window.event;
container.offset_x = e.clientX – container.offsetLeft;
container.offset_y = e.clientY – container.offsetTop;
document.onmousemove = function(e){
me.drag(e,me)
}
document.onmouseup = function(){
me.dragend(container)
}
}
},
drag:function(e,me){
e = e || window.event;//获得事件对象
var el = me.container;
var l = e.clientX – el.offset_x + “px”,
t = e.clientY – el.offset_y + “px”;
with(el.style){
left=l;
top=t;
cursor=”move”
}
if(me.ie6){
with(me.iframe.style){
left=l;
top=t;
}
}
!+”\v1″? document.selection.empty() : window.getSelection().removeAllRanges();
},
dragend:function(el){
el.style.cursor = “”;
document.onmouseup = document.onmousemove = null;
},
hide : function(){
this.container.style.display = “none” ;
if(this.ie6){
this.iframe.style.display = “none”;
}
this.mode(0,0);
//下面两行目的是生成 html,body{width:auto;height:auto;overflow:auto;}
this.incss(document.body, {width:”auto”,height:”auto”,overflow:”auto”});
this.incss(document.documentElement, {width:”auto”,height:”auto”,overflow:”auto”});
},
show : function(){
this.container.style.display = “block” ;
if(this.ie6){
this.iframe.style.display = “block”;
}
var size = this.getBrowserWindowSize();
this.mode(size.width, size.height);
},getBrowserWindowSize :function(){
var de = document.documentElement;
return {
width: (de.clientWidth || document.body.clientWidth),
height:(de.clientHeight || document.body.clientHeight)
}
},
createSVG : function(tag){
return document.createElementNS(“http://www.w3.org/2000/svg”,tag);
},
attr: function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
},
getEvent : function(e) {
e = e || window.event;
if (!e) {
var c = this.getEvent.caller;
while (c) {
e = c.arguments[0];
if (e && (Event == e.constructor || MouseEvent == e.constructor)) {
break;
}
c = c.caller;
}
}
var target = e.srcElement ? e.srcElement : e.target,
currentN = target.nodeName.toLowerCase(),
parentN = target.parentNode.nodeName.toLowerCase(),
grandN = target.parentNode.parentNode.nodeName.toLowerCase();
return [e,target,currentN,parentN,grandN];
},
mode:function(w,h){
var mask = Dialog.mask,me = this;
this.incss(document.body, {width:”100%”,height:”100%”,overflow:”hidden”});
this.incss(document.documentElement, {width:”100%”,height:”100%”,overflow:”hidden”});
this.incss(mask,{position:”absolute”,background:”#fff”,top:0,left:0,
width:w +”px”,height:h +”px”,”-moz-user-select”:”none”});
!+”\v1″? (mask.style.filter = “alpha(opacity=0)”) : (mask.style.opacity = “0”);
mask.onselectstart = function(e){
me.stopEvent(e);
}
mask.oncontextmenu = function(e){
me.stopEvent(e);
}
},
stopEvent:function(e){
e = e || window.event;
if(e.preventDefault) {
e.preventDefault();
e.stopPropagation();
}else{
e.returnValue = false;
e.cancelBubble = true;
}
},
incss:function(node,bag){
var str = “;”
for(var i in bag){
if(bag.hasOwnProperty(i))
str += i+”:”+bag[i]+”;”
}
node.style.cssText = str;
},
css:function(selector,declaration){
if(typeof document.createStyleSheet === \’undefined\’) {
document.createStyleSheet = (function() {
function createStyleSheet() {
var element = document.createElement(\’style\’);
element.type = \’text/css\’;
document.getElementsByTagName(\’head\’)[0].appendChild(element);
var sheet = document.styleSheets[document.styleSheets.length – 1];
if(typeof sheet.addRule === \’undefined\’)
sheet.addRule = function(selectorText, cssText, index) {
if(typeof index === \’undefined\’)
index = this.cssRules.length;
this.insertRule(selectorText + \’ {\’ + cssText + \’}\’, index);
};
return sheet;
}
return createStyleSheet;
})();
}
if(!!Dialog.sheet){
if(!Dialog.memory.exists(selector,declaration)){
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
}
}else{
Dialog.sheet = document.createStyleSheet();
var memory = function(){
var keys = [],values = [],size = 0;
return {
get : function(k){
var results = [];
for(var i=0,l=keys.length;i<l;i++){
if(keys[i] == k){
results.push(values[i])
}
}
return results;
},
exists:function(k,v){
var vs = this.get(k);
for(var i=0,l=vs.length;i<l;i++){
if(vs[i] == v)
return true;
}
return false;
},
set : function(k,v){
keys.push(k);
values.push(v);
size++;
},
length :function(){
return size;
}
}
}
Dialog.memory = memory();
Dialog.memory.set(selector,declaration);
Dialog.sheet.addRule(selector,declaration);
Dialog.mask = document.createElement(“div”);
document.body.insertBefore(Dialog.mask,this.container);
}
}
};window.onload = function(){
var dialog1,dialog2,dialog3
setTimeout(function(){ //定时器是为了能在我运行框中正常运行,项目中没有必须放到里面去!dialog1 = new Dialog({width:400,height:300,title:”司徒正美”});
dialog1.hide();
dialog2 = new Dialog({width:400,height:300,title:”司徒正美”});
dialog2.hide();
dialog3 = new Dialog({width:400,height:300,title:”司徒正美”});
dialog3.hide();},0)
var bn1 = document.getElementById(“test1”),
bn2 = document.getElementById(“test2”),
bn3 = document.getElementById(“test3”);
bn1.onclick = function(){
dialog1.show();
dialog1.content.innerHTML = “<table width=”+(dialog1.width-26)+” height=”+
(dialog1.height-56)+”><tr><td style=”text-align:center;” mce_style=”text-align:center;”>文字居中</td></tr></table>”
}
bn2.onclick = function(){
dialog2.show();
dialog2.content.innerHTML = “<iframe frameborder=0 src=”http://www.csszengarden.com/” mce_src=”http://www.csszengarden.com/” width=”+(dialog2.width-26)+” height=”+
(dialog2.height-96)+”></iframe>”
};
bn3.onclick = function(){
dialog3.show();
dialog3.content.innerHTML = “<table width=”+(dialog3.width-26)+” height=”+
(dialog3.height-96)+”><tr><td style=”text-align:center;” mce_style=”text-align:center;”>” + document.getElementById(“hide”).innerHTML +
“</td></tr></table>”
}
}
// –></mce:script>
<h2 style=”text-align:center” mce_style=”text-align:center”>一步步教你实现弹出窗口 by 司徒正美</h2><pre>
#navigation {
-webkit-box-shadow: 0 0 10px #000;
-moz-box-shadow: 0 0 10px #000;
}
#navigation li a:hover,
#navigation li a:focus {
-webkit-box-shadow: 0 0 5px #111;
-moz-box-shadow: 0 0 5px #111;
}
box-shadow属性可以用多个值:水平偏移、垂直偏移、模糊半径、伸展半径和阴影颜色。水平和垂直偏移和阴影色使用的最多。
在一个div上应用红色阴影,右边和下边偏移4px,无模糊,我们可以使用下面的代码:div {
-moz-box-shadow: 4px 4px 0 #f00;
-webkit-box-shadow: 4px 4px 0 #f00;
box-shadow: 4px 4px 0 #f00;
}
</pre>
<select name=”select1″>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
</select>
<select name=”select1″>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
<option>不要挡住我,不要挡住我</option>
</select><button id=”test1″>弹出窗口1</button>
<button id=”test2″>弹出窗口2(带iframe)</button>
<button id=”test3″>弹出窗口3(引用本页的隐藏层)</button>
<p style=”padding:1em;color:#a9ea00″ mce_style=”padding:1em;color:#a9ea00″>由于window.onload在运行框内(用window.open(“”,””,””)实现)中失效了,于是无法判断窗口的大小,从而无法实现居中对齐。在标准浏览器还有补救措施,在IE则彻彻底底败给它了。放心,Dialog类完全没问题,有问题的是运行框。</p>
<div style=”display:none” mce_style=”display:none” id=”hide”><center style=”padding:1em;font-weight:700″ mce_style=”padding:1em;font-weight:700″>用户登陆</center>
<p>
<label for=”username”>用户名</label>
<input type=”text” name=”username” id=”username” />
</p>
<p>
<label for=”password”>密 码</label>
<input type=”password” name=”password” id=”password” />
</p>
</div>
基本上是这样,300多行,为了兼容Opera的圆角与阴影,有30多行分配给它,为了修正IE6的select bug,有10行分配给它,为了让标准浏览器拥有IE风格的设置样式规则的方法,又要20行。其他的兼容代码估计也有二十行左右。因此浏览器这东西还是一家独大好了。我这个弹出窗口其实还有许多改进之处,如把圆角半透明边框独立出来,作为一个接口,那个动态添加样式的也可以再扩展一下,独立出来,做成另一个接口,再把模态化与拖动独立出来,然后像mootools那样实现类好了,超优雅。