[Catalyst-commits] r7200 - in trunk/examples/RestYUI: db lib lib/AdventREST/Controller root root/static root/user

jshirley at dev.catalyst.perl.org jshirley at dev.catalyst.perl.org
Sun Dec 2 17:26:06 GMT 2007


Author: jshirley
Date: 2007-12-02 17:26:05 +0000 (Sun, 02 Dec 2007)
New Revision: 7200

Added:
   trunk/examples/RestYUI/root/static/container.css
   trunk/examples/RestYUI/root/static/datatable.css
   trunk/examples/RestYUI/root/static/dt-arrow-dn.png
   trunk/examples/RestYUI/root/static/dt-arrow-up.png
   trunk/examples/RestYUI/root/static/json2.js
   trunk/examples/RestYUI/root/static/sprite.png
   trunk/examples/RestYUI/root/user/
   trunk/examples/RestYUI/root/user/single_user.tt
Modified:
   trunk/examples/RestYUI/db/adventrest.db
   trunk/examples/RestYUI/lib/AdventREST.pm
   trunk/examples/RestYUI/lib/AdventREST/Controller/User.pm
   trunk/examples/RestYUI/root/index.tt
Log:
The rest of the RestYUI/AdventREST article

Modified: trunk/examples/RestYUI/db/adventrest.db
===================================================================
(Binary files differ)

Modified: trunk/examples/RestYUI/lib/AdventREST/Controller/User.pm
===================================================================
--- trunk/examples/RestYUI/lib/AdventREST/Controller/User.pm	2007-12-02 17:12:14 UTC (rev 7199)
+++ trunk/examples/RestYUI/lib/AdventREST/Controller/User.pm	2007-12-02 17:26:05 UTC (rev 7200)
@@ -4,6 +4,19 @@
 use warnings;
 use base 'Catalyst::Controller::REST';
 
+# If we have a form, return JSON data
+__PACKAGE__->config(
+    'serialize' => {
+        'default' => 'text/x-json',
+        'map' => {
+            'text/xml'  => [ 'View', 'TT' ],
+            'text/html' => [ 'View', 'TT' ],
+            # Remap x-www-form-urlencoded to use JSON for serialization
+            'application/x-www-form-urlencoded' => 'JSON',
+        },
+    }
+);
+
 =head1 NAME
 
 AdventREST::Controller::User - Catalyst Advent Calendar REST Controller 
@@ -39,7 +52,7 @@
     my ( $self, $c ) = @_;
 
     $c->log->debug( $c->req->content_type );
-    $c->log->debug( $c->req->headers->as_string );
+    #$c->log->debug( $c->req->headers->as_string );
 
     my %user_list;
     my $user_rs = $c->model('DB::User')->search;
@@ -127,6 +140,7 @@
         user_id     => $user->user_id,
         fullname    => $user->fullname,
         description => $user->description,
+        uri         => $c->uri_for( $c->controller->action_for('single_user'), $user->user_id )->as_string
     };
 
     if ( $c->stash->{'user'} ) {

Modified: trunk/examples/RestYUI/lib/AdventREST.pm
===================================================================
--- trunk/examples/RestYUI/lib/AdventREST.pm	2007-12-02 17:12:14 UTC (rev 7199)
+++ trunk/examples/RestYUI/lib/AdventREST.pm	2007-12-02 17:26:05 UTC (rev 7200)
@@ -13,7 +13,7 @@
 # Static::Simple: will serve static files from the application's root 
 #                 directory
 
-use Catalyst qw/-Debug ConfigLoader Static::Simple/;
+use Catalyst qw/ConfigLoader Static::Simple/;
 
 our $VERSION = '0.01';
 

Modified: trunk/examples/RestYUI/root/index.tt
===================================================================
--- trunk/examples/RestYUI/root/index.tt	2007-12-02 17:12:14 UTC (rev 7199)
+++ trunk/examples/RestYUI/root/index.tt	2007-12-02 17:26:05 UTC (rev 7200)
@@ -2,34 +2,65 @@
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
   <title>Advent!  Now with more AJAX</title>
-  <script type="text/javascript" src=""></script>
+  <link rel="stylesheet" href="/static/container.css" media="screen"/>
+  <link rel="stylesheet" href="/static/datatable.css" media="screen"/>
+  <script type="text/javascript" src="/static/yui/yahoo.js"></script>
+  <script type="text/javascript" src="/static/yui/event.js"></script>
+  <script type="text/javascript" src="/static/yui/utilities.js"></script>
+  <script type="text/javascript" src="/static/yui/connection.js"></script>
+  <script type="text/javascript" src="/static/yui/dom.js"></script>
+  <script type="text/javascript" src="/static/yui/element-beta.js"></script>
+  <script type="text/javascript" src="/static/yui/datasource-beta.js"></script>
+  <script type="text/javascript" src="/static/yui/datatable-beta.js"></script>
  </head>
- <body>
+ <body class="yui-skin-sam">
   <div id="user_list"></div>
   <script type="text/javascript">
-    /* Create the YAHOO.util.DataSource object, the parameter is the
-       URI to your REST service
-    */
-    this.myDataSource = new YAHOO.util.DataSource("[%
-         c.uri_for( c.controller('User').action_for('user_list') ) %]");
-    this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
-    this.myDataSource.connXhrMode = "queueRequests";
-    this.myDataSource.responseSchema = {
-        resultsList: "result_set.result",
-        /* We have to define the fields for usage elsewhere */
-        fields: [
-            "pk1", "token", "default_lang", "languages",
-            "url", "t_created", "t_updated", "actions"
-        ]
-     };
-     
-     myDataTable = new YAHOO.widget.DataTable(
-        "user_list", myColumnDefs,
-        this.myDataSource, {
-            /* The initialRequest is appended to the URI to set params */
-            initialRequest: "page=1&content-type=text/x-json"
+  var Catalyst = {};
+  YAHOO.util.Event.addListener(window, "load", function() {
+    Catalyst.Example = new function() {
+        /* Create a format function to make the name a link. */
+        this.formatName = function( cell, record, column, source_data ) {
+            cell.innerHTML = "<a href='" + record.getData("uri") +
+                ">" + source_data + "</a>";
         }
-     );
+
+        /* Create the YAHOO.util.DataSource object, the parameter is the
+           URI to your REST service
+         */
+        this.myDataSource = new YAHOO.util.DataSource("[%
+            c.uri_for( c.controller('User').action_for('user_list') ) %]?");
+        this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
+        this.myDataSource.connXhrMode = "queueRequests";
+        this.myDataSource.responseSchema = {
+            resultsList: "result_set.result",
+            /* We have to define the fields for usage elsewhere */
+            fields: [ "user_id", "fullname", "uri" ]
+        };
+
+        var myColumnDefs = [
+            /* Setup our column definitions, and make the entries link to
+               the detail record by using the formatName formatter */
+            { key: "user_id", label: "ID", sortable: true,
+                formatter: this.formatName },
+            { key: "fullname", label: "Full Name", sortable: true,
+                formatter: this.formatName},
+            /* We don't need to define all of the columns, and the
+               URI is only useful behind the scenes.
+             */
+            /*{ key: "uri", label: "Location", sortable: true },*/
+        ];
+
+        this.myDataTable = new YAHOO.widget.DataTable(
+            "user_list", myColumnDefs,
+            this.myDataSource, {
+                /* The initialRequest is appended to the URI to set params */
+                initialRequest: "page=1&content-type=text/x-json",
+                fields: [ "ID", "Full Name" ]
+            }
+        );
+    };
+  });
   </script>
  </body>
 </html>

Added: trunk/examples/RestYUI/root/static/container.css
===================================================================
--- trunk/examples/RestYUI/root/static/container.css	                        (rev 0)
+++ trunk/examples/RestYUI/root/static/container.css	2007-12-02 17:26:05 UTC (rev 7200)
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.3.1
+*/
+.yui-overlay,.yui-panel-container{visibility:hidden;position:absolute;z-index:2;}.yui-panel-container form{margin:0;}.mask{z-index:1;display:none;position:absolute;top:0;left:0;right:0;bottom:0;overflow:auto;}.yui-panel-container select{_visibility:inherit;}.masked select,.drag select,.hide-select select{_visibility:hidden;}.hide-scrollbars,.hide-scrollbars *{overflow:hidden;}.hide-scrollbars select{display:none;}.show-scrollbars{overflow:auto;}.yui-panel-container.show-scrollbars,.yui-tt.show-scrollbars{overflow:visible;}.yui-panel-container.show-scrollbars .underlay,.yui-tt.show-scrollbars .yui-tt-shadow{overflow:auto;}.yui-tt-shadow{position:absolute;}.yui-skin-sam .mask{background-color:#000;opacity:.25;*filter:alpha(opacity=25);}.yui-skin-sam .yui-panel-container{padding:0 1px;*padding:2px 3px;}.yui-skin-sam .yui-panel{position:relative;*zoom:1;left:0;top:0;border-style:solid;border-width:1px 0;border-color:#808080;z-index:1;}.yui-skin-sam .yui-panel .hd,.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{*zoom:1;*position:relative;border-style:solid;border-width:0 1px;border-color:#808080;margin:0 -1px;}.yui-skin-sam .yui-panel .hd{border-bottom:solid 1px #ccc;}.yui-skin-sam .yui-panel .bd,.yui-skin-sam .yui-panel .ft{background-color:#F2F2F2;}.yui-skin-sam .yui-panel .hd{padding:0 10px;font-size:93%;line-height:2;*line-height:1.9;font-weight:bold;color:#000;background:url(sprite.png) repeat-x 0 -200px;}.yui-skin-sam .yui-panel .bd{padding:10px;}.yui-skin-sam .yui-panel .ft{border-top:solid 1px #808080;padding:5px 10px;font-size:77%;}.yui-skin-sam .yui-panel-container.focused .yui-panel .hd{}.yui-skin-sam .container-close{position:absolute;top:5px;right:6px;width:25px;height:15px;background:url(sprite.png) no-repeat 0 -300px;cursor:pointer;}.yui-skin-sam .yui-panel-container .underlay{right:-1px;left:-1px;}.yui-skin-sam .yui-panel-container.matte{padding:9px 10px;background-color:#fff;}.yui-skin-sam .yui-panel-container.shadow{_padding:2px 5px 0 3px;}.yui-skin-sam .yui-panel-container.shadow .underlay{position:absolute;top:2px;right:-3px;bottom:-3px;left:-3px;*top:3px;*left:-1px;*right:-1px;*bottom:-1px;_top:0;_right:0;_bottom:0;_left:0;_margin-top:3px;_margin-left:-1px;background-color:#000;opacity:.12;*filter:alpha(opacity=12);}.yui-skin-sam .yui-dialog .ft{border-top:none;padding:0 10px 10px 10px;font-size:100%;}.yui-skin-sam .yui-dialog .ft .button-group{display:block;text-align:right;}.yui-skin-sam .yui-dialog .ft .default{border-color:#304369;background-position:0 -1400px;}.yui-skin-sam .yui-dialog .ft .default .first-child{border-color:#304369;}.yui-skin-sam .yui-dialog .ft .default button{color:#fff;}.yui-skin-sam .yui-simple-dialog .bd .yui-icon{background:url(sprite.png) no-repeat 0 0;width:16px;height:16px;margin-right:10px;float:left;}.yui-skin-sam .yui-simple-dialog .bd span.blckicon{background-position:0 -1100px;}.yui-skin-sam .yui-simple-dialog .bd span.alrticon{background-position:0 -1050px;}.yui-skin-sam .yui-simple-dialog .bd span.hlpicon{background-position:0 -1150px;}.yui-skin-sam .yui-simple-dialog .bd span.infoicon{background-position:0 -1200px;}.yui-skin-sam .yui-simple-dialog .bd span.warnicon{background-position:0 -1900px;}.yui-skin-sam .yui-simple-dialog .bd span.tipicon{background-position:0 -1250px;}.yui-skin-sam .yui-tt .bd{position:relative;top:0;left:0;z-index:1;color:#000;padding:2px 5px;border-color:#D4C237 #A6982B #A6982B #A6982B;border-width:1px;border-style:solid;background-color:#FFEE69;}.yui-skin-sam .yui-tt.show-scrollbars .bd{overflow:auto;}.yui-skin-sam .yui-tt-shadow{top:2px;right:-3px;left:-3px;bottom:-3px;background-color:#000;}.yui-skin-sam .yui-tt-shadow-visible{opacity:.12;*filter:alpha(opacity=12);}

Added: trunk/examples/RestYUI/root/static/datatable.css
===================================================================
--- trunk/examples/RestYUI/root/static/datatable.css	                        (rev 0)
+++ trunk/examples/RestYUI/root/static/datatable.css	2007-12-02 17:26:05 UTC (rev 7200)
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.3.1
+*/
+table.yui-dt-table{table-layout:fixed;}th .yui-dt-header{position:relative;}th .yui-dt-label{position:relative;}th .yui-dt-resizer{position:absolute;margin-right:-6px;right:0;bottom:0;width:6px;height:100%;cursor:w-resize;cursor:col-resize;}.yui-dt-scrollable{*overflow-y:auto;}.yui-dt-scrollable thead{display:block;}.yui-dt-scrollable thead tr{position:relative;}.yui-dt-scrollbody{display:block;overflow:auto;}.yui-dt-editor{position:absolute;z-index:9000;}.yui-skin-sam .yui-dt-table{margin:0;padding:0;font-family:arial;font-size:inherit;border-collapse:collapse;border:1px solid #7F7F7F;}.yui-skin-sam .yui-dt-table caption{padding-bottom:1em;text-align:left;}.yui-skin-sam .yui-dt-table th{background:url(sprite.png) repeat-x 0 0;}.yui-skin-sam .yui-dt-table th,.yui-skin-sam .yui-dt-table th a{font-weight:normal;text-decoration:none;color:#000;vertical-align:bottom;}.yui-skin-sam .yui-dt-table th,.yui-skin-sam .yui-dt-table td{padding:4px 10px 4px 10px;border-right:1px solid #CBCBCB;}.yui-skin-sam .yui-dt-table td{text-align:left;}.yui-skin-sam .yui-dt-table th.yui-dt-last,.yui-skin-sam .yui-dt-table td.yui-dt-last{border-right:1px solid #7F7F7F;}.yui-skin-sam .yui-dt-list td{border-right:none;}.yui-skin-sam .yui-dt-table thead{border:1px solid #989898;}.yui-skin-sam .yui-dt-table tbody{border-left:1px solid #7F7F7F;border-right:1px solid #7F7F7F;border-bottom:1px solid #7F7F7F;}.yui-skin-sam .yui-dt-loading{background-color:#FFF;}.yui-skin-sam .yui-dt-loading{background-color:#FFF;}.yui-skin-sam .yui-dt-sortable{cursor:pointer;}.yui-skin-sam th.yui-dt-sortable{padding-right:5px;}.yui-skin-sam th.yui-dt-sortable .yui-dt-label{margin-right:15px;}.yui-skin-sam th.yui-dt-asc,.yui-skin-sam th.yui-dt-desc{background:url(sprite.png) repeat-x 0 -100px;}.yui-skin-sam th.yui-dt-asc .yui-dt-header{background:url(dt-arrow-up.png) no-repeat right;}.yui-skin-sam th.yui-dt-desc .yui-dt-header{background:url(dt-arrow-dn.png) no-repeat right;}.yui-dt-editable{cursor:pointer;}.yui-dt-editor{text-align:left;background-color:#F2F2F2;border:1px solid #808080;padding:6px;}.yui-dt-editor label{padding-left:4px;padding-right:6px;}.yui-dt-editor .yui-dt-button{padding-top:6px;text-align:right;}.yui-dt-editor .yui-dt-button button{background:url(sprite.png) repeat-x 0 0;border:1px solid #999;width:4em;height:1.8em;margin-left:6px;}.yui-dt-editor .yui-dt-button button.yui-dt-default{background:url(sprite.png) repeat-x 0 -1400px;background-color:#5584E0;border:1px solid #304369;color:#FFF}.yui-dt-editor .yui-dt-button button:hover{background:url(sprite.png) repeat-x 0 -1300px;color:#000;}.yui-dt-editor .yui-dt-button button:active{background:url(sprite.png) repeat-x 0 -1700px;color:#000;}.yui-skin-sam tr.yui-dt-even{background-color:#FFF;}.yui-skin-sam tr.yui-dt-odd{background-color:#EDF5FF;}.yui-skin-sam tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam tr.yui-dt-even td.yui-dt-desc{background-color:#EDF5FF;}.yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam tr.yui-dt-odd td.yui-dt-desc{background-color:#DBEAFF;}.yui-skin-sam .yui-dt-list tr.yui-dt-even{background-color:#FFF;}.yui-skin-sam .yui-dt-list tr.yui-dt-odd{background-color:#FFF;}.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc{background-color:#EDF5FF;}.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc{background-color:#EDF5FF;}.yui-skin-sam tr.yui-dt-highlighted,.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc,.yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc,.yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted,.yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted{cursor:pointer;background-color:#B2D2FF;}.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted,.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc,.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted{cursor:pointer;background-color:#B2D2FF;}.yui-skin-sam tr.yui-dt-selected td,.yui-skin-sam tr.yui-dt-selected td.yui-dt-asc,.yui-skin-sam tr.yui-dt-selected td.yui-dt-desc{background-color:#426FD9;color:#FFF;}.yui-skin-sam tr.yui-dt-even td.yui-dt-selected,.yui-skin-sam tr.yui-dt-odd td.yui-dt-selected{background-color:#446CD7;color:#FFF;}.yui-skin-sam .yui-dt-list tr.yui-dt-selected td,.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc,.yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc{background-color:#426FD9;color:#FFF;}.yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected,.yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected{background-color:#446CD7;color:#FFF;}.yui-skin-sam .yui-dt-paginator{display:block;margin:6px 0;white-space:nowrap;}.yui-skin-sam .yui-dt-paginator .yui-dt-first,.yui-skin-sam .yui-dt-paginator .yui-dt-last,.yui-skin-sam .yui-dt-paginator .yui-dt-selected{padding:2px 6px;}.yui-skin-sam .yui-dt-paginator a.yui-dt-first,.yui-skin-sam .yui-dt-paginator a.yui-dt-last{text-decoration:none;}.yui-skin-sam .yui-dt-paginator .yui-dt-previous,.yui-skin-sam .yui-dt-paginator .yui-dt-next{display:none;}.yui-skin-sam a.yui-dt-page{border:1px solid #CBCBCB;padding:2px 6px;text-decoration:none;}

Added: trunk/examples/RestYUI/root/static/dt-arrow-dn.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/RestYUI/root/static/dt-arrow-dn.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/RestYUI/root/static/dt-arrow-up.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/RestYUI/root/static/dt-arrow-up.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/RestYUI/root/static/json2.js
===================================================================
--- trunk/examples/RestYUI/root/static/json2.js	                        (rev 0)
+++ trunk/examples/RestYUI/root/static/json2.js	2007-12-02 17:26:05 UTC (rev 7200)
@@ -0,0 +1,262 @@
+/*
+    json2.js
+    2007-10-28
+
+    Public Domain
+
+    See http://www.JSON.org/js.html
+
+    This file creates a global JSON object containing two methods:
+
+        JSON.stringify(value, whitelist)
+            value       any JavaScript value, usually an object or array.
+
+            whitelist   an optional that determines how object values are
+                        stringified.
+
+            This method produces a JSON text from a JavaScript value.
+            There are three possible ways to stringify an object, depending
+            on the optional whitelist parameter.
+
+            If an object has a toJSON method, then the toJSON() method will be
+            called. The value returned from the toJSON method will be
+            stringified.
+
+            Otherwise, if the optional whitelist parameter is an array, then
+            the elements of the array will be used to select members of the
+            object for stringification.
+
+            Otherwise, if there is no whitelist parameter, then all of the
+            members of the object will be stringified.
+
+            Values that do not have JSON representaions, such as undefined or
+            functions, will not be serialized. Such values in objects will be
+            dropped, in arrays will be replaced with null. JSON.stringify()
+            returns undefined. Dates will be stringified as quoted ISO dates.
+
+            Example:
+
+            var text = JSON.stringify(['e', {pluribus, 'unum'}]);
+            // text is '["e",{"pluribus":"unum"}]'
+
+        JSON.parse(text, filter)
+            This method parses a JSON text to produce an object or
+            array. It can throw a SyntaxError exception.
+
+            The optional filter parameter is a function that can filter and
+            transform the results. It receives each of the keys and values, and
+            its return value is used instead of the original value. If it
+            returns what it received, then structure is not modified. If it
+            returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. If a key contains the string 'date' then
+            // convert the value to a date.
+
+            myData = JON.parse(text, function (key, value) {
+                return key.indexOf('date') >= 0 ? new Date(value) : value;
+            });
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+
+    Use your own copy. It is extremely unwise to load third party
+    code into your pages.
+*/
+
+/*jslint evil: true */
+/*extern JSON */
+
+if (!this.JSON) {
+
+    JSON = function () {
+
+        function f(n) {    // Format integers to have at least two digits.
+            return n < 10 ? '0' + n : n;
+        }
+
+        Date.prototype.toJSON = function () {
+
+// Eventually, this method will be based on the date.toISOString method.
+
+            return this.getUTCFullYear()   + '-' +
+                 f(this.getUTCMonth() + 1) + '-' +
+                 f(this.getUTCDate())      + 'T' +
+                 f(this.getUTCHours())     + ':' +
+                 f(this.getUTCMinutes())   + ':' +
+                 f(this.getUTCSeconds())   + 'Z';
+        };
+
+
+        var m = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        };
+
+        function stringify(value, whitelist) {
+            var a,          // The array holding the partial texts.
+                i,          // The loop counter.
+                k,          // The member key.
+                l,          // Length.
+                v;          // The member value.
+
+            switch (typeof value) {
+            case 'string':
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe sequences.
+
+                return /["\\\x00-\x1f]/.test(value) ?
+                    '"' + value.replace(/[\x00-\x1f\\"]/g, function (a) {
+                        var c = m[a];
+                        if (c) {
+                            return c;
+                        }
+                        c = a.charCodeAt();
+                        return '\\u00' + Math.floor(c / 16).toString(16) +
+                                                   (c % 16).toString(16);
+                    }) + '"' :
+                    '"' + value + '"';
+
+            case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+                return isFinite(value) ? String(value) : 'null';
+
+            case 'boolean':
+                return String(value);
+
+            case 'null':
+                return 'null';
+
+            case 'object':
+
+// Due to a specification blunder in ECMAScript,
+// typeof null is 'object', so watch out for that case.
+
+                if (!value) {
+                    return 'null';
+                }
+
+// If the object has a toJSON method, call it, and stringify the result.
+
+                if (typeof value.toJSON === 'function') {
+                    return stringify(value.toJSON());
+                }
+                a = [];
+                if (value.constructor === Array) {
+
+// The object is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+                    l = value.length;
+                    for (i = 0; i < l; i += 1) {
+                        a.push(stringify(value[i], whitelist) || 'null');
+                    }
+
+// Join all of the elements together and wrap them in brackets.
+
+                    return '[' + a.join(',') + ']';
+                }
+                if (whitelist) {
+
+// If a whitelist (array of keys) is provided, use it to select the components
+// of the object.
+
+                    l = whitelist.length;
+                    for (i = 0; i < l; i += 1) {
+                        k = whitelist[i];
+                        if (typeof k === 'string') {
+                            v = stringify(value[k], whitelist);
+                            if (v) {
+                                a.push(stringify(k) + ':' + v);
+                            }
+                        }
+                    }
+                } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+                    for (k in value) {
+                        if (typeof k === 'string') {
+                            v = stringify(value[k], whitelist);
+                            if (v) {
+                                a.push(stringify(k) + ':' + v);
+                            }
+                        }
+                    }
+                }
+
+// Join all of the member texts together and wrap them in braces.
+
+                return '{' + a.join(',') + '}';
+            }
+        }
+
+        return {
+            stringify: stringify,
+            parse: function (text, filter) {
+                var j;
+
+                function walk(k, v) {
+                    var i, n;
+                    if (v && typeof v === 'object') {
+                        for (i in v) {
+                            if (Object.prototype.hasOwnProperty.apply(v, [i])) {
+                                n = walk(i, v[i]);
+                                if (n !== undefined) {
+                                    v[i] = n;
+                                }
+                            }
+                        }
+                    }
+                    return filter(k, v);
+                }
+
+
+// Parsing happens in three stages. In the first stage, we run the text against
+// regular expressions that look for non-JSON pattern. We are especially
+// concerned with '()' and 'new' because they can cause invocation, and '='
+// because it can cause mutation. But just to be safe, we want to reject all
+// unexpected forms.
+
+// We split the first stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace all backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+                if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the second stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+                    j = eval('(' + text + ')');
+
+// In the optional third stage, we recursively walk the new structure, passing
+// each name/value pair to a filter function for possible transformation.
+
+                    return typeof filter === 'function' ? walk('', j) : j;
+                }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+                throw new SyntaxError('parseJSON');
+            }
+        };
+    }();
+}

Added: trunk/examples/RestYUI/root/static/sprite.png
===================================================================
(Binary files differ)


Property changes on: trunk/examples/RestYUI/root/static/sprite.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/examples/RestYUI/root/user/single_user.tt
===================================================================
--- trunk/examples/RestYUI/root/user/single_user.tt	                        (rev 0)
+++ trunk/examples/RestYUI/root/user/single_user.tt	2007-12-02 17:26:05 UTC (rev 7200)
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+    <title>REST User: [% rest.fullname || rest.error %]</title>
+    <script type="text/javascript" src="/static/yui/yahoo.js"></script>
+    <script type="text/javascript" src="/static/yui/event.js"></script>
+    <script type="text/javascript" src="/static/yui/utilities.js"></script>
+    <script type="text/javascript" src="/static/yui/connection.js"></script>
+    <script type="text/javascript" src="/static/yui/dom.js"></script>
+    <script type="text/javascript" src="/static/json2.js"></script>
+</head>
+<body>
+    [%
+    SET method = 'PUT';
+    # Editing an existing user?
+    IF rest.user_id;
+        # Set the method to POST
+        method = 'POST';
+    END;
+    %]
+    <form id="user_form">
+        <p>
+            <label for="user_id">User ID:</label>
+            <input id="user_id" type="text" disabled="disabled" value="[% c.req.args.0 %]"/>
+        </p><p>
+            <label for="fullname">Full Name:</label>
+            <input id="fullname" type="text" value="[% rest.fullname %]"/>
+        </p><p>
+            <label for="Description">Description:</label><br/>
+            <textarea name="description">[% rest.description %]</textarea>
+        </p><p>
+            <input type="submit" value="[% method == 'PUT' ? "Create User" : "Update User" %]"/>
+        </p>
+    </form>
+    <script type="text/javascript">
+    var handleSuccess = function(o) {
+        /* Object Created, check for Loc header */
+        if ( o.status == "201" ) {
+            var loc = o.getResponseHeader["Location"];
+            if ( loc ) {
+                document.location = loc;
+                return true;
+            }
+            /* Just refresh if we did not get a location
+             */
+            alert("Object was created successfully");
+            document.location = document.location;
+        } else if ( o.status == "200" ) {
+            alert("User Update OK");        
+        }
+    };
+
+    var handleFailure = function(o) {
+        alert("Failed! :(\n" + o.responseText);
+    }
+
+    YAHOO.util.Event.addListener(window, "load", function() {
+        var callback = {
+            success: handleSuccess,
+            failure: handleFailure
+        };
+        var form = YAHOO.util.Dom.get("user_form");
+        YAHOO.util.Event.addListener(form, "submit", function(e) {
+            YAHOO.util.Event.preventDefault(e);
+            window.setTimeout(function() {
+                var uri  = '[% c.req.uri %]';
+
+                var data = {
+                    user_id:     form['user_id'].value,
+                    fullname:    form['fullname'].value,
+                    description: form['description'].value
+                };
+                YAHOO.util.Connect.setDefaultPostHeader('text/x-json');
+                var request = YAHOO.util.Connect.asyncRequest(
+                    '[% method %]',
+                    uri,
+                    callback,
+                    JSON.stringify(data)
+                );
+            }, 200);
+        });
+    });
+    </script>
+</body>
+</html>




More information about the Catalyst-commits mailing list