Load parts of page on demand without jquery - javascript

I am completely new to web design and I am experimenting with few things.
Lets assume that I can't use jquety and I can't upload any file to the page, instead I can use simple javascript.
What I have now is a table with few tags, and a javascript function to show based on checkboxes.
Script
<script language="javascript">
function toggleTR(trId) {
var trArray = document.getElementsByTagName("tr");
for(i = 0; i < trArray.length; i++){
if(trArray[i].id == trId){
if(trArray[i].style.display == 'none'){
trArray[i].style.display = '';
}else{
trArray[i].style.display = 'none';
}
}
}
}
</script>
Checkbox
<input type="checkbox" onClick="toggleTR('TR1');"/> TR1
And simple table
<table>
<tr id="TR1" style="display: none;">
<td>content</td>
</tr>
</table>
It works as intended, however as the page gets bigger the load time is horrible.
Is there a way for those tags to be loaded on demand when display attribute is changed? I've read about lazy load, but could not get it to work with this.
Please try to explain it as easy as it could be, as I am totally inexperienced :-)

There can't be lazy load.
Your loop will keep on running till the end. Give a break statement if the id is found., so that the rest of th loop doesn't run.
<script language="javascript">
function toggleTR(trId) {
var trArray = document.getElementsByTagName("tr");
for(i = 0; i < trArray.length; i++){
if(trArray[i].id == trId){
if(trArray[i].style.display == 'none'){
trArray[i].style.display = '';
}else{
trArray[i].style.display = 'none';
}
break;
}
}
}
</script>
OR
You can find the particular element by id and toggle as desired. This would be recommended though.
var trobj = document.getElementById(trId);
if (var != null)
{
// toggle code here
}

As ID should be unique, this should be more optimised
function toggleTR(trId) {
var tr= document.getElementById(trId);
if(tr != null){
if(tr.style.display == 'none'){
tr.style.display = '';
}else{
tr.style.display = 'none';
}
}
}
And if you don't want to hide/show unique element, then you can use classes.
<table>
<tr class="TR1" style="display: none;">
<td>content</td>
</tr>
</table>
and
function toggleTR(trClass) {
var tr= document.querySelectorAll('.'+trClass);
if(tr != null){
for(var i = 0, l = tr.length; i < l ; i++){
if(tr[i].style.display == 'none'){
tr[i].style.display = '';
}else{
tr[i].style.display = 'none';
}
}
}
}

Related

How to add a cell in html table and check for duplicates, without entering the following loop?

Hey guys I am trying to add a new cell in html table and while checking for duplicates in the table. I loop over the table to check for duplicates but I want this alert to only show if there is a duplicate or not? Right now the alert is looping with the each function? It's probably an easy task but I can't handle it. Can someone help me?
$("#btnCheck").on("click", function() {
let company_name = $("#test1").val();
$('#companyTable tr').each(function() {
$(this).find('td').each(function() {
if ($(this).text() === company_name) {
alert("duplicate found");
return false;
} else {
alert("duplicate NOT found");
return false;
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="companyTable">
<thead>
<tr>
<td>Company Name</td>
</tr>
</thead>
<tbody>
<tr>
<td>toyota</td>
</tr>
<tr>
<td>bmw</td>
</tr>
<tr>
<td>suzuki</td>
</tr>
</tbody>
</table>
<input type="text" id="test1" />
<input type="button" id="btnCheck" value="ADD" />
I'm not common to JQuery, but in casual JavaScript this should work :
document.querySelector("#btnCheck").onclick = () => {
const companyName = document.querySelector("#test1").value;
let found = false;
document.querySelectorAll("#companyTable td").forEach(cell => {
if(cell.innerText == companyName){
found = true
}
})
alert("duplicate "+(found ? "" : "NOT ")+" found");
}
You do not need to query rows then cells.
alerting at each cell isn't the right thing to do. You should (as above) store your result (=found), and at the end of the loop only use your result.
Note: Using forEach in this case doesn't seem the most efficient way. You should rather you a casual for loop in order to break it as soon as you find a match :
const cells = document.querySelectorAll("#companyTable td");
found = false;
for(let i = 0; i < cells.length; i++){
if(cells[i].innerText == companyName) {
found = true;
break; // Stop the loop
}
}
In JQuery I would use something like
$("#companyTable tr td:contains('"+textToSearch+"')")
This should return all TD objects inside TR rows of your TABLE id="companyTable" which contains "textToSearch"
Break early from the outer loop, and only alert if it's not found after the loop:
$("#btnCheck").on("click", function () {
let company_name = $("#test1").val();
let found = false;
$('#companyTable tr').each(function () {
$(this).find('td').each(function() {
if ($(this).text() === company_name) {
alert("duplicate found");
found = true;
return false;
}
});
if (found) {
// no need to search through other rows either
return false;
}
});
if (!found) {
alert("duplicate NOT found");
}
});

Search Bar in HTML and JS

I created an HTML table with a lot of information about a country. Now I want the user to be able to search in this table for a piece of information like the Area.
function selectRow() {
var input, filter, table, trs, td;
input = document.getElementById("search");
filter = input.value.toUpperCase();
table = document.getElementById("dataRows");
trs = table.getElementsByTagName("tr");
for (let index = 0; index < trs.length; index++) {
td = trs[index].getElementsByTagName("td")[0];
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
trs[index].display = "";
} else {
trs[index].display = "none";
}
}
}
<input type="text" id="search" onkeyup="selectRow()" placeholder="Search.." />
<table id="dataRows">
<tr>
<th>Attributes</th>
<th>Value</th>
</tr>
<tr>
<td>Name</td>
<td>Australia</td>
</tr>
<tr>
<td>Area</td>
<td>7,741,220.00</td>
</tr>
<tr>
<td>Population</td>
<td>25,466,459</td>
</tr>
</table>
But when I try to use it I get the error: "Uncaught TypeError: Cannot read property 'innerHTML' of undefined"
I can't figure out why the td is undefined.
The most helpful thing to demonstrate first, I think, is a method that will let you diagnose this yourself in future. This sort of difficulty will occur all the time, so here is one method to help you generally problem solve these types of issues.
You know that <td> is not the value you expect, so check your expectation by outputting the values that you use to acquire <td>. You can do that by adding these console.log lines at the top of your loop:
for (let index = 0; index < trs.length; index++) {
console.log("trs[index]",trs[index]);
console.log("trs[index].getElementsByTagName(td)", trs[index].getElementsByTagName("td"));
With that, you should see that the first <tr> has <th> elements, not <td>! These surprises happen all the time, it's great to learn tricks to check your assumptions the quickest way you can.
Here's a very simple solution, the first and last line of this block are the same in your code:
for (let index = 0; index < trs.length; index++) {
var tds = trs[index].getElementsByTagName("td");
if(tds.length == 0) {
continue;
}
td = tds[0];
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
Looks like you've just started working through building this, I hope this helps!
<script>
function myFunction() {
// Declare variables
var input, filter, ul, li, a, i, txtValue;
input = document.getElementById('myInput');
filter = input.value.toUpperCase();
ul = document.getElementById("myUL");
li = ul.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];
txtValue = a.textContent || a.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
</script>
use ur code like this to get best result and without any error
edit
I think the tricky part of this is actually the accepting of user input intelligently. Therefore, I'd say the best thing to do is to pass off your searching to an autocomplete-type plugin. Once the page is ready, you pass the focus to an input text box, and then let the plugin do its magic as you search...
For example, you could use the quicksearch plugin.
Then given a table of data and an input like this:
<input id="searcher" type="text" name="searcher">
You could have a ready function that looks like this:
$('#searcher').quicksearch('table tbody tr', {
'delay': 100,
'bind': 'keyup keydown',
'show': function() {
if ($('#searcher').val() === '') {
return;
}
$(this).addClass('show');
},
'onAfter': function() {
if ($('#searcher').val() === '') {
return;
}
if ($('.show:first').length > 0){
$('html,body').scrollTop($('.show:first').offset().top);
}
},
'hide': function() {
$(this).removeClass('show');
},
'prepareQuery': function(val) {
return new RegExp(val, "i");
},
'testQuery': function(query, txt, _row) {
return query.test(txt);
}
});
$('#searcher').focus();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Try it out here: http://jsfiddle.net/ZLhAd/369/

Get a div inside a td with Javascript

I want to get the text inside the div in the class "atName".
I am looping though the table td's like this:
var searchString = document.getElementById("search").value;
if (searchString !== "") {
var cols = document.querySelectorAll('#theTable td'),
colslen = cols.length,
i = -1;
while (++i < colslen) {
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
Here i want to access the text inside the div
}
Every td is set up like this:
<td id="H" class="element nonmetal gasI">
<div class="atN">1</div>
<div class="atS gas"><a class="gas" href="https://en.wikipedia.org/wiki/Hydrogen" target="_blank">H</a></div>
<div class="atName">Hydrogen</div>
<div class="atW">1.00794</div>
</td>
I want the text inside the "atName" div.
Does anyone know how?
Thanks!
The same way you selected the tds:
cols[i].querySelector('.atName').textContent;
btw. you should give different IDs to your tds or use classes because IDs should be unique
UPDATE
To avoid any confusion, I'm already assuming we're looping the tds (from your code), and this line goes here:
while (++i < colslen) {
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
var divText = cols[i].querySelector('.atName').textContent; // <--- here
}
...
}
You can get the object by class name :
document.getElementsByClassName('atName')
But this return you a list of object with this class.
So you can do in your while:
while (++i < colslen)
{
if (cols[i].id.indexOf(searchString) > -1) {
cols[i].style.opacity = "1"
} else {
var text = cols[i].getElementsByClassName('atName')[0].textContent;
}
}
Maybe this will help?
var searchString = "Hy";
if (searchString !== "") {
var cols = document.querySelectorAll('#theTable tr td .atName');
for (var i=0;i<cols.length;i++)
{
if (cols[i].innerHTML.indexOf(searchString)>-1)
{
alert(cols[i].innerHTML);
}
}
}
What you're looking for is element.innerHTML but hopefully this selector trick will help you too.
Edit: element.textContent is different but you might desire to use it instead.

Onclick action: two functions; only first working. Quite desperate

This is my html code:
<td width="15%" align="center"><input name="submit" type="submit" class="button"
value="Basic" tabindex="13"
onclick="return submit_Click('bxbas','bxsht');" /></td>
And this is my javascript code:
<script type="text/javascript">
function submit_Click(aclass,bclass) {
var elementsa = document.getElementsByClassName(aclass);
for(i in elementsa)
{
elementsa[i].style.display = "block";
}
var elementsb = document.getElementsByClassName(bclass);
for(j in elementsb)
{
elementsb[j].style.display = "none";
}
}
</script>
Unfortunately this is not working. Apparently, only the first part of the function is working, the one that makes the first class (aclass) to be shown. The second one remains visible.
Thank you
Don't use For.. In in this case. If you Console.Log your elementsa you'll see that the last element is a not a number, so it breaks your elementsa[i]. Using "for" solves the problem:
function submit_Click(aclass, bclass) {
var elementsa = document.getElementsByClassName(aclass);
for (i=0; i < elementsa.length; i++) {
elementsa[i].style.display = "block";
}
var elementsb = document.getElementsByClassName(bclass);
for (j=0; j < elementsb.length; j++) {
elementsb[j].style.display = "none";
}
}

Not able to push data into array

I am trying to get to the logic of the Tic Tac Toe game which I almost have made a logic, but I am stuck while pushing the Data to the array. Here is a fiddle that I have created.
http://jsfiddle.net/afzaal_ahmad_zeeshan/6bgjp/1/
Let me explain the whole thing to you!
I am trying to use the 9 td of the table as the 8 rows of the possible win. For that I have given some of the tds a className depending on their location in the table.
The HTML is simple
<div class="vicvacvoe">
<table>
<tr>
<td class="line1 line4 line7"></td>
<td class="line1 line5"></td>
<td class="line1 line6 line8"></td>
</tr>
<tr>
<td class="line2 line4"></td>
<td class="line2 line5 line7 line8"></td>
<td class="line2 line6"></td>
</tr>
<tr>
<td class="line3 line4 line8"></td>
<td class="line3 line5"></td>
<td class="line3 line6 line7"></td>
</tr>
</table>
</div>
Just a simple table with 9 tds, the CSS is not relative to this so leave it I guess.
jQuery for this also simple one. But I am not able to push the data to the Array.
var vic = $('.vicvacvoe table tr td');
var player = 1;
var tick = '✓';
var cross = 'X';
var user1 = [];
var user2 = [];
vic.click(function () {
var className = $(this).attr('class');
if (className != 'dead') {
// A new board place to write on...
// Now do the processes here...
if (player == 1) {
// First player!
var cArray = className.split(' ');
for (i = 0; i < cArray.length; i++) {
for (j = 0; j < user1.length; j++) {
// check for each class
if (user1[j] != cArray[i]) {
user1.push(cArray[i]);
}
}
}
} else {
/* code for second player, the same */
}
$(this).text('Works!');
$(this).attr('class', 'dead');
}
});
This is the entire jQuery script. Actually when I run the code, it really does go to the end of the stack (to the class attribute change script) and it locks the td for further process and it write Works! in the td too. But I am not able to get the classNames inside the Array for that user. I want to save the line number for each user and then check whether he has 3 spots filled or not. I need help with the Array part.
Thanks!
I prefer simplicity so you could use indexOf to check whether the class is already in the users' array like so:
if (player == 1) {
// First player!
var cArray = className.split(' ');
for (i = 0; i < cArray.length; i++) {
if(user1.indexOf(cArray[i]) == -1) {
user1.push(cArray[i]);
} else {
// css class is already in the array
}
}
}
Your issue is here:
for (j = 0; j < user1.length; j++) {
The only place you add to the user1 array is within this loop. Now the array is initially empty, so clearly this loop will never iterate as user1.length is always 0.
I think your intent with this bit of code was to check if the value was already in the array in which case I suggest using $.inArray.

Categories

Resources