Tag: cakephp jquery

Speed things up with a custom-baked JSON view

Yet another gem of brilliance from Mr. jrbasso.

In a couple of my previous posts regarding CakePHP and JQuery, I’ve shown some basic strategies on setting up the communication between the client and the server.

This post, as one can guess from the title, is going to be more about optimization and making things run smoother and faster while respecting MVC and CakePHP’s methodologies.

Let’s consider a typical scenario… Somewhere in your application’s UI, a user will click an element such as a button, a link or what have ya, which will issue an AJAX request to the server. The response expected by the client (browser) will be a JSON object. (Yep, sounds like this has been done once or twice before…)

In order to respect MVC you’d usually create a controller action to process the AJAX request, perhaps grab some data from the DB and then create a view to output the JSON object.
While this is a proper approach to achieve the task at hand, one can certainly consider the overhead caused by loading the View object, the helpers and other “goodness” that comes with the typical MVC request.
Right away it becomes desirable to just echo out a json_encode()’d string right from your controller. But… whoa… I know that you’d never do something so offensive to the MVC paradigm ;)

Instead, let’s reach a middle ground… we don’t have to break MVC or cake, yet we’ll see how to make our custom JSON view act faster and more robustly.

First, we’ll make up a simple controller action such as the one here:

public function get_json_info() {
    $this->view = 'Json';
    $info = $this->MyModel->getSomeInfo();
    $json = array(
      'variableOne' => $info['some_var'],
      'variableTwo' => $info['another_var']
    );
    $this->set(compact('json'));
  }

As you see this is a totally bogus action, but it works in the same manner as you’d expect many controller actions to work when returning some JSON data.
There are two important things going on here, nonetheless:
1. $this->view = ‘Json’; instructs cake to use our custom JSON view, rather than a standard view class.
2. We’ve created a $json array with some data and set() it to be used by the view.

Now we can finally move on to look at our custom view class.
Create a file called json.php and place it in your app/views/ directory.

This particular implementation comes with a nice, little bonus. If you use Mark Story’s Debug Kit, this custom JSON view will ensure that it is working properly and doesn’t break anything as this tool is quite indispensable for many developers. For those who do not use Debug Kit at all, first you should :), and second you can make the view object even lighter by taking out the Debug Kit specific code (but that is something for your to play with).

Hopefully I didn’t mislead anyone with the title of the post, by making you think that you can “bake” such a view using the console tool. To make up for this, I offer a copy & paste solution instead ;)

Well here’s the little guy in all its glory:

<?php

class JsonView extends View {
  var $content = null;
  var $debugKit = null;

  function __construct(&$controller, $register = true) {
    if (is_object($controller) && isset($controller->viewVars['json'])) {
      if (isset($controller->helpers['DebugKit.Toolbar'])) {
        $this->debugKit = $controller->helpers['DebugKit.Toolbar'];
        parent::__construct($controller, $register);
      }
      $this->content = $controller->viewVars['json'];
    }
    if ($register) {
      ClassRegistry::addObject('view', $this);
    }
    Configure::write('debug', 0);
  }

  function render($action = null, $layout = null, $file = null) {
    if ($this->debugKit !== null) {
      DebugKitDebugger::startTimer('viewRender', __d('debug_kit', 'Rendering View', true));
      $this->loaded = $this->_loadHelpers($this->loaded, array('DebugKit.toolbar' => $this->debugKit, 'DebugKit.simpleGraph', 'html', 'number'));
      $this->_triggerHelpers('beforeRender');
    }

    if ($this->content === null) {
      $data = '';
    } else {
      $data = json_encode($this->content);
    }

    if ($this->debugKit !== null) {
      $this->_triggerHelpers('afterRender');

      DebugKitDebugger::stopTimer('viewRender');
      DebugKitDebugger::stopTimer('controllerRender');
      DebugKitDebugger::setMemoryPoint(__d('debug_kit', 'View render complete', true));

      $backend = $this->loaded['toolbar']->getName();
      $this->loaded['toolbar']->{$backend}->send();
    }

    return $data;
  }
}

As you see, our JsonView is a child of CakePHP’s core View class. It implements and overrides a couple of methods and does so in a much lighter fashion.

Just a few things to point out:

  • $this->content = $controller->viewVars['json'];
  • remember our bogus action where we’ve set() $json var for the view? Well, this is exactly what the view is going to expect to transform into the JSON object.

  • It does so quite easily: $data = json_encode($this->content);

And there you have it… light and speedy, not too greedy ;) Perfectly optimized for JSON output.
Enjoy.

Helpful jQuery modals

This post is actually mostly about jQuery (with some cake sprinkles), but why not…

Let’s examine a typical situation:

We have a Product model, which belongsTo a Category model.

Now we need to add some products…

An admin interface would have a category select input (or drop-down) and a few form fields to fill-in some product details. Happily, we venture to add our first product, only to realize that we have not yet created any categories… backtracking to create a category would be a shame and with a little help from jQuery we can easily solve this problem.

One state that developers rarely consider during (and after) development, is the “blank” state of the application, which in turn can lead to some unexpected behavior…

The goal is to do the following:

  1. Get to the www.example.com/products/add page
  2. Using jQuery, “realize” that our Category drop-down is empty
  3. Prompt the user through… “lightwindow-modal-jquery-ui-dialog”… To create at least one category, so we could get moving
  4. Refresh the product/add page with the newly created category neatly in place within the select input

Since I use jQuery extensively, I am going to pick jQuery UI’s dialog widget to accomplish my needs. (It may not be the most robust or feature-rich, but it plays nice with the jQuery core… and does what I need).

(It goes without saying that you should include jQuery core and jQuery UI libraries… load them from Google, if you’d like).

Anyway…
First, let’s take a look at the products/add view:

<?php $this->Html->script('jquery.form.js', array('inline' => FALSE)); ?>
<?php $this->Html->script('parent_list.js', array('inline' => FALSE)); ?>
<?php $this->Html->css(array('smoothness/jquery'), NULL, array('inline' => FALSE)); ?>

<div>
  <?php
    echo $this->Form->create('Product');
    echo $this->Form->input('category_id', array('class' => 'parent-list'));
    echo $this->Form->input('name');
    echo $this->Form->end('Add product');
  ?>
</div>

<div id=&quot;category-form&quot;>
  <?php
    echo $this->Form->create('Category', array('action' => 'add'));
    echo $this->Form->input('name');
    echo $this->Form->end('Create category');
  ?>
</div>

Stepping through the code, the first thing we see is the jquery.form plugin. This will be used for submitting the “category add” form via AJAX, from the modal. (Will show that later on).
Next, we load parent_list.js, which is going to handle most of the magic.
Finally, in the view we have a div category-form (which will be turned by jQuery UI into a dialog/modal).

As you can see both forms are very simple, for purpose of this example.

Now, let’s see the jQuery file, which does all the heavy lifting:

[javascript]
(function ($) {
var getModal = function () {
$(‘#category-form’).dialog({
modal: true,
autoOpen: false,
title: ‘Create a category’
});

if($(‘.parent-list’).children().size() === 0) {
$(‘#category-form’).dialog(‘open’);
}
};

var showResponse = function (response) {
if(response == ‘saved’) {
$(‘#category-form’).dialog(‘close’);
window.location.reload();
}
};

$(document).ready(function() {
getModal();

var submitOptions = {
success: showResponse,
dataType: ‘json’
};

$(‘#CategoryAddForm’).ajaxForm(submitOptions);
});
}(jQuery));
[/javascript]

This is more JavaScript/jQuery than I usually show, so let’s take a look at some interesting things.
First, you’ll notice that the entire code is wrapped into a “self-calling anonymous function”. To keep things simple, the two benefits of using such pattern is to avoid conflicts and global vars (although it is not evident from this example, but a little googlin’ will explain things in more detail).

Next, notice the function declarations: var getModal = function () … by using such assignment we avoid a couple of problems in everybody’s favorite IE (the above method will define the function at parse-time, rather than run-time). It also kind of “forces” the developer to declare and call things in proper sequence without hoping that the browser might pick up some of the slack, where developer was careless. At any rate, run your JavaScript through JSLint before going to production ;)

Now that the general stuff is out of the way, let’s see the “most important” line of code:
if($(‘.parent-list’).children().size() === 0)
The above will check the category select input (i.e. parent of the product) to see if it has any options (options are children of the category select in this case). If not, the jQuery goodness kicks in and we get a modal/dialog which displays the category add form, as you saw from the products/add view above.

Once the name is entered and submitted via AJAX, I send back “saved” from the server as a response (assuming that all goes well). At which point we close the dialog and refresh the page. Now, we have our newly added category as one of the options… and can continue to add the product without backtracking to create a category in some other UI.

Hopefully this serves as a decent example on how to build a much more intelligent UI and improve user experience, with the help from the lovely jQuery and CakePHP.

Solving the country/state problem with CakePHP and jQuery

I’d say that it is a pretty common issue (and maybe not quite “a problem”), where you would have a page with a billing form, which in turn, has a “Country” select as well as a “State” select.
Obviously not all countries have states, and thus comes the question of how to handle the situation.

Before going much further, I’d like to say that the whole point of the post is to show a solution to the common problem, but by no means it is the de facto standard of handling the form fields (as a matter of fact, I’ll say that there simply isn’t one).
If you consider every billing form that you’ve had to fill out in your internet life, each one, most likely, behaved differently in some way from the others.
Country, for which the application is purposed, and thus the target audience, not to mention the specific business needs of the application should guide the actual implementation.

For this example, we’ll do something like this:

  1. If selected country is “US” show the select input with the states
  2. For any other country change the select to a text input (allowing the user to enter what they please, if required)

Hmmm… a seemingly simple solution quite often requires a little bit of hackery. Or does it?
For security (or browser-related) reasons you cannot change an input type on the fly, otherwise it would be a perfectly reasonable thing to do.

… So how, after all, do we tackle this with cake and jQuery, without hacking around the problem?

First let’s consider this little snippet of a CakePHP form (view):

<div id=&quot;state-wrapper&quot;>
  <?php echo $this->Form->input('state', array('id' => 'state-select')); ?>
  <?php echo $this->Form->input('state', array('type' => 'text', 'id' => 'state-text')); ?>
</div>

As you see we have two nearly identical inputs. (Please note the different DOM id’s for later).
Also, you can guess which one is the select and which one will be a text input ;)

Now comes the fun jQuery code:

[javascript]
$(document).ready(function() {
stateText = $(‘#state-text’).detach();
stateSelect = $(‘#state-select’).detach();

checkSelected(stateText, stateSelect);

$(‘#country-select’).change(function() {
checkSelected(stateText, stateSelect);
});
});

function checkSelected(stateText, stateSelect) {
if ($(‘#country-select’).val() != ‘US’) {
stateText.appendTo(‘#state-wrapper’);
stateSelect.detach();
} else {
stateSelect.appendTo(‘#state-wrapper’);
stateText.detach();
}
}
[/javascript]

Let’s take a closer look at this…
Upon the initial load of the page we detach() both the select and text inputs from the DOM.

First of all… what is detach()?
Yet, another beauty of jQuery, which was introduced sometime in 1.4.
The detach() method actually removes the element from the DOM… but (unlike a more common remove()) it keeps all the element’s properties, data, associated jQuery events and everything else that comes with it. This allows us to later inject the “detached” element, as though it never “left”, back into the DOM.

So, once both elements are “detached”, we go ahead and check the currently selected country.
Here, the code should be pretty simple:

  1. If country does not equal “US”, show (via appendTo()) the text input
  2. Otherwise, show the select input (with all the pre-loaded states, as they were before the “detachment”).

Ah, The power of jQuery.

p.s. A more elegant solution would be to keep a list of states/provinces/regions/etc. for alll countries, which require one.
With that we could populate the state select via AJAX once such country is selected… or remove the field altogether. Surely this option would provide more consistency and data integrity, but introduce a bit of maintenance overhead. However, I’ve already showed this approach in an older post, so we’ll just leave things a little different and simpler this time.

Convention over Configuration – what's the big deal?

While writing a little about jQuery and CakePHP (part 1 and part 2), which I promise I am not quite done with yet…

… another topic slowly entered my brain…

Why do we love CakePHP so much? (And why do others equally hate it for the same reason?)

Here’s what our dear wikipedia had to say about this:

Convention over Configuration (aka Coding by convention) is a software design paradigm which seeks to decrease the number of decisions that developers need to make, gaining simplicity, but not necessarily losing flexibility.

In other words, for those who are lazy, like me, Convention over Configuration can make life so much easier and all one has to do in exchange is to follow a few simple rules (AKA conventions).

So let’s take a look at a practical (albeit a very simple) example of how Convention over Configuration can make your code do all… those nice things that wikipedia talks about.

Without wasting anymore time, let’s take a look at this tiny code snippet that I often use in my views:

 $javascript->link('jquery/page_specific/beers_view_beer', false);

If you haven’t read the previous posts, let me briefly explain what’s happening. In using jQuery many of my pages require view or page-specific jQuery files to be loaded.

Now that’s all nice and well… but whoa… seems like a lot of typing to me. No?

Wouldn’t it be nicer if I could just do:

 $jsManager->myJs();

And it would automagically load the appropriate jQuery file for the given page?

Well, you’ve probably noticed that I do use a Convention in the way I name the JS files:

1. Controller name = “beers”
2. Underscore
3. Action name = “view_beer”

Now, I’m not forcing my conventions onto you, but simply pointing out that having some sort of convention for naming your JavaScript files could come in handy, and that’s not something that is talked about very often.

Following this convention I can write a tiny helper that will handle the file includes for me, rather than me having to type out an entire path (oh no!).

So, let’s make the little helper js_manager.php (in our app/views/helpers directory):

<?php

class JsManagerHelper extends AppHelper {

    var $helpers = array('Javascript');

    //where's our jQuery path relevant to CakePHP's JS dir?
    var $_jqueryPath = 'jquery';

    //where do we keep our page/view relevant scripts?
    var $_pageScriptPath = 'page_specific';

    function myJs() {
      return $this->Javascript->link($this->_jqueryPath . '/' .
                                     $this->_pageScriptPath .'/' .
                                     $this->params['controller'] . '_' .
                                     $this->params['action'], false);
    }

}

?>

And that’s all there is to it.

Whenever I use $jsManager->myJs();, the helper will find and include the file based on the Convention specified by the three simple rules listed above. I hope the code is simple enough so that you can see exactly how it works.

Of course, I did a lot more typing by writing a helper… but if I’ve got an app with 700 views, it might come in quite handy in the long run. Not to mention, if for whatever reason I decide to change the ‘page_specific’ path name to something else, the change will be a lot easier to handle.

Granted this is a very simple example, but I hope it provides some insight as to why so many developers have embraced the Convention over Configuration paradigm.

And to summarize: learn the conventions (or make your own) and in the long run make your life easier (just like wikipedia promised)!

JQuery in the CakePHP world (part 2 – is client side code all that great?)

(part 1)

Now, how is this an introduction to jQuery + CakePHP?… well, let’s see in a minute.

First, I’d like to say that with the advent of frameworks such as jQuery, better browsers, which do a nicer job of supporting standards, and even faster PC’s and larger/better monitors, we can happily write better client-side code.

Meaning the following rules are slightly not as important anymore:

  1. A client’s browser may not support my code
  2. A client is not fast enough to process the code
  3. A client is never to be trusted

While the first two rules are becoming less and less applicable, the third one stays true for a while (and for a good reason).

Where does it come into play?

For purposes of this topic, and I can imagine many other cases, where it would be true, we’ll say “Data Validation”.

Indeed, if you validate data on the client-side only, you are running into a serious risk of getting some “really bad” data. So, always double-check the data on the server (that’s a rule that should rarely be bent).

The good news is that nothing is stopping us from doing data validation on the client, the server and might even throw in a little AJAX.

So, with that little foreword let’s see how we can do jQuery-based field validation, using CakePHP’s model validation rules.
(Worth to note, that there is an excellent jQuery plug-in, which is made to work with CakePHP that does great client/server validation for you, but this is an intro, so we’ll just take a look at some basics).

Let’s start with our typical User Model.
We’ll do a very simple validation to keep the code from getting obnoxious:

    class User extends AppModel {

          var $name = 'User';

          var $validate = array('username'=>
                                  array('rule'=>'isUnique',
                                          'message'=>'Sorry, this username already exists'));

    }

We’ll do one single check, whether or not the “username” field is unique. (Nothing unusual so far).

Let’s do a simple view (add.ctp):

<?php
    //let's load up the jQuery core
    echo $javascript->link('jquery/jquery.min', false);

    //and now... some file that will be specific to this view (page)
    echo $javascript->link('jquery/page_specific/users_add', false);
?>

<?php echo $form->create(); ?>
<?php echo $form->input('username', array('id'=>'username')); ?>
<?php echo $form->input('some_other_field'); ?>
<?php echo $form->end('Add User'); ?>

If you haven’t read part 1 (or haven’t worked much with JS/jQuery), some of this might get a little confusing. So I urge you
to do so and then come back.

Anyways, the only thing of interest here is the fact that I gave the “username” field an ID, that’s different from defau< array(‘id’=>’username’), the default DOM ID would be “UserUsername” (i.e. Camel-cased model and field name), but this is different than the field in the DB and what a model would expect. So this is just a little preparation to make our lives easier down the road.

Now comes our jQuery code, which is users_add.js:

[sourcecode language="javascript"]
$(document).ready( function() {

$(‘#username’).blur( function () {

fieldName = $(this).attr(‘id’);
fieldValue = $(this).val();

$.post(‘/users/ajax_validate’, {
field: fieldName,
value: fieldValue
},
function(error) {

if(error.length != 0) {

$(‘#username’).after(‘

‘ + error + ‘

‘);
}
else {
$(‘#’ + fieldName + ‘-exists’).remove();
}
});
});

});

[/cc]

To make the long story short, we post our field name (username) and our value (whatever it happens to be) to our User’s controller ajax_validate action. This only happens when the “username” field loses focus $(‘#username’).blur(… either by the user clicking away with the mouse or tabbing onto “some_other_field”.

So, we are going to let the user know that the username might be already taken while she is filling out the rest of the form.

Let’s use our Model’s validation rule and some good ol’ controller logic to get this working…

class UsersController extends AppController {

      var $name = 'Users';

      function add() {
          if(!empty($this->data)) {
              $this->User->save($this->data);
          }
      }

      function ajax_validate() {
          Configure::write('debug', 0);

          if($this->RequestHandler->isAjax()) {

              $this->data['User'][$this->params['form']['field']] = $this->params['form']['value'];

              $this->User->set($this->data);

              if($this->User->validates()) {
                  $this->autoRender = false;
              }
              else {
                 $errorArray = $this->validateErrors($this->User);

                 $this->set('error', $errorArray[$this->params['form']['field']]);
              }
          }
      }
    }

You can happily skip the add() action, since you’ve seen an example of that about a million times already.

Let’s look at our ajax_validate()
(By the way don’t forget to add var $components = array(’RequestHandler’); to your app controller or Users controller, as one of my kind readers had pointed out).

First, we create the data ($this->data['User']['username']) array to validate…
$this->data['User'][$this->params['form']['field']] = $this->params['form']['value'];

Remember, that our $this->params['form']['field'] and $this->params['form']['value'] come from jQuery. And because we gave the field the right ID the $this->params['form']['field'] can be applied to any field, thus making it all pretty dynamic (and the data array is built exactly as CakePHP would expect).

So then, we simply attempt to validate the data, as often with $this->User->validates().

In case it does, we need not return or render anything. (You could, but for this example we’ll keep it simple). The idea is that if the “username” is unique, there isn’t effectively anything further that needs to be done.

On the other hand, if the “username” is not unique, we extract the error message and set it for the view, to return back to our jQuery.

In this case we simply return the string, that was defined in our model. (‘Sorry, this username already exists’). You can return xml, JSON or whatever else… again keeping things simple.

Alright, we do need some view to “display” (in proper terms return) the error message back to jQuery script.

Here it is (ajax_validate.ctp):

<?php
    echo $error;
?>

Whew…

Now let’s take another look at a part of our jQuery code:

[sourcecode language="javascript"]

function(error) {

if(error.length != 0) {
$(‘#username’).after(‘

‘ + error + ‘

‘);
}
else {
$(‘#’ + fieldName + ‘-exists’).remove();
}
}
[/cc]

If anything came back from our ajax_validate() action, we add a div with the error message”

[sourcecode language="javascript"]
$(‘#username’).after(‘

‘ + error + ‘

‘);
[/cc]

If the user corrects the error, we happily remove the div from the DOM and… be done with it!

JQuery autocomplete in CakePHP

This is a quick example on how to setup an autocomplete field using JQuery and CakePHP.

Let’s assume that we have a Product model and products controller. Our goal is to allow the user to type in a few characters and then to display a matching list of products from the DB by using autocomplete.

First things first, be sure that you’ve included the JQuery library. If you are using $scripts_for_layout, then in your view file you’d probably do something like: $javascript->link(‘jquery/jquery.min’, false);
Next, you have to include the autocomplete plugin… There are a few of them out there.
Well, this one does the trick for me: http://www.pengoworks.com/workshop/jquery/autocomplete.htm

(Please refer to the documentation at the link above for details on how the JQuery autocomplete works and for an example of what it looks like. You can also grab the relevant CSS and the loader image from there).

After you save it somewhere in your JS directory (perhaps js/jquery/plugins) you should include it in the view just like this: $javascript->link(‘jquery/plugins/autocomplete’, false);

Now you need the form field that will be used as an autocomplete field. The plugin, by default, will expect a field with an id = “autoComplete”. So, as part of your form, you’ll probably do something like

[sourcecode language='php']
text(‘Product.name’, array(‘size’=>’30′, ‘id’=>’autoComplete’)); ?>
[/cc]

(Remember that we are assuming the Product model here)

Not too bad, so far. Alright, now we have to trigger the autocomplete by creating some JavaScript that will actually attach the autocomplete action to your form element.
Make a new JS file and call it autocompleteAction.js (don’t forget to also include it in the view).

Here’s what it should look like:

[sourcecode language='jscript']
$(document).ready(function(){
$(“#autoComplete”).autocomplete(“/products/autoComplete”,
{
minChars: 2,
cacheLength: 10,
onItemSelect: selectItem,
onFindValue: findValue,
formatItem: formatItem,
autoFill: false
});
});

function selectItem(li) {
findValue(li);
}

function findValue(li) {
if( li == null ) return alert(“No match!”);

// if coming from an AJAX call, let’s use the product id as the value
if( !!li.extra ) var sValue = li.extra[0];

// otherwise, let’s just display the value in the text box
else var sValue = li.selectValue;

alert(“The value you selected was: ” + sValue);
}

function formatItem(row) {
if(row[1] == undefined) {
return row[0];
}
else {
return row[0] + ” (id: ” + row[1] + “)”;
}
}

[/cc]

Just to cover the basics, the above action will tell the autocomplete to kick-in after you’ve typed two characters into your form field (minChars: 2). The lineSeparator: “^” tells autocomplete to jump onto the next line whenever it encounters the ^ character. I will explain this a little more later. It is worth noting that the default new line character is “\n”, but I could not get it to work with CakePHP so I’ve decided to use a somewhat obscure character instead, which is unlikely to appear in a product name. This is not a very good solution by any means and someday I will come back to figuring it out. (Update: this works just fine now, so no longer such trickery as I’ve used before is required).

So what’s going on here? Well, the autocomplete needs to get the list of available items (products in our case) somewhere, and this code tells it exactly where to look: autocomplete(“/products/autoComplete”… You’ve probably guessed that in terms of CakePHP you need to have a products controller and an autoComplete action. Now is a a good time to create one.

It should look something like:

[sourcecode language='html']
function autoComplete() {

Configure::write(‘debug’, 0);
$this->layout = ‘ajax’;

$products = $this->Product->find(‘all’, array(
‘conditions’=>array(‘Product.name LIKE’=>$this->params['url']['q'].’%'),
‘fields’=>array(‘name’, ‘id’)));

$this->set(‘products’, $products);
}
[/cc]

So basically we are looking for all products who’s name matches (LIKE) the two characters that we’ve typed in the form field. We are returning a product name and product id fields from the DB. Note the: $this->params['url']['q']. The autocomplete plugin uses the GET method to pass the form data to your controller and it expects to have a q= as the query string, and that’s how you read that query string in CakePHP. Now we’ve found some products and set the resulting array for the view. The view will actually be the list that pops under the text field once you start typing. Let’s create one (auto_complete.ctp):

[sourcecode language='html']
if(!empty($products)) {
foreach($products as $product) {
echo $product['Product']['name']. ‘|’ .$product['Product']['id'] . “\n”;
}
}
else {
echo ‘No results’;
}

[/cc]

Here we are looping through the products array and displaying the name and the id, of course if the array happens to be empty we will display ‘No results’.

That’s all there is to it. With some clever copy/paste and possibly a few quick changes this thing should be working like a charm in just less than twenty minutes.

Of course you’ll probably want to come up with some better usage for it than doing a JS alert…

Hooray JQuery

I’ve completely abandoned using Prototype/Scriptaculous in favor of JQuery.

I simply prefer the way JQuery does things:

  • Simple syntax
  • No more in-line JS
  • Lots of great plug-ins
  • JQuery UI has some very nice widgets
  • Lightweight

In terms of CakePHP it means that I can no longer rely on the built-in AJAX helpers. No big deal, I find that manually writing JQuery is not hard at all (and I’ve never really done any JS programming). And the helpers are actually lacking in some more complex features.

So bottom line is that you should at least spend a few hours to see what JQuery is capable of and how easy it is to use it. It might be a great benefit in the long run and chances are it will open up some great possibilites for your next app.