Ajax/jQuery Timing Issue - ajax

I have a click function that does a jQuery/Ajax $.post to get data from a webservice when a span is clicked. When there is a Firebug break point set on the click function, everything works as expected (some new table tr's are appended to a table). When there is no break point set, nothing happens when you click the span. Firebug doesn't show any errors. I assume from other stackoverflow questions that this is a timing problem, but I don't know what to do about it. I have tried changing from a $.post to a $.ajax and setting async to false, but that didn't fix it. Here's the code for the click handler:
$('.rating_config').click(function(event){
event.preventDefault();
event.stopPropagation();
var that = $(this);
// calculate the name of the module based on the classes of the parent <tr>
var mytrclasses = $(this).parents('tr').attr('class');
var modulestart = mytrclasses.indexOf('module-');
var start = mytrclasses.indexOf('-', modulestart) + 1;
var stop = mytrclasses.indexOf(' ', start);
var mymodule = mytrclasses.substring(start, stop);
mymodule = mymodule.replace(/ /g, '+');
mymodule = mymodule.replace(/_/g, '+');
mymodule = encodeURI(mymodule);
// calculate the name of the property based on the classes of the parent <tr>
var propertystart = mytrclasses.indexOf('property-');
var propstart = mytrclasses.indexOf('-', propertystart) + 1;
var propstop = mytrclasses.indexOf(' ', propstart);
var myproperty = mytrclasses.substring(propstart, propstop);
myproperty = myproperty.replace(/ /g, '+');
myproperty = myproperty.replace(/_/g, '+');
myproperty = encodeURI(myproperty);
var parentspanid = $(this).attr('id');
// Remove the comparison rows if they are already present, otherwise generate them
if ($('.comparison_' + parentspanid).length != 0) {
$('.comparison_' + parentspanid).remove();
} else {
$.post('http://localhost/LearnPHP/webservice.php?user=user-0&q=comparison&level=property&module=' + mymodule + '&version_id=1.0&property=' + myproperty + '&format=xml', function(data) {
var data = $.xml2json(data);
for (var propnum in data.configuration.modules.module.properties.property) {
var prop = data.configuration.modules.module.properties.property[propnum];
console.log(JSON.stringify(prop));
prop.mod_or_config = 'config';
var item_id = mymodule + '?' + prop.property_name + '?' + prop.version_id + '?' + prop.value;
item_id = convertId(item_id);
prop.id = item_id;
//alert('prop.conformity = ' + prop.conformity);
// genRow(row, module, comparison, comparison_parentspanid)
var rowstring = genRow(prop, mymodule, true, parentspanid);
console.log('back from genRow. rowstring = ' + rowstring);
$(that).closest('tr').after(rowstring);
//$('tr#node-' + data[row].id + ' span#rating' + row.id).css('background', '-moz-linear-gradient(left, #ff0000 0%, #ff0000 ' + data[row].conformity + '%, #00ff00 ' + 100 - data[row].conformity + '%, #00ff00 100%');
var conformity_color = getConformityColor(prop.conformity);
$('tr#comparison_module_' + mymodule + '_setting_' + prop.id + ' span#module_' + mymodule + '_rating' + prop.id).css({'background':'-moz-linear-gradient(left, ' + conformity_color + ' 0%, ' + conformity_color + ' ' + prop.conformity + '%, #fffff0 ' + prop.conformity + '%, #fffff0 100%)'});
//$('tr#comparison-' + data[row].id + ' span#rating' + data[row].id).css('background','-webkit-linear-gradient(left, #00ff00 0%, #00ff00 ' + data[row].conformity + '%, #ff0000 ' + (100 - (data[row].conformity + 2)) + '%, #ff0000 100%)');
}
});
// Hide the Fix by mod column
hideFixedByModCol();
$('tr.comparison_' + parentspanid).each(function(i){
if (i % 2 == 0) {
$(that).addClass('comparison_even');
} else {
$(that).addClass('comparison_odd');
}
});
}
});
Any help would be greatly appreciated!

I suspect your data is coming back improperly formed. Enclose your code from the break on within try {} catch {} to see the error generated. Also it would be a good idea to add error processing to your ajax request.

Related

I want to compare the price of stock with stoploss and alert me by email

I want to compare my list of stocks price with my set Stoploss which is stored and once the condition trigger alert by email. Below is my code
function emailAlert()
{
var stock1nameRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Watchlist").getRange("A5");
var stock1name = stock1nameRange.getValues();
var stock1cmpRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Watchlist").getRange("B5");
var stock1cmp = stock1cmpRange.getValues();
var stock1s1Range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Watchlist").getRange("AK5");
var s1 = stock1s1Range.getValues();
var stock1s2Range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Watchlist").getRange("AL5");
var s2 = stock1s2Range.getValues();
var ui = SpreadsheetApp.getUi();
if(stock1cmp<s1)
{
if(stock1cmp<s2)
{
ui.alert( stock1name + stock1cmp + 'is less than' +s2 );
var message = stock1name + stock1cmp + 'is less than' +s2 ;
MailApp.sendEmail("#gmail.com", "Stock Watchlist alert", message)
return s2
}
else
{
ui.alert( stock1name + stock1cmp + 'is less than' +s1 );
var message = stock1name + stock1cmp + 'is less than' +s1 ;
MailApp.sendEmail("#gmail.com", "Stock Watchlist alert", message )
return s1
}
}
}
This is for single stock. How can I make it more generic and compile all the stock list which pass the condition into single mail. Thanks.
Sen
In order to be able to select all the values you will be needing a for loop.
Snippet
function emailAlert() {
var ui = SpreadsheetApp.getUi();
var sheet = SpreadsheetApp.getActive().getSheetByName("Watchlist");
var stockName = sheet.getRange("A5:FINAL_RANGE").getValues();
var stockCmp = sheet.getRange("B5:FINAL_RANGE").getValues();
var s1 = sheet.getRange("AK5:FINAL_RANGE").getValues();
var s2 = sheet.getRange("AL5:FINAL_RANGE").getValues();
for (var i = 0; i < stockName.length; i++) {
if (stockCmp[i][0] < s1[i][0]) {
if (stockCmp[i][0] < s2[i][0]) {
ui.alert(stockName[i][0] + stockCmp[i][0] + ' is less than ' + s2[i][0]);
var message = stockName[i][0] + stockCmp[i][0] + ' is less than ' + s2[i][0];
MailApp.sendEmail("#gmail.com", "Stock Watchlist Alert", message);
return s2[i][0];
} else {
ui.alert(stockName[i][0] + stockCmp[i][0] + ' is less than ' + s1[i][0]);
var message = stockName[i][0] + stockCmp[i][0] + ' is less than ' + s1[i][0];
MailApp.sendEmail("#gmail.com", "Stock Watchlist Alert", message);
return s1[i][0];
}
}
}
}
Explanation
The above code loops through all the values from your columns by using a for loop and then based on the conditions you set, is sending the email and alerting the user. The range is retrieved by using the getRange() method with the a1Notation parameter. The a1Notation parameter here is represented by the start and the end of the range in which you have the values you need for the script.
Note
The above script is built considering the fact that the stockName, stockCmp, s1, s2 are all associated, meaning that they all have the same number of values stored in them.
Reference
Apps Script Range Class - getValues();
Apps Script Sheet Class - getRange(a1Notation);
JavaScript For Loop.

Bash script to get mongoStats

Hoping someone has a bash script handy that will hit a mongodb and get the collection stats something like the below that I can use in a shell script?
var collectionNames = db.getCollectionNames(), stats = [];
collectionNames.forEach(function (n) { stats.push(db[n].stats()); });
stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
for (var c in stats) { print(stats[c]['ns'] + ": " + stats[c]['size'] + " (" + stats[c]['storageSize'] + ")"); }
UPDATE
one other question --- looking to prefix the line with a datestamp
"db.getCollectionNames().forEach(function (n) { var s = db[n].stats(); print('date +'%D %r %Z'''namespace=' + s['ns'] +',count=' + s['count']+',avgObjSize=' + s['avgObjSize']+',storageSize=' + s['storageSize']) })"
but my date code doesn't seem to be working :(
mongo $DB_NAME --quiet --eval "db.getCollectionNames().forEach(function (n) { var s = db[n].stats(); print(s['ns'] + ',' + s['size'] + ',' + s['storageSize']) })" | sort --numeric-sort --reverse
It will print in a CSV format which you can you couple of tools to manipulate.
Update:
Just add avgObjSize, totalIndexSize and other keys you need, edit your main question with an output example so we can sort by whatever column you desire.
Update 2:
db.getCollectionNames().forEach(function (n) { var s = db[n].stats(); printjson({'namespace': s['ns'], 'size': s['size'], 'storage': s['storageSize']}) })
db.getCollectionNames().forEach(function (n) { var s = db[n].stats(); print('size=' + s['size'] +',avgObjSize=' + s['avgObjSize']) })

Running a mapreduce job on cloudera demo cdh3u4 (airline data example)

I'm doing the R-Hadoop tutorial (october 2012) of Jeffrey Breen.
At the moment I try to populate hdfs and then run the commands Jeffrey published in his tutorial in RStudio. Unfortunately I got some troubles with it:
UPDATE: I now moved the data folder to:
/home/cloudera/data/hadoop/wordcount (and same for airline-Data)
No when I run populate.hdfs.sh I get the following output:
[cloudera#localhost ~]$ /home/cloudera/TutorialBreen/bin/populate.hdfs.sh
mkdir: cannot create directory /user/cloudera: File exists
mkdir: cannot create directory /user/cloudera/wordcount: File exists
mkdir: cannot create directory /user/cloudera/wordcount/data: File exists
mkdir: cannot create directory /user/cloudera/airline: File exists
mkdir: cannot create directory /user/cloudera/airline/data: File exists
put: Target /user/cloudera/airline/data/20040325.csv already exists
And then I tried the commands in RStudio as shown in the tutorial but I get errors at the end. Can someone show me what I did wrong?
> if (LOCAL)
+ {
+ rmr.options.set(backend = 'local')
+ hdfs.data.root = 'data/local/airline'
+ hdfs.data = file.path(hdfs.data.root, '20040325-jfk-lax.csv')
+ hdfs.out.root = 'out/airline'
+ hdfs.out = file.path(hdfs.out.root, 'out')
+ if (!file.exists(hdfs.out))
+ dir.create(hdfs.out.root, recursive=T)
+ } else {
+ rmr.options.set(backend = 'hadoop')
+ hdfs.data.root = 'airline'
+ hdfs.data = file.path(hdfs.data.root, 'data')
+ hdfs.out.root = hdfs.data.root
+ hdfs.out = file.path(hdfs.out.root, 'out')
+ }
> asa.csvtextinputformat = make.input.format( format = function(con, nrecs) {
+ line = readLines(con, nrecs)
+ values = unlist( strsplit(line, "\\,") )
+ if (!is.null(values)) {
+ names(values) = c('Year','Month','DayofMonth','DayOfWeek','DepTime','CRSDepTime',
+ 'ArrTime','CRSArrTime','UniqueCarrier','FlightNum','TailNum',
+ 'ActualElapsedTime','CRSElapsedTime','AirTime','ArrDelay',
+ 'DepDelay','Origin','Dest','Distance','TaxiIn','TaxiOut',
+ 'Cancelled','CancellationCode','Diverted','CarrierDelay',
+ 'WeatherDelay','NASDelay','SecurityDelay','LateAircraftDelay')
+ return( keyval(NULL, values) )
+ }
+ }, mode='text' )
> mapper.year.market.enroute_time = function(key, val) {
+ if ( !identical(as.character(val['Year']), 'Year')
+ & identical(as.numeric(val['Cancelled']), 0)
+ & identical(as.numeric(val['Diverted']), 0) ) {
+ if (val['Origin'] < val['Dest'])
+ market = paste(val['Origin'], val['Dest'], sep='-')
+ else
+ market = paste(val['Dest'], val['Origin'], sep='-')
+ output.key = c(val['Year'], market)
+ output.val = c(val['CRSElapsedTime'], val['ActualElapsedTime'], val['AirTime'])
+ return( keyval(output.key, output.val) )
+ }
+ }
> reducer.year.market.enroute_time = function(key, val.list) {
+ if ( require(plyr) )
+ val.df = ldply(val.list, as.numeric)
+ else { # this is as close as my deficient *apply skills can come w/o plyr
+ val.list = lapply(val.list, as.numeric)
+ val.df = data.frame( do.call(rbind, val.list) )
+ }
+ colnames(val.df) = c('crs', 'actual','air')
+ output.key = key
+ output.val = c( nrow(val.df), mean(val.df$crs, na.rm=T),
+ mean(val.df$actual, na.rm=T),
+ mean(val.df$air, na.rm=T) )
+ return( keyval(output.key, output.val) )
+ }
> mr.year.market.enroute_time = function (input, output) {
+ mapreduce(input = input,
+ output = output,
+ input.format = asa.csvtextinputformat,
+ output.format='csv', # note to self: 'csv' for data, 'text' for bug
+ map = mapper.year.market.enroute_time,
+ reduce = reducer.year.market.enroute_time,
+ backend.parameters = list(
+ hadoop = list(D = "mapred.reduce.tasks=2")
+ ),
+ verbose=T)
+ }
> out = mr.year.market.enroute_time(hdfs.data, hdfs.out)
Error in file(f, if (format$mode == "text") "r" else "rb") :
cannot open the connection
In addition: Warning message:
In file(f, if (format$mode == "text") "r" else "rb") :
cannot open file 'data/local/airline/20040325-jfk-lax.csv': No such file or directory
> if (LOCAL)
+ {
+ results.df = as.data.frame( from.dfs(out, structured=T) )
+ colnames(results.df) = c('year', 'market', 'flights', 'scheduled', 'actual', 'in.air')
+ print(head(results.df))
+ }
Error in to.dfs.path(input) : object 'out' not found
Thank you so much!
First of all, it looks like the command:
/usr/bin/hadoop fs -mkdir /user/cloudera/wordcount/data
Is being split into multiple lines. Make sure you're entering it as-is.
Also, it is saying that the local directory data/hadoop/wordcount does not exist. Verify that you're running this command from the correct directory and that your local data is where you expect it to be.

Socket.io several rooms in Construct2

I am working on a game in Construct2 at the moment.
It is a HTML5 Javascript Engine.
I probably implement clay.io inside it.
My question however is about "Rooms"
Clay.io also helps with Rooms. However I am not sure If I will take that offer.
https://clay.io/docs/rooms
So when I want to limit the users per game to 10 for example. Would I then need to run two servers?
The socket.io server recives and returns data.. But would two games running with each 10 people not confuse the servers data? When person A on server A shoots some1, that this information could somehow end up on Person B on server B?
Or do the assigned ID's prevent this somehow?
Here is the Example Server that I want to upgrade for my needs:
var entities = [], count = 0;
var io = require("socket.io").listen(8099);
var INITIAL_X = 5;
var INITIAL_Y = 5;
var INITIAL_VEL_X = 0;
var INITIAL_VEL_Y = 0;
io.set('log level', 1);
io.sockets.on("connection", function (socket) {
var myNumber = count++;
//assign number
var mySelf = entities[myNumber] = [myNumber, INITIAL_X, INITIAL_Y, INITIAL_VEL_X, INITIAL_VEL_Y];
//Send the initial position and ID to connecting player
console.log(myNumber + ' sent: ' + 'I,' + mySelf[0] + ',' + mySelf[1] + ',' + mySelf[2]);
socket.send('I,' + mySelf[0] + ',' + mySelf[1] + ',' + mySelf[2]);
//Send to conencting client the current state of all the other players
for (var entity_idx = 0; entity_idx < entities.length; entity_idx++) {
//send initial update
if (entity_idx != myNumber) {
entity = entities[entity_idx];
if (typeof (entity) != "undefined" && entity != null) {
console.log(myNumber + ' sent: C for ' + entity_idx);
socket.send('C,' + entity[0] + ',' + entity[1] + ',' + entity[2]);
//send the client that just connected the position of all the other clients
}
}
}
//create new entity in all clients
socket.broadcast.emit("message",
'C,' + mySelf[0] + ',' + mySelf[1] + ',' + mySelf[2]);
socket.on("message", function (data) {
//if (myNumber == 0)
// console.log(myNumber + ' sent: ' +data);
var new_data = data.split(',');
if (new_data[0] == 'UM') {
mySelf[1] = new_data[1];
mySelf[2] = new_data[2];
mySelf[3] = new_data[3];
mySelf[4] = new_data[4];
//Update all the other clients about my update
socket.broadcast.emit("message",
'UM,' + mySelf[0] + ',' + mySelf[1] + ',' + mySelf[2] + ',' + mySelf[3] + ',' + mySelf[4]);
}
else if (new_data[0] == 'S') { // a s message
var shoot_info = [];
shoot_info[0] = new_data[1]; //ini x
shoot_info[1] = new_data[2]; //ini y
shoot_info[2] = new_data[3]; //degrees
//Update all the other clients about my update
socket.broadcast.emit("message",
'S,' + mySelf[0] + ',' + shoot_info[0] + ',' + shoot_info[1] + ',' + shoot_info[2]);
}
});
});
Socket.io has rooms that you can limit the broadcasts to, see: https://github.com/LearnBoost/socket.io/wiki/Rooms
Then rather than use socket.broadcast.emit you would use io.sockets.in('roomname').emit
A good way to mesh this with Clay.io is to have the room name be the room.id (in the Construct 2 plugin that's the RoomId expression). When the Clay.io room fills up (in C2 there's a condition for that), create the Socket.io room using that unique ID and put the players who "Rooms Filled" was just called for in that room.
I know it's a bit different since it's a game written in CoffeeScript instead of Construct 2, but we're using Clay.io rooms + Socket.io rooms in our Slime Volley game. Here is the code.

Ace editor, inaccurate horizontal scroll, how to fix?

Using Ace editor, works OK, except: and start and end of line, if there is at least one line of the document that doesn't fit the screen, horizontal scroll is incomplete. For caret at start of line, once the view is h-scrolled, it won't scroll back fully when caret is at start of line, and thus the caret won't show. Annoying. And the same for caret at end of line (although it seems it doesn't scroll at all, rather than not flush right, so might be different bugs. Anybody know how to fix? And what versions are affected?
(Oh, right, forgot to mention: the gutter is enabled.)
(Edit II: using Google Chrome 18.0.1025.162)
(E#3: forgot to mention: using Shift+scroll wheel I can manually fix it, scrolling full left. (E4: ...and that's just a clue; not a solution. One should not have to do any extraneous manual mousing.))
(Edit#N: managed to hide the gutter: "editor_loaded.renderer.setShowGutter(false);". Problem persists.)
Well, as requested (by 'WarFox'), here's what I did to get around the scrolling issues in version 0.2.0, straight out of local repo. HTH, YMMV. No guarantees for modifying this or any version, of course. The code for this.scrollCursorIntoView is modified to be:
this.scrollCursorIntoView = function() {
var log = function (s) {
// console.log("### scrollCursorIntoView ###: " + s);
};
// log("(scrollCursorIntoView...)");
function loge(expr) {
var value = eval(expr);
log("" + expr + " => " + value);
}
// the editor is not visible
if (this.$size.scrollerHeight === 0)
return;
var pos = this.$cursorLayer.getPixelPosition();
var left = pos.left + this.$padding;
log("left = " + left);
var top = pos.top;
log("top = " + top);
if (this.scrollTop > top) {
this.scrollToY(top);
}
if (this.scrollTop + this.$size.scrollerHeight < top + this.lineHeight) {
this.scrollToY(top + this.lineHeight - this.$size.scrollerHeight);
}
var scrollLeft = this.scroller.scrollLeft;
var left_ = left - this.characterWidth;
log("(scrollLeft > left): " + scrollLeft + " > " + left);
log("(scrollLeft > left_): " + scrollLeft + " > " + left_);
if (scrollLeft > left_) {
this.scrollToX(left_);
} else {
log("NOT (scrollLeft > left): " + scrollLeft + " > " + left);
log("NOT (scrollLeft > left_): " + scrollLeft + " > " + left_);
}
loge("scrollLeft");
log("scrollLeft = " + scrollLeft);
log("this.$size.scrollerWidth = " + this.$size.scrollerWidth);
log("left = " + left);
log("this.characterWidth = " + this.characterWidth);
var right_side_scroll_yes = scrollLeft + this.$size.scrollerWidth < left + this.characterWidth;
if (right_side_scroll_yes) {
log("(right side scroll...)");
//loge("this.layerConfig.width");
if (left > this.layerConfig.width) {
log("right #1");
log("this.layerConfig.width = " + this.layerConfig.width);
this.$desiredScrollLeft = left + 2 * this.characterWidth;
this.scrollToX(this.$desiredScrollLeft);
} else {
log("right #2");
var tmp = Math.round(left + this.characterWidth - this.$size.scrollerWidth);
loge("tmp");
this.scrollToX(tmp);
}
} else {
log("NOT (right_side_scroll_yes): " + scrollLeft + " > " + left);
}
};
Obviously, the logging calls are not necessary for anything but debugging.

Resources