开发者

JavaScript multiple object instances, cannot correctly access properties inside event handler

I have a working version of HTML5 drag & drop file uploader. I was editing the JS code to support multiple file uploads on same page. I came across with a problem by trying to access "instance" properties in methods which are registered as events.

The problem is shown by the code below, in method this.drop. The reason of existence of the this.$$upload_self property is to access data through this property. For example, I can't use this keyword inside this.drop function, because when event is raised, this not referring my "instance".

I'm not sure that by creating $$upload_self was a good idea.

The new instances area created like this:

  var recording_upload = new upload();
  recording_upload.init(recording_upload, ...);

Code of Drag & drop file upload:

    var upload = function() {
    this.$$upload_self = null;
    this.$drop = null;
    this.$status = null;
    this.$progress = null;
    this.maxNumberOfFiles = null;
    ...
    
    this.init = function (self, pUrl, maxNmbOfFiles, dropArea, progress, status) {
        $$upload_self = self;
        $$upload_self.postUrl = pUrl;
        $$upload_self.maxNumberOfFiles = maxNmbOfFiles;

        $$upload_self.$drop = $("#" + dropArea);
        $$upload_self.$progress = $("#" + progress);
        $$upload_self.$status = $("#" + status);

        $$upload_self.$drop.bind('dragenter', $$upload_self.enter);
        $$upload_self.$drop.bind('dragleave', $$upload_self.leave);
        $$upload_self.$drop.bind('drop', $$upload_self.drop);
    };
    
    this.enter = function (e) {
        $(e.target).addClass('hover');
        return false;
    };

    this.leave = function (e) {
        $(e.target).removeClass('hover');
        return false;
    };
    
    this.drop = function (e, _this) {
        $(e.target).removeClass('hover');
        var files = e.originalEvent.dataTransfer.files;

        if (files.length > $$upload_self.maxNumberOfFiles) { // for example, here $$upload_self references always last instance...
            $$upload_self.di开发者_运维知识库splayErrorMessage('Error: You can only drop ' + $$upload_self.maxNumberOfFiles + ' file(s) at time.');
            return false;
        }
     ...
    };
    ...
}

Is there any workaround to solve this issue? I believe this maybe a common problem, but can't find nothing to solve this problem.

Any help is very much appreciated.


You could ditch the new keyword altogether and use a fresh closure for each instance of upload.

EDIT: Updated to avoid potential clobbering of global this.

var upload = function(pUrl, maxNmbOfFiles, dropArea, progress, status) {
    return {
        postUrl: pUrl,
        ...
        drop: function(e) {
            ...
            if (files.length > this.maxNumberOfFiles) {
                this.displayErrorMessage(...);
            }
            ...
        },
        ...
    };
};

...

var someUpload = upload(...);


Try to search for a "scope". As an example see how it implemented in ExtJS.


In a modern browser you can do this:

  $$upload_self.$drop.bind('dragleave', $$upload_self.leave.bind($$upload_self));

For older IE versions you can do this:

  $$upload_self.$drop.bind('dragleave', function() { $$upload_self.leave(); });

Really the ".bind()" method of all Function objects in new browsers just creates a little intermediate function for you, essentially like the second example. The Mozilla docs page for ".bind()" has a very good block of code you can use as a "polyfill" patch for browsers that don't support ".bind()" natively.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜