Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Unified Diff: node_modules/vulcanize/node_modules/whacko/lib/api/attributes.js

Issue 800513006: Added vulcanize under third_party/npm_modules (Closed) Base URL: https://chromium.googlesource.com/infra/third_party/npm_modules.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: node_modules/vulcanize/node_modules/whacko/lib/api/attributes.js
diff --git a/node_modules/vulcanize/node_modules/whacko/lib/api/attributes.js b/node_modules/vulcanize/node_modules/whacko/lib/api/attributes.js
new file mode 100644
index 0000000000000000000000000000000000000000..22783f7251e072deab96e88ed7ae75018ff97c5a
--- /dev/null
+++ b/node_modules/vulcanize/node_modules/whacko/lib/api/attributes.js
@@ -0,0 +1,416 @@
+var _ = require('lodash'),
+ utils = require('../utils'),
+ isTag = utils.isTag,
+ domEach = utils.domEach,
+ hasOwn = Object.prototype.hasOwnProperty,
+ camelCase = utils.camelCase,
+ cssCase = utils.cssCase,
+ rspace = /\s+/,
+ dataAttrPrefix = 'data-',
+
+ // Lookup table for coercing string data-* attributes to their corresponding
+ // JavaScript primitives
+ primitives = {
+ null: null,
+ true: true,
+ false: false
+ },
+
+ // Attributes that are booleans
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ // Matches strings that look like JSON objects or arrays
+ rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/;
+
+
+var getAttr = function(elem, name) {
+ if (!elem || !isTag(elem)) return;
+
+ if (!elem.attribs) {
+ elem.attribs = {};
+ }
+
+ // Return the entire attribs object if no attribute specified
+ if (!name) {
+ return elem.attribs;
+ }
+
+ if (hasOwn.call(elem.attribs, name)) {
+ // Get the (decoded) attribute
+ return rboolean.test(name) ? name : elem.attribs[name];
+ }
+};
+
+var setAttr = function(el, name, value) {
+
+ if (value === null) {
+ removeAttribute(el, name);
+ } else {
+ el.attribs[name] = value+'';
+ }
+};
+
+exports.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') {
+ _.each(name, function(name, key) {
+ el.attribs[key] = name+'';
+ });
+ } else {
+ setAttr(el, name, value);
+ }
+ });
+ }
+
+ return getAttr(this[0], name);
+};
+
+var setData = function(el, name, value) {
+ if (typeof name === 'object') return _.extend(el.data, name);
+ if (typeof name === 'string' && value !== undefined) {
+ el.data[name] = value;
+ } else if (typeof name === 'object') {
+ _.exend(el.data, name);
+ }
+};
+
+// Read the specified attribute from the equivalent HTML5 `data-*` attribute,
+// and (if present) cache the value in the node's internal data store. If no
+// attribute name is specified, read *all* HTML5 `data-*` attributes in this
+// manner.
+var readData = function(el, name) {
+ var readAll = arguments.length === 1;
+ var domNames, domName, jsNames, jsName, value, idx, length;
+
+ if (readAll) {
+ domNames = Object.keys(el.attribs).filter(function(attrName) {
+ return attrName.slice(0, dataAttrPrefix.length) === dataAttrPrefix;
+ });
+ jsNames = domNames.map(function(domName) {
+ return camelCase(domName.slice(dataAttrPrefix.length));
+ });
+ } else {
+ domNames = [dataAttrPrefix + cssCase(name)];
+ jsNames = [name];
+ }
+
+ for (idx = 0, length = domNames.length; idx < length; ++idx) {
+ domName = domNames[idx];
+ jsName = jsNames[idx];
+ if (hasOwn.call(el.attribs, domName)) {
+ value = el.attribs[domName];
+
+ if (hasOwn.call(primitives, value)) {
+ value = primitives[value];
+ } else if (value === String(Number(value))) {
+ value = Number(value);
+ } else if (rbrace.test(value)) {
+ value = JSON.parse(value);
+ }
+
+ el.data[jsName] = value;
+ }
+ }
+
+ return readAll ? el.data : value;
+};
+
+exports.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);
+};
+
+/**
+ * Get the value of an element
+ */
+
+exports.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':
+ var queryString = 'input[type=radio][name="' + this.attr('name') + '"]:checked';
+ var parentEl, root;
+
+ // Go up until we hit a form or root
+ parentEl = this.closest('form');
+ if (parentEl.length === 0) {
+ root = (this.parents().last()[0] || this[0]).root;
+ parentEl = this._make(root);
+ }
+
+ 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;
+ 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(el.attribs.value);
+ });
+ }
+ return returnValue;
+ case 'option':
+ if (!querying) {
+ this.attr('value', value);
+ return this;
+ }
+ return this.attr('value');
+ }
+};
+
+/**
+ * Remove an attribute
+ */
+
+var removeAttribute = function(elem, name) {
+ if (!elem.attribs || !hasOwn.call(elem.attribs, name))
+ return;
+
+ delete elem.attribs[name];
+};
+
+
+exports.removeAttr = function(name) {
+ domEach(this, function(i, elem) {
+ removeAttribute(elem, name);
+ });
+
+ return this;
+};
+
+exports.hasClass = function(className) {
+ return _.any(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;
+ }
+ }
+ }
+ });
+};
+
+exports.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))
+ setClass += appendClass;
+ }
+
+ setAttr(this[i], 'class', setClass.trim());
+ }
+ }
+
+ return this;
+};
+
+var splitClass = function(className) {
+ return className ? className.trim().split(rspace) : [];
+};
+
+exports.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(' ');
+ }
+ }
+ });
+};
+
+exports.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;
+};
+
+exports.is = function (selector) {
+ if (selector) {
+ return this.filter(selector).length > 0;
+ }
+ return false;
+};
+
« no previous file with comments | « node_modules/vulcanize/node_modules/whacko/index.js ('k') | node_modules/vulcanize/node_modules/whacko/lib/api/css.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698