Methods

add

(source code)
add(items, options)
Add items into a Sharepoint List note: A Date must be provided as "YYYY-MM-DD" (only date comparison) or "YYYY-MM-DD hh:mm:ss" (date AND time comparison), or you can use $SP().toSPDate(new Date()) note: A person must be provided as "-1;#email" (e.g. "-1;#foo@bar.com") OR NT login with double \ (eg "-1;#europe\\foo_bar") OR the user ID note SP2013: If "-1;#" doesn't work on Sharepoint 2013, then try with "i:0#.w|" (e.g. "i:0#.w|europe\\foo_bar") ("i:0#.w|" may vary based on your authentification system -- see https://social.technet.microsoft.com/wiki/contents/articles/13921.sharepoint-20102013-claims-encoding.aspx) note: A lookup value must be provided as "X;#value", with X the ID of the value from the lookup list. --> it should also be possible to not pass the value but only the ID, e.g.: "X;#" note: A URL field must be provided as "http://www.website.com, Name" note: A multiple selection must be provided as ";#choice 1;#choice 2;#", or just pass an array as the value and it will do the trick note: A multiple selection of Lookup must be provided as ";#X;#Choice 1;#Y;#Choice 2;#" (with X the ID for "Choice 1", and "Y" for "Choice 2") --> it should also be possible to not pass the values but only the ID, e.g.: ";#X;#;#Y;#;#" note: A Yes/No checkbox must be provided as "1" (for TRUE) or "0" (for "False") note: A Term / Taxonomy / Managed Metadata field must be provided as "0;#|UniqueIdentifier" for the special hidden related column (see https://github.com/Aymkdn/SharepointPlus/wiki/ to know more) note: You cannot change the Approval Status when adding, you need to use the $SP().moderate function

Parameters:

Object|Array
items
List of items (e.g. [{Field_x0020_Name: "Value", OtherField: "new value"}, {Field_x0020_Name: "Value2", OtherField: "new value2"}])
Object
options Optional
Options (see below)
Number
options.packetsize Optional, Default: 15
If you have too many items to add, then we use `packetsize` to cut them into several requests (because Sharepoint cannot handle too many items at once)
Function
options.progress Optional
(current,max) If you provide more than 'packetsize' items then they will be treated by packets and you can use "progress" to know more about the steps
Boolean
options.escapeChar Optional, Default: true
Determines if we want to escape the special chars that will cause an error (for example '&' will be automatically converted to '&')
String
options.rootFolder Optional, Default: ''
When dealing with Discussion Board you need to provide the rootFolder of the Message when you post a reply

Returns:

Promise
resolve({passed, failed}), reject(error)

Example:

$SP().list("My List").add({Title:"Ok"});

$SP().list("List Name").add([{Title:"Ok"}, {Title:"Good"}]).then(function(items) { alert("Done!"); });

$SP().list("My List","http://my.sharepoi.nt/dir/").add({Title:"Ok"}).then(function(items) {
  if (items.failed.length > 0) {
    for (var i=0; i < items.failed.length; i++) console.log("Error '"+items.failed[i].errorMessage+"' with:"+items.failed[i].Title); // the 'errorMessage' attribute is added to the object
  }
  if (items.passed.length > 0) {
    for (var i=0; i < items.passed.length; i++) console.log("Success for:"+items.passed[i].Title+" (ID:"+items.passed[i].ID+")");
  }
});

// different ways to add John and Tom into the table
$SP().list("List Name").add({Title:"John is the Tom's Manager",Manager:"-1;#john@compagny.com",Report:"-1;#tom@compagny.com"}); // if you don't know the ID
$SP().list("My List").add({Title:"John is the Tom's Manager",Manager:"157",Report:"874"}); // if you know the Lookup ID

// for Discussion Board, please refer to https://github.com/Aymkdn/SharepointPlus/wiki/Sharepoint-Discussion-Board

addAttachment

(source code)
addAttachment(setup)
Add an attachment to a Sharepoint List Item

Parameters:

Object
setup
Options (see below)
Number
setup.ID
The item ID to attach the file
String
setup.filename
The name of the file
String
setup.attachment
An array buffer of the file content

Returns:

Promise
resolve(fileURL), reject()

Example:

$SP().list("My List").addAttachment({
  ID:1,
  filename:"helloworld.txt",
  attachment:"*ArrayBuffer*"
}).then(function(fileURL) {
  alert(fileURL)
});

cleanResult

(source code)
cleanResult(str, separator)
clean a string returned by a GET (remove ";#" and "string;#" and null becomes "")

Parameters:

String
str
The string to clean
String
separator Optional, Default: ";"
When it's a list we may want to have a different output (see examples)

Returns:

String
the cleaned string

Example:

$SP().cleanResult("15;#Paul"); // -> "Paul"
$SP().cleanResult("string;#Paul"); // -> "Paul"
$SP().cleanResult("string;#"); // -> ""
$SP().cleanResult(";#Paul;#Jacques;#Aymeric;#"); // -> "Paul;Jacques;Aymeric"
$SP().cleanResult(";#Paul;#Jacques;#Aymeric;#", ", "); // -> "Paul, Jacques, Aymeric"

get

(source code)
get(options)
Get the content of the list based on different criteria (by default the default view is used)

Parameters:

Object
options Optional
Options (see below)
String
options.fields Optional, Default: ""
The fields you want to grab (be sure to add "Attachments" as a field if you want to know the direct link to an attachment)
String
options.view Optional, Default: ""
If you specify a viewID or a viewName that exists for that list, then the fields/where/order settings for this view will be used in addition to the FIELDS/WHERE/ORDERBY you have defined (the user settings will be used first)
String|Array
options.where Optional, Default: ""
The query string (like SQL syntax) (you'll need to use double \\ before the inside ' -- see example below); you can use an array that will make the sequential requests but it will return all the data into one array (useful for the Sharepoint 2010 throttling limit)
Boolean
options.whereCAML Optional, Default: false
If you want to pass a WHERE clause that is with CAML Syntax only instead of SQL-like syntax -- see $SP().parse() for more info
Boolean
options.whereEscapeChar Optional, Default: true
Determines if we want to escape the special chars that will cause an error (for example '&' will be automatically converted to '&&amp;') -- this is applied to the WHERE clause only
Function
options.whereFct Optional, Default: function(w){return w}
Permits to apply your own function on the WHERE clause after conversion to CAML (can be useful also when you use the "view" parameter)
Function
options.progress Optional
When using an array for the WHERE or the PAGING option then you can call the progress function (see the example)
String
options.orderby Optional, Default: ""
The field used to sort the list result (you can also add "ASC" -default- or "DESC")
String
options.groupby Optional, Default: ""
The field used to group by the list result
Integer
options.rowlimit Optional, Default: 0
You can define the number of rows you want to receive back (0 is infinite)
Boolean
options.paging Optional, Default: false
If you have defined the 'rowlimit' then you can use 'paging' to cut by packets your full request -- this is useful when there is a list view threshold (attention: we cannot use "WHERE" or "ORDERBY" with this option)
Integer
options.page Optional, Default: infinite
When you use the `paging` option, several requests will be done until we get all the data, but using the `page` option you can define the number of requests/pages you want to get
String
options.listItemCollectionPositionNext Optional, Default: ""
When doing paging, this is the index used by Sharepoint to get the next/previous page
Boolean
options.useIndexForOrderBy Optional, Default: false
Based on https://spservices.codeplex.com/discussions/280642#post1323410 it permits to override the 5,000 items limit in an unique call (for Sharepoint 2010 only) -- see the example below to know how to use it
Boolean
options.expandUserField Optional, Default: false
When you get a user field, you can have more information (like name,email,sip,...) by switching this to TRUE
Boolean
options.dateInUTC Optional, Default: false
TRUE to return dates in Coordinated Universal Time (UTC) format. FALSE to return dates in ISO format.
Object
options.folderOptions Optional
Permits to read the content of a Document Library (see below)
String
options.folderOptions.path Optional, Default: ""
Relative path of the folders we want to explore (by default it's the root of the document library)
String
options.folderOptions.show Optional, Default: "FilesAndFolders_InFolder"
Four values: "FilesOnly_Recursive" that lists all the files recursively from the provided path (and its children); "FilesAndFolders_Recursive" that lists all the files and folders recursively from the provided path (and its children); "FilesOnly_InFolder" that lists all the files from the provided path; "FilesAndFolders_InFolder" that lists all the files and folders from the provided path
Boolean
options.queryOptions Optional
If you want to provide your own QueryOptions and overwrite the ones built for you -- it should be some XML code (see https://msdn.microsoft.com/en-us/library/lists.lists.getlistitems%28v=office.12%29.aspx?f=255&MSPPError=-2147217396)
Object
options.join Optional
Permits to create a JOIN closure between the current list and another one: it will be the same syntax than a regular GET (see the example below)
String
options.join.list Optional
Permits to establish the link between two lists (see the example below)
String
options.join.url Optional, Default: 'current website'
The website url (if different than the current website)
String
options.join.on Optional
Permits to establish the link between two lists (only between the direct parent list and its child, not with the grand parent) (see the example below)
String
options.join.onLookup Optional
Permits to establish the link between two lists based on a lookup field... it's more optimized than the simple `join.on` (see the example below)
Boolean
options.join.outer Optional, Default: false
If you want to do an outer join (you can also directly use "outerjoin" instead of "join")
Boolean
options.calendar Optional, Default: false
If you want to get the events from a Calendar List
Object
options.calendarOptions Optional
Options that will be used when "calendar:true" (see the example to know how to use it)
Boolean
options.calendarOptions.splitRecurrence Optional, Default: true
By default we split the events with a recurrence (so 1 item = 1 day of the recurrence)
String|Date
options.calendarOptions.referenceDate Optional, Default: today
This is the date used to retrieve the events -- that can be a JS Date object or a SP Date (String) [attention: if 'splitRecurrence' is FALSE, then Sharepoint will ignore this 'referenceDate'...]
String
options.calendarOptions.range Optional, Default: "Month"
By default we have all the events in the reference month (based on the referenceDate), but we can restrict it to a week with "Week" (from Monday to Sunday) (see https://blog.kodono.info/wordpress/2018/07/09/sharepoint-daterangesoverlap-value/)

Returns:

Promise
resolve(data returned by the server), reject(error from $SP().ajax())

Example:

$SP().list("List Name").get().then(function(data) {
  for (var i=0; i<data.length; i++) console.log(data[i].getAttribute("Title"));
});

// with some fields and an orderby command
$SP().list("ListName","http://www.mysharepoint.com/mydir/").get({
  fields:"Title,Organization",
  orderby:"Title DESC,Test_x0020_Date ASC"
}).then(function(data) {
  for (var i=0; i<data.length; i++) console.log(data[i].getAttribute("Title"));
});

// handle the errors
$SP().list("List Name").get().then(function(data) {
  for (var i=0; i<data.length; i++) console.log(data[i].getAttribute("Title"));
}).catch(function(err) {
  console.log("Error => ",err)
});

// the WHERE clause must be SQL-like
// the field names must be the internal names used by Sharepoint
// ATTENTION - note that here we open the WHERE string with simple quotes (') and that should be your default behavior each time you use WHERE
var name = "O'Sullivan, James";
$SP().list("My List").get({
  fields:"Title",
  where:'Fiscal_x0020_Week > 30 AND Fiscal_x0020_Week < 50 AND Name = "'+name+'"'
}).then(function(row) {
  for (var i=row.length;i--;) console.log(row[i].getAttribute("Title"));
});

// Same example but this time we write the name directly inside the query...
// So make sure to use a single backslash (\) if you have a simple quote ' inside your WHERE with a double quotes (") to open/close the string
$SP().list("My List").get({
  fields:"Title",
  where:'Fiscal_x0020_Week > 30 AND Fiscal_x0020_Week < 50 AND Name = "O\'Sullivan, James"'
}).then(function(row) {
  for (var i=row.length;i--;) console.log(row[i].getAttribute("Title"));
});
// Or to use a double backslash (\\) if you have a simple quote ' inside your WHERE with a simple quote (') to open/close the string
$SP().list("My List").get({
  fields:"Title",
  where:"Fiscal_x0020_Week > 30 AND Fiscal_x0020_Week < 50 AND Name = 'O\\'Sullivan, James'"
}).then(function(row) {
  for (var i=row.length;i--;) console.log(row[i].getAttribute("Title"));
});

// also in the WHERE clause you can use '[Me]' to filter by the current user,
$SP().list("My List").get({
  fields:"Title",
  where:"Author = '[Me]'"
}).then(function(row) {
  console.log(row[0].getAttribute("Title"));
});

// also in the WHERE clause you can use '[Today]' or '[Today-X]' with 'X' a number,
// Here it will return the records done yesterday
$SP().list("My List").get({
  fields:"Title",
  where:"Created = '[Today-1]'"
}).then(function(row) {
  console.log(row[0].getAttribute("Title"));
});

// Since 3.0.8, if you do a WHERE on a Date with the Time included, then it will compare with the tim
// see http://blogs.syrinx.com/blogs/sharepoint/archive/2008/08/05/caml-queries-with-dates.aspx
// here it will only show the items created at 2PM exactly -- if you want to check only the today, then use "Created = '2014-03-12'"
$SP().list("My List").get({
  fields:"Title",
  where:"Created = '2014-03-12 14:00:00'"
}).then(function(row) {
  console.log(row[0].getAttribute("Title"));
});

// We have a list called "My List" with a view already set that is called "Marketing View" with some FIELDS and a WHERE clause
// so the function will grab the view information and will get the data from the list with "Author = '[Me]'" and adding the view's WHERE clause too
$SP().list("My List","http://my.sharepoint.com/my/site/").get({
  view:"Marketing View",
  where:"Author = '[Me]'"
}).then(function(data) {
  for (var i=data.length; i--;) console.log(data[i].getAttribute("Title") + " by " + data[i].getAttribute("Author"));
});

// use the paging option for the large list to avoid the message "the attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator"
// ATTENTION: if you use the WHERE option then it could return the "view threshold" error message because the packet from the WHERE is too big and SharePoint is too stupid...
$SP().list("My List").get({
  fields:"ID,Title",
  rowlimit:5000,
  paging:true,
  progress:function progress(nbItemsLoaded) {
    // for each new page this function will be called
    console.log("It's still loading... already "+nbItemsLoaded+" items have been loaded!");
  }
}).then(function(data) {
  console.log(data.length); // -> 23587
})
// add the `page` option to stop after a number of requests/pages
// for example you only want the last record from a list that has more than 5,000 items
$SP().list("My List").get({fields:"ID",orderby:"ID DESC",rowlimit:1,paging:true,page:1}).then(function(data) {
  console.log("last ID : "+data[0].getAttribute("ID"));
})
// use `listItemCollectionPositionNext` to start from this index
$SP().list("My List").get({
  fields:"ID",
  orderby:"ID DESC",
  rowlimit:10,
  paging:true,
  page:1
}).then(function(data) {
  // "data" is our first page of data
  // get the next block
  return $SP().list("My List").get({fields:"ID",orderby:"ID DESC",rowlimit:10,paging:true,page:1,listItemCollectionPositionNext:data.NextPage})
}).then(function(data) {
  // here "data" is the 2nd block of data
  // If you want to access to the previous page, you can use:
  // listItemCollectionPositionNext:"Paged=TRUE&PagedPrev=True&p_ID="+ID
  // with ID the first/smallest ID of the current set.
  // reference: https://social.technet.microsoft.com/wiki/contents/articles/18606.sharepoint-2013-paging-with-sharepoint-client-object-model.aspx
})

// We can also find the files from a Document Shared Library
$SP().list("Shared Documents","http://my.share.point.com/my_site/").get({
  fields:"FileLeafRef,File_x0020_Size",
}).then(function(data) {
  for (var i=0; i<<data.length; i++) console.log("FileName:"+data[i].getAttribute("FileLeafRef"),"FileSize:"+data[i].getAttribute("File_x0020_Size"));
});

// We can join two or more lists together based on a condition
// ATTENTION: in that case the DATA passed to the callback will return a value for "LIST NAME.FIELD_x0020_NAME" and not directly "FIELD_x0020_NAME"
// ATTENTION: you need to make sure to call the 'fields' that will be used in the 'on' clause
$SP().list("Finance and Expense","http://my.sharepoint.com/my_sub/dir/").get({
  fields:"Expense_x0020_Type",
  where:"Finance_x0020_Category = 'Supplies'",
  join:{
    list:"Purchasing List",
    fields:"Region,Year,Expense_x0020_Type,Finance_x0020_Category,Cost",
    where:"Region = 'EMEA' AND Year = 2012",
    orderby:"Expense_x0020_Type,Finance_x0020_Category",
    on:"'Purchasing List'.Expense_x0020_Type = 'Finance and Expense'.Expense_x0020_Type",
    join:{
      list:"Financial Static Data",
      fields:"Region,Year,Expense_x0020_Type,Finance_x0020_Category,Forecast",
      where:"Region = 'EMEA' AND Year = 2012",
      on:"'Purchasing List'.Region = 'Financial Static Data'.Region AND 'Purchasing List'.Expense_x0020_Type = 'Financial Static Data'.Expense_x0020_Type"
    }
  }
}).then(function(data) {
  for (var i=0; i<data.length; i++) {
    console.log(data[i].getAttribute("Purchasing List.Region")+" | "+data[i].getAttribute("Purchasing List.Year")+" | "+data[i].getAttribute("Purchasing List.Expense_x0020_Type")+" | "+data[i].getAttribute("Purchasing List.Cost"));
  }
});

// By default "join" is an "inner join", but you can also do an "outerjoin"
// ATTENTION: in that case the DATA passed to the callback will return a value for "LIST NAME.FIELD_x0020_NAME" and not directly "FIELD_x0020_NAME"
// ATTENTION: you need to make sure to call the 'fields' that will be used in the 'on' clause
$SP().list("Finance and Expense","http://my.sharepoint.com/my_sub/dir/").get({
  fields:"Expense_x0020_Type",
  where:"Finance_x0020_Category = 'Supplies'",
  join:{
    list:"Purchasing List",
    fields:"Region,Year,Expense_x0020_Type,Finance_x0020_Category,Cost",
    where:"Region = 'EMEA' AND Year = 2012",
    orderby:"Expense_x0020_Type,Finance_x0020_Category",
    on:"'Purchasing List'.Expense_x0020_Type = 'Finance and Expense'.Expense_x0020_Type",
    outerjoin:{
      list:"Financial Static Data",
      fields:"Region,Year,Expense_x0020_Type,Finance_x0020_Category,Forecast",
      where:"Region = 'EMEA' AND Year = 2012",
      on:"'Purchasing List'.Region = 'Financial Static Data'.Region AND 'Purchasing List'.Expense_x0020_Type = 'Financial Static Data'.Expense_x0020_Type"
    }
  }
}).then(function(data) {
  for (var i=0; i<data.length; i++)
    console.log(data[i].getAttribute("Purchasing List.Region")+" | "+data[i].getAttribute("Purchasing List.Year")+" | "+data[i].getAttribute("Purchasing List.Expense_x0020_Type")+" | "+data[i].getAttribute("Purchasing List.Cost"));
})

// Another example of "outerjoin", but this time with fields tied to a Lookup ID
// Here 1 Project can have several Deliverables based on field "Project ID", and 1 Deliverable can have several team members based on "Deliverable ID"
$SP().list("Projects").get({
  fields:"ID,Project_x0020_Name",
  where:"Status = 'In Progress'",
  outerjoin:{
    list:"Deliverables",
    fields:"ID,Name",
    onLookup:"Project_x0020_ID",
    outerjoin:{
      list:"Team Members",
      fields:"ID,Deliverable_x0020_ID,Name",
      onLookup:"Deliverable_x0020_ID"
    }
  }
}).then(function(data) {
  var html = '<table class="table default"><thead><tr><th>Project ID</th><th>Project Name</th><th>Deliverable ID</th><th>Deliverable Name</th><th>Team ID</th><th>Member Name</th></tr></thead><tbody>'
  for (var i=0;i<data.length; i++) {
    html += '<tr><td>'+data[i].getAttribute("Projects.ID")+'</td><td>'+data[i].getAttribute("Projects.Project_x0020_Name")+'</td><td>'+data[i].getAttribute("Deliverables.ID")+'</td><td>'+data[i].getAttribute("Deliverables.Name")+'</td><td>'+data[i].getAttribute("Team Members.ID")+'</td><td>'+data[i].getAttribute("Team Members.Name")+'</td></tr>'
  }
  html += '</tbody></table>';
  $('#part1').html(html);
})

// With Sharepoint 2010 we are limited due to the throttling limit (see here for some very interesting information http://www.glynblogs.com/2011/03/sharepoint-2010-list-view-throttling-and-custom-caml-queries.html)
// So for example if I do WHERE:'Fiscal_x0020_Year = 2012' it will return an error because I have 6,500 items
// So I'll do several requests for each Fiscal_x0020_Week into this Fiscal Year
var query=[],q=[];
for (var i=1; i<54; i++) {
  q.push("Fiscal_x0020_Week = "+i);
  if (i%8==0 || i == 53) {
    query.push("("+q.join(" OR ")+") AND Fiscal_x0020_Year = 2012");
    q=[]
  }
}
// it returns :
// [
//   "(Fiscal_x0020_Week = 1 OR Fiscal_x0020_Week = 2 OR Fiscal_x0020_Week = 3 OR Fiscal_x0020_Week = 4 OR Fiscal_x0020_Week = 5 OR Fiscal_x0020_Week = 6 OR Fiscal_x0020_Week = 7 OR Fiscal_x0020_Week = 8) AND Fiscal_x0020_Year = 2012",
//   ...
//   "(Fiscal_x0020_Week = 49 OR Fiscal_x0020_Week = 50 OR Fiscal_x0020_Week = 51 OR Fiscal_x0020_Week = 52 OR Fiscal_x0020_Week = 53) AND Fiscal_x0020_Year = 2012"
// ]
$SP().list("Sessions").get({
  fields:"Title,Score",
  where:query,
  progress:function progress(current,max) {
    // when we use an array for the WHERE clause we are able to provide `current` and `max`
    console.log("Progress: "+current+" / "+max);
  }
}).then(function(data) {
  console.log(data.length); // -> 6,523
});
// also regarding the throttling limit, you can query a list on a user column in using the User ID
// For example if John Doe is recorded as "328;#Doe, John" then you'll have to use the special operator "~="
$SP().list("Sessions").get({
  fields:"Title",
  where:'User ~= 328"
}).then(function(data) {
  console.log(data.length);
});

// if you want to list only the files visible into a folder for a Document Library
$SP().list("My Shared Documents").get({
  fields:"BaseName,FileRef,FSObjType", // "BaseName" is the name of the file/folder; "FileRef" is the full path of the file/folder; "FSObjType" is 0 for a file and 1 for a folder (you need to apply $SP().cleanResult()), "File_x0020_Size" the filesize in bytes
  folderOptions:{
    path:"My Folder/Sub Folder/",
    show:"FilesOnly_InFolder"
  }
});

// if you want to list all the files and folders for a Document Library
$SP().list("My Shared Documents").get({
  fields:"BaseName,FileRef,FSObjType", // "BaseName" is the name of the file/folder; "FileRef" is the full path of the file/folder; "FSObjType" is 0 for a file and 1 for a folder (you need to apply $SP().cleanResult())
  folderOptions:{
    show:"FilesAndFolders_Recursive"
  }
});

// How to retrieve the events from a Calendar List
// NOTE -- when "calendar:true" we automatically get some fields: "Title", "EventDate" -- the Start Date --, "EndDate", "RecurrenceData", Duration", fAllDayEvent", "fRecurrence", "ID"
$SP().list("My Calendar").get({
  fields:"Description",
  calendar:true,
  calendarOptions:{
    referenceDate:new Date(2012,4,4),
    range: "Week"
  }
  where:"Category = 'Yellow'"
}).then(function(data) {
  var events=[];
  for (var i=0; i<data.length; i++) {
    // several information are available -- see below
    events.push({
      Title:         data[i].getAttribute("Title"),
      StartDateTime: data[i].getAttribute("EventDate"), // you can use $SP().toDate() to have a JS Date
      EndDateTime:   data[i].getAttribute("EndDate"), // you can use $SP().toDate() to have a JS Date
      Recurrence:    (data[i].getAttribute("fRecurrence") == 1 ? true : false),
      AllDayEvent:   (data[i].getAttribute("fAllDayEvent") == 1 ? true : false),
      RecurrenceEnd: (data[i].getAttribute("RecurrenceData")||"").replace(/.+([^<]+)<\/windowEnd>.+/,"$1"), // see the NOTE below
      ID:            data[i].getAttribute("ID"), // the ID for the recurrence events is special but can be also passed to "Display.aspx?ID="
      Duration:      1*data[i].getAttribute("Duration") // Duration is in SECONDS
    })
    // NOTE: with data[i].getAttribute("RecurrenceData") you'll find more info about the recurrence (like the end date for the serie, and much more),
    // but because there are a lot of scenario, I won't handle the different cases.
    // e.g. for a daily recurrence you can find the end date of the serie with: data[i].getAttribute("RecurrenceData").replace(/.+([^<]+)<\/windowEnd>.+/,"$1")
    // --> it will return a SP Date
  }
})

// for Discussion Board, please refer to https://github.com/Aymkdn/SharepointPlus/wiki/Sharepoint-Discussion-Board

// [It doesn't work with Sharepoint 2013 anymore, only for SP2010]
// You can use `useIndexForOrderBy:true` to override the list view threshold -- see https://spservices.codeplex.com/discussions/280642
// To make it to work, you need :
// 1) to have "ID > 0 AND Another_Index_Column_Filtered" in the WHERE Clause (so at least two filters), and then we can add some other WHERE (even the not indexed columns)
// 2) To use `orderby`, with an indexed column
// 3) To use `useIndexForOrderBy:true`
// see the below example with Trainer an indexed column, and Equipment a column not indexed
// NOTE: you need to test your WHERE to see if it works or not, because it's vary a lot depending of the kind of WHERE clause you'll use
$SP().list("Calendar",'http://intranet.dell.com/services/Educate/Toolbox/scheduling_tool/').get({
  fields:"Trainer",
  where:'ID > 0 AND Trainer <> "" AND Equipment LIKE "Box"',
  orderby:'Trainer',
  useIndexForOrderBy:true
}).then(function(d) {
  console.log(d.length)
})

getAttachment

(source code)
getAttachment(itemID)
Get the attachment(s) for an item

Parameters:

String|Number
itemID
The item ID

Returns:

Promise
resolve([results])

Example:

$SP().list("My List","http://my.site.com/mydir/").getAttachment(1).then(function(attachments) {
  for (var i=0; i<attachments.length; i++) console.log(attachments[i]); -> "https://my.site.com/site/Lists/Something/Attachments/46/helloworld.txt"
});

// you can also use $SP().list().get() using the "Attachments" field

getContentTypeInfo

(source code)
getContentTypeInfo(contentType, options)
Get the Content Type Info for a Content Type into the list

Parameters:

String
contentType
The Name or the ID (from $SP().list.getContentTypes) of the Content Type
Object
options Optional
Boolean
options.cache Optional, Default: true
Do we use the cache?

Returns:

Promise
resolve(fields), reject(error)

Example:

$SP().list("List Name").getContentTypeInfo("Item").then(function(fields) {
  for (var i=0; i<fields.length; i++) console.log(fields[i]["DisplayName"]+ ": "+fields[i]["Description"]);
});

$SP().list("List Name").getContentTypeInfo("0x01009C5212B2D8FF564EBE4873A01C57D0F9001").then(function(fields) {
  for (var i=0; i<fields.length; i++) console.log(fields[i]["DisplayName"]+ ": "+fields[i]["Description"]);
});

getContentTypes

(source code)
getContentTypes(options)
Get the Content Types for the list (returns Name, ID and Description)

Parameters:

Object
options Optional
Boolean
options.cache Optional, Default: true
Do we want to use the cache on recall for this function?

Returns:

Promise
resolve(contentTypes), reject(error)

Example:

$SP().list("List Name").getContentTypes().then(function(contentTypes) {
  for (var i=0; i<contentTypes.length; i++) console.log(contentTypes[i].Name, contentTypes[i].ID, contentTypes[i].Description);
});

getWorkflowID

(source code)
getWorkflowID(setup)
Find the WorkflowID for a workflow, and some other related info

Parameters:

Object
setup
Number
setup.ID
The item ID that is tied to the workflow
String
setup.workflowName
The name of the workflow

Returns:

Promise
resolve({workflowID, fileRef, description, instances}), reject(error)

Example:

$SP().list("List Name").getWorkflowID({ID:15, workflowName:"Workflow for List Name (manual)"}).then(function(params) {
  alert("Workflow ID:"+params.workflowID+" and the FileRef is: "+params.fileRef);
});

history

(source code)
history(params)
When versioning is an active option for your list, then you can use this function to find the previous values for a field

Parameters:

Object
params
See below
String|Number
params.ID
The item ID
String
params.Name
The field name

Returns:

Promise
resolve(data), reject(error)

Example:

$SP().list("My List").history({ID:1981, Name:"Critical_x0020_Comments"}).then(function(data) {
  for (var i=0,len=data.length; i<len; i++) {
    console.log("Date: "+data[i].getAttribute("Modified")); // you can use $SP().toDate() to convert it to a JavaScript Date object
    console.log("Editor: "+data[i].getAttribute("Editor")); // it's the long format type, so the result looks like that "328;#Doe,, John,#DOMAIN\john_doe,#John_Doe@example.com,#,#Doe,, John"
    console.log("Content: "+data[i].getAttribute("Critical_x0020_Comments")); // use the field name here
  }
});

info

(source code)
info()
Get the columns' information/metadata, and the list's details

Returns:

Promise
resolve(infos), reject(error)

Example:

$SP().list("List Name").info().then(function(infos) {
  // for columns' details:
  for (var i=0; i<infos.length; i++) console.log(infos[i]["DisplayName"]+ ": => ",infos[i]);
  // for list's details:
  console.log(infos._List)
});

lists

(source code)
lists(setup)
Get all the lists from the site

Parameters:

Object
setup Optional
Options (see below)
String
setup.url Optional, Default: 'current website'
The website url
Boolean
setup.cache Optional, Default: true
To get the result from the cache when available

Returns:

Promise
resolve({ID, Name, Description, Url, .....}), reject(error)

Example:

$SP().lists().then(function(lists) {
  for (var i=0; i<lists.length; i++) console.log("List #"+i+": "+lists[i].Name);
});

moderate

(source code)
moderate(approval, setup)
Moderate items from a Sharepoint List

Parameters:

Array
approval
List of items and ApprovalStatus (e.g. [{ID:1, ApprovalStatus:"Approved"}, {ID:22, ApprovalStatus:"Pending"}])
Object
setup Optional
Options (see below)
Number
setup.packetsize Optional, Default: 15
If you have too many items to moderate, then we use `packetsize` to cut them into several requests (because Sharepoint cannot handle too many items at once)
Function
setup.progress Optional
Two parameters: 'current' and 'max' -- if you provide more than `packetsize` ID then they will be treated by packets and you can use "progress" to know more about the steps

Returns:

Promise
resolve({passed, failed}), reject(error)

Example:

$SP().list("My List").moderate({ID:1, ApprovalStatus:"Rejected"}); // you must always provide the ID

$SP().list("Other List").moderate([{ID:5, ApprovalStatus:"Pending"}, {ID: 15, ApprovalStatus:"Approved"}]).then(function(items) {
  for (var i=0; i < items.failed.length; i++) console.log("Error with:"+items.failed[i].ID);
  for (var i=0; i < items.passed.length; i++) console.log("Success with:"+items.passed[i].getAttribute("Title"));
});

parse

(source code)
parse(where, escapeChar)
Use a WHERE sentence to transform it into a CAML Syntax sentence

Parameters:

String
where
The WHERE sentence to change
String
escapeChar Optional, Default: true
Determines if we want to escape the special chars that will cause an error (for example '&' will be automatically converted to '&amp;')

Example:

$SP().parse('ContentType = "My Content Type" OR Description <> null AND Fiscal_x0020_Week >= 43 AND Result_x0020_Date < "2012-02-03"');
// -> return <And><And><Or><Eq><FieldRef Name="ContentType" /><Value Type="Text">My Content Type</Value></Eq><IsNotNull><FieldRef Name="Description" /></IsNotNull></Or><Geq><FieldRef Name="Fiscal_x0020_Week" /><Value Type="Number">43</Value></Geq></And><Lt><FieldRef Name="Result_x0020_Date" /><Value Type="DateTime">2012-02-03</Value></Lt></And>

// available operators :
// "<" : less than
// "<=" : less than or equal to
// ">" : greater than
// ">=" : greater than or equal to
// "<>" : different
// "~=" : this must be only used when comparing to a number that represents the User ID (e.g. 'User ~= 328') - that permits to query a list with too many items but with the User column that is indexed
// " AND "
// " OR "
// " LIKE " : for example 'Title LIKE "foo"' will return "foobar" "foo" "barfoobar" "barfoo" and so on
// " IN " : for example 'Location IN ["Los Angeles","San Francisco","New York"]', equivalent to 'Location = "Los Angeles" OR Location = "San Francisco" OR Location = "New York"' — SP2013 limits each IN to 60 items. If you want to check Lookup IDs instead of text you can use '~' followed by the ID, for example 'Location IN ["~23", "~26", "~30"]'

// special words:
// '[Me]' : for the current user
// '[Today]' : to use the today date
// '[Today+X]' : to use today + X days
// Null : for the Null value
// TRUE : for the Yes/No columns
// FALSE : for the Yes/No columns

// in the below example, on the "&" will be escaped
var bar="Bob & Marley";
var foo="O'Conney";
$SP().parse('Bar = "'+bar+'" AND Foo = "'+foo+'"'); // -> <And><Eq><FieldRef Name="Bar" /><Value Type="Text">Bob & Marley</Value></Eq><Eq><FieldRef Name="Foo" /><Value Type="Text">O'Conney</Value></Eq></And>
$SP().parse("Bar = '"+bar+"' AND Foo = '"+foo+"'"); // don't put the simple and double quotes this way because it'll cause an issue with O'Conney

remove

(source code)
remove(itemsID, options)
Delete items from a Sharepoint List

Parameters:

Objet|Array
itemsID Optional
List of items ID (e.g. [{ID:1}, {ID:22}]) | ATTENTION if you want to delete a file you have to add the "FileRef" e.g. {ID:2,FileRef:"path/to/the/file.ext"}
Object
options Optional
Options (see below)
String
options.where Optional
If you don't specify the itemsID (first param) then you have to use a `where` clause - it will search for the list of items ID based on the `where` and it will then delete all of them
Number
options.packetsize Optional, Default: 15
If you have too many items to delete, then we use `packetsize` to cut them into several requests (because Sharepoint cannot handle too many items at once)
Function
options.progress Optional
Two parameters: 'current' and 'max' -- If you provide more than 'packetsize' ID then they will be treated by packets and you can use "progress" to know more about the steps

Returns:

Promise
resolve({passed, failed}), reject(error)

Example:

$SP().list("My List").remove({ID:1});
// we can use the WHERE clause instead providing the ID
$SP().list("My List").remove({where:"Title = 'OK'",progress:function(current,max) {
  console.log(current+"/"+max);
}});

// delete several items
$SP().list("List Name", "http://my.sharepoint.com/sub/dir/").remove([{ID:5}, {ID:7}]);

$SP().list("List").remove({ID:43, Title:"My title"}).then(function(items) {
  for (var i=0; i < items.failed.length; i++) console.log("Error with:"+items.failed[i].ID+" ("+items.failed[i].errorMessage+")"); // only .ID and .errorMessage are available
});

// example for deleting a file
$SP().list("My Shared Documents").remove({ID:4,FileRef:"my/directory/My Shared Documents/something.xls"});

startWorkflow

(source code)
startWorkflow(setup)
Manually start a workflow (that has been set to be manually started) (for "Sharepoint 2010 workflow" as the platform type)

Parameters:

Object
setup
String
setup.workflowName
The name of the workflow
Number
setup.ID Optional
The item ID that tied to the workflow
Array|Object
setup.parameters Optional
An array of object with {name:"Name of the parameter", value:"Value of the parameter"}
String
setup.fileRef Optional
Optional: you can provide the fileRef to avoid calling the $SP().list().getWorkflowID()
String
setup.workflowID Optional
Optional: you can provide the workflowID to avoid calling the $SP().list().getWorkflowID()

Returns:

Promise
resolve() if it's started, reject(error)

Example:

// if you want to call a Site Workflow, just leave the list name empty and don't provide an item ID, e.g.:
$SP().list("").startWorkflow({workflowName:"My Site Workflow"});

// to start a workflow for a list item
$SP().list("List Name").startWorkflow({ID:15, workflowName:"Workflow for List Name (manual)", parameters:{name:"Message",value:"Welcome here!"}).then(function() {
  alert("Worflow Started!")
}).catch(function(error) {
    console.log("Error: ",error);
});

startWorkflow2013

(source code)
startWorkflow2013(setup)
Manually start a work (that has been set to be manually started) (for "Sharepoint 2013 workflow" as the platform type)

Parameters:

Object
setup
Number
setup.ID Optional
The item ID that tied to the workflow
String
setup.workflowName
The name of the workflow
Array|Object
setup.parameters Optional
An array of object with {name:"Name of the parameter", value:"Value of the parameter"}

Returns:

Promise
resolve() when started, reject(error)

Example:

// if you want to call a Site Workflow, just leave the list name empty and don't provide an item ID, e.g.:
$SP().list("").startWorkflow2013({workflowName:"My Site Workflow"});

// to start a workflow for a list item
$SP().list("List Name").startWorkflow2013({ID:15, workflowName:"Workflow for List Name (manual)", parameters:{name:"Message",value:"Welcome here!"}).then(function() {
  console.log("workflow started")
}, function(error) {
  console.log("Error: ",error);
});

update

(source code)
update(items, options)
Update items from a Sharepoint List

Parameters:

Array
items
List of items (e.g. [{ID: 1, Field_x0020_Name: "Value", OtherField: "new value"}, {ID:22, Field_x0020_Name: "Value2", OtherField: "new value2"}])
Object
options Optional
Options (see below)
String
options.where Optional, Default: ""
You can define a WHERE clause
Number
options.packetsize Optional, Default: 15
If you have too many items to update, then we use `packetsize` to cut them into several requests (because Sharepoint cannot handle too many items at once)
Function
options.progress Optional
Two parameters: 'current' and 'max' -- if you provide more than 'packetsize' ID then they will be treated by packets and you can use "progress" to know more about the steps
Boolean
options.escapeChar Optional, Default: true
Determines if we want to escape the special chars that will cause an error (for example '&' will be automatically converted to '&amp;')

Returns:

Promise
resolve({passed, failed}), reject(error)

Example:

$SP().list("My List").update({ID:1, Title:"Ok"});
// if you use the WHERE then you must not provide the item ID:
$SP().list("List Name").update({Title:"Ok"},{where:"Status = 'Complete'"});

$SP().list("My List","http://sharepoint.org/mydir/").update([{ID:5, Title:"Ok"}, {ID: 15, Title:"Good"}]);

$SP().list("List Name").update({ID:43, Title:"Ok"}).then(function(items) {
  for (var i=0; i < items.failed.length; i++) console.log("Error '"+items.failed[i].errorMessage+"' with:"+items.failed[i].Title);
  var len=items.passed.length;
  console.log(len+(len>1?" items have been successfully added":" item has been successfully added"))
});

view

(source code)
view(viewID, options)
Get the view's details (like selected fields, order by, where, ....)

Parameters:

String
viewID Optional, Default: "The default view"
The view ID or view Name
Object
options Optional
(see below)
Boolean
options.cache Optional, Default: true
Get the view's info from the cache

Returns:

Promise
resolve({DefaultView, Name, ID, Type, Url, OrderBy, Fields, RowLimit, WhereCAML}), reject(error)

Example:

$SP().list("List Name").view("All Items").then(function(res) {
  for (var i=0; i<res.Fields.length; i++) console.log("Column "+i+": "+res.Fields[i]);
  console.log("And the GUI for this view is :"+res.ID);
});

views

(source code)
views(options)
Get the views' info for a List

Parameters:

Hash
options Optional
Boolean
options.cache Optional, Default: true
Get the info from the cache

Returns:

Promise
resolve({DefaultView, Name, ID, Type, Url}), reject(error)

Example:

$SP().list("My List").views().then(function(view) {
  for (var i=0; i<view.length; i++) {
    console.log("View #"+i+": "+view[i].Name);
  }
});