I am able to search and display the results that the user is typing on the keyup function. But now when the results show up inside my <div> tag, they are not clickable. Is there a way I can make them clickable and also allow the user to select multiple results from the live search results. This is what I tried so far.
HTML
<input type="text" id ="medication" name="medication" onkeyup="getsearch(this.value)"><br>
<div id="livesearch"></div>
JavaScript
function getsearch(val) {
results = [];
document.getElementById("livesearch").innerHTML = "";
if (val.length == 0) {
document.getElementById("livesearch").innerHTML = "";
document.getElementById("livesearch").style.border = "0px";
return;
}
console.log(s);
console.log("val", val);
if (val.length > 2) {
for (var i = 0; i < s.length; i++) {
for (key in s[i]) {
if (s[i][key].indexOf(val) != -1) {
$("#livesearch").append(s[i][key]);
$("#livesearch").append("<br/>");
results.push(s[i]);
}
}
}
}
console.log(results);
};
There are some other thing I would do differently here, but as far as what you are looking to do this should work.
if(val.length>2) {
for (var i = 0; i < s.length; i++) {
for (key in s[i]) {
if (s[i][key].indexOf(val) != -1) {
var newDom = $('<div><\div>'); //create a DOM element to wrap each of the return text in.
newDom.text(s[i][key]);
$("#livesearch").append(newDom);
results.push(s[i]);
}
}
}
}
Then you can assign the click event to you dynamically created DOM this way.
$('#livesearch').on('click', 'div', myDoStuffFunc);
function myDoStuffFunc(){
// this is fired from the click event
}
Related
I need to hide a <section> in my HTML with JavaScript while highlighting the text or to show it otherwise.
My selection works in this way:
document.addEventListener('click', function(){
var selected = window.getSelection();
var links = document.getElementsByClassName("linkAnnotation");
if (selected == '') {
links.setAttribute('style', 'display:block;');
} else {
links.setAttribute('style', 'display:none;');
}
})
but this setAttribute does not work as other hundreds of tries that I have done.
Can someone save my life??
Every setAttribute, style.innerHTML, etc.
when you are selecting links it retuns HTMLCollection forExample : [linkAnnotation1, linkAnnotation2] it not returns one element because your code doesnot works you must write for loop example:
document.addEventListener('click', function () {
var selected = window.getSelection();
var links = document.getElementsByClassName('linkAnnotation')
if (selected == '') {
for (let i = 0; i <= links.length - 1; i++) {
links[i].setAttribute('style', 'display:block')
}
}else {
for(let i = 0; i <= links.length - 1; i++) {
links[i].setAttribute('style', 'display:none')
}
}
})
getElementsByClassName returns a HTMLCollection (Which returns an array-like object of all child elements which have all of the given class name(s)). You have to iterate through all of those elements and change properties.
So, you have to use the following code:
document.addEventListener('click', function() {
var selected = window.getSelection();
var links = document.getElementsByClassName("linkAnnotation");
if (selected === '') {
links.forEach(val => { val.setAttribute('style', 'display:block;'); });
} else {
links.forEach(val => { val.setAttribute('style', 'display:none;'); });
}
})
I wanted to hide Optionset values on Field Service - Dynamics 365 app. We are doing customizations using Woodford Solution. Based on Resco Javascript Bridge Reference, I see no methods to hide options in existing Option Set. So I created a ComboBox and tried to add Options into ComboBox. But it is showing only one single option even if I add multiple options that too with the wrong Label on ComboBox.
if ((responseTypeOptionSetValues.length == responseTypeOptionSetLables.length)
&& responseTypeOptionSetLables.length > 0) {
for (i = 0; i < responseTypeOptionSetValues.length; i++) {
if (valueListOptions.length > 0) {
for (i = 0; i < responseTypeOptionSetValues.length; i++) {
if (valueListOptions.indexOf(responseTypeOptionSetValues[i].toString()) != -1) {
finalLabelValue = responseTypeOptionSetLables[i].toString();
finalOptionValue = responseTypeOptionSetValues[i].toString();
comboItem.listDataSource = {
**finalLabelValue: finalOptionValue,**
};
}
}
}
}
}
var data = new Object();
if ((responseTypeOptionSetValues.length == responseTypeOptionSetLables.length) && responseTypeOptionSetLables.length > 0) {
for (i = 0; i < responseTypeOptionSetValues.length; i++) {
if (valueListOptions.indexOf(responseTypeOptionSetValues[i].toString()) != -1) {
finalLabelValue = responseTypeOptionSetLables[i].toString();
finalOptionValue = responseTypeOptionSetValues[i].toString();
data[finalLabelValue] = finalOptionValue;
}
}
}
if (!isComboItemExists) {
comboItem.listDataSource = data;
detailView.insertItem(comboItem, -1);
}
else {
comboItem.listDataSource = data;
}
You're nesting your loops with the same variable name. Give each loop a unique variable: i, j, k...
I have been trying to make a very simple search engine for a school project, but I can't figure out how to compare the user input I receive (a string from an input-textbox) to data I have in an array (A NodeList object with a bunch of names).
I will elaborate a little bit on exactly what I want to achieve: I have a HTML page which contains a input form and a bunch of movie titles (in format) and I want to compare what the user types in the input form to the movie titles that are on the page. If the user input matches one of the movie titles I want that movies' highlighted, and if the input doesn't match any movies, I just want an alert box to pop up saying that the input didn't match any movies.
I have been trying to do it like this:
var All_Titles = document.getElementsByTagName("h3");
var User_Input = document.forms["search_form"];
function InputValidation() {
var x = document.forms["search_form"]["input_box"].value;
if (x == "" || x == null) {
alert("You haven't entered anything");
} else {
Search();
}
}
function Search() {
if (User_Input == All_Titles) {
document.writeln("It worked!");
} else {
alert("No matched movies");
}
}
As you can see, I first capture the user input in a var called "User_Input", and I do the same with the movie titles.
Then, I check if the user has actually any text into the search form; if they didn't, they receive an error message and if they did, I run the Search() function, which is defined below.
Here comes the tricky part: I don't really know how I can compare the user input to the 's that I have! I have tried it with an If-Statement as you can see, but that doesn't seem to work.
Can anyone assist me with this problem?
I prefer using jQuery witch allows to do the same with less coding.
using jQuery:
<script type="text/javascript">
function search() {
var flag = false;
movieName = $("#movieSearch").val();
$(".moviesList").children("h3").each(function(index) {
if (movieName === $(this).html()) {
$(this).css("background-color", "yellow");
flag = true;
} else {
$(this).css("background-color", "white");
}
});
if(flag == false) {
alert("no such movie was found");
}
}
</script>
same code but only JS (less readable and maintainable):
<script type="text/javascript">
function search() {
var flag = false;
movieName = document.getElementById("movieSearch").value;
movies = document.getElementsByTagName("h3");
for (var i = 0; i < movies.length; i++) {
if (movieName === movies[i].innerHTML) {
movies[i].style.backgroundColor = "yellow";
flag = true;
} else {
movies[i].style.backgroundColor = "white";
}
}
if(flag == false) {
alert("no such movie was found");
}
}
</script>
HTML:
<div class="moviesList">
<h3>HHH</h3>
<h3>mmm</h3>
<h3>123</h3>
</div>
<input type="text" id="movieSearch" />
<button onclick="search()">Search By Name</button>
jQuery is a very common js library. use it by simply adding:
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
You may try this example
var search = function() {
var movie = document.getElementById("movie").value;
if(!movie.replace(/\s+/g,'')) {//remove blank spaces
alert('Movie name required !');
return;
}
movie = movie.toUpperCase();
var list = document.getElementById('movieList');
list = list.getElementsByTagName('li');//movie title list
var i = list.length, html, flag = false, matches = [];
while(i --) {//walk through the list
html = list[i].innerHTML.toUpperCase();//get the movie in the li
if(-1 !== html.indexOf(movie)){//-1, string not found
flag = true;
matches.push(html);
}
}
if(!flag) {
alert('No match found !');
} else {
alert('Matched: ' + matches.join(', '));//show matching movies csv
}
};
<ul id="movieList">
<li>Star Wars</li>
<li>X-Men</li>
<li>MIB</li>
</ul>
<p>
Search <input type="text" id="movie"/><input type="button" onclick="search()" value="Search"/>
</p>
Use a loop to iterate through all the titles, comparing each with the user input
function Search() {
User_Input = User_Input.trim();
var i, len, title;
len = All_Titles.length;
for(i = 0; i < len; i++){
title = All_Titles[i].innerHTML.trim();
if(User_Input === title){
document.writeln("It worked!");
return;
}
}
if(i === len){
alert("No matched movies");
}
}
Here is my solution
function Search()
{
if (All_Titles.indexOf(User_Input)>-1)
{
alert("yes");
}
else
{
alert("No matched movies");
}
}
This solution may work for you.. try it
var arr = [];
for (var i = 0, ref = arr.length = All_Titles.length; i < ref; i++) {
arr[i] = All_Titles[i];
}
function Search()
{
if (arr.indexOf(User_Input)>-1)
{
alert("yes");
}
else
{
alert("not");
}
}
Array.prototype.indexOf = function(elt)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
I'm working on a page that includes a div with contenteditable="true" and I need to extract the text typed by the user as plain text to be later processed by some other javascript code. I then wrote this function:
function extractLines(elem) {
var nodes = elem.childNodes;
var lines = [];
for (i = 0; i < nodes.length; ++i) {
var node = nodes[i];
if (node.nodeType == 3) {
if (node.nodeValue.length > 0) {
lines.push(node.nodeValue);
}
}
if (node.nodeType == 1) {
if (node.nodeName == "BR") {
lines.push("");
}
else {
lines = lines.concat(extractLines(node));
}
}
}
return lines;
}
This takes an element and should return an array of lines. I don't expect it to work for any HTML, but it should be able to process what the browser generates on the div. Currently I'm testing on Chrome only (later I'll expand the idea to other browsers as they format of generated html is different on contenteditable divs).
Given this HTML:
<div id="target">aaa<div><br></div></div>
It correctly produces:
["aaa", ""]
But my problem is when the user insert two consecutive line breaks (EnterEnter). Chrome produces this:
<div id="target">aaa<div><br></div><div><br></div></div>
And my code gets stuck into an infinite loop. Why?
You can try with this:
console.log(extractLines(target));
Note: you might need to force-kill the tab (use Shift+Esc)
Live demo here (click).
var myElem = document.getElementById('myElem');
var myBtn = document.getElementById('myBtn');
myBtn.addEventListener('click', function() {
var results = [];
var children = myElem.childNodes;
for (var i=0; i<children.length; ++i) {
var child = children[i];
if (child.nodeName === '#text') {
results.push(child.textContent);
}
else {
var subChildren = child.childNodes;
for (var j=0; j<subChildren.length; ++j) {
var subChild = subChildren[j];
results.push(subChild.textContent);
}
}
}
console.log(results);
});
Old Answer
How about this? Live demo here (click).
var myElem = document.getElementById('myElem');
var myBtn = document.getElementById('myBtn');
myBtn.addEventListener('click', function() {
var results = [];
var children = myElem.childNodes;
for (var i=0; i<children.length; ++i) {
var text = children[i].textContent;
if (text) { //remove empty lines
results.push(text);
}
}
console.log(results);
});
You can remove that if (text) statement if you want to keep the empty lines.
I'm putting down markers via the Google Maps API based on checkboxes. I want the map to show only markers that are the intersection of all checked checkboxes.
I have function getCheckedBoxes(chkboxName) which will return an array containing the IDs of all checkedBoxes.
Function show displays markers based on whether they have that ID inside of one of their category properties.
function show(category, type) {
var checkedBoxes = getCheckedBoxes("checkbox");
if (checkedBoxes !== null) {
for (var i=0; i<checkedBoxes.length; i++) {
for (var n=0; n<gmarkers.length; n++) {
if (gmarkers[n][category].toUpperCase().indexOf(checkedBoxes[i].toUpperCase()) !== -1) {
gmarkers[n].setVisible(true);
}
}
}
}
// == check the checkbox ==
document.getElementById(type+" box").checked = true;
}
the problem line is obviously if (gmarkers[i][category].toUpperCase().indexOf(checkedBoxes[i].toUpperCase()) !== -1) which will cause the markers to be plot if it is satisfied only once. I need something like Python's all to ensure that 'TRUE' has to appear for every iteration.
Any ideas?
Dr. Molle suggested using every, but I can't seem to think of how it would work. Something like this?
function insideChecked(marker, category) {
var checkedBoxes = getCheckedBoxes("checkbox");
for (var i=0; i<checkedBoxes.length; i++) {
if (marker[category].toUpperCase().indexOf(checkedBoxes[i].toUpperCase()) == -1) {
return false;
}
return true
gmarker.every(insideChecked); ?
I solved it with this, but I would still like to know a better way to solve this issue:
function show(category, type) {
var tracker = 0;
var checkedBoxes = getCheckedBoxes("checkbox");
for (var i=0; i<gmarkers.length; i++) {
if (checkedBoxes !== null) {
for (var n=0; n<checkedBoxes.length; n++) {
if (gmarkers[i][category].toUpperCase().indexOf(checkedBoxes[n].toUpperCase()) !== -1) {
//found a match
tracker+=1;
}
}
}
if (tracker == checkedBoxes.length) {
gmarkers[i].setVisible(true);
tracker = 0;
}
else {
gmarkers[i].setVisible(false);
tracker = 0;
}
}
}