Maintaing show hide state of table after table reloads, using setInterval - javascript

What I am trying to achieve is, to have a series of tables built up with PHP (the number of tables is dynamic) this is reloaded every 5 seconds by using setInterval. Then be able to click on one of the tables to show or hide it. Ive got most of this working, but I have gotten stuck on maintaining the state of the tables, be they visible or hidden. Every time the table reloads the table state resets as its returning to its original state (I think a new reference is being passed, actually im almost certain thats whats happening). I tried copying the reference to the divs to a variable and comparing it to an old one (I took that bit of code out as it wasnt working) but I couldnt get the old settings into the new tags.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
var divStateArray;
function random_number() {
var random = Math.floor(Math.random()*110000);
return random;
}
//console.log(divStateArray);
function reload(state){
$(".responsecontainer").load('counter.php?randval=' + random_number(), function() {
var $rowelements = $(".divRow");
var $divRow = $('.divTable').find($rowelements);
//console.log($divRow);
//by copying $divRow it copies a reference/pointer into divStateArray.
//so any changes made to the properties of the div divRow are reflected in
//the afore mentioned variable.
divStateArray = $divRow;
//merge the old settings in divoldstate with the new references in divStateArray
if (state == 'all') {
divStateArray.hide();
}
});
}
//refresh the page every x miliseconds
var refreshId = setInterval(function() {
reload();
}, 5000);
$(document).ready(function() {
//show the spinning logo until the tables are loaded.
$(".responsecontainer").html('<img src="/lbadmin/images/ajax-loader.gif" width=32 height=32 />');
//display the page as soon as possible, then begin reloading every x seconds
reload('all');
$(document).on('click',".headRow",function(){
var $divRow = $(this).nextAll(".divRow")
//console.log($divRow);
if ($divRow.is(":hidden")) {
$divRow.show('fast');
}
else {
$divRow.hide('fast');
}
});
});
</script>
</head>
<body>
<p>hello</p>
<div class="responsecontainer" id="time1">
</div>
</br>
</body>
</html>
The table that gets loaded is (for the time being and for testing its just a static table but eventually this will change to multiple dynamic tables -
<?php
echo date("l, F d, Y h:i:s" ,time());
?>
<link rel="stylesheet" type="text/css" href="test.css" />
<p>hello</p>
</br>
<div class="divTable">
<div class="headRow">
<div class="divCell">LABEL: vippoo</div>
<div class="divCell">IP: 192.168.67.505</div>
<div class="divCell">Ports: 80-81</div>
<div class="divCell">Method: Layer 4</div>
<div class="divCell">Mode: DR</div>
<div class="divCell">Protocol: TCP</div>
<div class="divCell">Graph: link</div>
</div>
<div class="divRow">
<div class="divCell">label1</div>
<div class="divCell">192.168.66.666</div>
<div class="divCell">1</div>
<div class="divCell">Drain</div>
<div class="divCell">Halt</div>
<div class="divCell">uparrow</div>
<div class="divCell">graphlink</div>
</div>
<div class="divRow">
<div class="divCell">label1</div>
<div class="divCell">192.168.66.666</div>
<div class="divCell">1</div>
<div class="divCell">Drain</div>
<div class="divCell">Halt</div>
<div class="divCell">uparrow</div>
<div class="divCell">graphlink</div>
</div>
<div class="divRow">
<div class="divCell">label1</div>
<div class="divCell">192.168.66.666</div>
<div class="divCell">1</div>
<div class="divCell">Drain</div>
<div class="divCell">Halt</div>
<div class="divCell">uparrow</div>
<div class="divCell">graphlink</div>
</div>
</div>
</br>

Why don't you put a <div> around the table and show / hide that <div>? That way, if you reload the table, the visibility of the table remains the same as that is defined in the div around the table.

Why not simply check the state of the table before trying the refresh/reload?
If the table is hidden don't perform the refresh then the state of the table will not change.
Your set-interval method can continue to loop and that's where (within) you would add your check.
So your reload becomes something like this
function isTableHidden() {
var $divRow = $('.divTable').nextAll(".divRow")
return ($divRow.is(":hidden"))
}
function reload(state) {
if (isTableHidden())
return; // exit early and don't reload anything
$(".responsecontainer").load(
... rest of your oringal reload code ...
);
}

Related

Is there any way I can randomize the display of input submitted?

I'm not super great a javascript yet and I'm mostly a front end person. I am trying to have people's submissions be randomized across the screen but not entirely sure how to (it's okay if it wipes away everything with the refresh of the page). I have this so far:
<script>
function myFunction() {
var x = document.getElementById("myText").value;
document.getElementById("demo").innerHTML = x;
}
</script>
Which gives me an option where someone submits something and it appears on the bottom but I'm trying to have each response randomize somewhere on the screen.
I have the input displayed beneath the textbox but can't figure out how to have multiple answers show and then randomize across the screen.
Create multiple elements where you display the responses, then select one of them randomly when you're displaying.
function myFunction() {
var x = document.getElementById("myText").value;
let divs = document.querySelectorAll(".demo");
let chosen = divs[Math.floor(Math.random() * divs.length)];
chosen.innerText = x;
}
.demo {
height: 20px;
}
<input id="myText"> <button onclick="myFunction()">Enter</button>
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>
<div class="demo"></div>

How to Write a Function that Lists Products in a Table Side-by-Side

I have a script that allows users on my e-commerce site to select 3 products and it highlights the products as they select.
How can I grab the $pro_image, title, desc, etc. of the 3 products selected and put them into a table for side-by-side view?
I am assuming we will somehow need to check for the $pro_id that is selected to identify each product separately?
<div class="col-md-10">
<h4>Not sure which product to choose? <br> Select up to 3 and compare side-by-side.</h4>
<div class="col-md-2">
<button type="compare" class="btn btn-success" name="submit-compare">Compare</button>
</div>
<div class="col-md-12">
<?php getpcatpro();
$get_products = "SELECT * FROM products ORDER BY RAND() LIMIT 0,9";
$run_products = mysqli_query($con,$get_products);
while($row_products=mysqli_fetch_array($run_products)){
$pro_id = $row_products['product_id'];
$pro_title = $row_products['product_title'];
$pro_img1 = $row_products['product_img1'];
$pro_link = $row_products['product_link'];
echo "
<div class='col-md-4 col-sm-6'>
<div class='product' onclick='highlight(this)'>
<center>
<img class='img-responsive' src='admin_area/product_images/$pro_img1'>
</center>
<div class='text'>
<center>
<a href='$pro_link'> $pro_title </a>
</center>
</div>
</div>
</div> ";
}
?>
<script>
var selected_items = 0;
function highlight(target) {
if(target.style.border == ""){
if(selected_items < 3){
target.style.border = "1px solid red";
selected_items += 1;
}
} else{
target.style.border = "";
selected_items -= 1;
}
}
</script>
</div>
</div>
Firstly, there's no button type called 'compare', please stick to standards, you shouldn't put random things into these attributes, you can create your own if need be (which I do not think you need to). See here for the three types you are allowed: https://www.w3schools.com/tags/att_button_type.asp (you should just use 'button')
Second, do not add styles through JS, you will cause an entire repaint every time you change a pixel. Instead, toggle class names on the class attribute of an element, let CSS do the work of styling, and JS do the work of interaction.
Thirdly, move all 'PHP' to the top of your script (such as defining your SQL statement and fetching the result of it) rather than having these things interspersed within HTML (just use PHP later in the document to build HTML from the PHP variables at the top of the script), such as looping through your result set to build out the HTML, not to perform important tasks such fetching the data itself, this will help you track whats doing what where so you don't tie yourself up in IF statements etc.
OK, Create a function, bound to your compare button, that toggles the state of an element. Instead of 'highlighting' using styles, toggle a class 'compare' on the product parent container:
<style>
.product.compare{
border: 1px solid red;
}
</style>
<script>
$('.btn.compare').click(function(){
$(this).closest('.product').toggleClass('compare');
});
</script>
<div class='products'>
<div class='product' data-id='1'>
<h2>A Product</h2>
<button class='btn compare'>compare</button>
</div>
<div class='product' data-id='2'>
<h2>Another Product</h2>
<button class='btn compare'>compare</button>
</div>
</div>
This will basically, when the button is clicked, find the parent element with class '.product' then toggle the class '.compare' on it, so you should have .product.compare
You'll need to design your table to have fixed rows with class names, like so:
<table class='comparison'>
<thead>
<tr class='product-title'></tr>
</thead>
<tbody>
<tr class='product-price'></tr>
</tbody>
</table>
Once you have products with a toggled state (a class has been added which both highlights the row with CSS visibly, but also flags it for comparison to jQuery, create a new button and method for it to call to build the comparison table
<button class='btn goCompare'>Go Compare</button>
$(function(){
$(".btn.goCompare").on('click', function(e){
e.preventDefault();
buildComparisonTable();
});
});
function buildComparisonTable(){
var comparisonTableBody = $('table.comparison tbody');
var comparisonTableBodyProductTitleCol = $('table.comparison thead tr.product-title');
var comparisonTableBodyProductPriceCol = $('table.comparison tbody tr.product-price');
comparisonTableBody.find('.product-col').remove();
$('.product.compare').each(function(){
var id = $(this).attr('data-id');
var title = $(this).attr('data-title');
var price = $(this).attr('data-price');
comparisonTableBodyProductTitleCol.append('<th class="product-col">'+title+'</th>');
comparisonTableBodyProductPriceCol.append('<td class="product-col">'+price+'</td>');
});
}
The choice is yours, but think about how you can cleverly and correctly mark up your pages to be easily read by your scripts. You can either stuff all of the product data into attributes on a parent element:
<div class='product' data-id='1' data-title='A Product' data-price='$10.00' data-primary-category='Homeware'>
<h2>A Product</h2>
<button class='btn compare'>compare</button>
</div>
Or you can add a class to each element that has the data you intend to gleam:
<div class='product' data-id='1'>
<h2 class='product-title'>A Product</h2>
<span class='product-price'>$10.00</span>
<span class='product-category'>Homeware</span>
<img class='product-img' src='/images/product-1.jpg' />
</div>
Now you can target what you want easily and get information from it using proper class names, a considered layout, correct use of technologies and a simple approach. This code-pen illustrates: https://codepen.io/anon/pen/voBKgV

How do I get to the current picture source of a slideshow?

Completely new to coding over here. Learning the basics.
How can I get to "the picture only", when clicking on a current picture of a slideshow?
Normally in html I would just put this around it:
Current picture
But in this version I just don't seem to get it.
Clicking on the small pictures makes them appear as the big centred one.
Clicking on the big picture currently only pauses/continues the slideshow.
$(".crop-img").click(function(){
$("#bigImage").attr("src",
$(this).attr("src"));
});
var counter=1;
$("#image"+counter).click();
$("#forward").click(function(){
counter = counter + 1;
if (counter>4){
counter=1;
}
$("#image"+counter).click();
})
$("#backward").click(function(){
counter=counter-1;
if (counter<1){
counter=4;
}
$("#image"+counter).click();
})
$("#bigImage").click(function(){
paused=!paused;
})
Picture of how it looks is on my post about it.
Thank you!
Full code
<html>
<head>
<title> FWP - Gallery </title>
<script src="jquery-3.1.1.min.js"></script>
<link rel="stylesheet"
type="text/css"
href="bootstrap.css">
<link rel="stylesheet"
type="text/css"
href="mystyles.css">
<link rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=Gruppo">
<link rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=Syncopate">
</head>
<body>
<div class="container">
<h1>Image Gallery</h1>
<div class="row">
<div class="col-md-3 thin_border">
<img id="image1"
class="crop-img"
src="before.jpg"
alt="before prisma">
</div>
<div class="col-md-3 thin_border">
<img id="image2"
class="crop-img"
src="after.jpg"
alt="after prisma">
</div>
<div class="col-md-3 thin_border">
<img id="image3"
class="crop-img"
src="sleepy.jpg"
alt="Sleepy cat">
</div>
<div class="col-md-3 thin_border">
<img id="image4"
class="crop-img"
src="Cute.jpg"
alt="Cute cat">
</div>
</div>
<div class="row">
<div class="col-md-1 thin_border">
<button id="backward"><</button>
</div>
<div class="col-md-10 thin_border">
<img id="bigImage"
class="big-img"
src="before.jpg"
alt="before prisma">
</div>
<div class="col-md-1 thin_border">
<button id="forward">></button>
</div>
</div>
</div>
<script>
var paused=false;
setInterval(function(){
if(!paused){
$("#forward").click();
}
}, 3000);
$("#bigImage").click(function(){
paused=!paused;
});
$(".crop-img").click(function(){
$("#bigImage").attr("src",
$(this).attr("src"));
});
var counter=1;
$("#image"+counter).click();
$("#forward").click(function(){
counter = counter + 1;
if (counter>4) {
counter=1;
}
$("#image"+counter).click();
})
$("#backward").click(function(){
counter=counter-1;
if (counter<1) {
counter=4;
}
$("#image"+counter).click();
})
</script>
</body>
</html>
The section of javascript isn't vanilla javascript, it is a sample of this 'jquery' that you may have heard of in your quest to learn a bit of coding.
Jquery is syntactic sugar for javascript. $ is your cue to key in that this might be jquery (there are other js libraries that use $ syntax but I think jquery is the most prevalent).
$(".crop-img")
$("#bigImage")
$("#image"+counter)
This is jquery code to select an element from the page, the '.' is for selecting class, the '#' is for selecting id, there are tons of others you can look up as well. This gets you a jquery object that you can then save to a variable, call a method on, etc.
$(".crop-img").click(someFunctionNameHere);
$("#image"+counter).click();
These are examples of functions being called on the jquery objects, which happen to be event functions. The first is assigning a function to the click event of the selected element(s) (all elements with class 'crop-img'), the second is firing the click event of the selected element (the element with id='imageX' with 'X' being the current value of counter).
Also instead of a function name, you can just inline the function instead:
$("#bigImage").click(function(){
paused=!paused;
})
This assigns the unnamed inline function for the click event of the element with id='bigImage', which is where you want to pull up the image. Put your code in there that will bring up the image, it will run when the big image is clicked.
Such as if you want to actually go to the image, as in your html example, put this line in there:
window.location.href = "someHrefHere";
If you want to know the the src of the current bigImage, you can grab it with jquery:
var myhref = $("#bigImage").attr("src");
You can put it together from there.
Happy Coding!
You can retrieve the src of the current image when you click on the big image like this:
$( ".row div:nth-child("+counter+") img" ).attr('src')
counter was setted as index of your current image and this should be inside of your $("#bigImage") click function.

Javascript Performance for Dynamic Image Resouce?

I wrote an HTML page that supposed to switch fast between two pictures.
In the result I can see that the first picture is freezed for about a minute and JUST then they start to flip over fast and nicely. It is as if the first picture is loaded quickly and the second takes more time (they have quite the same size)
What can explain this behavior?
What should I do to make them flip from the very beginning?
Code:
<head>
<title>Visualize</title>
<script src="jquery-3.1.0.min.js"></script>
<script>
$(document).ready(function()
{
var file = "a";
setInterval(function()
{
$('.canvas').attr("src","images/"+ file +".png");
file = flipFile(file);
}, 290);
});
function flipFile(file)
{
if(file=="a")
{
file="b";
}
else if(file=="b")
{
file = "a";
}
return file;
}
</script>
</head>
<body>
<div class="container">
<img class="canvas" src="/images/file.png">
</div>
</body>
Two things I did
Placed <img> tag for each picture I want to deal with (with Display:None, for having them not visible)
Added "onload" attribute to the body that triggers the funciton that changes visibility between pictures.
This way the page waits for them to get loaded and just then starts the functionality.
`function visualize()
{
$('.loading').fadeOut(1000);
$('.blanket').fadeIn(1000);
setInterval(function()
{
$('.i'+fileIdx).show();
$('.i'+filePrevIdx).hide();
filePrevIdx = fileIdx;
fileIdx = addCyclic(fileIdx);
}, 290);
}`
`<body style="background-color: black;" onload="visualize()">
<div class="container">
<div class = "blanket" style="display: none;"></div>
<div class="loading">
Loading...
</div>
<img class="i1" src="./images/1.png" style="display: none;">
<img class="i2" src="./images/2.png" style="display: none;">
<img class="i3" src="./images/3.png" style="display: none;">
<img class="i4" src="./images/4.png" style="display: none;">
</div>
</body>`

Unexpected data representation

So I have an app, that allows you to add data, and then it displays all the data(still wip). So I made a Create and Read functionality so far using localStorage and jQueryMobile and jQueryUI.
But for some reason when I switch between pages(main page/add data page), I see cloned data on main page. Instead of 2 entries, I see 4 entries, and it's original 2 entries have a copy of each other. And when i refresh the page it's working fine, it displays only original data, without clones. Note that it's only happens when you go to Add page and then returning back to Main page(by clicking Home button).
Also When you are adding a run, for some reason it adding 2 runs at the same time(running add funciton 2 times)
Here is the code:
$(document).on('pageinit', function() {
//Display runs
showRuns();
//Add Handler for Adding Runs
$('#submitAdd').on('tap', addRun);
/*
* Show all runs on homepage
*/
function showRuns() {
//get runs Object
var runs = getRunsObject();
var i = 0;
if (runs != '' && runs != null) {
for (i; i < runs.length; i++) {
$('#stats').append('<li class="ui-body-inherit ui-li-static"><strong>Date: </strong>' + runs[i]["date"] + '<strong> <br/>Distnace: </strong>' + runs[i]["kms"] + 'km</li>');
}
$('#home').bind('pageinit', function() {
$('#stats').listview('refresh');
});
}
}
/*
* addRun function
*/
function addRun() {
//Get form values
var kms = $('#addKms').val();
var date = $('#addDate').val();
//Create 'Run' Object
var run = {
date: date,
kms: parseFloat(kms)
};
var runs = getRunsObject();
//Add run to runs array
runs.push(run);
alert('Run Added');
//Set stringified objects to localstorage
localStorage.setItem('runs', JSON.stringify(runs));
//Redirect
window.location.href = "index.php";
//Preventing form from submiting
return false;
}
/*
* getRunsObject
*/
function getRunsObject() {
//Set runs array
var runs = [];
//Get current runs from localStorage
var currentRuns = localStorage.getItem('runs');
//Check localStorage
if (currentRuns != null) {
//Set to runs
var runs = JSON.parse(currentRuns);
}
//Return sorted runs object
return runs.sort(function(a, b) {
return new Date(b.date) - new Date(a.date);
});
}
});
body {
text-align: center;
}
ul {
display: block;
}
.controls {
float: right;
}
<!DOCTYPE html>
<html>
<head>
<title>Running Tracker</title>
<link rel="stylesheet" href="css/style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.js"></script>
<script src="js/script.js"></script>
</head>
<body>
<!-- Main Page -->
<div data-role="page" id="home">
<header data-role="header" data-theme="a">
<h1>Running Tracker</h1>
</header>
<div data-role="navbar">
<ul>
<li>
Home
</li>
<li>
Add Run
</li>
</ul>
</div>
<div data-role="content">
<h3>Welcome to the RunningTracker App</h3>
<p>
With this app you can track your running, jogging or walking.
</p>
<h3>Your Latest Runs:</h3>
<ul id="stats" data-role="listview" data-filter="true" data-filter-placeholder="Filter runs by date or distance." data-inset="true"></ul>
<br/>
<button id="clearRuns" onclick="return confirm('Are You Sure?')">
Clear Data
</button>
</div>
<footer data-role="footer">
<h4>RunningTracker © 2015 GZ</h4>
</footer>
</div>
<!-- Add Run Page -->
<div data-role="page" id="add">
<header data-role="header" data-theme="a">
<h1>Running Tracker</h1>
</header>
<div data-role="navbar">
<ul>
<li>
Home
</li>
<li>
Add Run
</li>
</ul>
</div>
<div data-role="content">
<h3>Add Run</h3>
<form id="addForm">
<label for="km">Enter Kilometres:</label>
<input type="number" id="addKms">
<label for="km">Enter Date:</label>
<input type="date" data-role="date" class="date" id="addDate" data-inline="true">
<button id="submitAdd" class="ui-btn ui-corner-all">
Add Run
</button>
</form>
</div>
<footer data-role="footer">
<h4>RunningTracker © 2015 GZ</h4>
</footer>
</div>
</body>
</html>
For some reason example is not loading here on StackOverflow, so here is the live demo:
http://runningtracker.herokuapp.com/index.php
Try adding a new run, and then switch back to the add page, and then back to main page.
The problem is in the pageinit event handling. You are omitting the selector, so the handler is called twice (for home and for add pages), and in doing so you are calling $('#submitAdd').on('tap', addRun); twice, resulting in a double addRun call.
Change the line with:
$(document).on("pagecreate", "#home", function() {
(pagecreate now replaces pageinit, see jQM API)
Also, please change your "redirection" removing window.location.href = "index.php";.
That instruction changes the page bypassing jQuery Mobile navigation system, with the result of calling pageinit event after each addRun call (while it should be called only once).
Change your page using the change method instead:
$("body").pagecontainer("change", "#home", { transition: "none" });
Well, I found a solution. I replaced:
$(document).on('pageinit', function() {});
With:
$(document).one('pageinit', function() {});
As I understood it, I had 2 pages, so every function was running twice, and it was causing my problems. By using one instead of on I forced all the scripts to run only once, no matter how many pages I have.

Categories

Resources