分类:
2006-06-29 13:39:18
| /** | |
| 2 | |
| 3 | * 定义一个全局对象, 属性 Version 在发布的时候会替换为当前版本号 |
| 4 | |
| 5 | */ |
| 6 | |
| 7 | var Prototype = { |
| 8 | |
| 9 | Version: '@@VERSION@@' |
| 10 | |
| 11 | } |
| 12 | |
| 13 | |
| 14 | /** |
| 15 | |
| 16 | * 创建一种类型,注意其属性 create 是一个方法,返回一个构造函数。 |
| 17 | |
| 18 | * 一般使用如下 |
| 19 | |
| 20 | * var X = Class.create(); 返回一个类型,类似于 java 的一个 |
| 21 | |
| 22 | * Class实例。 |
| 23 | |
| 24 | * 要使用 X 类型,需继续用 new X()来获取一个实例,如同 java 的 |
| 25 | |
| 26 | * Class.newInstance()方法。 |
| 27 | |
| 28 | * |
| 29 | |
| 30 | * 返回的构造函数会执行名为 initialize 的方法, initialize 是 |
| 31 | |
| 32 | * Ruby 对象的构造器方法名字。 |
| 33 | |
| 34 | * 此时initialize方法还没有定义,其后的代码中创建新类型时会建立 |
| 35 | |
| 36 | * 相应的同名方法。 |
| 37 | |
| 38 | * |
| 39 | |
| 40 | * 如果一定要从java上去理解。你可以理解为用Class.create()创建一个 |
| 41 | |
| 42 | * 继承java.lang.Class类的类。 |
| 43 | |
| 44 | * 当然java不允许这样做,因为Class类是final的 |
| 45 | |
| 46 | * |
| 47 | |
| 48 | */ |
| 49 | |
| 50 | var Class = { |
| 51 | |
| 52 | create: function() { |
| 53 | |
| 54 | return function() { |
| 55 | |
| 56 | this.initialize.apply(this, arguments); |
| 57 | |
| 58 | } |
| 59 | |
| 60 | } |
| 61 | |
| 62 | } |
| 63 | |
| 64 | |
| 65 | /** |
| 66 | |
| 67 | * 创建一个对象,从变量名来思考,本意也许是定义一个抽象类,以后创建 |
| 68 | |
| 69 | * 新对象都 extend 它。 |
| 70 | |
| 71 | * 但从其后代码的应用来看, Abstract 更多是为了保持命名空间清晰的考虑。 |
| 72 | |
| 73 | * 也就是说,我们可以给 Abstract 这个对象实例添加新的对象定义。 |
| 74 | |
| 75 | * |
| 76 | |
| 77 | * 从java去理解,就是动态给一个对象创建内部类。 |
| 78 | |
| 79 | */ |
| 80 | |
| 81 | var Abstract = new Object(); |
| 82 | |
| 83 | |
| 84 | /** |
| 85 | |
| 86 | * 获取参数对象的所有属性和方法,有点象多重继承。但是这种继承是动态获得的。 |
| 87 | |
| 88 | * 如: |
| 89 | |
| 90 | * var a = new ObjectA(), b = new ObjectB(); |
| 91 | |
| 92 | * var c = a.extend(b); |
| 93 | |
| 94 | * 此时 c 对象同时拥有 a 和 b 对象的属性和方法。但是与多重继承不同的是, |
| 95 | |
| 96 | * c instanceof ObjectB 将返回false。 |
| 97 | |
| 98 | */ |
| 99 | |
| 100 | Object.prototype.extend = function(object) { |
| 101 | |
| 102 | for (property in object) { |
| 103 | |
| 104 | this[property] = object[property]; |
| 105 | |
| 106 | } |
| 107 | |
| 108 | return this; |
| 109 | |
| 110 | } |
| 111 | |
| 112 | |
| 113 | /** |
| 114 | |
| 115 | * 这个方法很有趣,它封装一个javascript函数对象,返回一个新函数对象,新函 |
| 116 | |
| 117 | * 数对象的主体和原对象相同,但是bind()方法参数将被用作当前对象的对象。 |
| 118 | |
| 119 | * 也就是说新函数中的 this 引用被改变为参数提供的对象。 |
| 120 | |
| 121 | * 比如: |
| 122 | |
| 123 | * |
| 124 | |
| 125 | * |
| 126 | |
| 127 | * ................. |
| 128 | |
| 129 | * |
| 140 | |
| 141 | * 那么,调用aaa.showValue 将返回"aaa", |
| 142 | |
| 143 | * 但调用aaa.showValue2 将返回"bbb"。 |
| 144 | |
| 145 | * |
| 146 | |
| 147 | * apply 是ie5.5后才出现的新方法(Netscape好像很早就支持了)。 |
| 148 | |
| 149 | * 该方法更多的资料参考MSDN |
| 150 | |
| 151 | * |
| 152 | |
| 153 | * 还有一个 call 方法,应用起来和 apply 类似。可以一起研究下。 |
| 154 | |
| 155 | */ |
| 156 | |
| 157 | Function.prototype.bind = function(object) { |
| 158 | |
| 159 | var method = this; |
| 160 | |
| 161 | return function() { |
| 162 | |
| 163 | method.apply(object, arguments); |
| 164 | |
| 165 | } |
| 166 | |
| 167 | } |
| 168 | |
| 169 | |
| 170 | /** |
| 171 | |
| 172 | * 和bind一样,不过这个方法一般用做html控件对象的事件处理。所以要传递event对象 |
| 173 | |
| 174 | * 注意这时候,用到了 Function.call。它与 Function.apply 的不同好像仅仅是对参 |
| 175 | |
| 176 | * 数形式的定义。如同 java 两个过载的方法。 |
| 177 | |
| 178 | */ |
| 179 | |
| 180 | Function.prototype.bindAsEventListener = function(object) { |
| 181 | |
| 182 | var method = this; |
| 183 | |
| 184 | return function(event) { |
| 185 | |
| 186 | method.call(object, event || window.event); |
| 187 | |
| 188 | } |
| 189 | |
| 190 | } |
| 191 | |
| 192 | |
| 193 | /** |
| 194 | |
| 195 | * 将整数形式RGB颜色值转换为HEX形式 |
| 196 | |
| 197 | */ |
| 198 | |
| 199 | Number.prototype.toColorPart = function() { |
| 200 | |
| 201 | var digits = this.toString(16); |
| 202 | |
| 203 | if (this < 16) return '0' + digits; |
| 204 | |
| 205 | return digits; |
| 206 | |
| 207 | } |
| 208 | |
| 209 | |
| 210 | /** |
| 211 | |
| 212 | * 典型 Ruby 风格的函数,将参数中的方法逐个调用,返回第一个成功执行的方法的返回值 |
| 213 | |
| 214 | */ |
| 215 | |
| 216 | var Try = { |
| 217 | |
| 218 | these: function() { |
| 219 | |
| 220 | var returnValue; |
| 221 | |
| 222 | |
| 223 | for (var i = 0; i < arguments.length; i++) { |
| 224 | |
| 225 | var lambda = arguments[i]; |
| 226 | |
| 227 | try { |
| 228 | |
| 229 | returnValue = lambda(); |
| 230 | |
| 231 | break; |
| 232 | |
| 233 | } catch (e) {} |
| 234 | |
| 235 | } |
| 236 | |
| 237 | |
| 238 | return returnValue; |
| 239 | |
| 240 | } |
| 241 | |
| 242 | } |
| 243 | |
| 244 | |
| 245 | /*--------------------------------------------------------------------------*/ |
| 246 | |
| 247 | |
| 248 | /** |
| 249 | |
| 250 | * 一个设计精巧的定时执行器 |
| 251 | |
| 252 | * 首先由 Class.create() 创建一个 PeriodicalExecuter 类型, |
| 253 | |
| 254 | * 然后用对象直接量的语法形式设置原型。 |
| 255 | |
| 256 | * |
| 257 | |
| 258 | * 需要特别说明的是 rgisterCallback 方法,它调用上面定义的函数原型方法bind, |
| 259 | |
| 260 | * 并传递自己为参数。 |
| 261 | |
| 262 | * 之所以这样做,是因为 setTimeout 默认总以 window 对象为当前对象,也就是说, |
| 263 | |
| 264 | * 如果 registerCallback 方法定义如下的话: |
| 265 | |
| 266 | * registerCallback: function() { |
| 267 | |
| 268 | * setTimeout(this.onTimerEvent, this.frequency * 1000); |
| 269 | |
| 270 | * } |
| 271 | |
| 272 | * 那么,this.onTimeoutEvent 方法执行失败,因为它无法 |
| 273 | |
| 274 | * 访问 this.currentlyExecuting 属性。 |
| 275 | |
| 276 | * 而使用了bind以后,该方法才能正确的找到this, |
| 277 | |
| 278 | * 也就是PeriodicalExecuter的当前实例。 |
| 279 | |
| 280 | */ |
| 281 | |
| 282 | var PeriodicalExecuter = Class.create(); |
| 283 | |
| 284 | PeriodicalExecuter.prototype = { |
| 285 | |
| 286 | initialize: function(callback, frequency) { |
| 287 | |
| 288 | this.callback = callback; |
| 289 | |
| 290 | this.frequency = frequency; |
| 291 | |
| 292 | this.currentlyExecuting = false; |
| 293 | |
| 294 | |
| 295 | this.registerCallback(); |
| 296 | |
| 297 | }, |
| 298 | |
| 299 | |
| 300 | registerCallback: function() { |
| 301 | |
| 302 | setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000); |
| 303 | |
| 304 | }, |
| 305 | |
| 306 | |
| 307 | onTimerEvent: function() { |
| 308 | |
| 309 | if (!this.currentlyExecuting) { |
| 310 | |
| 311 | try { |
| 312 | |
| 313 | this.currentlyExecuting = true; |
| 314 | |
| 315 | this.callback(); |
| 316 | |
| 317 | } finally { |
| 318 | |
| 319 | this.currentlyExecuting = false; |
| 320 | |
| 321 | } |
| 322 | |
| 323 | } |
| 324 | |
| 325 | |
| 326 | this.registerCallback(); |
| 327 | |
| 328 | } |
| 329 | |
| 330 | } |
| 331 | |
| 332 | |
| 333 | /*--------------------------------------------------------------------------*/ |
| 334 | |
| 335 | |
| 336 | /** |
| 337 | |
| 338 | * 这个函数就 Ruby 了。我觉得它的作用主要有两个 |
| 339 | |
| 340 | * 1. 大概是 document.getElementById(id) 的最简化调用。 |
| 341 | |
| 342 | * 比如:$("aaa") 将返回上 aaa 对象 |
| 343 | |
| 344 | * 2. 得到对象数组 |
| 345 | |
| 346 | * 比如: $("aaa","bbb") 返回一个包括id为 |
| 347 | |
| 348 | * "aaa"和"bbb"两个input控件对象的数组。 |
| 349 | |
| 350 | */ |
| 351 | |
| 352 | function $() { |
| 353 | |
| 354 | var elements = new Array(); |
| 355 | |
| 356 | |
| 357 | for (var i = 0; i < arguments.length; i++) { |
| 358 | |
| 359 | var element = arguments[i]; |
| 360 | |
| 361 | if (typeof element == 'string') |
| 362 | |
| 363 | element = document.getElementById(element); |
| 364 | |
| 365 | |
| 366 | if (arguments.length == 1) |
| 367 | |
| 368 | return element; |
| 369 | |
| 370 | |
| 371 | elements.push(element); |
| 372 | |
| 373 | } |
| 374 | |
| 375 | |
| 376 | return elements; |
| 377 | |
| 378 | } |
| 379 |