8/09/2007

Has Taiwan Never Been A Country In History?

0 comments

David Lu of the Taipei Economic and Cultural Office (TECRO) in San Francisco, a branch of Taiwan's officially unofficial representative office in the US, post an article in San Jose Mercury News regarding the issue of Taiwan entering UN (United Nations' exclusion of Taiwan is unjust). Some readers commented and claimed that "Taiwan has never been a country in the history".

In rebuttal, I post an article:

1) raventhorn: "Fact is, Taiwan NEVER represented itself in any treaty negotiations or signed any treaties. It was always considered as a part of some other country's territorial administration."

2) Alvin Ding: '"Taiwan" was never be a country in history'

----

These are incorrect statements. In her history, Taiwan established herself as an independent country at least twice, and exercised her sovereignty right through treaties numerous times.

In 1664, Cheng Jing (鄭經), son of Cheng cheng-gong (鄭成功), founded Tong-Ning Kingdom (東寧王國) in Taiwan. The kingdom has her own government, own army, own social system, and own business interactions with surrounding countries. It also has other own diplomatic relationships with other powers, in which Cheng was called "The King of Tyawan." (Taiwan was sometimes spelled as Tyawan at that time)

In 1895, Republic of Taiwan was established in Taiwan by Liu Jing-Song (劉景崧). It is the first republic country in Asia.

Aside from the above 2 official establishments, Taiwanese had exercised their sovereignty right independently as a country. For example, by signing treaties with other countries, as what Michael mentioned in his earlier post:

"the Qing denied controlling Taiwan on several occasions, and foreign powers negotiated directly with local aborigine leaders."


The countries who signed treaties with Taiwanese include USA, after USA marine was defeated (and one of USA Civil War Generals killed) by Taiwan aborigine (in around 1780, I believe).

Following raventhorn's own words: 'Treaties largely make up the foundation of "de jure" sovereignty,' then Taiwan has been an independent sovereignty many times in her history.

These are historical facts that shouldn't be withheld from the readers. I have to agree with Michael: "Raventhorn's 'rebuttal' sounds credible only because he withholds key facts from the reader."


Btw, David Lu's article is full of errors, not only in facts but also in English grammar.

7/23/2007

Javascript string replacing function (2)

0 comments

Previously I mentioned a string replacing function that, instead of building a string this way:

tag= '<' + tagname + ' style="background-color:'
+ bgcolor + ';color:' + color + '">' + text + '</' + tagname +'>'

allows for doing it this way:

tag0= '<___ style="background-color:___;color:___">___</___>'
tag1 = tag0._(tagname, bgcolor, color, text, tagname)

or this way :

tag00= '<[.tagname.] style="background-color:[.bgcolor.];'+
'color:[.color.]">[.txt.]</[.tagname.]>'

data = {tagname:'span', bgcolor:'#EEFFBB',color:'red',txt:'tag2'}
tag2 = tag00._(data)


After playing with the regular expression for a while, I come up with a short version :

String.prototype._=function(){
var i=-1, a= arguments
var t= typeof(a[0])=='string'
var rx = t?(/___/g):(/\[\.[A-Za-z0-9_]*\.\]/g)
var f = t?function(x){i++;return a[i]}
:function(x){return a[0][x.slice(2, -2)]||''}
return this.replace(rx,f)
}


To me it's amazing to see how such a task can be accomplished with such a neat code.

7/21/2007

Problems in Javascript Subclassing

0 comments

In javascript, the subclassing is done this way:

[1] function Person(name, sex){    # Define the superclass
[2] this.name = name
[3] this.sex = sex
[4] this.prn = function(){ return this.name + ', '+ this.sex }
[5] }

[6] function Man(name){ this.sex = 'M' } # Define the subclass
[7] Man.prototype = new Person() # Connect Person and Man

And the instantiation:
[8]  p = new Person('Jane','F')
[9] m = new Man('John')

Checking the function prn (defined in [4]):
p.prn() ==> Jane, F
m.prn() ==> undefined, M


As shown, the name John given to Man when instantiating m ([9]) is NOT transferred to m. It is obvious 'cos we didn't instruct it to do so when defining Man in [6].

Problem.1: Subclass Arguments Are Not Automatically Transferred To Subclass Instances



So, unless explicitly instructed, the arguments of a subclass will not be assigned to the instance of that subclass. That means, [6] needs to be re-defined as:
function Man(name){ 
this.sex = 'M'
this.name= name # <== new line
}

Note that the above highlighted line already exists in the superclass (line [2]). Why does it have to be re-done again in the subclass ? Didn't we already instruct Person to be the super class ?

Problem.2: An Instance of Subclass Is an Instance of the Superclass too ?


Lets investigate the instanceof operator in javascript:
[10] (p instanceof Person)  ==> true
[11] (m instanceof Man) ==> true
[12] (m instanceof Person) ==> true


Line [10] and [11] are what we expect. But [12]? How come m is an instance of Person ? This doesn't sound right.

Problem.3: The Constructor of A Subclass' Instance Is The Superclass But Not the Subclass ?


Check the constructor of the instances of subclass and of superclass:
[13] getConstructor(p) ==> Person
[14] getConstructor(m) ==> Person

Shouldn't the constructor of m be Man?

Solution Proposal



Lets try a new way of defining a subclass. Instead of
function Man(name){ 
this.sex = 'M'
this.name= name # <== new line
}

We try this:
function Woman(name){ update(this, new Person(name, 'F'))}
w= new Woman("Jan")

See the following table for comparison:

ClassesInstanceinstanceof
Person
constructor
function Person(name, sex){
this.name = name
this.sex = sex
this.prn = function(){
return this.name +','+this.sex}
}
ptruePerson
function Man(name){
this.sex = 'M'
this.name= name }
Man.prototype = new Person
mtruePerson
function Woman(name){
update(this, new Person(name,'F'))
}
wfalseWoman

7/20/2007

中國的食品污染

0 comments

今天讀到大紀元的一篇報導:毒牙膏再演鬧劇 質檢總局大變臉
http://epochtimes.com/b5/7/7/20/n1778129.htm

該文提到因中國外銷的含毒牙膏所引發的一連串新聞。文中提到的「二甘醇」是一種抗凝劑,若水中含有二甘醇,則在低溫時會防止水分子結成冰。二甘醇的含量越高,越不易結冰,可能在零下二、三十度時都還保持液體狀態不會變成冰塊。中國製的牙膏,就是利用二甘醇的這種特性,使其即使保存很久也不會硬化。這是對人體有害的有毒物質,因此像牙膏這種不小心會吃進人體的東西不應該含有二甘醇。

其他重點:

  1. 中國生產的幾種牙膏含有0.21%至7.5%的二甘醇。
  2. 中國衛生部不久公佈了該部「專家」的評估結論:「長期使用二甘醇含量低於15.6%的牙膏不會對人體健康產生不良影響」,但報告未顯示專家姓名,也沒說明該試驗的具體方法。
  3. 7月16日,中國質檢總局局長公開批評境外媒體對中國出口產品質量問題的報導是"顛倒黑白",他表示,中國食品合格率要高於美國。
  4. 中國工廠即使自己想要合法生產也很困難,因為他們購買的材料本身就是非法的有毒物(可能買不到無毒的)。譬如說,生產用的水,前幾年由於污染的加劇,中國政府不是採取措施防治並減少污染,反而降低水質標準,把以前的污染水當成合格水賣給企業
  5. 今年七月,據中國質檢總局對食品、化肥和農用機械等眾多消費品質量抽查,結果發現19.1%的產品達不到標準。其中最嚴重的是食品問題,特別是罐裝食品、乾果和果汁飲料。
  6. 中國常用油鹽醬醋米麵的合格率平均低於40%,特別是低價食品,其衛生質量根本無法保障。
  7. 中國進口到美國的食品只有 0.9% 有被抽查。即使在如此低的抽樣率下,中國裝船的食品每個月有 200 次在港口被拒收,排名世界第一。
  8. 中國食品藥品質量監測管理局2005年批准了1113個新藥,這數目等於美國近十年來新藥的「受理」總量(看清楚,不是批准量)。

About Subclassing in Javascript

0 comments

Let the superclass be:

function Person(sex){alert('I am Person')}

and subclasses:

function Man(){this.sex='M'}
function Woman(){this.sex='F'}

The following two subclassing approaches don't seem to make any difference:

Man.prototype = new Person
Woman.prototype = new Person()
m = new Man()
w = new Woman()

In both cases:
  • The function Person will be executed
  • The constructor of both m and w are Person


4/04/2007

IE's TextRange.compareEndPoints()

0 comments

TextRange object

The other day I was coding a web page that needs to make use of some javascript functions of textarea element. I did a little dig-out and ran into this compareEndPoints function. It is a function attached to a TextRange object. The IE-specific TextRange object serves as a mediator for the text input element (<input> with type="text", <textarea>...) to manupilate text-related operations (search, replace, copy, paste, insert ...).

Now assuming we have a <textarea> element object called oTextArea, a TextRange object can be created in one of the following ways:
  1. var oTR1 = oTextArea.createTextRange()
  2. var oTR2 = document.selection.createRange()
These code should appear inside an eventhandler, for example:

  oTextArea.onselect = function(){
...
var oTR1= this.createTextRange()
var oTR2= document.selection.createRange()
...
}

Both oTR1 and oTR2 are a TextRange object that has the following properties:

PropertiesoTR1oTR2
boundingHeight1616
boundingLeft15141
boundingTop124124
boundingWidth25256
offsetLeft15141
offsetTop124124
textThis is the test
<textarea> element
textarea
htmlTextThis is the test
&lt;textarea&gt; element.
textarea

Note that:
  1. What createTextRange returns (=oTR1) covers the entire value range of <textarea> while createRange covers only the range of text that is selected;
  2. All the numerical property values in TextRange object are in pixel. No information of index (the start and end point for the selected text range) is available;

compareEndPoints (type, textRange)

I won't go through all the methods of the TextRange object but this one compareEndPoints(type, textRange). This function checks the relationship between two TextRange objects by comparing the starting and ending indices of textRange.text :

  textRange1.compareEndPoints("StartToStart", textRange2)

The argument type can be one of the fillowing 4 : "StartToStart", "StartToEnd", "EndToStart" and "EndToEnd". When it is "StartToStart", it compares the starting index of textRange1.text with the that of textRange2.text. The return is either -1, 0 or 1.

Now, the reason that I talk about this compareEndPoints specifically. Since it is used upon two TextRange objects, and as we saw earlier that both createRange() and createTextRange() return a TextRange object, instinctly it would work like this:

   var oTR1= oTextArea.createTextRange()
var oTR2= document.selection.createRange()
var x = oTR1.compareEndPoints("StartToStart", oTR2)

However, it won't work. IE rejects this usage by showing "illegal argument" error. It took me a while of searching and code digging to figure out a way to do this:

   var oTR1 = document.body.createTextRange(); // Create TextRange on entire body 
oTR1.moveToElementText(oTextArea) // Use moreToElementText to move
// the TextRange to the textarea

var oTR2= document.selection.createRange();
var x = oTR1.compareEndPoints("StartToStart", oTR2)

Only when the createTextRange( ) is used in this way can the resulting TextRange object be used together in compareEndPoints( ) with that generated by createRange( ).

3/31/2007

My javascript addEvent

1 comments

In the end of 2005 several web programming gurus, Peter-Paul Koch (ppk), Dean Edward and Scott Andrew LePera host a "javascript recoding contest" in which they asked participants to submit their code for adding and removing events in javascript. A template page was designed to test the code. The winner was John Resig, whose original code is here. The final code was slightly modified version:

function addEvent( obj, type, fn )
{
if (obj.addEventListener)
obj.addEventListener( type, fn, false );
else if (obj.attachEvent)
{
obj["e"+type+fn] = fn;
obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
obj.attachEvent( "on"+type, obj[type+fn] );
}
}
function removeEvent( obj, type, fn )
{
if (obj.removeEventListener)
obj.removeEventListener( type, fn, false );
else if (obj.detachEvent)
{
obj.detachEvent( "on"+type, obj[type+fn] );
obj[type+fn] = null;
obj["e"+type+fn] = null;
}
}

I personally don't feel comfortable with these code. First of all, as one of the comments mentioned (#2 Posted by Tino Zijdel on 18 October 2005) that in cases of multiple-eventhandlers in IE, the eventhandler added last will be executed first:

... since this is for IE a wrapper around attachEvent, the execution order of the events is different ('random' according to Microsofts documentation, but LIFO in practice against FIFO using the W3C event model)

A simple test reveals this problem:

function init(){
var btn=document.createElement('input')
btn.value = 'Click me'
btn.type = 'button'
document.body.appendChild( btn )
addEvent( btn, "click", function(){alert("#1")} )
addEvent( btn, "click", function(){alert("#2")} )
}

Run the init() function as the onload eventhandler (<body onload="init()">) and load with browser. Firefox alerts "#1" then "#2". But IE alerts "#2" first then "#1", which is not what it should be.

Another part making me uncomfortable is that it uses the entire function content as the key name of a hash:

   obj["e"+type+fn] = fn;
obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }

Although none obvioiusly problem is mentioned or discussed, it could result in extremely long and complex key name, which, IMHO, is not what a hash is supposed to be.

I therefore came up with my own version:

function addEvent( obj, type, fn ) 
{
obj.eventHooks = obj.eventHooks || {} // set .eventHooks for obj if not exists
var evs = obj.eventHooks[type] || [] // set .eventHooks[type] if not exists
obj.eventHooks[type] = evs.concat( fn.concat? fn:[fn]) // this allows for multiple fns added
obj['on'+type] = function (e) // like addEvent(obj,"click",[f1,f2])
{
for (var i=0;i<this.eventHooks[type].length;i++)
{
this.tmp = this.eventHooks[type][i] // attach to the obj such that the this
this.tmp(e) // inside the function points to the obj correctly
this.tmp = undefined
}
}
obj = null
}
function removeEvent( obj, type, fn )
{
if (obj.eventHooks && obj.eventHooks[type])
{
var evs = obj.eventHooks[type]
for (var i=0; i<evs.length;i++)
{
if (evs[i]==fn)
{
obj.eventHooks[type] = evs.slice(0,i).concat(evs.slice(i+1))
break
}
}
}
obj = null
}

Unlike most addEvent inventions, in which either addEventListener or attachEvent is used, the above code simply stores eventhandlers into a buffer that has the following structure:

  obj.eventHooks = { click    : [f1, f2]
, keyup : []
, mouseover: [f3]
....
}

For each event, say, click, a function is assigned to the .onclick. This function carries out the following steps:
  1. Check if obj.eventHooks exists. If not, create one
  2. Check if obj.eventHooks.click exists. If not, create one
  3. Loop through each functions in obj.eventHooks.click
  4. For each function, attaches it to obj as a temporary obj.tmp, then executes obj.tmp(e). This makes sure that any this keyword inside that function point to the obj correctly.
A test page, using the contest template, is here. I am sure that there will be some downside along with this code, but at least at this moment it seems to solve the problems came with the winning code.