So I'm working on a project from a book where TaffyDB is used to create a collection of people. The project is a simple chatroom, where the list of users is generated as an html list of online users in the window. Currently I'm using fake data to test, and I have one for each loop (in jquery) that works correctly, printing five "avatars" to the screen.Yet, my each loop to print the online users runs twice: why is this? These two loops use the exact same setup, yet the second runs twice.
The for each that works:
people_db().each(function(person,idx){
var class_list;
if( person.get_is_anon() ){ return true; }
class_list = ['spa-avtr-box'];
if( person.id === chatee.id ){
class_list.push('spa-x-is-user');
}
$box = $('<div/>')
.addClass(class_list.join(' '))
.css( person.css_map )
.attr('data-id', String(person.id) )
.prop( 'title', spa.util_b.encodeHtml(person.name) )
.text( person.name )
.appendTo( $nav );
});
The loop that runs twice:
people_db().each(function(person,idx){
var select_class = '';
console.log(person);
if( person.get_is_anon() || person.get_is_user() ) {
return true;
}
if( chatee && chatee.id === person.id ){
select_class = 'spa-x-select';
}
list_html
+= '<div class="spa-chat-list-name'
+ select_class + '" data-id="' + person.id + '">'
+ spa.util_b.encodeHtml(person.name) + '</div>';
});
if( !list_html ){
list_html = String()
+ '<div class="spa-chat-list-note">'
+ 'To chat alone is the fate of all great souls...<br><br>'
+ 'No one is online'
+ '</div>';
clearChat();
}
jqueryMap.$list_box.html(list_html);
}
Any ideas what I'm doing wrong? I've gone through the rest of my code extensively and I'm not calling it twice, I'm almost certain is has to be something with the loop.
I'd start by making sure you're not calling it twice.
If you look at the console, does
console.log(person);
print twice?
If so unbind whatever is calling
people_db().each(function(person,idx){
before you bind it.
Related
Hi I have a simple question, do I need to specify lblWelcomeUserMessage.innerHTML = ""; ( see below in code ) in the following function before insertAdjacentHTML on it ? It actually works as it is without declaring it, but I want to know what is the optimal approach ?
// Dynamic HTML / user interface for ALL users
function showWelcomeMessage() {
//lblWelcomeUserMessage.innerHTML = "";
var sWelcomeUserMessage = '<h3>' + 'Welcome:' + ' ' + sessionStorage.getItem( 'name' ) +
' ' + sessionStorage.getItem( 'lastname' ) + ' ' + sessionStorage.getItem( 'role' ) + ' </h3>';
var iUserImage = '<img src=" ' + sessionStorage.getItem( 'image' ) + ' " width="50px">';
lblWelcomeUserMessage.insertAdjacentHTML( 'beforeend', sWelcomeUserMessage + iUserImage );
}
It depends on what you want to do.
If you are calling showWelcomeMessage function more than once then
you need to set it to empty lblWelcomeUserMessage.innerHTML = ""
function showWelcomeMessage() {
lblWelcomeUserMessage.innerHTML = "";
var sWelcomeUserMessage = '<h3>' + 'Welcome:' + ' ' + sessionStorage.getItem( 'name' ) +
' ' + sessionStorage.getItem( 'lastname' ) + ' ' + sessionStorage.getItem( 'role' ) + ' </h3>';
var iUserImage = '<img src=" ' + sessionStorage.getItem( 'image' ) + ' " width="50px">';
lblWelcomeUserMessage.insertAdjacentHTML( 'beforeend', sWelcomeUserMessage + iUserImage );
}
setInterval(showWelcomeMessage,4000);
OR
Otherwise you can remove lblWelcomeUserMessage.innerHTML = ""; from
above code
insertAdjacentHTML inserts some HTML around a node (lblWelcomeUserMessage, which you should have get before with something like lblWelcomeUserMessage = document.getElementById('welcome_tag')).
Setting it's inner content to an empty string is not really necessary, unless you want to clear it. It's rather a design issue than a programmatic one.
Optimal approach for what?
By the way based on MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
insertAdjacentHTML() parses the specified text as HTML or XML and
inserts the resulting nodes into the DOM tree at a specified position.
It does not reparse the element it is being used on and thus it does
not corrupt the existing elements inside that element. This avoids the
extra step of serialization, making it much faster than direct
innerHTML manipulation.
So it's basically depends on your needs. If you want to replace previous message you just add the lblWelcomeUserMessage.innerHTML = ""; , if you want to show all previous message just comment that code.
I have a PHP page that uses flush() and ob_flush() to output progress to a browser. The page is outputting a styled <ul class="progresslog"> where individual <li class="{success|warning|error}"> elements are being flushed to the browser.
I would like anything successful to be hidden, but anything with errors to show. At the moment, any errors are being "lost" in successful progress notifications. This is easily achieved with different classes on the <li> and some jQuery .slideUp() and .slideDown() methods to display the successes should the user wish to see them.
However, assuming successful progress, nothing will be displayed to the user, concerning them about whether there is any progress or not. I would like a summary link text to update as additional <li>'s are added to the list to show something along the lines of 22 success notifications. I would like this number to climb as output is received.
I have code to update the text contained in an <a id="progresslogtoggle"> element. It looks like this:
function updateProgress()
{
var count = $('.progresslog .success').length;
var warnings = $('.progresslog .warning').length;
var errors = $('.progresslog .error').length;
if (count > 0)
{
$('#progresslogtoggle').html ('Show ' + count + ' success notice' + (count != 1 ? 's' : '') + '. (' + warnings + ' warning' + (warnings != 1 ? 's' : '') + ' and ' + errors + ' error' + (errors != 1 ? 's' : '') + ' already shown)');
}
else
{
$('#progresslogtoggle').html ('There are no success notices to show! (' + warnings + ' warning' + (warnings != 1 ? 's' : '') + ' and ' + errors + ' error' + (errors != 1 ? 's' : '') + ' already shown)');
}
}
Currently, once the list is finished and the final </ul> is added, I also add a JavaScript snippet to call this updateProgress() function.
However, I would like to have the link updated as items are added to the list. I have tried:
$('.progresslog').on ('change', updateProgress());
but it does not seem to register adding children to the list as changing it.
How can I solve this problem?
Update:
PHP code (greatly simplified, but enough to illustrate the point):
echo "Please wait...</p>";
echo '<ul class="progresslog">';
// JS, as above, goes here, including an initial call to the function.
for ($i = 0; $i < 1000; $i ++)
{
// some lengthy process that takes time
sleep (1); // NOT REAL CODE!
echo '<li class="';
echo ($i % 5 == 0) ? 'warning' : 'success';
echo '">Notice ' . $i . '</li>';
flush ();
#ob_flush ();
}
echo "</ul>";
echo "<script type=\"text/javascript\">updateProgress();</script>";
Disclaimer: I realise that working with an incomplete DOM is bad, I don't wish to necessarily debate that issue here.
Try utilizing MutationObserver , observe childList of ul element.
See also this question.
The change method only works for input elements. For the DOM change you can use this:
$(".progresslog").bind("DOMSubtreeModified", function() {
alert("list changed");
});
I would like to achieve 2 things with this Code I have been working on so not sure if to separate the Questions:
JS:
function listPosts(data) {
postlimit =
var output='<ul data-role="listview" data-filter="true">';
$.each(data.posts,function(key,val) {
output += '<li>';
output += '<a href="#devotionpost" onclick="showPost(' + val.id + ')">';
output += '<h3>' + val.title + '</h3>';
output += '<p>' + excerpt + '</p>';
output += '</a>';
output += '</li>';
}); // go through each post
output+='</ul>';
$('#postlist').html(output);
} // lists all the posts
Questions:
1: I would like to limit the number of Dynamic List Posts returned to 8
2: While I limit the displayed items, I want to add a 'More...' text at the bottom so another set of 8 items is appended to already displayed list.
I am already trying out some codes but was hoping to get some guidance
function listPosts(data, postlimit) {
var $output = $('<ul class="posts" data-role="listview" data-filter="true">');
$.each(data.posts,function(key, val) {
$("<li>", {id: "post_" + val.id})
.append([
$("<h3>", {text: val.title}),
$("<p>", {text: val.excerpt})
])
.appendTo($output);
return (postlimit-- > 1);
});
$('#postlist').empty().append($output);
}
// exemplary delegated event handler
$(document).on("click", "ul.posts h3", function () {
$(this).show();
});
later ...
listPosts(data, 8);
Notes:
from $.each() you can return true or false. If you return false, the loop stops.
Try not to build HTML from concatenated strings. This is prone to XSS vulnerabilities that are easy to avoid. jQuery gives you the tools to build HTML safely.
Generally, for the same reason, try to avoid working with .html(), especially if you already have DOM elements to work with.
Don't use inline event handlers like onclick. At all. Ever.
I am answering you on basis of pure logic and implementation of logic. there could be API stuff for it , but I don't really know. Secondly; It would be a good solution to find some jQuery plugin if you don't have any problems with using jQuery.
call the function onMoreClick() upon clicking the More... html item
var end = 8;
var start = 1;
function onMoreClick()
{
start = end
end = end+8;
listPosts(data)
}
function listPosts(data) {
postlimit =
var output='<ul data-role="listview" data-filter="true">';
var i = start;
$.each(data.posts,function(key,val) {
if(i<end && i >=start){
output += '<li>';
output += '<a href="#devotionpost" onclick="showPost(' + val.id + ')">';
output += '<h3>' + val.title + '</h3>';
output += '<p>' + excerpt + '</p>';
output += '</a>';
output += '</li>';
i++;
}
}); // go through each post
output+='</ul>';
$('#postlist').html(output);
} // lists all the posts
I'm trying to get a javascript based "world clock" to run inside a pop up div that is shown with jQuery.
It works great when I look at it in the Dreamweaver Live View. But when I upload it to my server, the Javascript showClock(clockobj), which contains a document.write(...) command, executes immediately and rewrites the entire screen with the map. So, I took the showClock(clockobj) call out of the worldclock.html javascript and put it in the jQuery handler that opens the div. The map comes up with a click. But its not in the div. It takes over the whole screen.
How do I get it to display INSIDE the div, like all of the other buttons do on the page? (Tips, Converter, Add, Edit, Copy, etc,)
Here is the link, if you want to see what I'm doing:
http://www.bizzocall.com/cp-ManagePhone.php
Here's the JS:
<script src="http://www.clocklink.com/embed.js"></script><script type="text/javascript" language="JavaScript">
clockobj=new Object;clockobj.clockfile="world001-blue.swf";
clockobj.TimeZone="PST";
clockobj.width=480;
clockobj.height=250;
clockobj.wmode="transparent";
</script>
Here's the jQuery:
<script type="text/javascript">
$(function(){
// Dialog box
$('#worldclock').dialog({
autoOpen: false,
width: 540,
buttons: {
"Cancel": function() {
$(this).dialog("close");
}
}
});
// Dialog Link
$('#worldclockbtn').click(function(){
$('#worldclock').dialog('open');
showClock(clockobj);
return false;
});
});
</script>
The HTML:
<div id="worldclock" class="DialogBox">
<?php require_once('worldclock.html'); ?>
</div>
<div class="tiptxt" id="worldclockbtn" >WORLD CLOCK
<div class="arrowInCircle"></div>
</div>
Firstly get rid of one of your jqueries - you have several and different versions
they may be the reason for this error:
$("#picker").farbtastic is not a function
Source File: http://www.bizzocall.com/cp-ManagePhone.php
Line: 26
To handle a document.write, override it
var oldWrite = document.write;
var stringToWrite = ""; // this is polluting the window scope, but is for demo purposes ok
document.write=function(str) {
stringToWrite+=str
}
and use $("#someDiv").html(stringToWrite)
but looking at the JS, you can also just replace
function showBanner(BannerLink){
document.write(BannerLink);
}
with
function showBanner(BannerLink){
$("#someDiv").html(BannerLink);
}
update: replace the whole external script with
function showClock(obj){
//Aded by Takeshi Sugimoto on 2008/05/01 for SSL
var str = '';
if(obj.ssl == '1'){
str = '<embed src="https://secure.clocklink.com/clocks/';
}
else{
str = '<embed src="http://www.clocklink.com/clocks/';
}
//--
str += obj.clockfile;
str += "?";
for( prop in obj ) {
if( 'clockfile' == prop
|| 'width' == prop
|| 'height' == prop
|| 'wmode' == prop
|| 'type' == prop
) continue;
//Added by takeshi on 2007/01/29 (to display mutibyte chars by using URL encoding)
if(prop == "Title" || prop == "Message"){
str += ( prop + "=" + obj[prop] + "&" );
}
else{
str += ( prop + "=" + _escape(obj[prop]) + "&" );
}
//--
}
str += '" ';
str += ' width="' + obj.width + '"';
str += ' height="' + obj.height + '"';
str += ' wmode="' + obj.wmode + '"';
str += ' type="application/x-shockwave-flash">';
return str ;
}
function _escape(str){
str = str.replace(/ /g, '+');
str = str.replace(/%/g, '%25');
str = str.replace(/\?/, '%3F');
str = str.replace(/&/, '%26');
return str;
}
and do
$('#worldclock').html(showClock(clockobj)).dialog.....
I am having a bit of trouble with the Facebook JS SDK, specifically when using the FB.api() method. I have a list that gets populated from calling a php script using JQuery.get(), and with it, for each list item, comes the Facebook User ID. There are three types of "list items" that have different HTML for each, and I need to make a FB.api() call for each item, because each will come from a different user.
Here is the code I'm currently working with:
function( data ){
// Parse the json data
var parsed = jQuery.parseJSON( data );
// Create arrays for each message type
notifications = parsed.notifications;
gifts = parsed.gifts;
requests = parsed.requests;
// Counter and message to add
var i = 0;
var message = '';
var userData;
var displayPicUrl = '';
//
// NOTIFICATIONS
//
if( notifications && notifications.length > 0 ) {
// Loop through and create a new list item for each notification
for( i = 0; i < notifications.length; i++ ) {
// Get originator user data
FB.api( notifications[i].originator, function( response ) {
userData = response;
displayPicUrl = "http://graph.facebook.com/"+userData.id+"/picture";
message = '<li class="message">' +
'<img src="'+displayPicUrl+'" width="50" height="50" alt="Not one of the five birds I know." title="Not one of the five birds I know" />'+
'<p class="messageText">'+notifications[i].message+'.</p>' +
'<button class="acceptButton">Ok</button>' +
'</li>';
document.getElementById( 'notifications' ).innerHTML += message;
});
} //end loop
} //end if
//
// GIFTS
//
if( gifts && gifts.length > 0 ) {
// Loop through and create a list item for each gift
for( i = 0; i < gifts.length; i++ ) {
FB.api( gifts[i].originator, function( response ) {
if( !response || response.error ) {
alert( 'An error occured retrieving gifts')
} else {
userData = response;
displayPicUrl = "http://graph.facebook.com/"+userData.id+"/picture";
message = '<li class="message">' +
'<img src="'+displayPicUrl+'" width="50" height="50" alt="Not one of the five birds I know." title="Not one of the five birds I know" />'+
'<img class="giftImage" src="'+gifts[i].url+'" width="50" height="50" title="'+gifts[i].name+'" alt="'+gifts[i].name+'" />' +
'<p class="messageText">'+gifts[i].message+'</p>' +
'<button class="declineButton giftDecline">Decline</button>' +
'<button class="acceptButton giftAccept">Accept Gift</button>' +
'<span style="display:none;" id="giftId">'+gifts[i].giftId+'</span>' +
'</li>';
document.getElementById( 'gifts' ).innerHTML += message;
}
});
}
} // end if
//
// REQUESTS
//
if( requests && requests.length > 0 ) {
// Loop through and create a list item for each request
for( i = 0; i < requests.length; i++ ) {
FB.api( requests[i].originator, function( response ) {
if( !response || response.error ) {
alert( 'An error occured retrieving Requests' );
} else {
userData = response;
displayPicUrl = "http://graph.facebook.com/"+userData.id+"/picture";
message = '<li class="message">' +
'<img src="'+displayPicUrl+'" width="50" height="50" alt="Not one of the five birds I know." title="Not one of the five birds I know" />'+
'<img class="giftImage" src="'+requests[i].url+'" width="50" height="50" />' +
'<p class="messageText">'+requests[i].message+'</p>' +
'<button class="declineButton requestDecline">Decline</button>' +
'<button class="acceptButton requestAccept">'+requests[i].okButtonLabel+'</button>' +
'</li>';
document.getElementById( 'requests' ).innerHTML += message;
}
});
}
} // end if
The problem that I seem to be having is that once it hits the parts for Gifts and Requests, both the Gifts and Requests arrays become "undefined," which is odd because the code works perfectly fine when it's not wrapped in the callback of FB.api()... And, oddly enough, this problem does not seem to occur for the Notifications section. The gifts, requests, and notifications are just arrays of objects returned from the database as I said using JQuery.get() and there are no problems until I wrap the stuff in the api() method.
Any help would be greatly appreciated.
Cheers
If they are undefined only when wrapped in a FB.api() then your getting a facebook error. There are many reasons that this can happen, so its hard to pinpoint the exact cause, but I'll throw out a few ways that I deal with these:
Add an access token to your graph call, some facebook calls require it.
You need to make sure that you're application has the proper facebook code in it. For HTML include:
You also need to include this code in some document.ready sort of call:
//Facebook iFrame include
window.fbAsyncInit = function () {
FB.init({ appId: AppID, status: true, cookie: true, xfbml: true });
FB.Canvas.setAutoResize();
};
(function () {
var e = document.createElement('script');
e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
} ());
There may be a problem with how you set this up in facebook. Make sure that all URLs match. If they do not then your application will throw errors. This must be exact (www.ex.com and ex.com are different, and only one will work)
Make sure that under "On Facebook" Canvas URL and Tab URL match as well
Your graph call is wrong. Try adding an alert(displayPicUrl); call to your code, it may show you what errors you are getting. If that doesn't work, then try to reproduce the graph url call and enter that in yourself to see what that returns.
Hopefully one of those work