自定义选择标记

时间:2016-07-26 12:03:15

标签: javascript html5 web-component custom-tag

我想创建一个自定义选择标记,例如我希望它继承所有属性。我试过了:

document.registerElement('my-select', {
    prototype: Object.create(HTMLSelectElement.prototype),
    extends: 'select'
});

document.registerElement('my-option', {
    prototype: Object.create(HTMLOptionElement.prototype),
    extends: 'option'
});

但它似乎不起作用。我做错了什么?

2 个答案:

答案 0 :(得分:1)

您只提供了构建自定义选择组件的抽象方法。实现将包括创建两个原型,即select和option,最后使用我们将在HTML页面中声明的自定义选择框将其挂起。< / p>

查看演示文稿的小提琴链接https://jsfiddle.net/47gzo8kt/

<强>使用Javascript:

var CustomizedSelectOptionPrototype = Object.create(HTMLElement.prototype);
document.registerElement('cust-select-option', { prototype: CustomizedSelectOptionPrototype});

var CustomizedSelectProto = Object.create(HTMLSelectElement.prototype);
CustomizedSelectProto.createdCallback = function() {
    if (!this.getAttribute('tabindex')) {
        this.setAttribute('tabindex', 0);
    }
    this.placeholder = document.createElement('span');
    this.appendChild(this.placeholder);

    var selected = this.querySelector('cust-select-option[selected]');
    this.placeholder.textContent = selected ? selected.textContent : (this.getAttribute('placeholder') || '');
};
document.registerElement('cust-select', { prototype: CustomizedSelectProto, extends:"select"});

<强> HTML:

<label>
    Customized Select Box:
    <select is="cust-select" placeholder="Please select an option">
        <option selected value="1">English</option>
        <option value="2">French</option>
        <option value="3">Hindi</option>
    </select>
</label>

答案 1 :(得分:0)

自问这个问题以来已经有一段时间了。但是我遇到它想要做同样的事情。现在看来v0和v1规格一团糟。尽管对HTMLButtonElement使用相同的代码,但它在chrome中抛出非法构造函数,与使用HTMLSelectElement相同。我已经开始写这个并认为我会分享。它可以被清理,并且添加了更多的选择元素方法,但是其他人可以从这里获取它以根据他们的需要进行调整。

class mySelectElement extends HTMLElement {
    static get observedAttributes() { return ['disabled']; }
    constructor() {
        super();
        let shadowRoot = this.attachShadow({
                mode: 'open'
            }),
            content = document.createElement('slot'),
            options = null;
        content.setAttribute('select', 'option');
        shadowRoot.innerHTML = `<style>
:host([disabled]) {
background: grey;
pointer-events: none;
opacity: 0.4;
pointer-events: none;
height: 16px;
}
:host:before{
content: '';
}
:host{
contain: layout size style;
overflow: auto;
align-items:center;
background-color:rgb(255, 255, 255);
border: 1px solid black;
color:rgb(0, 0, 0);
display:inline-block;
font: 13.3333px Arial;
height:16px;
width:145px;
writing-mode:horizontal-tb;
-webkit-appearance:menulist;
-webkit-rtl-ordering:logical;
}
.hide{
display:none;
}
#options{
position: fixed;
border:1px solid blue;
}       
::slotted(option){
background-color:white;
}
::slotted(:hover){
background-color: #a4d8d2;
}
</style>
<div id="options" class="hide"></div>`;
        options = shadowRoot.getElementById('options');
        options.appendChild(content);
        this.disabled = false;
        this.setAttribute('tabIndex', -1);
        this.addEventListener('click', function (e) {
            let target = e.target;
            if (target.nodeName == 'OPTION') {
                this.value = target.value;
                Array.from(target.parentElement.children).forEach(x => x.removeAttribute('selected'));
                target.setAttribute('selected', '');
                shadowRoot.styleSheets[0].rules[1].style.cssText = "content: " 
                    + '"' + target.textContent + '"';
                this.blur();
            }
        });
        this.addEventListener('focus', function () {
            let rect = this.getBoundingClientRect();
            options.style.top = rect.bottom;
            options.style.left = rect.left;
            options.style.width = rect.width;
            options.classList.remove('hide');
        });
        this.addEventListener('focusout', function () {
            options.classList.add('hide');
        });
        this.add = function (item) {
            this.appendChild(item);
            if (this.value == undefined) {
                this.value = content.assignedNodes()[0].value;
                content.assignedNodes()[0].setAttribute('selected', '');
                shadowRoot.styleSheets[0].rules[1].style.cssText = "content: " +
                    '"' + content.assignedNodes()[0].textContent + '"';
            }
        }
        this.item = function (i) {
            return content.assignedNodes()[i];
        }
        this.namedItem = function (val) {
            return content.assignedNodes().find(x => x.value == val);
        }
        this.remove = function (i) {
            return content.assignedNodes()[i].remove();
        }
    }
    attributeChangedCallback(attributeName, oldValue, newValue, namespace) {
        if (attributeName == 'disabled') {
            if (newValue = '')
                this.disabled = true;
            else if (newValue == null)
                this.disabled = false;
        }

    }
}

customElements.define('my-select', mySelectElement);
var _select = customElements.get('my-select');

var select = new _select;
document.body.appendChild(select);
for (let i = 0; i < 10; i++) {
    let option = document.createElement('option');
    option.innerHTML = 'hello_' + i;
    option.value = 'h' + i;
    select.add(option);
}