diff --git a/changelog.md b/changelog.md
index af96607..bd34c16 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
# Changelog
+**Change Log v3.0.7 (December 14, 2013)**
+
+ - Fix a bug with $SP().formfields().elem() when it's a boolean-checkbox field (it returned the INPUT and the BR)
+ - Add 'paging' option in $SP().formfields().get() that permits to get data from a very large list (that is useful when there is a list view threshold)
+
**Change Log v3.0.6 (November 13, 2013)**
- Change the default value of "dateInUTC" to false for $SP().list().get()
diff --git a/sharepointplus-3.0.6.js b/old_versions/sharepointplus-3.0.6.js
similarity index 100%
rename from sharepointplus-3.0.6.js
rename to old_versions/sharepointplus-3.0.6.js
diff --git a/sharepointplus-3.0.6.min.js b/old_versions/sharepointplus-3.0.6.min.js
similarity index 100%
rename from sharepointplus-3.0.6.min.js
rename to old_versions/sharepointplus-3.0.6.min.js
diff --git a/sharepointplus-3.0.7.js b/sharepointplus-3.0.7.js
new file mode 100644
index 0000000..2a7fe56
--- /dev/null
+++ b/sharepointplus-3.0.7.js
@@ -0,0 +1,3941 @@
+/*!
+ * SharepointPlus v3.0.7
+ * Copyright 2013, Aymeric (@aymkdn)
+ * Contact: http://kodono.info
+ * Documentation: http://aymkdn.github.com/SharepointPlus/
+ * License: GPL v2 (http://aymkdn.github.com/SharepointPlus/license.txt)
+ */
+if (!Array.prototype.indexOf) {
+ /**
+ @ignore
+ @description in IE7- the Array.indexOf doesn't exist!
+ */
+ Array.prototype.indexOf = function (searchElement) {
+ "use strict";
+ if (this == null) {
+ throw new TypeError();
+ }
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 1) {
+ n = Number(arguments[1]);
+ if (n != n) { // shortcut for verifying if it's NaN
+ n = 0;
+ } else if (n != 0 && n != Infinity && n != -Infinity) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ }
+}
+
+if(!String.prototype.trim) {
+ /**
+ @ignore
+ @escription The trim() feature for String is not always available for all browsers
+ */
+ String.prototype.trim = function () {
+ return this.replace(/^\s+|\s+$/g,'');
+ };
+}
+
+// Global
+_SP_APPROVED=0;
+_SP_REJECTED=1;
+_SP_PENDING=2;
+_SP_DRAFT=3;
+_SP_SCHEDULED=4;
+_SP_CACHE_FORMFIELDS=null;
+
+(function(window) {
+ // define a faster way to apply a function to an array
+ var fastMap = function(source,fn) {
+ var iterations = source.length;
+ var dest = new Array(iterations);
+ var _n = iterations / 8;
+ var _caseTest = iterations % 8;
+ for (var i = iterations-1; i > -1; i--) {
+ var n = _n;
+ var caseTest = _caseTest;
+ do {
+ switch (caseTest) {
+ case 0: dest[i]=fn(source[i]); i--;
+ case 7: dest[i]=fn(source[i]); i--;
+ case 6: dest[i]=fn(source[i]); i--;
+ case 5: dest[i]=fn(source[i]); i--;
+ case 4: dest[i]=fn(source[i]); i--;
+ case 3: dest[i]=fn(source[i]); i--;
+ case 2: dest[i]=fn(source[i]); i--;
+ case 1: dest[i]=fn(source[i]); i--;
+ }
+ caseTest = 0;
+ } while (--n > 0);
+ }
+ return dest;
+ };
+
+ var decode_b64 = function(d,b,c,u,r,q,x){b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(r=q=x='';c=d.charAt(x++);~c&&(u=q%4?u*64+c:c,q++%4)?r+=String.fromCharCode(255&u>>(-2*q&6)):0)c=b.indexOf(c);return r};
+ var encode_b64 = function(a,b,c,d,e,f){b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";c="=";for(d=f='';e&=3,a.charAt(d++)||(b='=',e);f+=b.charAt(63&c>>++e*2))c=c<<8|a.charCodeAt(d-=!e);return f};
+
+ /**
+ @name $SP()
+ @class This is the object uses for all SharepointPlus related actions
+ */
+ function SharepointPlus() {
+ if (!(this instanceof arguments.callee)) return new arguments.callee();
+ }
+
+ SharepointPlus.prototype = {
+ data:[],
+ length:0,
+ listQueue:[],
+ needQueue:false,
+ /**
+ @name $SP().getVersion
+ @description Returns the SP version
+
+ @return The current version
+ */
+ getVersion:function() { return "3.0.4" },
+ /**
+ @name $SP().list
+ @namespace
+ @description Permits to define the list ID
+
+ @param {String} listID Ths list ID or the list name
+ @param {String} [url] If the list name is provided, then you need to make sure URL is provided too (then no need to define the URL again for the chained functions like 'get' or 'update')
+ @example
+ $SP().list("My List");
+ $SP().list("My List","http://my.sharpoi.nt/other.directory/");
+ */
+ list:function(list,url) {
+ this.reset();
+ if (url) {
+ // make sure we don't have a '/' at the end
+ if (url.substring(url.length-1,url.length)==='/') url=url.substring(0,url.length-1)
+ this.url=url;
+ }
+ else this._getURL();
+ // if list is not an ID but a name
+ /*if (list.charAt(0) != '{') {
+ this.listName=list;
+ if (url == undefined) throw "Error 'list': not able to find the URL!"; // we cannot determine the url
+ var found=false,_this=this;
+ this.lists({url:url}).each(function(idx,l) {
+ if (l["Name"]==list) {
+ _this.listID=l["ID"];
+ found=true;
+ return false;
+ }
+ });
+ if (!found) throw "Error 'list': not able to find the list called '"+list+"' at "+url;
+ return this;
+ }*/
+ this.listID = list.replace(/&/g,"&");
+ return this;
+ },
+ /**
+ @ignore
+ @name $SP()._getURL
+ @function
+ @description (internal use only) Store the current URL website into this.url
+ */
+ _getURL:function() {
+ if (this.url===undefined && typeof L_Menu_BaseUrl==="undefined" && jQuery('body').data('sp-currenturl')===undefined) {
+ // we'll use the Webs.asmx service to find the base URL
+ this.needQueue=true;
+ var _this=this;
+ var body=""
+ +""+window.location.href.replace(/&/g,"&")+"";
+ var url = window.location.protocol + "//" + window.location.host + "/_vti_bin/Webs.asmx";
+ jQuery.ajax({
+ type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ // we want to use myElem to change the getAttribute function
+ var result=data.getElementsByTagName('WebUrlFromPageUrlResult');
+ if (result.length) {
+ _this.url = result[0].firstChild.nodeValue.toLowerCase();
+ // save the result for future use in the page
+ jQuery('body').data('sp-currenturl',_this.url);
+ }
+ _this.needQueue=false;
+ }
+ });
+ } else this.url = this.url || jQuery('body').data('sp-currenturl') || (window.location.protocol +"//"+ window.location.host + L_Menu_BaseUrl);
+ return this;
+ },
+ /**
+ @ignore
+ @name $SP()._addInQueue
+ @function
+ @description (internal use only) Add a function in the queue
+ */
+ _addInQueue:function(args) {
+ this.listQueue.push(args);
+ if (this.listQueue.length===1) this._testQueue();
+ return this
+ },
+ /**
+ @ignore
+ @name $SP()._testQueue
+ @function
+ @description (internal use only) Permits to treat the queue
+ */
+ _testQueue:function() {
+ if (this.needQueue) {
+ var _this=this;
+ setTimeout(function() { _this._testQueue.call(_this) }, 25);
+ } else {
+ if (this.listQueue.length > 0) {
+ var todo = this.listQueue.shift();
+ todo.callee.apply(this, Array.prototype.slice.call(todo));
+ }
+ this.needQueue=(this.listQueue.length>0);
+ if (this.needQueue) {
+ var _this=this;
+ setTimeout(function() { _this._testQueue.call(_this) }, 25);
+ }
+ }
+ },
+ /**
+ @name $SP().parse
+ @function
+ @description Use a WHERE sentence to transform it into a CAML Syntax sentence
+
+ @param {String} where The WHERE sentence to change
+ @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><Gt><FieldRef Name="Description<" /></Gt></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>
+ */
+ parse:function(q) {
+ var queryString = q.replace(/(\s+)?(=|<=|>=|<>|<|>| LIKE | like )(\s+)?/g,"$2").replace(/""|''/g,"Null").replace(/==/g,"="); // remove unnecessary white space & replace '
+ var factory = [];
+ var limitMax = q.length;
+ var closeOperator="", closeTag = "", ignoreNextChar=false;
+ var lastField = "";
+ var parenthesis = {open:0};
+ for (var i=0; i < queryString.length; i++) {
+ var letter = queryString.charAt(i);
+ switch (letter) {
+ case "(": // find the deepest (
+ var start = i;
+ var openedApos=false;
+ while (queryString.charAt(i) == "(" && i < limitMax) { i++; parenthesis.open++; }
+ // find the corresponding )
+ while (parenthesis.open>0 && i < limitMax) {
+ i++;
+ // if there is a ' opened then ignore the ) until the next '
+ var charAtI = queryString.charAt(i);
+ if (charAtI=="\\") ignoreNextChar=true; // when we have a backslash \then ignore the next char
+ else if (!ignoreNextChar && charAtI=="'") openedApos=!openedApos;
+ else if (!ignoreNextChar && charAtI==")" && !openedApos) parenthesis.open--;
+ else ignoreNextChar=false;
+ }
+
+ var lastIndex = factory.length-1;
+
+ // concat with the first index
+ if (lastIndex>=0) {
+ if (closeOperator != "") factory[0] = "<"+closeOperator+">"+factory[0];
+ factory[0] += this.parse(queryString.substring(start+1, i));
+ if (closeOperator != "") factory[0] += ""+closeOperator+">";
+ //delete(factory[lastIndex]);
+ closeOperator = "";
+ } else factory[0] = this.parse(queryString.substring(start+1, i));
+ break;
+ case ">": // look at the operand
+ case "<": i++;
+ if (queryString.charAt(i) == "=") { // >= or <=
+ factory.push("<"+(letter==">"?"G":"L")+"eq>");
+ closeTag = ""+(letter==">"?"G":"L")+"eq>";
+ } else if (letter == "<" && queryString.charAt(i) == ">") { // <>
+ factory.push("");
+ closeTag = "";
+ } else {
+ i--;
+ factory.push("<"+(letter==">"?"G":"L")+"t>");
+ closeTag = ""+(letter==">"?"G":"L")+"t>";
+ }
+ break;
+ case "=": factory.push("");
+ closeTag = "";
+ break;
+ case " ": // check if it's AND or OR
+ if (queryString.substring(i,i+5).toUpperCase() == " AND ") {
+ // add the open tag in the array
+ closeOperator = "And";
+ i+=4;
+ }
+ else if (queryString.substring(i,i+4).toUpperCase() == " OR ") {
+ // add the open tag in the array
+ closeOperator = "Or";
+ i+=3;
+ }
+ else if (queryString.slice(i,i+6).toUpperCase() == " LIKE ") {
+ i+=5;
+ factory.push("");
+ closeTag = "";
+ }
+ else lastField += letter;
+ break;
+ case '"': // look now for the next "
+ case "'": var apos = letter;
+ var word = "";
+ while ((letter = queryString.charAt(++i)) != apos && i < limitMax) {
+ if (letter == "\\") letter = queryString.charAt(++i);
+ word+=letter;
+ }
+ lastIndex = factory.length-1;
+ factory[lastIndex] += '';
+ lastField = "";
+ var type = "Text"; //(isNaN(word) ? "Text" : "Number"); // check the type
+ if (/\d{4}-\d\d?-\d\d?((T| )\d{2}:\d{2}:\d{2})?/.test(word) || word == "[Today]") type="DateTime";
+ word = this._cleanString(word);
+ // two special words that are [Today] and [Me]
+ switch(word) {
+ case "[Today]": word = ''; break;
+ case "[Me]": word = ''; type = "Integer"; break;
+ }
+ factory[lastIndex] += ''+word+'';
+ factory[lastIndex] += closeTag;
+ closeTag = "";
+ // concat with the first index
+ if (lastIndex>0) {
+ if (closeOperator != "") factory[0] = "<"+closeOperator+">"+factory[0];
+ factory[0] += factory[lastIndex];
+ if (closeOperator != "") factory[0] += ""+closeOperator+">";
+ delete(factory[lastIndex]);
+ closeOperator = "";
+ }
+ break;
+ case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9":
+ if (closeTag != "") { // it's the value
+ var value = letter;
+ while (!isNaN(letter = queryString.charAt(++i)) && i < limitMax) value+=""+letter;
+ lastIndex = factory.length-1;
+ factory[lastIndex] += '';
+ lastField = "";
+ factory[lastIndex] += ''+value.replace(/ $/,"")+'';
+ factory[lastIndex] += closeTag;
+ closeTag = "";
+ // concat with the first index
+ if (lastIndex>0) {
+ if (closeOperator != "") factory[0] = "<"+closeOperator+">"+factory[0];
+ factory[0] += factory[lastIndex];
+ if (closeOperator != "") factory[0] += ""+closeOperator+">";
+ delete(factory[lastIndex]);
+ closeOperator = "";
+ }
+ i-=2;
+ break;
+ }
+ default: if (closeTag == "") lastField += letter;
+ else if (letter.toLowerCase() == "n" && queryString.substring(i,i+4).toLowerCase() == "null") { // if we have NULL as the value
+ lastIndex = factory.length-1;
+ if (closeTag == "") { // <>
+ factory[lastIndex] = "";
+ closeTag = "";
+ } else if (closeTag == "") { // =
+ factory[lastIndex] = "";
+ closeTag = "";
+ }
+ i+=3;
+ factory[lastIndex] += '';
+ lastField = "";
+ factory[lastIndex] += closeTag;
+ closeTag = "";
+ // concat with the first index
+ if (lastIndex>0) {
+ if (closeOperator != "") factory[0] = "<"+closeOperator+">"+factory[0];
+ factory[0] += factory[lastIndex];
+ if (closeOperator != "") factory[0] += ""+closeOperator+">";
+ delete(factory[lastIndex]);
+ closeOperator = "";
+ }
+ }
+ }
+ }
+ return factory.join("");
+ },
+ /**
+ @ignore
+ @name $SP()._parseOn
+ @function
+ @description (internal use only) Look at the ON clause to convert it
+
+ @param {String} on The ON clause
+ @return {Array}array of clauses
+ @example
+ $SP()._parseOn("'List1'.field1 = 'List2'.field2 AND 'List1'.Other_x0020_Field = 'List2'.Some_x0020_Field")
+ */
+ _parseOn:function(q) {
+ var factory = [];
+ var queryString = q.replace(/(\s+)?(=)(\s+)?/g,"$2").replace(/==/g,"=").split(" AND ");
+ for (var i=0; i and &)
+
+ @param {String} string The string to clean
+ @note That should be used as an internal function
+ */
+ _cleanString:function(str) {
+ return str.replace(/&(?!amp;|lt;|gt;)/g, "&").replace(//g, ">");
+ },
+ /**
+ @name $SP().cleanResult
+ @function
+ @description clean a string returned by a GET (remove ";#" and "string;#" and null becomes "")
+
+ @param {String} str The string to clean
+ @param {String} [separator=";"] When it's a list we may want to have a different output (see examples)
+ @return {String} the cleaned string
+
+ @example
+ $SP().cleanResult("15;#Paul"); // -> "Paul"
+ $SP().cleanResult("string;#Paul"); // -> "Paul"
+ $SP().cleanResult(";#Paul;#Jacques;#Aymeric;#"); // -> "Paul;Jacques;Aymeric"
+ $SP().cleanResult(";#Paul;#Jacques;#Aymeric;#", ", "); // -> "Paul, Jacques, Aymeric"
+ */
+ cleanResult:function(str,separator) {
+ if (str===null || typeof str==="undefined") return "";
+ separator = separator || ";";
+ return (typeof str==="string"?str.replace(/;#[0-9]+;#/g,separator).replace(/^[0-9]+;#/,"").replace(/^;#|;#$/g,"").replace(/;#/g,separator).replace(/string;#/,""):str);
+ },
+ /**
+ @name $SP().list.get
+ @function
+ @description Get the content of the list based on different criteria (by default the default view is used)
+
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.fields=""] 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)
+ @param {String|Array} [setup.where=""] 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)
+ @param {Function} [setup.progress] When using an array for the WHERE then you can call the progress function (see the example)
+ @param {Boolean} [setup.whereCAML=false] If you want to pass a WHERE clause that is with CAML Syntax only instead of SQL-like syntax
+ @param {String} [setup.orderby=""] The field used to sort the list result (you can also add "ASC" -default- or "DESC")
+ @param {String} [setup.groupby=""] The field used to group by the list result
+ @param {String} [setup.view=""] 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)
+ @param {Integer} [setup.rowlimit=0] You can define the number of rows you want to receive back (0 is infinite)
+ @param {Boolean} [setup.paging=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
+ @param {Boolean} [setup.expandUserField=false] When you get a user field, you can have more information (like name,email,sip,...) by switching this to TRUE
+ @param {Boolean} [setup.dateInUTC=true] TRUE to return dates in Coordinated Universal Time (UTC) format. FALSE to return dates in ISO format.
+ @param {Object} [setup.folderOptions] Permits to read the content of a Document Library (see below)
+ @param {String} [setup.folderOptions.path=""] Relative path of the folders we want to explore (by default it's the root of the document library)
+ @param {String} [setup.folderOptions.show="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
+ @param {Boolean} [setup.queryOptions=undefined] If you want to provide your own QueryOptions and overwrite the ones built for you -- it should be some XML code (see http://msdn.microsoft.com/en-us/library/lists.lists.getlistitems.aspx)
+ @param {Object} [setup.join] 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) (it doesn't use yet the JOIN options provided with Sharepoint 2010)
+ @param {String} [setup.join.list] Permits to establish the link between two lists (see the example below)
+ @param {String} [setup.join.url='current website'] The website url (if different than the current website)
+ @param {String} [setup.join.on] 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)
+ @param {Boolean} [setup.join.outer=false] If you want to do an outer join (you can also directly use "outerjoin" instead of "join")
+ @param {Function} [result=function(data,error)] A function with the data from the request as first argument, and the second argument is the error message in case something went wrong
+
+ @example
+ $SP().list("List Name").get(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"
+ }, function getData(data) {
+ for (var i=0; i<data.length; i++) console.log(data[i].getAttribute("Title"));
+ });
+
+ // handle the errors
+ $SP().list("List Name").get(function(data,error) {
+ if (error) { alert(error) }
+ for (var i=0; i<data.length; i++) console.log(data[i].getAttribute("Title"));
+ });
+
+ // the WHERE clause must be SQL-like, and think to use double slash \\ if you have a simple quote '
+ // the field names must be the internal names used by Sharepoint
+ $SP().list("My List").get({
+ fields:"Title",
+ where:"Fiscal_x0020_Week > 30 AND Fiscal_x0020_Week < 50 AND Name = 'O\\'Sullivan, James'"
+ }),function getData(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,
+ // or '[Today]' to filter by the current date
+ $SP().list("My List").get({
+ fields:"Title",
+ where:"Author = '[Me]'"
+ },function getData(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]'"
+ }, 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"
+ $SP().list("My List").get({fields:"ID,Title",rowlimit:5000,paging:true}, function(data) {
+ console.log(data.length); // -> 23587
+ })
+
+ // 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",
+ }, function getData(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"
+ }
+ }
+ },function getData(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"
+ }
+ }
+ },function getData(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"));
+ })
+
+ // 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) {
+ console.log("Progress: "+current+" / "+max);
+ }
+ },function getData(data) {
+ console.log(data.length); // -> 6,523
+ });
+
+ // 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())
+ 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"
+ }
+ });
+ */
+ get:function(setup, fct) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (this.listID == undefined) throw "Error 'get': you have to define the list ID/Name";
+ if (arguments.length === 1 && typeof setup === "function") return this.get({}, setup);
+
+ // default values
+ setup = setup || {};
+ if (this.url == undefined) throw "Error 'get': not able to find the URL!"; // we cannot determine the url
+ setup.fields = setup.fields || "";
+ setup.where = setup.where || "";
+ setup.orderby = setup.orderby || "";
+ setup.groupby = setup.groupby || "";
+ setup.rowlimit = setup.rowlimit || 0;
+ setup.paging = (setup.paging===true ? true : false);
+ if (setup.paging && setup.rowlimit === 0) setup.rowlimit = 5000; // if rowlimit is not defined, we set it to 5000 by default
+ setup.expandUserField = (setup.expandUserField===true?"True":"False");
+ setup.dateInUTC = (setup.dateInUTC===true?"True":"False");
+ setup.folderOptions = setup.folderOptions || null;
+ setup.view = setup.view || "";
+ // if (setup.whereCAML!==true) setup.whereCAML = (setup.view!="");
+ setup.results = setup.results || []; // internal use when there is a paging
+ setup.ListItemCollectionPositionNext = setup.ListItemCollectionPositionNext || ""; // internal use when there is paging
+
+ // if setup.where is an array, then it means we want to do several requests
+ // so we keep the first WHERE
+ if (typeof setup.where === "object") {
+ if (setup.originalWhere==undefined) setup.originalWhere = setup.where.slice(0);
+ setup.nextWhere = setup.where.slice(1);
+ setup.where = setup.where.shift();
+ } else {
+ setup.originalWhere = setup.where;
+ setup.nextWhere = [];
+ }
+ // we use the progress only when WHERE is an array
+ setup.progress = setup.progress || (function() {});
+
+ // if view is defined and is not a GUID, then we need to find the view ID
+ if (setup.view !== "") {
+ if (setup.view.charAt(0)!=="{") {
+ var _this=this;
+ // retrieve the View ID based on its name
+ // and find the view details
+ _this.view(setup.view,function(data,viewID) {
+ setup.view=viewID;
+ var where = (setup.whereCAML ? setup.where : _this.parse(setup.where));
+ where += data.whereCAML;
+ if (setup.where !== "" && data.whereCAML !== "") where = "" + where + "";
+ setup.where=where;
+ setup.fields += (setup.fields===""?"":",") + data.fields.join(",");
+ setup.orderby += (setup.orderby===""?"":",") + data.orderby;
+ setup.whereCAML=true;
+ setup.useOWS=true;
+ delete setup.view;
+ return _this.get.call(_this,setup,fct);
+ });
+ return this;
+ }
+
+ if (setup.whereCAML!==true) {
+ setup.where = this.parse(setup.where);
+ setup.whereCAML=true;
+ }
+ }
+
+ // if we have [Me]/[Today] in the WHERE, or we want to use the GROUPBY,
+ // then we want to use the Lists.asmx service
+ // also for Sharepoint 2010
+ // depreciate since v3.0
+ var useOWS = true;//( setup.groupby!="" || /\[Me\]|\[Today\]/.test(setup.where) || setup.forceOWS===true || typeof SP=="object");
+
+ // what about the fields ?
+ var fields="";
+ if (setup.fields == "" || setup.fields == [])
+ fields = "";
+ else {
+ if (typeof setup.fields == "string") setup.fields = setup.fields.replace(/^\s+/,"").replace(/\s+$/,"").replace(/( )?,( )?/g,",").split(",");
+ // depreciate since v3.0 // if (setup.fields.indexOf("Attachments") != -1) useOWS=true;
+ for (var i=0; i';
+ // depreciate since v3.0 fields += '';
+ }
+
+ // what about sorting ?
+ var orderby="";
+ if (setup.orderby != "") {
+ var fieldsDir = setup.orderby.split(",");
+ for (i=0; i 0) {
+ if (splt.length==2) direction = splt[1].toUpperCase();
+ orderby += ( useOWS ? '' : '' );
+ }
+ }
+ }
+ // LookupValue="True"
+
+ // what about groupby ?
+ var groupby="";
+ if (setup.groupby != "") {
+ var gFields = setup.groupby.split(",");
+ for (i=0; i';
+ }
+
+ // forge the parameters
+ var body = "";
+ var aReturn = [];
+
+ // if no queryOptions provided then we set the default ones
+ if (setup.queryOptions === undefined) {
+ setup._queryOptions = ""+setup.dateInUTC+""
+ + ""
+ + "True"
+ + (fields==="" ? "" : "False")
+ + ""+setup.expandUserField+"";
+ // check if we want something related to the folders
+ if (setup.folderOptions) {
+ var viewAttr;
+ switch (setup.folderOptions.show) {
+ case "FilesAndFolders_Recursive": viewAttr="RecursiveAll"; break
+ case "FilesOnly_InFolder": viewAttr="FilesOnly"; break
+ case "FilesAndFolders_InFolder": viewAttr=""; break
+ case "FilesOnly_Recursive":
+ default: viewAttr="Recursive"
+ }
+ setup._queryOptions += ""
+ if (setup.folderOptions.path) setup.queryOptions += ""+this.url + this.listID + '/' + setup.folderOptions.path+""
+ } else
+ setup._queryOptions += ""
+ } else setup._queryOptions = setup.queryOptions
+
+ var _this=this;
+ if (useOWS) {
+ body = ""
+ + ""
+ + ""
+ + ""
+ + ""+this.listID+""
+ + ""+setup.view+""
+ + ""
+ + ""
+ + ( setup.where!="" ? ""+ (setup.whereCAML?setup.where:this.parse(setup.where)) +"" : "" )
+ + ( groupby!="" ? ""+groupby+"" : "" )
+ + ( orderby!="" ? ""+orderby+"" : "" )
+ + ""
+ + ""
+ + ""
+ + ""
+ + fields
+ + ""
+ + ""
+ + ""+setup.rowlimit+""
+ + ""
+ + ""
+ + setup._queryOptions
+ + ""
+ + ""
+ + ""
+ + ""
+ + "";
+ // do the request
+ var url = this.url + "/_vti_bin/Lists.asmx";
+ jQuery.ajax({type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ // we want to use myElem to change the getAttribute function
+ var rows=data.getElementsByTagName('z:row');
+ if (rows.length==0) rows=data.getElementsByTagName('row'); // for Chrome 'bug'
+ aReturn = fastMap(rows, function(row) { return myElem(row); });
+ // we have data from a previous list, so let's merge all together the both of them
+ if (setup.joinData) {
+ var on = setup.joinData["noindex"];
+ var aResult = [];
+ var prevIndex="";
+ var listIndexFound={length:0};
+ if (!on.length) alert("$SP.get() -- Error 'get': you must define the ON clause with JOIN is used.");
+ // we have a linked list so do some stuff here to tie the two lists together
+ for (var i=0,stop=aReturn.length; i0)
+ for (var i=0,stop=aReturn.length; i0) { // if we need to so some more request
+ if (setup.results.length===0) setup.results=aReturn
+ setup.where = setup.nextWhere.slice(0);
+ _this.get(setup,fct)
+ } else if (typeof fct == "function") {
+ // rechange setup.where with the original one just in case it was an array to make sure we didn't override the original array
+ setup.where = setup.originalWhere;
+ fct.call(_this,(setup.results.length>0?setup.results:aReturn));
+ }
+ }
+ },
+ error:function(jqXHR, textStatus, errorThrown) {
+ var res = jqXHR.responseXML;
+ var err = res.getElementsByTagName("errorstring");
+ if (err && err[0]) fct.call(_this,[],"Error: "+err[0].firstChild.nodeValue)
+ else fct.call(_this,[],textStatus+": "+errorThrown);
+ }
+ });
+ } /*else {
+ body = ""
+ + ""
+ +" "
+ +" "
+ +" 1.0"
+ +" "
+ +" "
+ +" "
+ +" "
+ + ""
+ + ""
+ +" "
+ +" 0?setup.rowlimit:-1)+"\">"
+ +" "+fields+""
+ +" "+ (setup.whereCAML?setup.where:this.parse(setup.where)) +""
+ +" "+ ( groupby!="" ? ""+groupby+"" : "" )
+ +" "+ ( orderby!="" ? ""+orderby+"" : "" )
+ +" "
+ +" "
+ +" "
+ + ""
+ + "";
+ // do the request
+ var url = setup.url + "/_vti_bin/dspsts.asmx";
+ jQuery.ajax({type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/dsp/queryRequest'); },
+ dataType: "xml",
+ success:function(data) {
+ var aReturn=data.getElementsByTagName('Row');
+ if (setup.join) {
+ var on=[];
+ for (var i=0,stop=aReturn.length; i<tr><th>Column A</th><th>Column B</th></tr><tr><td>Hello</td><td>World!</td></tr></table>",
+ destination:"http://mysite/Shared Documents/myfile.xls",
+ url:"http://mysite/",
+ after:function() {
+ window.location.href="http://mysite/Shared Documents/myfile.xls";
+ }
+ });
+
+ // You can use https://github.com/Aymkdn/FileToDataURI if you want to be able to read a local file
+ // and then upload it to a document library, via Javascript/Flash
+ // We'll use "encoded:true" to say our content is alreadu a base64 string
+ $SP().createFile({
+ content:"*your stuff with FileToDataURI that returns a base64 string*",
+ encoded:true,
+ destination:"http://mysite/Shared Documents/myfile.xls",
+ url:"http://mysite/"
+ });
+
+ // NOTE: in some cases the file are automatically checked out, so you have to use $SP().checkin()
+ */
+ createFile:function(setup) {
+ // default values
+ setup = setup || {};
+ if (setup.content == undefined) throw "Error 'createFile': not able to find the file content.";
+ if (setup.destination == undefined) throw "Error 'createFile': not able to find the file destination path.";
+ setup.url = setup.url || this.url;
+ // if we didn't define the url in the parameters, then we need to find it
+ if (!setup.url) {
+ this._getURL();
+ return this._addInQueue(arguments);
+ }
+ if (setup.url == undefined) throw "Error 'createFile': not able to find the URL!"; // we cannot determine the url
+ setup.after = setup.after || (function(){});
+ setup.encoded = (setup.encoded==undefined?false:setup.encoded);
+
+ var _this=this;
+ var soapEnv = ""
+ +""
+ +""
+ +""
+ +"http://null"
+ +""+setup.destination+""
+ +""
+ +""+(setup.encoded?setup.content:encode_b64(setup.content))+""
+ +""
+ +""
+ +"";
+ jQuery.ajax({
+ url: setup.url + "/_vti_bin/copy.asmx",
+ type: "POST",
+ dataType: "xml",
+ data: soapEnv,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/CopyIntoItems'); },
+ contentType: "text/xml; charset=\"utf-8\"",
+ success:function(data) {
+ var a = data.getElementsByTagName('CopyResult');
+ if (a && a[0] && a[0].getAttribute("ErrorCode") != "Success") throw "Error 'createFile': "+a[0].getAttribute("ErrorCode")+" - "+a[0].getAttribute("ErrorMessage");
+ if (typeof setup.after == "function") setup.after.call(_this);
+ }
+ });
+
+ return this;
+ },
+ /**
+ @name $SP().createFolder
+ @function
+ @description Create a folter in a Document library
+
+ @param {Object} setup Options (see below)
+ @param {String} setup.path The relative path to the new folder
+ @param {String} setup.library The name of the Document Library
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [setup.after=function(){}] A callback function that will be triggered after the task
+
+ @example
+ // create a folder called "first" at the root of the Shared Documents library
+ // the result should be "http://mysite/Shared Documents/first/"
+ $SP().createFolder({
+ path:"first",
+ library:"Shared Documents",
+ url:"http://mysite/",
+ after:function() { alert("Folder created!"); }
+ });
+
+ // create a folder called "second" under "first"
+ // the result should be "http://mysite/Shared Documents/first/second/"
+ // if "first" doesn't exist then it will be created
+ $SP().createFolder({
+ path:"first/second",
+ library:"Shared Documents",
+ after:function() { alert("Folder created!"); }
+ });
+
+ // Note: To delete a folder you can use $SP().list().remove()
+ */
+ createFolder:function(setup) {
+ // default values
+ setup = setup || {};
+ if (setup.path == undefined) throw "Error 'createFolder': please provide the 'path'.";
+ if (setup.library == undefined) throw "Error 'createFolder': please provide the library name.";
+ setup.url = setup.url || this.url;
+ // if we didn't define the url in the parameters, then we need to find it
+ if (!setup.url) {
+ this._getURL();
+ return this._addInQueue(arguments);
+ }
+ if (setup.url == undefined) throw "Error 'createFolder': not able to find the URL!"; // we cannot determine the url
+ setup.after = setup.after || (function(){});
+
+ // split the path based on '/'
+ var path = setup.path.split('/'), toAdd=[], tmpPath="";
+ for (var i=0; i0?'/':'') + path[i];
+ toAdd.push({FSObjType:1, BaseName:tmpPath})
+ }
+ this.list(setup.library, setup.url).add(toAdd, {after:setup.after})
+ return this;
+ },
+ /**
+ @name $SP().checkin
+ @function
+ @description Checkin a file
+
+ @param {Object} [setup] Options (see below)
+ @param {String} setup.destination The full path to the file to check in
+ @param {String} [setup.comments=""] The comments related to the check in
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [setup.success=function(){}] A callback function that will be triggered when there is success
+ @param {Function} [setup.error=function(){}] A callback function that will be triggered if there is an error
+ @param {Function} [setup.after=function(){}] A callback function that will be triggered after the task
+
+ @example
+ $SP().checkin({
+ destination:"http://mysite/Shared Documents/myfile.txt",
+ comments:"Automatic check in with SharepointPlus",
+ after:function() { alert("Done"); }
+ });
+ */
+ checkin:function(setup) {
+ // default values
+ setup = setup || {};
+ if (setup.destination == undefined) throw "Error 'checkin': not able to find the file destination path.";
+ setup.url = setup.url || this.url;
+ // if we didn't define the url in the parameters, then we need to find it
+ if (!setup.url) {
+ this._getURL();
+ return this._addInQueue(arguments);
+ }
+ if (this.url == undefined) throw "Error 'checkin': not able to find the URL!"; // we cannot determine the url
+ setup.url = this.url;
+ setup.comments = setup.comments || "";
+ setup.success = setup.success || (function(){});
+ setup.error = setup.error || (function(){});
+ setup.after = setup.after || (function(){});
+
+ var _this=this;
+ var soapEnv = ''
+ + ''
+ + ''+setup.destination+''
+ + ''+setup.comments+''
+ + '1';
+
+ jQuery.ajax({
+ url: setup.url + "/_vti_bin/Lists.asmx",
+ type: "POST",
+ dataType: "xml",
+ data: soapEnv,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/CheckInFile'); },
+ contentType: "text/xml; charset=utf-8",
+ success:function(data) {
+ var res = data.getElementsByTagName('CheckInFileResult');
+ if (res && res[0] && res[0].firstChild.nodeValue != "true") setup.error.call(_this);
+ else setup.success.call(_this);
+
+ setup.after.call(_this);
+ }
+ });
+ },
+ /**
+ @name $SP().list.getAttachment
+ @function
+ @description Get the attachment(s) for some items
+
+ @param {String|Array} itemID The item IDs separated by a coma (ATTENTION: one request is done for each ID)
+ @param {Function} [result] A function with the data from the request as first argument
+
+ @example
+ $SP().list("My List","http://my.site.com/mydir/").getAttachment([1,15,24],function(data) {
+ for (var i=0; i<data.length; i++) console.log(data[i]);
+ });
+
+ $SP().list("My List").getAttachment("98", function(data) {
+ for (var i=0; i<data.length; i++) console.log(data[i]);
+ });
+ */
+ getAttachment:function(itemID, fct, passed) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (this.listID == undefined) throw "Error 'getAttachment': you have to define the list ID/Name";
+ if (arguments.length === 1 && typeof itemID === "function") throw "Error 'getAttachment': you have to define the item ID";
+ if (this.url == undefined) throw "Error 'getAttachment': not able to find the URL!"; // we cannot determine the url
+ if (typeof itemID !== "object") itemID = itemID.split(",");
+ passed = passed || [];
+
+ // forge the parameters
+ var body = ""
+ + ""
+ + " "
+ + " "
+ + " "+this.listID+""
+ + " "+itemID.shift()+""
+ + " "
+ + " "
+ + "";
+ // do the request
+ var _this=this;
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var aReturn = [];
+ jQuery.ajax({type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/GetAttachmentCollection'); },
+ dataType: "xml",
+ success:function(data) {
+ var a = data.getElementsByTagName('Attachment');
+ for (var i=0; i < a.length; i++) aReturn.push(a[i].firstChild.nodeValue);
+ if (aReturn.length===0) aReturn="";
+ else if (aReturn.length===1) aReturn=aReturn[0]
+ passed.push(aReturn);
+ // if we don't have any more attachment to search for
+ if (itemID.length===0) {
+ if (typeof fct === "function") fct.call(_this,passed);
+ } else {
+ // we have more attachments to find
+ _this.getAttachment(itemID,fct,passed)
+ }
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.info
+ @function
+ @description Get the information (StaticName, DisplayName, Description, Required ("TRUE", "FALSE", null), DefaultValue, Choices, etc...) - metadata - regarding the list for each column
+
+ @param {Function} [function()] A function with the data from the request as first argument
+
+ @example
+ $SP().list("List Name").info(function(fields) {
+ for (var i=0; i<fields.length; i++) console.log(fields[i]["DisplayName"]+ ": "+fields[i]["Description"]);
+ });
+
+ $SP().list("My list","http://intranet.site.com/dept/").info(function(fields) {
+ for (var i=0; i<fields.length; i++) console.log(fields[i]["DisplayName"]+ ": "+fields[i]["Description"]);
+ });
+ */
+ info:function(fct) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (this.listID == undefined) throw "Error 'info': you have to define the list ID";
+
+ // default values
+ if (this.url == undefined) throw "Error 'info': not able to find the URL!"; // we cannot determine the url
+
+ // forge the parameters
+ var body = '';
+ body += '';
+ body += ' ';
+ body += ' ';
+ body += ' '+this.listID+'';
+ body += ' ';
+ body += ' ';
+ body += '';
+
+ // do the request
+ var _this=this;
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var aReturn = [];
+ jQuery.ajax({type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/GetList'); },
+ dataType: "xml",
+ success:function(data) {
+ var arr = data.getElementsByTagName('Field');
+ var index = 0, aIndex, attributes, attrName, lenDefault;
+ for (var i=0; i < arr.length; i++) {
+ if (arr[i].getAttribute("ID")) {
+ aReturn[index] = [];
+ aIndex=aReturn[index];
+ attributes=arr[i].attributes;
+ for (var j=attributes.length; j--;) {
+ attrName=attributes[j].nodeName;
+ attrValue=attributes[j].nodeValue;
+ if (attrName==="Type") {
+ switch (attrValue) {
+ case "Choice":
+ case "MultiChoice": {
+ aIndex["FillInChoice"] = arr[i].getAttribute("FillInChoice");
+ var a=arr[i].getElementsByTagName("CHOICE");
+ var r=[];
+ for(var k=0; k0) {
+ nodeDefault=arr[i].getElementsByTagName("Default");
+ aReturn[index]["DefaultValue"]=[];
+ for (var q=0; q';
+ body += ' ';
+ body += ' ';
+ body += ' '+this.listID+'';
+ body += ' '+viewID+'';
+ body += ' ';
+ body += ' ';
+ body += '';
+
+ // do the request
+ var url = this.url + "/_vti_bin/Views.asmx";
+ var aReturn = ["fields","orderby","whereCAML"];
+ var _this=this;
+ jQuery.ajax({type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/GetView'); },
+ dataType: "xml",
+ success:function(data) {
+ aReturn.fields=[]
+ var arr = data.getElementsByTagName('ViewFields')[0].getElementsByTagName('FieldRef');
+ for (var i=0; i < arr.length; i++) aReturn.fields.push(arr[i].getAttribute("Name"));
+
+ aReturn.orderby="";
+ arr = data.getElementsByTagName('OrderBy');
+ if (arr.length) {
+ var orderby=[];
+ arr = arr[0].getElementsByTagName('FieldRef');
+ for (var i=0; i]+>(.*)<\/Where>/);
+ if(where.length==2) aReturn.whereCAML=where[1];
+ }
+
+ // cache the data
+ savedView.push({url:_this.url,data:aReturn,viewID:viewID,viewName:viewName});
+ jQuery('body').data('sp-view',savedView);
+
+ if (typeof fct == "function") fct.call(_this,aReturn,viewID);
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.views
+ @function
+ @description Get the views info (ID, Name, Url) for a List
+
+ @param {Function} [function()] A function with the data from the request as first argument
+
+ @example
+ $SP().list("My List").views(function(view) {
+ for (var i=0; i<view.length; i++) console.log("View #"+i+": "+view[i]['Name']");
+ });
+ */
+ views:function(fct) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (this.listID == undefined) throw "Error 'views': you have to define the list ID";
+
+ // default values
+ if (this.url == undefined) throw "Error 'views': not able to find the URL!"; // we cannot determine the url
+ fct = fct || function(){};
+
+ // check if we didn't save this information before
+ var savedViews = jQuery('body').data('sp-views');
+ if (savedViews!=undefined) {
+ for (var i=savedViews.length; i--;) {
+ if (savedViews[i].url==this.url) { fct.call(this,savedViews[i].data); return this }
+ }
+ } else savedViews=[];
+
+ // forge the parameters
+ var body = '';
+ body += '';
+ body += ' ';
+ body += ' ';
+ body += ' '+this.listID+'';
+ body += ' ';
+ body += ' ';
+ body += '';
+
+ // do the request
+ var url = this.url + "/_vti_bin/Views.asmx";
+ var aReturn = [];
+ var _this=this;
+ jQuery.ajax({type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ contentType: "text/xml; charset=utf-8",
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/GetViewCollection'); },
+ dataType: "xml",
+ success:function(data) {
+ var arr = data.getElementsByTagName('View');
+ for (var i=0; i < arr.length; i++) {
+ aReturn[i] = [];
+ aReturn[i]["ID"] = arr[i].getAttribute("Name");
+ aReturn[i]["Name"] = arr[i].getAttribute("DisplayName");
+ aReturn[i]["Url"] = arr[i].getAttribute("Url");
+ }
+
+ // save the data into the DOM for later usage
+ savedViews.push({url:_this.url,data:aReturn});
+ jQuery('body').data('sp-views',savedViews);
+ fct.call(_this,aReturn);
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().lists
+ @function
+ @description Get the lists from the site (for each list we'll have "ID", "Name", "Description", "Url")
+
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [function()] A function with the data from the request as first argument
+
+ @example
+ $SP().lists(function(list) {
+ for (var i=0; i<list.length; i++) console.log("List #"+i+": "+list[i]['Name']");
+ });
+ */
+ lists:function(setup, fct) {
+ if (arguments.length===1 && typeof setup === "function") return this.lists({}, setup);
+
+ // default values
+ setup = setup || {};
+ setup.url = setup.url || this.url;
+ // if we didn't define the url in the parameters, then we need to find it
+ if (!setup.url) {
+ this._getURL();
+ return this._addInQueue(arguments);
+ } else this.url=setup.url
+ if (this.url == undefined) throw "Error 'lists': not able to find the URL!"; // we cannot determine the url
+
+ // forge the parameters
+ var body = '';
+ body += '';
+ body += ' ';
+ body += ' ';
+ body += ' ';
+ body += ' ';
+ body += '';
+
+ // check if we didn't save this information before
+ var savedLists = jQuery('body').data('sp-lists');
+ if (savedLists!=undefined) {
+ for (var i=savedLists.length; i--;) {
+ if (savedLists[i].url==this.url) {
+ if (typeof fct == "function") fct(savedLists[i].data);
+ else {
+ this.data = savedLists[i].data;
+ this.length = this.data.length;
+ }
+ return this;
+ }
+ }
+ } else savedLists=[];
+
+ // do the request
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var aReturn = [];
+ var _this=this;
+ jQuery.ajax({type:"POST",
+ cache:false,
+ async:true,
+ url:url,
+ data:body,
+ contentType:"text/xml; charset=utf-8",
+ beforeSend:function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/GetListCollection'); },
+ dataType:"xml",
+ success:function(data) {
+ var arr = data.getElementsByTagName('List');
+ for (var i=0; i < arr.length; i++) {
+ aReturn[i] = [];
+ aReturn[i]["ID"] = arr[i].getAttribute("ID");
+ aReturn[i]["Name"] = arr[i].getAttribute("Title");
+ aReturn[i]["Url"] = arr[i].getAttribute("DefaultViewUrl");
+ aReturn[i]["Description"] = arr[i].getAttribute("Description");
+ }
+
+ // save the data into the DOM for later usage
+ savedLists.push({url:_this.url,data:aReturn});
+ jQuery('body').data('sp-lists',savedLists);
+ if (typeof fct == "function") fct.call(_this,aReturn);
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.add
+ @function
+ @description Add items into a Sharepoint List
+ note: A Date must be provided as "YYYY-MM-DD hh:mm:ss", 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: A lookup value must be provided as "X;#value", with X the ID of the value from the lookup list.
+ 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 Yes/No checkbox must be provided as "1" (for TRUE) or "0" (for "False")
+ note: You cannot change the Approval Status when adding, you need to use the $SP().moderate function
+
+ @param {Object|Array} items List of items (e.g. [{Field_x0020_Name: "Value", OtherField: "new value"}, {Field_x0020_Name: "Value2", OtherField: "new value2"}])
+ @param {Object} [setup] Options (see below)
+ @param {Function} [setup.progress] (current,max) If you provide more than 15 items then they will be treated by packets and you can use "progress" to know more about the steps
+ @param {Function} [setup.success] A function with the items added sucessfully
+ @param {Function} [setup.error] A function with the items not added
+ @param {Function} [setup.after] A function that will be executed at the end of the request
+ @param {Boolean} [setup.escapeChar=true] Determines if we want to escape the special chars that will cause an error (for example '&' will be automatically converted to '&')
+
+ @example
+ $SP().list("My List").add({Title:"Ok"});
+
+ $SP().list("List Name").add([{Title:"Ok"}, {Title:"Good"}], {after:function() { alert("Done!"); });
+
+ $SP().list("My List","http://my.sharepoi.nt/dir/").add({Title:"Ok"}, {error:function(items) {
+ for (var i=0; i < items.length; i++) console.log("Error '"+items[i].errorMessage+"' with:"+items[i].Title); // the 'errorMessage' attribute is added to the object
+ }, success:function(items) {
+ for (var i=0; i < items.length; i++) console.log("Success for:"+items[i].Title+" (ID:"+items[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
+ */
+ add:function(items, setup) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (arguments.length===0 || (arguments.length===1 && typeof items !== "object"))
+ throw "Error 'add': you need to define the list of items";
+ if (this.listID===undefined) throw "Error 'add': you need to use list() to define the list name.";
+
+ // default values
+ setup = setup || {};
+ if (this.url == undefined) throw "Error 'add': not able to find the URL!"; // we cannot determine the url
+ setup.success = setup.success || (function() {});
+ setup.error = setup.error || (function() {});
+ setup.after = setup.after || (function() {});
+ setup.escapeChar = (setup.escapeChar == undefined) ? true : setup.escapeChar;
+ setup.progress= setup.progress || (function() {});
+
+ if (typeof items === "object" && items.length==undefined) items = [ items ];
+ var itemsLength=items.length;
+
+ // define current and max for the progress
+ setup.progressVar = setup.progressVar || {current:0,max:itemsLength,passed:[],failed:[],eventID:"spAdd"+(""+Math.random()).slice(2)};
+ // we cannot add more than 15 items in the same time, so split by 15 elements
+ // and also to avoid surcharging the server
+ if (itemsLength > 15) {
+ var nextPacket=items.slice(0);
+ var cutted=nextPacket.splice(0,15);
+ var _this=this;
+ jQuery(document).on(setup.progressVar.eventID,function(event) {
+ jQuery(document).off(setup.progressVar.eventID);
+ _this.add(nextPacket,event.setup);
+ });
+ this.add(cutted,setup);
+ return this;
+ } else if (itemsLength == 0) {
+ setup.progress(1,1);
+ setup.error([]);
+ setup.success([]);
+ setup.after();
+ return this;
+ }
+
+ // increment the progress
+ setup.progressVar.current += itemsLength;
+
+ // build a part of the request
+ var updates = '';
+ var _this = this;
+ for (var i=0; i < items.length; i++) {
+ updates += '';
+ updates += 'New';
+ jQuery.each(items[i], function(key, value) {
+ if (typeof value === "object" && value.items!=undefined) value = ";#" + value.join(";#") + ";#"; // an array should be seperate by ";#"
+ if (setup.escapeChar && typeof value === "string") value = _this._cleanString(value); // replace & (and not &) by "&" to avoid some issues
+ updates += ""+value+"";
+ });
+ updates += '';
+ }
+ updates += '';
+
+ // build the request
+ var body = ""
+ + ""
+ + ""
+ + ""
+ + ""+this.listID+""
+ + ""
+ + updates
+ + ""
+ + ""
+ + ""
+ + "";
+
+ // send the request
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var _this=this;
+ jQuery.ajax({type:"POST",
+ cache:false,
+ async:true,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/UpdateListItems'); },
+ contentType:"text/xml; charset=utf-8",
+ dataType:"xml",
+ success:function(data) {
+ var result = data.getElementsByTagName('Result');
+ var len=result.length;
+ var passed = setup.progressVar.passed, failed = setup.progressVar.failed;
+ for (var i=0; i < len; i++) {
+ if (result[i].getElementsByTagName('ErrorCode')[0].firstChild.nodeValue == "0x00000000") { // success
+ var rows=result[i].getElementsByTagName('z:row');
+ if (rows.length==0) rows=result[i].getElementsByTagName('row'); // for Chrome 'bug'
+ items[i].ID = rows[0].getAttribute("ows_ID");
+ passed.push(items[i]);
+ } else {
+ items[i].errorMessage = result[i].getElementsByTagName('ErrorText')[0].firstChild.nodeValue;
+ failed.push(items[i]);
+ }
+ }
+
+ setup.progress(setup.progressVar.current,setup.progressVar.max);
+ // check if we have some other packets that are waiting to be treated
+ if (setup.progressVar.current < setup.progressVar.max)
+ jQuery(document).trigger({type:setup.progressVar.eventID,setup:setup});
+ else {
+ if (failed.length>0) setup.error.call(_this,failed);
+ if (passed.length>0) setup.success.call(_this,passed);
+ setup.after.call(_this);
+ }
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.update
+ @function
+ @description Update items from a Sharepoint List
+
+ @param {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"}])
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.where=""] You can define a WHERE clause
+ @param {Function} [setup.progress] Two parameters: 'current' and 'max' -- if you provide more than 15 ID then they will be treated by packets and you can use "progress" to know more about the steps
+ @param {Function} [setup.success] One parameter: 'passedItems' -- a function with the items updated sucessfully
+ @param {Function} [setup.error] One parameter: 'failedItems' -- a function with the items not updated
+ @param {Function} [setup.after] A function that will be executed at the end of the request
+ @param {Boolean} [setup.escapeChar=true] Determines if we want to escape the special chars that will cause an error (for example '&' will be automatically converted to '&')
+
+ @example
+ $SP().list("My List").update({ID:1, Title:"Ok"}); // you must always provide the ID
+ $SP().list("List Name").update({Title:"Ok"},{where:"Status = 'Complete'"}); // if you use the WHERE then you must not provide the item ID
+
+ $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"}, {error:function(items) {
+ for (var i=0; i < items.length; i++) console.log("Error '"+items[i].errorMessage+"' with:"+items[i].Title));
+ }});
+ */
+ update:function(items, setup) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (this.listID===undefined) throw "Error 'update': you need to use list() to define the list name.";
+
+ // default values
+ setup = setup || {};
+ if (this.url == undefined) throw "Error 'update': not able to find the URL!"; // we cannot determine the url
+ setup.where = setup.where || "";
+ setup.success = setup.success || (function() {});
+ setup.error = setup.error || (function() {});
+ setup.after = setup.after || (function() {});
+ setup.escapeChar = (setup.escapeChar == undefined) ? true : setup.escapeChar;
+ setup.progress= setup.progress || (function() {});
+
+ if (typeof items === "object" && items.length==undefined) items = [ items ];
+ var itemsLength=items.length;
+
+ // if there is a WHERE clause
+ if (itemsLength == 1 && setup.where) {
+ // call GET first
+ delete items[0].ID;
+ var _this=this;
+ this.get({fields:"ID",where:setup.where},function(data) {
+ // we need a function to clone the items
+ var clone = function(obj){
+ var newObj = {};
+ for (var k in obj) newObj[k]=obj[k];
+ return newObj;
+ };
+ var aItems=[];
+ for (var i=data.length;i--;) {
+ var it=clone(items[0]);
+ it.ID=data[i].getAttribute("ID");
+ aItems.push(it);
+ }
+ delete setup.where;
+ // now call again the UPDATE
+ _this.update(aItems,setup);
+ });
+ return this;
+ }
+
+ // define current and max for the progress
+ setup.progressVar = setup.progressVar || {current:0,max:itemsLength,passed:[],failed:[],eventID:"spUpdate"+(""+Math.random()).slice(2)};
+ // we cannot add more than 15 items in the same time, so split by 15 elements
+ // and also to avoid surcharging the server
+ if (itemsLength > 15) {
+ var nextPacket=items.slice(0);
+ var cutted=nextPacket.splice(0,15);
+ var _this=this;
+ jQuery(document).on(setup.progressVar.eventID,function(event) {
+ jQuery(document).off(setup.progressVar.eventID);
+ _this.update(nextPacket,event.setup);
+ });
+ this.update(cutted,setup);
+ return this;
+ } else if (itemsLength == 0) {
+ setup.progress(1,1);
+ setup.error([]);
+ setup.success([]);
+ setup.after();
+ return this;
+ }
+
+ // increment the progress
+ setup.progressVar.current += itemsLength;
+
+ // build a part of the request
+ var updates = '';
+ var _this = this;
+ for (var i=0; i < itemsLength; i++) {
+ updates += '';
+ if (items[i].ID == undefined) throw "Error 'update': you have to provide the item ID called 'ID'";
+ jQuery.each(items[i], function(key, value) {
+ if (typeof value === "object" && value.length!=undefined) value = ";#" + value.join(";#") + ";#"; // an array should be seperate by ";#"
+ if (setup.escapeChar && typeof value === "string") value = _this._cleanString(value); // replace & (and not &) by "&" to avoid some issues
+ updates += ""+value+"";
+ });
+ updates += '';
+ }
+ updates += '';
+
+ // build the request
+ var body = ""
+ + ""
+ + ""
+ + ""
+ + ""+this.listID+""
+ + ""
+ + updates
+ + ""
+ + ""
+ + ""
+ + "";
+
+ // send the request
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var _this=this;
+ jQuery.ajax({type:"POST",
+ cache:false,
+ async:true,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/UpdateListItems'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var result = data.getElementsByTagName('Result');
+ var len=result.length;
+ var passed = setup.progressVar.passed, failed = setup.progressVar.failed;
+ for (var i=0; i < len; i++) {
+ if (result[i].getElementsByTagName('ErrorCode')[0].firstChild.nodeValue == "0x00000000") // success
+ passed.push(items[i]);
+ else {
+ items[i].errorMessage = result[i].getElementsByTagName('ErrorText')[0].firstChild.nodeValue;
+ failed.push(items[i]);
+ }
+ }
+
+ setup.progress(setup.progressVar.current,setup.progressVar.max);
+ // check if we have some other packets that are waiting to be treated
+ if (setup.progressVar.current < setup.progressVar.max)
+ jQuery(document).trigger({type:setup.progressVar.eventID,setup:setup});
+ else {
+ if (failed.length>0) setup.error.call(_this,failed);
+ if (passed.length>0) setup.success.call(_this,passed);
+ setup.after.call(_this);
+ }
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.history
+ @function
+ @description When a textarea/multiple lines of text has the versioning option, then you can use this function to find the previous values
+
+ @param {Object} params See below
+ @param {String|Number} params.ID The item ID
+ @param {String} params.Name The field name
+ @param {Function} returnFct This function will have one parameter that is the data returned
+
+ @example
+ $SP().list("My List").history({ID:1981, Name:"Critical_x0020_Comments"}, function(data) {
+ for (var i=0,len=data.length; i"
+ + ""
+ + ""+this.listID+""
+ + ""+params.ID+""
+ + ""+params.Name+""
+ + "";
+
+ // send the request
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var _this=this;
+ jQuery.ajax({type:"POST",
+ cache:false,
+ async:true,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/GetVersionCollection'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ returnFct.call(_this, data.getElementsByTagName('Version'))
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.moderate
+ @function
+ @description Moderate items from a Sharepoint List
+
+ @param {Array} approval List of items and ApprovalStatus (e.g. [{ID:1, ApprovalStatus:"Approved"}, {ID:22, ApprovalStatus:"Pending"}])
+ @param {Object} [setup] Options (see below)
+ @param {Function} [setup.success] A function with the items updated sucessfully
+ @param {Function} [setup.error] A function with the items not updated
+ @param {Function} [setup.after] A function that will be executed at the end of the request
+ @param {Function} [setup.progress] Two parameters: 'current' and 'max' -- if you provide more than 15 ID then they will be treated by packets and you can use "progress" to know more about the steps
+
+ @example
+ $SP().list("My List").moderate({ID:1, ApprovalStatus:"Rejected"}); // you must always provide the ID
+
+ $SP().list("List Name").moderate([{ID:5, ApprovalStatus:"Pending"}, {ID: 15, ApprovalStatus:"Approved"}]);
+
+ $SP().list("Other List").moderate({ID:43, ApprovalStatus:"Approved"}, {
+ error:function(items) {
+ for (var i=0; i < items.length; i++) console.log("Error with:"+items[i].ID);
+ },
+ success:function(items) {
+ for (var i=0; i < items.length; i++) console.log("Success with:"+items[i].getAttribute("Title"));
+ }
+ });
+ */
+ moderate:function(items, setup) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (arguments.length===0 || (arguments.length===1 && typeof items === "object" && items.length === undefined))
+ throw "Error 'moderate': you need to define the list of items";
+ if (this.listID===undefined) throw "Error 'moderate': you need to use list() to define the list name.";
+
+ // default values
+ setup = setup || {};
+ if (this.url == undefined) throw "Error 'moderate': not able to find the URL!"; // we cannot determine the url
+ setup.async = (setup.async == undefined) ? true : setup.async;
+ setup.success = setup.success || (function() {});
+ setup.error = setup.error || (function() {});
+ setup.after = setup.after || (function() {});
+ setup.progress= setup.progress || (function() {});
+
+ if (typeof items === "object" && items.length==undefined) items = [ items ];
+ var itemsLength=items.length;
+
+ // define current and max for the progress
+ setup.progressVar = setup.progressVar || {current:0,max:itemsLength,passed:[],failed:[],eventID:"spModerate"+(""+Math.random()).slice(2)};
+
+ // we cannot add more than 15 items in the same time, so split by 15 elements
+ // and also to avoid surcharging the server
+ if (itemsLength > 15) {
+ var nextPacket=items.slice(0);
+ var cutted=nextPacket.splice(0,15);
+ var _this=this;
+ jQuery(document).on(setup.progressVar.eventID,function(event) {
+ jQuery(document).off(setup.progressVar.eventID);
+ _this.moderate(nextPacket,event.setup);
+ });
+ this.moderate(cutted,setup);
+ return this;
+ } else if (itemsLength == 0) {
+ setup.progress(1,1);
+ setup.success([]);
+ setup.error([]);
+ setup.after();
+ return this;
+ }
+
+ // increment the progress
+ setup.progressVar.current += itemsLength;
+
+ // build a part of the request
+ var updates = '';
+ var thisObject = this;
+ for (var i=0; i < itemsLength; i++) {
+ updates += '';
+ if (items[i].ID == undefined) throw "Error 'moderate': you have to provide the item ID called 'ID'";
+ else if (items[i].ApprovalStatus == undefined) throw "Error 'moderate': you have to provide the approval status 'ApprovalStatus' (Approved, Rejected, Pending, Draft or Scheduled)";
+ jQuery.each(items[i], function(key, value) {
+ if (key == "ApprovalStatus") {
+ key = "_ModerationStatus";
+ switch (value.toLowerCase()) {
+ case "approve":
+ case "approved": value=0; break;
+ case "reject":
+ case "deny":
+ case "denied":
+ case "rejected": value=1; break;
+ case "pending": value=2; break;
+ case "draft": value=3; break;
+ case "scheduled": value=4; break;
+ default: value=2; break;
+ }
+ }
+ updates += ""+value+"";
+ });
+ updates += '';
+ }
+ updates += '';
+
+ // build the request
+ var body = ""
+ + ""
+ + ""
+ + ""
+ + ""+this.listID+""
+ + ""
+ + updates
+ + ""
+ + ""
+ + ""
+ + "";
+
+ // send the request
+ var url = this.url + "/_vti_bin/lists.asmx";
+ var _this=this;
+ jQuery.ajax({type:"POST",
+ cache:false,
+ async:true,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/UpdateListItems'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var result = data.getElementsByTagName('Result');
+ var len=result.length;
+ var passed = setup.progressVar.passed, failed = setup.progressVar.failed;
+ var rows;
+ for (var i=0; i < len; i++) {
+ rows=result[i].getElementsByTagName('z:row');
+ if (rows.length==0) rows=data.getElementsByTagName('row'); // for Chrome
+ var item = myElem(rows[0]);
+ if (result[i].getElementsByTagName('ErrorCode')[0].firstChild.nodeValue == "0x00000000") // success
+ passed.push(item);
+ else {
+ items[i].errorMessage = result[i].getElementsByTagName('ErrorText')[0].firstChild.nodeValue;
+ failed.push(items[i]);
+ }
+ }
+
+ setup.progress(setup.progressVar.current,setup.progressVar.max);
+ // check if we have some other packets that are waiting to be treated
+ if (setup.progressVar.current < setup.progressVar.max)
+ jQuery(document).trigger({type:setup.progressVar.eventID,setup:setup});
+ else {
+ if (passed.length>0) setup.success.call(_this,passed);
+ if (failed.length>0) setup.error.call(_this,failed);
+ setup.after.call(_this);
+ }
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().list.remove
+ @function
+ @description Delete items from a Sharepoint List
+ @note You can also use the key word 'del' instead of 'remove'
+
+ @param {Objet|Array} itemsID 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"}
+ @param {Object} [setup] Options (see below)
+ @param {Function} [setup.progress] Two parameters: 'current' and 'max' -- If you provide more than 15 ID then they will be treated by packets and you can use "progress" to know more about the steps
+ @param {Function} [setup.success] One parameter: 'passedItems' -- a function with the items updated sucessfully
+ @param {Function} [setup.error] (One parameter: 'failedItems' -- a function with the items not updated
+ @param {Function} [setup.after] A function that will be executed at the end of the request
+
+ @example
+ $SP().list("My List").remove({ID:1}); // you must always provide the ID
+
+ // 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}]);
+
+ // example about how to use the "error" callback
+ $SP().list("List").remove({ID:43, Title:"My title"}, {error:function(items) {
+ for (var i=0; i < items.length; i++) console.log("Error with:"+items[i].ID+" ("+items[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"});
+ */
+ remove:function(items, setup) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+
+ // default values
+ if (!setup && items.where) { setup=items; items=[]; } // the case when we use the "where"
+ setup = setup || {};
+ if (this.url == undefined) throw "Error 'remove': not able to find the URL!"; // we cannot determine the url
+ setup.error = setup.error || (function() {});
+ setup.success = setup.success || (function() {});
+ setup.after = setup.after || (function() {});
+ setup.progress= setup.progress || (function() {});
+
+ if (typeof items === "object" && items.length==undefined) items = [ items ];
+ var itemsLength=items.length;
+
+ // if there is a WHERE clause
+ if (setup.where) {
+ // call GET first
+ if (itemsLength==1) delete items[0].ID;
+ var _this=this;
+ this.get({fields:"ID,FileRef",where:setup.where},function(data) {
+ // we need a function to clone the items
+ var clone = function(obj){
+ var newObj = {};
+ for (var k in obj) newObj[k]=obj[k];
+ return newObj;
+ };
+ var aItems=[],fileRef;
+ for (var i=data.length;i--;) {
+ var it=clone(items[0]);
+ it.ID=data[i].getAttribute("ID");
+ fileRef=data[i].getAttribute("FileRef");
+ if (fileRef) it.FileRef=$SP().cleanResult(fileRef);
+ aItems.push(it);
+ }
+ // now call again the REMOVE
+ delete setup.where;
+ _this.remove(aItems,setup);
+ });
+ return this;
+ } else if (itemsLength == 0) {
+ // nothing to delete
+ setup.progress(1,1);
+ setup.error.call(_this,[]);
+ setup.success.call(_this,[]);
+ setup.after.call(_this)
+ return _this;
+ }
+
+ // define current and max for the progress
+ setup.progressVar = setup.progressVar || {current:0,max:itemsLength,passed:[],failed:[],eventID:"spRemove"+(""+Math.random()).slice(2)};
+ // we cannot add more than 15 items in the same time, so split by 15 elements
+ // and also to avoid surcharging the server
+ if (itemsLength > 15) {
+ var nextPacket=items.slice(0);
+ var cutted=nextPacket.splice(0,15);
+ var _this=this;
+ jQuery(document).on(setup.progressVar.eventID,function(event) {
+ jQuery(document).off(setup.progressVar.eventID);
+ _this.remove(nextPacket,event.setup);
+ });
+ this.remove(cutted,setup);
+ return this;
+ }
+ // increment the progress
+ setup.progressVar.current += itemsLength;
+
+ // build a part of the request
+ var updates = '';
+ for (var i=0; i < items.length; i++) {
+ updates += '';
+ if (items[i].ID == undefined) throw "Error 'delete': you have to provide the item ID called 'ID'";
+ updates += ""+items[i].ID+"";
+ if (items[i].FileRef != undefined) updates += ""+items[i].FileRef+"";
+ updates += '';
+ }
+ updates += '';
+
+ // build the request
+ var body = ""
+ + ""
+ + ""
+ + ""
+ + ""+this.listID+""
+ + ""
+ + updates
+ + ""
+ + ""
+ + ""
+ + "";
+
+ // send the request
+ var _this=this;
+ var url = this.url + "/_vti_bin/lists.asmx";
+ jQuery.ajax({type:"POST",
+ cache:false,
+ async:true,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/UpdateListItems'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var result = data.getElementsByTagName('Result');
+ var len=result.length;
+ var passed = setup.progressVar.passed, failed = setup.progressVar.failed;
+ for (var i=0; i < len; i++) {
+ if (result[i].getElementsByTagName('ErrorCode')[0].firstChild.nodeValue == "0x00000000") // success
+ passed.push(items[i]);
+ else {
+ items[i].errorMessage = result[i].getElementsByTagName('ErrorText')[0].firstChild.nodeValue;
+ failed.push(items[i]);
+ }
+ }
+
+ setup.progress(setup.progressVar.current,setup.progressVar.max);
+ // check if we have some other packets that are waiting to be treated
+ if (setup.progressVar.current < setup.progressVar.max)
+ jQuery(document).trigger({type:setup.progressVar.eventID,setup:setup});
+ else {
+ if (failed.length>0) setup.error.call(_this,failed);
+ if (passed.length>0) setup.success.call(_this,passed);
+ setup.after.call(_this);
+ }
+ }
+ });
+ return this;
+ },
+ del:function(items, setup) { return this.remove(items,setup) },
+ /**
+ @name $SP().usergroups
+ @function
+ @description Find the Sharepoint groups where the specified user is member of
+
+ @param {String} username The username with the domain (don't forget to use a double \ like "mydomain\\john_doe")
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.url='current website'] The website url
+ @param {Boolean} [setup.error=true] The function will stop and throw an error when something went wrong (use FALSE to don't throw an error)
+ @param {Function} [result] A function that will be executed at the end of the request with a param that is an array with the result
+
+ @example
+ $SP().usergroups("mydomain\\john_doe",{url:"http://my.si.te/subdir/"}, function(groups) {
+ for (var i=0; i < groups.length; i++) console.log(groups[i]); // -> "Roadmap Admin", "Global Viewers", ...
+ });
+ */
+ usergroups:function(username, setup, fct) {
+ switch (arguments.length) {
+ case 1: if (typeof username === "object") return this.usergroups("",username,function(){});
+ else if (typeof username === "function") return this.usergroups("",{},username);
+ break;
+ case 2: if (typeof username === "string" && typeof setup === "function") return this.usergroups(username,{},setup);
+ if (typeof username === "object" && typeof setup === "function") return this.usergroups("",username,setup);
+ }
+
+ // default values
+ setup = setup || {};
+ if (setup.url == undefined) {
+ if (!this.url) { this._getURL(); return this._addInQueue(arguments) }
+ else setup.url=this.url;
+ } else this.url=setup.url;
+ fct = fct || (function() {});
+ if (!username) throw "Error 'usergroups': you have to set an username.";
+
+ username=username.toLowerCase();
+ setup.url=setup.url.toLowerCase();
+ // check the cache
+ // [ {user:"username", url:"url", data:"the groups"}, ... ]
+ var cache=jQuery('body').data("sp-usergroups") || [];
+ for (var i=cache.length; i--;) {
+ if (cache[i].user.toLowerCase() == username && cache[i].url.toLowerCase() == setup.url) {
+ fct.call(this,cache[i].data);
+ return this
+ }
+ }
+
+ // build the request
+ var body = ""
+ + ""
+ + ""+username+""
+ + "";
+
+ // send the request
+ var _this=this;
+ var url = setup.url + "/_vti_bin/usergroup.asmx";
+ jQuery.ajax({type:"POST",
+ cache:false,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/directory/GetGroupCollectionFromUser'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var aResult=[];
+ // get the details
+ data=data.getElementsByTagName('Group');
+ for (var i=0,len=data.length; i'
+ + '- '+fileRef+'
'
+ + '';
+ var _this=this;
+ jQuery.ajax({
+ type: "POST",
+ cache: false,
+ async: true,
+ url: this.url+"/_vti_bin/Workflow.asmx",
+ data: body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/workflow/GetWorkflowDataForItem'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ // we want to use myElem to change the getAttribute function
+ var rows=data.getElementsByTagName('WorkflowTemplate');
+ if (rows.length===0) throw "Error 'getWorkflowID': No workflow found for this item";
+ for (var i=rows.length; i--;) {
+ if (rows[i].getAttribute("Name") == setup.workflowName) {
+ setup.after.call(_this, {"fileRef":fileRef, "workflowID":"{"+rows[i].getElementsByTagName('WorkflowTemplateIdSet')[0].getAttribute("TemplateId")+"}"});
+ return _this
+ }
+ }
+ setup.after.call(_this, "Error 'getWorkflowID': impossible to find this workflow name!");
+ },
+ error:function(jqXHR, textStatus, errorThrown) {
+ throw "Error 'getWorkflowID': Something went wrong with the request over the Workflow Web Service..."
+ }
+ });
+ })
+ return this;
+ },
+ /**
+ @name $SP().list.startWorkflow
+ @function
+ @description Manually start a work (that has been set to be manually started) (-untested with Sharepoint 2007-)
+
+ @param {Object} setup
+ @param {Number} setup.ID The item ID that tied to the workflow
+ @param {String} setup.workflowName The name of the workflow
+ @param {Array|Object} [setup.parameters] An array of object with {name:"Name of the parameter", value:"Value of the parameter"}
+ @param {Function} [setup.after] This callback function that is called after the request is done
+ @param {String} [setup.fileRef] Optional: you can provide the fileRef to avoid calling the $SP().list().getWorkflowID()
+ @param {String} [setup.workflowID] Optional: you can provide the workflowID to avoid calling the $SP().list().getWorkflowID()
+
+ @example
+ $SP().list("List Name").startWorkflow({ID:15, workflowName:"Workflow for List Name (manual)", parameters:{name:"Message",value:"Welcome here!"}, after:function() {
+ alert("Workflow done!");
+ }});
+ **/
+ startWorkflow:function(setup) {
+ // check if we need to queue it
+ if (this.needQueue) { return this._addInQueue(arguments) }
+ if (this.listID == undefined) throw "Error 'startWorkflow': you have to define the list ID/Name";
+ if (this.url == undefined) throw "Error 'startWorkflow': not able to find the URL!";
+
+ setup = setup || {};
+ setup.after = setup.after || (function() {});
+ if (!setup.workflowName && !setup.workflowID) throw "Error 'startWorkflow': Please provide the workflow name!"
+ if (!setup.ID) throw "Error 'startWorkflow': Please provide the item ID!"
+
+ // find the FileRef and templateID
+ if (!setup.fileRef && !setup.workflowID) {
+ this.getWorkflowID({ID:setup.ID,workflowName:setup.workflowName,
+ after:function(params) {
+ setup.fileRef=params.fileRef;
+ setup.workflowID=params.workflowID;
+ this.startWorkflow(setup)
+ }
+ })
+ } else {
+ // define the parameters if any
+ var workflowParameters = "";
+ if (setup.parameters) {
+ var p;
+ if (setup.parameters.length == undefined) setup.parameters = [ setup.parameters ];
+ p = setup.parameters.slice(0);
+ workflowParameters = "";
+ for (var i=0; i"+p[i].value+""+p[i].name+">";
+ workflowParameters += "";
+ }
+
+ var body = ""
+ + ""
+ + "- "+setup.fileRef+"
"
+ + ""+setup.workflowID+""
+ + ""+workflowParameters+""
+ + "";
+ // do the request
+ var _this=this;
+ var url = this.url + "/_vti_bin/Workflow.asmx";
+ jQuery.ajax({
+ type: "POST",
+ cache: false,
+ async: true,
+ url: url,
+ data: body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/workflow/StartWorkflow'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ setup.after.call(_this)
+ },
+ error:function(jqXHR, textStatus, errorThrown) {
+ setup.after.call(_this)
+ }
+ });
+ }
+ return this;
+ },
+ /**
+ @name $SP().distributionLists
+ @function
+ @description Find the distribution lists where the specified user is member of
+
+ @param {String} username The username with or without the domain (don't forget to use a double \ like "mydomain\\john_doe")
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [result] A function that will be executed at the end of the request with a param that is an array with the result
+
+ @example
+ $SP().distributionLists("mydomain\\john_doe",{url:"http://my.si.te/subdir/"}, function(mailing) {
+ for (var i=0; i < mailing.length; i++) console.log(mailing[i]); // -> {SourceReference: "cn=listname,ou=distribution lists,ou=rainbow,dc=com", DisplayName:"listname", MailNickname:"List Name", Url:"mailto:listname@rainbow.com"}
+ });
+ */
+ distributionLists:function(username, setup, fct) {
+ switch (arguments.length) {
+ case 1: if (typeof username === "object") return this.distributionLists("",username,function(){});
+ else if (typeof username === "function") return this.distributionLists("",{},username);
+ break;
+ case 2: if (typeof username === "string" && typeof setup === "function") return this.distributionLists(username,{},setup);
+ if (typeof username === "object" && typeof setup === "function") return this.distributionLists("",username,setup);
+ }
+
+ // default values
+ setup = setup || {};
+ if (setup.url == undefined) {
+ if (!this.url) { this._getURL(); return this._addInQueue(arguments) }
+ else setup.url=this.url;
+ } else this.url=setup.url;
+ fct = fct || (function() {});
+ if (!username) throw "Error 'distributionLists': you have to set an username.";
+
+ username = username.toLowerCase();
+ setup.url=setup.url.toLowerCase();
+ // check the cache
+ // [ {user:"username", url:"url", data:"the distribution lists"}, ... ]
+ var cache=jQuery('body').data("sp-distributionLists") || [];
+ for (var i=cache.length; i--;) {
+ if (cache[i].user === username && cache[i].url === setup.url) {
+ fct.call(this,cache[i].data);
+ return this
+ }
+ }
+
+ // build the request
+ var body = ""
+ + ""
+ + ""+username+"";
+
+ // send the request
+ var _this=this;
+ var url = setup.url + "/_vti_bin/UserProfileService.asmx";
+ jQuery.ajax({type:"POST",
+ cache:false,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://microsoft.com/webservices/SharePointPortalServer/UserProfileService/GetUserMemberships') },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var aResult=[];
+ // get the details
+ data=data.getElementsByTagName('MembershipData');
+ for (var i=0,len=data.length; i {ID:"1234", Name:"Doe, John", LoginName:"mydomain\john_doe", Email:"john_doe@rainbow.com"}
+ });
+ */
+ groupMembers:function(groupname, setup, fct) {
+ switch (arguments.length) {
+ case 1: if (typeof groupname === "object") return this.groupMembers("",groupname,function(){});
+ else if (typeof groupname === "function") return this.groupMembers("",{},groupname);
+ break;
+ case 2: if (typeof groupname === "string" && typeof setup === "function") return this.groupMembers(groupname,{},setup);
+ if (typeof groupname === "object" && typeof setup === "function") return this.groupMembers("",groupname,setup);
+ }
+
+ // default values
+ setup = setup || {};
+ if (setup.url == undefined) {
+ if (!this.url) { this._getURL(); return this._addInQueue(arguments) }
+ else setup.url=this.url;
+ } else this.url=setup.url;
+ fct = fct || (function() {});
+ if (!groupname) throw "Error 'groupMembers': you have to set an groupname.";
+
+ groupname=groupname.toLowerCase();
+ setup.url=setup.url.toLowerCase();
+ // check the cache
+ // [ {user:"username", url:"url", data:"the distribution lists"}, ... ]
+ var cache=jQuery('body').data("sp-groupMembers") || [];
+ for (var i=cache.length; i--;) {
+ if (cache[i].group === groupname && cache[i].url === setup.url) {
+ fct.call(this,cache[i].data);
+ return this
+ }
+ }
+
+ // build the request
+ var body = ""
+ + ""
+ + ""+this._cleanString(groupname)+"";
+
+ // send the request
+ var _this=this;
+ var url = setup.url + "/_vti_bin/usergroup.asmx";
+ jQuery.ajax({type:"POST",
+ cache:false,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/directory/GetUserCollectionFromGroup') },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var aResult=[];
+ // get the details
+ data=data.getElementsByTagName('User');
+ for (var i=0,len=data.length; i -1) { fct.call(this,true); return this }
+ }
+
+ // if we are herit means we found nothing
+ fct.call(this,false);
+ return this
+ });
+ });
+ })
+
+ return this;
+ },
+ /**
+ @name $SP().people
+ @function
+ @description Find the user details like manager, email, colleagues, ...
+
+ @param {String} [username] With or without the domain, and you can also use an email address, and if you leave it empty it's the current user by default (if you use the domain, don't forget to use a double \ like "mydomain\\john_doe")
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [result] A function that will be executed at the end of the request with a param that is an array with the result, or a String with the error message
+
+ @example
+ $SP().people("john_doe",{url:"http://my.si.te/subdir/"}, function(people) {
+ if (typeof people === "string") {
+ alert(people); // there was a problem so we prompt it
+ } else
+ for (var i=0; i < people.length; i++) console.log(people[i]+" = "+people[people[i]]);
+ });
+ */
+ people:function(username, setup, fct) {
+ switch (arguments.length) {
+ case 1: if (typeof username === "object") return this.people("",username,function(){});
+ else if (typeof username === "function") return this.people("",{},username);
+ username=undefined;
+ break;
+ case 2: if (typeof username === "string" && typeof setup === "function") return this.people(username,{},setup);
+ if (typeof username === "object" && typeof setup === "function") return this.people("",username,setup);
+ }
+
+ // default values
+ setup = setup || {};
+ if (setup.url == undefined) {
+ if (!this.url) { this._getURL(); return this._addInQueue(arguments) }
+ else setup.url=this.url;
+ } else this.url=setup.url;
+ fct = fct || (function() {});
+ username = username || "";
+
+ // build the request
+ var body = ""
+ + ""
+ + ""+username+""
+ + "";
+
+ // send the request
+ var _this=this;
+ var url = setup.url + "/_vti_bin/UserProfileService.asmx";
+ jQuery.ajax({type:"POST",
+ cache:false,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://microsoft.com/webservices/SharePointPortalServer/UserProfileService/GetUserProfileByName'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var aResult=[];
+ // get the details
+ data=data.getElementsByTagName('PropertyData');
+ for (var i=0,len=data.length; i=1) value=value[0].firstChild.nodeValue;
+ else value="No Value";
+ aResult.push(name);
+ aResult[name]=value;
+ }
+ fct.call(_this,aResult);
+ },
+ error:function(req, textStatus, errorThrown) {
+ // any error ?
+ var error=req.responseXML.getElementsByTagName("faultstring");
+ fct.call(_this,"Error 'people': "+error[0].firstChild.nodeValue);
+ }
+ });
+ return this;
+ },
+ /**
+ @name $SP().whoami
+ @function
+ @description Find the current user details like manager, email, colleagues, ...
+
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [result] A function that will be executed at the end of the request with a param that is an array with the result
+
+ @example
+ $SP().whoami({url:"http://my.si.te/subdir/"}, function(people) {
+ for (var i=0; i < people.length; i++) console.log(people[i]+" = "+people[people[i]]);
+ });
+ */
+ whoami:function(setup, fct) {
+ if (typeof setup === "function") { fct=setup; setup = {} }
+ return this.people("",setup,fct);
+ },
+ /**
+ @name $SP().addressbook
+ @function
+ @description Find an user based on a part of his name
+
+ @param {String} word A part of the name from the guy you're looking for
+ @param {Object} [setup] Options (see below)
+ @param {String} [setup.limit=10] Number of results returned
+ @param {String} [setup.type='User'] Possible values are: 'All', 'DistributionList', 'SecurityGroup', 'SharePointGroup', 'User', and 'None' (see http://msdn.microsoft.com/en-us/library/people.spprincipaltype.aspx)
+ @param {String} [setup.url='current website'] The website url
+ @param {Function} [result] A function that will be executed at the end of the request with a param that is an array with the result (typically: AccountName,UserInfoID,DisplayName,Email,Departement,Title,PrincipalType)
+
+ @example
+ $SP().addressbook("john", {limit:25}, function(people) {
+ for (var i=0; i < people.length; i++) {
+ for (var j=0; j < people[i].length; j++) console.log(people[i][j]+" = "+people[i][people[i][j]]);
+ }
+ });
+ */
+ addressbook:function(username, setup, fct) {
+ switch (arguments.length) {
+ case 1: if (typeof username === "object") return this.addressbook("",username,function(){});
+ else if (typeof username === "function") return this.addressbook("",{},username);
+ username=undefined;
+ break;
+ case 2: if (typeof username === "string" && typeof setup === "function") return this.addressbook(username,{},setup);
+ if (typeof username === "object" && typeof setup === "function") return this.addressbook("",username,setup);
+ }
+
+ // default values
+ setup = setup || {};
+ if (setup.url == undefined) {
+ if (!this.url) { this._getURL(); return this._addInQueue(arguments) }
+ else setup.url=this.url;
+ } else this.url=setup.url;
+ setup.limit = setup.limit || 10;
+ setup.type = setup.type || "User";
+ fct = fct || (function() {});
+ username = username || "";
+
+ // build the request
+ var body = ""
+ + ""
+ + ""+username+""+setup.limit+""+setup.type+"";
+
+ // send the request
+ var _this=this;
+ var url = setup.url + "/_vti_bin/People.asmx";
+ jQuery.ajax({type: "POST",
+ cache:false,
+ url:url,
+ data:body,
+ beforeSend: function(xhr) { xhr.setRequestHeader('SOAPAction', 'http://schemas.microsoft.com/sharepoint/soap/SearchPrincipals'); },
+ contentType: "text/xml; charset=utf-8",
+ dataType: "xml",
+ success:function(data) {
+ var aResult=[];
+ // get the details
+ data=data.getElementsByTagName('PrincipalInfo');
+ for (var i=0,lenR=data.length; i -1 ? new Date(Date.UTC(year,month-1,day,hour,min,sec)) : new Date(year,month-1,day,hour,min,sec));
+ },
+ /**
+ @name $SP().toSPDate
+ @function
+ @description Change a Date object into a Sharepoint date string
+ @param {Date} [dateObject] the Sharepoint date string
+ @return {String} the equivalent string for the Date object passed
+ @example $SP().toSPDate(new Date("31/Oct/2012")); // --> "2012-10-31 00:00:00"
+ */
+ toSPDate:function(oDate) {
+ var pad = function(p_str){
+ if(p_str.toString().length==1){p_str = '0' + p_str;}
+ return p_str;
+ };
+ var month = pad(oDate.getMonth()+1);
+ var day = pad(oDate.getDate());
+ var year = oDate.getFullYear();
+ var hours = pad(oDate.getHours());
+ var minutes = pad(oDate.getMinutes());
+ var seconds = pad(oDate.getSeconds());
+ return year+"-"+month+"-"+day+" "+hours+":"+minutes+":"+seconds;
+ },
+ /**
+ @name $SP().toCurrency
+ @function
+ @description It will return a number with commas, currency sign and a specific number of decimals
+ @param {Number|String} number The number to format
+ @param {Number} [decimal=-1] The number of decimals (use -1 if you want to have 2 decimals when there are decimals, or no decimals if it's .00
+ @param {String} [sign='$'] The currency sign to add
+
+ @return {String} The converted number
+ @example
+
+ $SP().toCurrency(1500000); // --> $1,500,000
+ $SP().toCurrency(1500000,2,''); // --> 1,500,000.00
+ */
+ toCurrency:function(n,dec,sign) {
+ n=Number(n);
+ if (dec === undefined) dec=-1;
+ if (sign === undefined) sign='$';
+ var m="";
+ if (n<0) { m="-"; n*=-1; }
+ var s = n;
+ if (dec===-1) s = s.toFixed(2).replace('.00', '');
+ else s = s.toFixed(dec);
+ var digits = (Math.floor(n) + '').length;
+ for (var i=0, j=0, mod=digits%3; i {id:328, value:"Foo"}
+ */
+ getLookup:function(str) { if (!str) { return {id:"", value:""} } var a=str.split(";#"); return {id:a[0], value:a[1]}; },
+ /**
+ @name $SP().toXSLString
+ @function
+ @description Change a string into a XSL format string
+ @param {String} text The string to change
+ @return {String} the XSL version of the string passed
+ @example $SP().toXSLString("Big Title"); // --> "Big_x0020_Title"
+ */
+ toXSLString:function(str) {
+ if (typeof str !== "string") throw "Error 'toXLSString': '"+str+"' is not a string....";
+ // if the first car is a number, then FullEscape it
+ var FullEscape = function(strg, exceptNumeric) {
+ exceptNumeric = exceptNumeric || false;
+ var hexVals = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
+ var rstr = "";
+ for (var i=0; i < strg.length; i++) {
+ var c = strg.charAt(i);
+ var num = c.charCodeAt(0);
+ var temp = 0;
+ var hexString = "";
+ while (num >= 16) {
+ temp = num % 16;
+ num = Math.floor(num / 16);
+ hexString += hexVals[temp];
+ }
+ hexString += hexVals[num];
+ var tmpStr = "";
+ for (var k=hexString.length-1; k >= 0; k--) tmpStr += hexString.charAt(k);
+ rstr += "%" + tmpStr;
+ }
+ return rstr;
+ };
+ var aSpaces = str.split(" ");
+ var ret = "";
+ // check if there is a number and work length is smaller than 5 letters
+ if (/^[0-9]/.test(aSpaces[0]) && aSpaces[0].length < 5) {
+ // change the first letter
+ ret = FullEscape(str.charAt(0));
+ str = str.substring(1);
+ }
+ for (var i=0; i < str.length; i++) {
+ var c = str.charAt(i);
+ if (/[0-9A-Za-z_]/.test(c) === false) ret += FullEscape(c).toLowerCase();
+ else ret += c;
+ }
+ return ret.replace(/%([a-zA-Z0-9][a-zA-Z0-9])/g,"_x00$1_").substring(0,32);
+ },
+ /**
+ @name $SP().formfields
+ @namespace
+ @description Retrieve the fields info in the NewForm and in the EditForm
+ @return {Array} An array of hash with several keys: name, values, elements, type, and tr
+
+ @param {String|Array} [fields=""] A list of fields to get (e.g. "field1,other field,field2" or ["field1","other field","field2"]) and by default we take all fields ... ATTENTION if you have a field with "," then use only the Array as a parameter
+ @param {Object} [setup] Options (see below)
+ @param {Boolean} [setup.mandatory=undefined] Set it to 'true' to look for the mandatory fields (the "false" value has no effect)
+
+ @note You can use a data attribute called "sp-ignore" on any element in your form and the script will ignore it (useful when you add a custom field inside another one).
+
+ @example
+ $SP().formfields(); // return all the fields
+
+ $SP().formfields({mandatory:true}).each(function() { // return all the mandatory fields
+ var field = this;
+ if (field.val().length==0) console.log(field.name()+" is empty!");
+ });
+ $SP().formfields("Title,Contact Name,Email").each(function() { // return these three fields
+ var field = this;
+ console.log(field.name()+" has these values: "+field.val());
+ });
+ // if you have a field with a comma use an Array
+ $SP().formfields(["Title","Long field, isn't it?","Contact Name","Email"]).each(function() {
+ var field = this;
+ console.log(field.name()+" has the description: "+field.description());
+ });
+ // returns the fields "Title" and "New & York", and also the mandatory fields
+ $SP().formfields(["Title", "New & York"],{mandatory:true});
+ */
+ formfields:function(fields, settings) {
+ 'use strict';
+ this.reset();
+ if (arguments.length == 1 && typeof fields === "object" && typeof fields.length === "undefined") { settings=fields; fields=undefined; }
+
+ // default values
+ settings = settings || {};
+ fields = fields || [];
+ settings.cache = (settings.cache === false ? false : true);
+
+ var aReturn = [], bigLimit=10000;
+ if (typeof fields === "string") fields=( fields==="" ? [] : fields.split(",") );
+ var limit = (fields.length>0 ? fields.length : bigLimit);
+ if (limit === bigLimit && !settings.mandatory) settings.includeAll=true; // if we want all of them
+
+ // find all the fields, then cache them if not done already
+ if (_SP_CACHE_FORMFIELDS !== null) {
+ var allFields = _SP_CACHE_FORMFIELDS.slice(0);
+ if (settings.includeAll) {
+ this.length=allFields.length;
+ this.data=allFields;
+ return this;
+ }
+ var done=0,i,len=allFields.length,idx;
+ // retrieve the field names
+ var fieldNames=[];
+ for (i=0;i -1) aReturn.push(allFields[idx])
+ }
+ for (i=0,len=(settings.mandatory?allFields.length:0); i -1) { table = a[i]; break; } // we found our table!
+ } else
+ table=document.querySelector('table.ms-formtable')
+ if (!table) throw "Error: unable to find the table.ms-formtable!";
+
+ // this function will help to find the closest TR element instead of using jQuery.closest('tr')
+ var closestTR = function(nobr) {
+ var tr = nobr;
+ do { tr=tr.parentNode } while(tr.tagName.toLowerCase() !== "tr");
+ return tr;
+ };
+
+ // from jQuery
+ // Retrieve the text of an HTML element
+ var getText = function(elem) {
+ var i, node, nodeType = elem.nodeType, ret = "";
+ if (nodeType) {
+ if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
+ // Use textContent || innerText for elements
+ if (typeof elem.textContent === 'string') return elem.textContent;
+ else if (typeof elem.innerText === 'string') {
+ // Replace IE's carriage returns
+ return elem.innerText.replace(/\r/g, '');
+ } else {
+ // Traverse its children
+ for (elem = elem.firstChild; elem; elem = elem.nextSibling) ret += getText(elem);
+ }
+ } else if (nodeType === 3 || nodeType === 4) return elem.nodeValue;
+ } else {
+ // If no nodeType, this is expected to be an array
+ for (i = 0; (node = elem[i]); i++) {
+ // Do not traverse comment nodes
+ if (node.nodeType !== 8) ret += getText(node);
+ }
+ }
+ return ret;
+ }
+
+ if (settings.includeAll) limit=bigLimit;
+ // we now find the names of all fields
+ for (var a=table.getElementsByTagName('nobr'), i=-1, len=a.length, done=0; i -1) {
+ txt=html="Content Type";
+ includeThisField=true;
+ }
+ } else {
+ tr = undefined;
+ nobr = a[i];
+ html = nobr.innerHTML;
+ txt = getText(nobr); // use this one for the & and others
+
+ // clean the txt
+ if (html.indexOf("ms-formvalidation") > -1) { // this is a mandatory field
+ // remove the with the *
+ html = html.slice(0,-39);
+ if (html.charAt(html.length-2)=='<' && (html.charAt(html.length-1)=='s'||html.charAt(html.length-1)=='S')) html=html.slice(0,-2); // with IE we don't have "" around the class name
+ // do we want the mandatory fields ?
+ if (settings.mandatory) includeThisField=true
+ txt = txt.slice(0,-2); // it's a mandatory field so we want to remove the extra * at the end
+ isMandatory=true;
+ }
+
+ if (limit !== bigLimit) {
+ for (var k=0, lenk=limit; k -1) {
+ for (var b=document.getElementsByTagName("select"),bb=0; bb -1 || input[inp].className.indexOf("ms-long") > -1) {
+ elem.push(input[inp]);
+ if (!obj._type) obj._type="text";
+ if (input[inp].id.search(/DateTimeFieldDate$/) > -1) {
+ continueToSearch=true; // if we find an INPUT that is a DateTime field
+ obj._type="date"
+ } else if (input[inp].id.search(/_UrlFieldUrl$|_UrlFieldDescription$/) > -1) {
+ obj._type="url";
+ // it's an url so find the previous label
+ elem.pop();
+ elem.push(input[inp].previousSibling.previousSibling);
+ elem.push(input[inp])
+ } else inp=input.length
+ } else if (input[inp].title.indexOf("Specify your own value:") > -1) {
+ elem.push(input[inp])
+ if (obj._type.slice(0,7) === "choices") obj._type += " plus"
+ }
+ break;
+ case "radio":
+ if (input[inp].id.search(/_DropDownButton$/) > -1) {
+ obj._type="choices plus";
+ do {
+ elem.push(input[inp]);
+ if (!inp) elem.push("") // we're going to store the SELECT here
+ } while (++inp -1) obj._type="boolean"
+ else obj._type="choices checkbox"
+ // store the label if it exists
+ if (obj._type !== "boolean") elem.push(input[inp].nextSibling);
+ break;
+ }
+ }
+ }
+ if (elem.length === 0 || continueToSearch) {
+ var select = td.getElementsByTagName("select");
+ for (inp=0; inp -1 || select[inp].id.search(/_cbRate$|_Lookup$|_SelectResult$|_SelectCandidate$|_DateTimeFieldDateHours$|_DateTimeFieldDateMinutes$/) > -1) {
+ if (select[inp].id.search(/_SelectCandidate$|_SelectResult$|_DateTimeFieldDateHours$|_DateTimeFieldDateMinutes$/) > -1) {
+ if (select[inp].id.indexOf("DateTimeField") > -1) obj._type="date time"
+ elem.push(select[inp]); // multiple lookup selection, or Hour and Minutes
+ if (select[inp].id.indexOf("_SelectCandidate") > -1) { // it's for the two lists with multiple choices with Add/Remove buttons
+ // find the both buttons
+ var buttons = td.getElementsByTagName('button');
+ if (buttons.length === 2) {
+ elem.push(buttons[0]);
+ elem.push(buttons[1]);
+ obj._type="lookup multiple"
+ }
+ }
+ }
+ else {
+ if (continueToSearch) {
+ if (obj._type==="choices plus") elem[1]=select[inp]
+ else elem.push(select[inp])
+ }
+ else {
+ elem.push(select[inp]);
+ if (select[inp].id.search(/_Lookup$/) > -1) obj._type="lookup"
+ else if (!obj._type) obj._type="choices"
+ }
+ break
+ }
+ }
+ }
+ }
+ if (elem.length === 0) {
+ var other = td.getElementsByTagName("div");
+ for (inp=0; inp -1) {
+ elem.push(other[inp]);
+ obj._type="people"
+ break;
+ }
+ }
+ other = td.getElementsByTagName("textarea");
+ for (inp=0; inp -1 || other[inp].className.indexOf("ms-input") > -1) {
+ elem.push(other[inp]);
+ if (!obj._type) obj._type="text multiple";
+ else if (obj._type==="people") {
+ // find the a/img also
+ other = td.getElementsByTagName("a");
+ for (inp=0;inp -1) {
+ // with IE it's not a normal TEXTAREA but a iframe...
+ elem=td.getElementsByTagName('iframe');
+ }
+ else { // for others
+ other = td.getElementsByTagName('span');
+ for (inp=other.length; inp--;) {
+ if (other[inp].className.indexOf("ms-formdescription") > -1) {
+ elem.push(other[inp]);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // find the description, if any
+ if (td.nextSibling) {
+ var descro=td.nextSibling;
+ if (descro.nodeType==3) obj._description = getText(descro).trim()
+ }
+ }
+ obj._elements=elem;
+
+ // define the val()
+ switch(obj.type()) {
+ case "attachments": {
+ obj.val = function(v) {
+ if (v) alert("$SP.formfields Error: You cannot define a value for the Attachments")
+ else {
+ var elem=this.elem();
+ var ret=[];
+ for (v=0; v/,"")
+ if (v.search(/ -1) {
+ var ev=e[0].querySelectorAll('span > span');
+ if (ev.length>1) {
+ v=[];
+ var x;
+ for (var t=0; t/,"")
+ if (x !== "") v.push(x)
+ }
+ if (v.length===1) v=v[0]
+ else if (v.length===0) v=""
+ } else v=ev[0].innerHTML
+ }
+ // v=e[1].value.replace(/(<([^>]+)>)/ig,"").replace(/^\s+|\s+$| /g,"").replace(/;$/,"")
+ return (typeof v==="string" ? v.replace(/ |
/,"") : v);*/
+ v=e[0].innerHTML.replace(/(<([^>]+)>)/ig,"").replace(/^\s+|\s+$| /g,"").replace(/
| /g,"").replace(/;$/,"").split(";")
+ var ret=[];
+ for (var x=0; x -1) {
+ e[i-1].checked=true;
+ done.push(e[i].innerHTML);
+ if (type.slice(0,13) === "choices radio") return this
+ } else if (v !== undefined && e[i].tagName.toLowerCase() === "label") e[i-1].checked=false
+ else if (v === undefined && e[i].checked) {
+ if (type === "choices radio plus") {
+ if (e[i+1].innerHTML === "Specify your own value:") return e[i+2].value;
+ return e[i+1].innerHTML
+ } else
+ ret.push(e[i+1].innerHTML === "Specify your own value:" ? e[i+2].value : e[i+1].innerHTML)
+ }
+ }
+ if (v === undefined) return ret
+ if (v !== undefined) {
+ if (type === "choices radio plus") {
+ // if we are here then it means we didn't find the value in the radio boxes, so try the INPUT
+ e[e.length-3].checked=true;
+ e[e.length-1].value = v;
+ } else if (type === "choices checkbox plus") {
+ // go thru 'done' to see if a value must go into the INPUT
+ var rest=[];
+ for (var i=v.length; i--;) {
+ if (done.indexOf(v[i]) === -1) rest.push(v[i])
+ }
+ if (rest.length>0) {
+ e[e.length-3].checked=true;
+ e[e.length-1].value = rest.join(" ");
+ }
+ }
+ return this;
+ }
+ };
+ obj.options = function() {
+ var e=this.elem();
+ var ret=[];
+ var type=this.type().slice(-4);
+ for (var i=0; i return the name of the field
+ console.log(this.isMandatory()); // -> returns TRUE if it's a mandatory field
+ })
+ */
+ each:function(fct) {
+ for (var i=0,len=this.data.length; i "field value"
+ @return {String|Array|Object} Return the value of the field(s)
+
+ @example
+ $SP().formfields("Title").val(); // return "My project"
+ $SP().formfields("Title").val("My other project");
+ $SP().formfields("Title").val(); // return "My other project"
+
+ // it will set "Choice 1" and "Choice 2" for the "Make your choice" field, and "2012/12/31" for the "Booking Date" field
+ $SP().formfields("Make your choice,Booking Date").val([ ["Choice 1","Choice 2"], "2012/12/31" ]);
+
+ // it will set "My Value" for all the fields
+ $SP().formfields("Make your choice,Title,Other Field").val("My Value");
+
+ // it will return an array; each item represents a field
+ $SP().formfields("Make your choice,Title,Other Field").val(); // -> [ ["My Value"], "My Value", "Other Field" ]
+
+ // for a Link field
+ $SP().formfields("Link").val(["http://www.dell.com","Dell"]) // -> "Dell" is used as the description of the link, and "http://www.dell.com" as the Web address
+
+ // it will return a hashmap
+ $SP().formfields("Make your choice,Title,Other Field").val({identity:true}); // -> {"Make your choice":["My Value"], "Title":"My Value", "Other Field":"My Value"}
+ */
+ val:function(str) {
+ if (typeof str==="object" && str.identity !== undefined) {
+ identity=str.identity;
+ str=undefined;
+ } else identity=false
+ // it means we want to get the value
+ if (str === undefined) {
+ var aReturn = [];
+ this.each(function() {
+ if (identity) aReturn[this.name()] = this.val()
+ else aReturn.push(this.val())
+ })
+ return (aReturn.length===1 ? aReturn[0] : aReturn)
+ } else if (typeof str !== "object") { // we want to set a simple value
+ this.each(function() { this.val(str) });
+ } else {
+ var i=0;
+ if (this.length>1) {
+ if (str.length !== this.length) throw new Error("$SP.formfields.val: the array passed for val() must have the same size as the number of fields in formfields()")
+ this.each(function() { this.val(str[i++]) })
+ } else this.each(function() { this.val(str) })
+ }
+
+ return this;
+ },
+ /**
+ @name $SP().formfields.elem
+ @function
+ @description Get the HTML element(s) tied with the field(s) selected by "formfields"
+
+ @return {Array|HTMLElement|jQuery} Null is returned if nothing is found, or the found elements... if jQuery is defined then the HTML elements will be jQueryrize
+
+ @example
+ $SP().formfields("Title").elem(); // -> returns a HTML INPUT TEXT
+ $SP().formfields("List of options").elem(); / -> returns a HTML SELECT
+
+ */
+ elem:function() {
+ var aReturn = [];
+ var hasJQuery=(typeof jQuery === "function");
+ this.each(function() {
+ var e = this.elem();
+ aReturn.push(e.length === 1 ? e[0] : e)
+ })
+
+ switch(aReturn.length) {
+ case 0: return hasJQuery ? jQuery() : null;
+ case 1: return hasJQuery ? jQuery(aReturn[0]) : aReturn[0];
+ default: return hasJQuery ? jQuery(aReturn) : aReturn;
+ }
+ },
+ /**
+ @name $SP().formfields.row
+ @function
+ @description Get the TR element(s) tied with the field(s) selected by "formfields"
+ @return {Array|HTMLElement|jQuery} Null is returned if nothing is found, or the TR HTMLElement... or a jQuery object is returned if jQuery exists
+
+ @example
+ $SP().formfields("Title").row(); // return the TR element that is the parent (= the row)
+ $SP().formfields("Title").row().hide(); // because we have jQuery we can apply the hide()
+ */
+ row:function() {
+ var aReturn = [];
+ var hasJQuery=(typeof jQuery === "function");
+ this.each(function() {
+ aReturn.push(this.row())
+ })
+
+ switch(aReturn.length) {
+ case 0: return null;
+ case 1: return (hasJQuery ? jQuery(aReturn[0]) : aReturn[0]);
+ default: return (hasJQuery ? jQuery(aReturn) : aReturn);
+ }
+ },
+ /**
+ @name $SP().formfields.type
+ @function
+ @description Get the type of the field(s) selected by "formfields"
+ Here is the list of different types returned:
+ - "text" for the free text field;
+ - "text multiple" for the textarea zone;
+ - "attachments" for the attachments field;
+ - "lookup" for a lookup field (dropdown);
+ - "lookup multiple" for a lookup field with multiple selection (two dropdowns with two buttons);
+ - "content type" for the content type field;
+ - "boolean" for the yes/no checkbox;
+ - "date" for a date only field;
+ - "date time" for a date and time field;
+ - "choices" for a dropdown selection;
+ - "choices plus" for a dropdown selection with an input field to enter our own value;
+ - "choices radio" for the radio buttons selection;
+ - "choices radio plus" for the radio buttons selection with an input field to enter our own value;
+ - "choices checkbox" for the checkboxes field for a selection;
+ - "choices checkbox plus" for the checkboxes field for a selection with an input field to enter our own value;
+ - "people" for the poeple picker field;
+ - "url" for the link/url/picture field.
+
+ @return {String|Array} Returns the type of the field(s)
+
+ @example
+ $SP().formfields("Title").type(); // return "text"
+ $SP().formfields("List of options").type(); // return "choices"
+ */
+ type:function() {
+ var aReturn = [];
+ this.each(function() { aReturn.push(this.type()) })
+
+ switch(aReturn.length) {
+ case 0: return "";
+ case 1: return aReturn[0];
+ default: return aReturn;
+ }
+ },
+ /**
+ @name $SP().formfields.description
+ @function
+ @description Get the description of the field(s) selected by "formfields"
+
+ @return {String|Array} Returns the description of the field(s)
+
+ @example
+ $SP().formfields("Title").description(); // return "This is the description of this field"
+ $SP().formfields("List of options").description(); // return "", it means no description
+ */
+ description:function() {
+ var aReturn = [];
+ this.each(function() { aReturn.push(this.description()) })
+
+ switch(aReturn.length) {
+ case 0: return "";
+ case 1: return aReturn[0];
+ default: return aReturn;
+ }
+ },
+ /**
+ @name $SP().registerPlugin
+ @function
+ @description Permits to register a plugin
+
+ @param {String} pluginName You have to define the plugin name
+ @param {Function} pluginFct You have to define the function of the plugin with one parameter that are the options passed
+
+ @example
+ $SP().registerPlugin('test', function(options) {
+ console.log(options.message);
+ })
+ */
+ registerPlugin:function(name,fct) {
+ var $html=$('html');
+ var plugins=$html.data('sp-plugins') || [];
+ if (typeof plugins[name] !== "undefined")
+ throw "Error 'registerPlugin': '"+name+"' is already registered.";
+ plugins[name] = fct;
+ $html.data('sp-plugins',plugins);
+ return true;
+ },
+ /**
+ @name $SP().plugin
+ @function
+ @description Permits to use a plugin
+
+ @param {String} pluginName The plugin name to call
+ @param {Object} [options] The options for the plugin
+
+ @example
+ $SP().plugin('test',{message:"This is a test !"})
+ */
+ plugin:function(name,options) {
+ var plugins=$('html').data('sp-plugins') || [];
+ options = options || {};
+ if (typeof plugins[name] === "function") plugins[name].call(this,options);
+ else throw "Error $SP().plugin: the plugin '"+name+"' is not registered."
+ return this;
+ }
+ };
+
+
+ /**
+ * @description we need to extend an element for some cases with $SP().get
+ **/
+ var myElem = (function(){
+ var myElem = function(elem) { return new MyElemConstruct(elem); },
+ MyElemConstruct = function(elem) { this.mynode = elem; this.singleList=true; return this; };
+ myElem.fn = MyElemConstruct.prototype = {
+ getAttribute: function(id) { return this.mynode.getAttribute("ows_"+id.replace(/ /g,"")) }, /*.replace(/ /g,"")*/
+ getAttributes:function() { return this.mynode.attributes }
+ };
+ return myElem;
+ })();
+
+ var extendMyObject=function(arr) { this.attributes=arr };
+ extendMyObject.prototype.getAttribute=function(attr) { return this.attributes[attr] };
+ extendMyObject.prototype.getAttributes=function() { return this.attributes };
+
+ SharepointPlus.prototype.noConflict = function() {
+ window._$SP = window._SharepointPlus = window.$SP;
+ };
+
+ return window.$SP = window.SharepointPlus = SharepointPlus;
+
+})(window);
\ No newline at end of file
diff --git a/sharepointplus-3.0.7.min.js b/sharepointplus-3.0.7.min.js
new file mode 100644
index 0000000..8eb56e8
--- /dev/null
+++ b/sharepointplus-3.0.7.min.js
@@ -0,0 +1,8 @@
+/*!
+ * SharepointPlus v3.0.7
+ * Copyright 2013, Aymeric (@aymkdn)
+ * Contact: http://kodono.info
+ * Documentation: http://aymkdn.github.com/SharepointPlus/
+ * License: GPL v2 (http://aymkdn.github.com/SharepointPlus/license.txt)
+ */
+;if(!Array.prototype.indexOf){Array.prototype.indexOf=function(c){if(this==null){throw new TypeError()}var d=Object(this);var a=d.length>>>0;if(a===0){return -1}var e=0;if(arguments.length>1){e=Number(arguments[1]);if(e!=e){e=0}else{if(e!=0&&e!=Infinity&&e!=-Infinity){e=(e>0||-1)*Math.floor(Math.abs(e))}}}if(e>=a){return -1}var b=e>=0?e:Math.max(a-Math.abs(e),0);for(;b-1;i--){var n=_n;var caseTest=_caseTest;do{switch(caseTest){case 0:dest[i]=fn(source[i]);i--;case 7:dest[i]=fn(source[i]);i--;case 6:dest[i]=fn(source[i]);i--;case 5:dest[i]=fn(source[i]);i--;case 4:dest[i]=fn(source[i]);i--;case 3:dest[i]=fn(source[i]);i--;case 2:dest[i]=fn(source[i]);i--;case 1:dest[i]=fn(source[i]);i--}caseTest=0}while(--n>0)}return dest};var decode_b64=function(d,b,c,u,r,q,x){b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(r=q=x="";c=d.charAt(x++);~c&&(u=q%4?u*64+c:c,q++%4)?r+=String.fromCharCode(255&u>>(-2*q&6)):0){c=b.indexOf(c)}return r};var encode_b64=function(a,b,c,d,e,f){b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";c="=";for(d=f="";e&=3,a.charAt(d++)||(b="=",e);f+=b.charAt(63&c>>++e*2)){c=c<<8|a.charCodeAt(d-=!e)}return f};function SharepointPlus(){if(!(this instanceof arguments.callee)){return new arguments.callee()}}SharepointPlus.prototype={data:[],length:0,listQueue:[],needQueue:false,getVersion:function(){return"3.0.4"},list:function(list,url){this.reset();if(url){if(url.substring(url.length-1,url.length)==="/"){url=url.substring(0,url.length-1)}this.url=url}else{this._getURL()}this.listID=list.replace(/&/g,"&");return this},_getURL:function(){if(this.url===undefined&&typeof L_Menu_BaseUrl==="undefined"&&jQuery("body").data("sp-currenturl")===undefined){this.needQueue=true;var _this=this;var body=""+window.location.href.replace(/&/g,"&")+"";var url=window.location.protocol+"//"+window.location.host+"/_vti_bin/Webs.asmx";jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var result=data.getElementsByTagName("WebUrlFromPageUrlResult");if(result.length){_this.url=result[0].firstChild.nodeValue.toLowerCase();jQuery("body").data("sp-currenturl",_this.url)}_this.needQueue=false}})}else{this.url=this.url||jQuery("body").data("sp-currenturl")||(window.location.protocol+"//"+window.location.host+L_Menu_BaseUrl)}return this},_addInQueue:function(args){this.listQueue.push(args);if(this.listQueue.length===1){this._testQueue()}return this},_testQueue:function(){if(this.needQueue){var _this=this;setTimeout(function(){_this._testQueue.call(_this)},25)}else{if(this.listQueue.length>0){var todo=this.listQueue.shift();todo.callee.apply(this,Array.prototype.slice.call(todo))}this.needQueue=(this.listQueue.length>0);if(this.needQueue){var _this=this;setTimeout(function(){_this._testQueue.call(_this)},25)}}},parse:function(q){var queryString=q.replace(/(\s+)?(=|<=|>=|<>|<|>| LIKE | like )(\s+)?/g,"$2").replace(/""|''/g,"Null").replace(/==/g,"=");var factory=[];var limitMax=q.length;var closeOperator="",closeTag="",ignoreNextChar=false;var lastField="";var parenthesis={open:0};for(var i=0;i0&&i=0){if(closeOperator!=""){factory[0]="<"+closeOperator+">"+factory[0]}factory[0]+=this.parse(queryString.substring(start+1,i));if(closeOperator!=""){factory[0]+=""+closeOperator+">"}closeOperator=""}else{factory[0]=this.parse(queryString.substring(start+1,i))}break;case">":case"<":i++;if(queryString.charAt(i)=="="){factory.push("<"+(letter==">"?"G":"L")+"eq>");closeTag=""+(letter==">"?"G":"L")+"eq>"}else{if(letter=="<"&&queryString.charAt(i)==">"){factory.push("");closeTag=""}else{i--;factory.push("<"+(letter==">"?"G":"L")+"t>");closeTag=""+(letter==">"?"G":"L")+"t>"}}break;case"=":factory.push("");closeTag="";break;case" ":if(queryString.substring(i,i+5).toUpperCase()==" AND "){closeOperator="And";i+=4}else{if(queryString.substring(i,i+4).toUpperCase()==" OR "){closeOperator="Or";i+=3}else{if(queryString.slice(i,i+6).toUpperCase()==" LIKE "){i+=5;factory.push("");closeTag=""}else{lastField+=letter}}}break;case'"':case"'":var apos=letter;var word="";while((letter=queryString.charAt(++i))!=apos&&i";lastField="";var type="Text";if(/\d{4}-\d\d?-\d\d?((T| )\d{2}:\d{2}:\d{2})?/.test(word)||word=="[Today]"){type="DateTime"}word=this._cleanString(word);switch(word){case"[Today]":word='';break;case"[Me]":word='';type="Integer";break}factory[lastIndex]+=''+word+"";factory[lastIndex]+=closeTag;closeTag="";if(lastIndex>0){if(closeOperator!=""){factory[0]="<"+closeOperator+">"+factory[0]}factory[0]+=factory[lastIndex];if(closeOperator!=""){factory[0]+=""+closeOperator+">"}delete (factory[lastIndex]);closeOperator=""}break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":if(closeTag!=""){var value=letter;while(!isNaN(letter=queryString.charAt(++i))&&i';lastField="";factory[lastIndex]+=''+value.replace(/ $/,"")+"";factory[lastIndex]+=closeTag;closeTag="";if(lastIndex>0){if(closeOperator!=""){factory[0]="<"+closeOperator+">"+factory[0]}factory[0]+=factory[lastIndex];if(closeOperator!=""){factory[0]+=""+closeOperator+">"}delete (factory[lastIndex]);closeOperator=""}i-=2;break}default:if(closeTag==""){lastField+=letter}else{if(letter.toLowerCase()=="n"&&queryString.substring(i,i+4).toLowerCase()=="null"){lastIndex=factory.length-1;if(closeTag==""){factory[lastIndex]="";closeTag=""}else{if(closeTag==""){factory[lastIndex]="";closeTag=""}}i+=3;factory[lastIndex]+='';lastField="";factory[lastIndex]+=closeTag;closeTag="";if(lastIndex>0){if(closeOperator!=""){factory[0]="<"+closeOperator+">"+factory[0]}factory[0]+=factory[lastIndex];if(closeOperator!=""){factory[0]+=""+closeOperator+">"}delete (factory[lastIndex]);closeOperator=""}}}}}return factory.join("")},_parseOn:function(q){var factory=[];var queryString=q.replace(/(\s+)?(=)(\s+)?/g,"$2").replace(/==/g,"=").split(" AND ");for(var i=0;i/g,">")},cleanResult:function(str,separator){if(str===null||typeof str==="undefined"){return""}separator=separator||";";return(typeof str==="string"?str.replace(/;#[0-9]+;#/g,separator).replace(/^[0-9]+;#/,"").replace(/^;#|;#$/g,"").replace(/;#/g,separator).replace(/string;#/,""):str)},get:function(setup,fct){if(this.needQueue){return this._addInQueue(arguments)}if(this.listID==undefined){throw"Error 'get': you have to define the list ID/Name"}if(arguments.length===1&&typeof setup==="function"){return this.get({},setup)}setup=setup||{};if(this.url==undefined){throw"Error 'get': not able to find the URL!"}setup.fields=setup.fields||"";setup.where=setup.where||"";setup.orderby=setup.orderby||"";setup.groupby=setup.groupby||"";setup.rowlimit=setup.rowlimit||0;setup.paging=(setup.paging===true?true:false);if(setup.paging&&setup.rowlimit===0){setup.rowlimit=5000}setup.expandUserField=(setup.expandUserField===true?"True":"False");setup.dateInUTC=(setup.dateInUTC===true?"True":"False");setup.folderOptions=setup.folderOptions||null;setup.view=setup.view||"";setup.results=setup.results||[];setup.ListItemCollectionPositionNext=setup.ListItemCollectionPositionNext||"";if(typeof setup.where==="object"){if(setup.originalWhere==undefined){setup.originalWhere=setup.where.slice(0)}setup.nextWhere=setup.where.slice(1);setup.where=setup.where.shift()}else{setup.originalWhere=setup.where;setup.nextWhere=[]}setup.progress=setup.progress||(function(){});if(setup.view!==""){if(setup.view.charAt(0)!=="{"){var _this=this;_this.view(setup.view,function(data,viewID){setup.view=viewID;var where=(setup.whereCAML?setup.where:_this.parse(setup.where));where+=data.whereCAML;if(setup.where!==""&&data.whereCAML!==""){where=""+where+""}setup.where=where;setup.fields+=(setup.fields===""?"":",")+data.fields.join(",");setup.orderby+=(setup.orderby===""?"":",")+data.orderby;setup.whereCAML=true;setup.useOWS=true;delete setup.view;return _this.get.call(_this,setup,fct)});return this}if(setup.whereCAML!==true){setup.where=this.parse(setup.where);setup.whereCAML=true}}var useOWS=true;var fields="";if(setup.fields==""||setup.fields==[]){fields=""}else{if(typeof setup.fields=="string"){setup.fields=setup.fields.replace(/^\s+/,"").replace(/\s+$/,"").replace(/( )?,( )?/g,",").split(",")}for(var i=0;i'}}var orderby="";if(setup.orderby!=""){var fieldsDir=setup.orderby.split(",");for(i=0;i0){if(splt.length==2){direction=splt[1].toUpperCase()}orderby+=(useOWS?'':'')}}}var groupby="";if(setup.groupby!=""){var gFields=setup.groupby.split(",");for(i=0;i'}}var body="";var aReturn=[];if(setup.queryOptions===undefined){setup._queryOptions=""+setup.dateInUTC+'True'+(fields===""?"":"False")+""+setup.expandUserField+"";if(setup.folderOptions){var viewAttr;switch(setup.folderOptions.show){case"FilesAndFolders_Recursive":viewAttr="RecursiveAll";break;case"FilesOnly_InFolder":viewAttr="FilesOnly";break;case"FilesAndFolders_InFolder":viewAttr="";break;case"FilesOnly_Recursive":default:viewAttr="Recursive"}setup._queryOptions+='';if(setup.folderOptions.path){setup.queryOptions+=""+this.url+this.listID+"/"+setup.folderOptions.path+""}}else{setup._queryOptions+=''}}else{setup._queryOptions=setup.queryOptions}var _this=this;if(useOWS){body=''+this.listID+""+setup.view+""+(setup.where!=""?""+(setup.whereCAML?setup.where:this.parse(setup.where))+"":"")+(groupby!=""?""+groupby+"":"")+(orderby!=""?""+orderby+"":"")+""+fields+""+setup.rowlimit+""+setup._queryOptions+"";var url=this.url+"/_vti_bin/Lists.asmx";jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var rows=data.getElementsByTagName("z:row");if(rows.length==0){rows=data.getElementsByTagName("row")}aReturn=fastMap(rows,function(row){return myElem(row)});if(setup.joinData){var on=setup.joinData.noindex;var aResult=[];var prevIndex="";var listIndexFound={length:0};if(!on.length){alert("$SP.get() -- Error 'get': you must define the ON clause with JOIN is used.")}for(var i=0,stop=aReturn.length;i0){for(var i=0,stop=aReturn.length;i0){if(setup.results.length===0){setup.results=aReturn}setup.where=setup.nextWhere.slice(0);_this.get(setup,fct)}else{if(typeof fct=="function"){setup.where=setup.originalWhere;fct.call(_this,(setup.results.length>0?setup.results:aReturn))}}}}},error:function(jqXHR,textStatus,errorThrown){var res=jqXHR.responseXML;var err=res.getElementsByTagName("errorstring");if(err&&err[0]){fct.call(_this,[],"Error: "+err[0].firstChild.nodeValue)}else{fct.call(_this,[],textStatus+": "+errorThrown)}}})}return this},createFile:function(setup){setup=setup||{};if(setup.content==undefined){throw"Error 'createFile': not able to find the file content."}if(setup.destination==undefined){throw"Error 'createFile': not able to find the file destination path."}setup.url=setup.url||this.url;if(!setup.url){this._getURL();return this._addInQueue(arguments)}if(setup.url==undefined){throw"Error 'createFile': not able to find the URL!"}setup.after=setup.after||(function(){});setup.encoded=(setup.encoded==undefined?false:setup.encoded);var _this=this;var soapEnv='http://null'+setup.destination+""+(setup.encoded?setup.content:encode_b64(setup.content))+"";jQuery.ajax({url:setup.url+"/_vti_bin/copy.asmx",type:"POST",dataType:"xml",data:soapEnv,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/CopyIntoItems")},contentType:'text/xml; charset="utf-8"',success:function(data){var a=data.getElementsByTagName("CopyResult");if(a&&a[0]&&a[0].getAttribute("ErrorCode")!="Success"){throw"Error 'createFile': "+a[0].getAttribute("ErrorCode")+" - "+a[0].getAttribute("ErrorMessage")}if(typeof setup.after=="function"){setup.after.call(_this)}}});return this},createFolder:function(setup){setup=setup||{};if(setup.path==undefined){throw"Error 'createFolder': please provide the 'path'."}if(setup.library==undefined){throw"Error 'createFolder': please provide the library name."}setup.url=setup.url||this.url;if(!setup.url){this._getURL();return this._addInQueue(arguments)}if(setup.url==undefined){throw"Error 'createFolder': not able to find the URL!"}setup.after=setup.after||(function(){});var path=setup.path.split("/"),toAdd=[],tmpPath="";for(var i=0;i0?"/":"")+path[i];toAdd.push({FSObjType:1,BaseName:tmpPath})}this.list(setup.library,setup.url).add(toAdd,{after:setup.after});return this},checkin:function(setup){setup=setup||{};if(setup.destination==undefined){throw"Error 'checkin': not able to find the file destination path."}setup.url=setup.url||this.url;if(!setup.url){this._getURL();return this._addInQueue(arguments)}if(this.url==undefined){throw"Error 'checkin': not able to find the URL!"}setup.url=this.url;setup.comments=setup.comments||"";setup.success=setup.success||(function(){});setup.error=setup.error||(function(){});setup.after=setup.after||(function(){});var _this=this;var soapEnv=''+setup.destination+""+setup.comments+"1";jQuery.ajax({url:setup.url+"/_vti_bin/Lists.asmx",type:"POST",dataType:"xml",data:soapEnv,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/CheckInFile")},contentType:"text/xml; charset=utf-8",success:function(data){var res=data.getElementsByTagName("CheckInFileResult");if(res&&res[0]&&res[0].firstChild.nodeValue!="true"){setup.error.call(_this)}else{setup.success.call(_this)}setup.after.call(_this)}})},getAttachment:function(itemID,fct,passed){if(this.needQueue){return this._addInQueue(arguments)}if(this.listID==undefined){throw"Error 'getAttachment': you have to define the list ID/Name"}if(arguments.length===1&&typeof itemID==="function"){throw"Error 'getAttachment': you have to define the item ID"}if(this.url==undefined){throw"Error 'getAttachment': not able to find the URL!"}if(typeof itemID!=="object"){itemID=itemID.split(",")}passed=passed||[];var body=' '+this.listID+" "+itemID.shift()+" ";var _this=this;var url=this.url+"/_vti_bin/lists.asmx";var aReturn=[];jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetAttachmentCollection")},dataType:"xml",success:function(data){var a=data.getElementsByTagName("Attachment");for(var i=0;i';body+=" ";body+=' ';body+=" "+this.listID+"";body+=" ";body+=" ";body+="";var _this=this;var url=this.url+"/_vti_bin/lists.asmx";var aReturn=[];jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetList")},dataType:"xml",success:function(data){var arr=data.getElementsByTagName("Field");var index=0,aIndex,attributes,attrName,lenDefault;for(var i=0;i0){nodeDefault=arr[i].getElementsByTagName("Default");aReturn[index]["DefaultValue"]=[];for(var q=0;q';body+=" ";body+=' ';body+=" "+this.listID+"";body+=" "+viewID+"";body+=" ";body+=" ";body+="";var url=this.url+"/_vti_bin/Views.asmx";var aReturn=["fields","orderby","whereCAML"];var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetView")},dataType:"xml",success:function(data){aReturn.fields=[];var arr=data.getElementsByTagName("ViewFields")[0].getElementsByTagName("FieldRef");for(var i=0;i]+>(.*)<\/Where>/);if(where.length==2){aReturn.whereCAML=where[1]}}savedView.push({url:_this.url,data:aReturn,viewID:viewID,viewName:viewName});jQuery("body").data("sp-view",savedView);if(typeof fct=="function"){fct.call(_this,aReturn,viewID)}}});return this},views:function(fct){if(this.needQueue){return this._addInQueue(arguments)}if(this.listID==undefined){throw"Error 'views': you have to define the list ID"}if(this.url==undefined){throw"Error 'views': not able to find the URL!"}fct=fct||function(){};var savedViews=jQuery("body").data("sp-views");if(savedViews!=undefined){for(var i=savedViews.length;i--;){if(savedViews[i].url==this.url){fct.call(this,savedViews[i].data);return this}}}else{savedViews=[]}var body='';body+='';body+=" ";body+=' ';body+=" "+this.listID+"";body+=" ";body+=" ";body+="";var url=this.url+"/_vti_bin/Views.asmx";var aReturn=[];var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetViewCollection")},dataType:"xml",success:function(data){var arr=data.getElementsByTagName("View");for(var i=0;i';body+=" ";body+=' ';body+=" ";body+=" ";body+="";var savedLists=jQuery("body").data("sp-lists");if(savedLists!=undefined){for(var i=savedLists.length;i--;){if(savedLists[i].url==this.url){if(typeof fct=="function"){fct(savedLists[i].data)}else{this.data=savedLists[i].data;this.length=this.data.length}return this}}}else{savedLists=[]}var url=this.url+"/_vti_bin/lists.asmx";var aReturn=[];var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,contentType:"text/xml; charset=utf-8",beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetListCollection")},dataType:"xml",success:function(data){var arr=data.getElementsByTagName("List");for(var i=0;i15){var nextPacket=items.slice(0);var cutted=nextPacket.splice(0,15);var _this=this;jQuery(document).on(setup.progressVar.eventID,function(event){jQuery(document).off(setup.progressVar.eventID);_this.add(nextPacket,event.setup)});this.add(cutted,setup);return this}else{if(itemsLength==0){setup.progress(1,1);setup.error([]);setup.success([]);setup.after();return this}}setup.progressVar.current+=itemsLength;var updates='';var _this=this;for(var i=0;i';updates+="New";jQuery.each(items[i],function(key,value){if(typeof value==="object"&&value.items!=undefined){value=";#"+value.join(";#")+";#"}if(setup.escapeChar&&typeof value==="string"){value=_this._cleanString(value)}updates+=""+value+""});updates+=""}updates+="";var body=''+this.listID+""+updates+"";var url=this.url+"/_vti_bin/lists.asmx";var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/UpdateListItems")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var result=data.getElementsByTagName("Result");var len=result.length;var passed=setup.progressVar.passed,failed=setup.progressVar.failed;for(var i=0;i0){setup.error.call(_this,failed)}if(passed.length>0){setup.success.call(_this,passed)}setup.after.call(_this)}}});return this},update:function(items,setup){if(this.needQueue){return this._addInQueue(arguments)}if(this.listID===undefined){throw"Error 'update': you need to use list() to define the list name."}setup=setup||{};if(this.url==undefined){throw"Error 'update': not able to find the URL!"}setup.where=setup.where||"";setup.success=setup.success||(function(){});setup.error=setup.error||(function(){});setup.after=setup.after||(function(){});setup.escapeChar=(setup.escapeChar==undefined)?true:setup.escapeChar;setup.progress=setup.progress||(function(){});if(typeof items==="object"&&items.length==undefined){items=[items]}var itemsLength=items.length;if(itemsLength==1&&setup.where){delete items[0].ID;var _this=this;this.get({fields:"ID",where:setup.where},function(data){var clone=function(obj){var newObj={};for(var k in obj){newObj[k]=obj[k]}return newObj};var aItems=[];for(var i=data.length;i--;){var it=clone(items[0]);it.ID=data[i].getAttribute("ID");aItems.push(it)}delete setup.where;_this.update(aItems,setup)});return this}setup.progressVar=setup.progressVar||{current:0,max:itemsLength,passed:[],failed:[],eventID:"spUpdate"+(""+Math.random()).slice(2)};if(itemsLength>15){var nextPacket=items.slice(0);var cutted=nextPacket.splice(0,15);var _this=this;jQuery(document).on(setup.progressVar.eventID,function(event){jQuery(document).off(setup.progressVar.eventID);_this.update(nextPacket,event.setup)});this.update(cutted,setup);return this}else{if(itemsLength==0){setup.progress(1,1);setup.error([]);setup.success([]);setup.after();return this}}setup.progressVar.current+=itemsLength;var updates='';var _this=this;for(var i=0;i';if(items[i].ID==undefined){throw"Error 'update': you have to provide the item ID called 'ID'"}jQuery.each(items[i],function(key,value){if(typeof value==="object"&&value.length!=undefined){value=";#"+value.join(";#")+";#"}if(setup.escapeChar&&typeof value==="string"){value=_this._cleanString(value)}updates+=""+value+""});updates+=""}updates+="";var body=''+this.listID+""+updates+"";var url=this.url+"/_vti_bin/lists.asmx";var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/UpdateListItems")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var result=data.getElementsByTagName("Result");var len=result.length;var passed=setup.progressVar.passed,failed=setup.progressVar.failed;for(var i=0;i0){setup.error.call(_this,failed)}if(passed.length>0){setup.success.call(_this,passed)}setup.after.call(_this)}}});return this},history:function(params,returnFct){if(this.needQueue){return this._addInQueue(arguments)}if(this.listID===undefined){throw"Error 'history': you need to use list() to define the list name."}if(arguments.length!==2){throw"Error 'history': you need to provide two parameters."}if(typeof params!=="object"){throw"Error 'history': the first parameter must be an object."}else{if(params.ID===undefined||params.Name===undefined){throw"Error 'history': the first parameter must be an object with ID and Name."}}if(typeof returnFct!=="function"){throw"Error 'history': the second parameter must be a function."}var body=''+this.listID+""+params.ID+""+params.Name+"";var url=this.url+"/_vti_bin/lists.asmx";var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/GetVersionCollection")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){returnFct.call(_this,data.getElementsByTagName("Version"))}});return this},moderate:function(items,setup){if(this.needQueue){return this._addInQueue(arguments)}if(arguments.length===0||(arguments.length===1&&typeof items==="object"&&items.length===undefined)){throw"Error 'moderate': you need to define the list of items"}if(this.listID===undefined){throw"Error 'moderate': you need to use list() to define the list name."}setup=setup||{};if(this.url==undefined){throw"Error 'moderate': not able to find the URL!"}setup.async=(setup.async==undefined)?true:setup.async;setup.success=setup.success||(function(){});setup.error=setup.error||(function(){});setup.after=setup.after||(function(){});setup.progress=setup.progress||(function(){});if(typeof items==="object"&&items.length==undefined){items=[items]}var itemsLength=items.length;setup.progressVar=setup.progressVar||{current:0,max:itemsLength,passed:[],failed:[],eventID:"spModerate"+(""+Math.random()).slice(2)};if(itemsLength>15){var nextPacket=items.slice(0);var cutted=nextPacket.splice(0,15);var _this=this;jQuery(document).on(setup.progressVar.eventID,function(event){jQuery(document).off(setup.progressVar.eventID);_this.moderate(nextPacket,event.setup)});this.moderate(cutted,setup);return this}else{if(itemsLength==0){setup.progress(1,1);setup.success([]);setup.error([]);setup.after();return this}}setup.progressVar.current+=itemsLength;var updates='';var thisObject=this;for(var i=0;i';if(items[i].ID==undefined){throw"Error 'moderate': you have to provide the item ID called 'ID'"}else{if(items[i].ApprovalStatus==undefined){throw"Error 'moderate': you have to provide the approval status 'ApprovalStatus' (Approved, Rejected, Pending, Draft or Scheduled)"}}jQuery.each(items[i],function(key,value){if(key=="ApprovalStatus"){key="_ModerationStatus";switch(value.toLowerCase()){case"approve":case"approved":value=0;break;case"reject":case"deny":case"denied":case"rejected":value=1;break;case"pending":value=2;break;case"draft":value=3;break;case"scheduled":value=4;break;default:value=2;break}}updates+=""+value+""});updates+=""}updates+="";var body=''+this.listID+""+updates+"";var url=this.url+"/_vti_bin/lists.asmx";var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/UpdateListItems")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var result=data.getElementsByTagName("Result");var len=result.length;var passed=setup.progressVar.passed,failed=setup.progressVar.failed;var rows;for(var i=0;i0){setup.success.call(_this,passed)}if(failed.length>0){setup.error.call(_this,failed)}setup.after.call(_this)}}});return this},remove:function(items,setup){if(this.needQueue){return this._addInQueue(arguments)}if(!setup&&items.where){setup=items;items=[]}setup=setup||{};if(this.url==undefined){throw"Error 'remove': not able to find the URL!"}setup.error=setup.error||(function(){});setup.success=setup.success||(function(){});setup.after=setup.after||(function(){});setup.progress=setup.progress||(function(){});if(typeof items==="object"&&items.length==undefined){items=[items]}var itemsLength=items.length;if(setup.where){if(itemsLength==1){delete items[0].ID}var _this=this;this.get({fields:"ID,FileRef",where:setup.where},function(data){var clone=function(obj){var newObj={};for(var k in obj){newObj[k]=obj[k]}return newObj};var aItems=[],fileRef;for(var i=data.length;i--;){var it=clone(items[0]);it.ID=data[i].getAttribute("ID");fileRef=data[i].getAttribute("FileRef");if(fileRef){it.FileRef=$SP().cleanResult(fileRef)}aItems.push(it)}delete setup.where;_this.remove(aItems,setup)});return this}else{if(itemsLength==0){setup.progress(1,1);setup.error.call(_this,[]);setup.success.call(_this,[]);setup.after.call(_this);return _this}}setup.progressVar=setup.progressVar||{current:0,max:itemsLength,passed:[],failed:[],eventID:"spRemove"+(""+Math.random()).slice(2)};if(itemsLength>15){var nextPacket=items.slice(0);var cutted=nextPacket.splice(0,15);var _this=this;jQuery(document).on(setup.progressVar.eventID,function(event){jQuery(document).off(setup.progressVar.eventID);_this.remove(nextPacket,event.setup)});this.remove(cutted,setup);return this}setup.progressVar.current+=itemsLength;var updates='';for(var i=0;i';if(items[i].ID==undefined){throw"Error 'delete': you have to provide the item ID called 'ID'"}updates+=""+items[i].ID+"";if(items[i].FileRef!=undefined){updates+=""+items[i].FileRef+""}updates+=""}updates+="";var body=''+this.listID+""+updates+"";var _this=this;var url=this.url+"/_vti_bin/lists.asmx";jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/UpdateListItems")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var result=data.getElementsByTagName("Result");var len=result.length;var passed=setup.progressVar.passed,failed=setup.progressVar.failed;for(var i=0;i0){setup.error.call(_this,failed)}if(passed.length>0){setup.success.call(_this,passed)}setup.after.call(_this)}}});return this},del:function(items,setup){return this.remove(items,setup)},usergroups:function(username,setup,fct){switch(arguments.length){case 1:if(typeof username==="object"){return this.usergroups("",username,function(){})}else{if(typeof username==="function"){return this.usergroups("",{},username)}}break;case 2:if(typeof username==="string"&&typeof setup==="function"){return this.usergroups(username,{},setup)}if(typeof username==="object"&&typeof setup==="function"){return this.usergroups("",username,setup)}}setup=setup||{};if(setup.url==undefined){if(!this.url){this._getURL();return this._addInQueue(arguments)}else{setup.url=this.url}}else{this.url=setup.url}fct=fct||(function(){});if(!username){throw"Error 'usergroups': you have to set an username."}username=username.toLowerCase();setup.url=setup.url.toLowerCase();var cache=jQuery("body").data("sp-usergroups")||[];for(var i=cache.length;i--;){if(cache[i].user.toLowerCase()==username&&cache[i].url.toLowerCase()==setup.url){fct.call(this,cache[i].data);return this}}var body=""+username+"";var _this=this;var url=setup.url+"/_vti_bin/usergroup.asmx";jQuery.ajax({type:"POST",cache:false,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/directory/GetGroupCollectionFromUser")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var aResult=[];data=data.getElementsByTagName("Group");for(var i=0,len=data.length;i";var _this=this;jQuery.ajax({type:"POST",cache:false,async:true,url:this.url+"/_vti_bin/Workflow.asmx",data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/workflow/GetWorkflowDataForItem")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var rows=data.getElementsByTagName("WorkflowTemplate");if(rows.length===0){throw"Error 'getWorkflowID': No workflow found for this item"}for(var i=rows.length;i--;){if(rows[i].getAttribute("Name")==setup.workflowName){setup.after.call(_this,{fileRef:fileRef,workflowID:"{"+rows[i].getElementsByTagName("WorkflowTemplateIdSet")[0].getAttribute("TemplateId")+"}"});return _this}}setup.after.call(_this,"Error 'getWorkflowID': impossible to find this workflow name!")},error:function(jqXHR,textStatus,errorThrown){throw"Error 'getWorkflowID': Something went wrong with the request over the Workflow Web Service..."}})});return this},startWorkflow:function(setup){if(this.needQueue){return this._addInQueue(arguments)}if(this.listID==undefined){throw"Error 'startWorkflow': you have to define the list ID/Name"}if(this.url==undefined){throw"Error 'startWorkflow': not able to find the URL!"}setup=setup||{};setup.after=setup.after||(function(){});if(!setup.workflowName&&!setup.workflowID){throw"Error 'startWorkflow': Please provide the workflow name!"}if(!setup.ID){throw"Error 'startWorkflow': Please provide the item ID!"}if(!setup.fileRef&&!setup.workflowID){this.getWorkflowID({ID:setup.ID,workflowName:setup.workflowName,after:function(params){setup.fileRef=params.fileRef;setup.workflowID=params.workflowID;this.startWorkflow(setup)}})}else{var workflowParameters="";if(setup.parameters){var p;if(setup.parameters.length==undefined){setup.parameters=[setup.parameters]}p=setup.parameters.slice(0);workflowParameters="";for(var i=0;i"+p[i].value+""+p[i].name+">"}workflowParameters+=""}var body='- '+setup.fileRef+"
"+setup.workflowID+""+workflowParameters+"";var _this=this;var url=this.url+"/_vti_bin/Workflow.asmx";jQuery.ajax({type:"POST",cache:false,async:true,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/workflow/StartWorkflow")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){setup.after.call(_this)},error:function(jqXHR,textStatus,errorThrown){setup.after.call(_this)}})}return this},distributionLists:function(username,setup,fct){switch(arguments.length){case 1:if(typeof username==="object"){return this.distributionLists("",username,function(){})}else{if(typeof username==="function"){return this.distributionLists("",{},username)}}break;case 2:if(typeof username==="string"&&typeof setup==="function"){return this.distributionLists(username,{},setup)}if(typeof username==="object"&&typeof setup==="function"){return this.distributionLists("",username,setup)}}setup=setup||{};if(setup.url==undefined){if(!this.url){this._getURL();return this._addInQueue(arguments)}else{setup.url=this.url}}else{this.url=setup.url}fct=fct||(function(){});if(!username){throw"Error 'distributionLists': you have to set an username."}username=username.toLowerCase();setup.url=setup.url.toLowerCase();var cache=jQuery("body").data("sp-distributionLists")||[];for(var i=cache.length;i--;){if(cache[i].user===username&&cache[i].url===setup.url){fct.call(this,cache[i].data);return this}}var body=""+username+"";var _this=this;var url=setup.url+"/_vti_bin/UserProfileService.asmx";jQuery.ajax({type:"POST",cache:false,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://microsoft.com/webservices/SharePointPortalServer/UserProfileService/GetUserMemberships")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var aResult=[];data=data.getElementsByTagName("MembershipData");for(var i=0,len=data.length;i";var _this=this;var url=setup.url+"/_vti_bin/usergroup.asmx";jQuery.ajax({type:"POST",cache:false,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/directory/GetUserCollectionFromGroup")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var aResult=[];data=data.getElementsByTagName("User");for(var i=0,len=data.length;i-1){fct.call(this,true);return this}}fct.call(this,false);return this})})});return this},people:function(username,setup,fct){switch(arguments.length){case 1:if(typeof username==="object"){return this.people("",username,function(){})}else{if(typeof username==="function"){return this.people("",{},username)}}username=undefined;break;case 2:if(typeof username==="string"&&typeof setup==="function"){return this.people(username,{},setup)}if(typeof username==="object"&&typeof setup==="function"){return this.people("",username,setup)}}setup=setup||{};if(setup.url==undefined){if(!this.url){this._getURL();return this._addInQueue(arguments)}else{setup.url=this.url}}else{this.url=setup.url}fct=fct||(function(){});username=username||"";var body=""+username+"";var _this=this;var url=setup.url+"/_vti_bin/UserProfileService.asmx";jQuery.ajax({type:"POST",cache:false,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://microsoft.com/webservices/SharePointPortalServer/UserProfileService/GetUserProfileByName")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var aResult=[];data=data.getElementsByTagName("PropertyData");for(var i=0,len=data.length;i=1){value=value[0].firstChild.nodeValue}else{value="No Value"}aResult.push(name);aResult[name]=value}fct.call(_this,aResult)},error:function(req,textStatus,errorThrown){var error=req.responseXML.getElementsByTagName("faultstring");fct.call(_this,"Error 'people': "+error[0].firstChild.nodeValue)}});return this},whoami:function(setup,fct){if(typeof setup==="function"){fct=setup;setup={}}return this.people("",setup,fct)},addressbook:function(username,setup,fct){switch(arguments.length){case 1:if(typeof username==="object"){return this.addressbook("",username,function(){})}else{if(typeof username==="function"){return this.addressbook("",{},username)}}username=undefined;break;case 2:if(typeof username==="string"&&typeof setup==="function"){return this.addressbook(username,{},setup)}if(typeof username==="object"&&typeof setup==="function"){return this.addressbook("",username,setup)}}setup=setup||{};if(setup.url==undefined){if(!this.url){this._getURL();return this._addInQueue(arguments)}else{setup.url=this.url}}else{this.url=setup.url}setup.limit=setup.limit||10;setup.type=setup.type||"User";fct=fct||(function(){});username=username||"";var body=""+username+""+setup.limit+""+setup.type+"";var _this=this;var url=setup.url+"/_vti_bin/People.asmx";jQuery.ajax({type:"POST",cache:false,url:url,data:body,beforeSend:function(xhr){xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/SearchPrincipals")},contentType:"text/xml; charset=utf-8",dataType:"xml",success:function(data){var aResult=[];data=data.getElementsByTagName("PrincipalInfo");for(var i=0,lenR=data.length;i-1?new Date(Date.UTC(year,month-1,day,hour,min,sec)):new Date(year,month-1,day,hour,min,sec))},toSPDate:function(oDate){var pad=function(p_str){if(p_str.toString().length==1){p_str="0"+p_str}return p_str};var month=pad(oDate.getMonth()+1);var day=pad(oDate.getDate());var year=oDate.getFullYear();var hours=pad(oDate.getHours());var minutes=pad(oDate.getMinutes());var seconds=pad(oDate.getSeconds());return year+"-"+month+"-"+day+" "+hours+":"+minutes+":"+seconds},toCurrency:function(n,dec,sign){n=Number(n);if(dec===undefined){dec=-1}if(sign===undefined){sign="$"}var m="";if(n<0){m="-";n*=-1}var s=n;if(dec===-1){s=s.toFixed(2).replace(".00","")}else{s=s.toFixed(dec)}var digits=(Math.floor(n)+"").length;for(var i=0,j=0,mod=digits%3;i=16){temp=num%16;num=Math.floor(num/16);hexString+=hexVals[temp]}hexString+=hexVals[num];var tmpStr="";for(var k=hexString.length-1;k>=0;k--){tmpStr+=hexString.charAt(k)}rstr+="%"+tmpStr}return rstr};var aSpaces=str.split(" ");var ret="";if(/^[0-9]/.test(aSpaces[0])&&aSpaces[0].length<5){ret=FullEscape(str.charAt(0));str=str.substring(1)}for(var i=0;i0?fields.length:bigLimit);if(limit===bigLimit&&!settings.mandatory){settings.includeAll=true}if(_SP_CACHE_FORMFIELDS!==null){var allFields=_SP_CACHE_FORMFIELDS.slice(0);if(settings.includeAll){this.length=allFields.length;this.data=allFields;return this}var done=0,i,len=allFields.length,idx;var fieldNames=[];for(i=0;i-1){aReturn.push(allFields[idx])}}for(i=0,len=(settings.mandatory?allFields.length:0);i-1){table=a[i];break}}}else{table=document.querySelector("table.ms-formtable")}if(!table){throw"Error: unable to find the table.ms-formtable!"}var closestTR=function(nobr){var tr=nobr;do{tr=tr.parentNode}while(tr.tagName.toLowerCase()!=="tr");return tr};var getText=function(elem){var i,node,nodeType=elem.nodeType,ret="";if(nodeType){if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent}else{if(typeof elem.innerText==="string"){return elem.innerText.replace(/\r/g,"")}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem)}}}}else{if(nodeType===3||nodeType===4){return elem.nodeValue}}}else{for(i=0;(node=elem[i]);i++){if(node.nodeType!==8){ret+=getText(node)}}}return ret};if(settings.includeAll){limit=bigLimit}for(var a=table.getElementsByTagName("nobr"),i=-1,len=a.length,done=0;i-1){txt=html="Content Type";includeThisField=true}}else{tr=undefined;nobr=a[i];html=nobr.innerHTML;txt=getText(nobr);if(html.indexOf("ms-formvalidation")>-1){html=html.slice(0,-39);if(html.charAt(html.length-2)=="<"&&(html.charAt(html.length-1)=="s"||html.charAt(html.length-1)=="S")){html=html.slice(0,-2)}if(settings.mandatory){includeThisField=true}txt=txt.slice(0,-2);isMandatory=true}if(limit!==bigLimit){for(var k=0,lenk=limit;k-1){for(var b=document.getElementsByTagName("select"),bb=0;bb-1||input[inp].className.indexOf("ms-long")>-1){elem.push(input[inp]);if(!obj._type){obj._type="text"}if(input[inp].id.search(/DateTimeFieldDate$/)>-1){continueToSearch=true;obj._type="date"}else{if(input[inp].id.search(/_UrlFieldUrl$|_UrlFieldDescription$/)>-1){obj._type="url";elem.pop();elem.push(input[inp].previousSibling.previousSibling);elem.push(input[inp])}else{inp=input.length}}}else{if(input[inp].title.indexOf("Specify your own value:")>-1){elem.push(input[inp]);if(obj._type.slice(0,7)==="choices"){obj._type+=" plus"}}}break;case"radio":if(input[inp].id.search(/_DropDownButton$/)>-1){obj._type="choices plus";do{elem.push(input[inp]);if(!inp){elem.push("")}}while(++inp-1){obj._type="boolean"}else{obj._type="choices checkbox"}if(obj._type!=="boolean"){elem.push(input[inp].nextSibling)}break}}}if(elem.length===0||continueToSearch){var select=td.getElementsByTagName("select");for(inp=0;inp-1||select[inp].id.search(/_cbRate$|_Lookup$|_SelectResult$|_SelectCandidate$|_DateTimeFieldDateHours$|_DateTimeFieldDateMinutes$/)>-1){if(select[inp].id.search(/_SelectCandidate$|_SelectResult$|_DateTimeFieldDateHours$|_DateTimeFieldDateMinutes$/)>-1){if(select[inp].id.indexOf("DateTimeField")>-1){obj._type="date time"}elem.push(select[inp]);if(select[inp].id.indexOf("_SelectCandidate")>-1){var buttons=td.getElementsByTagName("button");if(buttons.length===2){elem.push(buttons[0]);elem.push(buttons[1]);obj._type="lookup multiple"}}}else{if(continueToSearch){if(obj._type==="choices plus"){elem[1]=select[inp]}else{elem.push(select[inp])}}else{elem.push(select[inp]);if(select[inp].id.search(/_Lookup$/)>-1){obj._type="lookup"}else{if(!obj._type){obj._type="choices"}}}break}}}}if(elem.length===0){var other=td.getElementsByTagName("div");for(inp=0;inp-1){elem.push(other[inp]);obj._type="people";break}}other=td.getElementsByTagName("textarea");for(inp=0;inp-1||other[inp].className.indexOf("ms-input")>-1){elem.push(other[inp]);if(!obj._type){obj._type="text multiple"}else{if(obj._type==="people"){other=td.getElementsByTagName("a");for(inp=0;inp-1){elem=td.getElementsByTagName("iframe")}else{other=td.getElementsByTagName("span");for(inp=other.length;inp--;){if(other[inp].className.indexOf("ms-formdescription")>-1){elem.push(other[inp]);break}}break}}}}if(td.nextSibling){var descro=td.nextSibling;if(descro.nodeType==3){obj._description=getText(descro).trim()}}}}obj._elements=elem;switch(obj.type()){case"attachments":obj.val=function(v){if(v){alert("$SP.formfields Error: You cannot define a value for the Attachments")}else{var elem=this.elem();var ret=[];for(v=0;v]+)>)/ig,"").replace(/^\s+|\s+$| /g,"").replace(/
| /g,"").replace(/;$/,"").split(";");var ret=[];for(var x=0;x-1){e[i-1].checked=true;done.push(e[i].innerHTML);if(type.slice(0,13)==="choices radio"){return this}}else{if(v!==undefined&&e[i].tagName.toLowerCase()==="label"){e[i-1].checked=false}else{if(v===undefined&&e[i].checked){if(type==="choices radio plus"){if(e[i+1].innerHTML==="Specify your own value:"){return e[i+2].value}return e[i+1].innerHTML}else{ret.push(e[i+1].innerHTML==="Specify your own value:"?e[i+2].value:e[i+1].innerHTML)}}}}}if(v===undefined){return ret}if(v!==undefined){if(type==="choices radio plus"){e[e.length-3].checked=true;e[e.length-1].value=v}else{if(type==="choices checkbox plus"){var rest=[];for(var i=v.length;i--;){if(done.indexOf(v[i])===-1){rest.push(v[i])}}if(rest.length>0){e[e.length-3].checked=true;e[e.length-1].value=rest.join(" ")}}}return this}};obj.options=function(){var e=this.elem();var ret=[];var type=this.type().slice(-4);for(var i=0;i1){if(str.length!==this.length){throw new Error("$SP.formfields.val: the array passed for val() must have the same size as the number of fields in formfields()")}this.each(function(){this.val(str[i++])})}else{this.each(function(){this.val(str)})}}}return this},elem:function(){var aReturn=[];var hasJQuery=(typeof jQuery==="function");this.each(function(){var e=this.elem();aReturn.push(e.length===1?e[0]:e)});switch(aReturn.length){case 0:return hasJQuery?jQuery():null;case 1:return hasJQuery?jQuery(aReturn[0]):aReturn[0];default:return hasJQuery?jQuery(aReturn):aReturn}},row:function(){var aReturn=[];var hasJQuery=(typeof jQuery==="function");this.each(function(){aReturn.push(this.row())});switch(aReturn.length){case 0:return null;case 1:return(hasJQuery?jQuery(aReturn[0]):aReturn[0]);default:return(hasJQuery?jQuery(aReturn):aReturn)}},type:function(){var aReturn=[];this.each(function(){aReturn.push(this.type())});switch(aReturn.length){case 0:return"";case 1:return aReturn[0];default:return aReturn}},description:function(){var aReturn=[];this.each(function(){aReturn.push(this.description())});switch(aReturn.length){case 0:return"";case 1:return aReturn[0];default:return aReturn}},registerPlugin:function(name,fct){var $html=$("html");var plugins=$html.data("sp-plugins")||[];if(typeof plugins[name]!=="undefined"){throw"Error 'registerPlugin': '"+name+"' is already registered."}plugins[name]=fct;$html.data("sp-plugins",plugins);return true},plugin:function(name,options){var plugins=$("html").data("sp-plugins")||[];options=options||{};if(typeof plugins[name]==="function"){plugins[name].call(this,options)}else{throw"Error $SP().plugin: the plugin '"+name+"' is not registered."}return this}};var myElem=(function(){var myElem=function(elem){return new MyElemConstruct(elem)},MyElemConstruct=function(elem){this.mynode=elem;this.singleList=true;return this};myElem.fn=MyElemConstruct.prototype={getAttribute:function(id){return this.mynode.getAttribute("ows_"+id.replace(/ /g,""))},getAttributes:function(){return this.mynode.attributes}};return myElem})();var extendMyObject=function(arr){this.attributes=arr};extendMyObject.prototype.getAttribute=function(attr){return this.attributes[attr]};extendMyObject.prototype.getAttributes=function(){return this.attributes};SharepointPlus.prototype.noConflict=function(){window._$SP=window._SharepointPlus=window.$SP};return window.$SP=window.SharepointPlus=SharepointPlus})(window);
\ No newline at end of file