diff --git a/.gitignore b/.gitignore
index 58bcbf8..0a70862 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,32 +1,33 @@
-# Windows image file caches
-Thumbs.db
-ehthumbs.db
-
-# Folder config file
-Desktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msm
-*.msp
-
-# =========================
-# Operating System Files
-# =========================
-
-# OSX
-# =========================
-
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# =========================
+# Operating System Files
+# =========================
+
+# OSX
+# =========================
+
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
-Icon
+Icon
+
# Thumbnails
._*
@@ -41,3 +42,6 @@ Icon
Network Trash Folder
Temporary Items
.apdisk
+
+#nodemodules
+node_modules
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6160d82
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+ - "4.1"
+ - "4.0"
+ - "0.12"
+ - "0.11"
+ - "0.10"
+ - "iojs"
\ No newline at end of file
diff --git a/README.md b/README.md
index e56cf0f..b216400 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# o.js
-*o.js beta v0.1.1*
+*o.js beta v0.2.0*
-o.js is a client side Odata Javascript library to simplify the request of data. The main goal is to build a **standalone, lightweight and easy** to understand Odata lib.
+o.js is a client side Odata Javascript library to simplify the request of data. The main goal is to build a **standalone, lightweight and easy** to understand Odata lib.
## Install ##
------------
@@ -11,9 +11,16 @@ Download the *o.js* or *o.min.js* file or install it via *bower* and add the scr
bower install o.js
```
+You can use o.js in node.js as well:
+```
+ npm install o.js
+
+ //var o = require('o.js');
+```
+
## Samples ##
------------
-For alle samples we are using the test odata service from Odata.org. You can find the metadata of this service here.
+For alle samples we are using the test odata service from Odata.org. You can find the metadata of this service here.
### Simple Odata query with o.js ###
----------------------
@@ -21,7 +28,7 @@ For alle samples we are using the test odata service from See this demonstration for more examples.
-
+Instead of manual getting your data with the `get()` function, this routing function always returns the data when somebody navigates to an URL with the hash value `index.html#Product/Detail/1/Some more parameter`. The `find()` method automatically maps the right parameter (in this example *1*). See this demonstration for more examples.
+
### Get data (details) ###
--------
-If you want to get data you need to call the `get()` function. This functions returns an async callback function which holds an array as it's parameter. If you use `first()` or the `find()` method it only returns the data because an array is not needed.
+If you want to get data you need to call the `get()` function. This functions returns an async callback function which holds an array as it's parameter. If you use `first()` or the `find()` method it only returns the data because an array is not needed.
You can also save your o-function to call it later:
```js
var oHandler=o('http://services.odata.org/V4/OData/OData.svc/Products');
@@ -60,7 +67,7 @@ oHandler.get(function(data) {
//or the saved var also contains the data:
console.log(oHandler.data);
});
-```
+```
If you need to get several data you can use promise. Currently o.js only suports [q.js](https://github.com/kriskowal/q). The following example show how you can get the data of two differend resources:
```js
@@ -81,7 +88,7 @@ o('http://services.odata.org/V4/OData/OData.svc/Products(2)').get().then(functio
}).fail(function(ex) {
console.log(ex);
}
-```
+```
## Add and change data ##
---------
@@ -94,34 +101,34 @@ You can use the `post()` function in combination with the `save()` method to add
o('http://services.odata.org/V4/OData/OData.svc/Products').post({Name:'Example 1',Description:'a'}).post({Name:'Example 2',Description:'b'}).save(function(data) {
console.log("Two Products added");
}
-````
+````
### Patch/Put: ###
---------
Changing (PATCH or PUT) data is nearly the same:
```js
o('http://services.odata.org/V4/OData/OData.svc/Products(1)').patch({Name:'NewName'}).save(function(data) {
- console.log("Product Name changed");
+ console.log("Product Name changed");
});
-````
+````
### Delete: ###
---------
To remove (DELETE) data you need to call `remove()`:
```js
o('http://services.odata.org/V4/OData/OData.svc/Products(1)').remove().save(function(data) {
- console.log("Product deleted");
+ console.log("Product deleted");
});
-````
+````
### Reference: ###
---------
To add an reference to an other resource use `ref` (to remove it simply use `removeRef` the same way):
```js
o('http://services.odata.org/V4/OData/OData.svc/Products(1)').ref('Categories', 2).save(function(data) {
- console.log("Product(1) associated with Categories(2)");
+ console.log("Product(1) associated with Categories(2)");
});
-````
+````
You can also combine a single data request (`first()` or `find()`) with the save method and chain it:
```js
@@ -133,7 +140,7 @@ o('http://services.odata.org/V4/OData/OData.svc/Products').find(2).get().then(fu
}).fail(function(ex) {
console.log("error");
});
-```
+```
### Endpoint configuration ###
---------
@@ -143,7 +150,7 @@ You can configure a endpoint with the `o().config()` function. This config is pe
o().config({
endpoint:'http://services.odata.org/V4/OData/OData.svc'
});
-
+
// after you have set an endpoint, you can shorten your queries:
o('Products').get(function(data) {
//same result like the first exmple on this page
@@ -165,7 +172,7 @@ However, if you have set an endpoint you can still do a full endpoint request fo
password:null, // a basic auth password
isAsync:true //set this to false to make synced (a)jax calls. (dosn't work with basic auth!)
});
-```
+```
### Full list of supported functions ###
---------
@@ -173,39 +180,39 @@ However, if you have set an endpoint you can still do a full endpoint request fo
Currently the following queries are supported:
`.find(int)` - returns the object with the given id. (Odata: Products*(1)*)
-
+
`.top(int)` - returns the top x objects (Odata: Products/?*$top=2*) - Synonym: `.take`
-
+
`.skip(int)` - returns the objects skipped by the given value (Odata: Products/?*$skip=2*)
-
+
`.first()` - returns the first object which is found (Odata: Products/?*$top=1*)
-
+
`.filter(string)` - adds a filter string (o.js can convered simple JS-Syntax. If you need something complex use the plain Odata $filter syntax: [see the Odata doc](http://www.odata.org/documentation/odata-version-3-0/url-conventions/) for more information) (Odata: Products/?*$filter=Name eq 'Example'*) - Synonym: `.where`
-
+
`.any(string, string)` - applies an any filter to an resource (Odata: Products/?*$filter=Categories/any(x:x/Name eq 'Test')*)
-
+
`.search(array, string)` - builds up a search $filter. The first parameter defines the columns to search in the second the searchword (e.g.: `.search(['Name', 'Description'], 'Test')`)
-
+
`.orderBy(string)` - orders the data (Odata: Products/?*$orderBy=Name*)
-
+
`.orderByDesc(string)` - orders the data descading (Odata: Products/?*$orderBy=Name*)
-
+
`.count()` - only counts the result (Odata: Products/*$count*)
-
+
`.inlineCount(string)` - adds a inlinecount to the result. (Odata: Products/?*$count=true*)
-
+
`.batch(string)` - adds a second resource to the request (Odata: $batch)
-
+
`.expand(string)` - expands a related resource (Odata: Products/?*$expand=ProductUnit*)
-
+
`.ref(string, string)` - expands a related resource (Odata: Products/*$ref=Categories(1)*)
-
+
`.deleteRef(string, string)` - expands a related resource (Odata: Products/*$ref=Categories(1)*)
-
+
`.post(object)` - Post data to an endpoint
-
+
`.patch(object)` - PATCH data on an endpoint
-
+
`.put(object)` - PUT data on an endpoint
-
+
`.remove(object)` - DELETE data on an endpoint (You must define only one resource: e.g: Products(1) )
diff --git a/example/app.js b/example/app.js
index a59f3c0..8450b2f 100644
--- a/example/app.js
+++ b/example/app.js
@@ -3,14 +3,14 @@
//
// An example for o.js.
//
-// By Jan Hommes
+// By Jan Hommes
// Date: 15.06.2015
// +++
//knockout view model
function ViewModel() {
var self=this;
-
+
//ko observables
self.People=ko.observableArray([]);
//self.currentPeople=ko.observable(null);
@@ -19,7 +19,7 @@ function ViewModel() {
self.total=ko.observable(0);
self.detailPeople=ko.observable();
self.isLoading=ko.observable(false);
-
+
self.remove = function(d) {
o('People(\'' + self.detailPeople().UserName + '\')/Trips(' + d.TripId + ')').remove().save(function() {
o('People(\'' + self.detailPeople().UserName + '\')').expand('Trips').get(function(d) {
@@ -27,7 +27,7 @@ function ViewModel() {
});
});
}
-
+
//o.js init
o().config({
endpoint:'http://services.odata.org/V4/%28S%28wptr35qf3bz4kb5oatn432ul%29%29/TripPinServiceRW/',
@@ -40,8 +40,8 @@ function ViewModel() {
self.isLoading(false);
}
});
-
-
+
+
//+++ initialize the routes +++
//get top 3 People on start TODO: At filter for best selling!
@@ -49,28 +49,26 @@ function ViewModel() {
self.route('Home');
self.People(data);
}).triggerRoute(window.location.hash === '' ? '#Home' : window.location.hash);
-
+
//get a People list on People click
- o('People').take(9).inlineCount().route('People',function(data) {
+ o('People').take(9).inlineCount().route('People', function(data) {
self.route('People');
self.People(data);
self.skip(0);
self.total(this.inlinecount);
});
-
+
//People pagination
- o('People').skip(':0').take(9).inlineCount().route('People/Page/:0',function(data) {
- console.log(this.param);
+ o('People').skip(':0').take(9).inlineCount().route('People/Page/:0', function(data) {
self.skip(parseInt(this.param[0]));
self.route('People');
self.People(data);
self.total(this.inlinecount);
});
-
+
//People detail
- o('People').filter('UserName == \':0\'').expand('Trips').first().route('People/Detail/:0',function(data) {
+ o('People').filter('UserName == \':0\'').expand('Trips').first().route('People/Detail/:0', function(data) {
self.route('Detail');
- console.log(data);
self.detailPeople(data);
});
}
diff --git a/o.js b/o.js
index 17aeeaf..3b36bf7 100644
--- a/o.js
+++ b/o.js
@@ -1,24 +1,24 @@
// +++
-// o.js v0.1b
+// o.js v0.2.0
//
// o.js is a simple oData wrapper for JavaScript.
-// Currently supporting the following operations:
+// Currently supporting the following operations:
// .get() / .post() / .put() / .delete() / .first() / .take() / .skip() / .filter() / .orderBy() / .orderByDesc() / .count() /.search() / .select() / .any() / .ref() / .deleteRef()
//
-// By Jan Hommes
-// Date: 25.06.2015
+// By Jan Hommes
+// Date: 13.01.2016
// --------------------
// The MIT License (MIT)
//
-// Copyright (c) 2015 Jan Hommes
-//
+// Copyright (c) 2016 Jan Hommes
+//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
@@ -30,9 +30,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// +++
-
function o(res) {
- base = this;
+ var base = this;
//base config object
base.oConfig = base.oConfig || {
@@ -107,7 +106,7 @@ function o(res) {
function oData(res, config) {
- base = this;
+ var base = this;
// --------------------+++ VARIABLES +++---------------------------
@@ -141,7 +140,7 @@ function oData(res, config) {
};
- //base external variables
+ //base external variables
base.data = []; //holds the data after an callback
base.inlinecount = null; //if inlinecount is set, here the counting is gold
base.param = {}; //this object holds all parameter for a route
@@ -160,6 +159,11 @@ function oData(res, config) {
routes = [routes];
}
+ // check support
+ if(typeof window === 'undefined') {
+ throwEx('Routes are only supported in a browser env.');
+ }
+
var prevHash = window.location.hash;
//literate over every rout and add a interval to check if the route is triggered
@@ -421,18 +425,20 @@ function oData(res, config) {
// TODO: maybe add some pseudonyms...
// +++
base.get = function (callback, errorCallback) {
+ // init the q -> if node require a node promise -> if ES6, try ES6 promise
+ var promise = initPromise();
+ currentPromise = promise.defer();
+
//start the request
- if (typeof Q !== 'undefined')
- currentPromise = Q.defer();
startRequest(callback, errorCallback, false);
- if (typeof Q !== 'undefined')
+ if (typeof promise !== 'undefined')
return (currentPromise.promise);
else
return (base);
}
// +++
- // adds a dataset to the current selected resource
+ // adds a dataset to the current selected resource
// if o("Product/ProductGroup").post(...) will post a dataset to the Product resource
// +++
base.save = function (callback, errorCallback) {
@@ -446,9 +452,11 @@ function oData(res, config) {
addNewResource(newResource);
}
+ var promise = initPromise();
+
//start the request with promise
- if (currentPromise || typeof callback === 'undefined') {
- currentPromise = Q.defer();
+ if (promise && typeof callback === 'undefined') {
+ currentPromise = promise.defer();
startRequest(callback, errorCallback, true);
return (currentPromise.promise);
}
@@ -460,7 +468,7 @@ function oData(res, config) {
}
// +++
- // adds a dataset to the current selected resource
+ // adds a dataset to the current selected resource
// o("Product/ProductGroup").post(...) will post a dataset to the Product resource
// alternative you can define a new resource by using .post({data},'OtherResource');
// +++
@@ -493,7 +501,7 @@ function oData(res, config) {
if (res) {
addNewResource(res);
}
-
+
if (!resource.path[resource.path.length-1] || !resource.path[resource.path.length-1].get)
throwEx('Bulk updates are not supported. You need to query a unique resource with find() to patch/put it.');
@@ -523,7 +531,7 @@ function oData(res, config) {
}
// +++
- // Returns the current query
+ // Returns the current query
// +++
base.query = function (overrideRes) {
return (buildQuery(overrideRes));
@@ -570,7 +578,7 @@ function oData(res, config) {
}
return (base);
}
-
+
// +++
// Set this value to add a progress handler to the current resource
// +++
@@ -583,6 +591,22 @@ function oData(res, config) {
// ---------------------+++ INTERNALS +++----------------------------
+ // +++
+ // initialize a promise callback
+ // +++
+ function initPromise() {
+ if (typeof Q !== 'undefined') {
+ var p = Q;
+ return(p);
+ }
+ else if(typeof window === 'undefined') {
+ var p = require('q');
+ return(p);
+ }
+ else {
+ return(null);
+ }
+ }
// +++
// builds a filter by a given data object to include or exclude values on a query
@@ -604,8 +628,7 @@ function oData(res, config) {
// builds a search filter
// ++++
function buildSearchFilter(searchColumns, searchWord, searchFunc) {
- var searchStr = "";
- var searchFunc = searchFunc || (oConfig.version == 4 ? 'contains' : 'substringof');
+ searchFunc = searchFunc || (oConfig.version == 4 ? 'contains' : 'substringof');
var searchWordSplit = searchWord.split(' ');
var isNotExactSearch = (searchFunc === 'contains' || searchFunc === 'substringof');
@@ -668,7 +691,7 @@ function oData(res, config) {
// +++
function getQuery() {
var tempStr = '';
-
+
for (queryName in resource.query) {
if (resource.query.hasOwnProperty(queryName) && resource.query[queryName] != null) {
tempStr += '&' + resource.queryList[resource.query[queryName]].name + '=' + strFormat(resource.queryList[resource.query[queryName]].value, internalParam);
@@ -802,7 +825,7 @@ function oData(res, config) {
if (!isQuery('$format')) {
addQuery('$format', base.oConfig.format);
}
-
+
//appendings
for(var i=0;i use base.queryArray
+ query: {}, //the query Array --> use base.queryArray
queryList: [],
method: 'GET',
data: null,
@@ -955,7 +980,7 @@ function oData(res, config) {
}
else {
var index = uriSplit[i].split('(');
- if (index.length === 1) {
+ if (index.length === 1 || startsWith(uriSplit[i], '(')) {
reqObj.path.push({ 'resource': uriSplit[i], 'get': null });
}
else {
@@ -999,7 +1024,7 @@ function oData(res, config) {
// +++
// internal function to check if a query exist. Otherwith throwEx a exception
// queries: Could be an array or an string
- // returns true if
+ // returns true if
// +++
function isQueryThrowEx(queries) {
if (isQuery(queries)) {
@@ -1185,15 +1210,15 @@ function oData(res, config) {
//do POST if the base.save() function was called
//TODO: || res.method==='PUT' || res.method==='DELETE'
else if ((res.method === 'POST' || res.method === 'PUT' || res.method === 'PATCH' || res.method === 'DELETE') && isSave) {
- var stringData = stringify(res.data);
+ //var stringData = stringify(res.data);
body += '--changeset_' + changsetGuid + '\n';
body += 'Content-Type: application/http\n';
body += 'Content-Transfer-Encoding: binary\n';
- body += 'Content-ID:' + i + 1 + '\n\n'; //This ID can be referenced $1/Customer
+ body += 'Content-ID:' + i + 1 + '\n\n'; //This ID can be referenced $1/Customer
body += res.method + ' ' + buildQuery(res) + ' HTTP/1.1\n';
body += 'Host: ' + base.oConfig.endpoint + '\n';
body += 'Content-Type: application/json\n';
- body += 'Content-Length:' + stringData.length + '\n\n';
+ //body += 'Content-Length:' + stringData.length + '\n\n';
body += stringify(resource.data) + '\n\n\n';
isChangeset = true;
}
@@ -1209,7 +1234,7 @@ function oData(res, config) {
// start a ajax request. data should be null if nothing to send
// +++
function startAjaxReq(ajaxRequest, data, callback, errorCallback, isBatch, headers, param, progress) {
-
+
//if start loading function is set call it
if (base.oConfig.start && overideLoading == null) {
base.oConfig.openAjaxRequests++;
@@ -1238,7 +1263,7 @@ function oData(res, config) {
else if(typeof progress === 'function') {
ajaxRequest.onprogress = progress;
}
-
+
ajaxRequest.onreadystatechange = function () {
//check the http status
if (ajaxRequest.readyState === 4) {
@@ -1261,9 +1286,9 @@ function oData(res, config) {
parseResponse(result[0].substring(0, result[0].length-16), tempBase);
dataArray.push(tempBase.data);
}
-
+
} while (result);
-
+
tempBase.data = dataArray;
}
}
@@ -1318,7 +1343,7 @@ function oData(res, config) {
ajaxRequest.setRequestHeader('Authorization', 'Basic ' + encodeBase64(base.oConfig.username + ':' + base.oConfig.password));
}
- //check if not IE 9 or 8
+ //check if not IE 9 or 8
if (!isXDomainRequest) {
//set headers
if (headers) {
@@ -1328,7 +1353,7 @@ function oData(res, config) {
}
}
- //additional headers
+ //additional headers
if (base.oConfig.headers.length > 0) {
//TODO: merge both normal and additional headers?!
for (var i = 0; i < base.oConfig.headers.length; i++) {
@@ -1398,8 +1423,17 @@ function oData(res, config) {
// Create the XHR object with CORS support
// +++
function createCORSRequest(method, url) {
- // TODO: Add older browser fallback here!
- var xhr = new XMLHttpRequest();
+ var xhr = null;
+
+ //if no window assume node.js
+ if(typeof window === 'undefined') {
+ var Xhr2 = require('xhr2');
+ xhr = new Xhr2();
+ }
+ else {
+ xhr = new XMLHttpRequest();
+ }
+
if (base.oConfig.isCors && 'withCredentials' in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, base.oConfig.isAsync);
@@ -1512,4 +1546,9 @@ function oData(res, config) {
}
return (init(res));
-}
\ No newline at end of file
+}
+
+// Export for npm
+if(typeof window === 'undefined') {
+ module.exports = o;
+}
diff --git a/o.min.js b/o.min.js
index d9fef29..7ed3fd9 100644
--- a/o.min.js
+++ b/o.min.js
@@ -1 +1 @@
-function o(e){function n(){for(var e,n={},t=0,r=arguments.length;r>t;t++)for(e in arguments[t])arguments[t].hasOwnProperty(e)&&(n[e]=arguments[t][e]);return n}return base=this,base.oConfig=base.oConfig||{endpoint:null,format:"json",version:4,strictMode:!0,start:null,ready:null,error:null,headers:[{name:"If-Match",value:"*"}],username:null,password:null,isAsync:!0,isCors:!0,openAjaxRequests:0,isHashRoute:!0,appending:""},base.config=function(e){base.oConfig=n(base.oConfig,e)},base.isEndpoint=function(){return null!==base.oConfig.endpoint},"undefined"==typeof e?base:new oData(e,base.oConfig)}function oData(e,n){function t(e,n,t,r){if(P(n)){var o="",a=[];for(i=0;i0?"?"+e.substring(1):""}function s(e){for(var n=0;n-1||e.toUpperCase().indexOf("HTTPS://")>-1?G=!1:base.oConfig.endpoint||N("You can not use resource query without defining your oData endpoint. Use o().config({endpoint:youeEndpoint}) to define your oData endpoint."),routeName=e,d(e),base)}function b(e){T("$expand")?(Y.queryList[Y.query.$expand].value+=","+e,Y.queryList[Y.query.$expand].original=Y.queryList[Y.query.$expand].value):v("$expand",e,e)}function y(e){var n=e.split("?"),t=e,r="",o={path:[],appending:"",query:{},queryList:[],method:"GET",data:null,progress:null};if(2===n.length){t=n[0],r=n[1];for(var a=r.split("&"),i=0;i0?e:void N(n+": Parameter must be set.")}function w(e,n){if("number"==typeof e)return e;var t=n;return e&&e.length>0&&(isNaN(e)||(t=parseInt(e))),t}function S(e){for(var n=0,t=0;t-1&&n++;return n}function O(e){for(var n=[],t=0;t-1&&n.push(t);for(var t=n.length-1;t>=0;t--)B.splice(n[t],1);B[0]&&(Y=B[0])}function E(e){return JSON?JSON.stringify(e):(N("No JSON support."),e)}function P(e){return"undefined"==typeof Array.isArray?"[object Array]"===e.toString():Array.isArray(e)}function A(e,n){return e?-1!==e.indexOf(n,e.length-n.length):!1}function R(e,n){return 0===e.indexOf(n)}function N(e){function n(e){this.message=e,this.name="o.js exception"}if(n.prototype=new Error,base.oConfig.strictMode===!0)throw new n(e);console.log("o.js exception: "+e)}function L(e,n){var t="",r=q(),a=!1;n&&(t+="--batch_"+e+"\n",t+="Content-Type: multipart/mixed; boundary=changeset_"+r+"\n\n");for(var i=0;i=200&&e.status<300){if(204!==e.status)if(a){var n,i=[],u=/({[\s\S]*?--batchresponse_)/g;do n=u.exec(e.responseText),n&&(H(n[0].substring(0,n[0].length-16),f),i.push(f.data));while(n);f.data=i}else H(e.responseText,f);I&&I.resolve(f),"function"==typeof t&&t.call(f,f.data,s)}else try{var p=e.responseText;if(JSON&&""!=e.responseText&&(p=JSON.parse(e.responseText)),""!==p&&p["odata.error"]){var l=p["odata.error"].message.value+" | HTTP Status: "+e.status+" | oData Code: "+p["odata.error"].code;N(l)}else N("Request to "+o()+" failed with HTTP status "+(e.status||404)+".")}catch(d){if(D(f,!0,e.status||404,e.responseText),"function"==typeof r)r(e.status||404,d);else{if(!I)throw d;d.status=e.status||404,I.reject(d)}}D(f,!1)}},base.oConfig.username&&base.oConfig.password&&(X&&N("CORS and Basic Auth is not supported for IE <= 9. Try to set isCors:false in the OData config if you do not need CORS support."),e.setRequestHeader("Authorization","Basic "+J(base.oConfig.username+":"+base.oConfig.password))),!X){if(i)for(var p=0;p0)for(var p=0;p>2,i=(3&t)<<4|r>>4,s=(15&r)<<2|o>>6,u=63&o,isNaN(r)?s=u=64:isNaN(o)&&(u=64),f=f+this._keyStr.charAt(a)+this._keyStr.charAt(i)+this._keyStr.charAt(s)+this._keyStr.charAt(u);return f},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");for(var n="",t=0;tr?n+=String.fromCharCode(r):r>127&&2048>r?(n+=String.fromCharCode(r>>6|192),n+=String.fromCharCode(63&r|128)):(n+=String.fromCharCode(r>>12|224),n+=String.fromCharCode(r>>6&63|128),n+=String.fromCharCode(63&r|128))}return n}};return n.encode(e)}base=this;var Y=null,B=[],M=[],G=!0,I=null,U=null,X=!1,z=function(){},W={},F={"==":"eq","===":"eq","!=":"ne","!==":"ne",">":"gt",">=":"ge","<":"lt","<=":"le","&&":"and","||":"or","!":"not","+":"add","-":"sub","*":"mul",".":"/","%":"mod"};return base.data=[],base.inlinecount=null,base.param={},base.oConfig=n,base.routes=base.route=function(e,n){P(e)||(e=[e]);for(var t=window.location.hash,r=0;rt;t++)for(e in arguments[t])arguments[t].hasOwnProperty(e)&&(n[e]=arguments[t][e]);return n}var t=this;return t.oConfig=t.oConfig||{endpoint:null,format:"json",version:4,strictMode:!0,start:null,ready:null,error:null,headers:[{name:"If-Match",value:"*"}],username:null,password:null,isAsync:!0,isCors:!0,openAjaxRequests:0,isHashRoute:!0,appending:""},t.config=function(e){t.oConfig=n(t.oConfig,e)},t.isEndpoint=function(){return null!==t.oConfig.endpoint},"undefined"==typeof e?t:new oData(e,t.oConfig)}function oData(e,n){function t(){if("undefined"!=typeof Q){var e=Q;return e}if("undefined"==typeof window){var e=require("q");return e}return null}function r(e,n,t,r){if(R(n)){var o="",a=[];for(i=0;i0?"?"+e.substring(1):""}function s(e){for(var n=0;n-1||e.toUpperCase().indexOf("HTTPS://")>-1?U=!1:B.oConfig.endpoint||k("You can not use resource query without defining your oData endpoint. Use o().config({endpoint:youeEndpoint}) to define your oData endpoint."),routeName=e,h(e),B)}function v(e){w("$expand")?(M.queryList[M.query.$expand].value+=","+e,M.queryList[M.query.$expand].original=M.queryList[M.query.$expand].value):C("$expand",e,e)}function m(e){var n=e.split("?"),t=e,r="",o={path:[],appending:"",query:{},queryList:[],method:"GET",data:null,progress:null};if(2===n.length){t=n[0],r=n[1];for(var a=r.split("&"),i=0;i0?e:void k(n+": Parameter must be set.")}function O(e,n){if("number"==typeof e)return e;var t=n;return e&&e.length>0&&(isNaN(e)||(t=parseInt(e))),t}function E(e){for(var n=0,t=0;t-1&&n++;return n}function P(e){for(var n=[],t=0;t-1&&n.push(t);for(var t=n.length-1;t>=0;t--)G.splice(n[t],1);G[0]&&(M=G[0])}function b(e){return JSON?JSON.stringify(e):(k("No JSON support."),e)}function R(e){return"undefined"==typeof Array.isArray?"[object Array]"===e.toString():Array.isArray(e)}function A(e,n){return e?-1!==e.indexOf(n,e.length-n.length):!1}function N(e,n){return 0===e.indexOf(n)}function k(e){function n(e){this.message=e,this.name="o.js exception"}if(n.prototype=new Error,B.oConfig.strictMode===!0)throw new n(e);console.log("o.js exception: "+e)}function L(e,n){var t="",r=$(),o=!1;n&&(t+="--batch_"+e+"\n",t+="Content-Type: multipart/mixed; boundary=changeset_"+r+"\n\n");for(var i=0;i=200&&e.status<300){if(204!==e.status)if(o){var n,i=[],s=/({[\s\S]*?--batchresponse_)/g;do n=s.exec(e.responseText),n&&(j(n[0].substring(0,n[0].length-16),f),i.push(f.data));while(n);f.data=i}else j(e.responseText,f);X&&X.resolve(f),"function"==typeof t&&t.call(f,f.data,u)}else try{var p=e.responseText;if(JSON&&""!=e.responseText&&(p=JSON.parse(e.responseText)),""!==p&&p["odata.error"]){var l=p["odata.error"].message.value+" | HTTP Status: "+e.status+" | oData Code: "+p["odata.error"].code;k(l)}else k("Request to "+a()+" failed with HTTP status "+(e.status||404)+".")}catch(d){if(H(f,!0,e.status||404,e.responseText),"function"==typeof r)r(e.status||404,d);else{if(!X)throw d;d.status=e.status||404,X.reject(d)}}H(f,!1)}},B.oConfig.username&&B.oConfig.password&&(W&&k("CORS and Basic Auth is not supported for IE <= 9. Try to set isCors:false in the OData config if you do not need CORS support."),e.setRequestHeader("Authorization","Basic "+Y(B.oConfig.username+":"+B.oConfig.password))),!W){if(i)for(var p=0;p0)for(var p=0;p>2,i=(3&t)<<4|r>>4,u=(15&r)<<2|o>>6,s=63&o,isNaN(r)?u=s=64:isNaN(o)&&(s=64),f=f+this._keyStr.charAt(a)+this._keyStr.charAt(i)+this._keyStr.charAt(u)+this._keyStr.charAt(s);return f},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");for(var n="",t=0;tr?n+=String.fromCharCode(r):r>127&&2048>r?(n+=String.fromCharCode(r>>6|192),n+=String.fromCharCode(63&r|128)):(n+=String.fromCharCode(r>>12|224),n+=String.fromCharCode(r>>6&63|128),n+=String.fromCharCode(63&r|128))}return n}};return n.encode(e)}var B=this,M=null,G=[],I=[],U=!0,X=null,z=null,W=!1,F=function(){},K={},V={"==":"eq","===":"eq","!=":"ne","!==":"ne",">":"gt",">=":"ge","<":"lt","<=":"le","&&":"and","||":"or","!":"not","+":"add","-":"sub","*":"mul",".":"/","%":"mod"};return B.data=[],B.inlinecount=null,B.param={},B.oConfig=n,B.routes=B.route=function(e,n){R(e)||(e=[e]),"undefined"==typeof window&&k("Routes are only supported in a browser env.");for(var t=window.location.hash,r=0;ro.js - Test page
-
+
-
-
+
+
-
-
+
+
-
-
+
+