From 037bc71b9a5276b16c39de1713a27f9629bdf641 Mon Sep 17 00:00:00 2001 From: Jason Westbrook Date: Fri, 28 Dec 2012 14:07:56 -0800 Subject: [PATCH 1/5] Added html5data methods set/get Based on the issue below sethtml5data() and gethtml5data() will write to the dataset and the write the data-* attributes correctly in any browsers that Prototype supports. https://prototype.lighthouseapp.com/projects/8886/tickets/250-support-for-dataset-property-and-data-attributes --- src/prototype/dom/dom.js | 88 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/prototype/dom/dom.js b/src/prototype/dom/dom.js index f14639bd9..dd48c697b 100644 --- a/src/prototype/dom/dom.js +++ b/src/prototype/dom/dom.js @@ -3103,12 +3103,94 @@ return value; } - - + //simple test for native HTML5 dataset existence + var NATIVEHTML5DATASET = (function (){ + var testelement = new Element("div",{"data-test-this-thing":"test"}); + if(typeof testelement.dataset != 'undefined' && typeof testelement.dataset.testThisThing != 'undefined') return true; + else return false; + } + /** + * Element.gethtml5data(@element[, datakey]) -> Object + * + * Retrieves HTML5 data-* attributes set on `element`. + * + * This will clear up any problems retreiving these data attributes on browsers + * that don't support them. + * + * ##### Example + * + * language: html + *
+ * + * Then: + * $("dataitem").gethtml5data().oldUrl; + * // -> "http://prototypejs.org" + **/ + function gethtml5data(element,datalabel){ + if(!(element = $(element))) return; + var returnobject = {}; + if(NATIVEHTML5DATASET) + { + if(datalabel != undefined) returnobject[datalabel.camelize()] = element.dataset[datalabel]; + else returnobject = element.dataset; + } + else + { + if(datalabel != undefined) returnobject[datalabel.camelize()] = element.readAttribute('data-'+datalabel); + else + { + var label = ""; + var numberattributes = element.attributes.length; + for(var t = 0; t < numberattributes ; t++) + { + if(element.attributes[t].name.match(/^data-.+/)) + { + label = element.attributes[t].name.replace(/^data-/,'').camelize(); + returnobject[label] = element.attributes[t].value; + } + } + } + } + return returnobject; + } + /** + * Element.sethtml5data(@element,datakey [,value]) -> Object + * + * Sets/Removes HTML5 data-* attributes on `element`. If `value` is not defined or null it will clear the data value on the element. + * + * This will clear up any problems setting these data attributes on browsers + * that don't support them. + * + * ##### Example + * + * language: html + *
+ * + * Then: + * $("dataitem").sethtml5data('newUrl','http://api.prototypejs.org'); + * $("dataitem").sethtml5data('oldUrl',null); + * + * language: html + *
+ **/ + function sethtml5data(element,datalabel,value){ + if(typeof value != undefined) + { + if(NATIVEHTML5DATASET) element.dataset[datalabel.camelize()] = value; + element.writeAttribute("data-"+datalabel.underscore().dasherize(),value); + } + else + { + delete element.dataset[datalabel.camelize()]; + element.writeAttribute("data-"+datalabel.underscore().dasherize(),null); + } + } Object.extend(methods, { getStorage: getStorage, store: store, - retrieve: retrieve + retrieve: retrieve, + gethtml5data: gethtml5data, + sethtml5data: sethtml5data }); From 9b03ceb14be1bd9595ac72fcd09e01617f9c7f9f Mon Sep 17 00:00:00 2001 From: Jason Westbrook Date: Mon, 31 Dec 2012 08:02:34 -0800 Subject: [PATCH 2/5] code optimizations suggested by @victor-homyakov --- src/prototype/dom/dom.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/prototype/dom/dom.js b/src/prototype/dom/dom.js index dd48c697b..446bbe097 100644 --- a/src/prototype/dom/dom.js +++ b/src/prototype/dom/dom.js @@ -3106,9 +3106,8 @@ //simple test for native HTML5 dataset existence var NATIVEHTML5DATASET = (function (){ var testelement = new Element("div",{"data-test-this-thing":"test"}); - if(typeof testelement.dataset != 'undefined' && typeof testelement.dataset.testThisThing != 'undefined') return true; - else return false; - } + return (testelement.dataset && testelement.dataset.testThisThing === 'test'); + }); /** * Element.gethtml5data(@element[, datakey]) -> Object * @@ -3142,10 +3141,10 @@ var label = ""; var numberattributes = element.attributes.length; for(var t = 0; t < numberattributes ; t++) - { - if(element.attributes[t].name.match(/^data-.+/)) + + if(element.attributes[t].name.startsWith('data-')) { - label = element.attributes[t].name.replace(/^data-/,'').camelize(); + label = element.attributes[t].name.substring(4).camelize(); returnobject[label] = element.attributes[t].value; } } @@ -3174,16 +3173,16 @@ *
**/ function sethtml5data(element,datalabel,value){ - if(typeof value != undefined) + if(typeof value !== 'undefined') { if(NATIVEHTML5DATASET) element.dataset[datalabel.camelize()] = value; - element.writeAttribute("data-"+datalabel.underscore().dasherize(),value); } else { delete element.dataset[datalabel.camelize()]; - element.writeAttribute("data-"+datalabel.underscore().dasherize(),null); + value = null; } + element.writeAttribute("data-"+datalabel.underscore().dasherize(),value); } Object.extend(methods, { getStorage: getStorage, From 7ec37f8a65a1ad2fa03b61e9a16c5ad3ebc9f4e6 Mon Sep 17 00:00:00 2001 From: Jason Westbrook Date: Mon, 31 Dec 2012 08:17:33 -0800 Subject: [PATCH 3/5] missing curly brace caused error --- src/prototype/dom/dom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prototype/dom/dom.js b/src/prototype/dom/dom.js index 446bbe097..4d216cccc 100644 --- a/src/prototype/dom/dom.js +++ b/src/prototype/dom/dom.js @@ -3141,7 +3141,7 @@ var label = ""; var numberattributes = element.attributes.length; for(var t = 0; t < numberattributes ; t++) - + { if(element.attributes[t].name.startsWith('data-')) { label = element.attributes[t].name.substring(4).camelize(); From 9320c59d76ee7c31f5b6cdc9d49df7b4546eb3f6 Mon Sep 17 00:00:00 2001 From: Jason Westbrook Date: Fri, 4 Jan 2013 00:21:07 -0800 Subject: [PATCH 4/5] curly brace styling --- src/prototype/dom/dom.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/prototype/dom/dom.js b/src/prototype/dom/dom.js index 4d216cccc..7c4bfa5a5 100644 --- a/src/prototype/dom/dom.js +++ b/src/prototype/dom/dom.js @@ -3128,22 +3128,16 @@ function gethtml5data(element,datalabel){ if(!(element = $(element))) return; var returnobject = {}; - if(NATIVEHTML5DATASET) - { + if(NATIVEHTML5DATASET){ if(datalabel != undefined) returnobject[datalabel.camelize()] = element.dataset[datalabel]; else returnobject = element.dataset; - } - else - { + }else{ if(datalabel != undefined) returnobject[datalabel.camelize()] = element.readAttribute('data-'+datalabel); - else - { + else{ var label = ""; var numberattributes = element.attributes.length; - for(var t = 0; t < numberattributes ; t++) - { - if(element.attributes[t].name.startsWith('data-')) - { + for(var t = 0; t < numberattributes ; t++){ + if(element.attributes[t].name.startsWith('data-')){ label = element.attributes[t].name.substring(4).camelize(); returnobject[label] = element.attributes[t].value; } @@ -3173,12 +3167,9 @@ *
**/ function sethtml5data(element,datalabel,value){ - if(typeof value !== 'undefined') - { + if(typeof value !== 'undefined'){ if(NATIVEHTML5DATASET) element.dataset[datalabel.camelize()] = value; - } - else - { + }else{ delete element.dataset[datalabel.camelize()]; value = null; } From 02333f8b6375636045b2927b9251dc1a5fee1595 Mon Sep 17 00:00:00 2001 From: Jason Westbrook Date: Thu, 24 Jan 2013 22:24:40 -0800 Subject: [PATCH 5/5] separate functions and use cached element Separated out native vs simulated HTML5 dataset usage and fixed up the test to see if native was available --- src/prototype/dom/dom.js | 54 +++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/prototype/dom/dom.js b/src/prototype/dom/dom.js index 7c4bfa5a5..c34ab8acc 100644 --- a/src/prototype/dom/dom.js +++ b/src/prototype/dom/dom.js @@ -3105,9 +3105,10 @@ } //simple test for native HTML5 dataset existence var NATIVEHTML5DATASET = (function (){ - var testelement = new Element("div",{"data-test-this-thing":"test"}); - return (testelement.dataset && testelement.dataset.testThisThing === 'test'); - }); + DIV.setAttribute('data-test-this-thing','test'); + return (typeof DIV.dataset !== 'undefined' && DIV.dataset.testThisThing === 'test') ? true : false; + })(); + DIV.removeAttribute('data-test-this-thing'); /** * Element.gethtml5data(@element[, datakey]) -> Object * @@ -3121,26 +3122,29 @@ * language: html *
* - * Then: - * $("dataitem").gethtml5data().oldUrl; - * // -> "http://prototypejs.org" + * + * $('dataitem').gethtml5data(); + * // -> {'oldUrl':'http://prototypejs.org'} + * $('dataitem').gethtml5data('oldUrl'); + * // -> 'http://prototypejs.org' **/ function gethtml5data(element,datalabel){ + if(!(element = $(element))) return; + if(datalabel != undefined) return element.dataset[datalabel]; + else return element.dataset; + } + //if the easy native html5 dataset is not supported do it the hard way + function gethtml5data_simulated(element,datalabel){ if(!(element = $(element))) return; var returnobject = {}; - if(NATIVEHTML5DATASET){ - if(datalabel != undefined) returnobject[datalabel.camelize()] = element.dataset[datalabel]; - else returnobject = element.dataset; - }else{ - if(datalabel != undefined) returnobject[datalabel.camelize()] = element.readAttribute('data-'+datalabel); - else{ - var label = ""; - var numberattributes = element.attributes.length; - for(var t = 0; t < numberattributes ; t++){ - if(element.attributes[t].name.startsWith('data-')){ - label = element.attributes[t].name.substring(4).camelize(); - returnobject[label] = element.attributes[t].value; - } + if(typeof datalabel !== 'undefined') return element.readAttribute('data-'+datalabel.underscore().dasherize()); + else{ + var label = ""; + var numberattributes = element.attributes.length; + for(var t = 0; t < numberattributes ; t++){ + if(element.attributes[t].name.startsWith('data-')){ + label = element.attributes[t].name.substring(5).camelize(); + returnobject[label] = element.attributes[t].value; } } } @@ -3168,19 +3172,23 @@ **/ function sethtml5data(element,datalabel,value){ if(typeof value !== 'undefined'){ - if(NATIVEHTML5DATASET) element.dataset[datalabel.camelize()] = value; + element.dataset[datalabel.camelize()] = value; }else{ delete element.dataset[datalabel.camelize()]; value = null; } element.writeAttribute("data-"+datalabel.underscore().dasherize(),value); - } + } + function sethtml5data_simulated(element,datalabel,value){ + value = value || null; + element.writeAttribute("data-"+datalabel.underscore().dasherize(),value); + } Object.extend(methods, { getStorage: getStorage, store: store, retrieve: retrieve, - gethtml5data: gethtml5data, - sethtml5data: sethtml5data + gethtml5data: NATIVEHTML5DATASET ? gethtml5data : gethtml5data_simulated, + sethtml5data: NATIVEHTML5DATASET ? sethtml5data : sethtml5data_simulated });