I am working with django , I want to scroll down auto when new messages added 'sent or received', I can scroll down auto when I refrech the page because of this code line :
$("#card-body").animate({ scrollTop: 20000000 }, "slow");
but when I send and I receive new messages the messages go down until I can't see them I have to scroll down manually
this is the js code :
<script>
/* send message*/
document.getElementById('send-btn-id').onclick = function (e) {
const msg = document.getElementById('message').value;
chatSocket.send(JSON.stringify({
'message': msg,
'user': me,
'friend': friendName
}));
document.getElementById('message').value = "";
};
const friendName = JSON.parse(document.getElementById('friend').textContent);
const me = JSON.parse(document.getElementById('me').textContent);
/* set friend profile name */
document.getElementById('friend-name').innerHTML = friendName['username'];
/* start conversation */
document.querySelector('.start-conversation').innerHTML = 'Start conversation with <strong>'+friendName['username']+'</strong>';
/* connection request */
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/chat/'
+ friendName['username']
+ '/'
);
chatSocket.onmessage = function (e) {
const data = JSON.parse(e.data);
var class_name = 'in';
var profile_image = '{{friend_obj.profile.image.url}}';
if(me['username'] == data.user['username']) {
data.user['username'] = 'Me';
class_name = 'out';
profile_image = '{{request.user.profile.image.url}}';
}
var chat_list = document.querySelector('#chat-list-id');
var chat = "<li class=\""+class_name+"\"><div class=\"chat-img\"><img alt=\"avatarchat\" src=\""+profile_image+"\"></div><div class=\"chat-body\"><div class=\"chat-message\"><h5>"+data.user['username']+"</h5><p>"+data.message+"</p></div></div></li>";
chat_list.innerHTML += chat;
};
</script>
If you want to do this easily, you can do the following:
window.scrollTo(0, document.body.scrollHeight);
Thanks to this post
WHAT YOU SHOULD NOT DO
window.scrollTo(0, 9999);
Even though the number is big, sometimes webpages can be VERY large.
BACK TO CONTENT
If you want it to scroll smoothly, then you can set this css property:
html {
scroll-behavior: smooth;
}
Working example:
const btmG = document.querySelector("#btm-good");
const btmB = document.querySelector("#btm-bad");
window.onload = () => {
btmG.onclick = () => {
window.scrollTo(0, document.body.scrollHeight);
};
btmB.onclick = () => {
window.scrollTo(0, 9999);
};
}
html {
scroll-behavior: smooth;
}
<button id="btm-good"> Scroll to bottom (not 9999) </button>
<button id="btm-bad"> Scroll to bottom (is 9999) </button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>Wait a sec, this isn't the bottom...<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
Hi
hello guys thanks to you I have found the solution and I want to share it with you and it works actually,so really thank you :
I thought that I can actually make this code line in the send, hold on you will understand after watching the code :
I have mentioned this before right
$("#card-body").animate({ scrollTop: 20000000 }, "slow");
and this one either :
/* send message*/
document.getElementById('send-btn-id').onclick = function (e) {
const msg = document.getElementById('message').value;
chatSocket.send(JSON.stringify({
'message': msg,
'user': me,
'friend': friendName
}));
document.getElementById('message').value = "";
};
so after watching your answers I think to put the line in the //send message like this :
/* send message*/
document.getElementById('send-btn-id').onclick = function (e) {
const msg = document.getElementById('message').value;
chatSocket.send(JSON.stringify({
'message': msg,
'user': me,
'friend': friendName
}));
document.getElementById('message').value = "";
$("#card-body").animate({ scrollTop: 20000000 }, "slow");
};
my english is not fine but the code works, I hope it helps someone facing same problem.
Related
Update 2: Apparently, bookmarklets as long as 2410 characters do work fully after all, which I tested with a script of the form javascript: var a=0; a++; a++; ... window.alert(a);. At 9424 characters, Chrome sync for the bookmarklet failed, but by copy/pasting the bookmark from an Email, I was still able to execute it. It remains unclear, why some scripts work when served as a script tag (see Update 1), but fail when executed from a javscript: URL directly.
Update 1: It looks like the same bookmarklet will work, by generating a <script/> tag pointing to the script hosted on dropbox. This only really leaves as explanation, that the browser engine on iOS has a hardcoded limit of less than 1024 characters for javascript: URLs.
Original Post
I am trying to figure out why some bookmarklets do nothing – not even trigger an error – on iOS, having no access to a Mac OS device.
For reference, consider the following two bookmarklets (formatted source below):
// DebugSimple.js
javascript:/* DebugSimple.js - 10:02:50 2019-12-23 */(function(){ document.body.innerHTML='';document.body.style.all='initial';function putString(string){document.body.innerText+=string;}const oldConsoleLog=console.log;console.log=function(...args){putString('(log) '+args.map(e=>e.toString()).join(' '));return oldConsoleLog(...args);};window.addEventListener('error',event=>{var msg='\n(err) ';msg+=!event ?'!!event = '+event :!event.error ?'!!event.error = '+event.error :!event.error.stack ?'!!event.error.stack = '+event.error.stack : event.error.stack;if(event&&event.error)for(const key in event.error){msg+='\nevent.error.'+key+'='+event.error[key];}putString(msg);});console.log("Log test.");setTimeout(backtraceTest,10);function backtraceTest(){backtraceTest2();}function backtraceTest2(){noSuchFunctionShouldExist();}})();undefined;
// DebugOverlay.js
javascript:/* DebugOverlay.js - 10:07:25 2019-12-23 */(function(){ const highestZIndex=Math.max(...Array.from(document.getElementsByTagName('*')).map(e=>window.getComputedStyle(e).zIndex).map(parseInt).filter(e=>!isNaN(e)));console.log(highestZIndex);function append(parent,html,callback=undefined){var e=document.createElement('DIV');parent.appendChild(e);e.outerHTML=html;e=parent.lastElementChild;if(callback)callback(e);return e;}const ifr=document.createElement('IFRAME');document.body.prepend(ifr);ifr.id='debugOverlay.js';ifr.style.all='initial';ifr.style.zIndex=highestZIndex+1;ifr.style.position='fixed';ifr.style.left='5%';ifr.style.right='5%';ifr.style.width='90%';ifr.style.height='90%';ifr.style.opacity='90%';ifr.style.backgroundColor='#ddd';ifr.style.border='1pt solid #888';ifr.contentDocument;ifr.contentDocument.open();ifr.contentDocument.close();const header=append(ifr.contentDocument.body,"<DIV id='header'/>",e=>{e.style.position='static';});const closeButton=append(header,"<A href='#' id='closeButton'>[CLOSE]</A>",e=>{e.addEventListener('click',()=>ifr.parentElement.removeChild(ifr));});const clearButton=append(header,"<A href='#' id='clearButton'>[CLEAR]</A>",e=>{e.addEventListener('click',()=>{output.innerHTML='';});});const output=append(ifr.contentDocument.body,"<DIV id='outputPane'/>",e=>{e.style.fontFamily='Sans';});append(ifr.contentDocument.body,"<DIV id='overScroll' style='height:30vh'/>");var fontSizeScale=0.8;function setOutputFontSize(scale){output.style.fontSize=(fontSizeScale*100)+'%';}setOutputFontSize(fontSizeScale);const fontSizePlus=append(header,"<A href='#' id='fontSizePlus'>[LGR]</A>",e=>{e.addEventListener('click',()=>{setOutputFontSize(fontSizeScale*=1.2);});});const fontSizeMinus=append(header,"<A href='#' id='fontSizePlus'>[SML]</A>",e=>{e.addEventListener('click',()=>{setOutputFontSize(fontSizeScale/=1.2);});});const toggleLog=append(header,"<A href='#' id='toggleLog'>[log(on)]</a>",e=>{var logVisibility=true;e.addEventListener('click',()=>{setLogVisibility(logVisibility=!logVisibility);});function setLogVisibility(bool){Array.from(output.getElementsByClassName('log')).forEach(ee=>{ee.style.display=bool ?'block':'none';e.innerText=bool ?'[log(on)]':'[log(off)]';});}setLogVisibility(logVisibility);});window.addEventListener('error',(evt)=>(addEntry(evt.error.stack)));function addEntry(string,category='error'){append(output,"<DIV class='entry "+category+"'/>",e=>{e.style.marginTop='0.5em';e.style.borderTop='1px solid #888';e.style.fontWeight=category=='error'?'bold':'';append(e,'<CODE/>',e=>{e.innerText=string;});});};const oldConsoleLog=console.log;console.log=function(...args){oldConsoleLog(...args);addEntry(args.join(' '),'log');};function testingIfErrorLogWorks_a(){testingIfErrorLogWorks_b();}function testingIfErrorLogWorks_b(){noSuchFunction();}setTimeout(testingIfErrorLogWorks_a,10);setTimeout(()=>console.log('LogTest'),20);setTimeout(testingIfErrorLogWorks_b,30);})();undefined;
I have added these as bookmarks on Google Chrome (Windows 10), and synchronized to iOS and Android.
On Android and Windows, both scripts work as expected:
DebugSimple.js replaces the body of the page by a log of errors with backtrace, and console.log invocations.
DebugOverlay.js ads an iframe overlay, where the errors are logged more cleanly.
On iOS, the simpler script DebugSimple.js will execute and log errors as expected, hence I know of that errors are being captured on iOS, albeit with less helpful output than on Android and Windows 10. This includes syntax errors, like typing javascript:}; into the URL bar (syntax error).
However, if I invoke the DebugOverlay.js script, even if I manually copy-paste it from the bookmarks, nothing happens at all; DebugSimple.js doesn't report any kind of error either.
I suspect, that it may be related to the length of the bookmarklet, as this behavior seems to occur for large bookmarklets mostly; But regardless, it seems strange that there is nothing at all, that would indicate the cause.
At this point I don't know how to proceed; Keep in mind that I don't have any Mac device.
Formatted source of DebugSimple.js
document.body.innerHTML = '';
document.body.style.all = 'initial';
function putString(string) {
document.body.innerText += string;
}
const oldConsoleLog = console.log;
console.log = function(...args) {
putString('(log) ' + args.map(e => e.toString()).join(' '));
return oldConsoleLog(...args);
};
window.addEventListener('error', event => {
var msg = '\n(err) ';
msg +=
!event ? '!!event = ' + event :
!event.error ? '!!event.error = ' + event.error :
!event.error.stack ? '!!event.error.stack = ' + event.error.stack :
event.error.stack;
if(event && event.error) for(const key in event.error) {
msg += '\nevent.error.' + key + '=' + event.error[key];
}
putString(msg);
});
// Test error.
console.log("Log test.");
setTimeout(backtraceTest,10);
function backtraceTest(){ backtraceTest2(); }
function backtraceTest2(){ noSuchFunctionShouldExist(); }
Formatted source of DebugOverlay.js
// DOES NOT WORK IN CHROME WHEN PASTED TO THE CONSOLE.
// The console messes somehow with error events.
// Should work when executed as bookmarklet or 'javascript:' URI.
const highestZIndex = Math.max(
...Array.from(document.getElementsByTagName('*'))
.map(e=>window.getComputedStyle(e).zIndex)
.map(parseInt)
.filter(e => !isNaN(e)));
console.log(highestZIndex);
function append(parent, html, callback = undefined) {
var e = document.createElement('DIV');
parent.appendChild(e);
e.outerHTML = html;
e = parent.lastElementChild;
if(callback) callback(e);
return e;
}
const ifr = document.createElement('IFRAME');
document.body.prepend(ifr);
ifr.id = 'debugOverlay.js';
ifr.style.all = 'initial';
ifr.style.zIndex = highestZIndex + 1;
ifr.style.position = 'fixed';
ifr.style.left = '5%';
ifr.style.right = '5%';
ifr.style.width = '90%';
ifr.style.height = '90%';
ifr.style.opacity = '90%';
ifr.style.backgroundColor = '#ddd';
ifr.style.border = '1pt solid #888';
// Firefox requires content to be initialized.
ifr.contentDocument;
ifr.contentDocument.open();
ifr.contentDocument.close();
const header = append(ifr.contentDocument.body, "<DIV id='header'/>", e => {
e.style.position = 'static';
});
const closeButton = append(header, "<A href='#' id='closeButton'>[CLOSE]</A>", e => {
e.addEventListener('click', () => ifr.parentElement.removeChild(ifr));
});
const clearButton = append(header, "<A href='#' id='clearButton'>[CLEAR]</A>", e => {
e.addEventListener('click', () => {
output.innerHTML = '';
});
});
const output = append(ifr.contentDocument.body, "<DIV id='outputPane'/>", e => {
e.style.fontFamily = 'Sans';
});
append(ifr.contentDocument.body, "<DIV id='overScroll' style='height:30vh'/>");
var fontSizeScale = 0.8;
function setOutputFontSize(scale) {
output.style.fontSize = (fontSizeScale * 100) + '%';
}
setOutputFontSize(fontSizeScale);
const fontSizePlus = append(header, "<A href='#' id='fontSizePlus'>[LGR]</A>", e => {
e.addEventListener('click', () => {
setOutputFontSize(fontSizeScale *= 1.2);
});
});
const fontSizeMinus = append(header, "<A href='#' id='fontSizePlus'>[SML]</A>", e => {
e.addEventListener('click', () => {
setOutputFontSize(fontSizeScale /= 1.2);
});
});
const toggleLog = append(header, "<A href='#' id='toggleLog'>[log(on)]</a>", e => {
var logVisibility = true;
e.addEventListener('click', () => {
setLogVisibility(logVisibility = !logVisibility);
});
function setLogVisibility(bool) {
Array.from(output.getElementsByClassName('log')).forEach(ee => {
ee.style.display = bool ? 'block' : 'none';
e.innerText = bool ? '[log(on)]' : '[log(off)]';
});
}
setLogVisibility(logVisibility);
});
window.addEventListener('error', (evt) => (addEntry(evt.error.stack)));
function addEntry(string, category='error') {
append(output, "<DIV class='entry "+category+"'/>", e => {
e.style.marginTop = '0.5em';
e.style.borderTop = '1px solid #888';
e.style.fontWeight = category == 'error' ? 'bold' : '';
append(e, '<CODE/>', e => { e.innerText = string; });
});
};
const oldConsoleLog = console.log;
console.log = function (...args) {
oldConsoleLog(...args);
addEntry(args.join(' '), 'log');
};
// For testing.
function testingIfErrorLogWorks_a() { testingIfErrorLogWorks_b(); }
function testingIfErrorLogWorks_b() { noSuchFunction(); }
setTimeout(testingIfErrorLogWorks_a,10);
setTimeout(()=>console.log('LogTest'), 20);
setTimeout(testingIfErrorLogWorks_b,30);
This is the jQuery code that basically opens and closes a div:
jQuery('#filter_werk').find('.raven-sortable').addClass('opened');
var toggle = document.getElementById('deknop');
var slider = document.querySelector('.raven-sortable');
toggle.addEventListener('click', toggleSlider, false);
function toggleSlider(){
if (slider.classList.contains('opened')) {
slider.classList.remove('opened');
slider.classList.add('closed');
} else {
slider.classList.remove('closed');
slider.classList.add('opened');
}
}
</script>
What I'm trying to do is change the content of the following div from "FILTER +" to "FILTER -" and back again to "FILTER +" when its clicked again
<div id="deknop">FILTER +</div>
Could this be done without breaking the current jQuery code?
Thank you!
As I understood the function toggleSlider works fine so try:
function toggleSlider(){
if (slider.classList.contains('opened')) {
slider.classList.remove('opened');
slider.classList.add('closed');
toggle.innerHTML = "FILTER +";
} else {
slider.classList.remove('closed');
slider.classList.add('opened');
toggle.innerHTML = "FILTER -";
}
}
You can add some logic to your toggleSlider() function that will change your #deknop text based on what it currently is (either ‘FILTER +’ or ‘FILTER -‘ like this:
function toggleSlider(){
$('#deknop').html($('#deknop').text() == 'FILTER +' ? 'FILTER -' : 'FILTER +');
if (slider.classList.contains('opened')) {
slider.classList.remove('opened');
slider.classList.add('closed');
} else {
slider.classList.remove('closed');
slider.classList.add('opened');
}
}
Well,
if I had to do this jQuery-style, I would either way try to separate the data from the view. Something like:
(() => {
const state = {
sliderOpen: true,
};
const $slider = $('.raven-sortable');
const $toggle = $('#deknop');
const updateView = () => {
if (state.sliderOpen) {
$slider.addClass('opened').removeClass('closed');
} else {
$slider.addClass('closed').removeClass('opened');
}
$toggle.text(`FILTER ${state.sliderOpen ? '+' : '-'}`);
};
const onToggleClick = () => {
state.sliderOpen = !state.sliderOpen;
updateView();
};
$toggle.click(onToggleClick);
updateView();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="raven-sortable">Raven sortable</button>
<button id="deknop"></button>
This is my code :
var newMailListener = {
msgAdded: function(aMsgHdr) {
if(!aMsgHdr.isRead) {
gFolderDisplay.selectMessage(aMsgHdr);
var uri = gFolderDisplay.selectedMessageUris;
alert(uri);
msgHdr = messenger.messageServiceFromURI(uri).messageURIToMsgHdr(uri);
alert(getMessageBody(msgHdr,uri));
goDoCommand("cmd_markAsRead");
}
}
};
function init() {
var ancienmsg = null;
var notificationService = Components.classes["#mozilla.org/messenger/msgnotificationservice;1"]
.getService(Components.interfaces.nsIMsgFolderNotificationService);
notificationService.addListener(newMailListener, notificationService.msgAdded);
}
addEventListener("load", init, true);
function getMessageBody(aMessageHeader, uri)
{
let messenger = Components.classes["#mozilla.org/messenger;1"] .createInstance(Components.interfaces.nsIMessenger);
alert("charge messenger");
let listener = Components.classes["#mozilla.org/network/sync-stream-listener;1"].createInstance(Components.interfaces.nsISyncStreamListener);
alert("charge listener");
messenger.messageServiceFromURI(uri)
.streamMessage(uri, listener, null, null, false, "");
let folder = aMessageHeader.folder;
alert("initialise messenger");
return folder.getMsgTextFromStream(listener.inputStream,
aMessageHeader.Charset,
65536,
32768,
false,
true,
{ });
}
It is supposed, according to the mozilla's documentation, to display, in an alert, the body of the mail received. But, every time during the return of the getMessageBody method, thunderbird crash and I need to restart it. Does anybody have an idea of why and how to display it ?
In another Stackoverflow question, I find this and it works for me.
Components.utils.import("resource:///modules/gloda/mimemsg.js");
var newMailListener = {
msgAdded: function(aMsgHdr) {
if( !aMsgHdr.isRead ){
MsgHdrToMimeMessage(aMsgHdr, null, function (aMsgHdr, aMimeMessage) {
// do something with aMimeMessage:
alert("the message body : " + aMimeMessage.coerceBodyToPlaintext());
//alert(aMimeMessage.allUserAttachments.length);
//alert(aMimeMessage.size);
}, true);
}
}
};
But you only get the text and not the HTML.
i've tried to create some notification message that should showing up anytime i have a new message. is done but the problem is if i refresh the browser then the message showing again. this is wrong. it should be hidden if already shows. does not matter if i refresh the browser again. it should be not show.
this is my code:
$(function(){
/* global MessageBus */
var name,
msgCube = $('.message_bus').data('queue') ;
MessageBus.ajax = function(args){
args["headers"]["X-NAME"] = name;
return $.ajax(args);
};
MessageBus.subscribe("/tasks" + msgCube, function(msg){
var obj = $.parseJSON(msg);
showMsg = function(){
var deffered = $.Deferred();
if(obj.state.viewed == 0){
dataModel = '<div class="msg">'
+ '<p>' + obj.task.name + '</p>'
+'<p>' + obj.task.description + '</p>';
$('.noticed').html(dataModel);
setTimeout(function () {
$(".noticed").fadeOut(300);
deffered.resolve();
}, 5000);
}
return deffered.promise();
};
//test don't show up after load
stopToLoad = function(){
console.log('load after');
$('.noticed').hide();
};
showMsg().then(function(){
stopToLoad();
});
//console.log(msg);
}, 0);
});
if you guys have an any sugestion, any solution, idea, i'll be glad and thanks for the Adviced.
best regard,
I am currently coding an instant chatbox using jquery which will show the latest chat on top (refreshes when user send data via post request)
and push the oldest chat downward and remove it.
The problem is that if more than one latest chat is retrieved(for example, 2), two new div will be prepended but only one oldest div is removed instead of two...I tried timeout but it didnt work either..
Below are the code snippets I believe which got problem in it.
function showData(currentchatstyle, data, final){
var newchatstyle;
if (currentchatstyle == "chatone") {
newchatstyle = "chattwo";
}
else {
newchatstyle = "chatone";
}
$('div[class^="chat"]:first').before('<div class="' + newchatstyle + '" style="display:none;">' + data + ' </div>');
$('div[class^="chat"]:first').slideDown(500,"swing", function(){
$('div[class^="chat"]').last().fadeOut(500, function() {
$(this).remove();
});
});
return newchatstyle;
}
$('input[name="content"]').keyup(function(key) {
if (key.which==13) {
var author = $('input[name="author"]').val();
var content = $('input[name="content"]').val();
var lastnum = $('postn:first').text();
var chatstyle = $('div[class^="chat"]:first').attr("class");
$.post(
"chatajax.php",
{ "author": author, "content": content, "lastnum": lastnum },
function(data) {
var msg = data.split("|~|");
for (var i = 0; i < msg.length; i++) {
chatstyle = showData(chatstyle, msg[i], true);
}
}
);
}
});
Help will be very much appreciated.
The problem is that you do select also currently-fading-out divs with $('div[class^="chat"]').last(), as you don't remove them immediately but in the animation callback. You for example might immediately remove the chat class so it won't be selected in the next call to showData.
Also, you should only use one class "chat" for a similar divs and for a zebra-style give them independent classes.
var chatstyle = "one";
function showData(data, final){
chatstyle = chatstyle=="one" ? "two" : "one";
var newDiv = $('<div class="chat '+chatstyle+'" style="display:none;">'+data+'</div>');
$('div.chat:first').before(newDiv);
newDiv.slideDown(500, "swing", function(){
$('div.chat:last').removeClass('chat').fadeOut(500, function() {
// ^^^^^^^^^^^^^^^^^^^^
$(this).remove();
});
});
}
function post(data) {
return $.post(
"chatajax.php",
data,
function(data) {
var msg = data.split("|~|");
for (var i = 0; i < msg.length; i++)
showData(msg[i], true); // what's "final"?
}
);
}
$('input[name="content"]').keyup(function(key) {
if (key.which==13)
post({
"author": $('input[name="author"]').val(),
"content": $('input[name="content"]').val(),
"lastnum": $('postn:first').text() // I'm sure this should not be extracted from the DOM
});
});