Your SlideShare is downloading. ×
0
SILVERSTRIPE CMS
              JAVASCRIPT REFACTORING
                         The jsparty is over!




Friday, 28 August ...
SCOPE
              • JavaScript    library upgrade, no more forks

              • CMS JavaScript cleanup
               ...
LIBRARIES

    • Prototype           1.4rc3 to jQuery 1.3

    • Random             UI code and ancient libs to jQuery UI ...
GOODBYE JSPARTY
         • Merged   external libraries
             to cms/thirdparty and sapphire/thirdparty




Friday, ...
THE DARK AGES

                         function hover_over() {
                           Element.addClassName(this, 'ove...
THE DARK AGES
                 class LeftAndMain {
            // ...
                public function returnItemToUser($p)...
BEST PRACTICES


                         • Don’t   claim global properties

                         • Assume    element ...
ENCAPSULATE: EXAMPLE
                                    Simple Highlight jQuery Plugin
                         // create...
BEST PRACTICES


                         • Useplain HTML, jQuery.data() and
                          jQuery.metadata to ...
STATE: EXAMPLE
                              Simple Form Changetracking

    State in CSS                 $('form :input')...
BEST PRACTICES
    • Ajax               responses should default to HTML
        Makes it easier to write unobtrusive mark...
AJAX: EXAMPLE
                   Simple Serverside Autocomplete for Page Titles
                          <form action"#">...
AJAX: EXAMPLE

                         class MyController {
                           function autocomplete($request) {
...
AJAX: EXAMPLE

                         $('.autocomplete input').live('change', function() {
                           va...
BEST PRACTICES

    • Use           events and observation for component communication

    • Use           composition fo...
RESOURCES

                              Documentation (unreleased)
                          http://doc.silverstripe.com/...
Upcoming SlideShare
Loading in...5
×

SilverStripe CMS JavaScript Refactoring

2,873

Published on

Outlines the refactoring effort of the SilverStripe CMS codebase, which was an internal project at SilverStripe Ltd. mid 2009. The main objective was to simplify CMS extensions for intermediate frontend/backend developers. In practice this meant a lot of housekeeping, and the consistent usage of jQuery and jQuery UI over PrototypeJS.

Published in: Technology
2 Comments
2 Likes
Statistics
Notes
No Downloads
Views
Total Views
2,873
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
21
Comments
2
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "SilverStripe CMS JavaScript Refactoring"

  1. 1. SILVERSTRIPE CMS JAVASCRIPT REFACTORING The jsparty is over! Friday, 28 August 2009
  2. 2. SCOPE • JavaScript library upgrade, no more forks • CMS JavaScript cleanup Rewrite in jQuery where feasible • CMS PHP Controller simplification • More solid UI components with jQuery UI and plugins • CSS Architecture for easier customization • Not a large-scale CMS redesign Friday, 28 August 2009
  3. 3. LIBRARIES • Prototype 1.4rc3 to jQuery 1.3 • Random UI code and ancient libs to jQuery UI 1.7 • Custom behaviour.js to jQuery.concrete • External libraries managed by Piston (piston.rubyforge.org/) instead of svn:externals Friday, 28 August 2009
  4. 4. GOODBYE JSPARTY • Merged external libraries to cms/thirdparty and sapphire/thirdparty Friday, 28 August 2009
  5. 5. THE DARK AGES function hover_over() { Element.addClassName(this, 'over'); } function hover_out() { Element.removeClassName(this, 'over'); } hover_behaviour = { onmouseover : hover_over, onmouseout : hover_out } jsparty/hover.js Friday, 28 August 2009
  6. 6. THE DARK AGES class LeftAndMain { // ... public function returnItemToUser($p) { // ... $response = <<<JS var tree = $('sitetree'); var newNode = tree.createTreeNode("$id", "$treeTitle", "{$p->class}{$hasChildren} {$singleInstanceCSSClass}"); node = tree.getTreeNodeByIdx($parentID); if(!node) { node = tree.getTreeNodeByIdx(0); } node.open(); node.appendTreeNode(newNode); newNode.selectTreeNode(); JS; FormResponse::add($response); FormResponse::add($this->hideSingleInstanceOnlyFromCreateFieldJS($p)); return FormResponse::respond(); } } cms/code/LeftAndMain.php (excerpt) Friday, 28 August 2009
  7. 7. BEST PRACTICES • Don’t claim global properties • Assume element collections • Encapsulate: jQuery.concrete, jQuery plugin, jQueryUI widget (in this order) Friday, 28 August 2009
  8. 8. ENCAPSULATE: EXAMPLE Simple Highlight jQuery Plugin // create closure (function($) { // plugin definition $.fn.hilight = function(options) { // build main options before element iteration var opts = $.extend({}, $.fn.hilight.defaults, options); // iterate and reformat each matched element return this.each(function() { $this = $(this); // build element specific options var o = $.meta ? $.extend({}, opts, $this.data()) : opts; // update element styles $this.css({backgroundColor: o.background,color: o.foreground}); }); }; // plugin defaults $.fn.hilight.defaults = {foreground: "red",background: "yellow"}; // end of closure })(jQuery); Friday, 28 August 2009
  9. 9. BEST PRACTICES • Useplain HTML, jQuery.data() and jQuery.metadata to encode initial state and (some) configuration • Better than building “object cathedrals” in most cases Friday, 28 August 2009
  10. 10. STATE: EXAMPLE Simple Form Changetracking State in CSS $('form :input').bind('change', function(e) { $(this.form).addClass('isChanged'); }); properties $('form').bind('submit', function(e) { if($(this).hasClass('isChanged')) return false; }); $('form :input').bind('change', function(e) { State in DOM $(this.form).data('isChanged', true); }); $('form').bind('submit', function(e) { (through jQuery.data()) if($(this).data('isChanged')) return false; }); Friday, 28 August 2009
  11. 11. BEST PRACTICES • Ajax responses should default to HTML Makes it easier to write unobtrusive markup and use SilverStripe templating • Use HTTP metadata to transport state and additional data Example: 404 HTTP status code to return “Not Found” Example: Custom “X-Status” header for more detailed UI status • Return JSON if HTML is not feasible Example: Update several tree nodes after CMS batch actions Alternative: Inspect the returned DOM for more structured data like id attributes • For AJAX and parameter transmission, <form> is your friend Friday, 28 August 2009
  12. 12. AJAX: EXAMPLE Simple Serverside Autocomplete for Page Titles <form action"#"> <div class="autocomplete {url:'MyController/autocomplete'}"> <input type="text" name="title" /> <div class="results" style="display: none;"> </div> <input type="submit" value="action_autocomplete" /> </form> MyController.ss Using jQuery.metadata, but could be a plain SilverStripe Form as well <ul> <% control Results %> <li id="Result-$ID">$Title</li> <% end_control %> </ul> AutoComplete.ss Friday, 28 August 2009
  13. 13. AJAX: EXAMPLE class MyController { function autocomplete($request) { $SQL_title = Convert::raw2sql($request->getVar('title')); $results = DataObject::get("Page", "Title LIKE '%$SQL_title%'"); if(!$results) return new HTTPResponse("Not found", 404); // Use HTTPResponse to pass custom status messages $this->response->setStatusCode(200, "Found " . $results->Count() . " elements"); // render all results with a custom template $vd = new ViewableData(); return $vd->customise(array( "Results" => $results ))->renderWith('AutoComplete'); } } MyController.php Friday, 28 August 2009
  14. 14. AJAX: EXAMPLE $('.autocomplete input').live('change', function() { var resultsEl = $(this).siblings('.results'); resultsEl.load( // get form action, using the jQuery.metadata plugin $(this).parent().metadata().url, // submit all form values $(this.form).serialize(), // callback after data is loaded function(data, status) { resultsEl.show(); // optional: get all record IDs from the new HTML var ids = jQuery('.results').find('li').map(function() { return $(this).attr('id').replace(/Record-/,''); }); } ); }); MyController.js Friday, 28 August 2009
  15. 15. BEST PRACTICES • Use events and observation for component communication • Use composition for synchronous, two-way communicatoin • Use callbacks to allow for customization • Don’t overuse prototypical inheritance and pseudo-classes • Only expose public APIs where necessary (through jQuery.concrete) Friday, 28 August 2009
  16. 16. RESOURCES Documentation (unreleased) http://doc.silverstripe.com/doku.php?id=2.4:javascript Source (unreleased, pre 2.4 alpha) http://github.com/chillu/sapphire/tree/jsrewrite http://github.com/chillu/cms/tree/jsrewrite Friday, 28 August 2009
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×