判断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" onclick="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");
发表评论
-
JSON.parse() 与 eval()
2012-01-12 11:31 16077JSON(JavaScript Object Notation ... -
jsp端自动下载并保存图片文件
2011-04-21 23:38 1552JScript code <script languag ... -
iFrame只要竖滚动条,不要横滚动条
2011-04-15 23:22 2383如题,就是在网页中,只显示右侧的垂直滚动条,而不要底部的水平滚 ... -
点击按钮保存网页中指定的图片,利用js实现
2011-04-15 00:50 4305有时候在网页上需要禁用右键菜单,但是需要点击某一按钮保存指定的 ... -
js正则验证
2011-03-31 22:47 767引用网址 http://hi.baidu.com/qui ... -
js 数组array的方法介绍
2011-03-18 00:23 832最近用到了Array就对其 ... -
ie的自动完成功能
2011-03-08 00:10 906<!DOCTYPE HTML PUBLIC " ... -
百度代码搜索,谷歌搜索
2011-03-07 23:55 925<!DOCTYPE HTML PUBLIC " ... -
Javascript的调试利器Firebug使用详解
2011-02-25 23:46 843Javascript的调试利器Firebug使用详解.doc -
IE和Firefox浏览器下javascript、CSS兼容性研究
2011-02-25 21:53 878IE和Firefox浏览器下javascript、CSS兼容性 ... -
JS验证日期时间是否合法
2011-02-17 21:00 1958/^(19|20)\d{2}-(0?\d|1[012])-(0 ... -
正则表达式的JS验证
2011-02-17 20:38 795/判断输入内容是否为空 function IsNull ... -
JS函数 验证日期合法(测试通过)
2011-02-17 20:07 1163<script type="text/java ... -
CSS 制作的三级菜单
2011-02-10 13:11 1065<html> <head> <m ... -
竖向显示,向右弹出的3级层导航菜单特效
2011-02-10 13:08 1446<!DOCTYPE html PUBLIC " ... -
CSS+JS三级滑动菜单
2011-02-10 13:06 1435<html> <head> <t ...
相关推荐
这篇文章"悟透JavaScript"很可能深入解析了JS的核心概念、语法特性和应用技巧,旨在帮助读者全面理解这门语言。 在JavaScript中,有几个关键的知识点是不容忽视的: 1. **基础语法**:包括变量(var, let, const)...
JavaScript作为Web开发必备的脚本语言,对于开发人员来说,它非常容易上手,并被数百万计的网页用来改进设计、验证表单、创建Cookies;但开发过程中经常会遇到一些莫名其妙的问题,使开发人员很头疼。本电子书汇集了...
这篇文章《JavaScript笔记》的配套代码提供了丰富的实例,旨在帮助读者深入理解和掌握JavaScript的基本概念、语法以及应用技巧。 首先,我们来看看“JS笔记”部分。在学习JavaScript时,理解变量的声明、数据类型...
生成JavaScript文章目录导航主要涉及以下几个关键知识点: 1. **HTML结构**:首先,HTML文档中需要有合适的标题元素(`<h1>`到`<h6>`),这些元素将被JavaScript解析并用于构建目录。例如,一级标题使用`<h1>`,二...
JavaScript,简称JS,是一种广泛应用于Web开发的轻量级脚本语言,由 Netscape 的 Brendan Eich 在1995年发明。它被设计用来增强网页的交互性,使用户能够与网页进行动态交流,而无需刷新页面。随着前端开发的发展,...
随后,文章推荐了一系列优质的JavaScript教程资源,从基础知识到高级特性,从入门教程到专业书籍,应有尽有。这些教程不仅详细讲解了JavaScript的语法和核心概念,还提供了丰富的示例代码和实践项目,帮助你逐步掌握...
**《关于JavaScript的好书推荐》** 这篇文章向读者介绍了几本非常适合初学者入门的JavaScript书籍。首先提到的一本书,作者并未给出具体名称,但通过描述可以推测是一本非常适合初学者用来建立对JavaScript的兴趣并...
文章带滚动效果,可以控制速度,鼠标触发机制等功能
文章旨在帮助面试者更好地准备JavaScript相关的面试,提高对JavaScript的理解和应用能力。 【适用人群】 这篇文章主要面向准备JavaScript相关面试的面试者,特别是那些对JavaScript有深入理解并希望提高面试表现的...
本项目为VS Code相关资源与技术文章的汇总设计源码,汇集了42个文件,其中包括30个PNG图片、4个Markdown文档、2个JSON文件、2个YAML文件、1个LICENSE文件、1个GIF动画、1个Sketch文件以及1个JavaScript文件。...
根据给定的信息,“JavaScript经典效果集锦”这篇文章主要介绍了多种使用JavaScript实现的网页特效与功能。下面将对文章中提及的一些经典效果进行详细介绍。 ### 1. 实现小技巧 文章开头提到了几个简单的...
本项目是基于PHP和Javascript开发的WordPress文章图片本地化插件,包含29个文件,其中包括16个PHP源代码文件、7个JavaScript脚本文件、1个LICENSE文件、1个Markdown文档文件、1个CSS样式表文件、1个SCSS样式表文件、...
本篇文章将深入探讨JavaScript语言的核心概念、语法以及JScript教程,同时还会提及fileSystemObject对象的相关知识。 首先,JavaScript语法是理解编程的基础。它采用C语言风格,包含变量声明、数据类型(如字符串、...
在文章中,我们可以看到作者使用JavaScript语言编写了一个连接Oracle实例的示例代码。这个示例代码使用了ADODB.Connection对象来连接Oracle实例,并执行了一条SELECT语句来查询数据库中的数据。 标签解释 ...
**jQuery文章底部弹出相关文章列表插件** 在网页设计中,提高用户浏览体验和页面交互性是非常重要的。本文将详细介绍一款基于jQuery和jQuery UI构建的文章底部弹出相关文章列表插件,它能够智能地在用户滚动到文章...
2. 保存离线阅读:使用浏览器的存储API(如localStorage或IndexedDB),JavaScript可以将文章内容保存在本地,方便用户在无网络连接时阅读。 3. 自定义样式:JavaScript可以改变文章的样式,如字体、背景色等,满足...
在网页设计中,提供相关的文章推荐可以增强用户体验,帮助用户发现更多感兴趣的内容。这款jQuery和CSS3结合的侧边栏滑动显示相关文章插件就是为此目的而设计的。它通过动态效果将文章的相关内容以侧边栏的形式展示,...
本压缩包"javascript经典特效---多篇文章的处理.rar"显然聚焦于如何利用JavaScript技术来处理和展示多篇文章,可能包括文章的加载、排序、搜索、分页等功能。 在JavaScript中,处理多篇文章的数据结构通常会选择...
- **定义与功能**:弹出式帮助是一种在用户需要时显示相关信息的功能,常用于提供额外的帮助或解释。 - **技术实现**: - 使用HTML的`<div>`元素结合CSS定位属性实现布局。 - JavaScript控制弹出窗口的显示与隐藏...