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