二月 26, 2011
by 小寒
1 comment
介绍
minify是一个基于php的开源项目,用它可以合并多个JS与CSS的请求。
下载与安装
下载链接:http://code.google.com/p/minify/
将下载下来的压缩包解压缩,将里面的min目录放到网站的根目录下。打开min目录修改里面的config.php文件,将$min_serveOptions['minApp']['maxFiles'] = 10;的值改大一些,这个参数表示一次请求最多可以合并多少个文件,因为YUI的细粒度很高,所以一次请求的模块文件很多,默认值10显然不够。同时将$min_cachePath = ‘/tmp’;这行的注释去掉,可以提升性能。
完成上面的步骤可以在浏览器测试一下,我机器的测试地址是http://localhost:8086/min/?f=/build/oop/oop.js,/build/event-custom/event-custom.js
注意服务器要开启mod_rewrite模块
改造YUI loader
因为YUI loader构造的请求地址是类似http://yui.yahooapis.com/combo?3.3.0/build/classnamemanager/classnamemanager-min.js&3.3.0/build/oop/oop-min.js&3.3.0/build/event-custom/event-custom-min.js&3.3.0/build/event/event-base-min.js&3.3.0/build/pluginhost/pluginhost-min.js&3.3.0/build/dom/dom-min.js&3.3.0/build/node/node-min.js&3.3.0/build/event/event-delegate-min.js&3.3.0/build/attribute/attribute-base-min.js&3.3.0/build/base/base-base-min.js&3.3.0/build/plugin/plugin-min.js&这样的,URL没有参数名,每个JS文件用”&”号分隔。而minify的地址格式是http://localhost:8086/min/?f=/build/oop/oop.js,/build/event-custom/event-custom.js,可以看出minify的请求地址用’f'当作参数名,每个JS地址用”,”号分隔。所以要对YUI loader进行一下改造,让它可以构造出符合minify格式的请求地址。
进入到YUI的build/loader文件夹,将loader.js备份一下,之后编辑loade.js,找到如下行:
url += frag;
if (i < (len - 1)) {
url += '&';
}
替换成下面的代码
//fixed YUI 3.1.0 combo bug
//http://yuilibrary.com/projects/yui3/ticket/2528680
if(url.slice(-3) ==='.js' || url.slice(-4) === '.css'){
//for K2
//使用Minfy 取代 Combo Handler
//url += '&';
url += ',';
}
url += frag;
// there is a bug that combo?a.css&b.css&
/*
if (i < (len - 1)) {
url += '&';
}
*/
在YUI使用minify
做完上面的工作之后,就可以在YUI中使用自己的combine服务了。在实例化YUI的时候加上如下的配置项:
YUI({
combine: true,
comboBase: '/min/?b=build&f=',
root: ''
}).use('placeholder', function(Y) {
Y.all('.test').plug(Y.Plugin.Placeholder);
});
JavaScript
二月 16, 2011
by 小寒
3 comments
// 定义:计算n的阶乘,并把结果传到con中
function fac(n, con) {
if(n <= 1) {
// 直接将1传到con中,并执行
con(1);
} else {
// 调用:求解n-1的阶乘
arguments.callee(n - 1, function(r) {
// 将n-1阶乘的结果与n相乘
con(n * r);
});
}
}
// 调用:计算5的阶乘
fac(5, function(r) {
console.debug(r);
});
JavaScript
一月 13, 2011
by 小寒
3 comments
学习了一下Nodejs和MongoDB,写了个示例程序,读取数据库中产品的列表。
var http = require("http"),
mongo = require("mongodb"),
events = require("events");
http.createServer(function(req, res) {
var products_emitter = new events.EventEmitter(),
// 创建到northwind数据库的链接。相当于use northwind
db = new mongo.Db("northwind", new mongo.Server('localhost', 27017, {}), {});
var listener = function(products) {
var html = [], len = products.length;
html.push('<!DOCTYPE html>');
html.push('<html>');
html.push('<head>');
html.push('<title>Nodejs</title>');
html.push('</head>');
html.push('<body>');
if(len > 0) {
html.push('<ul>');
for(var i = 0; i < len; i++) {
html.push('<li>' + products[i].name + '</li>');
}
html.push('</ul>');
}
html.push('</body>');
html.push('</html>');
res.writeHead(200, "Content-Type: text/html");
res.write(html.join(''));
res.end();
clearTimeout(timeout);
}
products_emitter.on('products', listener);
var timeout = setTimeout(function() {
products_emitter.emit('products', []);
products_emitter.removeListener('products', listener);
}, 10000);
db.open(function() {
// 打开名为products的表
db.collection("products", function(err, collection) {
// select * from products 相当于db.products.find()
collection.find(function(err, cursor) {
cursor.toArray(function(err, items) {
products_emitter.emit('products', items);
});
});
});
});
}).listen(8000);
console.log("Started");
JavaScript
十二月 29, 2010
by 小寒
0 comments
从新浪的库上copy下来的操作textarea的工具函数,用做学习研究目的。
App.TextareaUtils = (function () {
var it = {},
ds = document.selection;
it.selectionStart = function (oElement) {
if (!ds) {
return oElement.selectionStart
}
var er = ds.createRange(),
value, len, s = 0;
var er1 = document.body.createTextRange();
er1.moveToElementText(oElement);
for (s; er1.compareEndPoints("StartToStart", er) < 0; s++) {
er1.moveStart("character", 1)
}
return s
};
it.selectionBefore = function (oElement) {
return oElement.value.slice(0, it.selectionStart(oElement))
};
it.selectText = function (oElement, nStart, nEnd) {
oElement.focus();
if (!ds) {
oElement.setSelectionRange(nStart, nEnd);
return
}
var c = oElement.createTextRange();
c.collapse(1);
c.moveStart("character", nStart);
c.moveEnd("character", nEnd - nStart);
c.select()
};
it.insertText = function (oElement, sInsertText, nStart, nLen) {
oElement.focus();
nLen = nLen || 0;
if (!ds) {
var text = oElement.value,
start = nStart - nLen,
end = start + sInsertText.length;
oElement.value = text.slice(0, start) + sInsertText + text.slice(nStart, text.length);
it.selectText(oElement, end, end);
return
}
var c = ds.createRange();
c.moveStart("character", -nLen);
c.text = sInsertText
};
it.getCursorPos = function (obj) {
var CaretPos = 0;
if ($IE) {
obj.focus();
var range = null;
range = ds.createRange();
var stored_range = range.duplicate();
stored_range.moveToElementText(obj);
stored_range.setEndPoint("EndToEnd", range);
obj.selectionStart = stored_range.text.length - range.text.length;
obj.selectionEnd = obj.selectionStart + range.text.length;
CaretPos = obj.selectionStart
} else {
if (obj.selectionStart || obj.selectionStart == "0") {
CaretPos = obj.selectionStart
}
}
return CaretPos
};
it.getSelectedText = function (obj) {
var selectedText = "";
var getSelection = function (e) {
if (e.selectionStart != undefined && e.selectionEnd != undefined) {
return e.value.substring(e.selectionStart, e.selectionEnd)
} else {
return ""
}
};
if (window.getSelection) {
selectedText = getSelection(obj)
} else {
selectedText = ds.createRange().text
}
return selectedText
};
it.setCursor = function (obj, pos, coverlen) {
pos = pos == null ? obj.value.length : pos;
coverlen = coverlen == null ? 0 : coverlen;
obj.focus();
if (obj.createTextRange) {
var range = obj.createTextRange();
range.move("character", pos);
range.moveEnd("character", coverlen);
range.select()
} else {
obj.setSelectionRange(pos, pos + coverlen)
}
};
it.unCoverInsertText = function (obj, str, pars) {
pars = (pars == null) ? {} : pars;
pars.rcs = pars.rcs == null ? obj.value.length : pars.rcs * 1;
pars.rccl = pars.rccl == null ? 0 : pars.rccl * 1;
var text = obj.value,
fstr = text.slice(0, pars.rcs),
lstr = text.slice(pars.rcs + pars.rccl, text == "" ? 0 : text.length);
obj.value = fstr + str + lstr;
this.setCursor(obj, pars.rcs + (str == null ? 0 : str.length))
};
return it
})();
JavaScript
十一月 19, 2010
by 小寒
0 comments
默认情况下,Chrome下面的最小字体为12px,想要突破这个限制只要在css里面加入-webkit-text-size-adjust: none就好了。
CSS
十月 30, 2010
by 小寒
0 comments
对新浪微博OAuth认证的一点备忘,不求别人能看明白,只希望自己以后还能看懂……
第一步,通过已知的consumer key和consumer secret获取request token以及request token secret。
private function getRequestToken(){
$output = $this->OAuthGet(self::$REQUEST_TOKEN, NULL);
$token = OAuthUtil::parse_parameters($output);
return new OAuthToken($token['oauth_token'], $token['oauth_token_secret']);
}
这里的$REQUEST_TOKEN为http://api.t.sina.com.cn/oauth/request_token,这个方法不用提供给外部调用,所以可以声明为私有方法。
第二步,获取第一步传回的request token,然后引导用户前往新浪认证页面,认证成功后会返回oauth_verifier。
public function GetAuthorization() {
$token = $this->getRequestToken();
$result->Url = self::$AUTHORIZE . "?oauth_token={$token->key}";
$result->Token = $token;
return $result;
}
第二步中的$AUTHORIZE为http://api.t.sina.com.cn/oauth/authorize,即认证页面。其中返回的$result->Url加上oauth_callback参数用来做302跳转,而$result->Token要保存起来(可以存到session中)以便在第三步使用。例如:
$info = $oauth->GetAuthorization();
$_SESSION['request_token'] = $info->Token;
header("Location: {$info->Url}&oauth_callback=" . urlencode(CALLBACK_URL . '?ret=' . $_SERVER['REQUEST_URI']));
第三步,用户在第二步中http://api.t.sina.com.cn/oauth/authorize认证成功之后,新浪会带上oauth_verifier参数再跳转一次,地址是由上一步oauth_callback参数指定的。这一步会连同第一步返回的request token和request token secret以及第二步返回的oauth_verifier做最后一次认证,通过之后返回access token和access token secret,这对密钥可以用来访问受限的资源,认证流程到此结束。
public function GetAccessToken($token, $verifier) {
$output = $this->OAuthGet(self::$ACCESS_TOKEN . "?oauth_verifier=$verifier", $token);
$token = OAuthUtil::parse_parameters($output);
return new OAuthToken($token['oauth_token'], $token['oauth_token_secret']);
}
第三步认证其实是在上一步oauth_callback参数指定的地址中进行的,其中$ACCESS_TOKEN为http://api.t.sina.com.cn/oauth/access_token。
PHP
九月 27, 2010
by 小寒
1 comment
function PageQuery(q) {
if (q.length > 1) this.q = q.substring(1, q.length);
else this.q = null;
this.keyValuePairs = new Array();
if (q) {
for (var i = 0; i < this.q.split("&").length; i++) {
this.keyValuePairs[i] = this.q.split("&")[i];
}
}
this.getKeyValuePairs = function () { return this.keyValuePairs; }
this.getValue = function (s) {
for (var j = 0; j < this.keyValuePairs.length; j++) {
if (this.keyValuePairs[j].split("=")[0] == s)
return this.keyValuePairs[j].split("=")[1];
}
return false;
}
this.getParameters = function () {
var a = new Array(this.getLength());
for (var j = 0; j < this.keyValuePairs.length; j++) {
a[j] = this.keyValuePairs[j].split("=")[0];
}
return a;
}
this.getLength = function () { return this.keyValuePairs.length; }
}
function queryString(key) {
var page = new PageQuery(window.location.search);
return unescape(page.getValue(key));
}
JavaScript
八月 30, 2010
by 小寒
2 comments
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>主页面</title>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
}
body {
}
#div1 {
height: 2000px;
}
#floatedLayer {
position: fixed;
_position: absolute;
}
</style>
</head>
<body>
<div id="floatedLayer">
<iframe src="demo.html" width="580" height="542" frameborder="no"></iframe>
</div>
<div id="div1"></div>
<script type="text/javascript">
var floatedLayer = document.getElementById("floatedLayer");
function adjustPopupWin() {
var height = document.documentElement.clientHeight,
width = document.documentElement.clientWidth;
floatedLayer.style.left = Math.max((width - floatedLayer.offsetWidth) / 2, 0) + "px";
floatedLayer.style.top = Math.max((height - floatedLayer.offsetHeight) / 2, 0) + "px";
}
</script>
<!--[if IE 6]>
<script type="text/javascript">
function adjustPopupWin() {
var height = document.documentElement.clientHeight,
width = document.documentElement.clientWidth;
floatedLayer.style.left = Math.max((width - floatedLayer.offsetWidth) / 2, 0) + document.documentElement.scrollLeft + "px";
floatedLayer.style.top = Math.max((height - floatedLayer.offsetHeight) / 2, 0) + document.documentElement.scrollTop + "px";
}
window.onscroll = adjustPopupWin;
</script>
<![endif]-->
<script type="text/javascript">
window.onresize = adjustPopupWin;
adjustPopupWin();
</script>
</body>
</html>
CSS, HTML, JavaScript