From ecc391b6da34af0b65ed639c910f0deccbfeddf1 Mon Sep 17 00:00:00 2001 From: Olga Matviienko Date: Wed, 10 Feb 2016 15:44:57 +0200 Subject: [PATCH 01/31] MAGETWO-41203: [UI] Dashboard --- .../layout/adminhtml_dashboard_index.xml | 5 +- .../view/adminhtml/templates/timeline.phtml | 462 ++++++++++++++ .../templates/catalog/product/edit.phtml | 3 + .../web/css/source/_module.less | 3 + .../source/module/_staging-data-tooltip.less | 110 ++++ .../backend/web/css/source/_components.less | 3 + .../css/source/components/_data-tooltip.less | 143 +++++ .../web/css/source/components/_slider.less | 90 +++ .../web/css/source/components/_timeline.less | 391 ++++++++++++ .../web/css/source/variables/_icons.less | 5 +- .../web/fonts/admin-icons/admin-icons.eot | Bin 10560 -> 10876 bytes .../web/fonts/admin-icons/admin-icons.svg | 75 +-- .../web/fonts/admin-icons/admin-icons.ttf | Bin 10396 -> 10712 bytes .../web/fonts/admin-icons/admin-icons.woff | Bin 10472 -> 10788 bytes .../web/fonts/admin-icons/admin-icons.woff2 | Bin 5304 -> 5508 bytes .../web/fonts/admin-icons/selection.json | 604 ++++++++++-------- 16 files changed, 1537 insertions(+), 357 deletions(-) create mode 100644 app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml create mode 100644 app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/module/_staging-data-tooltip.less create mode 100644 app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less create mode 100644 app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less create mode 100644 app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml index d3bef5af3b771..b7404235f360e 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml @@ -17,7 +17,10 @@ - + + diff --git a/app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml b/app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml new file mode 100644 index 0000000000000..990c67ee5351f --- /dev/null +++ b/app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml @@ -0,0 +1,462 @@ + + + + + + + + +
+
+
+ + + +
+
+ Active + Upcoming +
+
+
+ + +
Priority
+
+
High
+
+
Low
+
+ +*/ +?> + +
+
+
+ +
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
    +
  • +
    + + Active Permanent Updates + +
    +
    +
    +
    +
    + + +
    + +
    +
  • +
  • +
    + + Up to 60% Off Closeout + +
    +
    +
    +
    11
    +
    +
    +
    + + +
    + +
    +
  • +
  • +
    + + Asfhh lahdow osdfha + +
    +
    +
    +
    11
    +
    +
    +
    + + +
    + +
    +
  • +
  • +
    + + Sign-up and Save + +
    +
    +
    +
    11
    + +
    +
    +
    + + +
    + +
    +
  • +
  • +
    + + Registration bonus + +
    +
    +
    +
    11
    +
    +
    +
    + + +
    + +
    +
  • +
  • +
    + + Registration bonus + +
    +
    +
    +
    11
    +
    +
    +
    + + +
    + +
    +
  • +
  • +
    + + Design Change + +
    +
    +
    +
    11
    +
    +
    +
    + + +
    + +
    +
  • +
+
+ + + +
+
+ + 1w + 4w +
+
+
+ + + + + + + + + + +
+ + +
+ +
+ +
+ + +
+ 15% off In-Store & Online +
+ + +
+
+ + +
+ +
+
Status:
+
Upcoming
+
Start:
+
01/22/2015 (Will be active in 5 days)
+
+ +
+
+ This campaign includes +
11 Objects
+
+ +
+
+ +
+
+
+
+
+ + + + + + +
+
+ +
+ + + + +
+
+
+ +
+ Fri 02/07/2015 +
+
+
+ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml index 80afb2b4c2205..180c098b89ed4 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml @@ -415,3 +415,6 @@ require([ } } + + + diff --git a/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less index eb86620c8bc15..25730eb58e2c0 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less @@ -1,6 +1,9 @@ + // /** // * Copyright © 2015 Magento. All rights reserved. // * See COPYING.txt for license details. // */ @import 'module/_scheduled-changes.less'; +@import 'module/_staging-data-tooltip.less'; + diff --git a/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/module/_staging-data-tooltip.less b/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/module/_staging-data-tooltip.less new file mode 100644 index 0000000000000..636e97a6e220d --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/module/_staging-data-tooltip.less @@ -0,0 +1,110 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@staging-events__border-color: @color-gray80; +@staging-events-duration__color: @color-gray60; +@staging-events-objects__background-color: @color-gray-darken0; +@staging-events-objects__timeline__background-color: #86de00; +@staging-events-objects__timeline__active__background-color: #77dcff; +@staging-events-objects-icon: @icon-clip__content; + +// +// Extends +// _____________________________________________ + +.abs-staging-events-item { + border-bottom: 1px solid @staging-events__border-color; + padding: 0 0 @indent__base; +} + +.abs-staging-events-count-icon { + border-radius: 10px; + display: inline-block; + line-height: 2.4rem; + padding: 0 @indent__s; + + &:before { + &:extend(.abs-icon all); + content: @staging-events-objects-icon; + display: inline-block; + font-size: 1.4rem; + margin-right: @indent__xs; + } +} + +// +// Staging events tooltip +// _____________________________________________ + +.staging-events-actions { + &:extend(.abs-staging-events-item all); + margin: @indent__s 0 0; + text-align: right; + + .action-secondary { + margin-left: @indent__s; + } +} + +.staging-events-summary { + &:extend(.abs-clearfix all); + &:extend(.abs-staging-events-item all); + margin: 0 0 1.5rem; + + dt { + clear: left; + float: left; + font-weight: @font-weight__bold; + margin: 1.5rem 0 0; + } + + dd { + float: left; + margin: 1.5rem 0 0 @indent__s; + + span { + color: @staging-events-duration__color; + } + } +} + +.staging-events-campaign { + &:extend(.abs-staging-events-item all); + + .items { + margin-left: @indent__base; + } +} + +.staging-events-campaign-objects { + margin: 0 0 @indent__s; +} + +.staging-events-campaign-objects-count { + &:extend(.abs-staging-events-count-icon all); + background-color: @staging-events-objects__background-color; + margin-left: @indent__s; + + .timeline-item & { + background: @staging-events-objects__timeline__background-color; + } + + .timeline-item._active & { + background: @staging-events-objects__timeline__active__background-color; + } +} + +.staging-events-delete { + margin-top: @indent__s; + text-align: right; + + .action-delete { + font-weight: @font-weight__regular; + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_components.less b/app/design/adminhtml/Magento/backend/web/css/source/_components.less index b376a1a2bd201..751968949675d 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_components.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_components.less @@ -12,5 +12,8 @@ @import 'components/_messages.less'; @import 'components/_popups.less'; @import 'components/_modals.less'; +@import 'components/_data-tooltip.less'; @import 'components/_modals_extend.less'; +@import 'components/_timeline.less'; @import 'components/_file-insertion.less'; +@import 'components/_slider.less'; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less new file mode 100644 index 0000000000000..a08a54142beb6 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less @@ -0,0 +1,143 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@data-tooltip__background-color: @color-white; +@data-tooltip__border-color: #007dbd; +@data-tooltip__border-width: 1px; +@data-tooltip__box-shadow: 2px 2px 8px 0 rgba(0,0,0,0.3); +@data-tooltip__z-index: @z-index-6; + +@data-tooltip-tail__height: 22px; +@data-tooltip-tail__width: @data-tooltip-tail__height; +@data-tooltip-tail__z-index: @z-index-1; + +// +// Tooltip +// _____________________________________________ + +.data-tooltip-wrapper { + position: absolute; + z-index: @data-tooltip__z-index; + + &._top { + .data-tooltip-tail { + display: block; + left: 50%; + margin-left: -@data-tooltip-tail__width / 2; + top: -(@data-tooltip-tail__height / 2 - @data-tooltip__border-width); + } + } + + &._right { + .data-tooltip-tail { + display: block; + margin-top: -@data-tooltip-tail__width / 2; + right: @data-tooltip-tail__height / 2 + @data-tooltip__border-width; + top: 50%; + } + } + + &._bottom { + .data-tooltip-tail { + bottom: @data-tooltip-tail__height / 2 + @data-tooltip__border-width; + display: block; + left: 50%; + margin-left: -@data-tooltip-tail__width / 2; + } + } + + &._left { + .data-tooltip-tail { + display: block; + left: -(@data-tooltip-tail__height / 2 - @data-tooltip__border-width); + top: 50%; + margin-top: -@data-tooltip-tail__width / 2; + } + } + + &._show { + height: auto; + opacity: 1; + transition: opacity .2s linear; + } + + &._hide { + height: 0; + opacity: 0; + overflow: hidden; + } +} + +.data-tooltip { + background-color: @data-tooltip__background-color; + border: @data-tooltip__border-width solid @data-tooltip__border-color; + box-shadow: @data-tooltip__box-shadow; + padding: @indent__base; + position: relative; + z-index: @data-tooltip-tail__z-index; + + .action-close { + position: absolute; + right: @indent__base; + top: @indent__base; + + &:focus { + background: none; + } + } +} + +.data-tooltip-title { + font-size: 1.7rem; + font-weight: @font-weight__semibold; + margin: 0 @indent__base @indent__base 0; +} + +.data-tooltip-content { + .items { + &:extend(.abs-list-reset-styles all); + .item { + margin: 0 0 1rem; + &:last-child { + margin-bottom: 0; + } + } + } +} + +.data-tooltip-tail { + display: none; + position: absolute; + + &:before { + background-color: @data-tooltip__background-color; + border: @data-tooltip__border-width solid @data-tooltip__border-color; + box-shadow: @data-tooltip__box-shadow; + content: ''; + height: @data-tooltip-tail__height; + left: 0; + position: absolute; + top: 0; + transform: rotate(45deg); + width: @data-tooltip-tail__width; + z-index: @data-tooltip-tail__z-index - 1; + } + + &:after { + background-color: @data-tooltip__background-color; + content: ''; + height: @data-tooltip-tail__height - @data-tooltip__border-width * 2; + left: @data-tooltip__border-width; + position: absolute; + top: @data-tooltip__border-width; + transform: rotate(45deg); + width: @data-tooltip-tail__width - @data-tooltip__border-width * 2; + z-index: @data-tooltip-tail__z-index + 1; + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less new file mode 100644 index 0000000000000..d0c73a1974b55 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less @@ -0,0 +1,90 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@data-slider-track__background-color: @color-gray-light3; +@data-slider-track__font-size: 1.1rem; +@data-slider-track__height: .1rem; +@data-slider-track__width: 100%; +@data-slider-track__z-index: @z-index-1; + +@data-slider-handle__background-color: @color-white-smoke; +@data-slider-handle__border-color: @color-gray76; +@data-slider-handle__box-shadow: 0 1px 2px 2px rgba(0, 0, 0, .03); +@data-slider-handle__height: 2.2rem; +@data-slider-handle__width: @data-slider-handle__height; + +@data-slider-handle-accent__background-color__end: @color-white-fog; +@data-slider-handle-accent__background-color__start: @color-gray-light2; +@data-slider-handle-accent__height: .8rem; +@data-slider-handle-accent__width: @data-slider-handle-accent__height; + +// +// Slider +// _____________________________________________ + +.data-slider { + &:extend(.abs-clearfix all); + font-size: @data-slider-track__font-size; + min-height: @data-slider-handle__height; + padding-top: 1.2rem; + position: relative; + width: @data-slider-track__width; + + &:before { + background: @data-slider-track__background-color; + content: ''; + display: block; + height: @data-slider-track__height; + position: absolute; + top: 0; + width: 100%; + z-index: @data-slider-track__z-index; + } +} + +.data-slider-from { + float: left; +} + +.data-slider-to { + float: right; +} + +.data-slider-handle { + background: @data-slider-handle__background-color; + border-radius: 50%; + border: 1px solid @data-slider-handle__border-color; + box-shadow: @data-slider-handle__box-shadow; + cursor: pointer; + display: block; + height: @data-slider-handle__height; + position: absolute; + top: -@data-slider-handle__height / 2; + width: @data-slider-handle__width; + z-index: @data-slider-track__z-index + 1; + + &:before { + .lib-background-gradient( + @_background-gradient: true, + @_background-gradient-direction: vertical, + @_background-gradient-color-start: @data-slider-handle-accent__background-color__start, + @_background-gradient-color-end: @data-slider-handle-accent__background-color__end, + @_background-gradient-color-position: false + ); + border-radius: 50%; + content: ''; + display: block; + height: @data-slider-handle-accent__height; + left: 50%; + margin: -@data-slider-handle-accent__height / 2 0 0 -@data-slider-handle-accent__width / 2; + position: absolute; + top: 50%; + width: @data-slider-handle-accent__width; + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less new file mode 100644 index 0000000000000..6294c9c44ddeb --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less @@ -0,0 +1,391 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@timeline__background-color: @color-white-fog2; +@timeline__border-color: @color-gray60; +@timeline__margin-top: @indent__base; +@timeline__scale: 1; + +@timeline-item__height: 3.6rem; +@timeline-unit__width: 100%/7; + +@timeline-event__background-color: #ccf391; +@timeline-event__border-color: #81c21d; +@timeline-event__active__background-color: #bceeff; +@timeline-event__active__border-color: #56c2e6; +@timeline-event__active__pemanent-color: @color-blue-pure; + +@timeline-action__color: #76c004; +@timeline-action__active__color: #56c2e6; + +@timeline-summary__background-color: #86de00; +@timeline-summary__active__background-color: #79dcff; + +@timeline-legend__color: @color-very-dark-gray; +@timeline-past__boder-color: fade(@color-tomato-brick, 55); + +@timeline-date__background-color: @color-white; +@timeline-date__color: @color-very-dark-gray-black; +@timeline-date__padding: 1rem .3rem; + +@timeline-priority-scale__color: @color-gray80; + +// +// Timeline +// --------------------------------------------- + +.timeline { + &:extend(.abs-clearer); + margin-top: @timeline__margin-top; + position: relative; + z-index: 1; +} + +.timeline-content { + background: @timeline__background-color; + border: 1px solid @timeline__border-color; + margin-bottom: @indent__base; + overflow-x: scroll; + overflow-y: hidden; + position: relative; + + &._from-now { + padding-left: 50px; + } +} + +.timeline-past { + background: linear-gradient(to left, transparent, fade(@color-white, 50) 25%, @color-white); + border-right: 2px solid @timeline-past__boder-color; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 50px; + z-index: 3; +} + +.timeline-scale { + float: right; + width: 160px; +} + +.timeline-legend { + float: left; + margin-left: 50px; +} + +.timeline-legend-item { + color: @timeline-legend__color; + display: inline-block; + line-height: 2rem; + vertical-align: middle; + + &:before { + border: 1px solid @timeline__border-color; + content: ''; + display: inline-block; + height: 2rem; + margin-right: 5px; + vertical-align: middle; + width: 2rem; + } + + &._active { + &:before { + background: @timeline-event__active__background-color; + } + } + + &._upcoming { + &:before { + background: @timeline-event__background-color; + } + } +} + +// +// Timeline items +// --------------------------------------------- + +.timeline-items { + .extend__list-reset-styles(); +} + +.timeline-item { + height: @timeline-item__height; + position: relative; + z-index: 2; + + & + .timeline-item { + margin-top: -1px; + } +} + +.timeline-event { + .lib-vendor-prefix-display(flex); + background: @timeline-event__background-color; + border: 1px solid @timeline-event__border-color; + cursor: pointer; + height: @timeline-item__height; + left: -1px; + overflow: hidden; + padding: 0 @indent__s; + position: absolute; + right: 0; + white-space: nowrap; + width: auto; + + ._permanent._active & { + color: @timeline-event__active__pemanent-color; + justify-content: center; + text-align: center; + } + + .timeline-item._active & { + background: @timeline-event__active__background-color; + border-color: @timeline-event__active__border-color; + } + + ._from-now ._scroll-end & { + margin-right: -50px; + } + + ._scroll-start:not(._active) & { + padding-left: @indent__l; + } + + ._scroll-end & { + padding-right: @indent__l; + } + + ._permanent & { + margin-right: 23px; + overflow: visible; + } + + ._from-now ._permanent._scroll-end & { + margin-right: -28px; + } +} + +.timeline-event-title { + .lib-vendor-prefix-flex-shrink(1); + display: inline-block; + font-weight: @font-weight__semibold; + line-height: 3.4rem; + max-width: 100%; + min-width: 2.2rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.timeline-event-info { + display: inline-block; + line-height: 3.4rem; + vertical-align: top; +} + +.timeline-event-details { + display: none; +} + +.timeline-event-actions { + .timeline-item._permanent & { + display: none; + } +} + +.timeline-action { + bottom: 0; + display: none; + margin: auto; + position: absolute; + right: 10px; + top: 0; + + > span { + .hidden(); + } + + &:extend(.abs-action-reset all); + &:active { + .scale(); + } + + &:before { + &:extend(.abs-icon all); + .transition(color); + color: @timeline-action__color; + content: @icon-arrow-right__content; + font-size: 1.8rem; + } + + &:hover { + cursor: pointer; + text-decoration: none; + } + + .timeline-item._active & { + &:before { + color: @timeline-action__active__color; + } + } + + &._tostart { + left: 10px; + right: auto; + + &:before { + content: @icon-arrow-left__content; + } + + .timeline-item._scroll-start:not(._active) & { + display: block; + } + } + + &._toend { + .timeline-item._scroll-end & { + display: block; + } + } +} + +// +// Timeline svg endings +// --------------------------------------------- + +svg { + .timeline-event & { + display: none; + height: 3.6rem; + margin-right: -2.4rem; + position: absolute; + right: 0; + top: -1px; + width: 2.8rem; + } + ._permanent .timeline-event & { + display: block; + } +} + +// Initial symbol styles +.svg__timeline-ending { + fill: inherit; + stroke: inherit; +} + +.svg__timeline-arrow { + stroke: transparent; +} + +// Context symbol use styles +.timeline-ending { + color: @timeline-summary__background-color; + fill: @timeline-event__background-color; + stroke: @timeline-event__border-color; + + .timeline-item._active & { + color: @timeline-summary__active__background-color; + fill: @timeline-event__active__background-color; + stroke: @timeline-event__active__border-color; + } +} + +// +// Timeline units row +// --------------------------------------------- + +.timeline-units { + .extend__list-reset-styles(); + font-size: 0; + white-space: nowrap; +} + +.timeline-unit { + border-right: 1px solid @timeline__border-color; + display: inline-block; + list-style-type: none; + margin: 0; + padding: 0; + width: @timeline-unit__width/@timeline__scale; + + &:last-child { + border-right: 0; + } + + &:before { + background-image: repeating-linear-gradient( + 180deg, + transparent, + transparent 5px, + #3e4040 5px, + #3e4040 6px, + #979999 6px, + #979999 7px + ); + bottom: 0; + content: ''; + margin-left: -1px; + position: absolute; + top: @font-size__tiny + 2rem + .2rem; + width: 1px; + z-index: 0; + } + + &:first-child { + &:before { + content: none; + } + } +} + +.timeline-date { + background: @timeline-date__background-color; + border-bottom: 1px solid @timeline__border-color; + color: @timeline-date__color; + display: block; + font-size: @font-size__tiny; + line-height: 1; + max-width: 100%; + overflow: hidden; + padding: @timeline-date__padding; + text-align: center; + text-overflow: ellipsis; +} + +// +// Priority scale +// --------------------------------------------- + +.timeline-priority { + float: left; + font-size: 1.1rem; + font-weight: @font-weight__semibold; + margin-right: 1.8rem; + margin-top: @timeline__margin-top; + text-align: center; +} + +.timeline-priority-title { + font-weight: @font-weight__bold; + padding: @timeline-date__padding; +} + +.timeline-priority-scale { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 210px solid @timeline-priority-scale__color; + height: 0; + margin: @indent__xs auto; + width: 0; +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less index e221ea34ce78a..8a58dba31929e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_icons.less @@ -73,4 +73,7 @@ @icon-camera__content: '\e63c'; @icon-grid__content: '\e63d'; @icon-list-menu__content: '\e63e'; -@icon-cart__content: '\e63f'; \ No newline at end of file +@icon-cart__content: '\e63f'; +@icon-screen__content: '\e640'; +@icon-video__content: '\e641'; +@icon-clip__content: '\e642'; // ToDo UI: in case of conflicts accept these icons and fonts - these are the freshest ones diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.eot b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.eot index c58f437b494cbc43eaab5814272baf15c6e7acd6..c354476d7367e33c9571ce4a63df6fd8621af3a7 100644 GIT binary patch delta 983 zcmYjPU1$?o6h3EWI+OY7OlCVxZ5<_(wv*OYBWaonirb175g(+LA}VMw(I7^Pingw7 ze9)>OqKyx(g5t9HAR@&ghzbVrNmN8dM1680K3GJAf~CpCb4UES%)N*2yXSoOyXQ`E zpuAo@ya3>J`<5T+W21&h{S6j|0Fxnp?N!Qp2UcOOFB2CcJq^YTq!$AmI^;fgQU> zw_i;^>n3~zpygCHlS*rSJ!t?}qy1!-2=$&cO?V~YmTYeSNRy(q5zbQ0oLzgirTTJ9 z)&fMS9!}>{Bg3#^5u5>NqeCFPJC)1)vqqjJyqF5chWG5-4?OKa`)#%lyxz(e18zl;zh*)o0p)Mz$>^2i_Gw+y=$-U%w^geQuCOzQX1UwGHLy3po6)P&>T(@49oFy*%A#hS%655ytyg!o*tr47;nX;ajjemD)L@9T$km^>4mz;7XK-2?yt delta 665 zcmewpav+G!L6d=Dj>bebGZyQIAO1~rD6g+)U|`q-#0kl{i3L(&XO1y2FvnY&m?ZH544I^NzK&6%-BdwRD?~Lg`ro`A(+23(5RGEGoT}g!&2eS?RAM}sGTr-El2&lz4JUK8Ft-bs91e7E?O_#OBY_*?kT o@&6Ez5pWThBk)R)MQ{_)a*!Kb82T6l!484B70lUuL1PUg0J&G3zyJUM diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg index 5003befe96ef2..cc3d221fd69e0 100644 --- a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg +++ b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.svg @@ -1,74 +1 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.ttf b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.ttf index 6e5be20e2c07b8f1950e48a521c65d68ad55f3dd..f6bf6a4a9a364fd9f62534ef869a85ca851fdf46 100644 GIT binary patch delta 982 zcmYjPT}TvB6h3EXo!R+uW+%rrZHk>$XDh9dbzOs^+9(kT`dN^upq8|jXiG{$E!rMT zeTXRSp+Aax=piH|38I3Q=qW6sBBI`kwud4j5E9+l&YkGzF!vtLchC9mcg~$FTi&K} zfB+!FN#LMqQ_6{H^SDt$9@5&qC!6jmoG45Iph@x0ed!}TL?Y`I{&Qjb&1w%cDj`WgHvL*M}IdFdaTz(C%8^x8)YY9;x z06y?jQ{h5+VO^zT$O|j*o3T*V zE6Z?n_JLYaq53zl-I=TAKDUWlK(m5DQ<9bHYDLzZ`P_h!Q;YR1#rIw{ip{=b#ZyeS zkBJgyNE8oMGyuI8Td)}ozSfG^bbEqSgerAmX2R{p%M(S*&}JJo!_fS%HG_LJ=fg`= zcww%NLEL?|&$TgLgd|wpIM)dDF1UyYa{}^_s2y*`)fi`uMtDMus!*&I6Y;1W`Foy- zRfP-zRrKZ&Pq2zusEQk3O6FddY9vv_9acDOS*gygmK$>%XVAe{rfF_A-Rt54QIc>M zL5|}tv$l4oEXoY$@KwY9gZmq}M$b{6NKClhOJHPft5<^0h{YrxNg^iVVdQR%QP6d% zFg|B8Scl&F8tT5bOItM!vY!Bem*@NY|M}8gZ?^O&Lj#T4Gb-frr96NzL&Kk@ol*U7 zZDT9y+s6j$pD6y}-)Y319Ba3i3D~~? delta 668 zcmcZ+JSVW8fsuiMft#U$ftkU;KUm+0Ux>LLD6$8L6OwZi3#7u%9AjW$lmYTX(i4jd zfV2RR5288Jb1Ks~%8qOR@+%k^lv6TN6H~a3n)Wd;sN4a{n`Hn6xK-I>7#LJVfP9sV z+>#33F7D?*z6DT^Ku&(LW1_)ob)W%i9zX?Mxrr483}Fltfcz^!zCvDNZt6@g&fh@( z7odi=g8bqVphJN`qXs0;z|0~x@qj&}{UkX{fA{vQDH4=|`P7z2$r)n_zU=V#PsROV+=XP0N>XB3rZ zWEZz*lxH-yXA(EpXS8QzRZ=rGF*7z26BS`oW?|@6bO`1z4Kylc)ePte;;>fi?Nzi7 zf{C;TgGBx@xWvc1fG}f6sUB3BV2zTB14JQANT3#~H5;PZB_8PX%^qAoC8I%c1jPS7 zJhYDIxB1Gz%>wck!zINZz_5nV|F^Oy0sR7u7hnKD08kI}f&V};_9UQRzXC~+Nyxxu za)z1*Bg^EqYR4xxsB6}9utu;pv5By)V7tYx!k)*ziv0xp6AmYi2^_mPK5%w$e&N#L zir`wrb%g5%*BfpH?i)M|JQ_R!JQY0Kc+T(&@tW}F@lN97;=9GK#P7hLz~91uj{k>% pjDU;49D!GYEP|VWmV?~j!qCSc2zCg}tzgdNvzqLijWw1s0s!=8nSlTR diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff index 42fb0dc0e65c612f72744e1fe69a588c859fe2ae..3bddc8cc50ebf7fc00c406e879376ed2eb38ea68 100644 GIT binary patch delta 1031 zcmYjQZAep57(Varym$A*dw27CO6UAkBA5@hzc6fuduKWqK|(CD<~oYA<^CSp4;bP&pA8Kp7%M=dGFn)O;@() zM>a;I1PG2r6-1=#!q)`S&#LrufuhvFu4Jr}5J(`uog#ZOJFzF$MY%_~cm0NY&%W;6 z$W0JZafV_vK3SXSh{Xvp+ffstkQ(aZ2_%v0$9)Bbc%Pd}Bo7@$?iSY1r6?1ms(lA` zp>Bg84ar%GhUD_*Wb7y&Tt$O;ZM2jA{jp>Rawo8`hvIw_Kht@j>k!_@`B%r_H^ynE zC0GTG>1J3_vl&c!&XTNR?;!u7%vr_|1~p`S4BolMmx(`0 zQ|On^ID454(TSe~2&r5GenSS%{*)IRwLa626c|3XSk?3zBNVAs!)7^SsD|oz>0rS6 z?BH0|Es67s;Hx%YRErB>VCJ4&R3tms(K$F<%6yFSic2xvZjT^JrKOUn1m`lxw3M8y zq!PzFS+_r8I;e**y{L~x zMk~=nbr1>rP2b<&BcT#q<3I+xAK?hC2k!C>%I z5MFpZo)(Wa!q4Lc0d^o23|fng&26m)D!nOqQN4Hn-fAXbFR0_u3AWk-YG&2hCGZ4Y zJm@0`=!8Dh+zL?(Jg(IXPiYK#LmOZ8j!Qd~l~Y8dZw?{P2fMrft@+z_Z|OT8Y{Alkhin_$$3EvgTswD| z8{odV>Rk!fMLxn`=HCje&>|cZdW2!&sn{dl5MPOwWJ+=An3R#;7kUa;7v7Qkzo`<(*Z8l(PwUCx^8f$< delta 678 zcmZ1y@*+^I+~3WOfsp|SG+r=pgXuX8jFSbmgePi>)z>HICKfO-FlGQHLO@t5?98$B z#A1-x9w46siUrbhD${^sM;I8CQ$U!b?8t_U)I=a#RRgHT41~Fkn)YP?1%YA-K)wnH zbE~q)WaO4q0L5B>`UOCkw~PCEPJS{_ouAqiprS4iHdw8`AvduCXtBBikPpFO3={Ga zb5nt04nU1J>U zlYkBdMGw%~U;xy^eBl291_t&dphvy}Nsvj%z-96lH4jFX$v@SOPd=lrS+o z!nT6#7P|_29{Vcx6YNhooH!@G$Ub@C5Kw z@NDBb!z;vV!kfoCiI0o#7QYg|1AhX43;#L(9|AH0E&_7|UJ0@YZUR~ka)S#)AA=y+ TAuzXsIg@3z*f-Z}EM)`$3YeT= diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff2 b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/admin-icons.woff2 index 80b861eefcc7c46e7038af15206f3f42228370f3..5a39ab634b8f754cbd7db7545cd811ac8509fba1 100644 GIT binary patch literal 5508 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 G00030k%b2U literal 5304 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 K^MV150ssJ36(nf@ diff --git a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json index 43b3727402def..89f90cf917062 100644 --- a/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json +++ b/app/design/adminhtml/Magento/backend/web/fonts/admin-icons/selection.json @@ -1,6 +1,57 @@ { "IcoMoonType": "selection", "icons": [ + { + "icon": { + "paths": [ + "M2041.366 1.102v1021.449h-175.926l-411.263-409.297v-204.59l411.263-407.568h175.926z", + "M1305.997 989.076c0 19.377-15.608 34.924-34.856 34.924h-1236.279c-19.255 0-34.863-15.547-34.863-34.924v-954.275c0-19.248 15.608-34.801 34.863-34.801h1236.279c19.248 0 34.856 15.553 34.856 34.801v954.275z" + ], + "width": 2041, + "attrs": [], + "isMulticolor": false, + "tags": [ + "video" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 127, + "id": 0, + "prevSize": 32, + "code": 58945, + "name": "video" + }, + "setIdx": 0, + "setId": 3, + "iconIdx": 0 + }, + { + "icon": { + "paths": [ + "M723.661 889.601c-2.404-10.843-4.034-21.47-5.282-31.583h-277.528c-2.458 20.233-6.917 43.087-14.646 64.305-7.79 21.277-18.796 40.54-33.824 54.15-15.028 13.552-33.689 22.104-59.788 22.158v25.369h494.020v-25.369c-26.142-0.058-44.737-8.61-59.838-22.158-22.44-20.307-35.961-53.91-43.114-86.873zM1126.214 0h-1093.209c-18.22 0-33.005 15.024-33.005 33.596v731.259c0 18.576 14.785 33.623 33.005 33.623h1093.209c18.224 0 33.067-15.051 33.067-33.623v-731.259c0-18.572-14.843-33.596-33.067-33.596zM1079.193 716.922h-999.234v-635.394h999.234v635.394z" + ], + "width": 1159, + "attrs": [], + "isMulticolor": false, + "tags": [ + "screen" + ], + "grid": 0 + }, + "attrs": [], + "properties": { + "order": 72, + "id": 1, + "prevSize": 32, + "code": 58944, + "name": "screen" + }, + "setIdx": 0, + "setId": 3, + "iconIdx": 1 + }, { "icon": { "paths": [ @@ -11,22 +62,22 @@ ], "attrs": [], "isMulticolor": false, - "grid": 0, "tags": [ "cart" - ] + ], + "grid": 0 }, "attrs": [], "properties": { "order": 71, - "id": 0, + "id": 2, "prevSize": 32, "code": 58943, "name": "cart" }, "setIdx": 0, - "setId": 1, - "iconIdx": 0 + "setId": 3, + "iconIdx": 2 }, { "icon": { @@ -53,14 +104,14 @@ ], "properties": { "order": 61, - "id": 32, + "id": 3, "prevSize": 32, "code": 58942, "name": "list-menu" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 0 + "setIdx": 0, + "setId": 3, + "iconIdx": 3 }, { "icon": { @@ -105,14 +156,14 @@ ], "properties": { "order": 112, - "id": 31, + "id": 4, "prevSize": 32, "code": 58941, "name": "grid" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 1 + "setIdx": 0, + "setId": 3, + "iconIdx": 4 }, { "icon": { @@ -136,14 +187,14 @@ ], "properties": { "order": 121, - "id": 30, + "id": 5, "prevSize": 32, "code": 58940, "name": "camera" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 2 + "setIdx": 0, + "setId": 3, + "iconIdx": 5 }, { "icon": { @@ -164,14 +215,14 @@ ], "properties": { "order": 111, - "id": 29, + "id": 6, "prevSize": 32, "code": 58939, "name": "tag" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 3 + "setIdx": 0, + "setId": 3, + "iconIdx": 6 }, { "icon": { @@ -198,14 +249,14 @@ ], "properties": { "order": 110, - "id": 1, + "id": 7, "prevSize": 32, "code": 58927, "name": "close-mage" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 4 + "setIdx": 0, + "setId": 3, + "iconIdx": 7 }, { "icon": { @@ -232,14 +283,14 @@ ], "properties": { "order": 109, - "id": 0, + "id": 8, "prevSize": 32, "code": 58938, "name": "menu-item" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 5 + "setIdx": 0, + "setId": 3, + "iconIdx": 8 }, { "icon": { @@ -260,14 +311,14 @@ ], "properties": { "order": 108, - "id": 28, + "id": 9, "prevSize": 32, "code": 58906, "name": "info" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 6 + "setIdx": 0, + "setId": 3, + "iconIdx": 9 }, { "icon": { @@ -288,14 +339,14 @@ ], "properties": { "order": 107, - "id": 27, + "id": 10, "prevSize": 32, "code": 58907, "name": "lock" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 7 + "setIdx": 0, + "setId": 3, + "iconIdx": 10 }, { "icon": { @@ -316,14 +367,14 @@ ], "properties": { "order": 106, - "id": 26, + "id": 11, "prevSize": 32, "code": 58908, "name": "loop" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 8 + "setIdx": 0, + "setId": 3, + "iconIdx": 11 }, { "icon": { @@ -344,14 +395,14 @@ ], "properties": { "order": 105, - "id": 25, + "id": 12, "prevSize": 32, "code": 58909, "name": "plus" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 9 + "setIdx": 0, + "setId": 3, + "iconIdx": 12 }, { "icon": { @@ -372,14 +423,14 @@ ], "properties": { "order": 104, - "id": 24, + "id": 13, "prevSize": 32, "code": 58910, "name": "recover" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 10 + "setIdx": 0, + "setId": 3, + "iconIdx": 13 }, { "icon": { @@ -401,14 +452,14 @@ ], "properties": { "order": 113, - "id": 23, + "id": 14, "prevSize": 32, "code": 58911, "name": "refresh" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 11 + "setIdx": 0, + "setId": 3, + "iconIdx": 14 }, { "icon": { @@ -430,14 +481,14 @@ ], "properties": { "order": 114, - "id": 22, + "id": 15, "prevSize": 32, "code": 58912, "name": "remove-small" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 12 + "setIdx": 0, + "setId": 3, + "iconIdx": 15 }, { "icon": { @@ -458,14 +509,14 @@ ], "properties": { "order": 117, - "id": 21, + "id": 16, "prevSize": 32, "code": 58913, "name": "retweet" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 13 + "setIdx": 0, + "setId": 3, + "iconIdx": 16 }, { "icon": { @@ -486,14 +537,14 @@ ], "properties": { "order": 36, - "id": 20, + "id": 17, "prevSize": 32, "code": 58914, "name": "unlocked" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 14 + "setIdx": 0, + "setId": 3, + "iconIdx": 17 }, { "icon": { @@ -515,14 +566,14 @@ ], "properties": { "order": 37, - "id": 19, + "id": 18, "prevSize": 32, "code": 58915, "name": "warning" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 15 + "setIdx": 0, + "setId": 3, + "iconIdx": 18 }, { "icon": { @@ -543,14 +594,14 @@ ], "properties": { "order": 38, - "id": 18, + "id": 19, "prevSize": 32, "code": 58916, "name": "arrow-left" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 16 + "setIdx": 0, + "setId": 3, + "iconIdx": 19 }, { "icon": { @@ -571,14 +622,14 @@ ], "properties": { "order": 39, - "id": 17, + "id": 20, "prevSize": 32, "code": 58917, "name": "arrow-right" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 17 + "setIdx": 0, + "setId": 3, + "iconIdx": 20 }, { "icon": { @@ -599,14 +650,14 @@ ], "properties": { "order": 103, - "id": 16, + "id": 21, "prevSize": 32, "code": 58918, "name": "back-arrow" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 18 + "setIdx": 0, + "setId": 3, + "iconIdx": 21 }, { "icon": { @@ -628,14 +679,14 @@ ], "properties": { "order": 102, - "id": 15, + "id": 22, "prevSize": 32, "code": 58919, "name": "calendar" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 19 + "setIdx": 0, + "setId": 3, + "iconIdx": 22 }, { "icon": { @@ -656,14 +707,14 @@ ], "properties": { "order": 101, - "id": 14, + "id": 23, "prevSize": 32, "code": 58920, "name": "caret-down" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 20 + "setIdx": 0, + "setId": 3, + "iconIdx": 23 }, { "icon": { @@ -684,14 +735,14 @@ ], "properties": { "order": 100, - "id": 13, + "id": 24, "prevSize": 32, "code": 58921, "name": "caret-left" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 21 + "setIdx": 0, + "setId": 3, + "iconIdx": 24 }, { "icon": { @@ -712,14 +763,14 @@ ], "properties": { "order": 99, - "id": 12, + "id": 25, "prevSize": 32, "code": 58922, "name": "caret-right" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 22 + "setIdx": 0, + "setId": 3, + "iconIdx": 25 }, { "icon": { @@ -740,14 +791,14 @@ ], "properties": { "order": 98, - "id": 11, + "id": 26, "prevSize": 32, "code": 58923, "name": "caret-up" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 23 + "setIdx": 0, + "setId": 3, + "iconIdx": 26 }, { "icon": { @@ -768,14 +819,14 @@ ], "properties": { "order": 97, - "id": 10, + "id": 27, "prevSize": 32, "code": 58924, "name": "ccw" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 24 + "setIdx": 0, + "setId": 3, + "iconIdx": 27 }, { "icon": { @@ -797,14 +848,14 @@ ], "properties": { "order": 96, - "id": 9, + "id": 28, "prevSize": 32, "code": 58925, "name": "check-mage" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 25 + "setIdx": 0, + "setId": 3, + "iconIdx": 28 }, { "icon": { @@ -825,14 +876,14 @@ ], "properties": { "order": 95, - "id": 8, + "id": 29, "prevSize": 32, "code": 58926, "name": "clock" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 26 + "setIdx": 0, + "setId": 3, + "iconIdx": 29 }, { "icon": { @@ -854,14 +905,14 @@ ], "properties": { "order": 94, - "id": 5, + "id": 30, "prevSize": 32, "code": 58928, "name": "delete" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 27 + "setIdx": 0, + "setId": 3, + "iconIdx": 30 }, { "icon": { @@ -883,14 +934,14 @@ ], "properties": { "order": 115, - "id": 4, + "id": 31, "prevSize": 32, "code": 58929, "name": "edit" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 28 + "setIdx": 0, + "setId": 3, + "iconIdx": 31 }, { "icon": { @@ -911,14 +962,14 @@ ], "properties": { "order": 122, - "id": 3, + "id": 32, "prevSize": 32, "code": 58930, "name": "error" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 29 + "setIdx": 0, + "setId": 3, + "iconIdx": 32 }, { "icon": { @@ -940,14 +991,14 @@ ], "properties": { "order": 124, - "id": 1, + "id": 33, "prevSize": 32, "code": 58931, "name": "help" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 30 + "setIdx": 0, + "setId": 3, + "iconIdx": 33 }, { "icon": { @@ -968,14 +1019,14 @@ ], "properties": { "order": 45, - "id": 0, + "id": 34, "prevSize": 32, "code": 58932, "name": "history" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 31 + "setIdx": 0, + "setId": 3, + "iconIdx": 34 }, { "icon": { @@ -996,14 +1047,14 @@ ], "properties": { "order": 58, - "id": 16, + "id": 35, "prevSize": 32, "code": 58936, "name": "not-installed" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 32 + "setIdx": 0, + "setId": 3, + "iconIdx": 35 }, { "icon": { @@ -1024,14 +1075,14 @@ ], "properties": { "order": 57, - "id": 15, + "id": 36, "prevSize": 32, "code": 58937, "name": "disabled" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 33 + "setIdx": 0, + "setId": 3, + "iconIdx": 36 }, { "icon": { @@ -1052,14 +1103,14 @@ ], "properties": { "order": 56, - "id": 14, + "id": 37, "prevSize": 32, "code": 58935, "name": "dot" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 34 + "setIdx": 0, + "setId": 3, + "iconIdx": 37 }, { "icon": { @@ -1083,14 +1134,14 @@ ], "properties": { "order": 93, - "id": 13, + "id": 38, "prevSize": 32, "code": 58933, "name": "export" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 35 + "setIdx": 0, + "setId": 3, + "iconIdx": 38 }, { "icon": { @@ -1114,14 +1165,14 @@ ], "properties": { "order": 92, - "id": 12, + "id": 39, "prevSize": 32, "code": 58934, "name": "import" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 36 + "setIdx": 0, + "setId": 3, + "iconIdx": 39 }, { "icon": { @@ -1163,14 +1214,14 @@ ], "properties": { "order": 91, - "id": 11, + "id": 40, "prevSize": 32, "code": 58903, "name": "gripper" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 37 + "setIdx": 0, + "setId": 3, + "iconIdx": 40 }, { "icon": { @@ -1191,14 +1242,14 @@ ], "properties": { "order": 90, - "id": 10, + "id": 41, "prevSize": 32, "code": 58904, "name": "forward" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 38 + "setIdx": 0, + "setId": 3, + "iconIdx": 41 }, { "icon": { @@ -1219,15 +1270,15 @@ ], "properties": { "order": 89, - "id": 9, + "id": 42, "prevSize": 32, "code": 58905, "name": "backward", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 39 + "setIdx": 0, + "setId": 3, + "iconIdx": 42 }, { "icon": { @@ -1251,14 +1302,14 @@ ], "properties": { "order": 88, - "id": 8, + "id": 43, "prevSize": 32, "code": 58901, "name": "expand-close" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 40 + "setIdx": 0, + "setId": 3, + "iconIdx": 43 }, { "icon": { @@ -1282,14 +1333,14 @@ ], "properties": { "order": 87, - "id": 7, + "id": 44, "prevSize": 32, "code": 58902, "name": "expand-open" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 41 + "setIdx": 0, + "setId": 3, + "iconIdx": 44 }, { "icon": { @@ -1314,14 +1365,14 @@ ], "properties": { "order": 86, - "id": 5, + "id": 45, "prevSize": 32, "code": 58896, "name": "system-config" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 42 + "setIdx": 0, + "setId": 3, + "iconIdx": 45 }, { "icon": { @@ -1346,14 +1397,14 @@ ], "properties": { "order": 85, - "id": 3, + "id": 46, "prevSize": 32, "code": 58897, "name": "home" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 43 + "setIdx": 0, + "setId": 3, + "iconIdx": 46 }, { "icon": { @@ -1378,14 +1429,14 @@ ], "properties": { "order": 84, - "id": 2, + "id": 47, "prevSize": 32, "code": 58898, "name": "lego" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 44 + "setIdx": 0, + "setId": 3, + "iconIdx": 47 }, { "icon": { @@ -1410,14 +1461,14 @@ ], "properties": { "order": 120, - "id": 1, + "id": 48, "prevSize": 32, "code": 58899, "name": "tool" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 45 + "setIdx": 0, + "setId": 3, + "iconIdx": 48 }, { "icon": { @@ -1438,14 +1489,14 @@ ], "properties": { "order": 125, - "id": 0, + "id": 49, "prevSize": 32, "code": 58900, "name": "upgrade" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 46 + "setIdx": 0, + "setId": 3, + "iconIdx": 49 }, { "icon": { @@ -1482,14 +1533,14 @@ ], "properties": { "order": 123, - "id": 18, + "id": 50, "prevSize": 32, "code": 58887, "name": "notification-02" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 47 + "setIdx": 0, + "setId": 3, + "iconIdx": 50 }, { "icon": { @@ -1517,15 +1568,15 @@ ], "properties": { "order": 7, - "id": 17, + "id": 51, "prevSize": 32, "code": 58888, "name": "product", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 48 + "setIdx": 0, + "setId": 3, + "iconIdx": 51 }, { "icon": { @@ -1569,15 +1620,15 @@ ], "properties": { "order": 17, - "id": 16, + "id": 52, "prevSize": 32, "code": 58886, "name": "logo", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 49 + "setIdx": 0, + "setId": 3, + "iconIdx": 52 }, { "icon": { @@ -1605,15 +1656,15 @@ ], "properties": { "order": 9, - "id": 15, + "id": 53, "prevSize": 32, "code": 58880, "name": "account", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 50 + "setIdx": 0, + "setId": 3, + "iconIdx": 53 }, { "icon": { @@ -1641,15 +1692,15 @@ ], "properties": { "order": 10, - "id": 14, + "id": 54, "prevSize": 32, "code": 58881, "name": "arrowdown", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 51 + "setIdx": 0, + "setId": 3, + "iconIdx": 54 }, { "icon": { @@ -1704,15 +1755,15 @@ ], "properties": { "order": 83, - "id": 13, + "id": 55, "prevSize": 32, "code": 58882, "name": "cms", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 52 + "setIdx": 0, + "setId": 3, + "iconIdx": 55 }, { "icon": { @@ -1740,15 +1791,15 @@ ], "properties": { "order": 82, - "id": 12, + "id": 56, "prevSize": 32, "code": 58883, "name": "customers", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 53 + "setIdx": 0, + "setId": 3, + "iconIdx": 56 }, { "icon": { @@ -1776,15 +1827,15 @@ ], "properties": { "order": 81, - "id": 11, + "id": 57, "prevSize": 32, "code": 58884, "name": "dashboard", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 54 + "setIdx": 0, + "setId": 3, + "iconIdx": 57 }, { "icon": { @@ -1811,15 +1862,15 @@ ], "properties": { "order": 80, - "id": 10, + "id": 58, "prevSize": 32, "code": 58885, "name": "filter", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 55 + "setIdx": 0, + "setId": 3, + "iconIdx": 58 }, { "icon": { @@ -1847,15 +1898,15 @@ ], "properties": { "order": 79, - "id": 6, + "id": 59, "prevSize": 32, "code": 58889, "name": "promotions", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 56 + "setIdx": 0, + "setId": 3, + "iconIdx": 59 }, { "icon": { @@ -1883,15 +1934,15 @@ ], "properties": { "order": 78, - "id": 5, + "id": 60, "prevSize": 32, "code": 58890, "name": "reports", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 57 + "setIdx": 0, + "setId": 3, + "iconIdx": 60 }, { "icon": { @@ -1919,15 +1970,15 @@ ], "properties": { "order": 77, - "id": 4, + "id": 61, "prevSize": 32, "code": 58891, "name": "sales", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 58 + "setIdx": 0, + "setId": 3, + "iconIdx": 61 }, { "icon": { @@ -1964,15 +2015,15 @@ ], "properties": { "order": 76, - "id": 3, + "id": 62, "prevSize": 32, "code": 58892, "name": "search", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 59 + "setIdx": 0, + "setId": 3, + "iconIdx": 62 }, { "icon": { @@ -2000,21 +2051,22 @@ ], "properties": { "order": 75, - "id": 2, + "id": 63, "prevSize": 32, "code": 58893, "name": "stores", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 60 + "setIdx": 0, + "setId": 3, + "iconIdx": 63 }, { "icon": { "paths": [ - "M1024 567.842v-116.547l-141.218-46.117-33.219-80.36 63.981-135.383-82.407-82.407-15.458 7.831-117.008 59.477-80.309-33.321-50.57-141.014h-116.496l-5.374 16.533-40.743 124.686-80.258 33.321-135.537-63.981-82.356 82.407 7.882 15.407 59.323 117.059-33.219 80.258-141.014 50.519v116.547l141.218 46.066 33.219 80.36-63.878 135.383 82.254 82.407 15.458-7.831 117.008-59.425 80.36 33.27 50.468 140.963h116.496l5.426-16.43 40.692-124.737 80.309-33.27 135.383 63.981 82.458-82.407-7.882-15.458-59.374-116.957 33.27-80.36 141.116-50.468zM512 675.228c-90.136 0-163.177-73.040-163.177-163.177s73.040-163.177 163.177-163.177c90.187 0 163.177 73.040 163.177 163.177s-72.989 163.177-163.177 163.177z" + "M944.97 329.042c-97.861 0-177.522 79.581-177.522 177.443 0 97.94 79.66 177.679 177.522 177.679 98.019 0 177.679-79.739 177.679-177.679 0-97.861-79.66-177.443-177.679-177.443zM944.97-0c-470.712 0-944.97 512-944.97 512s474.258 512 944.97 512c470.949 0 945.128-512 945.128-512s-474.179-512-945.128-512zM944.97 868.856c-200.057 0-362.292-162.078-362.292-362.45 0-200.057 162.236-362.292 362.292-362.292 200.214 0 362.45 162.236 362.45 362.292 0 200.451-162.236 362.45-362.45 362.45z" ], + "width": 1890, "attrs": [ { "opacity": 1, @@ -2023,7 +2075,7 @@ ], "isMulticolor": false, "tags": [ - "systems" + "views" ], "grid": 0 }, @@ -2034,52 +2086,42 @@ } ], "properties": { - "order": 74, - "id": 1, + "order": 73, + "id": 64, "prevSize": 32, - "code": 58894, - "name": "systems", + "code": 58895, + "name": "views", "ligatures": "" }, - "setIdx": 1, - "setId": 0, - "iconIdx": 61 + "setIdx": 0, + "setId": 3, + "iconIdx": 64 }, { "icon": { "paths": [ - "M944.97 329.042c-97.861 0-177.522 79.581-177.522 177.443 0 97.94 79.66 177.679 177.522 177.679 98.019 0 177.679-79.739 177.679-177.679 0-97.861-79.66-177.443-177.679-177.443zM944.97-0c-470.712 0-944.97 512-944.97 512s474.258 512 944.97 512c470.949 0 945.128-512 945.128-512s-474.179-512-945.128-512zM944.97 868.856c-200.057 0-362.292-162.078-362.292-362.45 0-200.057 162.236-362.292 362.292-362.292 200.214 0 362.45 162.236 362.45 362.292 0 200.451-162.236 362.45-362.45 362.45z" - ], - "width": 1890, - "attrs": [ - { - "opacity": 1, - "visibility": false - } + "M939.616 148.384c112.512 112.448 112.512 294.816 0 407.264l-350.944 350.976c-12.512 12.544-32.736 12.544-45.248 0-12.576-12.512-12.576-32.704 0-45.248l346.432-346.464c87.488-87.488 87.488-229.248-0.064-316.768-87.36-87.488-229.248-87.488-316.736 0l-462.304 456.864c-62.496 62.464-62.496 163.776 0 226.24 62.496 62.496 163.744 62.496 226.24 0l466.88-461.344c37.44-37.44 37.44-98.336 0-135.776-37.44-37.408-98.304-37.408-135.744 0l-351.008 351.008c-12.512 12.512-32.736 12.512-45.248 0-12.512-12.544-12.512-32.736 0-45.28l350.976-350.976c62.432-62.464 163.744-62.464 226.24 0 62.496 62.496 62.496 163.776 0 226.272l-466.88 461.376c-87.296 87.328-229.408 87.328-316.736 0-87.328-87.328-87.328-229.472 0-316.8l466.88-461.344c112.448-112.512 294.816-112.512 407.264 0z" ], + "attrs": [], "isMulticolor": false, "tags": [ - "views" + "clip", + "paperclip", + "attachment" ], - "grid": 0 + "grid": 32 }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], + "attrs": [], "properties": { - "order": 73, - "id": 0, + "id": 41, + "order": 130, "prevSize": 32, - "code": 58895, - "name": "views", - "ligatures": "" + "code": 58946, + "name": "clip" }, "setIdx": 1, - "setId": 0, - "iconIdx": 62 + "setId": 2, + "iconIdx": 41 } ], "height": 1024, From c4985ddc765b70185c16a309de665aa87014e022 Mon Sep 17 00:00:00 2001 From: Olga Matviienko Date: Wed, 10 Feb 2016 16:16:54 +0200 Subject: [PATCH 02/31] MAGETWO-41203: [UI] Dashboard --- .../view/adminhtml/templates/catalog/product/edit.phtml | 3 --- .../backend/Magento_Staging/web/css/source/_module.less | 2 -- 2 files changed, 5 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml index 180c098b89ed4..80afb2b4c2205 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit.phtml @@ -415,6 +415,3 @@ require([ } } - - - diff --git a/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less index 25730eb58e2c0..74c2b190d33cb 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_Staging/web/css/source/_module.less @@ -1,4 +1,3 @@ - // /** // * Copyright © 2015 Magento. All rights reserved. // * See COPYING.txt for license details. @@ -6,4 +5,3 @@ @import 'module/_scheduled-changes.less'; @import 'module/_staging-data-tooltip.less'; - From 5d8e655810a88155b7a846a7e75c1970abda230c Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Thu, 18 Feb 2016 09:46:56 +0200 Subject: [PATCH 03/31] MAGETWO-49292: Create column in grid with coloured update type (green/blue) - Also add legend to toolbar(MAGETWO-46422) --- .../view/base/web/templates/grid/listing.html | 2 +- .../web/css/source/module/_data-grid.less | 25 +++++++++++++++++++ .../web/css/source/components/_timeline.less | 4 +++ .../web/css/source/variables/_data-grid.less | 2 ++ 4 files changed, 32 insertions(+), 1 deletion(-) 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 702c07351767c..d02233cbe07c2 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 @@ -12,7 +12,7 @@ + css="getFieldClass($row())" click="getFieldHandler($row())" template="getBody()"/> 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 525b6f7260c65..808603fb05aaf 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 @@ -132,6 +132,23 @@ body._in-resize { &._odd-row { td { background-color: @data-grid-td__even__background-color; + + &._update-status-active { + background: @data-grid-td__update__active__background-color; + } + + &._update-status-upcoming { + background: @data-grid-td__update__upcoming__background-color; + } + } + } + + &:hover { + td { + &._update-status-active, + &._update-status-upcoming { + background-color: @data-grid-tr__hover__background-color; + } } } @@ -247,6 +264,14 @@ body._in-resize { top: auto; z-index: 1; } + + &._update-status-active { + background: @data-grid-td__update__active__background-color; + } + + &._update-status-upcoming { + background: @data-grid-td__update__upcoming__background-color; + } } th { diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less index 6294c9c44ddeb..374d7e4e65f92 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less @@ -97,12 +97,16 @@ width: 2rem; } + + &._update-status-active, &._active { &:before { background: @timeline-event__active__background-color; } } + + &._update-status-upcoming, &._upcoming { &:before { background: @timeline-event__background-color; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less index df5f3ad2ea0e2..1388dcad4eb78 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less @@ -25,6 +25,8 @@ @data-grid-td__odd__background-color: @page__background-color; @data-grid-td__odd__dragging__background-color: @color-gray85; @data-grid-td__odd__edit__background-color: darken(@data-grid-td__odd__background-color, 10%); +@data-grid-td__update__active__background-color: #bceeff; +@data-grid-td__update__upcoming__background-color: #ccf391; @data-grid-th__border-color: @color-darkie-gray; @data-grid-th__border-style: solid; From 7932828069225e74ab9eedd90507eda99cd4f1a7 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Fri, 19 Feb 2016 16:33:05 +0200 Subject: [PATCH 04/31] MAGETWO-49292: Create column in grid with coloured update type (green/blue) - Fix toolbar template and add styles --- .../backend/Magento_Ui/web/css/source/module/_data-grid.less | 4 ++-- .../Magento/backend/web/css/source/variables/_data-grid.less | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) 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 808603fb05aaf..f34970347f2fb 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 @@ -134,11 +134,11 @@ body._in-resize { background-color: @data-grid-td__even__background-color; &._update-status-active { - background: @data-grid-td__update__active__background-color; + background: @data-grid-td__odd__update__active__background-color; } &._update-status-upcoming { - background: @data-grid-td__update__upcoming__background-color; + background: @data-grid-td__odd__update__upcoming__background-color; } } } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less index 1388dcad4eb78..3d7171d57a93d 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less @@ -27,6 +27,8 @@ @data-grid-td__odd__edit__background-color: darken(@data-grid-td__odd__background-color, 10%); @data-grid-td__update__active__background-color: #bceeff; @data-grid-td__update__upcoming__background-color: #ccf391; +@data-grid-td__odd__update__active__background-color: darken(@data-grid-td__update__active__background-color, 10%); +@data-grid-td__odd__update__upcoming__background-color: darken(@data-grid-td__update__upcoming__background-color, 10%); @data-grid-th__border-color: @color-darkie-gray; @data-grid-th__border-style: solid; From 3e635649974c6d097dfb5e89dd401bb3d338a1f7 Mon Sep 17 00:00:00 2001 From: Denys Rul Date: Wed, 24 Feb 2016 19:36:46 +0200 Subject: [PATCH 05/31] MAGETWO-48673: Create listing extension for timeline --- .../layout/adminhtml_dashboard_index.xml | 5 +- .../view/adminhtml/templates/timeline.phtml | 462 ------------------ .../Ui/view/base/web/js/grid/listing.js | 51 +- .../web/js/lib/knockout/template/renderer.js | 4 +- .../base/web/js/timeline/timeline-view.js | 302 ++++++++++++ .../Ui/view/base/web/js/timeline/timeline.js | 290 +++++++++++ .../web/templates/grid/view-switcher.html | 17 + .../base/web/templates/timeline/record.html | 26 + .../base/web/templates/timeline/timeline.html | 86 ++++ .../web/css/source/components/_timeline.less | 2 + 10 files changed, 776 insertions(+), 469 deletions(-) delete mode 100644 app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml create mode 100644 app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js create mode 100644 app/code/Magento/Ui/view/base/web/js/timeline/timeline.js create mode 100644 app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/timeline/record.html create mode 100644 app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html diff --git a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml index b7404235f360e..d3bef5af3b771 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/adminhtml_dashboard_index.xml @@ -17,10 +17,7 @@ - - + diff --git a/app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml b/app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml deleted file mode 100644 index 990c67ee5351f..0000000000000 --- a/app/code/Magento/Backend/view/adminhtml/templates/timeline.phtml +++ /dev/null @@ -1,462 +0,0 @@ - - - - - - - - -
-
-
- - - -
-
- Active - Upcoming -
-
-
- - -
Priority
-
-
High
-
-
Low
-
- -*/ -?> - -
-
-
- -
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
    -
  • -
    - - Active Permanent Updates - -
    -
    -
    -
    -
    - - -
    - -
    -
  • -
  • -
    - - Up to 60% Off Closeout - -
    -
    -
    -
    11
    -
    -
    -
    - - -
    - -
    -
  • -
  • -
    - - Asfhh lahdow osdfha - -
    -
    -
    -
    11
    -
    -
    -
    - - -
    - -
    -
  • -
  • -
    - - Sign-up and Save - -
    -
    -
    -
    11
    - -
    -
    -
    - - -
    - -
    -
  • -
  • -
    - - Registration bonus - -
    -
    -
    -
    11
    -
    -
    -
    - - -
    - -
    -
  • -
  • -
    - - Registration bonus - -
    -
    -
    -
    11
    -
    -
    -
    - - -
    - -
    -
  • -
  • -
    - - Design Change - -
    -
    -
    -
    11
    -
    -
    -
    - - -
    - -
    -
  • -
-
- - - -
-
- - 1w - 4w -
-
-
- - - - - - - - - - -
- - -
- -
- -
- - -
- 15% off In-Store & Online -
- - -
-
- - -
- -
-
Status:
-
Upcoming
-
Start:
-
01/22/2015 (Will be active in 5 days)
-
- -
-
- This campaign includes -
11 Objects
-
- -
-
- -
-
-
-
-
- - - - - - -
-
- -
- - - - -
-
-
- -
- Fri 02/07/2015 -
-
-
- 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 67e91821d663c..2e3dc89aa4db8 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 @@ -17,7 +17,16 @@ define([ defaults: { template: 'ui/grid/listing', stickyTmpl: 'ui/grid/sticky/listing', + viewSwitcherTmpl: 'ui/grid/view-switcher', positions: false, + displayMode: 'grid', + displayModes: { + grid: { + value: 'grid', + label: 'Grid', + template: '${ $.template }' + } + }, dndConfig: { name: '${ $.name }_dnd', component: 'Magento_Ui/js/grid/dnd', @@ -48,6 +57,9 @@ define([ modules: { dnd: '${ $.dndConfig.name }', resize: '${ $.resizeConfig.name }' + }, + tracks: { + displayMode: true } }, @@ -96,7 +108,7 @@ define([ }, /** - * Inititalizes resize component. + * Initializes resize component. * * @returns {Listing} Chainable. */ @@ -170,7 +182,7 @@ define([ }, /** - * Reseorts child elements array according to provided positions. + * Resorts child elements array according to provided positions. * * @param {Object} positions - Object where key represents child * index and value is its' position. @@ -202,6 +214,41 @@ define([ return observable || this.visibleColumns; }, + /** + * Returns path to the template + * defined for a current display mode. + * + * @returns {String} Path to the template. + */ + getTemplate: function () { + var mode = this.displayModes[this.displayMode]; + + return mode.template; + }, + + /** + * Returns an array of available display modes. + * + * @returns {Array} + */ + getDisplayModes: function () { + var modes = this.displayModes; + + return _.values(modes); + }, + + /** + * Sets display mode to provided value. + * + * @param {String} index + * @returns {Listing} Chainable + */ + setDisplayMode: function (index) { + this.displayMode = index; + + return this; + }, + /** * Returns total number of displayed columns in grid. * diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js index 4bb148a0995c4..e7dc37e60d0c0 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js @@ -462,8 +462,10 @@ define([ 'textInput', 'component', 'uniqueName', + 'optionsText', + 'optionsValue', 'checkedValue', - 'selectedOptions' + 'selectedOptions', ], Array.prototype) }; diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js new file mode 100644 index 0000000000000..84fa7202299e1 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js @@ -0,0 +1,302 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'ko', + 'Magento_Ui/js/lib/view/utils/async', + 'underscore', + 'uiRegistry', + 'uiClass' +], function (ko, $, _, registry, Class) { + 'use strict'; + + return Class.extend({ + defaults: { + selectors: { + content: '.timeline-content', + item: '.timeline-item:not([data-role=no-data-msg])', + event: '.timeline-event' + } + }, + + /** + * Initializes TimelineView component. + * + * @returns {TimelineView} Chainable. + */ + initialize: function () { + _.bindAll( + this, + 'initContent', + 'initItem', + 'getItemBindings', + 'onEventElementRender', + 'onWindowResize', + 'onContentScroll', + 'onDataReloaded', + 'onToStartClick', + 'onToEndClick' + ); + + this._super(); + + this.model = registry.get(this.model); + + this.model.source.on('reloaded', this.onDataReloaded); + + $.async({ + selector: this.selectors.content, + component: this.model + }, this.initContent); + + $(window).on('resize', this.onWindowResize); + + return this; + }, + + /** + * Initializes timelines' content container element. + * + * @param {HTMLElement} content + * @returns {TimelineView} Chainable. + */ + initContent: function (content) { + this.$content = $(content); + + this.$content.on('scroll', this.onContentScroll); + + $.async(this.selectors.item, content, this.initItem); + $.async(this.selectors.event, content, this.onEventElementRender); + + return this; + }, + + /** + * Initializes timeline item element, + * e.g. establishes event listeners and applies data bindings. + * + * @param {HTMLElement} elem + * @returns {TimelineView} Chainable. + */ + initItem: function (elem) { + $(elem) + .bindings(this.getItemBindings) + .on('click', '._toend', this.onToEndClick) + .on('click', '._tostart', this.onToStartClick); + + return this; + }, + + /** + * Returns object with additional + * bindings for timeline item. + * + * @param {Object} ctx + * @returns {Object} + */ + getItemBindings: function (ctx) { + return { + style: { + width: ko.computed(function () { + var record = ctx.$row(); + + return this.getItemWidth(record); + }.bind(this)), + + 'margin-left': ko.computed(function () { + var record = ctx.$row(); + + return this.getItemMargin(record); + }.bind(this)) + } + }; + }, + + /** + * Calculates width of a record in percents. + * + * @param {Object} record + * @returns {String} + */ + getItemWidth: function (record) { + var days = 0; + + if (record) { + days = this.model.getDaysLength(record); + } + + return 100 / 7 * days + '%'; + }, + + /** + * Calculates left margin value for provided record. + * + * @param {Object} record + * @returns {String} + */ + getItemMargin: function (record) { + var offset = 0; + + if (record) { + offset = this.model.getStartDelta(record); + } + + return 100 / 7 * offset + '%'; + }, + + /** + * Returns collection of currently available + * timeline item elements. + * + * @returns {Array} + */ + getItems: function () { + return $(this.selectors.item, this.$content).toArray(); + }, + + /** + * Updates positions of timeline elements. + * + * @returns {TimelineView} Chainable. + */ + updateItemsPosition: function () { + this.getItems() + .forEach(this.updatePositionFor, this); + + return this; + }, + + /** + * Updates position of provided timeline element. + * + * @param {HTMLElement} elem + * @returns {TimelineView} Chainable. + */ + updatePositionFor: function (elem) { + var $elem = $(elem), + $event = $(this.selectors.event, $elem), + leftEdge = this.getLeftEdgeFor(elem), + rightEdge = this.getRightEdgeFor(elem); + + $event.css({ + left: leftEdge < 0 ? -leftEdge : 0, + right: rightEdge > 0 ? rightEdge : 0 + }); + + $elem.toggleClass('_scroll-start', leftEdge < 0) + .toggleClass('_scroll-end', rightEdge > 0); + + return this; + }, + + /** + * Scrolls content area to the start of provided element. + * + * @param {HTMLElement} elem + * @returns {TimelineView} + */ + toStartOf: function (elem) { + var leftEdge = this.getLeftEdgeFor(elem), + scroll = this.$content.scrollLeft(); + + this.$content.scrollLeft(scroll + leftEdge); + + return this; + }, + + /** + * Scrolls content area to the end of provided element. + * + * @param {HTMLElement} elem + * @returns {TimelineView} + */ + toEndOf: function (elem) { + var rightEdge = this.getRightEdgeFor(elem), + scroll = this.$content.scrollLeft(); + + this.$content.scrollLeft(scroll + rightEdge + 1); + + return this; + }, + + /** + * Calculates location of the left edge of an element + * relative to the contents' left edge. + * + * @param {HTMLElement} elem + * @returns {Number} + */ + getLeftEdgeFor: function (elem) { + var leftOffset = $(elem).offset().left; + + return leftOffset - this.$content.offset().left; + }, + + /** + * Calculates location of the right edge of an element + * relative to the contents' right edge. + * + * @param {HTMLElement} elem + * @returns {Number} + */ + getRightEdgeFor: function (elem) { + var elemWidth = $(elem).width(), + leftEdge = this.getLeftEdgeFor(elem); + + return leftEdge + elemWidth - this.$content.width(); + }, + + /** + * 'To Start' button 'click' event handler. + * + * @param {jQueryEvent} event + */ + onToStartClick: function (event) { + var elem = event.originalEvent.currentTarget; + + this.toStartOf(elem); + }, + + /** + * 'To End' button 'click' event handler. + * + * @param {jQueryEvent} event + */ + onToEndClick: function (event) { + var elem = event.originalEvent.currentTarget; + + this.toEndOf(elem); + }, + + /** + * Callback function which is invoked + * when event element was rendered. + */ + onEventElementRender: function () { + this.updateItemsPosition(); + }, + + /** + * Window 'resize' event handler. + */ + onWindowResize: function () { + this.updateItemsPosition(); + }, + + /** + * Content container 'scroll' event handler. + */ + onContentScroll: function () { + this.updateItemsPosition(); + }, + + /** + * Data 'reload' event handler. + */ + onDataReloaded: function () { + this.updateItemsPosition(); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js new file mode 100644 index 0000000000000..cefa72af29ca7 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js @@ -0,0 +1,290 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'underscore', + 'moment', + 'uiLayout', + 'Magento_Ui/js/grid/listing' +], function (_, moment, layout, Listing) { + 'use strict'; + + var ONE_DAY = 86400000; + + return Listing.extend({ + defaults: { + recordTmpl: 'ui/timeline/record', + dateFormat: 'YYYY-MM-DD hh:mm:ss', + headerFormat: 'ddd MM/DD', + detailsFormat: 'DD/MM/YYYY hh:mm:ss', + minDays: 4 * 7, + displayMode: 'timeline', + displayModes: { + timeline: { + label: 'Timeline', + value: 'timeline', + template: 'ui/timeline/timeline' + } + }, + viewConfig: { + component: 'Magento_Ui/js/timeline/timeline-view', + name: '${ $.name }_view', + model: '${ $.name }' + }, + range: {} + }, + + /** + * Initializes Timeline component. + * + * @returns {Timeline} Chainable. + */ + initialize: function () { + this._super() + .initView() + .updateRange(); + + return this; + }, + + /** + * Initializes observable properties. + * + * @returns {Timeline} Chainable. + */ + initObservable: function () { + this._super() + .observe.call(this.range, true, 'hasToday'); + + return this; + }, + + /** + * Initializes TimelineView component. + * + * @returns {Timeline} Chainable. + */ + initView: function () { + layout([this.viewConfig]); + + return this; + }, + + /** + * Checks if provided event record is active, + * i.e. it has already started. + * + * @param {Object} record + * @returns {Boolean} + */ + isActive: function (record) { + return record.status === 1; + }, + + /** + * Checks if provided event record is upcoming, + * i.e. it will start later on. + * + * @param {Object} record + * @returns {Boolean} + */ + isUpcoming: function (record) { + return record.status === 2; + }, + + /** + * Checks if provided event record is permanent, + * i.e. it has no ending time. + * + * @param {Object} record + * @returns {Boolean} + */ + isPermanent: function (record) { + return !this.getEndDate(record); + }, + + /** + * Checks if provided date indicates current day. + * + * @param {(Number|Moment)} date + * @returns {Boolenan} + */ + isToday: function (date) { + return moment().isSame(date, 'day'); + }, + + /** + * Checks if range object contains todays date. + * + * @returns {Boolean} + */ + hasToday: function () { + return this.range.hasToday; + }, + + /** + * Returns start date of provided record. + * + * @param {Object} record + * @returns {String} + */ + getStartDate: function (record) { + return record['start_time']; + }, + + /** + * Returns end date of provided record. + * + * @param {Object} record + * @returns {String} + */ + getEndDate: function (record) { + return record['end_time']; + }, + + /** + * Returns difference in days between records' start date + * and a first day of a range. + * + * @param {Object} record + * @returns {Number} + */ + getStartDelta: function (record) { + var start = this.createDate(this.getStartDate(record)), + firstDay = this.range.firstDay; + + return start.diff(firstDay) / ONE_DAY; + }, + + /** + * Calculates the amount of days that provided event lasts. + * + * @param {Object} record + * @returns {Number} + */ + getDaysLength: function (record) { + var start = this.createDate(this.getStartDate(record)), + end = this.createDate(this.getEndDate(record)); + + if (!end.isValid()) { + end = this.range.lastDay.endOf('day'); + } + + return end.diff(start) / ONE_DAY; + }, + + /** + * Creates new date object based on provided date string value. + * + * @param {String} dateStr + * @returns {Moment} + */ + createDate: function (dateStr) { + return moment(dateStr, this.dateFormat); + }, + + + /** + * Updates data of a range object, + * e.g. total days, first day and last day, etc. + * + * @returns {Object} Range instance. + */ + updateRange: function () { + var firstDay = this._getFirstDay(), + lastDay = this._getLastDay(), + totalDays = lastDay.diff(firstDay, 'days'), + days = [], + i = -1; + + if (totalDays < this.minDays) { + totalDays += this.minDays - totalDays; + } + + while (++i <= totalDays) { + days.push(+firstDay + ONE_DAY * i); + } + + return _.extend(this.range, { + days: days, + totalDays: totalDays, + firstDay: firstDay, + lastDay: moment(_.last(days)), + hasToday: this.isToday(firstDay) + }); + }, + + /** + * + * @private + * @param {String} key + * @returns {Array} + */ + _getDates: function (key) { + var dates = []; + + this.rows.forEach(function (record) { + if (record[key]) { + dates.push(this.createDate(record[key])); + } + }, this); + + return dates; + }, + + /** + * Returns date which is closest to the current day. + * + * @private + * @returns {Moment} + */ + _getFirstDay: function () { + var dates = this._getDates('start_time'), + first = moment.min(dates).subtract(1, 'day'), + today = moment(); + + if (!first.isValid() || first < today) { + first = today; + } + + return first.startOf('day'); + }, + + /** + * Returns the most distant date + * specified in available records. + * + * @private + * @returns {Moment} + */ + _getLastDay: function () { + var startDates = this._getDates('start_time'), + endDates = this._getDates('end_time'), + last = moment.max(startDates.concat(endDates)); + + return last.add(1, 'day').startOf('day'); + }, + + /** + * TODO: remove after integration with date binding. + * + * @param {Number} timestamp + * @returns {String} + */ + formatHeader: function (timestamp) { + return moment(timestamp).format(this.headerFormat); + }, + + /** + * TODO: remove after integration with date binding. + * + * @param {String} date + * @returns {String} + */ + formatDetails: function (date) { + return moment(date).format(this.detailsFormat); + } + }); +}); diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html b/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html new file mode 100644 index 0000000000000..db1e77f1ecc11 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html @@ -0,0 +1,17 @@ + + + +
+ + + +
+ From 0a84ae7fd4ee8c42c89b38c22e577db23936985e Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Fri, 26 Feb 2016 17:44:06 +0200 Subject: [PATCH 08/31] MAGETWO-49293: Create tooltip binding - intermediate version - implemented on timeline (time) --- .../web/js/lib/knockout/bindings/bootstrap.js | 1 + .../web/js/lib/knockout/bindings/tooltip.js | 502 ++++++++++++++++++ .../base/web/templates/timeline/timeline.html | 11 +- .../Ui/view/base/web/templates/tooltip.html | 9 + .../css/source/components/_data-tooltip.less | 4 + 5 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js create mode 100644 app/code/Magento/Ui/view/base/web/templates/tooltip.html diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js index de64a6d657a45..beebfea596e33 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js @@ -32,6 +32,7 @@ define(function (require) { collapsible: require('./collapsible'), staticChecked: require('./staticChecked'), simpleChecked: require('./simple-checked'), + tooltip: require('./tooltip'), repeat: require('knockoutjs/knockout-repeat'), fastForEach: require('knockoutjs/knockout-fast-foreach') }; diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js new file mode 100644 index 0000000000000..682741f5b4a46 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -0,0 +1,502 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery', + 'ko', + 'underscore', + 'mage/template', + 'text!ui/template/tooltip.html', + '../template/renderer' +], function ($, ko, _, template, tooltipTmpl, renderer) { + 'use strict'; + + var tooltip, + defaults, + positions, + transformProp, + checkedPositions = {}; + + defaults = { + tooltipWrapper: '[data-tooltip=tooltip-wrapper]', + tooltipContentBlock: 'data-tooltip-content', + closeButtonClass: 'action-close', + action: 'click', + step: 20, + delay: 0, + track: false, + position: 'top', + closeButton: false, + showed: false + }; + + /** + * Polyfill for css pransform + */ + transformProp = (function () { + var style = document.createElement('div').style, + base = 'Transform', + vendors = ['webkit', 'moz', 'ms', 'o'], + vi = vendors.length, + property; + + if (typeof style.transform != 'undefined') { + return 'transform'; + } + + while (vi--) { + property = vendors[vi] + base; + + if (typeof style[property] != 'undefined') { + return property; + } + } + })(); + + positions = { + map: { + horizontal: { + s: 'w', + p: 'left' + }, + vertical: { + s: 'h', + p: 'top' + } + }, + + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @returns {Object} tooltip data (position, className, etc) + */ + top: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { + checkedPositions.top = true; + + return positions._topLeftChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'vertical', 'horizontal', + 'right', 'left', '_bottom', 'top', positions.map); + }, + + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @returns {Object} tooltip data (position, className, etc) + */ + right: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { + checkedPositions.right = true; + + return positions._bottomRightChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'horizontal', + 'vertical', 'bottom', 'top', '_left', 'right', positions.map); + }, + + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @returns {Object} tooltip data (position, className, etc) + */ + bottom: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { + checkedPositions.bottom = true; + + return positions._bottomRightChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'vertical', + 'horizontal', 'left', 'right', '_top', 'bottom', positions.map); + }, + + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @returns {Object} tooltip data (position, className, etc) + */ + left: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { + checkedPositions.left = true; + + return positions._topLeftChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, + 'horizontal', 'vertical', 'top', 'bottom', '_right', 'left', positions.map); + }, + + /** + * Check can be tooltip setted to transmitted position + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @param {String} direction - direction position for map (vertical/horizontal) + * @param {String} directionDep - direction position for map, used for try set to next position + * @param {String} delegateFirst - priority position if tooltip can't be setted in current + * @param {String} delegateSecond - secondary position if tooltip can't be setted in current + * @param {String} className - class name for tooltip if tooltip can be setted in current position + * @param {String} side - current side position + * @param {Object} map - map for directions + * @returns {Object} tooltip data (position, className, etc) + */ + _bottomRightChecker: function (winSize, wrapSize, elemSize, elemPos, scrollPos, direction, directionDep, + delegateFirst, delegateSecond, className, side, map) { + var result = { + position: {} + }; + + if (elemPos[map[direction].p] + elemSize[map[direction].s] + wrapSize[map[direction].s] < + winSize[map[direction].s] + scrollPos[map[direction].p]) { + // If tooltip can be setted in left position + result.position[map[direction].p] = elemPos[map[direction].p] + elemSize[map[direction].s] + + defaults.step; + result.className = className; + result.side = side; + result = positions._normalize(winSize, wrapSize, elemSize, elemPos, scrollPos, directionDep, + delegateFirst, delegateSecond, result, map); + } else if (!checkedPositions[delegateFirst]) { + result = positions[delegateFirst].apply(null, arguments); + } else { + result.position = scrollPos; + } + + return result; + }, + + /** + * Check can be tooltip setted to transmitted position + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @param {String} direction - direction position for map (vertical/horizontal) + * @param {String} directionDep - direction position for map, used for try set to next position + * @param {String} delegateFirst - priority position if tooltip can't be setted in current + * @param {String} delegateSecond - secondary position if tooltip can't be setted in current + * @param {String} className - class name for tooltip if tooltip can be setted in current position + * @param {String} side - current side position + * @param {Object} map - map for directions + * @returns {Object} tooltip data (position, className, etc) + */ + _topLeftChecker: function (winSize, wrapSize, elemSize, elemPos, scrollPos, direction, directionDep, + delegateFirst, delegateSecond, className, side, map) { + var result = { + position: {} + }; + + if (elemPos[map[direction].p] - wrapSize[map[direction].s] > scrollPos[map[direction].p]) { + // If tooltip can be setted in left position + result.position[map[direction].p] = elemPos[map[direction].p] - wrapSize[map[direction].s] - + defaults.step; + result.className = className; + result.side = side; + result = positions._normalize(winSize, wrapSize, elemSize, elemPos, scrollPos, directionDep, + delegateFirst, delegateSecond, result, map); + } else if (!checkedPositions[delegateFirst]) { + result = positions[delegateFirst].apply(null, arguments); + } else { + result.position = scrollPos; + } + + return result; + }, + + /** + * Check can be tooltip setted to transmitted position + * + * @param {Object} winSize - screen size + * @param {Object} wrapSize - tooltip size + * @param {Object} elemSize - trigger size + * @param {Object} elemPos - trigger position + * @param {Object} scrollPos - scroll position + * @param {String} direction - direction position for map (vertical/horizontal) + * @param {String} delegateFirst - priority position if tooltip can't be setted in current + * @param {String} delegateSecond - secondary position if tooltip can't be setted in current + * @param {Object} data - available data + * @param {Object} map - map for directions + * @returns {Object} tooltip data (position, className, etc) + */ + _normalize: function (winSize, wrapSize, elemSize, elemPos, scrollPos, direction, delegateFirst, delegateSecond, + data, map) { + var depResult, + centerPosition = elemPos[map[direction].p] - + (wrapSize[map[direction].s] - elemSize[map[direction].s]) / 2; + + if (elemSize[map[direction].s] > wrapSize[map[direction].s]) { + // If tooltip width less then handler width + data.position[map[direction].p] = (elemSize[map[direction].s] - + wrapSize[map[direction].s]) / 2 + elemPos[map[direction].p]; + } else if (centerPosition + wrapSize[map[direction].s] < + winSize[map[direction].s] + scrollPos[map[direction].p] && + centerPosition > scrollPos[map[direction].p]) { + // If tooltip width more then handler width but placed in viewport + data.position[map[direction].p] = centerPosition; + } else { + // If tooltip width more then handler width and can't be placed in viewport by left side + /*eslint-disable no-lonely-if*/ + if (!checkedPositions[delegateFirst]) { + depResult = positions[delegateFirst].apply(null, arguments); + depResult.hasOwnProperty('className') ? + data = depResult : data.position[map[direction].p] = scrollPos[map[direction].p]; + } else if (!checkedPositions[delegateSecond]) { + depResult = positions[delegateSecond].apply(null, arguments); + depResult.hasOwnProperty('className') ? + data = depResult : data.position[map[direction].p] = scrollPos[map[direction].p]; + } else { + data.position[map[direction].p] = scrollPos[map[direction].p]; + } + } + + return data; + } + }; + + tooltip = { + + /** + * Create tooltip and append to DOM + * + * @param {Object} config - tooltip config + * @returns {Object} tooltip element + */ + createTooltip: function (config) { + var body = $('body'); + + $(template(tooltipTmpl, { + data: config + })).appendTo(body); + + tooltip.showed = true; + tooltip.element = $(config.tooltipWrapper); + + return tooltip.element; + }, + + /** + * Set data/handlers/position to tooltip + * + * @param {Object} elem - tooltip element + * @param {Object} viewModel - tooltip viewModel + * @param {Object} config - tooltip config + * @param {Object} bindingCtx - tooltip bindingCtx + * @param {Object} event - current event + */ + setContent: function (elem, viewModel, config, bindingCtx, event) { + var html = $(elem).html(), + tooltipElement; + + tooltip.destroy(config); + + if (tooltip.trigger && tooltip.trigger[0] === event.target && config.action === 'click') { + return tooltip.trigger = false; + } + + tooltip.trigger = $(event.target); + tooltip.targetElement = false; + $(document).on('mousemove', tooltip.setTargetData); + tooltip.timeout = setTimeout(function () { + $(document).off('mousemove', tooltip.setTargetData); + + if (!tooltip.targetElement || tooltip.trigger[0] === tooltip.targetElement) { + event.stopPropagation(); + tooltipElement = tooltip.createTooltip(config); + tooltipElement.find('.' + config.tooltipContentBlock).append(html); + tooltipElement.applyBindings(bindingCtx); + tooltip.setHandlers(config); + tooltip.setPosition(elem, tooltipElement, config, event); + } + }, config.delay); + }, + + /** + * Set target element + * + * @param {Object} event - current event + */ + setTargetData: function (event) { + tooltip.targetElement = event.target; + tooltip.event = event; + }, + + /** + * Set handlers to tooltip + * + * @param {Object} config - tooltip config + */ + setHandlers: function (config) { + + if (config.track) { + tooltip.trigger.on('mousemove', tooltip.track); + } + + if (config.action === 'click') { + $(document).on('click', tooltip.outerClick.bind(null, config)); + } + + if (config.closeButton) { + $('.' + config.closeButtonClass).on('click', tooltip.destroy.bind(null, config)); + } + + $(window).on('resize', tooltip.outerClick.bind(null, config)); + }, + + /** + * Change tooltip position when track is enabled + * + * @param {Object} event - current event + */ + track: function (event) { + var inequality = {}; + + if (tooltip.side === 'bottom' || tooltip.side === 'top') { + inequality.x = event.pageX - (tooltip.position.left + tooltip.element.outerWidth()/2); + tooltip.element[0].style[transformProp] = 'translateX(' + inequality.x + 'px)'; + } else if (tooltip.side === 'left' || tooltip.side === 'right' ) { + inequality.y = event.pageY - (tooltip.position.top + tooltip.element.outerHeight()/2); + tooltip.element[0].style[transformProp] = 'translateY(' + inequality.y + 'px)'; + } + }, + + /** + * Remove tooltip handlers + * + * @param {Object} config - tooltip config + */ + removeHandlers: function (config) { + if (config.track && tooltip.trigger) { + tooltip.trigger.off('mousemove', tooltip.track); + } + + if (config.action === 'click') { + $(document).off('click', tooltip.outerClick); + } + + if (config.closeButton) { + $('.' + config.closeButtonClass).off('click', tooltip.destroy); + } + + $(window).off('resize', tooltip.outerClick); + }, + + /** + * Outer click handler to close tooltip + * + * @param {Object} config - tooltip config + * @param {Object} event - current event + */ + outerClick: function (config, event) { + var tooltipElement = $(event.target).parents(config.tooltipWrapper)[0]; + + if (tooltip.showed && tooltipElement !== tooltip.element[0]) { + tooltip.destroy(config); + } + }, + + /** + * Set position to tooltip + * + * @param {Object} element - tooltip trigger + * @param {Object} tooltipElement - tooltip element + * @param {Object} config - tooltip config + * @param {Object} event - current event + */ + setPosition: function (element, tooltipElement, config, event) { + var handler = $(event.target), + windowSize = { + h: $(window).outerHeight(), + w: $(window).outerWidth() + }, + scrollPosition = { + top: $(window).scrollTop(), + left: $(window).scrollLeft() + }, + wrapperSize = { + h: tooltipElement.outerHeight(), + w: tooltipElement.outerWidth() + }, + elementSize = { + h: handler.outerHeight(), + w: handler.outerWidth() + }, + elementPosition = handler.offset(); + + _.extend(tooltip, + positions[config.position](windowSize, wrapperSize, elementSize, elementPosition, scrollPosition)); + checkedPositions = {}; + + if (config.track && tooltip.event && (tooltip.side === 'bottom' || tooltip.side === 'top')) { + tooltip.position.left -= (elementSize.w / 2 - tooltip.event.offsetX); + } else if (config.track && tooltip.event && (tooltip.side === 'left' || tooltip.side === 'right')) { + tooltip.position.top -= (elementSize.h / 2 - tooltip.event.offsetY); + } + + tooltipElement.css(tooltip.position); + tooltipElement.addClass(tooltip.className); + }, + + /** + * Destroy tooltip instance + * + * @param {Object} config - tooltip config + */ + destroy: function (config) { + config = config || {}; + clearTimeout(tooltip.timeout); + + if (tooltip.element) { + tooltip.element.remove(); + tooltip.showed = false; + } + + tooltip.removeHandlers(config); + } + }; + + ko.bindingHandlers.tooltip = { + + /** + * Initialize tooltip + * + * @param {Object} element - tooltip element + * @param {Function} valueAccessor - tooltip data + * @param {Object} allBindings - all bindings on current element + * @param {Object} viewModel - current element viewModel + * @param {Object} bindingCtx - current element binding context + */ + init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) { + var config = _.extend(defaults, valueAccessor()), + trigger = config.trigger, + action = config.action, + $parentScope = $(element).addClass('hidden').parent(); + + if (action === 'hover') { + $parentScope.on('mouseenter', trigger, + tooltip.setContent.bind(null, element, viewModel, config, bindingCtx)); + $parentScope.on('mouseleave', trigger, tooltip.destroy.bind(null, config)); + } else if (action === 'click') { + $parentScope.on('click', trigger, + tooltip.setContent.bind(null, element, viewModel, config, bindingCtx)); + } + + return { + controlsDescendantBindings: true + }; + } + }; + + renderer.addAttribute('tooltip'); +}); diff --git a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html index 64037a34aeade..58561aa105afe 100644 --- a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html +++ b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html @@ -40,7 +40,16 @@
  • -
  • From 5bee5480a909c59e15b33c25fd06f693fe2a4d5d Mon Sep 17 00:00:00 2001 From: Denys Rul Date: Sat, 27 Feb 2016 16:24:57 +0200 Subject: [PATCH 10/31] MAGETWO-49313: Stabilize implementation - Implement adapter binding for jquerys' 'slider' plugin - Rewrite view component to use native methods of DOM elements - Update view state in a loop - Minor changes --- .../web/js/lib/knockout/bindings/bootstrap.js | 1 + .../web/js/lib/knockout/bindings/range.js | 59 ++++++++++ .../web/js/lib/knockout/template/renderer.js | 2 +- .../base/web/js/timeline/timeline-view.js | 101 ++++++++++++------ .../Ui/view/base/web/js/timeline/timeline.js | 37 ++++++- .../base/web/templates/timeline/timeline.html | 27 ++--- .../web/css/source/components/_slider.less | 9 +- .../web/css/source/components/_timeline.less | 18 +--- 8 files changed, 182 insertions(+), 72 deletions(-) create mode 100644 app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js index beebfea596e33..7d5a95346cf02 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/bootstrap.js @@ -21,6 +21,7 @@ define(function (require) { return { i18n: require('./i18n'), scope: require('./scope'), + range: require('./range'), mageInit: require('./mage-init'), keyboard: require('./keyboard'), optgroup: require('./optgroup'), diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js new file mode 100644 index 0000000000000..4ee14ddc16eed --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/range.js @@ -0,0 +1,59 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'ko', + 'jquery', + '../template/renderer', + 'jquery/ui' +], function (ko, $, renderer) { + 'use strict'; + + ko.bindingHandlers.range = { + + /** + * Initializes binding and a slider update. + * + * @param {HTMLElement} element + * @param {Function} valueAccessor + */ + init: function (element, valueAccessor) { + var config = valueAccessor(), + value = config.value; + + $.extend(config, { + value: value(), + + /** + * Callback which is being called when sliders' value changes. + * + * @param {Event} event + * @param {Object} ui + */ + slide: function (event, ui) { + value(ui.value); + } + }); + + $(element).slider(config); + }, + + /** + * Updates sliders' plugin configuration. + * + * @param {HTMLElement} element + * @param {Function} valueAccessor + */ + update: function (element, valueAccessor) { + var config = valueAccessor(); + + config.value = ko.unwrap(config.value); + + $(element).slider('option', config); + } + }; + + renderer.addAttribute('range'); +}); diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js index e7dc37e60d0c0..8f5fb6646efef 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js @@ -465,7 +465,7 @@ define([ 'optionsText', 'optionsValue', 'checkedValue', - 'selectedOptions', + 'selectedOptions' ], Array.prototype) }; diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js index 3703d8349c38e..f510bb984278a 100644 --- a/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline-view.js @@ -7,11 +7,30 @@ define([ 'ko', 'Magento_Ui/js/lib/view/utils/async', 'underscore', + 'Magento_Ui/js/lib/view/utils/raf', 'uiRegistry', 'uiClass' -], function (ko, $, _, registry, Class) { +], function (ko, $, _, raf, registry, Class) { 'use strict'; + /** + * Polyfill of the 'classList.toggle' method. + * + * @param {HTMLElement} elem + */ + function toggleClass(elem) { + var classList = elem.classList, + args = Array.prototype.slice.call(arguments, 1), + $elem; + + if (classList) { + classList.toggle.apply(classList, args); + } else { + $elem = $(elem); + $elem.toggleClass.apply($elem, args); + } + } + return Class.extend({ defaults: { selectors: { @@ -30,6 +49,7 @@ define([ initialize: function () { _.bindAll( this, + 'refresh', 'initContent', 'initItem', 'initTimeUnit', @@ -89,15 +109,17 @@ define([ * @returns {TimelineView} Chainable. */ initContent: function (content) { - this.$content = $(content); + this.$content = content; - this.$content.on('scroll', this.onContentScroll); + $(content).on('scroll', this.onContentScroll); $(window).on('resize', this.onWindowResize); $.async(this.selectors.item, content, this.initItem); $.async(this.selectors.event, content, this.onEventElementRender); $.async(this.selectors.timeUnit, content, this.initTimeUnit); + this.refresh(); + return this; }, @@ -129,6 +151,20 @@ define([ return this; }, + /** + * Updates items positions in a + * loop if state of a view has changed. + */ + refresh: function () { + raf(this.refresh); + + if (this._update) { + this._update = false; + + this.updateItemsPosition(); + } + }, + /** * Returns object width additional bindings * for a timeline unit element. @@ -172,7 +208,7 @@ define([ * @returns {Number} */ getTimeUnitWidth: function () { - return 100 / 7 / this.model.scale; + return 100 / this.model.scale; }, /** @@ -214,7 +250,9 @@ define([ * @returns {Array} */ getItems: function () { - return $(this.selectors.item, this.$content).toArray(); + var items = this.$content.querySelectorAll(this.selectors.item); + + return _.toArray(items); }, /** @@ -232,22 +270,21 @@ define([ /** * Updates position of provided timeline element. * - * @param {HTMLElement} elem + * @param {HTMLElement} $elem * @returns {TimelineView} Chainable. */ - updatePositionFor: function (elem) { - var $elem = $(elem), - $event = $(this.selectors.event, $elem), - leftEdge = this.getLeftEdgeFor(elem), - rightEdge = this.getRightEdgeFor(elem); - - $event.css({ - left: leftEdge < 0 ? -leftEdge : 0, - right: rightEdge > 0 ? rightEdge : 0 - }); + updatePositionFor: function ($elem) { + var $event = $elem.querySelector(this.selectors.event), + leftEdge = this.getLeftEdgeFor($elem), + rightEdge = this.getRightEdgeFor($elem); + + if ($event) { + $event.style.left = (leftEdge < 0 ? -leftEdge : 0) + 'px'; + $event.style.right = (rightEdge > 0 ? rightEdge : 0) + 'px'; + } - $elem.toggleClass('_scroll-start', leftEdge < 0) - .toggleClass('_scroll-end', rightEdge > 0); + toggleClass($elem, '_scroll-start', leftEdge < 0); + toggleClass($elem, '_scroll-end', rightEdge > 0); return this; }, @@ -259,10 +296,9 @@ define([ * @returns {TimelineView} */ toStartOf: function (elem) { - var leftEdge = this.getLeftEdgeFor(elem), - scroll = this.$content.scrollLeft(); + var leftEdge = this.getLeftEdgeFor(elem); - this.$content.scrollLeft(scroll + leftEdge); + this.$content.scrollLeft += leftEdge; return this; }, @@ -274,10 +310,9 @@ define([ * @returns {TimelineView} */ toEndOf: function (elem) { - var rightEdge = this.getRightEdgeFor(elem), - scroll = this.$content.scrollLeft(); + var rightEdge = this.getRightEdgeFor(elem); - this.$content.scrollLeft(scroll + rightEdge + 1); + this.$content.scrollLeft += rightEdge + 1; return this; }, @@ -290,9 +325,9 @@ define([ * @returns {Number} */ getLeftEdgeFor: function (elem) { - var leftOffset = $(elem).offset().left; + var leftOffset = elem.getBoundingClientRect().left; - return leftOffset - this.$content.offset().left; + return leftOffset - this.$content.getBoundingClientRect().left; }, /** @@ -303,10 +338,10 @@ define([ * @returns {Number} */ getRightEdgeFor: function (elem) { - var elemWidth = $(elem).width(), + var elemWidth = elem.offsetWidth, leftEdge = this.getLeftEdgeFor(elem); - return leftEdge + elemWidth - this.$content.width(); + return leftEdge + elemWidth - this.$content.offsetWidth; }, /** @@ -335,7 +370,7 @@ define([ * Handler of the scale value 'change' event. */ onScaleChange: function () { - _.defer(this.updateItemsPosition); + this._update = true; }, /** @@ -343,28 +378,28 @@ define([ * when event element was rendered. */ onEventElementRender: function () { - this.updateItemsPosition(); + this._update = true; }, /** * Window 'resize' event handler. */ onWindowResize: function () { - this.updateItemsPosition(); + this._update = true; }, /** * Content container 'scroll' event handler. */ onContentScroll: function () { - this.updateItemsPosition(); + this._update = true; }, /** * Data 'reload' event handler. */ onDataReloaded: function () { - this.updateItemsPosition(); + this._update = true; } }); }); diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js index 50b7a983c728d..c50309e5005f8 100644 --- a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js @@ -19,11 +19,11 @@ define([ dateFormat: 'YYYY-MM-DD hh:mm:ss', headerFormat: 'ddd MM/DD', detailsFormat: 'DD/MM/YYYY hh:mm:ss', - scale: 1, + scale: 7, + scaleStep: 1, + minScale: 5, + maxScale: 28, minDays: 28, - minScale: 1, - maxScale: 4, - scaleStep: 1 / 7, displayMode: 'timeline', displayModes: { timeline: { @@ -59,6 +59,20 @@ define([ return this; }, + /** + * Initializes components configuration. + * + * @returns {Timeline} Chainable. + */ + initConfig: function () { + this._super(); + + this.maxScale = Math.min(this.minDays, this.maxScale); + this.minScale = Math.min(this.maxScale, this.minScale); + + return this; + }, + /** * Initializes observable properties. * @@ -195,6 +209,21 @@ define([ return moment(dateStr, this.dateFormat); }, + /** + * Converts days to weeks. + * + * @param {Number} days + * @returns {Number} + */ + daysToWeeks: function (days) { + var weeks = days / 7; + + if (weeks % 1) { + weeks = weeks.toFixed(1); + } + + return weeks; + }, /** * Updates data of a range object, diff --git a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html index d6ba91d31c6c0..182af637afdec 100644 --- a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html +++ b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html @@ -93,26 +93,15 @@
-
- - - + +
diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less index d0c73a1974b55..188f9d65e7d81 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_slider.less @@ -35,6 +35,7 @@ padding-top: 1.2rem; position: relative; width: @data-slider-track__width; + background: none; &:before { background: @data-slider-track__background-color; @@ -46,6 +47,10 @@ width: 100%; z-index: @data-slider-track__z-index; } + + .ui-slider-handle { + .data-slider-handle; + } } .data-slider-from { @@ -67,7 +72,9 @@ position: absolute; top: -@data-slider-handle__height / 2; width: @data-slider-handle__width; - z-index: @data-slider-track__z-index + 1; + z-index: @data-slider-track__z-index + 1 !important; + margin-left: -@data-slider-handle__width / 2 !important; + &:before { .lib-background-gradient( diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less index ec77ce8e12eab..c3bb2b01894c4 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less @@ -159,10 +159,6 @@ border-color: @timeline-event__active__border-color; } - ._from-now ._scroll-end & { - margin-right: -50px; - } - ._scroll-start:not(._active) & { padding-left: @indent__l; } @@ -175,10 +171,6 @@ margin-right: 23px; overflow: visible; } - - ._from-now ._permanent._scroll-end & { - margin-right: -28px; - } } .timeline-event-title { @@ -203,12 +195,6 @@ display: none; } -.timeline-event-actions { - .timeline-item._permanent & { - display: none; - } -} - .timeline-action { bottom: 0; display: none; @@ -262,6 +248,10 @@ .timeline-item._scroll-end & { display: block; } + + .timeline-item._permanent & { + display: none; + } } } From 7bddf27f995316980ca96d3b0ec85fb0949c1dfb Mon Sep 17 00:00:00 2001 From: Denys Rul Date: Sat, 27 Feb 2016 16:32:21 +0200 Subject: [PATCH 11/31] MAGETWO-49313: Stabilize implementation - Minimum scale value equals one week by default --- app/code/Magento/Ui/view/base/web/js/timeline/timeline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js index c50309e5005f8..6e737501869d9 100644 --- a/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js +++ b/app/code/Magento/Ui/view/base/web/js/timeline/timeline.js @@ -21,7 +21,7 @@ define([ detailsFormat: 'DD/MM/YYYY hh:mm:ss', scale: 7, scaleStep: 1, - minScale: 5, + minScale: 7, maxScale: 28, minDays: 28, displayMode: 'timeline', From 9e32c55a381bae555c0f6671216b748f3b5aa5c4 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 29 Feb 2016 09:27:48 +0200 Subject: [PATCH 12/31] MAGETWO-49293: Create tooltip binding - code refactoring --- .../web/js/lib/knockout/bindings/tooltip.js | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index 682741f5b4a46..e11e4570f5957 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -32,7 +32,7 @@ define([ }; /** - * Polyfill for css pransform + * Polyfill for css transform */ transformProp = (function () { var style = document.createElement('div').style, @@ -80,7 +80,7 @@ define([ checkedPositions.top = true; return positions._topLeftChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'vertical', 'horizontal', - 'right', 'left', '_bottom', 'top', positions.map); + 'right', 'left', '_bottom', 'top', positions.map); }, /** @@ -97,7 +97,7 @@ define([ checkedPositions.right = true; return positions._bottomRightChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'horizontal', - 'vertical', 'bottom', 'top', '_left', 'right', positions.map); + 'vertical', 'bottom', 'top', '_left', 'right', positions.map); }, /** @@ -114,7 +114,7 @@ define([ checkedPositions.bottom = true; return positions._bottomRightChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'vertical', - 'horizontal', 'left', 'right', '_top', 'bottom', positions.map); + 'horizontal', 'left', 'right', '_top', 'bottom', positions.map); }, /** @@ -131,7 +131,7 @@ define([ checkedPositions.left = true; return positions._topLeftChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, - 'horizontal', 'vertical', 'top', 'bottom', '_right', 'left', positions.map); + 'horizontal', 'vertical', 'top', 'bottom', '_right', 'left', positions.map); }, /** @@ -161,11 +161,11 @@ define([ winSize[map[direction].s] + scrollPos[map[direction].p]) { // If tooltip can be setted in left position result.position[map[direction].p] = elemPos[map[direction].p] + elemSize[map[direction].s] + - defaults.step; + defaults.step; result.className = className; result.side = side; result = positions._normalize(winSize, wrapSize, elemSize, elemPos, scrollPos, directionDep, - delegateFirst, delegateSecond, result, map); + delegateFirst, delegateSecond, result, map); } else if (!checkedPositions[delegateFirst]) { result = positions[delegateFirst].apply(null, arguments); } else { @@ -201,11 +201,11 @@ define([ if (elemPos[map[direction].p] - wrapSize[map[direction].s] > scrollPos[map[direction].p]) { // If tooltip can be setted in left position result.position[map[direction].p] = elemPos[map[direction].p] - wrapSize[map[direction].s] - - defaults.step; + defaults.step; result.className = className; result.side = side; result = positions._normalize(winSize, wrapSize, elemSize, elemPos, scrollPos, directionDep, - delegateFirst, delegateSecond, result, map); + delegateFirst, delegateSecond, result, map); } else if (!checkedPositions[delegateFirst]) { result = positions[delegateFirst].apply(null, arguments); } else { @@ -241,8 +241,8 @@ define([ data.position[map[direction].p] = (elemSize[map[direction].s] - wrapSize[map[direction].s]) / 2 + elemPos[map[direction].p]; } else if (centerPosition + wrapSize[map[direction].s] < - winSize[map[direction].s] + scrollPos[map[direction].p] && - centerPosition > scrollPos[map[direction].p]) { + winSize[map[direction].s] + scrollPos[map[direction].p] && + centerPosition > scrollPos[map[direction].p]) { // If tooltip width more then handler width but placed in viewport data.position[map[direction].p] = centerPosition; } else { @@ -308,7 +308,8 @@ define([ tooltip.trigger = $(event.target); tooltip.targetElement = false; $(document).on('mousemove', tooltip.setTargetData); - tooltip.timeout = setTimeout(function () { + + tooltip.timeout = _.delay(function () { $(document).off('mousemove', tooltip.setTargetData); if (!tooltip.targetElement || tooltip.trigger[0] === tooltip.targetElement) { @@ -437,15 +438,23 @@ define([ _.extend(tooltip, positions[config.position](windowSize, wrapperSize, elementSize, elementPosition, scrollPosition)); checkedPositions = {}; + tooltip._setPositionShift(config, elementSize); + tooltipElement.css(tooltip.position); + tooltipElement.addClass(tooltip.className); + }, + /** + * Set shift to position if track is enabled + * + * @param {Object} config - tooltip config + * @param {Object} elementSize - handler size + */ + _setPositionShift: function (config, elementSize) { if (config.track && tooltip.event && (tooltip.side === 'bottom' || tooltip.side === 'top')) { tooltip.position.left -= (elementSize.w / 2 - tooltip.event.offsetX); } else if (config.track && tooltip.event && (tooltip.side === 'left' || tooltip.side === 'right')) { tooltip.position.top -= (elementSize.h / 2 - tooltip.event.offsetY); } - - tooltipElement.css(tooltip.position); - tooltipElement.addClass(tooltip.className); }, /** From b039bd36c3c370c4ff4a9f764aef2da3dc6e404e Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 29 Feb 2016 10:40:29 +0200 Subject: [PATCH 13/31] MAGETWO-49293: Create tooltip binding - add copyright --- app/code/Magento/Ui/view/base/web/templates/tooltip.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/code/Magento/Ui/view/base/web/templates/tooltip.html b/app/code/Magento/Ui/view/base/web/templates/tooltip.html index 26ae8dbf2faf1..289bc9522c973 100644 --- a/app/code/Magento/Ui/view/base/web/templates/tooltip.html +++ b/app/code/Magento/Ui/view/base/web/templates/tooltip.html @@ -1,3 +1,9 @@ +
From 0768034f70df79d59d5374421b359a911969dd7b Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 29 Feb 2016 11:21:23 +0200 Subject: [PATCH 14/31] MAGETWO-49293: Create tooltip binding - stabialize --- .../Ui/view/base/web/js/lib/knockout/bindings/tooltip.js | 6 +++--- .../Ui/view/base/web/templates/{ => tooltip}/tooltip.html | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) rename app/code/Magento/Ui/view/base/web/templates/{ => tooltip}/tooltip.html (74%) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index e11e4570f5957..c2f2c7e914629 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -7,7 +7,7 @@ define([ 'ko', 'underscore', 'mage/template', - 'text!ui/template/tooltip.html', + 'text!ui/template/tooltip/tooltip.html', '../template/renderer' ], function ($, ko, _, template, tooltipTmpl, renderer) { 'use strict'; @@ -480,8 +480,8 @@ define([ /** * Initialize tooltip * - * @param {Object} element - tooltip element - * @param {Function} valueAccessor - tooltip data + * @param {Object} element - tooltip DOM element + * @param {Function} valueAccessor - ko observable property, tooltip data * @param {Object} allBindings - all bindings on current element * @param {Object} viewModel - current element viewModel * @param {Object} bindingCtx - current element binding context diff --git a/app/code/Magento/Ui/view/base/web/templates/tooltip.html b/app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html similarity index 74% rename from app/code/Magento/Ui/view/base/web/templates/tooltip.html rename to app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html index 289bc9522c973..02b11612f9472 100644 --- a/app/code/Magento/Ui/view/base/web/templates/tooltip.html +++ b/app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html @@ -8,7 +8,9 @@
<% if(data.closeButton){ %> - + <% } %>
From e4c5f2dbba05505f9a256455bc5d17eb5f26b699 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 29 Feb 2016 11:34:07 +0200 Subject: [PATCH 15/31] MAGETWO-49293: Create tooltip binding - codestyle --- .../Magento/Ui/view/base/web/templates/tooltip/tooltip.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html b/app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html index 02b11612f9472..1ce32807315c6 100644 --- a/app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html +++ b/app/code/Magento/Ui/view/base/web/templates/tooltip/tooltip.html @@ -9,7 +9,7 @@
<% if(data.closeButton){ %> <% } %>
From 93d43b487aa5bb053d6530957f2e6e05eac76c03 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Mon, 29 Feb 2016 12:22:15 +0200 Subject: [PATCH 16/31] MAGETWO-49293: Create tooltip binding - fix after resize --- .../Ui/view/base/web/js/lib/knockout/bindings/tooltip.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index c2f2c7e914629..165936ac4d408 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -299,12 +299,13 @@ define([ var html = $(elem).html(), tooltipElement; - tooltip.destroy(config); + if (tooltip.showed && tooltip.trigger && tooltip.trigger[0] === event.target && config.action === 'click') { + tooltip.destroy(config); - if (tooltip.trigger && tooltip.trigger[0] === event.target && config.action === 'click') { return tooltip.trigger = false; } + tooltip.destroy(config); tooltip.trigger = $(event.target); tooltip.targetElement = false; $(document).on('mousemove', tooltip.setTargetData); From f036fd076a24e4ede5fb96353f256dc7a90e569e Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Tue, 1 Mar 2016 10:58:53 +0200 Subject: [PATCH 17/31] MAGETWO-49293: Create tooltip binding - fix timeline tooltip configuration --- .../web/js/lib/knockout/bindings/tooltip.js | 96 +++++++++++++++---- .../base/web/templates/timeline/timeline.html | 4 +- .../css/source/components/_data-tooltip.less | 2 +- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index 165936ac4d408..6f0158a04f39a 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -276,6 +276,8 @@ define([ createTooltip: function (config) { var body = $('body'); + config = _.extend(defaults, config); + $(template(tooltipTmpl, { data: config })).appendTo(body); @@ -299,14 +301,20 @@ define([ var html = $(elem).html(), tooltipElement; - if (tooltip.showed && tooltip.trigger && tooltip.trigger[0] === event.target && config.action === 'click') { + config = _.extend(defaults, config); + + if (tooltip.showed && tooltip.trigger && tooltip.trigger[0] === event.currentTarget && config.action === 'click') { tooltip.destroy(config); return tooltip.trigger = false; } + if (config.action === 'click') { + tooltip.event = event; + } + tooltip.destroy(config); - tooltip.trigger = $(event.target); + tooltip.trigger = $(event.currentTarget); tooltip.targetElement = false; $(document).on('mousemove', tooltip.setTargetData); @@ -341,7 +349,7 @@ define([ */ setHandlers: function (config) { - if (config.track) { + if (config.track && config.action === 'hover') { tooltip.trigger.on('mousemove', tooltip.track); } @@ -366,9 +374,25 @@ define([ if (tooltip.side === 'bottom' || tooltip.side === 'top') { inequality.x = event.pageX - (tooltip.position.left + tooltip.element.outerWidth()/2); + + if (tooltip.position.left + inequality.x + tooltip.sizeData.wrapperSize.w > + tooltip.sizeData.windowSize.w + tooltip.sizeData.scrollPosition.left || + inequality.x + tooltip.position.left < tooltip.sizeData.scrollPosition.left) { + + return false; + } + tooltip.element[0].style[transformProp] = 'translateX(' + inequality.x + 'px)'; } else if (tooltip.side === 'left' || tooltip.side === 'right' ) { inequality.y = event.pageY - (tooltip.position.top + tooltip.element.outerHeight()/2); + + if (tooltip.position.top + inequality.x + tooltip.sizeData.wrapperSize.h > + tooltip.sizeData.windowSize.h + tooltip.sizeData.scrollPosition.top || + inequality.h + tooltip.position.top < tooltip.sizeData.scrollPosition.top) { + + return false; + } + tooltip.element[0].style[transformProp] = 'translateY(' + inequality.y + 'px)'; } }, @@ -416,30 +440,33 @@ define([ * @param {Object} config - tooltip config * @param {Object} event - current event */ - setPosition: function (element, tooltipElement, config, event) { - var handler = $(event.target), - windowSize = { + setPosition: function (element, tooltipElement, config) { + tooltip.sizeData = { + windowSize: { h: $(window).outerHeight(), w: $(window).outerWidth() }, - scrollPosition = { + scrollPosition: { top: $(window).scrollTop(), left: $(window).scrollLeft() }, - wrapperSize = { + wrapperSize: { h: tooltipElement.outerHeight(), w: tooltipElement.outerWidth() }, - elementSize = { - h: handler.outerHeight(), - w: handler.outerWidth() + elementSize: { + h: tooltip.trigger.outerHeight(), + w: tooltip.trigger.outerWidth() }, - elementPosition = handler.offset(); + elementPosition: tooltip.trigger.offset() + }; _.extend(tooltip, - positions[config.position](windowSize, wrapperSize, elementSize, elementPosition, scrollPosition)); + positions[config.position](tooltip.sizeData.windowSize, tooltip.sizeData.wrapperSize, + tooltip.sizeData.elementSize, tooltip.sizeData.elementPosition, tooltip.sizeData.scrollPosition)); checkedPositions = {}; - tooltip._setPositionShift(config, elementSize); + tooltip._setPositionShift(config, tooltip.sizeData.windowSize, tooltip.sizeData.wrapperSize, + tooltip.sizeData.elementSize, tooltip.sizeData.elementPosition, tooltip.sizeData.scrollPosition); tooltipElement.css(tooltip.position); tooltipElement.addClass(tooltip.className); }, @@ -448,13 +475,36 @@ define([ * Set shift to position if track is enabled * * @param {Object} config - tooltip config - * @param {Object} elementSize - handler size + * @param {Object} windowSize - window size + * @param {Object} wrapperSize - tooltip size + * @param {Object} elementSize - trigger size + * @param {Object} elementPosition - trigger position + * @param {Object} scrollPosition - scroll position */ - _setPositionShift: function (config, elementSize) { + _setPositionShift: function (config, windowSize, wrapperSize, elementSize, elementPosition, scrollPosition) { + var shift; + if (config.track && tooltip.event && (tooltip.side === 'bottom' || tooltip.side === 'top')) { - tooltip.position.left -= (elementSize.w / 2 - tooltip.event.offsetX); + shift = tooltip.position.left - (elementSize.w / 2 - + ($(tooltip.event.target).offset().left - tooltip.trigger.offset().left + tooltip.event.offsetX)); + + if (shift + wrapperSize.w > windowSize.w + scrollPosition.left) { + shift = windowSize.w + scrollPosition.left - wrapperSize.w; + } else if (shift < scrollPosition.left) { + shift = scrollPosition.left; + } + tooltip.position.left = shift; } else if (config.track && tooltip.event && (tooltip.side === 'left' || tooltip.side === 'right')) { - tooltip.position.top -= (elementSize.h / 2 - tooltip.event.offsetY); + shift = tooltip.position.top - (elementSize.h / 2 - + ($(tooltip.event.target).offset().top - tooltip.trigger.offset().top + tooltip.event.offsetY)); + + if (shift + wrapperSize.h > windowSize.h + scrollPosition.top) { + shift = windowSize.h + scrollPosition.top - wrapperSize.h; + } else if (shift < scrollPosition.top) { + shift = scrollPosition.top; + } + + tooltip.position.top = shift; } }, @@ -493,13 +543,17 @@ define([ action = config.action, $parentScope = $(element).addClass('hidden').parent(); + if (config.parentScope) { + $parentScope = $(config.parentScope); + } + if (action === 'hover') { $parentScope.on('mouseenter', trigger, - tooltip.setContent.bind(null, element, viewModel, config, bindingCtx)); + tooltip.setContent.bind(null, element, viewModel, valueAccessor(), bindingCtx)); $parentScope.on('mouseleave', trigger, tooltip.destroy.bind(null, config)); } else if (action === 'click') { $parentScope.on('click', trigger, - tooltip.setContent.bind(null, element, viewModel, config, bindingCtx)); + tooltip.setContent.bind(null, element, viewModel, valueAccessor(), bindingCtx)); } return { @@ -509,4 +563,4 @@ define([ }; renderer.addAttribute('tooltip'); -}); +}); \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html index 182af637afdec..e99df33d5d8c4 100644 --- a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html +++ b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html @@ -45,7 +45,8 @@ action: 'hover', delay: 200, track: true, - position: 'top' + position: 'top', + closeButton: false ">
@@ -60,6 +61,7 @@
  • - -
    diff --git a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html index e99df33d5d8c4..4fb73e1208686 100644 --- a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html +++ b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html @@ -34,7 +34,9 @@
    -
    +
    @@ -57,7 +59,7 @@ -
      +
      • - -
      • -
        - +
      • +
        +
      • 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 ebb18a5ba7a87..48f34efead34f 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 @@ -157,6 +157,12 @@ body._in-resize { } &.data-grid-tr-no-data { + td { + font-size: @data-grid__no-records__font-size; + padding: @data-grid__no-records__padding; + text-align: center; + } + &:hover { td { background-color: @data-grid-td__odd__background-color; @@ -979,6 +985,7 @@ body._in-resize { transform: rotate(45deg); width: 1.6rem; z-index: 3; + .ie9 & { display: none; } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less index c3bb2b01894c4..a4897643aff07 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_timeline.less @@ -11,6 +11,8 @@ @timeline__border-color: @color-gray60; @timeline__margin-top: @indent__base; @timeline__scale: 1; +@timeline__no-records__background-color: @color-white; + @timeline-item__height: 3.6rem; @timeline-unit__width: 100%/7; @@ -19,7 +21,10 @@ @timeline-event__border-color: #81c21d; @timeline-event__active__background-color: #bceeff; @timeline-event__active__border-color: #56c2e6; -@timeline-event__active__pemanent-color: @color-blue-pure; +@timeline-event__active__permanent__color: @color-blue-pure; +@timeline-event__no-records__background-color: transparent; +@timeline-event__no-records__border-color: transparent; +@timeline-event__no-records__color: @color-gray20; @timeline-action__color: #76c004; @timeline-action__active__color: #56c2e6; @@ -58,6 +63,10 @@ &._from-now { padding-left: 50px; } + + &._no-records { + background: @timeline__no-records__background-color; + } } .timeline-past { @@ -78,7 +87,6 @@ .timeline-legend { float: left; - margin-left: 50px; } .timeline-legend-item { @@ -121,6 +129,7 @@ .timeline-items { .extend__list-reset-styles(); min-height: @timeline-item__height * 7; + position: relative; } .timeline-item { @@ -131,6 +140,13 @@ & + .timeline-item { margin-top: -1px; } + + ._no-records & { + margin-top: -@timeline-item__height; + position: absolute; + top: 50%; + width: 100%; + } } .timeline-event { @@ -148,12 +164,16 @@ width: auto; min-width: 5.5rem; - ._permanent._active & { - color: @timeline-event__active__pemanent-color; + ._permanent._active &, + ._no-records & { justify-content: center; text-align: center; } + ._permanent._active & { + color: @timeline-event__active__permanent__color; + } + .timeline-item._active & { background: @timeline-event__active__background-color; border-color: @timeline-event__active__border-color; @@ -171,6 +191,13 @@ margin-right: 23px; overflow: visible; } + + ._no-records & { + background: @timeline-event__no-records__background-color; + border-color: @timeline-event__no-records__border-color; + color: @timeline-event__no-records__color; + cursor: default; + } } .timeline-event-title { @@ -183,6 +210,10 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + + ._no-records & { + font-weight: @font-weight__regular; + } } .timeline-event-info { @@ -343,6 +374,12 @@ svg { content: none; } } + + ._no-records & { + &:before { + display: none; + } + } } .timeline-date { diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less index 985d14cdb7031..b6d0702ff61c2 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_data-grid.less @@ -62,6 +62,9 @@ @data-grid-spinner__size: 4rem; +@data-grid__no-records__font-size: @font-size__l; +@data-grid__no-records__padding: @indent__l; + // Header @data-grid-header-add-indent__bottom: .9rem; From 56a80509ced4adc50190a9ff606f3012acea7215 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Wed, 2 Mar 2016 10:40:36 +0200 Subject: [PATCH 19/31] MAGETWO-49293: Create tooltip binding --- .../web/js/lib/knockout/bindings/tooltip.js | 951 ++++++++++++------ .../base/web/templates/timeline/timeline.html | 2 +- 2 files changed, 631 insertions(+), 322 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index 6f0158a04f39a..03be5307f57e7 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -16,19 +16,37 @@ define([ defaults, positions, transformProp, - checkedPositions = {}; + checkedPositions = {}, + iterator = 0, + previousTooltip, + tooltipData, + positionData = {}, + tooltipsCollection = {}; defaults = { tooltipWrapper: '[data-tooltip=tooltip-wrapper]', tooltipContentBlock: 'data-tooltip-content', closeButtonClass: 'action-close', + tailClass: 'data-tooltip-tail', action: 'click', - step: 20, delay: 0, track: false, + step: 20, position: 'top', closeButton: false, - showed: false + showed: false, + strict: true, + center: false + }; + + tooltipData = { + trigger: false, + timeout: 0, + element: false, + event: false, + targetElement: {}, + showed: false, + currentID: 0 }; /** @@ -55,313 +73,605 @@ define([ })(); positions = { - map: { - horizontal: { - s: 'w', - p: 'left' - }, - vertical: { - s: 'h', - p: 'top' - } - }, + + /*eslint max-depth: [0, 0]*/ /** * Wrapper function to get tooltip data (position, className, etc) * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position + * @param {Object} s - object with sizes and positions elements * @returns {Object} tooltip data (position, className, etc) */ - top: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { + top: function (s) { + var result = { + position: {} + }, + config = tooltip.getTooltip(tooltipData.currentID), + strict = !_.isUndefined(config.strict) ? config.strict : defaults.strict, + step = !_.isUndefined(config.step) ? config.step : defaults.step, + startPosition = !strict ? s.eventPosition : s.elementPosition; + checkedPositions.top = true; - return positions._topLeftChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'vertical', 'horizontal', - 'right', 'left', '_bottom', 'top', positions.map); + if (startPosition.top - s.tooltipSize.h - step > s.scrollPosition.top) { + result.position.top = startPosition.top - s.tooltipSize.h - step; + result.className = '_bottom'; + result.side = 'top'; + result = positions._normalizeTop(s, result, config); + } else if (!checkedPositions.right) { + result = positions.right.apply(null, arguments); + } else { + result = positions._positionCenter(s, result, config); + } + + return result; }, /** - * Wrapper function to get tooltip data (position, className, etc) + * Centered tooltip if tooltip does not fit in window * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position + * @param {Object} s - object with sizes and positions elements + * @param {Object} data - current data (position, className, etc) * @returns {Object} tooltip data (position, className, etc) */ - right: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { - checkedPositions.right = true; + _positionCenter: function (s, data) { + if (s.tooltipSize.w < s.windowSize.w) { + data.position.left = (s.windowSize.w - s.tooltipSize.w) / 2 + s.scrollPosition.left; + } else { + data.position.left = s.scrollPosition.left; + data.tooltipSize = { + width: s.windowSize.w + }; + } + + if (s.tooltipSize.h < s.windowSize.h) { + data.position.top = (s.windowSize.h - s.tooltipSize.h) / 2 + s.scrollPosition.top; + } else { + data.position.top = s.scrollPosition.top; + data.tooltipSize = { + height: s.windowSize.h + }; + } - return positions._bottomRightChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'horizontal', - 'vertical', 'bottom', 'top', '_left', 'right', positions.map); + return data; }, /** - * Wrapper function to get tooltip data (position, className, etc) + * Normalize horizontal position if element can be setted in vertical position * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position + * @param {Object} s - object with sizes and positions elements + * @param {Object} data - current data (position, className, etc) + * @param {Object} config - tooltip config * @returns {Object} tooltip data (position, className, etc) */ - bottom: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { - checkedPositions.bottom = true; + _normalizeTop: function (s, data, config) { + var center = !_.isUndefined(config.center) ? config.center : defaults.center, + startPosition = !center ? s.eventPosition : { + left: s.elementPosition.left + s.elementSize.w / 2, + top: s.elementPosition.top + }, + depResult; + + if (startPosition.left + s.tooltipSize.w / 2 < s.windowSize.w + s.scrollPosition.left && + startPosition.left - s.tooltipSize.w / 2 > s.scrollPosition.left) { + data.position.left = startPosition.left - s.tooltipSize.w / 2; + } else { - return positions._bottomRightChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, 'vertical', - 'horizontal', 'left', 'right', '_top', 'bottom', positions.map); + /*eslint-disable no-lonely-if*/ + if (!checkedPositions.right) { + depResult = positions.right.apply(null, arguments); + + if (depResult.hasOwnProperty('className')) { + data = depResult; + } else { + data.tail = {}; + + if (s.tooltipSize.w < s.windowSize.w) { + + if (startPosition.left > s.windowSize.w / 2 + s.scrollPosition.left) { + data.position.left = s.windowSize.w + s.scrollPosition.left - s.tooltipSize.w; + data.tail.left = startPosition.left - s.tooltipSize.w / 2 - data.position.left; + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = data.position.left - (startPosition.left - s.tooltipSize.w / 2); + } + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = s.eventPosition.left - s.windowSize.w / 2; + data.tooltipSize = { + width: s.windowSize.w + }; + } + } + } else { + data.tail = {}; + + if (s.tooltipSize.w < s.windowSize.w) { + + if (startPosition.left > s.windowSize.w / 2 + s.scrollPosition.left) { + data.position.left = s.windowSize.w + s.scrollPosition.left - s.tooltipSize.w; + data.tail.left = startPosition.left - s.tooltipSize.w / 2 - data.position.left; + + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = data.position.left - (startPosition.left - s.tooltipSize.w / 2); + } + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = s.eventPosition.left - s.windowSize.w / 2; + data.tooltipSize = { + width: s.windowSize.w + }; + } + } + } + + return data; }, /** - * Wrapper function to get tooltip data (position, className, etc) + * Normalize horizontal position if element can be setted in vertical position * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position + * @param {Object} s - object with sizes and positions elements + * @param {Object} data - current data (position, className, etc) + * @param {Object} config - tooltip config * @returns {Object} tooltip data (position, className, etc) */ - left: function (winSize, wrapSize, elemSize, elemPos, scrollPos) { - checkedPositions.left = true; + _normalizeBottom: function (s, data, config) { + var center = !_.isUndefined(config.center) ? config.center : defaults.center, + startPosition = !center ? s.eventPosition : { + left: s.elementPosition.left + s.elementSize.w / 2, + top: s.elementPosition.top + }, + depResult; - return positions._topLeftChecker(winSize, wrapSize, elemSize, elemPos, scrollPos, - 'horizontal', 'vertical', 'top', 'bottom', '_right', 'left', positions.map); + if (startPosition.left + s.tooltipSize.w / 2 < s.windowSize.w + s.scrollPosition.left && + startPosition.left - s.tooltipSize.w / 2 > s.scrollPosition.left) { + data.position.left = startPosition.left - s.tooltipSize.w / 2; + } else { + + /*eslint-disable no-lonely-if*/ + if (!checkedPositions.left) { + depResult = positions.left.apply(null, arguments); + + if (depResult.hasOwnProperty('className')) { + data = depResult; + } else { + data.tail = {}; + + if (s.tooltipSize.w < s.windowSize.w) { + + if (startPosition.left > s.windowSize.w / 2 + s.scrollPosition.left) { + data.position.left = s.windowSize.w + s.scrollPosition.left - s.tooltipSize.w; + data.tail.left = startPosition.left - s.tooltipSize.w / 2 - data.position.left; + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = data.position.left - (startPosition.left - s.tooltipSize.w / 2); + } + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = s.eventPosition.left - s.windowSize.w / 2; + data.tooltipSize = { + width: s.windowSize.w + }; + } + } + } else { + data.tail = {}; + + if (s.tooltipSize.w < s.windowSize.w) { + + if (startPosition.left > s.windowSize.w / 2 + s.scrollPosition.left) { + data.position.left = s.windowSize.w + s.scrollPosition.left - s.tooltipSize.w; + data.tail.left = startPosition.left - s.tooltipSize.w / 2 - data.position.left; + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = data.position.left - (startPosition.left - s.tooltipSize.w / 2); + } + } else { + data.position.left = s.scrollPosition.left; + data.tail.left = s.eventPosition.left - s.windowSize.w / 2; + data.tooltipSize = { + width: s.windowSize.w + }; + } + } + } + + return data; }, /** - * Check can be tooltip setted to transmitted position + * Normalize vertical position if element can be setted in horizontal position * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position - * @param {String} direction - direction position for map (vertical/horizontal) - * @param {String} directionDep - direction position for map, used for try set to next position - * @param {String} delegateFirst - priority position if tooltip can't be setted in current - * @param {String} delegateSecond - secondary position if tooltip can't be setted in current - * @param {String} className - class name for tooltip if tooltip can be setted in current position - * @param {String} side - current side position - * @param {Object} map - map for directions + * @param {Object} s - object with sizes and positions elements + * @param {Object} data - current data (position, className, etc) + * @param {Object} config - tooltip config * @returns {Object} tooltip data (position, className, etc) */ - _bottomRightChecker: function (winSize, wrapSize, elemSize, elemPos, scrollPos, direction, directionDep, - delegateFirst, delegateSecond, className, side, map) { + _normalizeRight: function (s, data, config) { + var center = !_.isUndefined(config.center) ? config.center : defaults.center, + startPosition = !center ? s.eventPosition : { + top: s.elementPosition.top + s.elementSize.h / 2, + left: s.elementPosition.left + }, + depResult; + + if (startPosition.top - s.tooltipSize.h / 2 > s.scrollPosition.top && + startPosition.top + s.tooltipSize.h / 2 < s.scrollPosition.top + s.windowSize.h) { + data.position.top = startPosition.top - s.tooltipSize.h / 2; + } else { + + /*eslint-disable no-lonely-if*/ + if (!checkedPositions.bottom) { + depResult = positions.bottom.apply(null, arguments); + + if (depResult.hasOwnProperty('className')) { + data = depResult; + } else { + data.tail = {}; + + if (s.tooltipSize.h < s.windowSize.h) { + + if (startPosition.top > s.scrollPosition.top + s.windowSize.h / 2) { + data.position.top = s.windowSize.h + s.scrollPosition.top - s.tooltipSize.h; + data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.top; + } else { + data.position.top = s.scrollPosition.top; + data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.top; + } + } else { + data.position.top = s.scrollPosition.top; + data.tail.top = s.eventPosition.top - s.scrollPosition.top - s.windowSize.h / 2; + data.tooltipSize = { + height: s.windowSize.h + }; + } + } + } else { + data.tail = {}; + + if (s.tooltipSize.h < s.windowSize.h) { + + if (startPosition.top > s.scrollPosition.top + s.windowSize.h / 2) { + data.position.top = s.scrollPosition.top; + data.tail.top = data.position.top - (startPosition.top - s.tooltipSize.h / 2); + } else { + data.position.top = s.windowSize.h + s.scrollPosition.top - s.tooltipSize.h; + data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.left; + } + } else { + data.position.top = s.scrollPosition.top; + data.tail.top = s.eventPosition.top - s.scrollPosition.top - s.windowSize.h / 2; + data.tooltipSize = { + height: s.windowSize.h + }; + } + } + } + + return data; + }, + + /** + * Normalize vertical position if element can be setted in horizontal position + * + * @param {Object} s - object with sizes and positions elements + * @param {Object} data - current data (position, className, etc) + * @param {Object} config - tooltip config + * @returns {Object} tooltip data (position, className, etc) + */ + _normalizeLeft: function (s, data, config) { + var center = !_.isUndefined(config.center) ? config.center : defaults.center, + startPosition = !center ? s.eventPosition : { + top: s.elementPosition.top + s.elementSize.h / 2, + left: s.elementPosition.left + }, + depResult; + + if (startPosition.top - s.tooltipSize.h / 2 > s.scrollPosition.top && + startPosition.top + s.tooltipSize.h / 2 < s.scrollPosition.top + s.windowSize.h) { + data.position.top = startPosition.top - s.tooltipSize.h / 2; + } else { + + /*eslint-disable no-lonely-if*/ + if (!checkedPositions.top) { + depResult = positions.top.apply(null, arguments); + + if (depResult.hasOwnProperty('className')) { + data = depResult; + } else { + data.tail = {}; + + if (s.tooltipSize.h < s.windowSize.h) { + + if (startPosition.top > s.scrollPosition.top + s.windowSize.h / 2) { + data.position.top = s.windowSize.h + s.scrollPosition.top - s.tooltipSize.h; + data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.top; + } else { + data.position.top = s.scrollPosition.top; + data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.top; + } + } else { + data.position.top = s.scrollPosition.top; + data.tail.top = s.eventPosition.top - s.scrollPosition.top - s.windowSize.h / 2; + data.tooltipSize = { + height: s.windowSize.h + }; + } + } + } else { + data.tail = {}; + + if (s.tooltipSize.h < s.windowSize.h) { + + if (startPosition.top > s.scrollPosition.top + s.windowSize.h / 2) { + data.position.top = s.scrollPosition.top; + data.tail.top = data.position.top - (startPosition.top - s.tooltipSize.h / 2); + } else { + data.position.top = s.windowSize.h + s.scrollPosition.top - s.tooltipSize.h; + data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.left; + } + } else { + data.position.top = s.scrollPosition.top; + data.tail.top = s.eventPosition.top - s.scrollPosition.top - s.windowSize.h / 2; + data.tooltipSize = { + height: s.windowSize.h + }; + } + } + } + + return data; + }, + + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} s - object with sizes and positions elements + * @returns {Object} tooltip data (position, className, etc) + */ + left: function (s) { var result = { - position: {} - }; + position: {} + }, + config = tooltip.getTooltip(tooltipData.currentID), + strict = !_.isUndefined(config.strict) ? config.strict : defaults.strict, + step = config.step || defaults.step, + startPosition = !strict ? s.eventPosition : s.elementPosition; + + checkedPositions.left = true; - if (elemPos[map[direction].p] + elemSize[map[direction].s] + wrapSize[map[direction].s] < - winSize[map[direction].s] + scrollPos[map[direction].p]) { - // If tooltip can be setted in left position - result.position[map[direction].p] = elemPos[map[direction].p] + elemSize[map[direction].s] + - defaults.step; - result.className = className; - result.side = side; - result = positions._normalize(winSize, wrapSize, elemSize, elemPos, scrollPos, directionDep, - delegateFirst, delegateSecond, result, map); - } else if (!checkedPositions[delegateFirst]) { - result = positions[delegateFirst].apply(null, arguments); + if (startPosition.left - s.tooltipSize.w - step > s.scrollPosition.left) { + result.position.left = startPosition.left - s.tooltipSize.w - step; + result.className = '_right'; + result.side = 'left'; + result = positions._normalizeLeft(s, result, config); + } else if (!checkedPositions.top) { + result = positions.top.apply(null, arguments); } else { - result.position = scrollPos; + result = positions._positionCenter(s, result, config); } return result; }, /** - * Check can be tooltip setted to transmitted position + * Wrapper function to get tooltip data (position, className, etc) * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position - * @param {String} direction - direction position for map (vertical/horizontal) - * @param {String} directionDep - direction position for map, used for try set to next position - * @param {String} delegateFirst - priority position if tooltip can't be setted in current - * @param {String} delegateSecond - secondary position if tooltip can't be setted in current - * @param {String} className - class name for tooltip if tooltip can be setted in current position - * @param {String} side - current side position - * @param {Object} map - map for directions + * @param {Object} s - object with sizes and positions elements * @returns {Object} tooltip data (position, className, etc) */ - _topLeftChecker: function (winSize, wrapSize, elemSize, elemPos, scrollPos, direction, directionDep, - delegateFirst, delegateSecond, className, side, map) { + bottom: function (s) { var result = { - position: {} - }; + position: {} + }, + config = tooltip.getTooltip(tooltipData.currentID), + strict = !_.isUndefined(config.strict) ? config.strict : defaults.strict, + step = config.step || defaults.step, + startPosition = !strict ? s.eventPosition : { + top: s.elementPosition.top + s.elementSize.h, + left: s.elementPosition.left + }; + + checkedPositions.bottom = true; - if (elemPos[map[direction].p] - wrapSize[map[direction].s] > scrollPos[map[direction].p]) { - // If tooltip can be setted in left position - result.position[map[direction].p] = elemPos[map[direction].p] - wrapSize[map[direction].s] - - defaults.step; - result.className = className; - result.side = side; - result = positions._normalize(winSize, wrapSize, elemSize, elemPos, scrollPos, directionDep, - delegateFirst, delegateSecond, result, map); - } else if (!checkedPositions[delegateFirst]) { - result = positions[delegateFirst].apply(null, arguments); + if (startPosition.top + s.tooltipSize.h + step < s.scrollPosition.top + s.windowSize.h) { + result.position.top = startPosition.top + step; + result.className = '_top'; + result.side = 'bottom'; + result = positions._normalizeBottom(s, result, config); + } else if (!checkedPositions.left) { + result = positions.left.apply(null, arguments); } else { - result.position = scrollPos; + result = positions._positionCenter(s, result, config); } return result; }, /** - * Check can be tooltip setted to transmitted position + * Wrapper function to get tooltip data (position, className, etc) * - * @param {Object} winSize - screen size - * @param {Object} wrapSize - tooltip size - * @param {Object} elemSize - trigger size - * @param {Object} elemPos - trigger position - * @param {Object} scrollPos - scroll position - * @param {String} direction - direction position for map (vertical/horizontal) - * @param {String} delegateFirst - priority position if tooltip can't be setted in current - * @param {String} delegateSecond - secondary position if tooltip can't be setted in current - * @param {Object} data - available data - * @param {Object} map - map for directions + * @param {Object} s - object with sizes and positions elements * @returns {Object} tooltip data (position, className, etc) */ - _normalize: function (winSize, wrapSize, elemSize, elemPos, scrollPos, direction, delegateFirst, delegateSecond, - data, map) { - var depResult, - centerPosition = elemPos[map[direction].p] - - (wrapSize[map[direction].s] - elemSize[map[direction].s]) / 2; - - if (elemSize[map[direction].s] > wrapSize[map[direction].s]) { - // If tooltip width less then handler width - data.position[map[direction].p] = (elemSize[map[direction].s] - - wrapSize[map[direction].s]) / 2 + elemPos[map[direction].p]; - } else if (centerPosition + wrapSize[map[direction].s] < - winSize[map[direction].s] + scrollPos[map[direction].p] && - centerPosition > scrollPos[map[direction].p]) { - // If tooltip width more then handler width but placed in viewport - data.position[map[direction].p] = centerPosition; + right: function (s) { + var result = { + position: {} + }, + config = tooltip.getTooltip(tooltipData.currentID), + strict = !_.isUndefined(config.strict) ? config.strict : defaults.strict, + step = config.step || defaults.step, + startPosition = !strict ? s.eventPosition : { + left: s.elementPosition.left + s.elementSize.w, + top: s.elementPosition.top + }; + + checkedPositions.right = true; + + if (startPosition.left + s.tooltipSize.w + step < s.windowSize.w + s.scrollPosition.left) { + result.position.left = startPosition.left + step; + result.className = '_left'; + result.side = 'right'; + result = positions._normalizeRight(s, result, config); + } else if (!checkedPositions.bottom) { + result = positions.bottom.apply(null, arguments); } else { - // If tooltip width more then handler width and can't be placed in viewport by left side - /*eslint-disable no-lonely-if*/ - if (!checkedPositions[delegateFirst]) { - depResult = positions[delegateFirst].apply(null, arguments); - depResult.hasOwnProperty('className') ? - data = depResult : data.position[map[direction].p] = scrollPos[map[direction].p]; - } else if (!checkedPositions[delegateSecond]) { - depResult = positions[delegateSecond].apply(null, arguments); - depResult.hasOwnProperty('className') ? - data = depResult : data.position[map[direction].p] = scrollPos[map[direction].p]; - } else { - data.position[map[direction].p] = scrollPos[map[direction].p]; - } + result = positions._positionCenter(s, result, config); } - return data; + return result; } }; tooltip = { /** - * Create tooltip and append to DOM + * Set new tooltip to tooltipCollection, save config, and add unic id * * @param {Object} config - tooltip config - * @returns {Object} tooltip element + * @returns {String} tooltip id */ - createTooltip: function (config) { - var body = $('body'); + setTooltip: function (config) { + var property = 'id-' + iterator; - config = _.extend(defaults, config); + tooltipsCollection[property] = config; + iterator++; - $(template(tooltipTmpl, { - data: config - })).appendTo(body); - - tooltip.showed = true; - tooltip.element = $(config.tooltipWrapper); + return property; + }, - return tooltip.element; + /** + * Get tooltip config by id + * + * @param {String} id - tooltip id + * @returns {Object} tooltip config + */ + getTooltip: function (id) { + return tooltipsCollection[id]; }, /** - * Set data/handlers/position to tooltip + * Set content to current tooltip * - * @param {Object} elem - tooltip element - * @param {Object} viewModel - tooltip viewModel - * @param {Object} config - tooltip config - * @param {Object} bindingCtx - tooltip bindingCtx - * @param {Object} event - current event + * @param {Object} tooltipElement - tooltip element + * @param {Object} viewModel - tooltip view model + * @param {String} id - tooltip id + * @param {Object} bindingCtx - tooltip context + * @param {Object} event - action event */ - setContent: function (elem, viewModel, config, bindingCtx, event) { - var html = $(elem).html(), - tooltipElement; + setContent: function (tooltipElement, viewModel, id, bindingCtx, event) { + var html = $(tooltipElement).html(), + config = tooltip.getTooltip(id), + body = $('body'), + delay = !_.isUndefined(config.delay) ? config.delay : defaults.delay; + + tooltipData.currentID = id; + tooltipData.trigger = $(event.currentTarget); + tooltip.setTargetData(event); + body.on('mousemove.setTargetData', tooltip.setTargetData); + tooltip.clearTimeout(id); + + tooltipData.timeout = _.delay(function () { + body.off('mousemove.setTargetData', tooltip.setTargetData); + + if (tooltipData.trigger[0] === tooltipData.targetElement) { + tooltip.destroy(id); + event.stopPropagation(); + tooltipElement = tooltip.createTooltip(id); + tooltipElement.find('.' + defaults.tooltipContentBlock).append(html); + tooltipElement.applyBindings(bindingCtx); + tooltip.setHandlers(id); + tooltip.setPosition(tooltipElement, id); + previousTooltip = id; + } - config = _.extend(defaults, config); + }, delay); + }, - if (tooltip.showed && tooltip.trigger && tooltip.trigger[0] === event.currentTarget && config.action === 'click') { - tooltip.destroy(config); + /** + * Set position to current tooltip + * + * @param {Object} tooltipElement - tooltip element + * @param {String} id - tooltip id + */ + setPosition: function (tooltipElement, id) { + var config = tooltip.getTooltip(id), + position = config.position || defaults.position, + tail, + tailMargin; - return tooltip.trigger = false; - } + tooltip.sizeData = { + windowSize: { + h: $(window).outerHeight(), + w: $(window).outerWidth() + }, + scrollPosition: { + top: $(window).scrollTop(), + left: $(window).scrollLeft() + }, + tooltipSize: { + h: tooltipElement.outerHeight(), + w: tooltipElement.outerWidth() + }, + elementSize: { + h: tooltipData.trigger.outerHeight(), + w: tooltipData.trigger.outerWidth() + }, + elementPosition: tooltipData.trigger.offset(), + eventPosition: { + left: tooltipData.event.pageX, + top: tooltipData.event.pageY + } + }; - if (config.action === 'click') { - tooltip.event = event; - } + _.extend(positionData, positions[position](tooltip.sizeData)); + checkedPositions = {}; + tooltipElement.css(positionData.position); + tooltipElement.addClass(positionData.className); + $('body').css('position', 'relative'); - tooltip.destroy(config); - tooltip.trigger = $(event.currentTarget); - tooltip.targetElement = false; - $(document).on('mousemove', tooltip.setTargetData); + if (positionData.tooltipSize) { + tooltipElement.css(positionData.tooltipSize); + } - tooltip.timeout = _.delay(function () { - $(document).off('mousemove', tooltip.setTargetData); + if (positionData.tail) { + tail = tooltipElement.find('.' + defaults.tailClass); - if (!tooltip.targetElement || tooltip.trigger[0] === tooltip.targetElement) { - event.stopPropagation(); - tooltipElement = tooltip.createTooltip(config); - tooltipElement.find('.' + config.tooltipContentBlock).append(html); - tooltipElement.applyBindings(bindingCtx); - tooltip.setHandlers(config); - tooltip.setPosition(elem, tooltipElement, config, event); + if (positionData.tail.left) { + tailMargin = parseInt(tail.css('margin-left'), 10); + tail.css('margin-left', tailMargin + positionData.tail.left); + } else { + tailMargin = parseInt(tail.css('margin-top'), 10); + tail.css('margin-top', tailMargin + positionData.tail.top); } - }, config.delay); + } }, /** - * Set target element + * Close tooltip if action happened outside handler and tooltip element * - * @param {Object} event - current event + * @param {String} id - tooltip id + * @param {Object} event - action event */ - setTargetData: function (event) { - tooltip.targetElement = event.target; - tooltip.event = event; + outerClick: function (id, event) { + var tooltipElement = $(event.target).parents(defaults.tooltipWrapper)[0]; + + if (tooltipData.showed && tooltipElement !== tooltipData.element[0]) { + tooltip.destroy(id); + } }, /** - * Set handlers to tooltip + * Parse keydown event and if event trigger is escape key - close tooltip * - * @param {Object} config - tooltip config + * @param {Object} event - action event */ - setHandlers: function (config) { - - if (config.track && config.action === 'hover') { - tooltip.trigger.on('mousemove', tooltip.track); - } - - if (config.action === 'click') { - $(document).on('click', tooltip.outerClick.bind(null, config)); - } - - if (config.closeButton) { - $('.' + config.closeButtonClass).on('click', tooltip.destroy.bind(null, config)); + keydownHandler: function (event) { + if (tooltipData.showed && event.keyCode === 27) { + tooltip.destroy(tooltipData.currentID); } - - $(window).on('resize', tooltip.outerClick.bind(null, config)); }, /** @@ -372,157 +682,155 @@ define([ track: function (event) { var inequality = {}; - if (tooltip.side === 'bottom' || tooltip.side === 'top') { - inequality.x = event.pageX - (tooltip.position.left + tooltip.element.outerWidth()/2); + if (positionData.side === 'bottom' || positionData.side === 'top') { + inequality.x = event.pageX - (positionData.position.left + tooltipData.element.outerWidth() / 2); - if (tooltip.position.left + inequality.x + tooltip.sizeData.wrapperSize.w > + if (positionData.position.left + inequality.x + tooltip.sizeData.tooltipSize.w > tooltip.sizeData.windowSize.w + tooltip.sizeData.scrollPosition.left || - inequality.x + tooltip.position.left < tooltip.sizeData.scrollPosition.left) { + inequality.x + positionData.position.left < tooltip.sizeData.scrollPosition.left) { return false; } - tooltip.element[0].style[transformProp] = 'translateX(' + inequality.x + 'px)'; - } else if (tooltip.side === 'left' || tooltip.side === 'right' ) { - inequality.y = event.pageY - (tooltip.position.top + tooltip.element.outerHeight()/2); + tooltipData.element[0].style[transformProp] = 'translateX(' + inequality.x + 'px)'; + } else if (positionData.side === 'left' || positionData.side === 'right') { + inequality.y = event.pageY - (positionData.position.top + tooltipData.element.outerHeight() / 2); - if (tooltip.position.top + inequality.x + tooltip.sizeData.wrapperSize.h > + if (positionData.position.top + inequality.x + tooltip.sizeData.tooltipSize.h > tooltip.sizeData.windowSize.h + tooltip.sizeData.scrollPosition.top || - inequality.h + tooltip.position.top < tooltip.sizeData.scrollPosition.top) { + inequality.h + positionData.position.top < tooltip.sizeData.scrollPosition.top) { return false; } - tooltip.element[0].style[transformProp] = 'translateY(' + inequality.y + 'px)'; + tooltipData.element[0].style[transformProp] = 'translateY(' + inequality.y + 'px)'; } }, /** - * Remove tooltip handlers + * Set handlers to tooltip * - * @param {Object} config - tooltip config + * @param {String} id - tooltip id */ - removeHandlers: function (config) { - if (config.track && tooltip.trigger) { - tooltip.trigger.off('mousemove', tooltip.track); + setHandlers: function (id) { + var config = tooltip.getTooltip(id), + action = config.action || defaults.action, + closeButton = !_.isUndefined(config.closeButton) ? config.closeButton : defaults.closeButton, + track = !_.isUndefined(config.track) ? config.track : defaults.track; + + if (track) { + tooltipData.trigger.on('mousemove.track', tooltip.track); } - if (config.action === 'click') { - $(document).off('click', tooltip.outerClick); + if (action === 'click') { + $(window).on('click.outerClick', tooltip.outerClick.bind(null, id)); } - if (config.closeButton) { - $('.' + config.closeButtonClass).off('click', tooltip.destroy); + if (closeButton) { + $('.' + defaults.closeButtonClass).on('click.closeButton', tooltip.destroy.bind(null, id)); } - $(window).off('resize', tooltip.outerClick); + $(window).on('keydown.tooltip', tooltip.keydownHandler); + $(window).on('scroll.tooltip', tooltip.outerClick.bind(null, id)); + $(window).on('resize.outerClick', tooltip.outerClick.bind(null, id)); }, /** - * Outer click handler to close tooltip + * Toggle tooltip * - * @param {Object} config - tooltip config - * @param {Object} event - current event + * @param {Object} tooltipElement - tooltip element + * @param {Object} viewModel - tooltip view model + * @param {String} id - tooltip id */ - outerClick: function (config, event) { - var tooltipElement = $(event.target).parents(config.tooltipWrapper)[0]; + toggleTooltip: function (tooltipElement, viewModel, id) { + if (previousTooltip === id && tooltipData.showed) { + tooltip.destroy(id); - if (tooltip.showed && tooltipElement !== tooltip.element[0]) { - tooltip.destroy(config); + return false; } + + tooltip.setContent.apply(null, arguments); }, /** - * Set position to tooltip + * Create tooltip and append to DOM * - * @param {Object} element - tooltip trigger - * @param {Object} tooltipElement - tooltip element - * @param {Object} config - tooltip config - * @param {Object} event - current event + * @param {String} id - tooltip id + * @returns {Object} tooltip element */ - setPosition: function (element, tooltipElement, config) { - tooltip.sizeData = { - windowSize: { - h: $(window).outerHeight(), - w: $(window).outerWidth() - }, - scrollPosition: { - top: $(window).scrollTop(), - left: $(window).scrollLeft() - }, - wrapperSize: { - h: tooltipElement.outerHeight(), - w: tooltipElement.outerWidth() - }, - elementSize: { - h: tooltip.trigger.outerHeight(), - w: tooltip.trigger.outerWidth() - }, - elementPosition: tooltip.trigger.offset() - }; + createTooltip: function (id) { + var body = $('body'), + config = tooltip.getTooltip(id); - _.extend(tooltip, - positions[config.position](tooltip.sizeData.windowSize, tooltip.sizeData.wrapperSize, - tooltip.sizeData.elementSize, tooltip.sizeData.elementPosition, tooltip.sizeData.scrollPosition)); - checkedPositions = {}; - tooltip._setPositionShift(config, tooltip.sizeData.windowSize, tooltip.sizeData.wrapperSize, - tooltip.sizeData.elementSize, tooltip.sizeData.elementPosition, tooltip.sizeData.scrollPosition); - tooltipElement.css(tooltip.position); - tooltipElement.addClass(tooltip.className); + $(template(tooltipTmpl, { + data: config + })).appendTo(body); + + tooltipData.showed = true; + tooltipData.element = $(defaults.tooltipWrapper); + + return tooltipData.element; }, /** - * Set shift to position if track is enabled + * Check action and clean timeout * - * @param {Object} config - tooltip config - * @param {Object} windowSize - window size - * @param {Object} wrapperSize - tooltip size - * @param {Object} elementSize - trigger size - * @param {Object} elementPosition - trigger position - * @param {Object} scrollPosition - scroll position + * @param {String} id - tooltip id */ - _setPositionShift: function (config, windowSize, wrapperSize, elementSize, elementPosition, scrollPosition) { - var shift; + clearTimeout: function (id) { + var config = tooltip.getTooltip(id), + action = config.action || defaults.action; - if (config.track && tooltip.event && (tooltip.side === 'bottom' || tooltip.side === 'top')) { - shift = tooltip.position.left - (elementSize.w / 2 - - ($(tooltip.event.target).offset().left - tooltip.trigger.offset().left + tooltip.event.offsetX)); - - if (shift + wrapperSize.w > windowSize.w + scrollPosition.left) { - shift = windowSize.w + scrollPosition.left - wrapperSize.w; - } else if (shift < scrollPosition.left) { - shift = scrollPosition.left; - } - tooltip.position.left = shift; - } else if (config.track && tooltip.event && (tooltip.side === 'left' || tooltip.side === 'right')) { - shift = tooltip.position.top - (elementSize.h / 2 - - ($(tooltip.event.target).offset().top - tooltip.trigger.offset().top + tooltip.event.offsetY)); - - if (shift + wrapperSize.h > windowSize.h + scrollPosition.top) { - shift = windowSize.h + scrollPosition.top - wrapperSize.h; - } else if (shift < scrollPosition.top) { - shift = scrollPosition.top; - } + if (action === 'hover') { + clearTimeout(tooltipData.timeout); + } + }, - tooltip.position.top = shift; + /** + * Check previous tooltip + */ + checkPreviousTooltip: function () { + if (!tooltipData.timeout) { + tooltip.destroy(); } }, /** * Destroy tooltip instance - * - * @param {Object} config - tooltip config */ - destroy: function (config) { - config = config || {}; - clearTimeout(tooltip.timeout); - - if (tooltip.element) { - tooltip.element.remove(); - tooltip.showed = false; + destroy: function () { + if (tooltipData.element) { + tooltipData.element.remove(); + tooltipData.showed = false; } - tooltip.removeHandlers(config); + $('body').css('position', 'static'); + positionData = {}; + tooltipData.timeout = false; + tooltip.removeHandlers(); + }, + + /** + * Remove tooltip handlers + */ + removeHandlers: function () { + $('.' + defaults.closeButtonClass).off('click.closeButton'); + tooltipData.trigger.off('mousemove.track'); + $(window).off('click.outerClick'); + $(window).off('scroll.tooltip'); + $(window).off('keydown.tooltip'); + $(window).off('resize.outerClick'); + }, + + /** + * Set target element + * + * @param {Object} event - current event + */ + setTargetData: function (event) { + tooltipData.event = event; + tooltipData.targetElement = event.type === 'mousemove' ? + event.target : event.currentTarget; } }; @@ -531,29 +839,30 @@ define([ /** * Initialize tooltip * - * @param {Object} element - tooltip DOM element + * @param {Object} elem - tooltip DOM element * @param {Function} valueAccessor - ko observable property, tooltip data * @param {Object} allBindings - all bindings on current element * @param {Object} viewModel - current element viewModel * @param {Object} bindingCtx - current element binding context */ - init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) { - var config = _.extend(defaults, valueAccessor()), + init: function (elem, valueAccessor, allBindings, viewModel, bindingCtx) { + var config = valueAccessor(), trigger = config.trigger, action = config.action, - $parentScope = $(element).addClass('hidden').parent(); + $parentScope = $(elem).addClass('hidden').parent(), + id; if (config.parentScope) { $parentScope = $(config.parentScope); } + id = tooltip.setTooltip(valueAccessor()); + if (action === 'hover') { - $parentScope.on('mouseenter', trigger, - tooltip.setContent.bind(null, element, viewModel, valueAccessor(), bindingCtx)); - $parentScope.on('mouseleave', trigger, tooltip.destroy.bind(null, config)); + $parentScope.on('mouseenter', trigger, tooltip.setContent.bind(null, elem, viewModel, id, bindingCtx)); + $parentScope.on('mouseleave', trigger, tooltip.checkPreviousTooltip.bind(null, id)); } else if (action === 'click') { - $parentScope.on('click', trigger, - tooltip.setContent.bind(null, element, viewModel, valueAccessor(), bindingCtx)); + $parentScope.on('click', trigger, tooltip.toggleTooltip.bind(null, elem, viewModel, id, bindingCtx)); } return { @@ -563,4 +872,4 @@ define([ }; renderer.addAttribute('tooltip'); -}); \ No newline at end of file +}); diff --git a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html index 4fb73e1208686..74b756e3ec41f 100644 --- a/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html +++ b/app/code/Magento/Ui/view/base/web/templates/timeline/timeline.html @@ -45,7 +45,7 @@
        - - - - - - - -
        + + + + + + + + +
        From b2c61410cff08af539d48fa6782902bdbb1501af Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Thu, 3 Mar 2016 09:44:38 +0200 Subject: [PATCH 26/31] MAGETWO-49293: Create tooltip binding - fix codestyle and configuration --- .../web/js/lib/knockout/bindings/tooltip.js | 411 ++++++++---------- 1 file changed, 173 insertions(+), 238 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index 521492a3bb2d3..12f72e5069c07 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -34,8 +34,8 @@ define([ tooltipContentBlock: 'data-tooltip-content', closeButtonClass: 'action-close', tailClass: 'data-tooltip-tail', - action: 'click', - delay: 0, + action: 'hover', + delay: 300, track: false, step: 20, position: 'top', @@ -113,6 +113,37 @@ define([ return positions._topLeftChecker(s, positions.map, 'horizontal', '_right', 'left', 'top'); }, + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} s - object with sizes and positions elements + * @returns {Object} tooltip data (position, className, etc) + */ + bottom: function (s) { + return positions._bottomRightChecker(s, positions.map, 'vertical', '_top', 'bottom', 'left'); + }, + + /** + * Wrapper function to get tooltip data (position, className, etc) + * + * @param {Object} s - object with sizes and positions elements + * @returns {Object} tooltip data (position, className, etc) + */ + right: function (s) { + return positions._bottomRightChecker(s, positions.map, 'horizontal', '_left', 'right', 'bottom'); + }, + + /** + * Check can tooltip setted on current position or not. If can't setted - delegate call. + * + * @param {Object} s - object with sizes and positions elements + * @param {Object} map - mapping for get direction positions + * @param {String} direction - vertical or horizontal + * @param {String} className - class whats should be setted to tooltip + * @param {String} side - parent method name + * @param {String} delegate - method name if tooltip can't be setted in current position + * @returns {Object} tooltip data (position, className, etc) + */ _topLeftChecker: function (s, map, direction, className, side, delegate) { var result = { position: {} @@ -123,8 +154,10 @@ define([ checkedPositions[side] = true; - if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step > s.scrollPosition[map[direction].p]) { - result.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step; + if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step > + s.scrollPosition[map[direction].p]) { + result.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - + config.step; result.className = className; result.side = side; changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical'; @@ -132,12 +165,23 @@ define([ } else if (!checkedPositions[delegate]) { result = positions[delegate].apply(null, arguments); } else { - result = positions._positionCenter(s, result, config); + result = positions.positionCenter(s, result); } return result; }, + /** + * Check can tooltip setted on current position or not. If can't setted - delegate call. + * + * @param {Object} s - object with sizes and positions elements + * @param {Object} map - mapping for get direction positions + * @param {String} direction - vertical or horizontal + * @param {String} className - class whats should be setted to tooltip + * @param {String} side - parent method name + * @param {String} delegate - method name if tooltip can't be setted in current position + * @returns {Object} tooltip data (position, className, etc) + */ _bottomRightChecker: function (s, map, direction, className, side, delegate) { var result = { position: {} @@ -151,7 +195,8 @@ define([ checkedPositions[side] = true; - if (startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step < s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]) { + if (startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step < + s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]) { result.position[map[direction].p] = startPosition[map[direction].p] + config.step; result.className = className; result.side = side; @@ -160,141 +205,71 @@ define([ } else if (!checkedPositions[delegate]) { result = positions[delegate].apply(null, arguments); } else { - result = positions._positionCenter(s, result, config); + result = positions.positionCenter(s, result); } return result; }, /** - * Wrapper function to get tooltip data (position, className, etc) + * Centered tooltip if tooltip does not fit in window * * @param {Object} s - object with sizes and positions elements + * @param {Object} data - current data (position, className, etc) * @returns {Object} tooltip data (position, className, etc) */ - bottom: function (s) { - return positions._bottomRightChecker(s, positions.map, 'vertical', '_top', 'bottom', 'left'); - }, + positionCenter: function (s, data) { + data = positions._positionCenter(s, data, 'horizontal', positions.map); + data = positions._positionCenter(s, data, 'vertical', positions.map); - /** - * Wrapper function to get tooltip data (position, className, etc) - * - * @param {Object} s - object with sizes and positions elements - * @returns {Object} tooltip data (position, className, etc) - */ - right: function (s) { - return positions._bottomRightChecker(s, positions.map, 'horizontal', '_left', 'right', 'bottom'); + return data; }, /** - * Centered tooltip if tooltip does not fit in window + * Centered tooltip side * * @param {Object} s - object with sizes and positions elements * @param {Object} data - current data (position, className, etc) + * @param {String} direction - vertical or horizontal + * @param {Object} map - mapping for get direction positions * @returns {Object} tooltip data (position, className, etc) */ - _positionCenter: function (s, data) { - if (s.tooltipSize.w < s.windowSize.w) { - data.position.left = (s.windowSize.w - s.tooltipSize.w) / 2 + s.scrollPosition.left; - } else { - data.position.left = s.scrollPosition.left; - data.tooltipSize = { - width: s.windowSize.w - }; - } - - if (s.tooltipSize.h < s.windowSize.h) { - data.position.top = (s.windowSize.h - s.tooltipSize.h) / 2 + s.scrollPosition.top; + _positionCenter: function (s, data, direction, map) { + if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) { + data.position[map[direction].p] = (s.windowSize[map[direction].s] - + s.tooltipSize[map[direction].s]) / 2 + s.scrollPosition[map[direction].p]; } else { - data.position.top = s.scrollPosition.top; - data.tooltipSize = { - height: s.windowSize.h - }; - } - - return data; - }, - - _normalize: function (s, data, config, delegate, map, direction) { - var startPosition = !config.center ? s.eventPosition : { - left: s.elementPosition.left + s.elementSize.w / 2, - top: s.elementPosition.top + s.elementSize.h / 2 - }, - depResult; - - if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 > s.scrollPosition[map[direction].p] && - startPosition[map[direction].p] + s.tooltipSize[map[direction].s] / 2 < s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]) { - data.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2; - } else { - - /*eslint-disable no-lonely-if*/ - if (!checkedPositions[delegate]) { - depResult = positions[delegate].apply(null, arguments); - - if (depResult.hasOwnProperty('className')) { - data = depResult; - } else { - data.tail = {}; - - if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) { - - if (startPosition[map[direction].p] > s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]) { - data.position[map[direction].p] = s.windowSize[map[direction].s] + s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s]; - data.tail[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p]; - } else { - data.position[map[direction].p] = s.scrollPosition[map[direction].p]; - data.tail[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p]; - } - } else { - data.position[map[direction].p] = s.scrollPosition[map[direction].p]; - data.tail[map[direction].p] = s.eventPosition[map[direction].p] - s.windowSize[map[direction].s] / 2; - data.tooltipSize = {}; - data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s]; - } - } - } else { - data.tail = {}; - - if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) { - - if (startPosition[map[direction].p] > s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]) { - data.position[map[direction].p] = s.windowSize[map[direction].s] + s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s]; - data.tail[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p]; - - } else { - data.position[map[direction].p] = s.scrollPosition[map[direction].p]; - data.tail[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p]; - } - } else { - data.position[map[direction].p] = s.scrollPosition[map[direction].p]; - data.tail[map[direction].p] = s.eventPosition[map[direction].p] - s.windowSize[map[direction].s] / 2; - data.tooltipSize = {}; - data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s]; - } - } + data.position[map[direction].p] = s.scrollPosition[map[direction].p]; + data.tooltipSize = {}; + data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s]; } return data; }, /** - * Normalize horizontal position if element can be setted in vertical position + * Normalize horizontal or vertical position. * * @param {Object} s - object with sizes and positions elements * @param {Object} data - current data (position, className, etc) * @param {Object} config - tooltip config + * @param {String} delegate - method name if tooltip can't be setted in current position + * @param {Object} map - mapping for get direction positions + * @param {String} direction - vertical or horizontal * @returns {Object} tooltip data (position, className, etc) */ - _normalizeHorizontal: function (s, data, config, delegate) { + _normalize: function (s, data, config, delegate, map, direction) { var startPosition = !config.center ? s.eventPosition : { left: s.elementPosition.left + s.elementSize.w / 2, - top: s.elementPosition.top + top: s.elementPosition.top + s.elementSize.h / 2 }, depResult; - if (startPosition.left - s.tooltipSize.w / 2 > s.scrollPosition.left && - startPosition.left + s.tooltipSize.w / 2 < s.scrollPosition.left + s.windowSize.w) { - data.position.left = startPosition.left - s.tooltipSize.w / 2; + if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 > + s.scrollPosition[map[direction].p] && startPosition[map[direction].p] + + s.tooltipSize[map[direction].s] / 2 < + s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]) { + data.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2; } else { /*eslint-disable no-lonely-if*/ @@ -304,45 +279,10 @@ define([ if (depResult.hasOwnProperty('className')) { data = depResult; } else { - data.tail = {}; - - if (s.tooltipSize.w < s.windowSize.w) { - - if (startPosition.left > s.windowSize.w / 2 + s.scrollPosition.left) { - data.position.left = s.windowSize.w + s.scrollPosition.left - s.tooltipSize.w; - data.tail.left = startPosition.left - s.tooltipSize.w / 2 - data.position.left; - } else { - data.position.left = s.scrollPosition.left; - data.tail.left = data.position.left - (startPosition.left - s.tooltipSize.w / 2); - } - } else { - data.position.left = s.scrollPosition.left; - data.tail.left = s.eventPosition.left - s.windowSize.w / 2; - data.tooltipSize = { - width: s.windowSize.w - }; - } + data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition); } } else { - data.tail = {}; - - if (s.tooltipSize.w < s.windowSize.w) { - - if (startPosition.left > s.windowSize.w / 2 + s.scrollPosition.left) { - data.position.left = s.windowSize.w + s.scrollPosition.left - s.tooltipSize.w; - data.tail.left = startPosition.left - s.tooltipSize.w / 2 - data.position.left; - - } else { - data.position.left = s.scrollPosition.left; - data.tail.left = data.position.left - (startPosition.left - s.tooltipSize.w / 2); - } - } else { - data.position.left = s.scrollPosition.left; - data.tail.left = s.eventPosition.left - s.windowSize.w / 2; - data.tooltipSize = { - width: s.windowSize.w - }; - } + data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition); } } @@ -350,72 +290,38 @@ define([ }, /** - * Normalize vertical position if element can be setted in horizontal position + * Calc tail position. * * @param {Object} s - object with sizes and positions elements * @param {Object} data - current data (position, className, etc) * @param {Object} config - tooltip config + * @param {String} delegate - method name if tooltip can't be setted in current position + * @param {Object} map - mapping for get direction positions + * @param {String} direction - vertical or horizontal + * @param {Object} startPosition - start position * @returns {Object} tooltip data (position, className, etc) */ - _normalizeVertical: function (s, data, config, delegate) { - var startPosition = !config.center ? s.eventPosition : { - top: s.elementPosition.top + s.elementSize.h / 2, - left: s.elementPosition.left - }, - depResult; + _normalizeTail: function (s, data, config, delegate, map, direction, startPosition) { + data.tail = {}; - if (startPosition.top - s.tooltipSize.h / 2 > s.scrollPosition.top && - startPosition.top + s.tooltipSize.h / 2 < s.scrollPosition.top + s.windowSize.h) { - data.position.top = startPosition.top - s.tooltipSize.h / 2; - } else { + if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) { - /*eslint-disable no-lonely-if*/ - if (!checkedPositions[delegate]) { - depResult = positions[delegate].apply(null, arguments); - - if (depResult.hasOwnProperty('className')) { - data = depResult; - } else { - data.tail = {}; - - if (s.tooltipSize.h < s.windowSize.h) { - - if (startPosition.top > s.windowSize.h / 2 + s.scrollPosition.top) { - data.position.top = s.windowSize.h + s.scrollPosition.top - s.tooltipSize.h; - data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.top; - } else { - data.position.top = s.scrollPosition.top; - data.tail.top = data.position.top - (startPosition.top - s.tooltipSize.h / 2); - } - } else { - data.position.top = s.scrollPosition.top; - data.tail.top = s.eventPosition.top - s.scrollPosition.top - s.windowSize.h / 2; - data.tooltipSize = { - height: s.windowSize.h - }; - } - } + if (startPosition[map[direction].p] > + s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]) { + data.position[map[direction].p] = s.windowSize[map[direction].s] + + s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s]; + data.tail[map[direction].p] = startPosition[map[direction].p] - + s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p]; } else { - data.tail = {}; - - if (s.tooltipSize.h < s.windowSize.h) { - - if (startPosition.top > s.windowSize.h / 2 + s.scrollPosition.top) { - data.position.top = s.windowSize.h + s.scrollPosition.top - s.tooltipSize.h; - data.tail.top = startPosition.top - s.tooltipSize.h / 2 - data.position.top; - } else { - data.position.top = s.scrollPosition.top; - data.tail.top = data.position.top - (startPosition.top - s.tooltipSize.h / 2); - - } - } else { - data.position.top = s.scrollPosition.top; - data.tail.top = s.eventPosition.top - s.scrollPosition.top - s.windowSize.h / 2; - data.tooltipSize = { - height: s.windowSize.h - }; - } + data.position[map[direction].p] = s.scrollPosition[map[direction].p]; + data.tail[map[direction].p] = startPosition[map[direction].p] - + s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p]; } + } else { + data.position[map[direction].p] = s.scrollPosition[map[direction].p]; + data.tail[map[direction].p] = s.eventPosition[map[direction].p] - s.windowSize[map[direction].s] / 2; + data.tooltipSize = {}; + data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s]; } return data; @@ -493,9 +399,7 @@ define([ * @param {String} id - tooltip id */ setPosition: function (tooltipElement, id) { - var config = tooltip.getTooltip(id), - tail, - tailMargin; + var config = tooltip.getTooltip(id); tooltip.sizeData = { windowSize: { @@ -522,26 +426,46 @@ define([ }; _.extend(positionData, positions[config.position](tooltip.sizeData)); - checkedPositions = {}; tooltipElement.css(positionData.position); tooltipElement.addClass(positionData.className); - $('body').css('position', 'relative'); + tooltip._setTooltipSize(positionData, tooltipElement); + tooltip._setTailPosition(positionData, tooltipElement); + checkedPositions = {}; + }, - if (positionData.tooltipSize) { - positionData.tooltipSize.w ? - tooltipElement.css('width', positionData.tooltipSize.w) : - tooltipElement.css('height', positionData.tooltipSize.h); + /** + * Check position data and change tooltip size if needs + * + * @param {Object} data - position data + * @param {Object} tooltipElement - tooltip element + */ + _setTooltipSize: function (data, tooltipElement) { + if (data.tooltipSize) { + data.tooltipSize.w ? + tooltipElement.css('width', data.tooltipSize.w) : + tooltipElement.css('height', data.tooltipSize.h); } + }, - if (positionData.tail) { + /** + * Check position data and set position to tail + * + * @param {Object} data - position data + * @param {Object} tooltipElement - tooltip element + */ + _setTailPosition: function (data, tooltipElement) { + var tail, + tailMargin; + + if (data.tail) { tail = tooltipElement.find('.' + defaults.tailClass); - if (positionData.tail.left) { + if (data.tail.left) { tailMargin = parseInt(tail.css('margin-left'), 10); - tail.css('margin-left', tailMargin + positionData.tail.left); + tail.css('margin-left', tailMargin + data.tail.left); } else { tailMargin = parseInt(tail.css('margin-top'), 10); - tail.css('margin-top', tailMargin + positionData.tail.top); + tail.css('margin-top', tailMargin + data.tail.top); } } }, @@ -578,31 +502,36 @@ define([ * @param {Object} event - current event */ track: function (event) { - var inequality = {}; - - if (positionData.side === 'bottom' || positionData.side === 'top') { - inequality.x = event.pageX - (positionData.position.left + tooltipData.element.outerWidth() / 2); - - if (positionData.position.left + inequality.x + tooltip.sizeData.tooltipSize.w > - tooltip.sizeData.windowSize.w + tooltip.sizeData.scrollPosition.left || - inequality.x + positionData.position.left < tooltip.sizeData.scrollPosition.left) { - - return false; - } - - tooltipData.element[0].style[transformProp] = 'translateX(' + inequality.x + 'px)'; - } else if (positionData.side === 'left' || positionData.side === 'right') { - inequality.y = event.pageY - (positionData.position.top + tooltipData.element.outerHeight() / 2); + var inequality = {}, + map = positions.map, + translate = { + left: 'translateX', + top: 'translateY' + }, + eventPosition = { + left: event.pageX, + top: event.pageY + }, + tooltipSize = { + w: tooltipData.element.outerWidth(), + h: tooltipData.element.outerHeight() + }, + direction = positionData.side === 'bottom' || positionData.side === 'top' ? 'horizontal' : 'vertical'; - if (positionData.position.top + inequality.x + tooltip.sizeData.tooltipSize.h > - tooltip.sizeData.windowSize.h + tooltip.sizeData.scrollPosition.top || - inequality.h + positionData.position.top < tooltip.sizeData.scrollPosition.top) { + inequality[map[direction].p] = eventPosition[map[direction].p] - (positionData.position[map[direction].p] + + tooltipSize[map[direction].s] / 2); - return false; - } + if (positionData.position[map[direction].p] + inequality[map[direction].p] + + tooltip.sizeData.tooltipSize[map[direction].s] > + tooltip.sizeData.windowSize[map[direction].s] + tooltip.sizeData.scrollPosition[map[direction].p] || + inequality[map[direction].p] + positionData.position[map[direction].p] < + tooltip.sizeData.scrollPosition[map[direction].p]) { - tooltipData.element[0].style[transformProp] = 'translateY(' + inequality.y + 'px)'; + return false; } + + tooltipData.element[0].style[transformProp] = translate[map[direction].p] + + '(' + inequality[map[direction].p] + 'px)'; }, /** @@ -699,7 +628,6 @@ define([ tooltipData.showed = false; } - $('body').css('position', 'static'); positionData = {}; tooltipData.timeout = false; tooltip.removeHandlers(); @@ -725,10 +653,16 @@ define([ setTargetData: function (event) { tooltipData.event = event; tooltipData.targetElement = event.type === 'mousemove' ? - event.target : event.currentTarget; + event.target : event.currentTarget; }, - mergingConfig: function (config) { + /** + * Merged user config with defaults configuration + * + * @param {Object} config - user config + * @returns {Object} merged config + */ + processingConfig: function (config) { return _.extend({}, defaults, config); } }; @@ -745,7 +679,7 @@ define([ * @param {Object} bindingCtx - current element binding context */ init: function (elem, valueAccessor, allBindings, viewModel, bindingCtx) { - var config = tooltip.mergingConfig(valueAccessor()), + var config = tooltip.processingConfig(valueAccessor()), $parentScope = config.parentScope ? $(config.parentScope) : $(elem).parent(), tooltipId; @@ -754,14 +688,15 @@ define([ if (isTouchDevice) { config.action = 'click'; } - tooltipId = tooltip.setTooltip(config); if (config.action === 'hover') { - $parentScope.on('mouseenter', config.trigger, tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx)); + $parentScope.on('mouseenter', config.trigger, + tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx)); $parentScope.on('mouseleave', config.trigger, tooltip.checkPreviousTooltip.bind(null, tooltipId)); } else if (config.action === 'click') { - $parentScope.on('click', config.trigger, tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx)); + $parentScope.on('click', config.trigger, + tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx)); } return { From 03f613471a7df7029f4ba954324b2d76887a4ac5 Mon Sep 17 00:00:00 2001 From: Volodymyr Zaets Date: Thu, 3 Mar 2016 11:01:09 +0200 Subject: [PATCH 27/31] MAGETWO-49293: Create tooltip binding - fix codestyle --- .../web/js/lib/knockout/bindings/tooltip.js | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index 12f72e5069c07..bcc7f22acf3b9 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -154,10 +154,12 @@ define([ checkedPositions[side] = true; - if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step > - s.scrollPosition[map[direction].p]) { + if ( + startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step > + s.scrollPosition[map[direction].p] + ) { result.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - - config.step; + config.step; result.className = className; result.side = side; changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical'; @@ -195,8 +197,10 @@ define([ checkedPositions[side] = true; - if (startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step < - s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]) { + if ( + startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step < + s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s] + ) { result.position[map[direction].p] = startPosition[map[direction].p] + config.step; result.className = className; result.side = side; @@ -268,7 +272,8 @@ define([ if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 > s.scrollPosition[map[direction].p] && startPosition[map[direction].p] + s.tooltipSize[map[direction].s] / 2 < - s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]) { + s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s] + ) { data.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2; } else { @@ -306,8 +311,10 @@ define([ if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) { - if (startPosition[map[direction].p] > - s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]) { + if ( + startPosition[map[direction].p] > + s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p] + ) { data.position[map[direction].p] = s.windowSize[map[direction].s] + s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s]; data.tail[map[direction].p] = startPosition[map[direction].p] - From 1aaabd82a11f005fb5a85e4ac02646141c06e2c2 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Thu, 3 Mar 2016 11:25:24 +0200 Subject: [PATCH 28/31] MAGETWO-49315: Stabilize implementation - fix tooltip position on enter key --- .../web/js/lib/knockout/bindings/tooltip.js | 45 +++++++++++++++---- .../css/source/components/_data-tooltip.less | 2 +- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js index bcc7f22acf3b9..ea1b7b9a3a0a1 100644 --- a/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js +++ b/app/code/Magento/Ui/view/base/web/js/lib/knockout/bindings/tooltip.js @@ -2,6 +2,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'jquery', 'ko', @@ -426,10 +427,7 @@ define([ w: tooltipData.trigger.outerWidth() }, elementPosition: tooltipData.trigger.offset(), - eventPosition: { - left: tooltipData.event.originalEvent.pageX, - top: tooltipData.event.originalEvent.pageY - } + eventPosition: this.getEventPosition(tooltipData.event) }; _.extend(positionData, positions[config.position](tooltip.sizeData)); @@ -477,6 +475,25 @@ define([ } }, + /** + * Resolves position for tooltip + * + * @param {Object} event + * @returns {Object} + */ + getEventPosition: function (event) { + var position = { + left: event.originalEvent && event.originalEvent.pageX || 0, + top: event.originalEvent && event.originalEvent.pageY || 0 + }; + + if (position.left === 0 && position.top === 0) { + _.extend(position, event.target.getBoundingClientRect()); + } + + return position; + }, + /** * Close tooltip if action happened outside handler and tooltip element * @@ -698,12 +715,22 @@ define([ tooltipId = tooltip.setTooltip(config); if (config.action === 'hover') { - $parentScope.on('mouseenter', config.trigger, - tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx)); - $parentScope.on('mouseleave', config.trigger, tooltip.checkPreviousTooltip.bind(null, tooltipId)); + $parentScope.on( + 'mouseenter', + config.trigger, + tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx) + ); + $parentScope.on( + 'mouseleave', + config.trigger, + tooltip.checkPreviousTooltip.bind(null, tooltipId) + ); } else if (config.action === 'click') { - $parentScope.on('click', config.trigger, - tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx)); + $parentScope.on( + 'click', + config.trigger, + tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx) + ); } return { diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less index e0bf817712c28..2b5c581c95a6b 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_data-tooltip.less @@ -11,7 +11,7 @@ @data-tooltip__border-color: #007dbd; @data-tooltip__border-width: 1px; @data-tooltip__box-shadow: 2px 2px 8px 0 rgba(0,0,0,0.3); -@data-tooltip__z-index: 999; +@data-tooltip__z-index: @overlay__z-index - 1; @data-tooltip-tail__height: 22px; @data-tooltip-tail__width: @data-tooltip-tail__height; From 86e164f0f03895313210f15fd6299ad672d92af7 Mon Sep 17 00:00:00 2001 From: Oleksandr Miroshnichenko Date: Thu, 3 Mar 2016 15:29:59 +0200 Subject: [PATCH 29/31] MAGETWO-49315: Stabilize implementation - fix switcher style --- .../Ui/view/base/web/templates/grid/view-switcher.html | 5 ++--- .../data-grid/data-grid-header/_data-grid-filters.less | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html b/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html index db1e77f1ecc11..d5335e2f4a38d 100644 --- a/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html +++ b/app/code/Magento/Ui/view/base/web/templates/grid/view-switcher.html @@ -5,8 +5,7 @@ */ --> - -
        +