(value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value
} catch (e) {
return value
}
}
$.type = type
$.isFunction = isFunction
$.isWindow = isWindow
$.isArray = isArray
$.isPlainObject = isPlainObject
//空对象
$.isEmptyObject = function(obj) {
var name
for (name in obj) return false
return true
}
//获取指定的值在数组中的位置
$.inArray = function(elem, array, i) {
return emptyArray.indexOf.call(array, elem, i)
}
//将字符串转成驼峰式的格式
$.camelCase = camelize
//去字符串头尾空格
$.trim = function(str) {
return str.trim()
}
// plugin compatibility
$.uuid = 0
$.support = {}
$.expr = {}
//遍历elements,将每条记录放入callback里进宪处理,保存处理函数返回值不为null或undefined的结果
//注意这里没有统一的用for in,是为了避免遍历数据默认属性的情况,如数组的toString,valueOf
$.map = function(elements, callback) {
var value, values = [],
i, key
//如果被遍历的数据是数组或者nodeList
if (likeArray(elements)) for (i = 0; i < elements.length; i++) {
value = callback(elements[i], i)
if (value != null) values.push(value)
} else
//如果是对象
for (key in elements) {
value = callback(elements[key], key)
if (value != null) values.push(value)
}
return flatten(values)
}
//遍历数组,将每条数据作为callback的上下文,并传入数据以及数据的索引进行处理,如果其中一条数据的处理结果明确返回false,
//则停止遍历,并返回elements
$.each = function(elements, callback) {
var i, key
if (likeArray(elements)) {
for (i = 0; i < elements.length; i++)
if (callback.call(elements[i], i, elements[i]) === false) return elements
} else {
for (key in elements)
if (callback.call(elements[key], key, elements[key]) === false) return elements
}
return elements
}
//过滤
$.grep = function(elements, callback) {
return filter.call(elements, callback)
}
if (window.JSON) $.parseJSON = JSON.parse
// Populate the class2type map
//填充class2type的值
$.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type["[object " + name + "]"] = name.toLowerCase()
})
//针对DOM的一些操作
// Define methods that will be available on all
// Zepto collections
$.fn = {
// Because a collection acts like an array
// copy over these useful array functions.
forEach: emptyArray.forEach,
reduce: emptyArray.reduce,
push: emptyArray.push,
sort: emptyArray.sort,
indexOf: emptyArray.indexOf,
concat: emptyArray.concat,
// `map` and `slice` in the jQuery API work differently
// from their array counterparts
map: function(fn) {
return $($.map(this, function(el, i) {
return fn.call(el, i, el)
}))
},
slice: function() {
return $(slice.apply(this, arguments))
},
//DOM Ready
ready: function(callback) {
if (readyRE.test(document.readyState)) callback($)
else document.addEventListener('DOMContentLoaded', function() {
callback($)
}, false)
return this
},
//取集合中对应指定索引的值,如果idx小于0,则idx等于idx+length,length为集合的长度
get: function(idx) {
return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
},
//将集合转换为数组
toArray: function() {
return this.get()
},
//获取集合长度
size: function() {
return this.length
},
//将集合从dom中删除
remove: function() {
return this.each(function() {
if (this.parentNode != null) this.parentNode.removeChild(this)
})
},
//遍历集合,将集合中的每一项放入callback中进行处理,去掉结果为false的项,注意这里的callback如果明确返回false
//那么就会停止循环了
each: function(callback) {
emptyArray.every.call(this, function(el, idx) {
return callback.call(el, idx, el) !== false
})
return this
},
//过滤集合,返回处理结果为true的记录
filter: function(selector) {
//this.not(selector)取到需要排除的集合,第二次再取反(这个时候this.not的参数就是一个集合了),得到想要的集合
if (isFunction(selector)) return this.not(this.not(selector))
//filter收集返回结果为true的记录
return $(filter.call(this, function(element) {
return zepto.matches(element, selector) //当element与selector匹配,则收集
}))
},
//将由selector获取到的结果追加到当前集合中
add: function(selector, context) {
return $(uniq(this.concat($(selector, context)))) //追加并去重
},
//返回集合中的第1条记录是否与selector匹配
is: function(selector) {
return this.length > 0 && zepto.matches(this[0], selector)
},
//排除集合里满足条件的记录,接收参数为:css选择器,function, dom ,nodeList
not: function(selector) {
var nodes = []
//当selector为函数时,safari下的typeof odeList也是function,所以这里需要再加一个判断selector.call !== undefined
if (isFunction(selector) && selector.call !== undefined) {
this.each(function(idx) {
//注意这里收集的是selector.call(this,idx)返回结果为false的时候记录
if (!selector.call(this, idx)) nodes.push(this)
})
} else {
//当selector为字符串的时候,对集合进行筛选,也就是筛选出集合中满足selector的记录
var excludes = typeof selector == 'string' ? this.filter(selector) :
//当selector为nodeList时执行slice.call(selector),注意这里的isFunction(selector.item)是为了排除selector为数组的情况
//当selector为css选择器,执行$(selector)
(likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
this.forEach(function(el) {
//筛选出不在excludes集合里的记录,达到排除的目的
if (excludes.indexOf(el) < 0) nodes.push(el)
})
}
return $(nodes) //由于上面得到的结果是数组,这里需要转成zepto对象,以便继承其它方法,实现链写
},
/*
接收node和string作为参数,给当前集合筛选出包含selector的集合
isObject(selector)是判断参数是否是node,因为typeof node == 'object'
当参数为node时,只需要判读当前记当里是否包含node节点即可
当参数为string时,则在当前记录里查询selector,如果长度为0,则为false,filter函数就会过滤掉这条记录,否则保存该记录
*/
has: function(selector) {
return this.filter(function() {
return isObject(selector) ? $.contains(this, selector) : $(this).find(selector).size()
})
},
/*
选择集合中指定索引的记录,当idx为-1时,取最后一个记录
*/
eq: function(idx) {
return idx === -1 ? this.slice(idx) : this.slice(idx, +idx + 1)
},
/*
取集合中的第一条记录
*/
first: function() {
var el = this[0] //取集合中的第一条记录
//如果集合中的第一条数据本身就已经是zepto对象则直接返回本身,否则转成zepto对象
//el && !isObject(el)在这里取到一个判断el是否为节点的情况,因为如果el是节点,那么isObject(el)的结果就是true
return el && !isObject(el) ? el : $(el)
},
/*
取集合中的最后一条记录
*/
last: function() {
var el = this[this.length - 1] //取集合中的最后一条记录
//如果el为node,则isObject(el)会为true,需要转成zepto对象
return el && !isObject(el) ? el : $(el)
},
/*
在当前集合中查找selector,selector可以是集合,选择器,以及节点
*/
find: function(selector) {
var result, $this = this
//如果selector为node或者zepto集合时
if (typeof selector == 'object')
//遍历selector,筛选出父级为集合中记录的selector
result = $(selector).filter(function() {
var node = this
//如果$.contains(parent, node)返回true,则emptyArray.some也会返回true,外层的filter则会收录该条记录
return emptyArray.some.call($this, function(parent) {
return $.contains(parent, node)
})
})
//如果selector是css选择器
//如果当前集合长度为1时,调用zepto.qsa,将结果转成zepto对象
else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
//如果长度大于1,则调用map遍历
else result = this.map(function() {
return zepto.qsa(this, selector)
})
return result
},
//取集合中第一记录的最近的满足条件的父级元素
closest: function(selector, context) {
var node = this[0],
collection = false
if (typeof selector == 'object') collection = $(selector)
//当selector是node或者zepto集合时,如果node不在collection集合中时需要取node.parentNode进行判断
//当selector是字符串选择器时,如果node与selector不匹配,则需要取node.parentNode进行判断
while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))
//当node 不是context,document的时候,取node.parentNode
node = node !== context && !isDocument(node) && node.parentNode
return $(node)
},
//取集合所有父级元素
parents: function(selector) {
var ancestors = [],
nodes = this
//通过遍历nodes得到所有父级,注意在while里nodes被重新赋值了
//本函数的巧妙之处在于,不停在获取父级,再遍历父级获取父级的父级
//然后再通过去重,得到最终想要的结果,当到达最顶层的父级时,nodes.length就为0了
while (nodes.length > 0)
//nodes被重新赋值为收集到的父级集合
nodes = $.map(nodes, function(node) {
//遍历nodes,收集集合的第一层父级
//ancestors.indexOf(node) < 0用来去重复
if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {
ancestors.push(node) //收集已经获取到的父级元素,用于去重复
return node
}
})
//上面还只是取到了所有的父级元素,这里还需要对其进行筛选从而得到最终想要的结果
return filtered(ancestors, selector)
},
//获取集合的父节点
parent: function(selector) {
return filtered(uniq(this.pluck('parentNode')), selector)
},
children: function(selector) {
return filtered(this.map(function() {
return children(this)
}), selector)
},
contents: function() {
return this.map(function() {
return slice.call(this.childNodes)
})
},
siblings: function(selector) {
return filtered(this.map(function(i, el) {
//先获取该节点的父节点中的所有子节点,再排除本身
return filter.call(children(el.parentNode), function(child) {
return child !== el
})
}), selector)
},
empty: function() {
return this.each(function() {
this.innerHTML = ''
})
},
//根据属性来获取当前集合的相关集合
pluck: function(property) {
return $.map(this, function(el) {
return el[property]
})
},
show: function() {
return this.each(function() {
//清除元素的内联display="none"的样式
this.style.display == "none" && (this.style.display = null)
//当样式表里的该元素的display样式为none时,设置它的display为默认值
if (getComputedStyle(this, '').getPropertyValue("display") == "none") this.style.display = defaultDisplay(this.nodeName) //defaultDisplay是获取元素默认display的方法
})
},
replaceWith: function(newContent) {
//将要替换的内容插入到被替换的内容前面,然后删除被替换的内容
return this.before(newContent).remove()
},
wrap: function(structure) {
var func = isFunction(structure)
if (this[0] && !func)
//如果structure是字符串,则将其转成DOM
var dom = $(structure).get(0),
//如果structure是已经存在于页面上的节点或者被wrap的记录不只一条,则需要clone dom
clone = dom.parentNode
关键词:zepto是啥