views:

1168

answers:

3

I am using the Nov version of the AjaxControlToolkit, and I found a logic error, but I am trying to figure out the best way to fix this, by Saturday, so that the program will work on IE.

This problem only has an error on IE, it works on Firefox3.5.

I have a AsyncFileUpload component on a tab that appears to not be visible when this function runs, and so the offset width is zero.

The problem is in the file AsyncFileUpload.pre.js, in function _app_onload, and this line: this._innerTB.style.width = (this._inputFile.offsetWidth - 107) + "px";

I don't want to compile it from the source, but this may end up being my best option, so I can fix the error.

But, this is probably going to be my fix: this._innerTB.style.width = ((this._inputFile.offsetWidth == 0) ? 200 : this._inputFile.offsetWidth) - 107) + "px";

But, I don't know if there is a better solution.

I could just write a new prototype function in my javascript class and just fix the logic error, which is better than recompiling. If I fix it in the code, then whenever I do an update I will need to keep replacing that line, until it gets fixed in the codebase.

But, I am trying to figure out if there is a way for an element to know that it has just become visible, as anytime you need to know the actual width of an element then you can't really set it up until it is displayed. I can't think of a way to know that, so what I tend to do is fix the elements on the tab the first time the tab is selected, but, for a generic library that is not a possible solution.

Location of the main question

So, before I send in a bug report about this I am curious if there is a better way to do it, rather than having it done when the page has been loaded, and assuming a minimum width that is probably wrong. <-- Question located here

I am using the follow code to create the element:

                   <cc1:AsyncFileUpload ID="AsyncFileUpload1" runat="server" 
                        OnClientUploadError="uploadError" OnClientUploadStarted="StartUpload" 
                        OnClientUploadComplete="UploadComplete" 
                        CompleteBackColor="Lime" UploaderStyle="Modern" Width="400px"
                        ErrorBackColor="Red" ThrobberID="Throbber"  
                        onuploadedcomplete="AsyncFileUpload1_UploadedComplete" 
                        UploadingBackColor="#66CCFF" />

And if it makes any difference I am using this as the ToolkitScriptManager seemed to introduce other errors, but that may have been my error:

<ajax:AjaxScriptManager ID="scriptmanager1" runat="server" EnablePartialRendering="true" ></ajax:AjaxScriptManager>

I am not certain if LoadScriptsBeforeUI would be useful, but I believe that I want the UI done before the scripts are loaded actually.

I find it interesting that the width I set isn't actually set when the dom tree is completed.

A: 

This isn't the ideal solution, but it does work, hopefully someone will have a better solution, as this is something I cannot submit to fix the bug. I added this to a javascript file of mine, but it is a hack, not a good solution. I had to replace the second function because of the line I commented out.

$(document).ready(function() {
    Sys.Extended.UI.AsyncFileUpload.prototype._app_onload = function(sender, e) {
        this.setThrobber(false);
        if (this._inputFile != null) {
            if (this._onchange$delegate == null) {
                this._onchange$delegate = Function.createDelegate(this, this._onchange);
                $addHandlers(this._inputFile, {
                    change: this._onchange$delegate
                });
            }
            if (Sys.Browser.agent == Sys.Browser.Firefox) {
                this._inputFile.size = 0;
                var width = this._inputFile.offsetWidth;
                this._inputFile.style.width = "";
                while (this._inputFile.offsetWidth < width) {
                    this._inputFile.size++;
                }
            }
            if (this._innerTB != null) {
                this._inputFile.blur();
                var inputFile = this._inputFile;
                setTimeout(function() { inputFile.blur(); }, 0);
                this._innerTB.style.width = ((this._inputFile.offsetWidth == 0 ? 200 : this._inputFile.offsetWidth) - 107) + "px";
                this._inputFile.parentNode.style.width = this._inputFile.offsetWidth + "px";
                if (Sys.Browser.agent == Sys.Browser.InternetExplorer) {
                    this._onmouseup$delegate = Function.createDelegate(this, this._onmouseup);
                    $addHandlers(this._inputFile, {
                        mouseup: this._onmouseup$delegate
                    });
                }
            }
        }
    };

    Sys.UI.DomEvent.prototype._removeHandler = function (elements, eventName, handler) {
        Sys._queryAll(elements, function(element) {
            var browserHandler = null;
//            if ((typeof (element._events) !== 'object') || !element._events) throw Error.invalidOperation(Sys.Res.eventHandlerInvalid);
            var cache = element._events[eventName];
            if (!(cache instanceof Array)) throw Error.invalidOperation(Sys.Res.eventHandlerInvalid);
            for (var i = 0, l = cache.length; i < l; i++) {
                if (cache[i].handler === handler) {
                    browserHandler = cache[i].browserHandler;
                    break;
                }
            }
            if (typeof (browserHandler) !== 'function') throw Error.invalidOperation(Sys.Res.eventHandlerInvalid);
            if (element.removeEventListener) {
                element.removeEventListener(eventName, browserHandler, false);
            }
            else if (element.detachEvent) {
                element.detachEvent('on' + eventName, browserHandler);
            }
            cache.splice(i, 1);
        });
    }
James Black
A: 

My Solution... probably not the best but works.

 _app_onload: function(sender, e) {
    this.setThrobber(false);
    if (this._inputFile != null) {
        if (this._onchange$delegate == null) {
            this._onchange$delegate = Function.createDelegate(this, this._onchange);
            $addHandlers(this._inputFile, {
                change: this._onchange$delegate
            });
        }
        if (Sys.Browser.agent == Sys.Browser.Firefox) {
            this._inputFile.size = 0;
            var width = this._inputFile.offsetWidth;
            this._inputFile.style.width = "";
            while (this._inputFile.offsetWidth < width) {
                this._inputFile.size++;
            }
        }
        if (this._innerTB != null) {
            this._inputFile.blur();
            var inputFile = this._inputFile;
            setTimeout(function() { inputFile.blur(); }, 0);
            if ((this._inputFile.offsetWidth - 107) >= 1) {
                this._innerTB.style.width = (this._inputFile.offsetWidth - 107) + "px";
                this._inputFile.parentNode.style.width = this._inputFile.offsetWidth + "px";
            }
            if (Sys.Browser.agent == Sys.Browser.InternetExplorer) {
                this._onmouseup$delegate = Function.createDelegate(this, this._onmouseup);
                $addHandlers(this._inputFile, {
                    mouseup: this._onmouseup$delegate
                });
            }
        }
    }
},

have forked at http://ajaxcontroltoolkit.codeplex.com/SourceControl/network/Forks/keyoke/AyncFileUploadFix

keyoke
Where do you put the code, in the onready function, if using jquery? That was my main problem making certain it was loaded at the right time, as my solution works, but sometimes it didn't it had to run after the javascript I wanted to change was loaded, but before it actually ran, so there was a race going.
James Black
I updated the init function, tested with post async and postback seems to work ok. But I guess my control is initially visible so thats why it works as has already set these properties to correct value.... havent had a chance to investigate further
keyoke
A: 

hi, try add this attribute to your scriptmanager

LoadScriptsBeforeUI="true"

I have download the source code and fix the codeline,but it still not working, then I add this attr to the scriptmanager,it works !!

check this page for detail if U wanna change the source code http://ajaxcontroltoolkit.codeplex.com/SourceControl/network/Forks/keyoke/AyncFileUploadFix/changeset/changes/30da4b8d1c6d

googi
Thank you, I haven't tried this, and I am no longer working on that project, but it looks like a great answer.
James Black