Подтвердить что ты не робот

Построение экземпляра DOMTokenList/DOMSettableTokenList

Интерфейсы DOMTokenList и DOMSettableTokenList (MDN, WHATWG) предоставляют методы для управления упорядоченными наборами строковые маркеры, представленные строками, разделенными пробелами. Они чаще всего используются в виде свойства Element.prototype.classList, DOMTokenList, который отражает атрибут class связанного элемента.

var div = document.createElement('div');
div.setAttribute('class', 'hello world goodnight moon');

var list = div.classList;

console.assert(list.length           === 4);
console.assert(list[0]               === 'hello');
console.assert(list.item(1)          === 'world');
console.assert(list.contains('moon') === true);
console.assert(list.contains('mars') === false);

list.remove('world', 'earth', 'dirt', 'sand');
list.add('hello', 'mars');
list.toggle('goodnight');

console.assert(div.getAttribute('class') === 'hello moon mars');
4b9b3361

Ответ 1

Вы не можете напрямую создать DOMTokenList или DOMSettableTokenList. Вместо этого вы должны использовать атрибут class для хранения и извлечения ваших данных и, возможно, сопоставить атрибут ids вашего элемента DOM с свойством classList.

    var element = document.querySelector('so-users');
    element.ids = element.classList;

Вы можете использовать relList в соответствии с документацией, но классList больше поддерживается, единственным недостатком является то, что вы можете столкнуться с проблемами, если один из ваших идентификаторов совпадает с именем класса, поэтому установите встроенный стиль, чтобы скрыть элемент на всякий случай.

Для пользовательской совместимости компонентов должна быть проблема (классList присутствует в IE >= 10, Firefox 3.6, Chrome 8, Opera 11.5 и Safari 5.1, см. http://caniuse.com/#feat=classlist), поэтому, если совместимость в ваших требованиях, используйте другое решение, размещенное ниже.

Если вы не можете использовать clases или classList и/или должны использовать атрибут ids, вы должны реализовать пользовательскую функцию в соответствии со спецификацией со следующими свойствами как функции.

  • элемент()
  • содержит()
  • добавить()
  • удалить()
  • переключение()

Это пример реализации таких функций.

var TokenList = function (ids) {
    'use strict';
    var idsArray = [],
        self = this,
        parse = function (id, functionName, cb) {
            var search = id.toString();
            if (search.split(' ').length > 1) {
                throw new Error("Failed to execute '" + functionName + "' on 'TokenList': The token provided ('" + search + "') contains HTML space characters, which are not valid in tokens.');");
            } else {
                cb(search);
            }
        };

    function triggerAttributeChange() {
        if (self.tokenChanged && typeof self.tokenChanged === 'function') {
            self.tokenChanged(idsArray.toString());
        }
    }

    if (ids && typeof ids === 'string') {
        idsArray = ids.split(' ');
    }
    self.item = function (index) {
        return idsArray[index];
    };

    self.contains = function (id) {
        parse(id, 'contains', function (search) {
            return idsArray.indexOf(search) !== -1;
        });
    };

    self.add = function (id) {
        parse(id, 'add', function (search) {
            if (idsArray.indexOf(search) === -1) {
                idsArray.push(search);
            }
            triggerAttributeChange();
        });
    };

    self.remove = function (id) {
        parse(id, 'remove', function (search) {
            idsArray = idsArray.filter(function (item) {
                return item !== id;
            });
            triggerAttributeChange();
        });
    };

    self.toggle = function (id) {
        parse(id, 'toggle', function (search) {
            if (!self.contains(search)) {
                self.add(search);
            } else {
                self.remove(search);
            }
        });
    };

    self.tokenChanged = null;

    self.toString = function () {
        var tokens = '',
            i;
        if (idsArray.length > 0) {
            for (i = 0; i < idsArray.length; i = i + 1) {
                tokens = tokens + idsArray[i] + ' ';
            }
            tokens = tokens.slice(0, tokens.length - 1);
        }
        return tokens;
    };
};

Задайте свойство ids в элементе с новым экземпляром этой функции, и, наконец, вы должны привязать целевой атрибут к свойству, слушая изменения элемента и обновив свойство o viceversa. Вы можете сделать это с помощью наблюдателя мутации.

Посмотрите событие стрельбы по изменению атрибута DOM и https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver p >

var attachTokenList = function (element, prop, initialValues) {
    'use strict';
    var initValues = initialValues || element.getAttribute(prop),
        MutationObserver = window.MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
        observer,
        config,
        cancelMutation = false;

    function createTokenList(values) {
        var tList = new TokenList(values);
        tList.tokenChanged = function () {
            element.setAttribute(prop, element[prop].toString());
            cancelMutation = true;
        };
        element[prop] = tList;
    }

    createTokenList(initValues);

    observer = new MutationObserver(function (mutation) {
        var i,
            mutationrec,
            newAttr;
        if (mutation.length > 0 && !cancelMutation) {
            for (i = 0; i < mutation.length; i = i + 1) {
                mutationrec = mutation[i];
                if (mutationrec.attributeName === prop && element[prop]) {
                    newAttr = element.getAttribute(prop);
                    createTokenList(newAttr);
                }
            }
        }
        cancelMutation = false;
    });

    config = {
        attributes: true
    };
    observer.observe(element, config);
};

Тестирование, чтобы увидеть, работает ли оно

<so-users ids="1234 5678"></so-users>
<button onclick="clickButton1()">Add 7890</button>
<button onclick="clickButton2()">Set to 3456</button>
<button onclick="clickButton3()">Add 9876</button>

Внутри тега script

var elem = document.querySelector('so-users');
attachTokenList(elem, 'ids')

function clickButton1 () {
    elem.ids.add('7890');
}

function clickButton2 () {
    elem.setAttribute('ids', '3456');
}

function clickButton3 () {
    elem.ids.add('9876');
}

Нажав кнопки последовательно, установите атрибут ids на "3456 9876"

Ответ 2

Использование Пользовательские элементы - Добавление свойств и методов JS, HTMLElement.dataset, попробуйте

var XFooProto = Object.create(HTMLElement.prototype);

// 1. Give x-foo a foo() method.
XFooProto.contains = function(id) {
  var data = JSON.parse(this.dataset.ids);
  return data.some(function(_id) {
    return id == _id
  })
};

XFooProto.add = function(id) {
  var data = JSON.parse(this.dataset.ids);
  if (!this.contains(id)) {
    data.push(id);
  };
  return data
};

XFooProto.remove = function(id) {
  var data = JSON.parse(this.dataset.ids);
  if (this.contains(id)) {
    for (var _id in data) {
      if (data[_id] === id) {
        data.splice(_id, 1)
      }
    };
  };
  return data
};

XFooProto.ids = function() {
  return this.dataset.ids
};

// 2. Define a property read-only "bar".
// Object.defineProperty(XFooProto, "ids", {value: this});

// 3. Register x-foo definition.
var XFoo = document.registerElement('x-foo', {prototype: XFooProto});

// 4. Instantiate an x-foo.
var xfoo = document.createElement('x-foo');

xfoo.dataset.ids = '["23354", "115866"]';

// 5. Add it to the page.
document.body.appendChild(xfoo);

console.log(xfoo.add("123")); // `["23354", "115866", "123"]`

console.log(xfoo.remove("123")); // `["23354", "115866"]`

console.log(xfoo.contains("123")); // `false`

console.log(xfoo.contains("23354")); // `true`

console.log(xfoo.ids()); // `["23354", "115866"]` , type : `String`

var pre = document.getElementsByTagName("pre")[0]

pre.innerText = JSON.stringify(JSON.parse(xfoo.dataset.ids), null, 4);
<pre></pre>