Mais conteúdo relacionado
Semelhante a Introduction to Client Side Dev in SharePoint Workshop (20)
Mais de Mark Rackley (11)
Introduction to Client Side Dev in SharePoint Workshop
- 2. About Mark Rackley
•
•
•
•
•
•
•
18+ years software
architecture and development
experience
SharePoint Junkie since 2007
Event Organizer
Blogger, Writer, Speaker
Bacon aficionado
@mrackley
http://www.sharepointhillbilly.com
2
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 3. Introduction to Client Side Dev Agenda
Story time - What’s and Why’s
What are we going to build today?
Deploying & Referencing Scripts
jQuery Primer
How to debug effectively
Modifying Default SharePoint Forms
REST / CSOM / SPServices
Third Party Libraries
SPA’s and SharePoint Hosted Apps
All links from this session
http://bit.ly/POSTCON06
Code Samples Available at
https://github.com/mrackley/SPClientSideDev
3
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 4. Client Side Development?
Why Bother?
Stay off the server
Deployment and maintenance can be easier
Upgrades can be painless
You don’t have to be a development guru
You don’t need expensive tools like Visual Studio… well you don’t NEED
any tools at all.
4
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 5. Why is JavaScript development so painful?
It’s not compiled
Simple errors can be hard to track down
It’s difficult to debug
Error messages are usually not helpful
There’s a lot of ways to do the exact same thing
Performance can be an issue
Inconsistent Results on Different Browsers
Non-developers are doing it
It can harm you farm!
5
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 6. Why is JavaScript development so painful?
var car = {
var car = {};
It’s not compiled
Simple errors can be hard to trackcar.color = “red”;
down
color: “red”,
It’s difficult to debug
make: “Jeep”,
car.make = “Jeep”;
Error messages are usually not helpful
model: “wrangler”
car.model=“wranger”;
There’s a lot of ways to do the exact same thing
}
Performance can be an issue
var car = {};
Inconsistent Results on Different“red”;
car[“color”] = Browsers
Non-developers are doing it = “Jeep”;
car[“make”]
It can harm you farm!
car[“model”] =“wranger”;
6
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 7. Oh yeah… so, what can’t you do?
Event Receivers
Timer Jobs
Elevate Privileges
This is a good thing
Write to the file system
7
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 8. Yadda Yadda Yadda and other Gobbledygook
Privileges
Scripts run with same permissions as currently logged in user
Cache busting
Stop caching of scripts by applying an inremental query string
parameter
http://urltoscript/myScript.js?rev=001
Eval
It‟s not as evil as everyone says
Async Processing
You are going to hate it with the passion of 1,000,000 burning suns
setTimeout
It feels like a hack because it usually is (but sometimes you might not
have a choice)
8
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 9. How about some best practices?
Avoid global variables
Write scripts in small digestible chunks
Code with performance in mind
Minify files, but make updates in un-minified files
Be consistent in structure and syntax ESPECIALLY if developing as part of a team
Document what you’ve done
9
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 10. Development Tools
Visual Studio Express Web (You don’t have to buy it)
TypeScript
http://www.typescriptlang.org/
Web Essentials (Does not work with VS Express )
http://www.microsoft.com/visualstudio/eng/products/visual-studio-expressproducts
http://visualstudiogallery.msdn.microsoft.com/07d54d12-7133-4e15-becb6f451ea3bea6
Napa
SharePoint Designer (yes… really)
Notepad++
http://baconipsum.com/
10
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 12. Deployment Scripts
Document Library
Can use metadata to enhance maintainability
Integrates well with SPD for development
Can be on different Site or Site Collection
Make sure users have read access
File System
Not an option in the cloud
Arguably faster than Document Library
Content Delivery Network (CDN)
Hosted by a third party
Not recommended for on-Premises Intranets
12
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 14. Referencing Scripts
ScriptLink
Need Visual Studio or SPD
Custom Action
Create feature in Visual Studio
Deploys Script across entire section colleciton
Content Editor Web Part
Deploys script to specific page
Quick and simple
Easily removable
Ideal for editing default pages
NEVER put scripts directly in CEWP
ORDER MATTERS!
14
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 15. Custom Action
(Deploy jQuery across Site Collection)
<?xml version="1.0" encoding="utf-8"?>
<Elements
xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
ScriptSrc="~sitecollection/SiteAssets/jquery.min.j
s"
Location="ScriptLink"
Sequence="100"
>
</CustomAction>
</Elements>
15
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 17. jQuery Primer
JavaScript Utility Library
jQuery() or $()
Allows interaction and manipulation of the DOM after page is rendered
Can interact with other systems using Web Services
Supported by Microsoft
17
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 19. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
19
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 20. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
//Retrieve the element by ID:
$(‚#myID‛);
20
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 21. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
//Retrieve the element by attribute:
$(‚div[attribute=‘myAttribute’]‛);
21
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 22. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
//Retrieve every div on the page
$(‚div‛).each(function() {
//‛this‛ is the current element in each loop
$(this).method();
});
//Hide all divs on the page
$(‚div‛).hide();
22
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 23. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
//Retrieve every div of a specific class
$(‚div.myClass‛).each(function() {
//‛this‛ is the current element in each loop
$(this).method();
});
//Hide all divs of a specific class on the page
$(‚div.myClass‛).hide();
//Hide all elements of a specific class on the page
$(‚.myClass‛).hide();
23
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 24. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
//Retrieve the div that contains content ‚World‛
$(‚div:contains(‘World’)‛).each(function() {
//‛this‛ is the current element in each loop
$(this).method();
});
24
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 25. jQuery Primer
<div id=“myID” attribute=“myAttribute” class=“myClass” ><b>Hello World</b></div>
//Retrieve the formatted HTML for an element
$(‚#myID‛).html(); //returns <b>Hello World</b>
//Set the formatted HTML for an element
$(‚#myID‛).html(‚<b>Hello Nurse</b>‛);
//Retrieve the text with HTML formatting stripped out
$(‚#myID‛).text(); //returns Hello World
//Set the unformatted text of an element
$(‚#myID‛).text(‚Hello Nurse‛);
25
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 26. jQuery Primer
Interacting with SharePoint Form Fields
//get input / select values
$(‚#id‛).val();
//set input / select values
$(‚#id‛).val(‚value‛);
//check a check box
$(‚#id").attr('checked','checked');
//uncheck a check box
$(‚#id").removeAttr('checked');
//is a check box checked?
if ($(‚#id‛).is(':checked'))
26
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 28. jQuery Primer
<tr id=„myRow‟><td><div id=„myElement‟></div><div id=„myOtherElement‟></div></td></tr>
//get the row that contains the div ‚myElement‛
$(‚#myElement‛).closest(‚tr‛);
//get the cell that contains the div
‚myElement‛
$(‚#myElement‛).closest(‚td‛);
Or
$(‚#myElement‛).parent();
28
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 29. jQuery Primer
<tr id=„myRow‟><td><div id=„myElement‟></div><div id=„myOtherElement‟></div></td></tr>
//get the div AFTER myElement
$(‚#myElement‛).next(‚div‛);
Or
$(‚#myElement‛).next();
//get the div BEFORE myOtherelement
$(‚#myOtherElement‛).prev(‚div‛);
Or
$(‚#myOtherElement‛).prev();
29
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 30. jQuery Primer - Chaining
//find the input element that has the ‚title‛ attribute equal to ‚Name‛
//then find it’s parent cell’s previous cell. Then find the ‚h3‛ element
and replace the HTML
$("input[title='Name']").closest("td").prev("td").find("h3").html("File
Name <font color='red'>*</font>");
//In English: Find the label for the field ‚Name‛ and change it to ‚File
Name‛ and add a red astrisk
//find the input element that has the ‚title‛ attribute equal to ‚City‛
//then hide the entire row that contains the input
$(‚input[title=‘City’]‛).closest(‚tr‛).hide();
//In English: Hide the SharePoint Form Field and label for the field
with the Display
//name ‚City‛
30
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 31. jQuery Primer – Promises
The .promise() method returns a dynamically generated Promise that is resolved once all actions of a
certain type bound to the collection, queued or not, have ended.
var call = $.ajax({ … });
call.done(function (data,textStatus, jqXHR){
alert(‚Success‛);
});
call.fail(function (jqXHR,textStatus,errorThrown){
alert("Error‛);
});
Using the When...Done Pattern with Promises in SharePoint 2013 Apps
http://www.shillier.com/archive/2013/03/11/using-the-when-done-pattern-withpromises-in-sharepoint-2013-apps.aspx
31
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 32. Essential jQuery Libraries
jQuery (It’s just JavaScript)
http://jquery.com/
jQuery UI (Make it prettier and more interactive)
http://jqueryui.com/
jQuery.cookie.js (because it works)
http://plugins.jquery.com/cookie/
32
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 33. How About Some jQuery Best Practices?
Use the Element’s ID when possible
Reduce DOM searches
Re-use code / Good coding practices
Use animations to hide slow performance
Delay loading of data until you need the data
33
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 34. jQueryUI
http://jqueryui.com/
jQuery UI is a curated set of user interface
interactions, effects, widgets, and themes built on top of the jQuery
JavaScript Library. Whether you're building highly interactive web
applications or you just need to add a date picker to a form control, jQuery
UI is the perfect choice.
34
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 35. jQueryUI– Basic Usage - Tabs
<div id="tabs">
<ul>
<li><a href="#tabs-1">Tab 1 title</a></li>
<li><a href="#tabs-2">Tab 2 title</a></li>
<li><a href="#tabs-3">Tab 3 title</a></li>
</ul>
<div id="tabs-1">
<p>content in tab 1</p>
</div>
<div id="tabs-2">
<p>content in tab 2</p>
</div>
<div id="tabs-3">
<p>content in tab 3</p>
</div>
</div>
<script>
$(function() {
$( "#tabs" ).tabs();
});
</script>
35
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 37. Debugging Basics
Alerts
Quick sanity checks
Are your scripts getting executed?
Developer Tools
Setting breakpoints
Evaluating expressions
Fiddler
Is the data I‟m expecting coming across the wire?
37
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 38. Debugging Tools
IE and Chrome Developer Tools (It’s like real debugging)
Fiddler (Essential when you need to see what’s really going on)
http://fiddler2.com/
jsLint & jsHint
Syntax / Quality Checking
Can be more frustrating than helpful
http://www.jslint.com/
http://www.jshint.com/
38
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 39. Common issues
Issue
Sympton
Script not loaded
“Object doesn’t support property or method”
Script loaded more than once /
Different versions of same library
Sporadic errors, sometimes it works, sometimes it doesn’t.
Missing quotes, semicolons,
commas, other syntax errors
“Expected <char>” (not always the right character) or Syntax Error.
Mismatched variable names (foo vs
Foo) or use of initialized variables.
Unable to get property ‘x’ of undefined or null reference.
‘x’ is undefined
No error, but unexpected results.
Timing / Async issues
Script errors, unexpected results
Conflicting jQuery libraries
Script errors, unexpected results
http://api.jquery.com/jQuery.noConflict/
Changes to script not taking effect
Script cached, use cache busting technique of incrementing a rev number on your script.
<script type="text/javascript" src="../../SiteAssets/jquery.min.js?rev=1.0"></script>
39
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 41. REST, CSOM, and SPServices
Rob Windsor - SharePoint 2013 Development: Client Object Model and REST
API.
http://www.pluralsight.com/training/Courses/TableOfContents/sharepoint
-2013-client-object-model-rest
Kirk Evans - What Every Developer Needs to Know About SharePoint
Apps, CSOM, and Anonymous Publishing Sites
http://blogs.msdn.com/b/kaevans/archive/2013/10/24/what-everydeveloper-needs-to-know-about-sharepoint-apps-csom-and-anonymouspublishing-sites.aspx
41
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 42. REST API Coverage
Sites, Webs, Features, Event Receivers, Site Collections
Lists, List Items, Fields, Content Types, Views, Forms, IRM
Files, Folders
Users, Roles, Groups, User Profiles, Feeds
Search
42
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 43. REST Get List Items Query
var call = $.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/GetByTitle('ListName')/items",
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
call.done(function (data,textStatus, jqXHR){
var options = "<option value='0'>(None)</option>";
for (index in data.d.results)
{
options += "<option value='"+ data.d.results[index].Id
+"'>"+data.d.results[index].Title+"</option>";
}
$("select[title='<Field Display Name>']").append(options);
});
call.fail(function (jqXHR,textStatus,errorThrown){
alert("Error retrieving Tasks: " + jqXHR.responseText);
});
43
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 44. Client Object Model Coverage
Sites, Webs, Features, Event Receivers, Site Collections
Lists, List Item s, Fields, Content Types, Views, Forms
Files, Folders
Users, Roles, Groups, User Profiles, Feeds
Web Parts
Search
Taxonomy
Workflow
IRM
E-Discovery
Analytics
Business Data
44
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 45. Client Side Object Model (CSOM) Get List Items Query
context = SP.ClientContext.get_current();
var speakerList = context.get_web().get_lists().getByTitle("Vendors");
var camlQuery = SP.CamlQuery.createAllItemsQuery();
this.listItems = speakerList.getItems(camlQuery);
context.load(listItems);
context.executeQueryAsync(ReadListItemSucceeded, ReadListItemFailed);
function ReadListItemSucceeded(sender, args) {
var enumerator = listItems.getEnumerator();
var options = "<option value='0'>(None)</option>";
while (enumerator.moveNext()) {
var listItem = enumerator.get_current();
var Vendor = listItem.get_item('Vendor');
var ID = listItem.get_id();
options += "<option value='"+ ID +"'>"+Vendor+"</option>";
}
$("select[title='<Field Display Name>']").append(options);
}
function ReadListItemFailed(sender, args) {
alert('Request failed. ' + args.get_message() + 'n' + args.get_stackTrace());
}
45
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 46. SPServices
jQuery library that wraps SharePoint’s .asmx Web Services in easy to call
methods
Pros
Shorter learning curve for those already comfortable with jQuery
Works well with anonymous access
Cross site access
Works in SharePoint 2007
Cons
.asmx web services have been deprecated
Results returned as XML that must be manually parsed
http://spservices.codeplex.com
46
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 47. SPServices Get List Items Query
$().SPServices({
operation: "GetListItems",
async: true,
listName: "Vendors",
CAMLViewFields: "<ViewFields><FieldRef Name='Vendor' /></ViewFields>",
CAMLQuery: "<Query><Where><Neq><FieldRef Name='ID' /><Value
Type='Number'>0</Value></Neq></Where></Query>";,completefunc: function(xData, Status) {
var options = "<option value='0'>(None)</option>";
$(xData.responseXML).SPFilterNode("z:row").each(function() { var Vendor =
($(this).attr("ows_Vendor"));
var ID = $(this).attr("ows_ID");
options += "<option value='"+ ID +"'>"+Vendor+"</option>";
});
$("select[title='<Field Display Name>']").append(options);
}});
47
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 48. Storing List Data
Storing data in arrays and JSON objects
var objArray = [
{ID: 1, Title:
{ID: 2, Title:
{ID: 3, Title:
{ID: 4, Title:
];
"Title
"Title
"Title
"Title
1"},
2"},
3"},
4"},
for (index in objArray)
{
var thisTitle = objArray[index].Title;
}
48
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 49. Reading / Storing List Data
Storing data in JSON objects
var objects = {};
objects[1] = {Title: "Title 1"};
objects[2] = {Title: "Title 2"};
objects[3] = {Title: "Title 3"};
for (id in objects)
{
var thisTitle = objects[id].Title;
}
49
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 51. Third Party Libraries
Pros
Saves development time
Hopefully written by someone smarter than me
Thoroughly tested
Cons
Library could become unsupported in the future
May not “work” in SharePoint
Free (jQueryUI) versus Paid (Kendo UI)
Community support vs. paid support
Paid generally has more consistent rendering
51
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 52. Using Third Party Libraries
Look for actively supported libraries
Test in target browsers before implementing
Duplicate file structure
Test “vanilla” in SharePoint first
Agree on a set of core libraries.
52
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 53. DataTables
http://www.datatables.net/
DataTables is a plug-in for the jQuery Javascript library. It is a highly
flexible tool, based upon the foundations of progressive
enhancement, which will add advanced interaction controls to any HTML
table.
53
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 54. DataTables – Basic Usage
//array of arrays
$('#example').dataTable( {
"aaData": [
["row 1","value"],
["row 2","value 2"],
],
"aoColumns": [ //field count must match column count
{ "sTitle": "Column Name" },
{ "sTitle": "Column Name 2" }
]
});
//array of objects
$('#example').dataTable({
"bProcessing": true,
"aaData": vendors, //array of objects
"aoColumns": [
{ "mData": "Vendor" }
]
});
54
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 56. FullCalendar
http://arshaw.com/fullcalendar/
FullCalendar is a jQuery plugin that provides a full-sized, drag &
drop calendar like the one below. It uses AJAX to fetch events on-the-fly for
each month and is easily configured to use your own feed format (an
extension is provided for Google Calendar). It is visually customizable and
exposes hooks for user-triggered events (like clicking or dragging an
event).
56
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 57. FullCalendar – Basic Usage
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay'
},
editable: false,
events: function(start, end, callback) {
//data query goes here
}
});
<div id='calendar'></div>
57
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 58. You mean I can have more than one date on a list?
Fullcalendar demo
- 59. Bluff Charts
http://bluff.jcoglan.com/
Bluff is a JavaScript port of the Gruff graphing library for Ruby. It is
designed to support all the features of Gruff with minimal dependencies;
the only third-party scripts you need to run it are a copy of JS.Class (2.6kB
gzipped) and a copy of Google’s ExCanvas to support canvas in Internet
Explorer. Both these scripts are supplied with the Bluff download. Bluff
itself is around 11kB gzipped.
59
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 60. Bluff Charts – Basic Usage
var g = new Bluff.Bar('LineBarChart', '800x400');
g.title = 'Tasks By User';
g.tooltips = true;
g.theme_37signals();
for (index in tasks)
{
g.data(tasks[index].name, [tasks[index].Completed,
tasks[index].Deferred,tasks[index].NotStarted,
tasks[index].InProgress,tasks[index].Waitingonsomeoneelse]);
}
g.labels = {0: 'Completed', 1: 'Deferred', 2: 'Not Started',
3: 'In Progress', 4: 'Waiting'};
g.draw();
60
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 62. SharePoint Hosted Apps and SPA’s
SharePoint Hosted App
SPA = Single Page Application
Andrew Connell – SharePoint Hosted Apps in 2013 as Single Page Apps
http://www.andrewconnell.com/blog/sharepoint-hosted-apps-in-sp-2013as-single-page-apps
62
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 63. Patterns and Practices
Bringing JavaScript / Client Side development into the 21st century
MV* Patterns
Adds badly needed structure and consistency
Separate display, business, and data retrieval logic
Data Binding
No need to keep track of objects at a granular level
63
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 64. Growing number of libraries
Knockout
http://knockoutjs.com/
Durandal
http://durandaljs.com/
AngularJS
http://angularjs.org/
Ember
http://emberjs.com/
Breeze
http://www.breezejs.com/
64
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 65. AngularJS
http://angularjs.org/
Open-source JavaScript framework, maintained by Google, that assists
with running single-page applications (SPA’s). Its goal is to augment
browser-based applications with model–view–controller (MVC)
capability, in an effort to make both development and testing easier.
65
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 69. TypeScript
http://www.typescriptlang.org/
TypeScript is a language for application-scale JavaScript development.
TypeScript is a typed superset of JavaScript that compiles to plain
JavaScript.
Any browser.
Any host.
Any OS.
Open Source.
69
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
- 71. Final Review
How to Deploy and Reference Scripts
How to effectively use jQuery and search the DOM
How to debug and find out what’s really going on
How to create highly stylized forms without InfoPath or expense form
tools
How to interact with SharePoint using REST, CSOM, and SPServices
How to use Third Party Libraries to do a lot of the heavy lifting
How to get started with SPA’s and SharePoint Hosted Apps
What TypeScript is and how to get started using it
How to go into the office on Monday and get stuff done!
71
© DEVintersection. All rights reserved.
http://www.DEVintersection.com