@@ -7,11 +7,13 @@ import $ from "jquery";
7
7
import ko from "knockout" ;
8
8
import $t from "mage/translate" ;
9
9
import "slick" ;
10
+ import _ from "underscore" ;
10
11
import Config from "../../config" ;
11
12
import ContentTypeInterface from "../../content-type" ;
12
13
import ContentTypeConfigInterface from "../../content-type-config.types" ;
13
14
import HideShowOption from "../../content-type-menu/hide-show-option" ;
14
15
import { OptionsInterface } from "../../content-type-menu/option.types" ;
16
+ import { DataObject } from "../../data-store" ;
15
17
import ObservableUpdater from "../observable-updater" ;
16
18
import BasePreview from "../preview" ;
17
19
@@ -21,15 +23,31 @@ import BasePreview from "../preview";
21
23
export default class Preview extends BasePreview {
22
24
public displayPreview : KnockoutObservable < boolean > = ko . observable ( false ) ;
23
25
public placeholderText : KnockoutObservable < string > ;
26
+ public widgetHtml : KnockoutObservable < string > = ko . observable ( ) ;
24
27
private element : Element ;
25
- private sliderReady : boolean = false ;
26
28
private messages = {
27
29
EMPTY : $t ( "Empty Products" ) ,
28
30
NO_RESULTS : $t ( "No products were found matching your condition" ) ,
29
31
LOADING : $t ( "Loading..." ) ,
30
32
UNKNOWN_ERROR : $t ( "An unknown error occurred. Please try again." ) ,
31
33
} ;
32
34
35
+ /**
36
+ * Define keys which when changed should not trigger the slider to be rebuilt
37
+ *
38
+ * @type {string[] }
39
+ */
40
+ private ignoredKeysForBuild : string [ ] = [
41
+ "margins_and_padding" ,
42
+ "border" ,
43
+ "border_color" ,
44
+ "border_radius" ,
45
+ "border_width" ,
46
+ "css_classes" ,
47
+ "text_align" ,
48
+ ] ;
49
+ private previousData : DataObject ;
50
+
33
51
/**
34
52
* @inheritdoc
35
53
*/
@@ -72,67 +90,59 @@ export default class Preview extends BasePreview {
72
90
this . initSlider ( ) ;
73
91
}
74
92
75
- /**
76
- * @inheritDoc
77
- */
78
- public onOptionVisibilityToggle ( ) : void {
79
- this . element = undefined ;
80
- this . sliderReady = false ;
81
- super . onOptionVisibilityToggle ( ) ;
82
- }
83
-
84
93
/**
85
94
* @inheritdoc
86
95
*/
87
96
protected afterObservablesUpdated ( ) : void {
88
97
super . afterObservablesUpdated ( ) ;
89
- this . displayPreview ( false ) ;
90
-
91
98
const data = this . contentType . dataStore . getState ( ) ;
92
99
93
- if ( ( typeof data . conditions_encoded !== "string" ) || data . conditions_encoded . length === 0 ) {
94
- this . placeholderText ( this . messages . EMPTY ) ;
95
-
96
- return ;
100
+ if ( this . hasDataChanged ( this . previousData , data ) ) {
101
+ this . displayPreview ( false ) ;
102
+
103
+ if ( ( typeof data . conditions_encoded !== "string" ) || data . conditions_encoded . length === 0 ) {
104
+ this . placeholderText ( this . messages . EMPTY ) ;
105
+
106
+ return ;
107
+ }
108
+
109
+ const url = Config . getConfig ( "preview_url" ) ;
110
+ const requestConfig = {
111
+ // Prevent caching
112
+ method : "POST" ,
113
+ data : {
114
+ role : this . config . name ,
115
+ directive : this . data . main . html ( ) ,
116
+ } ,
117
+ } ;
118
+
119
+ this . placeholderText ( this . messages . LOADING ) ;
120
+
121
+ $ . ajax ( url , requestConfig )
122
+ . done ( ( response ) => {
123
+ if ( typeof response . data !== "object" || ! Boolean ( response . data . content ) ) {
124
+ this . placeholderText ( this . messages . NO_RESULTS ) ;
125
+
126
+ return ;
127
+ }
128
+
129
+ if ( response . data . error ) {
130
+ this . widgetHtml ( response . data . error ) ;
131
+ } else {
132
+ this . widgetHtml ( response . data . content ) ;
133
+ this . displayPreview ( true ) ;
134
+ }
135
+ } )
136
+ . fail ( ( ) => {
137
+ this . placeholderText ( this . messages . UNKNOWN_ERROR ) ;
138
+ } ) ;
97
139
}
98
-
99
- const url = Config . getConfig ( "preview_url" ) ;
100
- const requestConfig = {
101
- // Prevent caching
102
- method : "POST" ,
103
- data : {
104
- role : this . config . name ,
105
- directive : this . data . main . html ( ) ,
106
- } ,
107
- } ;
108
-
109
- this . placeholderText ( this . messages . LOADING ) ;
110
-
111
- $ . ajax ( url , requestConfig )
112
- . done ( ( response ) => {
113
- if ( typeof response . data !== "object" || ! Boolean ( response . data . content ) ) {
114
- this . placeholderText ( this . messages . NO_RESULTS ) ;
115
-
116
- return ;
117
- }
118
-
119
- if ( response . data . error ) {
120
- this . data . main . html ( response . data . error ) ;
121
- } else {
122
- this . data . main . html ( response . data . content ) ;
123
- this . initSlider ( ) ;
124
- this . displayPreview ( true ) ;
125
- }
126
- } )
127
- . fail ( ( ) => {
128
- this . placeholderText ( this . messages . UNKNOWN_ERROR ) ;
129
- } ) ;
140
+ this . previousData = Object . assign ( { } , data ) ;
130
141
}
131
142
132
143
protected initSlider ( ) : void {
133
- if ( ! this . sliderReady && this . element && this . appearance ( ) === "carousel" ) {
144
+ if ( this . element && this . appearance ( ) === "carousel" ) {
134
145
$ ( this . element . children ) . slick ( this . buildSlickConfig ( ) ) ;
135
- this . sliderReady = true ;
136
146
}
137
147
}
138
148
@@ -156,4 +166,17 @@ export default class Preview extends BasePreview {
156
166
autoplaySpeed : parseFloat ( attributes [ "data-autoplay-speed" ] ) ,
157
167
} ;
158
168
}
169
+
170
+ /**
171
+ * Determine if the data has changed, whilst ignoring certain keys which don't require a rebuild
172
+ *
173
+ * @param {DataObject } previousData
174
+ * @param {DataObject } newData
175
+ * @returns {boolean }
176
+ */
177
+ private hasDataChanged ( previousData : DataObject , newData : DataObject ) {
178
+ previousData = _ . omit ( previousData , this . ignoredKeysForBuild ) ;
179
+ newData = _ . omit ( newData , this . ignoredKeysForBuild ) ;
180
+ return ! _ . isEqual ( previousData , newData ) ;
181
+ }
159
182
}
0 commit comments