cheerio = function (selector, context, root, options) { if (!(this instanceof Cheerio)) return new Cheerio(selector, context, root, options); this.options = _.defaults(options || {}, this.options); // $(), $(null), $(undefined), $(false) if (!selector) return this; if (root) { if (typeof root === 'string') root = parse(root, this.options); this._root = Cheerio.call(this, root); } // $($) if (selector.cheerio) return selector; // $(dom) if (isNode(selector)) selector = [selector]; // $([dom]) if (Array.isArray(selector)) { _.forEach(selector, _.bind(function(elem, idx) { this[idx] = elem; }, this)); this.length = selector.length; return this; } // $(<html>) if (typeof selector === 'string' && isHtml(selector)) { return Cheerio.call(this, parse(selector, this.options).children); } // If we don't have a context, maybe we have a root, from loading if (!context) { context = this._root; } else if (typeof context === 'string') { if (isHtml(context)) { // $('li', '<ul>...</ul>') context = parse(context, this.options); context = Cheerio.call(this, context); } else { // $('li', 'ul') selector = [context, selector].join(' '); context = this._root; } // $('li', node), $('li', [nodes]) } else if (!context.cheerio) { context = Cheerio.call(this, context); } // If we still don't have a context, return if (!context) return this; // #id, .class, tag return context.find(selector); }
n/a
contains = function (container, contained) { // According to the jQuery API, an element does not "contain" itself if (contained === container) { return false; } // Step up the descendants, 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; }
...
* Code & doc cleanup (davidchambers)
* Fixed bug in filter (jugglinmike)
0.10.6 / 2013-01-29
==================
* Added `$.contains(...)` (jugglinmike)
* formatting cleanup (davidchambers)
* Bug fix for `.children()` (jugglinmike & davidchambers)
* Remove global `render` bug (wvl)
0.10.5 / 2012-12-18
===================
...
html = function (dom, options) { var Cheerio = require('./cheerio'); // be flexible about parameters, sometimes we call html(), // with options as only parameter // check dom argument for dom element specific properties // assume there is no 'length' or 'type' properties in the options object if (Object.prototype.toString.call(dom) === '[object Object]' && !options && !('length' in dom) && !('type' in dom)) { options = dom; dom = undefined; } // sometimes $.html() used without preloading html // so fallback non existing options to the default ones options = _.defaults(options || {}, this._options, Cheerio.prototype.options); return render(this, dom, options); }
...
* Change state definition to more readable (Artem Burtsev)
* added test (0xBADC0FFEE)
* add class only if doesn't exist (Artem Burtsev)
* Made it less insane. (Alex Indigo)
* Implement `Cheerio#add` (Mike Pennisi)
* Use "loaded" instance of Cheerio in unit tests (Mike Pennisi)
* Be more strict with object check. (Alex Indigo)
* Added options argument to .html() static method. (Alex Indigo)
* Fixed encoding mishaps. Adjusted tests. (Alex Indigo)
* use dom-serializer module (fb55)
* don't test on 0.8, don't ignore 0.11 (Felix Böhm)
* parse: rm unused variables (coderaiser)
* cheerio: rm unused variable (coderaiser)
* Fixed test (Avi Kohn)
* Added test (Avi Kohn)
...
load = function (content, options) { var Cheerio = require('./cheerio'); options = _.defaults(options || {}, Cheerio.prototype.options); var root = parse(content, options); var initialize = function(selector, context, r, opts) { if (!(this instanceof initialize)) { return new initialize(selector, context, r, opts); } opts = _.defaults(opts || {}, options); return Cheerio.call(this, selector, context, r || root, opts); }; // Ensure that selections created by the "loaded" `initialize` function are // true Cheerio instances. initialize.prototype = Object.create(Cheerio.prototype); initialize.prototype.constructor = initialize; // Mimic jQuery's prototype alias for plugin authors. initialize.fn = initialize.prototype; // Keep a reference to the top-level scope so we can chain methods that implicitly // resolve selectors; e.g. $("<span>").(".bar"), which otherwise loses ._root initialize.prototype._originalRoot = root; // Add in the static methods _.merge(initialize, exports); // Add in the root initialize._root = root; // store options initialize._options = options; return initialize; }
...
</a>
</div>
<br />
```js
let cheerio = require('cheerio')
let $ = cheerio.load('<h2 class="title">Hello world</h2
>')
$('h2.title').text('Hello there!')
$('h2').addClass('welcome')
$.html()
//=> <h2 class="title welcome">Hello there!</h2>
```
...
parse = function (content, options) { var dom = exports.evaluate(content, options), // Generic root element root = exports.evaluate('<root></root>', options)[0]; root.type = 'root'; // Update the dom using the root exports.update(dom, root); return root; }
...
if (hasOwn.call(primitives, value)) {
value = primitives[value];
} else if (value === String(Number(value))) {
value = Number(value);
} else if (rbrace.test(value)) {
try {
value = JSON.parse(value);
} catch(e){ }
}
el.data[jsName] = value;
}
}
...
parseHTML = function (data, context, keepScripts) { var parsed; if (!data || typeof data !== 'string') { return null; } if (typeof context === 'boolean') { keepScripts = context; } parsed = this.load(data); if (!keepScripts) { parsed('script').remove(); } // The `children` array is used by Cheerio internally to group elements that // share the same parents. When nodes created through `parseHTML` are // inserted into previously-existing DOM structures, they will be removed // from the `children` array. The results of `parseHTML` should remain // constant across these operations, so a shallow copy should be returned. return parsed.root()[0].children.slice(); }
...
$.root().append('<ul id="vegetables"></ul>').html();
//=> <ul id="fruits">...</ul><ul id="vegetables"></ul>
```
#### $.contains( container, contained )
Checks to see if the `contained` DOM element is a descendant of the `container` DOM element.
#### $.parseHTML( data [, context ] [, keepScripts ] )
Parses a string into an array of DOM nodes. The `context` argument has no meaning for Cheerio, but it is maintained for API compatability
.
#### $.load( html[, options ] )
Load in the HTML. (See the previous section titled "Loading" for more information.)
### Plugins
...
root = function () { return this(this._root); }
...
* compatible with node 4.x (again)
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
text = function (elems) { if (!elems) { elems = this.root(); } var ret = '', len = elems.length, elem; for (var i = 0; i < len; i++) { elem = elems[i]; if (elem.type === 'text') ret += elem.data; else if (elem.children && elem.type !== 'comment') { ret += exports.text(elem.children); } } return ret; }
...
0.9.0 / 2012-07-24
==================
* Added node 8.x support
* Removed node 4.x support
* Add html(dom) support (@wvl)
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55)
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers)
* Tons of cleanup (@davidchambers)
0.8.3 / 2012-06-12
==================
* Fixed minor package regression (closes #60)
...
xml = function (dom) { var options = _.defaults({xmlMode: true}, this._options); return render(this, dom, options); }
...
* added test case for malformed json in data attributes (fb55)
* fix: handle some extreme cases like `data-custom="{{templatevar}}"`. There is possibility error while parsing json . (
Harish.K)
* Add missing optional selector doc for {prev,next}{All,Until} (Jérémie Astori)
* update to dom-serializer@0.1.0 (Felix Böhm)
* Document `Cheerio#serialzeArray` (Mike Pennisi)
* Fixed up `serializeArray()` and added multiple support (Todd Wolfson)
* Implement serializeArray() (Jarno Leppänen)
* recognize options in $.xml() (fb55)
* lib/static.js: text(): rm errant space before ++ (Chris Rebert)
* Do not expose internal `children` array (Mike Pennisi)
* Change lodash dependencies to ^3.1.0 (Samy Pessé)
* Update lodash@3.1.0 (Samy Pessé)
* Updates Readme.md: .not(function (index, elem)) (Patrick Ward)
* update to css-select@1.0.0 (fb55)
* Allow failures in Node.js v0.11 (Mike Pennisi)
...
addClass = function (value) { // Support functions if (typeof value === 'function') { return domEach(this, function(i, el) { var className = el.attribs['class'] || ''; exports.addClass.call([el], value.call(el, i, className)); }); } // Return if no value or not a string or function if (!value || typeof value !== 'string') return this; var classNames = value.split(rspace), numElements = this.length; for (var i = 0; i < numElements; i++) { // If selected element isn't a tag, move on if (!isTag(this[i])) continue; // If we don't already have classes var className = getAttr(this[i], 'class'), numClasses, setClass; if (!className) { setAttr(this[i], 'class', classNames.join(' ').trim()); } else { setClass = ' ' + className + ' '; numClasses = classNames.length; // Check if class already exists for (var j = 0; j < numClasses; j++) { var appendClass = classNames[j] + ' '; if (setClass.indexOf(' ' + appendClass) < 0) setClass += appendClass; } setAttr(this[i], 'class', setClass.trim()); } } return this; }
...
<br />
```js
let cheerio = require('cheerio')
let $ = cheerio.load('<h2 class="title">Hello world</h2>')
$('h2.title').text('Hello there!')
$('h2').addClass('welcome')
$.html()
//=> <h2 class="title welcome">Hello there!</h2>
```
## Installation
`npm install cheerio`
...
attr = function (name, value) { // Set the value (with attr map support) if (typeof name === 'object' || value !== undefined) { if (typeof value === 'function') { return domEach(this, function(i, el) { setAttr(el, name, value.call(el, i, el.attribs[name])); }); } return domEach(this, function(i, el) { if (!isTag(el)) return; if (typeof name === 'object') { _.forEach(name, function(value, name) { setAttr(el, name, value); }); } else { setAttr(el, name, value); } }); } return getAttr(this[0], name); }
...
0.12.2 / 2013-09-04
==================
* Correct implementation of `$.fn.text` (@jugglinmike)
* Refactor Cheerio array creation (@jugglinmike)
* Extend manipulation methods to accept Arrays (@jugglinmike)
* support .attr(attributeName, function(index, attr)) (@xiaohwan)
0.12.1 / 2013-07-30
==================
* Correct behavior of `Cheerio#parents` (@jugglinmike)
* Double quotes inside attributes kills HTML (@khoomeister)
* Making next({}) and prev({}) return empty object (@absentTelegraph)
...
data = function (name, value) { var elem = this[0]; if (!elem || !isTag(elem)) return; if (!elem.data) { elem.data = {}; } // Return the entire data object if no data specified if (!name) { return readData(elem); } // Set the value (with attr map support) if (typeof name === 'object' || value !== undefined) { domEach(this, function(i, el) { setData(el, name, value); }); return this; } else if (hasOwn.call(elem.data, name)) { return elem.data[name]; } return readData(elem, name); }
...
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
* Correct the implementation `filter` and `is` (@jugglinmike)
* add .data() function (@andi-neck)
* add .css() (@yields)
* Implements contents() (@jlep)
0.12.2 / 2013-09-04
==================
* Correct implementation of `$.fn.text` (@jugglinmike)
...
hasClass = function (className) { return _.some(this, function(elem) { var attrs = elem.attribs, clazz = attrs && attrs['class'], idx = -1, end; if (clazz) { while ((idx = clazz.indexOf(className, idx+1)) > -1) { end = idx + className.length; if ((idx === 0 || rspace.test(clazz[idx-1])) && (end === clazz.length || rspace.test(clazz[end]))) { return true; } } } }); }
...
Method for removing attributes by `name`.
```js
$('.pear').removeAttr('class').html()
//=> <li>Pear</li>
```
#### .hasClass( className )
Check to see if *any* of the matched elements have the given `className`.
```js
$('.pear').hasClass('pear')
//=> true
$('apple').hasClass('fruit')
...
is = function (selector) { if (selector) { return this.filter(selector).length > 0; } return false; }
...
* Breaking Change: Changed context from parent to the actual passed one (@swissmanu)
* Fixed: jquery checkbox val behavior (@jhubble)
* Added: output xml with $.xml() (@Maciek416)
* Bumped: htmlparser2 to 3.1.1
* Fixed: bug in attr(key, val) on empty objects (@farhadi)
* Added: prevAll, nextAll (@lessmind)
* Fixed: Safety check in parents and closest (@zero21xxx)
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
...
prop = function (name, value) { var i = 0, property; if (typeof name === 'string' && value === undefined) { switch (name) { case 'style': property = this.css(); _.forEach(property, function (v, p) { property[i++] = p; }); property.length = i; break; case 'tagName': case 'nodeName': property = this[0].name.toUpperCase(); break; default: property = getProp(this[0], name); } return property; } if (typeof name === 'object' || value !== undefined) { if (typeof value === 'function') { return domEach(this, function(i, el) { setProp(el, name, value.call(el, i, getProp(el, name))); }); } return domEach(this, function(i, el) { if (!isTag(el)) return; if (typeof name === 'object') { _.forEach(name, function(val, name) { setProp(el, name, val); }); } else { setProp(el, name, value); } }); } }
...
$('.apple').attr('id', 'favorite').html()
//=> <li class="apple" id="favorite">Apple</li>
```
> See http://api.jquery.com/attr/ for more information
#### .prop( name, value )
Method for getting and setting properties. Gets the property value for only the first element in the matched set.
```js
$('input[type="checkbox"]').prop('checked')
//=> false
$('input[type="checkbox"]').prop('checked', true).val()
...
removeAttr = function (name) { domEach(this, function(i, elem) { removeAttribute(elem, name); }); return this; }
...
$('input[type="text"]').val()
//=> input_text
$('input[type="text"]').val('test').html()
//=> <input type="text" value="test"/>
```
#### .removeAttr( name )
Method for removing attributes by `name`.
```js
$('.pear').removeAttr('class').html()
//=> <li>Pear</li>
```
...
removeClass = function (value) { var classes, numClasses, removeAll; // Handle if value is a function if (typeof value === 'function') { return domEach(this, function(i, el) { exports.removeClass.call( [el], value.call(el, i, el.attribs['class'] || '') ); }); } classes = splitClass(value); numClasses = classes.length; removeAll = arguments.length === 0; return domEach(this, function(i, el) { if (!isTag(el)) return; if (removeAll) { // Short circuit the remove all case as this is the nice one el.attribs.class = ''; } else { var elClasses = splitClass(el.attribs.class), index, changed; for (var j = 0; j < numClasses; j++) { index = elClasses.indexOf(classes[j]); if (index >= 0) { elClasses.splice(index, 1); changed = true; // We have to do another pass to ensure that there are not duplicate // classes listed j--; } } if (changed) { el.attribs.class = elClasses.join(' '); } } }); }
...
* Fixed error thrown in removeClass(...) @robashton
0.9.2 / 2012-08-10
==================
* added $(...).map(fn)
* manipulation: refactor `makeCheerioArray`
* make .removeClass() remove *all* occurrences (#64)
0.9.1 / 2012-08-03
==================
* fixed bug causing options not to make it to the parser
0.9.0 / 2012-07-24
...
toggleClass = function (value, stateVal) { // Support functions if (typeof value === 'function') { return domEach(this, function(i, el) { exports.toggleClass.call( [el], value.call(el, i, el.attribs['class'] || '', stateVal), stateVal ); }); } // Return if no value or not a string or function if (!value || typeof value !== 'string') return this; var classNames = value.split(rspace), numClasses = classNames.length, state = typeof stateVal === 'boolean' ? stateVal ? 1 : -1 : 0, numElements = this.length, elementClasses, index; for (var i = 0; i < numElements; i++) { // If selected element isn't a tag, move on if (!isTag(this[i])) continue; elementClasses = splitClass(this[i].attribs.class); // Check if class already exists for (var j = 0; j < numClasses; j++) { // Check if the class name is currently defined index = elementClasses.indexOf(classNames[j]); // Add if stateValue === true or we are toggling and there is no value if (state >= 0 && index < 0) { elementClasses.push(classNames[j]); } else if (state <= 0 && index >= 0) { // Otherwise remove but only if the item exists elementClasses.splice(index, 1); } } this[i].attribs.class = elementClasses.join(' '); } return this; }
...
* Fix bug in `removeClass` (@jugglinmike)
* Improve contributing.md (@jugglinmike)
* Fix and document .css() (@jugglinmike)
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
* Correct the implementation `filter` and `is` (@jugglinmike)
* add .data() function (@andi-neck)
* add .css() (@yields)
* Implements contents() (@jlep)
...
val = function (value) { var querying = arguments.length === 0, element = this[0]; if(!element) return; switch (element.name) { case 'textarea': return this.text(value); case 'input': switch (this.attr('type')) { case 'radio': if (querying) { return this.attr('value'); } else { this.attr('value', value); return this; } break; default: return this.attr('value', value); } return; case 'select': var option = this.find('option:selected'), returnValue; if (option === undefined) return undefined; if (!querying) { if (!this.attr().hasOwnProperty('multiple') && typeof value == 'object') { return this; } if (typeof value != 'object') { value = [value]; } this.find('option').removeAttr('selected'); for (var i = 0; i < value.length; i++) { this.find('option[value="' + value[i] + '"]').attr('selected', ''); } return this; } returnValue = option.attr('value'); if (this.attr().hasOwnProperty('multiple')) { returnValue = []; domEach(option, function(i, el) { returnValue.push(getAttr(el, 'value')); }); } return returnValue; case 'option': if (!querying) { this.attr('value', value); return this; } return this.attr('value'); } }
...
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)
0.10.8 / 2013-03-11
==================
...
cheerio = function (selector, context, root, options) { if (!(this instanceof Cheerio)) return new Cheerio(selector, context, root, options); this.options = _.defaults(options || {}, this.options); // $(), $(null), $(undefined), $(false) if (!selector) return this; if (root) { if (typeof root === 'string') root = parse(root, this.options); this._root = Cheerio.call(this, root); } // $($) if (selector.cheerio) return selector; // $(dom) if (isNode(selector)) selector = [selector]; // $([dom]) if (Array.isArray(selector)) { _.forEach(selector, _.bind(function(elem, idx) { this[idx] = elem; }, this)); this.length = selector.length; return this; } // $(<html>) if (typeof selector === 'string' && isHtml(selector)) { return Cheerio.call(this, parse(selector, this.options).children); } // If we don't have a context, maybe we have a root, from loading if (!context) { context = this._root; } else if (typeof context === 'string') { if (isHtml(context)) { // $('li', '<ul>...</ul>') context = parse(context, this.options); context = Cheerio.call(this, context); } else { // $('li', 'ul') selector = [context, selector].join(' '); context = this._root; } // $('li', node), $('li', [nodes]) } else if (!context.cheerio) { context = Cheerio.call(this, context); } // If we still don't have a context, return if (!context) return this; // #id, .class, tag return context.find(selector); }
n/a
contains = function (container, contained) { // According to the jQuery API, an element does not "contain" itself if (contained === container) { return false; } // Step up the descendants, 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; }
...
* Code & doc cleanup (davidchambers)
* Fixed bug in filter (jugglinmike)
0.10.6 / 2013-01-29
==================
* Added `$.contains(...)` (jugglinmike)
* formatting cleanup (davidchambers)
* Bug fix for `.children()` (jugglinmike & davidchambers)
* Remove global `render` bug (wvl)
0.10.5 / 2012-12-18
===================
...
html = function (dom, options) { var Cheerio = require('./cheerio'); // be flexible about parameters, sometimes we call html(), // with options as only parameter // check dom argument for dom element specific properties // assume there is no 'length' or 'type' properties in the options object if (Object.prototype.toString.call(dom) === '[object Object]' && !options && !('length' in dom) && !('type' in dom)) { options = dom; dom = undefined; } // sometimes $.html() used without preloading html // so fallback non existing options to the default ones options = _.defaults(options || {}, this._options, Cheerio.prototype.options); return render(this, dom, options); }
...
* Change state definition to more readable (Artem Burtsev)
* added test (0xBADC0FFEE)
* add class only if doesn't exist (Artem Burtsev)
* Made it less insane. (Alex Indigo)
* Implement `Cheerio#add` (Mike Pennisi)
* Use "loaded" instance of Cheerio in unit tests (Mike Pennisi)
* Be more strict with object check. (Alex Indigo)
* Added options argument to .html() static method. (Alex Indigo)
* Fixed encoding mishaps. Adjusted tests. (Alex Indigo)
* use dom-serializer module (fb55)
* don't test on 0.8, don't ignore 0.11 (Felix Böhm)
* parse: rm unused variables (coderaiser)
* cheerio: rm unused variable (coderaiser)
* Fixed test (Avi Kohn)
* Added test (Avi Kohn)
...
load = function (content, options) { var Cheerio = require('./cheerio'); options = _.defaults(options || {}, Cheerio.prototype.options); var root = parse(content, options); var initialize = function(selector, context, r, opts) { if (!(this instanceof initialize)) { return new initialize(selector, context, r, opts); } opts = _.defaults(opts || {}, options); return Cheerio.call(this, selector, context, r || root, opts); }; // Ensure that selections created by the "loaded" `initialize` function are // true Cheerio instances. initialize.prototype = Object.create(Cheerio.prototype); initialize.prototype.constructor = initialize; // Mimic jQuery's prototype alias for plugin authors. initialize.fn = initialize.prototype; // Keep a reference to the top-level scope so we can chain methods that implicitly // resolve selectors; e.g. $("<span>").(".bar"), which otherwise loses ._root initialize.prototype._originalRoot = root; // Add in the static methods _.merge(initialize, exports); // Add in the root initialize._root = root; // store options initialize._options = options; return initialize; }
...
</a>
</div>
<br />
```js
let cheerio = require('cheerio')
let $ = cheerio.load('<h2 class="title">Hello world</h2
>')
$('h2.title').text('Hello there!')
$('h2').addClass('welcome')
$.html()
//=> <h2 class="title welcome">Hello there!</h2>
```
...
parseHTML = function (data, context, keepScripts) { var parsed; if (!data || typeof data !== 'string') { return null; } if (typeof context === 'boolean') { keepScripts = context; } parsed = this.load(data); if (!keepScripts) { parsed('script').remove(); } // The `children` array is used by Cheerio internally to group elements that // share the same parents. When nodes created through `parseHTML` are // inserted into previously-existing DOM structures, they will be removed // from the `children` array. The results of `parseHTML` should remain // constant across these operations, so a shallow copy should be returned. return parsed.root()[0].children.slice(); }
...
$.root().append('<ul id="vegetables"></ul>').html();
//=> <ul id="fruits">...</ul><ul id="vegetables"></ul>
```
#### $.contains( container, contained )
Checks to see if the `contained` DOM element is a descendant of the `container` DOM element.
#### $.parseHTML( data [, context ] [, keepScripts ] )
Parses a string into an array of DOM nodes. The `context` argument has no meaning for Cheerio, but it is maintained for API compatability
.
#### $.load( html[, options ] )
Load in the HTML. (See the previous section titled "Loading" for more information.)
### Plugins
...
root = function () { return this(this._root); }
...
* compatible with node 4.x (again)
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
text = function (elems) { if (!elems) { elems = this.root(); } var ret = '', len = elems.length, elem; for (var i = 0; i < len; i++) { elem = elems[i]; if (elem.type === 'text') ret += elem.data; else if (elem.children && elem.type !== 'comment') { ret += exports.text(elem.children); } } return ret; }
...
0.9.0 / 2012-07-24
==================
* Added node 8.x support
* Removed node 4.x support
* Add html(dom) support (@wvl)
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55)
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers)
* Tons of cleanup (@davidchambers)
0.8.3 / 2012-06-12
==================
* Fixed minor package regression (closes #60)
...
xml = function (dom) { var options = _.defaults({xmlMode: true}, this._options); return render(this, dom, options); }
...
* added test case for malformed json in data attributes (fb55)
* fix: handle some extreme cases like `data-custom="{{templatevar}}"`. There is possibility error while parsing json . (
Harish.K)
* Add missing optional selector doc for {prev,next}{All,Until} (Jérémie Astori)
* update to dom-serializer@0.1.0 (Felix Böhm)
* Document `Cheerio#serialzeArray` (Mike Pennisi)
* Fixed up `serializeArray()` and added multiple support (Todd Wolfson)
* Implement serializeArray() (Jarno Leppänen)
* recognize options in $.xml() (fb55)
* lib/static.js: text(): rm errant space before ++ (Chris Rebert)
* Do not expose internal `children` array (Mike Pennisi)
* Change lodash dependencies to ^3.1.0 (Samy Pessé)
* Update lodash@3.1.0 (Samy Pessé)
* Updates Readme.md: .not(function (index, elem)) (Patrick Ward)
* update to css-select@1.0.0 (fb55)
* Allow failures in Node.js v0.11 (Mike Pennisi)
...
_make = function (dom, context) { var cheerio = new this.constructor(dom, context, this._root, this.options); cheerio.prevObject = this; return cheerio; }
...
updateDOM(elem, el);
});
return this;
};
exports.clone = function() {
return this._make(cloneDom(this.get(), this.options));
};
...
function makeDomArray(elem, clone) { if (elem == null) { return []; } else if (elem.cheerio) { return clone ? cloneDom(elem.get(), elem.options) : elem.get(); } else if (Array.isArray(elem)) { return _.flatten(elem.map(function(el) { return this._makeDomArray(el, clone); }, this)); } else if (typeof elem === 'string') { return evaluate(elem, this.options); } else { return clone ? cloneDom([elem]) : [elem]; } }
...
exports._makeDomArray = function makeDomArray(elem, clone) {
if (elem == null) {
return [];
} else if (elem.cheerio) {
return clone ? cloneDom(elem.get(), elem.options) : elem.get();
} else if (Array.isArray(elem)) {
return _.flatten(elem.map(function(el) {
return this._makeDomArray(el, clone);
}, this));
} else if (typeof elem === 'string') {
return evaluate(elem, this.options);
} else {
return clone ? cloneDom([elem]) : [elem];
}
};
...
add = function (other, context) { var selection = this._make(other, context); var contents = uniqueSort(selection.get().concat(this.get())); for (var i = 0; i < contents.length; ++i) { selection[i] = contents[i]; } selection.length = contents.length; return selection; }
...
End the most recent filtering operation in the current chain and return the set of matched elements to its previous state.
```js
$('li').eq(0).end().length
//=> 3
```
#### .add( selector [, context] )
#### .add( element )
#### .add( elements )
#### .add( html )
#### .add( selection )
Add elements to the set of matched elements.
```js
...
addBack = function (selector) { return this.add( arguments.length ? this.prevObject.filter(selector) : this.prevObject ); }
...
Add elements to the set of matched elements.
```js
$('.apple').add('.orange').length
//=> 2
```
#### .addBack( [filter] )
Add the previous set of elements on the stack to the current set, optionally filtered by a selector.
```js
$('li').eq(0).addBack('.orange').length
//=> 2
```
...
addClass = function (value) { // Support functions if (typeof value === 'function') { return domEach(this, function(i, el) { var className = el.attribs['class'] || ''; exports.addClass.call([el], value.call(el, i, className)); }); } // Return if no value or not a string or function if (!value || typeof value !== 'string') return this; var classNames = value.split(rspace), numElements = this.length; for (var i = 0; i < numElements; i++) { // If selected element isn't a tag, move on if (!isTag(this[i])) continue; // If we don't already have classes var className = getAttr(this[i], 'class'), numClasses, setClass; if (!className) { setAttr(this[i], 'class', classNames.join(' ').trim()); } else { setClass = ' ' + className + ' '; numClasses = classNames.length; // Check if class already exists for (var j = 0; j < numClasses; j++) { var appendClass = classNames[j] + ' '; if (setClass.indexOf(' ' + appendClass) < 0) setClass += appendClass; } setAttr(this[i], 'class', setClass.trim()); } } return this; }
...
<br />
```js
let cheerio = require('cheerio')
let $ = cheerio.load('<h2 class="title">Hello world</h2>')
$('h2.title').text('Hello there!')
$('h2').addClass('welcome')
$.html()
//=> <h2 class="title welcome">Hello there!</h2>
```
## Installation
`npm install cheerio`
...
after = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; domEach(this, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el), domSrc, dom; // If not found, move on if (index < 0) return; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); // Add element after `this` element uniqueSplice(siblings, index + 1, 0, dom, parent); }); return this; }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .after( content, [content, ...] )
Insert content next to each element in the set of matched elements.
```js
$('.apple').after('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
append = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; return domEach(this, function(i, el) { var dom, domSrc; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); concatenator(dom, el.children, el); }); }
...
$('li').eq(0).addBack('.orange').length
//=> 2
```
### Manipulation
Methods for modifying the DOM structure.
#### .append( content, [content, ...] )
Inserts content as the *last* child of each of the selected elements.
```js
$('ul').append('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
appendTo = function (target) { if (!target.cheerio) { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target.append(this); return this; }
...
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// <li class="plum">Plum</li>
// </ul>
```
#### .appendTo( target )
Insert every element in the set of matched elements to the end of the target.
```js
$('<li class="plum">Plum</li>').appendTo('#fruits')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
attr = function (name, value) { // Set the value (with attr map support) if (typeof name === 'object' || value !== undefined) { if (typeof value === 'function') { return domEach(this, function(i, el) { setAttr(el, name, value.call(el, i, el.attribs[name])); }); } return domEach(this, function(i, el) { if (!isTag(el)) return; if (typeof name === 'object') { _.forEach(name, function(value, name) { setAttr(el, name, value); }); } else { setAttr(el, name, value); } }); } return getAttr(this[0], name); }
...
0.12.2 / 2013-09-04
==================
* Correct implementation of `$.fn.text` (@jugglinmike)
* Refactor Cheerio array creation (@jugglinmike)
* Extend manipulation methods to accept Arrays (@jugglinmike)
* support .attr(attributeName, function(index, attr)) (@xiaohwan)
0.12.1 / 2013-07-30
==================
* Correct behavior of `Cheerio#parents` (@jugglinmike)
* Double quotes inside attributes kills HTML (@khoomeister)
* Making next({}) and prev({}) return empty object (@absentTelegraph)
...
before = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; domEach(this, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el), domSrc, dom; // If not found, move on if (index < 0) return; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); // Add element before `el` element uniqueSplice(siblings, index, 0, dom, parent); }); return this; }
...
// <li class="apple">Apple</li>
// <li class="plum">Plum</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .before( content, [content, ...] )
Insert content previous to each element in the set of matched elements.
```js
$('.apple').before('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
children = function (selector) { var elems = _.reduce(this, function(memo, elem) { return memo.concat(_.filter(elem.children, isTag)); }, []); if (selector === undefined) return this._make(elems); return exports.filter.call(elems, selector, this); }
...
* Fixed bug in filter (jugglinmike)
0.10.6 / 2013-01-29
==================
* Added `$.contains(...)` (jugglinmike)
* formatting cleanup (davidchambers)
* Bug fix for `.children()` (jugglinmike & davidchambers)
* Remove global `render` bug (wvl)
0.10.5 / 2012-12-18
===================
* Fixed botched publish from 0.10.4 - changes should now be present
...
clone = function () { return this._make(cloneDom(this.get(), this.options)); }
...
* compatible with node 4.x (again)
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
closest = function (selector) { var set = []; if (!selector) { return this._make(set); } domEach(this, function(idx, elem) { var closestElem = traverseParents(this, elem, selector, 1)[0]; // Do not add duplicate elements to the set if (closestElem && set.indexOf(closestElem) < 0) { set.push(closestElem); } }.bind(this)); return this._make(set); }
...
* Added: prevAll, nextAll (@lessmind)
* Fixed: Safety check in parents and closest (@zero21xxx)
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)
0.10.8 / 2013-03-11
...
contents = function () { return this._make(_.reduce(this, function(all, elem) { all.push.apply(all, elem.children); return all; }, [])); }
...
$('#fruits').children().length
//=> 3
$('#fruits').children('.pear').text()
//=> Pear
```
#### .contents()
Gets the children of each element in the set of matched elements, including text and comment nodes.
```js
$('#fruits').contents().length
//=> 3
```
...
css = function (prop, val) { if (arguments.length === 2 || // When `prop` is a "plain" object (toString.call(prop) === '[object Object]')) { return domEach(this, function(idx, el) { setCss(el, prop, val, idx); }); } else { return getCss(this[0], prop); } }
...
* Implement function signature of `after` (@jugglinmike)
* Implement function signature of `append`/`prepend` (@jugglinmike)
* Extend iteration methods to accept nodes (@jugglinmike)
* Improve `removeClass` (@jugglinmike)
* Complete function signature of `addClass` (@jugglinmike)
* Fix bug in `removeClass` (@jugglinmike)
* Improve contributing.md (@jugglinmike)
* Fix and document .css() (@jugglinmike)
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
...
data = function (name, value) { var elem = this[0]; if (!elem || !isTag(elem)) return; if (!elem.data) { elem.data = {}; } // Return the entire data object if no data specified if (!name) { return readData(elem); } // Set the value (with attr map support) if (typeof name === 'object' || value !== undefined) { domEach(this, function(i, el) { setData(el, name, value); }); return this; } else if (hasOwn.call(elem.data, name)) { return elem.data[name]; } return readData(elem, name); }
...
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
* Correct the implementation `filter` and `is` (@jugglinmike)
* add .data() function (@andi-neck)
* add .css() (@yields)
* Implements contents() (@jlep)
0.12.2 / 2013-09-04
==================
* Correct implementation of `$.fn.text` (@jugglinmike)
...
each = function (fn) { var i = 0, len = this.length; while (i < len && fn.call(this[i], i, this[i]) !== false) ++i; return this; }
...
Gets the children of each element in the set of matched elements, including text and comment nodes.
```js
$('#fruits').contents().length
//=> 3
```
#### .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
`. To break out of the `each` loop early, return with `false`.
```js
var fruits = [];
$('li').each(function(i, elem) {
fruits[i] = $(this).text();
...
empty = function () { domEach(this, function(i, el) { _.forEach(el.children, function(el) { el.next = el.prev = el.parent = null; }); el.children.length = 0; }); return this; }
...
//=> <ul id="fruits">
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="plum">Plum</li>
// </ul>
```
#### .empty()
Empties an element, removing all its children.
```js
$('ul').empty()
$.html()
//=> <ul id="fruits"></ul>
```
...
end = function () { return this.prevObject || this._make([]); }
...
//=> 2
$('.orange').index('li')
//=> 1
$('.apple').index($('#fruit, li'))
//=> 1
```
#### .end()
End the most recent filtering operation in the current chain and return the set of matched elements to its previous state.
```js
$('li').eq(0).end().length
//=> 3
```
...
eq = function (i) { i = +i; // Use the first identity optimization if possible if (i === 0 && this.length <= 1) return this; if (i < 0) i = this.length + i; return this[i] ? this._make(this[i]) : this._make([]); }
...
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
filter = function (match, container) { var testFn; container = container || this; if (typeof match === 'string') { testFn = select.compile(match, container.options); } else if (typeof match === 'function') { testFn = function(el, i) { return match.call(el, i, el); }; } else if (match.cheerio) { testFn = match.is.bind(match); } else { testFn = function(el) { return match === el; }; } return container._make(filterFn(this, testFn)); }
...
$('li').map(function(i, el) {
// this === el
return $(this).text();
}).get().join(' ');
//=> "apple orange pear"
```
#### .filter( selector ) <br /> .filter( selection ) <br /> .filter
( element ) <br /> .filter( function(index) )
Iterates over a cheerio object, reducing the set of selector elements to those that match the selector or pass the function'
;s test. When a Cheerio selection is specified, return only the elements contained in that selection. When an element is specified
, return only that element (if it is contained in the original selection). If using the function method, the function is executed
in the context of the selected element, so `this` refers to the current element.
Selector:
```js
$('li').filter('.orange').attr('class');
...
find = function (selectorOrHaystack) { var elems = _.reduce(this, function(memo, elem) { return memo.concat(_.filter(elem.children, isTag)); }, []); var contains = this.constructor.contains; var haystack; if (selectorOrHaystack && typeof selectorOrHaystack !== 'string') { if (selectorOrHaystack.cheerio) { haystack = selectorOrHaystack.get(); } else { haystack = [selectorOrHaystack]; } return this._make(haystack.filter(function(elem) { var idx, len; for (idx = 0, len = this.length; idx < len; ++idx) { if (contains(this[idx], elem)) { return true; } } }, this)); } var options = {__proto__: this.options, context: this.toArray()}; return this._make(select(selectorOrHaystack, elems, options)); }
...
0.20.0 / 2016-02-01
==================
* Add coveralls badge, remove link to old report (Felix Böhm)
* Update lodash dependeny to 4.1.0 (leif.hanack)
* Fix PR #726 adding 'appendTo()' and 'prependTo()' (Delgan)
* Added appendTo and prependTo with tests #641 (digihaven)
* Fix #780 by changing options context in '.find()' (Felix Böhm)
* Add an unit test checking the query of child (Delgan)
* fix #667: attr({foo: null}) removes attribute foo, like attr('foo', null) (Ray Waldin)
* Include reference to dedicated "Loading" section (Mike Pennisi)
* Added load method to $ (alanev)
* update css-select to 1.2.0 (Felix Böhm)
* Fixing Grammatical Error (Dan Corman)
* Test against node v0.12 --> v4.2 (Jason Kurian)
...
first = function () { return this.length > 1 ? this._make(this[0]) : this; }
...
==================
* Fixed .replaceWith(...) regression
0.6.1 / 2012-02-12
==================
* Added .first(), .last(), and .clone() commands.
* Option to parse using whitespace added to `.load`.
* Many bug fixes to make cheerio more aligned with jQuery.
* Added $(':root') to select the highest level element.
Many thanks to the contributors that made this release happen: @ironchefpython and @siddMahen
0.6.0 / 2012-02-07
...
get = function (i) { if (i == null) { return Array.prototype.slice.call(this); } else { return this[i < 0 ? (this.length + i) : i]; } }
...
* Added jQuery's $(...).replaceWith(...)
0.3.0 / 2011-11-19
==================
* Now using htmlparser2 for parsing (2x speed increase, cleaner, actively developed)
* Added benchmark directory for future speed tests
* $('...').dom() was funky, so it was removed in favor of $('...').get
span>(). $.dom() still works the same.
* $.root now correctly static across all instances of $
* Added a screencast
0.2.2 / 2011-11-9
=================
* Traversing will select `<script>` and `<style>` tags (Closes Issue: #8)
...
has = function (selectorOrHaystack) { var that = this; return exports.filter.call(this, function() { return that._make(this).find(selectorOrHaystack).length > 0; }); }
...
0.18.0 / 2014-11-06
==================
* bump htmlparser2 dependency to ~3.8.1 (Chris Rebert)
* Correct unit test titles (Mike Pennisi)
* Correct behavior of `after` and `before` (Mike Pennisi)
* implement jQuery's .has() (Chris Rebert)
* Update repository url (haqii)
* attr() should return undefined or name for booleans (Raoul Millais)
* Update Readme.md (Ryan Breen)
* Implement `Cheerio#not` (Mike Pennisi)
* Clone nodes according to original parsing options (Mike Pennisi)
* fix lint error (David Chambers)
* Add explicit tests for DOM level 1 API (Mike Pennisi)
...
hasClass = function (className) { return _.some(this, function(elem) { var attrs = elem.attribs, clazz = attrs && attrs['class'], idx = -1, end; if (clazz) { while ((idx = clazz.indexOf(className, idx+1)) > -1) { end = idx + className.length; if ((idx === 0 || rspace.test(clazz[idx-1])) && (end === clazz.length || rspace.test(clazz[end]))) { return true; } } } }); }
...
Method for removing attributes by `name`.
```js
$('.pear').removeAttr('class').html()
//=> <li>Pear</li>
```
#### .hasClass( className )
Check to see if *any* of the matched elements have the given `className`.
```js
$('.pear').hasClass('pear')
//=> true
$('apple').hasClass('fruit')
...
html = function (str) { if (str === undefined) { if (!this[0] || !this[0].children) return null; return $.html(this[0].children, this.options); } var opts = this.options; domEach(this, function(i, el) { _.forEach(el.children, function(el) { el.next = el.prev = el.parent = null; }); var content = str.cheerio ? str.clone().get() : evaluate('' + str, opts); updateDOM(content, el); }); return this; }
...
* Change state definition to more readable (Artem Burtsev)
* added test (0xBADC0FFEE)
* add class only if doesn't exist (Artem Burtsev)
* Made it less insane. (Alex Indigo)
* Implement `Cheerio#add` (Mike Pennisi)
* Use "loaded" instance of Cheerio in unit tests (Mike Pennisi)
* Be more strict with object check. (Alex Indigo)
* Added options argument to .html() static method. (Alex Indigo)
* Fixed encoding mishaps. Adjusted tests. (Alex Indigo)
* use dom-serializer module (fb55)
* don't test on 0.8, don't ignore 0.11 (Felix Böhm)
* parse: rm unused variables (coderaiser)
* cheerio: rm unused variable (coderaiser)
* Fixed test (Avi Kohn)
* Added test (Avi Kohn)
...
index = function (selectorOrNeedle) { var $haystack, needle; if (arguments.length === 0) { $haystack = this.parent().children(); needle = this[0]; } else if (typeof selectorOrNeedle === 'string') { $haystack = this._make(selectorOrNeedle); needle = this[0]; } else { $haystack = this; needle = selectorOrNeedle.cheerio ? selectorOrNeedle[0] : selectorOrNeedle; } return $haystack.get().indexOf(needle); }
...
If no index is specified, retrieve all elements matched by the Cheerio object:
```js
$('li').get().length
//=> 3
```
#### .index()
#### .index( selector )
#### .index( nodeOrSelection )
Search for a given element from among the matched elements.
```js
$('.pear').index()
...
insertAfter = function (target) { var clones = [], self = this; if (typeof target === 'string') { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target = this._makeDomArray(target); self.remove(); domEach(target, function(i, el) { var clonedSelf = self._makeDomArray(self.clone()); var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el); // If not found, move on if (index < 0) return; // Add cloned `this` element(s) after target element uniqueSplice(siblings, index + 1, 0, clonedSelf, parent); clones.push(clonedSelf); }); return this.constructor.call(this.constructor, this._makeDomArray(clones)); }
...
// <li class="apple">Apple</li>
// <li class="plum">Plum</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .insertAfter( target )
Insert every element in the set of matched elements after the target.
```js
$('<li class="plum">Plum</li>').insertAfter('.apple')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
insertBefore = function (target) { var clones = [], self = this; if (typeof target === 'string') { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target = this._makeDomArray(target); self.remove(); domEach(target, function(i, el) { var clonedSelf = self._makeDomArray(self.clone()); var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el); // If not found, move on if (index < 0) return; // Add cloned `this` element(s) after target element uniqueSplice(siblings, index, 0, clonedSelf, parent); clones.push(clonedSelf); }); return this.constructor.call(this.constructor, this._makeDomArray(clones)); }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .insertBefore( target )
Insert every element in the set of matched elements before the target.
```js
$('<li class="plum">Plum</li>').insertBefore('.apple')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
is = function (selector) { if (selector) { return this.filter(selector).length > 0; } return false; }
...
* Breaking Change: Changed context from parent to the actual passed one (@swissmanu)
* Fixed: jquery checkbox val behavior (@jhubble)
* Added: output xml with $.xml() (@Maciek416)
* Bumped: htmlparser2 to 3.1.1
* Fixed: bug in attr(key, val) on empty objects (@farhadi)
* Added: prevAll, nextAll (@lessmind)
* Fixed: Safety check in parents and closest (@zero21xxx)
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
...
last = function () { return this.length > 1 ? this._make(this[this.length - 1]) : this; }
...
==================
* Fixed .replaceWith(...) regression
0.6.1 / 2012-02-12
==================
* Added .first(), .last(), and .clone() commands.
* Option to parse using whitespace added to `.load`.
* Many bug fixes to make cheerio more aligned with jQuery.
* Added $(':root') to select the highest level element.
Many thanks to the contributors that made this release happen: @ironchefpython and @siddMahen
0.6.0 / 2012-02-07
...
map = function (fn) { return this._make(_.reduce(this, function(memo, el, i) { var val = fn.call(el, i, el); return val == null ? memo : memo.concat(val); }, [])); }
...
* Now supports mocha's test-coverage
* Deprecated self-closing tags (HTML5 doesn't require them)
* Fixed error thrown in removeClass(...) @robashton
0.9.2 / 2012-08-10
==================
* added $(...).map(fn)
* manipulation: refactor `makeCheerioArray`
* make .removeClass() remove *all* occurrences (#64)
0.9.1 / 2012-08-03
==================
* fixed bug causing options not to make it to the parser
...
next = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.next)) { if (isTag(elem)) { elems.push(elem); return; } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
// => []
$('.orange').closest('li')
// => [<li class="orange">Orange</li>]
$('.orange').closest('#fruits')
// => [<ul id="fruits"> ... </ul>]
```
#### .next([selector])
Gets the next sibling of the first selected element, optionally filtered by a selector.
```js
$('.apple').next().hasClass('orange')
//=> true
```
...
nextAll = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.next)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
Gets the next sibling of the first selected element, optionally filtered by a selector.
```js
$('.apple').next().hasClass('orange')
//=> true
```
#### .nextAll([selector])
Gets all the following siblings of the first selected element, optionally filtered by a selector.
```js
$('.apple').nextAll()
//=> [<li class="orange">Orange</li>, <li class="pear">Pear</li>
;]
$('.apple').nextAll('.orange')
//=> [<li class="orange">Orange</li>]
...
nextUntil = function (selector, filterSelector) { if (!this[0]) { return this; } var elems = [], untilNode, untilNodes; if (typeof selector === 'string') { untilNode = select(selector, this.nextAll().get(), this.options)[0]; } else if (selector && selector.cheerio) { untilNodes = selector.get(); } else if (selector) { untilNode = selector; } _.forEach(this, function(elem) { while ((elem = elem.next)) { if ((untilNode && elem !== untilNode) || (untilNodes && untilNodes.indexOf(elem) === -1) || (!untilNode && !untilNodes)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } else { break; } } }); return filterSelector ? exports.filter.call(elems, filterSelector, this) : this._make(elems); }
...
```js
$('.apple').nextAll()
//=> [<li class="orange">Orange</li>, <li class="pear">Pear</li>
;]
$('.apple').nextAll('.orange')
//=> [<li class="orange">Orange</li>]
```
#### .nextUntil([selector], [filter])
Gets all the following siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.apple').nextUntil('.pear')
//=> [<li class="orange">Orange</li>]
```
...
not = function (match, container) { var testFn; container = container || this; if (typeof match === 'string') { testFn = select.compile(match, container.options); } else if (typeof match === 'function') { testFn = function(el, i) { return match.call(el, i, el); }; } else if (match.cheerio) { testFn = match.is.bind(match); } else { testFn = function(el) { return match === el; }; } return container._make(filterFn(this, testFn)); }
...
* Fixed up `serializeArray()` and added multiple support (Todd Wolfson)
* Implement serializeArray() (Jarno Leppänen)
* recognize options in $.xml() (fb55)
* lib/static.js: text(): rm errant space before ++ (Chris Rebert)
* Do not expose internal `children` array (Mike Pennisi)
* Change lodash dependencies to ^3.1.0 (Samy Pessé)
* Update lodash@3.1.0 (Samy Pessé)
* Updates Readme.md: .not(function (index, elem)) (Patrick Ward)
* update to css-select@1.0.0 (fb55)
* Allow failures in Node.js v0.11 (Mike Pennisi)
* Added: Gittask badge (Matthew Mueller)
* Isolate prototypes of functions created via `load` (Mike Pennisi)
* Updates Readme.md: adds JS syntax highlighting (frankcash)
* #608 -- Add support for insertBefore/insertAfter syntax. Supports target types of: $, [$], selector (both single and multiple
results) (Ben Cochran)
* Clone input nodes when inserting over a set (Mike Pennisi)
...
parent = function (selector) { var set = []; domEach(this, function(idx, elem) { var parentElem = elem.parent; if (parentElem && set.indexOf(parentElem) < 0) { set.push(parentElem); } }); if (arguments.length) { set = exports.filter.call(set, selector, this); } return this._make(set); }
...
```js
$('#fruits').find('li').length
//=> 3
$('#fruits').find($('.apple')).length
//=> 1
```
#### .parent([selector])
Get the parent of each element in the current set of matched elements, optionally filtered by a selector.
```js
$('.pear').parent().attr('id')
//=> fruits
```
...
parents = function (selector) { var parentNodes = []; // When multiple DOM elements are in the original set, the resulting set will // be in *reverse* order of the original elements as well, with duplicates // removed. this.get().reverse().forEach(function(elem) { traverseParents(this, elem.parent, selector, Infinity) .forEach(function(node) { if (parentNodes.indexOf(node) === -1) { parentNodes.push(node); } } ); }, this); return this._make(parentNodes); }
...
* Fixed: Safety check in parents and closest (@zero21xxx)
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)
0.10.8 / 2013-03-11
==================
...
parentsUntil = function (selector, filter) { var parentNodes = [], untilNode, untilNodes; if (typeof selector === 'string') { untilNode = select(selector, this.parents().toArray(), this.options)[0]; } else if (selector && selector.cheerio) { untilNodes = selector.toArray(); } else if (selector) { untilNode = selector; } // When multiple DOM elements are in the original set, the resulting set will // be in *reverse* order of the original elements as well, with duplicates // removed. this.toArray().reverse().forEach(function(elem) { while ((elem = elem.parent)) { if ((untilNode && elem !== untilNode) || (untilNodes && untilNodes.indexOf(elem) === -1) || (!untilNode && !untilNodes)) { if (isTag(elem) && parentNodes.indexOf(elem) === -1) { parentNodes.push(elem); } } else { break; } } }, this); return this._make(filter ? select(filter, parentNodes, this.options) : parentNodes); }
...
```js
$('.orange').parents().length
// => 2
$('.orange').parents('#fruits').length
// => 1
```
#### .parentsUntil([selector][,filter])
Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector
, DOM node, or cheerio object.
```js
$('.orange').parentsUntil('#food').length
// => 1
```
#### .closest(selector)
...
prepend = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; return domEach(this, function(i, el) { var dom, domSrc; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); concatenator(dom, el.children, el); }); }
...
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// <li class="plum">Plum</li>
// </ul>
```
#### .prepend( content, [content, ...] )
Inserts content as the *first* child of each of the selected elements.
```js
$('ul').prepend('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
prependTo = function (target) { if (!target.cheerio) { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target.prepend(this); return this; }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .prependTo( target )
Insert every element in the set of matched elements to the beginning of the target.
```js
$('<li class="plum">Plum</li>').prependTo('#fruits')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
prev = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.prev)) { if (isTag(elem)) { elems.push(elem); return; } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
Gets all the following siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.apple').nextUntil('.pear')
//=> [<li class="orange">Orange</li>]
```
#### .prev([selector])
Gets the previous sibling of the first selected element optionally filtered by a selector.
```js
$('.orange').prev().hasClass('apple')
//=> true
```
...
prevAll = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.prev)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
Gets the previous sibling of the first selected element optionally filtered by a selector.
```js
$('.orange').prev().hasClass('apple')
//=> true
```
#### .prevAll([selector])
Gets all the preceding siblings of the first selected element, optionally filtered by a selector.
```js
$('.pear').prevAll()
//=> [<li class="orange">Orange</li>, <li class="apple">Apple</li>
;]
$('.pear').prevAll('.orange')
//=> [<li class="orange">Orange</li>]
...
prevUntil = function (selector, filterSelector) { if (!this[0]) { return this; } var elems = [], untilNode, untilNodes; if (typeof selector === 'string') { untilNode = select(selector, this.prevAll().get(), this.options)[0]; } else if (selector && selector.cheerio) { untilNodes = selector.get(); } else if (selector) { untilNode = selector; } _.forEach(this, function(elem) { while ((elem = elem.prev)) { if ((untilNode && elem !== untilNode) || (untilNodes && untilNodes.indexOf(elem) === -1) || (!untilNode && !untilNodes)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } else { break; } } }); return filterSelector ? exports.filter.call(elems, filterSelector, this) : this._make(elems); }
...
```js
$('.pear').prevAll()
//=> [<li class="orange">Orange</li>, <li class="apple">Apple</li>
;]
$('.pear').prevAll('.orange')
//=> [<li class="orange">Orange</li>]
```
#### .prevUntil([selector], [filter])
Gets all the preceding siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.pear').prevUntil('.apple')
//=> [<li class="orange">Orange</li>]
```
...
prop = function (name, value) { var i = 0, property; if (typeof name === 'string' && value === undefined) { switch (name) { case 'style': property = this.css(); _.forEach(property, function (v, p) { property[i++] = p; }); property.length = i; break; case 'tagName': case 'nodeName': property = this[0].name.toUpperCase(); break; default: property = getProp(this[0], name); } return property; } if (typeof name === 'object' || value !== undefined) { if (typeof value === 'function') { return domEach(this, function(i, el) { setProp(el, name, value.call(el, i, getProp(el, name))); }); } return domEach(this, function(i, el) { if (!isTag(el)) return; if (typeof name === 'object') { _.forEach(name, function(val, name) { setProp(el, name, val); }); } else { setProp(el, name, value); } }); } }
...
$('.apple').attr('id', 'favorite').html()
//=> <li class="apple" id="favorite">Apple</li>
```
> See http://api.jquery.com/attr/ for more information
#### .prop( name, value )
Method for getting and setting properties. Gets the property value for only the first element in the matched set.
```js
$('input[type="checkbox"]').prop('checked')
//=> false
$('input[type="checkbox"]').prop('checked', true).val()
...
remove = function (selector) { var elems = this; // Filter if we have selector if (selector) elems = elems.filter(selector); domEach(elems, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el); if (index < 0) return; siblings.splice(index, 1); if (el.prev) { el.prev.next = el.next; } if (el.next) { el.next.prev = el.prev; } el.prev = el.next = el.parent = el.root = null; }); return this; }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .remove( [selector] )
Removes the set of matched elements from the DOM and all their children. `selector` filters the set of matched elements to be removed
.
```js
$('.pear').remove()
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
removeAttr = function (name) { domEach(this, function(i, elem) { removeAttribute(elem, name); }); return this; }
...
$('input[type="text"]').val()
//=> input_text
$('input[type="text"]').val('test').html()
//=> <input type="text" value="test"/>
```
#### .removeAttr( name )
Method for removing attributes by `name`.
```js
$('.pear').removeAttr('class').html()
//=> <li>Pear</li>
```
...
removeClass = function (value) { var classes, numClasses, removeAll; // Handle if value is a function if (typeof value === 'function') { return domEach(this, function(i, el) { exports.removeClass.call( [el], value.call(el, i, el.attribs['class'] || '') ); }); } classes = splitClass(value); numClasses = classes.length; removeAll = arguments.length === 0; return domEach(this, function(i, el) { if (!isTag(el)) return; if (removeAll) { // Short circuit the remove all case as this is the nice one el.attribs.class = ''; } else { var elClasses = splitClass(el.attribs.class), index, changed; for (var j = 0; j < numClasses; j++) { index = elClasses.indexOf(classes[j]); if (index >= 0) { elClasses.splice(index, 1); changed = true; // We have to do another pass to ensure that there are not duplicate // classes listed j--; } } if (changed) { el.attribs.class = elClasses.join(' '); } } }); }
...
* Fixed error thrown in removeClass(...) @robashton
0.9.2 / 2012-08-10
==================
* added $(...).map(fn)
* manipulation: refactor `makeCheerioArray`
* make .removeClass() remove *all* occurrences (#64)
0.9.1 / 2012-08-03
==================
* fixed bug causing options not to make it to the parser
0.9.0 / 2012-07-24
...
replaceWith = function (content) { var self = this; domEach(this, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, dom = self._makeDomArray(typeof content === 'function' ? content.call(el, i, el) : content), index; // In the case that `dom` contains nodes that already exist in other // structures, ensure those nodes are properly removed. updateDOM(dom, null); index = siblings.indexOf(el); // Completely remove old element uniqueSplice(siblings, index, 1, dom, parent); el.parent = el.prev = el.next = el.root = null; }); return this; }
...
* Now testing with node v0.7.7
* Added travis-ci integration
* Replaced should.js with expect.js. Browser testing to come
* Fixed spacing between attributes and their values
* Added HTML tidy/pretty print
* Exposed node-htmlparser2 parsing options
* Revert .replaceWith(...) to be consistent with jQuery
0.6.2 / 2012-02-12
==================
* Fixed .replaceWith(...) regression
0.6.1 / 2012-02-12
...
serialize = function () { // Convert form elements into name/value objects var arr = this.serializeArray(); // Serialize each element into a key/value string var retArr = _.map(arr, function(data) { return encodeURIComponent(data.name) + '=' + encodeURIComponent(data.value); }); // Return the resulting serialization return retArr.join('&').replace(r20, '+'); }
...
* Merge pull request #881 from piamancini/patch-1
* Added backers and sponsors from OpenCollective
* Use jQuery from the jquery module in benchmarks (#871)
* Document, test, and extend static `$.text` method (#855)
* Fix typo on calling _.extend (#861)
* Update versions (#870)
* Use individual lodash functions (#864)
* Added `.serialize()` support. Fixes #69 (#827)
* Update Readme.md (#857)
* add extension for JSON require call
* remove gittask badge
* Merge pull request #672 from underdogio/dev/checkbox.radio.values.sqwished
* Added default value for checkboxes/radios
0.20.0 / 2016-02-01
...
serializeArray = function () { // Resolve all form elements from either forms or collections of form elements var Cheerio = this.constructor; return this.map(function() { var elem = this; var $elem = Cheerio(elem); if (elem.name === 'form') { return $elem.find(submittableSelector).toArray(); } else { return $elem.filter(submittableSelector).toArray(); } }).filter( // Verify elements have a name (`attr.name`) and are not disabled (`:disabled`) '[name!=""]:not(:disabled)' // and cannot be clicked (`[type=submit]`) or are used in `x-www-form-urlencoded` (`[type=file]`) + ':not(:submit, :button, :image, :reset, :file)' // and are either checked/don't have a checkable state + ':matches([checked], :not(:checkbox, :radio))' // Convert each of the elements to its value(s) ).map(function(i, elem) { var $elem = Cheerio(elem); var name = $elem.attr('name'); var val = $elem.val(); // If there is no value set (e.g. `undefined`, `null`), then return nothing if (val == null) { return null; } else { // If we have an array of values (e.g. `<select multiple>`), return an array of key/value pairs if (Array.isArray(val)) { return _.map(val, function(val) { // We trim replace any line endings (e.g. `\r` or `\r\n` with `\r\n`) to guarantee consistency across platforms // These can occur inside of `<textarea>'s` return {name: name, value: val.replace( rCRLF, '\r\n' )}; }); // Otherwise (e.g. `<input type="text">`, return only one key/value pair } else { return {name: name, value: val.replace( rCRLF, '\r\n' )}; } } // Convert our result to an array }).get(); }
...
#### .is( element )
#### .is( selection )
#### .is( function(index) )
Checks the current list of elements and returns `true` if _any_ of the elements match the selector. If using an element or Cheerio
selection, returns `true` if _any_ of the elements match. If using a predicate function, the function is executed in the context
of the selected element, so `this` refers to the current element.
### Forms
#### .serializeArray()
Encode a set of form elements as an array of names and values.
```js
$('<form><input name="foo" value="bar" /></form>').serializeArray()
//=> [ { name: 'foo', value: 'bar' } ]
```
...
siblings = function (selector) { var parent = this.parent(); var elems = _.filter( parent ? parent.children() : this.siblingsAndMe(), _.bind(function(elem) { return isTag(elem) && !this.is(elem); }, this) ); if (selector !== undefined) { return exports.filter.call(elems, selector, this); } else { return this._make(elems); } }
...
$('li').slice(1).eq(0).text()
//=> 'Orange'
$('li').slice(1, 2).length
//=> 1
```
#### .siblings([selector])
Gets the first selected element's siblings, excluding itself.
```js
$('.pear').siblings().length
//=> 2
$('.pear').siblings('.orange').length
...
slice = function () { return this._make([].slice.apply(this, arguments)); }
...
Gets all the preceding siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.pear').prevUntil('.apple')
//=> [<li class="orange">Orange</li>]
```
#### .slice( start, [end] )
Gets the elements matching the specified range
```js
$('li').slice(1).eq(0).text()
//=> 'Orange'
$('li').slice(1, 2).length
...
function splice() { [native code] }
...
for (var i = 0; i < arr.length; i++) {
var node = arr[i];
// Cleanly remove existing nodes from their previous structures.
var oldParent = node.parent || node.root,
oldSiblings = oldParent && oldParent.children;
if (oldSiblings && oldSiblings !== arr) {
oldSiblings.splice(oldSiblings.indexOf(node), 1);
if (node.prev) {
node.prev.next = node.next;
}
if (node.next) {
node.next.prev = node.prev;
}
}
...
text = function (str) { // If `str` is undefined, act as a "getter" if (str === undefined) { return $.text(this); } else if (typeof str === 'function') { // Function support return domEach(this, function(i, el) { var $el = [el]; return exports.text.call($el, str.call(el, i, $.text($el))); }); } // Append text node to each selected elements domEach(this, function(i, el) { _.forEach(el.children, function(el) { el.next = el.prev = el.parent = null; }); var elem = { data: '' + str, type: 'text', parent: el, prev: null, next: null, children: [] }; updateDOM(elem, el); }); return this; }
...
0.9.0 / 2012-07-24
==================
* Added node 8.x support
* Removed node 4.x support
* Add html(dom) support (@wvl)
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55)
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers)
* Tons of cleanup (@davidchambers)
0.8.3 / 2012-06-12
==================
* Fixed minor package regression (closes #60)
...
toArray = function () { return this.get(); }
...
cheerio.text($('div'))
//=> This is content.
```
### Miscellaneous
DOM element methods that don't fit anywhere else
#### .toArray()
Retrieve all the DOM elements contained in the jQuery set as an array.
```js
$('li').toArray()
//=> [ {...}, {...}, {...} ]
```
...
toString = function () { return $.html(this, this.options); }
n/a
toggleClass = function (value, stateVal) { // Support functions if (typeof value === 'function') { return domEach(this, function(i, el) { exports.toggleClass.call( [el], value.call(el, i, el.attribs['class'] || '', stateVal), stateVal ); }); } // Return if no value or not a string or function if (!value || typeof value !== 'string') return this; var classNames = value.split(rspace), numClasses = classNames.length, state = typeof stateVal === 'boolean' ? stateVal ? 1 : -1 : 0, numElements = this.length, elementClasses, index; for (var i = 0; i < numElements; i++) { // If selected element isn't a tag, move on if (!isTag(this[i])) continue; elementClasses = splitClass(this[i].attribs.class); // Check if class already exists for (var j = 0; j < numClasses; j++) { // Check if the class name is currently defined index = elementClasses.indexOf(classNames[j]); // Add if stateValue === true or we are toggling and there is no value if (state >= 0 && index < 0) { elementClasses.push(classNames[j]); } else if (state <= 0 && index >= 0) { // Otherwise remove but only if the item exists elementClasses.splice(index, 1); } } this[i].attribs.class = elementClasses.join(' '); } return this; }
...
* Fix bug in `removeClass` (@jugglinmike)
* Improve contributing.md (@jugglinmike)
* Fix and document .css() (@jugglinmike)
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
* Correct the implementation `filter` and `is` (@jugglinmike)
* add .data() function (@andi-neck)
* add .css() (@yields)
* Implements contents() (@jlep)
...
val = function (value) { var querying = arguments.length === 0, element = this[0]; if(!element) return; switch (element.name) { case 'textarea': return this.text(value); case 'input': switch (this.attr('type')) { case 'radio': if (querying) { return this.attr('value'); } else { this.attr('value', value); return this; } break; default: return this.attr('value', value); } return; case 'select': var option = this.find('option:selected'), returnValue; if (option === undefined) return undefined; if (!querying) { if (!this.attr().hasOwnProperty('multiple') && typeof value == 'object') { return this; } if (typeof value != 'object') { value = [value]; } this.find('option').removeAttr('selected'); for (var i = 0; i < value.length; i++) { this.find('option[value="' + value[i] + '"]').attr('selected', ''); } return this; } returnValue = option.attr('value'); if (this.attr().hasOwnProperty('multiple')) { returnValue = []; domEach(option, function(i, el) { returnValue.push(getAttr(el, 'value')); }); } return returnValue; case 'option': if (!querying) { this.attr('value', value); return this; } return this.attr('value'); } }
...
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)
0.10.8 / 2013-03-11
==================
...
wrap = function (wrapper) { var wrapperFn = typeof wrapper === 'function' && wrapper, lastIdx = this.length - 1; _.forEach(this, _.bind(function(el, i) { var parent = el.parent || el.root, siblings = parent.children, dom, index; if (!parent) { return; } if (wrapperFn) { wrapper = wrapperFn.call(el, i); } if (typeof wrapper === 'string' && !isHtml(wrapper)) { wrapper = this.parents().last().find(wrapper).clone(); } dom = this._makeDomArray(wrapper, i < lastIdx).slice(0, 1); index = siblings.indexOf(el); updateDOM([el], dom[0]); // The previous operation removed the current element from the `siblings` // array, so the `dom` array can be inserted without removing any // additional elements. uniqueSplice(siblings, index, 0, dom, parent); }, this)); return this; }
...
$('ul').text()
//=> Apple
// Orange
// Pear
```
#### .wrap( content )
The .wrap() function can take any string or object that could be passed to the $() factory function to specify a DOM structure.
This structure may be nested several levels deep, but should contain only one inmost element. A copy of this structure will be wrapped
around each of the elements in the set of matched elements. This method returns the original set of elements for chaining purposes
.
```js
var redFruit = $('<div class="red-fruit"></div>')
$('.apple').wrap(redFruit)
//=> <ul id="fruits">
...
css = function (prop, val) { if (arguments.length === 2 || // When `prop` is a "plain" object (toString.call(prop) === '[object Object]')) { return domEach(this, function(idx, el) { setCss(el, prop, val, idx); }); } else { return getCss(this[0], prop); } }
...
* Implement function signature of `after` (@jugglinmike)
* Implement function signature of `append`/`prepend` (@jugglinmike)
* Extend iteration methods to accept nodes (@jugglinmike)
* Improve `removeClass` (@jugglinmike)
* Complete function signature of `addClass` (@jugglinmike)
* Fix bug in `removeClass` (@jugglinmike)
* Improve contributing.md (@jugglinmike)
* Fix and document .css() (@jugglinmike)
0.12.3 / 2013-10-04
===================
* Add .toggleClass() function (@cyberthom)
* Add contributing guidelines (@jugglinmike)
* Fix bug in `siblings` (@jugglinmike)
...
serialize = function () { // Convert form elements into name/value objects var arr = this.serializeArray(); // Serialize each element into a key/value string var retArr = _.map(arr, function(data) { return encodeURIComponent(data.name) + '=' + encodeURIComponent(data.value); }); // Return the resulting serialization return retArr.join('&').replace(r20, '+'); }
...
* Merge pull request #881 from piamancini/patch-1
* Added backers and sponsors from OpenCollective
* Use jQuery from the jquery module in benchmarks (#871)
* Document, test, and extend static `$.text` method (#855)
* Fix typo on calling _.extend (#861)
* Update versions (#870)
* Use individual lodash functions (#864)
* Added `.serialize()` support. Fixes #69 (#827)
* Update Readme.md (#857)
* add extension for JSON require call
* remove gittask badge
* Merge pull request #672 from underdogio/dev/checkbox.radio.values.sqwished
* Added default value for checkboxes/radios
0.20.0 / 2016-02-01
...
serializeArray = function () { // Resolve all form elements from either forms or collections of form elements var Cheerio = this.constructor; return this.map(function() { var elem = this; var $elem = Cheerio(elem); if (elem.name === 'form') { return $elem.find(submittableSelector).toArray(); } else { return $elem.filter(submittableSelector).toArray(); } }).filter( // Verify elements have a name (`attr.name`) and are not disabled (`:disabled`) '[name!=""]:not(:disabled)' // and cannot be clicked (`[type=submit]`) or are used in `x-www-form-urlencoded` (`[type=file]`) + ':not(:submit, :button, :image, :reset, :file)' // and are either checked/don't have a checkable state + ':matches([checked], :not(:checkbox, :radio))' // Convert each of the elements to its value(s) ).map(function(i, elem) { var $elem = Cheerio(elem); var name = $elem.attr('name'); var val = $elem.val(); // If there is no value set (e.g. `undefined`, `null`), then return nothing if (val == null) { return null; } else { // If we have an array of values (e.g. `<select multiple>`), return an array of key/value pairs if (Array.isArray(val)) { return _.map(val, function(val) { // We trim replace any line endings (e.g. `\r` or `\r\n` with `\r\n`) to guarantee consistency across platforms // These can occur inside of `<textarea>'s` return {name: name, value: val.replace( rCRLF, '\r\n' )}; }); // Otherwise (e.g. `<input type="text">`, return only one key/value pair } else { return {name: name, value: val.replace( rCRLF, '\r\n' )}; } } // Convert our result to an array }).get(); }
...
#### .is( element )
#### .is( selection )
#### .is( function(index) )
Checks the current list of elements and returns `true` if _any_ of the elements match the selector. If using an element or Cheerio
selection, returns `true` if _any_ of the elements match. If using a predicate function, the function is executed in the context
of the selected element, so `this` refers to the current element.
### Forms
#### .serializeArray()
Encode a set of form elements as an array of names and values.
```js
$('<form><input name="foo" value="bar" /></form>').serializeArray()
//=> [ { name: 'foo', value: 'bar' } ]
```
...
function makeDomArray(elem, clone) { if (elem == null) { return []; } else if (elem.cheerio) { return clone ? cloneDom(elem.get(), elem.options) : elem.get(); } else if (Array.isArray(elem)) { return _.flatten(elem.map(function(el) { return this._makeDomArray(el, clone); }, this)); } else if (typeof elem === 'string') { return evaluate(elem, this.options); } else { return clone ? cloneDom([elem]) : [elem]; } }
...
exports._makeDomArray = function makeDomArray(elem, clone) {
if (elem == null) {
return [];
} else if (elem.cheerio) {
return clone ? cloneDom(elem.get(), elem.options) : elem.get();
} else if (Array.isArray(elem)) {
return _.flatten(elem.map(function(el) {
return this._makeDomArray(el, clone);
}, this));
} else if (typeof elem === 'string') {
return evaluate(elem, this.options);
} else {
return clone ? cloneDom([elem]) : [elem];
}
};
...
after = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; domEach(this, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el), domSrc, dom; // If not found, move on if (index < 0) return; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); // Add element after `this` element uniqueSplice(siblings, index + 1, 0, dom, parent); }); return this; }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .after( content, [content, ...] )
Insert content next to each element in the set of matched elements.
```js
$('.apple').after('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
append = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; return domEach(this, function(i, el) { var dom, domSrc; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); concatenator(dom, el.children, el); }); }
...
$('li').eq(0).addBack('.orange').length
//=> 2
```
### Manipulation
Methods for modifying the DOM structure.
#### .append( content, [content, ...] )
Inserts content as the *last* child of each of the selected elements.
```js
$('ul').append('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
appendTo = function (target) { if (!target.cheerio) { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target.append(this); return this; }
...
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// <li class="plum">Plum</li>
// </ul>
```
#### .appendTo( target )
Insert every element in the set of matched elements to the end of the target.
```js
$('<li class="plum">Plum</li>').appendTo('#fruits')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
before = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; domEach(this, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el), domSrc, dom; // If not found, move on if (index < 0) return; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); // Add element before `el` element uniqueSplice(siblings, index, 0, dom, parent); }); return this; }
...
// <li class="apple">Apple</li>
// <li class="plum">Plum</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .before( content, [content, ...] )
Insert content previous to each element in the set of matched elements.
```js
$('.apple').before('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
clone = function () { return this._make(cloneDom(this.get(), this.options)); }
...
* compatible with node 4.x (again)
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
empty = function () { domEach(this, function(i, el) { _.forEach(el.children, function(el) { el.next = el.prev = el.parent = null; }); el.children.length = 0; }); return this; }
...
//=> <ul id="fruits">
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="plum">Plum</li>
// </ul>
```
#### .empty()
Empties an element, removing all its children.
```js
$('ul').empty()
$.html()
//=> <ul id="fruits"></ul>
```
...
html = function (str) { if (str === undefined) { if (!this[0] || !this[0].children) return null; return $.html(this[0].children, this.options); } var opts = this.options; domEach(this, function(i, el) { _.forEach(el.children, function(el) { el.next = el.prev = el.parent = null; }); var content = str.cheerio ? str.clone().get() : evaluate('' + str, opts); updateDOM(content, el); }); return this; }
...
* Change state definition to more readable (Artem Burtsev)
* added test (0xBADC0FFEE)
* add class only if doesn't exist (Artem Burtsev)
* Made it less insane. (Alex Indigo)
* Implement `Cheerio#add` (Mike Pennisi)
* Use "loaded" instance of Cheerio in unit tests (Mike Pennisi)
* Be more strict with object check. (Alex Indigo)
* Added options argument to .html() static method. (Alex Indigo)
* Fixed encoding mishaps. Adjusted tests. (Alex Indigo)
* use dom-serializer module (fb55)
* don't test on 0.8, don't ignore 0.11 (Felix Böhm)
* parse: rm unused variables (coderaiser)
* cheerio: rm unused variable (coderaiser)
* Fixed test (Avi Kohn)
* Added test (Avi Kohn)
...
insertAfter = function (target) { var clones = [], self = this; if (typeof target === 'string') { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target = this._makeDomArray(target); self.remove(); domEach(target, function(i, el) { var clonedSelf = self._makeDomArray(self.clone()); var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el); // If not found, move on if (index < 0) return; // Add cloned `this` element(s) after target element uniqueSplice(siblings, index + 1, 0, clonedSelf, parent); clones.push(clonedSelf); }); return this.constructor.call(this.constructor, this._makeDomArray(clones)); }
...
// <li class="apple">Apple</li>
// <li class="plum">Plum</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .insertAfter( target )
Insert every element in the set of matched elements after the target.
```js
$('<li class="plum">Plum</li>').insertAfter('.apple')
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
insertBefore = function (target) { var clones = [], self = this; if (typeof target === 'string') { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target = this._makeDomArray(target); self.remove(); domEach(target, function(i, el) { var clonedSelf = self._makeDomArray(self.clone()); var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el); // If not found, move on if (index < 0) return; // Add cloned `this` element(s) after target element uniqueSplice(siblings, index, 0, clonedSelf, parent); clones.push(clonedSelf); }); return this.constructor.call(this.constructor, this._makeDomArray(clones)); }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .insertBefore( target )
Insert every element in the set of matched elements before the target.
```js
$('<li class="plum">Plum</li>').insertBefore('.apple')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
prepend = function () { var elems = slice.call(arguments), lastIdx = this.length - 1; return domEach(this, function(i, el) { var dom, domSrc; if (typeof elems[0] === 'function') { domSrc = elems[0].call(el, i, $.html(el.children)); } else { domSrc = elems; } dom = this._makeDomArray(domSrc, i < lastIdx); concatenator(dom, el.children, el); }); }
...
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// <li class="plum">Plum</li>
// </ul>
```
#### .prepend( content, [content, ...] )
Inserts content as the *first* child of each of the selected elements.
```js
$('ul').prepend('<li class="plum">Plum</li>')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
prependTo = function (target) { if (!target.cheerio) { target = this.constructor.call(this.constructor, target, null, this._originalRoot); } target.prepend(this); return this; }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .prependTo( target )
Insert every element in the set of matched elements to the beginning of the target.
```js
$('<li class="plum">Plum</li>').prependTo('#fruits')
$.html()
//=> <ul id="fruits">
// <li class="plum">Plum</li>
...
remove = function (selector) { var elems = this; // Filter if we have selector if (selector) elems = elems.filter(selector); domEach(elems, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, index = siblings.indexOf(el); if (index < 0) return; siblings.splice(index, 1); if (el.prev) { el.prev.next = el.next; } if (el.next) { el.next.prev = el.prev; } el.prev = el.next = el.parent = el.root = null; }); return this; }
...
// <li class="plum">Plum</li>
// <li class="apple">Apple</li>
// <li class="orange">Orange</li>
// <li class="pear">Pear</li>
// </ul>
```
#### .remove( [selector] )
Removes the set of matched elements from the DOM and all their children. `selector` filters the set of matched elements to be removed
.
```js
$('.pear').remove()
$.html()
//=> <ul id="fruits">
// <li class="apple">Apple</li>
...
replaceWith = function (content) { var self = this; domEach(this, function(i, el) { var parent = el.parent || el.root; if (!parent) { return; } var siblings = parent.children, dom = self._makeDomArray(typeof content === 'function' ? content.call(el, i, el) : content), index; // In the case that `dom` contains nodes that already exist in other // structures, ensure those nodes are properly removed. updateDOM(dom, null); index = siblings.indexOf(el); // Completely remove old element uniqueSplice(siblings, index, 1, dom, parent); el.parent = el.prev = el.next = el.root = null; }); return this; }
...
* Now testing with node v0.7.7
* Added travis-ci integration
* Replaced should.js with expect.js. Browser testing to come
* Fixed spacing between attributes and their values
* Added HTML tidy/pretty print
* Exposed node-htmlparser2 parsing options
* Revert .replaceWith(...) to be consistent with jQuery
0.6.2 / 2012-02-12
==================
* Fixed .replaceWith(...) regression
0.6.1 / 2012-02-12
...
text = function (str) { // If `str` is undefined, act as a "getter" if (str === undefined) { return $.text(this); } else if (typeof str === 'function') { // Function support return domEach(this, function(i, el) { var $el = [el]; return exports.text.call($el, str.call(el, i, $.text($el))); }); } // Append text node to each selected elements domEach(this, function(i, el) { _.forEach(el.children, function(el) { el.next = el.prev = el.parent = null; }); var elem = { data: '' + str, type: 'text', parent: el, prev: null, next: null, children: [] }; updateDOM(elem, el); }); return this; }
...
0.9.0 / 2012-07-24
==================
* Added node 8.x support
* Removed node 4.x support
* Add html(dom) support (@wvl)
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55)
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers)
* Tons of cleanup (@davidchambers)
0.8.3 / 2012-06-12
==================
* Fixed minor package regression (closes #60)
...
toString = function () { return $.html(this, this.options); }
n/a
wrap = function (wrapper) { var wrapperFn = typeof wrapper === 'function' && wrapper, lastIdx = this.length - 1; _.forEach(this, _.bind(function(el, i) { var parent = el.parent || el.root, siblings = parent.children, dom, index; if (!parent) { return; } if (wrapperFn) { wrapper = wrapperFn.call(el, i); } if (typeof wrapper === 'string' && !isHtml(wrapper)) { wrapper = this.parents().last().find(wrapper).clone(); } dom = this._makeDomArray(wrapper, i < lastIdx).slice(0, 1); index = siblings.indexOf(el); updateDOM([el], dom[0]); // The previous operation removed the current element from the `siblings` // array, so the `dom` array can be inserted without removing any // additional elements. uniqueSplice(siblings, index, 0, dom, parent); }, this)); return this; }
...
$('ul').text()
//=> Apple
// Orange
// Pear
```
#### .wrap( content )
The .wrap() function can take any string or object that could be passed to the $() factory function to specify a DOM structure.
This structure may be nested several levels deep, but should contain only one inmost element. A copy of this structure will be wrapped
around each of the elements in the set of matched elements. This method returns the original set of elements for chaining purposes
.
```js
var redFruit = $('<div class="red-fruit"></div>')
$('.apple').wrap(redFruit)
//=> <ul id="fruits">
...
parse = function (content, options) { var dom = exports.evaluate(content, options), // Generic root element root = exports.evaluate('<root></root>', options)[0]; root.type = 'root'; // Update the dom using the root exports.update(dom, root); return root; }
...
if (hasOwn.call(primitives, value)) {
value = primitives[value];
} else if (value === String(Number(value))) {
value = Number(value);
} else if (rbrace.test(value)) {
try {
value = JSON.parse(value);
} catch(e){ }
}
el.data[jsName] = value;
}
}
...
evaluate = function (content, options) { // options = options || $.fn.options; var dom; if (typeof content === 'string' || Buffer.isBuffer(content)) { dom = htmlparser.parseDOM(content, options); } else { dom = content; } return dom; }
...
*/
var htmlparser = require('htmlparser2');
/*
Parser
*/
exports = module.exports = function(content, options) {
var dom = exports.evaluate(content, options),
// Generic root element
root = exports.evaluate('<root></root>', options)[0];
root.type = 'root';
// Update the dom using the root
exports.update(dom, root);
...
update = function (arr, parent) { // normalize if (!Array.isArray(arr)) arr = [arr]; // Update parent if (parent) { parent.children = arr; } else { parent = null; } // Update neighbors for (var i = 0; i < arr.length; i++) { var node = arr[i]; // Cleanly remove existing nodes from their previous structures. var oldParent = node.parent || node.root, oldSiblings = oldParent && oldParent.children; if (oldSiblings && oldSiblings !== arr) { oldSiblings.splice(oldSiblings.indexOf(node), 1); if (node.prev) { node.prev.next = node.next; } if (node.next) { node.next.prev = node.prev; } } if (parent) { node.prev = arr[i - 1] || null; node.next = arr[i + 1] || null; } else { node.prev = node.next = null; } if (parent && parent.type === 'root') { node.root = parent; node.parent = null; } else { node.root = null; node.parent = parent; } } return parent; }
...
var dom = exports.evaluate(content, options),
// Generic root element
root = exports.evaluate('<root></root>', options)[0];
root.type = 'root';
// Update the dom using the root
exports.update(dom, root);
return root;
};
exports.evaluate = function(content, options) {
// options = options || $.fn.options;
...
contains = function (container, contained) { // According to the jQuery API, an element does not "contain" itself if (contained === container) { return false; } // Step up the descendants, 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; }
...
* Code & doc cleanup (davidchambers)
* Fixed bug in filter (jugglinmike)
0.10.6 / 2013-01-29
==================
* Added `$.contains(...)` (jugglinmike)
* formatting cleanup (davidchambers)
* Bug fix for `.children()` (jugglinmike & davidchambers)
* Remove global `render` bug (wvl)
0.10.5 / 2012-12-18
===================
...
html = function (dom, options) { var Cheerio = require('./cheerio'); // be flexible about parameters, sometimes we call html(), // with options as only parameter // check dom argument for dom element specific properties // assume there is no 'length' or 'type' properties in the options object if (Object.prototype.toString.call(dom) === '[object Object]' && !options && !('length' in dom) && !('type' in dom)) { options = dom; dom = undefined; } // sometimes $.html() used without preloading html // so fallback non existing options to the default ones options = _.defaults(options || {}, this._options, Cheerio.prototype.options); return render(this, dom, options); }
...
* Change state definition to more readable (Artem Burtsev)
* added test (0xBADC0FFEE)
* add class only if doesn't exist (Artem Burtsev)
* Made it less insane. (Alex Indigo)
* Implement `Cheerio#add` (Mike Pennisi)
* Use "loaded" instance of Cheerio in unit tests (Mike Pennisi)
* Be more strict with object check. (Alex Indigo)
* Added options argument to .html() static method. (Alex Indigo)
* Fixed encoding mishaps. Adjusted tests. (Alex Indigo)
* use dom-serializer module (fb55)
* don't test on 0.8, don't ignore 0.11 (Felix Böhm)
* parse: rm unused variables (coderaiser)
* cheerio: rm unused variable (coderaiser)
* Fixed test (Avi Kohn)
* Added test (Avi Kohn)
...
load = function (content, options) { var Cheerio = require('./cheerio'); options = _.defaults(options || {}, Cheerio.prototype.options); var root = parse(content, options); var initialize = function(selector, context, r, opts) { if (!(this instanceof initialize)) { return new initialize(selector, context, r, opts); } opts = _.defaults(opts || {}, options); return Cheerio.call(this, selector, context, r || root, opts); }; // Ensure that selections created by the "loaded" `initialize` function are // true Cheerio instances. initialize.prototype = Object.create(Cheerio.prototype); initialize.prototype.constructor = initialize; // Mimic jQuery's prototype alias for plugin authors. initialize.fn = initialize.prototype; // Keep a reference to the top-level scope so we can chain methods that implicitly // resolve selectors; e.g. $("<span>").(".bar"), which otherwise loses ._root initialize.prototype._originalRoot = root; // Add in the static methods _.merge(initialize, exports); // Add in the root initialize._root = root; // store options initialize._options = options; return initialize; }
...
</a>
</div>
<br />
```js
let cheerio = require('cheerio')
let $ = cheerio.load('<h2 class="title">Hello world</h2
>')
$('h2.title').text('Hello there!')
$('h2').addClass('welcome')
$.html()
//=> <h2 class="title welcome">Hello there!</h2>
```
...
parseHTML = function (data, context, keepScripts) { var parsed; if (!data || typeof data !== 'string') { return null; } if (typeof context === 'boolean') { keepScripts = context; } parsed = this.load(data); if (!keepScripts) { parsed('script').remove(); } // The `children` array is used by Cheerio internally to group elements that // share the same parents. When nodes created through `parseHTML` are // inserted into previously-existing DOM structures, they will be removed // from the `children` array. The results of `parseHTML` should remain // constant across these operations, so a shallow copy should be returned. return parsed.root()[0].children.slice(); }
...
$.root().append('<ul id="vegetables"></ul>').html();
//=> <ul id="fruits">...</ul><ul id="vegetables"></ul>
```
#### $.contains( container, contained )
Checks to see if the `contained` DOM element is a descendant of the `container` DOM element.
#### $.parseHTML( data [, context ] [, keepScripts ] )
Parses a string into an array of DOM nodes. The `context` argument has no meaning for Cheerio, but it is maintained for API compatability
.
#### $.load( html[, options ] )
Load in the HTML. (See the previous section titled "Loading" for more information.)
### Plugins
...
root = function () { return this(this._root); }
...
* compatible with node 4.x (again)
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
text = function (elems) { if (!elems) { elems = this.root(); } var ret = '', len = elems.length, elem; for (var i = 0; i < len; i++) { elem = elems[i]; if (elem.type === 'text') ret += elem.data; else if (elem.children && elem.type !== 'comment') { ret += exports.text(elem.children); } } return ret; }
...
0.9.0 / 2012-07-24
==================
* Added node 8.x support
* Removed node 4.x support
* Add html(dom) support (@wvl)
* fixed xss vulnerabilities on .attr(), .text(), & .html() (@benatkin, @FB55)
* Rewrote tests into javascript, removing coffeescript dependency (@davidchambers)
* Tons of cleanup (@davidchambers)
0.8.3 / 2012-06-12
==================
* Fixed minor package regression (closes #60)
...
xml = function (dom) { var options = _.defaults({xmlMode: true}, this._options); return render(this, dom, options); }
...
* added test case for malformed json in data attributes (fb55)
* fix: handle some extreme cases like `data-custom="{{templatevar}}"`. There is possibility error while parsing json . (
Harish.K)
* Add missing optional selector doc for {prev,next}{All,Until} (Jérémie Astori)
* update to dom-serializer@0.1.0 (Felix Böhm)
* Document `Cheerio#serialzeArray` (Mike Pennisi)
* Fixed up `serializeArray()` and added multiple support (Todd Wolfson)
* Implement serializeArray() (Jarno Leppänen)
* recognize options in $.xml() (fb55)
* lib/static.js: text(): rm errant space before ++ (Chris Rebert)
* Do not expose internal `children` array (Mike Pennisi)
* Change lodash dependencies to ^3.1.0 (Samy Pessé)
* Update lodash@3.1.0 (Samy Pessé)
* Updates Readme.md: .not(function (index, elem)) (Patrick Ward)
* update to css-select@1.0.0 (fb55)
* Allow failures in Node.js v0.11 (Mike Pennisi)
...
add = function (other, context) { var selection = this._make(other, context); var contents = uniqueSort(selection.get().concat(this.get())); for (var i = 0; i < contents.length; ++i) { selection[i] = contents[i]; } selection.length = contents.length; return selection; }
...
End the most recent filtering operation in the current chain and return the set of matched elements to its previous state.
```js
$('li').eq(0).end().length
//=> 3
```
#### .add( selector [, context] )
#### .add( element )
#### .add( elements )
#### .add( html )
#### .add( selection )
Add elements to the set of matched elements.
```js
...
addBack = function (selector) { return this.add( arguments.length ? this.prevObject.filter(selector) : this.prevObject ); }
...
Add elements to the set of matched elements.
```js
$('.apple').add('.orange').length
//=> 2
```
#### .addBack( [filter] )
Add the previous set of elements on the stack to the current set, optionally filtered by a selector.
```js
$('li').eq(0).addBack('.orange').length
//=> 2
```
...
children = function (selector) { var elems = _.reduce(this, function(memo, elem) { return memo.concat(_.filter(elem.children, isTag)); }, []); if (selector === undefined) return this._make(elems); return exports.filter.call(elems, selector, this); }
...
* Fixed bug in filter (jugglinmike)
0.10.6 / 2013-01-29
==================
* Added `$.contains(...)` (jugglinmike)
* formatting cleanup (davidchambers)
* Bug fix for `.children()` (jugglinmike & davidchambers)
* Remove global `render` bug (wvl)
0.10.5 / 2012-12-18
===================
* Fixed botched publish from 0.10.4 - changes should now be present
...
closest = function (selector) { var set = []; if (!selector) { return this._make(set); } domEach(this, function(idx, elem) { var closestElem = traverseParents(this, elem, selector, 1)[0]; // Do not add duplicate elements to the set if (closestElem && set.indexOf(closestElem) < 0) { set.push(closestElem); } }.bind(this)); return this._make(set); }
...
* Added: prevAll, nextAll (@lessmind)
* Fixed: Safety check in parents and closest (@zero21xxx)
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)
0.10.8 / 2013-03-11
...
contents = function () { return this._make(_.reduce(this, function(all, elem) { all.push.apply(all, elem.children); return all; }, [])); }
...
$('#fruits').children().length
//=> 3
$('#fruits').children('.pear').text()
//=> Pear
```
#### .contents()
Gets the children of each element in the set of matched elements, including text and comment nodes.
```js
$('#fruits').contents().length
//=> 3
```
...
each = function (fn) { var i = 0, len = this.length; while (i < len && fn.call(this[i], i, this[i]) !== false) ++i; return this; }
...
Gets the children of each element in the set of matched elements, including text and comment nodes.
```js
$('#fruits').contents().length
//=> 3
```
#### .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
`. To break out of the `each` loop early, return with `false`.
```js
var fruits = [];
$('li').each(function(i, elem) {
fruits[i] = $(this).text();
...
end = function () { return this.prevObject || this._make([]); }
...
//=> 2
$('.orange').index('li')
//=> 1
$('.apple').index($('#fruit, li'))
//=> 1
```
#### .end()
End the most recent filtering operation in the current chain and return the set of matched elements to its previous state.
```js
$('li').eq(0).end().length
//=> 3
```
...
eq = function (i) { i = +i; // Use the first identity optimization if possible if (i === 0 && this.length <= 1) return this; if (i < 0) i = this.length + i; return this[i] ? this._make(this[i]) : this._make([]); }
...
0.8.0 / 2012-05-27
==================
* Updated CSS parser to use FB55/CSSselect. Cheerio now supports most CSS3 psuedo selectors thanks to @FB55.
* ignoreWhitespace now on by default again. See #55 for context.
* Changed $(':root') to $.root(), cleaned up $.clone()
* Support for .eq(i) thanks to @alexbardas
* Removed support for node 0.4.x
* Fixed memory leak where package.json was continually loaded
* Tons more tests
0.7.0 / 2012-04-08
==================
...
filter = function (match, container) { var testFn; container = container || this; if (typeof match === 'string') { testFn = select.compile(match, container.options); } else if (typeof match === 'function') { testFn = function(el, i) { return match.call(el, i, el); }; } else if (match.cheerio) { testFn = match.is.bind(match); } else { testFn = function(el) { return match === el; }; } return container._make(filterFn(this, testFn)); }
...
$('li').map(function(i, el) {
// this === el
return $(this).text();
}).get().join(' ');
//=> "apple orange pear"
```
#### .filter( selector ) <br /> .filter( selection ) <br /> .filter
( element ) <br /> .filter( function(index) )
Iterates over a cheerio object, reducing the set of selector elements to those that match the selector or pass the function'
;s test. When a Cheerio selection is specified, return only the elements contained in that selection. When an element is specified
, return only that element (if it is contained in the original selection). If using the function method, the function is executed
in the context of the selected element, so `this` refers to the current element.
Selector:
```js
$('li').filter('.orange').attr('class');
...
find = function (selectorOrHaystack) { var elems = _.reduce(this, function(memo, elem) { return memo.concat(_.filter(elem.children, isTag)); }, []); var contains = this.constructor.contains; var haystack; if (selectorOrHaystack && typeof selectorOrHaystack !== 'string') { if (selectorOrHaystack.cheerio) { haystack = selectorOrHaystack.get(); } else { haystack = [selectorOrHaystack]; } return this._make(haystack.filter(function(elem) { var idx, len; for (idx = 0, len = this.length; idx < len; ++idx) { if (contains(this[idx], elem)) { return true; } } }, this)); } var options = {__proto__: this.options, context: this.toArray()}; return this._make(select(selectorOrHaystack, elems, options)); }
...
0.20.0 / 2016-02-01
==================
* Add coveralls badge, remove link to old report (Felix Böhm)
* Update lodash dependeny to 4.1.0 (leif.hanack)
* Fix PR #726 adding 'appendTo()' and 'prependTo()' (Delgan)
* Added appendTo and prependTo with tests #641 (digihaven)
* Fix #780 by changing options context in '.find()' (Felix Böhm)
* Add an unit test checking the query of child (Delgan)
* fix #667: attr({foo: null}) removes attribute foo, like attr('foo', null) (Ray Waldin)
* Include reference to dedicated "Loading" section (Mike Pennisi)
* Added load method to $ (alanev)
* update css-select to 1.2.0 (Felix Böhm)
* Fixing Grammatical Error (Dan Corman)
* Test against node v0.12 --> v4.2 (Jason Kurian)
...
first = function () { return this.length > 1 ? this._make(this[0]) : this; }
...
==================
* Fixed .replaceWith(...) regression
0.6.1 / 2012-02-12
==================
* Added .first(), .last(), and .clone() commands.
* Option to parse using whitespace added to `.load`.
* Many bug fixes to make cheerio more aligned with jQuery.
* Added $(':root') to select the highest level element.
Many thanks to the contributors that made this release happen: @ironchefpython and @siddMahen
0.6.0 / 2012-02-07
...
get = function (i) { if (i == null) { return Array.prototype.slice.call(this); } else { return this[i < 0 ? (this.length + i) : i]; } }
...
* Added jQuery's $(...).replaceWith(...)
0.3.0 / 2011-11-19
==================
* Now using htmlparser2 for parsing (2x speed increase, cleaner, actively developed)
* Added benchmark directory for future speed tests
* $('...').dom() was funky, so it was removed in favor of $('...').get
span>(). $.dom() still works the same.
* $.root now correctly static across all instances of $
* Added a screencast
0.2.2 / 2011-11-9
=================
* Traversing will select `<script>` and `<style>` tags (Closes Issue: #8)
...
has = function (selectorOrHaystack) { var that = this; return exports.filter.call(this, function() { return that._make(this).find(selectorOrHaystack).length > 0; }); }
...
0.18.0 / 2014-11-06
==================
* bump htmlparser2 dependency to ~3.8.1 (Chris Rebert)
* Correct unit test titles (Mike Pennisi)
* Correct behavior of `after` and `before` (Mike Pennisi)
* implement jQuery's .has() (Chris Rebert)
* Update repository url (haqii)
* attr() should return undefined or name for booleans (Raoul Millais)
* Update Readme.md (Ryan Breen)
* Implement `Cheerio#not` (Mike Pennisi)
* Clone nodes according to original parsing options (Mike Pennisi)
* fix lint error (David Chambers)
* Add explicit tests for DOM level 1 API (Mike Pennisi)
...
index = function (selectorOrNeedle) { var $haystack, needle; if (arguments.length === 0) { $haystack = this.parent().children(); needle = this[0]; } else if (typeof selectorOrNeedle === 'string') { $haystack = this._make(selectorOrNeedle); needle = this[0]; } else { $haystack = this; needle = selectorOrNeedle.cheerio ? selectorOrNeedle[0] : selectorOrNeedle; } return $haystack.get().indexOf(needle); }
...
If no index is specified, retrieve all elements matched by the Cheerio object:
```js
$('li').get().length
//=> 3
```
#### .index()
#### .index( selector )
#### .index( nodeOrSelection )
Search for a given element from among the matched elements.
```js
$('.pear').index()
...
last = function () { return this.length > 1 ? this._make(this[this.length - 1]) : this; }
...
==================
* Fixed .replaceWith(...) regression
0.6.1 / 2012-02-12
==================
* Added .first(), .last(), and .clone() commands.
* Option to parse using whitespace added to `.load`.
* Many bug fixes to make cheerio more aligned with jQuery.
* Added $(':root') to select the highest level element.
Many thanks to the contributors that made this release happen: @ironchefpython and @siddMahen
0.6.0 / 2012-02-07
...
map = function (fn) { return this._make(_.reduce(this, function(memo, el, i) { var val = fn.call(el, i, el); return val == null ? memo : memo.concat(val); }, [])); }
...
* Now supports mocha's test-coverage
* Deprecated self-closing tags (HTML5 doesn't require them)
* Fixed error thrown in removeClass(...) @robashton
0.9.2 / 2012-08-10
==================
* added $(...).map(fn)
* manipulation: refactor `makeCheerioArray`
* make .removeClass() remove *all* occurrences (#64)
0.9.1 / 2012-08-03
==================
* fixed bug causing options not to make it to the parser
...
next = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.next)) { if (isTag(elem)) { elems.push(elem); return; } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
// => []
$('.orange').closest('li')
// => [<li class="orange">Orange</li>]
$('.orange').closest('#fruits')
// => [<ul id="fruits"> ... </ul>]
```
#### .next([selector])
Gets the next sibling of the first selected element, optionally filtered by a selector.
```js
$('.apple').next().hasClass('orange')
//=> true
```
...
nextAll = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.next)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
Gets the next sibling of the first selected element, optionally filtered by a selector.
```js
$('.apple').next().hasClass('orange')
//=> true
```
#### .nextAll([selector])
Gets all the following siblings of the first selected element, optionally filtered by a selector.
```js
$('.apple').nextAll()
//=> [<li class="orange">Orange</li>, <li class="pear">Pear</li>
;]
$('.apple').nextAll('.orange')
//=> [<li class="orange">Orange</li>]
...
nextUntil = function (selector, filterSelector) { if (!this[0]) { return this; } var elems = [], untilNode, untilNodes; if (typeof selector === 'string') { untilNode = select(selector, this.nextAll().get(), this.options)[0]; } else if (selector && selector.cheerio) { untilNodes = selector.get(); } else if (selector) { untilNode = selector; } _.forEach(this, function(elem) { while ((elem = elem.next)) { if ((untilNode && elem !== untilNode) || (untilNodes && untilNodes.indexOf(elem) === -1) || (!untilNode && !untilNodes)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } else { break; } } }); return filterSelector ? exports.filter.call(elems, filterSelector, this) : this._make(elems); }
...
```js
$('.apple').nextAll()
//=> [<li class="orange">Orange</li>, <li class="pear">Pear</li>
;]
$('.apple').nextAll('.orange')
//=> [<li class="orange">Orange</li>]
```
#### .nextUntil([selector], [filter])
Gets all the following siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.apple').nextUntil('.pear')
//=> [<li class="orange">Orange</li>]
```
...
not = function (match, container) { var testFn; container = container || this; if (typeof match === 'string') { testFn = select.compile(match, container.options); } else if (typeof match === 'function') { testFn = function(el, i) { return match.call(el, i, el); }; } else if (match.cheerio) { testFn = match.is.bind(match); } else { testFn = function(el) { return match === el; }; } return container._make(filterFn(this, testFn)); }
...
* Fixed up `serializeArray()` and added multiple support (Todd Wolfson)
* Implement serializeArray() (Jarno Leppänen)
* recognize options in $.xml() (fb55)
* lib/static.js: text(): rm errant space before ++ (Chris Rebert)
* Do not expose internal `children` array (Mike Pennisi)
* Change lodash dependencies to ^3.1.0 (Samy Pessé)
* Update lodash@3.1.0 (Samy Pessé)
* Updates Readme.md: .not(function (index, elem)) (Patrick Ward)
* update to css-select@1.0.0 (fb55)
* Allow failures in Node.js v0.11 (Mike Pennisi)
* Added: Gittask badge (Matthew Mueller)
* Isolate prototypes of functions created via `load` (Mike Pennisi)
* Updates Readme.md: adds JS syntax highlighting (frankcash)
* #608 -- Add support for insertBefore/insertAfter syntax. Supports target types of: $, [$], selector (both single and multiple
results) (Ben Cochran)
* Clone input nodes when inserting over a set (Mike Pennisi)
...
parent = function (selector) { var set = []; domEach(this, function(idx, elem) { var parentElem = elem.parent; if (parentElem && set.indexOf(parentElem) < 0) { set.push(parentElem); } }); if (arguments.length) { set = exports.filter.call(set, selector, this); } return this._make(set); }
...
```js
$('#fruits').find('li').length
//=> 3
$('#fruits').find($('.apple')).length
//=> 1
```
#### .parent([selector])
Get the parent of each element in the current set of matched elements, optionally filtered by a selector.
```js
$('.pear').parent().attr('id')
//=> fruits
```
...
parents = function (selector) { var parentNodes = []; // When multiple DOM elements are in the original set, the resulting set will // be in *reverse* order of the original elements as well, with duplicates // removed. this.get().reverse().forEach(function(elem) { traverseParents(this, elem.parent, selector, Infinity) .forEach(function(node) { if (parentNodes.indexOf(node) === -1) { parentNodes.push(node); } } ); }, this); return this._make(parentNodes); }
...
* Fixed: Safety check in parents and closest (@zero21xxx)
* Added: .is(sel) (@zero21xxx)
0.11.0 / 2013-04-22
==================
* Added: .closest() (@jeremy-dentel)
* Added: .parents() (@zero21xxx)
* Added: .val() (@rschmukler & @leahciMic)
* Added: Travis support for node 0.10.0 (@jeremy-dentel)
* Fixed: .find() if no selector (@davidchambers)
* Fixed: Propagate syntax errors caused by invalid selectors (@davidchambers)
0.10.8 / 2013-03-11
==================
...
parentsUntil = function (selector, filter) { var parentNodes = [], untilNode, untilNodes; if (typeof selector === 'string') { untilNode = select(selector, this.parents().toArray(), this.options)[0]; } else if (selector && selector.cheerio) { untilNodes = selector.toArray(); } else if (selector) { untilNode = selector; } // When multiple DOM elements are in the original set, the resulting set will // be in *reverse* order of the original elements as well, with duplicates // removed. this.toArray().reverse().forEach(function(elem) { while ((elem = elem.parent)) { if ((untilNode && elem !== untilNode) || (untilNodes && untilNodes.indexOf(elem) === -1) || (!untilNode && !untilNodes)) { if (isTag(elem) && parentNodes.indexOf(elem) === -1) { parentNodes.push(elem); } } else { break; } } }, this); return this._make(filter ? select(filter, parentNodes, this.options) : parentNodes); }
...
```js
$('.orange').parents().length
// => 2
$('.orange').parents('#fruits').length
// => 1
```
#### .parentsUntil([selector][,filter])
Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector
, DOM node, or cheerio object.
```js
$('.orange').parentsUntil('#food').length
// => 1
```
#### .closest(selector)
...
prev = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.prev)) { if (isTag(elem)) { elems.push(elem); return; } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
Gets all the following siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.apple').nextUntil('.pear')
//=> [<li class="orange">Orange</li>]
```
#### .prev([selector])
Gets the previous sibling of the first selected element optionally filtered by a selector.
```js
$('.orange').prev().hasClass('apple')
//=> true
```
...
prevAll = function (selector) { if (!this[0]) { return this; } var elems = []; _.forEach(this, function(elem) { while ((elem = elem.prev)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } }); return selector ? exports.filter.call(elems, selector, this) : this._make(elems); }
...
Gets the previous sibling of the first selected element optionally filtered by a selector.
```js
$('.orange').prev().hasClass('apple')
//=> true
```
#### .prevAll([selector])
Gets all the preceding siblings of the first selected element, optionally filtered by a selector.
```js
$('.pear').prevAll()
//=> [<li class="orange">Orange</li>, <li class="apple">Apple</li>
;]
$('.pear').prevAll('.orange')
//=> [<li class="orange">Orange</li>]
...
prevUntil = function (selector, filterSelector) { if (!this[0]) { return this; } var elems = [], untilNode, untilNodes; if (typeof selector === 'string') { untilNode = select(selector, this.prevAll().get(), this.options)[0]; } else if (selector && selector.cheerio) { untilNodes = selector.get(); } else if (selector) { untilNode = selector; } _.forEach(this, function(elem) { while ((elem = elem.prev)) { if ((untilNode && elem !== untilNode) || (untilNodes && untilNodes.indexOf(elem) === -1) || (!untilNode && !untilNodes)) { if (isTag(elem) && elems.indexOf(elem) === -1) { elems.push(elem); } } else { break; } } }); return filterSelector ? exports.filter.call(elems, filterSelector, this) : this._make(elems); }
...
```js
$('.pear').prevAll()
//=> [<li class="orange">Orange</li>, <li class="apple">Apple</li>
;]
$('.pear').prevAll('.orange')
//=> [<li class="orange">Orange</li>]
```
#### .prevUntil([selector], [filter])
Gets all the preceding siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.pear').prevUntil('.apple')
//=> [<li class="orange">Orange</li>]
```
...
siblings = function (selector) { var parent = this.parent(); var elems = _.filter( parent ? parent.children() : this.siblingsAndMe(), _.bind(function(elem) { return isTag(elem) && !this.is(elem); }, this) ); if (selector !== undefined) { return exports.filter.call(elems, selector, this); } else { return this._make(elems); } }
...
$('li').slice(1).eq(0).text()
//=> 'Orange'
$('li').slice(1, 2).length
//=> 1
```
#### .siblings([selector])
Gets the first selected element's siblings, excluding itself.
```js
$('.pear').siblings().length
//=> 2
$('.pear').siblings('.orange').length
...
slice = function () { return this._make([].slice.apply(this, arguments)); }
...
Gets all the preceding siblings up to but not including the element matched by the selector, optionally filtered by another selector
.
```js
$('.pear').prevUntil('.apple')
//=> [<li class="orange">Orange</li>]
```
#### .slice( start, [end] )
Gets the elements matching the specified range
```js
$('li').slice(1).eq(0).text()
//=> 'Orange'
$('li').slice(1, 2).length
...
camelCase = function (str) { return str.replace(/[_.-](\w|$)/g, function(_, x) { return x.toUpperCase(); }); }
n/a
cloneDom = function (dom, options) { return parse(render(dom, options), options).children; }
n/a
cssCase = function (str) { return str.replace(/[A-Z]/g, '-$&').toLowerCase(); }
n/a
domEach = function (cheerio, fn) { var i = 0, len = cheerio.length; while (i < len && fn.call(cheerio, i, cheerio[i]) !== false) ++i; return cheerio; }
n/a
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; // Run the regex var match = quickExpr.exec(str); return !!(match && match[1]); }
n/a
isTag = function (type) { if (type.type) type = type.type; return tags[type] || false; }
n/a