Joomla2.5 framework seems to be interfering with javascript syntax - javascript

The below code works perfectly outside of Joomla2.5. as well as in earlier versions of Joomla , but fails when it's within a Joomla2.5 article, or rendered by a Joomla2.5 plugin.
The line in question is this one.
s1.addVariable('playlistfile', 'http://www.myserver.com/playlist.php?s=123&u=789
It returns an XML playlist which the player normally loads and plays as expected, but is the cuplprit because using a hardcoded file name with an XML extention works properly. I've tried all the usual encoding routines, but with no luck. Is there an approach, or syntax, that will work from within Joomla2.5?
Full Context:
<script type='text/javascript'>
var s1 = new SWFObject('http://www.myserver.com/v5.7/player.swf', 'player', '420', '315', '9.0.124', '#FFFFFF');
s1.addParam('allowfullscreen', 'true');
s1.addParam('allowscriptaccess', 'always');
s1.addVariable('streamer', 'rtmp://streaming.myserver.com/');
s1.addVariable('playlistfile', 'http://www.myserver.com/playlist.php?s=123&u=789');
s1.write('mediaspace1');
</script>
Also, I'm aware that there are newer, and other ways of loading the JW Player, but this is an interim step of converting many, many sites, and some legacy code must be retained.

Among the "usual encoding", have you tried "encodeURIComponent()" while adding the playlistfile variable? Not sure if PHP encoding would accomplish it, but Flash will not handle it correctly otherwise.

Related

Why does jquery return different values than the values submitted?

Update:
Please see the answer noted below as, ultimately, the problem had nothing to do with jsquery.
=============
Issue:
I submit an object to jquery to convert into a serialized string that will become part of a "POST" request to a server, and the data returned from the serialization request is different than the data sent on many occasions.
An example:
The JavaScript code that implements the server POST request:
function send_data(gpg_data) {
var query_string;
query_string = '?' + $.param(gpg_data, traditional = true);
console.log('gpg_data =', gpg_data)
console.log('query_string =', query_string);
$.post(server_address + query_string);
return;
}
This is the structure sent to the jquery param() function.
(copied from the browser console in developer mode.)
gpg_data =
{controller_status: 'Connected', motion_state: 'Stopped', angle_dir: 'Stopped', time_stamp: 21442, x_axis: 0, …}
angle_dir: "Stopped"
controller_status: "Connected"
force: 0
head_enable: 0
head_x_axis: 0
head_y_axis: 0
motion_state: "Stopped"
time_stamp: 21490
trigger_1: 0
trigger_2: 0
x_axis: 0
y_axis: "0.00"
. . . and the returned "query string" was:
query_string = ?controller_status=Connected&motion_state=Stopped&angle_dir=Stopped&time_stamp=21282&x_axis=0&y_axis=0.00&head_x_axis=0&head_y_axis=0&force=0&trigger_1=1&trigger_2=1&head_enable=0
The data received by the server is:
ImmutableMultiDict([('controller_status', 'Connected'), ('motion_state', 'Stopped'), ('angle_dir', 'Stopped'), ('time_stamp', '21282'), ('x_axis', '0'), ('y_axis', '0.00'), ('head_x_axis', '0'), ('head_y_axis', '0'), ('force', '0'), ('trigger_1', '1'), ('trigger_2', '1'), ('head_enable', '0')])
For example, note that "trigger_1" returns 1 when the data sent to it is a zero.
I have tried setting the query to "traditional = true" to revert to an earlier style of query handling as some articles suggested - which did not work.  I tried this with jquery 3.2 and 3.6.
I am not sure exactly how jquery manages to munge the data so I have no idea where to look.
I have looked at my script and at the unpacked jquery code, and I can make no sense out of why or how it does what it does.
Any help understanding this would be appreciated.
P.S.
web searches on "troubleshooting jquery" returned very complex replies that had more to do with editing e-commerce web pages with fancy buttons and logins than with simply serializing data.
P.P.S.
I am tempted to just chuck the jquery and write my own serialization routine. (grrrr!)
===================
Update:
As requested, a link to the browser-side context.
To run: unpack the zip file in a folder somewhere and attach an analog joystick/gamepad to any USB port, then launch index.html in a local browser.  Note that a purely digital gamepad - with buttons only or with a joystick that acts like four buttons - won't work.
You will want to try moving joystick axes 1 and 2, (programmatically axes 0 and 1) and use the first (0th) trigger button.
You will get a zillion CORS errors and it will complain bitterly that it cannot reach the server, but the server side context requires a GoPiGo-3 robot running GoPiGo O/S 3.0.1, so I did not include it.
Note: This does not work in Firefox as Firefox absolutely requires a "secure context" to use the Gamepad API.  It does work in the current version of Chrome, (Version 97.0.4692.99 (Official Build) (64-bit)), but throws warnings about requiring a secure context.
Please also note that I have made every attempt I know how to try to troubleshoot the offending JavaScript, but trying to debug code that depends on real-time event handling in a browser is something I have not figured out how to do - despite continuous searching and efforts.  Any advice on how to do this would be appreciated!
======================
Update:
Researching debugging JavaScript in Chrome disclosed an interesting tidbit:
Including the line // #ts-check as the first line in the JavaScript code turns on additional "linting" (?) or other checks that, (mostly) were a question of adding "var" to the beginning of variable declarations.
However. . . .
There was one comment it made:
gopigo3_joystick.x_axis = Number.parseFloat((jsdata.axes[0]).toFixed(2));
gopigo3_joystick.y_axis = Number.parseFloat(jsdata.axes[1]).toFixed(2);
I could not assign gopigo3_joystick.y_axis to a string object, (or something like that), and I was scratching my head - that was one of the pesky problems I was trying to solve!
If you look closely at that second line, you will notice I forgot a pair of parenthesis, and that second line should look like this:
gopigo3_joystick.y_axis = Number.parseFloat((jsdata.axes[1]).toFixed(2));
Problem solved - at least with respect to that problem.
I figured it out and it had nothing to do with jquery.
Apparently two things are true:
The state of the gpg_data object's structure is "computed", (snapshot taken), the first time the JavaScript engine sees the structure and that is the state that is saved, (even though the value may change later on). In other words, that value is likely totally bogus.
Note: This may only be true for Chrome. Previous experiments with Firefox showed that these structures were updated each time they were encountered and the values seen in the console were valid. Since Firefox now absolutely requires a secure context to use the gamepad API, I could not use Firefox for debugging.
I was trying to be "too clever". Given the following code snippet:
function is_something_happening(old_time, gopigo3_joystick) {
if (gopigo3_joystick.trigger_1 == 1 || gopigo3_joystick.head_enable == 1) {
if (old_time != Number.parseFloat((gopigo3_joystick.time_stamp).toFixed(0))) {
send_data(gopigo3_joystick)
old_time = gopigo3_joystick.time_stamp
}
}
return;
}
The idea behind this particular construction was to determine if "something interesting" is happening, where "something interesting" is defined as:
A keypress, (handled separately)
A joystick movement if either the primary trigger or the pinky trigger is pressed.
Movement without any trigger pressed is ignored so that if the user accidentally bumps against the joystick, the robot doesn't go running around.
Therefore the joystick data only gets updated if the trigger is pressed. In other words, trigger "release" events - the trigger is now = 0 - are not recorded.
The combination of these two events - Chrome taking a "snapshot" of object variables once and once only, (or not keeping them current) - and the trigger value persisting, lead me to believe that jquery was the problem since the values appeared to be different on each side of the jquery call.

How can I decode this obfuscated javascript?

I am in the process of setting up a blog through blogger.com and used a template from veethemes.com to get me started.
However, I noticed that there's an obfuscated script in the template and I'd prefer to know what it does to ensure that nothing untowards or unwanted is being done.
The code is as follows:
var _0x378a=["\x6B\x20\x45\x28\x73\x2C\x6E\x29\x7B\x79\x20\x73\x2E\x77\x28\x2F\x3C\x5C\x2F\x3F\x28\x3F\x21\x53\x5C\x73\x2A\x5C\x2F\x3F\x29\x5B\x61\x2D\x7A\x5D\x5B\x61\x2D\x54\x2D\x39\x5D\x2A\x5B\x5E\x3C\x3E\x5D\x2A\x3E\x2F\x4C\x2C\x22\x22\x29\x2E\x4B\x28\x2F\x5C\x73\x2B\x2F\x29\x2E\x31\x37\x28\x30\x2C\x6E\x2D\x31\x29\x2E\x5A\x28\x27\x20\x27\x29\x7D\x6B\x20\x31\x31\x28\x65\x2C\x74\x2C\x6E\x2C\x68\x2C\x63\x2C\x62\x2C\x71\x29\x7B\x35\x20\x72\x3D\x6A\x2E\x66\x28\x65\x29\x3B\x35\x20\x69\x3D\x6A\x2E\x66\x28\x6E\x29\x3B\x35\x20\x63\x3D\x63\x3B\x35\x20\x62\x3D\x62\x3B\x35\x20\x73\x3D\x22\x22\x3B\x35\x20\x6F\x3D\x72\x2E\x31\x39\x28\x22\x41\x22\x29\x3B\x35\x20\x61\x3D\x58\x3B\x35\x20\x70\x3D\x22\x22\x3B\x35\x20\x31\x36\x3D\x22\x75\x2E\x4D\x28\x57\x2E\x38\x2C\x20\x27\x31\x30\x27\x2C\x20\x27\x31\x32\x3D\x59\x2C\x20\x31\x33\x3D\x31\x34\x2C\x20\x31\x38\x3D\x78\x2C\x20\x31\x35\x3D\x78\x2C\x20\x4F\x2C\x20\x4E\x27\x29\x3B\x20\x79\x20\x50\x3B\x22\x3B\x49\x28\x6F\x2E\x51\x3E\x3D\x31\x29\x7B\x73\x3D\x27\x3C\x33\x20\x36\x3D\x22\x56\x2D\x55\x22\x3E\x3C\x61\x20\x38\x3D\x22\x27\x2B\x74\x2B\x27\x22\x3E\x3C\x41\x20\x36\x3D\x22\x52\x22\x20\x76\x3D\x22\x27\x2B\x6F\x5B\x30\x5D\x2E\x76\x2E\x77\x28\x2F\x73\x5C\x42\x5C\x64\x7B\x32\x2C\x34\x7D\x2F\x2C\x27\x73\x27\x2B\x31\x6F\x29\x2B\x27\x22\x20\x31\x71\x3D\x22\x22\x2F\x3E\x3C\x2F\x61\x3E\x3C\x2F\x33\x3E\x27\x3B\x61\x3D\x31\x73\x7D\x35\x20\x67\x3D\x27\x3C\x33\x20\x36\x3D\x22\x31\x72\x22\x3E\x3C\x33\x20\x36\x3D\x22\x31\x74\x22\x3E\x3C\x33\x20\x36\x3D\x22\x43\x22\x3E\x3C\x37\x20\x36\x3D\x22\x31\x61\x22\x3E\x27\x2B\x62\x2B\x27\x3C\x2F\x37\x3E\x3C\x37\x20\x36\x3D\x22\x31\x70\x22\x3E\x3C\x61\x20\x38\x3D\x22\x27\x2B\x74\x2B\x27\x23\x31\x6D\x22\x3E\x27\x2B\x63\x2B\x27\x3C\x2F\x61\x3E\x3C\x2F\x37\x3E\x3C\x2F\x33\x3E\x3C\x44\x3E\x3C\x61\x20\x38\x3D\x22\x27\x2B\x74\x2B\x27\x22\x3E\x27\x2B\x6E\x2B\x27\x3C\x2F\x61\x3E\x3C\x2F\x44\x3E\x3C\x33\x20\x36\x3D\x22\x43\x20\x31\x66\x22\x3E\x3C\x37\x20\x36\x3D\x22\x71\x22\x3E\x31\x65\x20\x31\x6E\x20\x27\x2B\x71\x2B\x27\x3C\x2F\x37\x3E\x3C\x37\x20\x36\x3D\x22\x68\x22\x3E\x31\x64\x20\x27\x2B\x68\x2B\x27\x3C\x2F\x37\x3E\x3C\x2F\x33\x3E\x3C\x2F\x33\x3E\x27\x2B\x73\x2B\x27\x3C\x33\x20\x36\x3D\x22\x31\x62\x22\x3E\x3C\x70\x3E\x27\x2B\x45\x28\x72\x2E\x6D\x2C\x61\x29\x2B\x27\x20\x5B\x2E\x2E\x2E\x2E\x2E\x5D\x3C\x2F\x70\x3E\x3C\x2F\x33\x3E\x3C\x2F\x33\x3E\x27\x3B\x72\x2E\x6D\x3D\x67\x7D\x3B\x75\x2E\x31\x63\x3D\x6B\x28\x29\x7B\x35\x20\x65\x3D\x6A\x2E\x66\x28\x22\x31\x67\x22\x29\x3B\x49\x28\x65\x3D\x3D\x31\x68\x29\x7B\x75\x2E\x31\x6C\x2E\x38\x3D\x22\x4A\x3A\x2F\x2F\x46\x2E\x47\x2E\x6C\x22\x7D\x65\x2E\x48\x28\x22\x38\x22\x2C\x22\x4A\x3A\x2F\x2F\x46\x2E\x47\x2E\x6C\x2F\x22\x29\x3B\x65\x2E\x48\x28\x22\x31\x6B\x22\x2C\x22\x31\x6A\x22\x29\x3B\x65\x2E\x6D\x3D\x22\x31\x69\x2E\x6C\x22\x7D","\x7C","\x73\x70\x6C\x69\x74","\x7C\x7C\x7C\x64\x69\x76\x7C\x7C\x76\x61\x72\x7C\x63\x6C\x61\x73\x73\x7C\x73\x70\x61\x6E\x7C\x68\x72\x65\x66\x7C\x7C\x7C\x74\x61\x67\x7C\x63\x6F\x6D\x6D\x65\x6E\x74\x7C\x7C\x7C\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64\x7C\x7C\x64\x61\x74\x65\x7C\x7C\x64\x6F\x63\x75\x6D\x65\x6E\x74\x7C\x66\x75\x6E\x63\x74\x69\x6F\x6E\x7C\x63\x6F\x6D\x7C\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C\x7C\x7C\x7C\x7C\x61\x75\x74\x68\x6F\x72\x7C\x7C\x7C\x7C\x77\x69\x6E\x64\x6F\x77\x7C\x73\x72\x63\x7C\x72\x65\x70\x6C\x61\x63\x65\x7C\x32\x34\x7C\x72\x65\x74\x75\x72\x6E\x7C\x7C\x69\x6D\x67\x7C\x7C\x6D\x65\x74\x61\x7C\x68\x32\x7C\x73\x74\x72\x69\x70\x54\x61\x67\x73\x7C\x77\x77\x77\x7C\x76\x65\x65\x74\x68\x65\x6D\x65\x73\x7C\x73\x65\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\x7C\x69\x66\x7C\x68\x74\x74\x70\x7C\x73\x70\x6C\x69\x74\x7C\x69\x67\x7C\x6F\x70\x65\x6E\x7C\x72\x65\x73\x69\x7A\x61\x62\x6C\x65\x7C\x73\x63\x72\x6F\x6C\x6C\x62\x61\x72\x73\x7C\x66\x61\x6C\x73\x65\x7C\x6C\x65\x6E\x67\x74\x68\x7C\x61\x72\x74\x69\x63\x6C\x65\x5F\x69\x6D\x67\x7C\x62\x72\x7C\x7A\x30\x7C\x6D\x65\x64\x69\x61\x7C\x70\x6F\x73\x74\x7C\x74\x68\x69\x73\x7C\x73\x75\x6D\x6D\x61\x72\x79\x5F\x6E\x6F\x69\x6D\x67\x7C\x35\x35\x30\x7C\x6A\x6F\x69\x6E\x7C\x77\x69\x6E\x64\x6F\x77\x4E\x61\x6D\x65\x7C\x72\x6D\x7C\x77\x69\x64\x74\x68\x7C\x68\x65\x69\x67\x68\x74\x7C\x36\x30\x30\x7C\x74\x6F\x70\x7C\x70\x6F\x70\x75\x70\x7C\x73\x6C\x69\x63\x65\x7C\x6C\x65\x66\x74\x7C\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x73\x42\x79\x54\x61\x67\x4E\x61\x6D\x65\x7C\x61\x72\x74\x69\x63\x6C\x65\x5F\x74\x61\x67\x73\x7C\x61\x72\x74\x69\x63\x6C\x65\x5F\x65\x78\x63\x65\x72\x70\x74\x7C\x6F\x6E\x6C\x6F\x61\x64\x7C\x6F\x6E\x7C\x70\x6F\x73\x74\x65\x64\x7C\x70\x6F\x73\x74\x5F\x6D\x65\x74\x61\x7C\x61\x74\x74\x72\x69\x5F\x62\x75\x74\x69\x6F\x6E\x7C\x6E\x75\x6C\x6C\x7C\x56\x65\x65\x54\x68\x65\x6D\x65\x73\x7C\x64\x6F\x66\x6F\x6C\x6C\x6F\x77\x7C\x72\x65\x6C\x7C\x6C\x6F\x63\x61\x74\x69\x6F\x6E\x7C\x63\x6F\x6D\x6D\x65\x6E\x74\x73\x7C\x62\x79\x7C\x37\x30\x30\x7C\x61\x72\x74\x69\x63\x6C\x65\x5F\x63\x6F\x6D\x6D\x65\x6E\x74\x73\x7C\x73\x74\x79\x6C\x65\x7C\x61\x72\x74\x69\x63\x6C\x65\x5F\x63\x6F\x6E\x74\x61\x69\x6E\x65\x72\x7C\x73\x75\x6D\x6D\x61\x72\x79\x69\x7C\x61\x72\x74\x69\x63\x6C\x65\x5F\x68\x65\x61\x64\x65\x72","","\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","\x72\x65\x70\x6C\x61\x63\x65","\x5C\x77\x2B","\x5C\x62","\x67"];
eval(function(_0x6c60x1,_0x6c60x2,_0x6c60x3,_0x6c60x4,_0x6c60x5,_0x6c60x6)
{_0x6c60x5=function(_0x6c60x3){return (_0x6c60x3<_0x6c60x2?_0x378a[4]:_0x6c60x5(
parseInt(_0x6c60x3/_0x6c60x2)))+((_0x6c60x3=_0x6c60x3%_0x6c60x2)>35?String[_0x378a[5]]
(_0x6c60x3+29):_0x6c60x3.toString(36))};if(!_0x378a[4][_0x378a[6]]
(/^/,String)){while(_0x6c60x3--){_0x6c60x6[_0x6c60x5(_0x6c60x3)]=_0x6c60x4[_0x6c60x3]||_0x6c60x5(_0x6c60x3)};
_0x6c60x4=[function(_0x6c60x5){return _0x6c60x6[_0x6c60x5]}];_0x6c60x5=function(){return _0x378a[7]};_0x6c60x3=1;};
while(_0x6c60x3--){if(_0x6c60x4[_0x6c60x3])
{_0x6c60x1=_0x6c60x1[_0x378a[6]]( new
RegExp(_0x378a[8]+_0x6c60x5(_0x6c60x3)+_0x378a[8],_0x378a[9]),
_0x6c60x4[_0x6c60x3])}};return _0x6c60x1;}(_0x378a[0],62,92,_0x378a[3]
[_0x378a[2]](_0x378a[1]),0,{}));
I was able to decode the first part using ddecode.com and came up with the following:
var _0x378a=["k E(s,n){y s.w(/<\/?(?!S\s*\/?)[a-z][a-T-9]*[^<>]*>/L,"").K(/\s+/).17(0,n-1).Z(' ')}k 11(e,t,n,h,c,b,q){5 r=j.f(e);5 i=j.f(n);5 c=c;5 b=b;5 s="";5 o=r.19("A");5 a=X;5 p="";5 16="u.M(W.8, '10', '12=Y, 13=14, 18=x, 15=x, O, N'); y P;";I(o.Q>=1){s='<3 6="V-U"><a 8="'+t+'"><A 6="R" v="'+o[0].v.w(/s\B\d{2,4}/,'s'+1o)+'" 1q=""/></a></3>';a=1s}5 g='<3 6="1r"><3 6="1t"><3 6="C"><7 6="1a">'+b+'</7><7 6="1p"><a 8="'+t+'#1m">'+c+'</a></7></3><D><a 8="'+t+'">'+n+'</a></D><3 6="C 1f"><7 6="q">1e 1n '+q+'</7><7 6="h">1d '+h+'</7></3></3>'+s+'<3 6="1b"><p>'+E(r.m,a)+' [.....]</p></3></3>';r.m=g};u.1c=k(){5 e=j.f("1g");I(e==1h){u.1l.8="J://F.G.l"}e.H("8","J://F.G.l/");e.H("1k","1j");e.m="1i.l"}","|","split","|||div||var|class|span|href|||tag|comment|||getElementById||date||document|function|com|innerHTML||||author||||window|src|replace|24|return||img||meta|h2|stripTags|www|veethemes|setAttribute|if|http|split|ig|open|resizable|scrollbars|false|length|article_img|br|z0|media|post|this|summary_noimg|550|join|windowName|rm|width|height|600|top|popup|slice|left|getElementsByTagName|article_tags|article_excerpt|onload|on|posted|post_meta|attri_bution|null|VeeThemes|dofollow|rel|location|comments|by|700|article_comments|style|article_container|summaryi|article_header","","fromCharCode","replace","\w+","\b","g"];
If I remove the script, the site breaks in certain places like Read More no longer cuts off the article on the home page and post headers are no longer visible, etc.
Any help in decoding this or tips on tools that may be available that would help me would be much appreciated.
Just remove eval in the code and throw it in the developer console.

PreloadJS cannot find audio

I'm working on hobby project. I'm using createjs. But, of course, I have a problem. Since I update the code to use Preloadjs, the browser can no longer find the audio files. Here is my loading code:
function load (canvasToShowProgress) {
canvas = canvasToShowProgress;
loadingStage = new createjs.Stage();
loadQueue = new createjs.LoadQueue(true);
progessText = new createjs.Text("Loading... 0%");
loadingStage.addChild(loadingStage);
loadingStage.update();
//start loading
loadQueue.installPlugin(createjs.Sound);
loadQueue.setMaxConnections(4); // Allow 4 concurrent loads
loadQueue.loadManifest("configuration/GameAssets.json");
loadQueue.on("progress", handleProgress);
loadQueue.on("complete",handleComplete);
}
My manifest GameAssets.json looks like this:
{"manifest":
[ {"src":"images/game/street.png", "id":"street"},
{"id":"Default", "src":"sounds/game/background.ogg"},
{"id":"Psychic", "src":"sounds/game/ps.ogg"},
{"id":"Nitro", "src":"sounds/game/ntr.ogg"}
]
}
By the way, the image is loaded perfectly. In the music player class, I call the audio by simply doing soundInstance = createjs.Sound.play(soundIds[currentPlayIndex]);. (The soundIds is temporary a hardcoded array with the ids. Where is my mistake?
First, I just want to confirm you are using the latest 0.6.0 releases of both SoundJS and PreloadJS (they need to be used together).
Currently only Firefox and Chrome support Ogg, so if you are using another browser you would need to provide and alternate format (mp3 is currently the most broadly supported) and set it up using SoundJS.alternateExtensions.
If you are still having loading errors, you'd likely need to dig into the errors a little more to determine the cause.
Hope that helps.
Your soundIds array declare like this
var soundIds=["Default","Psychic","Nitro"]
then call it like that
createjs.Sound.play(soundIds[0]);

How do I load an external file and make sure that it runs first in JSFiddle?

I have a JsFiddle here, and added Microsoft AJAX to be loaded through external JS/resource section. How can I tell whether or not my JS code is run after the AJAX file has finished loading?
Seems that the AJAX does not load either. :(
Here is the code in the JSFiddle:
Type.registerNamespace("Tutorial.Chapter1");
Tutorial.Chapter1.Person = function(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
};
Tutorial.Chapter1.Person.prototype = {
set_firstName: function(value) {
this._firstName = value;
},
get_firstName: function() {
return this._firstName;
},
set_lastName: function(value) {
this._lastName = value;
},
get_lastName: function() {
return this._lastName;
},
_firstName: "",
_lastName: "",
displayName: function() {
alert("Hi! " + this._firstName + " " + this._lastName);
}
};
Tutorial.Chapter1.Person.registerClass("Tutorial.Chapter1.Person", null);
The External Resources tab of jsFiddle is currently somewhat tricky and unstable to use.
The resources defined here are often not correctly included into the code. There seems to be an issue with the automatic recognition of JS and CSS resources. If this happens, the external resource is simply not added to the head section of the resulting code. You can check that by reviewing the source code of the Result frame of your jsFiddle. You will find that your MS AJAX resource is simply NOT mentioned in the resulting HTML code.
The correct recognition can actually be forced by adding a dummy value to the resource's URL like this (see –>jsFiddle docs for more info):
...&dummy=.js
Here is an example that shows how to add the external Google Maps API resource to a jsFiddle (mind the dummy parameter at the very end!):
https://maps.googleapis.com/maps/api/js?sensor=false&dummy=.js
Unfortunately this won't work for you as the MS AJAX URL will fail when additional parameters are appended.
A solution (and currently the safest way to load external resources) is to avoid the External Resources tab altogether and load external code manually in the first line(s) of jsFiddle's HTML window like this:
<script type='text/javascript' src="http://ajax.aspnetcdn.com/ajax/3.5/MicrosoftAjax.js"></script>
Here is your jsFiddle modified to use that method: http://jsfiddle.net/rEzW5/12/
It actually does not do a lot (I did not check what is wrong with the rest of your code), but at least it does not throw JavaScript errors anymore.
Open "Add Resources" section and add the url of your external script...
#Jpsy's approach no longer seems to work (see my comment under his answer).
For me, adding the resource under External Resources also didn't work. (According to the Firefox Debugger, it couldn't find the resource).
The only way I was able to get an external bit of JavaScript code (in my case jquery.backstretch.js) to work, was to use Google to find a Fiddle which used this resource (and worked), then Fork this Fiddle and copy/paste all my code into the HTML, CSS and JavaScript panels. Ugh!
#clayRay, You absolutely went thru a code surgery. Just resolved that by mentioning external source in plain html which in my case is
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
Using External Resources tab didn't help a bit...

What other options for replacing entire HTML document via W3C DOM?

I am curious about people's experiences with replacing the entire document at runtime in an Ajax web app. It's rare, but I've found a few situations where the app requires an entire page rebuild and everything is present locally without needing another server round-trip.
I can easily prepare the new document as either a new DOM tree or as a String. So I'm evaluating the trade-offs for various approaches.
If I want to use the String approach this seems to work:
document.open();
document.write(newStringDoc);
document.close();
Most browsers do this just fine, but many have a slight flicker when re-rendering. I've noticed that on the 2nd time through Firefox 4.0b7 will just sit there and spin as if it is loading. Hitting the stop button on the location bar seems to complete the page render. (Edit: this appears to be fixed in 4.0b8) Also this method seems to prevent the user from hitting refresh to reload the current URL (it reloads the dynamically generated page).
If I use a new DOM tree approach (which has different advantages/disadvantages in flexibility and speed), then this seems to work:
document.replaceChild(newDomDoc, document.documentElement);
Most browsers seem to handle this perfectly fine without flicker. Unfortunately, IE9 beta throws "DOM Exception: HIERARCHY_REQUEST_ERR (3)" on replaceChild and never completes. I haven't tried the latest preview release to see if this is just a new bug that got fixed. (Edit: this appears to be fixed in RC1.)
My question: does anyone have a different approach than either of these? Does anyone have any other caveats where perhaps a particular browser fundamentally breaks down with one of these approaches?
Update: Perhaps this will add context and help the imagination. Consider a situation where an application is offline. There is no server available to redirect or refresh. The necessary state of the application is already loaded (or stored) client-side. The UI is constructed from client-side templates.
I believe that Gmail uses iframes embedded within a root document. It appears the starting document for at least some of these iframes are just a bare HTML5 document which the parent document then manipulates.
Using an iframe would be another variant on the requirement to replace the current document by replacing the entire child iframe or just its document. The same situation exists though of what approach to attach the new document to the iframe.
I guess I will answer this with my own findings as I'm wrapping up my research on this.
Since the two browsers which have issues with one of these methods are both beta, I've opened bug reports which hopefully will resolve those before their full release:
Firefox 4 Beta: https://bugzilla.mozilla.org/show_bug.cgi?id=615927
Edit: Fixed in FF 4b8.
Internet Explorer 9 Beta: https://connect.microsoft.com/IE/feedback/details/626473
Edit: Fixed in IE9 RC1.
I've also found pretty consistently that this...
document.replaceChild(newDomDoc, document.documentElement);
...is 2-10x faster than this...
var doc = document.open("text/html");
doc.write(newStringDoc);
doc.close();
...even when including the time needed to build the DOM nodes vs. build the HTML string. This might be the reason for the flicker, or perhaps just another supporting argument for the DOM approach. Chrome doesn't have any flicker with either method.
Note the subtle change of storing the returned document which circumvents the bug in Firefox 4.0b7.
Also note this added MIME type which the IE docs claim is "required".
Finally, Internet Explorer seems to have a bit of trouble resolving link tags that were built before the new document is swapped in. Assigning the link href back to itself appears to patch it up.
// IE requires link repair
if (document.createStyleSheet) {
var head = document.documentElement.firstChild;
while (head && (head.tagName||"") !== "HEAD") {
head = head.nextSibling;
}
if (head) {
var link = head.firstChild;
while (link) {
if ((link.tagName||"") === "LINK") {
link.href = link.href;
}
link = link.nextSibling;
}
}
}
One could cover all bases and combine them like this...
var doc = document;
try {
var newRoot = newDoc.toDOM();
doc.replaceChild(newRoot, doc.documentElement);
// IE requires link repair
if (doc.createStyleSheet) {
var head = newRoot.firstChild;
while (head && (head.tagName||"") !== "HEAD") {
head = head.nextSibling;
}
if (head) {
var link = head.firstChild;
while (link) {
if ((link.tagName||"") === "LINK") {
link.href = link.href;
}
link = link.nextSibling;
}
}
}
} catch (ex) {
doc = doc.open("text/html");
doc.write(newDoc.toString());
doc.close();
}
...assuming you have the ability to choose your approach like I do.

Categories

Resources