diff --git a/cake/libs/view/helpers/ajax.php b/cake/libs/view/helpers/ajax.php index 0c97838f7..123576b78 100644 --- a/cake/libs/view/helpers/ajax.php +++ b/cake/libs/view/helpers/ajax.php @@ -208,11 +208,11 @@ class AjaxHelper extends AppHelper { * This function creates the javascript needed to make a remote call * it is primarily used as a helper for AjaxHelper::link. * - * @see AjaxHelper::link() for docs on options parameter. * @param array $options options for javascript * @return string html code for link to remote action + * @see AjaxHelper::link() for docs on options parameter. */ - function remoteFunction($options = null) { + function remoteFunction($options) { if (isset($options['update'])) { if (!is_array($options['update'])) { $func = "new Ajax.Updater('{$options['update']}',"; @@ -287,23 +287,13 @@ class AjaxHelper extends AppHelper { $options['url'] = array('action' => $params); } - $htmlOptions = array_merge( - array( - 'id' => 'form' . intval(rand()), - 'onsubmit' => "event.returnValue = false; return false;", - 'type' => $type - ), + $htmlOptions = array_merge(array( + 'id' => 'form' . intval(rand()), 'onsubmit' => "event.returnValue = false; return false;", + 'type' => $type), $this->__getHtmlOptions($options, array('model', 'with')) ); - $options = array_merge( - array( - 'model' => $model, - 'with' => "Form.serialize('{$htmlOptions['id']}')" - ), - $options - ); - + $options = array_merge(array('model' => $model,'with' => "Form.serialize('{$htmlOptions['id']}')"), $options); return $this->Form->create($options['model'], $htmlOptions) . $this->Javascript->event("'" . $htmlOptions['id']. "'", 'submit', $this->remoteFunction($options)); } @@ -658,8 +648,10 @@ class AjaxHelper extends AppHelper { /** * Private helper function for Javascript. * + * @param array $options Set of options + * @access private */ - function __optionsForAjax($options = array()) { + function __optionsForAjax($options) { if (isset($options['indicator'])) { if (isset($options['loading'])) { if (!empty($options['loading']) && substr(trim($options['loading']), -1, 1) != ';') { @@ -864,7 +856,6 @@ class AjaxHelper extends AppHelper { } $out = 'var __ajaxUpdater__ = {' . join(", \n", $data) . '};' . "\n"; $out .= 'for (n in __ajaxUpdater__) { if (typeof __ajaxUpdater__[n] == "string" && $(n)) Element.update($(n), unescape(decodeURIComponent(__ajaxUpdater__[n]))); }'; - e($this->Javascript->codeBlock($out, false)); } $scripts = $this->Javascript->getCache(); @@ -872,7 +863,8 @@ class AjaxHelper extends AppHelper { if (!empty($scripts)) { e($this->Javascript->codeBlock($scripts, false)); } - exit(); + + $this->stop(); } } } diff --git a/cake/tests/cases/libs/view/helpers/ajax.test.php b/cake/tests/cases/libs/view/helpers/ajax.test.php index 7a90fd0c7..b0cd7ace9 100644 --- a/cake/tests/cases/libs/view/helpers/ajax.test.php +++ b/cake/tests/cases/libs/view/helpers/ajax.test.php @@ -51,16 +51,32 @@ class PostAjaxTest extends Model { } } +class TestAjaxHelper extends AjaxHelper { + function stop() { + } +} + +class TestJavascriptHelper extends JavascriptHelper { + var $codeBlocks; + + function codeBlock($parameter) { + if (empty($this->codeBlocks)) { + $this->codeBlocks = array(); + } + $this->codeBlocks[] = $parameter; + } +} + /** * Short description for class. * * @package cake.tests * @subpackage cake.tests.cases.libs.view.helpers */ -class AjaxTest extends UnitTestCase { +class AjaxTest extends CakeTestCase { function setUp() { Router::reload(); - $this->Ajax =& new AjaxHelper(); + $this->Ajax =& new TestAjaxHelper(); $this->Ajax->Html =& new HtmlHelper(); $this->Ajax->Form =& new FormHelper(); $this->Ajax->Javascript =& new JavascriptHelper(); @@ -458,9 +474,104 @@ class AjaxTest extends UnitTestCase { $this->assertPattern('/^]+>\s*' . str_replace('/', '\\/', preg_quote('//')) . '\s*<\/script>$/', $result); } + function testRemoteFunction() { + $result = $this->Ajax->remoteFunction(array('complete' => 'testComplete();')); + $expected = 'new Ajax.Request(\'/\', {asynchronous:true, evalScripts:true, onComplete:function(request, json) {testComplete();}})'; + $this->assertEqual($result, $expected); + + $result = $this->Ajax->remoteFunction(array('update' => 'myDiv')); + $expected = 'new Ajax.Updater(\'myDiv\',\'/\', {asynchronous:true, evalScripts:true, requestHeaders:[\'X-Update\', \'myDiv\']})'; + $this->assertEqual($result, $expected); + + $result = $this->Ajax->remoteFunction(array('update' => array('div1', 'div2'))); + $expected = 'new Ajax.Updater(document.createElement(\'div\'),\'/\', {asynchronous:true, evalScripts:true, requestHeaders:[\'X-Update\', \'div1 div2\']})'; + $this->assertEqual($result, $expected); + + $result = $this->Ajax->remoteFunction(array('update' => 'myDiv', 'confirm' => 'Are you sure?')); + $expected = 'if (confirm(\'Are you sure?\')) { new Ajax.Updater(\'myDiv\',\'/\', {asynchronous:true, evalScripts:true, requestHeaders:[\'X-Update\', \'myDiv\']}); } else { event.returnValue = false; return false; }'; + } + + function testDiv() { + $oldXUpdate = env('HTTP_X_UPDATE'); + + $result = $this->Ajax->div('myDiv'); + $this->assertTags($result, array('div' => array('id' => 'myDiv'))); + + $_SERVER['HTTP_X_UPDATE'] = null; + $result = $this->Ajax->divEnd('myDiv'); + $this->assertTags($result, '/div'); + + $_SERVER['HTTP_X_UPDATE'] = 'secondDiv'; + $result = $this->Ajax->div('myDiv'); + $this->assertTags($result, array('div' => array('id' => 'myDiv'))); + $result = $this->Ajax->divEnd('myDiv'); + $this->assertTags($result, '/div'); + + $_SERVER['HTTP_X_UPDATE'] = 'secondDiv myDiv anotherDiv'; + $result = $this->Ajax->div('myDiv'); + $this->assertTrue(empty($result)); + + $result = $this->Ajax->divEnd('myDiv'); + $this->assertTrue(empty($result)); + + $_SERVER['HTTP_X_UPDATE'] = $oldXUpdate; + } + + function testAfterRender() { + $oldXUpdate = env('HTTP_X_UPDATE'); + $this->Ajax->Javascript =& new TestJavascriptHelper(); + + $_SERVER['HTTP_X_UPDATE'] = 'secondDiv myDiv anotherDiv'; + $result = $this->Ajax->div('myDiv'); + $this->assertTrue(empty($result)); + + echo 'Contents of myDiv'; + + $result = $this->Ajax->divEnd('myDiv'); + $this->assertTrue(empty($result)); + + ob_start(); + $this->Ajax->afterRender(); + + $result = array_shift($this->Ajax->Javascript->codeBlocks); + $this->assertPattern('/^\s*' . str_replace('/', '\\/', preg_quote('var __ajaxUpdater__ = {myDiv:"Contents%20of%20myDiv"};')) . '\s*' . str_replace('/', '\\/', preg_quote('for (n in __ajaxUpdater__) { if (typeof __ajaxUpdater__[n] == "string" && $(n)) Element.update($(n), unescape(decodeURIComponent(__ajaxUpdater__[n]))); }')) . '\s*$/s', $result); + + $_SERVER['HTTP_X_UPDATE'] = $oldXUpdate; + } + + function testEditor() { + $result = $this->Ajax->editor('myDiv', '/'); + $this->assertPattern('/^]+type="text\/javascript"[^<>]*>.+<\/script>$/s', $result); + $this->assertPattern('/^]+>\s*' . str_replace('/', '\\/', preg_quote('//')) . '\s*<\/script>$/s', $result); + $this->assertPattern('/^.+\s*' . str_replace('/', '\\/', preg_quote('new Ajax.InPlaceEditor(\'myDiv\', \'/\', {ajaxOptions:{asynchronous:true, evalScripts:true}});')) . '\s*.+$/s', $result); + + $result = $this->Ajax->editor('myDiv', '/', array('complete' => 'testComplete();')); + $this->assertPattern('/^]+type="text\/javascript"[^<>]*>.+<\/script>$/s', $result); + $this->assertPattern('/^]+>\s*' . str_replace('/', '\\/', preg_quote('//')) . '\s*<\/script>$/s', $result); + $this->assertPattern('/^.+\s*' . str_replace('/', '\\/', preg_quote('new Ajax.InPlaceEditor(\'myDiv\', \'/\', {ajaxOptions:{asynchronous:true, evalScripts:true, onComplete:function(request, json) {testComplete();}}});')) . '\s*.+$/s', $result); + + $result = $this->Ajax->editor('myDiv', '/', array('callback' => 'callback();')); + $this->assertPattern('/^]+type="text\/javascript"[^<>]*>.+<\/script>$/s', $result); + $this->assertPattern('/^]+>\s*' . str_replace('/', '\\/', preg_quote('//')) . '\s*<\/script>$/s', $result); + $this->assertPattern('/^.+\s*' . str_replace('/', '\\/', preg_quote('new Ajax.InPlaceEditor(\'myDiv\', \'/\', {callback:function(form, value) {callback();}, ajaxOptions:{asynchronous:true, evalScripts:true}});')) . '\s*.+$/s', $result); + + $result = $this->Ajax->editor('myDiv', '/', array('collection' => array(1 => 'first', 2 => 'second'))); + $this->assertPattern('/^]+type="text\/javascript"[^<>]*>.+<\/script>$/s', $result); + $this->assertPattern('/^]+>\s*' . str_replace('/', '\\/', preg_quote('//')) . '\s*<\/script>$/s', $result); + $this->assertPattern('/^.+\s*' . str_replace('/', '\\/', preg_quote('new Ajax.InPlaceCollectionEditor(\'myDiv\', \'/\', {collection:{"1":"first","2":"second"}, ajaxOptions:{asynchronous:true, evalScripts:true}});')) . '\s*.+$/s', $result); + + $result = $this->Ajax->editor('myDiv', '/', array('var' => 'myVar')); + $this->assertPattern('/^]+type="text\/javascript"[^<>]*>.+<\/script>$/s', $result); + $this->assertPattern('/^]+>\s*' . str_replace('/', '\\/', preg_quote('//')) . '\s*<\/script>$/s', $result); + $this->assertPattern('/^.+\s*' . str_replace('/', '\\/', preg_quote('var myVar = new Ajax.InPlaceEditor(\'myDiv\', \'/\', {ajaxOptions:{asynchronous:true, evalScripts:true}});')) . '\s*.+$/s', $result); + } + function tearDown() { unset($this->Ajax); ClassRegistry::flush(); } } + function restartOb($data) { + var_dump($data); + } ?> \ No newline at end of file diff --git a/cake/tests/lib/cake_test_case.php b/cake/tests/lib/cake_test_case.php index 6ab81f92c..90877f6f1 100644 --- a/cake/tests/lib/cake_test_case.php +++ b/cake/tests/lib/cake_test_case.php @@ -449,7 +449,7 @@ class CakeTestCase extends UnitTestCase { function assertTags($string, $expected, $fullDebug = false) { $regex = array(); $normalized = array(); - foreach ($expected as $key => $val) { + foreach ((array) $expected as $key => $val) { if (!is_numeric($key)) { $normalized[] = array($key => $val); } else {