Basically i have a REST api which return a JSON . In this JSON , it return the last viewed topic. For example
{ lastview : ABC }
So i want to insert this to my page
<div class = 'lastview'>Last viewed topic: </div>
$.getJSON("json link", function(data){
$('<a/>',{
text: data.lastview
}).appendTo('.lastview');
But since this data may change after another topic is viewed. What i mean is if user go to another topic name XYZ , the JSON change lastview from ABC to XYZ but the one in web will not ( still ABC ) because it only execute the function one time when the page loads.
So is there anyway to dynamically check the JSON and return correctly when the content changes ( What i mean is when the lastview topic change to XYZ , the one in div will automatically change to XYZ too)
Thanks
The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds.
1000 ms = 1 second.
The function is only executed once. If you need to repeat execution, use the setInterval() method.
setInterval({
$.getJSON("json link", function(data){
$('<a/>',
{
text: data.lastview
}).appendTo('.lastview');
}, 1000);
This is a sample of keep requesting and update every 500ms
setInterval(function() {
// Fake ajax
data = { lastview: "Page " + Math.floor(Math.random() * 3) };
// Just for demo
$("#lastview").empty();
$("#lastview").append(
$("<a></a>").text(data.lastview)
);
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Last viewed topic: <span id="lastview"></span></div>
Related
I am writing a simple webserver with micropython.
I want to switch on a relay for a certain duration (given in input by the user from the HTML form).
When the relay is off, I display a div with the input form for the duration and the activation button.
When the relay is on, the same div is replaced with a countdown; when the relay is on I want to refresh the div every second so that the countdown is updated. When the relay is off, I don't want the div to update because otherwise, if you try to input the duration, every second the input number in the box is cleared.
My div is updated by the following script:
<script>
$(document).ready(function () {
setInterval(function () {
$("#div_name").load(window.location.href + " #heatingDiv");
}, 1000);
});
</script>
The div is:
<div id="div_name">
<h1>Title</h1>
insert_content
</div>
The keyword "insert_content" is replaced with the HTML code inside the micropython program (accordingly to the relay state) before the HTML response is sent.
With the previous code everything works fine except for the fact that the div is updated every second even when the relay is off, making it impossible to input the duration in the form.
What I'd like to do is passing an argument to the script similarly as when one uses onClick to call it (I can modify "state" within micropython before sending the response):
<div id="div_name(state)">
<h1>Title</h1>
insert_content
</div>
and the script should look like:
<script>
$(document).ready(function () {
setInterval(function (var state) {
if(state){
$("#div_name").load(window.location.href + " #heatingDiv");
}
}, 1000);
});
</script>
Of course this does not work because id=div_name is not a function call: it is just to give an idea of what I'd like to achieve.
How can I do that?
Why not use a data attribute:
const $div = $("#div_name");
const state = $div.data('state');
if (state) {
setInterval(function() {
$div.load(window.location.href + " #heatingDiv");
}, 1000);
}
// if you are wanting to do the interval to check if the state changes, you could change it around
setInterval(function() {
const state = $div.data('state');
if (state) {
$div.load(window.location.href + " #heatingDiv");
}
}, 1000);
<div id="div_name" data-state="state">
<h1>Title</h1>
insert_content
</div>
Perhaps if you are only wanting to run the load when the state changes, you may be better of with a MutationObserver watching the data attribute instead of a timeout
I am working on a private application of a food sub reddit, what I'm retrieving some images witha limit of 20 images per view and when the user reach the bottom of the page it loads more information and appends it, like ajax; I'm doing the request server side and using Snoocore which is an API wrapper for Reddit. Snoocore actually provides a method to fetch information of the next page. From Snoocore's documentation:
// Instead of an HTTP verb, use a Snoocore helper `.listing`
// It will return a "slice" for a listing that has various
// helpers attached to it.
reddit('/r/askreddit/hot').listing().then(function(slice) {
// This is the front page of /r/askreddit
// `slice.children` contains the contents of the page.
console.log(slice.children);
// Get a promise for the next slice in this
// listing (the next page!)
return slice.next();
}).then(function(slice) {
// This is the second page of /r/askreddit
console.log(slice.children);
});
And this is my code:
reddit('/r/food/hot').listing({limit: 10}).then(result => {
for (var x in result.children){
if (result.children[x].data.link_flair_text === '[Homemade]' || result.children[x].data.link_flair_text === '[homemade]') {
if (result.children[x].data.domain !== 'imgur.com') {
if (result.children[x].data.post_hint !== "rich:video") {
titles.push({
'title': he.decode(result.children[x].data.title),
'imgurl': he.decode(result.children[x].data.url),
'user': result.children[x].data.author,
'submission': result.children[x].data.permalink
});
}
}
}
}
console.log(result.children[4].data);
res.render('index', {
'titleArr': titles
});
});
on my Pug template I have:
extends layout
block content
div#wrap
each i in titleArr
figure.figure
img.img-fluid.img-rounded(src= i.imgurl)
figcaption.figure-caption.text-center
p.text-muted #[i #{i.title}]
p
| #[i ―by ]
a(href="http://reddit.com" + i.submission, target="_blank")
| #[i /u/#{i.user}]
listing({limit: 10}) here is important because, well, it limits the post retrieved; actually I'm retrieving only 10, by default it retrieves 25; anyway, I'm looking for a way, how i said that when the user reach bottom of the page it loads more post; do I have to do this via client side? Or can I do this via server side in some way? Tell me if I need to explain my issue more in depth.
What you are looking for is "infinite scrolling", you basically want to do another request when your user reaches the bottom of the page that has been rendered.
This is going to require you to fire an ajax request when your browser scroll reaches the bottom of the page. If you were to use jQuery, your code would look something like this:
$(document).ready(function() {
var win = $(window);
var parts = location.pathname.split("/");
// assuming a url like domain.com/reddit/10 where 10
// is the total number of posts you're showing
var pageNumber = parts[3]; //this gives you access to the `10`
// then add 10 to the current page number and
pageNumber += 10
// use that for your ajax request
var url = "http://domain.com/reddit/"+pageNumber;
// Each time the user scrolls
win.scroll(function() {
// End of the document reached?
if ($(document).height() - win.height() == win.scrollTop()) {
$('#loading').show();
$.ajax({
url: url,
dataType: 'json',
success: function(json) {
// do something with your json of your posts
// then hide the loading gif or image.
$('#loading').hide();
}
});
}
});
});
This will fire the ajax request whenever your user reaches the bottom of the page, and paginate correctly. This is only the browser side, though.
You will need to edit your server endpoint slightly as well.
For example, you need to increase your limit dynamically
//you could use the req.params method from express to accomplish this
reddit('/r/food/hot').listing({limit: req.params.limit}).then(result => {
for (var x in result.children){
if (result.children[x].data.link_flair_text === '[Homemade]' || result.children[x].data.link_flair_text === '[homemade]') {
if (result.children[x].data.domain !== 'imgur.com') {
if (result.children[x].data.post_hint !== "rich:video") {
titles.push({
'title': he.decode(result.children[x].data.title),
'imgurl': he.decode(result.children[x].data.url),
'user': result.children[x].data.author,
'submission': result.children[x].data.permalink
});
}
}
}
}
console.log(result.children[4].data);
res.render('index', {
'titleArr': titles
});
});
Accessing the req.params.limit variable should work. You will need to edit your endpoint definition as well. I'm not sure how you have your server's routing setup right now, but this would be one way you could do it:
app.get('/reddit/posts/:limit', function(req, res) {
console.log('limit is: ', req.params.limit);
})
The idea here is that you want to increase the number of items you're fetching with each jQuery request. this is a pretty quick and dirty way of doing so, and I'm making some assumptions about how you're handling the server and what you're using, but this should get you 90% of the way there. Hope this helps!
I am trying to open a fancybox iframe on my page. Pass over some basic information to the iframe. Then I want to make it so that the iframe talks back to it's parent.
I am passing nameid-1 throughout statically, though I would really like to have this as variable such as: var nameid=$(this).attr('nameid')
I just don't know how to execute this all correctly as I am new to Ajax/Javascript and struggling with the logic.
Base.html
JS:
<script type='text/javascript'>
//<![CDATA[
// Popup Function
$(document).ready(function () {
$('a.openinformation').fancybox({
openEffect: 'fade',
openSpeed: 500 //,
});
});
// Update from iFrame
function setInformation(userText) {
$('#displayfield-nameid-1').html(userText);
$('#showhide-nameid-1').show();
}
//]]>
</script>
HTML:
<div>
<a class="openinformation fancybox.iframe" href="iframe.html" nameid= "1" originalname="Mary Poppins" >Mary Poppins</a>
</div>
<div id ="showhide-nameid-1" style=" display:none; background:#0CF;">
<p>Replacement Name: <span id="displayfield-nameid-1"></span></p>
</div>
iframe.html
JS :
<script type='text/javascript'>
//<![CDATA[
// Start
$(window).load(function () {
// When Loaded get going.
$(document).ready(function () {
$('a.doupdate').click(function () {
parent.setInformation($(this).text());
parent.$.fancybox.close();
});
$('a.closeremove').click(function () {
parent.$('#showhide-nameid-1').hide();
parent.$.fancybox.close();
});
});
});
//]]>
</script>
HTML
<p>The old name: $originalname;</p>
<p>The id for this column is: $nameid</p>
<p>Please select a new name:</p>
<div><a class="doupdate" href="#">Display new married name : Mary Smith</a></div>
<div><a class="doupdate" href="#">Display new married name: Sandy Shore</a></div>
<div><a class="closeremove" href="#" id="1">Clear (Hide) married Names Box</a></div>
Your question can be dived in two parts :
How to pass data (stored in variables) from parent page to an iframe (opened in fancybox)
How to manipulate data (and/or store such data in variables) inside the iframe and then pass those values to the parent page when fancybox is closed.
1). Pass data from parent page to (fancybox) iframe
I think your best choice is to store all your data in a single javascript object like :
var parentData = {};
... so you can pass a single object to the iframe instead of several variables. Then you can add different properties and values to that object like :
parentData.nameid = "1";
parentData.originalname = "Mary Poppins";
... or more if you need so.
You still may want to pass that information statically through (HTML5) data attributes like :
<a data-nameid="1" data-originalname="Mary Poppins" href="iframe.html" class="openinformation">Mary Poppins</a>
... and push the data values into the parentData object within the fancybox beforeLoad callback like :
beforeLoad : function () {
parentData.nameid = $(this.element).data("nameid");
parentData.originalname = $(this.element).data("originalname");
}
... that would give you much more flexibility IMHO.
Now, the only thing you need to do in the iframed page is to refer to those properties as parent.parentData.nameid and parent.parentData.originalname any time you need them, e.g.
having this html (iframe.html)
<p>The old name: <span id="originalname"></span></p>
<p>The id for this column is: <span id="nameid"></span></p>
... you can use this script to write the values of the parent object like :
$("#nameid").text(parent.parentData.nameid);
$("#originalname").text(parent.parentData.originalname);
Notice you cannot do (as in php)
<p>The old name: $originalname;</p>
... so we used <span> tags to write their content via javascript.
2). Pass data from iframed page to parent page.
First thing you need to do is to declare in your parent page, an object to store data from the iframe and a function to process it like :
var iframeData = {};
function setInformation(data) {
return iframeData = data;
};
Then in the iframed page, you can write different properties/values to the iframeData object and run the setInformation() function (in the parent page) from the iframe to pass the values to the parent page like :
$(".doupdate").on("click", function (e) {
e.preventDefault();
iframeData.newname = $(this).find("span").text(); // set object property/value
parent.setInformation(iframeData); // pass it to parent page
parent.$.fancybox.close();
});
The code above assumes you have a similar html like
<a class="doupdate" href="#">Display new married name : <span>Mary Smith</span></a>
... notice I wrapped the name I want pass in a span tag. Optionally you could separate it in 2 spans like :
<span class="fname">Mary</span><span class="lname">Smith</span>
... and write them in separated values like :
iframeData.fname = $(this).find("span.fname").text();
iframeData.lname = $(this).find("span.lname").text();
For the clear button, I would just reinitialize the variable and close fancybox like
$('a.closeremove').on("click", function (e) {
e.preventDefault();
iframeData = {}; // reset variable
parent.setInformation(iframeData); // pass it to parent page
parent.$.fancybox.close();
});
... and perform the manipulation of the parent page from the parent page itself using the fancybox afterClose callback like :
afterClose : function () {
if ( objLength(iframeData) > 0 ) {
$('#displayfield-nameid-1').html(iframeData.newname);
$('#showhide-nameid-1').show();
} else {
$("#displayfield-nameid-1").empty();
$('#showhide-nameid-1').hide();
}
}
... notice I will only show the selector #showhide-nameid-1 if the iframeData object's length is bigger than 0. Because that, I need a function to validate the object's length :
Based on this answer, you could do:
function objLength(iframeData) {
// ref https://stackoverflow.com/a/5533226/1055987
var count = 0, i;
for (i in iframeData) {
if (iframeData.hasOwnProperty(i)) {
count++;
}
}
return count;
};
... which will return the object's length.
Last note :
Since the iframed page is referring to the parent page using the prefix parent, it will return js errors if it's opened outside an iframe. You may want to validate first if the iframed page is actually contained inside an iframe before trying to access data back and forth to/from the parent page like :
if (window.self !== window.top) {
// the page is inside an iframe
}
See DEMO and feel free to explore the source code of both pages.
I have this code, it basically changes the word 'article' to 'articles' if the value is '0' or more than '1'. But the word only changes when the page is refreshed. Is it possible to automaticaly re-run the code at the same moment the value (quantity) changes?
<span id="quantity" class="simpleCart_quantity"></span> gets it's value from an external file, it is always a number (like 0, 1, 2, 3, etc.)
<span id="quantity" class="simpleCart_quantity"></span>
<span id="quantityText"></span>
<script type="text/javascript">
$(window).load(function()
{
var quantity = document.getElementById("quantity"),
quantityText = document.getElementById("quantityText");
if (parseInt(quantity.innerHTML, 10) === 1) {
quantityText.innerHTML = "article";
} else {
quantityText.innerHTML = "articles";
}
});
</script>
Thanks in advance!
Yes it's possible.
The direct and dirty way is to poll the server for changes at an interval. make a timer function that calls an ajax function that checks to see if the article count has changed.
something like:
setInterval(function(){
$.ajax({
url:"checkchanges.php",
dataType:"json",
type:'GET',
.success(function(data){
if (data.articlecount>1){ //pseudocode, it depends on how you get your data
$("#quantity").innerHTML="articles";
}
})
});
},3000);
Another method is to use a framework like meteor that wires the checking up for you.
Alright, I'm currently working to create on an account mainpage a applet to show each "kid" the user has registered to the site. My idea is simple :
Kid 1 / Kid 2 / Kid 3
As buttons (with style and such) when he goes on this page. When he clicks on one of those buttons/names, I use javascript to show the description of the infos of the kid, etc. When I click on another name, the current content closes and shows the new appropriate content.
The content is dynamically created, so the id's of the divs containing the info are named after the number of kids. Example : content_Info_Kid1, content_Info_Kid2, ... It doesnt matter how many kids there are, they will be named content_Info_Kid32 if need be.
Now, I'm not too comfy with AJAX and javascript in general. In fact, I am not at all.
My first idea was to do this in a separate javascript file.
$(document).ready(function() {
$("#content_info_kid1").hide();
$("#content_info_kid2").hide();
$("#content_info_kid3").hide();
$("#KID_1").click(function () {
if ($("#content_info_kid1").is(":hidden")){
$("#content_info_kid2").hide();
$("#content_info_kid3").hide();
$("#content_info_kid1").show("slow");
$(this).css("font-weight","bold");
$("#KID_2").css("font-weight","normal");
$("#KID_3").css("font-weight","normal");
}
});
$("#KID_2").click(function () {
if ($("#content_info_kid2").is(":hidden")){
$("#content_info_kid1").hide();
$("#content_info_kid3").hide();
$("#content_info_kid2").show("slow");
$(this).css("font-weight","bold");
$("#KID_1").css("font-weight","normal");
$("#KID_3").css("font-weight","normal");
}
});
$("#KID_3").click(function () {
if ($("#content_info_kid3").is(":hidden")){
$("#content_info_kid2").hide();
$("#content_info_kid1").hide();
$("#content_info_kid3").show("slow");
$(this).css("font-weight","bold");
$("#KID_1").css("font-weight","normal");
$("#KID_2").css("font-weight","normal");
}
});
});
Obviously, this is not dynamic. And I don't want to create 32 alternatives, of course. Can somebody point me the right direction to create a dynamic way to show my content based on the number of kids ?
EDIT (see bottom for updated on loading just one kid data at a time)
An example on how you could achieve that:
<style type='text/css' media='screen'>
button { margin-left:20px; display:inline; }
</style>
<script type='text/javascript' src='jquery-1.7.1.min.js'></script>
<script type='text/javascript'>
function loadKidData(kidID) {
switch (kidID) {
case 1 : $('#kName').text(' John Doe');
$('#kNickname').text(' Speedy');
$('#kHobbies').text(' Booling');
break;
case 2 : $('#kName').text(' Mathews Doe');
$('#kNickname').text(' Slowy');
$('#kHobbies').text(' Basketball, baseball');
break;
case 3 : $('#kName').text(' Jackson Doe');
$('#kNickname').text(' J-DOE');
$('#kHobbies').text(' Archery');
break;
case n : $('#kName').text(' Enne Doe');
$('#kNickname').text(' The-Nanny');
$('#kHobbies').text(' Anything goes');
break;
default : $('#kName').text('');
$('#kNickname').text('');
$('#kHobbies').text('');
}
}
jQuery( function () {
$('.nav').click( function () {
loadKidData($(this).html().replace('KID ','')*1.0); // *1.0 same as parseInt(...,10).
})
});
</script>
</head>
<body>
<button class='nav' >KID 1</button><button class='nav' >KID 2</button><button class='nav' >KID 3</button>
<div id='KID_INFO' style='margin:20px auto; overflow:auto; ' >
<p>Name:<span id='kName'></span></p>
<p>Nickname:<span id='kNickname'></span> </p>
<p>Hobbies:<span id='kHobbies'></span> </p>
</div>
</body>
Sample at: http://zequinha-bsb.int-domains.com/kidsinfo.html
Now, as far as dynamically displaying the data, it will have to do with your resources: database? If so, you could read the data and pass it over:
$.get('url-of-the-database-reading-script',function (data) {
// assumed all data comes back formatted:
$('#KIDS_INFO').html(data);
});
I can/could help you further, more details would help. Are you using classic asp (.asp); php; etc?
EDIT:
Instead of this:
jQuery( function () {
$('.nav').click( function () {
loadKidData($(this).html().replace('KID ','')*1.0); // *1.0 same as parseInt(...,10)
})
});
Do this:
jQuery( function () {
$('.nav').click( function () {
$.get('your-data-fetching-url?kidID='+$(this).html().replace('KID ','')*1.0, function (data) {
//assumed the data comes back formatted:
$('#KIDS_DATA').html(data);
})
})
});
Note that I put a question mark at the end of the url; followed by the querystring kidID=
Give each "Kid" button the same class and use that for the click handler. From there, you can associate the "content_info_kid" with the "kid" button either by
1)Using the index of the element. The button for kid2 should be index 1 relative to its parent and the content_info for kid2 should also be index 1 relative to its parent.
or
2)Extract the number from the ID of the button.
Both approaches are documented below.
$('.kid_button').click(function(){
// get number from index (this starts at '0')
// if your kid #'s start at 1, you should add 1 to this
var id = $(this).index();
// OR...get number from id where id format is kid_{#}
var id = $(this).attr('id').split('_').pop();
// now we have the number to append to everything else
// we should also associate all "content_info" with a class
// which we will call "kid_content"
if($("#content_info_kid"+id).is(":hidden")){
// hide all of the 'kid_contents'
$(".kid_content").hide();
// show the one we want
$("#content_info_kid"+id).show("slow");
// normalize all buttons
$(".kid_button").css("font-weight","normal");
// bold this one
$(this).css("font-weight","bold");
}
});