Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Strong Sauce
Jul 2, 2003

You know I am not really your father.





Pollyanna posted:

Unfortunately, it looks like Python's "translate to JSON" dealio causes a bit of a problem: all the keys are turned to strings, when I need them to be flat-out variables. e.g.:

code:
{"text": "MHNC", "id": 4523}, {"text": "MHO", "id": 4524}, {"text": "MHO$A", "id": 4525}
should be

code:
{text: "MHNC", id: 4523}, {text: "MHO", id: 4524}, {text: "MHO$A", id: 4525}
For context, this is what Select2 expects:

code:
data:[{id:0,text:'enhancement'},{id:1,text:'bug'},{id:2,text:'duplicate'},{id:3,text:'invalid'},{id:4,text:'wontfix'}]
How do I make it so that Python doesn't output the keys as strings?
Keys have to be strings in JSON. It shouldn't matter in this case.

Adbot
ADBOT LOVES YOU

Gism0
Mar 20, 2003

huuuh?
You need to parse the JSON to convert it to a proper Object..

var options = JSON.parse(data);

or take a look at this: http://stackoverflow.com/questions/18490609/select2-load-data-with-ajax-from-file

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Pollyanna posted:

For context, this is what Select2 expects:

code:
data:[{id:0,text:'enhancement'},{id:1,text:'bug'},{id:2,text:'duplicate'},{id:3,text:'invalid'},{id:4,text:'wontfix'}]

I don't understand what data: means in this case, unless it's a key in some top-level object.

Anyway, what you have there after data: is an array of objects

Actually, is the data you're currently getting this:

code:
[{"text": "MHNC", "id": 4523}, {"text": "MHO", "id": 4524}]
(An array of objects)

While it should be this:

code:
{data: [{"text": "MHNC", "id": 4523}, {"text": "MHO", "id": 4524}]}
(An object which has a key named "data" with a value of an array of objects)

Because neither
code:
{"text": "MHNC", "id": 4523}, {"text": "MHO", "id": 4524}, {"text": "MHO$A", "id": 4525}
nor
code:
data:[{id:0,text:'enhancement'},{id:1,text:'bug'},{id:2,text:'duplicate'},{id:3,text:'invalid'},{id:4,text:'wontfix'}]
is valid syntax without some outer structure.

Pollyanna
Mar 5, 2005

Milk's on them.


I honestly don't know. I managed to get it working, somehow, but it runs obnoxiously slowly whenever you try to look up a symbol. The time it takes to render a page tanked, too, so I'm just removing it for now. I'll look for something like tagging that doesn't depend on a lookup, instead you can just write "aapl,google,ibm" like you do on Tumblr.

pr0metheus
Dec 5, 2010
What is the correct approach to determining when a recursive function which also makes a bunch of async calls is done?

The solution I have come up is basically to create a counter object at each recursive call. This object contains total number of future recursive calls to be made on this level and the number completed plus a callback when all of them have been completed. I then pass it as one of the arguments to next recursive call. When a counter is done it will increment count of done calls in the parent count object. Here is some code:

code:
/**
Find stuff in file system!
*/

var fs = require('fs');

var Counter = function(total, onDone)
{
	this.total = total;
	this.count = 0;
	this.onDone = onDone;
	
	this.up = function()
	{
		this.count++;
		if( this.count == this.total )
		{
			onDone();
		}
	}
	
	if( this.total == 0 )
	{
		onDone();
	}
};

/*
Find stuff in rootPath recursively based on filter.  
filter takes in (name, files, stat).  if file is passed in then files will be null.  
if filter is ommited then all file/directory names will be retrieved.
When everything is done callback(err,arrayOfPaths) is called.
*/
function find( rootPath, filter, callback )
{
	if( !fs.statSync(rootPath).isDirectory() )
	{
		callback(rootPath + " is not a directory!", null );
		return;
	}

	var ret = new Array();
	function _doit( rootPath, ret, parentCounter )
	{
		fs.readdir( rootPath, function( err, files )
		{
			if( filter( rootPath, files ) )
			{
				ret.push( rootPath );
			}
			if( err )
			{
				callback(err, null);
			}
			var myCounter = new Counter( files.length, function()
			{
				// if parentCounter is null then we are in the first call.
				if( parentCounter )
				{
					parentCounter.up();
				}
				else
				{
					callback(null, ret, null);
				}
			});
			for( var file_i in files )
			{
				var file = rootPath + "/" + files[file_i];
				var stat = fs.lstatSync(file);
				var isDir = stat.isDirectory();
				var val =file;

				if( stat.isFile() && filter( file, null, stat ) )
				{
					ret.push(file);
				}

				// do not follow sym links or files.
				if( !isDir || stat.isSymbolicLink() )
				{
					myCounter.up();
				}
				else
				{
					_doit( file, ret, myCounter );
				}
			}
		});
	}
	_doit( rootPath, ret, undefined );
}
Can someone comment on efficiency of this approach and what other solutions may exist to joining on a recursive function with a shitton of async calls?

pr0metheus fucked around with this message at 08:21 on Jan 11, 2014

Chenghiz
Feb 14, 2007

WHITE WHALE
HOLY GRAIL

pr0metheus posted:

What is the correct approach to determining when a recursive function which also makes a bunch of async calls is done?

(...)

Can someone comment on efficiency of this approach and what other solutions may exist to joining on a recursive function with a shitton of async calls?

With jQuery this is a lot easier, and I'm sure there's a native way to implement this as well, I just don't know what it is. If each of your async calls is returning a deferred promise, you can put the promises into an array and give the script a function to run once all of the promises are resolved. So it would be something like this:
code:
var callServer = function () {
	var dfd = $.Deferred();
	Server.readdir(dir).done(function (results) {
		if (results) {
			dfd.resolve(results);
		} else {
			dfd.reject('No results found.');
		}
	}).fail(function (error) {
		dfd.reject(error);
	});
	return dfd.promise();
};

var promises = [];
for (var x=0; x<10; x++) { // just for example
	promises.push(callServer());
}
$.when.apply($, promises)
.then(function (results) {
	// your callback here
});
Notice the callServer function is returning an object that essentially represents the state of the async call. When the async call is done, the state of that object will be marked as 'resolved' (or 'rejected' if it fails). The $.when.then function chain specifies what to do when all of the async calls are done (if you want it to trigger only if all calls are successful, use .done() instead of .then()). You can chain the deferred object as deep as you need to, so in your implementation you might have additional logic to recursively search inside of what I call the callServer function here.

Sorry if this is confusing, it took me a while to work out how jQuery's deferred objects work; but they're really, really useful.
http://api.jquery.com/category/deferred-object/

Peanut and the Gang
Aug 24, 2009

by exmarx

pr0metheus posted:

What is the correct approach to determining when a recursive function which also makes a bunch of async calls is done?

The solution I have come up is basically to create a counter object at each recursive call. This object contains total number of future recursive calls to be made on this level and the number completed plus a callback when all of them have been completed. I then pass it as one of the arguments to next recursive call. When a counter is done it will increment count of done calls in the parent count object. Here is some code:

You can use the parallel() function of the async library for this.

code:
async = require('async');

var funcsToRun = [];
funcsToRun.push(function(cb){
  doStuff1(cb);
});
funcsToRun.push(function(cb){
  doStuff2(cb);
});
async.parallel(funcsToRun, function(){
  console.log('all done!');
});

pr0metheus
Dec 5, 2010
The problem with promises is that I do not know exactly how many promises I will need. Same with async. I do not know ahead of time how many async tasks I will generate.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

pr0metheus posted:

The problem with promises is that I do not know exactly how many promises I will need. Same with async. I do not know ahead of time how many async tasks I will generate.

I personally use Q. This library I wrote (http://malucomarinero.bitbucket.org/johodb/ - due for a clean up, about to start rolling it into a production app and filling out the rest of the features) uses Q promises extensively to interact with asynchronous local storage (IndexedDB and WebSQL). Sometimes those asynchronous calls generate MORE calls because there's more data to be found. As long as you're consistent with your return on the asynchronous promises, you can pick it all up at the end with a simple Q.all call on the promise stack.

For example (in coffeescript but you should get the idea):
CoffeeScript code:
stack = []
for obj in result
  stack.push @__getRelatedObjects(obj, {depth: opts.depth - 1})
g = Q.all stack
g.then (objs) ->
  ## do a thing involving all the objs, which are ordered in the same order the promises were in the array

Chenghiz
Feb 14, 2007

WHITE WHALE
HOLY GRAIL

pr0metheus posted:

The problem with promises is that I do not know exactly how many promises I will need. Same with async. I do not know ahead of time how many async tasks I will generate.

The structure I posted allows you to push as many promises into the promises array as you need to. I use it in my projects to update one or many lines of a given invoice, given the user's input - a situation in which you also don't know how many async calls you will be making. The 0-9 for loop is just for example.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





It looks like you're just trying to walk a file directory and then also filter out by some specifics. Why not just do a normal file walk that returns a callback'd array that you run filter() against?

Honestly maybe you should clarify what you are doing since this sounds eerily like its an XY problem.

pr0metheus
Dec 5, 2010
I just wanted to use async methods and figure out a way to join all of them and call a user specified function. Will look into promises. I am not quite sure they would be more efficient or easier to read then my counter solution, however.

Strong Sauce
Jul 2, 2003

You know I am not really your father.





No, I mean what is the actual task you are trying to do.

Ethereal
Mar 8, 2003

pr0metheus posted:

The problem with promises is that I do not know exactly how many promises I will need. Same with async. I do not know ahead of time how many async tasks I will generate.

Use the async.queue object to do this. You basically have a dynamic set of tasks that need to be executed with a callback at completion and the queue will let you add new directories to filter as you work your way down the tree.

pr0metheus
Dec 5, 2010

Strong Sauce posted:

No, I mean what is the actual task you are trying to do.

Recursively go through a given folder and pick out path's that meet some filter criteria.

Ethereal posted:

Use the async.queue object to do this. You basically have a dynamic set of tasks that need to be executed with a callback at completion and the queue will let you add new directories to filter as you work your way down the tree.

I will give async a try. Thank you guys for all the suggestions. Will give this more reading and experimentation.

Damiya
Jul 3, 2012
Is there a compelling reason to use Q over Bluebird or some other promises library? The benchmarks I've seen all peg Q as pretty much the slowest option out there.

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.

Damiya posted:

Is there a compelling reason to use Q over Bluebird or some other promises library? The benchmarks I've seen all peg Q as pretty much the slowest option out there.

I've used Q and like it, but if theres a more efficient alternative out there I'll be switching over, no question. Bluebird's API looks pretty exhaustive too, just at a quick read.

DholmbladRU
May 4, 2006
I am implementing the dropzone.js photo upload. However I do not want dropzone to handle the uploads because it seems like they go in bursts instead of all at once. I would like my photos to be uploaded at one time. To do so users will drag and drop photos into the dropzone area. From here they choose some custom options on the images. Then I would like a user to hit a custom button. This button can perform the following.

1. Add photos to multiImg[] array
2. invoke form

After a photo is uplaoded into the dropzone I will have access to all the information about the photo. Name, size, location(on uers computer). I am just unsure how to accomplish step 1 which is to take the photos and pass them into a form via javascript.

Is this even a good approach?


code:
 <form method="post" action="" enctype="multipart/form-data">
 <input type="file" accept='image/*' name="multiImg[]" id="multiImg" />

Opulent Ceremony
Feb 22, 2012

DholmbladRU posted:

I am implementing the dropzone.js photo upload. However I do not want dropzone to handle the uploads because it seems like they go in bursts instead of all at once. I would like my photos to be uploaded at one time.

I just used dropzone.js on a site where I have it uploading all the files at once with the rest of the form rather than one at a time, check this out: https://github.com/enyo/dropzone/wiki/Combine-normal-form-with-Dropzone

DholmbladRU
May 4, 2006

Opulent Ceremony posted:

I just used dropzone.js on a site where I have it uploading all the files at once with the rest of the form rather than one at a time, check this out: https://github.com/enyo/dropzone/wiki/Combine-normal-form-with-Dropzone

Yeah I was reading that documentation now actually. Unfortunately I need to add my dropzone via html as opposed to java script.


For some reason my current implementation is not passing the photos to the $this->post
code:
 
            <div id="photoContainer">
            
            <form action="inspections/uploadphotos" method="post"  class="dropzone" id="myDZ">
                  <button type="submit" id="dz" name="dz" value="Submit Photos" /> Submit Photos</button>
                <ul id="sort1"  class="dz-clickable" action="http://www.torrentplease.com/dropzone.php">
                </ul>
                     

                    <div>
                   
                 </div>
                </form>[s][/s]

php:
<?
  if ($this->request->method() === 'POST') {
            echo 'post';
            print_r($this->_post);
            
        }
?>
Result
code:
post( [dz] => Submit Photos )

DholmbladRU fucked around with this message at 18:20 on Jan 13, 2014

Opulent Ceremony
Feb 22, 2012

DholmbladRU posted:

Yeah I was reading that documentation now actually. Unfortunately I need to add my dropzone via html as opposed to java script.

From their docs, configuring the drop zone if you are using just HTML elements:

Dropzone posted:

But if you just have HTML elements with the dropzone class, then you don't programmatically instantiate the objects, so you have to store the configuration somewhere so Dropzone knows how to configure the dropzones when instantiating them.

This is done with the Dropzone.options object.

As for file data not getting posted, I recall having similar problems depending on where I was applying the special dropzone classes on my HTML elements, although I don't remember the details of making it work unfortunately. Try messing with them. Will your echo show stuff in the global FILES thingy? I'm not using PHP so I'm not really sure how that works.

My form looks like this:

code:
<form action="/MySite/Uploader" class="dropzone dropzone-previews dz-clickable" 
enctype="multipart/form-data" id="dropzone-form" method="post">
various <input>'s
<div class="dz-default dz-message"><span>Add files to upload by clicking or droppng them here.</span></div>
</form>
<button type="submit" class="btn pull-right">Finish</button>

Maluco Marinero
Jan 18, 2001

Damn that's a
fine elephant.
Yeah, the files aren't always kept in request->post. Check your php docs for file uploading, and change the form enctype to what it is in the post above mine.

DholmbladRU
May 4, 2006
Yeah I have been checking the $_FILES and $this->_post for any information related to images but is is empty. I am by no means a PHP developer...


form config
code:
    <div id="photoContainer">
            
                <form action="/inspections/uploadphotos" method="post" enctype="multipart/form-data" class="dropzone dz-clickable" id="my-DZ">
                <button type="submit" id="dz" name="dz" value="Submit " /> Submit Photos</button>
                </form>
                 
            </div>
dropzone config
code:
 
 $(document).ready(function() {
    
    Dropzone.options.myDZ=  { // The camelized version of the ID of the form element

  autoProcessQueue: false,
  uploadMultiple: true,
  parallelUploads: 100,
  maxFiles: 100,
  autoDiscover: false,



      // The setting up of the dropzone
            init: function () {

                var myDropzone = this;

                $("button[type=submit]").bind("click", function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    // If the user has selected at least one file, AJAX them over.
                    if (myDropzone.files.length !== 0) {
                      console.log(myDropzone.files.length);
                        myDropzone.processQueue();
                    // Else just submit the form and move on.
                    } else {
                        $('#my-DZ').submit();
                    }
                });

                this.on("successmultiple", function (files, response) {
                    // After successfully sending the files, submit the form and move on.
                    $('#my-DZ').submit();
                });
            }
        }
 
  }

   });

DholmbladRU fucked around with this message at 22:14 on Jan 13, 2014

Opulent Ceremony
Feb 22, 2012
If that is your entire Dropzone config I think you might be missing stuff. I'm pretty sure processQueue() needs to get run to actually post the file data. Take a look at the link I posted the first time, it shows you that method being used in the init function when configuring Dropzone.

Also are you sure the configuration is targetting your form? The way you identify your form in Dropzone.options needs to be camelized from the form element ID. For example, my form id is 'dropzone-form', and I'm targetting it in my Dropzone configuration by doing Dropzone.options.dropzoneForm. That is, remove hyphens and capitalize the first letter. Your id appears to be 'myDZ', so I think you would just target it with .options.mydz? I'm not sure about that part, maybe try playing with it.

Also, try putting the dz-clickable class on your actual form rather than a nested ul. I know I definitely had problems with stuff like that initially.

Edit: Here's my config as well:

code:
Dropzone.options.dropzoneForm = {
            // The camelized version of the ID of the form element

            paramName: "files",
            autoProcessQueue: false,
            uploadMultiple: true,
            parallelUploads: 100,
            maxFiles: 100,
            previewsContainer: ".dropzone-previews",
            clickable: true,
            dictDefaultMessage: 'Add files to upload by clicking or droppng them here.',
            addRemoveLinks: true,
            acceptedFiles: '.jpg,.pdf,.png,.doc,.docx,.bmp',
            dictInvalidFileType: 'This file type is not supported.',

            // The setting up of the dropzone
            init: function () {
                var myDropzone = this;

                $("button[type=submit]").bind("click", function (e) {
                    e.preventDefault();
                    e.stopPropagation();
                    // If the user has selected at least one file, AJAX them over.
                    if (myDropzone.files.length !== 0) {
                        myDropzone.processQueue();
                    // Else just submit the form and move on.
                    } else {
                        $('#dropzone-form').submit();
                    }
                });

                this.on("successmultiple", function (files, response) {
                    // After successfully sending the files, submit the form and move on.
                    $('#dropzone-form').submit();
                });
            }
        }

Opulent Ceremony fucked around with this message at 21:53 on Jan 13, 2014

DholmbladRU
May 4, 2006
The form gets submitted so I know the js for dropzone initialization is getting connected properly. But there still seems to be nothing along with the request. Ill have to look into it more. Thanks for the suggestions. Maybe its because I dont have ajax configured on this kohana...

DholmbladRU fucked around with this message at 22:52 on Jan 13, 2014

Damiya
Jul 3, 2012

Maluco Marinero posted:

I've used Q and like it, but if theres a more efficient alternative out there I'll be switching over, no question. Bluebird's API looks pretty exhaustive too, just at a quick read.

It's A+ compliant and assuming the benchmarks are legit (I haven't repro'd locally, but I have no reason to doubt them) Bluebird is definitely the way to go.

It's even better if you're using a browser that supports generator, but I'm not sure what that compatability matrix looks like.

TURTLE SLUT
Dec 12, 2005

I'm getting a very intermittent "Maximum call stack exceeded" error in an HTML5 app. Sounds like a normal recursive function error, and sure enough the last function in the stacktrace is a recursive function. But it is not in the stacktrace more than once, and actually the whole stacktrace is just 5 functions deep, starting from a setInterval.

Is this supposed to happen ever? Wouldn't an actual call stack exceed-ification include the giant stacktrace with 1000 functions or whatever the limit is on Chrome? I can't find anything actually wrong with the recursive loop either.

TURTLE SLUT fucked around with this message at 19:29 on Jan 20, 2014

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy
Can you post the code? Also make sure you're passing a reference to the function and not actually calling the function when you use setInterval.

TURTLE SLUT
Dec 12, 2005

Yeah, the interval is set up correctly. To note again, I get the call stack error about once every hundred refreshes and an out right crash maybe twice that often. Other times things work perfectly. :sigh: So I don't actually know if it has anything to do with this function. How to debug an outright browser crash?

code:
self.getTotalRotation = function(){
    if (self.parent) {
        return (self.rotation + self.parent.getTotalRotation()) % 360;
    }
    else {
        return self.rotation;
    }
};
I'm about 95% percent sure there is no circular reference involved here. And even if one of the parents of an object happened to be itself, it should print me a normal recursive stacktrace, not this mysterious bullshit.

Dolex
May 5, 2001

Are you checking if self.parent !== undefined?

What is self.parent?

OddObserver
Apr 3, 2009
How exactly would self change on that recursive call?
(Unless you create a separate instance with captured self
for every object, I guess..)

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

OddObserver posted:

How exactly would self change on that recursive call?
(Unless you create a separate instance with captured self
for every object, I guess..)

Experience has shown that people like to use "var self = this;" when using closures, and sometimes they slip and do "self = this;"

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Dolex posted:

Are you checking if self.parent !== undefined?

What is self.parent?

That's what if(self.parent) does

Bruegels Fuckbooks posted:

Experience has shown that people like to use "var self = this;" when using closures, and sometimes they slip and do "self = this;"

One more reason to use strict mode and linting.

TURTLE SLUT
Dec 12, 2005

I guess I should've given more context, but the app in question is a very large and I actually don't know if this piece of code has anything to do with the problem anymore :( The larger context is a tree structure with at most three or four levels in it, all with instances of the same class. I guess at this point the question is how to debug a crash that happens once every 100 refreshes. Selenium running 1000 repetitions a second and some sort of network logger so I can see the logs even when the browser crashes?

The Insect Court
Nov 22, 2012

by FactsAreUseless

JOHN SKELETON posted:

I guess I should've given more context, but the app in question is a very large and I actually don't know if this piece of code has anything to do with the problem anymore :( The larger context is a tree structure with at most three or four levels in it, all with instances of the same class. I guess at this point the question is how to debug a crash that happens once every 100 refreshes. Selenium running 1000 repetitions a second and some sort of network logger so I can see the logs even when the browser crashes?

Generate the node objects with a unique id that gets passed to the recursive call and have a line that checks to make sure that self.parent != self. Or some sort of visited flag to make sure you're not getting loops. It's hard to see how it's not the recursive function blowing up the stack assuming it's not some obscure browser bug, although it's hard to be sure just seeing that snippet.

Raskolnikov2089
Nov 3, 2006

Schizzy to the matic
So best practices wise, am I doing myself a disservice by leaving really detailed, obvious notes in my code? As in making myself look bad?

For instance, I explain why each div is hidden and under which circumstances it will be revealed, which a more experienced coder could no doubt easily figure out by reading my code.

MonkeyMaker
May 22, 2006

What's your poison, sir?

Raskolnikov2089 posted:

So best practices wise, am I doing myself a disservice by leaving really detailed, obvious notes in my code? As in making myself look bad?

For instance, I explain why each div is hidden and under which circumstances it will be revealed, which a more experienced coder could no doubt easily figure out by reading my code.

Strip the comments from whatever compiled/deployed version your code ends up in, but, no, you're doing the right thing. There is never enough documentation.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
The one thing to be wary of is documentation that may become inaccurate. Comments should generally be local in scope, otherwise you're likely to forget to update them when you change something elsewhere that happens to affect your comment. In general, wrong documentation is worse than not having documentation in the first place.

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

Sounds like good documentation to me.

Adbot
ADBOT LOVES YOU

Pollyanna
Mar 5, 2005

Milk's on them.


I'm prototyping a Knockout app right now, and I'm trying to add an input form that will add a filled-out row to a predefined table. However, I'm not sure how to do this.

Here's my JSFiddle:

http://jsfiddle.net/UZ3fS/7/

What's happening right now is that clicking "add application" adds a blank row, when it should be the data entered into the input field. I tried using the value binding to do this, but it doesn't seem to work. What am I missing?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply