cheerio
Advanced tools
Comparing version 0.10.8 to 0.11.0
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 | ||
@@ -3,0 +13,0 @@ ================== |
@@ -27,4 +27,3 @@ var _ = require('underscore'), | ||
if (!elem || !isTag(elem)) | ||
return undefined; | ||
if (!elem || !isTag(elem)) return; | ||
@@ -56,2 +55,73 @@ if (!elem.attribs) { | ||
/** | ||
* Get the value of an element | ||
*/ | ||
var val = exports.val = function(value) { | ||
var querying = arguments.length === 0, | ||
element = this[0]; | ||
if(!element) return; | ||
switch (element.name) { | ||
case 'textarea': | ||
return querying ? this.text() : this.each(function() { | ||
this.text(value); | ||
}); | ||
case 'input': | ||
switch (this.attr('type')) { | ||
case 'radio': | ||
var queryString = 'input[type=radio][name=' + this.attr('name') + ']:checked'; | ||
var parentEl = this; | ||
//Go up until we hit a form or root | ||
while(parentEl[0].name != 'form' && parentEl[0].name != 'root') parentEl = parentEl.parent(); | ||
if (querying) { | ||
return parentEl.find(queryString).attr('value'); | ||
} else { | ||
parentEl.find(':checked').removeAttr('checked'); | ||
parentEl.find('input[type=radio][value="' + value + '"]').attr('checked', ''); | ||
return this; | ||
} | ||
break; | ||
case 'checkbox': | ||
//@todo wwjd (what would jquery do) | ||
if (this.attr().hasOwnProperty('checked')) { | ||
return this.attr('value'); | ||
} | ||
return null; | ||
default: | ||
return querying ? this.attr('value') : this.each(function() { | ||
this.attr('value', value); | ||
}); | ||
} | ||
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 = []; | ||
option.each(function() { | ||
returnValue.push(this.attr('value')); | ||
}); | ||
} | ||
return returnValue; | ||
} | ||
}; | ||
/** | ||
* Remove an attribute | ||
@@ -58,0 +128,0 @@ */ |
@@ -7,9 +7,3 @@ var _ = require('underscore'), | ||
var find = exports.find = function(selector) { | ||
if (!selector) return this; | ||
try { | ||
var elem = select(selector, [].slice.call(this.children())); | ||
return this.make(elem); | ||
} catch(e) { | ||
return this.make([]); | ||
} | ||
return this.make(select(selector, [].slice.call(this.children()))); | ||
}; | ||
@@ -24,38 +18,35 @@ | ||
var next = exports.next = function(elem) { | ||
if (!this[0]) return this; | ||
var parents = exports.parents = function(selector) { | ||
var elems = traverseParents(this, this[0].parent, selector, Infinity); | ||
return elems.length ? elems : this; | ||
}; | ||
var nextSibling = this[0].next; | ||
while (nextSibling) { | ||
if (isTag(nextSibling)) return this.make(nextSibling); | ||
nextSibling = nextSibling.next; | ||
} | ||
var closest = exports.closest = function(selector) { | ||
return selector ? traverseParents(this, this[0], selector, 1) : []; | ||
}; | ||
return this; | ||
var next = exports.next = function() { | ||
var elem = this[0]; | ||
while ((elem = elem.next)) if (isTag(elem)) return this.make(elem); | ||
return this.make([]); | ||
}; | ||
var prev = exports.prev = function(elem) { | ||
if (!this[0]) return this; | ||
var prev = exports.prev = function() { | ||
var elem = this[0]; | ||
while ((elem = elem.prev)) if (isTag(elem)) return this.make(elem); | ||
return this.make([]); | ||
}; | ||
var prevSibling = this[0].prev; | ||
while (prevSibling) { | ||
if (isTag(prevSibling)) return this.make(prevSibling); | ||
prevSibling = prevSibling.prev; | ||
var siblings = exports.siblings = function(selector) { | ||
var elems = _.filter( | ||
this.parent() ? this.parent().children() : this.siblingsAndMe(), | ||
function(elem) { return isTag(elem) && elem !== this[0]; }, | ||
this | ||
); | ||
if (selector !== undefined) { | ||
elems = this.make(select(selector, elems)); | ||
} | ||
return this; | ||
return this.make(elems); | ||
}; | ||
var siblings = exports.siblings = function(elem) { | ||
if (!this[0]) return this; | ||
var self = this, | ||
siblings = (this.parent()) ? this.parent().children() | ||
: this.siblingsAndMe(); | ||
siblings = _.filter(siblings, function(elem) { | ||
return (elem !== self[0] && isTag(elem)); | ||
}); | ||
return this.make(siblings); | ||
}; | ||
var children = exports.children = function(selector) { | ||
@@ -74,12 +65,4 @@ | ||
var each = exports.each = function(fn) { | ||
var length = this.length, | ||
el, i; | ||
for (i = 0; i < length; ++i) { | ||
el = this[i]; | ||
if (fn.call(this.make(el), i, el) === false) { | ||
break; | ||
} | ||
} | ||
var i = 0, len = this.length; | ||
while (i < len && fn.call(this.make(this[i]), i, this[i]) !== false) ++i; | ||
return this; | ||
@@ -120,1 +103,12 @@ }; | ||
}; | ||
function traverseParents(self, elem, selector, limit) { | ||
var elems = []; | ||
while (elems.length < limit && elem.type !== 'root') { | ||
if (!selector || self.make(elem).filter(selector).length) { | ||
elems.push(elem); | ||
} | ||
elem = elem.parent; | ||
} | ||
return self.make(elems); | ||
} |
@@ -6,3 +6,3 @@ { | ||
"keywords": ["htmlparser", "jquery", "selector", "scraper"], | ||
"version": "0.10.8", | ||
"version": "0.11.0", | ||
"repository": { | ||
@@ -9,0 +9,0 @@ "type": "git", |
145
Readme.md
@@ -10,3 +10,3 @@ # cheerio [![Build Status](https://secure.travis-ci.org/MatthewMueller/cheerio.png?branch=master)](http://travis-ci.org/MatthewMueller/cheerio) | ||
var cheerio = require('cheerio'), | ||
$ = cheerio.load('<h2 class = "title">Hello world</h2>'); | ||
$ = cheerio.load('<h2 class="title">Hello world</h2>'); | ||
@@ -17,3 +17,3 @@ $('h2.title').text('Hello there!'); | ||
$.html(); | ||
//=> <h2 class = "title welcome">Hello there!</h2> | ||
//=> <h2 class="title welcome">Hello there!</h2> | ||
``` | ||
@@ -71,3 +71,3 @@ | ||
var cheerio = require('cheerio'), | ||
$ = cheerio.load('<ul id = "fruits">...</ul>'); | ||
$ = cheerio.load('<ul id="fruits">...</ul>'); | ||
``` | ||
@@ -79,3 +79,3 @@ | ||
$ = require('cheerio'); | ||
$('ul', '<ul id = "fruits">...</ul>'); | ||
$('ul', '<ul id="fruits">...</ul>'); | ||
``` | ||
@@ -87,3 +87,3 @@ | ||
$ = require('cheerio'); | ||
$('li', 'ul', '<ul id = "fruits">...</ul>'); | ||
$('li', 'ul', '<ul id="fruits">...</ul>'); | ||
``` | ||
@@ -95,3 +95,3 @@ | ||
```js | ||
$ = cheerio.load('<ul id = "fruits">...</ul>', { | ||
$ = cheerio.load('<ul id="fruits">...</ul>', { | ||
ignoreWhitespace: true, | ||
@@ -113,4 +113,4 @@ xmlMode: true | ||
For a list of options and their effects, see [this](https://github.com/FB55/node-htmlparser/wiki/DOMHandler) and | ||
[this](https://github.com/FB55/node-htmlparser/wiki/Parser-options). | ||
For a list of options and their effects, see [this](https://github.com/fb55/DomHandler) and | ||
[this](https://github.com/fb55/htmlparser2/wiki/Parser-options). | ||
@@ -134,3 +134,3 @@ ### Selectors | ||
$('li[class=orange]').html() | ||
//=> <li class = "orange">Orange</li> | ||
//=> <li class="orange">Orange</li> | ||
``` | ||
@@ -149,3 +149,3 @@ | ||
$('.apple').attr('id', 'favorite').html() | ||
//=> <li class = "apple" id = "favorite">Apple</li> | ||
//=> <li class="apple" id="favorite">Apple</li> | ||
``` | ||
@@ -155,2 +155,12 @@ | ||
#### .val( [value] ) | ||
Method for getting and setting the value of input, select, and textarea. Note: Support for `map`, and `function` has not been added yet. | ||
$('input[type="text"]').val() | ||
=> input_text | ||
$('input[type="text"]').val('test').html() | ||
=> <input type="text" value="test"/> | ||
#### .removeAttr( name ) | ||
@@ -183,6 +193,6 @@ Method for removing attributes by `name`. | ||
$('.pear').addClass('fruit').html() | ||
//=> <li class = "pear fruit">Pear</li> | ||
//=> <li class="pear fruit">Pear</li> | ||
$('.apple').addClass('fruit red').html() | ||
//=> <li class = "apple fruit red">Apple</li> | ||
//=> <li class="apple fruit red">Apple</li> | ||
``` | ||
@@ -197,6 +207,6 @@ | ||
$('.pear').removeClass('pear').html() | ||
//=> <li class = "">Pear</li> | ||
//=> <li class="">Pear</li> | ||
$('.apple').addClass('red').removeClass().html() | ||
//=> <li class = "">Apple</li> | ||
//=> <li class="">Apple</li> | ||
``` | ||
@@ -225,2 +235,25 @@ | ||
#### .parents([selector]) | ||
Get a set of parents filtered by `selector` of each element in the current set of match elements. | ||
```js | ||
$('.orange').parents().length | ||
// => 2 | ||
$('.orange').parents('#fruits').length | ||
// => 1 | ||
``` | ||
#### .closest(selector) | ||
Get the closest element that matches the selector by searching through the element and the elements parents. | ||
```js | ||
$('.orange').closest() | ||
// => [] | ||
$('.orange').closest('.apple') | ||
// => [] | ||
$('.orange').closest('li') | ||
// => [<li class="orange">Orange</li>] | ||
$('.orange').closest('#fruits') | ||
// => [<ul id="fruits"> ... </ul>] | ||
``` | ||
#### .next() | ||
@@ -253,3 +286,3 @@ Gets the next sibling of the first selected element. | ||
#### .siblings() | ||
#### .siblings( selector ) | ||
Gets the first selected element's siblings, excluding itself. | ||
@@ -260,2 +293,6 @@ | ||
//=> 2 | ||
$('.pear').siblings('.orange').length | ||
//=> 1 | ||
``` | ||
@@ -354,9 +391,9 @@ | ||
```js | ||
$('ul').append('<li class = "plum">Plum</li>') | ||
$('ul').append('<li class="plum">Plum</li>') | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "orange">Orange</li> | ||
// <li class = "pear">Pear</li> | ||
// <li class = "plum">Plum</li> | ||
//=> <ul id="fruits"> | ||
// <li class="apple">Apple</li> | ||
// <li class="orange">Orange</li> | ||
// <li class="pear">Pear</li> | ||
// <li class="plum">Plum</li> | ||
// </ul> | ||
@@ -369,9 +406,9 @@ ``` | ||
```js | ||
$('ul').prepend('<li class = "plum">Plum</li>') | ||
$('ul').prepend('<li class="plum">Plum</li>') | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "plum">Plum</li> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "orange">Orange</li> | ||
// <li class = "pear">Pear</li> | ||
//=> <ul id="fruits"> | ||
// <li class="plum">Plum</li> | ||
// <li class="apple">Apple</li> | ||
// <li class="orange">Orange</li> | ||
// <li class="pear">Pear</li> | ||
// </ul> | ||
@@ -384,9 +421,9 @@ ``` | ||
```js | ||
$('.apple').after('<li class = "plum">Plum</li>') | ||
$('.apple').after('<li class="plum">Plum</li>') | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "plum">Plum</li> | ||
// <li class = "orange">Orange</li> | ||
// <li class = "pear">Pear</li> | ||
//=> <ul id="fruits"> | ||
// <li class="apple">Apple</li> | ||
// <li class="plum">Plum</li> | ||
// <li class="orange">Orange</li> | ||
// <li class="pear">Pear</li> | ||
// </ul> | ||
@@ -399,9 +436,9 @@ ``` | ||
```js | ||
$('.apple').before('<li class = "plum">Plum</li>') | ||
$('.apple').before('<li class="plum">Plum</li>') | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "plum">Plum</li> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "orange">Orange</li> | ||
// <li class = "pear">Pear</li> | ||
//=> <ul id="fruits"> | ||
// <li class="plum">Plum</li> | ||
// <li class="apple">Apple</li> | ||
// <li class="orange">Orange</li> | ||
// <li class="pear">Pear</li> | ||
// </ul> | ||
@@ -416,5 +453,5 @@ ``` | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "orange">Orange</li> | ||
//=> <ul id="fruits"> | ||
// <li class="apple">Apple</li> | ||
// <li class="orange">Orange</li> | ||
// </ul> | ||
@@ -427,9 +464,9 @@ ``` | ||
```js | ||
var plum = $('<li class = "plum">Plum</li>') | ||
var plum = $('<li class="plum">Plum</li>') | ||
$('.pear').replaceWith(plum) | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "orange">Orange</li> | ||
// <li class = "plum">Plum</li> | ||
//=> <ul id="fruits"> | ||
// <li class="apple">Apple</li> | ||
// <li class="orange">Orange</li> | ||
// <li class="plum">Plum</li> | ||
// </ul> | ||
@@ -444,3 +481,3 @@ ``` | ||
$.html() | ||
//=> <ul id = "fruits"></ul> | ||
//=> <ul id="fruits"></ul> | ||
``` | ||
@@ -455,3 +492,3 @@ | ||
$('#fruits').html('<li class = "mango">Mango</li>').html() | ||
$('#fruits').html('<li class="mango">Mango</li>').html() | ||
//=> <li class="mango">Mango</li> | ||
@@ -478,6 +515,6 @@ ``` | ||
$.html() | ||
//=> <ul id = "fruits"> | ||
// <li class = "apple">Apple</li> | ||
// <li class = "orange">Orange</li> | ||
// <li class = "pear">Pear</li> | ||
//=> <ul id="fruits"> | ||
// <li class="apple">Apple</li> | ||
// <li class="orange">Orange</li> | ||
// <li class="pear">Pear</li> | ||
// </ul> | ||
@@ -490,3 +527,3 @@ ``` | ||
$.html('.pear') | ||
//=> <li class = "pear">Pear</li> | ||
//=> <li class="pear">Pear</li> | ||
``` | ||
@@ -493,0 +530,0 @@ |
@@ -6,2 +6,3 @@ var expect = require('expect.js'); | ||
var vegetables = require('./fixtures').vegetables; | ||
var inputs = require('./fixtures').inputs; | ||
@@ -65,2 +66,45 @@ describe('$(...)', function() { | ||
describe('.val', function() { | ||
it('.val(): on select should get value', function() { | ||
var val = $('select#one', inputs).val(); | ||
expect(val).to.equal('option_selected'); | ||
}); | ||
it('.val(): on text input should get value', function() { | ||
var val = $('input[type="text"]', inputs).val(); | ||
expect(val).to.equal('input_text'); | ||
}); | ||
it('.val(): on checked checkbox should get value', function() { | ||
var val = $('input[name="checkbox_on"]', inputs).val(); | ||
expect(val).to.equal('on'); | ||
}); | ||
it('.val(): on unchecked checkbox should get null', function() { | ||
var val = $('input[name="checkbox_off"]', inputs).val(); | ||
expect(val).to.equal(null); | ||
}); | ||
it('.val(): on radio should get value', function() { | ||
var val = $('input[type="radio"]', inputs).val(); | ||
expect(val).to.equal('on'); | ||
}); | ||
it('.val(): on multiple select should get an array of values', function() { | ||
var val = $('select#multi', inputs).val(); | ||
expect(val).to.have.length(2); | ||
}); | ||
it('.val(value): on input text should set value', function() { | ||
var element = $('input[type="text"]', inputs).val('test'); | ||
expect(element.val()).to.equal('test'); | ||
}); | ||
it('.val(value): on select should set value', function() { | ||
var element = $('select#one', inputs).val('option_not_selected'); | ||
expect(element.val()).to.equal('option_not_selected'); | ||
}); | ||
it('.val(value): on radio should set value', function() { | ||
var element = $('input[name="radio"]', inputs).val('off'); | ||
expect(element.val()).to.equal('off'); | ||
}); | ||
it('.val(values): on multiple select should set multiple values', function() { | ||
var element = $('select#multi', inputs).val(['1', '3', '4']); | ||
expect(element.val()).to.have.length(3); | ||
}); | ||
}); | ||
describe('.removeAttr', function() { | ||
@@ -67,0 +111,0 @@ |
@@ -10,4 +10,4 @@ var expect = require('expect.js'), | ||
it('() : should return this', function() { | ||
expect($('ul', fruits).find()[0].name).to.equal('ul'); | ||
it('() : should find nothing', function() { | ||
expect($('ul', fruits).find()).to.have.length(0); | ||
}); | ||
@@ -37,2 +37,10 @@ | ||
it('should throw a SyntaxError if given an invalid selector', function() { | ||
expect(function() { | ||
$('#fruits').find(':bah'); | ||
}).to.throwException(function(err) { | ||
expect(err).to.be.a(SyntaxError); | ||
}); | ||
}); | ||
}); | ||
@@ -70,3 +78,5 @@ | ||
it('(no next) : should return null (?)'); | ||
it('(no next) : should return empty for last child', function() { | ||
expect($('.pear', fruits).next()).to.have.length(0); | ||
}); | ||
@@ -82,3 +92,5 @@ }); | ||
it('(no prev) : should return null (?)'); | ||
it('(no prev) : should return empty for first child', function() { | ||
expect($('.apple', fruits).prev()).to.have.length(0); | ||
}); | ||
@@ -91,10 +103,60 @@ }); | ||
expect($('.orange', fruits).siblings()).to.have.length(2); | ||
expect($('#fruits', fruits).siblings()).to.have.length(0); | ||
}); | ||
it('(selector) : should get all siblings that match the selector', function() { | ||
expect($('.orange', fruits).siblings('li')).to.have.length(2); | ||
expect($('.orange', fruits).siblings('.apple')).to.have.length(1); | ||
expect($('.orange', fruits).siblings('.peach')).to.have.length(0); | ||
}); | ||
it('(selector) : should throw a SyntaxError if given an invalid selector', function() { | ||
expect(function() { | ||
$('.orange', fruits).siblings(':bah'); | ||
}).to.throwException(function(err) { | ||
expect(err).to.be.a(SyntaxError); | ||
}); | ||
}); | ||
}); | ||
describe('.parents', function() { | ||
it('() : should get all of the parents in logical order', function(){ | ||
var result = $('.orange', food).parents(); | ||
expect(result).to.have.length(2); | ||
expect(result[0].attribs.id).to.be('fruits'); | ||
expect(result[1].attribs.id).to.be('food'); | ||
result = $('#food', food).parents() | ||
expect(result).to.have.length(1); | ||
expect(result[0].attribs.id).to.be('food'); | ||
}) | ||
it('(selector) : should get all of the parents that match the selector in logical order', function() { | ||
var result = $('.orange', food).parents('#fruits'); | ||
expect(result).to.have.length(1); | ||
expect(result[0].attribs.id).to.be('fruits'); | ||
result = $('.orange', food).parents('ul'); | ||
expect(result).to.have.length(2); | ||
expect(result[0].attribs.id).to.be('fruits'); | ||
expect(result[1].attribs.id).to.be('food'); | ||
}) | ||
}); | ||
describe('.closest', function() { | ||
it('() : should return an empty array', function() { | ||
var result = $('.orange', fruits).closest(); | ||
expect(result).to.have.length(0); | ||
}) | ||
it('(selector) : should find the closest element that matches the selector, searching through its ancestors and itself', function() { | ||
expect($('.orange', fruits).closest('.apple')).to.have.length(0); | ||
var result = $('.orange', food).closest('#food'); | ||
expect(result[0].attribs['id']).to.be('food'); | ||
result = $('.orange', food).closest('ul'); | ||
expect(result[0].attribs['id']).to.be('fruits'); | ||
result = $('.orange', food).closest('li'); | ||
expect(result[0].attribs['class']).to.be('orange'); | ||
}) | ||
}); | ||
describe('.each', function() { | ||
@@ -139,3 +201,3 @@ | ||
}); | ||
describe('.filter', function() { | ||
@@ -151,3 +213,3 @@ it('(selector) : should reduce the set of matched elements to those that match the selector', function() { | ||
}); | ||
it('(fn) : should reduce the set of matched elements to those that pass the function\'s test', function() { | ||
@@ -154,0 +216,0 @@ var orange = $('li', fruits).filter(function(i, el) { |
@@ -22,1 +22,9 @@ exports.fruits = [ | ||
].join(''); | ||
exports.inputs = [ | ||
'<select id="one"><option value="option_not_selected">Option not selected</option><option value="option_selected" selected>Option selected</option></select>', | ||
'<input type="text" value="input_text" />', | ||
'<input type="checkbox" name="checkbox_off" value="off" /><input type="checkbox" name="checkbox_on" value="on" checked />', | ||
'<input type="radio" value="off" name="radio" /><input type="radio" name="radio" value="on" checked />', | ||
'<select id="multi" multiple><option value="1">1</option><option value="2" selected>2</option><option value="3" selected>3</option><option value="4">4</option></select>' | ||
].join(''); |
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
103851
2125
625
3