How to bold searched content using only javascript? - javascript

I'm trying to make an auto suggest search using javascript. All things are working fine, now i wanted to make searched text bold in the list.
Is this possible when user search something then only search text become bold in the result list. For example if i search one then one will be bold in the list.
var inputId = 'filter-search';
var itemsData = 'filter-value';
var displaySet = false;
var displayArr = [];
function getDisplayType(element) {
var elementStyle = element.currentStyle || window.getComputedStyle(element, "");
return elementStyle.display;
}
document.getElementById(inputId).onkeyup = function() {
var searchVal = this.value.toLowerCase();
var filterItems = document.querySelectorAll('[' + itemsData + ']');
for(var i = 0; i < filterItems.length; i++) {
if (!displaySet) {
displayArr.push(getDisplayType(filterItems[i]));
}
filterItems[i].style.display = 'none';
if(filterItems[i].getAttribute('filter-value').toUpperCase().indexOf(searchVal.toUpperCase()) >= 0) {
filterItems[i].style.display = displayArr[i];
}
}
displaySet = true;
}
<input type="text" id="filter-search" />
<ul>
<li filter-value="One Is">One Is (Uppercase)</li>
<li filter-value="one is">one is (Lowercase)</li>
<li filter-value="two">Two</li>
<li filter-value="three">Three</li>
<li filter-value="four">Four</li>
<li filter-value="five" >Five</li>
<li filter-value="six">Six</li>
<li filter-value="seven">Seven</li>
<li filter-value="eight">Eight</li>
<li filter-value="nine">Nine</li>
<li filter-value="ten" >Ten</li>
</ul>

I have done this via using below code
var textcontent = filterItems[i].textContent;
var replacedval = "<strong>"+currval+"</strong>"
var finalval = textcontent.replace(currval, replacedval);
filterItems[i].innerHTML = finalval;
filterItems[i].style.display = 'none';
Here is working JSFiddle
https://jsfiddle.net/ku5zv3dz/

It's not possible to change the style of only a part of a text contained within an element.
To do what you ask, you have to create an additional element (say, a <span> element) which will contain only the text you want to make bold, and append it. Then, you have to remove the same text from the original element.
For example
<li filter-value="One Is">
<span class="bold">One</span> Is (Uppercase)
</li>
Since you already know which part of the text has been searched, it should be trivial to do this using String.replace() and DOM manipulation methods like document.createElement and document.appendChild.

Here's what I got. I'm a little confused with your toLowerCase and toUpperCase code, but for the most part this works. Type in 'o', or 'u', or any of the above to test. It'll bold just what you typed in (in lowercase, since that's what your code does..)
var inputId = 'filter-search';
var itemsData = 'filter-value';
var displaySet = false;
var displayArr = [];
function getDisplayType(element) {
var elementStyle = element.currentStyle || window.getComputedStyle(element, "");
return elementStyle.display;
}
document.getElementById(inputId).onkeyup = function() {
var searchVal = this.value.toLowerCase();
var filterItems = document.querySelectorAll('[' + itemsData + ']');
for (var i = 0; i < filterItems.length; i++) {
var elem = filterItems[i]; // assign it to a variable so that i don't have to constantly say filterItems[i]
if (!displaySet) {
displayArr.push(getDisplayType(elem));
}
elem.style.display = 'none';
elem.innerHTML = elem.innerHTML.replace(/<b>/g, '').replace(/<\/b>/g, ''); // strip away all previous bold
if (elem.getAttribute('filter-value').toUpperCase().indexOf(searchVal.toUpperCase()) >= 0) {
elem.style.display = displayArr[i];
if (searchVal.length > 0) {
elem.innerHTML = elem.innerHTML.replace(new RegExp(searchVal, 'g'), '<b>' + searchVal + '</b>'); // replace search with bold
}
}
}
displaySet = true;
}
.
<input type="text" id="filter-search" />
<ul>
<li filter-value="One Is">One Is (Uppercase)</li>
<li filter-value="one is">one is (Lowercase)</li>
<li filter-value="two">Two</li>
<li filter-value="three">Three</li>
<li filter-value="four">Four</li>
<li filter-value="five" >Five</li>
<li filter-value="six">Six</li>
<li filter-value="seven">Seven</li>
<li filter-value="eight">Eight</li>
<li filter-value="nine">Nine</li>
<li filter-value="ten" >Ten</li>
</ul>
JSFiddle: https://jsfiddle.net/x5amcaqr/

Related

Search Filter with Javascript

I am trying to build a basic search filter where you search and a certain image appears on screen and I am trying to do this with javascript or simple jquery , I cannot seem to make the search work, and I am also wondering if it is possible to do a search based on a class name?
Here is my HTML code
<form onkeyup "function()" >
<input type="search" id = "myInput" placeholder="Search.." name="search" >
</form>
<ul id ="myUL">
<li class="SupernaturalCookbook"><img src="Images/SupernaturalCookbookCard.jpg" alt="SupernaturalCookbook"></li>
<li class="MarkOfAthena"><img src="Images/MarkOfAthenaCard.jpg" alt="MarkOfAthena"></li>
<li class="Instinct"><img src="Images/InstinctCard.jpg" alt="Instinct"></li>
<li class="CaminoIsland"><img src="Images/CaminoIslandCard.jpg" alt="caminoisland"></li>
<li class="TheLuckyOne"><img src="Images/TheLuckyOneCard.jpg" alt="theluckyone"></li>
<li class="TheWhistler"><img src="Images/TheWhistlerCard.jpg" alt="thewhistler"></li>
<li class="Greenlights"><img src="Images/GreenlightsCard.jpg" alt="greenlights"></li>
<li class="SeaOfMonsters"><img src="Images/SeaOfMonstersCard.jpg" alt="seaofmonsters"></li>
<li class="SerpentShadows"><img src="Images/SerpentShadowsCard.jpg" alt="serpentshadows"></li>
<li class="FromCrookToCook"><img src="Images/FromCrookToCookCard.jpg" alt="fromcrooktocook"></li>
</ul>
Here is my Javascript code:
var input = document.getElementById('myInput');
input.onkeyup = function () {
var filter = myInput.value.toUpperCase();
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
var name = lis[i].getElementsByClassName('class')[0].innerHTML;
if (name.toUpperCase().indexOf(filter) == 0)
lis[i].style.display = 'list-item';
else
lis[i].style.display = 'none';
}
In addition to what others added, please keep in mind that onkeyup only triggers when someone releases a key. However, there are other ways to change the input of an input field such as cut, paste, clear, etc. To make sure you have covered all the aspects, you can wrap your code in a named function and bind it to the following events
function search_images(){
///code goes here
}
input.onkeyup = search_images
input.onchange = search_images
input.onpaste = search_images
input.oncut = search_images
input.oninput = search_images
Also, be sure to RESET the filter if the input is empty. An alternative solution is as follows:-
function search_images() {
let filter = this.value.toUpperCase();
let lis = Array.from(document.getElementsByTagName('li'));
if (filter.length > 0) {
lis.forEach(li => {
if (Array.from(li.classList).join(" ").toUpperCase().indexOf(filter) >= 0) {
li.style.display = "list-item"
} else {
li.style.display = "none"
}
})
} else {
lis.forEach(li => li.style.display = "list-item")
}
}
const input = document.getElementById('myInput');
input.onkeyup = search_images
input.onchange = search_images
input.onpaste = search_images
input.oncut = search_images
input.oninput = search_images
<form>
<input type="search" id="myInput" placeholder="Search.." name="search">
</form>
<ul id="myUL">
<li class="SupernaturalCookbook">
<img src="Images/SupernaturalCookbookCard.jpg" alt="SupernaturalCookbook">
</li>
<li class="MarkOfAthena">
<img src="Images/MarkOfAthenaCard.jpg" alt="MarkOfAthena">
</li>
<li class="Instinct">
<img src="Images/InstinctCard.jpg" alt="Instinct">
</li>
<li class="CaminoIsland">
<img src="Images/CaminoIslandCard.jpg" alt="caminoisland">
</li>
<li class="TheLuckyOne">
<img src="Images/TheLuckyOneCard.jpg" alt="theluckyone">
</li>
<li class="TheWhistler">
<img src="Images/TheWhistlerCard.jpg" alt="thewhistler">
</li>
<li class="Greenlights">
<img src="Images/GreenlightsCard.jpg" alt="greenlights">
</li>
<li class="SeaOfMonsters">
<img src="Images/SeaOfMonstersCard.jpg" alt="seaofmonsters">
</li>
<li class="SerpentShadows">
<img src="Images/SerpentShadowsCard.jpg" alt="serpentshadows">
</li>
<li class="FromCrookToCook">
<img src="Images/FromCrookToCookCard.jpg" alt="fromcrooktocook">
</li>
</ul>
If you want to filter by class name, replace this line ...
var name = lis[i].getElementsByClassName('class')[0].innerHTML;
... with this:
var name = lis[i].className;
var input = document.getElementById('myInput');
input.onkeyup = function () {
var filter = input.value.toUpperCase();
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
var name = lis[i].className; // takes the classname
if (name.toUpperCase().indexOf(filter) >= 0) //Changed this part
lis[i].style.display = 'list-item';
else
lis[i].style.display = 'none';
}
}
indexOf method returns -1 if not found, else it will be greater than or equal than 0.

Javascript creating json object from two strings

So I will start with my needs. I have a task to create json output using nightwatch.js from the ul list where inside lists are few div elements with classes like name, surname... But really I can't think of any of solutions. Here is my html
<html>
<meta charset="utf-8">
<body>
<ul class="random">
<li class="list">
<div class="name">John</div>
<div class="surname">Lewis</div>
</li>
<li class="list odd">
<div class="name">Nick</div>
<div class="surname">Kyrgios</div>
</li>
</ul>
</body>
</html>
And here is my nightwatch.js script
'Test' : function(browser) {
function iterate(elements) {
elements.value.forEach(function(el) {
browser.elementIdText(el.ELEMENT, function(r) {
browser.elementIdAttribute(el.ELEMENT, 'class', function(att){
// output for json i guess
console.log(att.value + ' => ' + r.value)
})
});
});
}
browser
.url('http://url.com/nightwatch.php')
.waitForElementVisible('body', 8000)
.elements('css selector', 'ul li div', iterate)
.end();
}
Basically this will execute the following:
name => John
surname => Lewis
name => Nick
surname => Kyrgios
Output is a string for both...
And how can I make it like
[{name: "John", surname: "Lewis"}, {name: "Nick", surname: "Kyrgios"}]
This should work. You just need to keep track of the object and place it inside the array after list.
function iterate(elements) {
var objArr = [];
var obj = {};
elements.value.forEach(function(el, idx) {
browser.elementIdText(el.ELEMENT, function(r) {
browser.elementIdAttribute(el.ELEMENT, 'class', function(att){
if (obj.hasOwnProperty(att.value)) {
objArr.push(obj);
obj = {};
}
obj[att.value] = r.value;
});
});
if (idx === (elements.value.length-1)) {
objArr.push(obj);
console.log(objArr);
}
});
}
As with Will's solution, I used straight JavaScript. It does not appear that the nightwatch.js code for this provides any significant benefit. In addition, your question does not specify that only nightwatch.js should be used.
As opposed to Will, I have assumed that the class on your inner <div> elements could be arbitrary and that the arbitrary class should be used as the key/property on the object for that entry. Choosing to use this method vs. restricting it only to a name or surname property will depend on what your HTML really is, and how you want to handle classes which are not those two strings.
var theList = [];
var listItems = document.querySelectorAll('li');
for (var itemIndex=0,itemLength=listItems.length; itemIndex < itemLength; itemIndex++) {
var entry = {};
divs = listItems[itemIndex].querySelectorAll('div');
for (var divsIndex=0, divsLength=divs.length; divsIndex < divsLength; divsIndex++) {
entry[divs[divsIndex].className] = divs[divsIndex].textContent;
}
theList.push(entry);
}
outputJson = JSON.stringify(theList);
console.log(outputJson);
<html>
<meta charset="utf-8">
<body>
<ul class="random">
<li class="list">
<div class="name">John</div>
<div class="surname">Lewis</div>
</li>
<li class="list odd">
<div class="name">Nick</div>
<div class="surname">Kyrgios</div>
</li>
</ul>
</body>
</html>
What about something like this?
function iterate(elements) {
var jsonArray = [];
var jsonBuffer = "";
elements.value.forEach(function(el) {
browser.elementIdText(el.ELEMENT, function(r) {
browser.elementIdAttribute(el.ELEMENT, 'class', function(att){
// output for json i guess
if (att.value == 'name') {
jsonBuffer += "{" + att.value + ":" + "" + r.value + "" + ",";
}
else {
jsonBuffer += att.value + ":" + "" + r.value + "" + "}";
jsonArray.push(jsonBuffer);
jsonBuffer = "";
}
})
});
});
var jsonOutput = "[";
var i = 0;
jsonArray.forEach(function(el) {
if (i < jsonArray.length) {
jsonOutput += el + ",";
} else {
jsonOutput += el + "]";
}
i++;
}
}
I'm not familiar with Nightwatch, but you essentially loop through the elements and push them on to an array.
var results = [];
var entries = document.querySelectorAll('li');
for (var ix = 0; ix < entries.length; ix++) {
var name = entries[ix].querySelector('.name').innerText;
var surname = entries[ix].querySelector('.surname').innerText;
results.push({
name: name,
surname: surname
});
}
console.log(results);
<ul class="random">
<li class="list">
<div class="name">John</div>
<div class="surname">Lewis</div>
</li>
<li class="list odd">
<div class="name">Nick</div>
<div class="surname">Kyrgios</div>
</li>
</ul>

change text color of matching text from input in javascript

Here is my code
And I am trying to change the color of any match in the <li> elements that matches the text in the <input> element. So if you type lets say "this is a simple text" the result should look like this:
<input value="this is a simple text" id="term"/>
<ul id="ul-id" >
<li id="li-id-1"> hello budy <span style="color:red">this</span> <span style="color:red">is</span> really <span style="color:red">simple</span> stuff </li>
<li id="li-id-2"> <span style="color:red">this</span> <span style="color:red">is</span> it</li>
<li id="li-id-3"> there <span style="color:red">is</span> something here</li>
<li id="li-id-4"> plain <span style="color:red">text</span> file</li>
</ul>
Any help would be appreciated.
Thank you.
You can remove the delay function if you like, but this would lead to a performance loss:
// https://stackoverflow.com/a/9310752/1636522
RegExp.escape = function (text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
};
window.addEventListener('load', function () {
var wrapper = '<span style="background:yellow">$&</span>';
var input = document.getElementById('term');
var list = document.getElementById('ul-id');
var items = list.getElementsByTagName('li');
var l = items.length;
var source = Array.prototype.map.call(
items, function (li) { return li.textContent; }
);
var cmp = function (a, b) {
return b.length - a.length;
};
var delay = function (fn, ms) {
var id, scope, args;
return function () {
scope = this;
args = arguments;
id && clearTimeout(id);
id = setTimeout(function () {
fn.apply(scope, args);
}, ms);
};
};
term.addEventListener('keyup', delay(function () {
var i, re, val;
if (val = this.value.match(/[^ ]+/g)) {
val = val.sort(cmp).map(RegExp.escape);
re = new RegExp(val.join('|'), 'g');
for (i = 0; i < l; i++) {
items[i].innerHTML = source[i].replace(re, wrapper);
}
}
else {
for (i = 0; i < l; i++) {
items[i].textContent = source[i];
}
}
}, 500));
});
<input value="" id="term"/>
<ul id="ul-id" >
<li id="li-id-1"> hello budy this is really simple stuff </li>
<li id="li-id-2"> this is it</li>
<li id="li-id-3"> there is something here</li>
<li id="li-id-4"> plain text file</li>
</ul>
Similar topic: https://stackoverflow.com/a/20427785/1636522.
I don't know if it is possible with only RegEx, but here is a jQuery solution:
$('#term').change(function() {
var inpArr = $(this).val().split(" ");
$('#ul-id li').each(function() {
var liArr = $(this).text().split(" ");
var txt = "";
$.each(liArr, function(i, v) {
if(inpArr.indexOf(v) > -1) {
txt += "<span class='red'>"+ v +"</span> ";
} else {
txt += v + " ";
}
});
$(this).html(txt);
});
});
span.red {
color: red;
}
And the working fiddle: https://jsfiddle.net/ermk32yc/1/
Plain JS solution
var list = document.querySelector('#ul-id'),
listItem,
listItems,
term = document.querySelector('#term'),
oldRef = list.innerHTML,
oldValue;
term.addEventListener('keyup', function () {
var regExp,
value = term.value;
if (oldValue !== value) {
oldValue = value;
// Reset
list.innerHTML = oldRef;
if (value.trim() !== '') {
listItems = list.querySelectorAll('#ul-id li');
regExp = new RegExp(term.value, 'g');
// Perform matching
for (var i = 0; i < listItems.length; i++) {
listItem = listItems[i];
listItem.innerHTML = listItem.innerHTML.replace(regExp, function (match) {
return '<span class="matched">' + match + '</span>';
});
}
}
}
}, false);
.matched {
color: red;
}
<input id="term"/>
<ul id="ul-id" >
<li id="li-id-1"> hello budy this is really simple stuff </li>
<li id="li-id-2"> this is it</li>
<li id="li-id-3"> there is something here</li>
<li id="li-id-4"> plain text file</li>
</ul>
You might do something like this
$('#term').change(function (i) {
var terms = $('#term').val().split(" ");
$('#ul-id > li').each(function (i, el) {
var val = $(el).html().replace(/<[^<]+>/g, ''),
match;
terms.forEach(function (term) {
val = val.replace(new RegExp(term, 'g'),
'<span style="color:red">' + term + '</span>');
});
$(el).html(val);
});
});
https://jsfiddle.net/1vm0259x/5/
You can use the below solution if there is no html contents in the li elemnets
if (!RegExp.escape) {
RegExp.escape = function(value) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
var lis = [].slice.call(document.querySelectorAll('#ul-id li'));
lis.forEach(function(el) {
el.dataset.text = el.innerHTML;
});
document.querySelector('#term').addEventListener('change', function() {
var parts = this.value.split(' ').map(function(value) {
return '\\b' + RegExp.escape(value) + '\\b';
});
var regex = new RegExp(parts.join('|'), 'g');
lis.forEach(function(el) {
el.innerHTML = el.dataset.text.replace(regex, function(part) {
return '<span class="highlight">' + part + '</span>'
})
});
});
.highlight {
color: red;
}
<input id="term" />
<ul id="ul-id">
<li id="li-id-1">hello budy this is really simple stuff</li>
<li id="li-id-2">this is it</li>
<li id="li-id-3">there is something here</li>
<li id="li-id-4">plain text file</li>
</ul>
With jQuery
if (!RegExp.escape) {
RegExp.escape = function(value) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
$('#term').on('change keyup', function() {
//$('#ul-id li .highlight').contents().unwrap();//remove previous highlights
var parts = this.value.split(' ').map(function(value) {
return '\\b' + RegExp.escape(value) + '\\b';
});
var regex = new RegExp(parts.join('|'), 'g');
$('#ul-id li ').each(function() {
var text = $(this).text();
$(this).html(text.replace(regex, function(part) {
return '<span class="highlight">' + part + '</span>'
}))
})
});
.highlight {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="term" />
<ul id="ul-id">
<li id="li-id-1">hello budy this is really simple stuff</li>
<li id="li-id-2">this is it</li>
<li id="li-id-3">there is something here</li>
<li id="li-id-4">plain text file</li>
</ul>
you can handle blur event or you can copy paste the inner function code to wherever it is required. this is the guide code here you can more explore match function as per your requirement and then can traverse your li elements as shown below.
$('#term).blur(function() {
$('#ul-id li').foreach(function()
{
if($(this).text().match($("#term").text()))
{
///set/change here color of li element
$(this).css('color', 'red');
}
}
}

Apply multiple filter categories to a list of <li>(s) with javascript

I have this fiddle and I want to know how I can implement filtering function based on two categories. when someone click the filter, it should get the values from both the current filters selection, hide the list and show only the filter result. Any idea on how to implement this step? any help would be appreciated!!
<ul style='list-style-type: none;' class="filter1">
<li><span class="filtercat1">red</span>
</li>
<li><span class="filtercat1">blue</span>
</li>
<li><span class="filtercat1">yellow</span>
</li>
<li><span class="filtercat1">all</span>
</li>
</ul> <span id="filterbutton1">
« Previous
Next »
</span>
<ul style='list-style-type: none;' class="filter2">
<li><span class="filtercat2">orange</span>
</li>
<li><span class="filtercat2">apple</span>
</li>
<li><span class="filtercat2">papaya</span>
</li>
<li><span class="filtercat2">all</span>
</li>
</ul> <span id="filterbutton2">
« Previous
Next »
</span>
<ul id='list'>
<li class="">red orange</li>
<li class="">red apple</li>
<li class="">red papaya</li>
<li class="">blue orange</li>
<li class="">blue apple</li>
<li class="">blue papaya</li>
<li class="">yellow orange</li>
<li class="">yellow apple</li>
<li class="">yellow papaya</li>
</ul>
<span id="filterbutton">
filter
<span id="resetbutton">
reset
$(function () {
var all = $('.filtercat1').addClass("passiv");
var i = -1;
$('#prev' ).click(function () {
ctrlbutton(i = !i ? all.length - 1 : --i);
});
$('#next').click(function () {
ctrlbutton(i = ++i % all.length);
}).click();
function ctrlbutton(ele) {
all.removeClass("active").addClass("passiv");
all.eq(ele).removeClass("passiv").addClass("active");
}
})
$(function () {
var all = $('.filtercat2').addClass("passiv");
var i = -1;
$('#prev2').click(function () {
ctrlbutton(i = !i ? all.length - 1 : --i);
});
$('#next2').click(function () {
ctrlbutton(i = ++i % all.length);
}).click();
function ctrlbutton(ele) {
all.removeClass("active").addClass("passiv");
all.eq(ele).removeClass("passiv").addClass("active");
}
})
fiddle: http://jsfiddle.net/BlacBunny/5tfcuy1w/
Use this code
$("#list").find("li").each(function(){
this.className = "all "+this.innerHTML;
});
$("#filter").click(function(){
var class1 = $(".filter1").find(".active").text();
var class2 = $(".filter2").find(".active").text();
$("#list").find("li").addClass("passiv").end().find("."+class1+"."+class2)
.removeClass("passiv").addClass("active");
});
$("#reset").click(function(){
$("#list").find("li").addClass("active").removeClass("passiv");
});
I have not optimized this code. You are using dom ready function two times which is actually not required.
You can see the fiddle here
See Fiddle
This function will be called every time the filters are modified. The values of filter1 and filter2 must be modified per click to the filter buttons.
var filter1 = 'red'; // initial value of filter1
var filter2 = 'orange'; // initial value of filter2
function filterList() {
var list = $('#list li');
list.each(function(index, item) {
var itemContents = $(item).text();
if (itemContents.indexOf(filter1) >= 0 && itemContents.indexOf(filter2) >= 0) {
$(item).show();
} else {
console.log('hide ' + itemContents);
}
});
}
Fiddle
$("#filter").click(function() {
var filterCat1 = $(".filter1 .active").text();
var filterCat2 = $(".filter2 .active").text();
$("#list li").each( function( index, element ){
var text = $(element).text();
if((text.indexOf(filterCat1) < 0 && filterCat1 != "all")
|| (text.indexOf(filterCat2) < 0 && filterCat2 != "all"))
$(element).removeClass("active").addClass("passiv");
else
$(element).removeClass("passiv").addClass("active");
});
});
Try the contains selector
$('#filter').click(function() {
$("#list li").addClass("passiv");
var filter1 = $(".filter1 span.active").text();
var filter2 = $(".filter2 span.active").text();
var filter= (filter1 == "all" ? "" : filter1) + " " + (filter2 == "all" ? "" : filter2);
$('#list li:contains("' + filter + '")').removeClass("passiv");
});
http://jsfiddle.net/5tfcuy1w/10/

Use an array in this function to display values of chechboxes checked

This function replicates the user experience of a Select/MultiSelect dropdown element - displaying the values of checkboxes checked in a container (adds/removes them when they're checked/unchecked), and if more than 3 items have been checked it displays the # selected instead of the values selected.
It's a combination of 2 functions and they're not playing well together when items are unchecked (i.e. it's removing the values but not the commas, doesn't work correctly when more than 3 items have been selected, etc.)
I think it would be much better if I used an array to store the values, adding/removing values from the array when items are checked/unchecked, and I know how do to in PHP but not in Javascript. This code should create the array, but I can't figure out how to integrate it into my code.
$('input:checkbox[name="color[]"]:checked').each(function () {
selectedColors.push($(this).val());
});
Existing Code:
JS
$(".dropdown_container ul li").click(function () {
var text = $(this.children[0]).find("input").val();
var text_edited = text.replace(/_/g, " ");
var currentHtml = $(".dropdown_box span").html();
var positionLocation = currentHtml.indexOf(text_edited);
var numberChecked = $('input[name="color[]"]:checked').length;
if (positionLocation < 1) {
if (numberChecked <= 3) {
$(".dropdown_box span").html(currentHtml.replace('Colors', ''));
$(".dropdown_box span").append(', ' + text_edited);
} else {
$(".dropdown_box span").html(currentHtml.replace(currentHtml, numberChecked + " Selected"));
}
} else {
(currentHtmlRevised = currentHtml.replace(text_edited, ""));
$(".dropdown_box span").html(currentHtmlRevised.replace(currentHtml));
}
});
HTML
<div class="dropdown_box"><span>Colors</span></div>
<div class="dropdown_container">
<ul id="select_colors">
<li>
<label><a href="#"><div style="background-color: #ff8c00" class="color" onclick="toggle_colorbox_alt(this);"><div class=CheckMark>✓</div>
<input type="checkbox" name="color[]" value="Black" class="cbx"/>
</div>Black</a></label>
</li>
<!-- More List Items --!>
</ul>
</div>
Easiest to just replace the entire content each time. Also use the change event instead of the click event.
$(".dropdown_container input").change(function () {
var checked = $(".dropdown_container input:checked");
var span = $(".dropdown_box span");
if (checked.length > 3) {
span.html("" + checked.length + " selected");
}
else {
span.html(checked.map(function () { return $(this).val().replace("_"," "); }).get().join(", "));
}
});
Example: http://jsfiddle.net/bman654/FCVjj/
try this:
$('.cbx').change(function(){
var cbx = $('.cbx:checked');
var str = '';
if (cbx.length<=3 && cbx.length!=0){
for (var i=0;i<cbx.length;i++){
if (i>0) str += ', ';
str += cbx[i].value;
}
} else if (cbx.length==0){
str = 'Colors';
} else {
str = cbx.length;
}
$('.dropdown_box span').html(str);
});

Categories