2016-06-15 11 views
0

ライブ検索で次のコードを用意しました。入力フォーカスでは、使用可能なオプションのリストが表示されます。入力ぼかしでは、オプションが消えます。私の問題があります。リストからアイテムフォームをクリックすると、入力がフォーカスを失い、クリックイベントが発生する前にリストが消えます。カスタムデータリスト - 選択する前に選択肢が消える

var artists = [{"artist":"3 Doors Down"},{"artist":"5 Seconds of Summer"},{"artist":"Adele"},{"artist":"Alicia Keys"},{"artist":"Amanda Abizaid"}]; 
 

 
function liveSearch(element) { 
 
    return new liveSearch.prototype.init(element); 
 
} 
 
liveSearch.prototype = { 
 
    init : function(element) { 
 
    if (!element) { 
 
     this.element = document.createElement("ul"); 
 
     this.element.classList.add("liveSearch"); 
 
    } else { 
 
     this.element = element; 
 
    } 
 
    }, 
 
    update : function(queryElement) { 
 
    this.clear(); 
 
    var lookUpArray = queryElement.name + "s"; 
 
    var results = this.search(artists, queryElement.value, queryElement.name); 
 
    for (var i = 0; i < results.length; i++) { 
 
     var li = document.createElement("li"); 
 
     var value = results[i]; 
 
     if (queryElement.value != "") { 
 
     var re = new RegExp(queryElement.value, "gi"); 
 
     value = value.replace(re, "<span class=\"highlight\">" + "$&" + "</span>"); 
 
     } 
 
     li.innerHTML = value; 
 
     this.element.appendChild(li); 
 
    } 
 
    return results.length; 
 
    }, 
 
    search : function(lookUpArray, string) { 
 
    var results = []; 
 
    for (var i = 0; i < lookUpArray.length; i++) { 
 
     if (lookUpArray[i].artist.toLowerCase().search(string.toLowerCase()) != -1) { 
 
     results.push(lookUpArray[i].artist); 
 
     } 
 
    } 
 
    return results; 
 
    }, 
 
    clear : function() { 
 
    this.element.innerHTML = ""; 
 
    }, 
 
    hidden : function() { 
 
    this.element.style.display = "none"; 
 
    }, 
 
    visible : function() { 
 
    this.element.style.display = ""; 
 
    }, 
 
    remove : function() { 
 
    this.element.parentElement.removeChild(this.element); 
 
    }, 
 
}; 
 
liveSearch.prototype.init.prototype = liveSearch.prototype; 
 

 
$("#lyrics-form").on("focus", "input.liveSearch-input", function() { 
 
    this.parentElement.appendChild(liveSearch().element); 
 
    if (liveSearch(this.nextElementSibling).update(this)) { 
 
    liveSearch(this.nextElementSibling).visible(); 
 
    } else { 
 
    liveSearch(this.nextElementSibling).hidden(); 
 
    } 
 
}); 
 

 
$("#lyrics-form").on("blur", "input.liveSearch-input", function() { 
 
    liveSearch(this.nextElementSibling).remove(); 
 
}); 
 

 
$("#lyrics-form").on("keyup", "input.liveSearch-input", function() { 
 
    if (this.value != "") { 
 
    if (liveSearch(this.nextElementSibling).update(this)) { 
 
     liveSearch(this.nextElementSibling).visible(); 
 
    } else { 
 
     liveSearch(this.nextElementSibling).hidden(); 
 
    } 
 
    } else { 
 
    liveSearch(this.nextElementSibling).update(this); 
 
    } 
 
}); 
 

 
$("#lyrics-form").on("click", "li", function() { 
 
    this.parentElement.previousElementSibling.value = this.innerText; 
 
    liveSearch(this.parentElement).hidden(); 
 
});
input, ul { 
 
    width: 180px; 
 
    box-sizing: border-box; 
 
} 
 
.liveSearch { 
 
    margin: 0; 
 
    border: 1px solid silver; 
 
    box-shadow: 0 2px 5px rgba(0,0,0,.5); 
 
    position: absolute; 
 
    background: white; 
 
    padding: 5px; 
 
    max-height: 195px; 
 
    width: 180px; 
 
    overflow-y: scroll; 
 
    z-index: 1000; 
 
} 
 
.liveSearch li { 
 
    padding: 2px 5px; 
 
    cursor: default; 
 
} 
 
.liveSearch li:hover { 
 
    background: rgba(0,0,0,.05); 
 
    color: black; 
 
} 
 
.liveSearch .highlight { 
 
    font-weight: bold; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<form action="addlyrics.php" id="lyrics-form" method="post" autocomplete="off" enctype="multipart/form-data"> 
 
\t <input type="text" name="artist" id="artist" class="liveSearch-input" placeholder="Artist" required /> 
 
</form>

私はこの問題を回避するためにぼかしでタイムアウトを使用しましたが、それは十分ではありません。一貫性がなく、遅延が長くなるとデザインが醜いものになります。これをどうすれば解決できますか?

$("#lyrics-form").on("blur", "input.liveSearch-input", function() { 
    /* liveSearch(this.nextElementSibling).remove(); */ 
    setTimeout(function() { 
     liveSearch(this.nextElementSibling).remove(); 
    }.bind(this), 100); 
}); 

答えて

0

私はちょうどdatalist要素について学んだことがあります。それは私がここで成し遂げようとしていることをちょっとしますが、私はそれをスタイルしたり、変更することはできません。だから私は自分のコードにいくつかの変更を加え、カスタムデータリストを作った。

var artists = [{"artist":"3 Doors Down"},{"artist":"5 Seconds of Summer"},{"artist":"Adele"},{"artist":"Alicia Keys"},{"artist":"Amanda Abizaid"}]; 
 

 
function datalist(element) { 
 
    return new datalist.prototype.init(element); 
 
} 
 
datalist.prototype = { 
 
    init : function(element) { 
 
    if (!element) { 
 
     this.element = document.createElement("ul"); 
 
     this.element.classList.add("datalist");; 
 
     this.hide(); 
 
    } else { 
 
     this.element = element; 
 
    } 
 
    }, 
 
    update : function(queryElement) { 
 
    this.clear(); 
 
    var lookUpArray = queryElement.name + "s"; 
 
    var results = this.search(window[lookUpArray], queryElement.value, queryElement.name); 
 
    for (var i = 0; i < results.length; i++) { 
 
     var li = document.createElement("li"); 
 
     var value = results[i][queryElement.name]; 
 
     if (queryElement.value != "") { 
 
     var re = new RegExp(queryElement.value, "gi"); 
 
     value = value.replace(re, "<span class=\"highlight\">" + "$&" + "</span>"); 
 
     } 
 
     li.innerHTML = value; 
 
     this.element.appendChild(li); 
 
    } 
 
    return results.length; 
 
    }, 
 
    search : function(lookUpArray, string, queryType) { 
 
    var results = []; 
 
    for (var i = 0; i < lookUpArray.length; i++) { 
 
     if (lookUpArray[i][queryType].toLowerCase().search(string.toLowerCase()) != -1) { 
 
     results.push(lookUpArray[i]); 
 
     } 
 
    } 
 
    return results; 
 
    }, 
 
    clear : function() { 
 
    this.element.innerHTML = ""; 
 
    }, 
 
    hide : function() { 
 
    this.element.style.display = "none"; 
 
    }, 
 
    show : function() { 
 
    this.element.style.display = ""; 
 
    }, 
 
    remove : function() { 
 
    this.element.parentElement.removeChild(this.element); 
 
    }, 
 
}; 
 
datalist.prototype.init.prototype = datalist.prototype; 
 

 
var lastVisitedInput = null; 
 

 
$("#lyrics-form").on("focus", "input.datalist-input", function() { 
 
    if (this.parentElement.children.length == 1) { 
 
    this.parentElement.appendChild(datalist().element); 
 
    } 
 
    if (lastVisitedInput) { 
 
    datalist(lastVisitedInput.nextElementSibling).hide(); 
 
    } 
 
    lastVisitedInput = this; 
 
    if (datalist(this.nextElementSibling).update(this)) { 
 
    datalist(this.nextElementSibling).show(); 
 
    } 
 
}); 
 

 
$("#lyrics-form").on("input", "input.datalist-input", function() { 
 
    datalist(this.nextElementSibling).update(this); 
 
}); 
 

 
$(document).on("click", function(e) { 
 
    if (lastVisitedInput) { 
 
    var exceptions = getExceptions(lastVisitedInput); 
 
    if (!contains(exceptions, e.target)) { 
 
     datalist(lastVisitedInput.nextElementSibling).remove(); 
 
     lastVisitedInput = null; 
 
    } 
 
    } 
 
}); 
 

 
$("#lyrics-form").on("click", "li", function() { 
 
    this.parentElement.previousElementSibling.value = this.innerText; 
 
    $(this.parentElement.previousElementSibling).trigger("input"); 
 
}); 
 

 
function getExceptions(input) { 
 
    var exceptions = [ 
 
    input, 
 
    input.nextElementSibling, 
 
    ]; 
 
    for (var i = 0; i < input.nextElementSibling.children.length; i++) { 
 
    exceptions.push(input.nextElementSibling.children[i]); 
 
} 
 
return exceptions; 
 
} 
 

 
function contains(array, item) { 
 
    for (var i = 0; i < array.length; i++) { 
 
    if (array[i] === item) { 
 
     return true; 
 
    } 
 
    } 
 
    return false; 
 
}
input { 
 
    padding: 5px; 
 
} 
 
input, ul { 
 
    width: 200px; 
 
    box-sizing: border-box; 
 
} 
 
.datalist { 
 
    margin: 0; 
 
    border: 1px solid silver; 
 
    box-shadow: 0 2px 5px rgba(0,0,0,.5); 
 
    position: absolute; 
 
    background: white; 
 
    padding: 5px; 
 
    max-height: 200px; 
 
    overflow-y: scroll; 
 
    z-index: 1000; 
 
} 
 
.datalist li { 
 
    padding: 2px 5px; 
 
    cursor: default; 
 
} 
 
.datalist li:hover { 
 
    background: rgba(0,0,0,.05); 
 
    color: black; 
 
} 
 
.datalist .highlight { 
 
    font-weight: bold; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<form id="lyrics-form" autocomplete="off" enctype="multipart/form-data"> 
 
\t <input type="search" name="artist" id="artist" class="datalist-input" placeholder="Artist" required /> 
 
</form>

+0

項目が選択されると、リスト全体が消え。私はこれがデータリスト(Chromeバージョン63.0.3239.84(公式ビルド)(64ビット))を使用しようとするたびにこのケースであることを発見しました。 –

+0

@Ridバグだとは思わない、なぜなら、リストアイテムをフィルタリングし、一致したアイテムを返します。選択した後にボックスをクリックすると、入力したアイテムが処理され、一致するアイテムが返されます。 – akinuri

+0

あなたはおそらく正しいかもしれませんが、私はこのカウンターが直感的だと私は確かに私はそれを私たちのユーザーベースに提示することはできません知っている。 –

関連する問題