Skip to content

Commit

Permalink
Merge pull request #881 from huntc/deprecate-jquery-from-jsroute
Browse files Browse the repository at this point in the history
Deprecated support of jQuery from the Javascript router
  • Loading branch information
jroper committed Mar 20, 2013
2 parents 70849e7 + dd95be2 commit ace3e7f
Show file tree
Hide file tree
Showing 7 changed files with 538 additions and 461 deletions.
84 changes: 49 additions & 35 deletions documentation/manual/javaGuide/tutorials/zentasks/JavaGuide6.md

Large diffs are not rendered by default.

@@ -1,38 +1,28 @@
# Javascript Routing # Javascript Routing


The play router is able to generate Javascript code to handle routing from Javascript running client side back to your The play router is able to generate Javascript code to handle routing from Javascript running client side back to your application. The Javascript router aids in refactoring your application. If you change the structure of your URLs or parameter names your Javascript gets automatically updated to use that new structure.
application. This aids in refactoring your application, if you change the structure of your URLs or parameter names,
your Javascript gets automatically updated to use that new structure.


## Generating a Javascript router ## Generating a Javascript router


The first step to using Plays Javascript router is to generate it. The router will only expose the routes that you The first step to using Play's Javascript router is to generate it. The router will only expose the routes that you explicitly declare thus minimising the size of the Javascript code.
explicitly tell it to, thus minimising the size of the Javascript code and also avoiding unnecessarily giving away all
the information about the structure of your application.


There are two ways to generate a Javascript router, one is to embed the router in the HTML page using template There are two ways to generate a Javascript router. One is to embed the router in the HTML page using template directives. The other is to generate Javascript resources in an action that can be downloaded, cached and shared between pages.
directives, the other is to generate Javascript resources in an action that can be downloaded, cached and shared between
pages.


### Embedded router ### Embedded router


An embedded router can be generated using the ``@javascriptRouter`` directive inside a Scala template. Typically this An embedded router can be generated using the ``@javascriptRouter`` directive inside a Scala template. This is typically done inside the main decorating template.
might be done inside the main decorating template.


@helper.javascriptRouter("jsRoutes")( @helper.javascriptRouter("jsRoutes")(
routes.javascript.Users.list, routes.javascript.Users.list,
routes.javascript.Users.get routes.javascript.Users.get
) )


The first parameter is the name of the global variable that the router will be placed in. The second parameter is the The first parameter is the name of the global variable that the router will be placed in. The second parameter is the list of Javascript routes that should be included in this router. In order to use this function, your template must have an implicit RequestHeader in scope. For example this can be made available by adding ``(implicit req:
list of Javascript routes that should be included in this router. In order to use this function, your template must RequestHeader)`` to the end of your parameter declarations.
have an implicit RequestHeader in scope, for example this can be made available by adding ``(implicit req:
RequestHeader)`` to the end of your paramteer declarations.


### Router resource ### Router resource


A router resource can be generated by creating an action that invokes the router generator. It has a similar syntax to A router resource can be generated by creating an action that invokes the router generator. It has a similar syntax to embedding the router in a template:
embedding the router in a template:


def javascriptRoutes = Action { implicit request => def javascriptRoutes = Action { implicit request =>
import routes.javascript._ import routes.javascript._
Expand All @@ -44,26 +34,30 @@ embedding the router in a template:
).as("text/javascript") ).as("text/javascript")
} }


Having implemented this action, and of course adding it to your routes file, you can then include it as a resource in Having implemented this action, and of course adding it to your routes file, you can then include it as a resource in your templates:
your templates:


<script type="text/javascript" src="@routes.Application.javascriptRoutes"></script> <script type="text/javascript" src="@routes.Application.javascriptRoutes"></script>


## Using the router ## Using the router


The router uses jQuery by default to make requests. Making a call is as simple as: Using jQuery as an example, making a call is as simple as:


jsRoutes.controllers.Users.get(someId).ajax({success: /*...*/, error: /*...*/}); $.ajax(jsRoutes.controllers.Users.get(someId))
.done( /*...*/ )
.fail( /*...*/ );


The router also makes a few other pieces of information available, such as the ``url``, the ``method`` and the The router also makes a few other properties available including the ``url``, the ``type`` (the HTTP method), the ``absoluteURL`` and the ``webSocketURL``. For example the above call to jQuery's ajax function can also be made like:
``absoluteURL``, as properties on the route.


## Using a custom ajax method var r = jsRoutes.controllers.Users.get(someId);
$.ajax({url: r.url, type: r.type, success: /*...*/, error: /*...*/ });


If jQuery isn't your thing, or if you'd like to decorate the jQuery ajax method in some way, you can provide a function The above approach is required where other properties need setting such as success, error, context etc.
to the router to use to perform ajax queries. This function must accept the object that is passed to the ``ajax``
router method, and should expect the router to have set the ``type`` and ``url`` properties on it to the appropriate ## jQuery ajax method support
method and url for the router request.
> **Note:** Built-in support for jQuery's ajax function will be removed in a future release. This section on the built-in support is provided for reference purposes only. Please do not use the router's ajax function in new code and consider upgrading existing code as soon as possible. The previous section on using the router documents how jQuery should be used.
If jQuery isn't your thing, or if you'd like to decorate the jQuery ajax method in some way, you can provide a function to the router to use to perform ajax queries. This function must accept the object that is passed to the ``ajax`` router method, and should expect the router to have set the ``type`` and ``url`` properties on it to the appropriate method and url for the router request.


To define this function, in your action pass the ``ajaxMethod`` method parameter, eg: To define this function, in your action pass the ``ajaxMethod`` method parameter, eg:


Expand Down
3 changes: 2 additions & 1 deletion framework/src/play/src/main/scala/play/api/Routes.scala
Expand Up @@ -43,12 +43,13 @@ package play.api {
javascriptRouter(name, ajaxMethod, request.host, routes: _*) javascriptRouter(name, ajaxMethod, request.host, routes: _*)
} }


// TODO: This JS needs to be re-written as it isn't easily maintained.
def javascriptRouter(name: String, ajaxMethod: Option[String], host: String, routes: JavascriptReverseRoute*): String = { def javascriptRouter(name: String, ajaxMethod: Option[String], host: String, routes: JavascriptReverseRoute*): String = {
"""|var %s = {}; (function(_root){ """|var %s = {}; (function(_root){
|var _nS = function(c,f,b){var e=c.split(f||"."),g=b||_root,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g} |var _nS = function(c,f,b){var e=c.split(f||"."),g=b||_root,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g}
|var _qS = function(items){var qs = ''; for(var i=0;i<items.length;i++) {if(items[i]) qs += (qs ? '&' : '') + items[i]}; return qs ? ('?' + qs) : ''} |var _qS = function(items){var qs = ''; for(var i=0;i<items.length;i++) {if(items[i]) qs += (qs ? '&' : '') + items[i]}; return qs ? ('?' + qs) : ''}
|var _s = function(p,s){return p+((s===true||(s&&s.secure))?'s':'')+'://'} |var _s = function(p,s){return p+((s===true||(s&&s.secure))?'s':'')+'://'}
|var _wA = function(r){return {%s method:r.method,url:r.url,absoluteURL: function(s){return _s('http',s)+'%s'+r.url},webSocketURL: function(s){return _s('ws',s)+'%s'+r.url}}} |var _wA = function(r){return {%s method:r.method,type:r.method,url:r.url,absoluteURL: function(s){return _s('http',s)+'%s'+r.url},webSocketURL: function(s){return _s('ws',s)+'%s'+r.url}}}
|%s |%s
|})(%s) |})(%s)
""".stripMargin.format( """.stripMargin.format(
Expand Down
Expand Up @@ -10,14 +10,13 @@
* ) * )
* }}} * }}}
* *
* Now you can access your routes in JavaScript without hardcoded URL's, e.g.: * You can access your routes in JavaScript without hardcoded URL's, e.g. assuming jQuery's ajax function:
* {{{ * {{{
* jsRoutes.controllers.Users.list().ajax({success: /* ... */, error: /* ... */}) * $.ajax(jsRoutes.controllers.Users.list()).done( /* */ ).fail( /* */ )
* }}} * }}}
* Each action in the generated object has the following keys: * Each action in the generated object also has the following properties:
* * *ajax*: lets you perform a jQuery ajax call to that actiomn * * *type*: HTTP method
* * *method*: HTTP method * * *url*: the url to be used
* * *url*
* *
* @param name The javascript object name. * @param name The javascript object name.
* @param routes Set of routes to include in this javascript router. * @param routes Set of routes to include in this javascript router.
Expand Down
68 changes: 52 additions & 16 deletions samples/java/zentasks/app/assets/javascripts/main.coffee
Expand Up @@ -79,7 +79,10 @@ class Drawer extends Backbone.View
new Project new Project
el: $(project) el: $(project)
addGroup: -> addGroup: ->
jsRoutes.controllers.Projects.addGroup().ajax r = jsRoutes.controllers.Projects.addGroup()
$.ajax
url: r.url
type: r.type
success: (data) -> success: (data) ->
_view = new Group _view = new Group
el: $(data).appendTo("#projects") el: $(data).appendTo("#projects")
Expand All @@ -101,7 +104,10 @@ class Group extends Backbone.View
newProject: (e) -> newProject: (e) ->
e.preventDefault() e.preventDefault()
@el.removeClass("closed") @el.removeClass("closed")
jsRoutes.controllers.Projects.add().ajax r = jsRoutes.controllers.Projects.add()
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
group: @el.attr("data-group") group: @el.attr("data-group")
Expand All @@ -117,7 +123,10 @@ class Group extends Backbone.View
false if (!confirm "Remove group and projects inside?") false if (!confirm "Remove group and projects inside?")
id = @el.attr("data-group-id") id = @el.attr("data-group-id")
@loading(true) @loading(true)
jsRoutes.controllers.Projects.deleteGroup(@id).ajax r = jsRoutes.controllers.Projects.deleteGroup(@id)
$.ajax
url: r.url
type: r.type
context: this context: this
success: -> success: ->
@el.remove() @el.remove()
Expand All @@ -127,7 +136,10 @@ class Group extends Backbone.View
$.error("Error: " + err) $.error("Error: " + err)
renameGroup: (name) => renameGroup: (name) =>
@loading(true) @loading(true)
jsRoutes.controllers.Projects.renameGroup(@id).ajax r = jsRoutes.controllers.Projects.renameGroup(@id)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
name: name name: name
Expand Down Expand Up @@ -162,7 +174,10 @@ class Project extends Backbone.View
onChange: @renameProject onChange: @renameProject
renameProject: (name) -> renameProject: (name) ->
@loading(true) @loading(true)
jsRoutes.controllers.Projects.rename(@id).ajax r = jsRoutes.controllers.Projects.rename(@id)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
name: name name: name
Expand All @@ -175,7 +190,10 @@ class Project extends Backbone.View
deleteProject: (e) -> deleteProject: (e) ->
e.preventDefault() e.preventDefault()
@loading(true) @loading(true)
jsRoutes.controllers.Projects.delete(@id).ajax r = jsRoutes.controllers.Projects.delete(@id)
$.ajax
url: r.url
type: r.type
context: this context: this
success: -> success: ->
@el.remove() @el.remove()
Expand Down Expand Up @@ -224,7 +242,10 @@ class Tasks extends Backbone.View
project: @project project: @project
newFolder: (e) -> newFolder: (e) ->
e.preventDefault() e.preventDefault()
jsRoutes.controllers.Tasks.addFolder(@project).ajax r = jsRoutes.controllers.Tasks.addFolder(@project)
$.ajax
url: r.url
type: r.type
context: this context: this
success: (tpl) -> success: (tpl) ->
newFolder = new TaskFolder newFolder = new TaskFolder
Expand All @@ -236,7 +257,10 @@ class Tasks extends Backbone.View
false false
removeUser: (e) -> removeUser: (e) ->
e.preventDefault() e.preventDefault()
jsRoutes.controllers.Projects.removeUser(@project).ajax r = jsRoutes.controllers.Projects.removeUser(@project)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
user: $(e.target).parent().data('user-id') user: $(e.target).parent().data('user-id')
Expand All @@ -247,7 +271,10 @@ class Tasks extends Backbone.View
false false
addUser: (e) -> addUser: (e) ->
e.preventDefault() e.preventDefault()
jsRoutes.controllers.Projects.addUser(@project).ajax r = jsRoutes.controllers.Projects.addUser(@project)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
user: $(e.target).parent().data('user-id') user: $(e.target).parent().data('user-id')
Expand Down Expand Up @@ -284,10 +311,10 @@ class TaskFolder extends Backbone.View
$(document).focus() # temporary disable form $(document).focus() # temporary disable form
form = $(e.target) form = $(e.target)
taskBody = $("input[name=taskBody]", form).val() taskBody = $("input[name=taskBody]", form).val()
url = form.attr("action") r = jsRoutes.controllers.Tasks.add(@project, @id)
jsRoutes.controllers.Tasks.add(@project, @id).ajax $.ajax
url: url url: r.url
type: "POST" type: r.type
context: this context: this
data: data:
title: $("input[name=taskBody]", form).val() title: $("input[name=taskBody]", form).val()
Expand All @@ -304,7 +331,10 @@ class TaskFolder extends Backbone.View
false false
renameFolder: (name) => renameFolder: (name) =>
@loading(true) @loading(true)
jsRoutes.controllers.Tasks.renameFolder(@project, @id).ajax r = jsRoutes.controllers.Tasks.renameFolder(@project, @id)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
name: name name: name
Expand Down Expand Up @@ -366,7 +396,10 @@ class TaskItem extends Backbone.View
deleteTask: (e) => deleteTask: (e) =>
e.preventDefault() if e? e.preventDefault() if e?
@loading(false) @loading(false)
jsRoutes.controllers.Tasks.delete(@id).ajax r = jsRoutes.controllers.Tasks.delete(@id)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
name: name name: name
Expand All @@ -385,7 +418,10 @@ class TaskItem extends Backbone.View
false false
toggle: (val) => toggle: (val) =>
@loading(true) @loading(true)
jsRoutes.controllers.Tasks.update(@id).ajax r = jsRoutes.controllers.Tasks.update(@id)
$.ajax
url: r.url
type: r.type
context: this context: this
data: data:
done: val done: val
Expand Down

0 comments on commit ace3e7f

Please sign in to comment.