| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 | 
							- 'use strict';
 
- var cssSelect = require('css-select');
 
- var svgoCssSelectAdapter = require('./css-select-adapter');
 
- var cssSelectOpts = {
 
-   xmlMode: true,
 
-   adapter: svgoCssSelectAdapter
 
- };
 
- var JSAPI = module.exports = function(data, parentNode) {
 
-     Object.assign(this, data);
 
-     if (parentNode) {
 
-         Object.defineProperty(this, 'parentNode', {
 
-             writable: true,
 
-             value: parentNode
 
-         });
 
-     }
 
- };
 
- /**
 
-  * Perform a deep clone of this node.
 
-  *
 
-  * @return {Object} element
 
-  */
 
- JSAPI.prototype.clone = function() {
 
-     var node = this;
 
-     var nodeData = {};
 
-     Object.keys(node).forEach(function(key) {
 
-         if (key !== 'class' && key !== 'style' && key !== 'content') {
 
-             nodeData[key] = node[key];
 
-         }
 
-     });
 
-     // Deep-clone node data.
 
-     nodeData = JSON.parse(JSON.stringify(nodeData));
 
-     // parentNode gets set to a proper object by the parent clone,
 
-     // but it needs to be true/false now to do the right thing
 
-     // in the constructor.
 
-     var clonedNode = new JSAPI(nodeData, !!node.parentNode);
 
-     if (node.class) {
 
-         clonedNode.class = node.class.clone(clonedNode);
 
-     }
 
-     if (node.style) {
 
-         clonedNode.style = node.style.clone(clonedNode);
 
-     }
 
-     if (node.content) {
 
-         clonedNode.content = node.content.map(function(childNode) {
 
-             var clonedChild = childNode.clone();
 
-             clonedChild.parentNode = clonedNode;
 
-             return clonedChild;
 
-         });
 
-     }
 
-     return clonedNode;
 
- };
 
- /**
 
-  * Determine if item is an element
 
-  * (any, with a specific name or in a names array).
 
-  *
 
-  * @param {String|Array} [param] element name or names arrays
 
-  * @return {Boolean}
 
-  */
 
- JSAPI.prototype.isElem = function(param) {
 
-     if (!param) return !!this.elem;
 
-     if (Array.isArray(param)) return !!this.elem && (param.indexOf(this.elem) > -1);
 
-     return !!this.elem && this.elem === param;
 
- };
 
- /**
 
-  * Renames an element
 
-  *
 
-  * @param {String} name new element name
 
-  * @return {Object} element
 
-  */
 
- JSAPI.prototype.renameElem = function(name) {
 
-     if (name && typeof name === 'string')
 
-         this.elem = this.local = name;
 
-     return this;
 
- };
 
- /**
 
-  * Determine if element is empty.
 
-  *
 
-  * @return {Boolean}
 
-  */
 
-  JSAPI.prototype.isEmpty = function() {
 
-     return !this.content || !this.content.length;
 
- };
 
- /**
 
-  * Find the closest ancestor of the current element.
 
-  * @param elemName
 
-  *
 
-  * @return {?Object}
 
-  */
 
-  JSAPI.prototype.closestElem = function(elemName) {
 
-     var elem = this;
 
-     while ((elem = elem.parentNode) && !elem.isElem(elemName));
 
-     return elem;
 
- };
 
- /**
 
-  * Changes content by removing elements and/or adding new elements.
 
-  *
 
-  * @param {Number} start Index at which to start changing the content.
 
-  * @param {Number} n Number of elements to remove.
 
-  * @param {Array|Object} [insertion] Elements to add to the content.
 
-  * @return {Array} Removed elements.
 
-  */
 
-  JSAPI.prototype.spliceContent = function(start, n, insertion) {
 
-     if (arguments.length < 2) return [];
 
-     if (!Array.isArray(insertion))
 
-         insertion = Array.apply(null, arguments).slice(2);
 
-     insertion.forEach(function(inner) { inner.parentNode = this }, this);
 
-     return this.content.splice.apply(this.content, [start, n].concat(insertion));
 
- };
 
- /**
 
-  * Determine if element has an attribute
 
-  * (any, or by name or by name + value).
 
-  *
 
-  * @param {String} [name] attribute name
 
-  * @param {String} [val] attribute value (will be toString()'ed)
 
-  * @return {Boolean}
 
-  */
 
-  JSAPI.prototype.hasAttr = function(name, val) {
 
-     if (!this.attrs || !Object.keys(this.attrs).length) return false;
 
-     if (!arguments.length) return !!this.attrs;
 
-     if (val !== undefined) return !!this.attrs[name] && this.attrs[name].value === val.toString();
 
-     return !!this.attrs[name];
 
- };
 
- /**
 
-  * Determine if element has an attribute by local name
 
-  * (any, or by name or by name + value).
 
-  *
 
-  * @param {String} [localName] local attribute name
 
-  * @param {Number|String|RegExp|Function} [val] attribute value (will be toString()'ed or executed, otherwise ignored)
 
-  * @return {Boolean}
 
-  */
 
-  JSAPI.prototype.hasAttrLocal = function(localName, val) {
 
-     if (!this.attrs || !Object.keys(this.attrs).length) return false;
 
-     if (!arguments.length) return !!this.attrs;
 
-     var callback;
 
-     switch (val != null && val.constructor && val.constructor.name) {
 
-         case 'Number':   // same as String
 
-         case 'String':   callback = stringValueTest; break;
 
-         case 'RegExp':   callback = regexpValueTest; break;
 
-         case 'Function': callback = funcValueTest; break;
 
-         default:         callback = nameTest;
 
-     }
 
-     return this.someAttr(callback);
 
-     function nameTest(attr) {
 
-         return attr.local === localName;
 
-     }
 
-     function stringValueTest(attr) {
 
-         return attr.local === localName && val == attr.value;
 
-     }
 
-     function regexpValueTest(attr) {
 
-         return attr.local === localName && val.test(attr.value);
 
-     }
 
-     function funcValueTest(attr) {
 
-         return attr.local === localName && val(attr.value);
 
-     }
 
- };
 
- /**
 
-  * Get a specific attribute from an element
 
-  * (by name or name + value).
 
-  *
 
-  * @param {String} name attribute name
 
-  * @param {String} [val] attribute value (will be toString()'ed)
 
-  * @return {Object|Undefined}
 
-  */
 
-  JSAPI.prototype.attr = function(name, val) {
 
-     if (!this.hasAttr() || !arguments.length) return undefined;
 
-     if (val !== undefined) return this.hasAttr(name, val) ? this.attrs[name] : undefined;
 
-     return this.attrs[name];
 
- };
 
- /**
 
-  * Get computed attribute value from an element
 
-  *
 
-  * @param {String} name attribute name
 
-  * @return {Object|Undefined}
 
-  */
 
-  JSAPI.prototype.computedAttr = function(name, val) {
 
-     /* jshint eqnull: true */
 
-     if (!arguments.length) return;
 
-     for (var elem = this; elem && (!elem.hasAttr(name) || !elem.attr(name).value); elem = elem.parentNode);
 
-     if (val != null) {
 
-         return elem ? elem.hasAttr(name, val) : false;
 
-     } else if (elem && elem.hasAttr(name)) {
 
-         return elem.attrs[name].value;
 
-     }
 
- };
 
- /**
 
-  * Remove a specific attribute.
 
-  *
 
-  * @param {String|Array} name attribute name
 
-  * @param {String} [val] attribute value
 
-  * @return {Boolean}
 
-  */
 
-  JSAPI.prototype.removeAttr = function(name, val, recursive) {
 
-     if (!arguments.length) return false;
 
-     if (Array.isArray(name)) {
 
-         name.forEach(this.removeAttr, this);
 
-         return false;
 
-     }
 
-     if (!this.hasAttr(name)) return false;
 
-     if (!recursive && val && this.attrs[name].value !== val) return false;
 
-     delete this.attrs[name];
 
-     if (!Object.keys(this.attrs).length) delete this.attrs;
 
-     return true;
 
- };
 
- /**
 
-  * Add attribute.
 
-  *
 
-  * @param {Object} [attr={}] attribute object
 
-  * @return {Object|Boolean} created attribute or false if no attr was passed in
 
-  */
 
-  JSAPI.prototype.addAttr = function(attr) {
 
-     attr = attr || {};
 
-     if (attr.name === undefined ||
 
-         attr.prefix === undefined ||
 
-         attr.local === undefined
 
-     ) return false;
 
-     this.attrs = this.attrs || {};
 
-     this.attrs[attr.name] = attr;
 
-     if(attr.name === 'class') { // newly added class attribute
 
-         this.class.hasClass();
 
-     }
 
-     if(attr.name === 'style') { // newly added style attribute
 
-         this.style.hasStyle();
 
-     }
 
-     return this.attrs[attr.name];
 
- };
 
- /**
 
-  * Iterates over all attributes.
 
-  *
 
-  * @param {Function} callback callback
 
-  * @param {Object} [context] callback context
 
-  * @return {Boolean} false if there are no any attributes
 
-  */
 
-  JSAPI.prototype.eachAttr = function(callback, context) {
 
-     if (!this.hasAttr()) return false;
 
-     for (var name in this.attrs) {
 
-         callback.call(context, this.attrs[name]);
 
-     }
 
-     return true;
 
- };
 
- /**
 
-  * Tests whether some attribute passes the test.
 
-  *
 
-  * @param {Function} callback callback
 
-  * @param {Object} [context] callback context
 
-  * @return {Boolean} false if there are no any attributes
 
-  */
 
-  JSAPI.prototype.someAttr = function(callback, context) {
 
-     if (!this.hasAttr()) return false;
 
-     for (var name in this.attrs) {
 
-         if (callback.call(context, this.attrs[name])) return true;
 
-     }
 
-     return false;
 
- };
 
- /**
 
-  * Evaluate a string of CSS selectors against the element and returns matched elements.
 
-  *
 
-  * @param {String} selectors CSS selector(s) string
 
-  * @return {Array} null if no elements matched
 
-  */
 
-  JSAPI.prototype.querySelectorAll = function(selectors) {
 
-    var matchedEls = cssSelect(selectors, this, cssSelectOpts);
 
-    return matchedEls.length > 0 ? matchedEls : null;
 
- };
 
- /**
 
-  * Evaluate a string of CSS selectors against the element and returns only the first matched element.
 
-  *
 
-  * @param {String} selectors CSS selector(s) string
 
-  * @return {Array} null if no element matched
 
-  */
 
-  JSAPI.prototype.querySelector = function(selectors) {
 
-    return cssSelect.selectOne(selectors, this, cssSelectOpts);
 
- };
 
- /**
 
-  * Test if a selector matches a given element.
 
-  *
 
-  * @param {String} selector CSS selector string
 
-  * @return {Boolean} true if element would be selected by selector string, false if it does not
 
-  */
 
-  JSAPI.prototype.matches = function(selector) {
 
-    return cssSelect.is(this, selector, cssSelectOpts);
 
- };
 
 
  |