Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Tuesday, April 19, 2011

get window scroll bar width

浏览器因为操作系统或者系统主题不同,导致当前窗口中的scrollbar的宽度不一致,在web应用中影响了页面布局,下述方法可以获取到当前浏览器的滚动条宽度:


function getScrollBarWidth () {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";

var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild (inner);

document.body.appendChild (outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;

document.body.removeChild (outer);

return (w1 - w2);
};


Reference:http://www.alexandre-gomes.com/?p=115
http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html

Friday, January 28, 2011

IE throw null object exception when flash call javascript function

用open flash chart第一次正常载入一个图表到页面之后,当使用jQuery.fn.empty()方法移除此图表时,IE中会抛出一个错误,其他浏览器都是正常的,内容如下:


JScript - script block, line 1 character 124
'null' is null or not an object

通过IE8的debug工具可以看到出错时,javascript正在执行的代码如下:

try { document.getElementById("report-charts").SetReturnValue(__flash__toXML(ofc_resize([66,-96,66,-87])) ); } catch (e) { document.getElementById("report-charts").SetReturnValue("<undefined/>"); }

这个并不是页面中的javascript代码,应该是flash中调用外部javascript方法时,所使用的javascript代码,在IE8中断点调试,可以发现document.getElementById("report-charts")的结果为null,所以抛出了以上错误。
避过此问题的办法是在陊除已经载入的图表时,不调用jQuery.fn.empty()方法,而是直接使用jQuery.fn.html(''),将flash所在父元素的内容置空:

$('#report-charts').parent().html('');
// 如果使用$('#report-charts').parent().empty();在IE中则会报错
// ... 重新生成report-charts对象并载入新的flash图表
swfobject.embedSWF(ofc, "report-charts", "100%", "300", "9.0.0", "expressInstall.swf", {"get-data":"get_chart_0"});

Thursday, January 27, 2011

Open Flash Chart IO ERROR Loading test data Error #2032

在IE6中使用open flash chart2加载图表的json数据时,第一次载入数据,图表渲染正常,第二次就会报一个错误,提示数据加载错误:


Open Flash Chart
IO ERROR
Loading test data
Error #2032

而在其他的浏览器,如IE8/firefox/chrome中都是正常的,在网上搜索了一些回答,其中有人提到说这是因为浏览器的缓存造成的问题,只要在用swfobject加载open-flash-chart.swf时,在url后面加上一个动态参数,让浏览器不要使用本地缓存:

swfobject.embedSWF("open-flash-chart.swf?t=" + (new Date()).getTime(), "charts-div-id", "100%", "300", "9.0.0", "expressInstall.swf", {"get-data":"get_chart_0"});


References: Open Flash Chart IO ERROR Loading test data Error #2032

Sunday, December 19, 2010

javascript中array方法调用返回window对象

array中的很多方法通过call和apply调用时会返回window对象,如下写法在Firefox、Chrome等浏览器中会取到window对象:


window === ([]).sort.call();
window === ([]).reverse.call();
([]).concat.call()[0] === window


可以将这些array的方法重写,避免它在运行时的this指向window,如重写sort方法:

Array.prototype.sort = (function(sort) { return function(callback) {
return (this == window) ? null : (callback ? sort.call(this, function(a,b) {
return callback(a,b)}) : sort.call(this));
}})(Array.prototype.sort);

Sunday, October 24, 2010

Scripting java using rhino and javascript

通过Rhino可以使javascript调用java的标准类库,这使得javascript的编程能力得以强化,在服务器端已经有javascript的MVC框架,一般也是基于Rhino的.
首先在ubuntu上可以通过命令安装rhino:
$> sudo apt-get install rhino

安装完成后,在命令行中输入js或者rhino:

$> js
$> rhino
Rhino 1.7 release 2 2010 09 15
js> new Date()
Sun Oct 24 2010 17:24:27 GMT+0800 (CST)
js> /^\d+$/.test("369");
true

就可以进入javascript的控制台.

另外一种方式就是从网上下载rhino 1.5R4.1版本,在命令行中用java运行,下面的代码在命令行的rhino1.7版本中不能运行,因为无法导入java.awt.*的包:
$> java -jar rhino-1.5R4.1.jar
Rhino 1.5 release 4.1 2003 04 21
js> importPackage(java.awt);
js> frame = new Frame("JavaScript")
js> frame.show()
js> button = new Button("OK")
js> frame.add(button)
js> frame.show()
js> function printDate() { print(new Date()) }
js> o = { actionPerformed: printDate }
js> buttonListener = java.awt.event.ActionListener(o)
js> button.addActionListener(buttonListener)

javascript访问java的包和class

java中所有的代码都是class包装了的,而class又是在package下的,rhino为此封装了一个全局对象Packages,通过Packages可以引入所有的java类,如Package.java.lang, Packages.java.io等:

js> Packages.java.io.File
[JavaClass java.io.File]
js> importPackage(java.io)
js> File
[JavaClass java.io.File]

importPackage(java.io)的效果类似java代码中的import java.io.*;
java中的第三方类库也可以通过importClass和importPackage引入,如:
js> importPackage(Packages.org.mozilla.javascript);
js> Context.currentContext
org.mozilla.javascript.Context@1bc887b
js> importClass(java.awt.List)
js> List
[JavaClass java.awt.List]

在引入了java的类库之后,就可以在javascript中使用这些类库了,如:

js> new java.util.Date()
Sun Oct 24 17:46:50 CST 2010
js> new Date()
Sun Oct 24 2010 17:46:54 GMT+0800 (CST)
js> var f = new java.io.File("/etc/hosts");
js> f.exists();
true
js> f.getName();
hosts
js> java.lang.Math.PI
3.141592653589793
js> java.lang.Math.cos(0)
1
js> for (i in f) { print(i) }
getAbsoluteFile
setReadOnly
listFiles
setReadable
writable
hashCode
wait
setExecutable
usableSpace
file
canonicalPath
getUsableSpace
notifyAll
equals
getParent
mkdirs
parent
class
compareTo
freeSpace
getTotalSpace
createNewFile
toString
toURI
toURL
getCanonicalPath
getCanonicalFile
canonicalFile
renameTo
getParentFile
executable
getFreeSpace
absolute
deleteOnExit
canWrite
name
notify
path
canRead
getPath
delete
length
getClass
readable
totalSpace
absoluteFile
lastModified
absolutePath
isAbsolute
list
mkdir
setWritable
isHidden
readOnly
canExecute
isDirectory
hidden
directory
isFile
getName
getAbsolutePath
exists
parentFile
setLastModified
在上面列出的File的方法中,还包括了其从java.lang.Object中继承的所有方法.对于java的重载方法,javascript调用需要用特别的方式.

用javascript实现java的接口

如要实现Runnable接口,按以下方式操作:
js> var obj = { run: function () { print("\nrunning"); } }
js> obj.run()

running
js> var r = new java.lang.Runnable(obj);
js> r.getClass()
class adapter1
js> var t = new java.lang.Thread(r)
Thread[Thread-1,5,main]
js> t.start();
js>
running

用javascript创建java的数组对象

一般直接用javascript创建数组就可以,转为java对象时,rhino会处理类型转换,也可以用以下方法直接创建java数组:
js> var arr = java.lang.reflect.Array.newInstance(java.lang.String, 5); arr[0] = arr[1] = arr[2] = arr[3] = arr[4] = 'create java array using javascript.'
create java array using javascript.
js> arr
[Ljava.lang.String;@1e97f9f
js> arr[1]
create java array using javascript.
js>

Reference: http://www.mozilla.org/rhino/scriptjava.html

Tuesday, July 06, 2010

mongodb tutorial and references

Introduction


MongoDB is a collection-oriented, schema-free document database.

By collection-oriented, we mean that data is grouped into sets that are called 'collections'. Each collection has a unique name in the database, and can contain an unlimited number of documents. Collections are analogous to tables in a RDBMS, except that they don't have any defined schema.

By schema-free, we mean that the database doesn't need to know anything about the structure of the documents that you store in a collection. In fact, you can store documents with different structure in the same collection if you so choose.

By document, we mean that we store data that is a structured collection of key-value pairs, where keys are strings, and values are any of a rich set of data types, including arrays and documents. We call this data format "BSON" for "Binary Serialized dOcument Notation."

MongoDB is a server process that runs on Linux, Windows and OS X. It can be run both as a 32 or 64-bit application. We recommend running in 64-bit mode, since Mongo is limited to a total data size of about 2GB for all databases in 32-bit mode.

The MongoDB process listens on port 27017 by default (note that this can be set at start time - please see Command Line Parameters for more information).

MongoDB stores its data in files (default location is /data/db/), and uses memory mapped files for data management for efficiency.

Example data of mongodb


$> bin/mongo --shell slides.js


/*
* Slides for presentation on Mastering the MongoDB Shell.
* Copyright 2010 Mike Dirolf (http://dirolf.com)
* This work is licensed under the Creative Commons
* Attribution-Noncommercial-Share Alike 3.0 United States License. To
* view a copy of this license, visit
* http://creativecommons.org/licenses/by-nc-sa/3.0/us/ or send a
* letter to Creative Commons, 171 Second Street, Suite 300, San
* Francisco, California, 94105, USA.
* Originally given at MongoSF on 4/30/2010.
* Modified and given at MongoNYC on 5/21/2010.
* To use: run `mongo --shell slides.js`
*/
db = db.getSisterDB("shell");
db.dropDatabase();
// some sample data
for (var i = 0; i < 1000; i += 1) {
db.data.save({
x: i
});
} // "slides"
db.deck.save({
slide: 0,
welcome: "to MongoNYC!",
hashtag: "#mongonyc",
mirror: "http://confmirror.10gen.com/"
});
db.deck.save({
slide: 1,
title: "Mastering the MongoDB Shell",
who: "Mike Dirolf, 10gen",
handle: "@mdirolf"
});
db.deck.save({
slide: 2,
question: "what is the shell?",
answer: "a better Powerpoint?"
});
db.deck.save({
slide: 3,
question: "what is the shell?",
answer: "a full JavaScript environment"
});
db.deck.save({
slide: 4,
question: "what is the shell?",
answer: "a reference MongoDB client"
});
db.deck.save({
slide: 5,
"use cases": ["administrative scripting", "exploring and debugging", "learning (and teaching!)"]
});
db.deck.save({
slide: 6,
repl: ["arrows for history", "^L"]
});
db.deck.save({
slide: 7,
"getting help": ["help", "db.help", "db.foo.help"]
});
db.deck.save({
slide: 8,
"show": ["dbs", "collections", "users", "profile"]
});
db.deck.save({
slide: 9,
navigating: "databases",
how: "'use' or 'db.getSisterDB'"
});
db.deck.save({
slide: 10,
navigating: "collections",
how: "dots, brackets, or 'db.getCollection'",
note: "careful with names like foo-bar"
});
db.deck.save({
slide: 11,
"basic operations": ["insert", "findOne", "find", "remove"]
});
db.deck.save({
slide: 12,
"fun with cursors": ["auto-iteration", "it"]
});
db.deck.save({
slide: 13,
"error checking": "auto 'db.getLastError'"
});
db.deck.save({
slide: 14,
"commands": ["count", "stats", "repairDatabase"],
"meta": "listCommands"
});
db.deck.save({
slide: 15,
"pro tip!": "viewing JS source"
});
db.deck.save({
slide: 16,
"getting help": "--help"
});
db.deck.save({
slide: 17,
scripting: "run .js files",
tools: ["--eval", "--shell", "runProgram"]
});
db.deck.save({
slide: 18,
warning: "dates in JS suck"
});
db.deck.save({
slide: 19,
warning: "array iteration in JS sucks"
});
db.deck.save({
slide: 20,
warning: "numeric types in JS suck"
});
db.deck.save({
slide: 21,
so: "why JS?"
});
db.deck.save({
slide: 22,
homework: ["convince 2 friends to try MongoDB", "send feedback @mdirolf"]
});
db.deck.save({
slide: 23,
url: "github.com/mdirolf/shell_presentation",
questions: "?"
}); // current slide
var current = 0; // print current slide and advance
var next = function() {
var slide = db.deck.findOne({
slide: current
});
if (slide) {
current++;
delete slide._id;
delete slide.slide;
print(tojson(slide, null, false));
} else {
print("The End!");
}
}; // go to slide and print
var go = function(n) {
current = n;
next();
}; // repeat the previous slide
var again = function() {
current--;
next();
};


Basic Commands of mongodb



http://www.mongodb.org/display/DOCS/List+of+Database+Commands
http://rezmuh.sixceedinc.com/2010/02/basic-commands-to-get-you-started-with-mongodb.html

Privileged Commands

Certain operations are for the database administrator only. These privileged operations may only be performed on the special database named admin.

Start the server like this:
$> bin/mongod --dbpath /path/to/data

Stop it with Ctrl-C or with kill (but don’t use kill -9, which doesn’t give the server a chance to shut down cleanly and flush data to disk).

Viewing stats without the mongo console:
Visit http://localhost:28017 (28017 is the port the server is running on, plus 1000) to get an overview of what’s going on.
You can also query http://localhost:28017/_status to see the same data that db.serverStatus() returns, but in JSON format.

Use client command console:

$> bin/mongo

> use admin;
> db.addUser('dummy, 'dummy') // create new user with password "dummy"
> db.runCommand("shutdown"); // shut down the database

$> bin/mongo -u dummy -p dummy admin

Create a new Database:

> use new_database
> db.addUser('dummy', 'differentpassword')

$ bin/mongo -u dummy -p differentpassword new_database


Deleting a database:

> use [db name]
> db.dropDatabase()

Working with Collections (Tables):
> show collections

Lists all the available databases:
> show dbs

To get a list of data in a specific collection, use:
> db.[collection name].find()

Directory Global functions and properties:

> for(var o in this) {
print(o);
}
__quiet
chatty
friendlyEqual
doassert
assert
argumentsToArray
isString
isNumber
isObject
tojson
tojsonObject
shellPrint
printjson
shellPrintHelper
shellHelper
help
Random
killWithUris
Geo
connect
MR
MapReduceResult
__lastres__
sleep_
sleep
quit_
quit
getMemInfo_
getMemInfo
_srand_
_srand
_rand_
_rand
_isWindows_
_isWindows
_startMongoProgram_
_startMongoProgram
runProgram_
runProgram
runMongoProgram_
runMongoProgram
stopMongod_
stopMongod
stopMongoProgram_
stopMongoProgram
stopMongoProgramByPid_
stopMongoProgramByPid
rawMongoProgramOutput_
rawMongoProgramOutput
clearRawMongoProgramOutput_
clearRawMongoProgramOutput
removeFile_
removeFile
listFiles_
listFiles
resetDbpath_
resetDbpath
copyDbpath_
copyDbpath
_parsePath
_parsePort
createMongoArgs
startMongodTest
startMongod
startMongodNoReset
startMongos
startMongoProgram
startMongoProgramNoConnect
myPort
ShardingTest
printShardingStatus
MongodRunner
ReplPair
ToolTest
ReplTest
allocatePorts
SyncCCTest
db
hex_md5_
hex_md5
version_
version
i
current
next
__iscmd__
___it___
it

Directory properties of db:

> for(var o in db){
print(o);
}
_mongo
_name
shellPrint
getMongo
getSisterDB
getName
stats
getCollection
commandHelp
runCommand
_dbCommand
_adminCommand
addUser
removeUser
__pwHash
auth
createCollection
getProfilingLevel
dropDatabase
shutdownServer
cloneDatabase
cloneCollection
copyDatabase
repairDatabase
help
printCollectionStats
setProfilingLevel
eval
dbEval
groupeval
groupcmd
group
_groupFixParms
resetError
forceError
getLastError
getLastErrorObj
getLastErrorCmd
getPrevError
getCollectionNames
tojson
toString
currentOp
currentOP
killOp
killOP
getReplicationInfo
printReplicationInfo
printSlaveReplicationInfo
serverBuildInfo
serverStatus
version
printShardingStatus

> db.shell.help()
DBCollection help
db.foo.count()
db.foo.dataSize()
db.foo.distinct( key ) - eg. db.foo.distinct( 'x' )
db.foo.drop() drop the collection
db.foo.dropIndex(name)
db.foo.dropIndexes()
db.foo.ensureIndex(keypattern,options) - options should be an object with these possible fields: name, unique, dropDups
db.foo.reIndex()
db.foo.find( [query] , [fields]) - first parameter is an optional query filter. second parameter is optional set of fields to return.
e.g. db.foo.find( { x : 77 } , { name : 1 , x : 1 } )
db.foo.find(...).count()
db.foo.find(...).limit(n)
db.foo.find(...).skip(n)
db.foo.find(...).sort(...)
db.foo.findOne([query])
db.foo.findAndModify( { update : ... , remove : bool [, query: {}, sort: {}, 'new': false] } )
db.foo.getDB() get DB object associated with collection
db.foo.getIndexes()
db.foo.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )
db.foo.mapReduce( mapFunction , reduceFunction , <optional params> )
db.foo.remove(query)
db.foo.renameCollection( newName , <droptarget> ) renames the collection.
db.foo.runCommand( name , <options> ) runs a db command with the given name where the 1st param is the colleciton name
db.foo.save(obj)
db.foo.stats()
db.foo.storageSize() - includes free space allocated to this collection
db.foo.totalIndexSize() - size in bytes of all the indexes
db.foo.totalSize() - storage allocated for all data and indexes
db.foo.update(query, object[, upsert_bool, multi_bool])
db.foo.validate() - SLOW
db.foo.getShardVersion() - only for use with sharding

> db.help()
DB methods:
db.addUser(username, password[, readOnly=false])
db.auth(username, password)
db.cloneDatabase(fromhost)
db.commandHelp(name) returns the help for the command
db.copyDatabase(fromdb, todb, fromhost)
db.createCollection(name, { size : ..., capped : ..., max : ... } )
db.currentOp() displays the current operation in the db
db.dropDatabase()
db.eval(func, args) run code server-side
db.getCollection(cname) same as db['cname'] or db.cname
db.getCollectionNames()
db.getLastError() - just returns the err msg string
db.getLastErrorObj() - return full status object
db.getMongo() get the server connection object
db.getMongo().setSlaveOk() allow this connection to read from the nonmaster member of a replica pair
db.getName()
db.getPrevError()
db.getProfilingLevel()
db.getReplicationInfo()
db.getSisterDB(name) get the db at the same server as this onew
db.killOp(opid) kills the current operation in the db
db.printCollectionStats()
db.printReplicationInfo()
db.printSlaveReplicationInfo()
db.printShardingStatus()
db.removeUser(username)
db.repairDatabase()
db.resetError()
db.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 }
db.serverStatus()
db.setProfilingLevel(level,) 0=off 1=slow 2=all
db.shutdownServer()
db.stats()
db.version() current version of the server

> help()
HELP
show dbs show database names
show collections show collections in current database
show users show users in current database
show profile show most recent system.profile entries with time >= 1ms
use <db name> set curent database to <db name>
db.help() help on DB methods
db.foo.help() help on collection methods
db.foo.find() list objects in collection foo
db.foo.find( { a : 1 } ) list objects in foo where a == 1
it result of the last line evaluated; use to further iterate

If I insert the same Document twice, it does not raise an Error?



Using PyMongo for example, why does inserting the same document (read same _id) more than once not raise an error? When we need to detect if a document already exists in the database, we could try catching DuplicateKeyError on insert. Below we explicitly insert the document with the same _id twice but the exception is never raised. Why?

try:
doc = { _id: '123123' }
db.foo.insert(doc)
db.foo.insert(doc)
except pymongo.errors.DuplicateKeyError, error:
print("Same _id inserted twice:", error)

The answer is that DuplicateKeyError will only be raised if we do the insert in safe mode i.e. db.foo.insert(doc, safe=True). The reason why we do not see an error raised with most drivers but with MongoDB's interactive shell is because the shell does a safe insert by default whereas, with most drivers, it is the developers choice whether or not to use a safe insert.

MongoDB's interactive shell:
> doc = {_id: 123421, name: 'test'};
{ "_id" : 123421, "name" : "test" }
> db.deck.insert(doc)
> db.deck.insert(doc)
E11000 duplicate key error index: shell.deck.$_id_ dup key: { : 123421.0 }

Backup



http://effectif.com/mongodb/mongo-administration

There are basically two approaches to backing up a Mongo database:

1. mongodump and mongorestore are the classic approach. Dumps the contents of the database to files. The backup is stored in the same format as Mongo uses internally, so is very efficient. But it’s not a point-in-time snapshot.
2. To get a point-in-time snapshot, shut the database down, copy the disk files (e.g. with cp) and then start mongod up again.

Alternatively, rather than shutting mongod down before making your point-in-time snapshot, you could just stop it from accepting writes:

> db._adminCommand({fsync: 1, lock: 1})
{
"info" : "now locked against writes, use db.$cmd.sys.unlock.findOne() to unlock",
"ok" : 1
}

To unlock the database again, you need to switch to the admin database and then unlock it:

> use admin
switched to db admin
> db.$cmd.sys.unlock.findOne()
{ "ok" : 1, "info" : "unlock requested" }


If you don’t switch to the admin database first you’ll get an unauthorized error:

> db._adminCommand({fsync: 1, lock: 1})
{
"info" : "now locked against writes, use db.$cmd.sys.unlock.findOne() to unlock",
"ok" : 1
}

> db.$cmd.sys.unlock.findOne()
{ "err" : "unauthorized" }


You can take a point in time snapshot from a slave just as easily as your master database, which avoids downtime. This is one of the reasons that running a slave is so strongly recommended…

What RAID should I use?



http://www.mongodb.org/display/DOCS/Developer+FAQ

We recommend not using RAID-5, but rather, RAID-10 or the like. Both will work of course.

Replication



Do it (did you read the previous section?). Seriously.

Start your master and slave up like this:

$ mongod --master --oplogSize 500
$ mongod --slave --source localhost:27017 --port 3000 --dbpath /data/slave

When seeding a new slave server from master use the --fastsync option.

You can see what’s going on with these two commands:

> db.printReplicationInfo() # tells you how long your oplog will last
> db.printSlaveReplicationInfo() # tells you how far behind the slave is

If the slave isn’t keeping up, how do you find out what’s going on? Check the mongo log for any recent errors. Try connecting with the mongo console. Try running queries from the console to see if everything is working. Run the status commands above to try and find out which database is taking up resources. If you can’t work it out hop on the IRC channel; Mathias says they’ll be very responsive.

What is the difference between MongoDB and RDBMSs



http://sunoano.name/ws/mongodb.html#faqs

MySQL, PostgreSQL, ...
----------------------
Server:Port
- Database
- Table
- Row

MongoDB
--------
Server:Port
- Database
- Collection
- Document

The concept of server and database are very similar. But the concept of table and collection are quite different. In RDBMSs a table is a rectangle. It is all columns and rows. Each row has a fixed number of columns, if we add a new column, we add that column to each and every row.

In MongoDB a collection is more like a really big box and each document is like a little bag of stuff in that box. Each bag contains whatever it needs in a totally flexible manner (read schema-less). However, schema-less does not equal type-less i.e. it is just that any document has its own schema, which it may or may not share with any other document. In practice it is normal to have the same schema for all the documents in collection.

Clone Database



http://www.mongodb.org/display/DOCS/Clone+Database

MongoDB includes commands for copying a database from one server to another.

// copy an entire database from one name on one server to another
// name on another server. omit <from_hostname> to copy from one
// name to another on the same server.
db.copyDatabase(<from_dbname>, <to_dbname>, <from_hostname>);
// if you must authenticate with the source database
db.copyDatabase(<from_dbname>, <to_dbname>, <from_hostname>, <username>, <password>);
// in "command" syntax (runnable from any driver):
db.runCommand( { copydb : 1, fromdb : ..., todb : ..., fromhost : ... } );
// command syntax for authenticating with the source:
n = db.runCommand( { copydbgetnonce : 1, fromhost: ... } );
db.runCommand( { copydb : 1, fromhost: ..., fromdb: ..., todb: ..., username: ..., nonce: n.nonce, key: <hash of username, nonce, password > } );

// clone the current database (implied by 'db') from another host
var fromhost = ...;
print("about to get a copy of database " + db + " from " + fromhost);
db.cloneDatabase(fromhost);
// in "command" syntax (runnable from any driver):
db.runCommand( { clone : fromhost } );

What might be a use case for --fork?



The --fork switch forks a mongod process of another exiting process. One use case where this is pretty handy for example is if we SSH into a remote machine and start a MongoDB and leave right away after a new mongod got started.

The fastest way to do so would simply be to append /path/to/mongod --fork to the SSH command line since this will skip creating an intermediate shell and bring up a remote mongod right away.

Are there any Reasons not to use MongoDB?



http://sunoano.name/ws/mongodb.html#faqs

1. We need transactions (read ACID).
2. Our data is very relational.
3. Related to 2, we want to be able to do joins on the server (but can not do embedded objects / arrays).
4. We need triggers on our tables. There might be triggers available soon however.
5. Related to 4, we rely on triggers (or similar functionality) to do cascading updates. or deletes. As for #4, this issue probably goes away once triggers are available.
6. We need the database to enforce referential integrity (MongoDB has no notion of this at all).
7. If we need 100% per node durability.

Use Cases



http://www.mongodb.org/display/DOCS/Comparing+Mongo+DB+and+Couch+DB

It may be helpful to look at some particular problems and consider how we could solve them.

* if we were building Lotus Notes, we would use Couch as its programmer versioning reconciliation/MVCC model fits perfectly. Any problem where data is offline for hours then back online would fit this. In general, if we need several eventually consistent master-master replica databases, geographically distributed, often offline, we would use Couch.
* if we had very high performance requirements we would use Mongo. For example, web site user profile object storage and caching of data from other sources.
* if we were building a system with very critical transactions, such as bond trading, we would not use MongoDB for those transactions -- although we might in hybrid for other data elements of the system. For something like this we would likely choose a traditional RDBMS.
* for a problem with very high update rates, we would use Mongo as it is good at that. For example, updating real time analytics counters for a web sites (pages views, visits, etc.)

Generally, we find MongoDB to be a very good fit for building web infrastructure.

ruby driver of mongodb tutorial



http://api.mongodb.org/ruby/1.0.3/index.html
http://www.mongodb.org/display/DOCS/Ruby+Tutorial
http://github.com/mongodb/mongo-ruby-driver

$> gem update --system
$> gem install mongo
$> gem install bson
$> gem install bson_ext

Making a Connection:
# db = Mongo::Connection.new.db("shell")
# db = Mongo::Connection.new("localhost").db("shell")
db = Mongo::Connection.new("localhost", 27017).db("shell")


Listing All Databases:
m = Mongo::Connection.new # (optional host/port args)
m.database_names.each { |name| puts name }
m.database_info.each { |info| puts info.inspect}


Dropping a Database:
m.drop_database('database_name')


Authentication (Optional):
auth = db.authenticate(my_user_name, my_password)


Getting a Collection:
deck = db.collection("deck")


Inserting a Document:
deck = db['deck']

doc = {"name" => "MongoDB", "type" => "database", "count" => 1,
"info" => {"x" => 203, "y" => '102'}}
deck.insert(doc)
100.times { |i| deck.insert("i" => i) }


Finding the First Document In a Collection using find_one():
my_doc = deck.find_one()
puts my_doc.inspect


Note the _id element has been added automatically by MongoDB to your document. Remember, MongoDB reserves element names that start with _ for internal use.

Counting Documents in a Collection:
puts deck.count()


Using a Cursor to get all of the Documents:
deck.find.each { |row| puts row.inspect }


Getting a Single Document with a Query:
deck.find("i" => 71).each { |row| puts row.inspect }


Getting a Set of Documents With a Query:
deck.find("i" => {"$gt" => 50}).each { |row| puts row }


Querying with Regular Expressions:
deck.find("question" => /w/i).each { |row| puts row }


Creating An Index:
To create an index, you specify an index name and an array of field names to be indexed, or a single field name.
deck.create_index("i")
# deck.create_index([["i", Mongo::ASCENDING]])


Getting a List of Indexes on a Collection:
deck.index_information


Ruby driver example


require 'rubygems' not necessary for Ruby 1.9
require 'mongo'
# 需要先导入slides.js之后,再进行下面的ruby代码测试
db = Mongo::Connection.new.db("mydb")
db = Mongo::Connection.new("localhost").db("mydb")
m = Mongo::Connection.new("localhost", 27017)
db = m.db("shell")
puts db.inspect
m.database_names.each { |name| puts name }
m.database_info.each { |info| puts info.inspect}
db.collection_names.each { |name| puts name }
deck = db['deck']
doc = {"name" => "MongoDB", "type" => "database", "count" => 1,
"info" => {"x" => 203, "y" => '102'}}
deck.insert(doc)
100.times { |i| deck.insert("i" => i) }
my_doc = deck.find_one()
puts my_doc.inspect
puts deck.count()
deck.find.each { |row| puts row.inspect }
deck.find("i" => 71).each { |row| puts row.inspect }
deck.find("i" => {"$gt" => 90}).each { |row| puts row }
deck.find("i" => {"$gt" => 20, "$lte" => 30}).each { |row| puts row }
deck.find("question" => /w/i).each { |row| puts row }
deck.create_index([["i", Mongo::ASCENDING]])
p deck.index_information
db.validate_collection('deck')


References: http://www.mongodb.org/display/DOCS/Developer+Zone

Friday, June 25, 2010

script标签中的defer属性说明

script中的defer属性默认情况下是false的,其主要作用是为了提升页面性能,实际在目前的HTML 4.0中这个属性是个鸡肋,在各浏览器中表现也不一样,最好忽略此属性。

微软MSDN中的文档说明摘录部分内容如下:
Remarks: Using the attribute at design time can improve the download performance of a page because the browser does not need to parse and execute the script and can continue downloading and parsing the page instead.
Standards Information: This property is defined in HTML 4.0 World Wide Web link and is defined in World Wide Web Consortium (W3C) Document Object Model (DOM) Level 1 World Wide Web link.

W3C中的说明摘录部分内容如下:
defer [CI]
When set, this boolean attribute provides a hint to the user agent that the script is not going to generate any document content (e.g., no "document.write" in javascript) and thus, the user agent can continue parsing and rendering.
指示脚本不会生成任何的文档内容(不要在其中使用document.write命令,不要在defer型脚本程序段中包括任何立即执行脚本要使用的全局变量或者函数),浏览器可以继续解析并绘制页面。但是defer的script在什么时候执行,执行顺序情况并无明确规定。

正在制定的HTML5有极大可能会完善script标签的定义,这里有简单的HTML5中defer属性的定义和用法

async和defer二个属性属性与src属性一起使用,async定义脚本是否异步执行。
如果 async 属性为 true,则脚本会相对于文档的其余部分异步执行,这样脚本会可以在页面继续解析的过程中来执行。
如果 async 属性为 false,而 defer 属性为 true,则脚本会在页面完成解析时得到执行。
如果 async 和 defer 属性均为 false,那么脚本会立即执行,页面会在脚本执行完毕继续解析。

The async and defer attributes are boolean attributes that indicate how the script should be executed.

There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page. The exact processing details for these attributes are described below.

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behavior instead of the synchronous blocking behavior that is the default.

If one or both of the defer and async attributes are specified, the src attribute must also be specified.

Sunday, June 20, 2010

relationship of constructor and prototype in javascript


var animal = function(status) {
this.status = status;
this.breathes = "yes";
this.action = function() {
console.log('flying...')
};
},
human = function() {
this.name = 'human';
},
cat = function() {
this.type = 'cat';
};

// javascript支持原型继承,这种方式比类继承更强大,类继承中一个对象可以继承结构和行为,而原型继承可以继承结构和行为之外,并可以继承一个对象的状态
// new一个animal的实例对象作为cat.prototype的原型,这个animal实例对象就成为cat的实例对象原型链上的一员
// __proto__这个魔法属性在这些浏览器不能工作: ie 6/7/8, safari < 5, opera < 10.50
//当在cat的某个实例上检索一个属性时,如果在其本身中没有找到,则会延着原型链向上检索,如下例子中的c.__proto__即为一个animal对象
//如果检索c.breathes,如果在c对象本身没有找到此属性,则会检索t.__proto__.breathes、t.__proto__.__proto__.breathes等原型链上的对象,直到找到为止,没找到返回undefined
cat.prototype = new animal("live");
//cat继承的原型对象是具有特定状态的animal对象
var c = new cat();
console.log(cat.prototype);
console.log(cat.prototype.constructor.tostring());
console.log(c.constructor.tostring());
console.log("cat breathes:" + c.breathes);
console.log("c.__proto__:", c.__proto__);
//ie不支持此属性
//你可以利用object.__proto__这个魔法属性修改当前对象的原型,下面将一只猫猫化为人形
var d = new cat();
d.__proto__ = new human();
console.log("d.__proto__:", d.__proto__);
//从上面结果可以看到cat的实例c.constructor不是指向cat这个构造函数,而是animal构造函数
//需要修改对象的constructor为其构造函数本身
//当一个函数对象被创建时,function构造器产生的函数对象会运行类似这样的一些代码:this.prototype = {constructor: this},参考javascript: the good parts 5.1节说明
//新函数对象被赋予一个prototype属性,其值是包含一个constuctor属性,并且其属性值为此新函数对象本身
//但是通过原型方式继承时,会给prototype重新赋予一个新对象,此prototype对象中的constructor是指向其自身的构造函数,而不是新函数的,所以需要重置其fn.prototype.constructor = this
//参考javascript权威指南第五版example 9-3. subclassing a javascript class
cat.prototype.constructor = cat;
console.log(cat.prototype.constructor.tostring());
console.log(c.constructor.tostring());
console.log(c.__proto__);
var tostring = object.prototype.tostring;
language = function() {
this.type = "programming";
return {
"locale": "en",
"class-free": function() {
return false
},
"tostring": function() {
return tostring.apply(this, arguments)
}
// 如果tostring方法被重写成非function对象,则后面console中无法输出对象j
}
},
javascript = function() {
this.value = "javascript";
this["class-free"] = function() {
return true
};
};
language.prototype = {
a: 1,
b: 2
};
javascript.prototype = new language();
var j = new javascript();
console.log(j);
console.log(j.__proto__);
//locale: en,此处因为language构造函数返回不是this,而是另一个object直接量,而object直接的构造方法为object(),因此language的原型被丢失了
console.log(language.prototype);
console.log(javascript.prototype);
console.log(j.constructor.tostring());
//function object() { [native code] }


构造函数与其返回值


构造函数会返回一个对象,如果没有直接return语句,构造函数会自动返回当前对象:"return this;",也可以返回一个对象直接量,而不返回this,这样会中断正常的原型链。

prototype.js中class对象定义是封装在一个匿名函数里的,从而使得其内部变量和方法与外界隔离,其中有二句代码为:

function subclass() {};
subclass.prototype = parent.prototype;

因为parent的构造可能返回语句不是返回this对象,而是返回了一个其他的对象,如{tostring:true},如果不用subclass.prototype=parent.prototype这样写,可能这样会丢失原型链上的方法和属性,通过subclass这个空构造将parent.prototype引用到自身的prototype上,从而保持住部分原型链。
这其实也已经不是原型继承了,因为它不是通过new parent()来获取原型对象,丢失了new parent所得对象中的属性和方法。
prototype中的class其实放弃了原型对象,只是简单的继承了parent.prototype对象,已经失去原型继承可以继承对象状态的功能,这样操作其实是很好的模似了类继承方式。

var class = (function() {
function subclass() {};
function create() {
var parent = null,
properties = $a(arguments);
if (object.isfunction(properties[0])) parent = properties.shift();

function klass() {
this.initialize.apply(this, arguments);
}

object.extend(klass, class.methods);
klass.superclass = parent;
klass.subclasses = [];

if (parent) {
// 因为parent的构造可能返回对象直接量,而不是返回this,如{tostring:true}
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}

for (var i = 0; i < properties.length; i++) klass.addmethods(properties[i]);
if (!klass.prototype.initialize) klass.prototype.initialize = prototype.emptyfunction;
klass.prototype.constructor = klass;
return klass;
}
function addmethods(source) {
var ancestor = this.superclass && this.superclass.prototype;
var properties = object.keys(source);
if (!object.keys({
tostring: true
}).length) {
if (source.tostring != object.prototype.tostring) properties.push("tostring");
if (source.valueof != object.prototype.valueof) properties.push("valueof");
}
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i],
value = source[property];
if (ancestor && object.isfunction(value) && value.argumentnames().first() == "$super") {
var method = value;
value = (function(m) {
return function() {
return ancestor[m].apply(this, arguments);
};
})(property).wrap(method);
value.valueof = method.valueof.bind(method);
value.tostring = method.tostring.bind(method);
}
this.prototype[property] = value;
}
return this;
}
return {
create: create,
methods: {
addmethods: addmethods
}
};
})();

Tuesday, June 08, 2010

javascript: closures, lexical scope and scope chain

闭包的定义(javascript权威指南)如下:
JavaScript functions are a combination of code to be executed and the scope in which to execute them. This combination of code and scope is known as a closure in the computer science literature. All JavaScript functions are closures.
javascript的function定义了将要被执行的代码,并且指出在哪个作用域中执行这个方法,这种代码和作用域的组合体就是一个闭包,在代码中的变量是自由的未绑定的。闭包就像一个独立的生命体,有其自身要运行的代码,同时其自身携带了运行时所需要的环境。
javascript所有的function都是闭包。

闭包中包含了其代码运行的作用域,那这个作用域又是什么样子的呢,这就引入了词法作用域(lexical scope)的概念:
词法作用域是指方法运行的作用域是在方法定义时决定的,而不是方法运行时决定的。
所以在javascript中,function运行的作用域其实是一个static scope。但也有二个例外,就是with和eval,在这2者中的代码处于dynamic scope中,这给javascript带来额外的复杂度和计算量,因而也效率低下,避免使用。

当闭包在其词法作用域中运行过程中,如何检索其中的变量名?这就再引入了一个概念,作用域链(scope chain):
当一个方法function定义完成,其作用域链就是固定的了,并被保存成为方法内部状态的一部分,只是这个作用域链中调用对象的属性值不是固定的。作用域链是"活"的。
当一个方法在被调用时,会生成一个调用对象(call object or activation object),并将此call object加到其定义时确认下来的作用域链的顶端。
在这个call object上,方法的参数和方法内定义的局部变量名和值都会存在这个call object中,如果调用结束,这个call object会从作用域链的顶端移除,再没有被其他对象引用,内存也会被自动回收。
在此call object中使用的变量名会先从此方法局部变量和传入参数中检索,如果没有找到,就会向作用域链上的前一个对象查询,如此向上追溯,一直检索到global object(即window对象上),如果在整个作用域链上没有找到此变量名,则会返回undefined(没有指定对象直接查询变量名,没找到则抛出异常变量未定义)。
如此通过作用域链,javascrip就实现了call object中变量名检索。

在全局对象中一个方法调用完成之后,生成的call object会被回收,这看不出闭包(即当前被调用的方法)有什么功用。但是当一个外部方法的内部返回一个嵌套方法,并且返回的嵌套方法被全局对象引用时,或者是外部方法内将嵌套方法赋给全局对象的属性(jQuery构造方法就是在匿名方法内设置在window.jQuery上),外部方法调用生成的call object就会引用这个嵌套方法,而同时嵌套方法被全局对象引用,所以这个外部方法调用产生的call object及其属性就会继续生存在内存中,这时闭包(外部方法)的功用才被显示出来,下面以jQuery.fn.animation()方法调用过程为例进行说明:

1、当载入整个jquery.js文件时,会运行最外面的匿名方法(通过这个匿名方法形成一个命名空间,所有的变量名都是匿名方法内部定义的局部变量名):


(function( window, undefined ) {
// ......jQuery source code;
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
})(window);
2、因为匿名方法内部有一个内部方法jQuery被全局对象window的属性jQuery和$引用,这里变量名很搞,一个是匿名方法内嵌套的构造方法jQuery,另一个window对象的属性名jQuery。因为这个匿名方法内部的jQuery构造方法被全局对象window.jQuery引用,所以外围的匿名方法在运行时产生的call object会继续生存在内存中。此时,这个call object可以利用Firebug或者Chrome的debug工具可以看到,在Firebug中的scopeChain中称之为"Object",在Chrome的console中称之为"Closure",该对象中记录了当前这个最外围的匿名方法被调用后生成的call object上变量的值,这些变量是未绑定的,是自由的,其值可以被修改并保存在作用域链上。运行此匿名方法时,会将其call object置于global object之上,形成作用域链。
这里注意一点,这匿名方法是一个闭包,但运行方法生成的call object对象只是作用域链顶端的一个对象,记录了方法中的变量名和值。闭包不但包括这个运行的作用域,还包括其运行所需的代码。
3、页面不关闭,这个匿名方法调用生成的call object就会一直驻在内存中,接下来当页面发生了一个jQuery.fn.animate()方法的调用,这个时候javascript又会为.animate()方法生成一个call object,这个对象拥有传进来的参数名和值,以及在.animate()方法内部定义的一个局部变量opt和它的值。
同时,javascript会将生成的这个call object置于其作用域链(scope chain)的最前端,即此时的作用域链为:global object->anonymous function call object->animate call object。
4、接下来会调用jQuery.fn.queue()->jQuery.fn.each()->jQuery.fn.dequeue(),在这些方法调用过程也都会接触到第2步中所提到的那个匿名方法调用后生成的闭包,这中间过程略过,当运行到最后传参给.queue(function)的function时,因为这个匿名方法是定义在jQuery.fn.animate()方法内部的,所以其作用域链(scope chain)也就已经确定了,即global object->anonymous function call object->animate call object,当此匿名方法调用生成一个call object,会将此call object再置于animate call object之上。
5、对于最后的匿名function运行完成之后,如果这个匿名function对象还被其他element的queue数组引用,则第3步中运行.animate()方法生成的闭包将继续生存在内存之中,直到所有的效果方法运行完成,此匿名function没有其他引用时,.animate()调用生成的call object就会被回收。

Reference: JavaScript函数调用时的作用域链和调用对象是如何形成的及与闭包的关系

Monday, May 24, 2010

javascript中keyEvent按键事件说明(录自javascript权威指南第5版)

有3种按键类型,分别是keydown、keypress和keyup,它们分别对应onkeydown、onkeypress和onkeyup这几个事件处理器。
一个按键操作会产生这3个事件,依次是keydown、keypress,然后在按键释放的时候keyup。
这3个事件类型中,keypress事件是最为用户友好的:和它们相关的事件对象包含了所产生的实际字符的编码。keydown和keyup事件是较底层的,它们的按键事件包含一个和键盘所生成的硬件编码相关的“虚拟按键码”。对于ASCII字符集中的数字和字符,这些虚拟按键码和ASCII码相同。如果按下SHIFT键并按下数字2,keydown事件将通知发生了“SHITF-2”的按键事件。keypress事件会解释这一事件,说明这次按键产生了一个可打印的字符“@”。
对于不能打印的功能按键,如Backspace、Enter、Escape和箭头方向键、Page Up、Page Down以及F1到F12,它们会产生keydown和keyup事件。

在不同的浏览器中,按键事件的一些细节区别如下:


1、对于不能打印的功能按键,在Firefox中,也会产生keypress事件,在IE和Chrome中,则不会触发keypress事件,只有当按键有一个ASCII码的时候,即此字符为可打印字符或者一个控制字符的时候,keypress事件才会发生。对于这些不能打印的功能按键,可通过和keydown事件相关的keyCode来获取。
2、作为一条通用的规则,keydown事件对于功能按键来说是最有用的,而keypress事件对于可打印的按键来说是最有用的。
3、在IE中,Alt按键组合被认为是无法打印的,所以并不会触发keypress事件。
4、在Firefox中,按键事件定义有二个属性,keyCode存储了一个按键的较低层次的虚拟按键码,并且和keydown事件一起发送。charCode存储了按下一个键时所产生的可打印的字符的编码,并且和keypress事件一起发送。在Firefox中,功能按键会产生一个keypress事件,在这种情况下,charCode是0,而keyCode包含了虚拟按键码。在Firefox中,发生keydown事件时,charCode都为0,所以在keydown时获取charCode是无意义的。
5、在IE中,只有一个keyCode属性,并且它的解释也取决于事件的类型。对于keydown事件来说,keyCode是一个虚拟按键码,对于keypress事件来说,keyCode是一个字符码。
6、在Chrome中,功能键与IE中表现一样,不会触发keypress事件,对于keydown事件,也会在事件的keyCode中存储虚拟按键码,而charCode为0,与IE和Firefox表现一样,然而在发生可打印字符的keypress事件时,除了与Firefox一样,会在事件的charCode中存储实际按键编码之外,也会在keyCode中存储实际按键码,这二个值相同。
7、charCode字符码可以使用静态方数String.fromCharCode()转为字符。

Friday, March 26, 2010

notice "var" keywords of javascript in IE8

当前测试只是针对IE8,没有测试之前IE版本,以下代码在firefox/chrome中会按预期一样正常运行,代码测试注意打开firebug或者是console查看输出:


<script type="text/javascript">
// window.a 设置一个属性a到window上
window.a = 1;
// 正常打印出a:1
window.console.log(a);
</script>



<script type="text/javascript">
// 必须在此分二块script来写,如果写在一块script标签内,都会正常执行
// 在同一个script代码块内,javascript会解析当前代码块中所有的变量(之前没有出现过的变量名),并且都为 undefined
// 在这里还没有执行到var a=2,a为 undefined
// 针对IE8: window.a 也被置为 undefined
// 其他浏览器: window.a前面代码中已经定义,所以这里还是原来的值:1,而非像IE8中一样为 undefined
window.console.log(a);
var a = 2; // 注意前面有个变量声明: var
window.console.log(a);
</script>



<script type="text/javascript">
window.console.log(a);
// 这里因为没有用var新定义变量,所以a即为window.a,只是对变量重新赋值,代码执行没有问题
a = 3; // 注意前面没有变量声明: var
window.console.log(a);
</script>

以上代码在firefox/chrome中执行结果为: 1 1 2 2 3
以上代码在IE8中执行结果为: 1 undefined 2 2 3

Thursday, August 20, 2009

Element Data in jQuery

Added in jQuery 1.2
Attaching data to elements can be hazardous.
Store data: jQuery.data(elem, "name", "value");
Read data: jQuery.data(elem, "name");
All data is stored in a central cache and completely garbage collected,
as necessary.

Added in jQuery 1.2.3
Can handle namespacing:


$("div").data("test", "original");
$("div").data("test.plugin", "new data");
$("div").data("test") == "original"; // true
$("div").data("test.plugin") == "new data"; // true

Advanced data handling can be overridden by plugins:

$(element).bind("setData.draggable", function(event, key, value) {
self.options[key] = value;
}).bind("getData.draggable", function(event, key) {
return self.options[key];
});

Sunday, July 12, 2009

iframe src problem in firefox

<iframe src='javascript:'></iframe>
在firefox下,当运行到上面语句的时候,将会弹出错误控制台。

Thursday, May 14, 2009

RegExp escape function

RegExp.escape = (function() {
var punctuationChars = /([.*+?|/(){}[\]\\])/g;
return function(text) {
return text.replace(punctuationChars, '\\$1');
}
})();

var str = RegExp.escape('a+b/c*d$ ^{.}');
var reg = new RegExp(str);


Reference: http://simonwillison.net/2006/Jan/20/escape

Tuesday, May 12, 2009

Non-blocking JavaScript

Include via DOM

var js = document.createElement('script'); 
js.src = 'myscript.js'; 
var h = document.getElementsByTagName('head')[0]; 
h.appendChild(js);

Non-blocking JavaScript
  And what about my inline scripts?
  Setup a collection (registry) of inline scripts

Step 1
Inline in the <head>:
var myapp = { 
   stuff: [] 
}; 

Step 2
  Add to the registry
Instead of:
  alert('boo!');
Do:
  myapp.stuff.push(function(){ 
    alert('boo!'); 
  );

Step 3
  Execute all

var l = myapp.stuff.length;  
var l = myapp.stuff.length;  
for(var i = 0, i < l; i++) { 
myapp.stuff[i](); 

Sunday, April 19, 2009

0.1+0.2!==0.3 in javascript

>>> 0.1 + 0.2 !== 0.3
true
>>> 0.1 + 0.2
0.30000000000000004

javascript compare operations

'' == '0'; // false
0 == ''; // true
0 == '0'; // true
false == 'false'; // false
false == '0'; // true
false == undefined; // false
false == null; // false
null == undefined; // true
' \t\r\n ' == 0; // true

Tuesday, April 14, 2009

document onmousemove event differences in different browsers

当前文档document中如果有一个iframe时,当mouse滚过当前文档进入到iframe区域中时,不同的浏览器的表现形式有所不同,safari4/opera9.6中仍然能触发mouseover事件,但是在firefox3/ie中则不触发此mouseover事件,因为mouse已经离开了当前文档。

Tuesday, February 03, 2009

Javascript expression '\s'=='s' is true in ie6

在ie6中
var exp = '\s'=='s';
的结果返回为true.

Tuesday, January 06, 2009

Difference of String.match and Regexp.exec

The match( ) method is the most general of the String regular-expression methods. It takes a regular expression as its only argument (or converts its argument to a regular expression by passing it to the RegExp( ) constructor) and returns an array that contains the results of the match. If the regular expression has the g flag set, the method returns an array of all matches that appear in the string. For example:

"1 plus 2 equals 3".match(/\d+/g) // returns ["1", "2", "3"]

If the regular expression does not have the g flag set, match( ) does not do a global search; it simply searches for the first match. However, match( ) returns an array even when it does not perform a global search. In this case, the first element of the array is the matching string, and any remaining elements are the parenthesized subexpressions of the regular expression. Thus, if match( ) returns an array a, a[0] contains the complete match, a[1] contains the substring that matched the first parenthesized expression, and so on. To draw a parallel with the replace( ) method, a[n] holds the contents of $n.
For example, consider parsing a URL with the following code:
var url = /(\w+):\/\/([\w.]+)\/(\S*)/;
var text = "Visit my blog at http://www.example.com/~david";
var result = text.match(url);
if (result != null) {
var fullurl = result[0]; // Contains "http://www.example.com/~david"
var protocol = result[1]; // Contains "http"
var host = result[2]; // Contains "www.example.com"
var path = result[3]; // Contains "~david"
}
Finally, you should know about one more feature of the match( ) method. The array it returns has a length property, as all arrays do. When match( ) is invoked on a nonglobal regular expression, however, the returned array also has two other properties: the index property, which contains the character position within the string at which the match begins, and the input property, which is a copy of the target string. So in the previous code, the value of the result.index property would be 17 because the matched URL begins at character position 17 in the text. The result.input property holds the same string as the text variable. For a regular expression r and string s that does not have the g flag set, calling s.match(r) returns the same value as r.exec(s). The RegExp.exec( ) method is discussed a little later in this chapter.
var pattern = /\bJava\w*\b/g;
var text = "JavaScript is more fun than Java or JavaBeans!";
var result;
while((result = pattern.exec(text)) != null) {
alert("Matched '" + result[0] +
"' at position " + result.index +
" next search begins at position " + pattern.lastIndex);
}
When exec( ) is invoked on a nonglobal pattern, it performs the search and returns the result described earlier. When regexp is a global regular expression, however, exec( ) behaves in a slightly more complex way. It begins searching string at the character position specified by the lastIndex property of regexp. When it finds a match, it sets lastIndex to the position of the first character after the match. This means that you can invoke exec( ) repeatedly in order to loop through all matches in a string. When exec( ) cannot find any more matches, it returns null and resets lastIndex to zero. If you begin searching a new string immediately after successfully finding a match in another string, you must be careful to manually reset lastIndex to zero.
Note that exec( ) always includes full details of every match in the array it returns, whether or not regexp is a global pattern. This is where exec( ) differs from String.match( ), which returns much less information when used with global patterns. Calling the exec( ) method repeatedly in a loop is the only way to obtain complete pattern-matching information for a global pattern.

This article copy from OReilly's《JavaScript The Definitive Guide》5th Edition.