Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve css method #272

Merged
merged 9 commits into from
Oct 28, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,10 @@ $('ul').text()
// Pear
```

#### .css( [propertName] ) <br /> .css( [ propertyNames] ) <br /> .css( [propertyName], [value] ) <br /> .css( [propertName], [function] ) <br /> .css( [properties] )

Get the value of a style property for the first element in the set of matched elements or set one or more CSS properties for every matched element.

### Rendering
When you're ready to render the document, you can use the `html` utility function:

Expand Down
65 changes: 39 additions & 26 deletions lib/api/css.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var _ = require('underscore');
var toString = Object.prototype.toString;

/**
* Set / Get css.
Expand All @@ -8,56 +10,67 @@
* @api public
*/

exports.css = function(prop, val){
if (undefined == prop) return get(this);

switch (arguments.length) {
case 2: return set(this, prop, val);
case 0: return get(this);
case 1: return 'object' == typeof prop
? set(this, prop)
: get(this, prop);
exports.css = function(prop, val) {
if (arguments.length === 2 ||
// When `prop` is a "plain" object
(toString.call(prop) === '[object Object]')) {
return this.each(function(idx) {
set.call(this, prop, val, idx);
});
} else {
return get.call(this, prop);
}
};

/**
* Set styles of all elements.
*
* @param {Cheerio} self
* @param {String|Object} prop
* @param {String} val
* @param {Number} idx - optional index within the selection
* @return {self}
* @api private
*/

function set(self, prop, val){
function set(prop, val, idx) {
if ('string' == typeof prop) {
var styles = get(self);
styles[prop] = val;
return self.attr('style', stringify(styles));
var styles = get.call(this);
if (_.isFunction(val)) {
val = val.call(this[0], idx, this[0]);
}

if (val === '') {
delete styles[prop];
} else if (val != null) {
styles[prop] = val;
}

return this.attr('style', stringify(styles));
} else if ('object' == typeof prop) {
Object.keys(prop).forEach(function(k){
set(self, k, prop[k]);
});
return self;
set.call(this, k, prop[k]);
}, this);
return this;
}
}

/**
* Get parsed styles of the first element.
*
* @param {Cheerio} self
* @param {String} prop
* @return {Object}
* @api private
*/

function get(self, prop){
var styles = parse(self.attr('style'));
if (undefined == styles) throw new Error('undefined');
return 2 == arguments.length
? styles[prop]
: styles;
function get(prop) {
var styles = parse(this.attr('style'));
if (typeof prop === 'string') {
return styles[prop];
} else if (_.isArray(prop)) {
return _.pick(styles, prop);
} else {
return styles;
}
}

/**
Expand All @@ -68,7 +81,7 @@ function get(self, prop){
* @api private
*/

function stringify(obj){
function stringify(obj) {
return Object.keys(obj || {})
.reduce(function(str, prop){
return str += ''
Expand All @@ -88,7 +101,7 @@ function stringify(obj){
* @api private
*/

function parse(styles){
function parse(styles) {
styles = (styles || '').trim();

if ('' == styles) return {};
Expand Down
90 changes: 60 additions & 30 deletions test/api.css.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,73 @@

var expect = require('expect.js');
var $ = require('..');

describe('$(...)', function(){

describe('.css', function(){
it('(): should get all styles as object', function(){
var el = $('<li style="hai: there; wassup: 0;">');
expect(el.css()).to.eql({ hai: 'there', wassup: 0 });
})
describe('$(...)', function() {

it('(undefined): should retrun all styles as object', function(){
var el = $('<li style="color: white">');
expect(el.css()).to.eql({ color: 'white' });
})

it('(prop): should return a css property value', function(){
describe('.css', function() {
it('(prop): should return a css property value', function() {
var el = $('<li style="hai: there">');
expect(el.css('hai')).to.equal('there');
})
});

it('([prop1, prop2]): should return the specified property values as an object', function() {
var el = $('<li style="margin: 1px; padding: 2px; color: blue;">');
expect(el.css(['margin', 'color'])).to.eql({ margin: '1px', color: 'blue' });
});

it('(prop, val): should set a css property', function() {
var el = $('<li style="margin: 0;"></li><li></li>');
el.css('color', 'red');
expect(el.attr('style')).to.equal('margin: 0; color: red;');
expect(el.eq(1).attr('style')).to.equal('color: red;');
});

it('(prop, ""): should unset a css property', function() {
var el = $('<li style="padding: 1px; margin: 0;">');
el.css('padding', '');
expect(el.attr('style')).to.equal('margin: 0;');
});

describe('(prop, function):', function() {
beforeEach(function() {
this.$el = $('<div style="margin: 0;"></div><div style="margin: 0;"></div><div style="margin: 0;">');
});

it('should iterate over the selection', function() {
var count = 0;
var $el = this.$el;
this.$el.css('margin', function(idx, elem) {
expect(idx).to.equal(count);
expect(elem).to.equal($el[count]);
expect(this).to.equal($el[count]);
count++;
});
expect(count).to.equal(3);
});

it('(prop, val): should set a css property', function(){
var el = $('<li>');
el.css('wassup', 0);
expect(el.attr('style')).to.equal('wassup: 0;');
})
it('should set each attribute independently', function() {
var values = ['4px', '', undefined];
this.$el.css('margin', function(idx) {
return values[idx];
});
expect(this.$el.eq(0).attr('style')).to.equal('margin: 4px;');
expect(this.$el.eq(1).attr('style')).to.equal('');
expect(this.$el.eq(2).attr('style')).to.equal('margin: 0;');
});
});

it('(obj): should set each key and val', function(){
var el = $('<li>');
it('(obj): should set each key and val', function() {
var el = $('<li style="padding: 0;"></li><li></li>');
el.css({ foo: 0 });
expect(el.attr('style')).to.equal('foo: 0;');
})
expect(el.eq(0).attr('style')).to.equal('padding: 0; foo: 0;');
expect(el.eq(1).attr('style')).to.equal('foo: 0;');
});

describe('parser', function(){
it('should allow any whitespace between declarations', function(){
it('should allow any whitespace between declarations', function() {
var el = $('<li style="one \t:\n 0;\n two \f\r:\v 1">');
expect(el.css()).to.eql({ one: 0, two: 1 });
})
})
})
expect(el.css(['one', 'two'])).to.eql({ one: 0, two: 1 });
});
});
});

})
});