devextreme-aspnet-data
Version:
DevExtreme data layer extension for ASP.NET
373 lines (308 loc) • 11.5 kB
JavaScript
// Version: 2.2.0
// https://github.com/DevExpress/DevExtreme.AspNet.Data
// Copyright (c) Developer Express Inc.
/* global DevExpress:false, jQuery:false */
(function(factory) {
"use strict";
if(typeof define === "function" && define.amd) {
define(function(require, exports, module) {
module.exports = factory(
require("jquery"),
require("devextreme/data/custom_store"),
require("devextreme/data/utils")
);
});
} else if (typeof module === "object" && module.exports) {
module.exports = factory(
require("jquery"),
require("devextreme/data/custom_store"),
require("devextreme/data/utils")
);
} else {
DevExpress.data.AspNet = factory(
jQuery,
DevExpress.data.CustomStore,
DevExpress.data.utils
);
}
})(function($, CustomStore, dataUtils) {
"use strict";
function createStore(options) {
var store = new CustomStore(createStoreConfig(options));
store._useDefaultSearch = true;
return store;
}
function createStoreConfig(options) {
var keyExpr = options.key,
loadUrl = options.loadUrl,
loadMethod = options.loadMethod || "GET",
loadParams = options.loadParams,
updateUrl = options.updateUrl,
insertUrl = options.insertUrl,
deleteUrl = options.deleteUrl,
onBeforeSend = options.onBeforeSend,
onAjaxError = options.onAjaxError;
function send(operation, requiresKey, ajaxSettings, customSuccessHandler) {
var d = $.Deferred();
if(requiresKey && !keyExpr) {
d.reject(new Error("Primary key is not specified (operation: '" + operation + "', url: '" + ajaxSettings.url + "')"));
} else {
if(operation === "load") {
ajaxSettings.cache = false;
ajaxSettings.dataType = "json";
} else {
ajaxSettings.dataType = "text";
}
if(onBeforeSend)
onBeforeSend(operation, ajaxSettings);
$.ajax(ajaxSettings)
.done(function(res, textStatus, xhr) {
if(customSuccessHandler)
customSuccessHandler(d, res, xhr);
else
d.resolve();
})
.fail(function(xhr, textStatus) {
var error = getErrorMessageFromXhr(xhr);
if(onAjaxError) {
var e = { xhr: xhr, error: error };
onAjaxError(e);
error = e.error;
}
if(error)
d.reject(error);
else
d.reject(xhr, textStatus);
});
}
return d.promise();
}
function filterByKey(keyValue) {
if(!Array.isArray(keyExpr))
return [keyExpr, keyValue];
return keyExpr.map(function(i) {
return [i, keyValue[i]];
});
}
function loadOptionsToActionParams(options, isCountQuery) {
var result = {};
if(isCountQuery)
result.isCountQuery = isCountQuery;
if(options) {
["skip", "take", "requireTotalCount", "requireGroupCount"].forEach(function(i) {
if(options[i] !== undefined)
result[i] = options[i];
});
var normalizeSorting = dataUtils.normalizeSortingInfo,
group = options.group,
filter = options.filter,
select = options.select;
if(options.sort)
result.sort = JSON.stringify(normalizeSorting(options.sort));
if(group) {
if(!isAdvancedGrouping(group))
group = normalizeSorting(group);
result.group = JSON.stringify(group);
}
if(Array.isArray(filter)) {
filter = $.extend(true, [], filter);
stringifyDatesInFilter(filter);
result.filter = JSON.stringify(filter);
}
if(options.totalSummary)
result.totalSummary = JSON.stringify(options.totalSummary);
if(options.groupSummary)
result.groupSummary = JSON.stringify(options.groupSummary);
if(select) {
if(!Array.isArray(select))
select = [ select ];
result.select = JSON.stringify(select);
}
}
$.extend(result, loadParams);
return result;
}
function handleInsertUpdateSuccess(d, res, xhr) {
var mime = xhr.getResponseHeader("Content-Type"),
isJSON = mime && mime.indexOf("application/json") > -1;
d.resolve(isJSON ? JSON.parse(res) : res);
}
return {
key: keyExpr,
errorHandler: options.errorHandler,
load: function(loadOptions) {
return send(
"load",
false,
{
url: loadUrl,
method: loadMethod,
data: loadOptionsToActionParams(loadOptions)
},
function(d, res) {
processLoadResponse(d, res, function(res) {
return [ res.data, createLoadExtra(res) ];
});
}
);
},
totalCount: function(loadOptions) {
return send(
"load",
false,
{
url: loadUrl,
method: loadMethod,
data: loadOptionsToActionParams(loadOptions, true)
},
function(d, res) {
processLoadResponse(d, res, function(res) {
return [ res.totalCount ];
});
}
);
},
byKey: function(key) {
return send(
"load",
true,
{
url: loadUrl,
method: loadMethod,
data: loadOptionsToActionParams({ filter: filterByKey(key) })
},
function(d, res) {
processLoadResponse(d, res, function(res) {
return [ res.data[0] ];
});
}
);
},
update: updateUrl && function(key, values) {
return send(
"update",
true,
{
url: updateUrl,
method: options.updateMethod || "PUT",
data: {
key: serializeKey(key),
values: JSON.stringify(values)
}
},
handleInsertUpdateSuccess
);
},
insert: insertUrl && function(values) {
return send(
"insert",
true,
{
url: insertUrl,
method: options.insertMethod || "POST",
data: { values: JSON.stringify(values) }
},
handleInsertUpdateSuccess
);
},
remove: deleteUrl && function(key) {
return send("delete", true, {
url: deleteUrl,
method: options.deleteMethod || "DELETE",
data: { key: serializeKey(key) }
});
}
};
}
function processLoadResponse(d, res, getResolveArgs) {
res = expandLoadResponse(res);
if(!res || typeof res !== "object")
d.reject(new Error("Unexpected response received"));
else
d.resolve.apply(d, getResolveArgs(res));
}
function expandLoadResponse(value) {
if(Array.isArray(value))
return { data: value };
if(typeof value === "number")
return { totalCount: value };
return value;
}
function createLoadExtra(res) {
return {
totalCount: "totalCount" in res ? res.totalCount : -1,
groupCount: "groupCount" in res ? res.groupCount : -1,
summary: res.summary || null
};
}
function serializeKey(key) {
if(typeof key === "object")
return JSON.stringify(key);
return key;
}
function serializeDate(date) {
function zpad(text, len) {
text = String(text);
while(text.length < len)
text = "0" + text;
return text;
}
var builder = [1 + date.getMonth(), "/", date.getDate(), "/", date.getFullYear()],
h = date.getHours(),
m = date.getMinutes(),
s = date.getSeconds(),
f = date.getMilliseconds();
if(h + m + s + f > 0)
builder.push(" ", zpad(h, 2), ":", zpad(m, 2), ":", zpad(s, 2), ".", zpad(f, 3));
return builder.join("");
}
function stringifyDatesInFilter(crit) {
crit.forEach(function(v, k) {
if(Array.isArray(v)) {
stringifyDatesInFilter(v);
} else if(Object.prototype.toString.call(v) === "[object Date]") {
crit[k] = serializeDate(v);
}
});
}
function isAdvancedGrouping(expr) {
if(!Array.isArray(expr))
return false;
for(var i = 0; i < expr.length; i++) {
if("groupInterval" in expr[i] || "isExpanded" in expr[i])
return true;
}
return false;
}
function getErrorMessageFromXhr(xhr) {
var mime = xhr.getResponseHeader("Content-Type"),
responseText = xhr.responseText;
if(!mime)
return null;
if(mime.indexOf("text/plain") === 0)
return responseText;
if(mime.indexOf("application/json") === 0) {
var jsonObj = safeParseJSON(responseText);
if(typeof jsonObj === "string")
return jsonObj;
if(typeof jsonObj === "object") {
for(var key in jsonObj) {
if(typeof jsonObj[key] === "string")
return jsonObj[key];
}
}
return responseText;
}
return null;
}
function safeParseJSON(json) {
try {
return JSON.parse(json);
} catch(x) {
return null;
}
}
return {
createStore: createStore
};
});