http://www.cs.tut.fi/~jkorpela/www/justify.html
http://webdesign.about.com/od/styleproperties/p/blsptextalign.htm
2 <html xmlns="http://www.w3.org/1999/xhtml">
3
4 <head>
5 <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
6 <title>css文本两端对齐详解及实例</title>
7
8 <style type="text/css">
9 /*
10 两端对齐大家都知道text-align:justify;
11
12 text-justify确不曾被人们所熟悉,它是干什么的呢?。先来看下语法。
13
14 语法:text-justify : auto |inter-word | newspaper | distribute | distribute-all-lines | inter-ideograph
15 参数:
16 auto :允许浏览器用户代理确定使用的两端对齐法则
17 inter-word :通过增加字之间的空格对齐文本。该行为是对齐所有文本行最快的方法。它的两端对齐行为对段落的最后一行无效
18 newspaper : 通过增加或减少字或字母之间的空格对齐文本。是用于拉丁文字母表两端对齐的最精确格式
19 distribute :处理空格很像newspaper,适用于东亚文档。尤其是泰国
20 distribute-all-lines :两端对齐行的方式与distribute相同,也同样不包含两段对齐段落的最后一行。适用于表意字文档
21 inter-ideograph : 为表意字文本提供完全两端对齐。他增加或减少表意字和词间的空格
22 说明:
23 设置或检索对象内文本的对齐方式。
24 对应的脚本特性为textJustify。
25 */
26 .w1{ width:500px;}
27 .a1{background:#00FF00;
28 text-align:justify;/*firefox*/
29 text-justify:inter-ideograph;/*ie*/
30 -ms-text-justify: inter-ideograph;/*ie10 ;auto | distribute | distribute-all-lines | distribute-center-last | inter-cluster | inter-ideograph | inter-word | kashida | newspaper*/
31 }
32 .a2{ background:#FFFF00;}
33 .geovindu
34 {
35 text-align:justify;/*firefox*/
36 text-justify:inter-ideograph;/*ie*/
37
38 }
39 </style>
40 <style type="text/css">
绑定上下文
dojo.hitch可以将一个函数绑定到具体的上下文上执行。首先考虑1个或者2个参数的情形。再接受2个参数的时候,第一个参数表示要绑定的对象,第二个参数表示要绑定到对象上的方法(可以是一个函数定义或者字符串形式的函数名)。如:
第一种形式的调用:
*o: 要绑定的对象
*f: o中的成员函数
*/
dojo.hitch(o, o.f);
调用后返回的结果为:
return o.f.apply(o, arguments);
}
因此,dojo.hitch会返回一个函数
第二种调用形式:
*o: 要绑定的对象
*f: o中的成员函数
*/
dojo.hitch(o, "f");
调用后的返回结果:
return o["f"].apply(o, arguments);
}
dojo不仅能绑定成员函数,还能将一个普通函数绑定到一个对象上,或者将一个对象上的方法,绑定到另一个对象上。
*o: 要绑定的对象
*f: 普通函数
*/
dojo.hitch(o, f);
/*返回结果*/
function() {
return f.apply(o, arguments);
}
/*
*o: 要绑定的对象
*f: p中的成员函数
* o != p
*/
dojo.hitch(o, p.f);
/*返回结果*/
function() {
return p.f.apply(o, arguments);
}
如果只传递一个参数,那么相当于dojo.hitch中第一个参数被置为null,那么所传递的函数将在全局空间执行:
*f: 传递的函数
*/
dojo.hitch(null, f);
/*返回结果*/
f
dojo.hitch(null, "f");
/*返回结果*/
function() {
return dojo.global[f].apply(dojo.global, arguments); //dojo.global代表全局对象
}
绑定参数
当传递给dojo.hitch的参数大于2个时,第一个参数仍然是要绑定的对象,第二个参数也是要绑定到对象上的方法,其他的参数是传递给这个被绑定方法的参数:
*o: 要绑定的对象
*f: 要绑定的方法
*a1, a2,... ,an:要传递给f的参数
*/
dojo.hitch(o, f, a1, a2,..., an);
/*返回一个函数*/
function() {
return f.apply(o, [a1, a2, ..., an].concat(argumetns));
}
比如有这样一个函数:
alert(str1 + str2 + str3);
}
通过dojo.hitch调用:
print("easy"); // 打印this is easy
/* 实际上调用printArgs("this", "is", "easy");
总结
dojo.hitch实际上就是将一个函数绑定到另一个对象上面,并将这个函数的调用过程封装在一个匿名函数之中,然后将这个匿名函数作为返回值。
本文链接
function BigComputer(answer) {
this.the_answer = answer;
this.ask_question = function () {
alert(this.the_answer);
}
}
function addhandler() {
var deep_thought = new BigComputer(42),
the_button = document.getElementById('thebutton');
the_button.onclick = deep_thought.ask_question;
}
window.onload = addhandler;
</script>
很完美吧?想象一下,我们点击按钮,deep_thought.ask_question被执行,我们也得到了“42”。但是为什么浏览器却给我们一个undefined? 我们错在何处?
其实问题显而易见:我们给ask_question传递一个引用,它作为一个事件处理函数来执行,与作为对象方法来运行的上下文并不一样。简而言之,ask_question中的 this关键字指向了产生事件的DOM元素,而不是在BigComputer的对象中。DOM元素并不存在一个the_answer属性,所以我们得到的是 undefined而不是”42″. setTimeout也有类似的行为,它在延迟函数执行的同时跑到了一个全局的上下文中去了。
这个问题会在程序的所有角落时不时突然冒出,如果不细致地追踪程序的每一个角落的话,还是一个非常难以排错的问题,尤其在你的对象有跟DOM元素或者window对象同名属性的时候。
使用.apply()和.call()掌控上下文
在点击按钮的时候,我们真正需要的是能够咨询deep_thought一个问题,更进一步说,我们真正需要的是,在应答事件和setTimeout的呼叫时,能够在自身的本原上下文中呼叫对象的方法。有两个鲜为人知的JavaScript方法,apply和call,在我们执行函数呼叫时,可以曲线救国帮我们达到目的,允许我们手工覆盖this的默认值。我们先来看call:
<script type="text/javascript">
var first_object = {
num: 42
};
var second_object = {
num: 24
};
function multiply(mult) {
return this.num * mult;
}
multiply.call(first_object, 5); // 返回 42 * 5
multiply.call(second_object, 5); // 返回 24 * 5
</script>
在这个例子中,我们首先定义了两个对象,first_object和second_object,它们分别有自己的num属性。然后定义了一个multiply函数,它只接受一个参数,并返回该参数与this所指对象的num属性的乘积。如果我们呼叫函数自身,返回的答案极大可能是undefined,因为全局window对象并没有一个num属性除非有明确的指定。我们需要一些途径来告诉multiply里面的this关键字应该引用什么。而multiply的call方法正是我们所需要的。
call的第一个参数定义了在业已执行的函数内this的所指对象。其余的参数则传入业已执行的函数内,如同函数的自身呼叫一般。所以,当执行multiply.call(first_object, 5)时,multiply被呼叫,5传入作为第一个参数,而this关键字被设置为first_object的引用。同样,当执行multiply.call(second_object, 5)时,5传入作为第一个参数,而this关键字被设置为second_object的引用。
apply以call一样的方式工作,但可以让你把参数包裹进一个数组再传递给呼叫函数,在程序性生成函数呼叫时尤为有用。使用apply重现上一段代码,其实区别并不大:
<script type="text/javascript">
...
multiply.apply(first_object, [5]); // 返回 42 * 5
multiply.apply(second_object, [5]); // 返回 24 * 5
</script>
apply和call本身都非常有用,并值得贮藏于你的工具箱内,但对于事件处理函数所改变的上下文问题,也只是送佛到西天的中途而已,剩下的还是得我们来解决。在搭建处理函数时,我们自然而然地认为,只需简单地通过使用call来改变this的含义即可:
function addhandler() {var deep_thought = new BigComputer(42),
the_button = document.getElementById('thebutton');
the_button.onclick = deep_thought.ask_question.call(deep_thought);
}
代码之所以有问题的理由很简单:call立即执行了函数(译注:其实可以用一个匿名函数封装,例如the_button.onclick = function(){deep_thought.ask_question.call(deep_thought);},但比起即将讨论的bind来,依然不够优雅)。我们给onclcik处理函数一个函数执行后的结果而非函数的引用。所以我们需要利用另一个JavaScript特色,以解决这个问题。
.bind()之美
我并不是 Prototype JavaScript framework的忠实粉丝,但我对它的总体代码质量印象深刻。具体而言,它为Function对象增加一个简洁的补充,对我管理函数呼叫执行后的上下文产生了极大的正面影响:bind跟call一样执行相同的常见任务,改变函数执行的上下文。不同之处在于bind返回的是函数引用可以备用,而不是call的立即执行而产生的最终结果。
如果需要简化一下bind函数以抓住概念的重点,我们可以先把它插进前面讨论的乘积例子中去,看它究竟是如何工作的。这是一个相当优雅的解决方案:
<script type="text/javascript">
var first_object = {
num: 42
};
var second_object = {
num: 24
};
function multiply(mult) {
return this.num * mult;
}
Function.prototype.bind = function(obj) {
var method = this,
temp = function() {
return method.apply(obj, arguments);
};
return temp;
}
var first_multiply = multiply.bind(first_object);
first_multiply(5); // 返回 42 * 5
var second_multiply = multiply.bind(second_object);
second_multiply(5); // 返回 24 * 5
</script>
首先,我们定义了first_object, second_object和multiply函数,一如既往。细心处理这些后,我们继续为Function对象的prototype定义一个bind方法,这样的话,我们程序里的函数都有一个bind方法可用。当执行multiply.bind(first_object)时,JavaScript为bind方法创建一个运行上下文,把this置为multiply函数的引用,并把第一个参数obj置为first_object的引用。目前为止,一切皆顺。
这个解决方案的真正天才之处在于method的创建,置为this的引用所指(即multiply函数自身)。当下一行的匿名函数被创建,method通过它的作用域链访问,obj亦然(不要在此使用this, 因为新创建的函数执行后,this会被新的、局部的上下文覆盖)。这个this的别名让apply执行multiply函数成为可能,而传递obj则确保上下文的正确。用计算机科学的话说,temp是一个闭包(closure),它可以保证,需要在first_object的上下文中执行multiply,bind呼叫的最终返回可以用在任何的上下文中。
这才是前面说到的事件处理函数和setTimeout情形所真正需要的。以下代码完全解决了这些问题,绑定deep_thought.ask_question方法到deep_thought的上下文中,因此能在任何事件触发时都能正确运行:
function addhandler() {
var deep_thought = new BigComputer(42),
the_button = document.getElementById('thebutton');
the_button.onclick = deep_thought.ask_question.bind(deep_thought);
}
漂亮。
本文链接