Ответ 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"