36cb2beb8174c1c1e5a04d24038769701a05ebeeDav Glass/**
36cb2beb8174c1c1e5a04d24038769701a05ebeeDav Glass* @for DOM
36cb2beb8174c1c1e5a04d24038769701a05ebeeDav Glass* @module dom
36cb2beb8174c1c1e5a04d24038769701a05ebeeDav Glass*/
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeneyvar documentElement = Y.config.doc.documentElement,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y_DOM = Y.DOM,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney TAG_NAME = 'tagName',
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney OWNER_DOCUMENT = 'ownerDocument',
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney EMPTY_STRING = '',
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney addFeature = Y.Features.add,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney testFeature = Y.Features.test;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt SweeneyY.mix(Y_DOM, {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * Returns the text content of the HTMLElement.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @method getText
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {HTMLElement} element The html element.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @return {String} The text content of the element (includes text of any descending elements).
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney getText: (documentElement.textContent !== undefined) ?
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney function(element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var ret = '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = element.textContent;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return ret || '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney } : function(element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var ret = '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = element.innerText || element.nodeValue; // might be a textNode
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return ret || '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * Sets the text content of the HTMLElement.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @method setText
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {HTMLElement} element The html element.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {String} content The content to add.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney setText: (documentElement.textContent !== undefined) ?
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney function(element, content) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney element.textContent = content;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney } : function(element, content) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if ('innerText' in element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney element.innerText = content;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney } else if ('nodeValue' in element) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney element.nodeValue = content;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney 'for': 'htmlFor',
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney 'class': 'className'
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney } : { // w3c
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney 'htmlFor': 'for',
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney 'className': 'class'
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * Provides a normalized attribute interface.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @method setAttribute
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {HTMLElement} el The target element for the attribute.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {String} attr The attribute to set.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {String} val The value of the attribute.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney setAttribute: function(el, attr, val, ieAttr) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (el && attr && el.setAttribute) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney el.setAttribute(attr, val, ieAttr);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney else { Y.log('bad input to setAttribute', 'warn', 'dom'); }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * Provides a normalized attribute interface.
310222e0398f640815c4704d08bf0ea3af51c13fMichael Leibenson * @method getAttribute
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {HTMLElement} el The target element for the attribute.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @param {String} attr The attribute to get.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @return {String} The current value of the attribute.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney getAttribute: function(el, attr, ieAttr) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var ret = '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (el && attr && el.getAttribute) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = el.getAttribute(attr, ieAttr);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (ret === null) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = ''; // per DOM spec
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney else { Y.log('bad input to getAttribute', 'warn', 'dom'); }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return ret;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney VALUE_SETTERS: {},
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney VALUE_GETTERS: {},
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney getValue: function(node) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var ret = '', // TODO: return null?
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney getter;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (node && node[TAG_NAME]) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney getter = Y_DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (getter) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = getter(node);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney } else {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = node.value;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney // workaround for IE8 JSON stringify bug
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney // which converts empty string values to null
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (ret === EMPTY_STRING) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney ret = EMPTY_STRING; // for real
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return (typeof ret === 'string') ? ret : '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney setValue: function(node, val) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var setter;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (node && node[TAG_NAME]) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney setter = Y_DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (setter) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney setter(node, val);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney } else {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney node.value = val;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney creators: {}
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney});
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt SweeneyaddFeature('value-set', 'select', {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney test: function() {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var node = Y.config.doc.createElement('select');
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney node.innerHTML = '<option>1</option><option>2</option>';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney node.value = '2';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return (node.value && node.value === '2');
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney});
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeneyif (!testFeature('value-set', 'select')) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y_DOM.VALUE_SETTERS.select = function(node, val) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney for (var i = 0, options = node.getElementsByTagName('option'), option;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney option = options[i++];) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (Y_DOM.getValue(option) === val) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney option.selected = true;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney //Y_DOM.setAttribute(option, 'selected', 'selected');
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney break;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney}
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt SweeneyY.mix(Y_DOM.VALUE_GETTERS, {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney button: function(node) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney});
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt SweeneyY.mix(Y_DOM.VALUE_SETTERS, {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney // IE: node.value changes the button text, which should be handled via innerHTML
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney button: function(node, val) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var attr = node.attributes.value;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (!attr) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney attr = node[OWNER_DOCUMENT].createAttribute('value');
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney node.setAttributeNode(attr);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney attr.value = val;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney});
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt SweeneyY.mix(Y_DOM.VALUE_GETTERS, {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney option: function(node) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var attrs = node.attributes;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return (attrs.value && attrs.value.specified) ? node.value : node.text;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney select: function(node) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var val = node.value,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney options = node.options;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (options && options.length) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney // TODO: implement multipe select
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (node.multiple) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y.log('multiple select normalization not implemented', 'warn', 'DOM');
7d1963c4d72cbb90a8e2ac8633d3d084f341c119Matt Sweeney } else if (node.selectedIndex > -1) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney val = Y_DOM.getValue(options[node.selectedIndex]);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return val;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney});