Sometimes the div doesn't get scrolledTop - javascript

So I'm trying to create my own chat with support to offline messages.
I can use it already, but sometimes when I send a message, the scroll doesn't move as it should, and if I want to see the message I just sent I have to scroll down a little bit. It keeps having different behavior everytime and that's what bothers me.
this is the script responsible for the scrolling whenever I send a message
success: function () {
//do something with response
var url = '/Chat/ReturnTeacherNewMessages?Student_id=' + '#ViewBag.Student_id';
$('#user_content').load(url);
$('#MSG').val("");
$.ajax({
success: function () {
var wtf = $('#user_content');
height = wtf[0].scrollHeight;
wtf.scrollTop(height);
}
})
}

Are you using Jquery? try using .scrollTop API
in your case it should look something like this :
$('#user_content').scrollTop(0);

How about this?
$('#user_content').load(url, function(){
$(this).scrollTop($(this).height());
});

Thanks for your help, I was able to solve this issue
this is what I did
success: function () {
//do something with response
var url = '/Chat/ReturnTeacherNewMessages?Student_id=' + '#ViewBag.Student_id';
$('#user_content').load(url);
$('#MSG').val("");
$.ajax({
success: function () {
setTimeout(function () {
var wtf = $('#user_content');
height = wtf[0].scrollHeight;
wtf.scrollTop(height);
}, 1000);
}
})
}
I know that maybe it's not the best solution, but it's the only thing that works untill now, and it works perfectly. I just need to force the thread to wait for a bit before scrollingTop.

Related

Check the div's height every 5 seconds and change class if true

I have this function already, which checks for change, and if true only updates this div.
jQuery(document).ready( function($) {
var auto_refresh = setInterval(function() {
$.ajax({
success: function(data) {
var result = $('<div />').append(data).find('div#vs').html();
$('div#vs').html(result);
}
})
}, 5000); // refreshing after every 5000 milliseconds
})
This works great, but now I want to add another function, I have made this javascript http://jsfiddle.net/jockebq/ocLh1rLd/
What it does is that if the height of the div #vs exceeds 300px it will add class .vscroll to #vs.
I have managed to make this work great in JSFiddle, but I cannot figure out how to merge this together with my javascript above.
I'm very much stuck, and I cannot find any information on how to do this. All help and tips are much appreciated!
I am sure i am missing something here but why not just
add it inside the function passed to setInterval and run it alongside the ajax call
var auto_refresh = setInterval(function() {
$.ajax({
success: function(data) {
var result = $('<div />').append(data).find('div#vs').html();
$('div#vs').html(result);
if (document.getElementById('vs').clientHeight > 300 )
$('div#vs').addClass('vscroll');
}
});
}, 5000); // refreshing after every 5000 milliseconds
})
PS: Your ajax better not be as you pasted it here!
EDIT: added the code in the success callback, since you probably want to resize when the new content is appended,as said by Pierre

jQuery AUTOMATIC scroll (no button click) on document ready

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

Ajax wont call when output from another ajax

I have comment system using live ajax php, and also include for vote system on that comment
Logic: when i post new comment, system will call ajax function with method post, and display response in above of textarea for comment, that response is include vote system (a class="with_unique_id"), but when i click that vote, it wont calling ajax function (nothing happend in browser console), whereas in current comment that displaying in above of new comment, it working fine.
This is my ajax code for vote
jQuery(document).ready(function($){
$(".voteMe").click(function() {
var voteId = this.id;
var upOrDown = voteId.split('_');
$.ajax({
type: "post",
url: "<?php echo base_url('blog/likepost');?>/"+upOrDown[0],
cache: false,
data:'voteId='+upOrDown[0] + '&upOrDown=' +upOrDown[1],
success: function(response){
try{
if(response=='true'){
var newValue = parseInt($("#"+voteId+'_result').text()) + 1;
$("#"+voteId+'_result').html(newValue);
document.getElementById('likeStatus_'+upOrDown[0]).innerHTML = 'Success';
$("#likeStatus_"+upOrDown[0]).show();
setTimeout(function() { $("#likeStatus_"+upOrDown[0]).hide(); }, 5000);
}else{
$("#likeStatus_"+upOrDown[0]).show();
document.getElementById('likeStatus_'+upOrDown[0]).innerHTML = 'Liked';
setTimeout(function() { $("#likeStatus_"+upOrDown[0]).hide(); }, 5000);
}
}catch(err) {
alert(err.message);
}
},
error: function(){
alert('Error while request..');
}
});
});
});
It took me a while to read your code, but I guess this is the root cause:
if(response=='true'){
var newValue = parseInt($("#"+voteId+'_result').text()) + 1;
$("#"+voteId+'_result').html(newValue);
document.getElementById('likeStatus_'+upOrDown[0]).innerHTML = 'Success';
$("#likeStatus_"+upOrDown[0]).show();
setTimeout(function() { $("#likeStatus_"+upOrDown[0]).hide(); }, 5000);
}
This line here:
$("#"+voteId+'_result').html(newValue);
That become the link you want to click again. Right?
If that is so, then you need to re-assign the event handler.
By replacing the DOM element, you have also removed the assigned event handler
PS: You code is very hard to read. It will be nightmare for you to maintain it.
i have fixed my code with adding same ajax code function in response of current ajax with different id.
thankyou

automatic clicks on links and doing something with every page's DOM

i have some links in a web page ,what i want to do :
Trigger click event on every link
When the page of every link is loaded , do something with page's DOM(fillProducts here)
What i have tried :
function start(){
$('.category a').each(function(i){
$.when($(this).trigger('click')).done(function() {
fillProducts() ;
});
})
}
Thanks
What you want to do is much more complicated than you seem to be giving it credit for. If you could scrape webpages, including AJAX content, in 7 lines of js in the console of a web browser you'd put Google out of business.
I'm guessing at what you want a bit, but I think you want to look at using a headless browser, e.g. PhantomJs. You'll then be able to scrape the target pages and write the results to a JSON file (other formats exist) and use that to fillProducts - whatever that does.
Also, are you stealing data from someone else's website? Cause that isn't cool.
Here's a solution that may work for you if they are sending their ajax requests using jQuery. If they aren't you're going to need to get devilishly hacky to accomplish what you're asking (eg overriding the XMLHttpRequest object and creating a global observer queue for ajax requests). As you haven't specified how they're sending the ajax request I hope this approach works for you.
$.ajaxSetup({
complete: function(jQXHR) {
if(interested)
//do your work
}
});
The code below will click a link, wait for the ajax request to be sent and be completed, run you fillProducts function and then click the next link. Adapting it to run all the clicks wouldn't be difficult
function start(){
var links = $('.category a');
var i = 0;
var done = function() {
$.ajaxSetup({
complete: $.noop//remove your handler
});
}
var clickNext = function() {
$(links.get(i++)).click();//click current link then increment i
}
$.ajaxSetup({
complete: function(jQXHR) {
if(i < links.length) {
fillProducts();
clickNext();
} else {
done();
}
}
});
clickNext();
}
If this doesn't work for you try hooking into the other jqXHR events before hacking up the site too much.
Edit here's a more reliable method in case they override the complete setting
(function() {
var $ajax = $.ajax;
var $observer = $({});
//observer pattern from addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjquery
var obs = window.ajaxObserver = {
subscribe: function() {
$observer.on.apply($observer, arguments);
},
unsubscribe: function() {
$observer.off.apply($observer, arguments);
},
once: function() {
$observer.one.apply($observer, arguments);
},
publish: function() {
$observer.trigger.apply($observer, arguments);
}
};
$.ajax = function() {
var $promise = $ajax.apply(null, arguments);
obs.publish("start", $promise);
return $promise;
};
})();
Now you can hook into $.ajax calls via
ajaxObserver.on("start", function($xhr) {//whenever a $.ajax call is started
$xhr.done(function(data) {
//do stuff
})
});
So you can adapt the other snippet like
function start(){
var links = $('.category a');
var i = 0;
var clickNextLink = function() {
ajaxObserver.one("start", function($xhr) {
$xhr.done(function(data) {
if(i < links.length) {
fillProducts();
clickNextLink();
} else {
done();
}
});
})
$(links.get(i++)).click();//click current link then increment i
}
clickNextLink();
}
try this:
function start(){
$('.category a').each(function(i){
$(this).click();
fillProducts() ;
})
}
I get ya now. This is like say:
when facebook loads, I want to remove the adverts by targeting specific class, and then alter the view that i actually see.
https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
Is a plugin for firefox, this will allow you to create a javascript file, will then allow you to target a specific element or elements within the html rendered content.
IN order to catch the ajax request traffic, you just need to catcher that within your console.
I can not give you a tutorial on greasemonkey, but you can get the greasemonkey script for facebook, and use that as a guide.
http://mashable.com/2008/12/25/facebook-greasemonkey-scripts/
hope this is it

Loading GIF while AJAX completes

This should be quite simple but I'll be darned if I can work it out. Just trying to get a div to display while my ajax is processing and then hide once done (I've put a sleep in there purely to test its working as locally it loads so fast I'm not sure if its working or not)!
The html page has this code in the script: -
$(document).ready(function(){
$("#loadingGIF").ajaxStart(function () {
$(this).show();
});
$("#loadingGIF").ajaxStop(function () {
window.setTimeout(partB,5000)
$(this).hide();
});
function partB(){
//just because
}
var scenarioID = ${testScenarioInstance.id}
var myData = ${results as JSON}
populateFormData(myData, scenarioID);
});
There is then a div in my page like so (which I can see in the source of the page just hidden): -
<div id="loadingGIF" ><img src='${application.contextPath}/images/spinner.gif' height="50" width="50"></div>
The ready code then goes off and calls this: -
function populateFormData(results, scenarioID) {
$table = $('#formList')
for(var i in results){
var formIDX = (results[i]["forms_idx"])
var formID = (results[i]["form_id"])
appendSubTable(formIDX, scenarioID, $table, formID);
}
}
Which references this multiple times calling several AJAX posts: -
function appendSubTable(formIDX, scenarioID, $table, formID) {
var $subTable = $table.find("#" + formIDX).find('td:eq(1)').find("div").find("table")
var url = "**Trust me this bits OK ;) **"
$.post(url, {
formIDX : formIDX, scenarioID : scenarioID, formID :formID
}, function(data) {
$subTable.append(data)
}).fail(function() {
});
}
Any pointers gratefully received...
Interestingly I bunged some alerts into my ajaxstart and stop and neither show up ever so I'm missing something obvious :S When I check the console in firefox I can see that all my POSTs are completing....
You should probably add the Ajaxstart and stop global event handlers to the document node like this
$(document).ajaxStart(function () {
$("#loadingGIF").show();
});
I realized my problem, I needed to register the ajaxstart and stop to the document not the div!
So instead of this: -
$("#loadingGIF").ajaxStart(function () {
$(this).show();
});
I now have: -
$(document).ajaxStart(function () {
$("#loadingGIF").show();
});
I assume this is because its the document that the ajax is running against not the div although my understanding there may not be 100% accurate at least this works so please tell me if I've misunderstood this! :)
#jbl, thanks for this pointer I did this to also leave the notification on screen for a few more moments just to make sure everything is loaded.

Categories

Resources