Since the beginning CakePHP’s support for JavaScript has been with
Prototype/Scriptaculous. While we still think these are
excellent JavaScript libraries, the community has been asking for
support for other libraries. Rather than drop Prototype in favour
of another JavaScript library. We created an Adapter based helper,
and included 3 of the most requested libraries.
Prototype/Scriptaculous, Mootools/Mootools-more, and jQuery/jQuery
UI. While the API is not as expansive as the previous
AjaxHelper we feel that the adapter based solution allows for a
more extensible solution giving developers the power and
flexibility they need to address their specific application needs.
JavaScript Engines form the backbone of the new JsHelper. A
JavaScript engine translates an abstract JavaScript element into
concrete JavaScript code specific to the JavaScript library being
used. In addition they create an extensible system for others to
use.
Using a specific JavaScript engine
First of all download your preferred JavaScript library and place
it in app/webroot/js
Then you must include the library in your page. To include it in
all pages, add this line to the <head> section of
app/View/Layouts/default.ctp
:
echo $this->Html->script('jquery'); // Include jQuery library
Replace jquery
with the name of your library file (.js will be
added to the name).
By default scripts are cached, and you must explicitly print out
the cache. To do this at the end of each page, include this line
just before the ending </body>
tag:
echo $this->Js->writeBuffer(); // Write cached scripts
Warning
You must include the library in your page and print the cache for
the helper to function.
JavaScript engine selection is declared when you include the helper
in your controller:
public $helpers = array('Js' => array('Jquery'));
The above would use the Jquery Engine in the instances of JsHelper
in your views. If you do not declare a specific engine, the jQuery
engine will be used as the default. As mentioned before, there are
three engines implemented in the core, but we encourage the
community to expand the library compatibility.
Using jQuery with other libraries
The jQuery library, and virtually all of its plugins are
constrained within the jQuery namespace. As a general rule,
“global” objects are stored inside the jQuery namespace as well, so
you shouldn’t get a clash between jQuery and any other library
(like Prototype, MooTools, or YUI).
That said, there is one caveat:
By default, jQuery uses “$” as a shortcut for “jQuery”
To override the “$” shortcut, use the jQueryObject variable:
$this->Js->JqueryEngine->jQueryObject = '$j';
echo $this->Html->scriptBlock(
'var $j = jQuery.noConflict();',
array('inline' => false)
);
// Tell jQuery to go into noconflict mode
Using the JsHelper inside customHelpers
Declare the JsHelper in the $helpers
array in your
customHelper:
public $helpers = array('Js');
Note
It is not possible to declare a JavaScript engine inside a custom
helper. Doing that will have no effect.
If you are willing to use an other JavaScript engine than the
default, do the helper setup in your controller as follows:
public $helpers = array(
'Js' => array('Prototype'),
'CustomHelper'
);
Warning
Be sure to declare the JsHelper and its engine on top of the
$helpers
array in your controller.
The selected JavaScript engine may disappear (replaced by the
default) from the JsHelper object in your helper, if you miss to do
so and you will get code that does not fit your JavaScript
library.
JavaScript engine usage
The JsHelper
provides a few methods, and acts as a facade for
the the Engine helper. You should not directly access the Engine
helper except in rare occasions. Using the facade features of the
JsHelper
allows you to leverage the buffering and method
chaining features built-in; (method chaining only works in PHP5).
The JsHelper
by default buffers almost all script code
generated, allowing you to collect scripts throughout the view,
elements and layout, and output it in one place. Outputting
buffered scripts is done with $this->Js->writeBuffer();
this
will return the buffer contents in a script tag. You can disable
buffering wholesale with the $bufferScripts
property or setting
buffer => false
in methods taking $options
.
Since most methods in JavaScript begin with a selection of elements
in the DOM, $this->Js->get()
returns a $this, allowing you to
chain the methods using the selection. Method chaining allows you
to write shorter, more expressive code:
$this->Js->get('#foo')->event('click', $eventCode);
Is an example of method chaining. Method chaining is not possible
in PHP4 and the above sample would be written like:
$this->Js->get('#foo');
$this->Js->event('click', $eventCode);
Common options
In attempts to simplify development where JavaScript libraries can change,
a common set of options is supported by JsHelper
, these common
options will be mapped out to the library specific options
internally. If you are not planning on switching JavaScript
libraries, each library also supports all of its native callbacks
and options.
Callback wrapping
By default all callback options are wrapped with the an anonymous
function with the correct arguments. You can disable this behavior
by supplying the wrapCallbacks = false
in your options array.
Working with buffered scripts
One drawback to previous implementation of ‘Ajax’ type features was
the scattering of script tags throughout your document, and the
inability to buffer scripts added by elements in the layout. The
new JsHelper if used correctly avoids both of those issues. It is
recommended that you place $this->Js->writeBuffer()
at the
bottom of your layout file above the </body>
tag. This will
allow all scripts generated in layout elements to be output in one
place. It should be noted that buffered scripts are handled
separately from included script files.
-
JsHelper::writeBuffer($options = array())
Writes all JavaScript generated so far to a code block or caches
them to a file and returns a linked script.
Options
inline
- Set to true to have scripts output as a script
block inline if cache
is also true, a script link tag will be
generated. (default true)
cache
- Set to true to have scripts cached to a file and
linked in (default false)
clear
- Set to false to prevent script cache from being
cleared (default true)
onDomReady
- wrap cached scripts in domready event (default
true)
safe
- if an inline block is generated should it be wrapped
in <![CDATA[ … ]]> (default true)
Creating a cache file with writeBuffer()
requires that
webroot/js
be world writable and allows a browser to cache
generated script resources for any page.
-
JsHelper::buffer($content)
Add $content
to the internal script buffer.
-
JsHelper::getBuffer($clear = true)
Get the contents of the current buffer. Pass in false to not clear
the buffer at the same time.
Buffering methods that are not normally buffered
Some methods in the helpers are buffered by default. The engines
buffer the following methods by default:
event
sortable
drag
drop
slider
Additionally you can force any other method in JsHelper to use the
buffering. By appending an boolean to the end of the arguments you
can force other methods to go into the buffer. For example the
each()
method does not normally buffer:
$this->Js->each('alert("whoa!");', true);
The above would force the each()
method to use the buffer.
Conversely if you want a method that does buffer to not buffer, you
can pass a false
in as the last argument:
$this->Js->event('click', 'alert("whoa!");', false);
This would force the event function which normally buffers to
return its result.