我思故我强

prototype学习资料(二)

prototype学习资料(二)

js 代码
  1. /**   
  2. * 如果调用者在传入的options参数中定义 evalScripts=true,同时xmlhttp返回值的html中包含<script>标签的话,执行该脚本   
  3. */     
  4. if  ( this .options.evalScripts && scripts) {    
  5. /**   
  6. * 注意前二十行左右还有一个 match 的声明   
  7. * var match = new RegExp(Ajax.Updater.ScriptFragment, 'img');   
  8. * 和此处的区别就是,正则表达式匹配标记多一个 "g"。   
  9. * 多个g, 所以 scripts 是一个数组,数组中每个元素是一段 <script>...</script> 文本。   
  10. * 没有g, scripts.match(match)[1] 匹配的就是 <script>标记中的 script 代码。   
  11. * 关于正则表达式,请参考javascript的相关资料。   
  12. */     
  13. match =  new  RegExp(Ajax.Updater.ScriptFragment, 'im');    
  14. setTimeout(( function () {    
  15. for  ( var  i = 0; i < scripts.length; i++)    
  16. eval(scripts.match(match)[1]);    
  17. }).bind( this ), 10);    
  18. }    
  19. }    
  20. });    
  21. /**   
  22. * 定期更新器   
  23. */     
  24. Ajax.PeriodicalUpdater = Class.create();    
  25. Ajax.PeriodicalUpdater.prototype = ( new  Ajax.Base()).extend({    
  26. initialize:  function (container, url, options) {    
  27. this .setOptions(options);    
  28. this .onComplete =  this .options.onComplete;    
  29. this .frequency = ( this .options.frequency || 2);    
  30. // decay 可能是一个时间调整因素    
  31. this .decay = 1;    
  32. this .updater = {};    
  33. this .container = container;    
  34. this .url = url;    
  35. this .start();    
  36. },    
  37. start:  function () {    
  38. this .options.onComplete =  this .updateComplete.bind( this );    
  39. this .onTimerEvent();    
  40. },    
  41. stop:  function () {    
  42. this .updater.onComplete = undefined;    
  43. clearTimeout( this .timer);    
  44. ( this .onComplete || Ajax.emptyFunction).apply( this , arguments);    
  45. },    
  46. updateComplete:  function (request) {    
  47. if  ( this .options.decay) {    
  48. this .decay = (request.responseText ==  this .lastText ?    
  49. this .decay *  this .options.decay : 1);    
  50. this .lastText = request.responseText;    
  51. }    
  52. this .timer = setTimeout( this .onTimerEvent.bind( this ),    
  53. this .decay *  this .frequency * 1000);    
  54. },    
  55. onTimerEvent:  function () {    
  56. this .updater =  new  Ajax.Updater( this .container,  this .url,  this .options);    
  57. }    
  58. });    
  59. /**   
  60. * 根据 class attribute 的名字得到对象数组,支持 multiple class   
  61.  
  62. */     
  63. document.getElementsByClassName =  function (className) {    
  64. var  children = document.getElementsByTagName('*') || document.all;    
  65. var  elements =  new  Array();    
  66. for  ( var  i = 0; i < children.length; i++) {    
  67. var  child = children;    
  68. var  classNames = child.className.split(' ');    
  69. for  ( var  j = 0; j < classNames.length; j++) {    
  70. if  (classNames[j] == className) {    
  71. elements.push(child);    
  72. break ;    
  73. }    
  74. }    
  75. }    
  76. return  elements;    
  77. }    
  78. /*--------------------------------------------------------------------------*/     
  79. /**   
  80. * Element 就象一个 java 的工具类,主要用来 隐藏/显示/销除 对象,以及获取对象的简单属性。   
  81.  
  82. */     
  83. if  (!window.Element) {    
  84. var  Element =  new  Object();    
  85. }    
  86. Object.extend(Element, {    
  87. /**   
  88. * 切换 显示/隐藏   
  89. */     
  90. toggle:  function () {    
  91. for  ( var  i = 0; i < arguments.length; i++) {    
  92. var  element = $(arguments);    
  93. element.style.display =    
  94. (element.style.display == 'none' ?  ''  : 'none');    
  95. }    
  96. },    
  97. hide:  function () {    
  98. for  ( var  i = 0; i < arguments.length; i++) {    
  99. var  element = $(arguments);    
  100. element.style.display = 'none';    
  101. }    
  102. },    
  103. show:  function () {    
  104. for  ( var  i = 0; i < arguments.length; i++) {    
  105. var  element = $(arguments);    
  106. element.style.display =  '' ;    
  107. }    
  108. },    
  109. /**   
  110. * 从父节点中移除   
  111. */     
  112. remove:  function (element) {    
  113. element = $(element);    
  114. element.parentNode.removeChild(element);    
  115. },    
  116.   
  117. getHeight:  function (element) {    
  118. element = $(element);    
  119. return  element.offsetHeight;    
  120. },    
  121. /**   
  122. * 是否拥有 class 属性值   
  123. */     
  124. hasClassName:  function (element, className) {    
  125. element = $(element);    
  126. if  (!element)    
  127. return ;    
  128. var  a = element.className.split(' ');    
  129. for  ( var  i = 0; i < a.length; i++) {    
  130. if  (a == className)    
  131. return   true ;    
  132. }    
  133. return   false ;    
  134. },    
  135. /**   
  136. * 为对象添加 class 属性值   
  137. */     
  138. addClassName:  function (element, className) {    
  139. element = $(element);    
  140. Element.removeClassName(element, className);    
  141. element.className += ' ' + className;    
  142. },    
  143. /**   
  144. * 为对象移除 class 属性值   
  145. */     
  146. removeClassName:  function (element, className) {    
  147. element = $(element);    
  148. if  (!element)    
  149. return ;    
  150. var  newClassName =  '' ;    
  151. var  a = element.className.split(' ');    
  152. for  ( var  i = 0; i < a.length; i++) {    
  153. if  (a != className) {    
  154. if  (i > 0)    
  155. newClassName += ' ';    
  156. newClassName += a;    
  157. }    
  158. }    
  159. element.className = newClassName;    
  160. },    
  161. // removes whitespace-only text node children    
  162. cleanWhitespace:  function (element) {    
  163. var  element = $(element);    
  164. for  ( var  i = 0; i < element.childNodes.length; i++) {    
  165. var  node = element.childNodes;    
  166. if  (node.nodeType == 3 && !/S/.test(node.nodeValue))    
  167. Element.remove(node);    
  168. }    
  169. }    
  170. });    
  171. /**   
  172. * 为 Element.toggle 做了一个符号连接,大概是兼容性的考虑   
  173. */     
  174. var  Toggle =  new  Object();    
  175. Toggle.display = Element.toggle;    
  176. /**   
  177. * 动态插入内容的实现,MS的Jscript实现中对象有一个 insertAdjacentHTML 方法(http://msdn.microsoft.com/workshop/...djacenthtml.asp)   
  178. * 这里算是一个对象形式的封装。   
  179. */     
  180. Abstract.Insertion =  function (adjacency) {    
  181. this .adjacency = adjacency;    
  182. }    
  183. Abstract.Insertion.prototype = {    
  184. initialize:  function (element, content) {    
  185. this .element = $(element);    
  186. this .content = content;    
  187.   
  188. if  ( this .adjacency &&  this .element.insertAdjacentHTML) {    
  189. this .element.insertAdjacentHTML( this .adjacency,  this .content);    
  190. else  {    
  191. /**   
  192. * gecko 不支持 insertAdjacentHTML 方法,但可以用如下代码代替   
  193. */     
  194. this .range =  this .element.ownerDocument.createRange();    
  195. /**   
  196. * 如果定义了 initializeRange 方法,则实行,这里相当与定义了一个抽象的 initializeRange 方法   
  197. */     
  198. if  ( this .initializeRange)  this .initializeRange();    
  199. this .fragment =  this .range.createContextualFragment( this .content);    
  200. /**   
  201. * insertContent 也是一个抽象方法,子类必须实现   
  202. */     
  203. this .insertContent();    
  204. }    
  205. }    
  206. }    
  207. /**   
  208. * prototype 加深了我的体会,就是写js 如何去遵循 Don’t Repeat Yourself (DRY) 原则   
  209. * 上文中 Abstract.Insertion 算是一个抽象类,定义了名为 initializeRange 的一个抽象方法   
  210. * var Insertion = new Object() 建立一个命名空间   
  211. * Insertion.Before|Top|Bottom|After 就象是四个java中的四个静态内部类,而它们分别继承于Abstract.Insertion,并实现了initializeRange方法。   
  212. */     
  213. var  Insertion =  new  Object();    
  214. /**   
  215. * 将内容插入到指定节点的前面, 与指定节点同级   
  216. */     
  217. Insertion.Before = Class.create();    
  218. Insertion.Before.prototype = ( new  Abstract.Insertion('beforeBegin')).extend({    
  219. initializeRange:  function () {    
  220. this .range.setStartBefore( this .element);    
  221. },    
  222. insertContent:  function () {    
  223. this .element.parentNode.insertBefore( this .fragment,  this .element);    
  224. }    
  225. });    
  226. /**   
  227. * 将内容插入到指定节点的第一个子节点前,于是内容变为该节点的第一个子节点   
  228. */     
  229. Insertion.Top = Class.create();    
  230. Insertion.Top.prototype = ( new  Abstract.Insertion('afterBegin')).extend({    
  231. initializeRange:  function () {    
  232. this .range.selectNodeContents( this .element);    
  233. this .range.collapse( true );    
  234. },    
  235. insertContent:  function () {    
  236. this .element.insertBefore( this .fragment,  this .element.firstChild);    
  237. }    
  238. });    
  239. /**   
  240. * 将内容插入到指定节点的最后,于是内容变为该节点的最后一个子节点   
  241. */     
  242. Insertion.Bottom = Class.create();    
  243. Insertion.Bottom.prototype = ( new  Abstract.Insertion('beforeEnd')).extend({    
  244. initializeRange:  function () {    
  245. this .range.selectNodeContents( this .element);    
  246. this .range.collapse( this .element);    
  247. },    
  248. insertContent:  function () {    
  249. this .element.appendChild( this .fragment);    
  250. }    
  251. });    
  252. /**   
  253. * 将内容插入到指定节点的后面, 与指定节点同级   
  254. */     
  255. Insertion.After = Class.create();    
  256. Insertion.After.prototype = ( new  Abstract.Insertion('afterEnd')).extend({    
  257. initializeRange:  function () {    
  258. this .range.setStartAfter( this .element);    
  259. },    
  260. insertContent:  function () {    
  261. this .element.parentNode.insertBefore( this .fragment,    
  262. this .element.nextSibling);    
  263. }    
  264. });    
  265. /**   
  266. * 针对 页面元素对象(一般都是表单控件)的工具类,提供一些简单静态方法   
  267. * 这些方法显然常用在表单处理中   
  268. * 注意 Field 这种声明方式类似于 java 声明一个静态的 singleton 工具类   
  269. * 等同于 :   
  270. * var Field = new Object();   
  271. * Field.extend({...});   
  272.  
  273. * 后文中的 Form, Event, Position 对象声明方式如出一辙   
  274. */     
  275. var  Field = {    
  276. /**   
  277. * 清除参数引用的对象的值   
  278. */     
  279. clear:  function () {    
  280. for  ( var  i = 0; i < arguments.length; i++)    
  281. $(arguments).value =  '' ;    
  282. },    
  283. /**   
  284. * 使参数引用对象获取焦点   
  285. */     
  286. focus:  function (element) {    
  287. $(element).focus();    
  288. },    
  289. /**   
  290. * 判断参数引用对象是否有非空值,如为空值,返回false, 反之true   
  291. */     
  292. present:  function () {    
  293. for  ( var  i = 0; i < arguments.length; i++)    
  294. if  ($(arguments).value ==  '' return   false ;    
  295. return   true ;    
  296. },    
  297. /**   
  298. * 使选中参数引用对象   
  299. */     
  300. select:  function (element) {    
  301. $(element).select();    
  302. },    
  303. /**   
  304. * 使参数引用对象处于可编辑状态   
  305. */     
  306. activate:  function (element) {    
  307. $(element).focus();    
  308. $(element).select();    
  309. }    
  310. }    
  311. /**   
  312. * 表单工具类   
  313. */     
  314. var  Form = {    
  315. /**   
  316. * 将表单元素序列化后的值(其实就是 name=value 形式的名值配对)组合成 QueryString 的形式   
  317. */     
  318. serialize:  function (form) {    
  319. var  elements = Form.getElements($(form));    
  320. var  queryComponents =  new  Array();    
  321.   
  322. for  ( var  i = 0; i < elements.length; i++) {    
  323. var  queryComponent = Form.Element.serialize(elements);    
  324. if  (queryComponent)    
  325. queryComponents.push(queryComponent);    
  326. }    
  327.   
  328. return  queryComponents.join('&');    
  329. },    
  330. /**   
  331. * 得到表单的所有元素对象   
  332. */     
  333. getElements:  function (form) {    
  334. var  form = $(form);    
  335. var  elements =  new  Array();    
  336. for  (tagName  in  Form.Element.Serializers) {    
  337. var  tagElements = form.getElementsByTagName(tagName);    
  338. for  ( var  j = 0; j < tagElements.length; j++)    
  339. elements.push(tagElements[j]);    
  340. }    
  341. return  elements;    
  342. },    
  343. /**   
  344. * 根据 type 和 name 过滤得到表单中符合的  对象   
  345. */     
  346. getInputs:  function (form, typeName, name) {    
  347. var  form = $(form);    
  348. var  inputs = form.getElementsByTagName('input');    
  349.   
  350. if  (!typeName && !name)    
  351. return  inputs;    
  352.   
  353. var  matchingInputs =  new  Array();    
  354. for  ( var  i = 0; i < inputs.length; i++) {    
  355. var  input = inputs;    
  356. if  ((typeName && input.type != typeName) ||    
  357. (name && input.name != name))    
  358. continue ;    
  359. matchingInputs.push(input);    
  360. }    
  361. return  matchingInputs;    
  362. },    
  363. /**   
  364. * 将指定表单的元素置于不可用状态   
  365. */     
  366. disable:  function (form) {    
  367. var  elements = Form.getElements(form);    
  368. for  ( var  i = 0; i < elements.length; i++) {    
  369. var  element = elements;    
  370. element.blur();    
  371. element.disabled = ' true ';    
  372. }    
  373. },    
  374. /**   
  375. * 将指定表单的元素置于可用状态   
  376. */     
  377. enable:  function (form) {    
  378. var  elements = Form.getElements(form);    
  379. for  ( var  i = 0; i < elements.length; i++) {    
  380. var  element = elements;    
  381. element.disabled =  '' ;    
  382. }    
  383. },    
  384. /**   
  385. * 使表单的第一个非 hidden 类型而且处于可用状态的元素获得焦点   
  386. */     
  387. focusFirstElement:  function (form) {    
  388. var  form = $(form);    
  389. var  elements = Form.getElements(form);    
  390. for  ( var  i = 0; i < elements.length; i++) {    
  391. var  element = elements;    
  392. if  (element.type != 'hidden' && !element.disabled) {    
  393. Field.activate(element);    
  394. break ;    
  395. }    
  396. }    
  397. },    
  398. /*   
  399. * 重置表单   
  400. */     
  401. reset:  function (form) {    
  402. $(form).reset();    
  403. }    
  404. }    
  405. /**   
  406. * 表单元素工具类   
  407. */     
  408. Form.Element = {    
  409. /**   
  410. * 返回表单元素的值先序列化, 其实就是 name=value 形式的名值配对   
  411. */     
  412. serialize:  function (element) {    
  413. var  element = $(element);    
  414. var  method = element.tagName.toLowerCase();    
  415. var  parameter = Form.Element.Serializers[method](element);    
  416.   
  417. if  (parameter)    
  418. return  encodeURIComponent(parameter[0]) + '=' +    
  419. encodeURIComponent(parameter[1]);    
  420. },    
  421. /**   
  422. * 返回表单元素的值   
  423. */     
  424. getValue:  function (element) {    
  425. var  element = $(element);    
  426. var  method = element.tagName.toLowerCase();    
  427. var  parameter = Form.Element.Serializers[method](element);    
  428.   
  429. if  (parameter)    
  430. return  parameter[1];    
  431. }    
  432. }    
  433. /**   
  434. * prototype 的所谓序列化其实就是将表单的名字和值组合成一个数组   
  435. */     
  436. Form.Element.Serializers = {    
  437. input:  function (element) {    
  438. switch  (element.type.toLowerCase()) {    
  439. case  'submit':    
  440. case  'hidden':    
  441. case  'password':    
  442. case  'text':    
  443. return  Form.Element.Serializers.textarea(element);    
  444. case  'checkbox':    
  445. case  'radio':    
  446. return  Form.Element.Serializers.inputSelector(element);    
  447. }    
  448. return   false ;    
  449. },    
  450. /**   
  451. * 单/多选框 由此方法处理序列化   
  452. */     
  453. inputSelector:  function (element) {    
  454. if  (element.checked)    
  455. return  [element.name, element.value];    
  456. },    
  457. /**   
  458. * textarea 由此方法处理序列化   
  459. */     
  460. textarea:  function (element) {    
  461. return  [element.name, element.value];    
  462. },    
  463. /**   
  464. * select 下拉列表由此方法处理序列化   
  465. */     
  466. select:  function (element) {    
  467. var  value =  '' ;    
  468. if  (element.type == 'select-one') {    
  469. var  index = element.selectedIndex;    
  470. if  (index >= 0)    
  471. value = element.options[index].value || element.options[index].text;    
  472. else  {    
  473. /**   
  474. * 支持 select-mulitple 的下拉列表,返回的数组的第二个元素,是一个值数组   
  475. */     
  476. value =  new  Array();    
  477. for  ( var  i = 0; i < element.length; i++) {    
  478. var  opt = element.options;    
  479. if  (opt.selected)    
  480. value.push(opt.value || opt.text);    
  481. }    
  482. }    
  483. return  [element.name, value];    
  484. }    
  485. }  

posted on 2007-09-20 19:37 李云泽 阅读(235) 评论(0)  编辑  收藏 所属分类: Prototype(Ajax)


只有注册用户登录后才能发表评论。


网站导航: