mirror of
https://github.com/YunoHost-Apps/strut_ynh.git
synced 2024-09-03 20:26:33 +02:00
241 lines
No EOL
9.2 KiB
JavaScript
241 lines
No EOL
9.2 KiB
JavaScript
/**
|
|
* Add dataset support to elements
|
|
* No globals, no overriding prototype with non-standard methods,
|
|
* handles CamelCase properly, attempts to use standard
|
|
* Object.defineProperty() (and Function bind()) methods,
|
|
* falls back to native implementation when existing
|
|
* Inspired by http://code.eligrey.com/html5/dataset/
|
|
* (via https://github.com/adalgiso/html5-dataset/blob/master/html5-dataset.js )
|
|
* Depends on Function.bind and Object.defineProperty/Object.getOwnPropertyDescriptor (shims below)
|
|
* Licensed under the X11/MIT License
|
|
*/
|
|
|
|
// Inspired by https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
|
|
if (!Function.prototype.bind) {
|
|
Function.prototype.bind = function (oThis) {
|
|
'use strict';
|
|
if (typeof this !== "function") {
|
|
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
|
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
|
}
|
|
|
|
var aArgs = Array.prototype.slice.call(arguments, 1),
|
|
fToBind = this,
|
|
FNOP = function () {},
|
|
fBound = function () {
|
|
return fToBind.apply(
|
|
this instanceof FNOP && oThis ? this : oThis,
|
|
aArgs.concat(Array.prototype.slice.call(arguments))
|
|
);
|
|
};
|
|
|
|
FNOP.prototype = this.prototype;
|
|
fBound.prototype = new FNOP();
|
|
|
|
return fBound;
|
|
};
|
|
}
|
|
|
|
/*
|
|
* Xccessors Standard: Cross-browser ECMAScript 5 accessors
|
|
* http://purl.eligrey.com/github/Xccessors
|
|
*
|
|
* 2010-06-21
|
|
*
|
|
* By Eli Grey, http://eligrey.com
|
|
*
|
|
* A shim that partially implements Object.defineProperty,
|
|
* Object.getOwnPropertyDescriptor, and Object.defineProperties in browsers that have
|
|
* legacy __(define|lookup)[GS]etter__ support.
|
|
*
|
|
* Licensed under the X11/MIT License
|
|
* See LICENSE.md
|
|
*/
|
|
|
|
// Removed a few JSLint options as Notepad++ JSLint validator complaining and
|
|
// made comply with JSLint; also moved 'use strict' inside function
|
|
/*jslint white: true, undef: true, plusplus: true,
|
|
bitwise: true, regexp: true, newcap: true, maxlen: 90 */
|
|
|
|
/*! @source http://purl.eligrey.com/github/Xccessors/blob/master/xccessors-standard.js*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
var ObjectProto = Object.prototype,
|
|
defineGetter = ObjectProto.__defineGetter__,
|
|
defineSetter = ObjectProto.__defineSetter__,
|
|
lookupGetter = ObjectProto.__lookupGetter__,
|
|
lookupSetter = ObjectProto.__lookupSetter__,
|
|
hasOwnProp = ObjectProto.hasOwnProperty;
|
|
|
|
if (defineGetter && defineSetter && lookupGetter && lookupSetter) {
|
|
|
|
if (!Object.defineProperty) {
|
|
Object.defineProperty = function (obj, prop, descriptor) {
|
|
if (arguments.length < 3) { // all arguments required
|
|
throw new TypeError("Arguments not optional");
|
|
}
|
|
|
|
prop += ""; // convert prop to string
|
|
|
|
if (hasOwnProp.call(descriptor, "value")) {
|
|
if (!lookupGetter.call(obj, prop) && !lookupSetter.call(obj, prop)) {
|
|
// data property defined and no pre-existing accessors
|
|
obj[prop] = descriptor.value;
|
|
}
|
|
|
|
if ((hasOwnProp.call(descriptor, "get") ||
|
|
hasOwnProp.call(descriptor, "set")))
|
|
{
|
|
// descriptor has a value prop but accessor already exists
|
|
throw new TypeError("Cannot specify an accessor and a value");
|
|
}
|
|
}
|
|
|
|
// can't switch off these features in ECMAScript 3
|
|
// so throw a TypeError if any are false
|
|
if (!(descriptor.writable && descriptor.enumerable &&
|
|
descriptor.configurable))
|
|
{
|
|
throw new TypeError(
|
|
"This implementation of Object.defineProperty does not support" +
|
|
" false for configurable, enumerable, or writable."
|
|
);
|
|
}
|
|
|
|
if (descriptor.get) {
|
|
defineGetter.call(obj, prop, descriptor.get);
|
|
}
|
|
if (descriptor.set) {
|
|
defineSetter.call(obj, prop, descriptor.set);
|
|
}
|
|
|
|
return obj;
|
|
};
|
|
}
|
|
|
|
if (!Object.getOwnPropertyDescriptor) {
|
|
Object.getOwnPropertyDescriptor = function (obj, prop) {
|
|
if (arguments.length < 2) { // all arguments required
|
|
throw new TypeError("Arguments not optional.");
|
|
}
|
|
|
|
prop += ""; // convert prop to string
|
|
|
|
var descriptor = {
|
|
configurable: true,
|
|
enumerable : true,
|
|
writable : true
|
|
},
|
|
getter = lookupGetter.call(obj, prop),
|
|
setter = lookupSetter.call(obj, prop);
|
|
|
|
if (!hasOwnProp.call(obj, prop)) {
|
|
// property doesn't exist or is inherited
|
|
return descriptor;
|
|
}
|
|
if (!getter && !setter) { // not an accessor so return prop
|
|
descriptor.value = obj[prop];
|
|
return descriptor;
|
|
}
|
|
|
|
// there is an accessor, remove descriptor.writable;
|
|
// populate descriptor.get and descriptor.set (IE's behavior)
|
|
delete descriptor.writable;
|
|
descriptor.get = descriptor.set = undefined;
|
|
|
|
if (getter) {
|
|
descriptor.get = getter;
|
|
}
|
|
if (setter) {
|
|
descriptor.set = setter;
|
|
}
|
|
|
|
return descriptor;
|
|
};
|
|
}
|
|
|
|
if (!Object.defineProperties) {
|
|
Object.defineProperties = function (obj, props) {
|
|
var prop;
|
|
for (prop in props) {
|
|
if (hasOwnProp.call(props, prop)) {
|
|
Object.defineProperty(obj, prop, props[prop]);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}());
|
|
|
|
// Begin dataset code
|
|
|
|
if (!document.documentElement.dataset &&
|
|
// FF is empty while IE gives empty object
|
|
(!Object.getOwnPropertyDescriptor(Element.prototype, 'dataset') ||
|
|
!Object.getOwnPropertyDescriptor(Element.prototype, 'dataset').get)
|
|
) {
|
|
var propDescriptor = {
|
|
enumerable: true,
|
|
get: function () {
|
|
'use strict';
|
|
var i,
|
|
that = this,
|
|
HTML5_DOMStringMap,
|
|
attrVal, attrName, propName,
|
|
attribute,
|
|
attributes = this.attributes,
|
|
attsLength = attributes.length,
|
|
toUpperCase = function (n0) {
|
|
return n0.charAt(1).toUpperCase();
|
|
},
|
|
getter = function () {
|
|
return this;
|
|
},
|
|
setter = function (attrName, value) {
|
|
return (typeof value !== 'undefined') ?
|
|
this.setAttribute(attrName, value) :
|
|
this.removeAttribute(attrName);
|
|
};
|
|
try { // Simulate DOMStringMap w/accessor support
|
|
// Test setting accessor on normal object
|
|
({}).__defineGetter__('test', function () {});
|
|
HTML5_DOMStringMap = {};
|
|
}
|
|
catch (e1) { // Use a DOM object for IE8
|
|
HTML5_DOMStringMap = document.createElement('div');
|
|
}
|
|
for (i = 0; i < attsLength; i++) {
|
|
attribute = attributes[i];
|
|
// Fix: This test really should allow any XML Name without
|
|
// colons (and non-uppercase for XHTML)
|
|
if (attribute && attribute.name &&
|
|
(/^data-\w[\w\-]*$/).test(attribute.name)) {
|
|
attrVal = attribute.value;
|
|
attrName = attribute.name;
|
|
// Change to CamelCase
|
|
propName = attrName.substr(5).replace(/-./g, toUpperCase);
|
|
try {
|
|
Object.defineProperty(HTML5_DOMStringMap, propName, {
|
|
enumerable: this.enumerable,
|
|
get: getter.bind(attrVal || ''),
|
|
set: setter.bind(that, attrName)
|
|
});
|
|
}
|
|
catch (e2) { // if accessors are not working
|
|
HTML5_DOMStringMap[propName] = attrVal;
|
|
}
|
|
}
|
|
}
|
|
return HTML5_DOMStringMap;
|
|
}
|
|
};
|
|
try {
|
|
// FF enumerates over element's dataset, but not
|
|
// Element.prototype.dataset; IE9 iterates over both
|
|
Object.defineProperty(Element.prototype, 'dataset', propDescriptor);
|
|
} catch (e) {
|
|
propDescriptor.enumerable = false; // IE8 does not allow setting to true
|
|
Object.defineProperty(Element.prototype, 'dataset', propDescriptor);
|
|
}
|
|
} |