Javascript snipet error in render function in a react application - '}' expected - javascript

I am writing a simple react code that has a certain portion of javascript which is throwing me an error
var React = require('react');
var Link = require('react-router').Link;
var openColumnAnalysis = React.createClass({
render: function(){
return(
<body>
<div>
<Link to={"/"}>Reports Home</Link>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for Reports.."></input>
<ul id="myUL">
<li>
Map Report
</li>
<li>
Customer Report
</li>
</ul>
</div>
<script>
function myFunction()
{
// document.write("Hi")
filter = document.getElementById('myInput').value
li_tag = document.getElementById('myUL').getElementsByTagName('li')
for (i = 0; i < li_tag.length; i++)
{
a_tag = li_tag[i].getElementsByTagName('a')[0];
if (a_tag.innerHTML.toUpperCase().indexOf(filter) > -1)
{
li_tag[i].style.display = "";
}
else
{
li_tag[i].style.display = "none";
}
}
}
</script>
</body>
);
}
});
module.exports = openColumnAnalysis;
the 'document.write("Hi")' statement works perfectly. But even if I just write 'var inp;' and nothing else.. I start getting an error like '} expected'!
I don't understand where this is going wrong... I am following this link : https://www.w3schools.com/howto/howto_js_filter_lists.asp for this learning.
Edit: Pasting my code as ref as asked.. :) If I remove the script tag, then the code runs fine... but I am trying to filter the li tags here based on search input..
Thanking you in advance!

Thank you for your help, but I got an answer here. For some reason I am not sure script tags are not working when defined inside the return statement of any react function. So I created another function to perform the filtering and called the same in the render function as below:
filterRepo: function(){
return(
function myFunction() {
var filter = document.getElementById('myInput').value.toUpperCase();
var li = document.getElementById("myUL").getElementsByTagName('li');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
);
},
render: function(){
var repoLink = this.state.repoLinks;
repoLink = repoLink.map(function(item, index){
return(
<OpenReport key={index} desc={item.description} );
}.bind(this));
return(
<div id="inside_repoInfo">
<br></br>
<input type="text" id="myInput" onKeyUp={this.filterRepo()} placeholder="Search for Report.."></input>
<ul id="myUL" >{repoLink}</ul>
</div>
);
}
The rest of the code if only to display the list tag which I have defined in OpenReport component.
Hope this helps others!

Related

How to delete a DOM element from an array after you've clicked on it?

I was making a simple to-do list. You submit itens from an input and they go to the To-DO section. When you click over them they go to the 'Done' section. And when you click on them again, they vanish forever. It was all working fine.
But I realized the doneItens array kept growing in length, which I wanted to optimize. So I came up with this line of code
doneItens.splice(i, 1);
which goes inside an onclick event, which you can see in the code inside the deleteDone function.
That gives the error, though,
Error:{
"message": "Uncaught TypeError: doneItens.splice is not a function"
If I put it outside and below the onclick event it also doesn't work. How can I do it?
var input = document.getElementById('play');
var toDo = document.getElementsByTagName('ol')[0];
var done = document.getElementById('done');
function handleSubmit(event) {
event.preventDefault();
const newItem = document.createElement('li');
newItem.setAttribute('class', 'item');
newItem.append(input.value);
toDo.append(newItem);
input.value='';
deleteItem();
}
function deleteItem() {
const toBeDone = document.getElementsByClassName('item');
for(let i = 0; i < toBeDone.length; i++) {
toBeDone[i].onclick = () => {
appendItemDone(toBeDone[i]);
toBeDone[i].style.display = 'none';
deleteDone();
}
}
}
function appendItemDone(item) {
const newDone = document.createElement('li');
newDone.setAttribute('class', 'feito')
newDone.append(item.innerText);
done.append(newDone);
}
function deleteDone() {
const doneItens = document.getElementsByClassName('feito');
console.log('done length', doneItens.length)
for (let i = 0; i < doneItens.length; i++) {
doneItens[i].onclick = () => {
doneItens[i].style.display = 'none';
doneItens.splice(i, 1);
}
}
}
<div id='flex'>
<form class='form' onsubmit='handleSubmit(event)'>
<input placeholder='New item' type='text' id='play'>
<button>Send</button>
</form>
<div id='left'>
<h1 id='todo' >To-do:</h1>
<p class='instruction'><i>(Click over to mark as done)</i></p>
<ol id='here'></ol>
</div>
<div id='right'>
<h1>Done:</h1>
<p class='instruction'><i>(Click over to delete it)</i></p>
<p id='placeholder'></p>
<ol id='done'></ol>
</div>
</div>
With the use of JavaScript DOM API such as Node.removeChild(), Element.remove() and Node.parentNode, your task can be solved with this code:
const input = document.getElementById('play');
const todo = document.getElementById('todo');
const done = document.getElementById('done');
function handleSubmit(event) {
event.preventDefault();
// create new "todo" item
const newTodo = document.createElement('li');
newTodo.textContent = input.value;
todo.append(newTodo);
// clean the input field
input.value = '';
// listen to "click" event on the created item to move it to "done" section
newTodo.addEventListener('click', moveToDone);
}
function moveToDone(event) {
// remove "click"-listener to prevent event listener leaks
event.target.removeEventListener('click', moveToDone);
// move clicked todo-element to "done" section
const newDone = event.target.parentNode.removeChild(event.target);
done.append(newDone);
// listen to "click" event on the moved item to then completely delete it
newDone.addEventListener('click', removeFromDone);
debugElementsLeak();
}
function removeFromDone(event) {
// remove "click"-listener to prevent event listener leaks
event.target.removeEventListener('click', removeFromDone);
// complete remove clicked element from the DOM
event.target.remove();
debugElementsLeak();
}
function debugElementsLeak() {
const todoCount = todo.childElementCount;
const doneCount = done.childElementCount;
console.log({ todoCount, doneCount });
}
<div id="flex">
<form class="form" onsubmit="handleSubmit(event)">
<input placeholder="New item" type="text" id="play">
<button>Add item</button>
</form>
<div id="left">
<h1>To-do:</h1>
<p class="instruction"><em>(Click over to mark as done)</em></p>
<ol id="todo"></ol>
</div>
<div id="right">
<h1>Done:</h1>
<p class="instruction"><em>(Click over to delete it)</em></p>
<p id="placeholder"></p>
<ol id="done"></ol>
</div>
</div>
You'll want to use splice,
and then rather than use hidden, 'refresh' the done element by adding all elements in the spliced array.
I've commented my code where I've made changes and why
var input = document.getElementById('play');
var toDo = document.getElementsByTagName('ol')[0];
var done = document.getElementById('done');
function handleSubmit(event) {
event.preventDefault();
const newItem = document.createElement('li');
newItem.setAttribute('class', 'item');
newItem.append(input.value);
toDo.append(newItem);
input.value='';
deleteItem();
}
function deleteItem() {
const toBeDone = document.getElementsByClassName('item');
for(let i = 0; i < toBeDone.length; i++) {
toBeDone[i].onclick = () => {
appendItemDone(toBeDone[i].cloneNode(true));
toBeDone[i].style.display = 'none';
deleteDone();
}
}
}
function appendItemDone(item) {
const newDone = document.createElement('li');
newDone.setAttribute('class', 'feito')
newDone.append(item.innerText);
done.append(newDone);
}
function deleteDone() {
var doneItens = document.getElementsByClassName('feito');
for (let i = 0; i < doneItens.length; i++) {
doneItens[i].onclick = () => {
var splicedArray = spliceFromArray(doneItens,doneItens[i]);// NEW BIT -CALL NEW SPLICE FUNCTION
done.innerHTML=""; // NEW BIT - SET OVERALL DONE TO BLANK ON DELETE
for(var index in splicedArray){// NEW BIT - fOR EACH RETURNED ELEMENT IN THE SPLICE, ADD IT TO THE OVERALL DONE ELEMENT
done.appendChild(splicedArray[index]);
}
}
}
}
function spliceFromArray(arrayInput,element){// NEW BIT - SPLICE FUNCTION THAT RETURNS SPLICED ARRAY
var array = Array.from(arrayInput);
var index = array.indexOf(element);
if(index!=-1){
if(array.length==1 && index == 0){
array = [];
}
else{
array.splice(index,1);
}
}
return array;
}
<div id='flex'>
<form class='form' onsubmit='handleSubmit(event)'>
<input placeholder='New item' type='text' id='play'>
<button>Send</button>
</form>
<div id='left'>
<h1 id='todo' >To-do:</h1>
<p class='instruction'><i>(Click over to mark as done)</i></p>
<ol id='here'></ol>
</div>
<div id='right'>
<h1>Done:</h1>
<p class='instruction'><i>(Click over to delete it)</i></p>
<p id='placeholder'></p>
<ol id='done'></ol>
</div>
</div>

Can't filter search

I've been trying to get my search filter to work but can't get it to work. I'm a beginner but trying my best to make it work. Anyone out there that can help :)
The html
<div class="notes_search">
<input type="search" id="search_input" onkeyup="searchFilter()" placeholder="Search...">
</div>
<ul class="notes_list">
</ul>
<p class="notes_empty-msg">Nothing to show.</p>
</section>
</div>
The Script down bellow.
function searchFilter() {
// Declare variables
var input, filter, ul, li, a, i;
input = document.getElementsById('search');
filter = input.value.toUpperCase();
ul = document.getElementsById('search')[0];
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter)===0) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
There are a number of issues with your code.
First, it's getElementById not getElementsById, but you might find using querySelector and querySelectorAll easier to use as they match to CSS selectors (similar to jQuery).
Second, you don't have an element with a search id.
Third, your HTML contains no list items so it can't search for anything.
Here's a working version with annotations (using some more modern JS methods with which you might not be familiar but which can make the code more succinct). Note: it uses a class to make the items visible or not, and searches within the text content rather than just checking to see if it's at the start of the content which makes it a little more flexible.
function searchFilter() {
// You might find `querySelector` easier to use as it
// allows you to correspond elements with CSS selectors
const input = document.querySelector('#search');
const filter = input.value.toUpperCase();
const ul = document.querySelector('ul');
const lis = ul.getElementsByTagName("li");
for (i = 0; i < lis.length; i++) {
const item = lis[i];
const itemContent = item.textContent.toUpperCase();
// `textContent` might be more appropriate here
// You can use the newer string method `includes`
// to see if `filter` appears in the text content
if (filter.length && itemContent.includes(filter)) {
// Here I've used `classList` as the more modern
// method way of adding and removing classes
item.classList.add('visible');
} else {
item.classList.remove('visible');
}
}
}
li { display: none; }
.visible { display: block }
<div class="notes_search">
<input type="search" id="search" onkeyup="searchFilter()" placeholder="Search...">
</div>
<ul class="notes_list">
<li>Bob</li>
<li>Sue</li>
<li>Rita</li>
<li>Rita and Bob</li>
<li>John</li>
</ul>
<p class="notes_empty-msg">Nothing to show.</p>
</div>
Further reading
classList
String.includes
textContent
You have several things here that are incorrect:
It should be getElementById rather than getElementsById (not plural)
Your input element has the id of "search_input", but you're trying to find an element with the name "search". When looking for an element, it should be the exact name of id, and not a partial word containing it. So try input=document.getElementById('search_input');
Try using innerText rather than innerHtml: innerHtml returns in html format rather than plain text as I remember.
index.html
<div class="notes_search">
<input type="search" id="search_input" onkeyup="searchFilter()" placeholder="Search...">
</div>
<ul class="notes_list">
<li>hi</li>
<li>hi</li>
<li>bye</li>
</ul>
<p class="notes_empty-msg">Nothing to show.</p>
</section>
</div>
index.js
function searchFilter() {
// Declare variables
var input, filter, ul, li, a, i, text;
input = document.getElementById('search_input');
filter = input.value.toUpperCase();
ul = document.getElementsByClassName('notes_list')[0];
li = ul.getElementsByTagName("li");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("a")[0];
text = a.textContent || a.innerText;
if (a.innerHTML.toUpperCase().indexOf(filter)===0) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
I also added some li and a tag items to your html, since you didn't have them and it can't find tags that isn't on the html.
I am not fully sure what you are trying to achieve but would a simple html datalist work for your problem:
<input list="your-choices" id="search_input" placeholder="Search...">
<datalist id="your-choices">
<option value="car">
<option value="tree">
<option value="street">
<option value="sky">
<option value="whatever">
</datalist>
You Can search by Jquery
var searchRequest = null;
$(function () {
var minlength = 3;
$("#sample_search").keyup(function () {
var that = this,
value = $(this).val();
if (value.length >= minlength ) {
if (searchRequest != null)
searchRequest.abort();
searchRequest = $.ajax({
type: "GET",
url: "sample.php",
data: {
'search_keyword' : value
},
dataType: "text",
success: function(msg){
//we need to check if the value is the same
if (value==$(that).val()) {
//Receiving the result of search here
}
}
});
}
});
});

Filter/Search bar (list of <a> elements) - not working

I am trying to use this example by w3schools to add a search bar. I can't get it to work, I have changed it to match my elements but with no success. I have to have my js separate from the HTML document so no <script>
My issue is that It does not work, and I do not know how to debug it.
Here is my js file:
//search bar
function myFunction() {
// Declare variables
var input, filter, ul, div, li, a, span, i;
input = document.getElementById('myInput');
filter = input.value.toUpperCase();
ul = document.getElementById("container");
span = ul.getElementsByTagName('span');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = span[i].getElementsByTagName("a")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
span[i].style.display = "";
} else {
span[i].style.display = "none";
}
}
}
document.getElementById('myInput').addEventListener('keyup', myFunction);
And my HTML file
<div class="container">
<input type="text" id="myInput" placeholder="Search for names..">
<div id="container">
<span>Nico Nico Nii!!</span>
<span>Childish Gambino - Redbone</span>
<span>America F*ck Yeah!</span>
</div>
</div>
Firstly, you have a lot of unnecessary variables. You only need two, one to get the values of the list and the other to get value of filter. If there are more than one element, use class instead. See the working code below:
//search bar
function myFunction() {
var input, filter;
input = document.getElementsByClassName('myLinks');
filter = document.getElementById('myInput').value.toUpperCase();
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < input.length; i++) {
var currentElem = input[i];
var currentElemChild = input[i].children[0]
if (currentElemChild.innerHTML.toUpperCase().indexOf(filter) > -1) {
currentElem.style.display = "";
} else {
currentElem.style.display = "none";
}
}
}
document.getElementById('myInput').addEventListener('keyup', myFunction);
<div>
<input type="text" id="myInput" placeholder="Search for names..">
<ul id="container">
<li class="myLinks">Nico Nico Nii!!</li>
<li class="myLinks">Childish Gambino - Redbone</li>
<li class="myLinks">America F*ck Yeah!</li>
</ul>
</div>

JavaScript Live search through containers

I am working on some line in JS to do a live search. I have been trying to modify this https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_filter_list
to do what I am looking for, how ever I cant seem to understand what I am doing wrong. any pointers or corrections are greatly appreciated.
JS it should hide any twit that does not contain the search
var navbarSearchbutton = document.getElementById('navbar-search-button')[0];
navbarSearchbutton.addEventListener('onkeyup', function() {
searchFunction();
});
function searchFunction() {
var input, filter, ul, li, a, i, foo;
foo = document.getElementsByClassName("twit");
input = document.getElementById("navbar-search-input");
filter = input.value.toUpperCase();
li = document.getElementsByClassName("twit-text");
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("P")[0];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
foo[i].style.display = "none";
}
}
}
HTML for the search box and what I am searching.
<li class="navitem navbar-search">
<input type="text" id="navbar-search-input" placeholder="Search...">
<button type="button" id="navbar-search-button"><i class="fa fa-search"></i></button>
</li>
</ul>
</nav>
</header>
<main class="twit-container">
<article class="twit">
<div class="twit-icon">
<i class="fa fa-bullhorn"></i>
</div>
<div class="twit-content">
<p class="twit-text">
A body in motion must remain in motion unless acted upon by an outside force.
</p>
<p class="twit-attribution">
NewtonRulez
</p>
</div>
First, you are getting ('navbar-search-button by id. So, it will not return an id.
Second, the logic of searching by class name will not work. Below is an updated search function. I kept the same logic you are following to search for items by class names. You will need to to set the class name as twit-attribution for any new entry.
function searchFunction() {
var input, filter, ul, li, a, i, foo;
foo = document.getElementsByClassName("twit");
input = document.getElementById("navbar-search-input");
filter = input.value.toUpperCase();
li = document.getElementsByClassName("twit-attribution");
for (i = 0; i < li.length; i++) {
a = li[i];
if (a.innerHTML.toUpperCase().indexOf(filter) > -1) {
a.style.display = "";
} else {
a.style.display = "none";
}
}
}

Remove checked checkboxes

I am making a To-do list, where I want to be able to add new tasks, and delete tasks that are checked off. However, it seems my function just deletes all tasks, not just the ones that are checked off. Neither does it seem to allow new tasks to be added.
html:
<h1 id="title"> To-do list</h1>
<div id="task_area">
</div>
<input type="text" id="putin"></input>
<button id="add">add</button>
javascript:
<button id="clear">Clear completed tasks</button>
var tasks = document.getElementById("task_area")
var new_task = document.getElementById("add")
var clear = document.getElementById("clear")
new_task.addEventListener("click", function() {
var putin = document.getElementById("putin")
var input = document.createElement('input')
input.type = "checkbox"
var label = document.createElement('label')
label.appendChild(document.createTextNode(putin.value))
task_area.appendChild(input)
task_area.appendChild(label)
})
clear.addEventListener("click", function() {
for (i = 0; i < task_area.children.length; i++) {
if (task_area.children[i].checked === true) {
task_area.remove(tasks.children[i])
}
}
})
jsfiddle: https://jsfiddle.net/4coxL3um/
.remove removes the element you are calling it from, and doesn't take an argument for what to remove. The following:
task_area.remove(tasks.children[i])
should be
tasks.children[i].remove()
EDIT: As Mononess commented below, this will only remove the checkboxes and not the labels. While you could delete both using Jayesh Goyani's answer below, it's probably better that each input/label pair be wrapped in a single div or span for easier management.
You could try adding an event listener to each child of task_area that calls the below function. Haven't gotten a chance to test it out, and may not fulfill all of your requirements, but should get the job done.
function removeClicked() {
this.parentNode.removeChild(this);
}
Please try with the below code snippet. Below code will help you to remove selected checkbox with label.
<body>
<h1 id="title">To-do list</h1>
<div id="task_area">
</div>
<input type="text" id="putin" />
<button id="add">add</button>
<button id="clear">Clear completed tasks</button>
<script>
var tasks = document.getElementById("task_area")
var new_task = document.getElementById("add")
var clear = document.getElementById("clear")
new_task.addEventListener("click", function () {
var putin = document.getElementById("putin")
var input = document.createElement('input')
input.type = "checkbox"
var label = document.createElement('label')
label.appendChild(document.createTextNode(putin.value))
task_area.appendChild(input)
task_area.appendChild(label)
//document.getElementById("task_area").innerHTML = putin.value
})
clear.addEventListener("click", function () {
for (i = 0; i < task_area.children.length; i++) {
if (task_area.children[i].checked === true) {
tasks.children[i].nextSibling.remove();
tasks.children[i].remove();
}
}
})
</script>
</body>
Please let me know if any concern.

Categories

Resources