jQuery AUTOMATIC scroll (no button click) on document ready - javascript

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;
});
});

Related

Problems with automating the function jquery

Hello guys Here i have a function that reacts two time by a same button. One time when it's clicked it fades out other time it fades in, but the problem is one that after 2 clicks it stops responding. I am trying to make it loop but. I don't have any clue. I tried with the clickCounts ++ and if statements but it didn't give me any fruit.
so if you guys have any idea I'm quite opened to any suggestions.
$(function() {
$('#two').one("click", function() {
$("this").css({color:"#f790e8"})
$(".others:nth-child(1)").fadeOut("300")
$(".others:nth-child(2)").delay("150").fadeOut("300")
$(".others:nth-child(3)").delay("300").fadeOut("300")
$(".others:nth-child(4)").delay("450").fadeOut("300")
$(".tube1").delay("300").fadeIn("300")
$(".tube2").delay("450").fadeIn("300")
$(".tube3").delay("600").fadeIn("300")
$('#two').on("click", function() {
//this code will execute on second click and further clicks
$("this").css({color:"black"})
$(".others:nth-child(1)").delay("300").fadeIn("300")
$(".others:nth-child(2)").delay("450").fadeIn("300")
$(".others:nth-child(3)").delay("600").fadeIn("300")
$(".others:nth-child(4)").delay("750").fadeIn("300")
$(".tube1").fadeOut("300")
$(".tube2").delay("150").fadeOut("300")
$(".tube3").delay("300").fadeOut("300")
});
});
});
You'll probably have a better time setting a class on the element and using it to see which one of the two behaviors to trigger.
$(function () {
$("#two").on("click", function () {
const $this = $(this);
if ($this.hasClass("on")) {
//this code will execute on second click and further clicks
$this.css({ color: "black" });
$(".others:nth-child(1)").delay("300").fadeIn("300");
$(".others:nth-child(2)").delay("450").fadeIn("300");
$(".others:nth-child(3)").delay("600").fadeIn("300");
$(".others:nth-child(4)").delay("750").fadeIn("300");
$(".tube1").fadeOut("300");
$(".tube2").delay("150").fadeOut("300");
$(".tube3").delay("300").fadeOut("300");
} else {
$this.css({ color: "#f790e8" });
$(".others:nth-child(1)").fadeOut("300");
$(".others:nth-child(2)").delay("150").fadeOut("300");
$(".others:nth-child(3)").delay("300").fadeOut("300");
$(".others:nth-child(4)").delay("450").fadeOut("300");
$(".tube1").delay("300").fadeIn("300");
$(".tube2").delay("450").fadeIn("300");
$(".tube3").delay("600").fadeIn("300");
}
$this.toggleClass("on");
});
});

jQuery Scroll function for a web page is not working out?

I am trying to set scroll for a web page but it's not working out properly.
What I want is that when someone scroll to the middle of the or at least a little up before the footer element so I want to trigger scroll event and then wait for like 10 to 15 seconds as on triggering the scroll event the data is loaded through ajax which takes time and then each time to do so when someone goes down again to the footer so again the scroll function should get triggered.
What I am working now with is as follows but I want to enhance it to the above requirements :
$(document).on('scroll', function() {
if($(this).scrollTop()>=$('footer').position().top){
$('div#load_more').click();
}
});
Use $(window) instead of $(document)
// helper function does exactly what it says
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
var $canfetch = true;
$(window).on('scroll', function(e) {
var scrollHeight = $(window).scrollTop();
var scrollPosition = $(".highlight")[0].offsetTop;
// if user has reached bottom of page the sleep function for next scroll event will be fired.
if (scrollPosition-scrollHeight <= 0) {
if($canfetch) {
console.log("ajax call here");
}
$canfetch = false;
// sleep function usage
sleep(15000).then(() => {
alert("15 seconds have passed");
// return to top of page
$(window).scrollTop(0);
$canfetch = true;
});
}
});
.ok {
height:500px;
}
.highlight{
height:20px;
text-align:center;
background-color:yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ok"></div>
<div class="highlight">Reference Point</div>
<div class="ok"></div>
I just did a jsfiddle test of your code and had following observations:
a. Assuming the footer is in a div
if you are using class='footer' then you have to use
$('.footer').position().top
If you are using id='footer' then you have to use $('#footer').position().top
b. I added console.log($(this).scrollTop() + '~~footer positon top is '+ $('.footer').position().top); and found that the condition is never met.
1671~~footer positon top is 1868 when I scrolled all the way down.
Hope this helps a bit.
Side Note: You might want to consider a cool plugin called ajax load more to achieve similar feature.
Use the below function use $(window) instead of $(document):
$(window).on('scroll', function(e) {
alert("Scrolled");
});

Why this .js script stops working and is causing a browser freeze?

I've downloaded this Drupal 8 template and the site is at www.plotujeme.sk. It has an responsive navigation with this .js script:
function sidebar_menu() {
var windowsize = jQuerywindow.width(),
jQuerynav = jQuery("nav"),
slide = {
clear: function () {
jQuerybody.removeClass('toggled');
jQuery('.overlay').hide();
jQuery('.easy-sidebar-toggle').prependTo("header");
//jQuery('#search').prependTo("body");
jQuery('.navbar.easy-sidebar').removeClass('toggled');
jQuery('#navbar').removeAttr("style");
},
start: function () {
jQuery('.overlay').show();
jQuerybody.addClass('toggled');
jQueryhtml.addClass('easy-sidebar-active');
jQuerynav.addClass('easy-sidebar');
jQuery('.easy-sidebar-toggle').prependTo(".easy-sidebar");
//jQuery('#search').prependTo("#navbar");
jQuery('#navbar').height(jQuerywindow.height()).css({
"padding-top": "60px"
});
},
remove: function () {
jQuerynav.removeClass('easy-sidebar');
}
};
if (windowsize < 1003) {
jQuerynav.addClass('easy-sidebar');
jQuery('.easy-sidebar-toggle').on("click", function (e) {
e.preventDefault();
if (jQuerybody.hasClass('toggled')) {
slide.clear();
} else {
slide.start();
}
});
/*
jQueryhtml.on('swiperight', function () {
slide.start();
});
jQueryhtml.on('swipeleft', function () {
slide.clear();
}); */
} else {
slide.clear();
slide.remove();
}
}
and:
jQuery(document).ready(function () {
"use strict";
sidebar_menu();
jQuery(window).resize(function () {
sidebar_menu();
});
});
Problem is, that if I open responsive navigation by clicking on hamburger button, it works several times and then it stops working, the page and a browser freezes or is unresponsive for a long time. I also noticed that (even in template preview) sometimes it does not work at all and nothing happens after clicking hamburger icon. When I resize window multiple times sometimes it works sometimes not.
Do you see any error in the script that could possibly cause this problem?
Update: I also tried to use jQuery('.easy-sidebar-toggle').off("click"); just before jQuery('.easy-sidebar-toggle').on("click", function() {...}); but got the same results.
jQuery(window).resize(function () {
sidebar_menu();
});
As a result, whenever sidebar_menu function changes the window size, this function is called again and again, like a recursion, hence the freezing
I think the reason might be the following lines in the resize handler:
jQuerynav.addClass('easy-sidebar');
jQuery('.easy-sidebar-toggle').on("click", ...
They are run every time the window is resized by even one pixel, so a few dozen times a second if you drag the window border. Not sure about the first line, whether it adds the class over and over, but the second line certainly adds an event handler multiple times and fills up the stack. That's the reason your browser freezes. It just can't process the hundreds of registered events.
Just a guess, though.

.delay() not working on my .show() JQuery

I'm trying to make my footer disappear when on a mobile device and only when the keyboard is open. Which I have working perfectly, however the issue is that the footer reappears before the keyboard has time to close. Which is because I'm using the event from the textbox having focus not the keyboard being open. So I thought the best way to resolve this is with a .delay() however, this isn't working at all. Anyone have any ideas here?
<script>
var isMobileView = false; //global variable
$(document).ready(function () {
function setScreenWidthFlag() {
var newWindowWidth = $(window).width();
if ( $(window).width() > 600) {
isMobileView = false;
}
else {
isMobileView = true;
}
}
$(".tbinputArea").focus(function() {
if(isMobileView)
$("#footer").hide();
});
$(".tbinputArea").focusout(function() {
if(isMobileView)
$("#footer").delay(500).show();
});
setScreenWidthFlag();
$(window).on("resize", function (e) {
setScreenWidthFlag();
});
});
</script>
$("#footer").delay(500).show(0);
Try this.
refer this explanation precisely explained the reasons for it http://www.mattlunn.me.uk/blog/2012/06/jquery-delay-not-working-for-you/
Delay is just for queue delay not any event delay so try to add some events within like fadeIn or similar.

Adding a Quiz Timer, Fade Out/Skip to the next if timer reaches 0

I'm really new to jQuery but familiar with some other languages. I recently bought a quiz type script and I'm trying to add a simple 15 second timer to each question. It's only a fun quiz, so no need to worry about users playing with the javascript to increase time etc.
Basically, if a user does not pick a question within 15 seconds, it will automatically go on to the next question and the timer starts over again.
Answers have the .next tag, and when chosen it moves onto the next question as the code below shows (hopefully).
superContainer.find('.next').click(function () {
$(this).parents('.slide-container').fadeOut(500, function () {
$(this).next().fadeIn(500)
});
return false
});
The problem i have is if i use setInterval, i don't know how i can select the appropriate div again for fade it our and fade in the next one. I've tried the below code and a few similar scrappy idea's but it doesn't work, but maybe it will give a better idea of what I'm after though.
superContainer.find('.next').click(function () {
$active_count = $count;
countInterval = setInterval(function() {
$active_count--;
if($active_count <= 0){
clearInterval(countInterval);
$active_count = $count;
$(this).parents('.slide-container').fadeOut(500, function () {
$(this).next().fadeIn(500)
});
}
$('.question-timer').html($active_count);
}, 1000);
$(this).parents('.slide-container').fadeOut(500, function () {
$(this).next().fadeIn(500)
});
return false
});
I've only been using JQuery a day or two so excuse any obvious mistakes and bad code! Let me know if you need any other code or information
This is moderately tricky for a first jQuery project.
The knack (in this solution) is to factor out a goNext function that can be called in two ways - in response to a click event and in response to a 15 second setTimeout(), not setInterval().
$(function(){
var questionTimeout = null;
function goNext($el) {
clearTimeout(questionTimeout);
var $next = $el.next();
$el.fadeOut(500, function() {
if($next.length > 0) {
$next.fadeIn(500, function() {
questionTimeout = setTimeout(function() {
goNext($next);
}, 15000);
});
}
else {
afterLastQuestion();
}
});
}
function afterLastQuestion(){
alert("last question complete");
$start.show();
}
var $superContainer = $("#superContainer").on('click', '.next', function() {
goNext($(this).closest('.slide-container'));
return false;
});
var $start = $("#start").on('click', function(){
$(this).hide();
$superContainer.find(".slide-container")
.eq(0).clone(true,true)
.prependTo(superContainer)
.find(".next").trigger('click');
return false;
});
});
DEMO
The process is started by clicking a "start" link, causing the first question to be cloned followed by a simulated click on the clone's "next" link. This ensures that the (actual) first question is treated in exactly the same way as all the others.
I also included a afterLastQuestion() function. Modify its action to do whatever is necessary after the last question is answered (or times out).
You could keep the current question in a variable, resetting it on a next click and in the timer, e.g.
var $current;
superContainer.find('.next').click(function (e) {
e.preventDefault();
$(this).parents('.slide-container').fadeOut(500, function () {
$(this).next().fadeIn(500);
$current = $(this).next();
});
});​
You'll just need to set it to your first question on initialisation, and remember to reset your timer on a next click
Also, it's usually preferable to use e.preventDefault() rather than return false.

Categories

Resources