Elod P Csirmaz’s Blog: 2009

7 December 2009

Triggering a click event

One would think that to simulate a click event on a link, one would only have to call OBJECT.onclick(). However, apart from not following the URL set in the HREF, this does not seem to trigger event handlers that are not in the actual inline onclick handler, but have been attached to the object later. There is, however, another solution that does this:

function doEventDispatch() {
var evt = null,
elm = null;

if(document.getElementById) {
elm = document.getElementById('test');
}
if(document.createEvent) {
evt = document.createEvent('MouseEvents');
}
if(elm && elm.dispatchEvent && evt && evt.initMouseEvent) {
evt.initMouseEvent(
'click',
true, // Click events bubble
true, // and they can be cancelled
document.defaultView, // Use the default view
1, // Just a single click
0, // Don't bother with co-ordinates
0,
0,
0,
false, // Don't apply any key modifiers
false,
false,
false,
0, // 0 - left, 1 - middle, 2 - right
null); // Click events don't have any targets other than
// the recipient of the click
elm.dispatchEvent(evt);
}
}

(from a post by Michael Winter)


This still won't follow the URL set in the HREF attribute, so one might need to add

location.href=elm.href;

27 November 2009

Position:relative hides floats in Firefox

Probably one of the weirdest CSS things in Firefox is that something with position:relative will go over a float placed next to it. It does not happen if the position is static. It is hard to detect, but it can effectively disable all your links in a floated container, as they become hidden under a transparent P or DIV. The situation is the same in Chrome, but not in IE8.

Here is a little test: the red DIV is floated and includes a large link. The blue DIV has position:relative.


a
a
a


The link is only accessible below or above the blue container. I've found no other way of fixing this than to give position:static to elements next to the float.

21 October 2009

A solution to broken 'this' when using methods as handlers in JavaScript OO

Perhaps you've already run into the problem that 'this' does not refer to the instance the method belongs to when one tries to use a method in an object outside the context of the object, like as an event handler. To take an example using jQuery:

function myClass(){
this.myvar="Hello";
this.myfunc=function(){
alert(this.myvar);
}
}
var obj=new myClass();
$(document).ready(obj.myfunc);

The code would not work as 'this' inside event handlers in jQuery always refers to the HTML element that fired the event. An easy way of solving this is to take advantage of closures, that is, the fact that a function retains its execution context. In other words, a variable defined outside the function is accessible even if the function is called outside its original context, via a reference. Amend the above script as follows:

function myClass(){
var me=this;
this.myvar="Hello";
this.myfunc=function(){
alert(me.myvar);
}
}
var obj=new myClass();
$(document).ready(obj.myfunc);

This would work as expected. During instantiation, the variable 'me' becomes a reference to the object being defined. As it is in the execution context of myClass::myfunc, it remains accessible, and thus the current object can be reached from within the function even without using 'this'.

14 October 2009

Diff Tool for Source Codes

I've been trying to search for a diff tool with readable HTML output to create reports on scripts and source codes under development. As I couldn't find one that met my needs, I created one: it's accessible at http://www.epcsirmaz.co.uk/?q=diff.

Some features:
- Hosted on-line, there is no need to install anything locally
- Easily readable HTML-based output with the two versions displayed side by side
- Wrapped long lines
- Specially adapted to text files: disregards whitespaces and treats empty lines specially

As the script is specially adapted to detect individual insertions and removals, it is not an implementation of the longest common subsequence problem -- although I might amend the script later.

Hope you'll find this useful!

10 October 2009

jQuery UI Draggable and IE8

An interesting fact: if you use jQueryUI draggable on two DIVs one of which is contained in the other, interesting things can happen. If you start to drag the inner DIV, Firefox and Opera behaves as expected: only the inner DIV starts to follow the mouse. IE, however, starts to drag both DIVs, which results in the parent DIV following the mouse, and the child DIV moving twice as far as the mouse from the original location.

A solution to this problem can be to bind an event handler to the mousedown event on the child DIV, and stop event propagation.

15 September 2009

Firefox caches JavaScript variables

It seems that Firefox (since 1.5) tries to cache not only the contents of a page, but JavaScript variables as well with something called bfcache. This also means that, among other things, the onload event will not fire if the user uses the Back button, or that variables set on the page will not be re-set and global scripts are not executed again. This can be important in AJAX-based applications, or if one tries to implement an analytics system on the page.

Apparently, defining an onunload event handler prevents Firefox from doing this kind of caching.

Why is a global variable undefined?

It took me some time to debug a script in which a global variable was undefined in a function, as I thought it was due to closures or other scope-related things. But the real cause was simple: if a global variable is re-declared as local in a function, then it is undefined in the local scope before its second declaration.

var x=1;

function myfunc(){
alert(x); // shows "1"
}

function myfunc2(){
if(typeof(x)==='undefined'){
// this will execute as "x" is undefined here
}
var x=2;
alert(x); // shows "2"
}

Checking if a variable is defined in JavaScript

In short, do not use "if(myvariable){ ... }" to check whether a variable is defined in JavaScript, because if it is not, the browser will return with an error and stop executing the script. The typeof operator can be used instead: "if(typeof(myvariable)!=='undefined'){ ... }".

According to this article, checking "window.myvariable" might be necessary, although the tests I've done do not show that "x" and "window.x" would behave differently.

22 August 2009

PNG, gamma correction and IE7

It seems that not only PNG and IE6 can lead to unexpected difficulties -- PNG displayed in IE7 or IE8 can also surprise one. This is because PNG files can contain gamma correction information, and while most web browsers ignore this when displaying the image, IE7 and 8 do not. This can cause your images not to match the background they have been sliced from, and other unexpected things.

The solution might be to get rid of the gamma correction value altogether, as it is, fortunately, optional. (Or save everything as PNG with the same value.) In older browsers, however, this can cause problems. TweakPNG, as for setting the default background colour, is still a very good solution to edit these pieces of information in PNG images.

Source

29 July 2009

position:absolute vs. floats and containers

If you, like me, have run into the problem of defining a container for floated or absolutely positioned elements, this summary post might be helpful.

Absolutely positioned elements are positioned relative to a parent element which is a "containing block" a.k.a "offset container" a.k.a "layer". To make an element an offset container, simply use

- position:absolute, or
- position:relative, or
- position:fixed.
- position:static will not result in an offset container!

Coordinates of clicks are also returned according to offset containers. See this page as a source.

With floats one usually runs into the problem that they stick out of their parent elements, that is, the parent element is not stretched as far as the floats go. To solve this problem, the parent element needs to create a new "block formatting context". This happens if

- the parent element is floated
- its overflow is NOT visible (Note: May not work in IE6)
- its display property is a less common variant (table-cell, inline-block, etc.)
- its position is absolute or fixed (relative or static will NOT work)

See this post or Matt Ryall's article for more.

23 July 2009

Border-collapse bug in Firefox

You might be surprised if you try to draw another border around a table if border-collapse:collapse is set on the table itself, as Firefox happens to merge the border of the table with that of the element outside it. Here is a simple markup:

<div style="border:1px solid blue;width:20px;">
<table style="border:1px solid red;border-collapse:collapse">
<tr><td>X</td></tr>
</table>
</div>

And the result in FF 3.5 magnified:



The overlap is one pixel only, but it is enough to hide a 1px-wide border. The borders are drawn as expected in other browsers. The solution can be to use border-collapse:separate.

Images in DIVs and a small vertical space

It is trivial, yet I've forgotten. By default, images are inline elements, and are placed on the baseline. If one puts a DIV around it, it will include a small space below the baseline to accommodate letters extending below it. Here is a real-life example:



This cannot be fixed with a vertical-align on the IMG. Either set line-height in the DIV to zero, or the IMG should be rendered as a block element.

6 July 2009

Strange full width bug in Firefox 2

Fiefox (unlike IE6, Opera, Safari and Chrome) behaves strangely when trying to figure out the width of certain embedded elements.

By default, a DIV or a LI, as block elements, should take up 100% of the available horizontal space. However, in a certain combination of elements, Firefox 2 seems to get the size wrong. The simplest case I could find was the following:

CSS

html,body,ul{
margin:0;
padding:0;
border:0;
}
div#big{
border:1px solid red;
}
div#small{
min-width:20%; max-width:30%; /* USE width:25%; */
float:left;
border:1px solid black;
overflow:auto; /* USE visible */
}
.element{
border-bottom: 1px dashed black;
}


Markup

<div id="big">
<div id="small">
<div class="element">text</div>
<div class="element">longer-text</div>
<ul class="element"><li>list</li></ul>
</div>
</div>


What happens is that the elements classed as "element" will not take up the whole width of div.small. What is even more interesting is that all three of them have the very same width -- the width of the widest among them.

The phenomenon disappears if:

- one uses a normal "width" property on div#small (even if it is a percentage)
- if div#small's "overflow" is "visible" instead of "auto" or "hidden"
- div#small is not floated.

I have not tested this on newer versions of Firefox.

5 July 2009

Float container height (clearing)

It seems to have been a common problem to force containers to be at least as tall as floated elements that are contained in it. Alex Walker wrote an excellent article about some solutions as well as about very simple one.

The simple solution is to give overflow:auto; (or none) to the container. It seems to work in most browsers I have tested. NOTE: This seems to be related to the so-called block formatting contexts, which are explained here by Matt Ryall. The very same technique allows repairing blocks adjacent to floated elements.

I less elegant solution is to insert <br style="clear:all" /> just before the closing tag of the container. This, however, pollutes the markup.

Another solution seems to be to float the container as well.

I hope this post will make it easier to find this excellent article for whomever might need it.

11 June 2009

mousedown, click and dblclick events

Figuring out what kind of click occurred on an element can be tricky, as browsers treat mousedown, click and dblclick events differently. As I was developing a game in which a user might click on an element several times in a row, I started to experiment with these events. Below are the results represented in a nice visual way.

'd' stands for a mouseDown event
'u' stands for a mouseUp event
'.' signals a click event, and
':' stands for a dblclick event

Click and dblclick events are organized in different rows to make the pattern easier to identify. Event handlers were registered on an A element using in-line "on..." attributes, and the page was tested with a series of quick clicks.

Firefox 2 and Safari 3.2.3 (Win)
: : : :
. . . . . . . .
du du du du du du du du

-- This is a nice and clean pattern
with all possible events fired

Opera 9
: : : : :
. . . . . . . . . .
du du dddu du dddu du dddu du dddu du

-- The case here is complicated by a context menu
appearing after double clicks. Further mouse clicks
(see the mousedown events) close this menu, but do
not lead to click events

IE 6 and 8
: : : : :
. . . . .
du u du u du u du u du u

-- Here, click events appear in lieu of mousedown
events, and doubleclick events appear in lieu of
click events.

It might be tricky to find a direct way to know the number of clicks on an event if they happen in quick succession. The context menu of Opera aside, the number of mouseup events would be accurate. One could also try to combine mousedown, click and doubleclick events using some time measurement, or to use different strategies after browser detection.

29 May 2009

IE6 and transparent PNG images -- a solution

If you have ever been disturbed by the fact that Internet Explorer 6 uses either a background color stored in PNG images or a default background color to render transparent and semi-transparent pixels, here is a solution:

You can edit the default background color using tweakPNG. You will have to add and/or edit the bKGD "chunk" in the file, setting it to a color similar to the background on your webpage.

20 May 2009

onload and complete of images in IE, Firefox and Safari

Firing the onload() event seems to be inconsistent across browsers. I've tried to explore how browsers behave in this respect, as well as how the .complete property changes. Here are my findings:


ONLOAD FIRES COMPLETE
first cached new first cached new
Firefox 3 Y Y Y F T T
Firefox 2 Y Y Y F T T
IE 8 Y Y Y F T T
IE 6 Y Y Y T T T
Opera 9.52 Y Y Y T T T
Safari 3.2.3 Y N Y F T F


where 'first' means the case when first assigning a source to an image via JavaScript, 'cached' means when assigning the same source once again, and 'new' means when assigning a different source to the image. Values in the 'complete' section show the value of the .complete property as checked immediately after assigning the new source, and thus might be unreliable in case the connection is too fast.

Konqueror probably behaves the same way as Safari. The basic problem of registering the completion of image loads is with these two browsers; however, as the table shows, .complete can be used to distinguish between already cached images and images that are to be loaded.

14 May 2009

Geeting the relative coordinates of a click

If you want to get the coordinates of a click event relative to the object it happened to, the following event handler works fine on all borwsers provided that the object counts as a layer (offset container). To achieve this, use position:relative or absolute on the object.
funtion(e){
var mx=0;
var my=0;
if(window.event){
mx=window.event.offsetX;
my=window.event.offsetY;
}else{
mx=e.layerX;
my=e.layerY;
}
}

To get the global coordinates, see http://www.quirksmode.org/js/events_properties.html#position

Editor for Developers (Windows)

I was searching for a quick and nice editor to write JavaScript, PHP and XHTML code which could do autoindent, parenthesis pairing and some syntax highlighting. PsPad turned out to be a good solution; it's fully customizable, has tabs for each file opened, and it's free. http://www.pspad.com/.

Syntax Highlighting

This blog will use alexgorbatchev's Syntax Highlighter 2.0 to show snippets of codes in a more readable form. On first sight, it seems to be a nice and easy-to-use software, but only time will show how easy it is to integrate into Blogger.
http://alexgorbatchev.com/wiki/SyntaxHighlighter

JavaScript Event Object Reference

This seems to be a great reference for the JavaScript event object, emphasizing differences between IE and other browsers.
http://www.javascriptkit.com/jsref/event.shtml

While quriksmode.org describes compatibility issues in detail:
http://www.quirksmode.org/js/events_properties.html