Skip to content

Commit

Permalink
Merge branch 'master' of github.com:MatthewMueller/cheerio
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewmueller committed Jan 29, 2013
2 parents e60766d + 4e16eac commit 62b2186
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 68 deletions.
5 changes: 4 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ $('#fruits').children('.pear').text()
```

#### .each( function(index, element) )
Iterates over a cheerio object, executing a function for each matched element. When the callback is fired, the function is fired in the context of the DOM element, so `this` refers to the current element, which is equivalent to the function parameter `element`.
Iterates over a cheerio object, executing a function for each matched element. When the callback is fired, the function is fired in the context of the DOM element, so `this` refers to the current element, which is equivalent to the function parameter `element`. To break out of the `each` loop early, return with `false`.

```js
var fruits = [];
Expand Down Expand Up @@ -507,6 +507,9 @@ $.dom()
// }]
```

#### $.contains( container, contained )
Checks to see if the `contained` DOM element is a descendent of the `container` DOM element.

#### $.isArray( array )
Checks to see the passed argument is an array.

Expand Down
28 changes: 14 additions & 14 deletions lib/api/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ var _ = require('underscore'),
rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i;


function setAttr(el, name, value) {
if(typeof name === 'object') return _.extend(el.attribs, name);
var setAttr = function(el, name, value) {
if (typeof name === 'object') return _.extend(el.attribs, name);

if(value === null) {
if (value === null) {
removeAttribute(el, name);
} else {
el.attribs[name] = encode(value);
}

return el.attribs;
}
};

var attr = exports.attr = function(name, value) {
var elem = this[0];
Expand All @@ -33,19 +33,19 @@ var attr = exports.attr = function(name, value) {

// Return the entire attribs object if no attribute specified
if (!name) {
for(var a in elem.attribs) {
for (var a in elem.attribs) {
elem.attribs[a] = decode(elem.attribs[a]);
}
return elem.attribs;
}

// Set the value (with attr map support)
if(typeof name === 'object' || value !== undefined) {
if (typeof name === 'object' || value !== undefined) {
this.each(function(i, el) {
el.attribs = setAttr(el, name, value);
});
return this;
} else if(Object.hasOwnProperty.call(elem.attribs, name)) {
} else if (Object.hasOwnProperty.call(elem.attribs, name)) {
// Get the (decoded) attribute
return decode(elem.attribs[name]);
}
Expand All @@ -55,15 +55,15 @@ var attr = exports.attr = function(name, value) {
* Remove an attribute
*/

function removeAttribute(elem, name) {
var removeAttribute = function(elem, name) {
if (!isTag(elem.type) || !elem.attribs || !Object.hasOwnProperty.call(elem.attribs, name))
return;

if (rboolean.test(elem.attribs[name]))
elem.attribs[name] = false;
else
delete elem.attribs[name];
}
};


var removeAttr = exports.removeAttr = function(name) {
Expand Down Expand Up @@ -126,11 +126,11 @@ var addClass = exports.addClass = function(value) {
};

var removeClass = exports.removeClass = function(value) {
var classes = split(value);
var split = function(className) {
return className ? className.trim().split(rspace) : [];
};

function split(className) {
return !className ? [] : className.trim().split(rspace);
}
var classes = split(value);

// Handle if value is a function
if (_.isFunction(value)) {
Expand All @@ -140,7 +140,7 @@ var removeClass = exports.removeClass = function(value) {
}

return this.each(function(i, el) {
if(!isTag(el)) return;
if (!isTag(el)) return;
el.attribs['class'] = (!value) ? '' : _.reject(
split(el.attribs['class']),
function(name) { return _.contains(classes, name); }
Expand Down
14 changes: 7 additions & 7 deletions lib/api/manipulation.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ var html = exports.html = function(str) {

var toString = exports.toString = function() {
return $.html(this);
}
};

var text = exports.text = function(str) {
// If `str` blank or an object
Expand All @@ -168,12 +168,12 @@ var text = exports.text = function(str) {
}

var elem = {
data : encode(str),
type : 'text',
parent : null,
prev : null,
next : null,
children : []
data: encode(str),
type: 'text',
parent: null,
prev: null,
next: null,
children: []
};

// Append text node to each selected elements
Expand Down
26 changes: 16 additions & 10 deletions lib/api/traversing.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,28 @@ var siblings = exports.siblings = function(elem) {
};

var children = exports.children = function(selector) {
if (!this[0] || !this[0].children) return this;

var children = _.filter(this[0].children, function(elem) {
return (isTag(elem));
});
var elems = _.reduce(this, function(memo, elem) {
return memo.concat(_.filter(elem.children, isTag));
}, []);

if (selector === undefined) return this.make(children);
else if (_.isNumber(selector)) return this.make(children[selector]);
if (selector === undefined) return this.make(elems);
else if (_.isNumber(selector)) return this.make(elems[selector]);

return this.make(children).filter(selector);
return this.make(elems).filter(selector);
};

var each = exports.each = function(fn) {
_.each(this, function(el, i) {
fn.call(this.make(el), i, el);
}, this);
var length = this.length,
el, i;

for (i = 0; i < length; ++i) {
el = this[i];
if (fn.call(this.make(el), i, el) === false) {
break;
}
}

return this;
};

Expand Down
38 changes: 19 additions & 19 deletions lib/cheerio.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,33 +33,33 @@ var $ = require('./static');
*/

var Cheerio = module.exports = function(selector, context, root) {
if(!(this instanceof Cheerio)) return new Cheerio(selector, context, root);
if (!(this instanceof Cheerio)) return new Cheerio(selector, context, root);

// $(), $(null), $(undefined), $(false)
if(!selector) return this;
if (!selector) return this;

if(root) {
if(typeof root === 'string') root = parse(root);
if (root) {
if (typeof root === 'string') root = parse(root);
this._root = this.make(root, this);
}

// $($)
if(selector.cheerio) return selector;
if (selector.cheerio) return selector;

// $(dom)
if(selector.name || isArray(selector))
if (selector.name || isArray(selector))
return this.make(selector, this);

// $(<html>)
if(typeof selector === 'string' && isHtml(selector)) {
if (typeof selector === 'string' && isHtml(selector)) {
return this.make(parse(selector).children);
}

// If we don't have a context, maybe we have a root, from loading
if(!context) {
if (!context) {
context = this._root;
} else if(typeof context === 'string') {
if(isHtml(context)) {
} else if (typeof context === 'string') {
if (isHtml(context)) {
// $('li', '<ul>...</ul>')
context = parse(context);
context = this.make(context, this);
Expand All @@ -71,7 +71,7 @@ var Cheerio = module.exports = function(selector, context, root) {
}

// If we still don't have a context, return
if(!context) return this;
if (!context) return this;

// #id, .class, tag
return context.parent().find(selector);
Expand All @@ -94,9 +94,9 @@ Cheerio.prototype.cheerio = '[cheerio object]';
*/

Cheerio.prototype.options = {
ignoreWhitespace : false,
xmlMode : false,
lowerCaseTags : false
ignoreWhitespace: false,
xmlMode: false,
lowerCaseTags: false
};

/*
Expand All @@ -109,23 +109,23 @@ Cheerio.prototype.sort = [].splice;
/*
* Check if string is HTML
*/
function isHtml(str) {
var isHtml = function(str) {
// Faster than running regex, if str starts with `<` and ends with `>`, assume it's HTML
if ( str.charAt(0) === "<" && str.charAt( str.length - 1 ) === ">" && str.length >= 3 ) return true;
if (str.charAt(0) === '<' && str.charAt(str.length - 1) === '>' && str.length >= 3) return true;

// Run the regex
var match = quickExpr.exec(str);
return !!(match && match[1]);
}
};

/*
* Make a cheerio object
*/

Cheerio.prototype.make = function(dom, context) {
if(dom.cheerio) return dom;
if (dom.cheerio) return dom;
dom = (_.isArray(dom)) ? dom : [dom];
return _.extend(context || new Cheerio(), dom, { length : dom.length });
return _.extend(context || new Cheerio(), dom, { length: dom.length });
};

/**
Expand Down
16 changes: 8 additions & 8 deletions lib/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ exports = module.exports = function(content, options) {

// Generic root element
var root = {
type : 'root',
name : 'root',
parent : null,
prev : null,
next : null,
children : []
type: 'root',
name: 'root',
parent: null,
prev: null,
next: null,
children: []
};

// Update the dom using the root
Expand Down Expand Up @@ -84,8 +84,8 @@ var update = exports.update = function(arr, parent) {

// Update neighbors
for (var i = 0; i < arr.length; i++) {
arr[i].prev = arr[i-1] || null;
arr[i].next = arr[i+1] || null;
arr[i].prev = arr[i - 1] || null;
arr[i].next = arr[i + 1] || null;
arr[i].parent = parent || null;
}

Expand Down
12 changes: 6 additions & 6 deletions lib/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ var singleTag = {
Tag types from htmlparser
*/
var tagType = {
tag : 1,
script : 1,
link : 1,
style : 1,
template : 1
tag: 1,
script: 1,
link: 1,
style: 1,
template: 1
};

render = module.exports = function(dom, opts) {
var render = module.exports = function(dom, opts) {
dom = (isArray(dom) || dom.cheerio) ? dom : [dom];
opts = opts || {};

Expand Down
26 changes: 24 additions & 2 deletions lib/static.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ var load = exports.load = function(str, options) {
var Cheerio = require('./cheerio'),
root = parse(str, options);

function initialize(selector, context, r) {
var initialize = function(selector, context, r) {
return new Cheerio(selector, context, r || root);
}
};

// Add in the static methods
initialize.__proto__ = exports;
Expand Down Expand Up @@ -71,3 +71,25 @@ var text = exports.text = function(elems) {
var root = exports.root = function() {
return this(this._root);
};

/**
* $.contains()
*/
var contains = exports.contains = function(container, contained) {

// According to the jQuery API, an element does not "contain" itself
if (contained === container) {
return false;
}

// Step up the descendents, stopping when the root element is reached
// (signaled by `.parent` returning a reference to the same object)
while (contained && contained !== contained.parent) {
contained = contained.parent;
if (contained === container) {
return true;
}
}

return false;
};
2 changes: 1 addition & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var entities = require('entities');
* HTML Tags
*/

var tags = { tag : true, script : true, style : true };
var tags = { tag: true, script: true, style: true };

/**
* Check if the DOM element is a tag
Expand Down
Loading

0 comments on commit 62b2186

Please sign in to comment.