2

I'm displaying a series of images in a loop, and I'm trying to implement some sort of nudity filter so I'm using nude.js, a library that can somewhat detect nudity. Here's the code:

// we're inside a loop
$(".images").prepend($("<img>").attr({src: whatever, id: uniqueid}).load(function(e) {
    nude.load(e.target.id);
    nude.scan(function(result) { if (!result) $(e.target).detach(); });
});

However, it detaches all of the wrong images because nude.js is slow and it completes after the loop has gone on to the later iterations, detaching those images instead of the one it was working on.

I've tried using a function factory:

function generateCallback(arg) {
    return function(result) { if (!result) $(arg).detach(); };
}

and

nude.scan( generateCallback(e.target) )

but the same thing happens.

What I want is a load event that will remove the image if it seems to contain nudity. How can I do this properly?

EDIT: nude.js works like this:

nude.load(imageid);
nude.scan(callback); // it'll pass true or false into the callback

another edit: accidentally omitted the id setting from the code I posted, but it was there in my real code, so I added it here.

itdoesntwork
  • 4,666
  • 3
  • 25
  • 38
  • Where are you setting the ID of the image? (Which you use in `nude.load`?). The code you've currently got will work fine, as `e` is a local variable. FYI, you should set the `src` *after* attaching the `load` handler, as otherwise cached images will load between setting the `src` and attaching the handerl. – Matt Jan 04 '14 at 23:12
  • I'm setting it to `i` with count increasing, but I omitted that from the code I posted here (it's there now), and I'm sure it's getting set for all of them. The code I have currently (both function factory and without) doesn't work though even after flipping the order of setting the `src` and the load handler. – itdoesntwork Jan 04 '14 at 23:16
  • Yeah, the src and load tip was more of an FYI rather than an "itll fix your problem". – Matt Jan 04 '14 at 23:24
  • What do you get if you do a `console.log(e.target.id)` just prior to the call to `nude.load`? – nick_w Jan 04 '14 at 23:48
  • @nick_w I also put a message after the scan completes, to illustrate the problem: http://pastebin.com/9it3DWi6 – itdoesntwork Jan 04 '14 at 23:56
  • Interestingly enough, if I replace `nude.scan` with a dummy function that calls the callback with `true`, the whole thing works. I think it's a problem with either nude.js or how I'm using it. – itdoesntwork Jan 05 '14 at 00:36

2 Answers2

2

I suspect the case here is that this kind of sequential processing won't work with nude.js.

Looking at the nude.js code, I think your problem is occurring in the call to nude.scan. nude.js has a variable that stores the function to invoke after the scan has completed. When calling nude.scan(callback), this variable is set to be callback.

From your PasteBin, it seems as though the callback gets assigned as expected on the first call, but on the second and subsequent calls, it gets replaced, hence why the second image is detached and not the first.

nick_w
  • 14,758
  • 3
  • 51
  • 71
-1

What happends to your script, is that the e var is global to the function and so after each loop it gets replaced with the new one. So when the first image is scanned, e already became the event of the second image, which get detached.

To solve your problem, use closures. If you want to know more about closures, have a look here. Otherway, here's the solution to your problem :

$(".images").prepend($("<img>").attr({src: whatever, id: uniqueid}).load(function(e) {
    (function(e) {
        nude.load(e.target.id);
        nude.scan(function(result) { if (!result) $(e.target).detach(); });
    }) (e);
});

EDIT: AS nick_w said, there is var that contains the callback and probably gets replaced each time so this is why it isn't the right picture getting detached. You will probably have to modify the script yourself

Community
  • 1
  • 1
yachaka
  • 5,429
  • 1
  • 23
  • 35
  • I thought this would be the case at first, but nude.js has a single variable that stores the callback to run post-scan. This gets set to the function that is passed in to the call to `nude.scan`. As such, the callback invoked is going to be the one supplied in the most recent call to `nude.scan` hence the problem. You can also tell from the pastebin in the comments that variable scope is not the problem. – nick_w Jan 05 '14 at 01:05
  • Sorry, but everything apart from your edit is wrong. `e` will not get replaced with each iteration, because it is local to the event handler. – Matt Jan 05 '14 at 13:34