1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23: 24: 25: 26: 27: 28: 29: 30: 31:
32: class AjaxHelper extends AppHelper {
33:
34: 35: 36: 37: 38:
39: var $helpers = array('Html', 'Javascript', 'Form');
40:
41: 42: 43: 44: 45: 46:
47: var $Html = null;
48:
49: 50: 51: 52: 53: 54:
55: var $Javascript = null;
56:
57: 58: 59: 60: 61:
62: var $callbacks = array(
63: 'complete', 'create', 'exception', 'failure', 'interactive', 'loading',
64: 'loaded', 'success', 'uninitialized'
65: );
66:
67: 68: 69: 70: 71:
72: var $ajaxOptions = array(
73: 'after', 'asynchronous', 'before', 'confirm', 'condition', 'contentType', 'encoding',
74: 'evalScripts', 'failure', 'fallback', 'form', 'indicator', 'insertion', 'interactive',
75: 'loaded', 'loading', 'method', 'onCreate', 'onComplete', 'onException', 'onFailure',
76: 'onInteractive', 'onLoaded', 'onLoading', 'onSuccess', 'onUninitialized', 'parameters',
77: 'position', 'postBody', 'requestHeaders', 'success', 'type', 'update', 'with'
78: );
79:
80: 81: 82: 83: 84:
85: var $dragOptions = array(
86: 'handle', 'revert', 'snap', 'zindex', 'constraint', 'change', 'ghosting',
87: 'starteffect', 'reverteffect', 'endeffect', 'scroll', 'scrollSensitivity',
88: 'onStart', 'onDrag', 'onEnd'
89: );
90:
91: 92: 93: 94: 95:
96: var $dropOptions = array(
97: 'accept', 'containment', 'greedy', 'hoverclass', 'onHover', 'onDrop', 'overlap'
98: );
99:
100: 101: 102: 103: 104:
105: var $sortOptions = array(
106: 'constraint', 'containment', 'dropOnEmpty', 'ghosting', 'handle', 'hoverclass', 'onUpdate',
107: 'onChange', 'only', 'overlap', 'scroll', 'scrollSensitivity', 'scrollSpeed', 'tag', 'tree',
108: 'treeTag', 'update'
109: );
110:
111: 112: 113: 114: 115:
116: var $sliderOptions = array(
117: 'alignX', 'alignY', 'axis', 'disabled', 'handleDisabled', 'handleImage', 'increment',
118: 'maximum', 'minimum', 'onChange', 'onSlide', 'range', 'sliderValue', 'values'
119: );
120:
121: 122: 123: 124: 125:
126: var $editorOptions = array(
127: 'okText', 'cancelText', 'savingText', 'formId', 'externalControl', 'rows', 'cols', 'size',
128: 'highlightcolor', 'highlightendcolor', 'savingClassName', 'formClassName', 'loadTextURL',
129: 'loadingText', 'callback', 'ajaxOptions', 'clickToEditText', 'collection', 'okControl',
130: 'cancelControl', 'submitOnBlur'
131: );
132:
133: 134: 135: 136: 137:
138: var $autoCompleteOptions = array(
139: 'afterUpdateElement', 'callback', 'frequency', 'indicator', 'minChars', 'onShow', 'onHide',
140: 'parameters', 'paramName', 'tokens', 'updateElement'
141: );
142:
143: 144: 145: 146: 147:
148: var $__ajaxBuffer = array();
149:
150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212:
213: function link($title, $url = null, $options = array(), $confirm = null) {
214: if (!isset($url)) {
215: $url = $title;
216: }
217: if (!isset($options['url'])) {
218: $options['url'] = $url;
219: }
220:
221: if (!empty($confirm)) {
222: $options['confirm'] = $confirm;
223: unset($confirm);
224: }
225: $htmlOptions = $this->__getHtmlOptions($options, array('url'));
226: $options += array('safe' => true);
227:
228: unset($options['escape']);
229: if (empty($options['fallback']) || !isset($options['fallback'])) {
230: $options['fallback'] = $url;
231: }
232: $htmlDefaults = array('id' => 'link' . intval(mt_rand()), 'onclick' => '');
233: $htmlOptions = array_merge($htmlDefaults, $htmlOptions);
234:
235: $htmlOptions['onclick'] .= ' event.returnValue = false; return false;';
236: $return = $this->Html->link($title, $url, $htmlOptions);
237: $callback = $this->remoteFunction($options);
238: $script = $this->Javascript->event("'{$htmlOptions['id']}'", "click", $callback);
239:
240: if (is_string($script)) {
241: $return .= $script;
242: }
243: return $return;
244: }
245:
246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256:
257: function remoteFunction($options) {
258: if (isset($options['update'])) {
259: if (!is_array($options['update'])) {
260: $func = "new Ajax.Updater('{$options['update']}',";
261: } else {
262: $func = "new Ajax.Updater(document.createElement('div'),";
263: }
264: if (!isset($options['requestHeaders'])) {
265: $options['requestHeaders'] = array();
266: }
267: if (is_array($options['update'])) {
268: $options['update'] = implode(' ', $options['update']);
269: }
270: $options['requestHeaders']['X-Update'] = $options['update'];
271: } else {
272: $func = "new Ajax.Request(";
273: }
274:
275: $url = isset($options['url']) ? $options['url'] : "";
276: if (empty($options['safe'])) {
277: $url = $this->url($url);
278: } else {
279: $url = Router::url($url);
280: }
281:
282: $func .= "'" . $url . "'";
283: $func .= ", " . $this->__optionsForAjax($options) . ")";
284:
285: if (isset($options['before'])) {
286: $func = "{$options['before']}; $func";
287: }
288: if (isset($options['after'])) {
289: $func = "$func; {$options['after']};";
290: }
291: if (isset($options['condition'])) {
292: $func = "if ({$options['condition']}) { $func; }";
293: }
294:
295: if (isset($options['confirm'])) {
296: $func = "if (confirm('" . $this->Javascript->escapeString($options['confirm'])
297: . "')) { $func; } else { event.returnValue = false; return false; }";
298: }
299: return $func;
300: }
301:
302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314:
315: function remoteTimer($options = null) {
316: $frequency = (isset($options['frequency'])) ? $options['frequency'] : 10;
317: $callback = $this->remoteFunction($options);
318: $code = "new PeriodicalExecuter(function(pe) {{$callback}}, $frequency)";
319: return $this->Javascript->codeBlock($code);
320: }
321:
322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341:
342: function form($params = null, $type = 'post', $options = array()) {
343: $model = false;
344: if (is_array($params)) {
345: extract($params, EXTR_OVERWRITE);
346: }
347:
348: if (empty($options['url'])) {
349: $options['url'] = array('action' => $params);
350: }
351:
352: $htmlDefaults = array(
353: 'id' => 'form' . intval(mt_rand()),
354: 'onsubmit' => "event.returnValue = false; return false;",
355: 'type' => $type
356: );
357: $htmlOptions = $this->__getHtmlOptions($options, array('model', 'with'));
358: $htmlOptions = array_merge($htmlDefaults, $htmlOptions);
359:
360: $defaults = array('model' => $model, 'with' => "Form.serialize('{$htmlOptions['id']}')");
361: $options = array_merge($defaults, $options);
362: $callback = $this->remoteFunction($options);
363:
364: $form = $this->Form->create($options['model'], $htmlOptions);
365: $script = $this->Javascript->event("'" . $htmlOptions['id']. "'", 'submit', $callback);
366: return $form . $script;
367: }
368:
369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381:
382: function submit($title = 'Submit', $options = array()) {
383: $htmlOptions = $this->__getHtmlOptions($options);
384: $htmlOptions['value'] = $title;
385:
386: if (!isset($options['with'])) {
387: $options['with'] = 'Form.serialize(Event.element(event).form)';
388: }
389: if (!isset($htmlOptions['id'])) {
390: $htmlOptions['id'] = 'submit' . intval(mt_rand());
391: }
392:
393: $htmlOptions['onclick'] = "event.returnValue = false; return false;";
394: $callback = $this->remoteFunction($options);
395:
396: $form = $this->Form->submit($title, $htmlOptions);
397: $script = $this->Javascript->event('"' . $htmlOptions['id'] . '"', 'click', $callback);
398: return $form . $script;
399: }
400:
401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429:
430: function observeField($field, $options = array()) {
431: if (!isset($options['with'])) {
432: $options['with'] = 'Form.Element.serialize(\'' . $field . '\')';
433: }
434: $observer = 'Observer';
435: if (!isset($options['frequency']) || intval($options['frequency']) == 0) {
436: $observer = 'EventObserver';
437: }
438: return $this->Javascript->codeBlock(
439: $this->_buildObserver('Form.Element.' . $observer, $field, $options)
440: );
441: }
442:
443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455:
456: function observeForm($form, $options = array()) {
457: if (!isset($options['with'])) {
458: $options['with'] = 'Form.serialize(\'' . $form . '\')';
459: }
460: $observer = 'Observer';
461: if (!isset($options['frequency']) || intval($options['frequency']) == 0) {
462: $observer = 'EventObserver';
463: }
464: return $this->Javascript->codeBlock(
465: $this->_buildObserver('Form.' . $observer, $form, $options)
466: );
467: }
468:
469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482:
483: function autoComplete($field, $url = "", $options = array()) {
484: $var = '';
485: if (isset($options['var'])) {
486: $var = 'var ' . $options['var'] . ' = ';
487: unset($options['var']);
488: }
489:
490: if (!isset($options['id'])) {
491: $options['id'] = Inflector::camelize(str_replace(".", "_", $field));
492: }
493:
494: $divOptions = array(
495: 'id' => $options['id'] . "_autoComplete",
496: 'class' => isset($options['class']) ? $options['class'] : 'auto_complete'
497: );
498:
499: if (isset($options['div_id'])) {
500: $divOptions['id'] = $options['div_id'];
501: unset($options['div_id']);
502: }
503:
504: $htmlOptions = $this->__getHtmlOptions($options);
505: $htmlOptions['autocomplete'] = "off";
506:
507: foreach ($this->autoCompleteOptions as $opt) {
508: unset($htmlOptions[$opt]);
509: }
510:
511: if (isset($options['tokens'])) {
512: if (is_array($options['tokens'])) {
513: $options['tokens'] = $this->Javascript->object($options['tokens']);
514: } else {
515: $options['tokens'] = '"' . $options['tokens'] . '"';
516: }
517: }
518:
519: $options = $this->_optionsToString($options, array('paramName', 'indicator'));
520: $options = $this->_buildOptions($options, $this->autoCompleteOptions);
521:
522: $text = $this->Form->text($field, $htmlOptions);
523: $div = $this->Html->div(null, '', $divOptions);
524: $script = "{$var}new Ajax.Autocompleter('{$htmlOptions['id']}', '{$divOptions['id']}', '";
525: $script .= $this->Html->url($url) . "', {$options});";
526:
527: return "{$text}\n{$div}\n" . $this->Javascript->codeBlock($script);
528: }
529:
530: 531: 532: 533: 534: 535:
536: function div($id, $options = array()) {
537: if (env('HTTP_X_UPDATE') != null) {
538: $this->Javascript->enabled = false;
539: $divs = explode(' ', env('HTTP_X_UPDATE'));
540:
541: if (in_array($id, $divs)) {
542: @ob_end_clean();
543: ob_start();
544: return '';
545: }
546: }
547: $attr = $this->_parseAttributes(array_merge($options, array('id' => $id)));
548: return sprintf($this->Html->tags['blockstart'], $attr);
549: }
550:
551: 552: 553: 554: 555: 556:
557: function divEnd($id) {
558: if (env('HTTP_X_UPDATE') != null) {
559: $divs = explode(' ', env('HTTP_X_UPDATE'));
560: if (in_array($id, $divs)) {
561: $this->__ajaxBuffer[$id] = ob_get_contents();
562: ob_end_clean();
563: ob_start();
564: return '';
565: }
566: }
567: return $this->Html->tags['blockend'];
568: }
569:
570: 571: 572: 573: 574: 575:
576: function isAjax() {
577: return (isset($this->params['isAjax']) && $this->params['isAjax'] === true);
578: }
579:
580: 581: 582: 583: 584: 585: 586: 587: 588:
589: function drag($id, $options = array()) {
590: $var = '';
591: if (isset($options['var'])) {
592: $var = 'var ' . $options['var'] . ' = ';
593: unset($options['var']);
594: }
595: $options = $this->_buildOptions(
596: $this->_optionsToString($options, array('handle', 'constraint')), $this->dragOptions
597: );
598: return $this->Javascript->codeBlock("{$var}new Draggable('$id', " .$options . ");");
599: }
600:
601: 602: 603: 604: 605: 606: 607: 608: 609:
610: function drop($id, $options = array()) {
611: $optionsString = array('overlap', 'hoverclass');
612: if (!isset($options['accept']) || !is_array($options['accept'])) {
613: $optionsString[] = 'accept';
614: } else if (isset($options['accept'])) {
615: $options['accept'] = $this->Javascript->object($options['accept']);
616: }
617: $options = $this->_buildOptions(
618: $this->_optionsToString($options, $optionsString), $this->dropOptions
619: );
620: return $this->Javascript->codeBlock("Droppables.add('{$id}', {$options});");
621: }
622:
623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634:
635: function dropRemote($id, $options = array(), $ajaxOptions = array()) {
636: $callback = $this->remoteFunction($ajaxOptions);
637: $options['onDrop'] = "function(element, droppable, event) {{$callback}}";
638: $optionsString = array('overlap', 'hoverclass');
639:
640: if (!isset($options['accept']) || !is_array($options['accept'])) {
641: $optionsString[] = 'accept';
642: } else if (isset($options['accept'])) {
643: $options['accept'] = $this->Javascript->object($options['accept']);
644: }
645:
646: $options = $this->_buildOptions(
647: $this->_optionsToString($options, $optionsString),
648: $this->dropOptions
649: );
650: return $this->Javascript->codeBlock("Droppables.add('{$id}', {$options});");
651: }
652:
653: 654: 655: 656: 657: 658: 659: 660: 661:
662: function slider($id, $trackId, $options = array()) {
663: if (isset($options['var'])) {
664: $var = 'var ' . $options['var'] . ' = ';
665: unset($options['var']);
666: } else {
667: $var = 'var ' . $id . ' = ';
668: }
669:
670: $options = $this->_optionsToString($options, array(
671: 'axis', 'handleImage', 'handleDisabled'
672: ));
673: $callbacks = array('change', 'slide');
674:
675: foreach ($callbacks as $callback) {
676: if (isset($options[$callback])) {
677: $call = $options[$callback];
678: $options['on' . ucfirst($callback)] = "function(value) {{$call}}";
679: unset($options[$callback]);
680: }
681: }
682:
683: if (isset($options['values']) && is_array($options['values'])) {
684: $options['values'] = $this->Javascript->object($options['values']);
685: }
686:
687: $options = $this->_buildOptions($options, $this->sliderOptions);
688: $script = "{$var}new Control.Slider('$id', '$trackId', $options);";
689: return $this->Javascript->codeBlock($script);
690: }
691:
692: 693: 694: 695: 696: 697: 698: 699: 700:
701: function editor($id, $url, $options = array()) {
702: $url = $this->url($url);
703: $options['ajaxOptions'] = $this->__optionsForAjax($options);
704:
705: foreach ($this->ajaxOptions as $opt) {
706: if (isset($options[$opt])) {
707: unset($options[$opt]);
708: }
709: }
710:
711: if (isset($options['callback'])) {
712: $options['callback'] = 'function(form, value) {' . $options['callback'] . '}';
713: }
714:
715: $type = 'InPlaceEditor';
716: if (isset($options['collection']) && is_array($options['collection'])) {
717: $options['collection'] = $this->Javascript->object($options['collection']);
718: $type = 'InPlaceCollectionEditor';
719: }
720:
721: $var = '';
722: if (isset($options['var'])) {
723: $var = 'var ' . $options['var'] . ' = ';
724: unset($options['var']);
725: }
726:
727: $options = $this->_optionsToString($options, array(
728: 'okText', 'cancelText', 'savingText', 'formId', 'externalControl', 'highlightcolor',
729: 'highlightendcolor', 'savingClassName', 'formClassName', 'loadTextURL', 'loadingText',
730: 'clickToEditText', 'okControl', 'cancelControl'
731: ));
732: $options = $this->_buildOptions($options, $this->editorOptions);
733: $script = "{$var}new Ajax.{$type}('{$id}', '{$url}', {$options});";
734: return $this->Javascript->codeBlock($script);
735: }
736:
737: 738: 739: 740: 741: 742: 743: 744:
745: function sortable($id, $options = array()) {
746: if (!empty($options['url'])) {
747: if (empty($options['with'])) {
748: $options['with'] = "Sortable.serialize('$id')";
749: }
750: $options['onUpdate'] = 'function(sortable) {' . $this->remoteFunction($options) . '}';
751: }
752: $block = true;
753:
754: if (isset($options['block'])) {
755: $block = $options['block'];
756: unset($options['block']);
757: }
758: $strings = array(
759: 'tag', 'constraint', 'only', 'handle', 'hoverclass', 'tree',
760: 'treeTag', 'update', 'overlap'
761: );
762: $scrollIsObject = (
763: isset($options['scroll']) &&
764: $options['scroll'] != 'window' &&
765: strpos($options['scroll'], '$(') !== 0
766: );
767:
768: if ($scrollIsObject) {
769: $strings[] = 'scroll';
770: }
771:
772: $options = $this->_optionsToString($options, $strings);
773: $options = array_merge($options, $this->_buildCallbacks($options));
774: $options = $this->_buildOptions($options, $this->sortOptions);
775: $result = "Sortable.create('$id', $options);";
776:
777: if (!$block) {
778: return $result;
779: }
780: return $this->Javascript->codeBlock($result);
781: }
782:
783: 784: 785: 786: 787: 788:
789: function __optionsForAjax($options) {
790: if (isset($options['indicator'])) {
791: if (isset($options['loading'])) {
792: $loading = $options['loading'];
793:
794: if (!empty($loading) && substr(trim($loading), -1, 1) != ';') {
795: $options['loading'] .= '; ';
796: }
797: $options['loading'] .= "Element.show('{$options['indicator']}');";
798: } else {
799: $options['loading'] = "Element.show('{$options['indicator']}');";
800: }
801: if (isset($options['complete'])) {
802: $complete = $options['complete'];
803:
804: if (!empty($complete) && substr(trim($complete), -1, 1) != ';') {
805: $options['complete'] .= '; ';
806: }
807: $options['complete'] .= "Element.hide('{$options['indicator']}');";
808: } else {
809: $options['complete'] = "Element.hide('{$options['indicator']}');";
810: }
811: unset($options['indicator']);
812: }
813:
814: $jsOptions = array_merge(
815: array('asynchronous' => 'true', 'evalScripts' => 'true'),
816: $this->_buildCallbacks($options)
817: );
818:
819: $options = $this->_optionsToString($options, array(
820: 'contentType', 'encoding', 'fallback', 'method', 'postBody', 'update', 'url'
821: ));
822: $jsOptions = array_merge($jsOptions, array_intersect_key($options, array_flip(array(
823: 'contentType', 'encoding', 'method', 'postBody'
824: ))));
825:
826: foreach ($options as $key => $value) {
827: switch ($key) {
828: case 'type':
829: $jsOptions['asynchronous'] = ($value == 'synchronous') ? 'false' : 'true';
830: break;
831: case 'evalScripts':
832: $jsOptions['evalScripts'] = ($value) ? 'true' : 'false';
833: break;
834: case 'position':
835: $pos = Inflector::camelize($options['position']);
836: $jsOptions['insertion'] = "Insertion.{$pos}";
837: break;
838: case 'with':
839: $jsOptions['parameters'] = $options['with'];
840: break;
841: case 'form':
842: $jsOptions['parameters'] = 'Form.serialize(this)';
843: break;
844: case 'requestHeaders':
845: $keys = array();
846: foreach ($value as $key => $val) {
847: $keys[] = "'" . $key . "'";
848: $keys[] = "'" . $val . "'";
849: }
850: $jsOptions['requestHeaders'] = '[' . implode(', ', $keys) . ']';
851: break;
852: }
853: }
854: return $this->_buildOptions($jsOptions, $this->ajaxOptions);
855: }
856:
857: 858: 859: 860: 861: 862: 863: 864: 865:
866: function __getHtmlOptions($options, $extra = array()) {
867: foreach (array_merge($this->ajaxOptions, $this->callbacks, $extra) as $key) {
868: if (isset($options[$key])) {
869: unset($options[$key]);
870: }
871: }
872: return $options;
873: }
874:
875: 876: 877: 878: 879: 880: 881:
882: function _buildOptions($options, $acceptable) {
883: if (is_array($options)) {
884: $out = array();
885:
886: foreach ($options as $k => $v) {
887: if (in_array($k, $acceptable)) {
888: if ($v === true) {
889: $v = 'true';
890: } elseif ($v === false) {
891: $v = 'false';
892: }
893: $out[] = "$k:$v";
894: } elseif ($k === 'with' && in_array('parameters', $acceptable)) {
895: $out[] = "parameters:${v}";
896: }
897: }
898:
899: $out = implode(', ', $out);
900: $out = '{' . $out . '}';
901: return $out;
902: } else {
903: return false;
904: }
905: }
906:
907: 908: 909: 910: 911: 912: 913: 914:
915: function _buildObserver($klass, $name, $options = null) {
916: if (!isset($options['with']) && isset($options['update'])) {
917: $options['with'] = 'value';
918: }
919:
920: $callback = $this->remoteFunction($options);
921: $hasFrequency = !(!isset($options['frequency']) || intval($options['frequency']) == 0);
922: $frequency = $hasFrequency ? $options['frequency'] . ', ' : '';
923:
924: return "new $klass('$name', {$frequency}function(element, value) {{$callback}})";
925: }
926:
927: 928: 929: 930: 931: 932: 933:
934: function _buildCallbacks($options) {
935: $callbacks = array();
936:
937: foreach ($this->callbacks as $callback) {
938: if (isset($options[$callback])) {
939: $name = 'on' . ucfirst($callback);
940: $code = $options[$callback];
941: switch ($name) {
942: case 'onComplete':
943: $callbacks[$name] = "function(request, json) {" . $code . "}";
944: break;
945: case 'onCreate':
946: $callbacks[$name] = "function(request, xhr) {" . $code . "}";
947: break;
948: case 'onException':
949: $callbacks[$name] = "function(request, exception) {" . $code . "}";
950: break;
951: default:
952: $callbacks[$name] = "function(request) {" . $code . "}";
953: break;
954: }
955: if (isset($options['bind'])) {
956: $bind = $options['bind'];
957:
958: $hasBinding = (
959: (is_array($bind) && in_array($callback, $bind)) ||
960: (is_string($bind) && strpos($bind, $callback) !== false)
961: );
962:
963: if ($hasBinding) {
964: $callbacks[$name] .= ".bind(this)";
965: }
966: }
967: }
968: }
969: return $callbacks;
970: }
971:
972: 973: 974: 975: 976: 977: 978: 979:
980: function _optionsToString($options, $stringOpts = array()) {
981: foreach ($stringOpts as $option) {
982: $hasOption = (
983: isset($options[$option]) && !empty($options[$option]) &&
984: is_string($options[$option]) && $options[$option][0] != "'"
985: );
986:
987: if ($hasOption) {
988: if ($options[$option] === true || $options[$option] === 'true') {
989: $options[$option] = 'true';
990: } elseif ($options[$option] === false || $options[$option] === 'false') {
991: $options[$option] = 'false';
992: } else {
993: $options[$option] = "'{$options[$option]}'";
994: }
995: }
996: }
997: return $options;
998: }
999:
1000: 1001: 1002: 1003: 1004: 1005:
1006: function afterRender() {
1007: if (env('HTTP_X_UPDATE') != null && !empty($this->__ajaxBuffer)) {
1008: @ob_end_clean();
1009:
1010: $data = array();
1011: $divs = explode(' ', env('HTTP_X_UPDATE'));
1012: $keys = array_keys($this->__ajaxBuffer);
1013:
1014: if (count($divs) == 1 && in_array($divs[0], $keys)) {
1015: echo $this->__ajaxBuffer[$divs[0]];
1016: } else {
1017: foreach ($this->__ajaxBuffer as $key => $val) {
1018: if (in_array($key, $divs)) {
1019: $data[] = $key . ':"' . rawurlencode($val) . '"';
1020: }
1021: }
1022: $out = 'var __ajaxUpdater__ = {' . implode(", \n", $data) . '};' . "\n";
1023: $out .= 'for (n in __ajaxUpdater__) { if (typeof __ajaxUpdater__[n] == "string"';
1024: $out .= ' && $(n)) Element.update($(n), unescape(decodeURIComponent(';
1025: $out .= '__ajaxUpdater__[n]))); }';
1026: echo $this->Javascript->codeBlock($out, false);
1027: }
1028: $scripts = $this->Javascript->getCache();
1029:
1030: if (!empty($scripts)) {
1031: echo $this->Javascript->codeBlock($scripts, false);
1032: }
1033: $this->_stop();
1034: }
1035: }
1036: }
1037: