Code Newbie
News     Forums     Search     Members     Sign Up    

My Code Newbie
Username

Password

Articles/Snippets
ASP Classic
ASP.NET
C
C#
C++
HTML / CSS
Java
Javascript
Linux / BSD
Perl
PHP
Python
Ruby
SQL
VB 6
VB.NET

C.N. Friends
  Planet Rome

Link to Us!
Code Newbie
  Code Newbie
    forums
Go Back   Code Forums > Application and Web Development > HTML, XML, Javascript, AJAX
User Name
Password

Reply
 
LinkBack Thread Tools Display Modes
Old 02-23-2006, 07:17 AM   #1 (permalink)
l33t_1-1axx0r
Huzzah!
 
l33t_1-1axx0r's Avatar
 
Join Date: Feb 2006
Posts: 8
l33t_1-1axx0r is on a distinguished road
Send a message via AIM to l33t_1-1axx0r Send a message via MSN to l33t_1-1axx0r Send a message via Yahoo to l33t_1-1axx0r
AJAX n00b (Pretty involved issue, here!)

Hey guys,

Love the idea of these boards, first of all. Look forward to really getting into them as I'm always looking for ways to improve my own coding while trying to help others. I have some AJAX stuff here that I haven't quite grocked and would love to hear opinions on.

Okay, so maybe some of you vBulletin fans know about the AJAX Shoutbox

Pretty solid piece of coding....for a small forum. When you scale it upwards, however, it becomes increasingly buggy and inefficient, if not just draining on server resources. I have a number of ways I'm trying to improve the efficiency (i.e. adding a seperate column in the DB for tallying shouts as opposed to counting all rows everytime) but one particular issue escapes me and it's mainly due to my complete inexperience with AJAX and Javascript. Trying to learn both, but it's a slow process.

So here are some code snippets
(You can see a shoutbox implementation here: AMN Forums)

Shouting is a simple interactive with a form defined as follows:

Code:
<form action="vbshout.php?{$session['sessionurl']}" method="post" name="vbshoutform" onsubmit="return postShout(this)"> <input type='hidden' name='do' value='shout' /> <input type='hidden' name='color' /> <input type='hidden' name='fontFamily' /> <input type='hidden' name='fontWeight' /> <input type='hidden' name='textDecoration' /> <input type='hidden' name='fontStyle' />
And the AJAX/Javascript functions are here...

Code:
<script type='text/javascript'> <!-- postingShout = false function requestShouts() { if (!postingShout) { ShoutRequest = new vB_AJAX_Handler(true) ShoutRequest.onreadystatechange(showShouts) ShoutRequest.send('vbshout.php', 'nocache=' + (5 * Math.random() * 1.33) ) } } function showShouts() { if (ShoutRequest) { if (ShoutRequest.handler.readyState == 4 && ShoutRequest.handler.status == 200 && ShoutRequest.handler.responseText) { Shouts = fetch_object('vbshout') Shouts.innerHTML = '<table cellpadding="1" cellspacing="3" border="0" width="95%" align="left">' + ShoutRequest.handler.responseText + '</table>' setTimeout('requestShouts()', 20000) <if condition="$vboptions[shout_messages_order]"> document.getElementById('vbshout').scrollTop = 99999; </if> } } } function sb_CollectHV(sbForm) { rString = '' inputObjs = sbForm.getElementsByTagName('input') for (i = 0; i < inputObjs.length; i++) { if (inputObjs[i].type == 'hidden' && inputObjs[i].value != '') { rString += '&' + inputObjs[i].name + '=' + PHP.urlencode(inputObjs[i].value) } } return rString } function postShout(formObj) { doShout = new vB_AJAX_Handler(true) doShout.onreadystatechange(postedShout) if (postingShout) { alert('Posting in progress..') return false } Shout = formObj.shout.value if (Shout.replace(/ /g, '') == '') { alert('You must enter a shout!') return false } doShout.send('vbshout.php', 'do=shout&shout=' + PHP.urlencode(Shout) + sb_CollectHV(document.forms['vbshoutform'])) sb_Clear() postingShout = true return false } function postedShout() { if (doShout.handler.readyState == 4 && doShout.handler.status == 200) { postingShout = false requestShouts() } } function sb_Input_SC(sProperty, setting) { eval('document.forms["vbshoutform"].shout.style.' + sProperty + ' = "' + setting + '"') eval('document.forms["vbshoutform"].' + sProperty + '.value = "' + setting + '"') } function getSelectionValue(eSelector) { return eSelector.options[eSelector.options.selectedIndex].value == 'Default' ? '' : eSelector.options[eSelector.options.selectedIndex].value } function sb_PropChange(eSelector, sProperty) { sb_Input_SC(sProperty, getSelectionValue(eSelector)) } function sb_PropChange_Button_Value(sProperty) { trueValue = '' switch (sProperty) { case 'fontWeight': falseValue = 'bold' break; case 'textDecoration': falseValue = 'underline' break; case 'fontStyle': falseValue = 'italic' break; } return (eval('document.forms["vbshoutform"].' + sProperty + '.value'))? trueValue : falseValue } function sb_PropChange_Button(cButton, sProperty) { if (cButton.value.match(/\*/)) { cButton.value = cButton.value.replace(/\s+\*/, '') } else { cButton.value = cButton.value + ' *' } sb_Input_SC(sProperty, sb_PropChange_Button_Value(sProperty)) } function sb_Smilie(code) { document.forms["vbshoutform"].shout.value += ' ' + code return false } function sb_Clear() { document.forms["vbshoutform"].shout.value = '' return true; } function sb_Smilies(cButton) { if (cButton.value.match(/\*/)) { cButton.value = cButton.value.replace(/\s+\*/, '') } else { cButton.value = cButton.value + ' *' } document.getElementById('shout_emo').style.display = (document.getElementById('shout_emo').style.display == 'none')? '' : 'none' } requestShouts() --> </script>
So I can kind of understand whats happening here. When you submit a shout, it goes to postShout, creates a new AJAX handler, etc etc etc. What I do notice is that where a lot of other AJAX code involves passing entire html pages back and forth under the covers (stop me if I'm wrong), but here there seems to be just the single shout being passed through the AJAX.

Also, one of the major issues I'm having is that if you post a shout, then post another shout before the previous shout went through, the shoutbox deadlocks and won't refresh anymore. It has to do with the "isPosting" flag but I don't know any AJAX methods to force a call through... I guess it's getting hung up on the server end? Would it be worth it to implement a stack on the server end of things where shouts can be pushed until they can be popped out?

Here's the vbshout.php shout function, too.

Code:
// --------------------------------------------------- // Grab Latest X Shouts // --------------------------------------------------- if ($_GET['do'] == 'latest') { $NumShouts = $vbulletin->options['shout_display']; //For readability's sake $Output = array(); $Shouts = $DB->query(' select s.*, u.username, u.usergroupid from '.TABLE_PREFIX.'shout s left join '.TABLE_PREFIX.'user u on (u.userid = s.s_by) order by s.sid desc limit ' . $NumShouts); while ($Shout = $DB->fetch_array($Shouts)) { $Shout['time'] = buildTime($Shout['s_time']); $Shout['s_shout'] = bbcodeparser($Shout['s_shout']); $Shout['style'] = ''; $Shout['data'] = unserialize($Shout['s_data']); $Shout['username'] = fetch_musername($Shout, 'usergroupid'); if ($Shout['data']['color']) { $Shout['style'] .= 'color:'.$Shout['data']['color'].';'; } if ($Shout['data']['font']) { $Shout['style'] .= 'font-family:'.$Shout['data']['font'].';'; } if ($Shout['data']['bold']) { $Shout['style'] .= 'font-weight:'.$Shout['data']['bold'].';'; } if ($Shout['data']['underline']) { $Shout['style'] .= 'text-decoration:'.$Shout['data']['underline'].';'; } if ($Shout['data']['italic']) { $Shout['style'] .= 'font-style:'.$Shout['data']['italic'].';'; } if ($Shout['style']) { $Shout['s_shout'] = '<font style="'.$Shout['style'].'">'.$Shout['s_shout'].'</font>'; } eval('$Output[] .= "' . fetch_template('forumhome_vbshout_shout') . '";'); } if (isBanned($vbulletin->userinfo) && $vbulletin->options['shout_banned_perms'] > 0) { $Output = ''; $Shout = array( 'time' => buildTime(), 'username' => 'System Reponse', 's_shout' => 'You are currently banned from the shoutbox', ); eval('$Output .= "' . fetch_template('forumhome_vbshout_shout') . '";'); } if (empty($Output)) { $Output = ''; $Shout = array( 'time' => buildTime(), 'username' => 'System Reponse', 's_shout' => 'No Current Shouts', ); eval('$Output .= "' . fetch_template('forumhome_vbshout_shout') . '";'); } else { if ($vbulletin->options['shout_messages_order']) { $Output = array_reverse($Output); } $Shouts = $Output; $Output = ''; foreach ($Shouts as $Shout) { $Output .= $Shout; } } unset($Shouts, $Shout); echo $Output; exit; } // --------------------------------------------------- // End Latest X Shouts // --------------------------------------------------- // --------------------------------------------------- // Shout // --------------------------------------------------- if ($_POST['do'] == 'shout') { $vbulletin->input->clean_array_gpc('p', array( 'shout' => TYPE_NOHTML, 'color' => TYPE_NOHTML, 'fontFamily' => TYPE_NOHTML, 'fontWeight' => TYPE_NOHTML, 'fontStyle' => TYPE_NOHTML, 'textDecoration' => TYPE_NOHTML, )); $meShout = 0; if (!empty($vbulletin->GPC['shout']) && $vbulletin->userinfo['userid'] > 0 && !isBanned($vbulletin->userinfo)) { $ShoutData = addslashes(serialize(array( 'color' => addslashes(convert_urlencoded_unicode($vbulletin->GPC['color'])), 'font' => addslashes(convert_urlencoded_unicode($vbulletin->GPC['fontFamily'])), 'bold' => addslashes(convert_urlencoded_unicode($vbulletin->GPC['fontWeight'])), 'italic' => addslashes(convert_urlencoded_unicode($vbulletin->GPC['fontStyle'])), 'underline' => addslashes(convert_urlencoded_unicode($vbulletin->GPC['textDecoration'])), ))); $vbulletin->GPC['shout'] = convert_urlencoded_unicode($vbulletin->GPC['shout']); if (($vbulletin->GPC['shout'] = execCommand($vbulletin->GPC['shout'])) !== true) { $DB->query(" insert into ".TABLE_PREFIX."shout (s_time, s_by, s_shout, s_data, s_me) values (".TIMENOW.", {$vbulletin->userinfo['userid']}, '".addslashes($vbulletin->GPC['shout'])."', '{$ShoutData}', $meShout) "); $DB->query("UPDATE ".TABLE_PREFIX."user SET shouts = shouts + 1 WHERE userid = {$vbulletin->userinfo['userid']}"); } } exit; } // --------------------------------------------------- // End Shout // ---------------------------------------------------
It's a lot to read through if you're interested, but I don't have anything specific I'm looking for other than ways to tackle this problem. I don't need someone to write the AJAX for me, per se, but a good lead on some sources would be awesome and some ideas on the best, most efficient implementation would be awesome

__________________
l33t_1-1axx0r is offline   Reply With Quote
Old 02-23-2006, 08:48 AM   #2 (permalink)
sde
Moderator
 
sde's Avatar
 
Join Date: May 2002
Location: us.ca
Posts: 4,397
sde is on a distinguished road
i don't have time to look throught he code, but from what you're saying, it seems like the main problem is with the hang on the double submission.

my opinion would be to tackle it from the client side in the javascript. if there is a 'isposting' variable that gets set to true when you submit a shout, and then false when the server call returns data, ... then use that to prevent an ajax call from being sent in the first place. maybe cheezy, but the most dramatic example i could give would be to display an alert box if they try a double post.
__________________
sde is online now   Reply With Quote
Old 02-23-2006, 08:59 AM   #3 (permalink)
l33t_1-1axx0r
Huzzah!
 
l33t_1-1axx0r's Avatar
 
Join Date: Feb 2006
Posts: 8
l33t_1-1axx0r is on a distinguished road
Send a message via AIM to l33t_1-1axx0r Send a message via MSN to l33t_1-1axx0r Send a message via Yahoo to l33t_1-1axx0r
That is indeed one of the main issues I'm tackling, and that's the way it is handled. In fact, there's even an alert box that tells them that posting is in progress. However, the problem lies in that after seeing the alert box, they can't post again unless they do a complete page refresh. So the alert box may as well say "Oops, you screwed up. Refresh the whole page if you want to post again."
__________________
l33t_1-1axx0r is offline   Reply With Quote
Old 02-23-2006, 09:10 AM   #4 (permalink)
sde
Moderator
 
sde's Avatar
 
Join Date: May 2002
Location: us.ca
Posts: 4,397
sde is on a distinguished road
ok, i see that in the code. it looks like an empty shout is handled the same way, so my question is: does an empty shout break the script too?

what browser are you using. if not FF, i recommend you try it in firefox with the javascript console up to see if anything is being reported.
__________________
sde is online now   Reply With Quote
Old 02-23-2006, 09:35 AM   #5 (permalink)
l33t_1-1axx0r
Huzzah!
 
l33t_1-1axx0r's Avatar
 
Join Date: Feb 2006
Posts: 8
l33t_1-1axx0r is on a distinguished road
Send a message via AIM to l33t_1-1axx0r Send a message via MSN to l33t_1-1axx0r Send a message via Yahoo to l33t_1-1axx0r
I've used it with just about every browser to test it. I don't have the javascript console but good idea, I'll give that a whirl.

Another weird bug is that when people use Mozilla (Not firefox, Mozilla), then the AJAX breaks as soon as they try to shout. AKA, as long as they don't talk, they see shouts refreshing. As soon as they talk, the chat freezes. :/
__________________
l33t_1-1axx0r is offline   Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT -8. The time now is 12:08 AM.


Powered by vBulletin Version 3.6.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.0.0 RC8





Copyright © 2000-2006, Milano Interactive
Web Hosting provided by Portal 360 Web Hosting
Open Circle