2016-07-26 6 views
0

Я хочу, например, создать пользовательский тег select, и я хочу, чтобы он наследовал все атрибуты. Я пробовал:Custom select tag

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

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

Но, похоже, он не работает. Что я сделал не так?

ответ

1

Вы предоставляете только абстрактный способ создания настраиваемого компонента выбора. Реализация будет включать создание двух прототипов, а именно для выбора и опции, и, наконец, подключение к нему с помощью настраиваемого поля выбора, которое мы будем объявлять на странице HTML.

Оформить эту скрипку ссылку на демо: 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> 
+0

Нет Thats не то, что я хочу, я хочу написать: <КЛИЕНТ-Select-опции> .... .... –

+0

я хочу Каст-выбрать, чтобы вести себя так же, как

0

Это было некоторое время, так как этот вопрос был задан. Однако я наткнулся на это, пытаясь сделать то же самое. Кажется, спецификации v0 и v1 сейчас бесполезны. Несмотря на использование того же кода для HTMLButtonElement, он бросает незаконный конструктор в хром, так же как и с использованием 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); 
}