AJAX Appending instead of using .HTML for my chat - javascript

So basically, my chat right now works like this:
Every 2nd second it checks for my PHP file, loadchat.php.
Loadchat.php will get every row that is newer than their session.
It then replaces all current data in my div: #chatbox by using
.html() function.
Now here is the deal.
This seems very resource heavy, to load all the rows again and again and again.
I know there is a way to optimize this, by using .append() function.
All though, I can't seem to wrap my head around it.
I need to make some kind of a counter, or a timestamp when the last message was loaded to check if there is newer content (rows) than since last time it loaded, if there is, append that new content.
If I replace the .html function with .append, I will just keep getting the same messages over and over again, as right now.
How would I go about making this?
Thanks in advance.
//AJAX Timeout Loop Load Chat Function:
function loadChat() {
$.ajax({
method: 'POST',
url: 'ajax/load_chat.php',
success: function(data) {
$('#chatbox').html(data);
//console.log($('#chatbox')[0].scrollHeight - $('#chatbox').innerHeight());
//console.log($('#chatbox').scrollTop());
if(atBottom) {
$("#chatbox").stop().animate({ scrollTop: $('#chatbox')[0].scrollHeight}, 500);
}
},
});
}
EXAMPLE OF WHAT LOADCHAT WILL SEND BACK:
<script type="text/javascript">var imAdmin = true</script>
<div data-chat-sid="76561198216640736" data-chat-msid="76561198216640736" data-chat-sun="deinhoin" class="chat-box__content--single chat-box--mychat">
<div class="chat-box__content__single--avatar">
<div class="admin" style="background-image:url(https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/83/83b9e88c1f88451dcc97d2537416bbd413247ad6_full.jpg);"><span>Mod</span></div>
</div>
<div class="chat-box__content__single--title">deinhoin</div>
<div class="chat-box__content__single--message">adada</div>
</div>
It should only send the var imAdmin variable once. (works with .html()).

Try using .slice()
// `section` : container for chat message elements
var html = $("section div");
// `data` : `html` returned from server
var data = "<div>1</div><div>2</div><div>3</div>";
// if `data` `.length` greater than existing `section` `div` `.length`,
if ($(data).length > $(html).length) {
// `.slice()` elements greater than existing `section div` length
var newdata = $(data).slice($(html).length);
// append new elements to `section div`
$("section").append(newdata);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<section>
<div>1</div><div>2</div>
</section>

Try making use of the 'data' attribute. You could have something like 'data-timestamp' on each chat item and use that to work out what was placed when.

Related

JavaScript ignore missing DOM element/event

I am developing a new application where different pages has different DOM element like Map page has some map specific element and Message page has message specific. To reduce the number of requests, I am combining all scripts to one file and put into footer.
But the problem is that when I am on Map Page, getting error for the missing elements that are only exists on Message page, I believe I am missing something very easy but I could not figure it out.
You can use try and catch if you don't want your script stops.
i.e.
try{
var test = document.getElementById("someelementthatdontexsist");
alert(test.innerHTML);
}
catch(err){};
so as Esko suggested you need to use "if" to check if you are on right page to run appropriate code.
sample:
var PageName = document.getElementsByTagName('body');
document.getElementById("check_button").addEventListener('click', function () {
if (PageName[0].getAttribute('id') == "map_page") {
//do map_page things
document.getElementById("page_name").innerText = PageName[0].getAttribute('id');
}
if (PageName[0].getAttribute('id') == "message_page") {
//do message_page things
document.getElementById("page_name").innerText = PageName[0].getAttribute('id');
}
});
<body id="map_page">
<button id="check_button">Check page</button>
<span id="page_name">test
</span>
</body>

Javascript updates content asynchronously

I wonder how it is possible that using javascript, images can be loaded asynchronously by changing the src of the img element after the page has been loaded. I thought that AJAX is for things like that(getting data from server without refreshing the page). Please clarify why it is working that way. The images are on server side, so I thought that i should refresh the page before the result will be visible.
Here is a sample code:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
var photos = ["baloon", "game", "cliff"];
function changePhoto() {
var input=document.getElementById("ph1");
var iValue=input.value.trim();
for(var tmp in photos) {
if(photos[tmp] === iValue){
var img=document.getElementById("photo");
img.setAttribute("src", "img/"+iValue+".jpg");
}
}
}
</script>
</head>
<body>
<input class="form-control" id="ph1" type="text" onkeyup="">
<p>Photo: <span id="txtHint" onclick="changePhoto()"></span></p>
</div>
<div class="container" id="photocontainer">
<img id="photo">
</div>
</body>
</html>
The user agent simply sends a GET request in response to the changing of the src attribute, the same that is done when a page loads initially.
AJAX is a technology that allows for asynchronous requests in JavaScript on the client. Browsers can make any requests they want at any time, as in this case, but without AJAX that couldn't be done in client-side code loaded by a website.
For example, I just changed the src property of an element in a page through Chrome Developer Tools and watched the GET request execute.
What you're doing in your code is not Ajax. Is simple javascript.
To make this work with Ajax you need a server side aplication that actually renders the image or get the contents from an existing file, and after that you show your loaded file on the browser.
Look for a jQuery ajax calls.
On the return of the call you can put your code.
Like this:
$.ajax({
url: "SomeUrl/SomeMethod/"
})
.done(function (response) {
//Do stuff here with the response to show the image
});
When you change src atrribute of an img element browser automatically starts downloading this image asynchronously.
Your code is almost ok. You iterate through array incorrectly.
You can try doing it this way instead:
var photos = ["baloon", "game", "cliff"];
function changePhoto() {
var input=document.getElementById("ph1");
var iValue=input.value.trim();
if(photos.indexOf(iValue) > -1) {
var img=document.getElementById("photo");
img.setAttribute("src", "img/"+iValue+".jpg");
}
}
Iterating through array
You can iterate through array for example like this:
for(var i=0; i<photos.length; i++) {
var photo = photos[i];
//...
}
or like this:
for(var k in Object.keys(photos)) {
var photo = photos[k];
//...
}

jquery page load to get another page content, mouseover how to load once

I have a few pages, like a1.html, a2.html, a3.html, a4.html, a5.html....
All pages HTML Markup looks like
<div class="wrap">
<header>Header 2</header>
<saection>Section 2</section>
<footer>
<div class="hover"></div>
</footer>
</div>
so when onhover a1.html .hover class, then page loads a2.html .wrap and appendTo a1.html's body, on the same page, now we have a2.html's contents. when on hover a2.html 's '.hover' (still on a1.html) then loads a3.html's contents and so forth
$('.hover').on('mouseover', function(){
$.get( "/a2.html", function( data ){
///a2.html should be a variable
$('section', data).appendTo('body');
});
});
My question is how to just load a2.html, a3.html or a4.html contents just once when onhover .hover class. How do I test if a2.html is already loaded then, do not load it again? Thanks
Try something like that.
$('.hover').on('mouseover', function(){
if (!$(this).data('active')) {
$(this).data('active', true);
$.get( "/a2.html", function( data ){
///a2.html should be a variable
$('section', data).appendTo('body');
});
}
});
Using the data-set to store a flag (active here), let you the possibility to remove it later and to process again the handler instructions.
If you really want to load it once (and never ever later), replace on by one in your code (as told by #SSS).
$('.hover').one('mouseover', function(){
$.get( "/a2.html", function( data ){
///a2.html should be a variable
$('section', data).appendTo('body');
});
});
Be careful : the way you are using on (or one) binds the mouseover event only on existing DOM elements.
If you want to affect all existing and future DOM elements. You got to use it this way :
$('body').on('mouseover', '.hover', function(){
/// your instructions
});
Hope that will help.
The simplest way is $(..).one(event, handler). But what if you really need to do something after loading once and only once in an a asynchronized and promised way?
I have implemented a cards ui application facing the same problem: card defined in another html file which must be loaded and only once before update/show its content. My resolution is based on jQuery Promises API and a simple cache. Wish helpful and here is part of my code (the real one is much more complicated):
function expect(proc) {
var cache = {};
return function(key) {
if (!cache[key]) {
cache[key] = $.Deferred(function(deferred) {proc(deferred, key); })
.promise();
}
return cache[key];
};
}
var cards = expect(function(deferred, url) {
var $loader = $('div');
function whenDone() {
deferred.resolve(loader.contents());
}
$loader.load(url).then(whenDone);
});
cards('MyCard.html').done(function(contents) {
// It is promised that MyCard is loaded, do what you want here
});

Click all links on page containing string?

I'm trying to add a function to a toolbar Chrome extension I've made. What I'd like it to do is once a navigate to a particular page I'd like be able to push a button on the tool bar and have it "click" all of the links on that page containing harvest.game?user=123456 with 123456 being a different number for all of the links. It could be using jquery or javascript. The only catch is that the script will need to be inserted as an element to the head of the page as cross domain scripting is not allowed so no external references to a js file. I can handle the adding of the element but, I'm having no luck figuring out the actual function.
The elements containing the links all look like this:
<div class="friendWrap linkPanel">
<h5>Christine...</h5>
<div class="friend-icon">
<img src="https://graph.facebook.com/100001726475148/picture"></div>
<div class="levelBlock friend-info">
<p>level</p>
<h3 class="level">8</h3></div>
Harvest
<a class="boxLink" href="profile.game?user_id=701240"><span></span></a></div>
Something like this (I know this is a mess and doesn't work)? OR maybe something BETTER using jquery?
var rlr=1;
function harvestall(){var frt,rm,r,rld,tag,rl;
var frt=1000;
r=document.getElementsByClassName("friendWrap linkPanel");
rl=r.length;
rld=rl-rlr;
if(rld>=0){tag=r[rld].getElementsByTagName('a');
if (rl>=1 {rlr++;harvestall();}
else if (rl>=1) {tag[1].onclick();do something??? ;}
}
Something like this should work
$("a[href*='harvest.game?user=']").trigger("click");
// Using jQuery, wait for DOMReady ...
$(function harvestLinks() {
// Only create regexp once ...
var reURL = /harvest.game\?user=/,
// Create a ref variable for harvest links ...
// Use 'links' later without querying the DOM again.
links = $("a").filter(
function() {
// Only click on links matching the harvest URL ...
return this.href && reURL.test(this.href);
}
).click();
});

Get html from element from iFrame every 10 seconds

So i've been looking around for a while for a possible solution to make a javascript, jquery which searches in the iFrame for a certain class or id element. Then takes out the html inside of it. (example. <a id="link">Here's a link</a> ). then makes it a string out of it and also replay this function every 5 second or so. Is there anyone who know a good solution to this or a tutorial?
I've tried the function var inf = $('#iframeid').contents().find('#theid').html();but it didn't gave any success.
Try this:
function GetFrameData() {
var $MyFrame = $("#iframeid");
// You need to wait for the iFrame content to load first
// So, that the click events work properly
$MyFrame.load(function () {
var frameBody = $MyFrame.contents().find('body');
var inf = frameBody.find('#theid').html();
});
}
// Call the function every 5 seconds
setInterval(GetFrameData, 5000);

Categories