1
+ <!--
2
+ Copyright (c) 2011, salesforce.com, inc.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided
6
+ that the following conditions are met:
7
+
8
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the
9
+ following disclaimer.
10
+
11
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12
+ the following disclaimer in the documentation and/or other materials provided with the distribution.
13
+
14
+ Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or
15
+ promote products derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
18
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
+ POSSIBILITY OF SUCH DAMAGE.
25
+ -->
26
+ <!--
27
+ Sample Visualforce page for Force.com JavaScript REST Toolkit
28
+ -->
29
+ <apex:page standardStylesheets="false" showHeader="false" sidebar="false">
30
+ <head>
31
+ <title>
32
+ Force.com JavaScript REST Toolkit
33
+ </title>
34
+ <style type="text/css">
35
+ body {
36
+ font-family:"Arial";
37
+ }
38
+ table.main {
39
+ border: 1px solid #666;
40
+ }
41
+ .highlighted {
42
+ background-color:#D6EDFC;
43
+ }
44
+ .odd {
45
+ background-color:#fea;
46
+ }
47
+ form {
48
+ margin-bottom: 1em;
49
+ }
50
+ </style>
51
+ <!--
52
+ Download jQuery, jQuery UI and Trimpath Template, and put them in a
53
+ static resource bundles!
54
+ -->
55
+ <apex:includeScript
56
+ value="{!URLFOR($Resource.static, 'query.js')}" />
57
+ <apex:includeScript
58
+ value="{!URLFOR($Resource.static, 'jquery-ui.js')}" />
59
+ <apex:includeScript
60
+ value="{!URLFOR($Resource.static, 'template.js')}" />
61
+ <apex:includeScript
62
+ value="{!URLFOR($Resource.static, 'forcetk.js')}" />
63
+ <apex:stylesheet
64
+ value="{!URLFOR($Resource.static, 'jquery-ui.css')}" />
65
+
66
+ <script type="text/javascript">
67
+ // Get a reference to jQuery that we can work with
68
+ $j = jQuery.noConflict();
69
+
70
+ // Make our own startsWith utility fn
71
+ String.prototype.startsWith = function(str){
72
+ return (this.substr(0, str.length) === str);
73
+ }
74
+
75
+ // Get an instance of the REST API client
76
+ var client = new forcetk.Client('{!$Api.Session_ID}');
77
+
78
+ // We'll use this a lot :-)
79
+ var ajaxgif = "<img src='{!URLFOR($Resource.static, 'static/ajax.gif')}'/>";
80
+
81
+ var $dialog = null;
82
+
83
+ // Kick things off by doing a describe on Account...
84
+ $j(document).ready(function() {
85
+ $dialog = $j('<div></div>')
86
+ .dialog({
87
+ autoOpen: false,
88
+ width: 450
89
+ });
90
+
91
+ $j('#prompt').html(ajaxgif+" loading metadata...");
92
+ client.describe('Account', metadataCallback);
93
+ });
94
+
95
+ var timeout = null;
96
+
97
+ function autoFilter() {
98
+ if (timeout != null) {
99
+ clearTimeout(timeout);
100
+ }
101
+
102
+ var field = $j("#field").val();
103
+ var value = $j("#value").val();
104
+
105
+ filterAccounts(field,value);
106
+ }
107
+
108
+ function metadataCallback(response){
109
+ // Using TrimPath Template for now - may switch to jQuery Template at some
110
+ // point
111
+ $j('#prompt').html(TrimPath.processDOMTemplate("prompt_jst"
112
+ , response));
113
+
114
+ $j("#value").keyup(function(){
115
+ if (timeout != null) {
116
+ clearTimeout(timeout);
117
+ }
118
+ timeout = setTimeout("autoFilter()",1000);
119
+ });
120
+
121
+ $j('#go').click(function(e) {
122
+ var field = $j("#field").val();
123
+ var value = $j("#value").val();
124
+
125
+ e.preventDefault();
126
+ filterAccounts(field,value);
127
+ });
128
+
129
+ $j('#new').click(function(e) {
130
+ e.preventDefault();
131
+
132
+ // Just make Trimpath happy
133
+ var dummy = {};
134
+ var i;
135
+ for (i = 0; i < response.fields.length; i++) {
136
+ dummy[response.fields[i].name] = '';
137
+ }
138
+ $dialog.html(TrimPath.processDOMTemplate("edit_jst", dummy));
139
+ $dialog.find('#action').html('Create').click(function(e) {
140
+ e.preventDefault();
141
+ $dialog.dialog('close');
142
+
143
+ var fields = {};
144
+ $dialog.find('input').each(function() {
145
+ var child = $j(this);
146
+ if ( child.val().length > 0 ) {
147
+ fields[child.attr("name")] = child.val();
148
+ }
149
+ });
150
+
151
+ $j('#list').html(ajaxgif+" creating account...");
152
+
153
+ client.create('Account', fields, createCallback);
154
+ });
155
+ $dialog.dialog('option', 'title', 'New Account');
156
+ $dialog.dialog('open');
157
+ });
158
+
159
+ filterAccounts();
160
+ }
161
+
162
+ function queryCallback(response) {
163
+ $j('#list').html(TrimPath.processDOMTemplate("accounts_jst"
164
+ , response));
165
+
166
+ $j('#version').html($j.fn.jquery);
167
+ $j('#uiversion').html($j.ui.version);
168
+
169
+ $j("#list tr:nth-child(odd)").addClass("odd");
170
+
171
+ $j('#accounts').find('.id')
172
+ .hover(function() {
173
+ $j(this).addClass("highlighted");
174
+ },function(){
175
+ $j(this).removeClass("highlighted");
176
+ })
177
+ .click(showAccountDetail);
178
+ }
179
+
180
+ function detailCallback(response) {
181
+ if (response.Website != null
182
+ && !response.Website.startsWith('http://')) {
183
+ response.Website = 'http://'+response.Website;
184
+ }
185
+ $dialog.html(TrimPath.processDOMTemplate("detail_jst"
186
+ ,response));
187
+ $dialog.find('#industry').click(function(e) {
188
+ e.preventDefault();
189
+ $dialog.dialog('close');
190
+ filterIndustry($j(this).html());
191
+ });
192
+ $dialog.find('#delete').click(function(e) {
193
+ e.preventDefault();
194
+ $dialog.dialog('close');
195
+ $j('#list').html(ajaxgif+" deleting account...");
196
+ client.del('Account', $dialog.find('#id').val(), deleteCallback);
197
+ });
198
+ $dialog.find('#edit').click(function(e) {
199
+ e.preventDefault();
200
+ $dialog.html(TrimPath.processDOMTemplate("edit_jst"
201
+ ,response));
202
+ $dialog.find('#action').html('Update').click(function(e) {
203
+ e.preventDefault();
204
+ $dialog.dialog('close');
205
+
206
+ var fields = {};
207
+ $dialog.find('input').each(function() {
208
+ var child = $j(this);
209
+ if ( child.val().length > 0 && child.attr("name") != 'id') {
210
+ fields[child.attr("name")] = child.val();
211
+ }
212
+ });
213
+
214
+ $j('#list').html(ajaxgif+" updating account...");
215
+
216
+ client.update('Account', $dialog.find('#id').val(), fields, updateCallback);
217
+ });
218
+ });
219
+ }
220
+
221
+ function createCallback(response) {
222
+ $j('#list').html('Created '+response.id);
223
+
224
+ setTimeout("filterAccounts()",1000);
225
+ }
226
+
227
+ function updateCallback(response) {
228
+ $j('#list').html('Updated');
229
+
230
+ setTimeout("filterAccounts()",1000);
231
+ }
232
+
233
+ function deleteCallback(response) {
234
+ $j('#list').html('Deleted');
235
+
236
+ setTimeout("filterAccounts()",1000);
237
+ }
238
+
239
+ function showAccountDetail() {
240
+ // Show the dialog
241
+ $dialog.dialog('option', 'title', 'Account Detail');
242
+ $dialog.dialog('open');
243
+ $dialog.html(ajaxgif+" retrieving...");
244
+
245
+ // Get account details and populate the dialog
246
+ client.retrieve('Account', this.id, 'Name,Industry,TickerSymbol,Website'
247
+ , detailCallback);
248
+ }
249
+
250
+ function filterAccounts(field, value) {
251
+ $j('#list').html(ajaxgif+" loading data...");
252
+
253
+ var query = ( typeof value !== 'undefined' && value.length > 0 )
254
+ ? "SELECT Id, Name FROM Account WHERE "+field+" LIKE '"+value
255
+ +"%' ORDER BY Name LIMIT 20"
256
+ : "SELECT Id, Name FROM Account ORDER BY Name LIMIT 20";
257
+
258
+ client.query(query, queryCallback);
259
+ }
260
+ </script>
261
+ </head>
262
+ <body>
263
+ <div id="main">
264
+ <div id="prompt">
265
+ </div>
266
+ <div id="list">
267
+ </div>
268
+ </div>
269
+ <textarea id="prompt_jst" style="display:none;">
270
+ <form>
271
+ <h3 style="display:inline;">Filter on</h3>
272
+ <select id="field">
273
+ {for f in fields}
274
+ {if f.type == 'string'}
275
+ <option value="${f.name}">${f.label}</option>
276
+ {/if}
277
+ {/for}
278
+ </select>
279
+ <input type="text" id="value" />
280
+ <input type="submit" id="go" name="search" value="Search" />
281
+ </form>
282
+ <form>
283
+ <input type="submit" id="new" name="new" value="New" />
284
+ </form>
285
+ </textarea>
286
+
287
+ <textarea id="accounts_jst" style="display:none;">
288
+ <table class="main" id="accounts">
289
+ {for r in records}
290
+ <tr><td class="id" id="${r.Id}">${r.Name}</td></tr>
291
+ {/for}
292
+ </table>
293
+ <br/>
294
+ <a href="https://login.salesforce.com/secur/logout.jsp" id="logout">Logout</a>
295
+ <p>
296
+ <i>Running jQuery <span id="version">0.0.0</span>, jQuery UI <span id="uiversion">0.0.0</span></i>
297
+ </p>
298
+ </textarea>
299
+
300
+ <textarea id="detail_jst" style="display:none;">
301
+ <table>
302
+ {if Website != null}
303
+ <tr><td>Name:</td><td><a href="${Website}">${Name}</a></td></tr>
304
+ {else}
305
+ <tr><td>Name:</td><td>${Name}</td></tr>
306
+ {/if}
307
+ {if Industry != null}
308
+ <tr><td>Industry:</td><td><a href="#" id="industry">${Industry}</a></td></tr>
309
+ {/if}
310
+ {if TickerSymbol != null}
311
+ <tr><td>Ticker Symbol:</td><td><a href="http://www.google.com/finance?q=${TickerSymbol}">${TickerSymbol}</a></td></tr>
312
+ {/if}
313
+ </table>
314
+ <br/>
315
+ <form>
316
+ <input type="hidden" name="id" id="id" value="${Id}" />
317
+ <button id="delete">Delete</button>
318
+ <button id="edit">Edit</button>
319
+ </form>
320
+ </textarea>
321
+
322
+ <textarea id="edit_jst" style="display:none;">
323
+ <form id="editform">
324
+ <input type="hidden" name="id" id="id" value="${Id}" />
325
+ <table>
326
+ <tr><td>Name:</td><td><input name="Name" id="Name" value="${Name}"/></td></tr>
327
+ <tr><td>Industry:</td><td><input name="Industry" id="Industry" value="${Industry}"/></td></tr>
328
+ <tr><td>Ticker Symbol:</td><td><input name="TickerSymbol" id="TickerSymbol" value="${TickerSymbol}"/></td></tr>
329
+ </table>
330
+ <br/>
331
+ <button id="action" />
332
+ </form>
333
+ </textarea>
334
+ </body>
335
+ </apex:page>
0 commit comments