jqfree core

var $ = function(selector, context) {

return new $.fn.init(selector, context);

};

$.fn = $.prototype;

$.fn.init = function(selector, context) {

if (selector.nodeType === 1) {

this[0] = selector;

this.length = 1;

return this;

}

var parent = context || document;

var nodeList = parent.querySelectorAll(selector);

this.length = nodeList.length;

for (var i=0; i<this.length; i+=1) {

this[i] = nodeList[i];

}

return this;

};

$.fn.init.prototype = $.fn;

我们需要一个包装着DOM Elements的伪数组,此伪数组对象使用原型链去挂载共享的DOM处理方法,原理如下图。

//选择器

$('body'); //返回$.fn.init {0: body, length: 1, selector: "body"}

$('.class');

$('#id');

$('#id .class');

extend

jqfree中的extend函数参照了prototype.js的实现方式,$.extend和$.fn.extend功能相同,也都是通过浅拷贝的方式,把第二个参数上的对象扩展添加到第二个参数的对象上,如果没有指定第二个参数,则会把第一个参数添加到this上。需要给DOM元素添加方法的话,使用$.fn.extend如$.fn.append,而需要给全局$对象添加扩展的话,使用$.extend,如$.ajax。

$.extend = $.fn.extend = function (destination, source) {

//if source is not exist,copy the destination to this。

if (typeof source === 'undefined') {

source = destination;

destination = this;

}

for (var property in source) {

if (source.hasOwnProperty(property)) {

destination[property] = source[property];

}

}

return destination;

};

traverse

遍历jqfree对象中的DOM Elements。实际上是遍历了$.fn.init {0: body, length: 1, selector: "body"}这样的一个伪数组中的类似数组的那一部分。

$.fn.extend({

each: function (func) {

var i=0,

length = this.length;

for (; i<length; i+=1) {

func.call(this[i], this[i], i);

}

return this;

},

});

接受一个回调函数,其第一个参数为dom元素,第二个参数为序号,调用代码如

$('body').each(function(val, index){

console.log(val, index)

});

DOM processor。

文档操作。添加了append,prepend,remove,empty的方法,功用同原版jquery。因为生成的$.fn.init是个包含DOM的伪数组,所以操作中就需要遍历这个数组做append操作,目的是为了让选中的所有DOM元素都append一遍。appendChild为DOM level2方法,从IE6开始就支持。

$.fn.extend({

append: function (child) {

if ($.isString(child)) {

child = $(child)[0];

}

this.each(function(v, k) {

v.appendChild(child);

});

child = null;

return this;

},

});

调用代码如

var element = document.createElement('div');

$('body').append(element);

css

添加了css的方法,功用同原版jquery。现将css规则转为驼峰式,然后利用style属性插入,如 padding: 0px; max-width: 100%; clear: both; min-height: 1em; white-space: pre-wrap; color: rgb(62, 62, 62); font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; font-size: 16px; line-height: 25.6px; box-sizing: border-box !important; word-wrap: break-word !important;">

$.fn.extend({

css: function (cssRules, value) {

//中划线转为驼峰式

var transformHump = function (name) {

return name.replace(/\-(\w)/g, function(all, letter){

return letter.toUpperCase();

});

};

if ($.isString(cssRules)) {

if ($.isUndefined(value)) {

return this[0].style[transformHump(cssRules)];

} else {

this[0].style[transformHump(cssRules)] = value;

}

} else {

for (var i in cssRules) {

this[0].style[transformHump(i)] = cssRules[i];

}

}

return this;

},

});

支持两种写法,参数1和参数2可以互为键值对,或者参数1为一个对象,另外这里只第一个dom元素的css规则生效。调用代码如

//设置第一个body元素的color值

$('body').css('color', '#FFF');

$('body').css({

color: '#FFF',

background: 'green'

});

DOM filter

添加了dom过滤的几个函数,如children、parent、siblings。返回出去的DOM对象会再次被$.fn.init对象包装。

$.fn.extend({

children: function (selector) {

return $(selector, this[0]);

}

});

只对第一个DOM元素生效,调用代码如下:

$('body').children('.class'); //获取第一个body元素下的所有class名为'.class'的元素

attributes

获取属性,实现了attr,removeAttr,addClass,hasClass,removeClass,data,html这几个api,功能和jq相似。 拿addClass举例来说,classList为H5的API,不支持IE9及以下。所有被匹配的dom元素都会被addClass处理。

$.fn.extend({

addClass: function (className) {

this.each(function(v, k) {

//please use 'v.className += className' if you need support IE9.

v.classList.add(className);

});

return this;

},

});

调用方式如下:

$('body').addClass('someClass');

event

事件操作。绑定事件使用on,取消绑定事件使用off,触发事件使用trigger。拿on举例,直接使用了addEventListener监听,不支持IE8及以下。需要支持IE8级以下的话,请使用attachEvent兼容。

$.fn.extend({

on: function (event, func) {

this.each(function(v, k) {

//dom level 2,IE8 not support。

v.addEventListener(event, func, false);

});

return this;

},

});

第一个参数为事件名,第二个参数为回调,调用代码如下:

$('body').on('click', function(e){

console.log('click');

})

effect

其他效果,鉴于动画用css3会更直观,所以这里只实现了show和hide两个方法。所有匹配的DOM元素都会被影响,这里只是简单设置了display属性为block或者none,有待改进。

$.fn.extend({

show: function() {

this.each(function() {

this.style.display = 'block';

});

return this;

},

});

调用代码如下:

$('body').hide();

ajax

抽离jsonp,$.jsonp独立于$.ajax,毕竟jsonp的原理和ajax完全没有关系,如果使用$.ajax的话有些误导别人。 $.ajax和$.jsonp方法最后都会返回一个Promise对象,此Promise参照了这里的方案。

$.ajax只接受一个对象作为参数,并且支持使用promise的写法,调用如下

$.ajax({

url: '/test.json'

})

.then(function (d) {

console.log(d);

return $.ajax({

url: '/test.json'

})

}, function (d) {

console.log(d);

})

.then(function (d) {

console.log(d);

}, function (d) {

console.log(d);

});

$.jsonp({

url: '/test.json',

})

.then(function (d) {

console.log(d);

return $.jsonp({

url: '/test.json'

})

}, function (d) {

console.log(d);

})

.then(function (d) {

console.log(d);

}, function (d) {

console.log(d);

});

注意,本地没法测试ajax函数,如果有需要请在此项目目录下运行node server.js,接着去打开test.html文件的关于ajax的注释,再去localhost:3000/test.html就能看到测试ajax的内容。

cookie

将增删改查cookie操作都用一个函数搞定

$.extend({

cookie: function (cookieName, cookieValue, day) {

var readCookie = function (name) {

var arr,

reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'),

matched = document.cookie.match(reg);

if(arr = matched) {

return unescape(arr[2]);

} else {

return null;

}

};

var setCookie = function (name, value, time) {

var Days = time || 30;

var exp = new Date();

exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);

document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();

};

if (cookieName && cookieValue) {

//set cookie

setCookie(cookieName, cookieValue, day);

} else if (cookieName && $.isNull(cookieValue)) {

//delete cookie

setCookie(cookieName, '', -1);

} else if (cookieName) {

//read cookie

return readCookie(cookieName);

}

}

});

调用代码如下:

//添加cookie,前两个参数为cookie名和值,必填。第三个参数设置cookie有效时常,单位为天,可选。

$.cookie('test', 'content');

//读取cookie,只填第一个参数

$.cookie('test'); //"content"

//删除cookie, 第二个参数填null

$.cookie('test', null);

utils

添加了变量类型判断、时间解析函数、url解析函数、浮点数四舍五入小数位和获取随机位数字符串的辅助函数。

$.extend({

isUndefined: function(obj) {

return obj === void 0;

},

isNull: function(obj) {

return obj === null;

},

isBoolean: function(obj) {

return Object.prototype.toString.call(obj) === '[object Boolean]';

},

isNumber: function(obj) {

return Object.prototype.toString.call(obj) === '[object Number]';

},

isString: function(obj) {

return Object.prototype.toString.call(obj) === '[object String]';

},

isNaN: function(obj) {

return obj !== obj;

},

isFunction: function(obj) {

return typeof obj === 'function';

},

......

});

$.extend({

//$.parseTime(new Date().getTime(), 'YYYY-MM-DD hh:mm:ss')

//result: "2016-08-03 16:14:12"

parseTime: function (timeStamp, format) {

var date = new Date(timeStamp);

var o = {

'M+' : date.getMonth() + 1, //month

'D+' : date.getDate(), //day

'h+' : date.getHours(), //hour

'm+' : date.getMinutes(), //minute

's+' : date.getSeconds(), //second

'S' : date.getMilliseconds() //millisecond

}

if(/(Y+)/.test(format)) {

format = format.replace(RegExp.$1,

(date.getFullYear() + '').substr(4 - RegExp.$1.length));

}

for(var k in o) {

if (new RegExp('('+ k +')').test(format)) {

format = format.replace(RegExp.$1,

RegExp.$1.length == 1 ? o[k] : ('00'+ o[k]).substr((''+ o[k]).length));

}

}

return format;

},

//$.parseUrl(location.href)

//return an object contains the folling info.

parseUrl: function (url) {

var a =  document.createElement('a');

a.href = url;

return {

source: url,

protocol: a.protocol.replace(':',''),

host: a.hostname,

port: a.port,

query: a.search,

params: (function(){

var ret = {},

seg = a.search.replace(/^\?/,'').split('&'),

len = seg.length, i = 0, s;

for (;i<len;i++) {

if (!seg[i]) { continue; }

s = seg[i].split('=');

ret[s[0]] = s[1];

}

return ret;

})(),

file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],

hash: a.hash.replace('#',''),

path: a.pathname.replace(/^([^\/])/,'/$1'),

relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],

segments: a.pathname.replace(/^\//,'').split('/')

};

},

//$.toFixedFloat(15.658, 2)

//result: 15.66

toFixedFloat: function (value, precision) {

var power = Math.pow(10, precision || 0);

return String(Math.round(value * power) / power);

},

//for generate random string

//$.generateRandomAlphaNum(5)

//random result: like "rc3sr".

generateRandomAlphaNum: function (len) {

var rdmString = '';

for (; rdmString.length < len; rdmString += Math.random().toString(36).substr(2));

return rdmString.substr(0, len);

}

});

调用如下:

//参数1是时间戳,参数2是格式,年为Y,月为M,日为D,时h,分m,秒s,毫秒S,注意大小写,多余的位数补0

$.parseTime(new Date().getTime(), 'YYYY-MM-DD hh:mm:ss'); //"2016-08-03 16:14:12"。

//参数为url链接

$.parseUrl(location.href); //返回一个带诸多url信息的对象。

//参数1是目标浮点数,参数2是保留到第几位小数

$.toFixedFloat(15.658, 2); //四舍五入到两位小数:15.66

//参数为生成随机的字符串长度

$.generateRandomAlphaNum(5); //如"rc3sr"

最新文章

  1. HDU 4006 优先队列
  2. Java Map操作
  3. python中cPickle的用法
  4. DEDE5.7如何制作网站地图?
  5. DFS-HDU 1312 -Red and Black
  6. [书目20131114]微软技术丛书•快速软件开发(珍藏版) Rapid Development Taming Wild Software Schedules By Steve McConnell
  7. Eclipse 中使用Genymotion 作为模拟器的步骤
  8. 用PYTHON实现将电脑里的所有文件按大小排序,便于清理
  9. cf B. Fence
  10. Minix
  11. 获得view所在的控制器
  12. MFC TCHAR 和CHAR相互转换
  13. Android与js交互实例
  14. python常用正则表达式
  15. laradock
  16. django数据库连接快速配置
  17. nginx配置文件注释说明
  18. ueditor 使用
  19. ionic_ Network connectivity error occurred, are you offline?
  20. Grunt新手入门篇

热门文章

  1. 20145202马超 实验二《Java面向对象程序设计》实验报告
  2. oracle 11g XE 学习版添加scott用户方法全步骤
  3. windows 系统禁止使用 U 盘的方法
  4. 类的__new__方法使用
  5. L007- linux系统优化进阶课堂小节
  6. linq里lambda写的join查询,并附加动态拼接的条件,条件为enum类型的查询
  7. Sqlite Datetime类型详解
  8. Python网络编程(socketserver、TFTP云盘、HTTPServer服务器模型)
  9. ContOS软件包安装【零】
  10. 1030 Travel Plan (30 分)(最短路径 and dfs)