diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml index 3984099e1e81c1bf7faac1fc4f395dc8e5af650e..342d4d0a4b83efe2dc56ce1f29586bffcdf603ab 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -43,6 +43,7 @@ <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="template" xsi:type="string">ui/grid/toolbar</item> + <item name="stickyTmpl" xsi:type="string">ui/grid/sticky/toolbar</item> </item> </argument> <bookmark name="bookmarks"> @@ -692,4 +693,13 @@ </argument> </column> </columns> + <container name="sticky"> + <argument name="data" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/grid/sticky/sticky</item> + <item name="toolbarProvider" xsi:type="string">cms_page_listing.cms_page_listing.listing_top</item> + <item name="listingProvider" xsi:type="string">cms_page_listing.cms_page_listing.cms_page_columns</item> + </item> + </argument> + </container> </listing> diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js index f37832bc8972eddc3bf8e31b4a8d095e7bcdcff0..091cd9ee2ea570a238e72a1a27cb9eb36d579322 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/actions.js @@ -2,6 +2,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'underscore', 'mageUtils', @@ -35,7 +36,7 @@ define([ */ initObservable: function () { this._super() - .observe('actions opened'); + .observe('actions'); return this; }, @@ -253,40 +254,6 @@ define([ var action = this.getAction(rowIndex, actionIndex); return _.isObject(action.callback) || action.confirm || !action.href; - }, - - /** - * Opens or closes specific actions list. - * - * @param {Number} rowIndex - Index of a row, - * where actions are displayed. - * @returns {ActionsColumn} Chainable. - */ - toggleList: function (rowIndex) { - var state = false; - - if (rowIndex !== this.opened()) { - state = rowIndex; - } - - this.opened(state); - - return this; - }, - - /** - * Closes actions list. - * - * @param {Number} rowIndex - Index of a row, - * where actions are displayed. - * @returns {ActionsColumn} - */ - closeList: function (rowIndex) { - if (this.opened() === rowIndex) { - this.opened(false); - } - - return this; } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js index 905cd7d44ebf43246d26e2327392adb0fee0bc26..b48f1c9ed8a35adc457b2f03b0190a2cb4d7c3d2 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/multiselect.js @@ -60,7 +60,6 @@ define([ this._super() .observe([ 'disabled', - 'menuVisible', 'selected', 'excluded', 'excludeMode', @@ -74,28 +73,6 @@ define([ return this; }, - /** - * Toggles menu with a list of select actions. - * - * @returns {Multiselect} Chainable. - */ - toggleMenu: function () { - this.menuVisible(!this.menuVisible()); - - return this; - }, - - /** - * Hides menu with a list of select actions. - * - * @returns {Multiselect} Chainable. - */ - hideMenu: function () { - this.menuVisible(false); - - return this; - }, - /** * Selects specified record. * diff --git a/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js b/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js index a684f5eece069704ff3361ef02eb43c7d98f6a04..8bd34bb57f6a29a6413a6405275506ca6fee1db8 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/controls/bookmarks/bookmarks.js @@ -5,10 +5,9 @@ define([ 'underscore', 'mageUtils', - 'uiRegistry', 'uiLayout', - 'Magento_Ui/js/lib/collapsible' -], function (_, utils, registry, layout, Collapsible) { + 'uiComponent' +], function (_, utils, layout, Component) { 'use strict'; /** @@ -27,7 +26,7 @@ define([ return path.join('.'); } - return Collapsible.extend({ + return Component.extend({ defaults: { template: 'ui/grid/controls/bookmarks/bookmarks', defaultIndex: 'default', diff --git a/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js b/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js index 765e437334285090378e1db15d8ac33753da9ab8..4673bedd251f7a8b3ac778b40985bff8ed7a5eb0 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/controls/columns.js @@ -6,11 +6,11 @@ define([ 'underscore', 'mageUtils', 'mage/translate', - 'Magento_Ui/js/lib/collapsible' -], function (_, utils, $t, Collapsible) { + 'uiComponent' +], function (_, utils, $t, Component) { 'use strict'; - return Collapsible.extend({ + return Component.extend({ defaults: { template: 'ui/grid/controls/columns', minVisible: 1, diff --git a/app/code/Magento/Ui/view/base/web/js/grid/dnd.js b/app/code/Magento/Ui/view/base/web/js/grid/dnd.js index 3fa06634bd42c2a69c9001ec5b559dbdc1317c16..fbcffc466f1d01583e1b470799550a8afa78e7fe 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/dnd.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/dnd.js @@ -78,6 +78,7 @@ define([ y >= area.top && y <= area.bottom ); } + /*eslint-enable no-extra-parens*/ /** @@ -109,10 +110,22 @@ define([ return ko.dataFor(elem); } + /** + * Checks whether cols are identical + * + * @param {HTMLElement} c1 + * @param {HTMLElement} c2 + * @returns {Boolean} + */ + function compareCols(c1, c2) { + return c1.cellIndex === c2.cellIndex; + } + return Class.extend({ defaults: { rootSelector: '${ $.columnsProvider }:.admin__data-grid-wrap', tableSelector: '${ $.rootSelector } -> table.data-grid', + mainTableSelector: '[data-role="grid"]', columnSelector: '${ $.tableSelector } thead tr th', noSelectClass: '_no-select', hiddenClass: '_hidden', @@ -178,7 +191,7 @@ define([ * @returns {Dnd} Chainable. */ initTable: function (table) { - this.table = table; + this.table = $(table).is(this.mainTableSelector) ? table : this.table; $(table).addClass('data-grid-draggable'); @@ -263,12 +276,15 @@ define([ rect; this.coords = this.columns.map(function (column) { - var data; + var data, + colIndex = _.findIndex(cells, function (cell) { + return compareCols(cell, column); + }); rect = column.getBoundingClientRect(); data = { - index: cells.indexOf(column), + index: colIndex, target: column, orig: rect, left: rect.left - bodyRect.left, @@ -372,7 +388,7 @@ define([ this.dragleave(leavedArea); } - if (area && area.target !== this.dragArea.target) { + if (area && !compareCols(area.target, this.dragArea.target)) { this.dragenter(area); } }, @@ -479,7 +495,7 @@ define([ getModel(dragElem).dragging(false); - if (dropArea && dropArea.target !== dragElem) { + if (dropArea && !compareCols(dropArea.target, dragElem)) { this.drop(dropArea, dragArea); } }, diff --git a/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js b/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js index aab27ca0645e1f2246e5fdc07bf49096d9c846f5..9bd9d5318fef5db2c341e98c18abd6ad7bf211bc 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/editing/editor-view.js @@ -96,8 +96,10 @@ define([ * @returns {View} Chainable. */ initBulk: function (table) { + var tableBody = $('tbody', table)[0]; + $(this.bulkTmpl) - .prependTo('tbody', table) + .prependTo(tableBody) .applyBindings(this.model); return this; diff --git a/app/code/Magento/Ui/view/base/web/js/grid/export.js b/app/code/Magento/Ui/view/base/web/js/grid/export.js index 0350d156f2656ec8316d7152437a48ca93729dc5..032f5fcc36717432c9a8c0f08a41d7f9c42f5d13 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/export.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/export.js @@ -5,12 +5,11 @@ define([ 'jquery', 'underscore', - 'ko', - 'Magento_Ui/js/lib/collapsible' -], function ($, _, ko, Collapsible) { + 'uiComponent' +], function ($, _, Component) { 'use strict'; - return Collapsible.extend({ + return Component.extend({ defaults: { template: 'ui/grid/exportButton', diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js index 5af83c6ddf76f96ee751b7895c787a763ecdb588..a31b1fd2d50ad971f39ad8f4644d7bdb361cd095 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js @@ -9,7 +9,8 @@ define([ return Component.extend({ defaults: { - template: 'ui/grid/filters/chips' + template: 'ui/grid/filters/chips', + stickyTmpl: 'ui/grid/sticky/chips' }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js index b0eca130b00dfef94b2da7f276724771b61d01a0..e90dfd5984189c933635261bcfbf9d17da9dcbe8 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js @@ -6,8 +6,8 @@ define([ 'underscore', 'mageUtils', 'uiLayout', - 'Magento_Ui/js/lib/collapsible' -], function (_, utils, layout, Collapsible) { + 'uiComponent' +], function (_, utils, layout, Component) { 'use strict'; /** @@ -34,9 +34,10 @@ define([ return utils.mapRecursive(data, utils.removeEmptyValues.bind(utils)); } - return Collapsible.extend({ + return Component.extend({ defaults: { template: 'ui/grid/filters/filters', + stickyTmpl: 'ui/grid/sticky/filters', applied: { placeholder: true }, @@ -157,15 +158,6 @@ define([ return this; }, - /** - * Tells wether filters pannel should be opened. - * - * @returns {Boolean} - */ - isOpened: function () { - return this.opened() && this.hasVisible(); - }, - /** * Tells wether specified filter should be visible. * diff --git a/app/code/Magento/Ui/view/base/web/js/grid/listing.js b/app/code/Magento/Ui/view/base/web/js/grid/listing.js index 2713816a1686ac77edcca7a407fa61ff4a3a5841..7ec985fcf76a53dc540a4cd020b5a339b8e9065e 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/listing.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/listing.js @@ -2,6 +2,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'underscore', 'Magento_Ui/js/lib/spinner', @@ -13,6 +14,7 @@ define([ return Component.extend({ defaults: { template: 'ui/grid/listing', + stickyTmpl: 'ui/grid/sticky/listing', positions: false, storageConfig: { positions: '${ $.storageConfig.path }.positions' @@ -103,6 +105,11 @@ define([ return this; }, + /** + * Creates resize widget instance. + * + * @returns {Listing} Chainable. + */ initResize: function () { layout([this.resizeConfig]); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js index 871bbfbffc1624b312d6006ccf4b38599c5abb04..2e9a39b2bddd261c83c889ff1f31de99836b9544 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/massactions.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/massactions.js @@ -2,6 +2,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'underscore', 'uiRegistry', @@ -16,6 +17,8 @@ define([ return Collapsible.extend({ defaults: { template: 'ui/grid/actions', + stickyTmpl: 'ui/grid/sticky/actions', + componentType: 'massaction', selectProvider: '', actions: [], noItemsMsg: $t('You haven\'t selected any items!'), diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js b/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js index d1d61eca2b76bf231a0667d88da125f153977851..3f8c6cd8a658c3d9f660897434d1ca026033247a 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js @@ -2,6 +2,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'ko', 'underscore', @@ -14,9 +15,11 @@ define([ return Component.extend({ defaults: { template: 'ui/grid/paging/paging', + totalTmpl: 'ui/grid/paging-total', pageSize: 20, current: 1, selectProvider: '', + componentType: 'paging', sizesConfig: { component: 'Magento_Ui/js/grid/paging/sizes', diff --git a/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js b/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js index 177d1c6afe0a3b8e96f71c4e2339b27ca8f7df8e..62908da372266e90bba65a6f5c8dd368d42129c9 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js @@ -6,11 +6,11 @@ define([ 'ko', 'underscore', 'mageUtils', - 'Magento_Ui/js/lib/collapsible' -], function (ko, _, utils, Collapsible) { + 'uiComponent' +], function (ko, _, utils, Component) { 'use strict'; - return Collapsible.extend({ + return Component.extend({ defaults: { template: 'ui/grid/paging/sizes', value: 20, @@ -392,8 +392,8 @@ define([ * Listener of the 'value' property changes. */ onValueChange: function () { - this.close() - .discardAll(); + this.discardAll() + .trigger('close'); }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/grid/resize.js b/app/code/Magento/Ui/view/base/web/js/grid/resize.js index a98dd05073ba2303d37f67167d3b2e1d37baa623..cef9cb707cf7d064cea50b21c89142009fb0c087 100644 --- a/app/code/Magento/Ui/view/base/web/js/grid/resize.js +++ b/app/code/Magento/Ui/view/base/web/js/grid/resize.js @@ -18,6 +18,7 @@ define([ defaults: { rootSelector: '${ $.columnsProvider }:.admin__data-grid-wrap', tableSelector: '${ $.rootSelector } -> table.data-grid', + mainTableSelector: '[data-role="grid"]', columnSelector: '${ $.tableSelector } thead tr th', fieldSelector: '${ $.tableSelector } tbody tr td', @@ -84,10 +85,15 @@ define([ * @returns {Object} Chainable */ initTable: function (table) { - this.table = table; - this.tableWidth = $(table).outerWidth(); + if ($(table).is(this.mainTableSelector)) + { + this.table = table; + this.tableWidth = $(table).outerWidth(); + $(window).resize(this.checkAfterResize); + } + $(table).addClass(this.fixedLayoutClass); - $(window).resize(this.checkAfterResize); + return this; }, @@ -202,15 +208,17 @@ define([ */ initColumn: function (column) { var model = ko.dataFor(column), + ctxIndex = this.getCtxIndex(ko.contextFor(column)), table = this.table; model.width = this.getDefaultWidth(column); - if (!this.hasColumn(model, false)) { + if (!this.hasColumn(model, ctxIndex, false)) { + this.columnsElements[model.index] = this.columnsElements[model.index] || {}; + this.columnsElements[model.index][ctxIndex] = column; this.initResizableElement(column); - this.columnsElements[model.index] = column; - $(column).outerWidth(model.width); this.setStopPropagationHandler(column); + $(column).outerWidth(model.width); } this.refreshLastColumn(column); @@ -383,7 +391,7 @@ define([ _canResize: function (column) { if ( $(column).hasClass(this.visibleClass) || - !$(this.resizeConfig.depResizeElem.elem).find('.' + this.resizableElementClass).length + !$(this.resizeConfig.depResizeElem.elems[0]).find('.' + this.resizableElementClass).length ) { return false; } @@ -406,11 +414,11 @@ define([ event.stopImmediatePropagation(); cfg.curResizeElem.model = ko.dataFor(column); cfg.curResizeElem.ctx = ko.contextFor(column); - cfg.curResizeElem.elem = this.hasColumn(cfg.curResizeElem.model, true); + cfg.curResizeElem.elems = this.hasColumn(cfg.curResizeElem.model, false, true); cfg.curResizeElem.position = event.pageX; - cfg.depResizeElem.elem = this.getNextElement(cfg.curResizeElem.elem); - cfg.depResizeElem.model = ko.dataFor(cfg.depResizeElem.elem); - cfg.depResizeElem.ctx = ko.contextFor(cfg.depResizeElem.elem); + cfg.depResizeElem.elems = this.getNextElements(cfg.curResizeElem.elems[0]); + cfg.depResizeElem.model = ko.dataFor(cfg.depResizeElem.elems[0]); + cfg.depResizeElem.ctx = ko.contextFor(cfg.depResizeElem.elems[0]); this._setResizeClass(); @@ -420,8 +428,8 @@ define([ event.stopPropagation(); this.resizable = true; - cfg.curResizeElem.model.width = $(cfg.curResizeElem.elem).outerWidth(); - cfg.depResizeElem.model.width = $(cfg.depResizeElem.elem).outerWidth(); + cfg.curResizeElem.model.width = $(cfg.curResizeElem.elems[0]).outerWidth(); + cfg.depResizeElem.model.width = $(cfg.depResizeElem.elems[0]).outerWidth(); body.addClass(this.inResizeClass); body.bind('mousemove', this.mousemoveHandler); $(window).bind('mouseup', this.mouseupHandler); @@ -435,7 +443,8 @@ define([ */ mousemoveHandler: function (event) { var cfg = this.resizeConfig, - width = event.pageX - cfg.curResizeElem.position; + width = event.pageX - cfg.curResizeElem.position, + self = this; event.stopPropagation(); event.preventDefault(); @@ -448,26 +457,40 @@ define([ ) { cfg.curResizeElem.model.width += width; cfg.depResizeElem.model.width -= width; - $(cfg.curResizeElem.elem).outerWidth(cfg.curResizeElem.model.width); - $(cfg.depResizeElem.elem).outerWidth(cfg.depResizeElem.model.width); + + cfg.curResizeElem.elems.forEach(function (el) { + $(el).outerWidth(cfg.curResizeElem.model.width); + }); + cfg.depResizeElem.elems.forEach(function (el) { + $(el).outerWidth(cfg.depResizeElem.model.width); + }); + cfg.previousWidth = width; cfg.curResizeElem.position = event.pageX; } else if (width <= -(cfg.curResizeElem.model.width - this.minColumnWidth)) { - $(cfg.curResizeElem.elem).outerWidth(this.minColumnWidth); - $(cfg.depResizeElem.elem).outerWidth( + cfg.curResizeElem.elems.forEach(function (el) { + $(el).outerWidth(self.minColumnWidth); + }); + cfg.depResizeElem.elems.forEach(function (el) { + $(el).outerWidth( cfg.depResizeElem.model.width + cfg.curResizeElem.model.width - - this.minColumnWidth - ); + self.minColumnWidth); + }); + } else if (width >= cfg.depResizeElem.model.width - this.minColumnWidth) { - $(cfg.depResizeElem.elem).outerWidth(this.minColumnWidth); - $(cfg.curResizeElem.elem).outerWidth( - cfg.curResizeElem.model.width + - cfg.depResizeElem.model.width - - this.minColumnWidth - ); + cfg.depResizeElem.elems.forEach(function (el) { + $(el).outerWidth(self.minColumnWidth); + }); + cfg.curResizeElem.elems.forEach(function (el) { + $(el).outerWidth( + cfg.curResizeElem.model.width + + cfg.depResizeElem.model.width - + self.minColumnWidth + ); + }); } }, @@ -502,17 +525,17 @@ define([ * @param {Object} element - current element * @returns {Object} next element data */ - getNextElement: function (element) { + getNextElements: function (element) { var nextElem = $(element).next()[0], nextElemModel = ko.dataFor(nextElem), - nextElemData = this.hasColumn(nextElemModel, true); + nextElemData = this.hasColumn(nextElemModel, false, true); if (nextElemData) { if (nextElemModel.visible()) { return nextElemData; } - return this.getNextElement(nextElem); + return this.getNextElements(nextElem); } }, @@ -540,14 +563,20 @@ define([ * Check column is render or not * * @param {Object} model - cur column model + * @param {String|Boolean} ctxIndex - index of context, or false, if want to get cols from all ctx * @param {Boolean} returned - need return column object or not - * @return {Boolean} if returned param is false, returned boolean falue, else return current object data + * @return {Boolean} if returned param is false, returned boolean value, else return current object data */ - hasColumn: function (model, returned) { - if (this.columnsElements.hasOwnProperty(model.index)) { + hasColumn: function (model, ctxIndex, returned) { + var colElem = this.columnsElements[model.index] || {}, + getFromAllCtx = ctxIndex === false; + + if (colElem && (getFromAllCtx || colElem.hasOwnProperty(ctxIndex))) { if (returned) { - return this.columnsElements[model.index]; + return getFromAllCtx ? + _.values(colElem) : + colElem[ctxIndex]; } return true; @@ -581,6 +610,19 @@ define([ } return false; + }, + + /** + * Generate index that will indentify context + * + * @param {Object} ctx + * @return {String} + */ + getCtxIndex: function (ctx) + { + return ctx ? ctx.$parents.reduce(function (pv, cv) { + return (pv.index || pv) + (cv || {}).index; + }) : ctx; } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js b/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js new file mode 100644 index 0000000000000000000000000000000000000000..e779851a9315625ebe3b60f5c09c8769098139d1 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js @@ -0,0 +1,577 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'Magento_Ui/js/lib/view/utils/async', + 'underscore', + 'uiComponent', + 'Magento_Ui/js/lib/view/utils/raf' +], function ($, _, Component, raf) { + 'use strict'; + + return Component.extend({ + defaults: { + listingSelector: '${ $.listingProvider }::not([data-role = "sticky-el-root"])', + toolbarSelector: '${ $.toolbarProvider }::not([data-role = "sticky-el-root"])', + bulkRowSelector: '[data-role = "data-grid-bulk-row"]', + bulkRowHeaderSelector: '.data-grid-info-panel:visible', + tableSelector: 'table', + columnSelector: 'thead tr th', + rowSelector: 'tbody tr', + toolbarCollapsiblesSelector: '[data-role="toolbar-menu-item"]', + toolbarCollapsiblesActiveClass: '_active', + template: 'ui/grid/sticky/sticky', + stickyContainerSelector: '.sticky-header', + stickyElementSelector: '[data-role = "sticky-el-root"]', + leftDataGridCapSelector: '.data-grid-cap-left', + rightDataGridCapSelector: '.data-grid-cap-right', + visible: false, + enableToolbar: true, + enableHeader: true, + modules: { + toolbar: '${ $.toolbarProvider }', + listing: '${ $.listingProvider }' + }, + otherStickyElsSize: 77, + containerNode: null, + listingNode: null, + toolbarNode: null, + stickyListingNode: null, + stickyToolbarNode: null, + storedOriginalToolbarElements: [], + cache: {}, + flags: {}, + dirtyFlag: 'dirty' + }, + + /** + * Initializes Sticky component. + * + * @returns {Object} Chainable. + */ + initialize: function () { + this._super(); + _.bindAll(this, + 'adjustStickyElems', + 'initListingNode', + 'initToolbarNode', + 'initContainerNode', + 'initStickyListingNode', + 'initStickyToolbarNode', + 'initLeftDataGridCap', + 'initRightDataGridCap' + ); + + $.async(this.listingSelector, + this.initListingNode); + $.async(this.toolbarSelector, + this.initToolbarNode); + + $.async(this.stickyContainerSelector, + this, + this.initContainerNode); + $.async(this.stickyElementSelector, + this.listing(), + this.initStickyListingNode); + $.async(this.stickyElementSelector, + this.toolbar(), + this.initStickyToolbarNode); + + return this; + }, + + /** + * Init observables + * + * @returns {Object} Chainable. + */ + initObservable: function () { + this._super() + .observe(['visible']); + + return this; + }, + + /** + * Init original listing node + * + * @param {HTMLElement} node + */ + initListingNode: function (node) { + if ($(node).is(this.stickyElementSelector)) { + return; + } + this.listingNode = $(node); + this.columns = this.listingNode.find(this.columnSelector); + }, + + /** + * Init original toolbar node + * + * @param {HTMLElement} node + */ + initToolbarNode: function (node) { + if ($(node).is(this.stickyElementSelector)) { + return; + } + this.toolbarNode = $(node); + }, + + /** + * Init sticky listing node + * + * @param {HTMLElement} node + */ + initStickyListingNode: function (node) { + this.stickyListingNode = $(node); + this.checkPos(); + this.initListeners(); + }, + + /** + * Init sticky toolbar node + * + * @param {HTMLElement} node + */ + initStickyToolbarNode: function (node) { + this.stickyToolbarNode = $(node); + }, + + /** + * Init sticky header container node + * + * @param {HTMLElement} node + */ + initContainerNode: function (node) { + this.containerNode = $(node); + + $.async(this.leftDataGridCapSelector, + node, + this.initLeftDataGridCap); + $.async(this.rightDataGridCapSelector, + node, + this.initRightDataGridCap); + }, + + /** + * Init left DataGridCap + * + * @param {HTMLElement} node + */ + initLeftDataGridCap: function (node) { + this.leftDataGridCap = $(node); + }, + + /** + * Init right DataGridCap + * + * @param {HTMLElement} node + */ + initRightDataGridCap: function (node) { + this.rightDataGridCap = $(node); + }, + + /** + * Init listeners + * + * @returns {Object} Chainable. + */ + initListeners: function () { + this.adjustStickyElems(); + this.initOnResize() + .initOnScroll() + .initOnListingScroll(); + + return this; + }, + + /** + * Start to listen to window scroll event + * + * @returns {Object} Chainable. + */ + initOnScroll: function () { + this.lastHorizontalScrollPos = $(window).scrollLeft(); + document.addEventListener('scroll', function () { + this.flags.scrolled = true; + }.bind(this)); + + return this; + }, + + /** + * Start to listen to original listing scroll event + * + * @returns {Object} Chainable. + */ + initOnListingScroll: function () { + $(this.listingNode).scroll(function (e) { + this.flags.listingScrolled = true; + this.flags.listingScrolledValue = $(e.target).scrollLeft(); + }.bind(this)); + + return this; + }, + + /** + * Start to listen to window resize event + * + * @returns {Object} Chainable. + */ + initOnResize: function () { + $(window).resize(function () { + this.flags.resized = true; + }.bind(this)); + + return this; + }, + + /** + * Adjust sticky header elements according to flags of the events that have happened in the endless RAF loop + */ + adjustStickyElems: function () { + if (this.flags.resized || + this.flags.scrolled) { + this.checkPos(); + } + + if (this.visible()) { + this.checkTableElemsWidth(); + + if (this.flags.originalWidthChanged) { + this.adjustContainerElemsWidth(); + } + + if (this.flags.resized) { + this.onResize(); + } + + if (this.flags.scrolled) { + this.onWindowScroll(); + } + + if (this.flags.listingScrolled) { + this.onListingScroll(this.flags.listingScrolledValue); + } + } + _.each(this.flags, function (val, key) { + if (val === this.dirtyFlag) { + this.flags[key] = false; + } else if (val) { + this.flags[key] = this.dirtyFlag; + } + }, this); + + raf(this.adjustStickyElems); + }, + + /** + * Handles window scroll + */ + onWindowScroll: function () { + var scrolled = $(window).scrollLeft(), + horizontal = this.lastHorizontalScrollPos !== scrolled; + + if (horizontal) { + this.adjustOffset() + .adjustDataGridCapPositions(); + this.lastHorizontalScrollPos = scrolled; + } else { + this.checkPos(); + } + }, + + /** + * Handles original listing scroll + * + * @param {Number} scrolled + */ + onListingScroll: function (scrolled) { + this.adjustOffset(scrolled); + }, + + /** + * Handles window resize + */ + onResize: function () { + this.checkPos(); + this.adjustContainerElemsWidth() + .adjustDataGridCapPositions(); + }, + + /** + * Check if original table or columns change it dimensions and sets appropriate flag + */ + checkTableElemsWidth: function () { + var newWidth = this.getTableWidth(); + + if (this.cache.tableWidth !== newWidth) { + this.cache.tableWidth = newWidth; + this.flags.originalWidthChanged = true; + } else if (this.cache.colChecksum !== this.getColsChecksum()) { + this.cache.colChecksum = this.getColsChecksum(); + this.flags.originalWidthChanged = true; + } + }, + + /** + * Get the checksum of original columns width + * + * @returns {Number}. + */ + getColsChecksum: function () { + return _.reduce(this.columns, + function (pv, cv) { + return ($(pv).width() || pv) + '' + $(cv).width(); + }); + }, + + /** + * Get the width of the sticky table wrapper + * + * @returns {Number}. + */ + getListingWidth: function () { + return this.listingNode.width(); + }, + + /** + * Get the width of the original table + * + * @returns {Number}. + */ + getTableWidth: function () { + return this.listingNode.find(this.tableSelector).width(); + }, + + /** + * Get the top elem: header or toolbar + * + * @returns {HTMLElement}. + */ + getTopElement: function () { + return this.toolbarNode || this.listingNode; + }, + + /** + * Get the height of the other sticky elem (Page header) + * + * @returns {Number}. + */ + getOtherStickyElementsSize: function () { + return this.otherStickyElsSize; + }, + + /** + * Get top Y coord of the sticky header + * + * @returns {Number}. + */ + getListingTopYCoord: function () { + var bulkRowHeight = (this.listingNode.find(this.bulkRowSelector) || {}).height(); + + return this.listingNode.find('tbody').offset().top - + this.containerNode.height() - + $(window).scrollTop() + + bulkRowHeight; + }, + + /** + * Check if sticky header must be visible + * + * @returns {Boolean}. + */ + getMustBeSticky: function () { + var stickyTopCondition = this.getListingTopYCoord() - this.getOtherStickyElementsSize(), + stickyBottomCondition = this.listingNode.offset().top + + this.listingNode.height() - + $(window).scrollTop() - + (this.listingNode.find(this.bulkRowSelector) || {}).height() - + this.getOtherStickyElementsSize(); + + return stickyTopCondition < 0 && stickyBottomCondition > 0; + }, + + /** + * Resize sticky header and cols + * + * @returns {Object} Chainable. + */ + adjustContainerElemsWidth: function () { + this.resizeContainer() + .resizeCols() + .resizeBulk(); + + return this; + }, + + /** + * Resize sticky header + * + * @returns {Object} Chainable. + */ + resizeContainer: function () { + var listingWidth = this.getListingWidth(); + + this.stickyListingNode.innerWidth(listingWidth); + this.stickyListingNode.find(this.tableSelector).innerWidth(this.getTableWidth()); + + if (this.stickyToolbarNode) { + this.stickyToolbarNode.innerWidth(listingWidth); + } + + return this; + }, + + /** + * Resize sticky cols + * + * @returns {Object} Chainable. + */ + resizeCols: function () { + var cols = this.listingNode.find(this.columnSelector); + + this.stickyListingNode.find(this.columnSelector).each(function (ind) { + var originalColWidth = $(cols[ind]).width(); + + $(this).width(originalColWidth); + }); + + return this; + }, + + /** + * Resize bulk row header + * + * @returns {Object} Chainable. + */ + resizeBulk: function () { + var bulk = this.containerNode.find(this.bulkRowHeaderSelector)[0]; + if (bulk){ + $(bulk).innerWidth(this.getListingWidth()); + } + }, + + /** + * Reset viewport to the top of listing + */ + resetToTop: function () { + var posOfTopEl = this.getTopElement().offset().top - this.getOtherStickyElementsSize() || 0; + + $(window).scrollTop(posOfTopEl); + }, + + /** + * Adjust sticky header offset + * + * @param {Number} val + * @returns {Object} Chainable. + */ + adjustOffset: function (val) { + val = val || this.listingNode.scrollLeft(); + this.stickyListingNode.offset({ + left: this.listingNode.offset().left - val + }); + + return this; + }, + + /** + * Adjust both DataGridCap position + * + * @returns {Object} Chainable. + */ + adjustDataGridCapPositions: function () { + this.adjustLeftDataGridCapPos() + .adjustRightDataGridCapPos(); + + return this; + }, + + /** + * Adjust left DataGridCap position + * + * @returns {Object} Chainable. + */ + adjustLeftDataGridCapPos: function () { + this.leftDataGridCap.offset({ + left: this.listingNode.offset().left - this.leftDataGridCap.width() + }); + + return this; + }, + + /** + * Adjust right DataGridCap position + * + * @returns {Object} Chainable. + */ + adjustRightDataGridCapPos: function () { + this.rightDataGridCap.offset({ + left: this.listingNode.offset().left + this.listingNode.width() + }); + + return this; + }, + + /** + * Hides the oiginal toolbar opened dropdowns/collapsibles etc + */ + collapseOriginalElements: function () { + this.toolbarNode + .find(this.toolbarCollapsiblesSelector) + .css('visibility', 'hidden'); + $(this.listingNode.find(this.bulkRowSelector)[0]).css('visibility', 'hidden'); + }, + + /** + * Restores the oiginal toolbar opened dropdowns/collapsibles etc + */ + restoreOriginalElements: function () { + this.toolbarNode + .find(this.toolbarCollapsiblesSelector) + .css('visibility', 'visible'); + $(this.listingNode.find(this.bulkRowSelector)[0]).css('visibility', 'visible'); + }, + + /** + * Toggle the visibility of sticky header + * + * @returns {Object} Chainable. + */ + toggleContainerVisibility: function () { + this.visible(!this.visible()); + + return this; + }, + + /** + * Checks position of the listing to know if need to show/hide sticky header + * + * @returns {Boolean} whether the visibility of the sticky header was toggled. + */ + checkPos: function () { + var isSticky = this.visible(), + mustBeSticky = this.getMustBeSticky(), + needChange = isSticky !== mustBeSticky; + + if (needChange) { + if (mustBeSticky) { + this.collapseOriginalElements(); + this.toggleContainerVisibility(); + this.adjustContainerElemsWidth() + .adjustOffset() + .adjustDataGridCapPositions(); + + } else { + this.toggleContainerVisibility(); + this.restoreOriginalElements(); + } + } + + return needChange; + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/component/core.js b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js index fd3e81680aee113c56769ffd17786fc684a5159a..65eca7b967d7a31cb7ad750cd213ee051ad0898c 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/component/core.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/component/core.js @@ -23,7 +23,8 @@ define([ }, modules: { storage: '${ $.storageConfig.provider }' - } + }, + componentType: 'container' }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/collapsible.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/collapsible.js new file mode 100644 index 0000000000000000000000000000000000000000..0c5686fa8936ada9151c3c657b1ad0036e08401d --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/collapsible.js @@ -0,0 +1,189 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'jquery', + 'underscore' +], function (ko, $, _) { + 'use strict'; + + var collapsible, + defaults; + + defaults = { + closeOnOuter: true, + onTarget: false, + openClass: '_active', + as: '$collapsible' + }; + + collapsible = { + + /** + * Sets 'opened' property to true. + */ + open: function () { + this.opened(true); + }, + + /** + * Sets 'opened' property to false. + */ + close: function () { + this.opened(false); + }, + + /** + * Toggles value of the 'opened' property. + */ + toggle: function () { + this.opened(!this.opened()); + } + }; + + /** + * Document click handler which in case if event target is not + * a descendant of provided container element, closes collapsible model. + * + * @param {HTMLElement} container + * @param {Object} model + * @param {EventObject} e + */ + function onOuterClick(container, model, e) { + var target = e.target; + + if (target !== container && !container.contains(target)) { + model.close(); + } + } + + /** + * Creates 'css' binding which toggles + * class specified in 'name' parameter. + * + * @param {Object} model + * @param {String} name + * @returns {Object} + */ + function getClassBinding(model, name) { + var binding = {}; + + binding[name] = model.opened; + + return { + css: binding + }; + } + + /** + * Prepares configuration for the binding based + * on a default properties and provided options. + * + * @param {Object} [options={}] + * @returns {Object} Complete instance configuration. + */ + function buildConfig(options) { + if (typeof options !== 'object') { + options = {}; + } + + return _.extend({}, defaults, options); + } + + ko.bindingHandlers.collapsible = { + + /** + * Initializes 'collapsible' binding. + */ + init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) { + var $collapsible = Object.create(collapsible), + config = buildConfig(valueAccessor()), + outerClick, + bindings; + + _.bindAll($collapsible, 'open', 'close', 'toggle'); + + $collapsible.opened = ko.observable(false); + + bindingCtx[config.as] = $collapsible; + + if (config.closeOnOuter) { + outerClick = onOuterClick.bind(null, element, $collapsible); + + $(document).on('click', outerClick); + + ko.utils.domNodeDisposal.addDisposeCallback(element, function () { + $(document).off('click', outerClick); + }); + } + + if (config.openClass) { + bindings = getClassBinding($collapsible, config.openClass); + + ko.applyBindingsToNode(element, bindings, bindingCtx); + } + + if (config.onTarget) { + $(element).on('click', $collapsible.toggle); + } + + if (viewModel && _.isFunction(viewModel.on)) { + viewModel.on({ + close: $collapsible.close, + open: $collapsible.open, + toggleOpened: $collapsible.toggle + }); + } + } + }; + + ko.bindingHandlers.closeCollapsible = { + + /** + * Creates listener for the click event on provided DOM element, + * which closes associated with it collapsible model. + */ + init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) { + var name = valueAccessor() || defaults.as, + $collapsible = bindingCtx[name]; + + if ($collapsible) { + $(element).on('click', $collapsible.close); + } + } + }; + + ko.bindingHandlers.openCollapsible = { + + /** + * Creates listener for the click event on provided DOM element, + * which opens associated with it collapsible model. + */ + init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) { + var name = valueAccessor() || defaults.as, + $collapsible = bindingCtx[name]; + + if ($collapsible) { + $(element).on('click', $collapsible.open); + } + } + }; + + ko.bindingHandlers.toggleCollapsible = { + + /** + * Creates listener for the click event on provided DOM element, + * which toggles associated with it collapsible model. + */ + init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) { + var name = valueAccessor() || defaults.as, + $collapsible = bindingCtx[name]; + + if ($collapsible) { + $(element).on('click', $collapsible.toggle); + } + } + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/optgroup.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/optgroup.js index b4ef5df5a1340ed510a92e0378953cc1a5fa09ce..b95709baf311418d8a362f9a7ad86f1f40c389fb 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/optgroup.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/optgroup.js @@ -67,8 +67,13 @@ define([ if (typeof unwrappedArray.length === 'undefined') { // Coerce single value into array unwrappedArray = [unwrappedArray]; } + // Filter out any entries marked as destroyed filteredArray = ko.utils.arrayFilter(unwrappedArray, function (item) { + if (item && !item.label) { + return false; + } + return includeDestroyed || item === undefined || item === null || !ko.utils.unwrapObservable(item._destroy); }); filteredArray.map(recursivePathBuilder, null); @@ -211,8 +216,8 @@ define([ // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document. // That's why we first added them without selection. Now it's time to set the selection. if (previousSelectedValues.length) { - var isSelected = ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[0])) >= 0; - ko.utils.setOptionNodeSelectionState(newOptions[0], isSelected); + var isSelected = ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions.value)) >= 0; + ko.utils.setOptionNodeSelectionState(newOptions.value, isSelected); // If this option was changed from being selected during a single-item update, notify the change if (itemUpdate && !isSelected) { diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js index 843c126b663413058238b86dc03e5f82d2622f14..2c0bfa635587ef1c586d0f2dd9f4c8ab36ba48ed 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/bind/outer_click.js @@ -5,38 +5,75 @@ /** Creates outerClick binding and registers in to ko.bindingHandlers object */ define([ 'ko', - 'jquery' -], function (ko, $) { + 'jquery', + 'underscore' +], function (ko, $, _) { 'use strict'; - function clickWrapper(elem, callback, e) { - var target = e.target; + var defaults = { + onlyIfVisible: true + }; + + /** + * Document click handler which in case if event target is not + * a descendant of provided container element, + * invokes specfied in configuration callback. + * + * @param {HTMLElement} container + * @param {Object} config + * @param {EventObject} e + */ + function onOuterClick(container, config, e) { + var target = e.target, + callback = config.callback; - if (target !== elem && !elem.contains(target)) { + if (container === target || container.contains(target)) { + return; + } + + if (config.onlyIfVisible) { + if (!_.isNull(container.offsetParent)) { + callback(); + } + } else { callback(); } } + /** + * Prepares configuration for the binding based + * on a default properties and provided options. + * + * @param {(Object|Function)} [options={}] + * @returns {Object} + */ + function buildConfig(options) { + var config = {}; + + if (_.isFunction(options)) { + options = { + callback: options + }; + } else if (!_.isObject(options)) { + options = {}; + } + + return _.extend(config, defaults, options); + } + ko.bindingHandlers.outerClick = { /** - * Attaches click handler to document - * @param {HTMLElement} el - Element, that binding is applied to - * @param {Function} valueAccessor - Function that returns value, passed to binding - * @param {Object} allBindings - all bindings object - * @param {Object} viewModel - reference to viewmodel + * Initializes outer click binding. */ - init: function (element, valueAccessor, allBindings, viewModel) { - var callback = valueAccessor(), - wrapper; - - callback = callback.bind(viewModel); - wrapper = clickWrapper.bind(null, element, callback); + init: function (element, valueAccessor) { + var config = buildConfig(valueAccessor()), + outerClick = onOuterClick.bind(null, element, config); - $(document).on('click', wrapper); + $(document).on('click', outerClick); ko.utils.domNodeDisposal.addDisposeCallback(element, function () { - $(document).off('click', wrapper); + $(document).off('click', outerClick); }); } }; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js b/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js index b96c6107aafed4a3058082fb9d8304a924f5d218..2b0f3d1fc5dcadfc5f630efaea6a0bf5c4379dae 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/ko/initialize.js @@ -17,6 +17,7 @@ define([ './bind/mage-init', './bind/after-render', './bind/i18n', + './bind/collapsible', './extender/observable_array', './extender/bound-nodes', './extender/observable_array' diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js index df89d8d435b674dd2c0d6651467687acedf2f2a4..1b5743cd9d29aea5d12841306cd3dc0c1fd4ee6f 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js @@ -86,6 +86,7 @@ define([ data.ctx = ctx; } else { data.component = ctx; + data.ctx = '*'; } } else { data = _.isString(selector) ? @@ -93,8 +94,6 @@ define([ selector; } - data.ctx = data.ctx || '*'; - return data; } @@ -127,7 +126,8 @@ define([ */ function setRootListener(data, component) { boundedNodes.get(component, function (root) { - if (!$(root).is(data.ctx)) { + var ctx = data.ctx || '*' + if (!$(root).is(data.ctx || '*')) { return; } @@ -182,9 +182,11 @@ define([ domObserver.get(data.selector, data.fn, data.ctx); } }; + /*eslint-enable no-unused-vars*/ _.extend($.async, { + /*eslint-disable no-unused-vars*/ /** * Returns collection of elements found by provided selector data. @@ -215,6 +217,7 @@ define([ $(data.selector, nodes).toArray() : nodes; }, + /*eslint-enable no-unused-vars*/ /** diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js index ae5c2878e526271bf97da7521ce575a2c6547be3..25e900fe2af2994c24ae53fc1d422681bab6539c 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js @@ -42,26 +42,20 @@ define([ } /** - * Removes all non-element nodes from provided array - * and appends to it descendant elements. + * Extracts node identifier. If ID is not specified, + * then it will be created for the provided node. * - * @param {Array} nodes - * @returns {Array} + * @param {HTMLElement} node + * @returns {Number} */ - function formNodesList(nodes) { - var result = [], - children; - - _.toArray(nodes) - .filter(isElementNode) - .forEach(function (node) { - result.push(node); + function getNodeId(node) { + var id = node._observeId; - children = extractChildren(node); - result = result.concat(children); - }); + if (!id) { + id = node._observeId = counter++; + } - return result; + return id; } /** @@ -71,7 +65,15 @@ define([ * @param {Object} data */ function trigger(node, data) { + var id = getNodeId(node), + ids = data.invoked; + + if (_.contains(ids, id)) { + return; + } + data.callback(node); + data.invoked.push(id); } /** @@ -81,12 +83,8 @@ define([ * @returns {Object} */ function createNodeData(node) { - var id = node._observeId, - nodes = watchers.nodes; - - if (!id) { - id = node._observeId = counter++; - } + var nodes = watchers.nodes, + id = getNodeId(node); nodes[id] = nodes[id] || {}; @@ -137,10 +135,6 @@ define([ function addSelectorListener(selector, data) { var storage = watchers.selectors; - if (typeof selector !== 'string') { - return; - } - (storage[selector] = storage[selector] || []).push(data); } @@ -187,51 +181,67 @@ define([ } /** - * Extarcts nodes that matches specfied selector. - * If selector is an object, then it will be parsed as - * one of the possible array like values. + * Removes all non-element nodes from provided array + * and appends to it descendant elements. * - * @param {(jQueryObject|HTMLElement|Array|String)} selector - * @param {HTMLElement} [ctx=document.body] - Context that will be used to search for elements. - * @returns {Array} An array of available elements. + * @param {Array} nodes + * @returns {Array} */ - function getNodes(selector, ctx) { - var nodes = []; - - if (typeof selector === 'object') { - if (typeof selector.jquery === 'string' || !selector.tagName) { - nodes = _.toArray(selector); - } else if (selector.tagName) { - nodes = [selector]; - } - } else if (typeof selector === 'string') { - nodes = $(selector, ctx).toArray(); - } + function formNodesList(nodes) { + var result = [], + children; + + nodes = _.toArray(nodes).filter(isElementNode); - return nodes; + nodes.forEach(function (node) { + result.push(node); + + children = extractChildren(node); + result = result.concat(children); + }); + + return result; } /** - * Processes removed and added element nodes - * specified in mutation record. + * Collects all removed and added nodes from + * mutation records into separate arrays + * while removing duplicates between both types of changes. * - * @param {MutationRecord} mutation + * @param {Array} mutations - An array of mutation records. + * @returns {Object} Object with 'removed' and 'added' nodes arrays. */ - function handleMutation(mutation) { - var addedNodes = mutation.addedNodes, - removedNodes = mutation.removedNodes; + function formChangesLists(mutations) { + var removed = [], + added = []; - if (addedNodes.length) { - formNodesList(addedNodes).forEach(processAdded); - } + mutations.forEach(function (record) { + removed = removed.concat(_.toArray(record.removedNodes)); + added = added.concat(_.toArray(record.addedNodes)); + }); - if (removedNodes.length) { - formNodesList(removedNodes).forEach(processRemoved); - } + removed = removed.filter(function (node) { + var addIndex = added.indexOf(node), + wasAdded = !!~addIndex; + + if (wasAdded) { + added.splice(addIndex, 1); + } + + return !wasAdded; + }); + + return { + removed: formNodesList(removed), + added: formNodesList(added) + }; } globalObserver = new MutationObserver(function (mutations) { - mutations.forEach(handleMutation); + var changes = formChangesLists(mutations); + + changes.removed.forEach(processRemoved); + changes.added.forEach(processAdded); }); globalObserver.observe(document.body, { @@ -240,6 +250,7 @@ define([ }); return { + /** * Adds listener for the appearance of nodes that matches provided * selector and which are inside of the provided context. Callback will be @@ -250,15 +261,19 @@ define([ * @param {HTMLElement} [ctx=document.body] - Context inside of which to search for the node. */ get: function (selector, callback, ctx) { - var data; + var data, + nodes; data = { ctx: ctx || document.body, + type: 'add', callback: callback, - type: 'add' + invoked: [] }; - getNodes(selector, data.ctx).forEach(function (node) { + nodes = $(selector, data.ctx).toArray(); + + nodes.forEach(function (node) { trigger(node, data); }); @@ -273,21 +288,29 @@ define([ * @param {HTMLElement} [ctx=document.body] - Context inside of which to search for the node. */ remove: function (selector, callback, ctx) { - var data; + var nodes = [], + data; data = { ctx: ctx || document.body, + type: 'remove', callback: callback, - type: 'remove' + invoked: [] }; - getNodes(selector, data.ctx).forEach(function (node) { - addRemovalListener(node, data); - }); + if (typeof selector === 'object') { + nodes = !_.isUndefined(selector.length) ? + _.toArray(selector) : + [selector]; + } else if (_.isString(selector)) { + nodes = $(selector, ctx).toArray(); - if (typeof selector === 'string') { addSelectorListener(selector, data); } + + nodes.forEach(function (node) { + addRemovalListener(node, data); + }); }, /** diff --git a/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js new file mode 100644 index 0000000000000000000000000000000000000000..1c174a87fce56717874f85004bf286cc3faae280 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js @@ -0,0 +1,19 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +define(function () { + 'use strict'; + + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame|| + window.onRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback){ + window.setTimeout(callback, 1000/60); + } +}); diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html index 29a93df1a9805a33d0e614f70d52bc2c26bbbe5b..16b8fab2bb2877bf3a0bf039c7b55368347ce992 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/actions.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/actions.html @@ -4,26 +4,23 @@ * See COPYING.txt for license details. */ --> -<div class="col-xs-2"> - <div - class="action-select-wrap" - data-bind="css: {'_active': opened}, - click: toggleOpened, - outerClick: close"> - <button - class="action-select" - data-bind="i18n: 'Select Items'"> - <span data-bind="i18n: 'Actions'"></span> - </button> - <ul - class="action-menu" - data-bind="css: {'_active': opened}, - foreach: actions"> - <li data-bind="click: $parent.applyAction.bind($parent, type)"> - <span - class="action-menu-item" - data-bind="text: label"></span> - </li> - </ul> - </div> +<div + class="action-select-wrap" + data-bind="collapsible: {onTarget: true}" + data-role="toolbar-menu-item"> + <button + class="action-select" + data-bind="i18n: 'Select Items'"> + <span data-bind="i18n: 'Actions'"></span> + </button> + <ul + class="action-menu" + data-bind="css: {'_active': $collapsible.opened}, + foreach: actions"> + <li data-bind="click: $parent.applyAction.bind($parent, type)"> + <span + class="action-menu-item" + data-bind="text: label"></span> + </li> + </ul> </div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html b/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html index 2a4a46a38907496a37203eb4e6f83508c461eda4..22105aed42f6d0eb382162432c3317431a32cbeb 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/actions.html @@ -24,22 +24,17 @@ <!-- ko if: isMultiple(row._rowIndex) --> <div class="action-select-wrap" - data-bind=" - css : { - '_active' : opened() === row._rowIndex - }, - outerClick: closeList.bind($data, row._rowIndex)"> - <button class="action-select" data-bind="click: toggleList.bind($data, row._rowIndex)"> + data-bind="collapsible"> + <button class="action-select" data-bind="toggleCollapsible"> <span data-bind="i18n: 'Select'"></span> </button> <ul class="action-menu" - data-bind=" - css: { - '_active': opened() === row._rowIndex - }, - foreach: getVisibleActions(row._rowIndex)" - > + data-bind="css: { + '_active': $collapsible.opened + }, + foreach: getVisibleActions(row._rowIndex)" + > <li> <a class="action-menu-item" diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html b/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html index a2dce41dda5f53b643fe9ca7d092dc693e7dad44..4606d8e27b9a19e5236f6b7f28d66076805b43d1 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/columns/multiselect.html @@ -8,8 +8,8 @@ <th class="data-grid-multicheck-cell" data-bind="visible: visible"> <div class="action-multicheck-wrap" - data-bind="css: { '_active': menuVisible, '_disabled': !totalRecords()}, - outerClick: hideMenu"> + data-bind="css: {'_disabled': !totalRecords()}, + collapsible"> <input id="mass-select-checkbox" class="admin__control-checkbox" @@ -22,14 +22,14 @@ <button class="action-multicheck-toggle" data-toggle="dropdown" - data-bind="css: { '_active': menuVisible }, - click: toggleMenu, - enable: totalRecords"> + data-bind="css: { '_active': $collapsible.opened }, + enable: totalRecords, + toggleCollapsible"> <span data-bind="i18n: 'Options'"></span> </button> <ul class="action-menu" - data-bind="click: hideMenu, foreach: actions"> + data-bind="closeCollapsible, foreach: actions"> <li data-bind="click: $parent[value].bind($parent), visible: $parent.isActionRelevant(value)"> <span class="action-menu-item" data-bind="text: label"></span> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html index 07b20b76bb1039bd2b6b33e0e579e09c284971f8..850f3c2fce793487392414a8ff1f95bc45f5daa5 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/bookmarks.html @@ -7,11 +7,12 @@ <div class="admin__action-dropdown-wrap admin__data-grid-action-bookmarks" - data-bind="css: {_active: opened, _disabled: !collapsible}, outerClick: close"> + data-bind="collapsible" + data-role="toolbar-menu-item"> <button class="admin__action-dropdown" type="button" - data-bind="click: toggleOpened" + data-bind="toggleCollapsible" data-toggle="dropdown" aria-haspopup="true"> <span class="admin__action-dropdown-text" diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html index 7327208e7c520e4f694ad53f236a9f295848443a..707fad8eabbe87f3fc4120fd49e9b2afb6ce4b26 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/bookmarks/view.html @@ -5,7 +5,7 @@ */ --> <li - data-bind="css: {_edit: editing}, outerClick: endEdit"> + data-bind="css: {_edit: editing}, outerClick: endEdit.bind($data)"> <!-- ko if: editable --> <div class="action-dropdown-menu-item-edit"> <input @@ -17,18 +17,18 @@ placeholder: label }, keyboard: { - 13: function(){ $parent.close().saveView($data) } + 13: function(){ $collapsible.close(); $parent.saveView($data) } }" type="text"> <button class="action-submit" - data-bind="click: function(){ $parent.close().saveView($data) }, attr: {title: $t('Save all changes')}" + data-bind="click: $parent.saveView.bind($parent, $data), closeCollapsible, attr: {title: $t('Save all changes')}" type="button"> <span data-bind="i18n: 'Submit'"></span> </button> <div class="action-dropdown-menu-item-actions"> <button - data-bind="click: function(){ $parent.close().removeView($data) }, attr: {title: $t('Delete bookmark')}" + data-bind="click: $parent.removeView.bind($parent, $data), closeCollapsible, attr: {title: $t('Delete bookmark')}" class="action-delete" type="button"> <span data-bind="i18n: 'Delete'"></span> @@ -40,7 +40,7 @@ <a class="action-dropdown-menu-link" href="" - data-bind="text: label, click: function(){ $data.active(true); $parent.close(); }"></a> + data-bind="text: label, click: function(){ active(true); }, closeCollapsible"></a> <!-- ko if: editable --> <div class="action-dropdown-menu-item-actions"> <button @@ -52,4 +52,4 @@ </div> <!-- /ko --> </div> -</li> \ No newline at end of file +</li> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html b/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html index 41b13406d504e9b0e90d4248bd789bbe8bf81f75..e2dcc3d816376756169ad5896c5e14de65475fe8 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/controls/columns.html @@ -4,11 +4,13 @@ * See COPYING.txt for license details. */ --> -<div data-bind="css: {_active: opened}, outerClick: close" class="admin__action-dropdown-wrap admin__data-grid-action-columns"> +<div data-bind="collapsible" + class="admin__action-dropdown-wrap admin__data-grid-action-columns" + data-role="toolbar-menu-item"> <button class="admin__action-dropdown" type="button" - data-bind="click: toggleOpened" + data-bind="toggleCollapsible" data-toggle="dropdown" aria-haspopup="true"> <span class="admin__action-dropdown-text" data-bind="i18n: 'Columns'"></span> @@ -19,9 +21,22 @@ </div> <div class="admin__action-dropdown-menu-content" data-bind="foreach: elems"> <div class="admin__field-option"> - <input data-bind="attr: {id: 'grid-controls-columns-' + index}, disable: $parent.isDisabled($data), checked: visible" - class="admin__control-checkbox" type="checkbox"/> - <label data-bind="text: label, attr: {for: 'grid-controls-columns-' + index}" class="admin__field-label"></label> + <input + class="admin__control-checkbox" + type="checkbox" + data-bind=" + attr: { + id: ++ko.bindingHandlers['uniqueName'].currentIndex + '_uid' + }, + disable: $parent.isDisabled($data), + checked: visible"/> + <label + class="admin__field-label" + data-bind=" + text: label, + attr: { + for: ko.bindingHandlers['uniqueName'].currentIndex + '_uid' + }"></label> </div> </div> <div class="admin__action-dropdown-menu-footer"> @@ -31,10 +46,10 @@ </button> </div> <div class="admin__action-dropdown-footer-main-actions"> - <button data-bind="click: function () { $data.close().cancel(); }" class="action-tertiary" type="button"> + <button data-bind="click: cancel, closeCollapsible" class="action-tertiary" type="button"> <span data-bind="i18n: 'Cancel'"></span> </button> </div> </div> </div> -</div> \ No newline at end of file +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html b/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html index 5bdfb3db958eaf2d8c1fece8bfa2f10077fbd1f9..fe3d785f3d29a4cece894b3df02ece7467f7a6b1 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/editing/bulk.html @@ -8,7 +8,8 @@ class="data-grid-bulk-edit-panel data-grid-editable-row" data-bind=" visible: active, - foreach: fields"> + foreach: fields" + data-role="data-grid-bulk-row"> <td data-bind=" visible: $parent.getColumn(index).visible, diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html b/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html index d50c4fb2b9c1a169cc28fe1543154a08c468f237..84df5efc7227f9e2fde80a844b39c8017d177dea 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/exportButton.html @@ -7,11 +7,11 @@ <div class="admin__action-dropdown-wrap admin__data-grid-action-export" - data-bind="css: {_active: opened, _disabled: !collapsible}, outerClick: close"> + data-bind="collapsible"> <button class="admin__action-dropdown" type="button" - data-bind="click: toggleOpened" + data-bind="toggleCollapsible" data-toggle="dropdown" aria-haspopup="true"> <span class="admin__action-dropdown-text" data-bind="i18n: 'Export'"></span> @@ -41,7 +41,7 @@ <div class="admin__action-dropdown-footer-main-actions"> <button class="action-tertiary" - data-bind="click: close" + data-bind="closeCollapsible" type="button"> <span data-bind="i18n: 'Cancel'"></span> </button> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html index 78f14ebb39fe7981649700185965a5edb4bb4e74..d0e1787de6a1dc0609f6abc91419ca2f80f21946 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/elements/ui-select.html @@ -20,7 +20,7 @@ focusout: onFocusOut, keydown: keydownSwitcher }, - outerClick: outerClick"> + outerClick: outerClick.bind($data)"> <!-- ko ifnot: chipsEnabled --> <div class="action-select admin__action-multiselect" diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html b/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html index e81c1fd1dbf968392c306554cdf4298a37a87e70..c3ae31d52b181ec49fa5ca785cb018cb4824275a 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/filters/filters.html @@ -4,12 +4,21 @@ * See COPYING.txt for license details. */ --> -<div class="data-grid-filters-actions-wrap"> +<div class="data-grid-filters-actions-wrap" data-bind="collapsible: {openClass: false, closeOnOuter: false}"> <div class="data-grid-filters-action-wrap"> <button - class="action-default _active" + class="action-default" data-action="grid-filter-expand" - data-bind="click: toggleOpened, attr: { disabled: !hasVisible() }, css: { _active: isOpened() }"> + data-bind=" + click: $collapsible.toggle, + attr: { + disabled: !hasVisible(), + 'title': $t('Filters') + }, + css: { + _active: hasVisible() && $collapsible.opened() + }" + > <span data-bind="i18n: 'Filters'"></span> </button> </div> @@ -21,7 +30,7 @@ <div class="admin__data-grid-filters-wrap" - data-bind="css: { _show: isOpened() }" + data-bind="css: { _show: hasVisible() && $collapsible.opened() }" data-part="filter-form"> <fieldset class="admin__fieldset admin__data-grid-filters"> @@ -49,17 +58,16 @@ class="action-tertiary" type="button" data-action="grid-filter-cancel" - data-bind="click: function(){ $data.close().cancel(); }"> + data-bind="click: $data.cancel.bind($data), closeCollapsible"> <span data-bind="i18n: 'Cancel'"></span> </button> <button class="action-secondary" type="button" data-action="grid-filter-apply" - data-bind="click: function(){ $data.close().apply(); }"> + data-bind="click: $data.apply.bind($data), closeCollapsible"> <span data-bind="i18n: 'Apply Filters'"></span> </button> </div> </div> - </div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/listing.html b/app/code/Magento/Ui/view/base/web/templates/grid/listing.html index 49f0e2e392e2587762faefefb4a48e72407a3854..1a1428162c153627ca8d67ac3dad8199101a33c7 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/listing.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/listing.html @@ -4,8 +4,8 @@ * See COPYING.txt for license details. */ --> -<div class="admin__data-grid-wrap"> - <table class="data-grid"> +<div class="admin__data-grid-wrap" data-role="grid-wrapper"> + <table class="data-grid" data-role="grid"> <thead> <tr data-bind="foreach: elems"> <!-- ko template: getHeader() --><!-- /ko --> @@ -14,6 +14,7 @@ <tbody> <!-- ko foreach: { data: rows, as: 'row' } --> <tr class="data-row" + data-role="row" data-bind=" css: { '_odd-row': !!($index() % 2) @@ -35,4 +36,4 @@ <!-- /ko --> </tbody> </table> -</div> \ No newline at end of file +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html new file mode 100644 index 0000000000000000000000000000000000000000..0c79131bc2f8e4c994858b5e5d157641d571c5fd --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging-total.html @@ -0,0 +1,13 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="admin__control-support-text"> + <span data-bind="i18n: totalRecords"></span> records found + <!-- ko if: totalSelected --> + (<span data-bind="i18n: totalSelected"></span> selected) + <!-- /ko --> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html index 354193c7901b2596244f364fdc8af9a659478864..1961cfff11a3d7be640aace14992455fbb0981f8 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging/paging.html @@ -4,16 +4,7 @@ * See COPYING.txt for license details. */ --> -<div class="col-xs-3"> - <div class="admin__control-support-text"> - <span data-bind="text: totalRecords"></span> records found - <!-- ko if: totalSelected --> - (<span data-bind="text: totalSelected"></span> selected) - <!-- /ko --> - </div> -</div> - -<div class="col-xs-7 admin__data-grid-pager-wrap"> +<div class="admin__data-grid-pager-wrap" data-role="toolbar-menu-item"> <!-- ko scope: sizes --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> @@ -41,5 +32,4 @@ <span>Next page</span> </button> </div> - </div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html b/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html index ff61b6bdcf6f57d728cbf2225a262868ea8e675c..dcc9692793e40d2508b061fdf1a33a5f98c1bc6c 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/paging/sizes.html @@ -7,9 +7,10 @@ <div class="selectmenu" - data-bind="css: {_active: opened}, outerClick: close"> + data-bind="collapsible" + data-role="toolbar-collapsible-menu"> <div - data-bind="click: open" + data-bind="openCollapsible" class="selectmenu-value"> <input data-bind="value: _value, attr: {id: index}" @@ -18,11 +19,13 @@ <button class="selectmenu-toggle" type="button" - data-bind="click: toggleOpened, css: {_active: opened}" + data-bind="toggleCollapsible, css: {_active: $collapsible.opened}" aria-haspopup="true"> <span data-bind="i18n: 'Select'"></span> </button> - <div class="selectmenu-items" data-bind="css: {_active: opened}, outerClick: $data.discardAll.bind($data)"> + <div class="selectmenu-items" data-bind="css: {_active: $collapsible.opened}, + outerClick: discardAll.bind($data)" + data-role="toolbar-collapsible-menu"> <ul> <!-- ko foreach: optionsArray --> <li data-bind="css: { _edit: $parent.isEditing(value)}"> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html b/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html index 1a9d495f422965f61401709e6736a7a61c4662fc..3e518b7f874f2881ede0dd2edfa318b232c061cd 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/search/search.html @@ -5,7 +5,11 @@ */ --> <div class="data-grid-search-control-wrap"> + <label class="data-grid-search-label" for="data-grid-search" data-bind="attr: {title: $t('Search')}"> + <span data-bind="text: $t('Search')"></span> + </label> <input + id="data-grid-search" class="admin__control-text data-grid-search-control" data-bind=" attr: { @@ -20,4 +24,4 @@ <button class="action-submit" data-bind="click: apply.bind($data, false)" type="button"> <span data-bind="i18n: 'Search'"></span> </button> -</div> \ No newline at end of file +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/sticky/chips.html b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/chips.html new file mode 100644 index 0000000000000000000000000000000000000000..e396c223d8a92a5486335ffb6367c95f087322e6 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/chips.html @@ -0,0 +1,57 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div + class="admin__data-grid-filters-current" + data-bind="css: {_show: hasData()}"> + <div class="admin__current-filters-title-wrap"> + <span + class="admin__current-filters-title" + data-bind="i18n: 'Active filters:'"></span> + </div> + <div class="admin__current-filters-list-wrap"> + <ul class="admin__current-filters-list" data-role="filter-list"> + <!-- ko foreach: elems --> + <!-- ko foreach: previews --> + <li> + <span data-bind="text: label + ':'"></span> + + <!-- ko if: typeof preview === 'string' --> + <span data-bind="text: preview"></span> + <!-- /ko --> + + <!-- ko if: typeof preview === 'object' --> + <span> + <!-- ko text: preview[0] || '...' --><!-- /ko --> - <!-- ko text: preview[1] || '...' --><!-- /ko --> + </span> + <!-- /ko --> + + <button + class="action-remove" + data-action="grid-filter-remove-chip" + data-bind="click: $parent.clear.bind($parent, elem)" + type="button"> + <span data-bind="i18n: 'Remove'"></span> + </button> + </li> + <!-- /ko --> + <!-- /ko --> + </ul> + </div> + <div class="admin__current-filters-actions-wrap"> + <button + class="action-tertiary action-clear" + type="button" + data-action="grid-filter-reset" + data-bind=" + i18n: 'Clear all', + click: clear, + attr: { + 'data-action': hasData() ? 'grid-filter-reset' : '' + }" + ></button> + </div> +</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/sticky/filters.html b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/filters.html new file mode 100644 index 0000000000000000000000000000000000000000..9a7e06d5699a531809b9527972df744197a6feab --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/filters.html @@ -0,0 +1,22 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="data-grid-filters-actions-wrap"> + <div class="data-grid-filters-action-wrap"> + <button + class="action-default" + data-action="grid-filter-expand" + data-bind=" + click: function(){ + window.scrollTo(0, 0); + $data.trigger('open'); + }, + attr: {disabled: !hasVisible()}"> + <span data-bind="i18n: 'Filters'"></span> + </button> + <span class="filters-active" data-bind="text: $data.active().length || ''"></span> <!-- Added the amount of selected filters --> + </div> +</div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/sticky/listing.html b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/listing.html new file mode 100644 index 0000000000000000000000000000000000000000..fc0c43a4b43315304418d1e1ecbdc602236c06c9 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/listing.html @@ -0,0 +1,17 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="admin__data-grid-wrap" data-role="sticky-el-root"> + <table class="data-grid"> + <thead> + <tr data-bind="foreach: elems"> + <!-- ko template: getHeader() --><!-- /ko --> + </tr> + </thead> + <tbody> + </tbody> + </table> +</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/sticky/sticky.html b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/sticky.html new file mode 100644 index 0000000000000000000000000000000000000000..ec79fd08472ea7a588e5611796f8e6a090b7e43e --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/sticky.html @@ -0,0 +1,22 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div data-bind='visible: visible' class='sticky-header'> + <span class="data-grid-cap-left"></span> + <span class="data-grid-cap-right"></span> + <!-- ko if: enableToolbar --> + <!-- ko scope: toolbar --> + <!-- ko template: $data.stickyTmpl || getTemplate() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + + <!-- ko if: enableHeader --> + <!-- ko scope: listing --> + <!-- ko template: $data.stickyTmpl || getTemplate() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> +</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/sticky/toolbar.html b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/toolbar.html new file mode 100644 index 0000000000000000000000000000000000000000..156873520509f2e1c3cc25168f761102344d448d --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/sticky/toolbar.html @@ -0,0 +1,41 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="admin__data-grid-header" data-role="sticky-el-root"> + <div class="admin__data-grid-header-row"> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko if: $data.componentType === 'massaction' --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko if: $data.componentType === 'paging' --> + <!-- ko template: totalTmpl --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + <!-- ko foreach: getRegion('dataGridFilters') --> + <!-- ko template: $data.stickyTmpl || getTemplate() --><!-- /ko --> + <!-- /ko --> + <div class="admin__data-grid-actions-wrap"> + <!-- ko foreach: getRegion('dataGridActions') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko if: $data.componentType === 'paging' --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + </div> +</div> +<!-- ko foreach: getRegion('dataGridFilters') --> + <!-- ko if: $data.index === 'listing_filters' --> + <!-- ko scope: chips --> + <!-- ko template: $data.stickyTmpl || getTemplate() --> + <!-- /ko --> + <!-- /ko --> +<!-- /ko --> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html b/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html index 0812e3fe862d2fac42f48fdd80ead31355f23107..36482b1d973bae48f5d946dff86c27f6c0bc724e 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/toolbar.html @@ -5,20 +5,43 @@ */ --> -<div class="admin__data-grid-header"> +<div class="admin__data-grid-header" + data-role="data-grid-toolbar"> <div class="admin__data-grid-header-row"> <div class="admin__data-grid-actions-wrap"> <!-- ko foreach: getRegion('dataGridActions') --> - <!-- ko template: getTemplate() --><!-- /ko --> + <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </div> <!-- ko foreach: getRegion('dataGridFilters') --> - <!-- ko template: getTemplate() --><!-- /ko --> + <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </div> <div class="admin__data-grid-header-row row row-gutter"> - <!-- ko foreach: getRegion('bottom') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> + <div class="col-xs-2"> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko if: $data.componentType === 'massaction' --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + </div> + <div class="col-xs-10"> + <div class="row"> + <div class="col-xs-3"> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko if: $data.componentType === 'paging' --> + <!-- ko template: totalTmpl --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + </div> + <div class="col-xs-9"> + <!-- ko foreach: getRegion('bottom') --> + <!-- ko if: $data.componentType === 'paging' --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <!-- /ko --> + </div> + </div> + </div> </div> </div> diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html b/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html index db716f2a01323031a01ea4538bfa4689c2574df9..5a3f2997181c8499d0675de42d62acfd16c176b1 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/tree-massactions.html @@ -4,35 +4,33 @@ * See COPYING.txt for license details. */ --> -<div class="col-xs-2" data-bind="outerClick: close"> - <div - class="action-select-wrap" - data-bind="css: {'_active': opened}"> - <button - class="action-select" - data-bind="title: $t('Select Items'), click: toggleOpened"> - <span data-bind="text: $t('Actions')"></span> - </button> - <div class="action-menu-items"> - <ul - class="action-menu" - data-bind="css: {'_active': opened}, - foreach: {data: actions, as: 'action'}"> - <li +<div + class="action-select-wrap" + data-bind="css: {'_active': opened}, outerClick: close.bind($data)"> + <button + class="action-select" + data-bind="title: $t('Select Items'), click: toggleOpened"> + <span data-bind="text: $t('Actions')"></span> + </button> + <div class="action-menu-items"> + <ul + class="action-menu" + data-bind="css: {'_active': opened}, + foreach: {data: actions, as: 'action'}"> + <li data-bind="css: { '_visible': $data.visible, '_parent': $data.actions}"> - <span - class="action-menu-item" - data-bind="text: label, - click: $parent.applyAction.bind($parent, type)"> - </span> - <!-- ko if: $data.actions --> - <!-- ko template: {name: $parent.submenuTemplate, data: $parent} --> - <!-- /ko --> - <!-- /ko--> - </li> - </ul> - </div> + <span + class="action-menu-item" + data-bind="text: label, + click: $parent.applyAction.bind($parent, type)"> + </span> + <!-- ko if: $data.actions --> + <!-- ko template: {name: $parent.submenuTemplate, data: $parent} --> + <!-- /ko --> + <!-- /ko--> + </li> + </ul> </div> </div> diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less index 080f0e60d49481314c351aa874b5663f7d8f0b2f..50d58b39e6e259760e09a629c5f1b73dac11c1cc 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/_data-grid.less @@ -7,6 +7,13 @@ // UI -> Data Grid // _____________________________________________ +// +// Variables +// --------------------------------------------- + +@data-grid-sticky-header__z-index: @page-actions__fixed__z-index; +@data-grid-overlay__z-index: @data-grid-sticky-header__z-index + 1; + // // Components // --------------------------------------------- @@ -32,9 +39,9 @@ .admin__data-grid-loading-mask { background: rgba(255, 255, 255, .5); bottom: 0; - left: 0; + left: -@page-content__padding-horizontal; position: absolute; - right: 0; + right: -@page-content__padding-horizontal; top: 0; z-index: @data-grid-overlay__z-index; .spinner { @@ -767,4 +774,4 @@ body._in-resize { } } } -} \ No newline at end of file +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less index f83463ada82d3026424f9140080eddf41c6f3d77..61c9807d8e6b9d96001f9229e884526c70ca0fff 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/_data-grid-header.less @@ -17,6 +17,7 @@ @import 'data-grid-header/_data-grid-action-bookmarks.less'; @import 'data-grid-header/_data-grid-action-columns.less'; @import 'data-grid-header/_data-grid-action-export.less'; +@import 'data-grid-header/_data-grid-sticky-header.less'; .admin__data-grid-header { font-size: @font-size__base; // ToDo UI: should be deleted, added to prevent fz override with .grid diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less index 8cbd9e579ff23c15420bd925add44202e4639267..773abad71b93e9b82282af0c7b51b00f8e30ec4a 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-filters.less @@ -98,6 +98,9 @@ background-color: @data-grid-search-menu-item__background-color; } } + .data-grid-search-label { + display: none; + } } .data-grid-search-control { @@ -111,6 +114,7 @@ padding-left: @indent__base; .action-default { font-size: @data-grid-filters__font-size; + margin-bottom: 1rem; padding-left: @data-grid-filters-action__padding-left; padding-right: @data-grid-filters-action__padding-right; padding-top: @action__padding-top + .1rem; @@ -119,10 +123,8 @@ border-bottom-color: @data-grid-filters__background-color; border-right-color: @data-grid-filters-action__active__border-color; font-weight: @font-weight__semibold; - margin-left: 0; - margin-right: 0; - margin-top: -.1rem; - padding-bottom: 1.9rem; + margin: -.1rem 0 0; + padding-bottom: 1.6rem; padding-top: @action__padding-top + .2rem; position: relative; z-index: @data-grid-header__z-index - 19; @@ -138,6 +140,7 @@ } &:before { &:extend(.abs-icon all); + color: @action-dropdown__color; content: @icon-filter__content; font-size: 1.8rem; margin-right: .4rem; @@ -146,6 +149,9 @@ vertical-align: top; } } + .filters-active { + display: none; + } } // diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-sticky-header.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-sticky-header.less new file mode 100644 index 0000000000000000000000000000000000000000..0083101d59ff94c3eb1cfb61a03a64bc49724de6 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-sticky-header.less @@ -0,0 +1,271 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// --------------------------------------------- + +@data-grid-sticky-header__background-color: @color-white-fog; +@data-grid-sticky-header__border-color: @color-gray89; +@data-grid-sticky-header__box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.25); + +@data-grid-sticky-header-actions__background-color: @color-white; +@data-grid-sticky-header-actions__border-color: @action__border-color; +@data-grid-sticky-header-actions__box-shadow: @component__box-shadow__base; +@data-grid-sticky-header-actions__margin: -@indent__xs 0 0 1.1rem; +@data-grid-sticky-header-actions__padding: .6rem; +@data-grid-sticky-header-actions__z-index: 210; + +@data-grid-sticky-header-action-select__width: percentage((2 / @grid-columns)); + +// + +.sticky-header { + background-color: @data-grid-sticky-header__background-color; + border-bottom: 1px solid @data-grid-sticky-header__border-color; + box-shadow: @data-grid-sticky-header__box-shadow; + left: @page-wrapper__indent-left; + right: 0; + margin-top: -1px; + padding: @indent__xs @indent__l 0; + position: fixed; + top: 77px; + z-index: @data-grid-sticky-header__z-index; + + .admin__data-grid-wrap { + margin-bottom: 0; + overflow-x: visible; + padding-bottom: 0; + } + + .admin__data-grid-header-row { + position: relative; + text-align: right; + &:last-child { + margin: 0; + } + } + + .data-grid-search-control-wrap, + .data-grid-filters-actions-wrap, + .admin__data-grid-filters-wrap, + .admin__data-grid-pager-wrap, + .admin__data-grid-actions-wrap { + display: inline-block; + float: none; + vertical-align: top; + } + + // Action select + .action-select-wrap { + float: left; + margin-right: 1.5rem; + width: @data-grid-sticky-header-action-select__width; + } + + // Total found + .admin__control-support-text { + float: left; + } + + // Data Grid Search + .data-grid-search-control-wrap { + margin: @data-grid-sticky-header-actions__margin; + width: auto; + .data-grid-search-label { + box-sizing: border-box; + cursor: pointer; + display: block; + min-width: 3.8rem; + padding: 1.2rem @data-grid-sticky-header-actions__padding 1.7rem; + position: relative; + text-align: center; + &:before { + &:extend(.abs-icon all); + color: @action-dropdown__color; + content: @icon-search__content; + font-size: @data-grid-search-action__size; + transition: @smooth__color; + } + &:hover { + &:before { + color: @action-dropdown__hover__color; + } + } + span { + display: none; + } + } + } + + // Filters + .data-grid-filters-actions-wrap { + margin: @data-grid-sticky-header-actions__margin; + padding-left: 0; + position: relative; + .action-default { + background-color: transparent; + border: 1px solid transparent; + box-sizing: border-box; + min-width: 3.8rem; + padding: 1.2rem @data-grid-sticky-header-actions__padding 1.7rem; + text-align: center; + transition: all @appearing__transition-duration @apperaing__transition-timing-function; + span { + display: none; + } + &:before { + margin: 0; + } + &._active { + background-color: @data-grid-sticky-header-actions__background-color; + border-color: @data-grid-sticky-header-actions__border-color; + border-bottom-color: @data-grid-sticky-header-actions__background-color; + box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5); + z-index: @data-grid-sticky-header-actions__z-index; + &:after { + background-color: @data-grid-sticky-header-actions__background-color; + content: ''; + height: 6px; + left: -2px; + position: absolute; + right: -6px; + top: 100%; + } + } + } + } + + .data-grid-filters-action-wrap { + padding: 0; + } + + .admin__data-grid-filters-wrap { + background-color: @data-grid-sticky-header-actions__background-color; + border: 1px solid @data-grid-sticky-header-actions__border-color; + box-shadow: @data-grid-sticky-header__box-shadow; + left: 0; + padding-left: 3.5rem; + padding-right: 3.5rem; + position: absolute; + top: 100%; + width: 100%; + z-index: @data-grid-sticky-header-actions__z-index - 1; + } + + .admin__data-grid-filters-current { + + .admin__data-grid-filters-wrap { + &._show { + margin-top: -6px; + } + } + } + + .filters-active { + background-color: @color-phoenix-down; + border-radius: 10px; + color: @color-white; + display: block; + font-size: @font-size__base; + font-weight: @font-weight__bold; + padding: .1rem .7rem; + position: absolute; + right: -7px; + top: 0; + z-index: @data-grid-sticky-header-actions__z-index + 1; + &:empty { + padding-top: 0; + padding-bottom: 0; + } + } + + // Default view & columns + .admin__data-grid-actions-wrap { + margin: @data-grid-sticky-header-actions__margin; + padding-right: .3rem; + .admin__action-dropdown { + background-color: transparent; + box-sizing: border-box; + min-width: 3.8rem; + padding-left: @data-grid-sticky-header-actions__padding; + padding-right: @data-grid-sticky-header-actions__padding; + text-align: center; + .admin__action-dropdown-text { + display: inline-block; + min-width: 0; + max-width: 0; + overflow: hidden; + } + &:before { + margin: 0; + } + } + .admin__action-dropdown-wrap { + margin-right: 1.1rem; + } + .admin__action-dropdown-wrap, + .admin__action-dropdown { + &:after { + display: none; + } + } + ._active { + .admin__action-dropdown { + background-color: @color-white; + } + } + } + + .admin__data-grid-action-bookmarks { + .admin__action-dropdown { + &:before { + position: relative; + top: -3px; + } + } + } + + .admin__data-grid-filters-current { + border-top: 0; + border-bottom: 0; + margin-bottom: 0; + padding-bottom: 0; + padding-top: 0; + } + + .data-grid-search-control-wrap .data-grid-search-control, + .data-grid-search-control-wrap .action-submit, + .admin__data-grid-pager .admin__control-text, + .admin__data-grid-pager-wrap .admin__control-support-text { + display: none; + } + + .action-next { + margin: 0; + } + + // Table header + .data-grid { + margin-bottom: -1px; + } +} + +.data-grid-cap-left, +.data-grid-cap-right { + background-color: @data-grid-sticky-header__background-color; + bottom: -2px; + position: absolute; + top: 6rem; + width: @page-content__padding-horizontal; + z-index: @action-multicheck__z-index + 1; +} + +.data-grid-cap-left { + left: 0; +} + +.data-grid-cap-right { + right: 0; +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less index e26049d26d82a179dc9be92abf2b8d7a086a70ef..907fe6e29c951d49e54f86a3d6550ac7e5d2b845 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-dropdown.less @@ -93,11 +93,11 @@ .action-toggle-triangle( @_dropdown__padding-right: @action-dropdown__padding-right; ); - box-shadow: none; background-color: @action-dropdown__background-color; border: 1px solid transparent; border-bottom: none; border-radius: 0; + box-shadow: none; color: @action-dropdown__color; display: inline-block; font-size: @action-dropdown__font-size; diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js new file mode 100644 index 0000000000000000000000000000000000000000..7457a325e17e4f8476a869e71334a020c341363c --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js @@ -0,0 +1,37 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'Magento_Ui/js/grid/editing/bulk' +], function (Bulk) { + 'use strict'; + + describe('Magento_Ui/js/grid/editing/bulk', function () { + var bulkObj, + temp; + + beforeEach(function () { + bulkObj = new Bulk(); + }); + it('has initObservable', function () { + expect(bulkObj).toBeDefined(); + }); + it('has apply method', function () { + spyOn(bulkObj, 'isValid'); + temp = bulkObj.apply(); + expect(bulkObj.isValid).toHaveBeenCalled(); + expect(temp).toBeDefined(); + }); + it('can apply data', function () { + spyOn(bulkObj, 'getData'); + bulkObj.applyData(); + expect(bulkObj.getData).toHaveBeenCalled(); + }); + it('has updateState method', function () { + spyOn(bulkObj, 'updateState'); + bulkObj.updateState(); + expect(bulkObj.updateState).toHaveBeenCalled(); + }); + }) +}); \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js index 71cc27d7da04d57d3a572107e450d290cc4e83e0..4df1017646af7dc8846129ccc4eece119cc291b4 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js @@ -4,177 +4,80 @@ */ define([ - 'underscore', 'Magento_Ui/js/grid/filters/filters' -], function (_, Filters) { +], function (Filter) { 'use strict'; - describe('ui/js/grid/filters/filters', function () { - var filters; + describe('Magento_Ui/js/grid/filters/filters', function () { + var filterObj, + temp; beforeEach(function () { - filters = new Filters({ - elems: [], - index: 'index', - name: 'name', - indexField: 'id', - dataScope: 'scope', - provider: 'provider' - }); + filterObj = new Filter(); }); - - it('Default state - Select no fields.', function () { - expect(filters.elems()).toEqual([]); - filters.elems.push({id:1}); - filters.elems.push({id:1}); - expect(filters.elems()).not.toEqual([]); + it('has been initialized', function () { + expect(filterObj).toBeDefined(); }); - it('Checks if specified filter is active.', function () { - var filter = {id: 1}; - - expect(filters.isFilterActive(filter)).toBe(false); - filters.active().push(filter); - expect(filters.isFilterActive(filter)).toBe(true); + it('has initObservable', function () { + temp = filterObj.initObservable(); + expect(temp).toBeDefined(); }); - it('Tells whether specified filter should be visible.', function () { - var filter = { - visible: function () { - return false; - } - }; - - expect(filters.isFilterVisible(filter)).toBe(false); - filters.active().push(filter); - expect(filters.isFilterActive(filter)).toBe(true); - filter.visible = function() { - return true; - }; - expect(filters.isFilterActive(filter)).toBe(true); - filters.active().pop(); - expect(filters.isFilterActive(filter)).toBe(false); + it('has initElement', function () { + spyOn(filterObj, 'initElement'); + filterObj.initElement(); + expect(filterObj.initElement).toHaveBeenCalled(); }); - it('Checks if collection has visible filters.', function () { - var filter = { - visible: function () { - return false; - } + it('has clear', function () { + temp = filterObj.clear(); + expect(temp).toBeDefined(); + }); + it('has apply', function () { + temp = filterObj.apply(); + expect(temp).toBeDefined(); + }); + it('has cancel', function () { + temp = filterObj.cancel(); + expect(temp).toBeDefined(); + }); + it('has isOpened method', function () { + filterObj.opened = function () { + return true; }; - - filters.elems.push(filter); - expect(filters.hasVisible()).toBe(false); - filter.visible = function() { + filterObj.hasVisible = function () { return true; }; - filters.elems.push(filter); - expect(filters.hasVisible()).toBe(true); - filters.elems.removeAll(); - expect(filters.hasVisible()).toBe(false); - filters.active().push(filter); - expect(filters.hasVisible()).toBe(false); + temp = filterObj.isOpened(); + expect(temp).toBeTruthy(); }); - it('Tells whether filters panel should be opened.', function () { - var filter = { + it('has isFilterVisible method', function () { + temp = { visible: function () { return false; } }; - - filters.opened(false); - filters.elems.push(filter); - expect(filters.isOpened()).toBe(false); - filter.visible = function() { - return true; - }; - filters.elems.push(filter); - filters.opened(true); - expect(filters.isOpened()).toBe(true); - filters.elems.removeAll(); - expect(filters.isOpened()).toBe(false); - filters.active().push(filter); - expect(filters.isOpened()).toBe(false); - }); - it('Resets filters to the last applied state.', function () { - filters.applied = {}; - filters.filters = {}; - filters.cancel(); - expect(filters.filters).toEqual(filters.filters); - filters.filters = {id:1}; - filters.cancel(); - expect(filters.filters).toEqual({}); - filters.applied = {id:1}; - filters.cancel(); - expect(filters.filters).toEqual(filters.applied); + spyOn(filterObj, 'isFilterActive'); + filterObj.isFilterVisible(temp); + expect(filterObj.isFilterActive).toHaveBeenCalled(); }); - it('Sets filters data to the applied state.', function () { - filters.applied = {}; - filters.filters = {}; - filters.apply(); - expect(filters.applied).toEqual({}); - filters.filters = {}; - filters.applied = {id:2}; - filters.apply(); - expect(filters.applied).toEqual({}); - filters.filters = {id:1}; - filters.applied = {}; - filters.apply(); - expect(filters.applied).toEqual({id:1}); - filters.filters = {id:1}; - filters.applied = {id:2}; - filters.apply(); - expect(filters.applied).toEqual({id:1}); + it('has isFilterActive method', function () { + spyOn(filterObj, 'isFilterActive'); + filterObj.isFilterActive(); + expect(filterObj.isFilterActive).toHaveBeenCalled(); }); - it('Clears filters data.', function () { - var elem = { - value: '', - getPreview: function () { - return true; - }, - clear: function () { - this.value = ''; - return this.value; - } - }; - - filters.active.push(elem); - filters.applied = {}; - filters.filters = {}; - filters.clear(); - expect(filters.active.first().value).toEqual(''); - filters.active.first().value = 1; - filters.clear(); - expect(filters.active.first().value).toEqual(''); + it('has hasVisible method', function () { + spyOn(filterObj, 'hasVisible'); + filterObj.hasVisible(); + expect(filterObj.hasVisible).toHaveBeenCalled(); }); - it('Set active elements where exist value from elems.', function () { - var elem = { - getPreview: function () { - return true; - }, - hasData: function () { - return false; - } - }; - - filters.elems.push(elem); - filters.extractActive(); - expect(filters.active().length).toEqual(0); - elem.hasData = function() { - return true; - }; - filters.elems.removeAll(); - filters.elems().push(elem); - filters.extractActive(); - expect(filters.active().length).toEqual(1); + it('has extractActive method', function () { + spyOn(filterObj, 'extractActive'); + filterObj.extractActive(); + expect(filterObj.extractActive).toHaveBeenCalled(); }); - it('Set previews from argument elements.', function () { - var elem = { - getPreview: function() { - return true; - } - }; - - filters.elems.push(elem); - filters.extractActive(filters.elems); - expect(filters.active().length).toEqual(0); + it('has extractPreviews method', function () { + spyOn(filterObj, 'extractPreviews'); + filterObj.extractPreviews(); + expect(filterObj.extractPreviews).toHaveBeenCalled(); }); }); -}); +}); \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js index 7a03ca73938611fdc2f935c6d9afd3849c54f752..a213081a8115aa179513df062d8c1b424db64ecf 100644 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js @@ -51,8 +51,9 @@ define([ expect(type).toEqual('object'); }); it('Check "this.table" variable', function () { - obj.initTable('magento'); - expect(obj.table).toEqual('magento'); + arg = document.createElement('table'); + obj.initTable(arg); + expect(arg.classList.contains(obj.fixedLayoutClass)).toBeTruthy(); }); }); describe('"initColumn" method', function () { diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js new file mode 100644 index 0000000000000000000000000000000000000000..d1b31419379e51f76c853263dd72cc7cc0d32d6c --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js @@ -0,0 +1,57 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'Magento_Ui/js/grid/search/search' +], function (Search) { + 'use strict'; + + describe('Magento_Ui/js/search/search', function () { + var searchObj, + temp; + + beforeEach(function () { + searchObj = new Search(); + }); + it('has initialized', function () { + expect(searchObj).toBeDefined(); + }); + it('has initObservable', function () { + temp = searchObj.initObservable(); + expect(temp).toBeDefined(); + }); + it('has initObservable', function () { + spyOn(searchObj, 'initChips'); + searchObj.initChips(); + expect(searchObj.initChips).toHaveBeenCalled(); + }); + it('has initChips', function () { + spyOn(searchObj, 'chips'); + searchObj.initChips(); + expect(searchObj.chips).toHaveBeenCalled(); + }); + it('has clear', function () { + spyOn(searchObj, 'value'); + searchObj.clear(); + expect(searchObj.value).toHaveBeenCalled(); + }); + it('has clear', function () { + spyOn(searchObj, 'inputValue'); + searchObj.cancel(); + expect(searchObj.inputValue).toHaveBeenCalled(); + }); + it('has apply', function () { + spyOn(searchObj, 'value'); + spyOn(searchObj, 'inputValue'); + searchObj.apply(); + expect(searchObj.value).toHaveBeenCalled(); + expect(searchObj.inputValue).toHaveBeenCalled(); + }); + it('has updatePreview', function () { + spyOn(searchObj, 'updatePreview'); + searchObj.updatePreview(); + expect(searchObj.updatePreview).toHaveBeenCalled(); + }); + }); +}); diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js new file mode 100644 index 0000000000000000000000000000000000000000..7902ccc21444f4547924fc00f970bac4b22c87aa --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js @@ -0,0 +1,172 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'Magento_Ui/js/grid/sticky/sticky' +], function (_, Sticky) { + 'use strict'; + + describe('ui/js/grid/sticky/sticky', function () { + var stickyObj, + data, + stub; + + Sticky.prototype.initialize = function () { + }; + + stickyObj = new Sticky({}); + + describe('has initialized', function () { + it('has been defined', function () { + expect(stickyObj).toBeDefined(); + }); + it('has initialized observable', function () { + data = stickyObj.initObservable(); + expect(data).toBeDefined(); + }); + it('has initListingNode method', function () { + spyOn(stickyObj, 'initListingNode'); + stickyObj.initListingNode(); + expect(stickyObj.initListingNode).toHaveBeenCalled(); + }); + it('has initStickyToolbarNode method', function () { + stickyObj.initStickyToolbarNode({}); + expect(stickyObj.stickyToolbarNode).toBeDefined(); + }); + it('has initContainerNode method', function () { + spyOn(stickyObj, 'initContainerNode'); + stickyObj.initContainerNode(); + expect(stickyObj.initContainerNode).toHaveBeenCalled(); + }); + it('has initListeners method', function () { + spyOn(stickyObj, 'initListeners'); + stickyObj.initListeners(); + expect(stickyObj.initListeners).toHaveBeenCalled(); + }); + it('has initOnScroll method', function () { + stickyObj.initOnScroll(); + expect(stickyObj.lastHorizontalScrollPos).toBeDefined(); + }); + it('has initOnListingScroll method', function () { + spyOn(stickyObj, 'initOnListingScroll'); + stickyObj.initOnListingScroll(); + expect(stickyObj.initOnListingScroll).toHaveBeenCalled(); + }); + it('has initOnResize method', function () { + spyOn(stickyObj, 'initOnResize'); + stickyObj.initOnResize(); + expect(stickyObj.initOnResize).toHaveBeenCalled(); + }); + }); + describe('has handlers', function () { + it('has onWindowScroll event', function () { + stickyObj.adjustOffset = function (){ + return this; + }; + + stickyObj.lastHorizontalScrollPos = 100500; + spyOn(stickyObj, 'adjustDataGridCapPositions'); + stickyObj.onWindowScroll(); + expect(stickyObj.adjustDataGridCapPositions).toHaveBeenCalled(); + }); + it('has onListingScroll method', function () { + spyOn(stickyObj, 'adjustOffset'); + stickyObj.onListingScroll(); + expect(stickyObj.adjustOffset).toHaveBeenCalled(); + }); + it('has onResize method', function () { + spyOn(stickyObj, 'onResize'); + stickyObj.onResize(); + expect(stickyObj.onResize).toHaveBeenCalled(); + }); + }); + describe('has getters', function () { + it('has getListingWidth', function () { + stickyObj.listingNode = { + width: function () { + return 100500; + } + }; + data = stickyObj.getListingWidth(); + expect(data).toBeDefined(); + }); + it('has getTableWidth method', function () { + spyOn(stickyObj, 'getTableWidth'); + stickyObj.getTableWidth(); + expect(stickyObj.getTableWidth).toHaveBeenCalled(); + }); + it('has getTopElement', function () { + stickyObj.toolbarNode = {}; + data = stickyObj.getTopElement(); + expect(data).toBeDefined(); + }); + it('has getOtherStickyElementsSize', function () { + stickyObj.otherStickyElsSize = null; + data = stickyObj.getOtherStickyElementsSize(); + expect(data).toEqual(stickyObj.otherStickyElsSize); + }); + it('has getListingTopYCoord method', function () { + spyOn(stickyObj, 'getListingTopYCoord'); + stickyObj.getListingTopYCoord(); + expect(stickyObj.getListingTopYCoord).toHaveBeenCalled(); + }); + it('has getMustBeSticky method', function () { + spyOn(stickyObj, 'getMustBeSticky'); + stickyObj.getMustBeSticky(); + expect(stickyObj.getMustBeSticky).toHaveBeenCalled(); + }); + }); + describe('has dom manipulators', function () { + it('has resizeContainer event', function () { + spyOn(stickyObj, 'resizeContainer'); + stickyObj.resizeContainer(); + expect(stickyObj.resizeContainer).toHaveBeenCalled(); + }); + it('has resizeCols event', function () { + spyOn(stickyObj, 'resizeCols'); + stickyObj.resizeCols(); + expect(stickyObj.resizeCols).toHaveBeenCalled(); + }); + it('has resetToTop event', function () { + spyOn(stickyObj, 'resetToTop'); + stickyObj.resetToTop(); + expect(stickyObj.resetToTop).toHaveBeenCalled(); + }); + it('has toggleContainerVisibility event', function () { + spyOn(stickyObj, 'visible'); + stickyObj.toggleContainerVisibility(); + expect(stickyObj.visible).toHaveBeenCalled(); + }); + it('has adjustContainerElemsWidth event', function () { + stickyObj.resizeContainer = function(){ + return this; + }; + stickyObj.resizeCols = function(){ + return this; + }; + spyOn(stickyObj, 'resizeBulk'); + stickyObj.adjustContainerElemsWidth(); + expect(stickyObj.resizeBulk).toHaveBeenCalled(); + }); + it('has adjustOffset event', function () { + spyOn(stickyObj, 'adjustOffset'); + stickyObj.adjustOffset(); + expect(stickyObj.adjustOffset).toHaveBeenCalled(); + }); + it('has checkPos event', function () { + stickyObj.visible = function(){ + return false; + }; + stickyObj.getMustBeSticky = function(){ + return false; + }; + + data = stickyObj.checkPos(); + expect(data).toBeDefined(); + }) + }); + }) +}); \ No newline at end of file diff --git a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js index 3f076659b49239d26ac77fc5e593d511b4caf8f4..f198fee51b045e6a270758eda15d49e788531b3d 100644 --- a/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js +++ b/dev/tests/js/jasmine/tests/lib/mage/gallery.test.js @@ -113,7 +113,7 @@ define([ }); it('breakpoints override configs', function () { - expect($('.fotorama__arr').css('display')).toBe('none'); + expect($('.fotorama__arr').css('display')).toBe('block'); }); }); }); diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt index a76f67f4761e344f9a3011e1ef6e8d4a6746048e..f7c90d331d345918b1ef11d61b5c959ca3fa63fc 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/blacklist/magento.txt @@ -77,6 +77,7 @@ app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.j app/code/Magento/Checkout/view/frontend/web/js/checkout-data.js app/code/Magento/Checkout/view/frontend/web/js/discount-codes.js app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js +app/code/Magento/Checkout/view/frontend/web/js/model/authentication-messages.js app/code/Magento/Checkout/view/frontend/web/js/model/cart/estimate-service.js app/code/Magento/Checkout/view/frontend/web/js/model/cart/totals-processor/default.js app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js @@ -118,6 +119,7 @@ app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js app/code/Magento/Checkout/view/frontend/web/js/region-updater.js app/code/Magento/Checkout/view/frontend/web/js/shopping-cart.js app/code/Magento/Checkout/view/frontend/web/js/sidebar.js +app/code/Magento/Checkout/view/frontend/web/js/view/authentication-messages.js app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -161,7 +163,10 @@ app/code/Magento/Cms/view/adminhtml/requirejs-config.js app/code/Magento/Cms/view/adminhtml/web/js/folder-tree.js app/code/Magento/ConfigurableProduct/view/adminhtml/requirejs-config.js app/code/Magento/ConfigurableProduct/view/adminhtml/web/catalog/product/attribute.js +app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/advanced-pricing-handler.js app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js +app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/options/price-type-handler.js +app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/product-grid.js app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/attributes_values.js app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/bulk.js app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/steps/select_attributes.js @@ -315,7 +320,9 @@ app/code/Magento/Sales/view/frontend/web/js/view/last-ordered-items.js app/code/Magento/Sales/view/frontend/web/orders-returns.js app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js +app/code/Magento/SalesRule/view/frontend/web/js/model/payment/discount-messages.js app/code/Magento/SalesRule/view/frontend/web/js/view/cart/totals/discount.js +app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount-messages.js app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js app/code/Magento/Search/view/frontend/requirejs-config.js @@ -418,13 +425,13 @@ app/code/Magento/Ui/view/base/web/js/grid/export.js app/code/Magento/Ui/view/base/web/js/grid/filters/chips.js app/code/Magento/Ui/view/base/web/js/grid/filters/filters.js app/code/Magento/Ui/view/base/web/js/grid/filters/group.js -app/code/Magento/Ui/view/base/web/js/grid/listing.js app/code/Magento/Ui/view/base/web/js/grid/massactions.js app/code/Magento/Ui/view/base/web/js/grid/paging/paging.js app/code/Magento/Ui/view/base/web/js/grid/paging/sizes.js app/code/Magento/Ui/view/base/web/js/grid/provider.js app/code/Magento/Ui/view/base/web/js/grid/resize.js app/code/Magento/Ui/view/base/web/js/grid/search/search.js +app/code/Magento/Ui/view/base/web/js/grid/sticky/sticky.js app/code/Magento/Ui/view/base/web/js/grid/tree-massactions.js app/code/Magento/Ui/view/base/web/js/lib/class.js app/code/Magento/Ui/view/base/web/js/lib/collapsible.js @@ -438,6 +445,7 @@ app/code/Magento/Ui/view/base/web/js/lib/events.js app/code/Magento/Ui/view/base/web/js/lib/key-codes.js app/code/Magento/Ui/view/base/web/js/lib/ko/bind/after-render.js app/code/Magento/Ui/view/base/web/js/lib/ko/bind/class.js +app/code/Magento/Ui/view/base/web/js/lib/ko/bind/collapsible.js app/code/Magento/Ui/view/base/web/js/lib/ko/bind/datepicker.js app/code/Magento/Ui/view/base/web/js/lib/ko/bind/fadeVisible.js app/code/Magento/Ui/view/base/web/js/lib/ko/bind/i18n.js @@ -466,11 +474,13 @@ app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js app/code/Magento/Ui/view/base/web/js/lib/view/utils/async.js app/code/Magento/Ui/view/base/web/js/lib/view/utils/bindings.js app/code/Magento/Ui/view/base/web/js/lib/view/utils/dom-observer.js +app/code/Magento/Ui/view/base/web/js/lib/view/utils/raf.js app/code/Magento/Ui/view/base/web/js/modal/alert.js app/code/Magento/Ui/view/base/web/js/modal/confirm.js app/code/Magento/Ui/view/base/web/js/modal/modal.js app/code/Magento/Ui/view/base/web/js/modal/modalToggle.js app/code/Magento/Ui/view/frontend/web/js/model/messageList.js +app/code/Magento/Ui/view/frontend/web/js/model/messages.js app/code/Magento/Ui/view/frontend/web/js/view/messages.js app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js @@ -532,10 +542,13 @@ dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/b dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/storage.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/bookmarks/view.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/controls/columns.test.js +dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/editing/bulk.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/filters.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/filters/group.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/paging/paging.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/resize.test.js +dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/search/search.test.js +dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/sticky/sticky.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/grid/tree-massactions.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/core.test.js dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/lib/component/links.test.js diff --git a/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc b/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc index 49ab9e6c2cf2e3cb80b9a7cbb44a17855337ea8e..b8071503882e23246959a4b515edeb435a1f325c 100644 --- a/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc +++ b/dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc @@ -1,7 +1,4 @@ { - "plugins": [ - "jscs-jsdoc" - ], "disallowKeywords": [ "with", "continue" @@ -62,6 +59,7 @@ "beforeOpeningCurlyBrace": true, "beforeOpeningRoundBrace": true }, + "disallowNewlineBeforeBlockStatements": true, "disallowDanglingUnderscores": null, "disallowEmptyBlocks": true, "disallowMixedSpacesAndTabs": true, diff --git a/dev/tools/grunt/configs/eslint.js b/dev/tools/grunt/configs/eslint.js index 9ce30aa58156ea22b011b2503f987453a6bdec7a..5dcbccf9ad4cd50686d89e43facc5d240bcb7048 100644 --- a/dev/tools/grunt/configs/eslint.js +++ b/dev/tools/grunt/configs/eslint.js @@ -19,7 +19,7 @@ module.exports = { configFile: 'dev/tests/static/testsuite/Magento/Test/Js/_files/eslint/.eslintrc', reset: true, outputFile: 'dev/tests/static/eslint-error-report.xml', - format: 'checkstyle', + format: 'junit', quiet: true }, src: '' diff --git a/dev/tools/grunt/configs/jscs.js b/dev/tools/grunt/configs/jscs.js index 8b89e0293bdb5de151a19266e8ffe5fe28d83de4..338deb017017d7dd50521f7090bb6268975fc6f8 100644 --- a/dev/tools/grunt/configs/jscs.js +++ b/dev/tools/grunt/configs/jscs.js @@ -16,7 +16,7 @@ module.exports = { options: { config: 'dev/tests/static/testsuite/Magento/Test/Js/_files/jscs/.jscsrc', reporterOutput: 'dev/tests/static/jscs-error-report.xml', - reporter: 'checkstyle' + reporter: 'junit' }, src: '' } diff --git a/package.json b/package.json index 54a730729fb3be86a4d8db13c15cea36367ff409..8869196abeffc1653e34681226e7293a9c71c179 100644 --- a/package.json +++ b/package.json @@ -21,15 +21,14 @@ "grunt-contrib-jasmine": "^0.8.1", "grunt-contrib-less": "^0.12.0", "grunt-contrib-watch": "^0.6.1", - "grunt-eslint": "^16.0.0", + "grunt-eslint": "^17.0.0", "grunt-exec": "^0.4.6", - "grunt-jscs": "^1.8.0", + "grunt-jscs": "^2.1.0", "grunt-replace": "^0.9.2", "grunt-styledocco": "^0.1.4", "grunt-template-jasmine-requirejs": "^0.2.3", "grunt-text-replace": "^0.4.0", "imagemin-svgo": "^4.0.1", - "jscs-jsdoc": "^1.1.0", "load-grunt-config": "^0.16.0", "morgan": "^1.5.0", "node-minify": "^1.0.1",