I've written a small function for a search bar. Currently if the input doesn't match anything in my array, the function returns the last object in said array (which i made to be empty). I want to change it so that if the input is blank, the function returns "No Result" or something like that. Any ideas why this code isn't working as intended?
let websitePages =
'{"website_pages":[' +
'{"name":"Hamza", "path":"/hamza/"},' +
'{"name":"Jakub", "path":"/jakub/"},' +
'{"name":"Kevin", "path":"/kevin/"},' +
'{"name":"Sreeja", "path":"/sreeja/"},' +
'{"name":"Tristan", "path":"/tristan/"},' +
'{"name":"Math", "path":"/math/"},' +
'{"name":"History", "path":"/history/"},' +
'{"name":"Science", "path":"/sci/"},' +
'{"name":"Literature", "path":"/lit/"},' +
'{"name":"Periodic Table", "path":"/periodictable/"},' +
'{"name":"API Collection", "path":"/api_collection/"},' +
'{"name":"CRUD", "path":"/crud/"},' +
'{"name":"Async CRUD", "path":"/crud_api/"},' +
'{"name":"Database Search", "path":"/crud/search/"},' +
'{"name":"Search (Database)", "path":"/crud/search/"},' +
'{"name":"", "path":"//"}]}'; // this object is empty in case the user inputs a blank, so that the previous result is removed and no link is returned
function SearchMain() {
list = JSON.parse(websitePages);
input = document.getElementById("SearchInput");
filter = input.value.toUpperCase(); // the user's input is changed to uppercase so that the search is not case-sensitive
for (i = 0; i < websitePages.length; i++) {
// this section goes through the items in my array and checks if the user's input is the same as any object name
if (
filter ===
list.website_pages[i].name.toUpperCase().substring(0, filter.length)
) {
//using substrings allows users to only input part of the page name instead of the whole thing
link = list.website_pages[i].path;
document.getElementById("searchResult").innerHTML =
list.website_pages[i].name;
document.getElementById("searchResult").href = link;
} else if (filter === null) {
document.getElementById("searchResult").innerHTML = "No Results";
document.getElementById("searchResult").href = "";
}
}
}
For loop condition should be i < list.website_pages.length, also you should handle two error scenarios. One is input is empty and the search didnot find any valid match. I have updated them in the below fiddle.
Working Fiddle
let websitePages = '{"website_pages":[' +
'{"name":"Hamza", "path":"/hamza/"},' +
'{"name":"Jakub", "path":"/jakub/"},' +
'{"name":"Kevin", "path":"/kevin/"},' +
'{"name":"Sreeja", "path":"/sreeja/"},' +
'{"name":"Tristan", "path":"/tristan/"},' +
'{"name":"Math", "path":"/math/"},' +
'{"name":"History", "path":"/history/"},' +
'{"name":"Science", "path":"/sci/"},' +
'{"name":"Literature", "path":"/lit/"},' +
'{"name":"Periodic Table", "path":"/periodictable/"},' +
'{"name":"API Collection", "path":"/api_collection/"},' +
'{"name":"CRUD", "path":"/crud/"},' +
'{"name":"Async CRUD", "path":"/crud_api/"},' +
'{"name":"Database Search", "path":"/crud/search/"},' +
'{"name":"Search (Database)", "path":"/crud/search/"},' +
'{"name":"", "path":"//"}]}'; // this object is empty in case the user inputs a blank, so that the previous result is removed and no link is returned
function SearchMain() {
list = JSON.parse(websitePages);
input = document.getElementById('SearchInput');
filter = input.value.toUpperCase(); // the user's input is changed to uppercase so that the search is not case-sensitive
let isFound = false;
for (i = 0; i < list.website_pages.length; i++) { // this section goes through the items in my array and checks if the user's input is the same as any object name
if (filter === list.website_pages[i].name.toUpperCase().substring(0, filter.length)) { //using substrings allows users to only input part of the page name instead of the whole thing
link = list.website_pages[i].path;
document.getElementById('searchResult').innerHTML = list.website_pages[i].name;
document.getElementById('searchResult').href = link;
isFound = true;
}
}
if (!filter || !isFound) {
document.getElementById('searchResult').innerHTML = "No Results"
document.getElementById('searchResult').href = ""
}
}
<input type="text" id="SearchInput" />
<button onclick="SearchMain()">SearchMain</button>
<a id="searchResult"></a>
Simplified solution.
Avoid using for loop and make use of Array.find to find the matching node from the list.
Working Fiddle
let websitePages = '{"website_pages":[' +
'{"name":"Hamza", "path":"/hamza/"},' +
'{"name":"Jakub", "path":"/jakub/"},' +
'{"name":"Kevin", "path":"/kevin/"},' +
'{"name":"Sreeja", "path":"/sreeja/"},' +
'{"name":"Tristan", "path":"/tristan/"},' +
'{"name":"Math", "path":"/math/"},' +
'{"name":"History", "path":"/history/"},' +
'{"name":"Science", "path":"/sci/"},' +
'{"name":"Literature", "path":"/lit/"},' +
'{"name":"Periodic Table", "path":"/periodictable/"},' +
'{"name":"API Collection", "path":"/api_collection/"},' +
'{"name":"CRUD", "path":"/crud/"},' +
'{"name":"Async CRUD", "path":"/crud_api/"},' +
'{"name":"Database Search", "path":"/crud/search/"},' +
'{"name":"Search (Database)", "path":"/crud/search/"},' +
'{"name":"", "path":"//"}]}'; // this object is empty in case the user inputs a blank, so that the previous result is removed and no link is returned
function SearchMain() {
list = JSON.parse(websitePages);
input = document.getElementById('SearchInput');
filter = input.value.toUpperCase(); // the user's input is changed to uppercase so that the search is not case-sensitive
const matchingNode = filter ? list.website_pages.find(node => filter === node.name.toUpperCase().substring(0, filter.length)) : null;
if (matchingNode) {
document.getElementById('searchResult').innerHTML = matchingNode.name;
document.getElementById('searchResult').href = matchingNode.path;
}
else {
document.getElementById('searchResult').innerHTML = "No Results"
document.getElementById('searchResult').href = ""
}
}
<input type="text" id="SearchInput" />
<button onclick="SearchMain()">SearchMain</button>
<a id="searchResult"></a>
When I dynamically create checkbox and div, I want to have different id for each of them (like id_1, id_2...).
The first value of my array is erased by the next value.
Currently, I create checkbox for each value I have in my array:
var containerCheckbox = $('#listCheckboxCategories');
// var listCheckboxCategories = $('#listCheckboxCategories');
var CheckboxCreate = '<input id="catCheckbox" type="checkbox" name="categoriesCheckbox" required/>';
var categoriesName = '<span id="catName"/>';
if (tileConfig.isThereFilterRadios == "Yes" && res !== undefined) {
$('#ShowCategories').show();
$('#containerCategories').show();
$.each(res.list, function(index, cat) {
//ToDo: inserer cat.name dans le span
// categoriesName.html(cat.name)
containerCheckbox.append(CheckboxCreate, categoriesName);
$("#catName").html(cat.name);
});
}
Can someone help me ?
You could create a function to return the checkbox element, that way you could pass a variable into the function (eg index) to add to the html to make each id unique
for example
createCheckbox = function (index) {
return '<input id="catCheckbox_' + index + '" type="checkbox" name="categoriesCheckbox" required/>';
}
var containerCheckbox = $('#listCheckboxCategories');
var categoriesName = '<span id="catName"/>';
if (tileConfig.isThereFilterRadios == "Yes" && res !== undefined) {
$('#ShowCategories').show();
$('#containerCategories').show();
$.each(res.list, function(index, cat) {
containerCheckbox.append(createCheckbox(index), categoriesName);
$("#catName").html(cat.name);
});
}
Below code appends text in a box how to avoid entering duplicate values..?
$('#plan td.n').click(function(){
$(this).html('B').css("background-color","red");
$("input:text").val(this.id);
var toAdd = $("input[name=checkListItem]").val();
$(".list").append("<div class = 'item'>" + toAdd + "</div>")//add the seat number to box
});
I'd probably do something like this below. Hope it helps
var lookupObj = {};
var toAdd = $("input[name=checkListItem]").val();
if(!lookupObj[toAdd]) {
$(".list").append("<div class = 'item'>" + toAdd + "</div>")
lookupObj[toAdd] = true;
}
Assuming your markup looks like this:
<input name="checkListItem" value=""/>
<input type="submit" class="addItem" value="Add/Remove"/>
<div class="list">
</div>
You can add an event which filters items which match the text (exactly) of the current .val() of the checkListItem input, which lets you delete the item in the list if it is a duplicate.
$('.addItem').on('click', function() {
var toAdd = $("input[name=checkListItem]").val(),
exists = $('.item').filter(function() {
return $(this).text() == toAdd;
});
if (exists.length > 0) {
exists.remove();
} else {
$(".list").append("<div class = 'item'>" + toAdd + "</div>");
}
});
https://jsfiddle.net/milesrobinson/563h1fq6/
// if you don't care the performance, this is the easy way
var finded = false;
$(".list > .item").each(function(idx){
if (toAdd === $(this).html()) {
finded = true;
return false;
}
});
if (!finded) {
$(".list").append("<div class = 'item'>" + toAdd + "</div>")
}
I am trying to make this work with the help of jQuery docs but not success so far.
I have two boxes paynow and payfull that has 0 initial value but I am filling these boxes dynamically (jQuery) with product prices.
Now I have to update these values further with select option to discount the price (multiply with data-percent). This is the HTML.
<select class="discount">
<option data-percent="0">Select Discount Coupon</option>
<option data-percent="5">ABCD</option>
<option data-percent="10">EFGH</option>
<option data-percent="15">IJKL</option>
</select>
<span class="price" id="paynow">$0.00</span>
<span class="price" id="payfull">$0.00</span>
EDIT: jQuery code
$(document).ready(function() {
// For Calculator
function Cost_Calculator() {
var Currency = '$';
var messageHTML = 'Please contact us for a price.';
function CostFilter(e) {
return e;
}
//Calculate function
function calculate() {
//Blank!
var CalSaveInfo = [];
$('#cost_calc_custom-data, #cost_calc_breakdown').html('');
//Calculate total
var calCost = 0;
var calculate_class = '.cost_calc_calculate';
$('.cost_calc_active').each(function() {
//Calculation
calCost = calCost + parseFloat($(this).data('value'));
//Add to list
var optionName = $(this).attr('value');
var appendName = '<span class="cost_calc_breakdown_item">' + optionName + '</span>';
var optionCost = $(this).attr('data-value');
var appendCost = '<span class="cost_calc_breakdown_price">' + Currency + optionCost + '</span>';
if (optionCost != "0") {
var appendItem = '<li>' + appendName + appendCost + '</li>';
}
//hidden data
var appendPush = ' d1 ' + optionName + ' d2 d3 ' + optionCost + ' d4 ';
$('#cost_calc_breakdown').append(appendItem);
CalSaveInfo.push(appendPush);
});
//Limit to 2 decimal places
calCost = calCost.toFixed(2);
//Hook on the cost
calCost = CostFilter(calCost);
var CustomData = '#cost_calc_custom-data';
$.each(CalSaveInfo, function(i, v) {
$(CustomData).append(v);
});
//Update price
if (isNaN(calCost)) {
$('#paynow').html(messageHTML);
$('#payfull').html(messageHTML);
$('.addons-box').hide();
} else {
$('#paynow').html(Currency + calCost);
$('#payfull').html(Currency + calCost);
$('.addons-box').show();
}
}
//Calculate on click
$('.cost_calc_calculate').click(function() {
if ($(this).hasClass('single')) {
//Add cost_calc_active class
var row = $(this).data('row');
//Add class to this only
$('.cost_calc_calculate').filter(function() {
return $(this).data('row') == row;
}).removeClass('cost_calc_active');
$(this).addClass('cost_calc_active');
} else {
// Remove class if clicked
if ($(this).hasClass('cost_calc_active')) {
$(this).removeClass('cost_calc_active');
} else {
$(this).addClass('cost_calc_active');
}
}
//Select item
var selectItem = $(this).data('select');
var currentItem = $('.cost_calc_calculate[data-id="' + selectItem + '"]');
var currentRow = currentItem.data('row');
if (selectItem !== undefined) {
if (!$('.cost_calc_calculate[data-row="' + currentRow + '"]').hasClass('cost_calc_active'))
currentItem.addClass('cost_calc_active');
}
//Bring in totals & information
$('#cost_calc_breakdown_container, #cost_calc_clear_calculation').fadeIn();
$('.cost_calc_hide').hide();
$('.cost_calc_calculate').each(function() {
calculate();
});
return true;
});
$('#cost_calc_clear_calculation').click(function() {
$('.cost_calc_active').removeClass('cost_calc_active');
calculate();
$('#cost_calc_breakdown').html('<p id="empty-breakdown">Nothing selected</p>');
return true;
});
}
//Run cost calculator
Cost_Calculator();
});
How about this one:
var totalPayNowPrice=parseFloat($('#paynow').text());
var totalPayFullPrice=parseFloat($('#payfull').text());
$('.discount').on('change',function(){
if(parseInt($('.discount option:selected').attr('data-percent'))){
$('#paynow').text((totalPayNowPrice*parseInt($('.discount option:selected').attr('data-percent')))+'$');
$('#payfull').text((totalPayFullPrice*parseInt($('.discount option:selected').attr('data-percent')))+'$');
}
});
Just put the $ sign in you spans after the numbers, in order to parse function would work.
JSFIDDLE
UPDATE
From another point I think there is a better solution to use prototype and store you current prices in spans inside global variable, then you can use them wherever you want. Here the pseudo prototype for your use, if you`d like just customize it for you using:
function Test(){
this.totalPayNowPrice=1;//the is 1 only for check code working
this.totalPayFullPrice=1;
}
Test.prototype={
init: function(){
var scope=this;
$('.discount').on('change',function(){
if(parseInt($('.discount option:selected').attr('data-percent'))){
$('#paynow').text((scope.totalPayNowPrice*parseInt($('.discount option:selected').attr('data-percent')))+'$');
$('#payfull').text((scope.totalPayFullPrice*parseInt($('.discount option:selected').attr('data-percent')))+'$');
}
},
updatePaynowPrice:function(newPrice){
this.totalPayNowPrice=totalPayNowPrice;
},
updatePayfullPrice:function(newPrice){
this.totalPayFullPrice=totalPayNowPrice;
}
}
you can use
$(document).ready(function(){
// get price from #paynow (just a number)
var getPaynow = $('#paynow').text().match(/\d+/);
// get price from #payfull (just a number)
var getPayfull = $('#payfull').text().match(/\d+/);
$('.discount').on('change', function(){
// get data-percent from selected option
var discount = parseFloat($(this).find('>option:selected').attr('data-percent'));
//alert(discount +'///'+ getPaynow+'///'+ getPayfull);
//update price for #paynow and #payfull
$('#paynow').text('$'+parseFloat(getPaynow - (getPaynow * discount / 100)));
$('#payfull').text('$'+parseFloat(getPayfull - (getPayfull * discount / 100)));
});
});
Working Demo
in your code you can update prices after this part of code
//Update price
if (isNaN(calCost)) {
$('#paynow').html(messageHTML);
$('#payfull').html(messageHTML);
$('.addons-box').hide();
} else {
$('#paynow').html(Currency + calCost);
$('#payfull').html(Currency + calCost);
$('.addons-box').show();
}
//get price from #paynow (just a number)
getPaynow = $('#paynow').text().match(/\d+/);
// get price from #payfull (just a number)
getPayfull = $('#payfull').text().match(/\d+/);
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);
});