Differences between designMode and contentEditable

To make a web page editable, IE provides two methods. One of them is setting document.designMode = “on”, which can only be applied to the entire document. And the other method is setting contentEditable = “true”, which can be applied to any HTML elements. The good part of the first method is that the same syntax can also be used for Firefox, which is why I prefer using the method. According to the document located at http://msdn2.microsoft.com/en-us/library/ms537837(VS.85).aspx, setting document.designMode = “on” and document.body.contentEditable = “true” are supposed to have exactly the same effect.

 

And it did look like they do

 

But as I go on and do more things with the editor, I started to make some disturbing discoveries. The first weird thing I noticed was that if the document.domain property was set for the document, I don’t get to access the editing area as the browser would throw an “access denied” exception. I’m sure that this should not have anything to do with the cross-domain issues because

1. The same domain value was set for the outer document and the editing area (iframe).

2. Firefox does not complain.

3. It works fine if I used the second method and make use of the contentEditable property.

 

And the next thing I discovered is that those two methods react differently to the lines that the source code looks something like <p> </p>. The designMode method would take it as a blank line. But the contentEditable method would take it as a line with a “space”.

 

These behaviours are not documented anywhere and took me such a long time to pin point what is causing the differences. And I believe that there must be more “subtle” differences between the two, which would cause someone to spend a hell of a time. So, if any of you reading this, discover any other differences, it would be very appreciated if you would share your knowledge here. 😀

 

Should I go for designMode or contentEditable for my editor?

It has been such a confusing time for me. Then, I saw this article http://starkravingfinkle.org/blog/2007/07/firefox-3-contenteditable/, which says that Firefox will have support for contentEditable property for the next major release. And now, my guess is that the designMode would slowly fade away as contentEditable is “supposed” to do the same thing and some more. So, yes, my decision for now is the contentEditable for IE/Safari and designMode for Firefox until the support is added.

Reading binary files using Ajax

A growing number of web applications are making more and more use of client-side technologies because thanks to Ajax, it is now possible to write more fluid and more responsive web applications using only client-side technologies.

Now, web developers from all around the globe are releasing really interesting utilities and applications using only client-side technologies, many of which used to be within the domain of server-side technologies.

But when it comes to binary files, helping hands from server-side technologies are often necessary.

So I googled around to see what I can do about binary files with Ajax and found this Marcus Granado’s post at http://mgran.blogspot.com/2006/08/downloading-binary-streams-with.html

What he posted there worked like a charm for FireFox and Safari but I couldn’t get it to work for IE.

But luckily, within the same page, someone had posted up a solution for IE as a comment, which is written in VBScript.

So I put them all together in this BinFileReader function, which provides cross-browser support and helper methods to easily access the binary contents.

 

* BinFileReader: http://www.heypage.com/nagoon97/BinFileReader/BinFileReader.js

getFileSize() Return the file size
getFilePointer() Return the reading position
movePointerTo(iTo) Move the reading position to iTo.
movePointer(iDirection) Move the reading position in iDirection.
For all the following read functions,
– The reading position will move to the end of where the content is last read
– When iFrom is ommited, current reading position is used
readNumber(iNumBytes, iFrom) Read and return iNumBytes-byte number starting at iFrom.
readString(iNumChars, iFrom) Read and return iNumChars characters starting at iFrom.
readUnicodeString(iNumChars, iFrom) Read and return iNumChars unicoded characters starting at iFrom.

 

* Example:
var bmpFile = new BinFileReader(“image.bmp”);
bmpFile.movePointerTo(18);
var width = bmpFile.readNumber(4);
var height = bmpFile.readNumber(4);

 
* Demo:
http://www.heypage.com/nagoon97/BinFileReader/BinFileReader_demo.html

http://www.heypage.com/nagoon97/BinFileReader/MosaicBuilder_demo.html

 

* Related Posts 

http://nagoon97.wordpress.com/2008/04/09/ajax-mosaic-builder/

Method overloading in Javascript

To simulate method overloading in Javascript, many “if” statements are often used, which makes the code alot less intuitive.

So, I came up with the following function to simulate method overloading without harming the readability of the source code.

/**
 * You can find more about this function at
 * http://nagoon97.com/method-overloading-in-javascript/
 *
 * Copyright (c) 2008 Andy G.P. Na <[email protected]>
 * The source code is freely distributable under the terms of an MIT-style license.
 */
function methodOverloading(funcName, args) {
    var sFuncName = funcName;
    var func = null;

    sFuncName += "$" + getType(args[0]);
    for (var i = 1; i < args.length; i++) {
        sFuncName += "$" + getType(args[i]);
    }

    if (func = eval(sFuncName))
        return func.apply(this, args);

    throw (sFuncName + " is not defined");
}

Just place the function like the following and you are ready to go.

function add() {
    // pass in the function name as the 1st element of the 2nd argument
    return methodOverloading.apply(this, ["add", arguments]);
}

Now, you can overload a function just by naming the new functions with the type of parameters that the function takes, each parameters separated by a string.

function add$string$string(str1, str2) {
    return str1 + ", " + str2;
}

function add$number$number(num1, num2) {
    return num1 + num2;
}

function add$undefined() {
    return "no parameter is given!";
}

And when you call the function

alert(add("s1", "s2")); // this will display "s1, s2"
alert(add(1, 2)); // this will display 3
alert(add()); // this will display "no parameter is given!"

Please note that you need to include getType() function that I have posted HERE.
getType() is used to give methodOverloading() function the ability to overload method with user defined custom objects.
If this feature is not needed and you do not want to include the function, you can change it to typeof() and use it as

function methodOverloading(funcName, args) {
    var sFuncName = funcName;
    var func = null;

    sFuncName += "$" + typeof(args[0]);
    for (var i = 1; i < args.length; i++) {
        sFuncName += "$" + typeof(args[i]);
    }

    if (func = eval(sFuncName))
        return func.apply(this, args);

    throw (sFuncName + " is not defined");
}

And just in case you were wondering how to use this in a function,

function inc() {
    this.do = function() {
        return methodOverloading.apply(this, ["this.do", arguments]);
    }
    this.do$string = function(str) {
        return str + ", " + str;
    }
    this.do$number = function(num) {
        return num + 1;
    }
}

oInc = new inc();

alert(oInc.do("ABC"));
alert(oInc.do(1));

 

Improved typeof for the exact object type

When I first started writing scripts in Javascript, the typeof() operator did not capture much of my attention.

Because of my experience in other programming languages, I naturally believed that the operator would give me the exact name and this firm belief cost me many hours of debugging.

And when I realized that the operator won’t even tell me whether a given object is an instance of Array or Date, it was very frustrating because I’ve designed the entire script based on the assumption that the operator would provide me the exact object type.

So, I wrote the following short function, which privodes the constructor’s function name when it was given an object.

/**
 * You can find more about this function at
 * http://nagoon97.com/gettype/
 *
 * Copyright (c) 2008 Andy G.P. Na <[email protected]>
 * The source code is freely distributable under the terms of an MIT-style license.
 */
function getType(v){
 var result = typeof(v);
 if (result == "object"){
  result = "@unknown";
  if(v.constructor){
   var sConstructor = v.constructor.toString();
   var iStartIdx = sConstructor.indexOf(' ' ) + 1;
   var iLength = sConstructor.indexOf('(' ) - iStartIdx;

   var sFuncName = sConstructor.substr(iStartIdx, iLength);
   if (iStartIdx && sFuncName) result = sFuncName;
  }
 }
 return result.toLowerCase();
}

“@” was added in front of the word “unknown” because the function name can actually be “unknown” and this confusion can be avoided by adding “@”, which cannot be used for function names.