其实对 BFC(Block Formatting Contexts 块级格式化上下文) 听过很多次了,虽然每次都无意中也有用到,但是并没有深入的看看这个到底是个什么东西。今天有点时间看到了这篇文章,但是感觉理解起来有点吃力,所以总结下,按照自己的理解再写一写,一方面加深记忆,一方面,以后自己理解起来也方便。

1. 防止外边距叠加。
这里的防止外边距叠加不是两个同级(兄弟)元素之间的外边距叠加,而是防止父元素和子元素之间的外边距叠加。来个结构:

  <div class="a"></div>
  <div class="a">
    <div class="b"></div>
    <div class="b"></div>
  </div>

然后样式:

  .a, .b {
    margin:10px 0;
  }
  .a {
    width:200px;
    height:50px;
    background:red;
  }
 .b {
    width:100px;
    height:10px;
    background:blue;
  }

此时给 .a .b 都有一个

  margin:10px 0;

的外边距。但是并没有触发 .b 的 BFC 特性,此时如图所示:

对 BFC (Block Formatting Contexts) 的一点理解
例子请看:http://jsbin.com/odesoz/3/

然后给 .a 添加

  overflow:hidden;

以触发 .a 的 BFC 特性,此时结果如图所示:

对 BFC (Block Formatting Contexts) 的一点理解
红色是 .a ,蓝色是 .b ,且 .b(蓝色) 是 .a(红色) 的子元素,一目了然。
此时的例子请看:http://jsbin.com/odesoz/2/

2. 清除浮动
其实平常我们使用的清除浮动的技巧,也就是利用了 BFC 的原理。
浮动元素导致父级元素的高度塌陷,此时触发父级元素的 BFC,因为

创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素,反之亦然,同时BFC任然属于文档中的普通流。

其实这句话挺不好理解的,按我的理解,就是这个元素触发了 BFC 然后它就需要按它的行为来,不管里面的元素是什么样子的。不管你浮动不浮动,我多大我就是多大。所以讲浮动闭合(清除)了。
到这里,其实另一点也就呼之欲出了,那是什么呢?就是 只要是可以使父级元素触发 BFC 的特性,都可以闭合浮动。这些就是闭合浮动的原理。(参考

例子可看:http://jsbin.com/odesoz/5/(清除浮动), http://jsbin.com/odesoz/7/ (未清除浮动)

3. 块级格式化上下文不会重叠浮动元素
其实也就是如果有浮动元素和 BFC 一起的话,BFC 元素,会表现为有宽高的样子。具体请看这篇文章的 3.3,因为我觉得这里写的会比我写得好。而且配图也不错。

那么到底神马是 BFC 呢? (其实这些不想写来着,网上那么多,但还是加深印象吧)

其实说的简单点,就类似于在一个环境中的好几个 display:block 的元素所产生的相互影响的原理和表现。

比较专业的说法就是:它能把一个集合中的 float, margin, clear 等等的各种元素包裹,形成的一个集合就为 BFC , BFC 中的任何都不会对 BFC 外的元素产生影响。
通俗地来说:创建了 BFC 的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素,反之亦然,同时 BFC 仍然属于文档中的普通流。
在普通流( Normal flow )中,在创建了块格式化上下文的元素中的子元素都会按照块格式化上下文提供的规矩来排列自己,除非自己也创建一个新的块格式化上下文。

如何触发块级格式化上下文(BFC)?

    float:left|right ,除了none
    overflow:hidden|auto|scroll(也就是除了overflow:visible;)
    position: absolute|fixed
    display:inline-block|table-cell|table
    fieldset 元素
    表格的单元格(display: table-cells,TD、TH)
    表格的标题(display: table-captions,CAPTION)
    表格元素创建的 “匿名框” 。(display:table 之后创建的匿名框 http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes)

虽然 IE6 7 不支持 BFC,但是在他们中有一个类似的概念 hasLayout。触发hasLayout的条件:

    position: absolute 
    float: left|right 
    display: inline-block 
    width: 除 “auto” 外的任意值 
    height: 除 “auto” 外的任意值 (例如很多人清除浮动会用到 height: 1%  ) 
    zoom: 除 “normal” 外的任意值 (MSDN)
    writing-mode: tb-rl (MSDN)
  在 IE7 中,overflow 也变成了一个 layout 触发器:
    min-width:任何值
    min-height:任何值
    max-width:除了none之外的任何值
    max-height:除了none之外的任何值
    overflow: hidden|scroll|auto ( 这个属性在IE之前版本中没有触发 layout 的功能。 )
    overflow-x|-y: hidden|scroll|auto (CSS3 盒模型中的属性,尚未得到浏览器的广泛支持。他们在之前IE版本中同样没有触发 layout 的功能)

其他一些知识点,请参考引用文章中的那几篇引用文章。

如论如何,还是不习惯 Ubuntu 的 Unity 桌面,捉摸着怎么将此桌面换成之前熟悉的 Gnome 呢,搜了一大圈互联网,终于在这篇文章里面找到了方法,试了试,还不错,只是没有删除 Unity 的方法,不过这个并不重要,删不删都无所谓。

稍微翻一下,以后用得着,别人也可以用。

1. 先安装 Gnome Packages。

打开终端,输入

sudo apt-get install ubuntu-gnome-desktop ubuntu-gnome-default-settings

此时如果出现选择 GDM 或者是 LightGDM 的话,请选择 GDM。

如果,你已经使用了 GDM 或者系统没有出现选择设置的界面,或者你选择了使用 LightGDM 的话,那么你可以使用下面的命令来重新设置。

sudo dpkg-reconfigure gdm

当然,不是非要一定使用 GDM 的,也可以使用 LightGDM 但是这样就不能体验完整的 Gnome 3 了。

同时,最好可以将 ubuntu-setting 这个包给删除掉(我没有删除,用的没有问题)。至于这个包是干嘛的,这里就不翻译了,反正说的是删不删对使用都没有影响。不过删除了之后,某些 ubuntu 默认的设置就会被改变,例如窗口的按钮顺序, Rhythmbox 插件也是靠这个包来启用的。

这样就完了,接下来的是可选的步骤。

2. 安装一些其它的 Ubuntu 的包,例如 GNOME Documents 和 Boxes(做了这一步,但是基本没用,我也不知道干嘛的)。

sudo apt-get install gnome-documents gnome-boxes

注:因为一个 bug boxes 只在 64位上才可用,32位这里就不要装了。

3. 更新 GNOME Control Center, Nautilus, Totem 以及其他的 GNOME 3 packages 到 3.6.x(这一步也没有做)

不过要先加一个 PPA 才行。

sudo add-apt-repository ppa:gnome3-team/gnome3

然后请遵循这个文章,或者用系统更新来安装。

如果安装了 PPA 之后,有些包将会被更新为: GNOME Control Center 3.6.3, Aisleriot 3.6.0, Brasero 3.6.0, Nautilus 3.6.3 以及 Totem 3.6.2.这个 PPA 同样提供了 Transmission 0.7.1, Transmageddon 0.23 以及 Sound Juicer 3.5.0(至于这些软件都是干嘛的,我也不知道,我没有用,没有做到这一步,也就没有更新)。

4. 删除 overlay scrollbars(这一步也没有做)
到这一步,基本就完成了,但是这里使用的还不是 Gnome 的 overlay scrollbars 而是 Ubuntu 自己的,所以通过下面的命令,将 Ubuntu 自己的 overlay scrollbars 删掉,从而使用 Gnome 3 的。

5. 然后就是重启了,当然注销也可以,只是注销看不到登陆界面的效果。

回调与作用域

在前面的例子中,执行回调的函数一般都如下所示:

    a(b);

而回调一般都如下所示:

    b(parameters);

这在一般情况下都可以正常的工作,但在某些时候,回调并不仅仅是单一的函数,而是某个对象的方法,并且如果该回调使用 this 来引用其所属的对象的话,就会导致错误发生。

假如有一个 add 的回调函数,它是 app 对象的一个方法:

	var app = {};  
	app.number = 1;  
	app.add = function (n) {  
		n = n + this.number;  
	};

makeArray 函数做了类似下面的事:

var makeArray = function (callback) {  
	// ...  
	if (typeof callback === "function") {  
		callback(i);  
	}  
	// ...  
};

调用

makeArray(app.add);

当调用的时候,它并不能按照预期的那样工作,因为 this.number 将会是 undefined。这里 this 将会指向全局对象,因为 makeArray 是一个全局函数。

如果 makeArray 是某个对象的方法,那么在回调函数中的 this 将会指向这个对象而不是期望的 app。(详情请了解下 javascript 中的 this)

解决这个问题的方法就是传递一个回调函数,此外再传递这个回调函数属于的对象作为一个参数:

makeArray(app.add, app);

紧跟着,我们需要去修改 makeArray 去绑定(bind)传递进来的对象:

var makeArray = function (callback, callback_obj) {  
	//...  
	if (typeof callback === "function") {  
		callback.call(callback_obj, i);  
	}  
	// ...  
};

对于传递一个对象和一个被用来回调的方法,另一个可选的方法就是将方法作为字符串传递,那么你就不会重复对象两次。换言之:

makeArray(app.add, app);

会变成:

makeArray("add", app);

那么 makeArray 将会变为如下面几行所示:

var makeArray = function (callback, callback_obj) {  
	if (typeof callback === "string") {  
		callback = callback_obj[callback];  
	}  
	//...  
	if (typeof callback === "function") {  
		callback.call(callback_obj, i);  
	}  
	// ...  
};

匿名的事件监听器

回调模式在日常中被经常使用,比如,当你附加一个事件监听器给页面上的某个元素时,你实际上提供了一个指向了回调函数的引用,并且在事件发生时被调用。

这里有个例子,怎么将 console.log() 作为一个回调函数监听文档的 click 事件:

	document.addEventListener("click", console.log, false);

绝大部分客户端浏览器都是事件驱动的(event-driven),当一个页面加载完成,会触发load事件,然后用户可以通过和页面交互触发各种各样的事件,比如:click, keypress, mouseover, mousemove等等,因为回调模式,JavaScript特别适合事件驱动编程,能让你的程序异步的工作,换言之,就是不受顺序限制。

在异步的事件驱动的JavaScript,可以提供一个回调函数用于在正确的时候被调用;有时候甚至可能提供比实际请求还要多的回调函数,因为某些事件可能不会发生,比如:如果用户不点击“购买”按钮,那么你用于验证表单格式的函数永远不会被调用。

定时

另一个使用回调模式的例子就是使用浏览器的window对象的setTimeout()和setInterval()方法,这些方法也可以接受和执行回调函数:

	var thePlotThickens = function () {  
		console.log('500ms later...');  
	};  
	setTimeout(thePlotThickens, 500);

再次注意一下,thePlotThickens 是如何被作为一个参数传递的,注意这里仍旧没有使用括号,因为你不想它立即执行,传递字符串 “thePlotThickens()” 取代函数的引用和eval()类似,是不好的模式。

当然可以提供匿名函数的方式进行调用。

	setTimeout(function(){thePlotThickens()}, 500);

回调

在 javascript 中,函数都是对象,这也就表明了他们也可以被作为参数,从而传递给其他函数。例如,将函数 a() 作为参数传递给 b() 时,那么,在某一时刻 b() 可能会执行或者说调用 a(); 在这种情况下,a() 就被称作毁掉函数(callback function),也可简称为回调(callback)。

代码示例:

    function b(callback) {
        // do something
        callback();
    }

    function a() {
        // do something
    }

    b(a);

这里需要注意的是,在 b(a) 中,作为参数的 a 函数,是不带括号的,括号表示要执行(此函数),而此处只需要将 a 函数传递给 b 函数,让 b 函数在适当的时候,加上括号调用它即可。

注:可以使用 火狐,或者谷歌的 javascript 控制台,如果调用 console.log(a) 的话,就会得到 a 的函数的定义代码,而前面说了括号表示要执行,所以加上括号之后,表示要执行 a 函数的代码,a 其实只是一个名字而已。

代码改写示例

首先不使用回调的方式来定义两个函数,然后使用回调的方式重构这两个函数。

使函数具有通用的,单一功能的行为,这是非常好的思想,可以对函数的功能一目了然,阅读和修改也更方便。下面两个函数都是用这种思想来定义。

makeArray 函数用来生成一个大数组,并且返回这个大数组。

    var makeArray = function () {
        var i     = 100000,
            array = [];
        while (i) {
            i --;
            array.push(i);
        } 
        return array;
    }

arrayPlus 函数的功能只对数组的元素进行处理。

    var arrayPlus = function (array) {
        var i   = 0,
            max = array.length;
        for(; i < max; i++) {
            console.log(array[i] + 1);
        }
    }

执行这两个函数

    arrayPlus(makeArray());  // 生成数组,并给所有的数字元素 +1 再返回此数组

函数达到了我们的目的,但是对于客户端 javascript 来说,性能在一定程度上也是至关重要的,但是上面的实现是比较低效率的,因为生成数组的 makeArray 有一遍大循环,而处理数组元素的 arrayPlus 函数,做了同样的一遍大循环。如果将 makeArray 中的 array.push(i); 改为 array.push(i+1); 即可,这样是高效的,但是这样生成数组和处理数组高度耦合,其并不再是一个通用的具有单一功能的函数,不符合我们的思想。

那么我们尝试使用回调的方式来重构

    var makeArray = function (callback) {
        var i     = 100000,
            array = [];
        while (i) {
            i --;
            if(typeof callback === 'function'){
                callback(i);
            }
            array.push(i);
        } 
        return array;
    }

    var arrayPlus = function (n) {
        console.log(++n);
    }

重构之后的代码,makeArray 唯一额外的任务是要检查是否有提供回调函数,如果有则执行,如果没有则不执行,并没有破坏原来 makeArray 函数的功能,makeArray 仍然可以像以前一样使用。而 arrayPlus 则变得更加简单。

调用,执行即可

    makeArray(arrayPlus);  // 注意和重构前的调用对比

对于回调函数来说,可以是已经定义好的函数,也可以是匿名函数,在调用主函数时创建回调函数,例如:

    makeArray(function(n){
       console.log(++n); 
    });

主题名称: wSpring 系列 Insects Awaken / 惊蛰
主题链接: https://yimity.com/2013/03/15/wordpress-free-theme-insects-awaken.html
主题描述: Insects Awaken. 单栏主题,支持后台选项,包括自定义站点统计,页面上部背景自主更换,是否显示头像以及阅读模式和浏览模式的切换,SEO 友好,支持自定义菜单,支持IE8以上,及 Chrome,Firefox,Opera等现代浏览器。不需要任何插件支持。
主题版本: 1.0
主题作者: 一米
发布日期:03月15日。
主题预览:https://yimity.com/
灵感来源:http://www.diandian.com/themes/110/show 咖啡因折页,感谢。
介绍:
Insects Awaken. 单栏主题,支持后台选项,包括自定义站点统计,页面上部背景自主更换,是否显示头像以及阅读模式和浏览模式的切换,SEO 友好,支持自定义菜单,支持IE8以上,及 Chrome,Firefox,Opera等现代浏览器。不需要任何插件支持。即使 JS 加载失败,功能同样正常可用。文章样式已经定义好,几乎所有的文章发表即可正常显示。支持 10 种文章格式。只支持多说评论系统。请使用多说的 WordPress 插件,后台有说明。全站 placeholder 支持。极度个性化的 404 页面。

Read more…

接上一篇

1. 进入 SVN 的 hooks 目录

cd /home/svn/node/hooks

2. 新建post-commit文件

3. 输入以下内容

#!/bin/sh
REPOS=$1
REV=$2
time=`date "+%Y-%m-%d %H:%M:%S"`
export LANG=C.UTF-8

# 当用户提交的时候注释里包含 auto_deploy 字符串的时候才发布到 web 目录
if (/usr/local/svn/bin/svnlook log -r $REV /home/svn/node/ | grep "auto_deploy")
then
echo "start deploy $time" >> /tmp/svn_autocommit.log
/usr/local/svn/bin/svn export --username yimity --password ******* "svn://127.0.0.1" /home/wwwroot/ajax --force --no-auth-cache
fi

为了不使每次提交之后都发布,所以判断下 只有在提交的注释中包含 auto_deploy 时,才发布。
注意其中的 /usr/local/svn/bin/ 和 /home/svn/node/ 以及 /home/wwwroot/ajax 这三个路径,第一个是安装 svn 的路径,上一篇有讲,第二个是 svn 的版本库目录,第三个是网站服务器目录,至于 svn://127.0.0.1 这个则是 svn 的访问目录了,也可以是外部地址,即:工作电脑获取的地址。
注意 export LANG=C.UTF-8 请看问题 2 字符集。

4. 修改权限

chmod +x post-commit

保存,在本地修改保存提交试试看。

出现错误:
1. Store password unencrypted
进入

vi /home/root/.subversion/servers

将所有的

# store-plaintext-passwords = no

改成

# store-plaintext-passwords = yes

即可

2. 字符集
使用

locale -a

查看系统字符集,如我的 VPS 只有

C
C.UTF-8
POSIX

所以设置成 zh_CN.UTF-8 就会出错

然后设置 3 中的

export LANG=C.UTF-8

修改为

export LANG=系统列出来的字符集的名字

3. 权限
如果新建了不同的组和用户(非 root),权限问题的话,肯定应该会有,比较复杂,这里不多说了。

参考:http://blog.51yip.com/server/901.html 以及 http://www.wp1998.net/2012/834.html