sproutit-sproutcore 1.0.20090721145251 → 1.0.20090721145280
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +3 -3
- data/VERSION.yml +2 -2
- data/frameworks/sproutcore/Buildfile +0 -1
- data/gen/app/templates/apps/@target_name@/core.js +27 -0
- data/gen/app/templates/apps/@target_name@/english.lproj/loading.rhtml +9 -0
- data/gen/app/templates/apps/@target_name@/english.lproj/main_page.js +22 -0
- data/gen/app/templates/apps/@target_name@/english.lproj/strings.js +15 -0
- data/gen/app/templates/apps/@target_name@/main.js +30 -0
- data/gen/controller/templates/controllers/@filename@.js +18 -0
- data/gen/controller/templates/tests/controllers/@filename@.js +15 -0
- data/gen/framework/templates/frameworks/@target_name@/core.js +21 -0
- data/gen/framework/templates/frameworks/@target_name@/english.lproj/strings.js +15 -0
- data/gen/language/templates/@filename@/strings.js +14 -0
- data/gen/model/templates/fixtures/@filename@.js +35 -0
- data/gen/model/templates/models/@filename@.js +19 -0
- data/gen/model/templates/tests/models/@filename@.js +15 -0
- data/gen/project/templates/@filename@/Buildfile +7 -0
- data/gen/project/templates/@filename@/README +7 -0
- data/gen/test/templates/tests/@filename@.js +15 -0
- data/gen/theme/templates/themes/@target_name@/english.lproj/strings.js +15 -0
- data/gen/view/templates/tests/views/@filename@.js +15 -0
- data/gen/view/templates/views/@filename@.js +18 -0
- data/lib/sproutcore/models/generator.rb +2 -2
- metadata +21 -33
- data/frameworks/sproutcore/frameworks/deprecated/core.js +0 -59
- data/frameworks/sproutcore/frameworks/deprecated/lib/button_views.rb +0 -330
- data/frameworks/sproutcore/frameworks/deprecated/lib/collection_view.rb +0 -83
- data/frameworks/sproutcore/frameworks/deprecated/lib/core_views.rb +0 -326
- data/frameworks/sproutcore/frameworks/deprecated/lib/form_views.rb +0 -253
- data/frameworks/sproutcore/frameworks/deprecated/lib/index.rhtml +0 -75
- data/frameworks/sproutcore/frameworks/deprecated/lib/menu_views.rb +0 -93
- data/frameworks/sproutcore/frameworks/deprecated/server/rails_server.js +0 -80
- data/frameworks/sproutcore/frameworks/deprecated/server/rest_server.js +0 -178
- data/frameworks/sproutcore/frameworks/deprecated/server/server.js +0 -673
- data/frameworks/sproutcore/frameworks/deprecated/system/animator.js +0 -679
- data/frameworks/sproutcore/frameworks/deprecated/system/binding.js +0 -36
- data/frameworks/sproutcore/frameworks/deprecated/system/browser.js +0 -75
- data/frameworks/sproutcore/frameworks/deprecated/system/classic_responder.js +0 -312
- data/frameworks/sproutcore/frameworks/deprecated/system/event.js +0 -58
- data/frameworks/sproutcore/frameworks/deprecated/system/globals.js +0 -20
- data/frameworks/sproutcore/frameworks/deprecated/system/misc.js +0 -58
- data/frameworks/sproutcore/frameworks/deprecated/system/node_descriptor.js +0 -72
- data/frameworks/sproutcore/frameworks/deprecated/system/object.js +0 -122
- data/frameworks/sproutcore/frameworks/deprecated/system/path_module.js +0 -432
- data/frameworks/sproutcore/frameworks/deprecated/system/string.js +0 -107
- data/frameworks/sproutcore/frameworks/deprecated/tests/application/application.rhtml +0 -125
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/clippingFrame.rhtml +0 -401
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/frame.rhtml +0 -357
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/classic_view/isVisibleInWindow.rhtml +0 -147
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/base.rhtml +0 -298
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/incremental_rendering.rhtml +0 -260
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/collection/source_list_rendering.rhtml +0 -143
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/popup_button.rhtml +0 -128
- data/frameworks/sproutcore/frameworks/deprecated/tests/views/text_field.rhtml +0 -37
- data/frameworks/sproutcore/frameworks/deprecated/views/collection.js +0 -24
@@ -1,75 +0,0 @@
|
|
1
|
-
<% # SPROUTCORE DEFAULT INDEX TEMPLATE
|
2
|
-
# This template provide provides a basic wrapper for a SproutCore client.
|
3
|
-
# Most of the time, it will be sufficient for your own needs. However, if
|
4
|
-
# you need to create your own template, you can do so by copying this file
|
5
|
-
# into your client, naming it 'index.rhtml' and then adding the options
|
6
|
-
# :index => 'index' to your client declaration in routes.rb.
|
7
|
-
#
|
8
|
-
# See the comments in this file for more information on what you can
|
9
|
-
# change.
|
10
|
-
-%>
|
11
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
12
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
13
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
14
|
-
<head>
|
15
|
-
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
16
|
-
<% # @title will be defined if you passed :title in routes.rb -%>
|
17
|
-
<title><%= (@title.to_s || bundle_name.to_s || '').capitalize %></title>
|
18
|
-
<% #
|
19
|
-
# This line should appear in your head area to include the stylesheets
|
20
|
-
# generated by your client. If you need to include your own
|
21
|
-
# stylesheets, you don't need to change it here. Instead, use the
|
22
|
-
# :requires option in routes.rb.
|
23
|
-
-%>
|
24
|
-
<script src="<%= static_url('detect-browser') %>" type="text/javascript"></script>
|
25
|
-
|
26
|
-
<%= stylesheets_for_client %>
|
27
|
-
<%= @content_for_page_styles %>
|
28
|
-
</head>
|
29
|
-
<body class="<%= @theme || 'sc-theme' %> focus">
|
30
|
-
<script type="text/javascript">
|
31
|
-
var SC; if (!SC) SC = {} ;
|
32
|
-
if (SC.setupBodyClassNames) SC.setupBodyClassNames() ;
|
33
|
-
</script>
|
34
|
-
|
35
|
-
<% #
|
36
|
-
# This is where you root body element will appear. To cause your
|
37
|
-
# content to appear here, just declare content_for('body') in one of
|
38
|
-
# your partials.
|
39
|
-
-%>
|
40
|
-
<!-- Main Page Body -->
|
41
|
-
<%= @content_for_body %>
|
42
|
-
|
43
|
-
<% #
|
44
|
-
# This is where the resources you delcare will appear. You must
|
45
|
-
# include the following three lines verbatim for the resources you
|
46
|
-
# declare to be properly used.
|
47
|
-
-%>
|
48
|
-
<!-- Resources to be removed from DOM on page load -->
|
49
|
-
<div id="resources" style="display:none; visibility: hidden;">
|
50
|
-
<%= @content_for_resources -%>
|
51
|
-
</div>
|
52
|
-
|
53
|
-
<% #
|
54
|
-
# This line should appear at the bottom of your page to include your
|
55
|
-
# generated JavaScript and any libraries you reference. If you need
|
56
|
-
# to include other javascripts, add them to the :requires option of
|
57
|
-
# your client in routes.rb instead of changing it here.
|
58
|
-
-%>
|
59
|
-
<!-- Include Site Javascript -->
|
60
|
-
<%= javascripts_for_client %>
|
61
|
-
<%= @content_for_page_javascript %>
|
62
|
-
|
63
|
-
<% #
|
64
|
-
# The following lines to the closing body tag must be included at the
|
65
|
-
# very end of your file. This will actually setup the JavaScript
|
66
|
-
# views on your page and register SproutCore to start on page load.
|
67
|
-
-%>
|
68
|
-
<!-- Render Page Views -->
|
69
|
-
<%= render_page_views %>
|
70
|
-
|
71
|
-
<!-- Start SproutCore on Page Load -->
|
72
|
-
<script type="text/javascript">window.onload = SC.didLoad;</script>
|
73
|
-
<%= @content_for_final %>
|
74
|
-
</body>
|
75
|
-
</html>
|
@@ -1,93 +0,0 @@
|
|
1
|
-
############################################################
|
2
|
-
# MENU VIEW HELPERS
|
3
|
-
#
|
4
|
-
# The view helpers defined in this file help you create popup menus. You can
|
5
|
-
# define a menu in your RHTML helper to be used somewhere else with code like
|
6
|
-
# this:
|
7
|
-
#
|
8
|
-
|
9
|
-
# This is the quick way to define a menu item. Use this approach if you just
|
10
|
-
# want to create a menu with item names and perform an action:
|
11
|
-
#
|
12
|
-
# <% menu_view :action_menu, :validate=>'My.controller.validate' do |m| %>
|
13
|
-
# <%= m.item :item_1, 'Item 1', :action => 'doSomething' %>
|
14
|
-
# <%= m.separator_item %>
|
15
|
-
# <%= m.item :item_2, 'Item 2', :action => 'doAnother Thing' %>
|
16
|
-
# <% end %>
|
17
|
-
#
|
18
|
-
require_helpers 'core_views'
|
19
|
-
require_helpers 'button_views'
|
20
|
-
|
21
|
-
# This will create a popup menu. You should define internal outlets
|
22
|
-
# for the menu items. More options to follow.
|
23
|
-
view_helper :popup_menu_view do
|
24
|
-
var :tag, 'ul'
|
25
|
-
view 'SC.PopupMenuView'
|
26
|
-
end
|
27
|
-
|
28
|
-
# Creates a menu item view. Normally you don't want to create these
|
29
|
-
# directly. Instead use the menu_view helpers.
|
30
|
-
#
|
31
|
-
# OPTIONS:
|
32
|
-
# :action =>
|
33
|
-
# The action to invoke when the menu item is selected.
|
34
|
-
#
|
35
|
-
# :label =>
|
36
|
-
# The label for the menu item.
|
37
|
-
#
|
38
|
-
# :icon =>
|
39
|
-
# The icon for the menu item. No icon will show if this is not set.
|
40
|
-
#
|
41
|
-
# :shortcut =>
|
42
|
-
# You must pass the actualy bit of HTML you want to display as a keyboard
|
43
|
-
# shortcut
|
44
|
-
#
|
45
|
-
# THE FOLLOWING PREVIOUS BEHAVIOR IS CURRENTLY DISABLED
|
46
|
-
# The shortcut key for this menu item. Shortcuts are only active when
|
47
|
-
# the anchorview the popup menu is attached to is part of the in-focus
|
48
|
-
# pane. Shortcuts should be named in the standard input manager
|
49
|
-
# syntax like this: alt_ctrl_shift_k (for Alt-Ctrl-Shift-K)
|
50
|
-
#
|
51
|
-
# Note that on the web, Cmd (on the Mac) and Ctrl are equivalent.
|
52
|
-
# Always use ctrl when defining shortcuts.
|
53
|
-
#
|
54
|
-
# :enabled (bindable) =>
|
55
|
-
# Determines if the menu item will be enabled or not. This is generally
|
56
|
-
# handled by your validate method or through bindings.
|
57
|
-
#
|
58
|
-
# :selected (bindable) =>
|
59
|
-
# Determines if the menu item is selected or not. May also be a mixed
|
60
|
-
# state. This is generally handled by your validate method or through
|
61
|
-
# bindings.
|
62
|
-
#
|
63
|
-
# :alt =>
|
64
|
-
# name another item in this menu that is the alternate form of the
|
65
|
-
# receiver. If the alt item is enabled, this one will be hidden and
|
66
|
-
# visa versa.
|
67
|
-
#
|
68
|
-
view_helper :menu_item_view, :extends => :button_view do
|
69
|
-
|
70
|
-
# JavaScript
|
71
|
-
view 'SC.MenuItemView'
|
72
|
-
|
73
|
-
# HTML
|
74
|
-
var :tag, 'li'
|
75
|
-
var :shortcut
|
76
|
-
# var(:shortcut) { |sc| sc.split('_').map { |x| x.capitalize } * '-' }
|
77
|
-
css_class_names << 'menu-item'
|
78
|
-
|
79
|
-
@my_href = @href || 'javascript:;'
|
80
|
-
@href = nil
|
81
|
-
@inner_html = [
|
82
|
-
%(<a href="#{@my_href}">),
|
83
|
-
'<span class="inner">',
|
84
|
-
@image,
|
85
|
-
%(<span class="label">#{@label}</span>),
|
86
|
-
'</span>',
|
87
|
-
'<span class="sel">✓</span>',
|
88
|
-
'<span class="mixed">-</span>',
|
89
|
-
%(<span class="shortcut">#{@shortcut}</span>),
|
90
|
-
'</a>'
|
91
|
-
] * ''
|
92
|
-
|
93
|
-
end
|
@@ -1,80 +0,0 @@
|
|
1
|
-
// ========================================================================
|
2
|
-
// SproutCore -- JavaScript Application Framework
|
3
|
-
// Copyright ©2006-2008, Sprout Systems, Inc. and contributors.
|
4
|
-
// Portions copyright ©2008 Apple, Inc. All rights reserved.
|
5
|
-
// ========================================================================
|
6
|
-
|
7
|
-
require('server/rest_server') ;
|
8
|
-
|
9
|
-
/**
|
10
|
-
@class
|
11
|
-
|
12
|
-
This server extends SC.RestServer and leverages Rails feature to protect
|
13
|
-
your controller actions from CSRF attacks by using the authenticity token
|
14
|
-
from rails in requests from SproutCore. For more information about this
|
15
|
-
feature from Rails see the documentation in rails for module
|
16
|
-
ActionController::RequestForgeryProtection.
|
17
|
-
|
18
|
-
To use this server create it like for example:
|
19
|
-
|
20
|
-
{{{
|
21
|
-
Contacts = SC.Object.create({
|
22
|
-
server: SC.RailsServer.create({ prefix: ['Contacts'] })
|
23
|
-
}) ;
|
24
|
-
}}}
|
25
|
-
|
26
|
-
In order for SproutCore to send the authenticity token in the body of
|
27
|
-
requests there is one prerequisite: you must initialize the SproutCore app
|
28
|
-
by setting the following two variables:
|
29
|
-
|
30
|
-
| SC.RAILS_AUTH_TOKEN_NAME | Should be set to the name of the authenticity token |
|
31
|
-
| SC.AUTH_TOKEN | Should be set to the value of the authenticity token |
|
32
|
-
|
33
|
-
Following is a description of how this can be achieved. Stick the following
|
34
|
-
code in one of your controllers:
|
35
|
-
|
36
|
-
{{{
|
37
|
-
# Passes the authenticity token for use in javascript
|
38
|
-
def auth_token
|
39
|
-
respond_to do |wants|
|
40
|
-
wants.js do
|
41
|
-
if protect_against_forgery?
|
42
|
-
render :text => "var SC = SC || {};
|
43
|
-
SC.RAILS_AUTH_TOKEN_NAME = '#{request_forgery_protection_token}';
|
44
|
-
SC.RAILS_AUTH_TOKEN = '#{form_authenticity_token}';"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
}}}
|
50
|
-
|
51
|
-
And make it accessible via your rails routes.rb file, for example:
|
52
|
-
|
53
|
-
{{{
|
54
|
-
map.connect 'auth-token.js', :controller => 'application', :action => 'auth_token'
|
55
|
-
}}}
|
56
|
-
|
57
|
-
Lastly, add a reference to the script to the :javascript_libs property
|
58
|
-
in your sc-config file, for example:
|
59
|
-
|
60
|
-
{{{
|
61
|
-
c[:javascript_libs] = ['/sc/auth-token.js']
|
62
|
-
}}}
|
63
|
-
|
64
|
-
|
65
|
-
@extends SC.RestServer
|
66
|
-
@author Lawrence Pit
|
67
|
-
@copyright 2006-2008, Sprout Systems, Inc. and contributors.
|
68
|
-
@since SproutCore 1.0
|
69
|
-
*/
|
70
|
-
SC.RailsServer = SC.RestServer.extend({
|
71
|
-
|
72
|
-
urlFor: function(resource, action, ids, params, method) {
|
73
|
-
if (method != 'get' && SC.RAILS_AUTH_TOKEN_NAME) {
|
74
|
-
params[SC.RAILS_AUTH_TOKEN_NAME] = SC.RAILS_AUTH_TOKEN;
|
75
|
-
}
|
76
|
-
|
77
|
-
return sc_super();
|
78
|
-
}
|
79
|
-
|
80
|
-
}) ;
|
@@ -1,178 +0,0 @@
|
|
1
|
-
// ========================================================================
|
2
|
-
// SproutCore -- JavaScript Application Framework
|
3
|
-
// Copyright ©2006-2008, Sprout Systems, Inc. and contributors.
|
4
|
-
// Portions copyright ©2008 Apple, Inc. All rights reserved.
|
5
|
-
// ========================================================================
|
6
|
-
|
7
|
-
require('server/server') ;
|
8
|
-
|
9
|
-
/**
|
10
|
-
@class
|
11
|
-
|
12
|
-
Usually you wouldn't need to call any of the methods on this class or it's
|
13
|
-
superclass, except for calling the +listFor+ method. The other methods are
|
14
|
-
called for you when you work with your model objects. For example, calling
|
15
|
-
myObject.commit(); will call the commitRecords method on this server if you
|
16
|
-
had defined this server to be to the +dataSource+ of myObject.
|
17
|
-
|
18
|
-
To have an SC model reflect data on a backend server attach an instance of
|
19
|
-
this class to your application. For example:
|
20
|
-
|
21
|
-
{{{
|
22
|
-
Contacts = SC.Object.create({
|
23
|
-
server: SC.RestServer.create({ prefix: ['Contacts'] })
|
24
|
-
}) ;
|
25
|
-
}}}
|
26
|
-
|
27
|
-
Then attach that server as the +dataSource+ to each model class that you
|
28
|
-
want to have reflected. Also define a +resourceURL+ which defines the URL
|
29
|
-
where the collection of your model can be queried. For example:
|
30
|
-
|
31
|
-
{{{
|
32
|
-
Contacts.Contact = SC.Record.extend(
|
33
|
-
dataSource: Contacts.server,
|
34
|
-
resourceURL: 'sc/contacts',
|
35
|
-
properties: ['guid','firstName','lastName'],
|
36
|
-
primaryKey: 'guid'
|
37
|
-
}) ;
|
38
|
-
}}}
|
39
|
-
|
40
|
-
When you work with your models, behind the scenes SC will use 5 main methods
|
41
|
-
on this server. Each is listed below, together with the HTTP method used in
|
42
|
-
the call to the backend server and the URL that is being called. The URL is
|
43
|
-
based on the example given above.
|
44
|
-
|
45
|
-
listFor GET /sc/contacts
|
46
|
-
|
47
|
-
createRecords POST /sc/contacts
|
48
|
-
|
49
|
-
refreshRecords
|
50
|
-
for one record GET /sc/contacts/12345
|
51
|
-
|
52
|
-
refreshRecords
|
53
|
-
for many records GET /sc/contacts?ids=1,2,3,4,5,6
|
54
|
-
|
55
|
-
commitRecords
|
56
|
-
for one record PUT /sc/contacts/12345
|
57
|
-
|
58
|
-
commitRecords
|
59
|
-
for many records PUT /sc/contacts?ids=1,2,3,4,5
|
60
|
-
|
61
|
-
destroyRecords
|
62
|
-
for one record DELETE /sc/contacts/12345
|
63
|
-
|
64
|
-
destroyRecords
|
65
|
-
for many records DELETE /sc/contacts?ids=1,2,3,4,5
|
66
|
-
|
67
|
-
The above is the default behaviour of this server. If you want different
|
68
|
-
URLs to be generated then extend this class and override the +urlFor+
|
69
|
-
method.
|
70
|
-
|
71
|
-
Another way to override the above is to tell SC where member resources can
|
72
|
-
be refreshed, committed and destroyed. For example, when SC calls
|
73
|
-
|
74
|
-
{{{
|
75
|
-
GET /sc/contacts
|
76
|
-
}}}
|
77
|
-
|
78
|
-
you could reply as follows:
|
79
|
-
|
80
|
-
{{{
|
81
|
-
records: [
|
82
|
-
{ guid: '123',
|
83
|
-
type: "Contact",
|
84
|
-
refreshURL: "/contacts?refresh=123",
|
85
|
-
updateURL: "/contacts/123?update=Y",
|
86
|
-
destroyURL: "/contacts/123",
|
87
|
-
firstName: "Charles",
|
88
|
-
...
|
89
|
-
}],
|
90
|
-
...
|
91
|
-
}
|
92
|
-
}}}
|
93
|
-
|
94
|
-
Then when contact 123 needs to be refreshed later on by SC, it will call:
|
95
|
-
|
96
|
-
{{{
|
97
|
-
GET /contacts?refresh=123
|
98
|
-
}}}
|
99
|
-
|
100
|
-
instead of GET /contacts/123. Note that this only works for members on your
|
101
|
-
resource. If a collection of contacts needed to be refreshed it would still
|
102
|
-
call for example GET /contacts?id=123,456,789 instead of making 3 separate
|
103
|
-
calls.
|
104
|
-
|
105
|
-
Because some browsers cannot actually perform an HTTP PUT or HTTP DELETE it
|
106
|
-
will actually perform an HTTP POST but will put an additional key,value pair
|
107
|
-
in the post data packet. For HTTP PUT it will add _method='put' and for
|
108
|
-
HTTP DELETE it will add _method='delete' in the post data.
|
109
|
-
|
110
|
-
Via the SC.Server#request method you can also call collection and member
|
111
|
-
functions on your resource. Use the +action+ parameter for this. For
|
112
|
-
example, server.request('contacts', 'archive', null, params, 'delete')
|
113
|
-
would call:
|
114
|
-
|
115
|
-
{{{
|
116
|
-
DELETE /contacts/archive
|
117
|
-
}}}
|
118
|
-
|
119
|
-
And server.request('contacts', 'give', [12345], {'amount': 1000}, 'put')
|
120
|
-
would call:
|
121
|
-
|
122
|
-
{{{
|
123
|
-
PUT /contacts/12345/give
|
124
|
-
}}}
|
125
|
-
|
126
|
-
with post data amount=1000.
|
127
|
-
|
128
|
-
Alternatively explicitely define the URL to use by setting the +url+
|
129
|
-
property in the +params+ argument that is passed to the server.request
|
130
|
-
method. For example:
|
131
|
-
|
132
|
-
{{{
|
133
|
-
Contacts.server.request(null,null,null, {url: '/sc/archive'}, 'delete')
|
134
|
-
}}}
|
135
|
-
|
136
|
-
would call:
|
137
|
-
|
138
|
-
{{{
|
139
|
-
DELETE /sc/archive
|
140
|
-
}}}
|
141
|
-
|
142
|
-
|
143
|
-
@extends SC.Server
|
144
|
-
@author Lawrence Pit
|
145
|
-
@copyright 2006-2008, Sprout Systems, Inc. and contributors.
|
146
|
-
@since SproutCore 1.0
|
147
|
-
*/
|
148
|
-
SC.RestServer = SC.Server.extend({
|
149
|
-
|
150
|
-
/**
|
151
|
-
@see SC.Server.urlFor
|
152
|
-
**/
|
153
|
-
urlFor: function(resource, action, ids, params, method) {
|
154
|
-
url = resource;
|
155
|
-
if (ids && ids.length == 1) url = url + '/' + ids[0];
|
156
|
-
if (action && action != '') url = url + '/' + action;
|
157
|
-
return url;
|
158
|
-
},
|
159
|
-
|
160
|
-
|
161
|
-
/* privates, overrides the values in SC.Server */
|
162
|
-
|
163
|
-
_listForAction: '',
|
164
|
-
_listForMethod: 'get',
|
165
|
-
|
166
|
-
_createAction: '',
|
167
|
-
_createMethod: 'post',
|
168
|
-
|
169
|
-
_refreshAction: '',
|
170
|
-
_refreshMethod: 'get',
|
171
|
-
|
172
|
-
_commitAction: '',
|
173
|
-
_commitMethod: 'put',
|
174
|
-
|
175
|
-
_destroyAction: '',
|
176
|
-
_destroyMethod: 'delete'
|
177
|
-
|
178
|
-
}) ;
|
@@ -1,673 +0,0 @@
|
|
1
|
-
// ========================================================================
|
2
|
-
// SproutCore -- JavaScript Application Framework
|
3
|
-
// Copyright ©2006-2008, Sprout Systems, Inc. and contributors.
|
4
|
-
// Portions copyright ©2008 Apple, Inc. All rights reserved.
|
5
|
-
// ========================================================================
|
6
|
-
|
7
|
-
require('core') ;
|
8
|
-
|
9
|
-
SC.URL_ENCODED_FORMAT = 'url-encoded' ;
|
10
|
-
SC.JSON_FORMAT = 'json';
|
11
|
-
|
12
|
-
// The Server object knows how to send requests to the server and how to
|
13
|
-
// get things back from the server. It automatically handles situations
|
14
|
-
// such as 304 caching and queuing requests to send to the server later if
|
15
|
-
// the computer becomes disconnected from the internet.
|
16
|
-
|
17
|
-
// The Server object is designed to work with a resource oriented application.
|
18
|
-
// That is, you do someting like this:
|
19
|
-
//
|
20
|
-
// Server.request('resource','verb',{ parameters })
|
21
|
-
// or
|
22
|
-
// Server.create('resource',{ parameters })
|
23
|
-
// Server.refresh('resource',{ parameters })
|
24
|
-
// Server.update('resource',{ parameters })
|
25
|
-
// Server.destroy('resource',{ parameters })
|
26
|
-
//
|
27
|
-
// parameters include:
|
28
|
-
// onSuccess -- passes back returned text
|
29
|
-
// onFailure --
|
30
|
-
//
|
31
|
-
//
|
32
|
-
// SC.Record.refresh
|
33
|
-
// SC.Record.commit --> create/update
|
34
|
-
// SC.Record.destroy
|
35
|
-
SC.Server = SC.Object.extend({
|
36
|
-
|
37
|
-
// Set this to the prefix for your app. Server will use this to convert
|
38
|
-
// record_type properties into recordTypes.
|
39
|
-
prefix: null,
|
40
|
-
|
41
|
-
// Set this string to the format to be used to set your resource and verb.
|
42
|
-
urlFormat: '/%@/%@',
|
43
|
-
|
44
|
-
// Set this string to either rails or json to set the post transport protocol
|
45
|
-
postFormat: SC.URL_ENCODED_FORMAT,
|
46
|
-
|
47
|
-
// Set this string to true when escaping the JSON string is necessary
|
48
|
-
escapeJSON: true,
|
49
|
-
|
50
|
-
// call this in your main to preload any data sent from the server with the
|
51
|
-
// initial page load.
|
52
|
-
preload: function(clientData) {
|
53
|
-
if ((!clientData) || (clientData.size == 0)) return ;
|
54
|
-
this.refreshRecordsWithData(clientData,SC.Record,null,false);
|
55
|
-
},
|
56
|
-
|
57
|
-
// This is the root method for accessing a server resource. Pass in the
|
58
|
-
// resource URL, verb name, and any parameters. There are several special-
|
59
|
-
// purpose parameters used also:
|
60
|
-
//
|
61
|
-
// onSuccess -- function invoked when request completes. Expects the format
|
62
|
-
// didSucceed(status,ajaxRequest,cacheCode,context)
|
63
|
-
// onFailure -- function invoked when request fails. Same format.
|
64
|
-
// requestContext -- simply passed back.
|
65
|
-
// cacheCode -- String indicating the time of the last refresh.
|
66
|
-
// url -- override the default url building with this url.
|
67
|
-
//
|
68
|
-
request: function(resource, action, ids, params, method) {
|
69
|
-
|
70
|
-
// Get Settings and Options
|
71
|
-
if (!params) params = {} ;
|
72
|
-
var opts = {} ;
|
73
|
-
var onSuccess = params.onSuccess; delete params.onSuccess;
|
74
|
-
var onNotModified = params.onNotModified; delete params.onNotModified ;
|
75
|
-
var onFailure = params.onFailure ; delete params.onFailure ;
|
76
|
-
var context = params.requestContext ; delete params.requestContext ;
|
77
|
-
var accept = params.accept ; delete params.accept ;
|
78
|
-
var cacheCode = params.cacheCode; delete params.cacheCode ;
|
79
|
-
// enable JSON for every operation
|
80
|
-
var records = params.records ;
|
81
|
-
if ((this.get('postFormat') == SC.JSON_FORMAT) && records) {
|
82
|
-
params.records = (this.get('escapeJSON')) ? escape(records.toJSONString()) : records.toJSONString() ;
|
83
|
-
}
|
84
|
-
var url = params.url; delete params.url;
|
85
|
-
|
86
|
-
opts.requestHeaders = {'Accept': 'application/json, text/javascript, application/xml, text/xml, text/html, */*'} ;
|
87
|
-
if (accept) opts.requestHeaders['Accept'] = accept ;
|
88
|
-
if (cacheCode) opts.requestHeaders['Sproutit-Cache'] = cacheCode ;
|
89
|
-
opts.method = method || 'get' ;
|
90
|
-
|
91
|
-
if (!url) url = this.urlFor(resource, action, ids, params, opts.method) ;
|
92
|
-
|
93
|
-
// handle ids
|
94
|
-
if (ids && ids.length > 1) {
|
95
|
-
params.ids = [ids].flatten().join(',') ;
|
96
|
-
}
|
97
|
-
|
98
|
-
// adds a custom HTTP header for remote requests
|
99
|
-
opts.requestHeaders = {'X-SproutCore-Version' : '1.0'} ;
|
100
|
-
|
101
|
-
// convert parameters.
|
102
|
-
var parameters = this._toQueryString(params) ;
|
103
|
-
if (parameters && parameters.length > 0) opts.parameters = parameters ;
|
104
|
-
|
105
|
-
var request ; // save for later
|
106
|
-
|
107
|
-
// Save callback functions.
|
108
|
-
opts.onSuccess = function(request) {
|
109
|
-
// var cacheCode = request.getHeader('Last-Modified') ;
|
110
|
-
// if ((transport.status == '200') && (transport.responseText == '304 Not Modified')) {
|
111
|
-
// if (onNotModified) onNotModified(transport.status, transport, cacheCode,context);
|
112
|
-
// } else {
|
113
|
-
if (onSuccess) onSuccess(request.status, request, cacheCode,context);
|
114
|
-
// }
|
115
|
-
} ;
|
116
|
-
|
117
|
-
opts.onFailure = function(request) {
|
118
|
-
// var cacheCode = request.getHeader('Last-Modified') ;
|
119
|
-
if (onFailure) onFailure(request.status, request, cacheCode,context);
|
120
|
-
} ;
|
121
|
-
|
122
|
-
console.log('REQUEST: %@ %@'.fmt(opts.method, url)) ;
|
123
|
-
|
124
|
-
var that = this ;
|
125
|
-
var processRequestChange = function() {
|
126
|
-
if (request.readyState == 4) {
|
127
|
-
if (request.status == 200) opts.onSuccess.apply(that, [request]) ;
|
128
|
-
else opts.onFailure.apply(that, [request]) ;
|
129
|
-
}
|
130
|
-
};
|
131
|
-
|
132
|
-
var ajaxRequest = function(url, opts) {
|
133
|
-
var opts = opts || {} ;
|
134
|
-
request = false;
|
135
|
-
|
136
|
-
if (window.XMLHttpRequest && !(window.ActiveXObject)) {
|
137
|
-
try {
|
138
|
-
request = new XMLHttpRequest();
|
139
|
-
} catch(e) {
|
140
|
-
request = false;
|
141
|
-
}
|
142
|
-
// branch for IE/Windows ActiveX version
|
143
|
-
} else if (window.ActiveXObject) {
|
144
|
-
try {
|
145
|
-
request = new ActiveXObject("Msxml2.XMLHTTP");
|
146
|
-
} catch(e) {
|
147
|
-
try {
|
148
|
-
request = new ActiveXObject("Microsoft.XMLHTTP");
|
149
|
-
} catch(e) {
|
150
|
-
request = false;
|
151
|
-
}
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
155
|
-
if (request) {
|
156
|
-
request.onreadystatechange = processRequestChange ;
|
157
|
-
request.open(opts.method, url, true) ;
|
158
|
-
request.send(opts.parameters || '') ;
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
ajaxRequest(url, opts) ;
|
163
|
-
},
|
164
|
-
|
165
|
-
/**
|
166
|
-
Generates the URL that is going to be called by this server. Note that you
|
167
|
-
should only return relative URLs. You can only call resources that are on
|
168
|
-
the same domain as where this script was downloaded from.
|
169
|
-
|
170
|
-
@param {String} resource the URL where the collection of the resource can be queried
|
171
|
-
@param {String} action the action that should be performed on the resource
|
172
|
-
@param {Array} ids array of identifiers of your model instances
|
173
|
-
@param {Array} params parameters that were passed to the SC.Server#request method
|
174
|
-
@param {String} method the HTTP method that will be used
|
175
|
-
@returns {String} the URL to use in the request to the backend server
|
176
|
-
**/
|
177
|
-
urlFor: function(resource, action, ids, params, method) {
|
178
|
-
var idPart = (ids && ids.length == 1) ? ids[0] : '';
|
179
|
-
return this.urlFormat.format(resource, action) + idPart;
|
180
|
-
},
|
181
|
-
|
182
|
-
// RECORD METHODS
|
183
|
-
// These methods do the basic record changes.
|
184
|
-
|
185
|
-
|
186
|
-
// ..........................................
|
187
|
-
// LIST
|
188
|
-
// This is the method called by a collection to get an updated list of
|
189
|
-
// records.
|
190
|
-
listFor: function(opts) {
|
191
|
-
var recordType = opts.recordType ;
|
192
|
-
var resource = recordType.resourceURL() ;
|
193
|
-
|
194
|
-
if (!resource) return false ;
|
195
|
-
|
196
|
-
var order = opts.order || 'id' ;
|
197
|
-
if (!(order instanceof Array)) order = [order] ;
|
198
|
-
order = order.map(function(str){
|
199
|
-
return str.decamelize() ; //rubyify
|
200
|
-
}).join(',') ;
|
201
|
-
|
202
|
-
params = {} ;
|
203
|
-
if (opts.conditions) {
|
204
|
-
var conditions = this._decamelizeData(opts.conditions) ;
|
205
|
-
for(var key in conditions) {
|
206
|
-
params[key] = conditions[key] ;
|
207
|
-
}
|
208
|
-
}
|
209
|
-
|
210
|
-
params.requestContext = opts ;
|
211
|
-
params.onSuccess = this._listSuccess.bind(this) ;
|
212
|
-
params.onNotModified = this._listNotModified.bind(this) ;
|
213
|
-
params.onFailure = this._listFailure.bind(this) ;
|
214
|
-
if (opts.cacheCode) params.cacheCode = opts.cacheCode ;
|
215
|
-
if (opts.offset) params.offset = opts.offset;
|
216
|
-
if (opts.limit) params.limit = opts.limit ;
|
217
|
-
if (order) params.order = order ;
|
218
|
-
this.request(resource, this._listForAction, null, params, this._listMethod) ;
|
219
|
-
},
|
220
|
-
|
221
|
-
_listForAction: 'list',
|
222
|
-
_listMethod: 'get',
|
223
|
-
|
224
|
-
_listSuccess: function(status, transport, cacheCode, context) {
|
225
|
-
var json = eval('json='+transport.responseText) ;
|
226
|
-
if (!json) { console.log('invalid json!'); return; }
|
227
|
-
|
228
|
-
// first, build any records passed back
|
229
|
-
if (json.records) {
|
230
|
-
this.refreshRecordsWithData(json.records,context.recordType,cacheCode,false);
|
231
|
-
}
|
232
|
-
|
233
|
-
// next, convert the list of ids into records.
|
234
|
-
var recs = (json.ids) ? json.ids.map(function(guid) {
|
235
|
-
return SC.Store.getRecordFor(guid,context.recordType) ;
|
236
|
-
}) : [] ;
|
237
|
-
|
238
|
-
// now invoke callback
|
239
|
-
if (context.callback) context.callback(recs,json.count,cacheCode) ;
|
240
|
-
},
|
241
|
-
|
242
|
-
_listNotModified: function(status, transport, cacheCode, context) {
|
243
|
-
if (context.callback) context.callback(null,null,null) ;
|
244
|
-
},
|
245
|
-
|
246
|
-
_listFailure: function(status, transport, cacheCode, records) {
|
247
|
-
console.log('listFailed!') ;
|
248
|
-
},
|
249
|
-
|
250
|
-
|
251
|
-
// ..........................................
|
252
|
-
// CREATE
|
253
|
-
|
254
|
-
// send the records back to create them. added a special parameter to
|
255
|
-
// the hash for each record, _guid, which will be used onSuccess.
|
256
|
-
createRecords: function(records) {
|
257
|
-
if (!records || records.length == 0) return ;
|
258
|
-
|
259
|
-
records = this._recordsByResource(records) ; // sort by resource.
|
260
|
-
for(var resource in records) {
|
261
|
-
if (resource == '*') continue ;
|
262
|
-
|
263
|
-
var curRecords = records[resource] ;
|
264
|
-
|
265
|
-
// collect data for records
|
266
|
-
var server = this ; var context = {} ;
|
267
|
-
var data = curRecords.map(function(rec) {
|
268
|
-
var recData = server._decamelizeData(rec.getPropertyData()) ;
|
269
|
-
recData._guid = SC.guidFor(rec) ;
|
270
|
-
context[SC.guidFor(rec)] = rec ;
|
271
|
-
return recData ;
|
272
|
-
}) ;
|
273
|
-
|
274
|
-
// issue request
|
275
|
-
this.request(resource, this._createAction, null, {
|
276
|
-
requestContext: context,
|
277
|
-
onSuccess: this._createSuccess.bind(this),
|
278
|
-
onFailure: this._createFailure.bind(this),
|
279
|
-
records: data
|
280
|
-
}, this._createMethod) ;
|
281
|
-
}
|
282
|
-
},
|
283
|
-
|
284
|
-
_createAction: 'create',
|
285
|
-
_createMethod: 'post',
|
286
|
-
|
287
|
-
// This method is called when a create is successful. It first goes through
|
288
|
-
// and assigns the primaryKey to each record.
|
289
|
-
_createSuccess: function(status, transport, cacheCode, context) {
|
290
|
-
var json = eval('json='+transport.responseText) ;
|
291
|
-
if (!(json instanceof Array)) json = [json] ;
|
292
|
-
|
293
|
-
// first go through and assign the primaryKey to each record.
|
294
|
-
if (!context) context = {} ;
|
295
|
-
json.forEach(function(data) {
|
296
|
-
var guid = SC.guidFor(data) ;
|
297
|
-
var rec = (guid) ? context[guid] : null ;
|
298
|
-
if (rec) {
|
299
|
-
var pk = rec.get('primaryKey') ;
|
300
|
-
var dataKey = (pk == 'guid') ? 'id' : pk.decamelize().toLowerCase().replace(/\-/g,'_') ;
|
301
|
-
rec.set(pk,data[dataKey]) ;
|
302
|
-
rec.set('newRecord',false) ;
|
303
|
-
}
|
304
|
-
}) ;
|
305
|
-
|
306
|
-
// now this method will work so go do it.
|
307
|
-
this.refreshRecordsWithData(json,context._recordType,cacheCode,true) ;
|
308
|
-
},
|
309
|
-
|
310
|
-
_createFailure: function(status, transport, cacheCode, records) {
|
311
|
-
console.log('createFailed!') ;
|
312
|
-
},
|
313
|
-
|
314
|
-
|
315
|
-
// ..........................................
|
316
|
-
// REFRESH
|
317
|
-
|
318
|
-
refreshRecords: function(records) {
|
319
|
-
if (!records || records.length == 0) return ;
|
320
|
-
|
321
|
-
records = this._recordsByResource(records) ; // sort by resource.
|
322
|
-
for(var resource in records) {
|
323
|
-
if (resource == '*') continue ;
|
324
|
-
|
325
|
-
var curRecords = records[resource] ;
|
326
|
-
|
327
|
-
// collect resource ids, sort records into hash, and get cacheCode.
|
328
|
-
var cacheCode = null ; var ids = [] ; var context = {} ;
|
329
|
-
var primaryKey = curRecords[0].get('primaryKey') ; // assumes all the same
|
330
|
-
curRecords.forEach(function(r) {
|
331
|
-
cacheCode = cacheCode || r._cacheCode ;
|
332
|
-
var key = r.get(primaryKey);
|
333
|
-
if (key) { ids.push(key); context[key] = r; }
|
334
|
-
});
|
335
|
-
context._recordType = this._instantiateRecordType(curRecords[0].get('type'), this.prefix, null) ; // default rec type.
|
336
|
-
|
337
|
-
params = {
|
338
|
-
requestContext: context,
|
339
|
-
cacheCode: ((cacheCode=='') ? null : cacheCode),
|
340
|
-
onSuccess: this._refreshSuccess.bind(this),
|
341
|
-
onFailure: this._refreshFailure.bind(this)
|
342
|
-
};
|
343
|
-
|
344
|
-
if (ids.length == 1 && curRecords[0].refreshURL) params['url'] = curRecords[0].refreshURL;
|
345
|
-
|
346
|
-
// issue request
|
347
|
-
this.request(resource, this._refreshAction, ids, params, this._refreshMethod) ;
|
348
|
-
}
|
349
|
-
},
|
350
|
-
|
351
|
-
_refreshAction: 'show',
|
352
|
-
_refreshMethod: 'get',
|
353
|
-
|
354
|
-
// This method is called when a refresh is successful. It expects an array
|
355
|
-
// of hashes, which it will convert to records.
|
356
|
-
_refreshSuccess: function(status, transport, cacheCode, context) {
|
357
|
-
var json = eval('json='+transport.responseText) ;
|
358
|
-
if (!(json instanceof Array)) json = [json] ;
|
359
|
-
this.refreshRecordsWithData(json,context._recordType,cacheCode,true) ;
|
360
|
-
},
|
361
|
-
|
362
|
-
_refreshFailure: function(status, transport, cacheCode, records) {
|
363
|
-
console.log('refreshFailed!') ;
|
364
|
-
},
|
365
|
-
|
366
|
-
// ..........................................
|
367
|
-
// COMMIT
|
368
|
-
|
369
|
-
commitRecords: function(records) {
|
370
|
-
if (!records || records.length == 0) return ;
|
371
|
-
|
372
|
-
records = this._recordsByResource(records) ; // sort by resource.
|
373
|
-
for(var resource in records) {
|
374
|
-
if (resource == '*') continue ;
|
375
|
-
|
376
|
-
var curRecords = records[resource] ;
|
377
|
-
|
378
|
-
// collect data for records
|
379
|
-
var server = this ;
|
380
|
-
|
381
|
-
// start format differences
|
382
|
-
var data = null;
|
383
|
-
switch(this.get('postFormat')){
|
384
|
-
case SC.URL_ENCODED_FORMAT:
|
385
|
-
data = curRecords.map(function(rec) {
|
386
|
-
return server._decamelizeData(rec.getPropertyData()) ;
|
387
|
-
}) ;
|
388
|
-
break;
|
389
|
-
case SC.JSON_FORMAT:
|
390
|
-
// get all records and put them into an array
|
391
|
-
var objects = [];
|
392
|
-
for(rec in curRecords){
|
393
|
-
if (!curRecords.hasOwnProperty(rec)) continue ;
|
394
|
-
objects.push(curRecords[rec].get('attributes') || {});
|
395
|
-
}
|
396
|
-
|
397
|
-
// convert to JSON and escape if this.escapeJSON is true
|
398
|
-
if(this.get('escapeJSON')){
|
399
|
-
data = escape(objects.toJSONString());
|
400
|
-
} else {
|
401
|
-
data = objects.toJSONString();
|
402
|
-
}
|
403
|
-
break;
|
404
|
-
default:
|
405
|
-
break;
|
406
|
-
}
|
407
|
-
// end format differences
|
408
|
-
|
409
|
-
if (data) {
|
410
|
-
var ids = [];
|
411
|
-
if (curRecords.length == 1) {
|
412
|
-
var primaryKey = curRecords[0].get('primaryKey') ;
|
413
|
-
var key = curRecords[0].get(primaryKey);
|
414
|
-
if (key) ids.push(key);
|
415
|
-
}
|
416
|
-
|
417
|
-
params = {
|
418
|
-
requestContext: records,
|
419
|
-
onSuccess: this._commitSuccess.bind(this),
|
420
|
-
onFailure: this._commitFailure.bind(this),
|
421
|
-
records: data
|
422
|
-
};
|
423
|
-
|
424
|
-
if (ids.length == 1 && curRecords[0].updateURL) params['url'] = curRecords[0].updateURL;
|
425
|
-
|
426
|
-
// issue request
|
427
|
-
this.request(resource, this._commitAction, ids, params, this._commitMethod) ;
|
428
|
-
}
|
429
|
-
}
|
430
|
-
},
|
431
|
-
|
432
|
-
_commitAction: 'update',
|
433
|
-
_commitMethod: 'post',
|
434
|
-
|
435
|
-
// This method is called when a refresh is successful. It expects an array
|
436
|
-
// of hashes, which it will convert to records.
|
437
|
-
_commitSuccess: function(status, transport, cacheCode, context) {
|
438
|
-
var json = eval('json='+transport.responseText) ;
|
439
|
-
if (!(json instanceof Array)) json = [json] ;
|
440
|
-
this.refreshRecordsWithData(json,context._recordType,cacheCode,true) ;
|
441
|
-
},
|
442
|
-
|
443
|
-
_commitFailure: function(status, transport, cacheCode, records) {
|
444
|
-
console.log('commitFailed!') ;
|
445
|
-
},
|
446
|
-
|
447
|
-
// ..........................................
|
448
|
-
// DESTROY
|
449
|
-
|
450
|
-
destroyRecords: function(records) {
|
451
|
-
if (!records || records.length == 0) return ;
|
452
|
-
|
453
|
-
records = this._recordsByResource(records) ; // sort by resource.
|
454
|
-
for(var resource in records) {
|
455
|
-
var curRecords = records[resource] ;
|
456
|
-
|
457
|
-
if (resource == '*') {
|
458
|
-
curRecords.forEach(function(rec){
|
459
|
-
rec.set('isDeleted',true) ;
|
460
|
-
SC.Store.removeRecord(rec) ;
|
461
|
-
});
|
462
|
-
continue ;
|
463
|
-
}
|
464
|
-
|
465
|
-
// collect resource ids, sort records into hash, and get cacheCode.
|
466
|
-
var ids = [] ; var key ;
|
467
|
-
var primaryKey = curRecords[0].get('primaryKey') ;
|
468
|
-
|
469
|
-
curRecords.forEach(function(rec) {
|
470
|
-
if ((key = rec.get(primaryKey)) && (!rec.get('newRecord'))) {
|
471
|
-
ids.push(key) ;
|
472
|
-
}
|
473
|
-
rec.set('isDeleted',true) ;
|
474
|
-
SC.Store.removeRecord(rec) ;
|
475
|
-
}) ;
|
476
|
-
|
477
|
-
// issue request -- we may not have ids to send tho (for ex, if all
|
478
|
-
// records were newRecords.)
|
479
|
-
if (ids && ids.length > 0) {
|
480
|
-
params = {
|
481
|
-
requestContext: records,
|
482
|
-
onSuccess: this._destroySuccess.bind(this),
|
483
|
-
onFailure: this._destroyFailure.bind(this)
|
484
|
-
};
|
485
|
-
|
486
|
-
if (ids.length == 1 && curRecords[0].destroyURL) params['url'] = curRecords[0].destroyURL;
|
487
|
-
|
488
|
-
this.request(resource, this._destroyAction, ids, params, this._destroyMethod) ;
|
489
|
-
}
|
490
|
-
}
|
491
|
-
},
|
492
|
-
|
493
|
-
_destroyAction: 'destroy',
|
494
|
-
_destroyMethod: 'post',
|
495
|
-
|
496
|
-
_destroySuccess: function(status, transport, cacheCode, records) {
|
497
|
-
console.log('destroySuccess!') ;
|
498
|
-
},
|
499
|
-
|
500
|
-
_destroyFailure: function(status, transport, cacheCode, records) {
|
501
|
-
console.log('destroyFailed!') ;
|
502
|
-
},
|
503
|
-
|
504
|
-
// ..........................................
|
505
|
-
// SUPPORT
|
506
|
-
|
507
|
-
// This method is called by the various handlers once they have extracted
|
508
|
-
// their data.
|
509
|
-
refreshRecordsWithData: function(dataAry,recordType,cacheCode,loaded) {
|
510
|
-
var server = this ;
|
511
|
-
|
512
|
-
// Loop through the data Array and prepare each element
|
513
|
-
var prepedDataAry = [];
|
514
|
-
for (var idx = 0; idx < dataAry.length; idx++)
|
515
|
-
{
|
516
|
-
var currElem = server._prepareDataForRecords(dataAry[idx], server, recordType);
|
517
|
-
if (currElem !== null) prepedDataAry.push(currElem);
|
518
|
-
}
|
519
|
-
|
520
|
-
// now update.
|
521
|
-
SC.Store.updateRecords(prepedDataAry,server,recordType,loaded) ;
|
522
|
-
},
|
523
|
-
|
524
|
-
// ................................
|
525
|
-
// PRIVATE METHODS
|
526
|
-
|
527
|
-
_prepareDataForRecords: function(data, server, defaultType) {
|
528
|
-
if (data === null) {
|
529
|
-
return null;
|
530
|
-
} else if (SC.typeOf(data) == SC.T_ARRAY) {
|
531
|
-
var that = this;
|
532
|
-
return data.map( function(d) {
|
533
|
-
return that._prepareDataForRecords(d, server, defaultType) ;
|
534
|
-
}) ;
|
535
|
-
} else if (SC.typeOf(data) == SC.T_HASH) {
|
536
|
-
data = server._camelizeData(data) ; // camelize the keys received back.
|
537
|
-
if (data.id) {
|
538
|
-
// convert the 'id' property to 'guid'
|
539
|
-
data.guid = data.id;
|
540
|
-
delete data.id;
|
541
|
-
}
|
542
|
-
data.recordType = server._instantiateRecordType(data.type, server.prefix, defaultType);
|
543
|
-
if (data.recordType) {
|
544
|
-
return data;
|
545
|
-
} else {
|
546
|
-
console.log("Data RecordType could not be instantiated!: "+data.type) ;
|
547
|
-
return null; // could not process.
|
548
|
-
}
|
549
|
-
} else {
|
550
|
-
console.log("Unknown data type in SC.Server#_prepareDataForRecords. Should be array or hash.") ;
|
551
|
-
return null; // could not process.
|
552
|
-
}
|
553
|
-
},
|
554
|
-
|
555
|
-
_instantiateRecordType: function(recordType, prefix, defaultType) {
|
556
|
-
if (recordType) {
|
557
|
-
var recordName = recordType.capitalize() ;
|
558
|
-
if (prefix) {
|
559
|
-
for (var prefixLoc = 0; prefixLoc < prefix.length; prefixLoc++) {
|
560
|
-
var prefixParts = prefix[prefixLoc].split('.');
|
561
|
-
var namespace = window;
|
562
|
-
for (var prefixPartsLoc = 0; prefixPartsLoc < prefixParts.length; prefixPartsLoc++) {
|
563
|
-
var namespace = namespace[prefixParts[prefixPartsLoc]] ;
|
564
|
-
}
|
565
|
-
if (namespace !== window) return namespace[recordName] ;
|
566
|
-
}
|
567
|
-
} else return window[recordName] ;
|
568
|
-
} else return defaultType;
|
569
|
-
},
|
570
|
-
|
571
|
-
// places records from array into hash, sorted by resourceURL.
|
572
|
-
_recordsByResource: function(records) {
|
573
|
-
var ret = {} ;
|
574
|
-
records.forEach(function(rec) {
|
575
|
-
var recs = ret[rec.resourceURL || '*'] || [] ;
|
576
|
-
recs.push(rec) ;
|
577
|
-
ret[rec.resourceURL || '*'] = recs ;
|
578
|
-
}) ;
|
579
|
-
return ret ;
|
580
|
-
},
|
581
|
-
|
582
|
-
_camelizeData: function(data) {
|
583
|
-
if (data == null) return data ;
|
584
|
-
|
585
|
-
// handle array
|
586
|
-
var that = this ;
|
587
|
-
if (data instanceof Array) return data.map(function(d){
|
588
|
-
return that._camelizeData(d) ;
|
589
|
-
}) ;
|
590
|
-
|
591
|
-
// handle other objects
|
592
|
-
if (typeof(data) == "object") {
|
593
|
-
var ret = {} ;
|
594
|
-
for(var key in data) {
|
595
|
-
var value = that._camelizeData(data[key]) ;
|
596
|
-
if (key == 'id') key = 'guid' ;
|
597
|
-
ret[key.replace(/_/g,'-').camelize()] = value ;
|
598
|
-
}
|
599
|
-
return ret ;
|
600
|
-
}
|
601
|
-
|
602
|
-
// otherwise just return value
|
603
|
-
return data ;
|
604
|
-
},
|
605
|
-
|
606
|
-
_decamelizeData: function(data) {
|
607
|
-
if (data == null) return data ;
|
608
|
-
|
609
|
-
// handle array
|
610
|
-
var that = this ;
|
611
|
-
if (data instanceof Array) return data.map(function(d){
|
612
|
-
return that._decamelizeData(d) ;
|
613
|
-
}) ;
|
614
|
-
|
615
|
-
// handle other objects
|
616
|
-
if (typeof(data) == "object") {
|
617
|
-
var ret = {} ;
|
618
|
-
for(var key in data) {
|
619
|
-
var value = that._decamelizeData(data[key]) ;
|
620
|
-
if (key == 'guid') key = 'id' ;
|
621
|
-
ret[key.decamelize()] = value ;
|
622
|
-
}
|
623
|
-
return ret ;
|
624
|
-
}
|
625
|
-
|
626
|
-
// otherwise just return value
|
627
|
-
return data ;
|
628
|
-
},
|
629
|
-
|
630
|
-
// converts a string, array, or hash into a query string. root is the
|
631
|
-
// root string applied to each element key. Used for nesting.
|
632
|
-
_toQueryString: function(params,rootKey) {
|
633
|
-
|
634
|
-
// handle nulls
|
635
|
-
if (params == null) {
|
636
|
-
return rootKey + '=';
|
637
|
-
|
638
|
-
// handle arrays
|
639
|
-
} else if (params instanceof Array) {
|
640
|
-
var ret = [] ;
|
641
|
-
for(var loc=0;loc<params.length;loc++) {
|
642
|
-
var key = (rootKey) ? (rootKey + '['+loc+']') : loc ;
|
643
|
-
ret.push(this._toQueryString(params[loc],key)) ;
|
644
|
-
}
|
645
|
-
return ret.join('&') ;
|
646
|
-
|
647
|
-
// handle objects
|
648
|
-
} else if (typeof(params) == "object") {
|
649
|
-
var ret = [];
|
650
|
-
for(var cur in params) {
|
651
|
-
var key = (rootKey) ? (rootKey + '['+cur+']') : cur ;
|
652
|
-
ret.push(this._toQueryString(params[cur],key)) ;
|
653
|
-
}
|
654
|
-
return ret.join('&') ;
|
655
|
-
|
656
|
-
// handle other values
|
657
|
-
} else return [rootKey,params].join('=') ;
|
658
|
-
},
|
659
|
-
|
660
|
-
init: function() {
|
661
|
-
sc_super();
|
662
|
-
SC.Server.addServer(this);
|
663
|
-
}
|
664
|
-
|
665
|
-
}) ;
|
666
|
-
|
667
|
-
SC.Server.servers = [];
|
668
|
-
|
669
|
-
SC.Server.addServer = function(server) {
|
670
|
-
var ary = SC.Server.servers;
|
671
|
-
ary.push(server);
|
672
|
-
SC.Server.servers = ary;
|
673
|
-
};
|