From a34e4b4ca270f022567a0f60c2cd97e51610ae98 Mon Sep 17 00:00:00 2001 From: Kendo Bot Date: Wed, 17 Jan 2018 04:59:32 +0200 Subject: [PATCH] Sync with Kendo UI Professional --- .../helpers/html-helpers/buttongroup.md | 154 ++++++++++++ .../helpers/tag-helpers/upload.md | 22 +- .../helpers/buttongroup/overview.md | 217 ++++++++++++++++ src/kendo.data.js | 1 + src/kendo.data.odata.js | 235 +++++++++++++++++- 5 files changed, 613 insertions(+), 16 deletions(-) create mode 100644 docs-aspnet-core/helpers/html-helpers/buttongroup.md create mode 100644 docs-aspnet-mvc/helpers/buttongroup/overview.md diff --git a/docs-aspnet-core/helpers/html-helpers/buttongroup.md b/docs-aspnet-core/helpers/html-helpers/buttongroup.md new file mode 100644 index 00000000000..a7314d7f7a7 --- /dev/null +++ b/docs-aspnet-core/helpers/html-helpers/buttongroup.md @@ -0,0 +1,154 @@ +--- +title: ButtonGroup +page_title: ButtonGroup | Telerik UI for ASP.NET Core HtmlHelpers +description: "Learn the basics when working with the ButtonGroup HtmlHelper for ASP.NET Core (MVC 6 or ASP.NET Core MVC)." +slug: htmlhelpers_buttongroup_aspnetcore +--- + +# ButtonGroup HtmlHelper Overview + +The ButtonGroup HtmlHelper extension is a server-side wrapper for the [Kendo UI ButtonGroup](https://demos.telerik.com/kendo-ui/buttongroup/index) widget. + +For more information on the HtmlHelper, refer to the article on the [ButtonGroup HtmlHelper for ASP.NET MVC](http://docs.telerik.com/aspnet-mvc/helpers/buttongroup/overview). + +## Getting Started + +### Initialization + +The following example demonstrates how to initialize the ButtonGroup. + +###### Example + +``` + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` + +## Icons + +Kendo UI ButtonGroup provides a method for configuring icons - `.Icon()`. + +###### Example + +``` + @(Html.Kendo().ButtonGroup() + .Name("player") + .Items(t => + { + t.Add().Icon("play"); + t.Add().Icon("pause"); + t.Add().Icon("stop"); + })) +``` + +The above configuration is expected to produce the HTML output from the following example. + +###### Example + +
+ + + + + + + + + +
+ +## Features + +### Enable and Disable ButtonGroup + +Kendo UI ButtonGroup can be configured to be initially disabled via its `.Enable()` setting. The ButtonGroup can also be disabled or enabled at any time with JavaScript by using its `.Enable()` method with a Boolean argument. + +The example below demonstrates how to enable and disable the ButtonGroup. + +The following example demonstrates how to use `.Enable()`. + +###### Example + +``` + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Enable(false) + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` + +For more information on the [`enable` method of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup#methods-enable), refer to the [API of the ButtonGroup control](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup). + +### Index + +Initially selected index of the Kendo UI ButtonGroup can be configured via its `index` property. An index could be selected via `select()` method with a Integer argument. + +The example below demonstrates how to select a button by its index. + +###### Example + +``` + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Index(1) + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` + +For more information on the [`index` setting of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup#configuration-index), refer to the [API of the ButtonGroup control](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup). + + +### Selection + +Kendo UI ButtonGroup can restrict the numbers of Buttons that can be selected via its `.Selection()` property. It can be configured with `single` or `multiple` selection. + +The following example demonstrates how to use `.Selection()`. + +###### Example + +``` + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Selection("multiple") + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` + +For more information on the [`selection` setting of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup#configuration-selection), refer to the [API of the ButtonGroup control](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup). + +## Reference + +### Existing Instances + +For more information on how to access an instance, refer to the [introductory article on the ButtonGroup](http://docs.telerik.com/kendo-ui/controls/navigation/buttongroup/overview). + +## See Also + +* [JavaScript API Reference of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup) +* [ButtonGroup HtmlHelper for ASP.NET MVC](http://docs.telerik.com/aspnet-mvc/helpers/buttongroup/overview) +* [ButtonGroup Official Demos](http://demos.telerik.com/aspnet-core/buttongroup/index) +* [Overview of Telerik UI for ASP.NET Core]({% slug overview_aspnetmvc6_aspnetmvc %}) +* [Get Started with Telerik UI for ASP.NET Core in ASP.NET Core Projects]({% slug gettingstarted_aspnetmvc6_aspnetmvc %}) +* [Get Started with Telerik UI for ASP.NET Core in ASP.NET Core Projects on Linux]({% slug gettingstartedlinux_aspnetmvc6_aspnetmvc %}) +* [Known Issues with Telerik UI for ASP.NET Core]({% slug knownissues_aspnetmvc6_aspnetmvc %}) diff --git a/docs-aspnet-core/helpers/tag-helpers/upload.md b/docs-aspnet-core/helpers/tag-helpers/upload.md index 8b9b130bcbb..0fd6c9d4876 100644 --- a/docs-aspnet-core/helpers/tag-helpers/upload.md +++ b/docs-aspnet-core/helpers/tag-helpers/upload.md @@ -16,16 +16,16 @@ The following example demonstrates how to define the Upload by using the Upload > **Important** > -> A change in the Upload's tag names has been introduced in R1 2018, in order to ensure tag naming consistency across the Telerik UI for ASP.NET Core suite. Since R1 2018 release the ` tag name has been changed to ``, `` to ``, `` to ``, `` to ``, `` to ``. +> A change in the Upload's tag names has been introduced in R1 2018, in order to ensure tag naming consistency across the Telerik UI for ASP.NET Core suite. Since R1 2018 release the `` tag name has been changed to ``, `` to ``, `` to ``, `` to ``, `` to ``. ###### Example - - - - - + + + + + @@ -46,11 +46,11 @@ The Upload tag helper configuration options are passed as attributes of the tag ``` ```tab-tagHelper - - - - - + + + + + ``` diff --git a/docs-aspnet-mvc/helpers/buttongroup/overview.md b/docs-aspnet-mvc/helpers/buttongroup/overview.md new file mode 100644 index 00000000000..2094a925703 --- /dev/null +++ b/docs-aspnet-mvc/helpers/buttongroup/overview.md @@ -0,0 +1,217 @@ +--- +title: Overview +page_title: Overview | Kendo UI ButtonGroup HtmlHelper +description: "Get started with the server-side wrapper for the Kendo UI ButtonGroup widget for ASP.NET MVC." +slug: overview_buttongrouphelper_aspnetmvc +position: 1 +--- + +# ButtonGroup HtmlHelper Overview + +The ButtonGroup HtmlHelper extension is a server-side wrapper for the [Kendo UI ButtonGroup](https://demos.telerik.com/kendo-ui/buttongroup/index) widget. + +Make sure you are familiar with the fundamental Kendo UI widget concepts and that the [Kendo UI MVC wrappers]({% slug overview_aspnetmvc %}) are set up correctly. + +## Getting Started + +### Initialization + +The following example demonstrates how to initialize the ButtonGroup. + +###### Example + +```tab-Razor + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` +```tab-ASPX + + <%= Html.Kendo().ButtonGroup() + .Name("select-period") + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + }) %> +``` + +## Icons + +Kendo UI ButtonGroup provides a method for configuring icons - `.Icon()`. + +###### Example + +```tab-Razor + + @(Html.Kendo().ButtonGroup() + .Name("player") + .Items(t => + { + t.Add().Icon("play"); + t.Add().Icon("pause"); + t.Add().Icon("stop"); + })) +``` +```tab-ASPX + + <%= Html.Kendo().ButtonGroup() + .Name("player") + .Items(t => + { + t.Add().Icon("play"); + t.Add().Icon("pause"); + t.Add().Icon("stop"); + }) %> +``` + +The above configuration is expected to produce the HTML output from the following example. + +###### Example + +
+ + + + + + + + + +
+ +## Features + +### Enable and Disable ButtonGroup + +Kendo UI ButtonGroup can be configured to be initially disabled via its `.Enable()` setting. The ButtonGroup can also be disabled or enabled at any time with JavaScript by using its `.Enable()` method with a Boolean argument. + +The example below demonstrates how to enable and disable the ButtonGroup. + +The following example demonstrates how to use `.Enable()`. + +###### Example + +```tab-Razor + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Enable(false) + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` +```tab-ASPX + + <%= Html.Kendo().ButtonGroup() + .Name("select-period") + .Enable(false) + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + }) %> +``` + +For more information on the [`enable` method of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup#methods-enable), refer to the [API of the ButtonGroup control](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup). + +### Index + +Initially selected index of the Kendo UI ButtonGroup can be configured via its `index` property. An index could be selected via `select()` method with a Integer argument. + +The example below demonstrates how to select a button by its index. + +###### Example + +```tab-Razor + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Index(1) + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` +```tab-ASPX + + <%= Html.Kendo().ButtonGroup() + .Name("select-period") + .Index(1) + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + }) %> +``` + +For more information on the [`index` setting of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup#configuration-index), refer to the [API of the ButtonGroup control](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup). + + +### Selection + +Kendo UI ButtonGroup can restrict the numbers of Buttons that can be selected via its `.Selection()` property. It can be configured with `single` or `multiple` selection. + +The following example demonstrates how to use `.Selection()`. + +###### Example + +```tab-Razor + + @(Html.Kendo().ButtonGroup() + .Name("select-period") + .Selection("multiple") + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + })) +``` +```tab-ASPX + + <%= Html.Kendo().ButtonGroup() + .Name("select-period") + .Selection("multiple") + .Items(t => + { + t.Add().Text("Month"); + t.Add().Text("Quarter"); + t.Add().Text("Year"); + }) %> +``` + +For more information on the [`selection` setting of the ButtonGroup](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup#configuration-selection), refer to the [API of the ButtonGroup control](http://docs.telerik.com/kendo-ui/api/javascript/ui/buttongroup). + +## Reference + +### Existing Instances + +For more information on how to access an instance, refer to the [introductory article on the ButtonGroup](http://docs.telerik.com/kendo-ui/controls/navigation/buttongroup/overview). + +## See Also + +* [Telerik UI for ASP.NET MVC API Reference: ButtonGroupBuilder](/api/Kendo.Mvc.UI.Fluent/ButtonGroupBuilder) +* [Overview of Telerik UI for ASP.NET MVC]({% slug overview_aspnetmvc %}) +* [Fundamentals of Telerik UI for ASP.NET MVC]({% slug fundamentals_aspnetmvc %}) +* [Scaffolding in Telerik UI for ASP.NET MVC]({% slug scaffolding_aspnetmvc %}) +* [Overview of the Kendo UI ButtonGroup Widget](http://docs.telerik.com/kendo-ui/controls/navigation/buttongroup/overview) +* [Telerik UI for ASP.NET MVC API Reference Folder](/api/Kendo.Mvc/AggregateFunction) +* [Telerik UI for ASP.NET MVC HtmlHelpers Folder]({% slug overview_autocompletehelper_aspnetmvc %}) +* [Tutorials on Telerik UI for ASP.NET MVC]({% slug overview_timeefficiencyapp_aspnetmvc6 %}) +* [Telerik UI for ASP.NET MVC Troubleshooting]({% slug troubleshooting_aspnetmvc %}) diff --git a/src/kendo.data.js b/src/kendo.data.js index ad1d5240d70..ae656455c78 100644 --- a/src/kendo.data.js +++ b/src/kendo.data.js @@ -1786,6 +1786,7 @@ var __meta__ = { // jshint ignore:line }; parameterMap = options.parameterMap; + that.submit = options.submit; if (isFunction(options.push)) { that.push = options.push; diff --git a/src/kendo.data.odata.js b/src/kendo.data.odata.js index b5728842cd0..5539e3871de 100644 --- a/src/kendo.data.odata.js +++ b/src/kendo.data.odata.js @@ -13,6 +13,9 @@ var __meta__ = { // jshint ignore:line (function($, undefined) { var kendo = window.kendo, extend = $.extend, + NEWLINE = "\r\n", + DOUBLELINE = "\r\n\r\n", + isFunction = kendo.isFunction, odataFilters = { eq: "eq", neq: "ne", @@ -171,6 +174,174 @@ var __meta__ = { // jshint ignore:line } } + function hex16() { + return Math.floor((1 + Math.random()) * 0x10000).toString(16).substr(1); + } + + function createBoundary(prefix) { + return prefix + hex16() + '-' + hex16() + '-' + hex16(); + } + + function createDelimeter(boundary, close) { + var result = NEWLINE + "--" + boundary; + + if (close) { + result += "--"; + } + + return result; + } + + function createCommand(transport, item, httpVerb, command) { + var transportUrl = transport.options[command].url; + var commandPrefix = kendo.format("{0} ", httpVerb); + + if (isFunction(transportUrl)) { + return commandPrefix + transportUrl(item); + } else { + return commandPrefix + transportUrl; + } + } + + function getOperationHeader(changeset, changeId) { + var header = ""; + + header += createDelimeter(changeset, false); + header += NEWLINE + 'Content-Type: application/http'; + header += NEWLINE + 'Content-Transfer-Encoding: binary'; + header += NEWLINE + 'Content-ID: ' + changeId; + + return header; + } + + function getOperationContent(item) { + var content = ""; + + content += NEWLINE + "Content-Type: application/json;odata=minimalmetadata"; + content += NEWLINE + "Prefer: return=representation"; + content += DOUBLELINE + kendo.stringify(item); + + return content; + } + + function getOperations(collection, changeset, changeId, command, transport, skipContent) { + var requestBody = ""; + + for (var i = 0; i < collection.length; i++) { + requestBody += getOperationHeader(changeset, changeId); + requestBody += DOUBLELINE + createCommand(transport, collection[i], transport.options[command].type, command) + ' HTTP/1.1'; + if (!skipContent) { + requestBody += getOperationContent(collection[i]); + } + requestBody += NEWLINE; + changeId++; + } + + return requestBody; + } + + function processCollection(colection, boundary, changeset, changeId, transport, command, skipContent) { + var requestBody = ""; + + requestBody += getBoundary(boundary, changeset); + requestBody += getOperations(colection, changeset, changeId, command, transport, skipContent); + requestBody += createDelimeter(changeset, true); + requestBody += NEWLINE; + + return requestBody; + } + + function getBoundary(boundary,changeset) { + var requestBody = ""; + + requestBody += "--" + boundary + NEWLINE; + requestBody += "Content-Type: multipart/mixed; boundary=" + changeset + NEWLINE; + + return requestBody; + } + + function createBatchRequest(transport, colections) { + var options = {}; + var boundary = createBoundary("sf_batch_"); + var requestBody = ""; + var changeId = 0; + var batchURL = transport.options.batch.url; + var changeset = createBoundary("sf_changeset_"); + + options.type = transport.options.batch.type; + options.url = isFunction(batchURL) ? batchURL() : batchURL; + options.headers = { + "Content-Type": "multipart/mixed; boundary=" + boundary + }; + + if (colections.updated.length) { + requestBody += processCollection(colections.updated, boundary, changeset, changeId, transport, "update", false); + changeId += colections.updated.length; + changeset = createBoundary("sf_changeset_"); + } + + if (colections.destroyed.length) { + requestBody += processCollection(colections.destroyed, boundary, changeset, changeId, transport, "destroy", true); + changeId += colections.destroyed.length; + changeset = createBoundary("sf_changeset_"); + } + + if (colections.created.length) { + requestBody += processCollection(colections.created, boundary, changeset, changeId, transport, "create", false); + } + + requestBody += createDelimeter(boundary, true); + + options.data = requestBody; + + return options; + } + + function parseBatchResponse(responseText) { + var responseMarkers = responseText.match(/--changesetresponse_[a-z0-9-]+$/gm); + var markerIndex = 0; + var collections = []; + var changeBody; + var status; + var code; + var marker; + var jsonModel; + + collections.push({ models: [], passed: true }); + + for (var i = 0; i < responseMarkers.length; i++) { + marker = responseMarkers[i]; + if (marker.lastIndexOf('--', marker.length - 1)) { + if (i < responseMarkers.length - 1) { + collections.push({ models: [], passed: true }); + } + continue; + } + + if (!markerIndex) { + markerIndex = responseText.indexOf(marker); + } else { + markerIndex = responseText.indexOf(marker, markerIndex + marker.length); + } + + changeBody = responseText.substring(markerIndex, responseText.indexOf("--", markerIndex + 1)); + status = changeBody.match(/^HTTP\/1\.\d (\d{3}) (.*)$/gm).pop(); + code = kendo.parseFloat(status.match(/\d{3}/g).pop()); + + if (code >= 200 && code <= 299) { + jsonModel = changeBody.match(/\{.*\}/gm); + if (jsonModel) { + collections[collections.length - 1].models.push(JSON.parse(jsonModel[0])); + } + } else { + collections[collections.length - 1].passed = false; + } + + } + + return collections; + } + extend(true, kendo.data, { schemas: { odata: { @@ -260,13 +431,20 @@ var __meta__ = { // jshint ignore:line "odata-v4": { type: "json", data: function(data) { - data = $.extend({}, data); - stripMetadata(data); + if ($.isArray(data)) { + for (var i = 0; i < data.length; i++) { + stripMetadata(data[i]); + } + return data; + } else { + data = $.extend({}, data); + stripMetadata(data); - if (data.value) { - return data.value; + if (data.value) { + return data.value; + } + return [data]; } - return [data]; }, total: function(data) { return data["@odata.count"]; @@ -275,6 +453,9 @@ var __meta__ = { // jshint ignore:line }, transports: { "odata-v4": { + batch: { + type: "POST" + }, read: { cache: true, // to prevent jQuery from adding cache buster dataType: "json" @@ -304,6 +485,50 @@ var __meta__ = { // jshint ignore:line } return result; + }, + submit: function(e) { + var that = this; + var options = createBatchRequest(that, e.data); + var collections = e.data; + + if (!collections.updated.length && !collections.destroyed.length && !collections.created.length) { + return; + } + + $.ajax(extend(true, {}, { + success: function (response) { + var responses = parseBatchResponse(response); + var index = 0; + var current; + + if (collections.updated.length) { + current = responses[index]; + if (current.passed) { + // Pass either the obtained models or an empty array if only status codes are returned. + e.success(current.models.length ? current.models : [], "update"); + } + index++; + } + if (collections.destroyed.length) { + current = responses[index]; + if (current.passed) { + // For delete operations OData returns only status codes. + // Passing empty array to datasource will force it to correctly remove the deleted items from the pristine collection. + e.success([], "destroy"); + } + index++; + } + if (collections.created.length) { + current = responses[index]; + if (current.passed) { + e.success(current.models, "create"); + } + } + }, + error: function (response, status, error) { + e.error(response, status, error); + } + }, options)); } } }