Permalink
Browse files

more robust object type checks, taken from jQuery

This fixes operating on DOM elements within iframe.

Fixes #667

Thanks:
* John Resig
* John-David Dalton
* Rafaël Blais Masson
* Robert Katić
* Ariel Flesler
  • Loading branch information...
1 parent b51d6d7 commit b451f22d3d956f379f241cdf2f82fec70af609f1 @mislav mislav committed Dec 23, 2012
Showing with 61 additions and 13 deletions.
  1. +37 −13 src/zepto.js
  2. +24 −0 test/zepto.html
View
@@ -28,7 +28,8 @@ var Zepto = (function() {
classSelectorRE = /^\.([\w-]+)$/,
idSelectorRE = /^#([\w-]*)$/,
tagSelectorRE = /^[\w-]+$/,
- toString = {}.toString,
+ class2type = {},
+ toString = class2type.toString,
zepto = {},
camelize, uniq,
tempParent = document.createElement('div')
@@ -46,10 +47,17 @@ var Zepto = (function() {
return match
}
- function isFunction(value) { return toString.call(value) == "[object Function]" }
- function isObject(value) { return value instanceof Object }
- function isPlainObject(value) {
- return isObject(value) && value != window && value.__proto__ == Object.prototype
+ function type(obj) {
+ return obj == null ? String(obj) :
+ class2type[toString.call(obj)] || "object"
+ }
+
+ function isFunction(value) { return type(value) == "function" }
+ function isWindow(obj) { return obj != null && obj == obj.window }
+ function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }
+ function isObject(obj) { return type(obj) == "object" }
+ function isPlainObject(obj) {
+ return isObject(obj) && !isWindow(obj) && obj.__proto__ == Object.prototype
}
function isArray(value) { return value instanceof Array }
function likeArray(obj) { return typeof obj.length == 'number' }
@@ -201,7 +209,7 @@ var Zepto = (function() {
// This method can be overriden in plugins.
zepto.qsa = function(element, selector){
var found
- return (element === document && idSelectorRE.test(selector)) ?
+ return (isDocument(element) && idSelectorRE.test(selector)) ?
( (found = element.getElementById(RegExp.$1)) ? [found] : [] ) :
(element.nodeType !== 1 && element.nodeType !== 9) ? [] :
slice.call(
@@ -259,11 +267,18 @@ var Zepto = (function() {
}
}
+ $.type = type
$.isFunction = isFunction
$.isObject = isObject
$.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)
}
@@ -310,6 +325,11 @@ var Zepto = (function() {
if (window.JSON) $.parseJSON = JSON.parse
+ // Populate the class2type map
+ $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase()
+ })
+
// Define methods that will be available on all
// Zepto collections
$.fn = {
@@ -409,14 +429,14 @@ var Zepto = (function() {
closest: function(selector, context){
var node = this[0]
while (node && !zepto.matches(node, selector))
- node = node !== context && node !== document && node.parentNode
+ node = node !== context && !isDocument(node) && node.parentNode
return $(node)
},
parents: function(selector){
var ancestors = [], nodes = this
while (nodes.length > 0)
nodes = $.map(nodes, function(node){
- if ((node = node.parentNode) && node !== document && ancestors.indexOf(node) < 0) {
+ if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {
ancestors.push(node)
return node
}
@@ -679,12 +699,13 @@ var Zepto = (function() {
// Generate the `width` and `height` functions
;['width', 'height'].forEach(function(dimension){
$.fn[dimension] = function(value){
- var offset, Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() })
- if (value === undefined) return this[0] == window ? window['inner' + Dimension] :
- this[0] == document ? document.documentElement['offset' + Dimension] :
+ var offset, el = this[0],
+ Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() })
+ if (value === undefined) return isWindow(el) ? el['inner' + Dimension] :
+ isDocument(el) ? el.documentElement['offset' + Dimension] :
(offset = this.offset()) && offset[dimension]
else return this.each(function(idx){
- var el = $(this)
+ el = $(this)
el.css(dimension, funcArg(this, value, idx, el[dimension]()))
})
}
@@ -702,7 +723,10 @@ var Zepto = (function() {
$.fn[operator] = function(){
// arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
- var nodes = $.map(arguments, function(n){ return isObject(n) ? n : zepto.fragment(n) }),
+ var argType, nodes = $.map(arguments, function(arg) {
+ argType = type(arg)
+ return argType == "object" || argType == "array" ? arg : zepto.fragment(arg)
+ }),
parent, copyByClone = this.length > 1
if (nodes.length < 1) return this
View
@@ -226,6 +226,8 @@
<svg></svg>
+ <iframe src="fixtures/iframe_document.html"></iframe>
+
</div><!-- fixtures -->
<script>
@@ -562,6 +564,20 @@
t.assertEqual(Node.DOCUMENT_FRAGMENT_NODE, documentFragment.get(0).nodeType)
},
+ testDollarWithElementInIframe: function(t){
+ var iframe = $('#fixtures iframe').get(0),
+ iframeWin = iframe.contentWindow,
+ iframeDoc = iframe.contentDocument,
+ iframeBody = iframeDoc.body,
+ iframeEl = $(iframeBody).find('b')
+
+ t.assertIdentical(iframeWin, $(iframeWin).get(0))
+ t.assertIdentical(iframeDoc, $(iframeDoc).get(0))
+ t.assertIdentical(iframeBody, $(iframeBody).get(0))
+ t.assertEqual('B', iframeEl.pluck('tagName').join(','))
+ t.assertEqual('Hello from iframe!', iframeEl.text())
+ },
+
testDollarWithFragment: function(t){
var fragment = $("<div>")
t.assertLength(1, fragment)
@@ -1021,6 +1037,14 @@
t.assertEqualCollection($(expected), $('#li2').parents('ul'))
},
+ testParentsIframe: function(t){
+ var iframeBody = $('iframe').get(0).contentDocument.body
+ t.assertEqualCollection(
+ [iframeBody, iframeBody.parentNode],
+ $(iframeBody).find('b').first().parents()
+ )
+ },
+
testParent: function(t){
var el = $('#li1')
t.assertEqualCollection($('#parents'), el.parent())

0 comments on commit b451f22

Please sign in to comment.