Skip to content

Added html5data methods set/get #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 85 additions & 3 deletions src/prototype/dom/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return (testelement.dataset && testelement.dataset.testThisThing === 'test');

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
* <div id="dataitem" data-old-url="http://prototypejs.org"></div>
*
* Then:
* $("dataitem").gethtml5data().oldUrl;
* // -> "http://prototypejs.org"
**/
function gethtml5data(element,datalabel){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var getHtml5Data = NATIVEHTML5DATASET ? function(element, datalabel) {
  if (!(element = $(element))) return;
  return datalabel ? element.dataset[datalabel.camelize()] : element.dataset;
} : function(element, datalabel) {
  // skipped
};
  1. You can make two different implementations (native/emulated) rather than check each time.
  2. You return object {someCamelizedProperty: value} instead of plain value when datalabel is provided. IMHO when I call element.getHtml5Data('my-data') I just want my data back without any extra effort to extract it from an object.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for 1 - thats a good idea - the other code changes were simple ones - let me work on separating them out

for 2 I was thinking of doing that - but I wanted to be consistent with the return value (an object) vs "if you ask for one value you'll get a string - otherwise you get an object" what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of time similar methods in other frameworks are used to retrieve exactly one value. Compare

var data1 = element1.getHtml5Data('my-data'), data2 = element2.getHtml5Data('my-data');

with

var data1 = element1.getHtml5Data('my-data')['my-data'], data2 = element2.getHtml5Data('my-data')['my-data'];

Even if you need two or three values from the same element

var a = element.getHtml5Data('my-data-a'), b = element.getHtml5Data('my-data-b');

looks not worser than

var data = element.getHtml5Data(), a = data['my-data-a'], b = data['my-data-b'];

Also in this example count the time needed for enumerating all attributes of an element and retrieving all data- attributes in order to get just few attributes with known names.

P.S. Everything is an object :)

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-.+/))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for regexp. String#startsWith is enough (and faster).

{
label = element.attributes[t].name.replace(/^data-/,'').camelize();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, just use substring rather than replace(RegExp, String)

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
* <div id="dataitem" data-old-url="http://prototypejs.org"></div>
*
* Then:
* $("dataitem").sethtml5data('newUrl','http://api.prototypejs.org');
* $("dataitem").sethtml5data('oldUrl',null);
*
* language: html
* <div id="dataitem" data-new-url="http://api.prototypejs.org"></div>
**/
function sethtml5data(element,datalabel,value){
if(typeof value != undefined)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is Object.isUndefined()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't agree with this change as Object.isUndefined() is defined as

  function isUndefined(object) {
    return typeof object === "undefined";
  }

granted the line should be corrected to

if(typeof value !== 'undefined')

{
if(NATIVEHTML5DATASET) element.dataset[datalabel.camelize()] = value;
element.writeAttribute("data-"+datalabel.underscore().dasherize(),value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines 3177, 3180 and 3185 can be merged for dataset emulation:

if (Object.isUndefined(value))
  value = null;
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
});


Expand Down