Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
joshine
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
joshine
Commits
7565e55f
Commit
7565e55f
authored
Sep 24, 2022
by
lmf
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
http://47.99.244.21:9999/root/joshine
parents
dac15acc
e308c5b6
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1428 additions
and
21 deletions
+1428
-21
app/design/frontend/Joshine/breeze/Magento_Theme/layout/breeze_default.xml
+1
-1
app/design/frontend/Joshine/breeze/etc/view.xml
+1
-1
app/design/frontend/Joshine/breeze/web/css/_custom.less
+15
-1
app/design/frontend/Joshine/breeze/web/js/breeze/components/swatch-renderer.js
+1333
-0
lib/web/mage/menu.js
+78
-18
No files found.
app/design/frontend/Joshine/breeze/Magento_Theme/layout/breeze_default.xml
View file @
7565e55f
...
@@ -243,7 +243,7 @@
...
@@ -243,7 +243,7 @@
<item
name=
"sort_order"
xsi:type=
"number"
>
25
</item>
<item
name=
"sort_order"
xsi:type=
"number"
>
25
</item>
<item
name=
"items"
xsi:type=
"array"
>
<item
name=
"items"
xsi:type=
"array"
>
<item
name=
"configurable"
xsi:type=
"string"
>
Swissup_Breeze/js/components/configurable
</item>
<item
name=
"configurable"
xsi:type=
"string"
>
Swissup_Breeze/js/components/configurable
</item>
<item
name=
"Magento_Swatches/js/swatch-renderer"
xsi:type=
"string"
>
Swissup_Breeze/js
/components/swatch-renderer
</item>
<item
name=
"Magento_Swatches/js/swatch-renderer"
xsi:type=
"string"
>
js/breeze
/components/swatch-renderer
</item>
<item
name=
"configurable-configure"
xsi:type=
"string"
>
Swissup_Breeze/js/components/configurable-configure
</item>
<item
name=
"configurable-configure"
xsi:type=
"string"
>
Swissup_Breeze/js/components/configurable-configure
</item>
</item>
</item>
</item>
</item>
...
...
app/design/frontend/Joshine/breeze/etc/view.xml
View file @
7565e55f
...
@@ -97,7 +97,7 @@
...
@@ -97,7 +97,7 @@
<image
id=
"swatch_image"
type=
"swatch_image"
>
<image
id=
"swatch_image"
type=
"swatch_image"
>
<width>
40
</width>
<width>
40
</width>
<height>
5
0
</height>
<height>
4
0
</height>
</image>
</image>
<!-- These lists use category_page_grid fallback. Not need to declare srcset for them -->
<!-- These lists use category_page_grid fallback. Not need to declare srcset for them -->
...
...
app/design/frontend/Joshine/breeze/web/css/_custom.less
View file @
7565e55f
...
@@ -1657,6 +1657,20 @@ button.action.submit.primary {
...
@@ -1657,6 +1657,20 @@ button.action.submit.primary {
}
}
}
}
.swatch-option.color, .swatch-option.text, .swatch-option.image{
width: 40px !important;
height: 40px !important;
}
.block-minicart .block-content>.actions .action.checkout{
background: #000;
}
.cart-container .action.primary,.cart-container .action-primary,.cart-container [type='submit'],.cart-container .pagebuilder-button-primary{
background: #000;
}
.products.products-grid .product.product-item-details .image{
margin: 0 !important;
}
//色块强制大小
//色块强制大小
#product-options-wrapper .swatch-option.image{
#product-options-wrapper .swatch-option.image{
...
@@ -1666,7 +1680,7 @@ button.action.submit.primary {
...
@@ -1666,7 +1680,7 @@ button.action.submit.primary {
}
}
//颜色提示强制关闭
//颜色提示强制关闭
.breeze .field-tooltip-content, .breeze .tooltip.wrapper .tooltip.content, .breeze .mini
cart-wrapper .mage-dropdown-dialog, .breeze .mini
search .search-autocomplete, .breeze .map-popup, .breeze .swatch-option-tooltip {
.breeze .field-tooltip-content, .breeze .tooltip.wrapper .tooltip.content, .breeze .minisearch .search-autocomplete, .breeze .map-popup, .breeze .swatch-option-tooltip {
display: none !important;
display: none !important;
}
}
...
...
app/design/frontend/Joshine/breeze/web/js/breeze/components/swatch-renderer.js
0 → 100644
View file @
7565e55f
/* global _ */
(
function
()
{
'use strict'
;
$
.
widget
(
'SwatchRendererTooltip'
,
{
options
:
{
delay
:
200
,
//how much ms before tooltip to show
tooltipClass
:
'swatch-option-tooltip'
//configurable, but remember about css
},
/** [_init description] */
_init
:
function
()
{
var
$widget
=
this
,
$this
=
this
.
element
,
$element
=
$
(
'.'
+
$widget
.
options
.
tooltipClass
),
timer
,
type
=
parseInt
(
$this
.
data
(
'option-type'
),
10
),
label
=
$this
.
data
(
'option-label'
),
thumb
=
$this
.
data
(
'option-tooltip-thumb'
),
value
=
$this
.
data
(
'option-tooltip-value'
),
width
=
$this
.
data
(
'thumb-width'
),
height
=
$this
.
data
(
'thumb-height'
),
$image
,
$title
,
$corner
;
if
(
!
$element
.
length
)
{
$element
=
$
(
'<div class="'
+
$widget
.
options
.
tooltipClass
+
'"><div class="image"></div><div class="title"></div><div class="corner"></div></div>'
);
$
(
'body'
).
append
(
$element
);
}
$image
=
$element
.
find
(
'.image'
);
$title
=
$element
.
find
(
'.title'
);
$corner
=
$element
.
find
(
'.corner'
);
$this
.
hover
(
function
()
{
if
(
$this
.
hasClass
(
'disabled'
))
{
return
;
}
timer
=
setTimeout
(
function
()
{
var
leftOpt
=
null
,
leftCorner
=
0
,
left
,
$window
;
if
(
type
===
2
)
{
// Image
$image
.
css
({
'background'
:
'url("'
+
thumb
+
'") no-repeat center'
,
//Background case
'background-size'
:
'initial'
,
'width'
:
width
+
'px'
,
'height'
:
height
+
'px'
});
$image
.
show
();
}
else
if
(
type
===
1
)
{
// Color
$image
.
css
({
background
:
value
});
$image
.
show
();
}
else
if
(
type
===
0
||
type
===
3
)
{
// Default
$image
.
hide
();
}
$title
.
text
(
label
);
$element
.
show
();
leftOpt
=
$this
.
offset
().
left
;
left
=
leftOpt
+
$this
.
width
()
/
2
-
$element
.
width
()
/
2
;
$window
=
$
(
window
);
// the numbers (5 and 5) is magick constants for offset from left or right page
if
(
left
<
0
)
{
left
=
5
;
}
else
if
(
left
+
$element
.
width
()
>
$window
.
width
())
{
left
=
$window
.
width
()
-
$element
.
width
()
-
5
;
}
// the numbers (6, 3 and 18) is magick constants for offset tooltip
leftCorner
=
0
;
if
(
$element
.
width
()
<
$this
.
width
())
{
leftCorner
=
$element
.
width
()
/
2
-
3
;
}
else
{
leftCorner
=
(
leftOpt
>
left
?
leftOpt
-
left
:
left
-
leftOpt
)
+
$this
.
width
()
/
2
-
6
;
}
$corner
.
css
({
left
:
leftCorner
});
$element
.
css
({
left
:
left
,
top
:
$this
.
offset
().
top
-
$element
.
height
()
-
$corner
.
height
()
-
18
}).
show
();
},
$widget
.
options
.
delay
);
},
function
()
{
$element
.
hide
();
clearTimeout
(
timer
);
});
$
(
document
).
on
(
'tap.SwatchRendererTooltip'
,
function
()
{
$element
.
hide
();
clearTimeout
(
timer
);
});
$this
.
on
(
'tap'
,
function
(
event
)
{
event
.
stopPropagation
();
});
},
destroy
:
function
()
{
$
(
document
).
off
(
'tap.SwatchRendererTooltip'
);
this
.
_super
();
}
});
$
.
widget
(
'SwatchRenderer'
,
{
component
:
'Magento_Swatches/js/swatch-renderer'
,
options
:
{
classes
:
{
attributeClass
:
'swatch-attribute'
,
attributeLabelClass
:
'swatch-attribute-label'
,
attributeSelectedOptionLabelClass
:
'swatch-attribute-selected-option'
,
attributeOptionsWrapper
:
'swatch-attribute-options'
,
attributeInput
:
'swatch-input'
,
optionClass
:
'swatch-option'
,
selectClass
:
'swatch-select'
,
moreButton
:
'swatch-more'
,
loader
:
'swatch-option-loading'
},
// option's json config
jsonConfig
:
{},
// swatch's json config
jsonSwatchConfig
:
{},
// selector of parental block of prices and swatches (need to know where to seek for price block)
selectorProduct
:
'.product-info-main'
,
// selector of price wrapper (need to know where set price)
selectorProductPrice
:
'[data-role=priceBox]'
,
//selector of product images gallery wrapper
mediaGallerySelector
:
'[data-gallery-role=gallery-placeholder]'
,
// selector of category product tile wrapper
selectorProductTile
:
'.product-item'
,
// number of controls to show (false or zero = show all)
numberToShow
:
false
,
// show only swatch controls
onlySwatches
:
false
,
// enable label for control
enableControlLabel
:
true
,
// control label id
controlLabelId
:
''
,
// text for more button
moreButtonText
:
$
.
__
(
'More'
),
// Callback url for media
mediaCallback
:
''
,
// Local media cache
mediaCache
:
{},
// Cache for BaseProduct images. Needed when option unset
mediaGalleryInitial
:
[{}],
// Use ajax to get image data
useAjax
:
false
,
/**
* Defines the mechanism of how images of a gallery should be
* updated when user switches between configurations of a product.
*
* As for now value of this option can be either 'replace' or 'prepend'.
*
* @type {String}
*/
gallerySwitchStrategy
:
'replace'
,
// whether swatches are rendered in product list or on product page
inProductList
:
false
,
// sly-old-price block selector
slyOldPriceSelector
:
'.sly-old-price'
,
// tier prise selectors start
tierPriceTemplateSelector
:
'#tier-prices-template'
,
tierPriceBlockSelector
:
'[data-role="tier-price-block"]'
,
tierPriceTemplate
:
''
,
// tier prise selectors end
// A price label selector
normalPriceLabelSelector
:
'.product-info-main .normal-price .price-label'
},
/**
* Get chosen product
*
* @returns int|null
*/
getProduct
:
function
()
{
var
products
=
this
.
_CalcProducts
();
return
_
.
isArray
(
products
)
?
products
[
0
]
:
null
;
},
/**
* Get chosen product id
*
* @returns int|null
*/
getProductId
:
function
()
{
var
products
=
this
.
_CalcProducts
();
return
_
.
isArray
(
products
)
&&
products
.
length
===
1
?
products
[
0
]
:
null
;
},
/**
* @private
*/
_init
:
function
()
{
if
(
$
(
this
.
element
).
attr
(
'data-rendered'
))
{
return
;
}
this
.
_markup
=
this
.
element
.
html
();
$
(
this
.
element
).
attr
(
'data-rendered'
,
true
);
if
(
_
.
isEmpty
(
this
.
options
.
jsonConfig
.
images
))
{
this
.
options
.
useAjax
=
true
;
this
.
_debouncedLoadProductMedia
=
_
.
debounce
(
this
.
_LoadProductMedia
.
bind
(
this
),
500
);
}
this
.
options
.
tierPriceTemplate
=
$
(
this
.
options
.
tierPriceTemplateSelector
).
html
();
if
(
this
.
options
.
jsonConfig
!==
''
&&
this
.
options
.
jsonSwatchConfig
!==
''
)
{
this
.
options
.
jsonConfig
.
mappedAttributes
=
_
.
clone
(
this
.
options
.
jsonConfig
.
attributes
);
this
.
_sortAttributes
();
this
.
_RenderControls
();
this
.
_setPreSelectedGallery
();
$
(
this
.
element
).
trigger
(
'swatch.initialized'
);
}
else
{
console
.
log
(
'SwatchRenderer: No input data received'
);
}
},
destroy
:
function
()
{
$
(
this
.
element
).
removeAttr
(
'data-rendered'
).
html
(
this
.
_markup
);
this
.
_super
();
},
/**
* @private
*/
_sortAttributes
:
function
()
{
this
.
options
.
jsonConfig
.
attributes
=
_
.
sortBy
(
this
.
options
.
jsonConfig
.
attributes
,
function
(
attribute
)
{
return
parseInt
(
attribute
.
position
,
10
);
});
},
/**
* @private
*/
_create
:
function
()
{
var
options
=
this
.
options
,
gallery
=
$
(
'.column.main'
).
find
(
'[data-gallery-role="gallery-placeholder"]'
),
productData
=
this
.
_determineProductData
(),
$main
=
productData
.
isInProductView
?
this
.
element
.
parents
(
'.column.main'
)
:
this
.
element
.
parents
(
'.product-item-info'
);
if
(
productData
.
isInProductView
)
{
gallery
.
gallery
(
'instance'
)
?
this
.
_onGalleryLoaded
(
gallery
)
:
gallery
.
on
(
'gallery:loaded'
,
this
.
_onGalleryLoaded
.
bind
(
this
,
gallery
));
}
else
{
options
.
mediaGalleryInitial
=
[{
'img'
:
$main
.
find
(
'.product-image-photo'
).
attr
(
'src'
)
}];
}
this
.
productForm
=
this
.
element
.
parents
(
this
.
options
.
selectorProductTile
).
find
(
'form'
).
first
(
'first'
);
this
.
inProductList
=
this
.
productForm
.
length
>
0
;
},
/**
* Determine product id and related data
*
* @returns {{productId: *, isInProductView: bool}}
* @private
*/
_determineProductData
:
function
()
{
// Check if product is in a list of products.
var
productId
,
isInProductView
=
false
;
productId
=
this
.
element
.
parents
(
'.product-item-info'
)
.
find
(
'.price-box.price-final_price'
)
.
attr
(
'data-product-id'
);
if
(
!
productId
)
{
// Check individual product.
productId
=
$
(
'[name=product]'
).
val
();
isInProductView
=
productId
>
0
;
}
return
{
productId
:
productId
,
isInProductView
:
isInProductView
};
},
/**
* Render controls
*
* @private
*/
_RenderControls
:
function
()
{
var
$widget
=
this
,
container
=
this
.
element
,
classes
=
this
.
options
.
classes
,
chooseText
=
this
.
options
.
jsonConfig
.
chooseText
,
showTooltip
=
this
.
options
.
showTooltip
;
$widget
.
optionsMap
=
{};
$
.
each
(
this
.
options
.
jsonConfig
.
attributes
,
function
()
{
var
item
=
this
,
controlLabelId
=
'option-label-'
+
item
.
code
+
'-'
+
item
.
id
,
options
=
$widget
.
_RenderSwatchOptions
(
item
,
controlLabelId
),
select
=
$widget
.
_RenderSwatchSelect
(
item
,
chooseText
),
input
=
$widget
.
_RenderFormInput
(
item
),
listLabel
=
''
,
label
=
''
;
// Show only swatch controls
if
(
$widget
.
options
.
onlySwatches
&&
!
$widget
.
options
.
jsonSwatchConfig
.
hasOwnProperty
(
item
.
id
))
{
return
;
}
if
(
$widget
.
options
.
enableControlLabel
)
{
label
+=
'<span id="'
+
controlLabelId
+
'" class="'
+
classes
.
attributeLabelClass
+
'">'
+
$
(
'<i></i>'
).
text
(
item
.
label
).
html
()
+
'</span>'
+
'<span class="'
+
classes
.
attributeSelectedOptionLabelClass
+
'"></span>'
;
}
if
(
$widget
.
inProductList
)
{
$widget
.
productForm
.
append
(
input
);
input
=
''
;
listLabel
=
'aria-label="'
+
$
(
'<i></i>'
).
text
(
item
.
label
).
html
()
+
'"'
;
}
else
{
listLabel
=
'aria-labelledby="'
+
controlLabelId
+
'"'
;
}
// Create new control
container
.
append
(
'<div class="'
+
classes
.
attributeClass
+
' '
+
item
.
code
+
'" '
+
'data-attribute-code="'
+
item
.
code
+
'" '
+
'data-attribute-id="'
+
item
.
id
+
'">'
+
label
+
'<div aria-activedescendant="" '
+
'aria-invalid="false" '
+
'aria-required="true" '
+
'role="listbox" '
+
listLabel
+
'class="'
+
classes
.
attributeOptionsWrapper
+
' clearfix">'
+
options
+
select
+
'</div>'
+
input
+
'</div>'
);
$widget
.
optionsMap
[
item
.
id
]
=
{};
// Aggregate options array to hash (key => value)
$
.
each
(
item
.
options
,
function
()
{
if
(
this
.
products
.
length
>
0
)
{
$widget
.
optionsMap
[
item
.
id
][
this
.
id
]
=
{
price
:
parseInt
(
$widget
.
options
.
jsonConfig
.
optionPrices
[
this
.
products
[
0
]].
finalPrice
.
amount
,
10
),
products
:
this
.
products
};
}
});
});
if
(
showTooltip
===
1
)
{
// Connect Tooltip
container
.
find
(
'[data-option-type="1"], [data-option-type="2"],'
+
' [data-option-type="0"], [data-option-type="3"]'
)
.
SwatchRendererTooltip
();
}
// Hide all elements below more button
$
(
'.'
+
classes
.
moreButton
).
nextAll
().
hide
();
// Handle events like click or change
$widget
.
_EventListener
();
// Rewind options
$widget
.
_Rewind
(
container
);
// timout is used to wait till price-box widget will be mounted
setTimeout
(
function
()
{
$widget
.
_EmulateSelected
(
$
.
parseQuery
());
$widget
.
_EmulateSelected
(
$widget
.
_getSelectedAttributes
());
},
80
);
},
/**
* Render swatch options by part of config
*
* @param {Object} config
* @param {String} controlId
* @returns {String}
* @private
*/
_RenderSwatchOptions
:
function
(
config
,
controlId
)
{
var
optionConfig
=
this
.
options
.
jsonSwatchConfig
[
config
.
id
],
optionClass
=
this
.
options
.
classes
.
optionClass
,
sizeConfig
=
this
.
options
.
jsonSwatchImageSizeConfig
,
moreLimit
=
parseInt
(
this
.
options
.
numberToShow
,
10
),
moreClass
=
this
.
options
.
classes
.
moreButton
,
moreText
=
this
.
options
.
moreButtonText
,
countAttributes
=
0
,
html
=
''
;
if
(
!
this
.
options
.
jsonSwatchConfig
.
hasOwnProperty
(
config
.
id
))
{
return
''
;
}
$
.
each
(
config
.
options
,
function
(
index
)
{
var
id
,
type
,
value
,
thumb
,
label
,
width
,
height
,
attr
,
swatchImageWidth
,
swatchImageHeight
;
if
(
!
optionConfig
.
hasOwnProperty
(
this
.
id
))
{
return
''
;
}
// Add more button
if
(
moreLimit
===
countAttributes
++
)
{
html
+=
'<a href="#" class="'
+
moreClass
+
'"><span>'
+
moreText
+
'</span></a>'
;
}
id
=
this
.
id
;
type
=
parseInt
(
optionConfig
[
id
].
type
,
10
);
value
=
optionConfig
[
id
].
hasOwnProperty
(
'value'
)
?
$
(
'<i></i>'
).
text
(
optionConfig
[
id
].
value
).
html
()
:
''
;
thumb
=
optionConfig
[
id
].
hasOwnProperty
(
'thumb'
)
?
optionConfig
[
id
].
thumb
:
''
;
width
=
_
.
has
(
sizeConfig
,
'swatchThumb'
)
?
sizeConfig
.
swatchThumb
.
width
:
110
;
height
=
_
.
has
(
sizeConfig
,
'swatchThumb'
)
?
sizeConfig
.
swatchThumb
.
height
:
90
;
label
=
this
.
label
?
$
(
'<i></i>'
).
text
(
this
.
label
).
html
()
:
''
;
attr
=
// ' id="' + controlId + '-item-' + id + '"' +
' index="'
+
index
+
'"'
+
' aria-checked="false"'
+
' aria-describedby="'
+
controlId
+
'"'
+
' tabindex="0"'
+
' data-option-type="'
+
type
+
'"'
+
' data-option-id="'
+
id
+
'"'
+
' data-option-label="'
+
label
+
'"'
+
' aria-label="'
+
label
+
'"'
+
' role="option"'
+
' data-thumb-width="'
+
width
+
'"'
+
' data-thumb-height="'
+
height
+
'"'
;
attr
+=
thumb
!==
''
?
' data-option-tooltip-thumb="'
+
thumb
+
'"'
:
''
;
attr
+=
value
!==
''
?
' data-option-tooltip-value="'
+
value
+
'"'
:
''
;
swatchImageWidth
=
_
.
has
(
sizeConfig
,
'swatchImage'
)
?
sizeConfig
.
swatchImage
.
width
:
30
;
swatchImageHeight
=
_
.
has
(
sizeConfig
,
'swatchImage'
)
?
sizeConfig
.
swatchImage
.
height
:
20
;
if
(
!
this
.
hasOwnProperty
(
'products'
)
||
this
.
products
.
length
<=
0
)
{
attr
+=
' data-option-empty="true"'
;
}
if
(
type
===
0
)
{
// Text
html
+=
'<div class="'
+
optionClass
+
' text" '
+
attr
+
'>'
+
(
value
?
value
:
label
)
+
'</div>'
;
}
else
if
(
type
===
1
)
{
// Color
html
+=
'<div class="'
+
optionClass
+
' color" '
+
attr
+
' style="background: '
+
value
+
' no-repeat center; background-size: initial;">'
+
''
+
'</div>'
;
}
else
if
(
type
===
2
)
{
// Image
html
+=
'<div class="'
+
optionClass
+
' image" '
+
attr
+
' style="background: url('
+
value
+
') no-repeat center; background-size: initial;width:'
+
swatchImageWidth
+
'px; height:'
+
swatchImageHeight
+
'px">'
+
''
+
'</div>'
;
}
else
if
(
type
===
3
)
{
// Clear
html
+=
'<div class="'
+
optionClass
+
'" '
+
attr
+
'></div>'
;
}
else
{
// Default
html
+=
'<div class="'
+
optionClass
+
'" '
+
attr
+
'>'
+
label
+
'</div>'
;
}
});
return
html
;
},
/**
* Render select by part of config
*
* @param {Object} config
* @param {String} chooseText
* @returns {String}
* @private
*/
_RenderSwatchSelect
:
function
(
config
,
chooseText
)
{
var
html
;
if
(
this
.
options
.
jsonSwatchConfig
.
hasOwnProperty
(
config
.
id
))
{
return
''
;
}
html
=
'<select class="'
+
this
.
options
.
classes
.
selectClass
+
' '
+
config
.
code
+
'">'
+
'<option value="0" data-option-id="0">'
+
chooseText
+
'</option>'
;
$
.
each
(
config
.
options
,
function
()
{
var
label
=
this
.
label
,
attr
=
' value="'
+
this
.
id
+
'" data-option-id="'
+
this
.
id
+
'"'
;
if
(
!
this
.
hasOwnProperty
(
'products'
)
||
this
.
products
.
length
<=
0
)
{
attr
+=
' data-option-empty="true"'
;
}
html
+=
'<option '
+
attr
+
'>'
+
label
+
'</option>'
;
});
html
+=
'</select>'
;
return
html
;
},
/**
* Input for submit form.
* This control shouldn't have "type=hidden", "display: none" for validation work :(
*
* @param {Object} config
* @private
*/
_RenderFormInput
:
function
(
config
)
{
return
'<input class="'
+
this
.
options
.
classes
.
attributeInput
+
' super-attribute-select" '
+
'name="super_attribute['
+
config
.
id
+
']" '
+
'type="text" '
+
'value="" '
+
'data-selector="super_attribute['
+
config
.
id
+
']" '
+
'data-validate="{required: true}" '
+
'aria-required="true" '
+
'aria-invalid="false">'
;
},
/**
* Event listener
*
* @private
*/
_EventListener
:
function
()
{
var
$widget
=
this
,
options
=
this
.
options
.
classes
,
target
;
$widget
.
element
.
on
(
'click'
,
'.'
+
options
.
optionClass
,
function
()
{
return
$widget
.
_OnClick
(
$
(
this
),
$widget
);
});
$widget
.
element
.
on
(
'change'
,
'.'
+
options
.
selectClass
,
function
()
{
return
$widget
.
_OnChange
(
$
(
this
),
$widget
);
});
$widget
.
element
.
on
(
'click'
,
'.'
+
options
.
moreButton
,
function
(
e
)
{
e
.
preventDefault
();
return
$widget
.
_OnMoreClick
(
$
(
this
));
});
$widget
.
element
.
on
(
'keydown'
,
function
(
e
)
{
if
(
e
.
which
===
13
)
{
target
=
$
(
e
.
target
);
if
(
target
.
is
(
'.'
+
options
.
optionClass
))
{
return
$widget
.
_OnClick
(
target
,
$widget
);
}
else
if
(
target
.
is
(
'.'
+
options
.
selectClass
))
{
return
$widget
.
_OnChange
(
target
,
$widget
);
}
else
if
(
target
.
is
(
'.'
+
options
.
moreButton
))
{
e
.
preventDefault
();
return
$widget
.
_OnMoreClick
(
target
);
}
}
});
},
/**
* Load media gallery using ajax or json config.
*
* @private
*/
_loadMedia
:
function
()
{
var
$main
=
this
.
inProductList
?
this
.
element
.
parents
(
'.product-item-info'
)
:
this
.
element
.
parents
(
'.column.main'
),
images
;
if
(
this
.
options
.
useAjax
)
{
this
.
_debouncedLoadProductMedia
();
}
else
{
images
=
this
.
options
.
jsonConfig
.
images
[
this
.
getProduct
()];
if
(
!
images
)
{
images
=
this
.
options
.
mediaGalleryInitial
;
}
this
.
updateBaseImage
(
this
.
_sortImages
(
images
),
$main
,
!
this
.
inProductList
);
}
},
/**
* Sorting images array
*
* @private
*/
_sortImages
:
function
(
images
)
{
return
_
.
sortBy
(
images
,
function
(
image
)
{
return
parseInt
(
image
.
position
,
10
);
});
},
/**
* Event for swatch options
*
* @param {Object} $this
* @param {Object} $widget
* @private
*/
_OnClick
:
function
(
$this
,
$widget
)
{
var
$parent
=
$this
.
parents
(
'.'
+
$widget
.
options
.
classes
.
attributeClass
),
$wrapper
=
$this
.
parents
(
'.'
+
$widget
.
options
.
classes
.
attributeOptionsWrapper
),
$label
=
$parent
.
find
(
'.'
+
$widget
.
options
.
classes
.
attributeSelectedOptionLabelClass
),
attributeId
=
$parent
.
data
(
'attribute-id'
),
$input
=
$parent
.
find
(
'.'
+
$widget
.
options
.
classes
.
attributeInput
),
checkAdditionalData
=
JSON
.
parse
(
this
.
options
.
jsonSwatchConfig
[
attributeId
][
'additional_data'
]),
$priceBox
=
$widget
.
_getProductWrapper
().
find
(
this
.
options
.
selectorProductPrice
);
if
(
$widget
.
inProductList
)
{
$input
=
$widget
.
productForm
.
find
(
'.'
+
$widget
.
options
.
classes
.
attributeInput
+
'[name="super_attribute['
+
attributeId
+
']"]'
);
}
if
(
$this
.
hasClass
(
'disabled'
))
{
return
;
}
if
(
$this
.
hasClass
(
'selected'
))
{
$parent
.
removeAttr
(
'data-option-selected'
).
find
(
'.selected'
).
removeClass
(
'selected'
);
$input
.
val
(
''
);
$label
.
text
(
''
);
$this
.
attr
(
'aria-checked'
,
false
);
}
else
{
$parent
.
attr
(
'data-option-selected'
,
$this
.
data
(
'option-id'
)).
find
(
'.selected'
).
removeClass
(
'selected'
);
$label
.
text
(
$this
.
data
(
'option-label'
));
$input
.
val
(
$this
.
data
(
'option-id'
));
$input
.
attr
(
'data-attr-name'
,
this
.
_getAttributeCodeById
(
attributeId
));
$this
.
addClass
(
'selected'
);
$widget
.
_toggleCheckedAttributes
(
$this
,
$wrapper
);
}
$widget
.
_Rebuild
();
if
(
$priceBox
.
priceBox
(
'instance'
))
{
$widget
.
_UpdatePrice
();
}
$
(
document
).
trigger
(
'updateMsrpPriceBlock'
,
[
this
.
_getSelectedOptionPriceIndex
(),
$widget
.
options
.
jsonConfig
.
optionPrices
,
$priceBox
]);
if
(
parseInt
(
checkAdditionalData
[
'update_product_preview_image'
],
10
)
===
1
)
{
$widget
.
_loadMedia
();
}
$input
.
trigger
(
'change'
);
},
/**
* Get selected option price index
*
* @return {String|undefined}
* @private
*/
_getSelectedOptionPriceIndex
:
function
()
{
var
allowedProduct
=
this
.
_getAllowedProductWithMinPrice
(
this
.
_CalcProducts
());
if
(
_
.
isEmpty
(
allowedProduct
))
{
return
undefined
;
}
return
allowedProduct
;
},
/**
* Get human readable attribute code (eg. size, color) by it ID from configuration
*
* @param {Number} attributeId
* @returns {*}
* @private
*/
_getAttributeCodeById
:
function
(
attributeId
)
{
var
attribute
=
this
.
options
.
jsonConfig
.
mappedAttributes
[
attributeId
];
return
attribute
?
attribute
.
code
:
attributeId
;
},
/**
* Toggle accessibility attributes
*
* @param {Object} $this
* @param {Object} $wrapper
* @private
*/
_toggleCheckedAttributes
:
function
(
$this
,
$wrapper
)
{
$wrapper
.
attr
(
'aria-activedescendant'
,
$this
.
attr
(
'id'
))
.
find
(
'.'
+
this
.
options
.
classes
.
optionClass
).
attr
(
'aria-checked'
,
false
);
$this
.
attr
(
'aria-checked'
,
true
);
},
/**
* Event for select
*
* @param {Object} $this
* @param {Object} $widget
* @private
*/
_OnChange
:
function
(
$this
,
$widget
)
{
var
$parent
=
$this
.
parents
(
'.'
+
$widget
.
options
.
classes
.
attributeClass
),
attributeId
=
$parent
.
data
(
'attribute-id'
),
$input
=
$parent
.
find
(
'.'
+
$widget
.
options
.
classes
.
attributeInput
);
if
(
$widget
.
productForm
.
length
>
0
)
{
$input
=
$widget
.
productForm
.
find
(
'.'
+
$widget
.
options
.
classes
.
attributeInput
+
'[name="super_attribute['
+
attributeId
+
']"]'
);
}
if
(
$this
.
val
()
>
0
)
{
$parent
.
attr
(
'data-option-selected'
,
$this
.
val
());
$input
.
val
(
$this
.
val
());
}
else
{
$parent
.
removeAttr
(
'data-option-selected'
);
$input
.
val
(
''
);
}
$widget
.
_Rebuild
();
$widget
.
_UpdatePrice
();
$widget
.
_loadMedia
();
$input
.
trigger
(
'change'
);
},
/**
* Event for more switcher
*
* @param {Object} $this
* @private
*/
_OnMoreClick
:
function
(
$this
)
{
$this
.
nextAll
().
show
();
$this
.
blur
().
remove
();
},
/**
* Rewind options for controls
*
* @private
*/
_Rewind
:
function
(
controls
)
{
controls
.
find
(
'div[data-option-id], option[data-option-id]'
).
removeClass
(
'disabled'
).
removeAttr
(
'disabled'
);
controls
.
find
(
'div[data-option-empty], option[data-option-empty]'
)
.
attr
(
'disabled'
,
true
)
.
addClass
(
'disabled'
)
.
attr
(
'tabindex'
,
'-1'
);
},
/**
* Rebuild container
*
* @private
*/
_Rebuild
:
function
()
{
var
$widget
=
this
,
controls
=
$widget
.
element
.
find
(
'.'
+
$widget
.
options
.
classes
.
attributeClass
+
'[data-attribute-id]'
),
selected
=
controls
.
filter
(
'[data-option-selected]'
);
// Enable all options
$widget
.
_Rewind
(
controls
);
// done if nothing selected
if
(
selected
.
length
<=
0
)
{
return
;
}
// Disable not available options
controls
.
each
(
function
()
{
var
$this
=
$
(
this
),
id
=
$this
.
data
(
'attribute-id'
),
products
=
$widget
.
_CalcProducts
(
id
);
if
(
selected
.
length
===
1
&&
selected
.
first
().
data
(
'attribute-id'
)
===
id
)
{
return
;
}
$this
.
find
(
'[data-option-id]'
).
each
(
function
()
{
var
$element
=
$
(
this
),
option
=
$element
.
data
(
'option-id'
);
if
(
!
$widget
.
optionsMap
.
hasOwnProperty
(
id
)
||
!
$widget
.
optionsMap
[
id
].
hasOwnProperty
(
option
)
||
$element
.
hasClass
(
'selected'
)
||
$element
.
is
(
':selected'
)
)
{
return
;
}
if
(
_
.
intersection
(
products
,
$widget
.
optionsMap
[
id
][
option
].
products
).
length
<=
0
)
{
$element
.
attr
(
'disabled'
,
true
).
addClass
(
'disabled'
);
}
});
});
},
/**
* Get selected product list
*
* @returns {Array}
* @private
*/
_CalcProducts
:
function
(
$skipAttributeId
)
{
var
$widget
=
this
,
selectedOptions
=
'.'
+
$widget
.
options
.
classes
.
attributeClass
+
'[data-option-selected]'
,
products
=
[];
// Generate intersection of products
$widget
.
element
.
find
(
selectedOptions
).
each
(
function
()
{
var
id
=
$
(
this
).
data
(
'attribute-id'
),
option
=
$
(
this
).
attr
(
'data-option-selected'
);
if
(
$skipAttributeId
!==
undefined
&&
$skipAttributeId
===
id
)
{
return
;
}
if
(
!
$widget
.
optionsMap
.
hasOwnProperty
(
id
)
||
!
$widget
.
optionsMap
[
id
].
hasOwnProperty
(
option
))
{
return
;
}
if
(
products
.
length
===
0
)
{
products
=
$widget
.
optionsMap
[
id
][
option
].
products
;
}
else
{
products
=
_
.
intersection
(
products
,
$widget
.
optionsMap
[
id
][
option
].
products
);
}
});
return
products
;
},
/**
* Update total price
*
* @private
*/
_UpdatePrice
:
function
()
{
var
$widget
=
this
,
$product
=
$widget
.
_getProductWrapper
(),
$productPrice
=
$product
.
find
(
this
.
options
.
selectorProductPrice
),
result
=
$widget
.
_getNewPrices
(),
tierPriceHtml
,
isShow
;
$productPrice
.
trigger
(
'updatePrice'
,
{
'prices'
:
$widget
.
_getPrices
(
result
,
$productPrice
.
priceBox
(
'option'
).
prices
)
}
);
isShow
=
typeof
result
!=
'undefined'
&&
result
.
oldPrice
.
amount
!==
result
.
finalPrice
.
amount
;
$productPrice
.
find
(
'span'
).
first
().
toggleClass
(
'special-price'
,
isShow
);
$product
.
find
(
this
.
options
.
slyOldPriceSelector
)[
isShow
?
'show'
:
'hide'
]();
if
(
typeof
result
!=
'undefined'
&&
result
.
tierPrices
&&
result
.
tierPrices
.
length
)
{
if
(
this
.
options
.
tierPriceTemplate
)
{
tierPriceHtml
=
_
.
template
(
this
.
options
.
tierPriceTemplate
)({
'tierPrices'
:
result
.
tierPrices
,
'$t'
:
$
.
__
,
'currencyFormat'
:
this
.
options
.
jsonConfig
.
currencyFormat
,
'priceUtils'
:
$
.
catalog
.
priceUtils
});
$
(
this
.
options
.
tierPriceBlockSelector
).
html
(
tierPriceHtml
).
show
();
}
}
else
{
$
(
this
.
options
.
tierPriceBlockSelector
).
hide
();
}
$
(
this
.
options
.
normalPriceLabelSelector
).
hide
();
_
.
each
(
$
(
'.'
+
this
.
options
.
classes
.
attributeOptionsWrapper
),
function
(
attribute
)
{
if
(
$
(
attribute
).
find
(
'.'
+
this
.
options
.
classes
.
optionClass
+
'.selected'
).
length
===
0
)
{
if
(
$
(
attribute
).
find
(
'.'
+
this
.
options
.
classes
.
selectClass
).
length
>
0
)
{
_
.
each
(
$
(
attribute
).
find
(
'.'
+
this
.
options
.
classes
.
selectClass
),
function
(
dropdown
)
{
if
(
$
(
dropdown
).
val
()
===
'0'
)
{
$
(
this
.
options
.
normalPriceLabelSelector
).
show
();
}
}.
bind
(
this
));
}
else
{
$
(
this
.
options
.
normalPriceLabelSelector
).
show
();
}
}
}.
bind
(
this
));
},
/** [_getProductWrapper description] */
_getProductWrapper
:
function
()
{
var
selector
=
this
.
options
.
selectorProduct
.
replace
(
'.product-item-details'
,
'.product-item-info'
),
wrapper
=
this
.
element
.
closest
(
selector
);
if
(
!
wrapper
.
length
)
{
wrapper
=
this
.
element
.
closest
(
'.column.main'
).
find
(
selector
);
}
return
wrapper
;
},
/**
* Get new prices for selected options
*
* @returns {*}
* @private
*/
_getNewPrices
:
function
()
{
var
$widget
=
this
,
newPrices
=
$widget
.
options
.
jsonConfig
.
prices
,
allowedProduct
=
this
.
_getAllowedProductWithMinPrice
(
this
.
_CalcProducts
());
if
(
!
_
.
isEmpty
(
allowedProduct
))
{
newPrices
=
this
.
options
.
jsonConfig
.
optionPrices
[
allowedProduct
];
}
return
newPrices
;
},
/**
* Get prices
*
* @param {Object} newPrices
* @param {Object} displayPrices
* @returns {*}
* @private
*/
_getPrices
:
function
(
newPrices
,
displayPrices
)
{
var
$widget
=
this
;
if
(
_
.
isEmpty
(
newPrices
))
{
newPrices
=
$widget
.
_getNewPrices
();
}
_
.
each
(
displayPrices
,
function
(
price
,
code
)
{
if
(
newPrices
[
code
])
{
displayPrices
[
code
].
amount
=
newPrices
[
code
].
amount
-
displayPrices
[
code
].
amount
;
}
});
return
displayPrices
;
},
/**
* Get product with minimum price from selected options.
*
* @param {Array} allowedProducts
* @returns {String}
* @private
*/
_getAllowedProductWithMinPrice
:
function
(
allowedProducts
)
{
var
optionPrices
=
this
.
options
.
jsonConfig
.
optionPrices
,
product
=
{},
optionFinalPrice
,
optionMinPrice
;
_
.
each
(
allowedProducts
,
function
(
allowedProduct
)
{
optionFinalPrice
=
parseFloat
(
optionPrices
[
allowedProduct
].
finalPrice
.
amount
);
if
(
_
.
isEmpty
(
product
)
||
optionFinalPrice
<
optionMinPrice
)
{
optionMinPrice
=
optionFinalPrice
;
product
=
allowedProduct
;
}
},
this
);
return
product
;
},
/**
* Gets all product media and change current to the needed one
*
* @private
*/
_LoadProductMedia
:
function
()
{
var
$widget
=
this
,
$this
=
$widget
.
element
,
productData
=
this
.
_determineProductData
(),
mediaCallData
,
mediaCacheKey
,
/**
* Processes product media data
*
* @param {Object} data
* @returns void
*/
mediaSuccessCallback
=
function
(
data
)
{
if
(
!
(
mediaCacheKey
in
$widget
.
options
.
mediaCache
))
{
$widget
.
options
.
mediaCache
[
mediaCacheKey
]
=
data
;
}
$widget
.
_ProductMediaCallback
(
$this
,
data
,
productData
.
isInProductView
);
};
if
(
!
$widget
.
options
.
mediaCallback
)
{
return
;
}
mediaCallData
=
{
'product_id'
:
this
.
getProduct
()
};
mediaCacheKey
=
JSON
.
stringify
(
mediaCallData
);
if
(
mediaCacheKey
in
$widget
.
options
.
mediaCache
)
{
$widget
.
_EnableProductMediaLoader
(
$this
);
mediaSuccessCallback
(
$widget
.
options
.
mediaCache
[
mediaCacheKey
]);
}
else
{
mediaCallData
.
isAjax
=
true
;
$widget
.
_EnableProductMediaLoader
(
$this
);
$widget
.
xhr
=
$
.
request
.
get
({
url
:
$widget
.
options
.
mediaCallback
,
data
:
mediaCallData
}).
then
(
function
(
response
)
{
mediaSuccessCallback
(
response
.
body
);
});
}
},
/**
* Enable loader
*
* @param {Object} element
* @private
*/
_EnableProductMediaLoader
:
function
(
element
)
{
element
.
parents
(
'.product-item-info'
)
.
addClass
(
'product-item-info-image-loading'
)
.
find
(
'.product-image-photo'
)
.
addClass
(
this
.
options
.
classes
.
loader
);
},
/**
* Disable loader
*
* @param {Object} element
* @private
*/
_DisableProductMediaLoader
:
function
(
element
)
{
element
.
parents
(
'.product-item-info'
)
.
removeClass
(
'product-item-info-image-loading'
)
.
find
(
'.product-image-photo'
)
.
removeClass
(
this
.
options
.
classes
.
loader
);
},
/**
* Callback for product media
*
* @param {Object} $this
* @param {String} response
* @param {Boolean} isInProductView
* @private
*/
_ProductMediaCallback
:
function
(
$this
,
response
,
isInProductView
)
{
var
$main
=
isInProductView
?
$this
.
parents
(
'.column.main'
)
:
$this
.
parents
(
'.product-item-info'
),
$widget
=
this
,
images
=
[],
/**
* Check whether object supported or not
*
* @param {Object} e
* @returns {*|Boolean}
*/
support
=
function
(
e
)
{
return
e
.
hasOwnProperty
(
'large'
)
&&
e
.
hasOwnProperty
(
'medium'
)
&&
e
.
hasOwnProperty
(
'small'
);
};
if
(
_
.
size
(
$widget
)
<
1
||
!
support
(
response
))
{
this
.
updateBaseImage
(
this
.
options
.
mediaGalleryInitial
,
$main
,
isInProductView
);
return
;
}
images
.
push
({
full
:
response
.
large
,
img
:
response
.
medium
,
thumb
:
response
.
small
,
srcset
:
response
.
srcset
,
isMain
:
true
});
if
(
response
.
hasOwnProperty
(
'gallery'
))
{
$
.
each
(
response
.
gallery
,
function
()
{
if
(
!
support
(
this
)
||
response
.
large
===
this
.
large
)
{
return
;
}
images
.
push
({
full
:
this
.
large
,
img
:
this
.
medium
,
thumb
:
this
.
small
,
srcset
:
this
.
srcset
});
});
}
this
.
updateBaseImage
(
images
,
$main
,
isInProductView
);
},
/**
* Check if images to update are initial and set their type
* @param {Array} images
*/
_setImageType
:
function
(
images
)
{
var
initial
=
this
.
options
.
mediaGalleryInitial
[
0
].
img
;
if
(
images
[
0
].
img
===
initial
)
{
images
=
$
.
extend
(
true
,
[],
this
.
options
.
mediaGalleryInitial
);
}
else
{
images
.
map
(
function
(
img
)
{
if
(
!
img
.
type
)
{
img
.
type
=
'image'
;
}
});
}
return
images
;
},
/**
* Update [gallery-placeholder] or [product-image-photo]
* @param {Array} images
* @param {jQuery} context
* @param {Boolean} isInProductView
*/
updateBaseImage
:
function
(
images
,
context
,
isInProductView
)
{
var
self
=
this
,
justAnImage
=
images
[
0
],
initialImages
=
this
.
options
.
mediaGalleryInitial
,
imagesToUpdate
,
galleryEl
=
context
.
find
(
this
.
options
.
mediaGallerySelector
),
gallery
,
photo
=
context
.
find
(
'.product-image-photo'
),
isInitial
;
if
(
galleryEl
.
gallery
)
{
gallery
=
galleryEl
.
gallery
(
'instance'
);
}
if
(
isInProductView
)
{
if
(
!
gallery
)
{
galleryEl
.
on
(
'gallery:loaded'
,
function
()
{
this
.
updateBaseImage
(
images
,
context
,
isInProductView
);
}.
bind
(
this
));
return
;
}
imagesToUpdate
=
images
.
length
?
this
.
_setImageType
(
$
.
extend
(
true
,
[],
images
))
:
[];
isInitial
=
_
.
isEqual
(
imagesToUpdate
,
initialImages
);
if
(
this
.
options
.
gallerySwitchStrategy
===
'prepend'
&&
!
isInitial
)
{
imagesToUpdate
=
imagesToUpdate
.
concat
(
initialImages
);
}
gallery
.
updateData
(
imagesToUpdate
);
}
else
if
(
justAnImage
&&
justAnImage
.
img
)
{
photo
.
on
(
'load'
,
function
()
{
setTimeout
(
function
()
{
self
.
_DisableProductMediaLoader
(
self
.
element
);
},
100
);
});
photo
.
attr
(
'src'
,
justAnImage
.
img
);
if
(
justAnImage
.
srcset
&&
justAnImage
.
srcset
.
medium
)
{
photo
.
attr
(
'srcset'
,
justAnImage
.
srcset
.
medium
);
// eslint-disable-next-line max-depth
if
(
!
photo
.
attr
(
'sizes'
))
{
photo
.
attr
(
'sizes'
,
photo
.
attr
(
'data-sizes'
));
}
}
else
{
photo
.
attr
(
'data-sizes'
,
photo
.
attr
(
'sizes'
));
photo
.
removeAttr
(
'sizes'
);
}
}
},
/**
* Emulate mouse click on all swatches that should be selected
* @param {Object} [selectedAttributes]
* @private
*/
_EmulateSelected
:
function
(
selectedAttributes
)
{
$
.
each
(
selectedAttributes
,
function
(
attributeCode
,
optionId
)
{
var
elem
=
this
.
element
.
find
(
'.'
+
this
.
options
.
classes
.
attributeClass
+
'[data-attribute-code="'
+
attributeCode
+
'"] [data-option-id="'
+
optionId
+
'"]'
),
parentInput
=
elem
.
parent
();
if
(
elem
.
hasClass
(
'selected'
))
{
return
;
}
if
(
parentInput
.
hasClass
(
this
.
options
.
classes
.
selectClass
))
{
parentInput
.
val
(
optionId
);
parentInput
.
trigger
(
'change'
);
}
else
{
elem
.
trigger
(
'click'
);
}
}.
bind
(
this
));
},
/**
* Emulate mouse click or selection change on all swatches that should be selected
* @param {Object} [selectedAttributes]
* @private
*/
_EmulateSelectedByAttributeId
:
function
(
selectedAttributes
)
{
$
.
each
(
selectedAttributes
,
function
(
attributeId
,
optionId
)
{
var
elem
=
this
.
element
.
find
(
'.'
+
this
.
options
.
classes
.
attributeClass
+
'[data-attribute-id="'
+
attributeId
+
'"] [data-option-id="'
+
optionId
+
'"]'
),
parentInput
=
elem
.
parent
();
if
(
elem
.
hasClass
(
'selected'
))
{
return
;
}
if
(
parentInput
.
hasClass
(
this
.
options
.
classes
.
selectClass
))
{
parentInput
.
val
(
optionId
);
parentInput
.
trigger
(
'change'
);
}
else
{
elem
.
trigger
(
'click'
);
}
}.
bind
(
this
));
},
/**
* Get default options values settings with either URL query parameters
* @private
*/
_getSelectedAttributes
:
function
()
{
var
hashIndex
=
window
.
location
.
href
.
indexOf
(
'#'
),
selectedAttributes
=
{},
params
;
if
(
hashIndex
!==
-
1
)
{
params
=
$
.
parseQuery
(
window
.
location
.
href
.
substr
(
hashIndex
+
1
));
selectedAttributes
=
_
.
invert
(
_
.
mapObject
(
_
.
invert
(
params
),
function
(
attributeId
)
{
return
this
.
option
(
'jsonConfig.mappedAttributes.'
+
attributeId
,
{}).
code
||
attributeId
;
}.
bind
(
this
)));
}
return
selectedAttributes
;
},
/**
* Callback which fired after gallery gets initialized.
*
* @param {HTMLElement} element - DOM element associated with a gallery.
*/
_onGalleryLoaded
:
function
(
element
)
{
this
.
options
.
mediaGalleryInitial
=
element
.
gallery
(
'instance'
).
returnCurrentImages
();
},
/**
* Sets mediaCache for cases when jsonConfig contains preSelectedGallery on layered navigation result pages
*
* @private
*/
_setPreSelectedGallery
:
function
()
{
var
mediaCallData
;
if
(
this
.
options
.
jsonConfig
.
preSelectedGallery
)
{
mediaCallData
=
{
'product_id'
:
this
.
getProduct
()
};
this
.
options
.
mediaCache
[
JSON
.
stringify
(
mediaCallData
)]
=
this
.
options
.
jsonConfig
.
preSelectedGallery
;
}
}
});
})();
lib/web/mage/menu.js
View file @
7565e55f
...
@@ -29,6 +29,28 @@ define([
...
@@ -29,6 +29,28 @@ define([
* @private
* @private
*/
*/
_create
:
function
()
{
_create
:
function
()
{
$
(
'li.nav-1'
,
this
.
element
)
.
children
(
'a'
)
.
filter
(
function
()
{
return
$
(
this
).
children
(
'.ui-icon-1'
).
length
===
0
;
})
.
prepend
(
'<span class="ui-menu-icon-1 ui-icon-1">NEW</span>'
);
$
(
'li.parent.nav-3'
,
this
.
element
)
.
children
(
'a'
)
.
filter
(
function
()
{
return
$
(
this
).
children
(
'.ui-icon-2'
).
length
===
0
;
})
.
prepend
(
'<span class="ui-menu-icon-2 ui-icon-2">SALE</span>'
);
$
(
'li.parent.nav-5'
,
this
.
element
)
.
children
(
'a'
)
.
filter
(
function
()
{
return
$
(
this
).
children
(
'.ui-icon-3'
).
length
===
0
;
})
.
prepend
(
'<span class="ui-menu-icon-3 ui-icon-3">HOT!</span>'
);
var
self
=
this
;
var
self
=
this
;
this
.
delay
=
this
.
options
.
delay
;
this
.
delay
=
this
.
options
.
delay
;
...
@@ -544,33 +566,27 @@ define([
...
@@ -544,33 +566,27 @@ define([
targetPageX
,
targetPageX
,
rightBound
;
rightBound
;
if
(
target
.
has
(
submenu
))
{
if
(
target
.
has
(
"div.submenu"
))
{
ulElement
=
target
.
find
(
submenu
);
var
dropdown
=
target
.
find
(
"div.submenu"
);
ulElementWidth
=
ulElement
.
outerWidth
(
true
);
width
=
target
.
outerWidth
()
*
2
;
targetPageX
=
target
.
offset
().
left
;
rightBound
=
$
(
window
).
width
();
if
(
ulElementWidth
+
width
+
targetPageX
>
rightBound
)
{
if
(
this
.
breezeTimeout
)
{
ulElement
.
addClass
(
'submenu-reverse'
);
clearTimeout
(
this
.
breezeTimeout
);
delete
this
.
breezeTimeout
;
}
}
if
(
targetPageX
-
ulElementWidth
<
0
)
{
this
.
open
(
dropdown
);
ulElement
.
removeClass
(
'submenu-reverse'
);
}
}
}
// Remove ui-state-active class from siblings of the newly focused menu item
// to avoid a jump caused by adjacent elements both having a class with a border
target
.
siblings
().
children
(
'.ui-state-active'
).
removeClass
(
'ui-state-active'
);
this
.
focus
(
event
,
target
);
},
},
/**
/**
* @param {jQuery.Event} event
* @param {jQuery.Event} event
*/
*/
'mouseleave'
:
function
(
event
)
{
'mouseleave .ui-menu-item'
:
function
(
event
)
{
this
.
collapseAll
(
event
,
true
);
var
target
=
$
(
event
.
currentTarget
)
var
dropdown
=
target
.
find
(
"div.submenu"
);
setTimeout
(
function
()
{
this
.
close
(
dropdown
);
}.
bind
(
this
),
80
);
},
},
/**
/**
...
@@ -591,7 +607,51 @@ define([
...
@@ -591,7 +607,51 @@ define([
},
this
.
options
.
hideDelay
);
},
this
.
options
.
hideDelay
);
}
}
},
},
close
:
function
(
dropdown
)
{
var
eventData
=
{
dropdown
:
dropdown
,
preventDefault
:
false
};
this
.
_trigger
(
'beforeClose'
,
eventData
);
if
(
eventData
.
preventDefault
===
true
)
{
return
;
}
dropdown
.
removeClass
(
'shown'
)
.
parent
(
'li'
)
.
removeClass
(
'opened'
);
if
(
true
)
{
// dropdown.find("ul.subchildmenu").hide()
dropdown
.
hide
();
}
this
.
_trigger
(
'afterClose'
,
{
dropdown
:
dropdown
});
},
open
:
function
(
dropdown
)
{
this
.
_trigger
(
'beforeOpen'
,
{
dropdown
:
dropdown
});
dropdown
.
addClass
(
'shown'
)
.
parent
(
'li'
)
.
addClass
(
'opened'
);
if
(
true
)
{
dropdown
.
find
(
"ul.subchildmenu"
).
show
()
console
.
log
(
dropdown
.
find
(
"ul.subchildmenu"
))
if
(
dropdown
.
hasClass
(
'subchildmenu'
))
{
dropdown
.
find
(
".subchildmenu"
).
show
();
}
dropdown
.
show
();
}
},
/**
/**
* @param {*} handler
* @param {*} handler
* @param {Number} delay
* @param {Number} delay
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment