Compare input to every id and output the closest matching one [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm making basic search on my website. When you type into the search it automatically compares the input against every element-id in the document. When it finds a match it scrolls to the matched element. As of now the search works only when you input the exact id (excluding case-sensitivity and spaces).
Here is my JQuery code:
$('#search-box').focus(function() {
$('#search-box').keyup(function () {
var x = $('#search-box').val().replace(/\s+/g, '').toLowerCase();
if ($("#" + x).length !== 0) {
navbarHeight = $('#fixed-navbar').height();
$('html, body').animate({scrollTop:$('#'+x).position().top - window.navbarHeight}, 500);
}
});
});
I think, I've tried everything starting from .match() to using plugins like List.js.
Is there a way to compare inputed text to id's and output the first matching one? Tolerance modifier would be neat but not required.

My solution:
// Searches automatically for first matching id
var idArray = $("div[id^='x-']") // find spans with ID attribute
.map(function() { return this.id; })// convert to set of IDs
.get(); // convert to instance of Array (optional)
navbarHeight = $('#fixed-navbar').height();
console.log(idArray);
$('#search-box').keyup(function () {
for (var i=0; i<idArray.length; i++) {
var input = $('#search-box').val().replace(/\s+/g, '').toLowerCase();
matched = idArray[i].match(new RegExp(input));
if (matched !== null) {
$('html, body').animate({scrollTop:$('#'+ idArray[i]).position().top - window.navbarHeight});
console.log('Matched part: ' + matched);
break;
};
if (matched == undefined) {
matched = [];
matched.length = 0;
};
};
});
Working JSFiddle.
(thx for help guys /s)
Final thoughts:
I didn't add the tolerance variable but it's easy enough (compared to this IMO).
Also, I may add so that it stats to search only from the beginning of the id (because people usually start typing the beginning of the word) but then the "search anywhere in the name" functionality won't work.
Edit: Finally managed to make it work the way I asked to. Code almost rewritten and updated.

Related

Why does the splice() array method always deletes all objects following the selected index in Javascript? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 months ago.
Improve this question
I'm currently studying Javascript and the teacher asked us to create a program that allows users to create, edit and delete hotels using object arrays.
I managed to created the showHotels() function without any issue but I'm having troubles deleting a specific hotel from the created array as when I use the splice() method it deletes the object selected but also all the following ones.
The user will have to enter the name of the hotel in order to delete it, we therefore do not know the index of the object.
I am only allowed to use Visual Studio Code and nothing else to write my code.
import { Hotel } from "./hotels.js"
document.getElementById('createHotel').addEventListener('click', createHotel)
document.getElementById('deleteHotel').addEventListener('click', deleteHotel)
document.getElementById('showHotel').addEventListener('click', showHotel)
document.getElementById('editHotel').addEventListener('click', editHotel)
let myHotelArray = []
function createHotel() {
const hotelName = prompt(`Please enter the name of hotel:`, `W Hotel`)
const numberOfRooms = prompt(`Please enter the number of rooms:`, `68`)
const numberOfFloors = prompt(`Please enter the number of floors:`, `12`)
const totalArea = prompt('Please enter the total area of the hotel:', `250`)
myHotelArray.push(new Hotel(hotelName, numberOfRooms, numberOfFloors, totalArea))
}
function showHotel() {
let hotelsFormated = []
for (let i = 0; i < myHotelArray.length; i++) {
hotelsFormated.push(`${myHotelArray[i].toString()} <br><br>`);
}
document.getElementById('hotels').innerHTML = hotelsFormated.join('')
console.log(myHotelArray)
}
function deleteHotel() {
const selectHotel = prompt(`Please enter the name of the hotel you'd like to delete:`)
const hotelIndex = myHotelArray.findIndex(i => i.hotelName === selectHotel)
if (hotelIndex >= 0) {
myHotelArray.splice(hotelIndex)
}
else {
alert("This hotel couldn't be found. Please try again")
}
function editHotel() {
}
}
As mention in mdn Array.splice can receive 2 arguments:
start: Zero-based index at which to start changing the array (dont
know what the zero-based mean but use the start argument as any
natural Number)
deleteCount: An integer indicating the number of elements in the
array to remove from start.
I think adding deleteCount in your statment like this myHotelArray.splice(hotelIndex, 1) will solve it.
The splice method will remove from the list and return all the items from hotelIndex to hotelIndex+deletCount.

jquery indexOf not finding the names i am trying to block [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
ok so i have an input and am trying to make it so that when a specific name is inputted, it gives an alert and e.off()'s. I do not know why this code wont work. the code is in a function but that is ok, I am just having problems here Thank You. the html input does have an id of #nameInput so we are ok there too.
var name = $('#nameInput').val();
var names = ["john","jon","johnn"];
var a = names.indexOf("john","jon","johnn") > -1;
if (name == a) {
alert('That is the Bosses name silly!');
e.off();
}
The .indexOf() function is not a jQuery thing; it's part of (modern) standard JavaScript. It takes one argument and one optional argument. The first is the thing to search for, and the second optional argument is the starting position for the search (default being index 0).
The function returns a number, as your code seems to expect. However, you then compare the name in the input field to the true/false returned from the comparison following your (incorrect) call to .indexOf(), so it's not surprising that it doesn't do what you expect.
var name = $('#nameInput').val();
var names = ["john","jon","johnn"];
var bad_name = false;
for(var k in names) {
var this_name = names[k];
if( name.indexOf(this_name) > -1 ) {
bad_name = true;
break;
}
}
if(bad_name) {
alert('That is the Bosses name silly!');
e.off();
}
.indexOf was used incorrectly. The object it is called on should be the name string, not the list of names, and it only takes one parameter, so you have to do multiple checks.
Also, the a value would have been a boolean, so you directly check its value, not compare it to name
If all this is in a function, consider having another function outside of it so that you can reuse it later if needed. You need to iterate through the array of names matching your string against the array's items. There are many many ways to do it, but here's an easy one.
function isName(inputName, namesArray) {
var nameFound = false; // Returns false if there's no match
namesArray.forEach(function(name) { // For each name in namesArray
if (inputName === name) {
nameFound = true;
}
});
return nameFound;
}
console.log(isName('john', ['john', 'jon', 'johnn']));
console.log(isName('nobody', ['john', 'jon', 'johnn']));
// You can then have your if statement
if(isName(name, names)) {
alert('That is the Bosses name silly!');
e.off();
}

How do I create a list of quotes in my html from javascript objects? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
*A Jsfiddle would be appreciated, thanks!
This is a sample of what I've been given in a js document:
var comments = [
{"name":"John","comment":"Text","timestamp":69379200},
{"name":"Ronny","comment":"Text","timestamp":1007683200},
{"name":"Darrel","comment":"Text","timestamp":172281600}
];
How do I load that into my preexisting unordered list as list items? Ideally in this sort of a format (including turning the unix timestamps into this format):
<ul class="testimonials">
<li>
<blockquote>"Text"</blockquote>
<cite>-John, 8/23/2014</cite>
</li>
<li>
<blockquote>"Text"</blockquote>
<cite>-Ronny, 8/23/2014</cite>
</li>
<li>
<blockquote>"Text"</blockquote>
<cite>-Darrel, 8/23/2014</cite>
</li>
</ul>
I'm new to loading javascript into my html, so if anyone can help me out and explain, I'd really appreciate it! Thanks!
Try something like this:
// the parent element
var ulElement = document.createElement("ul");
ulElement.setAttribute("class", "testimonials");
// iterate through the array
for ( var i = 0 ; i < comments.length ; i++ ) {
// extract data from JavaScript
var currentObj = comments[i];
var currentName = currentObj.name;
var currentComment = currentObj.comment;
var currentTimestamp = currentObj.timestamp;
// create child nodes for the parent
var liElement = document.createElement("li");
// blockquote
var blockquoteElement = document.createElement("blockquote");
var t1 = document.createTextNode(currentComment);
blockquoteElement.appendChild(t1);
// cite
var citeElement = document.createElement("cite");
var d = new Date(currentTimestamp*1000);
var formattedDate = d.getMonth()+ "/" + d.getDate() + "/" + d.getFullYear()
var t2 = document.createTextNode(currentName + ", " + formattedDate);
citeElement.appendChild(t2);
// add children for li
liElement.appendChild(blockquoteElement);
liElement.appendChild(citeElement);
// add child nodes to parent
ulElement.appendChild(liElement);
}
Here you can see a fiddle
Here is something to get you started:
var comments = [
{"name":"John","comment":"Text","timestamp":69379200},
{"name":"Ronny","comment":"Text2","timestamp":1007683200},
{"name":"Darrel","comment":"Text3","timestamp":172281600}
];
var feed = document.getElementById('feed'); // get our UL element
var output = ""; // define output string variable
for (var i = 0; i < comments.length; i++) { // start the loop
output += '<li><blockquote>' + //
comments[i].comment + // build the output
'</blockquote><cite>-' + // on each iteration
comments[i].name + ', ' + // and append it
comments[i].timestamp + // to its previous value
'</cite></li>'; //
}
feed.innerHTML = output; // after the loop is done,
// set the contents of our UL
// element to the output we just built
See it in action here: http://jsfiddle.net/4aoh682q/1/
(note: I didn't convert the timestamp into formatted date)
The simplest way is to use some templating framework like Mustache or even the simple mechanism Underscore.js uses and be done with it.
One big problem with Shomz's answer (as of this writing) is it doesn't handle html injection issues.
The answer from curiosu would seem to handle that from first reading but it could possibly be better; it's better to minimize interaction with the DOM to avoid causing issues with the rendering engine. His doesn't necessarily do this―it is likely only a problem if the ul element has already been added. But see how verbose this DOM code is? Creating elements using the DOM apis can be quite useful, but writing the code is so tedious!
If you only need this functionality to create lists, it would actually be better not to use the templating framework as that code is just extra crap to bog down the page, but if you are using more than one list thing and you need extra flexibility to quickly modify what classes elements need, etc, it is hard to beat the usefulness of a templating framework.
Edit:
I will add that it's not hard to fix the encoding issues in Shomz's answer, and performance issues, if there are any, could be fixed by using an array, and joining afterwards.
Just add a proper htmlEncode
function htmlEncode( html ) {
return document.createElement( 'a' ).appendChild(
document.createTextNode( html ) ).parentNode.innerHTML;
}
and then
var feed = document.getElementById('feed'); // get our UL element
var output = []; // define output string variable
for (var i = 0; i < comments.length; i++) { // start the loop
output.push('<li><blockquote>' + //
htmlEncode(comments[i].comment) + // build the output
'</blockquote><cite>-' + // on each iteration
htmlEncode(comments[i].name) + ', ' + // and append it
comments[i].timestamp + // to its previous value
'</cite></li>'); //
}
feed.innerHTML = output.join(""); // after the loop is done,
// set the contents of our UL
// element to the output we just built
http://jsfiddle.net/4aoh682q/6/

Does my javascript contain repetitive code that can be reduced? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I feel like there is too much repetitive code going on here. All I am doing is doing a basic regex match for a string in the URL. If a match is found, I find an li with a class (.index, .grid, .type) and add the active class. This is just for my main nav in an attempt to make it some what dynamic. However, I feel like there is a more efficient way to code this. Any help is greatly appreciated.
$( document ).ready(function() {
var myLocation = window.location;
var convertURL = new String(myLocation);
var index = /index/i;
var grid = /grid/i;
var type = /type/i;
var urlIndex = convertURL.match(index);
var urlGrid = convertURL.match(grid);
var urlType = convertURL.match(type);
if(urlIndex) {
$('.index').addClass('active');
}else if(urlGrid) {
$('.grid').addClass('active');
}else if(urlType) {
$('.type').addClass('active');
}
});
$(function(){
["index", "grid", "type"].forEach(function(term){
if(new RegExp(term, "i").test(location.href))
$("." + term).addClass("active");
});
});
$(document).ready(function () {
// use single var per function, good for minimizing and other stuff
var
i,
// new string literal, not String object
convertURL = '' + window.location,
// the array of strings keeps only the difference from the repetitive code
classes = ['index', 'grid', 'type'],
// using functions with proper arguments reduces repetitivness
matches = function (regex) {
return convertURL.match(new RegExp(regex, 'i'));
}
// var
;
// always use += instead of ++ -> makes for clear intention
for (i = 0; i < classes.length; i += 1) {
if (matches(classes[i])) {
// returning out of this function stops iteration
return $('.' + classes[i]).addClass('active');
}
}
});

Grab airport name based on airport code from json data [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Working on a flight booking website. Have a json file which contains the airport codes, city name and country name.
[{"iata":"UTK","lon":"169.86667","iso":"MH","status":1,"name":"Utirik Airport","continent":"OC","type":"airport","lat":"11.233333","size":"small"}]
Now if my iata airport code matches to UTK i want to return the name.
Use filter() to find the object within the Array by its iata:
var arr = [{"iata":"UTK","lon":"169.86667","iso":"MH","status":1,"name":"Utirik Airport","continent":"OC","type":"airport","lat":"11.233333","size":"small"}];
function findByCode(arr, iata){
var filtered = arr.filter(function(e){return e.iata = iata});
return (filtered.length == 1) ? filtered[0]:undefined;
}
console.log(findByCode(arr,"UTK").name);
JS Fiddle: http://jsfiddle.net/dE9nP/
$string = '[{"iata":"UTK","lon":"169.86667","iso":"MH","status":1,"name":"Utirik Airport","continent":"OC","type":"airport","lat":"11.233333","size":"small"}]';
$data = json_decode($string);
echo count($data);
for($i=0;$i<count($data);$i++){
if($data[$i]->iata == 'UTK') echo $data[$i]->name;
}
you can use file_get_contents if the data in a file instead of $string;
This is basic searching! You need to loop over the array, and check each item for the matching code, then return the result. Here is a function:
function findAirport(myArray, iata){
for(var i = 0; i < myArray.length; i++){
var item = myArray[i];
if(item["iata"] === iata){
return item;
}
}
return null;
}
You can use that function like so:
var airports = [{"iata":"UTK","lon":"169.86667","iso":"MH","status":1,"name":"Utirik Airport","continent":"OC","type":"airport","lat":"11.233333","size":"small"}];
var match = findAirport(airports, "UTK");
if(match){
console.log("name = " + match.name);
}
Just to highlight my preference to using simple for loops over other functions such as filter, here is a performance test comparing my answer to the other one that uses filter. I know it's meaningless in most real use cases, but I wanted to keep a reference to the jsperf link :)
NOTE: This answer was provided before the question tags were edited. At the time of posting this question was asking for a javascript solution

Categories

Resources