css.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. var domEach = require('../utils').domEach,
  2. _ = {
  3. pick: require('lodash.pick'),
  4. };
  5. var toString = Object.prototype.toString;
  6. /**
  7. * Set / Get css.
  8. *
  9. * @param {String|Object} prop
  10. * @param {String} val
  11. * @return {self}
  12. * @api public
  13. */
  14. exports.css = function(prop, val) {
  15. if (arguments.length === 2 ||
  16. // When `prop` is a "plain" object
  17. (toString.call(prop) === '[object Object]')) {
  18. return domEach(this, function(idx, el) {
  19. setCss(el, prop, val, idx);
  20. });
  21. } else {
  22. return getCss(this[0], prop);
  23. }
  24. };
  25. /**
  26. * Set styles of all elements.
  27. *
  28. * @param {String|Object} prop
  29. * @param {String} val
  30. * @param {Number} idx - optional index within the selection
  31. * @return {self}
  32. * @api private
  33. */
  34. function setCss(el, prop, val, idx) {
  35. if ('string' == typeof prop) {
  36. var styles = getCss(el);
  37. if (typeof val === 'function') {
  38. val = val.call(el, idx, styles[prop]);
  39. }
  40. if (val === '') {
  41. delete styles[prop];
  42. } else if (val != null) {
  43. styles[prop] = val;
  44. }
  45. el.attribs.style = stringify(styles);
  46. } else if ('object' == typeof prop) {
  47. Object.keys(prop).forEach(function(k){
  48. setCss(el, k, prop[k]);
  49. });
  50. }
  51. }
  52. /**
  53. * Get parsed styles of the first element.
  54. *
  55. * @param {String} prop
  56. * @return {Object}
  57. * @api private
  58. */
  59. function getCss(el, prop) {
  60. var styles = parse(el.attribs.style);
  61. if (typeof prop === 'string') {
  62. return styles[prop];
  63. } else if (Array.isArray(prop)) {
  64. return _.pick(styles, prop);
  65. } else {
  66. return styles;
  67. }
  68. }
  69. /**
  70. * Stringify `obj` to styles.
  71. *
  72. * @param {Object} obj
  73. * @return {Object}
  74. * @api private
  75. */
  76. function stringify(obj) {
  77. return Object.keys(obj || {})
  78. .reduce(function(str, prop){
  79. return str += ''
  80. + (str ? ' ' : '')
  81. + prop
  82. + ': '
  83. + obj[prop]
  84. + ';';
  85. }, '');
  86. }
  87. /**
  88. * Parse `styles`.
  89. *
  90. * @param {String} styles
  91. * @return {Object}
  92. * @api private
  93. */
  94. function parse(styles) {
  95. styles = (styles || '').trim();
  96. if (!styles) return {};
  97. return styles
  98. .split(';')
  99. .reduce(function(obj, str){
  100. var n = str.indexOf(':');
  101. // skip if there is no :, or if it is the first/last character
  102. if (n < 1 || n === str.length-1) return obj;
  103. obj[str.slice(0,n).trim()] = str.slice(n+1).trim();
  104. return obj;
  105. }, {});
  106. }