xyc
2025-02-21 664db98c9e8595ce4dd636a27f480e3a08b81ff5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
 * jQuery module to work with SVG attributes
 * @module jQueryAttr
 * @license MIT
 */
 
/**
* This fixes `$(...).attr()` to work as expected with SVG elements.
* Does not currently use `*AttributeNS()` since we rarely need that.
* Adds {@link external:jQuery.fn.attr}.
* See {@link https://api.jquery.com/attr/} for basic documentation of `.attr()`.
*
* Additional functionality:
* - When getting attributes, a string that's a number is returned as type number.
* - If an array is supplied as the first parameter, multiple values are returned
*    as an object with values for each given attribute.
* @function module:jQueryAttr.jQueryAttr
* @param {external:jQuery} $ The jQuery object to which to add the plug-in
* @returns {external:jQuery}
*/
export default function ($) {
  const proxied = $.fn.attr,
    svgns = 'http://www.w3.org/2000/svg';
  /**
  * @typedef {PlainObject.<string, string|Float>} module:jQueryAttr.Attributes
  */
  /**
  * @function external:jQuery.fn.attr
  * @param {string|string[]|PlainObject.<string, string>} key
  * @param {string} value
  * @returns {external:jQuery|module:jQueryAttr.Attributes}
  */
  $.fn.attr = function (key, value) {
    const len = this.length;
    if (!len) { return proxied.apply(this, arguments); }
    for (let i = 0; i < len; ++i) {
      const elem = this[i];
      // set/get SVG attribute
      if (elem.namespaceURI === svgns) {
        // Setting attribute
        if (value !== undefined) {
          elem.setAttribute(key, value);
        } else if (Array.isArray(key)) {
          // Getting attributes from array
          const obj = {};
          let j = key.length;
 
          while (j--) {
            const aname = key[j];
            let attr = elem.getAttribute(aname);
            // This returns a number when appropriate
            if (attr || attr === '0') {
              attr = isNaN(attr) ? attr : (attr - 0);
            }
            obj[aname] = attr;
          }
          return obj;
        }
        if (typeof key === 'object') {
          // Setting attributes from object
          for (const [name, val] of Object.entries(key)) {
            elem.setAttribute(name, val);
          }
        // Getting attribute
        } else {
          let attr = elem.getAttribute(key);
          if (attr || attr === '0') {
            attr = isNaN(attr) ? attr : (attr - 0);
          }
          return attr;
        }
      } else {
        return proxied.apply(this, arguments);
      }
    }
    return this;
  };
  return $;
}