Friday, August 31, 2007

CentOS 默认语言设置

如果安装了中文为默认语言时,centos语言编码是“zh_CN.UTF-8”,在本机上的SHELL是能看到正常的中文的,但是通过SSH连上来就会发现所有的汉字变成乱码了。
编辑/etc/sysconfig/i18n,修改“LANG="zh_CN.UTF-8"”为“LANG="zh_CN.GB18030"”,重新登录即可。

Thursday, August 30, 2007

get iframe body contents

document.getElementById('iframe_id').contentWindow.document.body.innerHTML
这样就取到了了Iframe中的HTML正文内容了,在FF/IE中测试通过。

Sunday, August 26, 2007

Rails Routes 详解

$>cd RubyOnRails/app/path
$>cd script/console
>>rs = ActionController::Routing::Routes
>>puts rs.routes
ANY /:controller/service.wsdl/ {:action=>"wsdl"}
ANY /:controller/:action/:id.:format/ {}
ANY /:controller/:action/:id/ {}
=>nil

修改config/routes.rb文件,添加一行
map.connect 'modules/controller/:action/*other', :controller => 'modules/controller'
回到console
>>rs.reload
>>puts rs.routes
ANY /:controller/service.wsdl/ {:action=>"wsdl"}
ANY /:controller/:action/:id.:format/ {}
ANY /:controller/:action/:id/ {}
ANY /modules/controller/:action/:other/ {:controller=>"modules/controller"}
=>nil
>>rs.recognize_path '/modules/controller/test/2?x=1'
=>{:action=>"test", :other=>["2?x=1"], :controller=>"modules/controller"}
>>rs.recognize_path '/test/action/1'
=>{:action=>"action", :id=>"1", :controller=>"test"}
>> rs.add_route('/x/y/z', {:controller => 'test', :action => 'index', :id => 0})=> #>>puts rs.routes
ANY /:controller/service.wsdl/ {:action=>"wsdl"}
ANY /:controller/:action/:id.:format/ {}
ANY /:controller/:action/:id/ {}
ANY /modules/controller/:action/:other/ {:controller=>"modules/controller"}
ANY /x/y/z/ {:action=>"index", :id=>0, :controller=>"test"}
=> nil
>> rs.draw do |map|
?> map.connect '/blog/:id', :controller => 'blog', :action => 'list'
>> end
=> [ActionController::Base, ActionView::Base]
>> puts rs.routes
ANY /blog/:id/ {:action=>"list", :controller=>"blog"}
=> nil
>> rs.recognize_path '/blog/1'
=> {:action=>"list", :id=>"1", :controller=>"blog"}
这里发现原来的routes全部不见了,只有这个新建的routes了,因为draw方法内部实现为:


def draw
clear!
yield Mapper.new(self)
named_routes.install
end

draw方法块里的map对象里method_missing方法就是用来实现具名路由named routes的。先看下源码如下:

def method_missing(route_name, *args, &proc)
super unless args.length >= 1 && proc.nil?
@set.add_named_route(route_name, *args)
end

上面对实例变量@set就是前面的rs对象,那么就看一下rs.add_named_route方法吧
>>rs.clear!
>>rs.add_named_route('index', 'user/index', :controller => 'user', :action => 'index')
puts rs.named_routes
#
=> nil
>> puts rs.routes
ANY /user/index/ {:action=>"index", :controller=>"user"}
=> nil
>> puts rs.named_routes.routes
indexANY /user/index/ {:action=>"index", :controller=>"user"}
=> nil
定义了具名路后就可以在controller/view中像url_for一样调用,只要在route name后面加上_url就可以,url_for在console里不能调试,可以用rs.generate(request)方法测试。
# In addition to providing url_for, named routes are also accessible after including UrlWriter.
url_for(:controller => 'signup', action => 'index', :token => token)
index_url(:id => 1)
#=> http://localhost/user/index?id=1
>> rs.generate(:controller => 'test', :action => 'index', :id => 3)
=> "/test/index/3"
另外在map这个对象里有个方法root可以给根目录定义路径,用法如下:

>> rs.draw do |map|
?> map.root :controller => 'test', :action => 'list'
>> end
ArgumentError: Illegal route: the :controller must be specified!
from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:965:in `build'
from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1172:in `add_route'
from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1178:in `add_named_route'
from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:997:in `root_without_deprecation'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/deprecation.rb:94:in `root'
from (irb):60
from /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/routing.rb:1139:in `draw'
from (irb):59


# Added deprecation notice for anyone who already added a named route called "root".
# It'll be used as a shortcut for map.connect '' in Rails 2.0.
# def root(*args, &proc)
# super unless args.length >= 1 && proc.nil?
# @set.add_named_route("root", *args)
# end
# deprecate :root => "(as the the label for a named route) will become a shortcut for map.connect '', so find another name"

Rails2.0才会引进此方法,所以Rails建议用户不要使用此具名路由,如下:
>> rs.draw do |map|
?> map.root '', :controller => 'test', :action => 'list'
>> end
=> [ActionController::Base, ActionView::Base]
>> puts rs.routes
ANY / {:action=>"list", :controller=>"test"}
=> nil
>> puts rs.named_routes.routes
rootANY / {:action=>"list", :controller=>"test"}
=> nil
这个写法其实就是做了个具名路由,而不是调用map.root方法,调用的是method_missing方法。

Rails ActiveRecord Observer usage

要使Observer工作,第一种做法是在controller里声明, 这样unit test就无法加载此observer到console中


# app/models/flower_observer.rb
class FlowerObserver < ActiveRecord::Observer
observe Flower

def after_create(model)
# model.do_something!
end
end

# controller(s)
class FlowerController < ApplicationController
observer :flower_observer
end

第二种做法可以加载observer到console中:

# app/models/foo_bar.rb
class FooBar < ActiveRecord::Base
end

FooBarObserver.instance

最后一个方法是在config/environment.rb中加载此observer:

config.active_record.observers = :flower_observer


参考RobbyOnRails

one_to_one relationship explain and notice

以Agile Web Development with Rails书中关于has_one 关系的order和invoice关系做个例子,其中设了一个total_price字段在invoice表中,不能为空,当做以下操作时:
o = Order.find(1)
i = Invoice.new
o.invoice = i
这个时候Rails会自动保存i这个Invoice对象,保存过和书里有插图说明,先将原来记录的order_id置为NULL,再插入些记录。而此记录在数据库里是设定了非空,所以不会插入成功。
得到的log如下:


Order Load (0.002154) SELECT * FROM orders WHERE (orders.`id` = 1)
Invoice Load (0.002144) SELECT * FROM invoices WHERE (invoices.order_id = 1) LIMIT 1
SQL (0.000859) BEGIN
Invoice Update (0.002496) UPDATE invoices SET `created_at` = '2007-08-26 17:21:30', `total_price` = '9.0', `order_id` = NULL WHERE `id` = 1
SQL (0.003602) COMMIT
SQL (0.000605) BEGIN
SQL (0.000000) Mysql::Error: Column 'total_price' cannot be null: INSERT INTO invoices (`order_id`, `total_price`, `created_at`) VALUES(1, NULL, '2007-08-26 18:07:21')
SQL (0.000865) ROLLBACK

这就造成了数据问题,在这里是数据库做限制,所以程序出错还可以知道出错,如果是通过validate或者before_save过滤器过滤的话,就很难查觉数据没有写入库中,所以这种写法书里不推荐,而是先强制保存子对象i再保存父对象o
或者写入事务中:

Order.transaction do
o.invoice = i
end

程序还是会报错,因为数据库写不进去的。可以再begin..end捕获错误。

>> o = Order.new do |x|
?> x.name = 'a'
>> x.email = 'a@test.com'
>> x.address = 'Shanghai'
>> end
=> #"a", "updated_at"=>nil, "pay_type"=>nil, "address"=>"Shanghai", "created_at"=>nil, "email"=>"a@test.com"}>
>> i = Invoice.new
=> #nil, "total_price"=>nil, "created_at"=>nil}>
>> i.order = o
=> #"a", "updated_at"=>nil, "pay_type"=>nil, "address"=>"Shanghai", "created_at"=>nil, "email"=>"a@test.com"}>
>> i.save
ActiveRecord::StatementInvalid: Mysql::Error: Column 'total_price' cannot be null: INSERT INTO invoices (`order_id`, `total_price`, `created_at`) VALUES(5, NULL, '2007-08-26 18:36:24')

one_to_one relationship中保存子对象i时会先保存其父对象o,而保存父对象o则子对象不会一起保存。以上例子产生的log如下:

SQL (0.000750) BEGIN
SQL (0.080562) INSERT INTO orders (`name`, `updated_at`, `pay_type`, `address`, `created_at`, `email`) VALUES('a', '2007-08-26 18:36:23', NULL, 'Shanghai', '2007-08-26 18:36:23', 'a@test.com')
SQL (0.000000) Mysql::Error: Column 'total_price' cannot be null: INSERT INTO invoices (`order_id`, `total_price`, `created_at`) VALUES(5, NULL, '2007-08-26 18:36:24')
SQL (0.005971) ROLLBACK

Rails 是将其包装在一个事务里处理的,所以不会生成一条新的order记录。

BTW:
在has_many关系中与上面has_one是相反的,当保存了父对象之后会遍历父对象中的全部子对象并保存,如果父对象和子对象都是新建对象,不能先保存子对象,因为无法取到父对象的id。如下例子说明:

order = Order.new
[1, 2, 3].each do |prd_id|
product = Product.find(prd_id)
order.line_items << LineItem.new(:product =>product, :quantity => 2, :total_price => 3.22)
end
order.save

产生Log如下:

Product Load (0.002137) SELECT * FROM products WHERE (products.`id` = 1)
SQL (0.023867) BEGIN
SQL (0.002860) COMMIT
Product Load (0.001754) SELECT * FROM products WHERE (products.`id` = 2)
SQL (0.066274) BEGIN
SQL (0.001553) COMMIT
Product Load (0.002514) SELECT * FROM products WHERE (products.`id` = 3)
SQL (0.001669) BEGIN
SQL (0.000442) COMMIT
SQL (0.000661) BEGIN
SQL (0.003558) INSERT INTO orders (`name`, `updated_at`, `pay_type`, `address`, `created_at`, `email`) VALUES(NULL, '2007-08-26 19:30:18', NULL, NULL, '2007-08-26 19:30:18', NULL)
SQL (0.002258) INSERT INTO line_items (`order_id`, `updated_at`, `total_price`, `product_id`, `quantity`, `created_at`) VALUES(9, '2007-08-26 19:30:18', '3.22', 1, 2, '2007-08-26 19:30:18')
SQL (0.002302) INSERT INTO line_items (`order_id`, `updated_at`, `total_price`, `product_id`, `quantity`, `created_at`) VALUES(9, '2007-08-26 19:30:18', '3.22', 2, 2, '2007-08-26 19:30:18')
SQL (0.004991) INSERT INTO line_items (`order_id`, `updated_at`, `total_price`, `product_id`, `quantity`, `created_at`) VALUES(9, '2007-08-26 19:30:18', '3.22', 3, 2, '2007-08-26 19:30:18')
SQL (0.069437) COMMIT


order = Order.new
product = Product.find(1)
li = LineItem.new(:product =>product, :quantity => 2, :total_price => 3.22)
order.line_items << li
li.save

产生Log如下:

Product Load (0.002695) SELECT * FROM products WHERE (products.`id` = 1)
SQL (0.023173) BEGIN
SQL (0.000987) COMMIT
SQL (0.000777) BEGIN
SQL (0.000000) Mysql::Error: Column 'order_id' cannot be null: INSERT INTO line_items (`order_id`, `updated_at`, `total_price`, `product_id`, `quantity`, `created_at`) VALUES(NULL, '2007-08-26 19:34:15', '3.22', 1, 2, '2007-08-26 19:34:15')
SQL (0.002174) ROLLBACK
SQL (0.003055) BEGIN
SQL (0.001734) COMMIT

model callbacks of Rails ActiveRecord


class Encrypter
def before_save(model)
model.name.tr! 'a-z', 'b-za'
end

def after_save(model)
model.name.tr! 'b-za', 'a-z'
end

# alias_method :after_find, :after_save
# alias_method
# Makes new_id a new copy of the method old_id. This can be used to retain access to
# methods that are overridden.

alias after_find after_save
# Aliasing
# alias new_name old_name
# creates a new name that refers to an existing method, operator, global variable, or reg-
# ular expression backreference ($&, $`, $', and $+). Local variables, instance variables,
# class variables, and constants may not be aliased. The parameters to alias may be
# names or symbols.

end

class ActiveRecord::Base
def self.encrypted
encrypt = Encrypter.new
before_save encrypt
after_save encrypt
after_find encrypt
module_eval <<-"end_eval"
def after_find
# Unlike all the other callbacks, after_find and after_initialize will only be run
# if an explicit implementation is defined (def after_find).
end
end_eval
end
end

class User < ActiveRecord::Base
encrypted
protected
def validate_on_create()
puts 'existed user name' if self.class.exists? :name => name
end
end

Saturday, August 25, 2007

Control Apache from System Preferences in OSX

Filed under Mac

Here’s a cool way to control Apache (other than the included version) on OSX. Apache will also auto start on boot using this method.

First, add this line to your httpd.conf file:

PidFile /private/var/run/httpd.pid

Now, open up Terminal and type the following:

cd /usr/sbin
mv apachectl apachectl_bak
ln -s /usr/local/apache2/bin/apachectl apachectl

Now you can go to System Preferences->Sharing and start or stop Personal Web Sharing. Enjoy!

Rails callbacks explain

source article

Callbacks


From the API documentation, "Callbacks are hooks into the lifecycle of an Active Record object that allows you to trigger logic before or after an alteration of the object state." There are callbacks for: validate, create, save, update, destroy, find, new/initialize, and associations (Association Callbacks are discussed in the Associations section below).



You may configure most of these callbacks (excluding find, initialize, and association callbacks) in two different ways: (1) overwrite the default method or (2) register with the macros. The macros are more powerful and more commonly used, especially as the macros add their behavior into a callback hierarchy that is maintained through a class inheritance hierarchy. That is, if you register callbacks for the Animal class (which inherits from ActiveRecord::Base) and subsequently define a Monkey class (which inherits from Animal), then Monkey will also inherit the Animal callbacks.



The callback macros can be used in four different ways (see the very clear discussion in the "Types of callbacks" section on the ActiveRecord::Callbacks API page)


  1. symbol reference to a protected or private method in the model

  2. an object to be messaged with the callback method and record

  3. a method string

  4. a method Proc



The validation callback hierarchy



These series are triggered by calls to:
object.valid?

New Record Existing Record
----------------------------- -----------------------------
before_validation before_validation
before_validation_on_create before_validation_on_update
<< object validated here >> << object validated here >>
after_validation after_validation
after_validation_on_create after_validation_on_update



This series is triggered by calls to:
Model.create
object.save (if not previously saved)

before_validation
before_validation_on_create
<< object validated here >>
after_validation
after_validation_on_create
before_save
before_create
<< db record created here >>
after_create
after_save



This series is triggered by calls to:
object.save (if previously saved)
object.update_attributes

before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_save
before_update
<< db record saved/updated here >>
after_update
after_save

A save! call triggers the validation series twice. If save! is called on a new record, the new record validation series with *_on_create methods is called twice.



This series is triggered by calls to:
object.save!

before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_save
before_update
<< db record saved/updated here >>
after_update
after_save

Several of the save/update methods appear to bypass validation (or at least the validation callbacks) and only call the save callbacks.



This series is triggered by calls to:
object.increment!
object.decrement!
object.toggle!
object.update_attribute

before_save
before_update
<< db record saved/updated here >>
after_update
after_save

The object.update callback hierarchy only triggers the update callbacks.



This series is triggered by calls to:
object.update

before_update
<< db record updated here >>
after_update

However, the model update class method triggers a full series of callbacks.



This series is triggered by calls to:
Model.update

after_find (if defined)
after_initialize (if defined)
before_validation
before_validation_on_update
<< object validated here >>
after_validation
after_validation_on_update
before_save
before_update
<< db record saved/updated here >>
after_update
after_save

increment_counter and decrement_counter bypass all callbacks



These methods bypass all callbacks:
Model.decrement_counter
Model.increment_counter



This series is triggered by calls to:
object.destroy

before_destroy
<< record is deleted here >>
after_destroy

This series is triggered by calls to:
Model.destroy
Model.destroy_all

after_find (if defined)
after_initialize (if defined)
before_destroy
<< record is deleted here >>
after_destroy

These don't trigger any callbacks:
Model.delete
Model.delete_all

The after_find and after_initialize callbacks may will only be called if the default method is overwritten (no macros here).



Triggered by a call to:
Model.new

after_initialize (if defined)

--------------------------------------------

Triggered by a call to:
object.reload
Model.find

after_find (if defined)
after_initialize (if defined)

Friday, August 24, 2007

Rails controller request and response methods and instance_variables


class TestController < ApplicationController
before_filter { |controller| p controller.request.methods.sort; p controller.request.instance_variables }
after_filter { |controller| p controller.response.methods.sort; p controller.response.instance_variables }

def index
end
end


# ["==", "===", "=~", "__id__", "__send__", "`", "accepts", "b64encode", "blank?", "cgi", "cgi=", "class", "clone", "content_type", "cookies", "copy_instance_variables_from", "daemonize", "dclone", "decode64", "decode_b", "delete?", "display", "domain", "dup", "enable_warnings", "encode64", "env", "eql?", "equal?", "extend", "extend_with_included_modules_from", "extended_by", "formatted_post?", "freeze", "frozen?", "gem", "get?", "hash", "head?", "host", "host_with_port", "id", "inspect", "instance_eval", "instance_exec", "instance_of?", "instance_values", "instance_variable_get", "instance_variable_set", "instance_variables", "is_a?", "kind_of?", "load", "method", "method_missing", "methods", "nil?", "object_id", "parameters", "path", "path_parameters", "path_parameters=", "port", "port_string", "post?", "post_format", "pretty_inspect", "pretty_print", "pretty_print_cycle", "pretty_print_inspect", "pretty_print_instance_variables", "private_methods", "protected_methods", "protocol", "public_methods", "put?", "query_parameters", "query_string", "raw_post", "relative_url_root", "relative_url_root=", "remote_ip", "remove_subclasses_of", "request_parameters", "request_uri", "require", "require_gem", "require_library_or_gem", "reset_session", "respond_to?", "returning", "send", "server_software", "session", "session=", "session_options", "session_options=", "silence_stderr", "silence_stream", "silence_warnings", "singleton_methods", "ssl?", "standard_port", "subclasses_of", "subdomains", "suppress", "symbolized_path_parameters", "taguri", "taguri=", "taint", "tainted?", "to_a", "to_json", "to_param", "to_s", "to_yaml", "to_yaml_properties", "to_yaml_style", "type", "unloadable", "untaint", "with_options", "xhr?", "xml_http_request?", "xml_post?", "yaml_post?"]
# ["@session", "@request_method", "@query_parameters", "@parameters", "@content_type", "@request_parameters", "@session_options", "@session_options_with_string_keys", "@symbolized_path_parameters", "@env", "@cgi", "@path_parameters"]
# ["==", "===", "=~", "__id__", "__send__", "`", "assigns", "assigns=", "b64encode", "blank?", "body", "body=", "charset", "charset=", "class", "clone", "content_type", "content_type=", "cookies", "cookies=", "copy_instance_variables_from", "daemonize", "dclone", "decode64", "decode_b", "display", "dup", "enable_warnings", "encode64", "eql?", "equal?", "extend", "extend_with_included_modules_from", "extended_by", "freeze", "frozen?", "gem", "hash", "headers", "headers=", "id", "inspect", "instance_eval", "instance_exec", "instance_of?", "instance_values", "instance_variable_get", "instance_variable_set", "instance_variables", "is_a?", "kind_of?", "layout", "layout=", "load", "method", "methods", "nil?", "object_id", "out", "pretty_inspect", "pretty_print", "pretty_print_cycle", "pretty_print_inspect", "pretty_print_instance_variables", "private_methods", "protected_methods", "public_methods", "redirect", "redirected_to", "redirected_to=", "redirected_to_method_params", "redirected_to_method_params=", "remove_subclasses_of", "require", "require_gem", "require_library_or_gem", "respond_to?", "returning", "send", "session", "session=", "silence_stderr", "silence_stream", "silence_warnings", "singleton_methods", "subclasses_of", "suppress", "taguri", "taguri=", "taint", "tainted?", "template", "template=", "to_a", "to_json", "to_param", "to_s", "to_yaml", "to_yaml_properties", "to_yaml_style", "type", "unloadable", "untaint", "with_options"]
# ["@session", "@headers", "@assigns", "@body", "@redirected_to", "@cgi", "@template"]

Rails output compress plugin

source code from: http://blog.craz8.com/files/compress.rb


require 'stringio'
require 'zlib'

class OutputCompressionFilter

def self.filter(controller)
return if controller.response.headers['Content-Encoding'] || controller.request.env['HTTP_ACCEPT_ENCODING'].nil?
begin
controller.request.env['HTTP_ACCEPT_ENCODING'].split(/\s*,\s*/).each do |encoding|
# TODO: use "q" values to determine user agent encoding preferences
case encoding
when /\Agzip\b/
StringIO.open('', 'w') do |strio|
begin
gz = Zlib::GzipWriter.new(strio)
gz.write(controller.response.body)
controller.response.body = strio.string
ensure
gz.close if gz
end
end
when /\Adeflate\b/
controller.response.body = Zlib::Deflate.deflate(controller.response.body, Zlib::BEST_COMPRESSION)
when /\Aidentity\b/
# do nothing for identity
else
next # the encoding is not supported, try the next one
end
controller.logger.info "Response body was encoded with #{encoding}"
controller.response.headers['Content-Encoding'] = encoding
break # the encoding is supported, stop
end
end
controller.response.headers['Content-Length'] = controller.response.body.length
if controller.response.headers['Vary'] != '*'
controller.response.headers['Vary'] =
controller.response.headers['Vary'].to_s.split(',').push('Accept-Encoding').uniq.join(',')
end
end

end

Ruby metaprogramming example


module Properties
def property(sym)
# 实际上,使用Ruby中已有的attr_accessor :property可以起到同样的效果。
define_method(sym) do
instance_variable_get("@#{sym}")
end

define_method("#{sym}=") do |value|
instance_variable_set("@#{sym}", value)
puts sym
end

define_method("add_#{sym}_listener") do |z|
puts sym
z.call('yy') if z.kind_of?Proc
puts z if z.kind_of?String
end
end
end

class CruiseShip
self.extend Properties
property :direction
property :speed

def initialize
@listener = []
end

end

h = CruiseShip.new
h.add_direction_listener('xxxx')
h.add_speed_listener lambda {|x| puts "Oy... someone changed the property to #{x}"}
h.speed = 10

puts h.speed

ruby metaprogramming 需要熟悉Ruby的一些方法和类:
eval
class_eval
module_eval
const_get
instance_variable_get
instance_variable_set
define_method
const_missing
undef
remove_method
undef_method
remove_const
ancestors
constants
class_variables
instance_variables
instance_methods
public_instance_methods
protected_instance_methods
included_modules
private_methods
public_methods
caller
set_trace_func
ObjectSpace.each_object
method_missing
alias_method
singleton_method_added
inherited
included
extend_object
define_finalizer
block_given?
yield

Thursday, August 23, 2007

Ruby realize cookie management


#!/usr/bin/env ruby
require 'pp'
require 'erb'
require 'uri'
require 'hpricot'
require 'net/http'
require 'net/https'

module CookieMechanism
def cookies_hashed(set_cookie, path, domain)
expires = 'Mon, 01-Jan-2010 00:00:00 GMT'
arr_hashed = Array.new
if set_cookie
arr = set_cookie.split(/, /)
for i in 0 ... arr.size - 1
if arr[i] =~ /Expires=/ && arr[i + 1] =~ /.*GMT/
arr[i] << ', ' << arr[i + 1]
arr[i + 1] = ''
end
end
arr.delete_if {|del| del == ''}
arr.each do |cookie|
fields = cookie.split(';')
hashed = Hash.new
hashed['Path'] = path
hashed['Domain'] = domain
hashed['Secure'] = 0
fields.each do |f|
h = f.strip.split('=', 2)
h[0].capitalize! if h[0].capitalize =~ /Expires|Path|Domain|Secure/i
h[1] = 1 if h[0] == 'Secure'
hashed.merge!({h[0] => h[1]})
end
if hashed.has_key?('Expires')
hashed['Expires'] = 0 if Time.httpdate(hashed['Expires']) <= Time.now()
else
hashed['Expires'] = expires
end
arr_hashed << hashed
end
end
return arr_hashed
end

def cookies_process(arr_hashed_new, arr_hashed_old = Array.new)
arr_hashed_new.each do |new|
same_key = 0
new.each do |new_key, new_value|
if new_key !~ /Expires|Path|Domain|Secure/i
arr_hashed_old.each do |old|
old.each do |old_key, old_value|
if old_key !~ /Expires|Path|Domain|Secure/i && same_key == 0
if old_key == new_key
same_key = 1
end
end
break if same_key == 1
end
end
if same_key == 1
arr_hashed_old.each do |old|
old.each do |old_key, old_value|
if old_key == new_key
if new['Path'] == old['Path'] && new['Domain'] == old['Domain']
if new['Expires'] != 0
old[old_key] = new_value
old['Expires'] = new['Expires']
old['Secure'] = new['Secure']
else
arr_hashed_old.delete(old)
end
else
arr_hashed_old << new if new['Expires'] != 0
end
end
end
end
else
arr_hashed_old << new if new['Expires'] != 0
end
end
end
end
return arr_hashed_old
end

def cookies_request(arr_hashed_old, path, domain, secure = 0)
cookie = String.new
cookies = Array.new
arr_hashed_old.each do |old|
reg_str = Regexp.escape(old['Path'])
reg_path = Regexp.new('^' + reg_str)
reg_str = Regexp.escape(old['Domain'])
reg_domain = Regexp.new(reg_str + '$')
if path =~ reg_path && domain =~ reg_domain
if secure == 0
cookies << old if old['Secure'] == 0
else
cookies << old
end
end
end
cookies.sort!{|a, b| a['Path'] <=> b['Path']}.reverse!
cookies.each do |c|
c.each do |key, value|
if key !~ /Expires|Path|Domain|Secure/i
cookie == '' ? cookie += key + '=' + value : cookie += '; ' + key + '=' + value
end
end
end
return cookie
end

def add_cookie(response, path, domain, arr_hashed_old)
set_cookie = response['set-cookie'] # response: HTTPResponse object
arr_hashed_new = cookies_hashed(set_cookie, path, domain)
arr_hashed_old = cookies_process(arr_hashed_new, arr_hashed_old)
end

def get_http_headers(path, domain, arr_hashed_old)
headers = {
'Cookie' => cookies_request(arr_hashed_old, path, domain, 0),
'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
'Connection' => 'Keep-Alive',
'Accept-Language' => 'zh-cn'
}
end

def post_http_headers(path, domain, arr_hashed_old)
headers = {
'Cookie' => cookies_request(arr_hashed_old, path, domain, 0),
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
'Connection' => 'Keep-Alive',
'Accept-Language' => 'zh-cn'
}
end

def get_https_headers(path, domain, arr_hashed_old)
headers = {
'Cookie' => cookies_request(arr_hashed_old, path, domain, 1),
'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
'Connection' => 'Keep-Alive',
'Accept-Language' => 'zh-cn'
}
end

def post_https_headers(path, domain, arr_hashed_old)
headers = {
'Cookie' => cookies_request(arr_hashed_old, path, domain, 1),
'Content-Type' => 'application/x-www-form-urlencoded',
'User-Agent' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)',
'Connection' => 'Keep-Alive',
'Accept-Language' => 'zh-cn'
}
end
end

Tuesday, August 21, 2007

HTML pass parameters to Flash AS3


<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="Example" width="100%" height="100%"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
<param name="movie" value="Example.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#dddddd" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="FlashVars" value="foo=1&bar=2" />
<embed src="Example.swf"
quality="high"
bgcolor="#dddddd"
width="50%"
height="50%"
name="Example"
align="middle"
play="true"
loop="false"
quality="high"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer"
FlashVars="foo=1&bar=2"
>
</embed>
</object>

param中的FlashVars可以传参数给IE中的Flash(其他参数也是,如宽高),embed中的FlashVars可以传参数给Firefox中的Flash(其他参数也是,如宽高)。
AS3中可以这样接收传进来的参数,如

var foo:String = root.loaderInfo.parameters.foo;
var request:URLRequest = new URLRequest("http://localdomain/get.php?foo=" + foo);
var loader:URLLoader = new URLLoader();
loader.load(request);

这里如果get.php是个中转页,则需要设置cache无效,不然第一次重定向有效,后面的会不生效了(这里有个恶心的地方,Firefox只要在这个中转页上加了就可以每次刷新重定向,IE则需要在重定向目标页面也要加上这个头信息说明Cache无效才能每次刷新也重定向生效)。不过这个对于静态页面写了META标签也是不行。
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

Sunday, August 19, 2007

JavaScript window.getSelection usage example


<script type="text/javascript" language="javascript">
if (window.getSelection) {
// Mozilla
if (String(window.getSelection()))
return String(window.getSelection());
} else if (document.getSelection) {
// Opera? Netscape 4?
if (document.getSelection())
return document.getSelection();
} else {
// IE
if ( document.selection.createRange().text )
return document.selection.createRange().text;
}
</script>
//以下代码是只能用于IE
<input type="text" id="test" value="get the next character after current cursor? 可取中文字" size="60"><br/>
<input type="button" value="取当前光标的后一个字母" onclick="nextChar()"><br/>
<input type="text" value="取当前光标的位置" onclick="charPosition()"><br/>

<script type="text/javascript" language="javascript">
<!--
var s;
function nextChar()
{
document.getElementById('test').focus();
var sel = document.selection.createRange();
sel.moveStart("character",0);
sel.moveEnd("character",1);
s = sel.text.slice(-1);
alert("S = " + s);
}

function charPosition() {
var obj = window.event.srcElement;
var s=document.selection.createRange();
s.setEndPoint("StartToStart", obj.createTextRange())
var pos = s.text.length;
alert(pos);
obj.createTextRange().select();
alert(document.selection.createRange().text);
}
//-->
</script>

Rails ActionView::Helpers::PrototypeHelper::JavaScriptGenerator::GeneratorMethods example


<div id="d1">
div d1
</div>
<div id="a1">
a1 will Effect.Fade
</div>
<div id="a2">
a2 id will be alerted
</div>
<div id="a3">
a3 content will be replaced by function testCall
</div>
<div id="list">
<ul>
<li>1</li>
<li class="none">2</li>
<li>3</li>
<li class="none">4</li>
<li>5</li>
<li class="none">6</li>
</ul>
</div>
<%= javascript_tag "function testCall(id, f){ alert(id); f(); return }" %>
<%=
update_page_tag do |page|
page.insert_html 'top', 'd1', '<div>insert top of div d1</div>'
page.call 'Effect.Fade', 'a1', :duration => 5
page.call 'testCall', 'a2' do |d|
d.replace 'a3', :partial => 'replace'
end

page.select('div[id="list"] ul li.none').each do |item|
item.hide
end
end
%>

Saturday, August 18, 2007

Rails link_to_function and button_to_function usage example


<div id="details">
div details visual effect
</div>

<%= button_to_function "Greeting", "alert('Hello world!')" %>
<%=
button_to_function "Highlight Details" do |page|
page.visual_effect :highlight, 'details'
end
%>
<br/>
<%= define_javascript_functions %>

<%= link_to_function "Greeting", "alert('Hello world!')" %>
<br/>
<%=
link_to_function("Toggle Blind Div Details", nil, :id => "more_link") do |page|
page.visual_effect :toggle_blind, 'details'
page.replace_html 'more_link', :partial => 'replace'
end
%>
<br/>
<%=
link_to_function("Replace HTML", nil, :id => "replace_link") do |page|
page.replace_html 'replace_link', "replaced html"
end
%>

Thursday, August 16, 2007

用Ruby spreadsheet/excel 生成Excel文档(附问题)

require "rubygems"
require "spreadsheet/excel"
include Spreadsheet

workbook = Excel.new("test.xls")

format = Format.new
format.color = "green"
format.bold = true

worksheet = workbook.add_worksheet
worksheet.write(0, 0, "Hello", format)
worksheet.write(1, 1, ["Matz","Larry","Guido"])

workbook.close

这是doc里的例子,但是format并不能应用到"Hello"这个格子上,需要用format = workbook.add_format(:color => "green", :bold => true)才能真正生效,有知道原因的朋友可以回帖知会一下,谢谢。
PS: 这个lib只能生成,读取用parseexcel这个lib。

scriptaculous auto complete example


<style type="text/css">
div.autocomplete {
position:absolute;
width:250px;
background-color:white;
border:1px solid #888;
margin:0px;
padding:0px;
}
div.autocomplete ul {
list-style-type:none;
margin:0px;
padding:0px;
}
div.autocomplete ul li.selected { background-color: #ffb;}
div.autocomplete ul li {
list-style-type:none;
display:block;
margin:0;
padding:2px;
height:32px;
cursor:pointer;
}
</style>

<script src="prototype.js" type="text/javascript"></script>
<script src="effects.js" type="text/javascript"></script>
<script src="controls.js" type="text/javascript"></script>

<input type="text" id="autocomplete" name="autocomplete_parameter"/>
<span id="indicator1" style="display: none"><img src="indicator.gif" alt="Working..." /></span>
<div id="autocomplete_choices" class="autocomplete"></div>

<script type="text/javascript">
function updateElemTest(selectedElement) {
alert(selectedElement.id);
$('autocomplete').value = selectedElement.innerHTML;
}
function getSelectionId(input, li) {
alert (input.value + ' + ' + li.id);
}
function calledOnHide(input, update) {
new Effect.Fade(update,{duration: 1})
}

//new Ajax.Autocompleter("autocomplete", "autocomplete_choices", "ajax_response.html", {
// paramName: "value",
// minChars: 2,
// updateElement: updateElemTest, //取代默认方法(更新input),用户自定义更新
// indicator: 'indicator1'
// });

//new Ajax.Autocompleter("autocomplete", "autocomplete_choices", "ajax_response.html", {
// paramName: "value", //本来默认传过去的参数名是input name,可以重定义覆盖此名字
// minChars: 2,
// afterUpdateElement : getSelectionId, //只发生在默认更新动作发生之后
// indicator: 'indicator1'
// });

var my_completer = new Ajax.Autocompleter("autocomplete", "autocomplete_choices", "ajax_response.html", { onHide: calledOnHide });
</script>

<!--
ajax_response.html example:
<ul>
<li id="1">yes</li>
<li id="2">no</li>
<li id="3">thanks</li>
</ul>
-->

Monday, August 13, 2007

Hpricot CSS Selector speed test

require 'rubygems'
require 'scrubyt' # mechanize hpricot open-uri rubyinline parse-tree ...

doc = Hpricot(open('http://extjs.com/playpen/slickspeed/system/template.php?include=prototype.js&function=$$&modifier=&nocache=1187009411'))


def step(doc, selector)
print selector + "\t\t"
start_time = Time.now.to_f
rs = doc/selector
end_time = Time.now.to_f
print rs.length.to_s + "\t\t"
puts ((end_time - start_time) * 1000).round # !> (...) interpreted as grouped expression
end

step(doc, "*")
step(doc, "div:only-child")
step(doc, "div:contains(CELIA)")
step(doc, "div:nth-child(even)")
step(doc, "div:nth-child(2n)")
step(doc, "div:nth-child(odd)")
step(doc, "div:nth-child(2n+1)")
step(doc, "div:nth-child(n)")
step(doc, "div:last-child")
step(doc, "div:first-child")
step(doc, "div:not(:first-child)")
step(doc, "div:not(.dialog)")
step(doc, "div > div")
step(doc, "div + div")
step(doc, "div ~ div")
step(doc, "body")
step(doc, "body div")
step(doc, "div")
step(doc, "div div")
step(doc, "div div div")
step(doc, "div, div, div")
step(doc, "div, a, span")
step(doc, ".dialog")
step(doc, "div.dialog")
step(doc, "div.dialog.emphatic")
step(doc, "div .dialog")
step(doc, "div.character, div.dialog")
step(doc, "#speech5")
step(doc, "div#speech5")
step(doc, "div #speech5")
step(doc, "div.scene div.dialog")
step(doc, "div#scene1 div.dialog div")
step(doc, "#scene1 #speech1")
step(doc, "div[@class]")
step(doc, "div[@class='dialog']")
step(doc, "div[@class^='dia']")
step(doc, "div[@class$='log']")
step(doc, "div[@class*='sce']")
step(doc, "div[@class|='dialog']")
step(doc, "div[@class!='madeup']")
step(doc, "div[@class~='dialog']")

# >> selector founded time
# >> * 755 24
# >> div:only-child 22 223
# >> div:contains(CELIA) 26 130
# >> div:nth-child(even) 106 70
# >> div:nth-child(2n) 14 65
# >> div:nth-child(odd) 137 116
# >> div:nth-child(2n+1) 14 191
# >> div:nth-child(n) 31 65
# >> div:last-child 53 101
# >> div:first-child 51 89
# >> div:not(:first-child) 192 100
# >> div:not(.dialog) 192 49
# >> div > div 242 171
# >> div + div 0 35
# >> div ~ div 240 6882
# >> body 1 20
# >> body div 243 37
# >> div 243 26
# >> div div 242 287
# >> div div div 241 525
# >> div, div, div 729 72
# >> div, a, span 243 184
# >> .dialog 51 41
# >> div.dialog 51 48
# >> div.dialog.emphatic 5 52
# >> div .dialog 51 318
# >> div.character, div.dialog 99 104
# >> #speech5 1 3
# >> div#speech5 1 165
# >> div #speech5 1 26
# >> div.scene div.dialog 49 101
# >> div#scene1 div.dialog div 142 240
# >> #scene1 #speech1 1 3
# >> div[@class] 103 40
# >> div[@class='dialog'] 45 50
# >> div[@class^='dia'] 51 47
# >> div[@class$='log'] 45 57
# >> div[@class*='sce'] 1 201
# >> div[@class|='dialog'] 45 62
# >> div[@class!='madeup'] 243 46
# >> div[@class~='dialog'] 51 51

Friday, August 10, 2007

Classical Inheritance in JavaScript

Classical Inheritance in JavaScript


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Function.method('inherits', function (parent) {
var d = {}, p = (this.prototype = new parent());
this.method('uber', function uber(name) {
if (!(name in d)) {
d[name] = 0;
}
var f, r, t = d[name], v = parent.prototype;
if (t) {
while (t) {
v = v.constructor.prototype;
t -= 1;
}
f = v[name];
} else {
f = p[name];
if (f == this[name]) {
f = v[name];
}
}
d[name] += 1;
r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
d[name] -= 1;
return r;
});
return this;
});
Function.method('swiss', function (parent) {
for (var i = 1; i < arguments.length; i += 1) {
var name = arguments[i];
this.prototype[name] = parent.prototype[name];
}
return this;
});

function Parenizor(value) {
this.setValue(value);
}

Parenizor.method('setValue', function (value) {
this.value = value;
return this;
});

Parenizor.method('getValue', function () {
return this.value;
});

Parenizor.method('toString', function () {
return '(' + this.getValue() + ')';
});

var myParenizor = new Parenizor(0);
var myString = myParenizor.toString();
doc(myParenizor.value);
doc(myString);

function ZParenizor(value) {
this.setValue(value);
}

ZParenizor.inherits(Parenizor);

ZParenizor.method('toString', function () {
if (this.getValue()) {
return this.uber('toString');
}
return "-0-";
});

/*There is another way to write ZParenizor. Instead of inheriting from Parenizor, we write a constructor that calls the Parenizor constructor, passing off the result as its own. And instead of adding public methods, the constructor adds privileged methods.

function ZParenizor2(value) {
var that = new Parenizor(value);
that.toString = function () {
if (this.getValue()) {
return this.uber('toString');
}
return "-0-"
};
return that;
}*/

var myZParenizor = new ZParenizor(0);
var myString = myZParenizor.toString();
doc(myZParenizor.value);
doc(myString);
</script>

Private Members in JavaScript

Private Members in JavaScript


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}

function Container(param) {

function dec() {
// private function
if (secret > 0) {
// encloures
secret -= 1;
return true;
} else {
return false;
}
}

this.member = param;
var secret = 3; // private variables only be made in constructor function
var that = this;

this.service = function () {
// privileged function
if (dec()) {
//return that.member;
return this.member;
} else {
return null;
}
};
}

var myContainer = new Container('abc');
doc(myContainer.service()); // abc
doc(myContainer.service()); // abc
doc(myContainer.service()); // abc
doc(myContainer.service()); // null
</script>

Thursday, August 09, 2007

Ruby Quiz author's currying explain example


class Proc
def curry(&block)
lambda {|*args| call(*block[*args]) }
end
end

murry = lambda {|i, j, *k| i * j}
# p murry[5, 2]

multiply = murry.curry {|*k| k + [2]} #=> Proc, lambda{|*args| call(*block[*args])}; block #=> Proc, lambda {|*k| k + [2]}; k.class is Array.
p multiply[5] # proc[] is synonym for proc.call
p multiply[5, 3] # output 5 * 3 = 15, not 5 * 2
# step explain double[5]
p lambda {|*k| k + [2]}[5]
p murry.call(*[5, 2])

p lambda {|*k| k + [2]}[5, 4, 3]
p murry.call(*[5, 4, 3, 2]) # 5 * 4

# Javascript: alert(function(){return arguments[0] * arguments[1];}.apply(null, function(){return [arguments[0]].concat(2);}(5)));


class Object
def curry(new_name, old_name, &args_munger)
([Class, Module].include?(self.class) ? self : self.class).class_eval do
define_method(new_name) { |*args| send(old_name, *args_munger[args]) }
end
end
end

class Value
def initialize(value)
@value = value
end

def *(other)
@value * other
end

curry(:double, :*) { [2] }
curry(:triple, :*) { |args| args.unshift(3) }
end

five, howdy = Value.new(5), Value.new("Howdy ")
puts five * 2 # => 10
puts five.double # => 10
puts five.triple # => 15
puts howdy.triple # => "Howdy Howdy Howdy "

Sunday, August 05, 2007

prototype javascript library try.these example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}
var rs = Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
);
doc(rs);

var lambda = function() {return new ActiveXObject('Msxml2.XMLHTTP')};
try {
lambda();
} catch (e) {
doc(e);
}
</script>

prototype javascript library 1.5.1 examples


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

doc(Prototype.Version);
doc(document.evaluate);
doc(!!document.evaluate);

doc(Prototype.emptyFunction);
doc(Prototype.K('test'));

var reg = new RegExp(Prototype.ScriptFragment);
doc(reg);
doc(reg.source);

var script = '<script type="text/javascript" charset="utf-8">var x;<\/script>';

var rs = reg.exec(script);
doc(rs.length);
</script>

prototype javascript library toJSON example


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}

var o = new Object();
o = {
a: 'a',
b: 'bb',
c: 'ccc'
};
doc(Object.keys(o));
doc(Object.values(o));
doc(Object.inspect(o));
doc(Object.toJSON(o)); //{"a": "a", "b": "bb", "c": "ccc"}
doc((new Date).toJSON());
</script>

Javascript keyword "this" explain

In JavaScript this always refers to the “owner” of the function we're executing, or rather, to the object that a function is a method of.
When we define our faithful function doSomething() in a page, its owner is the page,
or rather, the window object (or global object) of JavaScript.
An onclick property, though, is owned by the HTML element it belongs to.

Examples - copying
this is written into the onclick method in the following cases:

element.onclick = doSomething
element.addEventListener('click',doSomething,false)
element.onclick = function () {this.style.color = '#cc0000';}
<element onclick="this.style.color = '#cc0000';">

Examples - referring
In the following cases this refers to the window:
element.onclick = function () {doSomething()}
element.attachEvent('onclick',doSomething)
<element onclick="doSomething()">
<a href="#" id="a1" style="color: #ddd"> test </a>
<script type="text/javascript" charset="utf-8">
function doSomething() {
this.style.color = '#cc0000';
}

var a1 = $('a1');
// a1.addEventListener('click', doSomething, false);
a1.onclick = doSomething; // copy function.
</script>

prototype javascript library Template pattern example


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}

function printCart(){
//creating a sample cart
var cart = new Object();
cart.items = [ ];
//putting some sample items in the cart
cart.items.push({product: 'Book 123', price: 24.50, quantity: 1});
cart.items.push({product: 'Set of Pens', price: 5.44, quantity: 3});
cart.items.push({product: 'Gift Card', price: 10.00, quantity: 4});
//here we create our template for formatting each item
var itemFormat = new Template('You are ordering #{quantity} units of #{product} at $#{price} each.');
var formatted = '';
for(var i=0; i<cart.items.length; i++){
var cartItem = cart.items[i];
formatted += itemFormat.evaluate(cartItem) + '<br/>\n';
}

doc(formatted);
}
printCart();

var oldStr = 'testStringGsubAndTemplate';
var oldPattern = /Str(.*?)(G.*?)And/;
var regNoReplace = ' {1} + {2} ';
var regAllReplace = ' #{1} + #{2} ';
var regPartReplace = ' \\#{1} + #{2} ';

var rnr = oldStr.gsub(oldPattern, regNoReplace);
doc(rnr);
var rar = oldStr.gsub(oldPattern, regAllReplace);
doc(rar);
var rpr = oldStr.gsub(oldPattern, regPartReplace);
doc(rpr);
//alert(regNoReplace.match(Template.Pattern)); // return null, will not perform replacement function(match) {var before... }
var tg = (new Template(regNoReplace)).evaluate(oldStr.match(oldPattern));
doc(tg);
//alert(regPartReplace.match(Template.Pattern)); // return match object, will perform replacement function(match) {return template.ev....}
var tgp = (new Template(regPartReplace)).evaluate(oldStr.match(oldPattern));
doc(tgp);
</script>

String and RegExp function example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}
var url = "The URL is http://www.w3c.org/DOM/Activity";
var pattern = /(\w+):\/\/([\w\.]+)\/([\w\/]+)/;
// three subexpressions
var results = url.match(pattern);
doc("results.input =\t" + results.input);
doc("results.index =\t" + results.index);
for (var i=0; i < results.length; i++) {
doc("results[" + i + "] =\t" + results[i]);
}

doc("========================================================")
var s = 'text1test2test3'
var m = s.match(/test/);
var n = /test/.exec(s);

doc('m == n : ' + (m == n));
doc('typeof m=' + typeof m);
doc('typeof n=' + typeof n);
doc('m[0]=' + m[0]);
doc('n[0]=' + n[0]);
doc('m.index=' + m.index);
doc('n.index=' + n.index);
doc('m.input=' + m.input);
doc('n.input=' + n.input);

</script>

prototype javascript library String extend function example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}
var str = '<font color="blue">ThereAreTest1AndTest2AndTest3AndtTest4AndTest5AndTest6AndTest7.</font>';
//doc('String.scan() = ' + str.scan(/test/i, 'Text'));
//doc('String.truncate() = ' + str.truncate());
doc('String.strip() = ' + str.strip());
doc('String.stripTags() = ' + str.stripTags());

var srt = '<script type="text/javascript" charset="utf-8">var x = 1; alert(x);<\/script>';
//srt.stripScripts();
//srt.evalScripts();
doc('srt.extractScripts() = ' + srt.extractScripts());
doc('str.escapeHTML() = ' + str.escapeHTML());
doc('str.unescapeHTML() = ' + str.unescapeHTML());

var queryStr = '?a=1&b=2&c=3&d=4#anchor';
var queryParams = queryStr.toQueryParams();
for(var p in queryParams){
doc('queryParams[' + p + '] = ' + queryParams[p]);
}

doc('String.succ() = ' + queryStr.succ());

var came = 'test-camelize-again';
doc('String.camelize() = ' + came.camelize());
doc('String.capitalize() = ' + came.capitalize());
doc('String.inspect() = ' + came.inspect(true));
</script>

prototype javascript library String.gsub example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

// Ruby String.gsub
// In the block form, the current match is passed in as a parameter,
// and variables such as $1, $2, $`, $&, and $' will be set appropriately.
// The value returned by the block will be substituted for the match on each call.
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
var result = '', source = this, match;
replacement = arguments.callee.prepareReplacement(replacement);
doc(replacement);
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
// pass match (object) to replacement(function),
// return value replace match[0]...
// origin Template.evaluate function recursive invoke String.gsub function
source = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
}
}
return result;
},

sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
count = count === undefined ? 1 : count;

return this.gsub(pattern, function(match) {
//alert(match.index);
//alert(match[0]);
if (--count < 0) return match[0];
return replacement(match);
});
}
});

String.prototype.gsub.prepareReplacement = function(replacement) {
if (typeof replacement == 'function') return replacement;
var template = new Template(replacement);
return function(match) { return template.evaluate(match) };
}

var Template = Class.create();
Template.prototype = {
initialize: function(template, pattern) {
alert(template.toString());
this.template = template.toString();
},

evaluate: function(match_object) {
return '<font color="red">' + this.template + '</font>';
}
}

var str = 'ThereAreTest1AndTest2AndTest3.';
var txt = str.gsub(/test/i, 'Text');
doc(txt);

var txt2 = str.sub(/test/i, 'Text', 2);
doc(txt2);
</script>

prototype javascript library String and Object extend example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

Object.extend(String, {
win: doc('this is object of Window ? ' + (this instanceof Window)), // true
size: function (str) {
return arguments.callee.print(str);
}
});

String.size.print = function (arg) {
//doc('String.size.print() = ' + arg.length);
return arg.length;
};

var s = "string size";

doc('String.size = ' + String.size(s));
doc(String.size.print(s));

var wStr = $w('a b c d e f g');
doc(wStr.inspect());
</script>

DOM Range Selections

DOM Range Selections
The DOM Range API (http://www.w3.org/TR/DOM-Level-2-Traversal-Range/) introduced in DOM Level 2 is another convenience extension that allows you to select a range of content in a document programmatically. To create a range, use document.CreateRange(), which will return a Range object.
var myRange = document.createRange();

Once you have a Range object, you can set what it contains using a variety of methods. Given our example range, we might use myRange.setStart(), myRange.setEnd(), myRange.setStartBefore(), myRange.setStartAfter(), myRange.setEndBefore(), and myRange.setEndAfter() to set the start and end points of the range. Each of these methods takes a Node primarily, though setStart() and setEnd() take a numeric value indicating an offset value. You may also just as easily select a particular node using myRange.selectNode() or its contents using myRange.selectNodeContents(). A simple example here selects two paragraphs as a range.


<p id="p1">This is sample <em>text</em> go ahead and create a <i>selection</i>
over a portion of this paragraph.</p>
<p id="p2">Another paragraph</p>
<p id="p3">Yet another paragraph.<br/></p>
<p id="p4">Yet another paragraph again.</p>
<p id="m">

[IE]Once you have a range, you can perform a variety of methods upon it, including extractContents(), cloneContents(), and deleteContents(), and even add contents using insertNode(). While the Range API is quite interesting, it is at the time of this edition’s writing only partially implemented in Mozilla. Internet Explorer uses a completely different proprietary method for ranges and selections. </p>

<script type="text/javascript">
<!--
var myRange1;
var myRange2;
var myRange3;
var myDiv;
var p1 = document.getElementById('p1');
if (document.createRange) {
myRange1 = document.createRange();
myRange1.setStartBefore(document.getElementById('p1'));
myRange1.setEndAfter(document.getElementById('p2'));
//alert(myRange1);
myRange2 = document.createRange();
myRange2.selectNodeContents(document.getElementById('p4'));
//alert(myRange2);
myRange3 = document.createRange();
myRange3.selectNodeContents(p1);
myDiv = myRange3.createContextualFragment('<div id="d1">test createContextualFragment of Mozilla</div>');
p1.appendChild(myDiv);
/* Now highlight using Mozilla style selections */
mySelection = window.getSelection();
mySelection.addRange(myRange1);
mySelection.addRange(myRange2);
}
//-->
</script>

prototype javascript library Position example


<div id="d1" style="left: 228px; top: 24px; width: 200px; height: 36px;">
<a href="#" id="a1">a1</a>
<br/>
</div>
<div id="d2">
<a href="#" id="a2">a2</a>
<br/>
</div>
<div id="d3">d3</div>
<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}
var a2 = $('a2');
var d1 = $('d1');
var d2 = $('d2');
var d3 = $('d3');
doc('a2.offsetWidth = ' + a2.offsetWidth);
doc('a2.offsetHeight = ' + a2.offsetHeight);
doc(Position.within(a2, 18, 38));
doc(Position.realOffset(a2).inspect());
doc(Position.cumulativeOffset(a2).inspect());
doc(Position.offsetParent(a2));
doc(Position.overlap('vertical', a2));
doc(Position.page(a2).inspect());
Position.absolutize(a2);
//Position.relativize(a2);
Position.clone(d1, d3);
</script>

prototype javascript library Range example


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write(argument);
document.write("<br />\n");
}

var orf = $R('a', 'g', false);
doc('orf exclusive is false:')
orf.each(function (c) {
doc(c);
});

doc('ort exclusive is true:')
var ort = $R('a', 'g', true);
ort.each(function (c) {
doc(c);
});

doc('orf.include("g") = ' + orf.include('g'));
doc('ort.include("g") = ' + ort.include('g'));
</script>

prototype javascript library Object extend example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br /><br />\n");
}

Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}

var o = {
test: 'test it',
sex: 'man',
info: function () {
return this.test + " and " + this.sex;
},
ivk: function () {
return this.info.apply(this); // invoke this.info function
}
}

for(var p in Object) {
doc('Object["' + p + '"] = ' + Object[p]);
}

doc("=============================================================");

Object.extend(Object, o);

for(var p in Object) {
doc('Object["' + p + '"] = ' + Object[p]);
}

alert(Object.ivk());

</script>

prototype javascript library Number extends example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}

doc((255).toColorPart());
doc((3).succ());
(5).times(function (i) {
doc(i);
})
</script>

prototype javascript library Insertion example


<div id="d1">
<div id="dd1">1</div>
</div>
<div id="d2">2</div>
<div id="d3">3</div>

<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}

new Insertion.Before('d2', '<div id="d2before">Insertion Before d2</div>');
new Insertion.After('d2', '<div id="d2after">Insertion After d2</div>');

new Insertion.Top('d1', '<div id="d1top">Insertion Top d1</div>');
new Insertion.Bottom('d1', '<div id="d1bottom">Insertion Bottom d1</div>');
</script>

prototype javascript library Hash example


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write(argument);
document.write("<br />\n");
}

var pair = ['a', 'aaa'];
pair.key = 'a', pair.value = 'aaa';
doc('pair.inspect() = ' + pair.inspect());
doc('pair.key = ' + pair.key);
doc('pair.value = ' + pair.value);

doc('=====================================================')

var o = {
x: 'xxx',
y: 'yyy',
z: 'zzz'
};
var h1 = Hash(o); // this.constructor => Window
var h2 = new Hash(o); // this.constructor => function (obj) { Object.extend(this, obj || {}); }
doc('h2.constructor = ' + h2.constructor);
doc('h2.constructor == Hash => ' + (h2.constructor == Hash)); // true
doc('h2.inspect() = ' + h2.inspect().escapeHTML());
doc('h2.keys() = ' + h2.keys().inspect());
doc('h2.values() = ' + h2.values().inspect());

var o2 = {
a: 'aaa',
b: 'bbb',
c: 'ccc',
x: 'xyz'
};
h2.merge(o2);
doc('h2.inspect() = ' + h2.inspect().escapeHTML());
doc('h2.size() = ' + h2.size());
doc('h2.x = ' + h2.x);
doc('h2.toQueryString() = ' + h2.toQueryString());
var rm = h2.remove('a', 'b');
doc('h2.remove() = ' + rm.inspect());
doc('h2.inspect() = ' + h2.inspect().escapeHTML());

</script>

prototype javascript library Form observe example


<form action="event_observe_submit" method="post" id="f1" name="form_name" accept-charset="utf-8">
<p><input type="text" id="t1" name="t1" value="Continue">text</p>
<p><input type="text" id="t2" name="t2" value="Continue">text</p>
<p><input type="checkbox" id="c1" name="cb[]" checked>checkbox</p>
<p><input type="checkbox" id="c2" name="cb[]">checkbox</p>
<p><input type="submit" id="s1" name="submit" value="Continue"></p>
</form>
<script type="text/javascript" charset="utf-8">
//new Field.EventObserver('t1', function (args) { alert(args + args.value); });
//new Field.EventObserver('c1', function (args) { alert(args + args.value); });
new Form.EventObserver('f1', function (args) { alert(args + args.value); });
</script>

prototype javascript library Form extend example


<form action="form_submit" id="f1" method="post" accept-charset="utf-8">
<p><input type="text" name="test1" value="test1" id="test1"></p>
<p><input type="text" name="test2" value="test2" id="test2"></p>
<p>
<select id="s1" name="s1">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</p>
<p><input type="submit" value="submit"></p>
</form>
<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}

//Form.disable('f1');
Form.focusFirstElement('f1');
doc($('s1').type);// select-one
</script>

prototype javascript library event observe example


<div id="d1">
<a href="http://www.google.com" id="a1" target="_blank" onclick="testEvent(event); return false;">www.google.com</a>
<a href="http://www.baidu.com" id="a2" target="_blank">www.baidu.com</a>
<a href="http://www.yahoo.com" id="a3" target="_blank" onclick="alert(this); return false;">www.yahoo.com</a>
</div>
<br/>
<script type="text/javascript" charset="utf-8">
function testEvent(event) {
var e = Event.element(event);
alert(Event.findElement(event, 'div').id);
alert(e.id);
//alert(Event.pointerX(event));
//alert(Event.pointerY(event));
}

/*for(var p in Event){
doc('Event["' + p + '"] = ' + Event[p]);
}*/

var handler = function (e) {
alert(e.which);
Event.stop(e); // prevent pop window to www.baidu.com
};

Event.observe('a2', 'click', handler, true);
Event.stopObserving('a2', 'click', handler, true); // cancel observe , click will pop window to www.baidu.com
</script>

prototype javascript library Element extend example


<div id="d1">replace</div>
<div id="d11" class="c1 c2 c3">x</div>
<div id="d10">xx</div>
<div id="d20">y</div>
<div id="d3">test</div>
<form action="index" method="post" id="f1" accept-charset="utf-8" style="background: #ddd; border: #ccc double 1px;">
<input type="text" name="input1" value="origin is enabled" id="input1">element.disable()<br/>
<input type="text" name="input2" value="origin is disabled" id="input2" disabled="true">element.enable()<br/>
<input type="text" name="input3" value="test activate()" id="input3">element.activate()<br/>
<input type="text" name="input4" value="test clear" id="input4">element.clear()<br/>
<input type="text" name="input5" value="test present(id input5)" id="input5">element.present()<br/>
<input type="text" name="input6" value="test serialize()" id="input6">element.serialize()<br/>
<input type="text" name="input7" value="test focus()" id="input7">element.focus()<br/>
<input type="text" name="input8" value="test select()" id="input8">element.select()<br/>
<input type="submit" value="Continue →"><br/>
</form>
<div id="d4">test Element scrollTo()</div>
<div id="d5">test element scrollTo()</div>
<div id="image">
<%= image_tag 'rails' %>
</div>
<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}
$('input1').disable();
$('input2').enable();
//$('input3').activate();
$('input4').clear();
doc('$("input5").present() = ' + $('input5').present());
doc('$("input6").serialize() is: ' + $('input6').serialize());
//$('input7').focus();
$('input8').select();

doc('form action is: ' + $('f1').readAttribute('action'));
doc('style of form: ' + $('f1').readAttribute('style'));
doc('getStyle background of form: ' + $('f1').getStyle('background'));

var cn = new Element.ClassNames('d11');
cn.add('c4');
cn.remove('c2');

Element.update('d10', 'test<strong> Element.update(element, "HTML") </strong>');
$('d20').update('test<strong> element.update("HTML") </strong>');

Element.replace('d1', '<div id="d2"><span>replaced div</span></div>');
doc(Element.inspect('d2'));
doc(Element.ancestors('d2').inspect().escapeHTML());
doc(Element.descendants('d2').inspect().escapeHTML());
doc(Element.previousSiblings('d3').inspect().escapeHTML());
doc(Element.nextSiblings('d3').inspect().escapeHTML());

Element.setOpacity('image', 0.6);
doc($('image').getOpacity());

$H(Element.Methods).each (function (m) {
doc(m);
});

doc($H(Element.getDimensions('d4')).inspect().escapeHTML());
// Element.scrollTo('d4');
$('f1').scrollTo();
doc("$('d5').empty() is: " + $('d5').empty());

var timer1 = setTimeout(function () {
$('d5').replace('<div id="d5">replace timer1</div>');
}, 5000);
var timer2 = setTimeout(function () {
$('d5').replace('<div id="d5">timeout d5</div>');
}, 15000);

$('f1').request({onComplete: function (xhr) {
alert(xhr.responseText);
}});
</script>

prototype javascript library Element event observe example


<a href="http://www.baidu.com" id="a1"> baidu </a>
<script type="text/javascript" charset="utf-8">
/*Event.observe('a1', 'click', function (o) {
alert(o.eventPhase + o.type);
//Event.stop(o);
}, false);

Event.observe('a1', 'click', function (o) {
alert(o.eventPhase);
Event.stop(o);
}, true);*/

/*Object.extend(Element.prototype, {
click: function (callback) {
this.onclick = callback;
},
mouseout: function (callback) {
this.onmouseout = function (evt) {
alert(evt.eventPhase);
callback.apply(this, $A(arguments));
}
}
});*/

var evts = ("blur,focus,load,resize,scroll,unload,click,dblclick," +
"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
"submit,keydown,keypress,keyup,error
").split(",");
evts.each(function (e) {
Element.prototype[e] = function (handler) {
this['on' + e] = handler;
}
});
var a1 = $('a1');
a1.click(function (e) {
alert(e.type);
Event.stop(e);
});
a1.click(function (e) {
alert(e.eventPhase);
Event.stop(e);
}); // will override before a1.click handler
a1.mouseout(function (e) {
alert(e.type);
});
</script>

event observe o.eventPhase #=> 2
Event.stop will prevent event performed, browser will not go to baidu.com

JavaScript Dom 修正


<script language="JavaScript" type="Text/JavaScript">
<!--
if(window.Event){// 修正Event的DOM
/*
IE5 MacIE5 Mozilla Konqueror2.2 Opera5
event yes yes yes yes yes
event.returnValue yes yes no no no
event.cancelBubble yes yes no no no
event.srcElement yes yes no no no
event.fromElement yes yes no no no
*/
Event.prototype.__defineSetter__("returnValue",function(b){//
if(!b)this.preventDefault();
return b;
});
Event.prototype.__defineSetter__("cancelBubble",function(b){// 设置或者检索当前事件句柄的层次冒泡
if(b)this.stopPropagation();
return b;
});
Event.prototype.__defineGetter__("srcElement",function(){
var node=this.target;
while(node.nodeType!=1)node=node.parentNode;
return node;
});
Event.prototype.__defineGetter__("fromElement",function(){// 返回鼠标移出的源节点
var node;
if(this.type=="mouseover")
node=this.relatedTarget;
else if(this.type=="mouseout")
node=this.target;
if(!node)return;
while(node.nodeType!=1)node=node.parentNode;
return node;
});
Event.prototype.__defineGetter__("toElement",function(){// 返回鼠标移入的源节点
var node;
if(this.type=="mouseout")
node=this.relatedTarget;
else if(this.type=="mouseover")
node=this.target;
if(!node)return;
while(node.nodeType!=1)node=node.parentNode;
return node;
});
Event.prototype.__defineGetter__("offsetX",function(){
return this.layerX;
});
Event.prototype.__defineGetter__("offsetY",function(){
return this.layerY;
});
}
if(window.Document){// 修正Document的DOM
/*
IE5 MacIE5 Mozilla Konqueror2.2 Opera5
document.documentElement yes yes yes yes no
document.activeElement yes null no no no

*/
}
if(window.Node){// 修正Node的DOM
/*
IE5 MacIE5 Mozilla Konqueror2.2 Opera5
Node.contains yes yes no no yes
Node.replaceNode yes no no no no
Node.removeNode yes no no no no
Node.children yes yes no no no
Node.hasChildNodes yes yes yes yes no
Node.childNodes yes yes yes yes no
Node.swapNode yes no no no no
Node.currentStyle yes yes no no no

*/
Node.prototype.replaceNode=function(Node){// 替换指定节点
this.parentNode.replaceChild(Node,this);
}
Node.prototype.removeNode=function(removeChildren){// 删除指定节点
if(removeChildren)
return this.parentNode.removeChild(this);
else{
var range=document.createRange();
range.selectNodeContents(this);
return this.parentNode.replaceChild(range.extractContents(),this);
}
}
Node.prototype.swapNode=function(Node){// 交换节点
var nextSibling=this.nextSibling;
var parentNode=this.parentNode;
node.parentNode.replaceChild(this,Node);
parentNode.insertBefore(node,nextSibling);
}
}
if(window.HTMLElement){
HTMLElement.prototype.__defineGetter__("all",function(){
var a=this.getElementsByTagName("*");
var node=this;
a.tags=function(sTagName){
return node.getElementsByTagName(sTagName);
}
return a;
});
HTMLElement.prototype.__defineGetter__("parentElement",function(){
if(this.parentNode==this.ownerDocument)return null;
return this.parentNode;
});
HTMLElement.prototype.__defineGetter__("children",function(){
var tmp=[];
var j=0;
var n;
for(var i=0;i<this.childNodes.length;i++){
n=this.childNodes[i];
if(n.nodeType==1){
tmp[j++]=n;
if(n.name){
if(!tmp[n.name])
tmp[n.name]=[];
tmp[n.name][tmp[n.name].length]=n;
}
if(n.id)
tmp[n.id]=n;
}
}
return tmp;
});
HTMLElement.prototype.__defineGetter__("currentStyle", function(){
return this.ownerDocument.defaultView.getComputedStyle(this,null);
});
HTMLElement.prototype.__defineSetter__("outerHTML",function(sHTML){
var r=this.ownerDocument.createRange();
r.setStartBefore(this);
var df=r.createContextualFragment(sHTML);
this.parentNode.replaceChild(df,this);
return sHTML;
});
HTMLElement.prototype.__defineGetter__("outerHTML",function(){
var attr;
var attrs=this.attributes;
var str="<"+this.tagName;
for(var i=0;i
attr=attrs[i];
if(attr.specified)
str+=" "+attr.name+'="'+attr.value+'"';
}
if(!this.canHaveChildren)
return str+">";
return str+">"+this.innerHTML+"";
});
HTMLElement.prototype.__defineGetter__("canHaveChildren",function(){
switch(this.tagName.toLowerCase()){
case "area":
case "base":
case "basefont":
case "col":
case "frame":
case "hr":
case "img":
case "br":
case "input":
case "isindex":
case "link":
case "meta":
case "param":
return false;
}
return true;
});

HTMLElement.prototype.__defineSetter__("innerText",function(sText){
var parsedText=document.createTextNode(sText);
this.innerHTML=parsedText;
return parsedText;
});
HTMLElement.prototype.__defineGetter__("innerText",function(){
var r=this.ownerDocument.createRange();
r.selectNodeContents(this);
return r.toString();
});
HTMLElement.prototype.__defineSetter__("outerText",function(sText){
var parsedText=document.createTextNode(sText);
this.outerHTML=parsedText;
return parsedText;
});
HTMLElement.prototype.__defineGetter__("outerText",function(){
var r=this.ownerDocument.createRange();
r.selectNodeContents(this);
return r.toString();
});
HTMLElement.prototype.attachEvent=function(sType,fHandler){
var shortTypeName=sType.replace(/on/,"");
fHandler._ieEmuEventHandler=function(e){
window.event=e;
return fHandler();
}
this.addEventListener(shortTypeName,fHandler._ieEmuEventHandler,false);
}
HTMLElement.prototype.detachEvent=function(sType,fHandler){
var shortTypeName=sType.replace(/on/,"");
if(typeof(fHandler._ieEmuEventHandler)=="function")
this.removeEventListener(shortTypeName,fHandler._ieEmuEventHandler,false);
else
this.removeEventListener(shortTypeName,fHandler,true);
}
HTMLElement.prototype.contains=function(Node){// 是否包含某节点
do if(Node==this)return true;
while(Node=Node.parentNode);
return false;
}
HTMLElement.prototype.insertAdjacentElement=function(where,parsedNode){
switch(where){
case "beforeBegin":
this.parentNode.insertBefore(parsedNode,this);
break;
case "afterBegin":
this.insertBefore(parsedNode,this.firstChild);
break;
case "beforeEnd":
this.appendChild(parsedNode);
break;
case "afterEnd":
if(this.nextSibling)
this.parentNode.insertBefore(parsedNode,this.nextSibling);
else
this.parentNode.appendChild(parsedNode);
break;
}
}
HTMLElement.prototype.insertAdjacentHTML=function(where,htmlStr){
var r=this.ownerDocument.createRange();
r.setStartBefore(this);
var parsedHTML=r.createContextualFragment(htmlStr);
this.insertAdjacentElement(where,parsedHTML);
}
HTMLElement.prototype.insertAdjacentText=function(where,txtStr){
var parsedText=document.createTextNode(txtStr);
this.insertAdjacentElement(where,parsedText);
}
HTMLElement.prototype.attachEvent=function(sType,fHandler){
var shortTypeName=sType.replace(/on/,"");
fHandler._ieEmuEventHandler=function(e){
window.event=e;
return fHandler();
}
this.addEventListener(shortTypeName,fHandler._ieEmuEventHandler,false);
}
HTMLElement.prototype.detachEvent=function(sType,fHandler){
var shortTypeName=sType.replace(/on/,"");
if(typeof(fHandler._ieEmuEventHandler)=="function")
this.removeEventListener(shortTypeName,fHandler._ieEmuEventHandler,false);
else
this.removeEventListener(shortTypeName,fHandler,true);
}
}
//-->
</script>

此程序由某文章回帖处转过来的,未知原作者。

prototype javascript library Class example


<script type="text/javascript" charset="utf-8">
function doc (argument) {
document.write(argument);
document.write("<br />\n");
}
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}

var MyClass = Class.create();
MyClass.prototype = {
initialize: function (msg) {
this.msg = msg;
return msg;
},

showMsg: function () {
doc(this.msg);
}
}

var c = new MyClass('test'); // Class.create('test')
c.showMsg();

var o = {
name: 'test it',
sex: 'man',
info: function () {
return this.name + " and " + this.sex;
},
ivk: function () {
return this.info.apply(this); // invoke this.info function
}
}

doc(o.info());
doc(o.ivk());

/*function TestThis () {
doc(this); // object Window
this.name = 'name test';
this.sex = 'name man';
}
var t = TestThis();
doc(name);
doc(self.name);
doc(this.sex);
for (var p in this) {
doc(this['p']);
}*/
</script>

The Global object holds the global properties and methods listed. These properties and methods do not need to be referenced or invoked through any other object. Any variables and functions you define in your own top-level code become properties of the Global object. The Global object has no name, but you can refer to it in top-level code (i.e. outside of methods) with the this keyword. In client-side JavaScript, the Window object serves as the Global object. It has quite a few additional properties and methods, and can be referred to as window.

prototype javascript library Enumerable.each example


<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write(argument);
document.write("<br />\n");
}
var Enumerable = {
each: function(iterator) {
var index = 0;
try {
this._each(function(value) {
alert(iterator); // then alert function(i){doc(i);} every time
iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
return this;
}
};
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0, length = this.length; i < length; i++){
alert(iterator); // first alert function(value) {alert(iterator); iterater(value, index++);} every time
iterator(this[i]); // through here revoke follow alert
}
}
});
Object.extend(Array.prototype, Enumerable);

var a = [1, 2, 3, 4];
a.each(function (i) {
doc(i);
});
/*
var t = a.all(function (i) {
return i.constructor == Number;
})
doc('all() = ' + t); // true
var f = a.all(function (i) {
return i % 2 == 0;
})
doc('all() = ' + f); // false

var y = a.any(function (i) {
return i % 2 == 0;
})
doc('any() = ' + y); // true

var m = a.collect(function (i) {
return i * 10;
}); // Array.map
doc('inspect() = ' + m.inspect());

var fa = a.findAll(function (i){
return i % 2 == 0;
});
doc('findAll() = ' + fa.inspect());

var str = ['test1', 'test2', 'test3', 'text1', 'text2', 'text3'];
var sg = str.grep(/test/i);
doc('grep() = ' + sg.inspect());

var inc = str.include('test1');
doc('include() = ' + inc);

var sum = a.inject(0, function (s, i) {
return s + i;
});
doc('sum = ' + sum);
doc('max = ' + a.max());
doc('min = ' + a.min());
doc('first = ' + a.first());
doc('last = ' + a.last());

a = a.concat(2, 4);
doc('a = ' + a.inspect());
doc('uniq() = ' + a.uniq().inspect());*/
</script>

prototype javascript library ajax example


<div id="ajax_div">
use ajax to update it!
</div>
<br/>
<div id="ajax_failure">
if evalScript set false, sayHi is not defined!
</div>

<input type="button" name="button_ajax" value="ajax update div" id="button_ajax" />

<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<p>\n");
document.write(argument);
document.write("</p>\n");
}
var url = '/prototype/ajax_eval_script';
var options = {
method: 'get',
evalScripts: true,
parameters: 'id=1',
insertion: Insertion.Top
}

//new Ajax.Updater('ajax_div', url, options);
//new Ajax.Request(url, {onComplete: function (req) { alert(req.responseText); }});
var ajax = new Ajax.Request();
doc('ajax.transport type is ' + ajax.transport); //ajax.transport = Ajax.getTransport();
new Ajax.Updater({success: 'ajax_div', failure: 'ajax_failure'}, url, options);

ajax.setOptions(Object.extend(options, {onComplete: function(req) {
$('ajax_div').innerHTML = req + "<br/>\n" +
"req == ajax.transport is " + (req == ajax.transport) + "<br/>\n" +
"Server is " + req.getResponseHeader('Server') + "<br/>\n" +
"ajax request status is " + ajax.transport.status + "<br/>\n";
}
}));
$('button_ajax').onclick = function (event) { ajax.request('/prototype/ajax_eval_script'); };
</script>

/prototype/ajax_eval_script

<script language="javascript" type="text/javascript">
//function sayHi(){ // do nothing, function is not generated in runtime
//var sayHi = function(){ // not use the "var" keyword
sayHi = function(){
alert('Hi');
}
</script>

<input type="button" value="Click Me" onclick="sayHi()"/>
Note that in the previous example we did not use the var keyword to declare the variable. Doing so would have created a function object that would be local to the script block (at least in IE and FireFox). Without the var keyword the function object is scoped to the window, which is our intent.

prototype javascript library Selector example


<ul id="fruits">
<li id="apples">
<h3 title="yummy!" id="hid">Apples</h3>
<ul id="list-of-apples">
<li id="golden-delicious" title="yummy!" >Golden Delicious</li>
<li id="mutsu" title="yummy!">Mutsu</li>
<li id="mcintosh">McIntosh</li>
<li id="ida-red">Ida Red</li>
</ul>
<p id="saying">An apple a day keeps the doctor away.</p>
</li>
</ul>
<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<br>\n");
document.write(argument);
document.write("</br>\n");
}

$$('p', 'h3').each(function (i) {
doc(i.tagName.toLowerCase() + ':' + i.id);
});
doc('======================================================================');
// $$(exps) == document.getElementsBySelector(exps) == Selector.findChildElements(document, $A(exps))
Selector.findChildElements(document, ['p', 'h3']).each(function (i) {
doc(i.tagName.toLowerCase() + ':' + i.id);
});
doc('======================================================================');
doc(Selector.matchElements($('apples', 'saying'), 'p').length);
Selector.matchElements($('apples', 'saying'), 'p').each(function (i) {
doc(i.tagName.toLowerCase() + ':' + i.id);
});
doc(Selector.findElement($('apples', 'golden-delicious', 'mutsu', 'mcintosh', 'ida-red'), 'li', 1).id);
doc('======================================================================');
doc($('apples').match('li'));
doc($('apples').match('p'));
var s = new Selector('p');
doc(s.match($('saying')));
doc('======================================================================');
var l = new Selector('li p');
l.findElements($('fruits')).each(function (i) {
doc(i.tagName.toLowerCase() + ':' + i.id);
});
var l = new Selector('ul li');
l.findElements($('fruits')).each(function (i) {
doc(i.tagName.toLowerCase() + ':' + i.id);
});
doc('======================================================================');
$('apples').getElementsBySelector('[title="yummy!"]').each(function (y) {
doc(y.tagName.toLowerCase());
});
doc('======================================================================');
$('apples').getElementsBySelector( 'p#saying', 'li[title="yummy!"]').each(function (c) {
doc(c.tagName.toLowerCase());
});
doc('======================================================================');
doc($('apples').getElementsBySelector('[title="disgusting!"]').length);
doc('======================================================================');
doc($('apples').getElementsBySelector('[id^="m"]').length);
$('apples').getElementsBySelector('[id^="m"]').each(function (i) {
doc(i.tagName.toLowerCase() + ':' + i.id);
});

</script>

prototype javascript library Selector.handlers example


<ul id="fruits">
<li id="apples">
<h3 title="yummy!" id="hid">Apples</h3>
<ul id="list-of-apples">
<li id="golden-delicious" title="yummy!" >Golden Delicious</li>
<li id="mutsu" title="yummy!">Mutsu</li>
<li id="mcintosh">McIntosh</li>
<li id="ida-red">Ida Red</li>
</ul>
<p id="saying">An apple a day keeps the doctor away.</p>
</li>
</ul>
<form action="index" method="post" id="f1" accept-charset="utf-8" style="background: #ddd; border: #ccc double 1px;">
<input type="text" name="input1" value="origin is enabled" id="input1"><br/>
<input type="text" name="input2" value="origin is disabled" id="input2" disabled="true"><br/>
<input type="text" name="other3" value="origin is disabled" id="other3" disabled=""><br/>
<input type="submit" value="Continue →" id="submit" name="submit"><br/>
</form>
<script type="text/javascript" charset="utf-8">
function doc(argument) {
document.write("<br/>\n");
document.write(argument);
document.write("<br/>\n");
}

var s1 = Selector.matchElements($('apples', 'golden-delicious', 'mutsu', 'mcintosh', 'ida-red'), 'li');
var s2 = $('apples').getElementsBySelector( 'p#saying', 'li[title="yummy!"]' );
var sh = Selector.handlers;
var l = new Selector('ul li');
var f = l.findElements($('fruits'));
sh.mark(f).each(function (s) {
doc(s.id + ' counted? ' + s._counted);
});
sh.unmark(f).each(function (s) {
doc(s.id + ' counted? ' + s._counted);
});
doc('=============================================');
s1.each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('=============================================');
s2.each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('concat=============================================');
sh.concat(s1, s2).each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('unique=============================================');
sh.unique(sh.concat(s1, s2)).each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('array.uniq()=============================================');
sh.concat(s1, s2).uniq().each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('descendant=============================================');
sh.descendant(sh.unique(sh.concat(s1, s2))).each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('child=============================================');
sh.child(sh.concat(s1, s2)).each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('adjacent=============================================');
sh.adjacent(f).each(function (s) {
doc(s.tagName.toLowerCase() + ".id = " + s.id);
});
doc('=============================================');
var inputs = $$('form/input[name*="input"]');
inputs.each(function (i) {
doc(i.id);
});

</script>

Friday, August 03, 2007

prototype javascript library Function extends example


<script type="text/javascript" src="prototype.js" charset="utf-8"></script>

<input type="checkbox" id="myChk" value="1"/> Test Function.prototype.bindAsEventListener

<input type="button" id="myBut1" value="bind element test" onclick="doc.bind(this)('arg1', 'arg2');"/> Test Function.prototype.bind

<input type="button" id="myBut2" value="bind window test" onclick="doc.bind(self)('arg1');"/> Test Function.prototype.bind

<script type="text/javascript" charset="utf-8">
function doc(){
// this 根据调用它的对象不同而不同,可以是element对象, 也可以是当前window对象
alert([this].concat($A(arguments)).inspect());
}

//declaring the class
var CheckboxWatcher = Class.create();
//defining the rest of the class implementation
CheckboxWatcher.prototype = {
initialize: function(chkBox, message) {
this.chkBox = $(chkBox);
this.message = message;
//this.chkBox.onclick
// = this.showMessage.bindAsEventListener(this, ' other extraInfo')
// => function(event) { return __method.apply(object, [event || window.event].concat(args));}

//将showMessage方法做为this object的方法来调用并返回showMessage方法的结果
//既然是将showMessage做为this object的方法来调用,那showMessage中的this是指向当前调用它的object(即为CheckboxWatcher的实例对象,如watcher)。
//this.chkBox.onclick = this.showMessage.apply(this, ['none event', ' other extraInfo']);
//assigning our method to the event
this.chkBox.onclick = this.showMessage.bindAsEventListener(this, ' other extraInfo');
},

showMessage: function(evt, extraInfo) {
//this是指向watcher这个实例对象的
//showMessage这个方法一般是不会从外部调用的
alert(this.message + ' (' + evt + ')' + extraInfo);
},

bindExample: function() {
alert(this.message + "\n" + $A(arguments).inspect);
}
};

var watcher = new CheckboxWatcher('myChk', 'Changed');
</script>