libre-jqgrid 4.17.2 → 4.17.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/.tscache/all/hashes/free-jqgrid.d.ts-74303c8b076937117540c0cb798f2053 +1 -0
  2. package/.tscache/all/hashes/test.ts-0d81877a31bc5d7ac52dd35a66602f01 +1 -0
  3. package/.tscache/all/timestamp +0 -0
  4. package/dist/css/ui.jqgrid.css +1618 -0
  5. package/dist/css/ui.jqgrid.min.css +4 -0
  6. package/dist/css/ui.jqgrid.min.css.map +1 -0
  7. package/dist/i18n/grid.locale-ar.js +198 -0
  8. package/dist/i18n/grid.locale-bg.js +201 -0
  9. package/dist/i18n/grid.locale-bs.js +230 -0
  10. package/dist/i18n/grid.locale-ca.js +204 -0
  11. package/dist/i18n/grid.locale-cn.js +237 -0
  12. package/dist/i18n/grid.locale-cs.js +197 -0
  13. package/dist/i18n/grid.locale-da.js +196 -0
  14. package/dist/i18n/grid.locale-de.js +240 -0
  15. package/dist/i18n/grid.locale-el.js +195 -0
  16. package/dist/i18n/grid.locale-en.js +256 -0
  17. package/dist/i18n/grid.locale-es.js +202 -0
  18. package/dist/i18n/grid.locale-fa.js +211 -0
  19. package/dist/i18n/grid.locale-fi.js +201 -0
  20. package/dist/i18n/grid.locale-fr.js +197 -0
  21. package/dist/i18n/grid.locale-gl.js +197 -0
  22. package/dist/i18n/grid.locale-he.js +198 -0
  23. package/dist/i18n/grid.locale-hr.js +231 -0
  24. package/dist/i18n/grid.locale-hu.js +196 -0
  25. package/dist/i18n/grid.locale-id.js +238 -0
  26. package/dist/i18n/grid.locale-is.js +197 -0
  27. package/dist/i18n/grid.locale-it.js +189 -0
  28. package/dist/i18n/grid.locale-ja.js +203 -0
  29. package/dist/i18n/grid.locale-kr.js +194 -0
  30. package/dist/i18n/grid.locale-lt.js +199 -0
  31. package/dist/i18n/grid.locale-me.js +198 -0
  32. package/dist/i18n/grid.locale-nl.js +208 -0
  33. package/dist/i18n/grid.locale-no.js +180 -0
  34. package/dist/i18n/grid.locale-pl.js +204 -0
  35. package/dist/i18n/grid.locale-pt-br.js +210 -0
  36. package/dist/i18n/grid.locale-pt.js +196 -0
  37. package/dist/i18n/grid.locale-ro.js +210 -0
  38. package/dist/i18n/grid.locale-ru.js +196 -0
  39. package/dist/i18n/grid.locale-sk.js +198 -0
  40. package/dist/i18n/grid.locale-sl.js +230 -0
  41. package/dist/i18n/grid.locale-sr.js +199 -0
  42. package/dist/i18n/grid.locale-sv.js +198 -0
  43. package/dist/i18n/grid.locale-th.js +195 -0
  44. package/dist/i18n/grid.locale-tr.js +197 -0
  45. package/dist/i18n/grid.locale-tw.js +199 -0
  46. package/dist/i18n/grid.locale-ua.js +199 -0
  47. package/dist/i18n/grid.locale-vi.js +238 -0
  48. package/dist/i18n/min/grid.locale-ar.js +10 -0
  49. package/dist/i18n/min/grid.locale-ar.js.map +1 -0
  50. package/dist/i18n/min/grid.locale-bg.js +10 -0
  51. package/dist/i18n/min/grid.locale-bg.js.map +1 -0
  52. package/dist/i18n/min/grid.locale-ca.js +15 -0
  53. package/dist/i18n/min/grid.locale-ca.js.map +1 -0
  54. package/dist/i18n/min/grid.locale-cn.js +10 -0
  55. package/dist/i18n/min/grid.locale-cn.js.map +1 -0
  56. package/dist/i18n/min/grid.locale-cs.js +11 -0
  57. package/dist/i18n/min/grid.locale-cs.js.map +1 -0
  58. package/dist/i18n/min/grid.locale-da.js +10 -0
  59. package/dist/i18n/min/grid.locale-da.js.map +1 -0
  60. package/dist/i18n/min/grid.locale-de.js +21 -0
  61. package/dist/i18n/min/grid.locale-de.js.map +1 -0
  62. package/dist/i18n/min/grid.locale-el.js +10 -0
  63. package/dist/i18n/min/grid.locale-el.js.map +1 -0
  64. package/dist/i18n/min/grid.locale-en.js +11 -0
  65. package/dist/i18n/min/grid.locale-en.js.map +1 -0
  66. package/dist/i18n/min/grid.locale-es.js +16 -0
  67. package/dist/i18n/min/grid.locale-es.js.map +1 -0
  68. package/dist/i18n/min/grid.locale-fa.js +8 -0
  69. package/dist/i18n/min/grid.locale-fa.js.map +1 -0
  70. package/dist/i18n/min/grid.locale-fi.js +11 -0
  71. package/dist/i18n/min/grid.locale-fi.js.map +1 -0
  72. package/dist/i18n/min/grid.locale-fr.js +10 -0
  73. package/dist/i18n/min/grid.locale-fr.js.map +1 -0
  74. package/dist/i18n/min/grid.locale-gl.js +9 -0
  75. package/dist/i18n/min/grid.locale-gl.js.map +1 -0
  76. package/dist/i18n/min/grid.locale-he.js +10 -0
  77. package/dist/i18n/min/grid.locale-he.js.map +1 -0
  78. package/dist/i18n/min/grid.locale-hr.js +11 -0
  79. package/dist/i18n/min/grid.locale-hr.js.map +1 -0
  80. package/dist/i18n/min/grid.locale-hu.js +10 -0
  81. package/dist/i18n/min/grid.locale-hu.js.map +1 -0
  82. package/dist/i18n/min/grid.locale-id.js +10 -0
  83. package/dist/i18n/min/grid.locale-id.js.map +1 -0
  84. package/dist/i18n/min/grid.locale-is.js +9 -0
  85. package/dist/i18n/min/grid.locale-is.js.map +1 -0
  86. package/dist/i18n/min/grid.locale-it.js +2 -0
  87. package/dist/i18n/min/grid.locale-it.js.map +1 -0
  88. package/dist/i18n/min/grid.locale-ja.js +10 -0
  89. package/dist/i18n/min/grid.locale-ja.js.map +1 -0
  90. package/dist/i18n/min/grid.locale-kr.js +2 -0
  91. package/dist/i18n/min/grid.locale-kr.js.map +1 -0
  92. package/dist/i18n/min/grid.locale-lt.js +10 -0
  93. package/dist/i18n/min/grid.locale-lt.js.map +1 -0
  94. package/dist/i18n/min/grid.locale-me.js +10 -0
  95. package/dist/i18n/min/grid.locale-me.js.map +1 -0
  96. package/dist/i18n/min/grid.locale-nl.js +2 -0
  97. package/dist/i18n/min/grid.locale-nl.js.map +1 -0
  98. package/dist/i18n/min/grid.locale-no.js +2 -0
  99. package/dist/i18n/min/grid.locale-no.js.map +1 -0
  100. package/dist/i18n/min/grid.locale-pl.js +18 -0
  101. package/dist/i18n/min/grid.locale-pl.js.map +1 -0
  102. package/dist/i18n/min/grid.locale-pt-br.js +21 -0
  103. package/dist/i18n/min/grid.locale-pt-br.js.map +1 -0
  104. package/dist/i18n/min/grid.locale-pt.js +9 -0
  105. package/dist/i18n/min/grid.locale-pt.js.map +1 -0
  106. package/dist/i18n/min/grid.locale-ro.js +10 -0
  107. package/dist/i18n/min/grid.locale-ro.js.map +1 -0
  108. package/dist/i18n/min/grid.locale-ru.js +10 -0
  109. package/dist/i18n/min/grid.locale-ru.js.map +1 -0
  110. package/dist/i18n/min/grid.locale-sk.js +10 -0
  111. package/dist/i18n/min/grid.locale-sk.js.map +1 -0
  112. package/dist/i18n/min/grid.locale-sr.js +10 -0
  113. package/dist/i18n/min/grid.locale-sr.js.map +1 -0
  114. package/dist/i18n/min/grid.locale-sv.js +10 -0
  115. package/dist/i18n/min/grid.locale-sv.js.map +1 -0
  116. package/dist/i18n/min/grid.locale-th.js +10 -0
  117. package/dist/i18n/min/grid.locale-th.js.map +1 -0
  118. package/dist/i18n/min/grid.locale-tr.js +10 -0
  119. package/dist/i18n/min/grid.locale-tr.js.map +1 -0
  120. package/dist/i18n/min/grid.locale-tw.js +11 -0
  121. package/dist/i18n/min/grid.locale-tw.js.map +1 -0
  122. package/dist/i18n/min/grid.locale-ua.js +10 -0
  123. package/dist/i18n/min/grid.locale-ua.js.map +1 -0
  124. package/dist/i18n/min/grid.locale-vi.js +10 -0
  125. package/dist/i18n/min/grid.locale-vi.js.map +1 -0
  126. package/dist/jquery.jqgrid.min.js +11 -0
  127. package/dist/jquery.jqgrid.min.js.map +1 -0
  128. package/{js/jquery.jqgrid.src.js.1 → dist/jquery.jqgrid.src.js} +1 -1
  129. package/dist/modules/grid.base.js +8518 -0
  130. package/dist/modules/grid.celledit.js +673 -0
  131. package/dist/modules/grid.common.js +844 -0
  132. package/dist/modules/grid.custom.js +1795 -0
  133. package/dist/modules/grid.filter.js +897 -0
  134. package/dist/modules/grid.formedit.js +2537 -0
  135. package/dist/modules/grid.grouping.js +737 -0
  136. package/dist/modules/grid.import.js +251 -0
  137. package/dist/modules/grid.inlinedit.js +784 -0
  138. package/dist/modules/grid.jqueryui.js +965 -0
  139. package/dist/modules/grid.pivot.js +862 -0
  140. package/dist/modules/grid.subgrid.js +379 -0
  141. package/dist/modules/grid.tbltogrid.js +141 -0
  142. package/dist/modules/grid.treegrid.js +683 -0
  143. package/dist/modules/jqdnr.js +188 -0
  144. package/dist/modules/jqmodal.js +292 -0
  145. package/dist/modules/jquery.fmatter.js +1061 -0
  146. package/dist/modules/jsonxml.js +343 -0
  147. package/dist/modules/min/grid.base.js +11 -0
  148. package/dist/modules/min/grid.base.js.map +1 -0
  149. package/dist/modules/min/grid.celledit.js +2 -0
  150. package/dist/modules/min/grid.celledit.js.map +1 -0
  151. package/dist/modules/min/grid.common.js +2 -0
  152. package/dist/modules/min/grid.common.js.map +1 -0
  153. package/dist/modules/min/grid.custom.js +2 -0
  154. package/dist/modules/min/grid.custom.js.map +1 -0
  155. package/dist/modules/min/grid.filter.js +2 -0
  156. package/dist/modules/min/grid.filter.js.map +1 -0
  157. package/dist/modules/min/grid.formedit.js +2 -0
  158. package/dist/modules/min/grid.formedit.js.map +1 -0
  159. package/dist/modules/min/grid.grouping.js +2 -0
  160. package/dist/modules/min/grid.grouping.js.map +1 -0
  161. package/dist/modules/min/grid.import.js +2 -0
  162. package/dist/modules/min/grid.import.js.map +1 -0
  163. package/dist/modules/min/grid.inlinedit.js +2 -0
  164. package/dist/modules/min/grid.inlinedit.js.map +1 -0
  165. package/dist/modules/min/grid.jqueryui.js +2 -0
  166. package/dist/modules/min/grid.jqueryui.js.map +1 -0
  167. package/dist/modules/min/grid.pivot.js +2 -0
  168. package/dist/modules/min/grid.pivot.js.map +1 -0
  169. package/dist/modules/min/grid.subgrid.js +2 -0
  170. package/dist/modules/min/grid.subgrid.js.map +1 -0
  171. package/dist/modules/min/grid.tbltogrid.js +2 -0
  172. package/dist/modules/min/grid.tbltogrid.js.map +1 -0
  173. package/dist/modules/min/grid.treegrid.js +2 -0
  174. package/dist/modules/min/grid.treegrid.js.map +1 -0
  175. package/dist/modules/min/jqdnr.js +2 -0
  176. package/dist/modules/min/jqdnr.js.map +1 -0
  177. package/dist/modules/min/jqmodal.js +2 -0
  178. package/dist/modules/min/jqmodal.js.map +1 -0
  179. package/dist/modules/min/jquery.fmatter.js +2 -0
  180. package/dist/modules/min/jquery.fmatter.js.map +1 -0
  181. package/dist/modules/min/jsonxml.js +2 -0
  182. package/dist/modules/min/jsonxml.js.map +1 -0
  183. package/dist/plugins/css/ui.multiselect.css +30 -0
  184. package/dist/plugins/css/ui.multiselect.min.css +2 -0
  185. package/dist/plugins/css/ui.multiselect.min.css.map +1 -0
  186. package/dist/plugins/grid.odata.js +1313 -0
  187. package/dist/plugins/jqgrid_download.js +109 -0
  188. package/dist/plugins/jquery.contextmenu-ui.js +304 -0
  189. package/dist/plugins/jquery.contextmenu.js +174 -0
  190. package/dist/plugins/jquery.createcontexmenufromnavigatorbuttons.js +172 -0
  191. package/dist/plugins/jquery.jqgrid.showhidecolumnmenu.js +201 -0
  192. package/dist/plugins/min/grid.odata.js +11 -0
  193. package/dist/plugins/min/grid.odata.js.map +1 -0
  194. package/dist/plugins/min/jquery.contextmenu-ui.js +26 -0
  195. package/dist/plugins/min/jquery.contextmenu-ui.js.map +1 -0
  196. package/dist/plugins/min/jquery.contextmenu.js +19 -0
  197. package/dist/plugins/min/jquery.contextmenu.js.map +1 -0
  198. package/dist/plugins/min/jquery.createcontexmenufromnavigatorbuttons.js +12 -0
  199. package/dist/plugins/min/jquery.createcontexmenufromnavigatorbuttons.js.map +1 -0
  200. package/dist/plugins/min/jquery.jqgrid.showhidecolumnmenu.js +10 -0
  201. package/dist/plugins/min/jquery.jqgrid.showhidecolumnmenu.js.map +1 -0
  202. package/dist/plugins/min/ui.multiselect.js +30 -0
  203. package/dist/plugins/min/ui.multiselect.js.map +1 -0
  204. package/dist/plugins/ui.multiselect.js +389 -0
  205. package/dist/ts/free-jqgrid.d.ts +2132 -0
  206. package/js/jquery.jqgrid.min.js +1 -1
  207. package/js/jquery.jqgrid.min.js.map +1 -1
  208. package/js/jquery.jqgrid.src.js +8 -3
  209. package/libre-jqgrid-4.17.4.tgz +0 -0
  210. package/package.json +1 -1
  211. package/.github/workflows/npm.yml +0 -47
@@ -0,0 +1,1313 @@
1
+ /**
2
+ * @license OData plugin for Free-jqGrid
3
+ *
4
+ * Copyright (c) 2014-2018, Mark Babayev (https://github.com/mirik123) markolog@gmail.com
5
+ * License MIT (MIT-LICENSE.txt)
6
+ *
7
+ * inspired by Richard Bennett gist code: jqGrid.ODataExtensions.js
8
+ * https://gist.github.com/dealproc/6678280
9
+ */
10
+
11
+ /*jslint continue: true, nomen: true, plusplus: true, unparam: true, todo: true, vars: true, white: true */
12
+ /*global jQuery, define, module, require */
13
+
14
+ (function (factory) {
15
+ "use strict";
16
+ if (typeof define === "function" && define.amd) {
17
+ // AMD. Register as an anonymous module.
18
+ define([
19
+ "jquery",
20
+ "free-jqgrid/grid.base"
21
+ ], factory);
22
+ } else if (typeof module === "object" && module.exports) {
23
+ // Node/CommonJS
24
+ module.exports = function (root, $) {
25
+ if ($ === undefined) {
26
+ // require("jquery") returns a factory that requires window to
27
+ // build a jQuery instance, we normalize how we use modules
28
+ // that require this pattern but the window provided is a noop
29
+ // if it's defined (how jquery works)
30
+ $ = typeof window !== "undefined" ?
31
+ require("jquery") :
32
+ require("jquery")(root || window);
33
+ }
34
+ require("free-jqgrid/grid.base");
35
+ factory($);
36
+ return $;
37
+ };
38
+ } else {
39
+ // Browser globals
40
+ factory(jQuery);
41
+ }
42
+ }(function ($) {
43
+ /*
44
+ *Functions:
45
+ * parseMetadata - $.jgrid.odataHelper.parseMetadata(rawdata, metadatatype)
46
+ * metadatatype can be: xml,json,datajs.
47
+ * this is a generic function that can be used in external packages too, not only in jqGrid.
48
+ * It parses $metadata ajax response in xml/json format to plain javascript object.
49
+ * IT can also consume metadata returned from datajs.js method "OData.parseMetadata"
50
+ *
51
+ * odataGenColModel - $("#grid").jqGrid('odataGenColModel', {...});
52
+ * This function generates jqgrid style columns by requesting odata $metadata.
53
+ * It is automatically called by odataInit when gencolumns=true.
54
+ *
55
+ * Options:
56
+ * metadatatype: 'xml' - ajax dataType, can be json, jsonp or xml
57
+ * async: false - set ajax sync/async for $metadata request (when calling from odataInit only async=false is supported)
58
+ * entitySet: null - required field, the name of the desired entity set
59
+ * expandable: (none|link|json|subgrid) - the expansion type for ComplexTypes and NavigationProperties, for details see "odata colModel parameters".
60
+ * metadataurl: (odataurl || p.url) + '/$metadata'
61
+ * - set ajax url for $metadata request
62
+ * successfunc: null - odataGenColModel callback to see when metadata request is over and jqgrid can be refreshed
63
+ * parsecolfunc: null - event for converting parsed metadata data array in form of {name,type,nullable,iskey,...} to the jqgrid colModel array
64
+ * parsemetadatafunc: null - event for converting unparsed metadata data (xml or json) to the jqgrid colModel array
65
+ * errorfunc: null - error callback
66
+ *
67
+ * jqGrid Events:
68
+ * jqGridODataParseMetadata - the same as parsemetadatafunc, when no custom function exists the default function is used: $("#grid").jqGrid('parseMetadata', rawdata, dataType)
69
+ * jqGridODataParseColumns - the same as parsecolfunc, when no custom function exists the default function is used: $("#grid").jqGrid('parseColumns', {...})
70
+ *
71
+ * odataInit - $("#grid").jqGrid('odataInit', {...});
72
+ * This is main plugin function. It should be called before colModel is initialized.
73
+ * When columns are defined manually it can be called from events beforeInitGrid, onInitGrid.
74
+ * When columns are created automatically it can be called from event beforeInitGrid only.
75
+ *
76
+ * Options:
77
+ * gencolumns: false - automatically generate columns from odata $metadata (calls odataGenColModel)
78
+ * odataurl: p.url - required field, main odata url
79
+ * datatype: 'json' - ajax dataType, can be json, jsonp or xml
80
+ * entitySet: null - required field, the name of the desired entity set
81
+ * annotations: false - use odata annotations for getting jqgrid parameters: page,records,count,total
82
+ * annotationName: "@jqgrid.GridModelAnnotate" - odata annotations class and namespace
83
+ * version - odata version, used to set $count=true or $inlinecount=allpages
84
+ * errorfunc: null - error callback
85
+ * metadatatype: datatype || 'xml' - when gencolumns=true, alternative ajax dataType for $metadata request
86
+ * odataverbs: { - http verbs for odata and their corresponding actions in jqgrid
87
+ * inlineEditingAdd: 'POST',
88
+ * inlineEditingEdit: 'PATCH',
89
+ * formEditingAdd: 'POST',
90
+ * formEditingEdit: 'PUT'
91
+ * }
92
+ *
93
+ * odata colModel parameters
94
+ * isnavigation - the column type is a NavigationProperty that points to another entity
95
+ * iscomplex - the column type is a ComplexType
96
+ * iscollection - the column is a Collection of entities that can be opened in a new subgrid
97
+ * nosearch - when true, this column is excluded from odata search
98
+ * unformat: function (searchField, searchString, searchOper) - works analogous to xmlmap/jsonmap,
99
+ * for example the function body can be: { return searchString !== '-1' ? 'cltype/Id' : null; }
100
+ * expand: (link|json|subgrid) - defines data expansion types for complex amd navigation properties,
101
+ * it works only with custom formatters specified in odata cmTemplates.
102
+ * link - the link to the property is displayed
103
+ * json - the property data is displayed in a json string form
104
+ * subgrid - jquery subgrid is opened when clicking on a link inside column
105
+ *
106
+ * odata column templates (cmTemplate)
107
+ * odataComplexType - column template for odata Complex type.
108
+ * odataNavigationProperty - column template for odata Navigation property.
109
+ *
110
+ *Plugin allows setting custom cmTemplates for any odata type, for example:
111
+ * $.jgrid.cmTemplate["Edm.GeographyPoint"] = {
112
+ * editable: false,
113
+ * formatter: function(cellvalue, options, rowObject) {
114
+ * if (!cellvalue && this.p.datatype === 'xml') {
115
+ * var xmlvalue = $(rowObject).filter(function() {
116
+ * return this.localName.toLowerCase() === options.colModel.name.toLowerCase();
117
+ * });
118
+ * cellvalue = $.jgrid.odataHelper.convertXmlToJson(xmlvalue[0]);
119
+ * }
120
+ * if(cellvalue.crs && cellvalue.coordinates) {
121
+ * return $.jgrid.format('<div>{0}</div><div>[{1},{2}]</div>', cellvalue.crs.properties.name, cellvalue.coordinates[0], cellvalue.coordinates[1]);
122
+ * }
123
+ * return $.jgrid.format('<div>{0}</div>', cellvalue);
124
+ * }
125
+ * };
126
+ *
127
+ * Example of using standard service from http://www.odata.org/odata-services:
128
+ * $("#grid").jqGrid({
129
+ * ...,
130
+ * beforeInitGrid: function () {
131
+ * $(this).jqGrid('odataInit', {
132
+ * annotations: false,
133
+ * metadatatype: 'xml',
134
+ * datatype: 'jsonp',
135
+ * version: 4,
136
+ * gencolumns: true,
137
+ * expandable: 'json',
138
+ * entitySet: 'Products',
139
+ * odataurl: "http://services.odata.org/V4/OData/OData.svc/Products",
140
+ * metadataurl: 'http://services.odata.org/V4/OData/OData.svc/$metadata',
141
+ * errorfunc: function (jqXHR, parsedError) {
142
+ * jqXHR = jqXHR.xhr || jqXHR;
143
+ * parsedError = $('#errdialog').html() + parsedError;
144
+ * $('#errdialog').html(parsedError).dialog('open');
145
+ * });
146
+ * }
147
+ * });
148
+ *
149
+ * $.ajax({
150
+ * url: 'http://services.odata.org/V4/OData/OData.svc/$metadata',
151
+ * dataType: xml,
152
+ * type: 'GET'
153
+ * }).done(function(data, st, xhr) {
154
+ * var dataType = xhr.getResponseHeader('Content-Type').indexOf('json') >= 0 ? 'json' : 'xml';
155
+ * if(dataType === 'json') {
156
+ * data = $.jgrid.odataHelper.resolveJsonReferences(data);
157
+ * }
158
+ * data = $.jgrid.odataHelper.parseMetadata(data, dataType);
159
+ * var colModels = {};
160
+ * for (i in data) {
161
+ * if (data.hasOwnProperty(i) && i) {
162
+ * colModels[i] = $(this).jqGrid('parseColumns', data[i], 'subgrid');
163
+ * }
164
+ * }
165
+ * $("#grid").jqGrid({
166
+ * colModel: colModels['Product'],
167
+ * odata: {
168
+ * iscollection: true,
169
+ * subgridCols: colModels
170
+ * },
171
+ * ...,
172
+ * beforeInitGrid: function () {
173
+ * $(this).jqGrid('odataInit', {
174
+ * annotations: false,
175
+ * datatype: 'jsonp',
176
+ * version: 4,
177
+ * gencolumns: false,
178
+ * entitySet: 'Products',
179
+ * odataurl: "http://services.odata.org/V4/OData/OData.svc/Products"
180
+ * });
181
+ * }
182
+ * });
183
+ * });
184
+ *
185
+ * Examples of using custom services from https://github.com/mirik123/jqGridSamples:
186
+ * $("#grid").jqGrid({
187
+ * colModel: colModelDefinition,
188
+ * ...,
189
+ * // when columns are defined manually (gencolumns=false) the odataInit call can be also put in onInitGrid event.
190
+ * beforeInitGrid: function () {
191
+ * $(this).jqGrid('odataInit', {
192
+ * version: 3,
193
+ * gencolumns: false,
194
+ * odataurl: 'http://localhost:56216/odata/ODClient'
195
+ * });
196
+ * }
197
+ * });
198
+ *
199
+ * $("#grid").jqGrid({
200
+ * colModel: colModelDefinition,
201
+ * ...,
202
+ * beforeInitGrid: function () {
203
+ * $(this).jqGrid('odataInit', {
204
+ * version: 4,
205
+ * datatype: 'json',
206
+ * annotations: true,
207
+ * gencolumns: true,
208
+ * entitySet: 'ODClient',
209
+ * odataurl: 'http://localhost:56216/odata/ODClient',
210
+ * metadataurl: 'http://localhost:56216/odata/$metadata'
211
+ * });
212
+ * }
213
+ * });
214
+ *
215
+ * $("#grid").jqGrid({
216
+ * colModel: colModelDefinition,
217
+ * ...,
218
+ * beforeInitGrid: function () {
219
+ * $(this).jqGrid('odataInit', {
220
+ * version: 4,
221
+ * datatype: 'xml',
222
+ * annotations: false,
223
+ * gencolumns: true,
224
+ * entitySet: 'ODClient',
225
+ * odataurl: 'http://localhost:56216/odata/ODClient',
226
+ * metadataurl: 'http://localhost:56216/odata/$metadata'
227
+ * });
228
+ * }
229
+ * });
230
+ */
231
+
232
+ "use strict";
233
+ $.jgrid.odataHelper = {
234
+ //http://stackoverflow.com/questions/15312529/resolve-circular-references-from-json-object
235
+ resolveJsonReferences: function (json, refs) {
236
+ var i, ref, byid = {}; // all objects by id
237
+ refs = refs || []; // references to objects that could not be resolved
238
+
239
+ function recurse(obj, prop, parent) {
240
+ if (typeof obj !== 'object' || !obj) {// a primitive value
241
+ return obj;
242
+ }
243
+ if (Object.prototype.toString.call(obj) === '[object Array]') {
244
+ for (i = 0; i < obj.length; i++) {
245
+ // check also if the array element is not a primitive value
246
+ if (typeof obj[i] !== 'object' || !obj[i]) {// a primitive value
247
+ return obj[i];
248
+ }
249
+ if (obj[i].$ref) {
250
+ obj[i] = recurse(obj[i], i, obj);
251
+ }
252
+ else {
253
+ obj[i] = recurse(obj[i], prop, obj);
254
+ }
255
+ }
256
+ return obj;
257
+ }
258
+ if (obj.$ref) { // a reference
259
+ ref = obj.$ref;
260
+ if (byid[ref]) {
261
+ return byid[ref];
262
+ }
263
+ // else we have to make it lazy:
264
+ refs.push([parent, prop, ref]);
265
+ return;
266
+ }
267
+ if (obj.$id) {
268
+ var id = obj.$id;
269
+ delete obj.$id;
270
+ if (obj.$values) {// an array
271
+ obj = obj.$values.map(recurse);
272
+ }
273
+ else {// a plain object
274
+ var itm;
275
+ for (itm in obj) {
276
+ if (obj.hasOwnProperty(itm)) {
277
+ obj[itm] = recurse(obj[itm], itm, obj);
278
+ }
279
+ }
280
+ }
281
+ byid[id] = obj;
282
+ }
283
+ return obj;
284
+ }
285
+
286
+ if (typeof json === 'string') {
287
+ json = JSON.parse(json);
288
+ }
289
+ json = recurse(json); // run it!
290
+
291
+ for (i = 0; i < refs.length; i++) { // resolve previously unknown references
292
+ ref = refs[i];
293
+ ref[0][ref[1]] = byid[ref[2]];
294
+ // Notice that this throws if you put in a reference at top-level
295
+ }
296
+
297
+ return json;
298
+ },
299
+
300
+ // Changes XML to JSON
301
+ //http://davidwalsh.name/convert-xml-json
302
+ convertXmlToJson: function (xml) {
303
+ // Create the return object
304
+ var obj = {}, i, j, attribute, item, nodeName, old;
305
+
306
+ if (!xml) { return null; }
307
+
308
+ if (xml.nodeType === 1) { // element
309
+ // do attributes
310
+ if (xml.attributes.length > 0) {
311
+ obj["@attributes"] = {};
312
+ for (j = 0; j < xml.attributes.length; j++) {
313
+ attribute = xml.attributes.item(j);
314
+ obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
315
+ }
316
+ }
317
+ }
318
+ else if (xml.nodeType === 3) { // text
319
+ obj = xml.nodeValue;
320
+ }
321
+ else if (!xml.nodeType) {
322
+ obj = xml;
323
+ }
324
+
325
+ // do children
326
+ if (xml.hasChildNodes && xml.hasChildNodes()) {
327
+ for (i = 0; i < xml.childNodes.length; i++) {
328
+ item = xml.childNodes.item(i);
329
+ if (item.nodeType === 3) {
330
+ return item.nodeValue;
331
+ }
332
+
333
+ nodeName = item.nodeName;
334
+ if (obj[nodeName] === undefined) {
335
+ obj[nodeName] = $.jgrid.odataHelper.convertXmlToJson(item);
336
+ } else {
337
+ if (obj[nodeName].push === undefined) {
338
+ old = obj[nodeName];
339
+ obj[nodeName] = [];
340
+ obj[nodeName].push(old);
341
+ }
342
+ obj[nodeName].push($.jgrid.odataHelper.convertXmlToJson(item));
343
+ }
344
+ }
345
+ }
346
+
347
+ return $.isEmptyObject(obj) ? null : obj;
348
+ },
349
+
350
+ parseMetadata: function (rawdata, metadatatype) {
351
+ function parseXmlMetadata(data) {
352
+ var entities = {}, entityValues = [], mdata = {};
353
+ var namespace = $('Schema', data).attr('Namespace') + '.';
354
+
355
+ $('EntityContainer EntitySet', data).each(function (i, itm) {
356
+ entities[$(itm).attr('EntityType').replace(namespace, '')] = $(itm).attr('Name');
357
+ entityValues.push($(itm).attr('Name'));
358
+ });
359
+
360
+ $('EntityType, ComplexType', data).each(function () {
361
+ var cols, props, keys, key, iskey, isComplex, isNav, entityType, attr;
362
+
363
+ props = $(this).find('Property,NavigationProperty');
364
+ keys = $('Key PropertyRef', this);
365
+ key = keys && keys.length > 0 ? keys.first().attr('Name') : '';
366
+ entityType = $(this).attr('Name');
367
+
368
+ if (props) {
369
+ cols = [];
370
+ props.each(function (n, itm) {
371
+ attr = {};
372
+ $.each(itm.attributes, function () {
373
+ attr[this.name] = this.value;
374
+ });
375
+
376
+ iskey = attr.Name === key;
377
+ isNav = itm.tagName === 'NavigationProperty';
378
+ isComplex = itm.tagName === 'Property' && $('ComplexType[Name="' + attr.Name + '"]', data).length > 0;
379
+
380
+ cols.push($.extend({
381
+ iskey: iskey,
382
+ isComplex: isComplex,
383
+ isNavigation: isNav,
384
+ isCollection: $.inArray(attr.Name, entityValues) >= 0
385
+ }, attr));
386
+ });
387
+
388
+ if(entities[entityType]) {
389
+ mdata[entities[entityType]] = cols;
390
+ }
391
+ mdata[entityType] = cols;
392
+ }
393
+ });
394
+
395
+ return mdata;
396
+ }
397
+
398
+ function parseJsonMetadata(data) {
399
+ var cols, props, keys, key, iskey, i, j, isComplex, isNav, nullable, type, entityType, mdata = {}, entities = {}, entityValues = [];
400
+
401
+ for (i = 0; i < data.EntityContainer.Elements.length; i++) {
402
+ entities[data.EntityContainer.Elements[i].Type.ElementType.Definition.Name] = data.EntityContainer.Elements[i].Name;
403
+ entityValues.push(data.EntityContainer.Elements[i].Name);
404
+ }
405
+
406
+ for (i = 0; i < data.SchemaElements.length ; i++) {
407
+ props = Array.prototype.concat(data.SchemaElements[i].DeclaredProperties, data.SchemaElements[i].NavigationProperties).filter(function(itm) {return !!itm;});
408
+ keys = data.SchemaElements[i].DeclaredKey;
409
+ key = keys && keys.length > 0 ? keys[0].Name : '';
410
+ entityType = data.SchemaElements[i].Name;
411
+
412
+ if (props) {
413
+ cols = [];
414
+ for (j = 0; j < props.length; j++) {
415
+ iskey = props[j].Name === key;
416
+ nullable = props[j].Type.IsNullable;
417
+ type = props[j].Type.Definition.Namespace + props[j].Type.Definition.Name;
418
+ isComplex = !!props[j].Type.Definition.DeclaredProperties;
419
+ isNav = !isComplex && !props[j].Type;
420
+
421
+ cols.push({
422
+ Name: props[j].Name,
423
+ Type: type,
424
+ Nullable: nullable,
425
+ iskey: iskey,
426
+ isComplex: isComplex,
427
+ isNavigation: isNav,
428
+ isCollection: $.inArray(props[j].Name, entityValues) >= 0
429
+ });
430
+ }
431
+
432
+ if(entities[entityType]) {
433
+ mdata[entities[entityType]] = cols;
434
+ }
435
+ mdata[entityType] = cols;
436
+ }
437
+ }
438
+
439
+ return mdata;
440
+ }
441
+
442
+ function parseDataJSMetadata(data) {
443
+ var cols, props, keys, key, iskey, i, j, isComplex, isNav, nullable, type, entityType, mdata = {}, entities = {}, entityValues = [], entityTypes = [], complexTypes = [];
444
+ var schema = data.dataServices.schema[0];
445
+ var namespace = schema.namespace + '.';
446
+
447
+ for (i = 0; i < schema.entityContainer[0].entitySet.length; i++) {
448
+ entities[schema.entityContainer[0].entitySet[i].entityType.replace(namespace, '')] = schema.entityContainer[0].entitySet[i].name;
449
+ entityValues.push(schema.entityContainer[0].entitySet[i].name);
450
+ }
451
+
452
+ for (i = 0; i < schema.complexType.length; i++) {
453
+ complexTypes.push(schema.complexType[i].name);
454
+ }
455
+
456
+ entityTypes = Array.prototype.concat(schema.entityType, schema.complexType).filter(function(itm) {return !!itm;});
457
+ for (i = 0; i < entityTypes.length ; i++) {
458
+ props = Array.prototype.concat(entityTypes[i].property, entityTypes[i].navigationProperty).filter(function(itm) {return !!itm;});
459
+ keys = entityTypes[i].key;
460
+ key = keys && keys.propertyRef.length > 0 ? keys.propertyRef[0].name : '';
461
+ entityType = entityTypes[i].name;
462
+
463
+ if (props) {
464
+ cols = [];
465
+ for (j = 0; j < props.length; j++) {
466
+ iskey = props[j].name === key;
467
+ nullable = props[j].nullable !== "false";
468
+ type = props[j].type;
469
+ isComplex = !!props[j].type && $.inArray(props[j].type.replace(namespace, ''), complexTypes) >= 0;
470
+ isNav = !props[j].type;
471
+
472
+ cols.push({
473
+ Name: props[j].name,
474
+ Type: type,
475
+ Nullable: nullable,
476
+ iskey: iskey,
477
+ isComplex: isComplex,
478
+ isNavigation: isNav,
479
+ isCollection: $.inArray(props[j].name, entityValues) >= 0
480
+ });
481
+ }
482
+
483
+ if(entities[entityType]) {
484
+ mdata[entities[entityType]] = cols;
485
+ }
486
+ mdata[entityType] = cols;
487
+ }
488
+ }
489
+
490
+ return mdata;
491
+ }
492
+
493
+ var mdata;
494
+ switch(metadatatype) {
495
+ case 'xml':
496
+ mdata = parseXmlMetadata(rawdata);
497
+ break;
498
+ case 'json':
499
+ mdata = parseJsonMetadata(rawdata);
500
+ break;
501
+ case 'datajs':
502
+ mdata = parseDataJSMetadata(rawdata);
503
+ break;
504
+ }
505
+
506
+ return mdata;
507
+ },
508
+
509
+ loadError: function (jqXHR, textStatus, errorThrown) {
510
+ var status = jqXHR.status;
511
+ var title = textStatus;
512
+ var message = errorThrown;
513
+
514
+ if (!jqXHR.responseJSON) {
515
+ if (jqXHR.responseXML) {
516
+ jqXHR.responseText = jqXHR.responseText.replace(/<(\/?)([^:>\s]*:)?([^>]+)>/g, "<$1$3>");
517
+ jqXHR.responseXML = $.parseXML(jqXHR.responseText);
518
+ jqXHR.responseJSON = $.jgrid.odataHelper.convertXmlToJson(jqXHR.responseXML);
519
+ }
520
+ else if (jqXHR.responseText) {
521
+ try {
522
+ jqXHR.responseJSON = $.parseJSON(jqXHR.responseText);
523
+ }
524
+ catch (ignore) {
525
+ }
526
+ }
527
+ }
528
+
529
+ if (jqXHR.responseJSON) {
530
+ var odataerr = jqXHR.responseJSON["@odata.error"] || jqXHR.responseJSON["odata.error"] || jqXHR.responseJSON.error;
531
+ if (odataerr) {
532
+ if (odataerr.innererror) {
533
+ if (odataerr.innererror.internalexception) {
534
+ title = odataerr.innererror.internalexception.message;
535
+ message = odataerr.innererror.internalexception.stacktrace || '';
536
+ }
537
+ else {
538
+ title = odataerr.innererror.message;
539
+ message = odataerr.innererror.stacktrace || '';
540
+ }
541
+ }
542
+ else {
543
+ title = odataerr.message.value || odataerr.message;
544
+ message = odataerr.stacktrace || '';
545
+ }
546
+ }
547
+ }
548
+ else if (errorThrown && $.isPlainObject(errorThrown)) {
549
+ title = errorThrown.message;
550
+ message = errorThrown.stack;
551
+ status = errorThrown.code;
552
+ }
553
+
554
+ var errstring = "<div>Status/error code: " + status + "</div><div>Message: " + title + '</div><div style="font-size: 0.8em;">' + message + '</div><br/>';
555
+
556
+ return errstring;
557
+ }
558
+ };
559
+
560
+ $.jgrid.cmTemplate.odataComplexType = {
561
+ editable: false,
562
+ formatter: function (cellvalue, options, rowObject) {
563
+ return $(this).jqGrid('odataJson', cellvalue, options, rowObject);
564
+ }
565
+ };
566
+
567
+ $.jgrid.cmTemplate.odataNavigationProperty = {
568
+ editable: false,
569
+ formatter: function (cellvalue, options, rowObject) {
570
+ if (!options.colModel.odata.expand || options.colModel.odata.expand === 'link') {
571
+ return $(this).jqGrid('odataLink', cellvalue, options, rowObject);
572
+ }
573
+ if (options.colModel.odata.expand === 'json') {
574
+ return $(this).jqGrid('odataJson', cellvalue, options, rowObject);
575
+ }
576
+ if (options.colModel.odata.expand === 'subgrid') {
577
+ return $(this).jqGrid('odataSubgrid', cellvalue, options, rowObject);
578
+ }
579
+ }
580
+ };
581
+
582
+ $.jgrid.cmTemplate["Edm.GeographyPoint"] = {
583
+ editable: false,
584
+ formatter: function (cellvalue, options, rowObject) {
585
+ if (!cellvalue && this.p.datatype === 'xml') {
586
+ var xmlvalue = $(rowObject).filter(function () {
587
+ return this.localName.toLowerCase() === options.colModel.name.toLowerCase();
588
+ });
589
+ cellvalue = $.jgrid.odataHelper.convertXmlToJson(xmlvalue[0]);
590
+ }
591
+
592
+ if (cellvalue.crs && cellvalue.coordinates) {
593
+ return $.jgrid.format('<div>{0}</div><div>[{1},{2}]</div>', cellvalue.crs.properties.name, cellvalue.coordinates[0], cellvalue.coordinates[1]);
594
+ }
595
+
596
+ return $.jgrid.format('<div>{0}</div>', cellvalue);
597
+ }
598
+ };
599
+
600
+ $.jgrid.extend({
601
+ odataLink: function (cellvalue, options, rowObject) {
602
+ var keyValue, result, $p = this[0].p;
603
+ if ($p.datatype !== 'xml') {
604
+ if (rowObject[options.colModel.name + '@odata.navigationLink']) {
605
+ keyValue = rowObject[options.colModel.name + '@odata.navigationLink'];
606
+ result = $.jgrid.format('<a href="{0}/{1}" target="_self">{2}</a>', $p.odata.baseUrl, keyValue, options.colModel.name);
607
+ return result;
608
+ }
609
+
610
+ keyValue = rowObject[$p.jsonReader.id];
611
+ }
612
+ else {
613
+ keyValue = (function (id) {
614
+ return $(rowObject).filter(function () {
615
+ return this.localName && this.localName.toLowerCase() === id;
616
+ }).text();
617
+ }($p.xmlReader.id.toLowerCase()));
618
+ }
619
+
620
+ if ($p.odata.iscollection) {
621
+ result = $.jgrid.format('<a href="{0}({1})/{2}" target="_self">{2}</a>', $p.url, keyValue, options.colModel.name);
622
+ }
623
+ else {
624
+ result = $.jgrid.format('<a href="{0}/{1}" target="_self">{1}</a>', $p.url, options.colModel.name);
625
+ }
626
+
627
+ return result;
628
+ },
629
+
630
+ odataJson: function (cellvalue, options, rowObject) {
631
+ var i, result, $p = this[0].p, tmpObj = {};
632
+ if ($p.datatype === 'xml') {
633
+ var xmlvalue = $(rowObject).filter(function () {
634
+ return this.localName.toLowerCase() === options.colModel.name.toLowerCase();
635
+ });
636
+ cellvalue = $.jgrid.odataHelper.convertXmlToJson(xmlvalue[0]);
637
+ }
638
+
639
+ for (i in cellvalue) {
640
+ if (cellvalue.hasOwnProperty(i) && i && i.indexOf('@odata.') < 0 && i.indexOf('@attributes') < 0) {
641
+ tmpObj[i] = cellvalue[i];
642
+ }
643
+ }
644
+
645
+ result = JSON.stringify(tmpObj, null, 1);
646
+ return result;
647
+ },
648
+
649
+ odataSubgrid: function (cellvalue, options, rowObject) {
650
+ var i, keyValue, result, $p = this[0].p;
651
+ if ($p.datatype !== 'xml') {
652
+ keyValue = rowObject[$p.jsonReader.id];
653
+ }
654
+ else {
655
+ keyValue = (function (id) {
656
+ return $(rowObject).filter(function () {
657
+ return this.localName && this.localName.toLowerCase() === id;
658
+ }).text();
659
+ }($p.xmlReader.id.toLowerCase()));
660
+ }
661
+
662
+ for (i in $p._index) {
663
+ if ($p._index.hasOwnProperty(i) && i && keyValue === $p._index[i].toString()) {
664
+ keyValue = i;
665
+ break;
666
+ }
667
+ }
668
+
669
+ var onclick = '\'$(\"#{2}\").jqGrid(\"setGridParam\", { odata: {activeEntitySet: \"{1}\" } });$(\"#{2}\").jqGrid(\"expandSubGridRow\", \"{0}\");return false;\'';
670
+ result = '<a style="cursor:pointer" data-id="{0}" onclick=' + onclick + '>{1}</a>';
671
+ result = $.jgrid.format(result, keyValue, options.colModel.name, options.gid);
672
+ return result;
673
+ },
674
+
675
+ parseColumns: function (cols, expandable) {
676
+ var i = 0, isInt, isNum, isDate, isBool, cmTemplate, newcol = [], searchrules, searchtype, label;
677
+ var intTypes = 'Edm.Int16,Edm.Int32,Edm.Int64';
678
+ var numTypes = 'Edm.Decimal,Edm.Double,Edm.Single';
679
+ var boolTypes = 'Edm.Byte,Edm.SByte';
680
+
681
+ for (i = 0; i < cols.length; i++) {
682
+ isInt = intTypes.indexOf(cols[i].Type) >= 0;
683
+ isNum = numTypes.indexOf(cols[i].Type) >= 0;
684
+ isBool = boolTypes.indexOf(cols[i].Type) >= 0;
685
+ isDate = cols[i].Type && (cols[i].Type.indexOf('Edm.') >= 0 && (cols[i].Type.indexOf('Date') >= 0 || cols[i].Type.indexOf('Time') >= 0));
686
+ cmTemplate =
687
+ $.jgrid.cmTemplate[cols[i].Type] ? cols[i].Type :
688
+ cols[i].isComplex ? 'odataComplexType' :
689
+ cols[i].isNavigation ? 'odataNavigationProperty' :
690
+ isInt ? 'integerStr' :
691
+ isNum ? 'numberStr' :
692
+ isBool ? 'booleanCheckbox' :
693
+ 'text';
694
+
695
+ searchrules = { integer: isInt, number: isNum, date: isDate, required: !cols[i].Nullable || cols[i].Nullable === 'false' };
696
+ searchtype = isInt ? 'integer' : isNum ? 'number' : isDate ? 'datetime' : isBool ? 'checkbox' : 'text';
697
+ label = (cols[i].isNavigation || cols[i].isComplex) ?
698
+ '<span class="ui-icon ui-icon-arrowreturn-1-s" style="display:inline-block;vertical-align:middle;"></span>' + cols[i].Name : cols[i].Name;
699
+
700
+ newcol.push($.extend({
701
+ label: label,
702
+ name: cols[i].Name,
703
+ index: cols[i].Name,
704
+ editable: !cols[i].isNavigation && !cols[i].iskey,
705
+ searchrules: searchrules,
706
+ editrules: searchrules,
707
+ searchtype: searchtype,
708
+ inputtype: searchtype,
709
+ edittype: searchtype,
710
+ key: cols[i].iskey,
711
+ odata: {
712
+ expand: cols[i].isNavigation ? expandable : cols[i].isComplex ? 'json' : null,
713
+ isnavigation: cols[i].isNavigation,
714
+ iscomplex: cols[i].isComplex,
715
+ iscollection: cols[i].isCollection
716
+ }
717
+ }, $.jgrid.cmTemplate[cmTemplate]));
718
+ }
719
+
720
+ return newcol;
721
+ },
722
+
723
+ odataInit: function (options) {
724
+ // builds out OData expressions... the condition.
725
+ function prepareExpression(p, searchField, searchString, searchOper) {
726
+ var i, col;
727
+
728
+ // if we want to support "in" clauses, we need to follow this stackoverflow article:
729
+ //http://stackoverflow.com/questions/7745231/odata-where-id-in-list-query/7745321#7745321
730
+ // this is for basic searching, with a single term.
731
+ if (searchField && (searchString || searchOper === 'nu' || searchOper === 'nn')) {
732
+ if (searchString) {
733
+ //append '' when searched field is of the string type
734
+ for (i = 0; i < p.colModel.length; i++) {
735
+ col = p.colModel[i];
736
+ if (col.name === searchField) {
737
+ if (col.odata.nosearch) { return; }
738
+ if (col.odata.unformat) {
739
+ searchField = $.jgrid.isFunction(col.odata.unformat) ? col.odata.unformat(searchField, searchString, searchOper) : col.odata.unformat;
740
+ if (!searchField) { return; }
741
+ }
742
+ if (!col.searchrules || (!col.searchrules.integer && !col.searchrules.number && !col.searchrules.date)) {
743
+ searchString = "'" + searchString + "'";
744
+ }
745
+ else if (col.searchrules && col.searchrules.date) {
746
+ searchString = (new Date(searchString)).toISOString();
747
+ //v3: postData.searchString = "datetimeoffset'" + postData.searchString + "'";
748
+ //v2: postData.searchString = "DateTime'" + postData.searchString + "'";
749
+ }
750
+
751
+ break;
752
+ }
753
+ }
754
+ }
755
+
756
+ switch (searchOper) {
757
+ case "in": // is in
758
+ case "cn": // contains
759
+ //return "substringof(" + searchString + ", " + searchField + ") eq true";
760
+ return "indexof(" + searchField + ",tolower(" + searchString + ")) gt -1";
761
+ case "ni": // is not in
762
+ case "nc": // does not contain.
763
+ //return "substringof(" + searchString + ", " + searchField + ") eq false";
764
+ return "indexof(" + searchField + ",tolower(" + searchString + ")) eq -1";
765
+ case "bw": // begins with
766
+ return "startswith(" + searchField + "," + searchString + ") eq true";
767
+ case "bn": // does not begin with
768
+ return "startswith(" + searchField + "," + searchString + ") eq false";
769
+ case "ew": // ends with
770
+ return "endswith(" + searchField + "," + searchString + ") eq true";
771
+ case "en": // does not end with.
772
+ return "endswith(" + searchField + "," + searchString + ") eq false";
773
+ case "nu": // is null
774
+ return searchField + " eq null";
775
+ case "nn": // is not null
776
+ return searchField + " ne null";
777
+ default: // eq,ne,lt,le,gt,ge,
778
+ return searchField + " " + searchOper + " " + searchString;
779
+ }
780
+ }
781
+ }
782
+
783
+ // when dealing with the advanced query dialog, this parses the encapsulating Json object
784
+ // which we will then build the advanced OData expression from.
785
+ function parseFilterGroup(filterGroup, p) {
786
+ var i, rule, filterText = "", filterRes;
787
+ if (filterGroup.groups) {
788
+ if (filterGroup.groups.length) {
789
+ for (i = 0; i < filterGroup.groups.length; i++) {
790
+ filterText += "(" + parseFilterGroup(filterGroup.groups[i], p) + ")";
791
+
792
+ if (i < filterGroup.groups.length - 1) {
793
+ filterText += " " + filterGroup.groupOp.toLowerCase() + " ";
794
+ }
795
+ }
796
+
797
+ if (filterGroup.rules && filterGroup.rules.length) {
798
+ filterText += " " + filterGroup.groupOp.toLowerCase() + " ";
799
+ }
800
+ }
801
+ }
802
+
803
+ if (filterGroup.rules.length) {
804
+ for (i = 0; i < filterGroup.rules.length; i++) {
805
+ rule = filterGroup.rules[i];
806
+
807
+ filterRes = prepareExpression(p, rule.field, rule.data, rule.op);
808
+ if (filterRes) {
809
+ filterText += filterRes + " " + filterGroup.groupOp.toLowerCase() + " ";
810
+ }
811
+ }
812
+ }
813
+
814
+ filterText = filterText.trim().replace(/\s(and|or)$/, '').trim();
815
+
816
+ return filterText;
817
+ }
818
+
819
+ function setupWebServiceData(p, o, postData) {
820
+ var params = {};
821
+
822
+ //var expandlist = p.colModel.filter(function(itm) { return itm.odata && itm.odata.isnavigation && (itm.odata.expand === 'json' || itm.odata.expand === 'subgrid'); });
823
+ //if(expandlist.length > 0) {
824
+ // params.$expand = expandlist.reduce(function(x,y) { return x+','+ y.name; }, '').substring(1);
825
+ //}
826
+
827
+ //Query options $orderby, $count, $skip and $top cannot be applied to the requested resource
828
+ if (!p.odata.iscollection) {
829
+ if (!o.version || o.version < 4) {
830
+ params.$format = o.datatype === 'xml' ? 'atom' : 'application/json;odata=fullmetadata';
831
+ }
832
+ else {
833
+ params.$format = o.datatype === 'xml' ? 'atom' : 'application/json;odata.metadata=full';
834
+ }
835
+
836
+ return params;
837
+ }
838
+
839
+ params = {
840
+ $top: postData.rows, //- $top removes odata.nextLink parameter
841
+ $skip: (parseInt(postData.page, 10) - 1) * p.rowNum
842
+ };
843
+
844
+ if (o.datatype === 'jsonp') { params.$callback = o.callback; }
845
+ if (!o.version || o.version < 4) {
846
+ params.$inlinecount = "allpages";
847
+ params.$format = o.datatype === 'xml' ? 'atom' : 'application/json;odata=fullmetadata';
848
+ }
849
+ else {
850
+ params.$count = true;
851
+ params.$format = o.datatype === 'xml' ? 'atom' : 'application/json;odata.metadata=full';
852
+ }
853
+
854
+ // if we have an order-by clause to use, then we build it.
855
+ if (postData.sidx) {
856
+ // two columns have the following data:
857
+ // postData.sidx = "{ColumnName} {order}, {ColumnName} "
858
+ // postData.sord = "{order}"
859
+ // we need to split sidx by the ", " and see if there are multiple columns. If there are, we need to go through
860
+ // each column and get its parts, then parse that for the appropriate columns to build for the sort.
861
+
862
+ params.$orderby = postData.sidx + " " + postData.sord;
863
+ }
864
+
865
+ if (!postData._search) { return params; }
866
+
867
+ // complex searching, with a groupOp. This is for if we enable the form for multiple selection criteria.
868
+ if (postData.filters) {
869
+ var filterGroup = $.parseJSON(postData.filters);
870
+ var groupSearch = parseFilterGroup(filterGroup, p);
871
+
872
+ if (groupSearch.length > 0) {
873
+ params.$filter = groupSearch;
874
+ }
875
+ }
876
+ else {
877
+ params.$filter = prepareExpression(p, postData.searchField, postData.searchString, postData.searchOper);
878
+ }
879
+
880
+ return params;
881
+ }
882
+
883
+ function subgridRowExpanded(p, o, subgrid_id, row_id) {
884
+ //var rowObject = $(this).jqGrid('getRowData', row_id, p.odata.activeEntitySet), result;
885
+ //var rowObject = p.data[p._index[row_id]][p.odata.activeEntitySet], result;
886
+ var result, colModel = p.colModel.filter(function (itm) { return itm.name === p.odata.activeEntitySet; })[0];
887
+ row_id = p._index[row_id];
888
+
889
+ if (p.odata.iscollection) {
890
+ result = $.jgrid.format('{0}({1})/{2}', p.url, row_id, p.odata.activeEntitySet);
891
+ }
892
+ else {
893
+ result = $.jgrid.format('{0}/{1}', p.url, p.odata.activeEntitySet);
894
+ }
895
+
896
+ var odatainit = {
897
+ datatype: o.datatype,
898
+ version: o.version,
899
+ gencolumns: false,
900
+ expandable: o.expandable,
901
+ odataurl: result,
902
+ errorfunc: o.errorfunc,
903
+ annotations: o.annotations,
904
+ entitySet: p.odata.activeEntitySet
905
+ };
906
+
907
+ $("#" + subgrid_id).html('<table id="' + subgrid_id + '_t" class="scroll"></table>');
908
+ $("#" + subgrid_id + "_t").jqGrid({
909
+ colModel: p.odata.subgridCols[p.odata.activeEntitySet],
910
+ odata: $.extend({}, p.odata, colModel.odata),
911
+ loadonce: true,
912
+ beforeInitGrid: function () {
913
+ $(this).jqGrid('odataInit', odatainit);
914
+ },
915
+ loadError: function (jqXHR, textStatus, errorThrown) {
916
+ var parsedError = $.jgrid.odataHelper.loadError(jqXHR, textStatus, errorThrown);
917
+ parsedError = $('#errdialog').html() + parsedError;
918
+ $('#errdialog').html(parsedError).dialog('open');
919
+ }
920
+ });
921
+ }
922
+
923
+ function initDefaults(p, o) {
924
+ var i, defaultGetAjaxOptions = {
925
+ datatype: o.datatype,
926
+ jsonpCallback: o.callback
927
+ },
928
+ subGridRowExpandedFunc = function (subgrid_id, row_id) {
929
+ return subgridRowExpanded(p, o, subgrid_id, row_id);
930
+ };
931
+
932
+ if (!p.odata) { p.odata = { iscollection: true }; }
933
+
934
+ $.extend(p, {
935
+ serializeGridData: function (postData) {
936
+ postData = setupWebServiceData(p, o, postData);
937
+ this.p.odata.postData = postData;
938
+ return postData;
939
+ },
940
+ ajaxGridOptions: defaultGetAjaxOptions,
941
+ mtype: 'GET',
942
+ url: o.odataurl
943
+ }, defaultGetAjaxOptions);
944
+
945
+ if (p.colModel) {
946
+ for (i = 0; i < p.colModel.length; i++) {
947
+ if (p.colModel[i].odata && p.colModel[i].odata.expand === 'subgrid') {
948
+ p.subGrid = true;
949
+ p.subGridRowExpanded = subGridRowExpandedFunc;
950
+ p.odata.activeEntitySet = p.colModel[i].name;
951
+ p.loadonce = true;
952
+
953
+ break;
954
+ }
955
+ }
956
+ }
957
+
958
+ var defaultAjaxOptions = {
959
+ contentType: 'application/' + (o.datatype === 'jsonp' ? 'json' : o.datatype) + ';charset=utf-8',
960
+ datatype: (o.datatype === 'jsonp' ? 'json' : o.datatype)
961
+ };
962
+
963
+ p.inlineEditing = $.extend(true, {
964
+ beforeSaveRow: function (options, rowid) {
965
+ if (options.extraparam.oper === 'edit') {
966
+ options.url = o.odataurl;
967
+ options.mtype = o.odataverbs.inlineEditingEdit;
968
+ options.url += '(' + rowid + ')';
969
+ }
970
+ else {
971
+ options.url = o.odataurl;
972
+ options.mtype = o.odataverbs.inlineEditingAdd;
973
+ }
974
+
975
+ return true;
976
+ },
977
+ serializeSaveData: function (postdata) {
978
+ return JSON.stringify(postdata);
979
+ },
980
+ ajaxSaveOptions: defaultAjaxOptions
981
+ }, p.inlineEditing || {});
982
+
983
+ $.extend(p.formEditing, {
984
+ onclickSubmit: function (options, postdata, frmoper) {
985
+ if (frmoper === 'add') {
986
+ options.url = o.odataurl;
987
+ options.mtype = o.odataverbs.formEditingAdd;
988
+ }
989
+ else if (frmoper === 'edit') {
990
+ options.url = o.odataurl + '(' + postdata[p.id + "_id"] + ')';
991
+ options.mtype = o.odataverbs.formEditingEdit;
992
+ }
993
+
994
+ return postdata;
995
+ },
996
+ ajaxEditOptions: defaultAjaxOptions,
997
+ serializeEditData: function (postdata) {
998
+ return JSON.stringify(postdata);
999
+ }
1000
+ });
1001
+
1002
+ $.extend(p.formDeleting, {
1003
+ url: o.odataurl,
1004
+ mtype: "DELETE",
1005
+ serializeDelData: function () {
1006
+ return "";
1007
+ },
1008
+ onclickSubmit: function (options, postdata) {
1009
+ options.url += '(' + postdata + ')';
1010
+ return '';
1011
+ },
1012
+ ajaxDelOptions: defaultAjaxOptions
1013
+ });
1014
+
1015
+ var keyName = p.colModel.filter(function (itm) { return !!itm.key; })[0];
1016
+ keyName = keyName ? keyName.name : (p.sortname || 'id');
1017
+
1018
+ if (o.datatype === 'xml') {
1019
+ if (o.annotations) {
1020
+ $.extend(true, p, {
1021
+ loadBeforeSend: function (jqXHR) {
1022
+ jqXHR.setRequestHeader("Prefer", 'odata.include-annotations="*"');
1023
+ }
1024
+ });
1025
+ }
1026
+
1027
+ var root = '>feed';
1028
+ var entry = '>entry';
1029
+ var cell = '>content>properties';
1030
+
1031
+ $.extend(true, p, {
1032
+ xmlReader: {
1033
+ root: function (data) {
1034
+ data = data.childNodes[0];
1035
+ data.innerHTML = data.innerHTML.replace(/<(\/?)([^:>\s]*:)?([^>]+)>/g, "<$1$3>");
1036
+
1037
+ var param = $(data).attr('m:context');
1038
+ if (param) {
1039
+ p.odata.baseUrl = param.substring(0, param.indexOf('/$metadata'));
1040
+ p.odata.entityType = param.substring(param.indexOf('#') + 1).replace('/$entity', '');
1041
+ }
1042
+
1043
+ param = $(data).attr('m:type');
1044
+ if (param) {
1045
+ p.odata.entityType = param.replace('#', '');
1046
+ }
1047
+
1048
+ return data;
1049
+ },
1050
+ row: function (data) {
1051
+ if (data.localName === 'entry') {
1052
+ data = [data];
1053
+ }
1054
+ else {
1055
+ data = $(entry, data);
1056
+ }
1057
+
1058
+ return data;
1059
+ },
1060
+ cell: function (data) {
1061
+ return $(cell, data).get(0).childNodes;
1062
+ },
1063
+ records: function (data) {
1064
+ return $(root + entry, data).length; //$('count', data).text()
1065
+ },
1066
+ page: function () {
1067
+ var skip = p.odata.postData.$skip + p.rowNum;
1068
+ return Math.ceil(skip / p.rowNum);
1069
+ },
1070
+ total: function (data) {
1071
+ var records = $(root + entry, data).length; //$('count', data).text()
1072
+ var skip = p.odata.postData.$skip + p.rowNum;
1073
+ return Math.ceil(skip / p.rowNum) + (records > 0 ? 1 : 0);
1074
+ },
1075
+ repeatitems: true,
1076
+ userdata: 'userdata',
1077
+ id: keyName
1078
+ }
1079
+ });
1080
+ }
1081
+ else {
1082
+ $.extend(true, p, {
1083
+ jsonReader: {
1084
+ root: function (data) {
1085
+ var param = data['@odata.context'];
1086
+ if (param) {
1087
+ p.odata.baseUrl = param.substring(0, param.indexOf('/$metadata'));
1088
+ p.odata.entityType = param.substring(param.indexOf('#') + 1).replace('/$entity', '');
1089
+ }
1090
+
1091
+ param = data['@odata.type'];
1092
+ if (param) {
1093
+ p.odata.entityType = param.replace('#', '');
1094
+ }
1095
+
1096
+ //data = $.jgrid.odataHelper.resolveJsonReferences(data);
1097
+ return data.value || [data];
1098
+ },
1099
+ repeatitems: true,
1100
+ id: keyName
1101
+ }
1102
+ });
1103
+
1104
+ if (o.annotations) {
1105
+ $.extend(true, p, {
1106
+ loadBeforeSend: function (jqXHR) {
1107
+ jqXHR.setRequestHeader("Prefer", 'odata.include-annotations="*"');
1108
+ },
1109
+ jsonReader: {
1110
+ records: function (data) {
1111
+ return data[o.annotationName].records;
1112
+ },
1113
+ page: function (data) { return data[o.annotationName].page; },
1114
+ total: function (data) { return data[o.annotationName].total; },
1115
+ userdata: function (data) { return data[o.annotationName].userdata; }
1116
+ }
1117
+ });
1118
+ }
1119
+ else {
1120
+ $.extend(true, p, {
1121
+ jsonReader: {
1122
+ records: function (data) { return data["odata.count"] || data["@odata.count"]; },
1123
+ page: function (data) {
1124
+ var skip;
1125
+ if (data["odata.nextLink"]) {
1126
+ skip = parseInt(data["odata.nextLink"].split('skip=')[1], 10);
1127
+ }
1128
+ else {
1129
+ skip = p.odata.postData.$skip + p.rowNum;
1130
+ var total = data["odata.count"] || data["@odata.count"];
1131
+ if (skip > total) { skip = total; }
1132
+ }
1133
+
1134
+ return Math.ceil(skip / p.rowNum);
1135
+ },
1136
+ total: function (data) {
1137
+ var total = data["odata.count"] || data["@odata.count"];
1138
+ return Math.ceil(total / p.rowNum);
1139
+ },
1140
+ userdata: "userdata"
1141
+ }
1142
+ });
1143
+ }
1144
+ }
1145
+ }
1146
+
1147
+ return this.each(function () {
1148
+ var $t = this, $self = $(this), p = this.p;
1149
+ if (!$t.grid || !p) { return; }
1150
+
1151
+ var o = $.extend(true, {
1152
+ gencolumns: false,
1153
+ odataurl: p.url,
1154
+ datatype: 'json', //json,jsonp,xml
1155
+ entitySet: null,
1156
+ annotations: false,
1157
+ annotationName: "@jqgrid.GridModelAnnotate",
1158
+ odataverbs: {
1159
+ inlineEditingAdd: 'POST',
1160
+ inlineEditingEdit: 'PATCH',
1161
+ formEditingAdd: 'POST',
1162
+ formEditingEdit: 'PUT'
1163
+ }
1164
+ }, options || {});
1165
+ if (o.datatype === 'jsonp') { o.callback = "jsonpCallback"; }
1166
+
1167
+ if (!o.entitySet) {
1168
+ if ($.jgrid.isFunction(o.errorfunc)) { o.errorfunc({}, 'entitySet cannot be empty', 0); }
1169
+ return;
1170
+ }
1171
+ if (o.gencolumns) {
1172
+ var gencol = $.extend(true, {
1173
+ parsecolfunc: null,
1174
+ parsemetadatafunc: null,
1175
+ successfunc: null,
1176
+ errorfunc: null,
1177
+ async: false,
1178
+ entitySet: null,
1179
+ metadatatype: options.datatype || 'xml',
1180
+ metadataurl: (options.odataurl || p.url) + '/$metadata'
1181
+ }, options || {});
1182
+
1183
+ if (gencol.async) {
1184
+ gencol.successfunc = function () {
1185
+ if ($t.grid.hDiv) { $t.grid.hDiv.loading = false; }
1186
+ $self.jqGrid('setGridParam', { datatype: o.datatype }).trigger('reloadGrid');
1187
+ };
1188
+
1189
+ if ($t.grid.hDiv) { $t.grid.hDiv.loading = true; }
1190
+ }
1191
+
1192
+ $self.jqGrid('odataGenColModel', gencol);
1193
+ }
1194
+
1195
+ initDefaults(p, o);
1196
+ });
1197
+ },
1198
+
1199
+ odataGenColModel: function (options) {
1200
+ var $t = this[0], p = $t.p, $self = $($t), mdata, coldata;
1201
+
1202
+ var o = $.extend(true, {
1203
+ parsecolfunc: null,
1204
+ parsemetadatafunc: null,
1205
+ successfunc: null,
1206
+ errorfunc: null,
1207
+ entitySet: null,
1208
+ metadataurl: p.url + '/$metadata',
1209
+ metadatatype: 'xml', //json,jsonp,xml
1210
+ expandable: 'link',
1211
+ async: false
1212
+ }, options || {});
1213
+ if (o.metadatatype === 'jsonp') { o.callback = "jsonpCallback"; }
1214
+
1215
+ if (!o.entitySet) {
1216
+ if ($.jgrid.isFunction(o.errorfunc)) { o.errorfunc({}, 'entitySet cannot be empty', 0); }
1217
+ return;
1218
+ }
1219
+
1220
+ $.ajax({
1221
+ url: o.metadataurl,
1222
+ type: 'GET',
1223
+ dataType: o.metadatatype,
1224
+ jsonpCallback: o.callback,
1225
+ //contentType: 'application/' + o.metadatatype + ';charset=utf-8',
1226
+ //headers: {
1227
+ //"OData-Version": "4.0"
1228
+ //"Accept": "application/json;odata=light;q=1,application/json;odata=verbose;q=0.5"
1229
+ //},
1230
+ async: o.async,
1231
+ cache: false
1232
+ })
1233
+ .done(function (data, st, xhr) {
1234
+ var i = 0, j = 0, k = 0;
1235
+
1236
+ //var data = $.parseXML(data.responseText);
1237
+ if (o.metadatatype === 'json' || o.metadatatype === 'jsonp') { data = $.jgrid.odataHelper.resolveJsonReferences(data); }
1238
+ mdata = $self.triggerHandler("jqGridODataParseMetadata", data);
1239
+ if (!mdata && $.jgrid.isFunction(o.parsemetadatafunc)) { mdata = o.parsemetadatafunc(data, st, xhr); }
1240
+ if (!mdata) {
1241
+ mdata = $.jgrid.odataHelper.parseMetadata(data, o.metadatatype);
1242
+ if (mdata) {
1243
+ coldata = $self.triggerHandler("jqGridODataParseColumns", [o, mdata]);
1244
+ if (!coldata && $.jgrid.isFunction(o.parsecolfunc)) { coldata = o.parsecolfunc(o, mdata); }
1245
+ if (!coldata) {
1246
+ coldata = {};
1247
+ for (i in mdata) {
1248
+ if (mdata.hasOwnProperty(i) && i) {
1249
+ coldata[i] = $self.jqGrid('parseColumns', mdata[i], o.expandable);
1250
+ }
1251
+ }
1252
+ }
1253
+ }
1254
+ }
1255
+ else {
1256
+ coldata = mdata;
1257
+ }
1258
+
1259
+ if (coldata) {
1260
+ for (k in coldata) {
1261
+ if (coldata.hasOwnProperty(k) && k) {
1262
+ for (i = 0; i < p.colModel.length; i++) {
1263
+ for (j = 0; j < coldata[k].length; j++) {
1264
+ if (coldata[k][j].name === p.colModel[i].name) {
1265
+ $.extend(true, coldata[k][j], p.colModel[i]);
1266
+ break;
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+ }
1272
+
1273
+ p.colModel = coldata[o.entitySet];
1274
+ if (!p.colModel) {
1275
+ if ($.jgrid.isFunction(o.errorfunc)) { o.errorfunc({ data: data, status: st, xhr: xhr }, 'EntitySet ' + o.entitySet + ' is not found'); }
1276
+ }
1277
+
1278
+ if (!p.odata) { p.odata = { iscollection: true }; }
1279
+ p.odata.subgridCols = coldata;
1280
+
1281
+ if ($.jgrid.isFunction(o.successfunc)) {
1282
+ o.successfunc();
1283
+ }
1284
+ }
1285
+ else {
1286
+ if ($.jgrid.isFunction(o.errorfunc)) { o.errorfunc({ data: data, status: st, xhr: xhr }, 'parse $metadata error'); }
1287
+ }
1288
+ })
1289
+ .fail(function (xhr, err, code) {
1290
+ if ($.jgrid.isFunction(o.errorfunc)) {
1291
+ var parsedError = $.jgrid.odataHelper.loadError(xhr, err, code);
1292
+ o.errorfunc({ xhr: xhr, error: err, code: code }, parsedError);
1293
+ }
1294
+ });
1295
+
1296
+ return coldata;
1297
+ }
1298
+
1299
+ //TODO: make function that checks allowed types of "odata.metadata"
1300
+ /*getAllowedDataTypes: function(url, callback) {
1301
+ $.ajax({
1302
+ url: url,
1303
+ type: 'HEAD'
1304
+ })
1305
+ .done(function (data, st, xhr) {
1306
+ if($.jgrid.isFunction(callback)) {
1307
+ var result = [];
1308
+ callback(result);
1309
+ }
1310
+ });
1311
+ }*/
1312
+ });
1313
+ }));