阿当的博客











{十二月 14, 2009}   javascript的分层概念

在webrebuild北京站上做的一次分享,总结了一下javascript的分层概念。

   这里特别推荐一下YUI3给我们带来的分层概念:

1)底层(框架提供):封装DOM和Event相关操作,提供跨浏览器兼容的接口,扩展原生javascript语言本身不提供的但又特实用的接口,例如namespace;

2)抽象类层(框架提供):提供类的抽象层,用于统一框架组件层,自定义组件层和应用层中所有类的格式,例如统一初始化方法,毁灭方法,属性如何定义,监听事件在什么方法里等等等等;

3)通用组件层(框架提供):依赖底层的接口,继承自抽象类的抽象类,提供通用型组件,和项目具体需求没有直接关系,也就是说,不是定制型的组件。

4)自定义组件层(开发工程师提供):根据项目需求,定制型的组件,它依赖底层和通用组件层,继承自抽象类层,是根据具体项目进行的封装,定制型组件。

5)应用层(开发工程师提供):这一层是和页面具体需求相关的,面向应用的。用mvc来划分的话,前面四层全是m,这一层是c。它调用前面四层提供的m,集中精力在应用逻辑上。这一层如果需要自定义类,也需要继承自抽象类层。

ppt见:http://www.adanghome.com/share/javascripthierarchical.ppt



{十一月 19, 2009}   [原创] 如何在ietester下使用firebug

首先,需要说明的是,此firebug并不是firefox下的插件firebug。众所周知,firebug是firefox下的调试利器,但在ie下没有相关的插件,为了在ie下实现firebug功能,所以出了这么一个组件,它是完全用js生成的仿firebug界面。功能当然没有真正的firebug强大,但其操作和firebug很像,界面也像,对于习惯firebug的工程师来说,使用它非常亲切。其官方网站是http://uicss.cn/r.php?hr=http://getfirebug.com/lite.html

    有一点很让人郁闷的是,官方提供的加载它的方法是给html加载一个<script>标签,引用这段js到页面里去。这个在开发阶段当然是没有问题,但如果是调试已经在线上的页面,比如http://www.sina.com.cn,怎么办呢?有办法能像firefox下的firebug一样随时可以调用吗?

     有,一个最简单的办法就是使用油猴。IE下的油猴见:http://www.bhelpuri.net/Trixie/

      如果是使用maxthon的话,maxthon也有自己的油猴插件,叫做more scripts,见:http://addons.maxthon.cn/zh_CN/search/all/bW9yZSBzY3JpcHRz

      但问题是我们经常需要在ie6,ie7,ie8三个不同版本的ie下进行调试,如果是其中一个版本出现了问题呢?当然,ie6,ie7和ie8的js引擎没啥大区别,主要是指css方面的问题。我们如何调试呢?为了调试ie6,ie7和ie8,我们最常用的软件是ietester,而ietester本身其实也带调试工具DebugBar。用DEbugBar比起ie自带的developer toolbar最大的好处是它可以运行在不同的内核之上,ie6,7,8都可以进行调试。但DebugBar真的是超级难用!!如果能将ietester的多ie内核功能,结合firebug的易用性,该多好啊!可是ietester下没有油猴。。。

      还是有办法的,现在就告诉你我的办法。首先打开ietester的DebugBar,切换到脚本标签,可以看到最下面一栏有个输入框,注释写着”// Javascript 控制台”,这是个类似于firebug的脚本控制台的功能,可以输入js并运行。如截图:

我们在这里输入脚本:

=============================================

var s = document.createElement(“script”);
s.src = ‘http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js’;
s.type=”text/javascript”;
if(document.all){
   s.onreadystatechange = function(){
    if(this.readyState == “loaded” || this.readyState == “complete”){
     alert(“loaded success in ie”);
    }
   }
} else {
   s.onload = function(){
    alert(“load success”);
   }
}
document.body.appendChild(s);
================================================

这里的思路是动态创建一个script标签,然后监听它的onload事件,当它加载完成时,会alert一下加载成功信息。运行脚本,等到弹出”loaded success in ie”后,表示我们的firebug组件的脚本已经加载进来了。但此时,firebug的界面并没有出现!别着急,我们将输入框中的代码清除掉,再输入如下代码:

==================

firebug.init();

==================

    运行它,过一会儿,就会看到firebug的界面出现了!我用这个方法成功在htttp://www.sina.com.cn调出了firebug,如截图所示:


 

ok,ietester下我们已经可以使用firebug了。接下来,我们看看不同版本ie内核下的firebug能不能按我们预期的那样,在不同内核下真实显示当前的信息。

写了个小demo,如下:

=======================================

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd“>
<html>
<head>
<title>阿当制作</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
</head>
<body>
<style type=”text/css”>
#test{padding:20px;background:green;*background:blue;_background:yellow}
</style>
<div id=”test”>hello world</div>
</body>
</html>

=======================================
定义了一个id为test的div,用css hack让它在ie6,7,8下背景色分别为yellow,blue,green。然后,看看在不同内核版本下firebug会如何显示当前的样式信息呢?见截图:





{十月 22, 2009}   [原创 js]自定义元素位置和大小

用YUI2做的一个小demo,实现了元素的drag和resize功能,自定义添加或减少元素,还可以将元素的位置,长宽等信息打印出来。

演示地址:www.adanghome.com/js_demo/1/

代码如下:

==========================================================
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title> 阿当制作</title>
<link type=”text/css” rel=”stylesheet” href=”http://assets.taobaocdn.com/app/tbs/css/public_1_0_0.css” />
<link type=”text/css” rel=”Stylesheet” href=”http://assets.taobaocdn.com/app/tbs/css/jf_express_1_0_0.css” />
<style type=”text/css”>
#wrapper{width:950px;margin:50px auto;}
#previewBox{float:left;display:inline;border:2px solid #666;width:750px;position:relative;height:420px;}
/*#previewBox .leftApp{filter:alpha(opacity=70); opacity: .7;}*/
#inputsWrapper{float:right;display:inline;width:140px;padding:10px;border:2px solid #e0e0de}
#inputsBox span,.leftApp{display:block;margin-top:5px;background:#f2f9ff;border:2px solid #98d6fd;height:22px;line-height:22px;text-align:center;color:#000;cursor:move;font-size:14px;}
p.leftApp,span.leftApp,div.leftApp{position:absolute;margin:0;width:136px;left:0;top:0}
.leftApp_closeBtn{position:absolute;right:15px;top:5px;cursor:pointer;}
#infoBox{padding:10px;margin-top:10px;border:3px solid #ccc;}
</style>
</head>
<body>
<div id=”wrapper”>
<div id=”previewBox”><p style=”width:200px;height:100px;left:50px;top:30px;” myname=”a”>发件人姓名</p><p myname=”b”>发件人地址</p></div>
<div id=”inputsWrapper”>
<h2>打印项 <img src=”http://assets.taobaocdn.com/app/tbs/img/jf_tip.gif” title=”拖动您需要打印的内容项放置到左侧模板中适合的位置。” /></h2>
<p id=”inputsBox”>
<span myname=”a”>发件人姓名</span>
<span myname=”b”>发件人电话</span>
<span myname=”c”>发件人公司</span>
<span myname=”d”>发件人地址</span>
<span myname=”e”>发件人邮编</span>
<span myname=”f”>收件人姓名</span>
<span myname=”g”>收件人电话</span>
<span myname=”h”>收件人地址</span>
<span myname=”i”>收件人邮编</span>
<span myname=”j”>货物清单</span>
<span myname=”k”>发货单号</span>
<span myname=”l”>自定义项</span>
</p>
</div>
<p><input type=”button” value=”显示模块信息” id=”btn” /><p>
<p id=”infoBox”></p>
</div>
<script type=”text/javascript” src=”http://assets.taobaocdn.com/yui/2.7.0/build/yuiloader/yuiloader-min.js”></script>
<script type=”text/javascript”>
var loader = new YAHOO.util.YUILoader({base:”http://assets.taobaocdn.com/yui/2.7.0/build/”});
loader.require(['dom', 'event', 'dragdrop','resize','animation']);
function init(){
var Y=YAHOO.lang,YE = YAHOO.util.Event,YD = YAHOO.util.Dom,YDC=YD.getElementsByClassName,YUC = YAHOO.util.Connect,JSON = YAHOO.lang.JSON,YR = YAHOO.util.Resize;
var CONFIG = {
leftAppContainer : “previewBox”,
rightAppContainer : “inputsBox”,
leftApp : “leftApp”
};

YAHOO.namespace(“express”);

//====================
// LeftApp类
//====================
YAHOO.express.LeftApp = function(id, config) {
this.manager = YD.get(config.manager);
this.el = YD.get(id);
this.el.mytext = this.el.innerHTML;
YAHOO.express.LeftApp.superclass.constructor.call(this, id, config);
YE.on(this.el,”click”,function(){
this.manager.maxAdd();
YD.setStyle(this.el,”zIndex”,this.manager.max);
},null,this);
this.Init();
};

YAHOO.extend(YAHOO.express.LeftApp, YR, {
Init : function(){
this.addCloseBtn();
},
addCloseBtn : function(){
var closeBtn = document.createElement(“img”);
closeBtn.src = “http://assets.taobaocdn.com/app/tbs/img/btn_del.gif”;
closeBtn.className=”leftApp_closeBtn”;
this.el.appendChild(closeBtn);
YE.on(closeBtn,”click”,function(){
this.el.parentNode.removeChild(this.el);
},null,this);
}
});

//=====================
//    LeftApp管理对象
//=====================
YAHOO.express.LeftAppManager = {
max:10,
init : function(){
var leftAppEls = YDC(“leftApp”,”*”,”previewBox”);
for(var i=0,n=leftAppEls.length;i<n;i++){
this.addMod(leftAppEls[i]);
}
},
addMod : function(el){
new YAHOO.express.LeftApp(el,{
handles: ‘all’,
knobHandles: true,
hover:true,
proxy: true,
draggable: true,
manager:this
});
},
maxAdd : function(){
this.max++;
},
getAppsInfo : function(imgInfo){
var leftAppEls = YDC(“leftApp”,”*”,”previewBox”) , wid = 750 , hei = 420 , info = [] , node;
for(var i=0,n=leftAppEls.length;i<n;i++){
node = leftAppEls[i];
info.push(‘{“width”:”‘+ Math.round((node.offsetWidth – 4)*100/wid) + ‘%”,”height”:”‘ + Math.round((node.offsetHeight – 4)*100/hei) + ‘%”,”left”:”‘ + (/%$/.test(YD.getStyle(node,”left”)) ? YD.getStyle(node,”left”) : Math.round(parseInt(YD.getStyle(node,”left”),10)*100/wid) + ‘%’) + ‘”,”top”:”‘ + (/%$/.test(YD.getStyle(node,”top”)) ? YD.getStyle(node,”top”) : Math.round(parseInt(YD.getStyle(node,”top”),10)*100/hei) + ‘%’) + ‘”,”name”:”‘+ (node.myname ? node.myname : node.getAttribute(“myname”))+’”,”text”:”‘+(node.mytext ? node.mytext : node.getAttribute(“mytext”))+’”}’);
}
info = info.join(“,”);
info = “[" + info + "]“;
return info;
}
}

//====================
// RightApp类
//====================
YAHOO.express.RightApp = function(id, sGroup, config) {
YAHOO.express.RightApp.superclass.constructor.call(this, id, sGroup, config);
var el = this.getDragEl();
YD.setStyle(el, “opacity”, 0.67);
};

YAHOO.extend(YAHOO.express.RightApp, YAHOO.util.DDProxy, {
startDrag: function(x, y) {
var dragEl = this.getDragEl();
var clickEl = this.getEl();
YD.setStyle(clickEl, “visibility”, “hidden”);
dragEl.innerHTML = clickEl.innerHTML;
YD.setStyle(dragEl, “color”, YD.getStyle(clickEl, “color”));
YD.setStyle(dragEl, “backgroundColor”, YD.getStyle(clickEl, “backgroundColor”));
YD.setStyle(dragEl, “fontSize”, YD.getStyle(clickEl, “fontSize”));
YD.setStyle(dragEl, “lineHeight”, YD.getStyle(clickEl, “lineHeight”));
YD.setStyle(dragEl, “textAlign”, YD.getStyle(clickEl, “textAlign”));
YD.setStyle(dragEl, “border”, “2px solid #98D6FD”);
},
endDrag: function(e) {
var srcEl = this.getEl();
var proxy = this.getDragEl();
YD.setStyle(proxy, “visibility”, “”);
if(YD.getRegion(CONFIG.leftAppContainer).contains(YD.getRegion(proxy))){
var newNode = document.createElement(“p”);
newNode.innerHTML = srcEl.innerHTML;
newNode.myname = srcEl.getAttribute(“myname”);
YD.get(CONFIG.leftAppContainer).appendChild(newNode);
YD.addClass(newNode,CONFIG.leftApp);
YD.setXY(newNode,YD.getXY(proxy));
YAHOO.express.LeftAppManager.addMod(newNode);
YD.setStyle(proxy, “visibility”, “hidden”);
YD.setStyle(srcEl, “visibility”, “”);
} else {
var a = new YAHOO.util.Motion(
proxy, {
points: {
to: YD.getXY(srcEl)
}
},
0.2,
YAHOO.util.Easing.easeOut
)
a.onComplete.subscribe(function() {
YD.setStyle(proxy, “visibility”, “hidden”);
YD.setStyle(srcEl, “visibility”, “”);
});
a.animate();
}
}
});

//=====================
//    RightApp管理对象
//=====================
YAHOO.express.RightAppManager = {
init : function(){
var rightAppEls = YD.get(CONFIG.rightAppContainer).getElementsByTagName(“span”);
for(var i=0,n=rightAppEls.length;i<n;i++){
new YAHOO.express.RightApp(rightAppEls[i],”right”);
}
}
}

//==================
//    程序初始化
//==================
function init(){
YAHOO.express.LeftAppManager.init();
YAHOO.express.RightAppManager.init();
YE.on(“btn”,”click”,function(){
YD.get(“infoBox”).innerHTML = YAHOO.express.LeftAppManager.getAppsInfo();
});
};
init();
}
</script>
<script type=”text/javascript”>
if(typeof init == “function”){
loader.onSuccess = init;
}
loader.insert();
</script>
</body>
</html>



{十月 13, 2009}   写的某个网站的脚本
记录一下,一些习惯用法已经不想改变了,直接拿出来copy,所以mark一下。

脚本地址:http://assets.taobaocdn.com/app/tbs/js/manage_1_0_7.js



{九月 29, 2009}   YUI的treeview组件——带checkbox类型的treeview如何实现disabled功能
这两天要实现树形目录,功能中要求树形目录带checkbox,而且有默认状态,默认带勾选的,不允许取消。

YUI带checkbox的treeview是通过样式实现的,其实是不带input的,所以没办法实现disabled。选中状态其实是通过挂上高亮的class,treeview本身提供禁止高亮的功能,但一旦禁止,就显示不了勾选,所以不能使用yui的禁止高亮功能完成disabled。

写了个demo,可以模拟disabled功能。如下:

====================================================

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>阿当制作</title>
<script src="http://assets.taobaocdn.com/yui/2.7.0/build/yuiloader/yuiloader-min.js" type="text/javascript"></script>
<script type="text/javascript">
var loader = new YAHOO.util.YUILoader();  
</script>
</head>

<body class="yui-skin-sam">
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.0r4/build/treeview/assets/skins/sam/treeview.css" />
<div id="tree" class="ygtv-checkbox">
<ul>
<li>1
<ul>
<li>1-1</li>
<li>1-2
<ul>
<li>1-2-1</li>
<li>1-2-2</li>
</ul>
</li>
</ul>   
</li>
<li myid="345">2</li>
<li class="expanded">3
<ul>
<li yuiConfig=’{"highlightState":1}’>02/01/2009</li>
<li>3-2</li>
</ul>
</li>
</ul>
</div>
<input type="button" value="确定" id="btn" />
<script type="text/javascript">
function init(){
var tree1 = new YAHOO.widget.TreeView("tree");
tree1.subscribe(‘clickEvent’,tree1.onEventToggleHighlight);
tree1.setNodesProperty(‘propagateHighlightUp’,true);
tree1.setNodesProperty(‘propagateHighlightDown’,true);
tree1.render();
tree1.subscribe(‘dblClickEvent’,tree1.onEventEditNode);

var hiLit = tree1.getNodesByProperty(‘highlightState’,1);
if(YAHOO.lang.isArray(hiLit)){
for(var i=0,n=hiLit.length;i<n;i++){
hiLit[i].openFlag = true;
}
}
tree1.subscribe("highlightEvent", function(node) {
if(node.openFlag){
node.highlight();
}
});

YAHOO.util.Event.on("btn","click",function(){
var hiLit = tree1.getNodesByProperty(‘highlightState’,1);
if(hiLit[0].isLeaf ){
alert(hiLit[0].index);
}
});
}
</script>

<script type="text/javascript">
loader.require(['dom', 'event','treeview','json']);
if(init){
loader.onSuccess = init;
}
loader.insert();
</script>
</body>
</html>

==============================================================



{八月 21, 2009}   YUI3的widget抽象类小demo
YUI3比起YUI2在自定义类方面做了很大的改进。YUI2几乎没有提供用于自定义类的特殊支持,到了YUI3,一切组件都是建立在base,plugin和widget这三种抽象类的基础上的。为自定义类提供了统一的格式和标准!

用widget抽象类做的小demo,感受一下YUI3自定义类的强大:

===================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>阿当制作</title>
<script src="http://yui.yahooapis.com/3.0.0b1/build/yui/yui-min.js" type="text/javascript"></script>

</head>
<body class="yui-skin-sam">
<style type="text/css">

</style>
<div class="join" id="join">
<p><label>第一个数:</label> <input type="text" /></p>
<p><label>第二个数:</label> <input type="text" /></p>
<p>相加结果为:<span class="result"></span></p>
<p><input type="button" class="addBtn" value="相加" /></p>
</div>
<script type="text/javascript">
YUI().use("node","console","dump","anim","dd","slider","widget",function(Y){
var mycon = new Y.Console().render();
function Join(cfg){
Join.superclass.constructor.apply(this,arguments);
}
Join.NAME = "join";
Join.ATTRS = {
result : {
value : null
},
btnEl : {
value : null
},
inputEls : {
value : null
},
resultEl : {
value : null
}
};
Join.HTML_PARSER = {
btnEl : ".addBtn",
inputEls : ["input"],
resultEl : function(contentBox){   
return contentBox.query(".result");
}
};
Y.extend(Join,Y.Widget,{
bindUI : function(){
this.get("btnEl").on("click",function(){
var num = parseInt(this.get("inputEls").item(0).get("value")) + parseInt(this.get("inputEls").item(1).get("value"));
this.set("result",num);
},this);
this.on("resultChange",function(e){
mycon.log(e.newVal);
this._setVal(e.newVal);
}); 
},
syncUI : function(){
var str = this.get("result");
this._setVal(str);
},
_setVal : function(str){
this.get("resultEl").set("innerHTML",str);
}
});
var myJoin = new Join({contentBox:"#join"});
myJoin.render();
})

</script>

</body>
</html>
===========================================



{七月 17, 2009}   [原创] 简单树形菜单
用YUI3做的一个简单小实例。

====================================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>阿当制作</title>
</head>
<style type="text/css">
    .content{display:none;}
    ul{list-style:none;}
</style>
<body>
   <ul class="menu">
    <li>
        <div><img src="http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/expand.gif" class="btn" /> 标题1</div>
        <div class="content">
            内容1
        </div>
    </li>
    <li>
        <div><img src="http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/expand.gif" class="btn" /> 标题2</div>
        <div class="content">
            内容2
        </div>
    </li>
    <li>
        <div><img src="http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/expand.gif" class="btn" /> 标题3</div>
        <div class="content">
            内容3
        </div>
    </li>
    <li>
        <div><img src="http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/expand.gif" class="btn" /> 标题4</div>
        <div class="content">
            内容4
        </div>
    </li>
    <li>
        <div><img src="http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/expand.gif" class="btn" /> 标题5</div>
        <div class="content">
            内容5
        </div>
    </li>
   </ul>
    <script src="http://yui.yahooapis.com/3.0.0b1/build/yui/yui-min.js" type="text/javascript"></script>
<script type="text/javascript">
    YUI().use("node","event",function(Y){
        function MenuItem(node){
            var imgSrc = ["http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/expand.gif","http://style.china.alibaba.com/js/myalibaba/AlicnTree/images/collapse.gif"];
            var btn = node.query(".btn");   
            var content = node.query(".content");
            btn.on("click",function(){
                Y.all(".content").setStyle("display","none");
                Y.all(".btn").set("src",imgSrc[0]);
                if(content.getStyle("display") == "none"){
                    content.setStyle("display","block");
                    btn.set("src",imgSrc[1]);
                } else {
                    content.setStyle("display","none");
                    btn.set("src",imgSrc[0]);
                }
            },this);
        }
        Y.all(".menu li").each(function(n,k){
            new MenuItem(n);   
        });
    });
</script>
</body>
</html>
============================================================



{六月 24, 2009}   [原创 js] 自定义页面功能

     演示地址:http://www.adanghome.com/tbs/manage.html

      这是一个自定义页面的demo,提供自定义布局,拖动模块位置,添加模块,删除模块,拖动导航,重命名,更改页面样式,更改页面标题等等功能。因为主要想展示DHTML,所以重点在js上,没有用ajax或者cookie记录更改状态。

  



{五月 12, 2009}   我最早的全flash站

   我做的第一个纯flash网站,其实也只有一个页面。

   http://www.adanghome.com/flashsite/




about

打造高品质的前端代码

pages
categories
archive
et cetera