2017-01-09 3 views
0

Я пытаюсь создать выпадающее меню для выбора в ячейке таблицы с использованием ванильного javascript. Как-то мне удалось создать дублированный набор параметров в процессе, который вы можете увидеть на консоли, если вы запустите код. Возможно, то, что я делаю, это неправильный подход. Любой совет будет принят во внимание.javascript динамическое добавление опции для выбора необъяснимо приводит к дублированию набора опций

let allrooms = ['entry', 'kitchen', 'bath', 'hall', 'bed', 'garage']; 
 
let selectedrooms = ['bath', 'kitchen', 'garage']; 
 

 
let menuHeader = document.getElementById('menu-header'); 
 
let roomcontainer = document.getElementById('menu-roomcontainer'); 
 

 
// set the menu header (also a 'td') to a comma delimited string 
 
function addRoomNamesToMenuHeader() { 
 
    menuHeader.childNodes[0].nodeValue = selectedrooms.toString(); 
 
} 
 

 
// create and append options to a 'select' from a string array 
 
(function addProjectRoomsToMenu() { 
 
    addRoomNamesToMenuHeader(); 
 
    let str = 'added elements: ' 
 
    for (let r of allrooms) { 
 
    let newroom = document.createElement('option'); 
 
    newroom.innerHTML = '<option value="' + r + '" class="devroom">' + r + '</option>'; 
 
    roomcontainer.appendChild(newroom); 
 
    if (selectedrooms.indexOf(r) > -1) { 
 
     newroom.selected = 'selected'; 
 
    } 
 
    str += (roomcontainer.children.length + ' ' + r + ' '); 
 
    } 
 
    console.log(str); 
 

 
    let list = document.querySelectorAll('option'); 
 
    str = 'NOTE DUPLICATES: option list =\n'; 
 
    for (let i = 0; i < list.length; i++) { 
 
    str += ('\t' + i + ' ' + list[i].label + ' ' + list[i].selected + ' '); 
 
    if (i & 1) { 
 
     str += '\n'; 
 
    } 
 
    } 
 
    console.log(str); 
 

 
    let selected = Array.prototype.map.apply(
 
    roomcontainer.querySelectorAll('option option[selected]'), [ 
 
     function(o) { 
 
     return o.value; 
 
     } 
 
    ] 
 
); 
 
    console.log('NOTE EMPTY QUERY FOR "option option[selected]"=' + selected); 
 
})(); 
 

 
// changes in option selections will result in a change to 
 
// 'selectedrooms' and menuheader 
 
roomcontainer.onchange = function(e) { 
 
    let selected = Array.prototype.map.apply(
 
    roomcontainer.querySelectorAll('option option[selected]'), [ 
 
     function(o) { 
 
     return o.value; 
 
     } 
 
    ] 
 
); 
 
    console.log('NOTE EMPTY LIST selected "option"=' + selected); 
 

 
    selected = Array.prototype.map.apply(
 
    roomcontainer.querySelectorAll('option'), [ 
 
     function(o) { 
 
     return o.value; 
 
     } 
 
    ] 
 
); 
 
    console.log('NOTE DUPLICATES IN LIST all "option"=' + selected); 
 

 
    // TODO: KLUDGE WORK-AROUND 
 
    selectedrooms.length = 0; 
 
    let list = document.querySelectorAll('option'); 
 
    for (let i = 0; i < list.length; i++) { 
 
    if (list[i].selected) { 
 
     selectedrooms.push(list[i].label); 
 
    } 
 
    } 
 
    addRoomNamesToMenuHeader(); 
 
} 
 

 
document.onclick = function(e) { 
 
    let target = (e && e.target) || (event && event.srcElement); 
 

 
    if (target === menuHeader && roomcontainer.style.display == "none") { 
 
    roomcontainer.style.display = "block"; 
 
    } else if (target.parentNode !== roomcontainer) { 
 
    roomcontainer.style.display = "none"; 
 
    } 
 
}
#menu-roomcontainer, 
 
#menu-header, 
 
table { 
 
    font-family: 'Open Sans', sans-serif; 
 
    font-size: 1em; 
 
    max-width: 14em; 
 
    min-width: 14em; 
 
    padding: 3px; 
 
    border: 1px solid blue; 
 
} 
 
/*prevent pushing down subsequent rows*/ 
 

 
#menu-roomcontainer { 
 
    position: absolute; 
 
} 
 
/*prevent empty cell from collapsing*/ 
 

 
tr:before { 
 
    content: '\a0'; 
 
} 
 
#menu-header { 
 
    color: blue; 
 
} 
 
option { 
 
    color: darkolivegreen; 
 
} 
 
option:hover { 
 
    background: lightgray; 
 
} 
 
option:checked { 
 
    background: lightseagreen; 
 
} 
 
option, 
 
#menu-header:hover { 
 
    cursor: pointer; 
 
} 
 
option, 
 
td { 
 
    margin: 0; 
 
}
<table> 
 
    <tr> 
 
    <td id='menu-header'> 
 
     <select multiple id='menu-roomcontainer' style='display: none;'></select> 
 
    </td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 1</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 2</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 3</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 4</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 5</td> 
 
    </tr> 
 
</table>

+0

Было бы полезно, если вы сократите свой код только сегмент, который имеет проблемы. –

ответ

0

Это неправильно:

newroom.innerHTML = '<option value="' + r + '" class="devroom">' + r + '</option>'; 

newroom это уже <option> элемент, поэтому вы создаете возможность внутри вариант, который является недействительным. Оно должно быть:

newroom.value = r; 
newroom.className = 'devroom'; 
newroom.innerHTML = r; 

let allrooms = ['entry', 'kitchen', 'bath', 'hall', 'bed', 'garage']; 
 
let selectedrooms = ['bath', 'kitchen', 'garage']; 
 

 
let menuHeader = document.getElementById('menu-header'); 
 
let roomcontainer = document.getElementById('menu-roomcontainer'); 
 

 
// set the menu header (also a 'td') to a comma delimited string 
 
function addRoomNamesToMenuHeader() { 
 
    menuHeader.childNodes[0].nodeValue = selectedrooms.toString(); 
 
} 
 

 
// create and append options to a 'select' from a string array 
 
(function addProjectRoomsToMenu() { 
 
    addRoomNamesToMenuHeader(); 
 
    let str = 'added elements: ' 
 
    for (let r of allrooms) { 
 
    let newroom = document.createElement('option'); 
 
    newroom.value = r; 
 
    newroom.className = 'devroom'; 
 
    newroom.innerHTML = r; 
 
    roomcontainer.appendChild(newroom); 
 
    if (selectedrooms.indexOf(r) > -1) { 
 
     newroom.selected = 'selected'; 
 
    } 
 
    str += (roomcontainer.children.length + ' ' + r + ' '); 
 
    } 
 
    console.log(str); 
 

 
    let list = document.querySelectorAll('option'); 
 
    str = 'NOTE DUPLICATES: option list =\n'; 
 
    for (let i = 0; i < list.length; i++) { 
 
    str += ('\t' + i + ' ' + list[i].label + ' ' + list[i].selected + ' '); 
 
    if (i & 1) { 
 
     str += '\n'; 
 
    } 
 
    } 
 
    console.log(str); 
 

 
    let selected = Array.prototype.map.apply(
 
    roomcontainer.querySelectorAll('option option[selected]'), [ 
 
     function(o) { 
 
     return o.value; 
 
     } 
 
    ] 
 
); 
 
    console.log('NOTE EMPTY QUERY FOR "option option[selected]"=' + selected); 
 
})(); 
 

 
// changes in option selections will result in a change to 
 
// 'selectedrooms' and menuheader 
 
roomcontainer.onchange = function(e) { 
 
    let selected = Array.prototype.map.apply(
 
    roomcontainer.querySelectorAll('option option[selected]'), [ 
 
     function(o) { 
 
     return o.value; 
 
     } 
 
    ] 
 
); 
 
    console.log('NOTE EMPTY LIST selected "option"=' + selected); 
 

 
    selected = Array.prototype.map.apply(
 
    roomcontainer.querySelectorAll('option'), [ 
 
     function(o) { 
 
     return o.value; 
 
     } 
 
    ] 
 
); 
 
    console.log('NOTE DUPLICATES IN LIST all "option"=' + selected); 
 

 
    // TODO: KLUDGE WORK-AROUND 
 
    selectedrooms.length = 0; 
 
    let list = document.querySelectorAll('option'); 
 
    for (let i = 0; i < list.length; i++) { 
 
    if (list[i].selected) { 
 
     selectedrooms.push(list[i].label); 
 
    } 
 
    } 
 
    addRoomNamesToMenuHeader(); 
 
} 
 

 
document.onclick = function(e) { 
 
    let target = (e && e.target) || (event && event.srcElement); 
 

 
    if (target === menuHeader && roomcontainer.style.display == "none") { 
 
    roomcontainer.style.display = "block"; 
 
    } else if (target.parentNode !== roomcontainer) { 
 
    roomcontainer.style.display = "none"; 
 
    } 
 
}
#menu-roomcontainer, 
 
#menu-header, 
 
table { 
 
    font-family: 'Open Sans', sans-serif; 
 
    font-size: 1em; 
 
    max-width: 14em; 
 
    min-width: 14em; 
 
    padding: 3px; 
 
    border: 1px solid blue; 
 
} 
 
/*prevent pushing down subsequent rows*/ 
 

 
#menu-roomcontainer { 
 
    position: absolute; 
 
} 
 
/*prevent empty cell from collapsing*/ 
 

 
tr:before { 
 
    content: '\a0'; 
 
} 
 
#menu-header { 
 
    color: blue; 
 
} 
 
option { 
 
    color: darkolivegreen; 
 
} 
 
option:hover { 
 
    background: lightgray; 
 
} 
 
option:checked { 
 
    background: lightseagreen; 
 
} 
 
option, 
 
#menu-header:hover { 
 
    cursor: pointer; 
 
} 
 
option, 
 
td { 
 
    margin: 0; 
 
}
<table> 
 
    <tr> 
 
    <td id='menu-header'> 
 
     <select multiple id='menu-roomcontainer' style='display: none;'></select> 
 
    </td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 1</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 2</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 3</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 4</td> 
 
    </tr> 
 
    <tr> 
 
    <td>Row 5</td> 
 
    </tr> 
 
</table>

+0

Большое спасибо. Извините, за то, что вы не подтвердили ранее. Я думал, что получаю уведомление по электронной почте на своем обычном электронном адресе. Кроме того, с тех пор я решил, что лучше использовать UL вместо SELECT, поскольку ключевое слово Control Key/Shift Key предотвратит использование мобильных устройств, –