dd71c5d4916a2880738772de11c74919ee40f08c
[yaffs-website] / web / themes / contrib / bootstrap / js / attributes.js
1 (function ($, _) {
2
3   /**
4    * Class to help modify attributes.
5    *
6    * @param {object} object
7    *   An object to initialize attributes with.
8    *
9    * @constructor
10    */
11   var Attributes = function (object) {
12     this.data = object && _.isObject(object) && _.clone(object) || {};
13   };
14
15   /**
16    * Renders the attributes object as a string to inject into an HTML element.
17    *
18    * @returns {string}
19    */
20   Attributes.prototype.toString = function () {
21     var output = '';
22     var name, value;
23     var checkPlain = function (str) {
24       return str && str.toString().replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;') || '';
25     };
26     for (name in this.data) {
27       if (!this.data.hasOwnProperty(name)) continue;
28       value = this.data[name];
29       if (_.isFunction(value)) value = value();
30       if (_.isObject(value)) value = _.values(value);
31       if (_.isArray(value)) value = value.join(' ');
32       output += ' ' + checkPlain(name) + '="' + checkPlain(value) + '"';
33     }
34     return output;
35   };
36
37   /**
38    * Add class(es) to the array.
39    *
40    * @param {string|Array} value
41    *   An individual class or an array of classes to add.
42    *
43    * @return {Attributes}
44    *
45    * @chainable
46    */
47   Attributes.prototype.addClass = function (value) {
48     var classes = this.getClasses();
49     value = [].concat(classes, value);
50     this.set('class', _.uniq(value));
51     return this;
52   };
53
54   /**
55    * Returns whether the requested attribute exists.
56    *
57    * @param {string} name
58    *   An attribute name to check.
59    *
60    * @return {boolean}
61    *   TRUE or FALSE
62    */
63   Attributes.prototype.exists = function (name) {
64     return this.data[name] !== void(0) && this.data[name] !== null;
65   };
66
67   /**
68    * Retrieve a specific attribute from the array.
69    *
70    * @param {string} name
71    *   The specific attribute to retrieve.
72    * @param {*} defaultValue
73    *   (optional) The default value to set if the attribute does not exist.
74    *
75    * @return {*}
76    *   A specific attribute value, passed by reference.
77    */
78   Attributes.prototype.get = function (name, defaultValue) {
79     if (!this.exists(name)) this.data[name] = defaultValue;
80     return this.data[name];
81   };
82
83   /**
84    * Retrieves a cloned copy of the internal attributes data object.
85    *
86    * @returns {Object}
87    */
88   Attributes.prototype.getData = function () {
89     return _.clone(this.data);
90   };
91
92   /**
93    * Retrieves classes from the array.
94    *
95    * @return {Array}
96    *   The classes array.
97    */
98   Attributes.prototype.getClasses = function () {
99     var classes = [].concat(this.get('class', []));
100     return _.uniq(classes);
101   };
102
103   /**
104    * Indicates whether a class is present in the array.
105    *
106    * @param {string|Array} name
107    *   The class(es) to search for.
108    *
109    * @return {boolean}
110    *   TRUE or FALSE
111    */
112   Attributes.prototype.hasClass = function (name) {
113     name = [].concat(name);
114     var classes = this.getClasses();
115     var found = false;
116     _.each(name, function (value) { if (_.indexOf(classes, value) !== -1) found = true; });
117     return found;
118   };
119
120   /**
121    * Merges multiple values into the array.
122    *
123    * @param {object} values
124    *   An associative key/value array.
125    * @param {boolean} [recursive]
126    *   Flag determining whether or not to recursively merge key/value pairs.
127    *
128    * @return {Attributes}
129    *
130    * @chainable
131    */
132   Attributes.prototype.merge = function (values, recursive) {
133     values = values instanceof Attributes ? values.getData() : values;
134     if (recursive === void(0) || recursive) {
135       this.data = $.extend(true, {}, this.data, values);
136     }
137     else {
138       $.extend(this.data, values);
139     }
140     return this;
141   };
142
143   /**
144    * Removes an attribute from the array.
145    *
146    * @param {string} name
147    *   The name of the attribute to remove.
148    *
149    * @return {Attributes}
150    *
151    * @chainable
152    */
153   Attributes.prototype.remove = function (name) {
154     if (this.exists(name)) delete this.data[name];
155     return this;
156   };
157
158   /**
159    * Removes a class from the attributes array.
160    *
161    * @param {string|Array} value
162    *   An individual class or an array of classes to remove.
163    *
164    * @return {Attributes}
165    *
166    * @chainable
167    */
168   Attributes.prototype.removeClass = function (value) {
169     this.set('class', _.without(this.getClasses(), [].concat(value)));
170     return this;
171   };
172
173   /**
174    * Replaces a class in the attributes array.
175    *
176    * @param {string} oldValue
177    *   The old class to remove.
178    * @param {string} newValue
179    *   The new class. It will not be added if the old class does not exist.
180    *
181    * @return {Attributes}
182    *
183    * @chainable
184    */
185   Attributes.prototype.replaceClass = function (oldValue, newValue) {
186     var classes = this.getClasses();
187     var i = _.indexOf(oldValue, classes);
188     if (i >= 0) {
189       classes[i] = newValue;
190       this.set('class', classes);
191     }
192     return this;
193   };
194
195   /**
196    * Sets an attribute on the array.
197    *
198    * @param {string} name
199    *   The name of the attribute to set.
200    * @param {*} value
201    *   The value of the attribute to set.
202    *
203    * @return {Attributes}
204    *
205    * @chainable
206    */
207   Attributes.prototype.set = function (name, value) {
208     this.data[name] = value;
209     return this;
210   };
211
212   /**
213    * Creates an Attributes instance.
214    *
215    * @param {object|Attributes} object
216    *   An object to initialize attributes with.
217    *
218    * @returns {Attributes}
219    *
220    * @global
221    *
222    * @constructor
223    */
224   window.Attributes = function (object) {
225     return object instanceof Attributes ? object : new Attributes(object);
226   };
227
228 })(window.jQuery, window._);