Permalink
Browse files

Moving JS generating methods to BaseEngine class

Adding duplicate script detection.
  • Loading branch information...
1 parent 2362f28 commit 3e0d6459574210977a735ed82cfa28c7f67233a9 @markstory markstory committed Mar 8, 2009
Showing with 161 additions and 107 deletions.
  1. +54 −44 cake/libs/view/helpers/js.php
  2. +107 −63 cake/tests/cases/libs/view/helpers/js.test.php
@@ -111,7 +111,7 @@ class JsHelper extends AppHelper {
* @var array
* @access private
**/
- var $__includedScriptNames = array();
+ var $__includedScripts = array();
/**
* __objects
*
@@ -170,16 +170,6 @@ function call__($method, $params) {
trigger_error(sprintf(__('JsHelper:: Missing Method %s is undefined', true), $method), E_USER_WARNING);
}
/**
- * Create an alert message in Javascript
- *
- * @param string $message Message you want to alter.
- * @access public
- * @return void
- */
- function alert_($message) {
- return 'alert("' . $this->escape($message) . '");';
- }
-/**
* Returns one or many <script> tags depending on the number of scripts given.
*
* If the filename is prefixed with "/", the path will be relative to the base path of your
@@ -190,9 +180,11 @@ function alert_($message) {
*
* @param mixed $url String or array of javascript files to include
* @param boolean $inline Whether script should be output inline or into scripts_for_layout.
+ * @param boolean $once Whether or not the script should be checked for uniqueness. If true scripts will only be
+ * included once, use false to allow the same script to be included more than once per request.
* @return mixed
**/
- function uses($url, $inline = true) {
+ function uses($url, $inline = true, $once = true) {
if (is_array($url)) {
$out = '';
foreach ($url as $i) {
@@ -204,6 +196,11 @@ function uses($url, $inline = true) {
return;
}
+ if ($once && isset($this->__includedScripts[$url])) {
+ return null;
+ }
+ $this->__includedScripts[$url] = true;
+
if (strpos($url, '://') === false) {
if ($url[0] !== '/') {
$url = JS_URL . $url;
@@ -266,27 +263,7 @@ function if_($if, $then, $else = null, $elseIf = array()) {
return $out;
}
-/**
- * Create a confirm() message
- *
- * @param string $message Message you want confirmed.
- * @access public
- * @return void
- */
- function confirm_($message) {
- return 'confirm("' . $this->escape($message) . '");';
- }
-/**
- * Create a prompt() Javascript function
- *
- * @param string $message Message you want to prompt.
- * @param string $default Default message
- * @access public
- * @return void
- */
- function prompt_($message, $default = '') {
- return 'prompt("' . $this->escape($message) . '", "' . $this->escape($default) . '");';
- }
+
/*
* Tries a series of expressions, and executes after first successful completion.
* (See Prototype's Try.these).
@@ -340,16 +317,7 @@ function load_($url = null, $options = array()) {
}
return $func;
}
-/**
- * Redirects to a URL
- *
- * @param mixed $url
- * @param array $options
- * @return string
- */
- function redirect_($url = null) {
- return 'window.location = "' . Router::url($url) . '";';
- }
+
/* function get__($name) {
return $this->__object($name, 'id');
@@ -398,10 +366,52 @@ function __construct() {
$this->useNative = function_exists('json_encode');
}
/**
+ * Create an alert message in Javascript
+ *
+ * @param string $message Message you want to alter.
+ * @access public
+ * @return void
+ */
+ function alert($message) {
+ return 'alert("' . $this->escape($message) . '");';
+ }
+/**
+ * Redirects to a URL
+ *
+ * @param mixed $url
+ * @param array $options
+ * @return string
+ */
+ function redirect($url = null) {
+ return 'window.location = "' . Router::url($url) . '";';
+ }
+/**
+ * Create a confirm() message
+ *
+ * @param string $message Message you want confirmed.
+ * @access public
+ * @return void
+ */
+ function confirm($message) {
+ return 'confirm("' . $this->escape($message) . '");';
+ }
+/**
+ * Create a prompt() Javascript function
+ *
+ * @param string $message Message you want to prompt.
+ * @param string $default Default message
+ * @access public
+ * @return void
+ */
+ function prompt($message, $default = '') {
+ return 'prompt("' . $this->escape($message) . '", "' . $this->escape($default) . '");';
+ }
+/**
* Generates a JavaScript object in JavaScript Object Notation (JSON)
- * from an array
+ * from an array. Will use native JSON encode method if available, and $useNative == true
*
* Options:
+ *
* - prefix - String prepended to the returned data.
* - postfix - String appended to the returned data.
* - stringKeys - A list of array keys to be treated as a string
@@ -92,34 +92,6 @@ function testMethodDispatching() {
$js->someMethodThatSurelyDoesntExist();
}
/**
- * test prompt() creation
- *
- * @return void
- **/
- function testPrompt() {
- $result = $this->Js->prompt('Hey, hey you', 'hi!');
- $expected = 'prompt("Hey, hey you", "hi!");';
- $this->assertEqual($result, $expected);
-
- $result = $this->Js->prompt('"Hey"', '"hi"');
- $expected = 'prompt("\"Hey\"", "\"hi\"");';
- $this->assertEqual($result, $expected);
- }
-/**
- * test alert generation
- *
- * @return void
- **/
- function testAlert() {
- $result = $this->Js->alert('Hey there');
- $expected = 'alert("Hey there");';
- $this->assertEqual($result, $expected);
-
- $result = $this->Js->alert('"Hey"');
- $expected = 'alert("\"Hey\"");';
- $this->assertEqual($result, $expected);
- }
-/**
* test script tag generation
*
* @return void
@@ -130,16 +102,25 @@ function testUses() {
'script' => array('type' => 'text/javascript', 'src' => 'js/foo.js')
);
$this->assertTags($result, $expected);
+
+ $result = $this->Js->uses(array('foobar', 'bar'));
+ $expected = array(
+ array('script' => array('type' => 'text/javascript', 'src' => 'js/foobar.js')),
+ '/script',
+ array('script' => array('type' => 'text/javascript', 'src' => 'js/bar.js')),
+ '/script',
+ );
+ $this->assertTags($result, $expected);
$result = $this->Js->uses('jquery-1.3');
$expected = array(
'script' => array('type' => 'text/javascript', 'src' => 'js/jquery-1.3.js')
);
$this->assertTags($result, $expected);
- $result = $this->Js->uses('/plugin/js/jquery-1.3');
+ $result = $this->Js->uses('/plugin/js/jquery-1.3.2');
$expected = array(
- 'script' => array('type' => 'text/javascript', 'src' => '/plugin/js/jquery-1.3.js')
+ 'script' => array('type' => 'text/javascript', 'src' => '/plugin/js/jquery-1.3.2.js')
);
$this->assertTags($result, $expected);
@@ -148,15 +129,6 @@ function testUses() {
'script' => array('type' => 'text/javascript', 'src' => 'js/scriptaculous.js?load=effects')
);
$this->assertTags($result, $expected);
-
- $result = $this->Js->uses(array('foo', 'bar'));
- $expected = array(
- array('script' => array('type' => 'text/javascript', 'src' => 'js/foo.js')),
- '/script',
- array('script' => array('type' => 'text/javascript', 'src' => 'js/bar.js')),
- '/script',
- );
- $this->assertTags($result, $expected);
$view = new JsHelperView();
ClassRegistry::addObject('view', $view);
@@ -205,45 +177,36 @@ function testAssetTimestamping() {
touch(WWW_ROOT . 'js' . DS. '__cake_js_test.js');
$timestamp = substr(strtotime('now'), 0, 8);
- $result = $this->Js->uses('__cake_js_test');
- $this->assertPattern('/__cake_js_test.js\?' . $timestamp . '[0-9]{2}"/', $result);
+ $result = $this->Js->uses('__cake_js_test', true, false);
+ $this->assertPattern('/__cake_js_test.js\?' . $timestamp . '[0-9]{2}"/', $result, 'Timestamp value not found %s');
Configure::write('debug', 0);
- $result = $this->Js->uses('__cake_js_test');
+ $result = $this->Js->uses('__cake_js_test', true, false);
$this->assertPattern('/__cake_js_test.js"/', $result);
Configure::write('Asset.timestamp', 'force');
- $result = $this->Js->uses('__cake_js_test');
- $this->assertPattern('/__cake_js_test.js\?' . $timestamp . '[0-9]{2}"/', $result);
+ $result = $this->Js->uses('__cake_js_test', true, false);
+ $this->assertPattern('/__cake_js_test.js\?' . $timestamp . '[0-9]{2}"/', $result, 'Timestamp value not found %s');
unlink(WWW_ROOT . 'js' . DS. '__cake_js_test.js');
+ Configure::write('debug', 2);
}
/**
- * test confirm generation
- *
- * @return void
- **/
- function testConfirm() {
- $result = $this->Js->confirm('Are you sure?');
- $expected = 'confirm("Are you sure?");';
- $this->assertEqual($result, $expected);
-
- $result = $this->Js->confirm('"Are you sure?"');
- $expected = 'confirm("\"Are you sure?\"");';
- $this->assertEqual($result, $expected);
- }
-/**
- * test Redirect
+ * test that scripts added with uses() are only ever included once.
*
* @return void
**/
- function testRedirect() {
- $result = $this->Js->redirect(array('controller' => 'posts', 'action' => 'view', 1));
- $expected = 'window.location = "/posts/view/1";';
- $this->assertEqual($result, $expected);
+ function testUniqueScriptInsertion() {
+ $result = $this->Js->uses('foo');
+ $this->assertNotNull($result);
+
+ $result = $this->Js->uses('foo');
+ $this->assertNull($result, 'Script returned upon duplicate inclusion %s');
}
}
+
+
/**
* JsBaseEngine Class Test case
*
@@ -299,6 +262,87 @@ function testEscaping() {
$expected = 'my \\\"string\\\"';
$this->assertEqual($result, $expected);
}
+/**
+ * test prompt() creation
+ *
+ * @return void
+ **/
+ function testPrompt() {
+ $result = $this->JsEngine->prompt('Hey, hey you', 'hi!');
+ $expected = 'prompt("Hey, hey you", "hi!");';
+ $this->assertEqual($result, $expected);
+
+ $result = $this->JsEngine->prompt('"Hey"', '"hi"');
+ $expected = 'prompt("\"Hey\"", "\"hi\"");';
+ $this->assertEqual($result, $expected);
+ }
+/**
+ * test alert generation
+ *
+ * @return void
+ **/
+ function testAlert() {
+ $result = $this->JsEngine->alert('Hey there');
+ $expected = 'alert("Hey there");';
+ $this->assertEqual($result, $expected);
+
+ $result = $this->JsEngine->alert('"Hey"');
+ $expected = 'alert("\"Hey\"");';
+ $this->assertEqual($result, $expected);
+ }
+/**
+ * test confirm generation
+ *
+ * @return void
+ **/
+ function testConfirm() {
+ $result = $this->JsEngine->confirm('Are you sure?');
+ $expected = 'confirm("Are you sure?");';
+ $this->assertEqual($result, $expected);
+
+ $result = $this->JsEngine->confirm('"Are you sure?"');
+ $expected = 'confirm("\"Are you sure?\"");';
+ $this->assertEqual($result, $expected);
+ }
+/**
+ * test Redirect
+ *
+ * @return void
+ **/
+ function testRedirect() {
+ $result = $this->JsEngine->redirect(array('controller' => 'posts', 'action' => 'view', 1));
+ $expected = 'window.location = "/posts/view/1";';
+ $this->assertEqual($result, $expected);
+ }
+/**
+ * testObject encoding with non-native methods.
+ *
+ * @return void
+ **/
+ function testObject() {
+ $this->JsEngine->useNative = false;
+
+ $object = array('title' => 'New thing', 'indexes' => array(5, 6, 7, 8));
+ $result = $this->JsEngine->object($object);
+ $expected = '{"title":"New thing","indexes":[5,6,7,8]}';
+ $this->assertEqual($result, $expected);
+
+ $result = $this->JsEngine->object(array('default' => 0));
+ $expected = '{"default":0}';
+ $this->assertEqual($result, $expected);
+
+ $result = $this->JsEngine->object(array(
+ '2007' => array(
+ 'Spring' => array('1' => array('id' => 1, 'name' => 'Josh'), '2' => array('id' => 2, 'name' => 'Becky')),
+ 'Fall' => array('1' => array('id' => 1, 'name' => 'Josh'), '2' => array('id' => 2, 'name' => 'Becky'))
+ ), '2006' => array(
+ 'Spring' => array('1' => array('id' => 1, 'name' => 'Josh'), '2' => array('id' => 2, 'name' => 'Becky')),
+ 'Fall' => array('1' => array('id' => 1, 'name' => 'Josh'), '2' => array('id' => 2, 'name' => 'Becky')
+ ))
+ ));
+ $expected = '{"2007":{"Spring":{"1":{"id":1,"name":"Josh"},"2":{"id":2,"name":"Becky"}},"Fall":{"1":{"id":1,"name":"Josh"},"2":{"id":2,"name":"Becky"}}},"2006":{"Spring":{"1":{"id":1,"name":"Josh"},"2":{"id":2,"name":"Becky"}},"Fall":{"1":{"id":1,"name":"Josh"},"2":{"id":2,"name":"Becky"}}}}';
+ $this->assertEqual($result, $expected);
+ }
}
?>

0 comments on commit 3e0d645

Please sign in to comment.