Skip to content

Commit ded55d6

Browse files
author
Pat Patterson
committed
Move from callbacks to ES6 promises.
1 parent 0c1e81f commit ded55d6

File tree

5 files changed

+395
-397
lines changed

5 files changed

+395
-397
lines changed

OlderUpdates.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
Older Updates
2+
=============
3+
4+
* [Visualforce Remote Objects](https://www.salesforce.com/us/developer/docs/pages/index_Left.htm#CSHID=pages_remote_objects.htm|StartTopic=Content%2Fpages_remote_objects.htm|SkinName=webhelp) are proxy objects that enable basic DML operations on sObjects directly from JavaScript. Behind the scenes, the Remote Objects controller handles sharing rules, field level security, and other data accessibility concerns. Pages that use Remote Objects are subject to all the standard Visualforce limits, but like JavaScript remoting, Remote Objects calls don’t count toward API request limits.
5+
6+
7+
Since Remote Objects are more secure than RemoteTK (which does not respect sharing rules, FLS etc since system-level access is proxied via the RemoteTK controller), and similarly do not consume API calls (the main motivation for RemoteTK), RemoteTK has been removed from the toolkit.
8+
9+
* Since the Summer '13 release, the `/services/data` endpoint has been exposed on Visualforce hosts, so no proxy is now required for REST API calls in JavaScript served via Visualforce (although the proxy **is** still required for calls to `/services/apexrest`). `forcetk.js` has been updated to reflect this.
10+
11+
* Inserting or updating blob data using the `create` or `update` functions (passing base64-encoded binary data in JSON) is limited by the REST API to 50 MB of text data or 37.5 MB of base64–encoded data. New functions, `createBlob` and `updateBlob`, allow creation and update of ContentVersion and Document records with binary ('blob') content with a size of up to 500 MB. Here is a minimal sample that shows how to upload a file to Chatter Files:
12+
13+
<apex:page docType="html-5.0" title="File Uploader">
14+
<h3>
15+
Select a file to upload as a new Chatter File.
16+
</h3>
17+
<input type="file" id="file" onchange="upload()"/>
18+
<p id="message"></p>
19+
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
20+
<script src="{!$Resource.forcetk}"></script>
21+
<script>
22+
var client = new forcetk.Client();
23+
24+
client.setSessionToken('{!$Api.Session_ID}');
25+
26+
function upload() {
27+
var file = $("#file")[0].files[0];
28+
client.createBlob('ContentVersion', {
29+
Origin: 'H', // 'H' for Chatter File, 'C' for Content Document
30+
PathOnClient: file.name
31+
}, file.name, 'VersionData', file)
32+
.then(function(response){
33+
console.log(response);
34+
$("#message").html("Chatter File created: <a target=\"_blank\" href=\"/" + response.id + "\">Take a look!</a>");
35+
})
36+
.catch(function(request, status, response){
37+
$("#message").html("Error: " + status);
38+
});
39+
}
40+
</script>
41+
</apex:page>
42+
43+
Under the covers, `createBlob` sends a multipart message. See the REST API doc page [Insert or Update Blob Data](https://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_insert_update_blob.htm) for more details.

README.markdown

Lines changed: 26 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,73 +13,42 @@ Due to the [same origin policy](http://en.wikipedia.org/wiki/Same_origin_policy)
1313
Recent Updates
1414
--------------
1515

16-
* [Visualforce Remote Objects](https://www.salesforce.com/us/developer/docs/pages/index_Left.htm#CSHID=pages_remote_objects.htm|StartTopic=Content%2Fpages_remote_objects.htm|SkinName=webhelp) are proxy objects that enable basic DML operations on sObjects directly from JavaScript. Behind the scenes, the Remote Objects controller handles sharing rules, field level security, and other data accessibility concerns. Pages that use Remote Objects are subject to all the standard Visualforce limits, but like JavaScript remoting, Remote Objects calls don’t count toward API request limits.
17-
18-
19-
Since Remote Objects are more secure than RemoteTK (which does not respect sharing rules, FLS etc since system-level access is proxied via the RemoteTK controller), and similarly do not consume API calls (the main motivation for RemoteTK), RemoteTK has been removed from the toolkit.
20-
21-
* Since the Summer '13 release, the `/services/data` endpoint has been exposed on Visualforce hosts, so no proxy is now required for REST API calls in JavaScript served via Visualforce (although the proxy **is** still required for calls to `/services/apexrest`). `forcetk.js` has been updated to reflect this.
22-
23-
* Inserting or updating blob data using the `create` or `update` functions (passing base64-encoded binary data in JSON) is limited by the REST API to 50 MB of text data or 37.5 MB of base64–encoded data. New functions, `createBlob` and `updateBlob`, allow creation and update of ContentVersion and Document records with binary ('blob') content with a size of up to 500 MB. Here is a minimal sample that shows how to upload a file to Chatter Files:
24-
25-
<apex:page docType="html-5.0" title="File Uploader">
26-
<h3>
27-
Select a file to upload as a new Chatter File.
28-
</h3>
29-
<input type="file" id="file" onchange="upload()"/>
30-
<p id="message"></p>
31-
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
32-
<script src="{!$Resource.forcetk}"></script>
33-
<script>
34-
var client = new forcetk.Client();
35-
36-
client.setSessionToken('{!$Api.Session_ID}');
37-
38-
function upload() {
39-
var file = $("#file")[0].files[0];
40-
client.createBlob('ContentVersion', {
41-
Origin: 'H', // 'H' for Chatter File, 'C' for Content Document
42-
PathOnClient: file.name
43-
}, file.name, 'VersionData', file, function(response){
44-
console.log(response);
45-
$("#message").html("Chatter File created: <a target=\"_blank\" href=\"/" + response.id + "\">Take a look!</a>");
46-
}, function(request, status, response){
47-
$("#message").html("Error: " + status);
48-
});
49-
}
50-
</script>
51-
</apex:page>
52-
53-
Under the covers, `createBlob` sends a multipart message. See the REST API doc page [Insert or Update Blob Data](https://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_insert_update_blob.htm) for more details.
16+
[Older Updates](OlderUpdates.md)
5417

5518
Dependencies
5619
------------
5720

58-
The toolkit uses [jQuery](http://jquery.com/). It has been tested on jQuery 1.4.4 and 1.5.2, but other versions may also work.
21+
The toolkit uses [ECMAScript 6 Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
22+
23+
TBD - Babel
5924

6025
Configuration
6126
-------------
6227

63-
ForceTK requires that you add the correct REST endpoint hostname for your instance (i.e. https://na1.salesforce.com/ or similar) as a remote site in *Your Name > Administration Setup > Security Controls > Remote Site Settings*.
28+
If you are using ForceTK from JavaScript hosted in an 'off platform' web page (for example, in a Heroku app), you will need to add the app's origin (protocol, host and port, for example https://myapp.herokuapp.com/) to your org's [CORS configuration](https://help.salesforce.com/htviewhelpdoc?err=1&id=extend_code_cors.htm&siteLang=en_US).
6429

6530
Using ForceTK in a Visualforce page
6631
-----------------------------------
6732

68-
Create a zip file containing app.js, forcetk.js, jquery.js, and any other static resources your project may need. Upload the zip via *Your Name > App Setup > Develop > Static Resources*.
33+
Create a zip file containing app.js, forcetk.js and any other static resources your project may need. Upload the zip via *Your Name > App Setup > Develop > Static Resources*.
6934

7035
Your Visualforce page will need to include jQuery and the toolkit, then create a client object, passing a session ID to the constructor. An absolutely minimal sample is:
7136

7237
<apex:page>
73-
<apex:includeScript value="{!URLFOR($Resource.static, 'jquery.js')}" />
74-
<apex:includeScript value="{!URLFOR($Resource.static, 'forcetk.js')}" />
38+
<apex:includeScript value="{!$Resource.forcetk}" />
7539
<script type="text/javascript">
76-
// Get an instance of the REST API client and set the session ID
77-
var client = new forcetk.Client();
78-
client.setSessionToken('{!$Api.Session_ID}');
79-
80-
client.query("SELECT Name FROM Account LIMIT 1", function(response){
81-
$('#accountname').text(response.records[0].Name);
82-
});
40+
// Get an instance of the REST API client and set the session ID
41+
var client = new forcetk.Client();
42+
client.setSessionToken('{!$Api.Session_ID}');
43+
44+
client.query("SELECT Name FROM Account LIMIT 1")
45+
.then(function(response){
46+
document.getElementById("accountname").textContent = response.records[0].Name;
47+
})
48+
.catch(function(error){
49+
console.error(error);
50+
alert(error);
51+
});
8352
</script>
8453
<p>The first account I see is <span id="accountname"></span>.</p>
8554
</apex:page>
@@ -89,9 +58,9 @@ More fully featured samples are provided in [example.page](Force.com-JavaScript-
8958
Using the Toolkit in an HTML page outside the Force.com platform
9059
----------------------------------------------------------------
9160

92-
You will need to deploy proxy.php to your server, configuring CORS support (see comments in proxy.php) if your JavaScript is to be hosted on a different server.
61+
As mentioned above, you will need to [configure CORS](https://help.salesforce.com/htviewhelpdoc?err=1&id=extend_code_cors.htm&siteLang=en_US) to call the Force.com REST API from JavaScript hosted 'off-platform'.
9362

94-
Your HTML page will need to include jQuery and the toolkit, then create a client object, passing a session ID to the constructor. An absolutely minimal sample using OAuth to obtain a session ID is:
63+
Your HTML page will need to include the toolkit, then create a client object, passing a session ID to the constructor. An absolutely minimal sample using OAuth to obtain a session ID is:
9564

9665
<html>
9766
<head>
@@ -148,13 +117,17 @@ Your HTML page will need to include jQuery and the toolkit, then create a client
148117
</script>
149118
<p id="message">Click here.</p>
150119
</html>
120+
121+
TBD - new OAuth!
151122

152123
More fully featured samples are provided in [example.html](Force.com-JavaScript-REST-Toolkit/blob/master/example.html) and [mobile.html](Force.com-JavaScript-REST-Toolkit/blob/master/mobile.html).
153124

154125
Using the Toolkit in a Cordova app
155126
----------------------------------
156127

157-
Your HTML page will need to include jQuery, the toolkit and Cordova. You will also need to install the [InAppBrowser](http://plugins.cordova.io/#/package/org.apache.cordova.inappbrowser) plugin to be able to pop up a browser window for authentication. Create a client object, passing a session ID to the constructor. You can use __https://login.salesforce.com/services/oauth2/success__ as the redirect URI and catch the page load in InAppBrowser.
128+
TBD - update for current Cordova!
129+
130+
Your HTML page will need to include the toolkit and Cordova. You will also need to install the [InAppBrowser](http://plugins.cordova.io/#/package/org.apache.cordova.inappbrowser) plugin to be able to pop up a browser window for authentication. Create a client object, passing a session ID to the constructor. You can use __https://login.salesforce.com/services/oauth2/success__ as the redirect URI and catch the page load in InAppBrowser.
158131

159132
An absolutely minimal sample using OAuth to obtain a session ID is:
160133

app.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@
6161
"WHERE "+$("#field").val()+" LIKE '%"+request.term+"%' "+
6262
"ORDER BY Name LIMIT 20";
6363

64-
client.query(query, function( data ) {
64+
client.query(query)
65+
.then(function( data ) {
6566
response( $.map( data.records, function( record ) {
6667
return {
6768
label: record.Name,
6869
value: record.Id
6970
}
7071
}));
71-
}, errorCallback);
72+
})
73+
.catch(errorCallback);
7274
},
7375
minLength: 2,
7476
delay: 1000,
@@ -115,7 +117,9 @@
115117

116118
$('#list').html(ajaxgif+" creating account...");
117119

118-
client.create('Account', fields, createCallback, errorCallback);
120+
client.create('Account', fields)
121+
.then(createCallback)
122+
.catch(errorCallback);
119123
});
120124
$dialog.dialog('option', 'title', 'New Account');
121125
$dialog.dialog('open');
@@ -167,7 +171,9 @@
167171
e.preventDefault();
168172
$dialog.dialog('close');
169173
$('#list').html(ajaxgif+" deleting account...");
170-
client.del('Account', $dialog.find('#id').val(), deleteCallback, errorCallback);
174+
client.del('Account', $dialog.find('#id').val())
175+
.then(deleteCallback)
176+
.catch(errorCallback);
171177
});
172178
$dialog.find('#edit').click(function(e) {
173179
e.preventDefault();
@@ -187,7 +193,9 @@
187193

188194
$('#list').html(ajaxgif+" updating account...");
189195

190-
client.update('Account', $dialog.find('#id').val(), fields, updateCallback, errorCallback);
196+
client.update('Account', $dialog.find('#id').val(), fields)
197+
.then(updateCallback)
198+
.catch(errorCallback);
191199
});
192200
});
193201
}
@@ -217,8 +225,9 @@
217225
$dialog.html(ajaxgif+" retrieving...");
218226

219227
// Get account details and populate the dialog
220-
client.retrieve('Account', id, 'Name,Industry,TickerSymbol,Website'
221-
, detailCallback, errorCallback);
228+
client.retrieve('Account', id, 'Name,Industry,TickerSymbol,Website')
229+
.then(detailCallback)
230+
.catch(errorCallback);
222231
}
223232

224233
function filterIndustry(industry) {
@@ -227,7 +236,9 @@
227236
var query = "SELECT Id, Name FROM Account WHERE Industry = '"+industry
228237
+"' ORDER BY Name LIMIT 20";
229238

230-
client.query(query, queryCallback, errorCallback);
239+
client.query(query)
240+
.then(queryCallback)
241+
.catch(errorCallback);
231242
}
232243

233244
function filterAccounts(field, value) {
@@ -238,6 +249,8 @@
238249
+"%' ORDER BY Name LIMIT 20"
239250
: "SELECT Id, Name FROM Account ORDER BY Name LIMIT 20";
240251

241-
client.query(query, queryCallback, errorCallback);
252+
client.query(query)
253+
.then(queryCallback)
254+
.catch(errorCallback);
242255
}
243256

example.page

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,33 +42,35 @@ Sample Visualforce page for Force.com JavaScript REST Toolkit
4242
<apex:includeScript value="{!URLFOR($Resource.static, '/static/template.js')}" />
4343
<apex:includeScript value="{!URLFOR($Resource.sample, '/forcetk.js')}" />
4444
<apex:includeScript value="{!URLFOR($Resource.sample, '/app.js')}" />
45-
<script type="text/javascript">
46-
/*
47-
* This is the Visualforce-specific JavaScript code for our sample app.
48-
* It must go in the VF page so that merge variables are processed.
49-
*/
45+
<script type="text/javascript">
46+
/*
47+
* This is the Visualforce-specific JavaScript code for our sample app.
48+
* It must go in the VF page so that merge variables are processed.
49+
*/
50+
51+
// Get an instance of the REST API client and set the session ID
52+
var client = new forcetk.Client();
53+
client.setSessionToken('{!$Api.Session_ID}');
5054

51-
// Get an instance of the REST API client and set the session ID
52-
var client = new forcetk.Client();
53-
client.setSessionToken('{!$Api.Session_ID}');
55+
var ajaxgif = "<img src='{!URLFOR($Resource.sample, '/ajax.gif')}' />";
5456

55-
var ajaxgif = "<img src='{!URLFOR($Resource.sample, '/ajax.gif')}' />";
57+
var $dialog = null;
5658

57-
var $dialog = null;
59+
$(document).ready(function() {
60+
// Set up the dialog
61+
$dialog = $('<div></div>')
62+
.dialog({
63+
autoOpen: false,
64+
width: 450
65+
});
5866

59-
$(document).ready(function() {
60-
// Set up the dialog
61-
$dialog = $('<div></div>')
62-
.dialog({
63-
autoOpen: false,
64-
width: 450
65-
});
66-
67-
// Kick things off by doing a describe on Account...
68-
$('#prompt').html(ajaxgif+" loading metadata...");
69-
client.describe('Account', metadataCallback);
70-
});
71-
</script>
67+
// Kick things off by doing a describe on Account...
68+
$('#prompt').html(ajaxgif+" loading metadata...");
69+
client.describe('Account')
70+
.then(metadataCallback)
71+
.catch(errorCallback);
72+
});
73+
</script>
7274
</head>
7375
<body>
7476
<div class="ui-widget" id="main">
@@ -103,7 +105,7 @@ Sample Visualforce page for Force.com JavaScript REST Toolkit
103105
{/for}
104106
</table>
105107
<br/>
106-
<a href="#" id="logout">Logout</a>
108+
<a href="#" id="logout">Logout</a>
107109
<p>
108110
<i>Running jQuery <span id="version">0.0.0</span>, jQuery UI <span id="uiversion">0.0.0</span></i>
109111
</p>
@@ -144,4 +146,4 @@ Sample Visualforce page for Force.com JavaScript REST Toolkit
144146
</form>
145147
</textarea>
146148
</body>
147-
</apex:page>
149+
</apex:page>

0 commit comments

Comments
 (0)