/// jquery.dataset v0.1.0 -- HTML5 dataset jQuery plugin /// http://orangesoda.net/jquery.dataset.html /// Copyright (c) 2009, Ben Weaver. All rights reserved. /// This software is issued "as is" under a BSD license /// . All warrenties disclaimed. /// The HTML5 specification allows elements to have custom data /// attributes that are prefixed with `data-'. They may be /// conveniently accessed through an element's `dataset' property. /// This plugin provides similar functionality. /// /// The methods in the plugin are designed to be similar to the /// built-in `attr' and `data' methods. All names are without the /// `data-' prefix. // /// These methods are defined: /// /// dataset() /// Return an object with all custom attribute (name, value) items. /// /// dataset(name) /// Return the value of the attribute `data-NAME'. /// /// dataset(name, value) /// Set the value of attribtue `data-NAME' to VALUE. /// /// dataset({...}) /// Set many custom attributes at once. /// /// removeDataset(name) /// Remove the attribute `data-NAME'. /// /// removeDataset([n1, n2, ...]) /// Remove the attributes `data-N1', `data-N2', ... (function($) { var PREFIX = 'data-', PATTERN = /^data\-(.*)$/; function dataset(name, value) { if (value !== undefined) { // dataset(name, value): set the NAME attribute to VALUE. return this.attr(PREFIX + name, value); } switch (typeof name) { case 'string': // dataset(name): get the value of the NAME attribute. return this.attr(PREFIX + name); case 'object': // dataset(items): set the values of all (name, value) items. return set_items.call(this, name); case 'undefined': // dataset(): return a mapping of (name, value) items for the // first element. return get_items.call(this); default: throw 'dataset: invalid argument ' + name; } } function get_items() { return this.foldAttr(function(index, attr, result) { var match = PATTERN.exec(this.name); if (match) result[match[1]] = this.value; }); } function set_items(items) { for (var key in items) { this.attr(PREFIX + key, items[key]); } return this; } function remove(name) { if (typeof name == 'string') { // Remove a single attribute; return this.removeAttr(PREFIX + name); } return remove_names(name); } function remove_names(obj) { var idx, length = obj && obj.length; // For any object, remove attributes named by the keys. if (length === undefined) { for (idx in obj) { this.removeAttr(PREFIX + idx); } } // For an array, remove attributes named by the values. else { for (idx = 0; idx < length; idx++) { this.removeAttr(PREFIX + obj[idx]); } } return this; } $.fn.dataset = dataset; $.fn.removeDataset = remove_names; })(jQuery); (function($) { function each_attr(proc) { if (this.length > 0) { $.each(this[0].attributes, proc); } return this; } function fold_attr(proc, acc) { return fold((this.length > 0) && this[0].attributes, proc, acc); } /* * A left-fold operator. The behavior is the same as $.each(), * but the callback is called with the accumulator as the third * argument. The default accumulator is an empty object. */ function fold(object, proc, acc) { var length = object && object.length; // The default accumulator is an empty object. if (acc === undefined) acc = {}; // Returning an empty accumulator when OBJECT is "false" // makes FOLD more composable. if (!object) return acc; // Check to see if OBJECT is an array. if (length !== undefined) { for (var i = 0, value = object[i]; (i < length) && (proc.call(value, i, value, acc) !== false); value = object[++i]) { } } // Object is a map of (name, value) items. else { for (var name in object) { if (proc.call(object[name], name, object[name], acc) === false) break; } } return acc; } function fold_jquery(proc, acc) { if (acc === undefined) acc = []; return fold(this, proc, acc); } $.fn.eachAttr = each_attr; $.fn.foldAttr = fold_attr; $.fn.fold = fold_jquery; $.fold = fold; })(jQuery);