i have a website with tags system like kind of the system that work on stackoverflow.
my questions about it is:
$("#area1 ul li").hover(function(){
var width= $(this).offset();
$(".flyout").css({"top":width.top+19,"left":width.left});
$(".flyout").toggle();
setTimeout(function() {
$.ajax({
url: web + "sources/queans/sql.php", type: "POST",
data: {
action: "taginfo",
tag: $(this).text(),
token: t,
ajax: "1"
},
success: function (output) {
$(".flyout").html(output);
}
});
}, 2000);
$(".flyout").html('<center><img style="margin-top:20px;" src="http://www.cloudynights.com/public/style_images/master/ajax_loading.gif" /> </center>');
});
Do this Jquery script is wait 2 seconds while the mouse are hover
the element?
if user remove the mouse hover the element do the query will still
running and execute the code? if no how can i stop the code before
it require from sql.php file data?
Do this Jquery script is wait 2 seconds while the mouse are hover the element?
Not exactly, once a user has hovered over the element, a timer is started and 2 seconds later the action is performed. The user does not have to remain hovering the element for this to happen.
if user remove the mouse hover the element do the query will still running and execute the code?
As specified above, the action will execute 2 seconds after first hovering the element, regardless of what the user does thereafter.
if no how can i stop the code before it require from sql.php file data?
Capture the result of the call to setTimeout into a variable (commonly called timerId or similar), and call clearTimeout(timerId) when the user stops hovering the element.
See the following simplified demo.
var timerId;
$('.container').hover(function(){
$('.message').text('Hover has been started, background will change in 5 seconds. Mouse out to cancel');
var $this = $(this);
timerId = setTimeout(function(){
$this.css('background-color','red');
},5000);
},
function(){
clearTimeout(timerId);
$('.message').text('Action cancelled');
});
.container{
width:300px;
height:300px;
border: 1px solid black
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div>Hover over me</div>
<div class="message"></div>
</div>
.hover() usually takes two arguments, handlerIn and handlerOut functions. As you have only one function, it will be invoked when the mouse pointer enters the element. My understanding is that you're displaying some pop-up next to element with some loading icon on hover, that's good because giving some visual feedback to the user encourages him to stay on that element.
setTimeout(callback,2000) will invoke that callback after waiting for minimum 2sec (it can be more - no guarantee on that ;)) but if the user leaves the element you're still firing the Ajax call without tracking that mouseleave event. So pass another function to hover() which will be invoked when the user leaves the element.
/* two variables outside hover scope to
hold reference to setTimeout & Ajax call*/
var timer, ajaxRequest;
$("#area1 ul li").hover(function(){
var width= $(this).offset();
$(".flyout").css({"top":width.top+19,"left":width.left});
$(".flyout").toggle();
timer = setTimeout(function() {
ajaxRequest = $.ajax({
url: web + "sources/queans/sql.php", type: "POST",
data: {
action: "taginfo",
tag: $(this).text(),
token: t,
ajax: "1"
},
success: function (output) {
$(".flyout").html(output);
}
});
}, 2000);
$(".flyout").html('<center><img style="margin-top:20px;" src="http://www.cloudynights.com/public/style_images/master/ajax_loading.gif" /> </center>');
},
function(){
// second callback to handle mouseleave
if(typeof ajaxRequest !== 'undefined'){
// abort the ongoing Ajax call
ajaxRequest.abort();
}else if(typeof timer !== 'undefined'){
// timeout callback is not invoked yet, so clear it
clearTimeout(timer);
}
// show some message in flyout or close the popup directly
});
Related
I'd like to display the #LoadingDiv while checkCoupon is firing, and have it disappear when it finishes, to show the function is in progress. checkCoupon is triggered by a button click (not displayed).
I've tried a variety of things including creating another function to include in onclick event, I've put this in different parts of the ajax call, and tried altering the CSS in different ways. It's still not working.
Any idea how to get this functionality and have this display properly at the beginning of the call starts?
function checkCoupon() {
var coupon = document.getElementById('couponCode').value;
var coupon_v = false;
$('#LoadingDiv').css('display', 'block');
$.ajax({
type: 'post',
url: 'coupon.php',
async: false,
data: {
'coupon': coupon
},
success: function(data) {
if (data != "empty") {
coupon_v = data;
}
}
})
}
<div id="LoadingDiv" style="display:none;">One Moment Please...<br />
<img src="images/progressbar.gif" class="displayed" alt="" />
</div>
You can hide the div on ajax complete function which is called when the request finishes (after the success or error callbacks are executed):
complete: function(){
$('#LoadingDiv').hide();
}
You can make use of jQuery's beforeSend and complete methods to address states before and after the call:
function checkCoupon() {
var coupon = document.querySelector('#couponCode').value;
var coupon_v = false;
let $loading = $('#LoadingDiv');
$.ajax({
type: 'post',
url: '.', //coupon.php
async: false,
data: {
'coupon': coupon
},
beforeSend: function() {
$loading.removeClass('hide')
},
success: function(data) {
if (data != "empty") {
coupon_v = data;
}
},
complete: function() {
// timeout only used for demo effect
window.setTimeout(function() {
$loading.addClass('hide')
}, 1500)
}
})
}
.hide {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="LoadingDiv" class="hide">One Moment Please...<br />
<img src="images/progressbar.gif" class="displayed" alt="" />
</div>
<input type="hidden" id="couponCode" value="3" />
<button onclick="checkCoupon()">Click</button>
I had the same issue. I know this is an older question by now, but obviously still relevant as I ran into the same conundrum.
I would call the showLoadingOverlay() method which would make the loading div visible, then run the function I wanted to run and then hide the loading overlay, but the overlay would never show. I finally found that the issue was that the function I was performing after showing the loading overlay was happening too quickly and it would pause the process of showing the overlay until it was done and then the hide function on the overlay was being called too quickly afterwards when the show method was able to resume. This is why it appeared that nothing was happening at all.
So, you need to delay the function you are trying to call (I used the setTimeout() method). The 400 in the setTimeout() method is 400 miliseconds that will be delayed before performing the processFunction method. Here is a generic way to accomplish your goal:
Javascript:
/******************************************************************************************
* Toggle loading overlay.
* ***************************************************************************************/
/**
* Toggle the loading overlay in order to prevent the user from performing any actions.
* The processFunction must call the endLoadOverlay method once it is finished.
* #param {any} processFunction The process to perform while the loading screen is active.
* This method must call the endLoadOverlay method once it is done.
*/
function startLoadOverlay(processFunction) {
$('#overlay').css('display', '');
setTimeout(processFunction, 400);
}
/**
* Ends the loading overlay.
* */
function endLoadOverlay() {
$('#overlay').css('display', 'none');
}
/******************************************************************************************
* End of toggle loading overlay.
* ***************************************************************************************/
Then when you call the startLoadOverlay() method pass the method that you want to accomplish through it. In my example I'm having a button click event call the overlay method:
HTML:
<button id="btnDoAction" type="button" onclick="startLoadOverlay(myFunctionToAccomplish);">Accomplish Something</button>
Remember, myFunctionToAccomplish() is the method that I want performed while the overlay is visible. NOTE: The method that you pass to the startLoadOverlay() method must call the endLoadOverlay() method after it is done processing in order to hide the loading overlay. So:
Javascript
function myFunctionToAccomplish() {
// Perform functionality.
//TODO: Add whatever functionality here.
// Once I'm done I need to call the endLoadOverlay() method in order to hide the loading overlay.
endLoadOverlay();
}
In case you are curious about my $('#overlay') element. The idea is basically from here: https://www.w3schools.com/howto/howto_css_overlay.asp
I am creating a chat, everything works perfectly, it scrolls down when i click the "Send" button, but I want it to scroll all the way down when the document is ready. I have done this by adding the scrolling function to setInterval, but the problem with that is that the user basically cant scroll up to see previous chat messages because he gets scrolled down every 0.1 seconds. My code is:
$(function () {
//$("#messages").scrollTop($("#messages").prop("scrollHeight")); Doesnt work at all
function updateChat(){
$("#messages").load('chat/ajaxLoad.php');
//$("#messages").scrollTop($("#messages").prop("scrollHeight")); This works but the user cannot scroll up anymore
}
setInterval(function () {
updateChat();
}, 100);
$("#post").submit(function(){
$.post("chat/ajaxPost.php", $('#post').serialize(), function (data) {
$("#messages").append('<div>'+data+'</div>');
$("#messages").scrollTop($("#messages").prop("scrollHeight")); // This works but only when the user presses the send button
$("#text").val("");
});
return false;
});
});
Add this to your code.
var chat = $("#messages").html();
setInterval(function () {
updateChat();
if(chat !== $("#messages").html()){
$("#messages").scrollTop($("#messages").prop("scrollHeight"));
chat = $("#messages").html();
}
}, 2000);
I think this should work (didnt test), but there are some better ways you can optimise this like not saving the whole .html() into a variable.
The idea here is that it checks if the content is changed every 2 seconds. If it is, it scrolls down.
I see what's your problem and I have 2 ideas for you :
You scroll down only when a new message is post, for example with an Ajax request you could check if number of messages is > in compare with the last 0.1s, if yes you scroll if not you ignore.
You scroll down every 1-2s only if the scroll is at the maximum bottom position. If the scroll is not at the maximum you do not scroll. I feel this solution is better.
You need to seperate the actions on your application,
also you missed many checks that can make the application work properly and will
make it easy to maintain.
How i suggestion the code will look:
$(function () {
function updateMessages(){
var messages_before_update = $("#messages").html();
$("#messages").load('chat/ajaxLoad.php');
var message_after_update = $("#messages").html();
if(messages_before_update !== message_after_update){
scrollToBottom();
}
}
function scrollToBottom(){
var scroll_height = $("#messages").prop("scrollHeight");
var scroll_top = $("#messages").scrollTop();
if(scroll_height !== scroll_top){
$("#messages").scrollTop($("#messages").prop("scrollHeight"));
}
}
function addMessage(message){
$("#messages").append('<div>' + message + '</div>');
}
setInterval(updateMessages, 100);
$("#post").submit(function () {
$.post("chat/ajaxPost.php", $('#post').serialize(), function (data) {
addMessage(data);
scrollToBottom();
$("#text").val("");
});
return false;
});
});
I have a content area that gets dynamically loaded with new content when you press the previous or continue buttons. A simple example of html is:
<div id="contentArea"></div>
<nav>
<ul>
<li class="butPrev">Previous</li>
<li class="butNext">Next</li>
</ul>
</nav>
What I used to do in iOS6 is have a mask over the content area on first load that I could click to trigger audio and video and then all other dynamic HTML5 videos would play. I am not sure about iOS7, but iOS8 doesn't allow this. I would have to do it for each page, which defeats the purpose of the mask and is a pain for a user.
As an alternative, I am trying to trigger the play of videos with the next button click. The problem is that the next button captures the dynamic content, loads it into the content area and at that time needs to trigger the play, which iOS doesn't like. Is there any way to wait until the content area is loaded, while staying within the click event so it doesn't get blocked? Here is what I am trying (I have stripped out the Ajax stuff):
var contentLoaded = false;
$('nav li').click(function(){
contentLoaded = false;
//load HTML with HTML5 video via Ajax
//when done, sets contentLoaded = true
triggerAutoplay();
});
function triggerAutoplay() {
if (contentLoaded) {
$('video[autoplay]').each(function(){
if ($('this').attr('autoplay') != "false") {
this.play();
}
});
} else {
setTimeout(triggerAutoplay,100);
}
}
im not sure if i understand you right, but maybe you should call the play in the success of your ajax call like so:
$('nav li').click(function(){
$.ajax({
url: "whatever"
}).done(function() {
//do some stuff
triggerAutoplay();
});
});
function triggerAutoplay() {
$('video[autoplay]').each(function(){
if ($('this').attr('autoplay') != "false") {
this.play();
}
});
}
The play trigger has to be within the click function, so I have to set async to false so that the ajax completes before the function is call like:
$('nav li').click(function(){
$.ajax({
url: "whatever",
async: false
});
triggerAutoplay();
});
function triggerAutoplay() {
$('video[autoplay]').each(function(){
if ($('this').attr('autoplay') != "false") {
this.play();
}
});
}
I have certain "pages" on my website that are sortable. They also auto update to a database.
After my li list is sorted, a php page is called that re-orders the "pages" and then I call .html(data) to change the order of the pages that are displayed on the page.
After doing this, however, my auto update functions in my javascript stop working.
There is a #form1 that works before the sort takes place and the .html(data) is called. Once it is called, the previous #form1 get's removed and re-added to the page. This is when it stops working.
Does anyone know the reasoning for this?
My update script
$("#reportNav").sortable({
stop : function(event, ui){
var postData = $(this).sortable('serialize');
var url = "saveOrder.php";
$.ajax({
type: "POST",
url: url,
data: postData,
success: function(data) { $('#reportContainer').html(data); },
error: function(data) { $changesSaved.text("Could not re-order pages."); }
});
}
});
What stops working/stops being called
var timeoutId;
$('#form1').on('input propertychange change', function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
// Runs 1 second (1000 ms) after the last change
$("#form1").submit();
}, 1000);
});
Probably a case of over-writing your elements that has handlers bound, in which case you need event delegation:
$('#reportContainer').on('input propertychange change', '#form1', function() {
I'm using some jQuery code to create tabs in which the page's content is broken up into (navigable from the top of the tab block) and am looking to do the following when a "next" or "previous" link (placed at the bottom of each tab's content) is clicked:
The page to scroll up to the top of the tab block (successfully implemented using ".scrollTo" plugin) over 750ms
Once scrolled, the tab to change to the corresponding "previous" or "next" tab (identified by a hashtag url) - 250ms later.
Using the following code:
$(".external_link").click(function() {
$.scrollTo(515, 750, {easing:'easeInOutQuad'});
setTimeout(changeTab($(this).attr("href")), 1000);
return false;
});
the two happen at the same time at the mo. If anyone could shed some light on what I'm doing wrong I'd be really appreciative.
The code in full:
$(document).ready(function() {
$(".tab_content").hide();
$("ul.content_tabs li:first").addClass("active").show();
$(".tab_content:first").show();
$('.content_tabs li').each(function(i) {
var thisId = $(this).find("a").attr("href");
thisId = thisId.substring(1,thisId.length) + '_top';
$(this).attr("id",thisId);
});
function changeTab(activeTab) {
$("ul.content_tabs li").removeClass("active");
$(activeTab + '_top').addClass("active");
$(".tab_content").hide();
$(activeTab).fadeIn();
}
//check to see if a tab is called onload
if (location.hash!=""){changeTab(location.hash);}
//if you call the page and want to show a tab other than the first, for instance index.html#tab4
$("ul.content_tabs li").click(function() {
if ($(this).hasClass("active"))
return false;
changeTab($(this).find("a").attr("href"));
return false;
});
$(".external_link").click(function() {
$.scrollTo(515, 750, {easing:'easeInOutQuad'});
setTimeout(changeTab($(this).attr("href")), 1000);
return false;
});
});
Am I right to be attempting to do this with setTimeout? My knowledge is incredibly limited.
setTimeout(changeTab($(this).attr("href")), 1000);
That's the wrong one, you have to put in a function, not the result of executing a function, and 250 ms makes more sense. changeTab is a function, changeTab(argument) is executing a function. So try
var that = $(this);
setTimeout(function() {changeTab(that.attr("href"))}, 250);
I think the reason they execute at the same time is because you call the changeTab-function directly when you set the timeout, and the previous function waits for 750ms before proceding.
You are passing a function call to setTimeout(). You need to pass a function reference. The call will get executed immediately, but a function reference will be executed when the timeout expires. Call setTimeout() like this:
setTimeout(function() { changeTab($(this).attr("href")); }, 1000);
Also, you should consider taking advantage of the onAfter option of the .scrollTo() plugin which indicates a function to be called when the scrolling is completed. It may make more sense to go:
$.scrollTo(515, 750, {
easing: 'easeInOutQuad',
onAfter: function () {
setTimeout(function() { changeTab($(this).attr("href")); }, 250);
}
});