Click to show private chat

Want to thank me? Put this in your blog:

Siderite Zackwehdex's Blog

↑ Grab this Headline Animator

Low band version

Monday, July 13, 2009

jQuery UI resizable plugin - relative position issues and external handles
0 comments

Well, I have been trying to build this control and from day one I had weird issues with the display on Internet Explorer 7. Apparently, because of a bug Rick Strahl reported in his blog, elements that have the position relative escape their containers when the containers themselves are not relative. You will see there a comment from me when I hadn't really understood the problem :(

With the jQuery UI resizable plugin, the base functionality is to change the entire body of the resized control to position relative, causing all kind of trouble, only to permit the resize handles to move around the element (like the south handle having a bottom setting of aproximately 0 px). So, after making all kinds of changes to the javascript in order to solve the IE7 relative position bug, I finally submited and started changing the resizable plugin itself.

The idea was simple: remove position relative, make two divs, one inner and one outer, resize them both in the same time, while another div placed in between would act as the south handle. But it didn't work. I couldn't set an element external to the resized element as the handle, as explained here.

The fix above, though, doesn't entirely show the dimension of the problem. The resizable plugin is incredibly buggy! The documentation says that you can specify custom handles either as jQuery strings or as elements or jQuery objects. That is not correct, as the handles passed as objects are stored in a handles field, but then another _handles field is initialized and the first completely ignored! Also, as in the post above, you need to bind the javascript events to every external element as well, since the original mouse capturing events are placed only on the resized element.

Ok, so the fix is this:

  • look for a this._handles = $('.ui-resizable-handle', this.element).disableSelection(); line. This is where handles is being ignored. Replace it with:
    if (this.handles) {
    var handles=$('nothingReally');
    for (var i in this.handles)
    handles[handles.length++]=this.handles[i][0];
    this._handles=handles;
    } else {
    this._handles = $('.ui-resizable-handle', this.element)
    }
    $.each(this._handles,function() { $(this).disableSelection(); });
  • look for a _mouseInit: function you will see there a line like this.element.bind... you need to add a similar one underneath for all the handles:
    // Add mouse events for the handles as well
    if (this._handles)
    for (var i=0; i<this._handles.length; i++) {
    $(this._handles[i]).bind('mousedown.'+this.widgetName, function(event) {
    return self._mouseDown(event);
    })
    .bind('click.'+this.widgetName, function(event) {
    if(self._preventClickEvent) {
    self._preventClickEvent = false;
    event.stopImmediatePropagation();
    return false;
    }
    });
    }


The change here allows to pass objects (either elements or jQueries) as handles, thus allowing for external elements to act as handles. Removing 'this.element' from the query is not a good idea in case you want to use more resizable controls on the same page. You want only children of a container to act as handles. It could work to move upwards on the control tree until you can get a child that fits the string jquery, but I think that's overkill.

Hope that helps someone.

Thursday, July 09, 2009

GetWebResourceUrl generated WebResources.axd url is invalid
0 comments

I made a few controls that loaded and included a resource js file. And it all worked well, until I wanted to load the js file from the Page object. The generated url was invalid. After hours of nervewrecking attempts I realised that the problem was I was using control.GetType() to get the type required as a parameter in GetWebResourceUrl. And the page, even if inheriting from a custom page object that resided in the assembly where the embedded resources were, was of the site assembly.

Solution: use GetWebResourceUrl(typeof(knownClassInTheAssembly),resourceName);

Warning: my object was inherited from Page and placed in the necessary assembly. And it still didn't work. It is good to remember that ASP.Net pages are not of the type they inherit from, but a class with the name of the page and that resides in the dynamically generated assembly of the site! So be careful where you use this.GetType()

jQuery Firexof error: Could not convert JavaScript argument arg 0 [nsIDOMViewCSS.getComputedStyle]
0 comments

So I am building this new jQuery based control and I am terribly smug about it until I run the test site on FireFox. Kaboom! Nothing is working. Why? Because FireFox has some issues with the computed style on hidden elements and jQuery people just don't want to fix the problem. But hey, jQuery is open source, right?

So, let's detail the problem. Here is a jQuery bug posting that explains far better than I could what is going on. Aparently, the offsetParent of a hidden element is null in FireFox and the jQuery core function returns the document object when null is given as a parameter [ $(null)==document ]. Then running the FireFox specific function for getting the computed style [ document.defaultView.getComputedStyle(element,null) ] throws an error because the element is now document and it has no style, only its body has.

So, why not fix that? The FireFox error text is '[Exception... "Could not convert JavaScript argument arg 0 [nsIDOMViewCSS.getComputedStyle]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: /jqueryJsFile/ :: anonymous :: line 1349" data: no]'.

The line number might vary with the type of jQuery file version you are using and the amount of modifications you have done to it. What you should find at said line is something like: var computedStyle = defaultView.getComputedStyle(elem, null);.

Solution: Just add above it if (elem == document) elem = document.body; and it solves this particular issue.

In the minifyied version look for var M=q.getComputedStyle(I,null) and add before it if (I==document) I=document.body;


It would be far more elegant to address the problem where the offsetParent is assumed to be not null, but with so many plugins for jQuery, you can't just test them all.

PNG images are not displayed!
1 comments

I met an especially obnoxious situation where I had deployed a perfectly working control library on a server and then, when testing how it worked using the remote browser on that server, I noticed only some of the resources where displayed. Mainly, some PNG files where not loaded.

Funny enough, if I went to the properties of the displayed images I saw their correct size. That actually meant that they were loaded correctly, so it wasn't a WebResource.axd issue. The remote browser was Internet Explorer 7, which has no problems displaying the PNG format. After changing all the images to GIF, I also found a solution for that problem.

Some "security" feature in Windows, especially Windows Server 2003 SP1, but also in SP2, messes with some PNG images being displayed. Probably, that security option was implemented to fix this issue. Here is the Microsoft knowledge base article detailing the fix.

Wednesday, July 08, 2009

WebResource.axd or ScriptResource.axd do not work!
1 comments

So you have some embedded resources in your ASP.Net control library and you want to use them. But instead, nothing works. Scripts are not loaded and images are not displayed.

Look in the IIS log files and check for an error like this: "Exception information: Exception type: ArgumentOutOfRangeException Exception message: Specified argument was out of the range of valid values. Parameter name: utcDate".

If you see it, then your assembly where the resources are embedded has the build date into the future! This also applies to the code you just built and the date is correct and the date of the server where you want to copy it to is in the past. It also applies when the time is in the past, as when you are copying it on a server in a different timezone!