使用javascript存储(和检索!)特定于dom元素的数据的最佳方法

时间:2011-09-27 23:05:57

标签: javascript html

我有一个下拉列表矩阵,我希望能够在用户可视化编辑设置时向用户显示(例如,将表格单元格的背景设置为红色)。如果他们将其切换回原始值,它将返回默认背景颜色。这样就可以明确地清楚系统的状态。

为此,我在onchange元素上设置<select>处理程序,如下所示:select.setAttribute('onchange','chSel(this,'+select.selectedIndex+');');其中select<select>元素。

它将调用函数chSel并引用自身和当前设置,因此它将能够设置将通过CSS确定显示属性的类:

function chSel(node, origSelIndex) {
    if (node.selectedIndex == origSelIndex) // switching back to the set state
    node.parentNode.removeAttribute('class');
    else node.parentNode.setAttribute('class','cell_changed');
}

这不需要检索动态数据,尽管selectedIndex处理程序中保存的onchange值用作特定于元素的静态数据。

我想通过在我的桌子周围做一个边框来扩展我所描述的这个功能,当我的任何内容被修改时,我打算将其涂成红色,这样如果桌子很大,它仍然可以一目了然如果其任何条目被修改。

有一种糟糕的方法和更好的方法来实现这一点。我知道如何在兼容的HTML / XHTML中实现的坏方法是chSel(在用户与下拉菜单交互时执行)运行完整搜索整个表格以计算编辑,并相应地标记表格边框。这实际上可能不是性能问题,但我预计它会是。我认为它不会很好地扩展。

更好的方法是保持编辑元素的数量。当该数字回落到零(用户将所有编辑内容更改回原始值)时,我可以将该表重新标记为未编辑。

然而,这需要我有一些方法来确定选择菜单是否已从新值更改为不同的新值,而不是从原始值更改为新值,即它现在与值更改为。似乎没有办法做到这一点。 This discussion似乎表明我无法在保持文档有效的同时创建和检索自定义属性。当我试图分配任意属性时,我很难检索它们的值。

还剩下什么?我可以构建一个对象,我将其用作从元素到整数的哈希吗? javascript甚至会让我这样做吗?

3 个答案:

答案 0 :(得分:2)

我不确定我是否完全遵循您要做的事情,但您可以在javascript变量或自定义DOM属性中跟踪状态。 Javascript变量稍微容易一些,但是你必须给它们一个合适的范围,这样它们才能在你的操作期间存活下来。自定义DOM属性有时更容易实现面向对象并避免任何全局javascript变量。 jQuery的.data()能力实际上介于两者之间。它使用一个自定义数据属性来标记带有唯一标记的DOM对象,然后将所有实际数据存储在javascript地图中。

一旦你适当地存储状态,任何时候你得到一个变化事件,你可以比较以前的值,看看从以前的状态实际改变了什么,更新你的新状态并将新值保存为以前的值或做任何事情否则你需要做。

例如,通过这种方式,您可以保留已编辑项目的数量,并且当值从0变为非零或非零到0时,您可以根据需要更改整个表格外观。同样,只要单个单元格发生变化,您就可以更新它的外观。

如果您的DOM元素是您唯一的数据结构,那么创建自定义属性并在其中保留其他数据可能最简单。 HTML5的方法是将“data-”预先发送到您的属性名称,如obj.setAttribute("data-origSelectIndex", x)obj["data-origSelectIndex"] = x,以防止它们与标准属性发生任何名称冲突。

如果您有任何理由不想使用自定义属性,那么您需要创建一个并行的javascript数据结构(可能是一个数组,其中数组中的每个项目都以某种方式对应一个DOM元素,您可以映射两者之间持有数据。

答案 1 :(得分:1)

大多数表单控件都有 defaultValue 属性。要确定是否有任何更改已从默认值更改,请循环显示它们并将当前 defaultValue 进行比较。对于select元素,请始终将其设置为 selected ,并检查当前选定的option是否将其 defaultSelected 属性设置为true。类似的单选按钮和复选框。

这样你就不必存储任何值,它由DOM元素本身完成。

答案 2 :(得分:0)

使用dom属性作为一种全局变量来处理@jfriend00的建议:

Jsfiddle demo

CSS

.selected { border: 1px solid red;}

HTML

<div id="table1">
    <select id="sel1">
        <option>1</option>
        <option>2</option>
        <option selected>3</option>
    </select>
    <select id="sel2">
        <option selected>1</option>
        <option>2</option>
        <option>3</option>
    </select>
</div>
<div id="table2">
    <select id="sel3">
        <option>1</option>
        <option selected>2</option>
        <option>3</option>
    </select>
    <select id="sel4">
        <option selected>1</option>
        <option>2</option>
        <option>3</option>
    </select>
</div>

使用Javascript:

(function(){
    var selects = document.getElementsByTagName('select'),
        i = 0,
        selectLength = selects.length;

    var applyParentChange = function(node, val){
        var currentEdits = node.getAttribute('data-edits') || 0;
        currentEdits = parseFloat(currentEdits, 10) + val;
        if(currentEdits <= 0) {
            currentEdits = 0;
            node.className = '';
        } else {
            node.className = 'selected';
        }

        node.setAttribute('data-edits',currentEdits);

    };

    var onSelectChange = function(){
        var defaultIndex = parseFloat(this.getAttribute('data-default'),10);
        if(defaultIndex === this.selectedIndex){
            applyParentChange(this.parentNode, -1);
            this.className = '';
        } else {
            applyParentChange(this.parentNode, 1);
            this.className = 'selected'; 
        }

    };

    for(i=0; i<selectLength; i+=1){
        selects[i].setAttribute('data-default',selects[i].selectedIndex);
        selects[i].onchange = onSelectChange;
    }
})();

稍微讨论一下代码......

您获得了所有select元素的集合,并为其提供了带有默认选定索引的自定义属性,并直接为其提供onchange事件。

在更改时,它会检查新索引与原始(默认)索引,并在需要时将CSS应用于元素。然后它将它传递给父节点(在这种情况下为div,但可以是任何)。

在父级中,我们为编辑数保留了类似的自定义属性。如果有人不断重复选择默认值,则0的最小值是保持设置。如果它有1个或多个编辑,则应用CSS,如果为0则删除。

请注意,这只是一种方法,您可以将一个集合保存在一个保持引用/计数的变量中,一些使用隐藏(屏幕外)输入元素来存储值......