[code="java"]
判断js数组包是否包含某个元素
要判断数组中是否包含某个元素,从原理来来说,就是遍历整个数组,然后判断是否相等,我们来造个轮子,名字就山寨PHP的数组函数in_array()

view sourceprint?
1 Array.prototype.in_array = function(e)

2 {

3 for(i=0;i<this.length;i++)

4 {

5 if(this[i] == e)

6 return true;

7 }

8 return false;

9 }
或者

view sourceprint?
1 Array.prototype.in_array = function(e)

2 {

3 for(i=0;i<this.length && this[i]!=e;i++);

4 return !(i==this.length);

5 }
Filed under: JavaScript Array 发表评论 判断一个元素(对象)是否为另一个元素的子元素
js通过contains和compareDocumentPosition方法来确定DOM节点间的关系,判断一个元素(对象)是否为另一个元素的子元素

首先自己写一个:

view sourceprint?
1 function isParent(obj,pobj){

2 do{

3 obj = obj.parentNode;

4 if(obj==pobj){

5 return true;

6 }

7 }while(obj.tagName!='BODY');

8 return false;

9 }
Filed under: JavaScript 未分类 发表评论 js通过classname来获取元素
原生JS有3种方式来获取元素:

getElementById('id')
getElementsByName('name')
getElementsByTagName('tag')
getElementById是获取元素最快的方式,但我们不能给每个HTML元素都加以ID吧,所以我们需要一个很方便的通过classname来获取元素:

view sourceprint?
01 function getElementsByClassName(className,tagName){

02 var ele=[],all=document.getElementsByTagName(tagName||"*");

03 for(var i=0;i<all.length;i++){

04 if(all[i].className==className){

05 ele[ele.length]=all[i];

06 }

07 }

08 return ele;

09 }

10 console.log(getElementsByClassName("entry"));

11 console.log(getElementsByClassName("entry","div"));
Filed under: JavaScript className 前端开发 发表评论 jQuery hasClass(),jQuery判断元素是否含有className
jQuery中的hasClass(selector)

返回值

Boolean

参数

class (String) : 用于匹配的类名,注意不需要加"."

检查当前的元素是否含有某个特定的类,如果有,则返回true。

这其实就是 is("." + class)。我们看下源代码:

view sourceprint?
1 function (selector) {

2 return this.is("." + selector);

3 }
Filed under: jQuery javaScript className 发表评论 返回两个数组中不同的元素,求数组反集
有两个数组

view sourceprint?
1 var a=['1','2','3','4']

2 var b=['1','2']
如何比较才能返回两个数组中不同的元素,其实就是求两个数组的反集,得到数组c=['3','4']

基本的算法就是比较两个数组的元素,把不同的挑出来放到一个数组里,最后返回该Array

我在上一篇文章中山寨了一个JS版的in_array函数
Filed under: JavaScript Array 发表评论 jquery.add()追加元素
我们先来看下jQuery官方文档上add()方法的使用

1)add(expr) 在原对象的基础上再附加符合指定表达式的jquery对象

2)add(el) 在匹配对象的基础上再附加指定的dom元素。

3)add(els) 在匹配对象的基础上再附加指定的一组对象,els是一个数组。

4)add(html)在匹配对象的基础上再附加指定的一段HTML片段
Filed under: 前端开发, jQuery add 发表评论 jQuery获得元素位置
jquery 中有两个获取元素位置的方法offset()和position(),这两个方法之间有什么异同

offset():

获取匹配元素在当前视口的相对偏移。

返回的对象包含两个整形属性:top 和 left。此方法只对可见元素有效。

.offset()方法可以让我们重新设置元素的位置。这个元素的位置是相对于document对象的。如果对象原先的position样式属性是 static的话,会被改成relative来实现重定位。

position():

获取匹配元素相对父元素的偏移。
Filed under: jQuery 绝对定位 offset 发表评论 javascript获取Dom节点元素
在前端开发中,经常要通过JavaScript来获取页面中某个DOM元素,然后更新该元素的样式、内容等。如何获取要更新的元素,是首先要解决的问题。令人欣慰的是,使用JavaScript获取DOM节点的方法有很多种,这里简单做一下总结:

1. 通过顶层document节点获取:
Filed under: JavaScript DOM 发表评论 原生JavaScript给元素增加className
jquery的addClass如何用原生javascript实现?

class是元素的属性,所以我们可以通过setAttribute来获取class

这里需要注意的是class在IE中是保留关键字

所以我们获取某个元素的class时需要用className来代替class

className在所有浏览器中都兼容

view sourceprint?
1 ele.getAttribute("className");//IE

2 ele.getAttribute("class");//非IE浏览器

3 ele.setAttribute("className","类名");//IE
Filed under: JavaScript cssClass 发表评论 jQuery替换element元素上已经绑定的事件
jQuery如何重新绑定已经绑定的事件?虽然我们现在推荐行为分离,渐进增强,但在很多遗留系统里还是存在很多这样的代码

view sourceprint?
1 <input type="button" value="ClickMe" id="btn1" οnclick="foo()" />
就是直接在DOM元素上绑定事件

这样做有很多缺点

1.代码高度耦合

2.增加HTML大小

3.书写不了逻辑性很强的代码
Filed under: jQuery unbind bind event JavaScript事件 发表评论 JQuery 获取,遍历和操作表单元素Select,checkbox,radio

是的方式的发

Filed under: jQuery 发表评论 magento查看用户是否登录
在magento中有些功能是需要用户登录之后才可以展示给客户看到.在magento中用户登录是放在session中的 如果要查看用户是否登录来控制权限可以这样用

view sourceprint?
1 if (!Mage::getSingleton("customer/session")->isLoggedIn()) {

2 // 客户没有登录,这里输入处理流程.

3 }
注意前面有个感叹号。。

我们可以在controller中实现,如果用户没有登录,就跳转到登录页面去

view sourceprint?
1 if (!Mage::getSingleton("customer/session")->isLoggedIn())

2 {

3 $session = Mage::getSingleton("customer/session");

4 $customerLoginURL = $this->getBaseUrl() . "customer/account/login";

5 Mage::app()->getFrontController()->getResponse()->setRedirect($customerLoginURL)->sendResponse();

6 }
Filed under: Magento controller 会员 发表评论 js框架jRaiser源代码

view sourceprint?
0001 /*

0002 * jRaiser Javascript Library v1.3.3

0003 * http://code.google.com/p/jraiser/

0004 *

0005 * Copyright 2008-2010 Heero.Luo (http://heeroluo.net/)

0006 * licensed under a modified MIT license

0007 * For detail, see http://code.google.com/p/jraiser/wiki/license

0008 *

0009 * Creation date: 2008/2/6

0010 * Modified date: 2010/4/29

0011 */

0012 (function(window, undefined) {

0013 var version = "1.3.3 Build 201004291430", // 版本号

0014 globalName = "jRaiser"; // 全局标识符

0015 // 防止重复加载

0016 if (window[globalName] && window[globalName].version >= version) { return; }

0017 var _$ = window.$, // 记录当前框架,以便恢复

0018 document = window.document,

0019 /// @overload 根据CSS选择器和上下文匹配出HTML元素

0020 /// @param {String} CSS选择器

0021 /// @param {HTMLElement,Array,HTMLCollection} 上下文

0022 /// @return {HTMLElement,Array} 匹配到的经扩展的HTML元素

0023 /// @overload 扩展HTML元素

0024 /// @param {HTMLElement,Array,HTMLCollection} 要扩展的Html元素

0025 /// @return {HTMLElement,Array} 经扩展的HTML元素

0026 jRaiser = window[globalName] = window.$ = function(selector, context) {

0027 if (!selector) { return selector; }

0028 "string" === typeof selector && (selector = getElemsBySelector(selector, context));

0029 return extendElems(selector);

0030 };

0031 /// 根据上下文及CSS选择器获取结果集中的第一个元素

0032 /// @param {String} CSS选择器

0033 /// @param {HTMLElement,Array,HTMLCollection} 上下文

0034 /// @return {HTMLElement} 匹配到的经扩展的HTML元素

0035 jRaiser.one = function(selector, context) {

0036 return extendElems(getElemsBySelector(selector, context, 1));

0037 };

0038 /// 根据上下文及CSS选择器获取所有元素

0039 /// @param {String} CSS选择器

0040 /// @param {HTMLElement,Array,HTMLCollection} 上下文

0041 /// @return {Array} 匹配到的经扩展的HTML元素数组

0042 jRaiser.all = function(selector, context) {

0043 return extendElems(getElemsBySelector(selector, context, 0));

0044 };

0045 // 根据上下文及CSS选择器获取HTML元素

0046 // @param {String} CSS选择器

0047 // @param {HTMLElement,Array,HTMLCollection} 上下文

0048 // @param {Number} 结果集数量限制:默认返回原结果;为1时只返回第一个元素;为0时把结果按数组形式返回

0049 // @return {HTMLElement,Array} 匹配到的经扩展的HTML元素

0050 function getElemsBySelector(selector, context, limit) {

0051 // 通过选择器解析引擎获取元素

0052 var result = selectorQuery.exec(selector, context || document);

0053 if (limit !== undefined) {

0054 if (result) {

0055 var isArray = jRaiser.util.isArray(result);

0056 if (1 === limit && isArray) {

0057 return result[0];

0058 } else if (0 === limit && !isArray) {

0059 return [result];

0060 }

0061 } else if (0 === limit) {

0062 return [];

0063 }

0064 }

0065 return result;

0066 }

0067 // 扩展HTML元素(数组)

0068 // @param {HTMLElement,Array,HTMLCollection} 元素(数组)

0069 // @return {HtmlElement,Array} 扩展后的元素

0070 function extendElems(elems) {

0071 if (elems && !elems[globalName]) {

0072 if (elems.nodeType) { // 扩展Html元素和非IE下的XML元素

0073 if ("unknown" !== typeof elems.getAttribute) {

0074 for (var p in jRaiser.element) {

0075 // 不覆盖原有的属性和方法

0076 undefined === elems[p] && (elems[p] = jRaiser.element[p]);

0077 }

0078 }

0079 } else { // HTMLCollection Or Array

0080 elems = jRaiser.util.extend(jRaiser.util.toArray(elems), jRaiser.element);

0081 }

0082 }

0083 return elems;

0084 }

0085 /// 标识当前版本

0086 jRaiser.version = version;

0087 /// 恢复本类库对$和jRaiser全局变量的占用

0088 /// @return {Object} jRaiser对象

0089 jRaiser.resume = function() {

0090 _$ = window.$;

0091 window.$ = window[globalName] = jRaiser;

0092 return jRaiser;

0093 };

0094 /// 恢复最近一次本类库加载前或jRaiser.resume方法调用前的$变量

0095 /// @return {Mixed} 原$变量

0096 jRaiser.retire = function() {

0097 window.$ = _$;

0098 return _$;

0099 };

0100 // 用于特性检查的元素

0101 var testElem = document.createElement("div");

0102 testElem.innerHTML = "<p class='TEST'></p>";

0103 // selectorQuery选择器解析引擎

0104 var selectorQuery = {

0105 SPACE : /\s*([\s>~+,])\s*/g, // 用于去空格

0106 ISSIMPLE : /^#?[\w\u00c0-\uFFFF_-]+$/, // 判断是否简单选择器(只有id或tagname,不包括*)

0107 IMPLIEDALL : /([>\s~\+,]|^)([#\.\[:])/g, // 用于补全选择器

0108 ATTRVALUES : /=(["'])([^'"]*)\1]/g, // 用于替换引号括起来的属性值

0109 ATTR : /\[\s*([\w\u00c0-\uFFFF_-]+)\s*(?:(\S?\=)\s*(.*?))?\s*\]/g, // 用于替换属性选择器

0110 PSEUDOSEQ : /\(([^\(\)]*)\)$/g, // 用于匹配伪类选择器最后的序号

0111 BEGINIDAPART : /^(?:\*#([\w\u00c0-\uFFFF_-]+))/, // 用于分离开头的id选择器

0112 STANDARD : /^[>\s~\+:]/, // 判断是否标准选择器(以空格、>、~或+开头)

0113 STREAM : /[#\.>\s\[\]:~\+]+|[^#\.>\s\[\]:~\+]+/g, // 用于把选择器表达式分离成操作符/操作数 数组

0114 ISINT : /^\d+$/, // 判断是否整数

0115 // 判断是否使用浏览器的querySelectorAll

0116 enableQuerySelector : testElem.querySelectorAll && testElem.querySelectorAll(".TEST").length > 0,

0117 tempAttrValues : [], // 临时记录引号/双引号间的属性值

0118 tempAttrs: [], // 临时记录属性表达式

0119 idName : globalName + "UniqueId",

0120 id : 0,

0121 // 解析CSS选择器获取元素

0122 // @param {String} 选择器

0123 // @param {HTMLElement,Array,HTMLCollection} 上下文

0124 // @return {HTMLElement,Array,HTMLCollection} 匹配到的元素

0125 exec : function(selector, context) {

0126 var result, // 最后结果

0127 selectors, // selector数组

0128 selCount, // selector数组长度

0129 i, j, // 循环变量

0130 temp, // 临时搜索结果

0131 matchs, // 操作符/操作数 数组

0132 streamLen, // 操作符/操作数 数组长度

0133 token, // 操作符

0134 filter, // 操作数

0135 t = this;

0136 // 清除多余的空白

0137 selector = selector.trim();

0138 if ("" === selector) { return; }

0139 // 对简单选择符的优化操作

0140 if (t.ISSIMPLE.test(selector)) {

0141 if (0 === selector.indexOf("#") && typeof context.getElementById !== "undefined") {

0142 //alert("simple id: " + selector); // @debug

0143 return t.getElemById(context, selector.substr(1));

0144 } else if (typeof context.getElementsByTagName !== "undefined") {

0145 //alert("simple tagname: " + selector); // @debug

0146 return jRaiser.util.toArray(context.getElementsByTagName(selector));

0147 }

0148 }

0149 // 使用querySelectorAll

0150 if (t.enableQuerySelector && context.nodeType) {

0151 try {

0152 return jRaiser.util.toArray(context.querySelectorAll(selector));

0153 } catch (e) {

0154 }

0155 }

0156 // 转换成数组,统一处理

0157 context = context.nodeType ? [context] : jRaiser.util.toArray(context);

0158 selectors = selector.replace(t.SPACE, "$1") // 去空白

0159 .replace(t.ATTRVALUES, t.analyzeAttrValues) // 替换属性值

0160 .replace(t.ATTR, t.analyzeAttrs) // 替换属性选择符

0161 .replace(t.IMPLIEDALL, "$1*$2") // 添加必要的"*"(例如.class1 => *.class1)

0162 .split(","); // 分离多个选择器

0163 selCount = selectors.length;

0164 i = -1; result = [];

0165 while (++i < selCount) {

0166 // 重置上下文

0167 temp = context;

0168 selector = selectors[i];

0169 if (t.BEGINIDAPART.test(selector)) { // 优化以id选择器开头且上下文是document的情况

0170 if (typeof context[0].getElementById !== "undefined") {

0171 //alert("begin with id selector: " + RegExp.$1); // @debug

0172 temp = [t.getElemById(context[0], RegExp.$1)];

0173 //alert("result: " + temp); // @debug

0174 if (!temp[0]) {

0175 continue;

0176 }

0177 selector = RegExp.rightContext;

0178 } else { // 上下文不是document, 恢复常规查找

0179 selector = selectors[i];

0180 }

0181 }

0182 // 处理后续的部分

0183 if (selector !== "") {

0184 if (!t.STANDARD.test(selector)) {

0185 selector = " " + selector;

0186 }

0187 // 分离换成字符串数组,从0开始双数是操作符,单数是操作数(例如 " *.class1" => [" ", "*", ".", "class1"])

0188 matchs = selector.match(t.STREAM) || []; streamLen = matchs.length; j = 0;

0189 //alert("stream: " + matchs); // @debug

0190 while (j < streamLen) {

0191 token = matchs[j++]; filter = matchs[j++];

0192 //alert(token + (this.operators[token] ? " is " : " is not ") + "exist"); // @debug

0193 //alert("filter: " + filter); // @debug

0194 //alert("context: " + temp); // @debug

0195 temp = t.operators[token] ? t.operators[token](temp, filter) : [];

0196 if (0 === temp.length) {

0197 break;

0198 }

0199 }

0200 }

0201 jRaiser.util.merge(result, temp);

0202 }

0203 // 清空临时数组

0204 t.tempAttrValues.length = t.tempAttrs.length = 0;

0205 return result.length > 1 ? t.unique(result) : result;

0206 },

0207 // 属性替换处理函数

0208 analyzeAttrs : function($1, $2, $3, $4) {

0209 return "[]" + (selectorQuery.tempAttrs.push([$2, $3, $4]) - 1);

0210 },

0211 // 属性值替换处理函数

0212 analyzeAttrValues : function($1, $2, $3) {

0213 return "=" + (selectorQuery.tempAttrValues.push($3) - 1) + "]";

0214 },

0215 // 获取不重复的元素id

0216 // @param {HTMLElement} 元素

0217 // @return {Number} id

0218 generateId : function(elem) {

0219 var idName = this.idName, id;

0220 try {

0221 id = elem[idName] = elem[idName] || new Number(++this.id);

0222 } catch (e) {

0223 id = elem.getAttribute(idName);

0224 if (!id) {

0225 id = new Number(++this.id);

0226 elem.setAttribute(idName, id);

0227 }

0228 }

0229 return id.valueOf();

0230 },

0231 // 去除数组中的重复元素

0232 // @param {Array} 元素数组

0233 // @return {Array} 已去重复的元素数组

0234 unique : function(elems) {

0235 var result = [], i = 0, flags = {}, elem, id;

0236 while (elem = elems[i++]) {

0237 if (1 === elem.nodeType) {

0238 id = this.generateId(elem);

0239 if (!flags[id]) {

0240 flags[id] = true;

0241 result.push(elem);

0242 }

0243 }

0244 }

0245 return result;

0246 },

0247 // 属性名映射

0248 attrMap : {

0249 "class" : "className",

0250 "for" : "htmlFor"

0251 },

0252 // 获取元素属性

0253 // @param {HTMLElement} 元素

0254 // @param {String} 属性名

0255 // @return {String} 属性值

0256 getAttribute : function(elem, attrName) {

0257 var trueName = this.attrMap[attrName] || attrName, attrValue = elem[trueName];

0258 if ("string" !== typeof attrValue) {

0259 if ("undefined" !== typeof elem.getAttributeNode) {

0260 attrValue = elem.getAttributeNode(attrName);

0261 attrValue = undefined == attrValue ? attrValue : attrValue.value;

0262 } else if (elem.attributes) { // for IE5.5

0263 attrValue = String(elem.attributes[attrName]);

0264 }

0265 }

0266 return null == attrValue ? "" : attrValue;

0267 },

0268 // 通过id获取元素

0269 // @param {HTMLElement} 上下文,一般是document

0270 // @param {String} id

0271 // @return {HTMLElement} 元素

0272 getElemById : function(context, id) {

0273 var result = context.getElementById(id);

0274 if (result && result.id !== id && context.all) { // 修复IE下的id/name bug

0275 result = context.all[id];

0276 if (result) {

0277 result.nodeType && (result = [result]);

0278 for (var i = 0; i < result.length; i++) {

0279 if (this.getAttribute(result[i], "id") === id) {

0280 return result[i];

0281 }

0282 }

0283 }

0284 } else {

0285 return result;

0286 }

0287 },

0288 // 搜索指定位置的某标签名元素

0289 // @param {Array} 上下文

0290 // @param {String} 第一个元素相对位置

0291 // @param {String} 下一个元素相对位置

0292 // @param {String} 标签名

0293 // @param {Number} 最多进行多少次查找

0294 // @return {Array} 搜索结果

0295 getElemsByTagName : function(context, first, next, tagName, limit) {

0296 var result = [], i = -1, len = context.length, elem, counter, tagNameUpper;

0297 tagName !== "*" && (tagNameUpper = tagName.toUpperCase());

0298 while (++i < len) {

0299 elem = context[i][first]; counter = 0;

0300 while (elem && (!limit || counter < limit)) {

0301 if (1 === elem.nodeType) {

0302 (elem.nodeName.toUpperCase() === tagNameUpper || !tagNameUpper) && result.push(elem);

0303 counter++;

0304 }

0305 elem = elem[next];

0306 }

0307 }

0308 return result;

0309 },

0310 // 根据指定顺序检查上下文父元素的第n个子元素是否该上下文元素

0311 // @param {Array} 上下文

0312 // @param {Number} 序号

0313 // @param {String} 第一个元素相对位置

0314 // @param {String} 下一个元素相对位置

0315 // @return {Array} 搜索结果

0316 checkElemPosition : function(context, seq, first, next) {

0317 var result = [];

0318 if (!isNaN(seq)) {

0319 var len = context.length, i = -1,

0320 cache = {}, // 节点缓存

0321 parent, id, current, child;

0322 while (++i < len) {

0323 parent = context[i].parentNode; // 找到父节点

0324 id = this.generateId(parent); // 为父节点生成一个id作为缓存键值

0325 if (undefined === cache[id]) { // 如果缓存中没有,则重新寻找父元素的第N个子元素

0326 current = 0; // 重置当前序号

0327 child = parent[first]; // 第一个元素

0328 while (child) {

0329 1 === child.nodeType && current++; // 序号加1

0330 if (current < seq) {

0331 child = child[next]; // 还没到指定序号,继续找

0332 } else {

0333 break; // 已经到指定序号,中断循环

0334 }

0335 }

0336 cache[id] = child || 0; // 记下本次搜索结果

0337 } else {

0338 child = cache[id];

0339 }

0340 context[i] === child && result.push(context[i]); // 搜索结果与节点相符

0341 }

0342 }

0343 return result;

0344 },

0345 // 获取特定位置的元素

0346 // @param {Array} 上下文

0347 // @param {Number} 第一个位置

0348 // @param {Number} 下一个位置递增量

0349 // @return {Array} 过滤结果

0350 getElemsByPosition : function(context, first, next) {

0351 var i = first, len = context.length, result = [];

0352 while (i >= 0 && i < len) {

0353 result.push(context[i]);

0354 i += next;

0355 }

0356 return result;

0357 },

0358 // 根据属性值过滤元素

0359 // @param {Array} 上下文

0360 // @param {Array} 属性数组

0361 // @return {Array} 过滤结果

0362 getElemsByAttribute : function(context, filter) {

0363 var result = [], elem, i = 0,

0364 check = this.attrOperators[filter[1] || ""],

0365 attrValue = "~=" === filter[1] ? " " + filter[2] + " " : filter[2];

0366 if (check) {

0367 while (elem = context[i++]) {

0368 check(this.getAttribute(elem, filter[0]), attrValue) && result.push(elem);

0369 }

0370 }

0371 return result;

0372 },

0373 // 操作符

0374 operators : {

0375 // id选择符

0376 "#" : function(context, id) {

0377 return selectorQuery.getElemsByAttribute(context, ["id", "=", id]);

0378 },

0379 // 后代选择符

0380 " " : function(context, tagName) {

0381 var len = context.length;

0382 if (1 === len) {

0383 return context[0].getElementsByTagName(tagName);

0384 } else {

0385 var result = [], i = -1;

0386 while (++i < len) {

0387 jRaiser.util.merge(result, context[i].getElementsByTagName(tagName));

0388 }

0389 return result;

0390 }

0391 },

0392 // 类名选择器

0393 "." : function(context, className) {

0394 return selectorQuery.getElemsByAttribute(context, ["class", "~=", className]);

0395 },

0396 // 子元素选择符

0397 ">" : function(context, tagName) {

0398 return selectorQuery.getElemsByTagName(context, "firstChild", "nextSibling", tagName);

0399 },

0400 // 同级元素选择符

0401 "+" : function(context, tagName) {

0402 return selectorQuery.getElemsByTagName(context, "nextSibling", "nextSibling", tagName, 1);

0403 },

0404 // 同级元素选择符

0405 "~" : function(context, tagName) {

0406 return selectorQuery.getElemsByTagName(context, "nextSibling", "nextSibling", tagName);

0407 },

0408 // 属性选择符

0409 "[]" : function(context, filter) {

0410 filter = selectorQuery.tempAttrs[filter];

0411 if (filter) {

0412 if (selectorQuery.ISINT.test(filter[2])) {

0413 filter[2] = selectorQuery.tempAttrValues[filter[2]];

0414 }

0415 return selectorQuery.getElemsByAttribute(context, filter);

0416 } else {

0417 return context;

0418 }

0419 },

0420 // 伪类选择符

0421 ":" : function(context, filter) {

0422 var seq;

0423 if (selectorQuery.PSEUDOSEQ.test(filter)) {

0424 seq = parseInt(RegExp.$1);

0425 filter = RegExp.leftContext;

0426 }

0427 return selectorQuery.pseOperators[filter] ? selectorQuery.pseOperators[filter](context, seq) : [];

0428 }

0429 },

0430 // 属性操作符

0431 attrOperators : {

0432 // 是否包含指定属性值

0433 "" : function(value) { return value !== ""; },

0434 // 是否与指定属性值相等

0435 "=" : function(value, input) { return input === value; },

0436 // 是否包含指定属性值

0437 "~=" : function(value, input) { return (" " + value + " ").indexOf(input) >= 0; },

0438 // 是否与指定属性值不等

0439 "!=" : function(value, input) { return input !== value; },

0440 // 属性值是否以某段字符串开头

0441 "^=" : function(value, input) { return value.indexOf(input) === 0; },

0442 // 属性值是否以某段字符串结尾

0443 "$=" : function(value, input) { return value.substr(value.length - input.length) === input; },

0444 // 属性值是否包含某段子字符串

0445 "*=" : function(value, input) { return value.indexOf(input) >= 0; }

0446 },

0447 // 伪类选择符

0448 pseOperators : {

0449 // 获取第一个子元素

0450 "first-child" : function(context) {

0451 return selectorQuery.checkElemPosition(context, 1, "firstChild", "nextSibling");

0452 },

0453 // 获取第n个子元素

0454 "nth-child" : function(context, seq) {

0455 return selectorQuery.checkElemPosition(context, seq, "firstChild", "nextSibling");

0456 },

0457 // 获取最后一个子元素

0458 "last-child" : function(context) {

0459 return selectorQuery.checkElemPosition(context, 1, "lastChild", "previousSibling");

0460 },

0461 // 获取倒数第n个子元素

0462 "nth-last-child" : function(context, seq) {

0463 return selectorQuery.checkElemPosition(context, seq, "lastChild", "previousSibling");

0464 },

0465 // 获取第奇数个元素

0466 "odd" : function(context) {

0467 return selectorQuery.getElemsByPosition(context, 0, 2);

0468 },

0469 // 获取第偶数个元素

0470 "even": function(context) {

0471 return selectorQuery.getElemsByPosition(context, 1, 2);

0472 },

0473 // 获取第N个元素前的元素

0474 "lt" : function(context, seq) {

0475 return selectorQuery.getElemsByPosition(context, seq - 1, -1);

0476 },

0477 // 获取第N个元素后的元素

0478 "gt" : function(context, seq) {

0479 return selectorQuery.getElemsByPosition(context, seq + 1, 1);

0480 }

0481 }

0482 };

0483 // HTML元素扩展操作,用于继承

0484 jRaiser.element = {

0485 /// 获取指定序号的元素

0486 /// @param {Number} 序号

0487 /// @return {HTMLElement} 元素

0488 get : function(i) {

0489 return this.nodeType === undefined ? this[i] : (0 == i ? this : undefined);

0490 },

0491 /// @overload 获取指定序号并经过扩展的元素

0492 /// @param {Number} 序号索引

0493 /// @return {HTMLElement} 指定序号并经过扩展的元素

0494 /// @overload 以当前元素为上下文通过CSS选择器获取元素

0495 /// @param {String} CSS选择器

0496 /// @return {HTMLElement,Array} 匹配到的经扩展的HTML元素

0497 $ : function(selector) {

0498 return jRaiser("number" === typeof selector ? this.get(selector) : selector, this);

0499 },

0500 /// 检查当前元素是否包含某些样式类

0501 /// @param {String} 样式类名

0502 /// @return {Boolean} 元素是否包含某个样式类

0503 hasClass : function(className) { return jRaiser.style.hasClass(this, className); },

0504 /// 添加样式

0505 /// @param {String,Object} 类名或样式,多个类名用空格隔开

0506 /// @return {HTMLElement,Array} 当前元素

0507 addCss : function(css) { return jRaiser.style.addCss(this, css); },

0508 /// 移除样式

0509 /// @param {String,Object} 类名或样式,多个类名用空格隔开

0510 /// @return {HTMLElement,Array} 当前元素

0511 removeCss : function(css) { return jRaiser.style.removeCss(this, css); },

0512 /// 添加事件委托函数

0513 /// @param {String} 事件名,多个事件用逗号隔开

0514 /// @param {Function} 事件委托函数

0515 /// @param {Mixed} 额外数据

0516 /// @return {HTMLElement,Array} 当前元素

0517 addEvent : function(eventName, handler, data) {

0518 return jRaiser.event.addEvent(this, eventName, handler, data);

0519 },

0520 /// 移除事件委托函数

0521 /// @param {String} 事件名,多个事件用逗号隔开

0522 /// @param {Function} 事件委托函数

0523 /// @return {HTMLElement,Array} 当前元素

0524 removeEvent : function(eventName, handler) {

0525 return jRaiser.event.removeEvent(this, eventName, handler);

0526 },

0527 /// @overload 获取当前元素的属性值

0528 /// @param {String} 属性名

0529 /// @return {Mixed} 属性值

0530 /// @overload 设置当前元素的属性值

0531 /// @param {String} 属性名

0532 /// @param {String,Function} 属性值或用于计算属性值的函数

0533 /// @return {HTMLElement,Array} 当前元素

0534 attr : function(name, value) {

0535 var t = this;

0536 name = selectorQuery.attrMap[name] || name;

0537 if (value !== undefined) {

0538 return jRaiser.dom.eachNode(t, function(name, value) {

0539 this[name] = jRaiser.util.isFunction(value) ? value.call(this) : value;

0540 }, arguments);

0541 } else {

0542 var elem = this.get(0);

0543 return elem ? elem[name] : undefined;

0544 }

0545 },

0546 /// 对每个节点执行特定操作

0547 /// @param {Function} 要执行的操作

0548 /// @return {HTMLElement, Array} 当前元素

0549 each : function(callback) {

0550 return jRaiser.dom.eachNode(this, callback);

0551 }

0552 };

0553 jRaiser.element[globalName] = jRaiser.element.$;

0554 // window对象、document对象的添加、移除事件方法

0555 window.addEvent = document.addEvent = jRaiser.element.addEvent;

0556 window.removeEvent = document.removeEvent = jRaiser.element.removeEvent;

0557 var tplCache = {}, // 模板缓存

0558 slice = Array.prototype.slice,

0559 toString = Object.prototype.toString; // 简写toString

0560 /// 工具类、工具函数

0561 jRaiser.util = {

0562 /// 检查变量是否Array类型

0563 /// @param {Mixed} 待测变量

0564 /// @return {Boolean} 待测变量是否Array类型

0565 isArray : function(value) { return toString.call(value) === "[object Array]"; },

0566 /// 检查变量是否函数类型

0567 /// @param {Mixed} 待测变量

0568 /// @return {Boolean} 待测变量是否Function类型

0569 isFunction : function(value) { return toString.call(value) === "[object Function]"; },

0570 /// 把集合转换为数组

0571 /// @param {Array,Collection} 数组或集合

0572 /// @return {Array} 数组

0573 toArray : function(col) {

0574 if (jRaiser.util.isArray(col)) { return col; }

0575 var arr;

0576 try {

0577 arr = slice.call(col);

0578 } catch (e) {

0579 arr = [];

0580 var i = col.length;

0581 while (i) {

0582 arr[--i] = col[i];

0583 }

0584 }

0585 return arr;

0586 },

0587 /// 合并数组

0588 /// @param {Array} 目标数组

0589 /// @param {Array,Collection} 源数组

0590 /// @return {Array} 混合后的目标数组

0591 merge : function(first, second) {

0592 var i = second.length, pos = first.length;

0593 while (--i >= 0) {

0594 first[pos + i] = second[i];

0595 }

0596 return first;

0597 },

0598 /// 模板转换

0599 /// @param {String} 模板代码

0600 /// @param {Object} 值集合

0601 /// @param {Boolean} 是否缓存模板,默认为是

0602 /// @return {String} 转换后的代码

0603 parseTpl : function(tpl, values, isCached) {

0604 var func = tplCache[tpl];

0605 null == values && (values = {});

0606 if (!func) {

0607 func = new Function("obj", "var _=[];with(obj){_.push('" +

0608 tpl.replace(/[\r\t\n]/g, " ")

0609 .replace(/'(?=[^#]*#>)/g, "\t")

0610 .split("'").join("\\'")

0611 .split("\t").join("'")

0612 .replace(/<#=(.+?)#>/g, "',$1,'")

0613 .split("<#").join("');")

0614 .split("#>").join("_.push('")

0615 + "');}return _.join('');");

0616 (null == isCached || true === isCached) && (tplCache[tpl] = func);

0617 }

0618 return func(values);

0619 },

0620 /// 把源对象的属性和方法扩展到目标对象上

0621 /// @param {Mixed} 目标对象

0622 /// @param {Mixed} 源对象

0623 /// @return {Mixed} 已扩展的目标对象

0624 extend : function(des, src) {

0625 for (var p in src) {

0626 des[p] = src[p];

0627 }

0628 return des;

0629 },

0630 /// 遍历数组或对象,对每个成员执行某个方法

0631 /// @param {Mixed} 数组或对象

0632 /// @param {Function} 回调函数

0633 /// @param {Array} 额外参数

0634 /// @return {Mixed} 原数组或对象

0635 each : function(obj, callback, args) {

0636 var i = -1, len = obj.length,

0637 isObj = len === undefined || jRaiser.util.isFunction(obj);

0638 if (args) {

0639 if (isObj) {

0640 for (i in obj ) {

0641 if (false === callback.apply(obj[i], args)) {

0642 break;

0643 }

0644 }

0645 } else {

0646 while (++i < len) {

0647 if (false === callback.apply(obj[i], args)) {

0648 break;

0649 }

0650 }

0651 }

0652 } else {

0653 if (isObj) {

0654 for (i in obj) {

0655 if (false === callback.call(obj[i], i, obj[i])) {

0656 break;

0657 }

0658 }

0659 } else {

0660 while (++i < len) {

0661 if (false === callback.call(obj[i], i, obj[i])) {

0662 break;

0663 }

0664 }

0665 }

0666 }

0667 return obj;

0668 }

0669 };

0670 // 快速访问

0671 jRaiser.parseTpl = jRaiser.util.parseTpl;

0672 jRaiser.each = jRaiser.util.each;

0673 var readyList = [], // DOM Ready函数队列

0674 isReadyBound, // 是否已绑定DOM Ready事件

0675 onDomReady;

0676 if (document.addEventListener) {

0677 onDomReady = function() {

0678 document.removeEventListener("DOMContentLoaded", onDomReady, false);

0679 domReadyNow();

0680 };

0681 } else if (document.attachEvent) { // For IE Only

0682 onDomReady = function() {

0683 if ("complete" === document.readyState) {

0684 document.detachEvent("onreadystatechange", onDomReady);

0685 domReadyNow();

0686 }

0687 };

0688 }

0689 // DOM Ready检查 For IE

0690 function doScrollCheck() {

0691 if (jRaiser.dom.isReady) { return; }

0692 try {

0693 document.documentElement.doScroll("left");

0694 } catch (e) {

0695 setTimeout(doScrollCheck, 1);

0696 return;

0697 }

0698 domReadyNow();

0699 }

0700 // DOM已就绪

0701 function domReadyNow() {

0702 if (!jRaiser.dom.isReady) {

0703 if (!document.body) { return setTimeout(domReadyNow, 13); }

0704 jRaiser.dom.isReady = true;

0705 if (readyList) {

0706 var i = -1, len = readyList.length;

0707 while (++i < len) {

0708 readyList[i].call(document, jRaiser);

0709 }

0710 readyList = null;

0711 }

0712 }

0713 }

0714 // 绑定DOMReady事件

0715 function bindReady() {

0716 if (isReadyBound) { return; }

0717 if ("complete" === document.readyState) { return domReadyNow(); }

0718 if (document.addEventListener) {

0719 document.addEventListener("DOMContentLoaded", domReadyNow, false);

0720 window.addEventListener("load", domReadyNow, false);

0721 } else if (document.attachEvent) {

0722 document.attachEvent("onreadystatechange", domReadyNow);

0723 window.attachEvent("onload", domReadyNow);

0724 var isTopLevel;

0725 try {

0726 isTopLevel = window.frameElement == null;

0727 } catch(e) {}

0728 document.documentElement.doScroll && isTopLevel && doScrollCheck();

0729 }

0730 isReadyBound = true;

0731 }

0732 /// DOM操作

0733 jRaiser.dom = {

0734 /// 把节点放到数组容器中

0735 /// @param {HTMLElement,HTMLCollection,Array} 节点或节点集合

0736 /// @return {Array} 节点数组

0737 wrapByArray : function(nodes) {

0738 if (nodes) {

0739 if (nodes.nodeType !== undefined || nodes.setInterval) {

0740 return [nodes];

0741 } else if (nodes.length) {

0742 return jRaiser.util.toArray(nodes);

0743 }

0744 }

0745 return [];

0746 },

0747 /// 对节点执行指定操作

0748 /// @param {HTMLElement,Array,HTMLCollection} 节点

0749 /// @param {Function} 回调函数

0750 /// @param {Array} 额外的参数

0751 /// @return {HTMLElement,Array,HTMLCollection} 指定节点

0752 eachNode : function(nodes, callback, args) {

0753 jRaiser.each(jRaiser.dom.wrapByArray(nodes), callback, args);

0754 return nodes;

0755 },

0756 /// 在DOM就绪时执行指定函数

0757 /// @param {Function} 指定函数

0758 /// @param {Object} 当前对象

0759 ready : function(fn) {

0760 // 绑定事件

0761 bindReady();

0762 if (jRaiser.dom.isReady) {

0763 fn.call(document, jRaiser);

0764 } else {

0765 readyList.push(fn);

0766 }

0767 return this;

0768 }

0769 };

0770 // 快速访问

0771 jRaiser.ready = jRaiser.dom.ready;

0772 // 对CSS样式字符串进行解释的正则表达式

0773 var CSSSPACE = /\s*([:;])\s*/g,

0774 STYLENAME = /[^:;]+?(?=:)/g,

0775 STYLESPLITER = /[^:;]+/g,

0776 CLASSSPLITER = /[^\s]+/g,

0777 FIXCSSNAME = /-([a-z])/gi,

0778 FLOATNAME = testElem.style.styleFloat !== undefined ? "styleFloat" : "cssFloat",

0779 ISFLOAT = /^float$/i;

0780 // 添加样式类

0781 function addClasses(classes, len, str) {

0782 if (this.className) {

0783 var className = " " + this.className + " ", i = -1;

0784 while (++i < len) {

0785 -1 === className.indexOf(" " + classes[i] + " ") && (className += (classes[i] + " "));

0786 }

0787 this.className = className.trim();

0788 } else {

0789 this.className = str;

0790 }

0791 }

0792 // 添加样式

0793 function addStyles(styles, len, str) {

0794 if (!this.style.cssText && str) {

0795 this.style.cssText = str;

0796 } else {

0797 var i = 0;

0798 while (i < len) {

0799 this.style[styles[i++]] = styles[i++].replace(/^NULL$/i, "");

0800 }

0801 }

0802 }

0803 // 删除样式类

0804 function removeClasses(classes, len, str) {

0805 switch (this.className) {

0806 case str:

0807 this.className = "";

0808 break;

0809 case "":

0810 return;

0811 break;

0812 default:

0813 var className = " " + this.className + " ", i = -1;

0814 while (++i < len) {

0815 className = className.replace(" " + classes[i] + " ", " ");

0816 }

0817 this.className = className.trim();

0818 break;

0819 }

0820 }

0821 // 删除样式

0822 function removeStyles(styles, len) {

0823 for (var i = 0; i < len; i++) {

0824 this.style[styles[i]] !== undefined && (this.style[styles[i]] = "");

0825 }

0826 }

0827 /// 样式控制

0828 jRaiser.style = {

0829 /// 把样式名转换成样式属性名

0830 /// @param {String} 样式名

0831 /// @return {String} 样式属性名

0832 fixStyleName : function(name) {

0833 return ISFLOAT.test(name) ? FLOATNAME : name.replace(FIXCSSNAME, function($0, $1) {

0834 return $1.toUpperCase(); // 转换为js标准的样式名

0835 });

0836 },

0837 /// 检查指定元素是否包含某些样式类

0838 /// @param {HTMLElement,HTMLCollection,Array} 指定元素

0839 /// @param {String} 样式类名

0840 /// @return {Boolean} 元素是否包含某个样式类

0841 hasClass : function(elems, className) {

0842 elems = jRaiser.dom.wrapByArray(elems);

0843 var i = elems.length;

0844 if (i > 0) {

0845 className = " " + className + " ";

0846 while (--i >= 0) {

0847 if ((" " + elems[i].className + " ").indexOf(className) >= 0) {

0848 return true;

0849 }

0850 }

0851 }

0852 return false;

0853 },

0854 // 识别CSS样式

0855 // @param {String,Object} 样式

0856 // @return {Array} 标记了样式类型的样式流

0857 parse : function(css) {

0858 var result;

0859 if ("string" === typeof css) {

0860 var hasSemi = css.indexOf(";") >= 0, hasColon = css.indexOf(":") >= 0;

0861 if (hasSemi || hasColon) {

0862 result = css.trim()

0863 .replace(CSSSPACE, "$1")

0864 .replace(hasColon ? STYLENAME : STYLESPLITER, jRaiser.style.fixStyleName)

0865 .match(STYLESPLITER);

0866 if (hasColon && result.length % 2 !== 0) {

0867 throw "invalid inline style";

0868 }

0869 result.type = "style";

0870 } else {

0871 result = css.match(CLASSSPLITER) || [];

0872 result.type = "class";

0873 }

0874 } else {

0875 result = [];

0876 for (var name in css) {

0877 result.push(jRaiser.style.fixStyleName(name), css[name]);

0878 }

0879 result.type = "style";

0880 }

0881 return result;

0882 },

0883 /// 为指定HTML元素添加样式

0884 /// @param {HTMLElement,Array,HTMLCollection} 指定元素

0885 /// @param {String,Object} 样式

0886 /// @return {HTMLElement,Array,HTMLCollection} 指定元素

0887 addCss : function(elems, css) {

0888 var stream = jRaiser.style.parse(css);

0889 return jRaiser.dom.eachNode(

0890 elems, "class" === stream.type ? addClasses : addStyles,

0891 [stream, stream.length, "string" === typeof css ? css : undefined]

0892 );

0893 },

0894 /// 为指定HTML元素移除样式

0895 /// @param {HTMLElement,Array,HTMLCollection} 指定元素

0896 /// @param {String,Object} 样式

0897 /// @return {HTMLElement,Array,HTMLCollection} 指定元素

0898 removeCss : function(elems, css) {

0899 var stream = jRaiser.style.parse(css);

0900 return jRaiser.dom.eachNode(

0901 elems, "class" === stream.type ? removeClasses : removeStyles,

0902 [stream, stream.length, css]

0903 );

0904 },

0905 /// 获取指定元素的当前样式

0906 /// @param {HTMLElement,Array,HTMLCollection} 指定元素

0907 /// @param {String} 样式名

0908 /// @param {Object} 元素所在的页面的window对象,默认为当前window对象

0909 /// @return {String} 样式值

0910 getCurrentStyle : function(nodes, styleName, w) {

0911 if (!nodes) { return undefined; }

0912 !nodes.nodeType && (nodes = nodes[0]);

0913 return (nodes.currentStyle || (w || window).getComputedStyle(nodes, null))

0914 [jRaiser.style.fixStyleName(styleName)];

0915 }

0916 };

0917 // 添加事件

0918 function newEvent(eventName, handler, data) {

0919 var t = this;

0920 handler = jRaiser.event.delegate(t, eventName, handler, data);

0921 if (t.attachEvent) {

0922 t.attachEvent("on" + eventName, handler);

0923 } else if (t.addEventListener) {

0924 t.addEventListener(eventName, handler, false);

0925 }

0926 }

0927 // 移除事件

0928 function disposeEvent(eventName, handler) {

0929 var t = this;

0930 handler = jRaiser.event.getDelegate(t, eventName, handler);

0931 if (t.detachEvent) {

0932 t.detachEvent("on" + eventName, handler);

0933 } else if (t.removeEventListener) {

0934 t.removeEventListener(eventName, handler, false);

0935 }

0936 }

0937 var EVENTSPLITER = /\s*,\s*/, // 事件名分隔符

0938 eventId = 0; // 事件编号基值

0939 /// 事件处理

0940 jRaiser.event = {

0941 /// 事件Id属性名

0942 idName : globalName + "EventId",

0943 /// 事件容器名

0944 eventsWrapper : globalName + "Events",

0945 /// 为指定HTML元素添加事件委托函数

0946 /// @param {HTMLElement,Array,HTMLCollection} 指定元素

0947 /// @param {String} 事件名,多个事件名用逗号隔开

0948 /// @param {Function} 事件委托函数

0949 /// @param {Object} 额外传入的数据

0950 /// @return {HTMLElement,Array,HTMLCollection} 指定元素

0951 addEvent : function(elems, eventNames, handler, data) {

0952 eventNames = eventNames.split(EVENTSPLITER);

0953 var i = eventNames.length;

0954 while (--i >= 0) {

0955 jRaiser.dom.eachNode(elems, newEvent, [eventNames[i], handler, data]);

0956 }

0957 return elems;

0958 },

0959 /// 为指定HTML元素移除事件委托函数

0960 /// @param {HTMLElement,Array,HTMLCollection} 指定元素

0961 /// @param {String} 事件名,多个事件名用逗号隔开

0962 /// @param {Function} 事件处理函数

0963 /// @return {HTMLElement,Array,HTMLCollection} 指定元素

0964 removeEvent : function(elems, eventNames, handler) {

0965 eventNames = eventNames.split(EVENTSPLITER);

0966 var i = eventNames.length;

0967 while (--i >= 0) {

0968 jRaiser.dom.eachNode(elems, disposeEvent, [eventNames[i], handler]);

0969 }

0970 return elems;

0971 },

0972 /// 生成事件代理

0973 /// @param {HTMLElement} 元素

0974 /// @param {String} 事件名

0975 /// @param {Function} 事件处理函数

0976 /// @param {Object} 额外传入的数据

0977 /// @return {Function} 事件代理

0978 delegate : function(elem, eventName, handler, data) {

0979 var t = jRaiser.event, events = elem[t.eventsWrapper] = elem[t.eventsWrapper] || {}, // 取得事件Hash表引用

0980 id = handler[t.idName] = handler[t.idName] || ++eventId; // 获取不重复的事件编号

0981 // 生成特定事件Hash表

0982 events[eventName] = events[eventName] || {};

0983 var trueHandler = events[eventName][id];

0984 if (!trueHandler) {

0985 trueHandler = function(e) {

0986 e = t.fix(e);

0987 var temp = handler.call(elem, e, data || {});

0988 false === temp && e.preventDefault();

0989 return temp;

0990 };

0991 events[eventName][id] = trueHandler;

0992 }

0993 return trueHandler;

0994 },

0995 /// 获取事件代理

0996 /// @param {HTMLElement} 元素

0997 /// @param {String} 事件名

0998 /// @param {Function} 事件处理函数

0999 /// @return {Function} 事件代理

1000 getDelegate : function(elem, eventName, handler) {

1001 var t = jRaiser.event;

1002 try {

1003 return elem[t.eventsWrapper][eventName][handler[t.idName]];

1004 } catch (e) {

1005 }

1006 return handler;

1007 },

1008 /// 修复不同浏览器的事件兼容性

1009 /// @param {Event} 事件对象

1010 /// @return {Event} 修复后的事件对象

1011 fix : function(e) {

1012 if (!e.target) {

1013 e.target = e.srcElement || document;

1014 }

1015 if (3 == e.target.nodeType) {

1016 e.target = e.target.parentNode;

1017 }

1018 e.timestamp = e.timeStamp || Date.now();

1019 e.preventDefault = e.preventDefault || function() {

1020 e.returnValue = false;

1021 };

1022 if (undefined === e.pageX && undefined !== e.clientX) {

1023 var doc = document.documentElement, body = document.body;

1024 e.pageX = e.clientX + (doc.scrollLeft || body.scrollLeft || 0) - (doc.clientLeft || 0);

1025 e.pageY = e.clientY + (doc.scrollTop || body.scrollTop || 0) - (doc.clientTop || 0);

1026 }

1027 if (!e.which) {

1028 e.which = e.charCode || e.keyCode;

1029 }

1030 // 鼠标单击:1 == 左键; 2 == 中键; 3 == 右键

1031 if (!e.which && e.button) {

1032 e.which = (e.button & 1 ? 1 : (e.button & 2 ? 3 : (e.button & 4 ? 2 : 0)));

1033 }

1034 return e;

1035 }

1036 };

1037 // 获取客户端信息

1038 var userAgent = window.navigator.userAgent.toLowerCase();

1039 /// 浏览器检测对象

1040 jRaiser.browser = {

1041 /// {String} 浏览器版本

1042 version : (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [0,'0'])[1],

1043 /// {Boolean} 是否Safari浏览器

1044 safari : /webkit/.test(userAgent),

1045 /// {Boolean} 是否Opera浏览器

1046 opera : /opera/.test(userAgent),

1047 /// {Boolean} 是否IE浏览器

1048 msie : /msie/.test(userAgent) && !/opera/.test(userAgent),

1049 /// {Boolean} 是否Mozilla浏览器

1050 mozilla : /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)

1051 };

1052 /// Ajax操作

1053 jRaiser.ajax = {

1054 /// 创建XmlHttpRequest对象

1055 /// @return {XMLHttpRequest} XmlHttpRequest对象

1056 createXhr : function() {

1057 var xhr;

1058 try {

1059 xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();

1060 } catch (e) { }

1061 if (!xhr) {

1062 throw "failed to create XMLHttpRequest object";

1063 }

1064 return xhr;

1065 },

1066 /// 发送Ajax请求

1067 /// @param {String} 请求地址

1068 /// @param {String} 发送方式,"GET"或"POST",默认为GET

1069 /// @param {Object} 发送的数据

1070 /// @param {Object} 其他可选参数

1071 /// @param {XMLHttpRequest} 用于发送请求的XmlHttpRequest对象,如不指定则自动创建

1072 /// @return {XMLHttpRequest} XmlHttpRequest对象

1073 send : function(url, method, data, options, xhr) {

1074 // 创建XMLHttpRequest对象

1075 xhr = xhr || jRaiser.ajax.createXhr();

1076 var hasCompleted;

1077 // 修正参数

1078 "string" === typeof method && (method = method.toUpperCase());

1079 method = method !== "GET" && method !== "POST" ? "GET" : method; // 默认为GET

1080 options = options || {};

1081 options.async = "boolean" === typeof options.async ? options.async : true;

1082 // 连接参数键值对

1083 var postData;

1084 if (data) {

1085 postData = [];

1086 for (var d in data) {

1087 data[d] != null && postData.push(d + "=" + encodeURIComponent(data[d]));

1088 }

1089 postData = postData.join("&").replace(/%20/g, "+");

1090 if ("GET" === method) {

1091 url += ("?" + postData);

1092 postData = undefined;

1093 }

1094 }

1095 // 超时处理(异步处理时才有效)

1096 options.async && !isNaN(options.timeout) && options.timeout > 0 && setTimeout(function() {

1097 if (!hasCompleted) {

1098 xhr.abort();

1099 options.onTimeout && options.onTimeout(xhr);

1100 }

1101 }, options.timeout);

1102 // 设定状态变换时的事件

1103 xhr.onreadystatechange = function() {

1104 if (4 == xhr.readyState) {

1105 hasCompleted = true;

1106 var eventName = 200 == xhr.status ? "onSuccess" : "onError";

1107 options[eventName] && options[eventName](xhr);

1108 }

1109 };

1110 // 打开连接并发送数据

1111 xhr.open(method, url, options.async, options.username, options.password);

1112 var contentType = [];

1113 "POST" === method && contentType.push("application/x-www-form-urlencoded");

1114 // 设置header

1115 if (options.headers) {

1116 for (var h in options.headers) {

1117 if ("content-type" === h.toLowerCase()) {

1118 contentType.push(options.headers[h]);

1119 } else {

1120 xhr.setRequestHeader(h, options.headers[h]);

1121 }

1122 }

1123 }

1124 contentType.length &&

1125 xhr.setRequestHeader("Content-Type", contentType.join(";").replace(/;+/g, ";").replace(/;$/, ""));

1126 xhr.send(postData);

1127 return xhr;

1128 },

1129 /// 动态加载外部Javascript文件

1130 /// @param {String} 文件地址

1131 /// @param {Function} 加载完成后执行的回调函数

1132 /// @param {String} 编码

1133 /// @param {Object} 文档对象,默认为当前文档

1134 importJs : function(url, onComplete, charset, doc) {

1135 doc = doc || document;

1136 var script = doc.createElement("script");

1137 script.language = "javascript"; script.type = "text/javascript";

1138 if (charset) {

1139 script.charset = charset;

1140 }

1141 // 读取完后的操作

1142 script.onload = script.onreadystatechange = function() {

1143 if (!script.readyState || "loaded" == script.readyState || "complete" == script.readyState) {

1144 onComplete && onComplete();

1145 script.onload = script.onreadystatechange = null;

1146 script.parentNode.removeChild(script);

1147 }

1148 };

1149 script.src = url;

1150 doc.getElementsByTagName("head")[0].appendChild(script);

1151 }

1152 };

1153 // Cookie过期时间格式

1154 var EXPIRESWITHUNIT = /[smhdMy]$/,

1155 TIMEUNITS = {

1156 s : 1,

1157 m : 60,

1158 h : 60 * 60,

1159 d : 24 * 60 * 60,

1160 M : 30 * 24 * 60 * 60,

1161 y : 365 * 24 * 60 * 60

1162 };

1163 /// Cookie操作

1164 jRaiser.cookie = {

1165 /// 编码函数

1166 encoder : window.encodeURIComponent,

1167 /// 解码函数

1168 decoder : window.decodeURIComponent,

1169 /// 获取Cookie值

1170 /// @param {String} Cookie名

1171 /// @return {String} Cookie值

1172 get : function(name) {

1173 var t = jRaiser.cookie;

1174 name = t.encoder(name) + "=";

1175 var cookie = document.cookie, beginPos = cookie.indexOf(name), endPos;

1176 if (-1 === beginPos) {

1177 return undefined;

1178 }

1179 beginPos += name.length; endPos = cookie.indexOf(";", beginPos);

1180 if (endPos === -1) {

1181 endPos = cookie.length;

1182 }

1183 return t.decoder(cookie.substring(beginPos, endPos));

1184 },

1185 /// 写入Cookie值

1186 /// @param {String} Cookie名

1187 /// @param {Mixed} Cookie值

1188 /// @param {Number,Date,String} 过期时间

1189 /// @param {String} 域,默认为当前页

1190 /// @param {String} 路径,默认为当前路径

1191 /// @param {Boolean} 是否仅把Cookie发送给受保护的服务器连接(https),默认为否

1192 set : function(name, value, expires, domain, path, secure) {

1193 var t = jRaiser.cookie, cookieStr = [t.encoder(name) + "=" + t.encoder(value)];

1194 if (expires) {

1195 var date, unit;

1196 if ("[object Date]" === toString.call(expires)) {

1197 date = expires;

1198 } else {

1199 if ("string" === typeof expires && EXPIRESWITHUNIT.test(expires)) {

1200 expires = expires.substring(0, expires.length - 1);

1201 unit = RegExp.lastMatch;

1202 }

1203 if (!isNaN(expires)) {

1204 date = new Date();

1205 date.setTime(date.getTime() + expires * TIMEUNITS[unit || "m"] * 1000);

1206 }

1207 }

1208 date && cookieStr.push("expires=" + date.toUTCString());

1209 }

1210 path && cookieStr.push("path=" + path);

1211 domain && cookieStr.push("domain=" + domain);

1212 secure && cookieStr.push("secure");

1213 document.cookie = cookieStr.join(";");

1214 },

1215 /// 删除Cookie

1216 /// @param {String} Cookie名

1217 /// @param {String} 域

1218 /// @param {String} 路径

1219 del : function(name, domain, path) {

1220 document.cookie = jRaiser.cookie.encoder(name) + "=" + (path ? ";path=" + path : "") + (domain ? ";domain=" + domain : "") + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";

1221 }

1222 };

1223 var whiteSpaces = /^\s+|\s+$/g;

1224 /// 去掉当前字符串两端的某段字符串

1225 /// @param {String} 要去掉的字符串,默认为空白

1226 /// @return {String} 修整后的字符串

1227 !String.prototype.trim && (String.prototype.trim = function() { return this.replace(whiteSpaces, ""); });

1228 /// 从左边开始截取一定长度的子字符串

1229 /// @param {Number} 长度

1230 /// @return {String} 子字符串

1231 String.prototype.left = function(n) { return this.substr(0, n); };

1232 /// 从右边开始截取一定长度的子字符串

1233 /// @param {Number} 长度

1234 /// @return {String} 子字符串

1235 String.prototype.right = function(n) { return this.slice(-n); };

1236 /// 格式化字符串

1237 /// @param {String} 要格式化的字符串

1238 /// @param {String} 参数

1239 /// @return {String} 格式化后的字符串

1240 String.format = function(str) {

1241 var args = arguments, re = new RegExp("%([1-" + args.length + "])", "g");

1242 return String(str).replace(re, function($0, $1) {

1243 return args[$1];

1244 });

1245 };

1246 /// 为函数绑定this和参数

1247 /// @param {Mixed} 需绑定为this的对象

1248 /// @param {Mixed} 参数

1249 /// @return {Function} 绑定this和参数的函数

1250 Function.prototype.bind = function() {

1251 if (!arguments.length) { return this; }

1252 var method = this, args = slice.call(arguments), object = args.shift();

1253 return function() {

1254 return method.apply(object, args.concat(slice.call(arguments)));

1255 };

1256 };

1257 /// 在当前数组中检索指定元素

1258 /// @param {Mixed} 指定元素

1259 /// @param {Number} 开始搜索的位置,默认为0

1260 /// @return {Number} 指定元素在数组中第一个匹配项的索引;如果该元素不存在于数组中,返回-1

1261 !Array.prototype.indexOf && (Array.prototype.indexOf = function(elt, from) {

1262 var len = this.length, from = Number(from) || 0;

1263 from = from < 0 ? Math.ceil(from) : Math.floor(from);

1264 from < 0 && (from += len);

1265 for (; from < len; from++) {

1266 if (this[from] === elt) { return from; }

1267 }

1268 return -1;

1269 });

1270 /// 删除当前数组指定位置的元素

1271 /// @param {Number} 指定位置

1272 /// @return {Array} 当前数组

1273 Array.prototype.remove = function(n) {

1274 n >= 0 && this.splice(n, 1);

1275 return this;

1276 };

1277 // 把数字转换成两位数的字符串

1278 function toTwoDigit(num) { return num < 10 ? "0" + num : num; }

1279 // 临时记录正在转换的日期

1280 var tempYear, tempMonth, tempDate, tempHour, tempMinute, tempSecond;

1281 // 格式替换函数

1282 function getDatePart(part) {

1283 switch (part) {

1284 case "yyyy": return tempYear;

1285 case "yy": return tempYear.toString().slice(-2);

1286 case "MM": return toTwoDigit(tempMonth);

1287 case "M": return tempMonth;

1288 case "dd": return toTwoDigit(tempDate);

1289 case "d": return tempDate;

1290 case "HH": return toTwoDigit(tempHour);

1291 case "H": return tempHour;

1292 case "hh": return toTwoDigit(tempHour > 12 ? tempHour - 12 : tempHour);

1293 case "h": return tempHour > 12 ? tempHour - 12 : tempHour;

1294 case "mm": return toTwoDigit(tempMinute);

1295 case "m": return tempMinute;

1296 case "ss": return toTwoDigit(tempSecond);

1297 case "s": return tempSecond;

1298 default: return part;

1299 }

1300 }

1301 /// 返回当前日期的毫秒表示

1302 /// @param {Number} 当前日期的毫秒表示

1303 Date.now = Date.now || function() { return +new Date; }

1304 /// 返回指定格式的日期字符串

1305 /// @param {String} 格式

1306 /// @return {String} 指定格式的日期字符串

1307 Date.prototype.format = function(formation) {

1308 tempYear = this.getFullYear();

1309 tempMonth = this.getMonth() + 1;

1310 tempDate = this.getDate();

1311 tempHour = this.getHours();

1312 tempMinute = this.getMinutes();

1313 tempSecond = this.getSeconds();

1314 return formation.replace(/y+|m+|d+|h+|s+|H+|M+/g, getDatePart);

1315 };

1316 // 回收资源

1317 testElem = null;

1318 })(window);
Filed under: JavaScript 源码分析 JavaScript框架 发表评论 js框架中类继承的比较
首先我们来看下jQuery之父john resig的实现方法:

jq之父写的类继承方式的特点是:

有私有变量
可以写在一个构造函数中
可以多级继承,可以有多个父类(需要某种特定格式)
继承基于prototype,且不会执行父类的构造函数
保持了父类的函数链,可以在子类中用this._super简单调用
instanceof 对子类、父类都生效
这是目前为止我看到的最好的方法。除了定义了一个全局变量Class外

view sourceprint?
01 // Inspired by base2 and Prototype

02 (function(){

03 var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

04 // The base Class implementation (does nothing)

05 this.Class = function(){};

06 // Create a new Class that inherits from this class

07 Class.extend = function(prop) {

08 var _super = this.prototype;

09 // Instantiate a base class (but only create the instance,

10 // don't run the init constructor)

11 initializing = true;

12 var prototype = new this();

13 initializing = false;

14 // Copy the properties over onto the new prototype

15 for (var name in prop) {

16 // Check if we're overwriting an existing function

17 prototype[name] = typeof prop[name] == "function" &&

18 typeof _super[name] == "function" && fnTest.test(prop[name]) ?

19 (function(name, fn){

20 return function() {

21 var tmp = this._super;

22 // Add a new ._super() method that is the same method

23 // but on the super-class

24 this._super = _super[name];

25 // The method only need to be bound temporarily, so we

26 // remove it when we're done executing

27 var ret = fn.apply(this, arguments);

28 this._super = tmp;

29 return ret;

30 };

31 })(name, prop[name]) :

32 prop[name];

33 }

34 // The dummy class constructor

35 function Class() {

36 // All construction is actually done in the init method

37 if ( !initializing && this.init )

38 this.init.apply(this, arguments);

39 }

40 // Populate our constructed prototype object

41 Class.prototype = prototype;

42 // Enforce the constructor to be what we expect

43 Class.constructor = Class;

44 // And make this class extendable

45 Class.extend = arguments.callee;

46 return Class;

47 };

48 })();
Filed under: JavaScript jQuery ExtJS JavaScript框架 YUI 发表评论 magento中的getBaseUrl函数
在magento中如果要获取js,media,skin目录,我们可以使用magento的

view sourceprint?
1 Mage::getBaseUrl()
这个函数..假设我们的网站根目录是:http://192.168.1.10/magento/

如果我要获取js目录

view sourceprint?
1 <?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_JS);//http://192.168.1.10/magento/js/ ?>
Filed under: Magento 发表评论 jQuery的unbind()函数详解
jQuery的绑定事件非常方便,有bind、unbind、live、one,还有它帮你把一些常用的事件给单独了出来,比如控件的onclick事件,我们绑定onclick事件的时候只需要

view sourceprint?
1 $("#testButton").click(function() {

2 alert("I'm Test Button");

JavaScript相关文章推荐相关推荐

  1. 关于JavaScript相关文章

    http://www.cnblogs.com/xia520pi/archive/2012/05/12/2497013.html 关于JavaScript相关文章 1)JavaScript框架之继承机制 ...

  2. PHP简单实现“相关文章推荐”功能的方法

    通常在做内容网站的时候,需要在每一篇文章中出现与该文章相关的文章列表.对于大多数人来说,使用的方法通常是:建立一个关键词列表,判断每篇文章包含有那些关键词,最后根据关键词找出与某篇文章最相关的文章.对 ...

  3. JavaScript相关图书推荐

    JavaScript语言精粹(修订版) 作      者 Douglas Crockford(道格拉斯·克罗克福德) 著:赵泽欣 等 译 出 版 社 电子工业出版社 出版时间 2012-09-01 版 ...

  4. 数据挖掘——相似文章推荐

    相似文章推荐:在用户阅读某篇文章时,为用户推荐更多的与在读文章内容相类似的文章 相关概念: 推荐(Recommended):指介绍好的人或事物,希望被任用或接受.数据挖掘领域,推荐包括相似推荐和协同过 ...

  5. python数据挖掘实战笔记——文本挖掘(9):相似文章推荐

    概念: 相似文本推荐:在用户阅读某篇文章的时候,为用户推荐更多与在读文章内容类似的文章. **推荐:**指介绍好的人或事物,希望被任用或接受.数据挖掘领域,推荐包括相似推荐及协同过滤推荐. **相似推 ...

  6. php 中 相关文章 的思路,WordPress实现推荐相关文章功能代码

    WordPress实现推荐相关文章功能有2种方法:一种是可以在单篇日志和 feed 中都生成推荐相关文章功能,不过,功能越强大,代码也就会相应较多,所以这里还提供第二种,仅在单篇日志中实现在相关日志的 ...

  7. DedeCMS最新文章、相关文章、推荐文章、热点文章、头条

    DedeCMS最新文章: <ul>     {dede:arclist row='10' titlelen='50'}     <li><a href="htt ...

  8. 织梦标签调用:最新文章、相关文章、推荐文章、热点文章、头条

    DedeCMS最新文章: {dede:arclist row='10' titlelen='50'} [field:title/] {/dede:arclist} 如果要排除头条文章加上 noflag ...

  9. Silverlight 2 相关文章汇总

    概述 对自己写的Silverlight 2的相关文章做一下汇总,便于大家直接查找.另外,大家如果有关于Silverlight 2方面的问题,也可以在这里提出,我将尽力为大家解答. 一步一步学习Silv ...

  10. 【收藏】ASP.NET英文技术文章推荐[10/28 – 11/3]

    [1]PHP on IIS7 w/FastCGI(IIS7中的PHP和FastCGI模块) 最新版本的IIS 7.0即将随着Windows Vista一同发布,在极大增强了其主要支持的ASP.NET功 ...

最新文章

  1. 可视化解释11种基本神经网络架构
  2. 6. Oracle闪回特性
  3. 数据中心在颠覆性全球经济中的重要作用
  4. asp动态树菜单集合(3/3)
  5. ITK:来自图像的多分辨率金字塔
  6. ci框架 反向代理配置_《网站建设》Nginx配置反向代理
  7. python编程一球从100米_Python基础练习实例20(弹球问题)
  8. Python学习入门基础:注释、变量基本使用、变量的命名
  9. ecshop_商品描述远程图片自动本地化插件
  10. 瞎扯系列:判断NPN及PNP管型之右手定则
  11. Requested registry access is not allowed 解决办法
  12. PyTorch入门(一)数据集的一些基础操作
  13. python, c/c++去掉文本的换行符
  14. python如何移动图片_python 简单图像处理(3) 平移
  15. 7-18(查找) 新浪微博热门话题(30 分)
  16. 没有MsVCp140如何安装MysQl,怎样安装msvcp140.dll_msvcp140.dll安装教程
  17. 【TencentOS tiny学习】源码分析(6)——互斥锁
  18. python fun函数、求4x4整型数组的主对角线元素的和_求一个4×4的整型二维数组主对角线元素之和...
  19. Windows双屏配置(笔记本+外显示器)
  20. 荣耀8/16-年月日转换

热门文章

  1. mysql debug版本_MySQL各个版本区别
  2. 阿里巴巴开发手册强制使用SLF4J作为门面担当的秘密,被我发现了
  3. sparksql 与flinksql 建表 与 连表记录
  4. 计算机专业人才需求调研背景,计算机专业人才需求调研报告
  5. ios微信浏览器扫码进入页面加载完成失效
  6. windows11右键恢复完整右键菜单
  7. 基于社交网络分析算法(SNA)的反欺诈(二)
  8. P2P网贷平台风险分析报告
  9. 软件开发项目各阶段交付物列表
  10. 使用YYLabel做文本竖向展示