From 75026715d153d01742dc37552a6500bf8e30cb7f Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 28 Jul 2009 00:04:43 -0400 Subject: [PATCH] Adding additional tests to Request and updating callback argument list. --- cake/libs/view/helpers/js.php | 51 +++++++++++- cake/libs/view/helpers/prototype_engine.php | 31 +++++++- .../view/helpers/prototype_engine.test.php | 79 ++++++++++++++----- 3 files changed, 140 insertions(+), 21 deletions(-) diff --git a/cake/libs/view/helpers/js.php b/cake/libs/view/helpers/js.php index ed09da2ec..0db3e3c96 100644 --- a/cake/libs/view/helpers/js.php +++ b/cake/libs/view/helpers/js.php @@ -364,6 +364,13 @@ class JsBaseEngineHelper extends AppHelper { **/ var $bufferedMethods = array('event', 'sortable', 'drag', 'drop', 'slider'); +/** + * Contains a list of callback names -> default arguments. + * + * @var array + **/ + var $_callbackArguments = array(); + /** * Constructor. * @@ -872,8 +879,14 @@ class JsBaseEngineHelper extends AppHelper { **/ function _parseOptions($options, $safeKeys = array()) { $out = array(); + $safeKeys = array_flip($safeKeys); + $wrapCallbacks = true; + if (isset($options['wrapCallbacks'])) { + $wrapCallbacks = $options['wrapCallbacks']; + unset($options['wrapCallbacks']); + } foreach ($options as $key => $value) { - if (!is_int($value) && !in_array($key, $safeKeys)) { + if (!is_int($value) && !isset($safeKeys[$key])) { $value = $this->value($value); } $out[] = $key . ':' . $value; @@ -904,6 +917,42 @@ class JsBaseEngineHelper extends AppHelper { return $options; } +/** + * Prepare callbacks and wrap them with function ([args]) { } as defined in + * _callbackArgs array. + * + * @param string $method Name of the method you are preparing callbacks for. + * @param array $options Array of options being parsed + * @param string $callbacks Keys that contain callbacks + * @access protected + * @return array Array of options with callbacks added. + **/ + function _prepareCallbacks($options, $callbacks = array()) { + $wrapCallbacks = true; + if (isset($options['wrapCallbacks'])) { + $wrapCallbacks = $options['wrapCallbacks']; + } + unset($options['wrapCallbacks']); + if (!$wrapCallbacks) { + return $options; + } + + foreach ($callbacks as $callback) { + if (!isset($options[$callback])) { + continue; + } + $args = null; + if (isset($this->_callbackArguments[$callback])) { + $args = $this->_callbackArguments[$callback]; + } + if (empty($args)) { + continue; + } + $options[$callback] = 'function (' . $args . ') {' . $options[$callback] . '}'; + } + return $options; + } + /** * Convert an array of data into a query string * diff --git a/cake/libs/view/helpers/prototype_engine.php b/cake/libs/view/helpers/prototype_engine.php index a959fe4c7..b939c9623 100644 --- a/cake/libs/view/helpers/prototype_engine.php +++ b/cake/libs/view/helpers/prototype_engine.php @@ -69,6 +69,29 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { 'value' => 'sliderValue', ) ); + +/** + * Contains a list of callback names -> default arguments. + * + * @var array + **/ + var $_callbackArguments = array( + 'onSlide' => 'event', + 'onChange' => 'event', + 'onHover' => 'event', + 'onDrop' => 'event', + 'onStart' => 'event', + 'change' => 'event', + 'onDrag' => 'event', + 'onUpdate' => 'event', + 'onEnd' => 'event', + 'onCreate' => 'transport', + 'onComplete' => 'transport', + 'onFailure' => 'response, jsonHeader', + 'onRequest' => 'transport', + 'onSuccess' => 'response, jsonHeader' + ); + /** * Create javascript selector for a CSS rule * @@ -97,7 +120,7 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { * - 'wrap' - Whether you want the callback wrapped in an anonymous function. (defaults true) * - 'stop' - Whether you want the event to stopped. (defaults true) * - * @param string $type Type of event to bind to the current dom id + * @param string $type Type of event to bind to the current 946 id * @param string $callback The Javascript function you wish to trigger or the function literal * @param array $options Options for the event. * @return string completed event handler @@ -201,6 +224,7 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { unset($options['update'], $options['type']); } $callbacks = array('onCreate', 'onComplete', 'onFailure', 'onRequest', 'onSuccess'); + $options = $this->_prepareCallbacks($options, $callbacks); if (isset($options['dataExpression'])) { $callbacks[] = 'parameters'; unset($options['dataExpression']); @@ -223,6 +247,7 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { function sortable($options = array()) { $options = $this->_mapOptions('sortable', $options); $callbacks = array('onStart', 'change', 'onDrag', 'onDrop', 'onChange', 'onUpdate', 'onEnd'); + $options = $this->_prepareCallbacks($options, $callbacks); $options = $this->_parseOptions($options, $callbacks); if (!empty($options)) { $options = ', {' . $options . '}'; @@ -241,6 +266,7 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { function drag($options = array()) { $options = $this->_mapOptions('drag', $options); $callbacks = array('onStart', 'change', 'onDrag', 'onEnd'); + $options = $this->_prepareCallbacks($options, $callbacks); $options = $this->_parseOptions($options, $callbacks); if (!empty($options)) { $options = ', {' . $options . '}'; @@ -262,6 +288,7 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { function drop($options = array()) { $options = $this->_mapOptions('drop', $options); $callbacks = array('onHover', 'onDrop'); + $options = $this->_prepareCallbacks($options, $callbacks); $options = $this->_parseOptions($options, $callbacks); if (!empty($options)) { $options = ', {' . $options . '}'; @@ -284,6 +311,8 @@ class PrototypeEngineHelper extends JsBaseEngineHelper { $callbacks = array('onSlide', 'onChange'); $options = $this->_mapOptions('slider', $options); + $options = $this->_prepareCallbacks($options, $callbacks); + if (isset($options['min']) && isset($options['max'])) { $options['range'] = array($options['min'], $options['max']); unset($options['min'], $options['max']); diff --git a/cake/tests/cases/libs/view/helpers/prototype_engine.test.php b/cake/tests/cases/libs/view/helpers/prototype_engine.test.php index 4819c3827..d68f5668c 100644 --- a/cake/tests/cases/libs/view/helpers/prototype_engine.test.php +++ b/cake/tests/cases/libs/view/helpers/prototype_engine.test.php @@ -30,6 +30,7 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { function startTest() { $this->Proto =& new PrototypeEngineHelper(); } + /** * end test * @@ -38,6 +39,7 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { function endTest() { unset($this->Proto); } + /** * test selector method * @@ -47,27 +49,28 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $result = $this->Proto->get('#content'); $this->assertEqual($result, $this->Proto); $this->assertEqual($this->Proto->selection, '$("content")'); - + $result = $this->Proto->get('a .remove'); $this->assertEqual($result, $this->Proto); $this->assertEqual($this->Proto->selection, '$$("a .remove")'); - + $result = $this->Proto->get('document'); $this->assertEqual($result, $this->Proto); $this->assertEqual($this->Proto->selection, "$(document)"); - + $result = $this->Proto->get('window'); $this->assertEqual($result, $this->Proto); $this->assertEqual($this->Proto->selection, "$(window)"); - + $result = $this->Proto->get('ul'); $this->assertEqual($result, $this->Proto); $this->assertEqual($this->Proto->selection, '$$("ul")'); - + $result = $this->Proto->get('#some_long-id.class'); $this->assertEqual($result, $this->Proto); $this->assertEqual($this->Proto->selection, '$$("#some_long-id.class")'); } + /** * test event binding * @@ -87,6 +90,7 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $expected = "\$(\"myLink\").observe(\"click\", function (event) {event.stop();\nElement.hide(this);});"; $this->assertEqual($result, $expected); } + /** * test dom ready event creation * @@ -97,6 +101,7 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $expected = 'document.observe("dom:loaded", function (event) {foo.name = "bar";});'; $this->assertEqual($result, $expected); } + /** * test Each method * @@ -108,6 +113,7 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $expected = '$$("#foo li").each(function (item, index) {item.hide();});'; $this->assertEqual($result, $expected); } + /** * test Effect generation * @@ -126,11 +132,11 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $result = $this->Proto->effect('fadeIn'); $expected = '$("foo").appear();'; $this->assertEqual($result, $expected); - + $result = $this->Proto->effect('fadeIn', array('speed' => 'fast')); $expected = '$("foo").appear({duration:0.50000000000});'; $this->assertEqual($result, $expected); - + $result = $this->Proto->effect('fadeIn', array('speed' => 'slow')); $expected = '$("foo").appear({duration:2});'; $this->assertEqual($result, $expected); @@ -138,11 +144,11 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $result = $this->Proto->effect('fadeOut'); $expected = '$("foo").fade();'; $this->assertEqual($result, $expected); - + $result = $this->Proto->effect('fadeOut', array('speed' => 'fast')); $expected = '$("foo").fade({duration:0.50000000000});'; $this->assertEqual($result, $expected); - + $result = $this->Proto->effect('fadeOut', array('speed' => 'slow')); $expected = '$("foo").fade({duration:2});'; $this->assertEqual($result, $expected); @@ -163,6 +169,7 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $expected = 'Effect.slideUp($("foo"), {duration:2});'; $this->assertEqual($result, $expected); } + /** * Test Request Generation * @@ -179,7 +186,8 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { 'before' => 'doBefore', 'success' => 'doSuccess', 'error' => 'doError', - 'data' => array('name' => 'jim', 'height' => '185cm') + 'data' => array('name' => 'jim', 'height' => '185cm'), + 'wrapCallbacks' => false )); $expected = 'var jsRequest = new Ajax.Request("/posts/view/1", {method:"post", onComplete:doComplete, onCreate:doBefore, onFailure:doError, onSuccess:doSuccess, parameters:{"name":"jim","height":"185cm"}});'; $this->assertEqual($result, $expected); @@ -191,7 +199,8 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $result = $this->Proto->request('/people/edit/1', array( 'method' => 'post', 'complete' => 'doSuccess', - 'update' => '#update-zone' + 'update' => '#update-zone', + 'wrapCallbacks' => false )); $expected = 'var jsRequest = new Ajax.Updater("update-zone", "/people/edit/1", {method:"post", onComplete:doSuccess});'; $this->assertEqual($result, $expected); @@ -201,22 +210,35 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { 'complete' => 'doSuccess', 'error' => 'handleError', 'type' => 'json', - 'data' => array('name' => 'jim', 'height' => '185cm') + 'data' => array('name' => 'jim', 'height' => '185cm'), + 'wrapCallbacks' => false )); $expected = 'var jsRequest = new Ajax.Request("/people/edit/1", {method:"post", onComplete:doSuccess, onFailure:handleError, parameters:{"name":"jim","height":"185cm"}});'; $this->assertEqual($result, $expected); - + $result = $this->Proto->request('/people/edit/1', array( 'method' => 'post', 'complete' => 'doSuccess', 'error' => 'handleError', 'type' => 'json', 'data' => '$("element").serialize()', - 'dataExpression' => true + 'dataExpression' => true, + 'wrapCallbacks' => false )); $expected = 'var jsRequest = new Ajax.Request("/people/edit/1", {method:"post", onComplete:doSuccess, onFailure:handleError, parameters:$("element").serialize()});'; $this->assertEqual($result, $expected); + + $result = $this->Proto->request('/people/edit/1', array( + 'method' => 'post', + 'before' => 'doBefore();', + 'success' => 'doSuccess();', + 'complete' => 'doComplete();', + 'error' => 'handleError();', + )); + $expected = 'var jsRequest = new Ajax.Request("/people/edit/1", {method:"post", onComplete:function (transport) {doComplete();}, onCreate:function (transport) {doBefore();}, onFailure:function (response, jsonHeader) {handleError();}, onSuccess:function (response, jsonHeader) {doSuccess();}});'; + $this->assertEqual($result, $expected); } + /** * test sortable list generation * @@ -229,10 +251,12 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { 'start' => 'onStart', 'complete' => 'onComplete', 'sort' => 'onSort', + 'wrapCallbacks' => false )); $expected = 'var jsSortable = Sortable.create($("myList"), {onChange:onSort, onStart:onStart, onUpdate:onComplete, snap:5});'; $this->assertEqual($result, $expected); } + /** * test drag() method. Scriptaculous lacks the ability to take an Array of Elements * in new Drag() when selection is a multiple type. Iterate over the array. @@ -243,23 +267,26 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $this->Proto->get('#element'); $result = $this->Proto->drag(array( 'start' => 'onStart', - 'drag' => 'onDrag', + 'drag' => 'onDrag', 'stop' => 'onStop', 'snapGrid' => array(10, 10), + 'wrapCallbacks' => false )); $expected = 'var jsDrag = new Draggable($("element"), {onDrag:onDrag, onEnd:onStop, onStart:onStart, snap:[10,10]});'; $this->assertEqual($result, $expected); - + $this->Proto->get('div.dragger'); $result = $this->Proto->drag(array( 'start' => 'onStart', - 'drag' => 'onDrag', + 'drag' => 'onDrag', 'stop' => 'onStop', 'snapGrid' => array(10, 10), + 'wrapCallbacks' => false )); $expected = '$$("div.dragger").each(function (item, index) {new Draggable(item, {onDrag:onDrag, onEnd:onStop, onStart:onStart, snap:[10,10]});});'; $this->assertEqual($result, $expected); } + /** * test drop() method * @@ -269,12 +296,14 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { $this->Proto->get('#element'); $result = $this->Proto->drop(array( 'hover' => 'onHover', - 'drop' => 'onDrop', - 'accept' => '.drag-me' + 'drop' => 'onDrop', + 'accept' => '.drag-me', + 'wrapCallbacks' => false )); $expected = 'Droppables.add($("element"), {accept:".drag-me", onDrop:onDrop, onHover:onHover});'; $this->assertEqual($result, $expected); } + /** * ensure that slider() method behaves properly * @@ -288,10 +317,22 @@ class PrototypeEngineHelperTestCase extends CakeTestCase { 'change' => 'onChange', 'complete' => 'onComplete', 'value' => 4, + 'wrapCallbacks' => false )); $expected = 'var jsSlider = new Control.Slider($("handle"), $("element"), {axis:"horizontal", onChange:onComplete, onSlide:onChange, sliderValue:4});'; $this->assertEqual($result, $expected); + + $this->Proto->get('#element'); + $result = $this->Proto->slider(array( + 'handle' => '#handle', + 'change' => 'change();', + 'complete' => 'complete();', + 'value' => 4 + )); + $expected = 'var jsSlider = new Control.Slider($("handle"), $("element"), {onChange:function (event) {complete();}, onSlide:function (event) {change();}, sliderValue:4});'; + $this->assertEqual($result, $expected); } + /** * test the serializeForm implementation. *