52572b82 by Jeff Balicki

404

Signed-off-by: Jeff <jeff@gotenzing.com>
1 parent 423dd060
Showing 78 changed files with 19907 additions and 12 deletions
This diff could not be displayed because it is too large.
1 /* -------------------------------------------------------------------
2 Microtip
3
4 Modern, lightweight css-only tooltips
5 Just 1kb minified and gzipped
6
7 @author Ghosh
8 @package Microtip
9
10 ----------------------------------------------------------------------
11 1. Base Styles
12 2. Direction Modifiers
13 3. Position Modifiers
14 --------------------------------------------------------------------*/
15
16
17 /* ------------------------------------------------
18 [1] Base Styles
19 -------------------------------------------------*/
20
21 [aria-label][role~="tooltip"] {
22 position: relative;
23 }
24
25 [aria-label][role~="tooltip"]::before,
26 [aria-label][role~="tooltip"]::after {
27 transform: translate3d(0, 0, 0);
28 -webkit-backface-visibility: hidden;
29 backface-visibility: hidden;
30 will-change: transform;
31 opacity: 0;
32 pointer-events: none;
33 transition: all var(--microtip-transition-duration, .18s) var(--microtip-transition-easing, ease-in-out) var(--microtip-transition-delay, 0s);
34 position: absolute;
35 box-sizing: border-box;
36 z-index: 10;
37 transform-origin: top;
38 }
39
40 [aria-label][role~="tooltip"]::before {
41 background-size: 100% auto !important;
42 content: "";
43 }
44
45 [aria-label][role~="tooltip"]::after {
46 background: rgba(17, 17, 17, .9);
47 border-radius: 4px;
48 color: #ffffff;
49 content: attr(aria-label);
50 font-size: var(--microtip-font-size, 13px);
51 font-weight: var(--microtip-font-weight, normal);
52 text-transform: var(--microtip-text-transform, none);
53 padding: .5em 1em;
54 white-space: nowrap;
55 box-sizing: content-box;
56 }
57
58 [aria-label][role~="tooltip"]:hover::before,
59 [aria-label][role~="tooltip"]:hover::after,
60 [aria-label][role~="tooltip"]:focus::before,
61 [aria-label][role~="tooltip"]:focus::after {
62 opacity: 1;
63 pointer-events: auto;
64 }
65
66
67
68 /* ------------------------------------------------
69 [2] Position Modifiers
70 -------------------------------------------------*/
71
72 [role~="tooltip"][data-microtip-position|="top"]::before {
73 background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
74 height: 6px;
75 width: 18px;
76 margin-bottom: 5px;
77 }
78
79 [role~="tooltip"][data-microtip-position|="top"]::after {
80 margin-bottom: 11px;
81 }
82
83 [role~="tooltip"][data-microtip-position|="top"]::before {
84 transform: translate3d(-50%, 0, 0);
85 bottom: 100%;
86 left: 50%;
87 }
88
89 [role~="tooltip"][data-microtip-position|="top"]:hover::before {
90 transform: translate3d(-50%, -5px, 0);
91 }
92
93 [role~="tooltip"][data-microtip-position|="top"]::after {
94 transform: translate3d(-50%, 0, 0);
95 bottom: 100%;
96 left: 50%;
97 }
98
99 [role~="tooltip"][data-microtip-position="top"]:hover::after {
100 transform: translate3d(-50%, -5px, 0);
101 }
102
103 /* ------------------------------------------------
104 [2.1] Top Left
105 -------------------------------------------------*/
106 [role~="tooltip"][data-microtip-position="top-left"]::after {
107 transform: translate3d(calc(-100% + 16px), 0, 0);
108 bottom: 100%;
109 }
110
111 [role~="tooltip"][data-microtip-position="top-left"]:hover::after {
112 transform: translate3d(calc(-100% + 16px), -5px, 0);
113 }
114
115
116 /* ------------------------------------------------
117 [2.2] Top Right
118 -------------------------------------------------*/
119 [role~="tooltip"][data-microtip-position="top-right"]::after {
120 transform: translate3d(calc(0% + -16px), 0, 0);
121 bottom: 100%;
122 }
123
124 [role~="tooltip"][data-microtip-position="top-right"]:hover::after {
125 transform: translate3d(calc(0% + -16px), -5px, 0);
126 }
127
128
129 /* ------------------------------------------------
130 [2.3] Bottom
131 -------------------------------------------------*/
132 [role~="tooltip"][data-microtip-position|="bottom"]::before {
133 background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
134 height: 6px;
135 width: 18px;
136 margin-top: 5px;
137 margin-bottom: 0;
138 }
139
140 [role~="tooltip"][data-microtip-position|="bottom"]::after {
141 margin-top: 11px;
142 }
143
144 [role~="tooltip"][data-microtip-position|="bottom"]::before {
145 transform: translate3d(-50%, -10px, 0);
146 bottom: auto;
147 left: 50%;
148 top: 100%;
149 }
150
151 [role~="tooltip"][data-microtip-position|="bottom"]:hover::before {
152 transform: translate3d(-50%, 0, 0);
153 }
154
155 [role~="tooltip"][data-microtip-position|="bottom"]::after {
156 transform: translate3d(-50%, -10px, 0);
157 top: 100%;
158 left: 50%;
159 }
160
161 [role~="tooltip"][data-microtip-position="bottom"]:hover::after {
162 transform: translate3d(-50%, 0, 0);
163 }
164
165
166 /* ------------------------------------------------
167 [2.4] Bottom Left
168 -------------------------------------------------*/
169 [role~="tooltip"][data-microtip-position="bottom-left"]::after {
170 transform: translate3d(calc(-100% + 16px), -10px, 0);
171 top: 100%;
172 }
173
174 [role~="tooltip"][data-microtip-position="bottom-left"]:hover::after {
175 transform: translate3d(calc(-100% + 16px), 0, 0);
176 }
177
178
179 /* ------------------------------------------------
180 [2.5] Bottom Right
181 -------------------------------------------------*/
182 [role~="tooltip"][data-microtip-position="bottom-right"]::after {
183 transform: translate3d(calc(0% + -16px), -10px, 0);
184 top: 100%;
185 }
186
187 [role~="tooltip"][data-microtip-position="bottom-right"]:hover::after {
188 transform: translate3d(calc(0% + -16px), 0, 0);
189 }
190
191
192 /* ------------------------------------------------
193 [2.6] Left
194 -------------------------------------------------*/
195 [role~="tooltip"][data-microtip-position="left"]::before,
196 [role~="tooltip"][data-microtip-position="left"]::after {
197 bottom: auto;
198 left: auto;
199 right: 100%;
200 top: 50%;
201 transform: translate3d(10px, -50%, 0);
202 }
203
204 [role~="tooltip"][data-microtip-position="left"]::before {
205 background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
206 height: 18px;
207 width: 6px;
208 margin-right: 5px;
209 margin-bottom: 0;
210 }
211
212 [role~="tooltip"][data-microtip-position="left"]::after {
213 margin-right: 11px;
214 }
215
216 [role~="tooltip"][data-microtip-position="left"]:hover::before,
217 [role~="tooltip"][data-microtip-position="left"]:hover::after {
218 transform: translate3d(0, -50%, 0);
219 }
220
221
222 /* ------------------------------------------------
223 [2.7] Right
224 -------------------------------------------------*/
225 [role~="tooltip"][data-microtip-position="right"]::before,
226 [role~="tooltip"][data-microtip-position="right"]::after {
227 bottom: auto;
228 left: 100%;
229 top: 50%;
230 transform: translate3d(-10px, -50%, 0);
231 }
232
233 [role~="tooltip"][data-microtip-position="right"]::before {
234 background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
235 height: 18px;
236 width: 6px;
237 margin-bottom: 0;
238 margin-left: 5px;
239 }
240
241 [role~="tooltip"][data-microtip-position="right"]::after {
242 margin-left: 11px;
243 }
244
245 [role~="tooltip"][data-microtip-position="right"]:hover::before,
246 [role~="tooltip"][data-microtip-position="right"]:hover::after {
247 transform: translate3d(0, -50%, 0);
248 }
249
250 /* ------------------------------------------------
251 [3] Size
252 -------------------------------------------------*/
253 [role~="tooltip"][data-microtip-size="small"]::after {
254 white-space: initial;
255 width: 80px;
256 }
257
258 [role~="tooltip"][data-microtip-size="medium"]::after {
259 white-space: initial;
260 width: 150px;
261 }
262
263 [role~="tooltip"][data-microtip-size="large"]::after {
264 white-space: initial;
265 width: 260px;
266 }
1 /* -------------------------------------------------------------------
2 Microtip
3
4 Modern, lightweight css-only tooltips
5 Just 1kb minified and gzipped
6
7 @author Ghosh
8 @package Microtip
9
10 ----------------------------------------------------------------------
11 1. Base Styles
12 2. Direction Modifiers
13 3. Position Modifiers
14 --------------------------------------------------------------------*/
15 [aria-label][role~="tooltip"]{position:relative}[aria-label][role~="tooltip"]::before,[aria-label][role~="tooltip"]::after{transform:translate3d(0,0,0);-webkit-backface-visibility:hidden;backface-visibility:hidden;will-change:transform;opacity:0;pointer-events:none;transition:all var(--microtip-transition-duration,.18s) var(--microtip-transition-easing,ease-in-out) var(--microtip-transition-delay,0s);position:absolute;box-sizing:border-box;z-index:10;transform-origin:top}[aria-label][role~="tooltip"]::before{background-size:100% auto!important;content:""}[aria-label][role~="tooltip"]::after{background:rgba(17,17,17,.9);border-radius:4px;color:#fff;content:attr(aria-label);font-size:var(--microtip-font-size,13px);font-weight:var(--microtip-font-weight,normal);text-transform:var(--microtip-text-transform,none);padding:.5em 1em;white-space:nowrap;box-sizing:content-box}[aria-label][role~="tooltip"]:hover::before,[aria-label][role~="tooltip"]:hover::after,[aria-label][role~="tooltip"]:focus::before,[aria-label][role~="tooltip"]:focus::after{opacity:1;pointer-events:auto}[role~="tooltip"][data-microtip-position|="top"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:6px;width:18px;margin-bottom:5px}[role~="tooltip"][data-microtip-position|="top"]::after{margin-bottom:11px}[role~="tooltip"][data-microtip-position|="top"]::before{transform:translate3d(-50%,0,0);bottom:100%;left:50%}[role~="tooltip"][data-microtip-position|="top"]:hover::before{transform:translate3d(-50%,-5px,0)}[role~="tooltip"][data-microtip-position|="top"]::after{transform:translate3d(-50%,0,0);bottom:100%;left:50%}[role~="tooltip"][data-microtip-position="top"]:hover::after{transform:translate3d(-50%,-5px,0)}[role~="tooltip"][data-microtip-position="top-left"]::after{transform:translate3d(calc(-100% + 16px),0,0);bottom:100%}[role~="tooltip"][data-microtip-position="top-left"]:hover::after{transform:translate3d(calc(-100% + 16px),-5px,0)}[role~="tooltip"][data-microtip-position="top-right"]::after{transform:translate3d(calc(0% + -16px),0,0);bottom:100%}[role~="tooltip"][data-microtip-position="top-right"]:hover::after{transform:translate3d(calc(0% + -16px),-5px,0)}[role~="tooltip"][data-microtip-position|="bottom"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:6px;width:18px;margin-top:5px;margin-bottom:0}[role~="tooltip"][data-microtip-position|="bottom"]::after{margin-top:11px}[role~="tooltip"][data-microtip-position|="bottom"]::before{transform:translate3d(-50%,-10px,0);bottom:auto;left:50%;top:100%}[role~="tooltip"][data-microtip-position|="bottom"]:hover::before{transform:translate3d(-50%,0,0)}[role~="tooltip"][data-microtip-position|="bottom"]::after{transform:translate3d(-50%,-10px,0);top:100%;left:50%}[role~="tooltip"][data-microtip-position="bottom"]:hover::after{transform:translate3d(-50%,0,0)}[role~="tooltip"][data-microtip-position="bottom-left"]::after{transform:translate3d(calc(-100% + 16px),-10px,0);top:100%}[role~="tooltip"][data-microtip-position="bottom-left"]:hover::after{transform:translate3d(calc(-100% + 16px),0,0)}[role~="tooltip"][data-microtip-position="bottom-right"]::after{transform:translate3d(calc(0% + -16px),-10px,0);top:100%}[role~="tooltip"][data-microtip-position="bottom-right"]:hover::after{transform:translate3d(calc(0% + -16px),0,0)}[role~="tooltip"][data-microtip-position="left"]::before,[role~="tooltip"][data-microtip-position="left"]::after{bottom:auto;left:auto;right:100%;top:50%;transform:translate3d(10px,-50%,0)}[role~="tooltip"][data-microtip-position="left"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:18px;width:6px;margin-right:5px;margin-bottom:0}[role~="tooltip"][data-microtip-position="left"]::after{margin-right:11px}[role~="tooltip"][data-microtip-position="left"]:hover::before,[role~="tooltip"][data-microtip-position="left"]:hover::after{transform:translate3d(0,-50%,0)}[role~="tooltip"][data-microtip-position="right"]::before,[role~="tooltip"][data-microtip-position="right"]::after{bottom:auto;left:100%;top:50%;transform:translate3d(-10px,-50%,0)}[role~="tooltip"][data-microtip-position="right"]::before{background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E) no-repeat;height:18px;width:6px;margin-bottom:0;margin-left:5px}[role~="tooltip"][data-microtip-position="right"]::after{margin-left:11px}[role~="tooltip"][data-microtip-position="right"]:hover::before,[role~="tooltip"][data-microtip-position="right"]:hover::after{transform:translate3d(0,-50%,0)}[role~="tooltip"][data-microtip-size="small"]::after{white-space:initial;width:80px}[role~="tooltip"][data-microtip-size="medium"]::after{white-space:initial;width:150px}[role~="tooltip"][data-microtip-size="large"]::after{white-space:initial;width:260px}
...\ No newline at end of file ...\ No newline at end of file
1 /*!
2 Modaal - accessible modals - v0.4.4
3 by Humaan, for all humans.
4 http://humaan.com
5 */
6
7 .modaal-noscroll {
8 overflow: hidden;
9 }
10
11 .modaal-accessible-hide {
12 position: absolute !important;
13 clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
14 clip: rect(1px, 1px, 1px, 1px);
15 padding: 0 !important;
16 border: 0 !important;
17 height: 1px !important;
18 width: 1px !important;
19 overflow: hidden;
20 }
21
22 .modaal-overlay {
23 position: fixed;
24 top: 0;
25 left: 0;
26 width: 100%;
27 height: 100%;
28 z-index: 999;
29 opacity: 0;
30 }
31
32 .modaal-wrapper {
33 display: block;
34 position: fixed;
35 top: 0;
36 left: 0;
37 width: 100%;
38 height: 100%;
39 z-index: 9999;
40 overflow: auto;
41 opacity: 1;
42 box-sizing: border-box;
43 -webkit-overflow-scrolling: touch;
44 -webkit-transition: all 0.3s ease-in-out;
45 transition: all 0.3s ease-in-out;
46 }
47
48 .modaal-wrapper * {
49 box-sizing: border-box;
50 -webkit-font-smoothing: antialiased;
51 -moz-osx-font-smoothing: grayscale;
52 -webkit-backface-visibility: hidden;
53 }
54
55 .modaal-wrapper .modaal-close {
56 border: none;
57 background: transparent;
58 padding: 0;
59 -webkit-appearance: none;
60 }
61
62 .modaal-wrapper.modaal-start_none {
63 display: none;
64 opacity: 1;
65 }
66
67 .modaal-wrapper.modaal-start_fade {
68 opacity: 0;
69 }
70
71 .modaal-wrapper *[tabindex="0"] {
72 outline: none !important;
73 }
74
75 .modaal-wrapper.modaal-fullscreen {
76 overflow: hidden;
77 }
78
79 .modaal-outer-wrapper {
80 display: table;
81 position: relative;
82 width: 100%;
83 height: 100%;
84 }
85
86 .modaal-fullscreen .modaal-outer-wrapper {
87 display: block;
88 }
89
90 .modaal-inner-wrapper {
91 display: table-cell;
92 width: 100%;
93 height: 100%;
94 position: relative;
95 vertical-align: middle;
96 text-align: center;
97 padding: 80px 25px;
98 }
99
100 .modaal-fullscreen .modaal-inner-wrapper {
101 padding: 0;
102 display: block;
103 vertical-align: top;
104 }
105
106 .modaal-container {
107 position: relative;
108 display: inline-block;
109 width: 100%;
110 margin: auto;
111 text-align: left;
112 color: #000;
113 max-width: 1000px;
114 border-radius: 0px;
115 background: #fff;
116 box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
117 cursor: auto;
118 }
119
120 .modaal-container.is_loading {
121 height: 100px;
122 width: 100px;
123 overflow: hidden;
124 }
125
126 .modaal-fullscreen .modaal-container {
127 max-width: none;
128 height: 100%;
129 overflow: auto;
130 }
131
132 .modaal-close {
133 position: fixed;
134 right: 20px;
135 top: 20px;
136 color: #fff;
137 cursor: pointer;
138 opacity: 1;
139 width: 50px;
140 height: 50px;
141 background: rgba(0, 0, 0, 0);
142 border-radius: 100%;
143 -webkit-transition: all 0.2s ease-in-out;
144 transition: all 0.2s ease-in-out;
145 }
146
147 .modaal-close:focus,
148 .modaal-close:hover {
149 outline: none;
150 background: #fff;
151 }
152
153 .modaal-close:focus:before,
154 .modaal-close:focus:after,
155 .modaal-close:hover:before,
156 .modaal-close:hover:after {
157 background: #b93d0c;
158 }
159
160 .modaal-close span {
161 position: absolute !important;
162 clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
163 clip: rect(1px, 1px, 1px, 1px);
164 padding: 0 !important;
165 border: 0 !important;
166 height: 1px !important;
167 width: 1px !important;
168 overflow: hidden;
169 }
170
171 .modaal-close:before,
172 .modaal-close:after {
173 display: block;
174 content: " ";
175 position: absolute;
176 top: 14px;
177 left: 23px;
178 width: 4px;
179 height: 22px;
180 border-radius: 4px;
181 background: #fff;
182 -webkit-transition: background 0.2s ease-in-out;
183 transition: background 0.2s ease-in-out;
184 }
185
186 .modaal-close:before {
187 -webkit-transform: rotate(-45deg);
188 -ms-transform: rotate(-45deg);
189 transform: rotate(-45deg);
190 }
191
192 .modaal-close:after {
193 -webkit-transform: rotate(45deg);
194 -ms-transform: rotate(45deg);
195 transform: rotate(45deg);
196 }
197
198 .modaal-fullscreen .modaal-close {
199 background: #afb7bc;
200 right: 10px;
201 top: 10px;
202 }
203
204 .modaal-content-container {
205 padding: 30px;
206 }
207
208 .modaal-confirm-wrap {
209 padding: 30px 0 0;
210 text-align: center;
211 font-size: 0;
212 }
213
214 .modaal-confirm-btn {
215 font-size: 14px;
216 display: inline-block;
217 margin: 0 10px;
218 vertical-align: middle;
219 cursor: pointer;
220 border: none;
221 background: transparent;
222 }
223
224 .modaal-confirm-btn.modaal-ok {
225 padding: 10px 15px;
226 color: #fff;
227 background: #555;
228 border-radius: 3px;
229 -webkit-transition: background 0.2s ease-in-out;
230 transition: background 0.2s ease-in-out;
231 }
232
233 .modaal-confirm-btn.modaal-ok:hover {
234 background: #2f2f2f;
235 }
236
237 .modaal-confirm-btn.modaal-cancel {
238 text-decoration: underline;
239 }
240
241 .modaal-confirm-btn.modaal-cancel:hover {
242 text-decoration: none;
243 color: #2f2f2f;
244 }
245
246 .modaal-instagram .modaal-container {
247 width: auto;
248 background: transparent;
249 box-shadow: none !important;
250 }
251
252 .modaal-instagram .modaal-content-container {
253 padding: 0;
254 background: transparent;
255 }
256
257 .modaal-instagram .modaal-content-container > blockquote {
258 width: 1px !important;
259 height: 1px !important;
260 opacity: 0 !important;
261 }
262
263 .modaal-instagram iframe {
264 opacity: 0;
265 margin: -6px !important;
266 border-radius: 0 !important;
267 width: 1000px !important;
268 max-width: 800px !important;
269 box-shadow: none !important;
270 -webkit-animation: instaReveal 1s linear forwards;
271 animation: instaReveal 1s linear forwards;
272 }
273
274 .modaal-image .modaal-inner-wrapper {
275 padding-left: 140px;
276 padding-right: 140px;
277 }
278
279 .modaal-image .modaal-container {
280 width: auto;
281 max-width: 100%;
282 }
283
284 .modaal-gallery-wrap {
285 position: relative;
286 color: #fff;
287 }
288
289 .modaal-gallery-item {
290 display: none;
291 }
292
293 .modaal-gallery-item img {
294 display: block;
295 }
296
297 .modaal-gallery-item.is_active {
298 display: block;
299 }
300
301 .modaal-gallery-label {
302 position: absolute;
303 left: 0;
304 width: 100%;
305 margin: 20px 0 0;
306 font-size: 18px;
307 text-align: center;
308 color: #fff;
309 }
310
311 .modaal-gallery-label:focus {
312 outline: none;
313 }
314
315 .modaal-gallery-control {
316 position: absolute;
317 top: 50%;
318 -webkit-transform: translateY(-50%);
319 -ms-transform: translateY(-50%);
320 transform: translateY(-50%);
321 opacity: 1;
322 cursor: pointer;
323 color: #fff;
324 width: 50px;
325 height: 50px;
326 background: rgba(0, 0, 0, 0);
327 border: none;
328 border-radius: 100%;
329 -webkit-transition: all 0.2s ease-in-out;
330 transition: all 0.2s ease-in-out;
331 }
332
333 .modaal-gallery-control.is_hidden {
334 opacity: 0;
335 cursor: default;
336 }
337
338 .modaal-gallery-control:focus,
339 .modaal-gallery-control:hover {
340 outline: none;
341 background: #fff;
342 }
343
344 .modaal-gallery-control:focus:before,
345 .modaal-gallery-control:focus:after,
346 .modaal-gallery-control:hover:before,
347 .modaal-gallery-control:hover:after {
348 background: #afb7bc;
349 }
350
351 .modaal-gallery-control span {
352 position: absolute !important;
353 clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
354 clip: rect(1px, 1px, 1px, 1px);
355 padding: 0 !important;
356 border: 0 !important;
357 height: 1px !important;
358 width: 1px !important;
359 overflow: hidden;
360 }
361
362 .modaal-gallery-control:before,
363 .modaal-gallery-control:after {
364 display: block;
365 content: " ";
366 position: absolute;
367 top: 16px;
368 left: 25px;
369 width: 4px;
370 height: 18px;
371 border-radius: 4px;
372 background: #fff;
373 -webkit-transition: background 0.2s ease-in-out;
374 transition: background 0.2s ease-in-out;
375 }
376
377 .modaal-gallery-control:before {
378 margin: -5px 0 0;
379 -webkit-transform: rotate(-45deg);
380 -ms-transform: rotate(-45deg);
381 transform: rotate(-45deg);
382 }
383
384 .modaal-gallery-control:after {
385 margin: 5px 0 0;
386 -webkit-transform: rotate(45deg);
387 -ms-transform: rotate(45deg);
388 transform: rotate(45deg);
389 }
390
391 .modaal-gallery-next-inner {
392 left: 100%;
393 margin-left: 40px;
394 }
395
396 .modaal-gallery-next-outer {
397 right: 45px;
398 }
399
400 .modaal-gallery-prev:before,
401 .modaal-gallery-prev:after {
402 left: 22px;
403 }
404
405 .modaal-gallery-prev:before {
406 margin: 5px 0 0;
407 -webkit-transform: rotate(-45deg);
408 -ms-transform: rotate(-45deg);
409 transform: rotate(-45deg);
410 }
411
412 .modaal-gallery-prev:after {
413 margin: -5px 0 0;
414 -webkit-transform: rotate(45deg);
415 -ms-transform: rotate(45deg);
416 transform: rotate(45deg);
417 }
418
419 .modaal-gallery-prev-inner {
420 right: 100%;
421 margin-right: 40px;
422 }
423
424 .modaal-gallery-prev-outer {
425 left: 45px;
426 }
427
428 .modaal-video-wrap {
429 margin: auto 50px;
430 position: relative;
431 }
432
433 .modaal-video-container {
434 position: relative;
435 padding-bottom: 56.25%;
436 height: 0;
437 overflow: hidden;
438 max-width: 100%;
439 box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
440 background: #000;
441 max-width: 1300px;
442 margin-left: auto;
443 margin-right: auto;
444 }
445
446 .modaal-video-container iframe,
447 .modaal-video-container object,
448 .modaal-video-container embed {
449 position: absolute;
450 top: 0;
451 left: 0;
452 width: 100%;
453 height: 100%;
454 }
455
456 .modaal-iframe .modaal-content {
457 width: 100%;
458 height: 100%;
459 }
460
461 .modaal-iframe-elem {
462 width: 100%;
463 height: 100%;
464 display: block;
465 }
466
467 .modaal-loading-spinner {
468 background: none;
469 position: absolute;
470 width: 200px;
471 height: 200px;
472 top: 50%;
473 left: 50%;
474 margin: -100px 0 0 -100px;
475 -webkit-transform: scale(0.25);
476 -ms-transform: scale(0.25);
477 transform: scale(0.25);
478 }
479
480 .modaal-loading-spinner > div {
481 width: 24px;
482 height: 24px;
483 margin-left: 4px;
484 margin-top: 4px;
485 position: absolute;
486 }
487
488 .modaal-loading-spinner > div > div {
489 width: 100%;
490 height: 100%;
491 border-radius: 15px;
492 background: #fff;
493 }
494
495 .modaal-loading-spinner > div:nth-of-type(1) > div {
496 -webkit-animation: modaal-loading-spinner 1s linear infinite;
497 animation: modaal-loading-spinner 1s linear infinite;
498 -webkit-animation-delay: 0s;
499 animation-delay: 0s;
500 }
501
502 .modaal-loading-spinner > div:nth-of-type(2) > div,
503 .modaal-loading-spinner > div:nth-of-type(3) > div {
504 -ms-animation: modaal-loading-spinner 1s linear infinite;
505 -moz-animation: modaal-loading-spinner 1s linear infinite;
506 -webkit-animation: modaal-loading-spinner 1s linear infinite;
507 -o-animation: modaal-loading-spinner 1s linear infinite;
508 }
509
510 .modaal-loading-spinner > div:nth-of-type(1) {
511 -ms-transform: translate(84px, 84px) rotate(45deg) translate(70px, 0);
512 -webkit-transform: translate(84px, 84px) rotate(45deg) translate(70px, 0);
513 transform: translate(84px, 84px) rotate(45deg) translate(70px, 0);
514 }
515
516 .modaal-loading-spinner > div:nth-of-type(2) > div {
517 -webkit-animation: modaal-loading-spinner 1s linear infinite;
518 animation: modaal-loading-spinner 1s linear infinite;
519 -webkit-animation-delay: .12s;
520 animation-delay: .12s;
521 }
522
523 .modaal-loading-spinner > div:nth-of-type(2) {
524 -ms-transform: translate(84px, 84px) rotate(90deg) translate(70px, 0);
525 -webkit-transform: translate(84px, 84px) rotate(90deg) translate(70px, 0);
526 transform: translate(84px, 84px) rotate(90deg) translate(70px, 0);
527 }
528
529 .modaal-loading-spinner > div:nth-of-type(3) > div {
530 -webkit-animation: modaal-loading-spinner 1s linear infinite;
531 animation: modaal-loading-spinner 1s linear infinite;
532 -webkit-animation-delay: .25s;
533 animation-delay: .25s;
534 }
535
536 .modaal-loading-spinner > div:nth-of-type(4) > div,
537 .modaal-loading-spinner > div:nth-of-type(5) > div {
538 -ms-animation: modaal-loading-spinner 1s linear infinite;
539 -moz-animation: modaal-loading-spinner 1s linear infinite;
540 -webkit-animation: modaal-loading-spinner 1s linear infinite;
541 -o-animation: modaal-loading-spinner 1s linear infinite;
542 }
543
544 .modaal-loading-spinner > div:nth-of-type(3) {
545 -ms-transform: translate(84px, 84px) rotate(135deg) translate(70px, 0);
546 -webkit-transform: translate(84px, 84px) rotate(135deg) translate(70px, 0);
547 transform: translate(84px, 84px) rotate(135deg) translate(70px, 0);
548 }
549
550 .modaal-loading-spinner > div:nth-of-type(4) > div {
551 -webkit-animation: modaal-loading-spinner 1s linear infinite;
552 animation: modaal-loading-spinner 1s linear infinite;
553 -webkit-animation-delay: .37s;
554 animation-delay: .37s;
555 }
556
557 .modaal-loading-spinner > div:nth-of-type(4) {
558 -ms-transform: translate(84px, 84px) rotate(180deg) translate(70px, 0);
559 -webkit-transform: translate(84px, 84px) rotate(180deg) translate(70px, 0);
560 transform: translate(84px, 84px) rotate(180deg) translate(70px, 0);
561 }
562
563 .modaal-loading-spinner > div:nth-of-type(5) > div {
564 -webkit-animation: modaal-loading-spinner 1s linear infinite;
565 animation: modaal-loading-spinner 1s linear infinite;
566 -webkit-animation-delay: .5s;
567 animation-delay: .5s;
568 }
569
570 .modaal-loading-spinner > div:nth-of-type(6) > div,
571 .modaal-loading-spinner > div:nth-of-type(7) > div {
572 -ms-animation: modaal-loading-spinner 1s linear infinite;
573 -moz-animation: modaal-loading-spinner 1s linear infinite;
574 -webkit-animation: modaal-loading-spinner 1s linear infinite;
575 -o-animation: modaal-loading-spinner 1s linear infinite;
576 }
577
578 .modaal-loading-spinner > div:nth-of-type(5) {
579 -ms-transform: translate(84px, 84px) rotate(225deg) translate(70px, 0);
580 -webkit-transform: translate(84px, 84px) rotate(225deg) translate(70px, 0);
581 transform: translate(84px, 84px) rotate(225deg) translate(70px, 0);
582 }
583
584 .modaal-loading-spinner > div:nth-of-type(6) > div {
585 -webkit-animation: modaal-loading-spinner 1s linear infinite;
586 animation: modaal-loading-spinner 1s linear infinite;
587 -webkit-animation-delay: .62s;
588 animation-delay: .62s;
589 }
590
591 .modaal-loading-spinner > div:nth-of-type(6) {
592 -ms-transform: translate(84px, 84px) rotate(270deg) translate(70px, 0);
593 -webkit-transform: translate(84px, 84px) rotate(270deg) translate(70px, 0);
594 transform: translate(84px, 84px) rotate(270deg) translate(70px, 0);
595 }
596
597 .modaal-loading-spinner > div:nth-of-type(7) > div {
598 -webkit-animation: modaal-loading-spinner 1s linear infinite;
599 animation: modaal-loading-spinner 1s linear infinite;
600 -webkit-animation-delay: .75s;
601 animation-delay: .75s;
602 }
603
604 .modaal-loading-spinner > div:nth-of-type(7) {
605 -ms-transform: translate(84px, 84px) rotate(315deg) translate(70px, 0);
606 -webkit-transform: translate(84px, 84px) rotate(315deg) translate(70px, 0);
607 transform: translate(84px, 84px) rotate(315deg) translate(70px, 0);
608 }
609
610 .modaal-loading-spinner > div:nth-of-type(8) > div {
611 -webkit-animation: modaal-loading-spinner 1s linear infinite;
612 animation: modaal-loading-spinner 1s linear infinite;
613 -webkit-animation-delay: .87s;
614 animation-delay: .87s;
615 }
616
617 .modaal-loading-spinner > div:nth-of-type(8) {
618 -ms-transform: translate(84px, 84px) rotate(360deg) translate(70px, 0);
619 -webkit-transform: translate(84px, 84px) rotate(360deg) translate(70px, 0);
620 transform: translate(84px, 84px) rotate(360deg) translate(70px, 0);
621 }
622
623 @media only screen and (min-width: 1400px) {
624
625 .modaal-video-container {
626 padding-bottom: 0;
627 height: 731px;
628 }
629
630 }
631
632 @media only screen and (max-width: 1140px) {
633
634 .modaal-image .modaal-inner-wrapper {
635 padding-left: 25px;
636 padding-right: 25px;
637 }
638
639 .modaal-gallery-control {
640 top: auto;
641 bottom: 20px;
642 -webkit-transform: none;
643 -ms-transform: none;
644 transform: none;
645 background: rgba(0, 0, 0, 0.7);
646 }
647
648 .modaal-gallery-control:before,
649 .modaal-gallery-control:after {
650 background: #fff;
651 }
652
653 .modaal-gallery-next {
654 left: auto;
655 right: 20px;
656 }
657
658 .modaal-gallery-prev {
659 left: 20px;
660 right: auto;
661 }
662
663 }
664
665 @media screen and (max-width: 900px) {
666
667 .modaal-instagram iframe {
668 width: 500px !important;
669 }
670
671 }
672
673 @media only screen and (max-width: 600px) {
674
675 .modaal-instagram iframe {
676 width: 280px !important;
677 }
678
679 }
680
681 @media screen and (max-height: 1100px) {
682
683 .modaal-instagram iframe {
684 width: 700px !important;
685 }
686
687 }
688
689 @media screen and (max-height: 1000px) {
690
691 .modaal-inner-wrapper {
692 padding-top: 60px;
693 padding-bottom: 60px;
694 }
695
696 .modaal-instagram iframe {
697 width: 600px !important;
698 }
699
700 }
701
702 @media screen and (max-height: 900px) {
703
704 .modaal-instagram iframe {
705 width: 500px !important;
706 }
707
708 .modaal-video-container {
709 max-width: 900px;
710 max-height: 510px;
711 }
712
713 }
714
715 @media only screen and (max-height: 820px) {
716
717 .modaal-gallery-label {
718 display: none;
719 }
720
721 }
722
723 @keyframes instaReveal {
724
725 0% {
726 opacity: 0;
727 }
728
729 100% {
730 opacity: 1;
731 }
732
733 }
734
735 @-webkit-keyframes instaReveal {
736
737 0% {
738 opacity: 0;
739 }
740
741 100% {
742 opacity: 1;
743 }
744
745 }
746
747 @-webkit-keyframes modaal-loading-spinner {
748
749 0% {
750 opacity: 1;
751 -ms-transform: scale(1.5);
752 -webkit-transform: scale(1.5);
753 transform: scale(1.5);
754 }
755
756 100% {
757 opacity: .1;
758 -ms-transform: scale(1);
759 -webkit-transform: scale(1);
760 transform: scale(1);
761 }
762
763 }
764
765 @keyframes modaal-loading-spinner {
766
767 0% {
768 opacity: 1;
769 -ms-transform: scale(1.5);
770 -webkit-transform: scale(1.5);
771 transform: scale(1.5);
772 }
773
774 100% {
775 opacity: .1;
776 -ms-transform: scale(1);
777 -webkit-transform: scale(1);
778 transform: scale(1);
779 }
780
781 }
782
1 /*!
2 Modaal - accessible modals - v0.4.4
3 by Humaan, for all humans.
4 http://humaan.com
5 */.modaal-noscroll{overflow:hidden}.modaal-accessible-hide{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}.modaal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999;opacity:0}.modaal-wrapper{display:block;position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999;overflow:auto;opacity:1;box-sizing:border-box;-webkit-overflow-scrolling:touch;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.modaal-wrapper *{box-sizing:border-box;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden}.modaal-wrapper .modaal-close{border:none;background:0 0;padding:0;-webkit-appearance:none}.modaal-wrapper.modaal-start_none{display:none;opacity:1}.modaal-wrapper.modaal-start_fade{opacity:0}.modaal-wrapper [tabindex="0"]{outline:0!important}.modaal-wrapper.modaal-fullscreen{overflow:hidden}.modaal-outer-wrapper{display:table;position:relative;width:100%;height:100%}.modaal-fullscreen .modaal-outer-wrapper{display:block}.modaal-inner-wrapper{display:table-cell;width:100%;height:100%;position:relative;vertical-align:middle;text-align:center;padding:80px 25px}.modaal-fullscreen .modaal-inner-wrapper{padding:0;display:block;vertical-align:top}.modaal-container{position:relative;display:inline-block;width:100%;margin:auto;text-align:left;color:#000;max-width:1000px;border-radius:0;background:#fff;box-shadow:0 4px 15px rgba(0,0,0,.2);cursor:auto}.modaal-container.is_loading{height:100px;width:100px;overflow:hidden}.modaal-fullscreen .modaal-container{max-width:none;height:100%;overflow:auto}.modaal-close{position:fixed;right:20px;top:20px;color:#fff;cursor:pointer;opacity:1;width:50px;height:50px;background:rgba(0,0,0,0);border-radius:100%;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.modaal-close:focus,.modaal-close:hover{outline:0;background:#fff}.modaal-close:focus:after,.modaal-close:focus:before,.modaal-close:hover:after,.modaal-close:hover:before{background:#b93d0c}.modaal-close span{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}.modaal-close:after,.modaal-close:before{display:block;content:" ";position:absolute;top:14px;left:23px;width:4px;height:22px;border-radius:4px;background:#fff;-webkit-transition:background .2s ease-in-out;transition:background .2s ease-in-out}.modaal-close:before{-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.modaal-close:after{-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.modaal-fullscreen .modaal-close{background:#afb7bc;right:10px;top:10px}.modaal-content-container{padding:30px}.modaal-confirm-wrap{padding:30px 0 0;text-align:center;font-size:0}.modaal-confirm-btn{font-size:14px;display:inline-block;margin:0 10px;vertical-align:middle;cursor:pointer;border:none;background:0 0}.modaal-confirm-btn.modaal-ok{padding:10px 15px;color:#fff;background:#555;border-radius:3px;-webkit-transition:background .2s ease-in-out;transition:background .2s ease-in-out}.modaal-confirm-btn.modaal-ok:hover{background:#2f2f2f}.modaal-confirm-btn.modaal-cancel{text-decoration:underline}.modaal-confirm-btn.modaal-cancel:hover{text-decoration:none;color:#2f2f2f}.modaal-instagram .modaal-container{width:auto;background:0 0;box-shadow:none!important}.modaal-instagram .modaal-content-container{padding:0;background:0 0}.modaal-instagram .modaal-content-container>blockquote{width:1px!important;height:1px!important;opacity:0!important}.modaal-instagram iframe{opacity:0;margin:-6px!important;border-radius:0!important;width:1000px!important;max-width:800px!important;box-shadow:none!important;-webkit-animation:instaReveal 1s linear forwards;animation:instaReveal 1s linear forwards}.modaal-image .modaal-inner-wrapper{padding-left:140px;padding-right:140px}.modaal-image .modaal-container{width:auto;max-width:100%}.modaal-gallery-wrap{position:relative;color:#fff}.modaal-gallery-item{display:none}.modaal-gallery-item img{display:block}.modaal-gallery-item.is_active{display:block}.modaal-gallery-label{position:absolute;left:0;width:100%;margin:20px 0 0;font-size:18px;text-align:center;color:#fff}.modaal-gallery-label:focus{outline:0}.modaal-gallery-control{position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);opacity:1;cursor:pointer;color:#fff;width:50px;height:50px;background:rgba(0,0,0,0);border:none;border-radius:100%;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.modaal-gallery-control.is_hidden{opacity:0;cursor:default}.modaal-gallery-control:focus,.modaal-gallery-control:hover{outline:0;background:#fff}.modaal-gallery-control:focus:after,.modaal-gallery-control:focus:before,.modaal-gallery-control:hover:after,.modaal-gallery-control:hover:before{background:#afb7bc}.modaal-gallery-control span{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}.modaal-gallery-control:after,.modaal-gallery-control:before{display:block;content:" ";position:absolute;top:16px;left:25px;width:4px;height:18px;border-radius:4px;background:#fff;-webkit-transition:background .2s ease-in-out;transition:background .2s ease-in-out}.modaal-gallery-control:before{margin:-5px 0 0;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.modaal-gallery-control:after{margin:5px 0 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.modaal-gallery-next-inner{left:100%;margin-left:40px}.modaal-gallery-next-outer{right:45px}.modaal-gallery-prev:after,.modaal-gallery-prev:before{left:22px}.modaal-gallery-prev:before{margin:5px 0 0;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.modaal-gallery-prev:after{margin:-5px 0 0;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.modaal-gallery-prev-inner{right:100%;margin-right:40px}.modaal-gallery-prev-outer{left:45px}.modaal-video-wrap{margin:auto 50px;position:relative}.modaal-video-container{position:relative;padding-bottom:56.25%;height:0;overflow:hidden;max-width:100%;box-shadow:0 0 10px rgba(0,0,0,.3);background:#000;max-width:1300px;margin-left:auto;margin-right:auto}.modaal-video-container embed,.modaal-video-container iframe,.modaal-video-container object{position:absolute;top:0;left:0;width:100%;height:100%}.modaal-iframe .modaal-content{width:100%;height:100%}.modaal-iframe-elem{width:100%;height:100%;display:block}.modaal-loading-spinner{background:0 0;position:absolute;width:200px;height:200px;top:50%;left:50%;margin:-100px 0 0 -100px;-webkit-transform:scale(.25);-ms-transform:scale(.25);transform:scale(.25)}.modaal-loading-spinner>div{width:24px;height:24px;margin-left:4px;margin-top:4px;position:absolute}.modaal-loading-spinner>div>div{width:100%;height:100%;border-radius:15px;background:#fff}.modaal-loading-spinner>div:nth-of-type(1)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:0s;animation-delay:0s}.modaal-loading-spinner>div:nth-of-type(2)>div,.modaal-loading-spinner>div:nth-of-type(3)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite}.modaal-loading-spinner>div:nth-of-type(1){-ms-transform:translate(84px,84px) rotate(45deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(45deg) translate(70px,0);transform:translate(84px,84px) rotate(45deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(2)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.12s;animation-delay:.12s}.modaal-loading-spinner>div:nth-of-type(2){-ms-transform:translate(84px,84px) rotate(90deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(90deg) translate(70px,0);transform:translate(84px,84px) rotate(90deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(3)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.25s;animation-delay:.25s}.modaal-loading-spinner>div:nth-of-type(4)>div,.modaal-loading-spinner>div:nth-of-type(5)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite}.modaal-loading-spinner>div:nth-of-type(3){-ms-transform:translate(84px,84px) rotate(135deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(135deg) translate(70px,0);transform:translate(84px,84px) rotate(135deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(4)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.37s;animation-delay:.37s}.modaal-loading-spinner>div:nth-of-type(4){-ms-transform:translate(84px,84px) rotate(180deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(180deg) translate(70px,0);transform:translate(84px,84px) rotate(180deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(5)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.5s;animation-delay:.5s}.modaal-loading-spinner>div:nth-of-type(6)>div,.modaal-loading-spinner>div:nth-of-type(7)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite}.modaal-loading-spinner>div:nth-of-type(5){-ms-transform:translate(84px,84px) rotate(225deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(225deg) translate(70px,0);transform:translate(84px,84px) rotate(225deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(6)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.62s;animation-delay:.62s}.modaal-loading-spinner>div:nth-of-type(6){-ms-transform:translate(84px,84px) rotate(270deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(270deg) translate(70px,0);transform:translate(84px,84px) rotate(270deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(7)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.75s;animation-delay:.75s}.modaal-loading-spinner>div:nth-of-type(7){-ms-transform:translate(84px,84px) rotate(315deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(315deg) translate(70px,0);transform:translate(84px,84px) rotate(315deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(8)>div{-webkit-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-webkit-animation-delay:.87s;animation-delay:.87s}.modaal-loading-spinner>div:nth-of-type(8){-ms-transform:translate(84px,84px) rotate(360deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(360deg) translate(70px,0);transform:translate(84px,84px) rotate(360deg) translate(70px,0)}@media only screen and (min-width:1400px){.modaal-video-container{padding-bottom:0;height:731px}}@media only screen and (max-width:1140px){.modaal-image .modaal-inner-wrapper{padding-left:25px;padding-right:25px}.modaal-gallery-control{top:auto;bottom:20px;-webkit-transform:none;-ms-transform:none;transform:none;background:rgba(0,0,0,.7)}.modaal-gallery-control:after,.modaal-gallery-control:before{background:#fff}.modaal-gallery-next{left:auto;right:20px}.modaal-gallery-prev{left:20px;right:auto}}@media screen and (max-width:900px){.modaal-instagram iframe{width:500px!important}}@media only screen and (max-width:600px){.modaal-instagram iframe{width:280px!important}}@media screen and (max-height:1100px){.modaal-instagram iframe{width:700px!important}}@media screen and (max-height:1000px){.modaal-inner-wrapper{padding-top:60px;padding-bottom:60px}.modaal-instagram iframe{width:600px!important}}@media screen and (max-height:900px){.modaal-instagram iframe{width:500px!important}.modaal-video-container{max-width:900px;max-height:510px}}@media only screen and (max-height:820px){.modaal-gallery-label{display:none}}@keyframes instaReveal{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes instaReveal{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-webkit-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1)}}@keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-webkit-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-webkit-transform:scale(1);transform:scale(1)}}
...\ No newline at end of file ...\ No newline at end of file
1 /*!
2 Modaal - accessible modals - v0.4.4
3 by Humaan, for all humans.
4 http://humaan.com
5 */
6
7 // Modaal Variables
8 // --------------------------------------------------------
9
10 $modaal-overlay-color: rgba(0,0,0, 0.8);
11
12 $modaal-radius: 0px; //5px
13 $modaal-main-bg: #fff;
14 $modaal-main-text: #000;
15 $modaal-max-width: 1000px;
16 $modaal-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
17 $modaal-padding: 30px;
18 $modaal-hover-color: rgba(0,0,0, 0.7);
19 $modaal-close-hover-color: #b93d0c;
20
21 $modaal-light: #fff;
22 $modaal-primary: #555;
23 $modaal-grey: #afb7bc;
24
25
26 // Modaal Mixins
27 // --------------------------------------------------------
28 @mixin modaal-transition($type, $speed: .2s, $ease: ease-in-out) {
29 transition: $type #{$speed} #{$ease};
30 }
31 @mixin modaal-hidetext() {
32 position: absolute !important;
33 clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
34 clip: rect(1px, 1px, 1px, 1px);
35 padding:0 !important;
36 border:0 !important;
37 height: 1px !important;
38 width: 1px !important;
39 overflow: hidden;
40 }
41
42
43 // Modaal Structure
44 // --------------------------------------------------------
45 .modaal-noscroll {
46 overflow: hidden;
47 }
48 .modaal-accessible-hide {
49 @include modaal-hidetext;
50 }
51
52 .modaal-overlay {
53 position: fixed;
54 top: 0;
55 left: 0;
56 width: 100%;
57 height: 100%;
58 z-index: 999;
59 opacity: 0;
60 }
61 .modaal-wrapper {
62 display: block;
63 position: fixed;
64 top: 0;
65 left: 0;
66 width: 100%;
67 height: 100%;
68 z-index: 9999;
69 overflow: auto;
70 opacity: 1;
71 box-sizing: border-box;
72 -webkit-overflow-scrolling: touch;
73 @include modaal-transition(all, 0.3s);
74 & * {
75 box-sizing: border-box;
76 -webkit-font-smoothing: antialiased;
77 -moz-osx-font-smoothing: grayscale;
78 -webkit-backface-visibility: hidden;
79 }
80 .modaal-close {
81 border: none;
82 background: transparent;
83 padding: 0;
84 -webkit-appearance: none;
85 }
86
87 &.modaal-start_none {
88 display: none;
89 opacity: 1;
90 }
91 &.modaal-start_fade {
92 opacity: 0;
93 }
94
95 & *[tabindex="0"] {
96 outline: none !important;
97 }
98
99 // is fullscreen
100 &.modaal-fullscreen {
101 overflow: hidden;
102 }
103 }
104 .modaal-outer-wrapper {
105 display: table;
106 position: relative;
107 width: 100%;
108 height: 100%;
109 .modaal-fullscreen & {
110 display: block;
111 }
112 }
113 .modaal-inner-wrapper {
114 display: table-cell;
115 width: 100%;
116 height: 100%;
117 position: relative;
118 vertical-align: middle;
119 text-align: center;
120 padding: 80px 25px;
121
122 // when is fullscreen
123 .modaal-fullscreen & {
124 padding: 0;
125 display: block;
126 vertical-align: top;
127 }
128 }
129 .modaal-container {
130 position: relative;
131 display: inline-block;
132 width: 100%;
133 margin: auto;
134 text-align: left;
135 color: $modaal-main-text;
136 max-width: $modaal-max-width;
137 border-radius: $modaal-radius;
138 background: $modaal-main-bg;
139 box-shadow: $modaal-shadow;
140 cursor: auto;
141
142 // while loading
143 &.is_loading {
144 height: 100px;
145 width: 100px;
146 overflow: hidden;
147 }
148 // when is fullscreen
149 .modaal-fullscreen & {
150 max-width: none;
151 height: 100%;
152 overflow: auto;
153 }
154 }
155
156 .modaal-close {
157 position: fixed;
158 right: 20px;
159 top: 20px;
160 color: $modaal-light;
161 cursor: pointer;
162 opacity: 1;
163 width: 50px;
164 height: 50px;
165 background: rgba(0,0,0, 0);
166 border-radius: 100%;
167 @include modaal-transition(all);
168 &:focus,
169 &:hover {
170 outline: none;
171 background: #fff;
172 &:before,
173 &:after { background: $modaal-close-hover-color; }
174 }
175 span {
176 @include modaal-hidetext;
177 }
178 &:before,
179 &:after {
180 display: block;
181 content: " ";
182 position: absolute;
183 top: 14px;
184 left: 23px;
185 width: 4px;
186 height: 22px;
187 border-radius: 4px;
188 background: #fff;
189 @include modaal-transition(background);
190 }
191 &:before {
192 transform: rotate(-45deg);
193 }
194 &:after {
195 transform: rotate(45deg);
196 }
197 .modaal-fullscreen & {
198 background: $modaal-grey;
199 right: 10px;
200 top: 10px;
201 }
202 }
203
204 .modaal-content-container {
205 padding: $modaal-padding;
206 }
207
208
209 // Confirm Modaal
210 // --------------------------------------------------------
211
212 .modaal-confirm-wrap {
213 padding: 30px 0 0;
214 text-align: center;
215 font-size: 0;
216 }
217 .modaal-confirm-btn {
218 font-size: 14px;
219 display: inline-block;
220 margin: 0 10px;
221 vertical-align: middle;
222 cursor: pointer;
223 border: none;
224 background: transparent;
225
226 // Ok Button
227 &.modaal-ok {
228 padding: 10px 15px;
229 color: $modaal-light;
230 background: $modaal-primary;
231 border-radius: 3px;
232 @include modaal-transition(background);
233 &:hover {
234 background: darken($modaal-primary, 15%);
235 }
236 }
237 &.modaal-cancel {
238 text-decoration: underline;
239 &:hover {
240 text-decoration: none;
241 color: darken($modaal-primary, 15%);
242 }
243 }
244 }
245
246
247
248 @keyframes instaReveal {
249 0% { opacity: 0; }
250 100% { opacity: 1; }
251 }
252 @-o-keyframes instaReveal {
253 0% { opacity: 0; }
254 100% { opacity: 1; }
255 }
256 @-moz-keyframes instaReveal {
257 0% { opacity: 0; }
258 100% { opacity: 1; }
259 }
260 @-webkit-keyframes instaReveal {
261 0% { opacity: 0; }
262 100% { opacity: 1; }
263 }
264 @-ms-keyframes instaReveal {
265 0% { opacity: 0; }
266 100% { opacity: 1; }
267 }
268
269 // Instagram Photo
270 // --------------------------------------------------------
271
272 .modaal-instagram {
273 .modaal-container {
274 width: auto;
275 background: transparent;
276 box-shadow: none !important;
277 }
278 .modaal-content-container {
279 padding: 0;
280 background: transparent;
281 }
282 .modaal-content-container > blockquote {
283 width: 1px !important;
284 height: 1px !important;
285 opacity: 0 !important;
286 }
287 iframe {
288 opacity: 0;
289 margin: -6px !important;
290 border-radius: 0 !important;
291 width: 1000px !important;
292 max-width: 800px !important;
293 box-shadow: none !important;
294
295 animation: instaReveal 1s linear forwards;
296 }
297 }
298
299
300
301 // Gallery
302 // --------------------------------------------------------
303 .modaal-image {
304 .modaal-inner-wrapper {
305 padding-left: 140px;
306 padding-right: 140px;
307 }
308 .modaal-container {
309 width: auto;
310 max-width: 100%;
311 }
312 }
313
314 .modaal-gallery-wrap {
315 position: relative;
316 color: $modaal-light;
317 }
318 .modaal-gallery-item {
319 display: none;
320 img {
321 display: block;
322 //width: 100%;
323 }
324 &.is_active {
325 display: block;
326 }
327 }
328 .modaal-gallery-label {
329 position: absolute;
330 left: 0;
331 width: 100%;
332 margin: 20px 0 0;
333 font-size: 18px;
334 text-align: center;
335 color: #fff;
336 &:focus {
337 outline: none;
338 }
339 }
340 .modaal-gallery-control {
341 position: absolute;
342 top: 50%;
343 transform: translateY(-50%);
344 opacity: 1;
345 cursor: pointer;
346 color: $modaal-light;
347 width: 50px;
348 height: 50px;
349 background: rgba(0,0,0, 0);
350 border: none;
351 border-radius: 100%;
352 @include modaal-transition(all);
353 &.is_hidden {
354 opacity: 0;
355 cursor: default;
356 }
357 &:focus,
358 &:hover {
359 outline: none;
360 background: #fff;
361 &:before,
362 &:after {
363 background: $modaal-grey;
364 }
365 }
366 span {
367 @include modaal-hidetext;
368 }
369
370 &:before,
371 &:after {
372 display: block;
373 content: " ";
374 position: absolute;
375 top: 16px;
376 left: 25px;
377 width: 4px;
378 height: 18px;
379 border-radius: 4px;
380 background: #fff;
381 @include modaal-transition(background);
382 }
383 &:before {
384 margin: -5px 0 0;
385 transform: rotate(-45deg);
386 }
387 &:after {
388 margin: 5px 0 0;
389 transform: rotate(45deg);
390 }
391 }
392 .modaal-gallery-next {
393 &-inner {
394 left: 100%;
395 margin-left: 40px;
396 }
397 &-outer {
398 right: 45px;
399 }
400 }
401 .modaal-gallery-prev {
402 &:before,
403 &:after { left: 22px; }
404 &:before {
405 margin: 5px 0 0;
406 transform: rotate(-45deg);
407 }
408 &:after {
409 margin: -5px 0 0;
410 transform: rotate(45deg);
411 }
412
413 &-inner {
414 right: 100%;
415 margin-right: 40px;
416 }
417 &-outer {
418 left: 45px;
419 }
420 }
421
422
423 // Video
424 // --------------------------------------------------------
425 .modaal-video-wrap {
426 margin: auto 50px;
427 position: relative;
428 }
429
430 .modaal-video-container {
431 position: relative;
432 padding-bottom: 56.25%;
433 height: 0;
434 overflow: hidden;
435 max-width: 100%;
436 box-shadow: 0 0 10px rgba(0,0,0, 0.3);
437 background: #000;
438 max-width: 1300px;
439 margin-left: auto;
440 margin-right: auto;
441 iframe,
442 object,
443 embed {
444 position: absolute;
445 top: 0;
446 left: 0;
447 width: 100%;
448 height: 100%;
449 }
450 }
451
452 // Modaal iFrame
453 // --------------------------------------------------------
454 .modaal-iframe .modaal-content {
455 width: 100%;
456 height: 100%;
457 }
458 .modaal-iframe-elem {
459 width: 100%;
460 height: 100%;
461 display: block;
462 }
463
464
465 // Responsive styles
466 // --------------------------------------------------------
467 @media only screen and (min-width: 1400px) {
468 .modaal-video-container {
469 padding-bottom: 0;
470 height: 731px;
471 }
472 }
473
474 @media only screen and (max-width: 1140px) {
475 .modaal-image {
476 .modaal-inner-wrapper {
477 padding-left: 25px;
478 padding-right: 25px;
479 }
480 }
481 .modaal-gallery-control {
482 top: auto;
483 bottom: 20px;
484 transform: none;
485 background: rgba(0,0,0, 0.7);;
486 &:before,
487 &:after {
488 background: #fff;
489 }
490 }
491 .modaal-gallery-next {
492 left: auto;
493 right: 20px;
494 }
495 .modaal-gallery-prev {
496 left: 20px;
497 right: auto;
498 }
499 }
500
501 @media screen and (max-width: 900px) {
502 .modaal-instagram iframe {
503 width: 500px !important;
504 }
505 }
506 @media screen and (max-height: 1100px) {
507 .modaal-instagram iframe {
508 width: 700px !important;
509 }
510 }
511 @media screen and (max-height: 1000px) {
512 .modaal-inner-wrapper {
513 padding-top: 60px;
514 padding-bottom: 60px;
515 }
516 .modaal-instagram iframe {
517 width: 600px !important;
518 }
519 }
520 @media screen and (max-height: 900px) {
521 .modaal-instagram iframe {
522 width: 500px !important;
523 }
524 .modaal-video-container {
525 max-width: 900px;
526 max-height: 510px;
527 }
528 }
529
530 @media only screen and (max-width: 600px) {
531 .modaal-instagram iframe {
532 width: 280px !important;
533 }
534 }
535 @media only screen and (max-height: 820px) {
536 .modaal-gallery-label {
537 display: none;
538 }
539 }
540
541
542
543 // CSS loading gif
544 // --------------------------------------------------------
545 .modaal-loading-spinner {
546 background: none;
547 position: absolute;
548 width: 200px;
549 height: 200px;
550 top: 50%;
551 left: 50%;
552 margin: -100px 0 0 -100px;
553 transform: scale(0.25);
554 }
555 @-ms-keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-moz-transform:scale(1.5);-webkit-transform:scale(1.5);-o-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-moz-keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-moz-transform:scale(1.5);-webkit-transform:scale(1.5);-o-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-webkit-keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-moz-transform:scale(1.5);-webkit-transform:scale(1.5);-o-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-o-keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-moz-transform:scale(1.5);-webkit-transform:scale(1.5);-o-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@keyframes modaal-loading-spinner{0%{opacity:1;-ms-transform:scale(1.5);-moz-transform:scale(1.5);-webkit-transform:scale(1.5);-o-transform:scale(1.5);transform:scale(1.5)}100%{opacity:.1;-ms-transform:scale(1);-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}.modaal-loading-spinner>div{width:24px;height:24px;margin-left:4px;margin-top:4px;position:absolute}.modaal-loading-spinner>div>div{width:100%;height:100%;border-radius:15px;background:#fff}.modaal-loading-spinner>div:nth-of-type(1)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:0s;-moz-animation-delay:0s;-webkit-animation-delay:0s;-o-animation-delay:0s;animation-delay:0s}.modaal-loading-spinner>div:nth-of-type(2)>div,.modaal-loading-spinner>div:nth-of-type(3)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite}.modaal-loading-spinner>div:nth-of-type(1){-ms-transform:translate(84px,84px) rotate(45deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(45deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(45deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(45deg) translate(70px,0);transform:translate(84px,84px) rotate(45deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(2)>div{animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.12s;-moz-animation-delay:.12s;-webkit-animation-delay:.12s;-o-animation-delay:.12s;animation-delay:.12s}.modaal-loading-spinner>div:nth-of-type(2){-ms-transform:translate(84px,84px) rotate(90deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(90deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(90deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(90deg) translate(70px,0);transform:translate(84px,84px) rotate(90deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(3)>div{animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.25s;-moz-animation-delay:.25s;-webkit-animation-delay:.25s;-o-animation-delay:.25s;animation-delay:.25s}.modaal-loading-spinner>div:nth-of-type(4)>div,.modaal-loading-spinner>div:nth-of-type(5)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite}.modaal-loading-spinner>div:nth-of-type(3){-ms-transform:translate(84px,84px) rotate(135deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(135deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(135deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(135deg) translate(70px,0);transform:translate(84px,84px) rotate(135deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(4)>div{animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.37s;-moz-animation-delay:.37s;-webkit-animation-delay:.37s;-o-animation-delay:.37s;animation-delay:.37s}.modaal-loading-spinner>div:nth-of-type(4){-ms-transform:translate(84px,84px) rotate(180deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(180deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(180deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(180deg) translate(70px,0);transform:translate(84px,84px) rotate(180deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(5)>div{animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.5s;-moz-animation-delay:.5s;-webkit-animation-delay:.5s;-o-animation-delay:.5s;animation-delay:.5s}.modaal-loading-spinner>div:nth-of-type(6)>div,.modaal-loading-spinner>div:nth-of-type(7)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite}.modaal-loading-spinner>div:nth-of-type(5){-ms-transform:translate(84px,84px) rotate(225deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(225deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(225deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(225deg) translate(70px,0);transform:translate(84px,84px) rotate(225deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(6)>div{animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.62s;-moz-animation-delay:.62s;-webkit-animation-delay:.62s;-o-animation-delay:.62s;animation-delay:.62s}.modaal-loading-spinner>div:nth-of-type(6){-ms-transform:translate(84px,84px) rotate(270deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(270deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(270deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(270deg) translate(70px,0);transform:translate(84px,84px) rotate(270deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(7)>div{animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.75s;-moz-animation-delay:.75s;-webkit-animation-delay:.75s;-o-animation-delay:.75s;animation-delay:.75s}.modaal-loading-spinner>div:nth-of-type(7){-ms-transform:translate(84px,84px) rotate(315deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(315deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(315deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(315deg) translate(70px,0);transform:translate(84px,84px) rotate(315deg) translate(70px,0)}.modaal-loading-spinner>div:nth-of-type(8)>div{-ms-animation:modaal-loading-spinner 1s linear infinite;-moz-animation:modaal-loading-spinner 1s linear infinite;-webkit-animation:modaal-loading-spinner 1s linear infinite;-o-animation:modaal-loading-spinner 1s linear infinite;animation:modaal-loading-spinner 1s linear infinite;-ms-animation-delay:.87s;-moz-animation-delay:.87s;-webkit-animation-delay:.87s;-o-animation-delay:.87s;animation-delay:.87s}.modaal-loading-spinner>div:nth-of-type(8){-ms-transform:translate(84px,84px) rotate(360deg) translate(70px,0);-moz-transform:translate(84px,84px) rotate(360deg) translate(70px,0);-webkit-transform:translate(84px,84px) rotate(360deg) translate(70px,0);-o-transform:translate(84px,84px) rotate(360deg) translate(70px,0);transform:translate(84px,84px) rotate(360deg) translate(70px,0)}
1 /*!
2 Modaal - accessible modals - v0.4.4
3 by Humaan, for all humans.
4 http://humaan.com
5 */
6 /**
7 Modaal jQuery Plugin : Accessible Modals
8
9 ==== General Options ===
10 type (string) : ajax, inline, image, iframe, confirm. Defaults to 'inline'
11 content_source (stribg) : Accepts a string value for your target element, such as '#my-content'. This allows for when trigger element is
12 an `<a href="#">` link. Not to be confused with the already existing `source` event.
13 animation (string) : Fade, expand, down, up. Defaults to 'fade'
14 after_callback_delay (integer) : Specify a delay value for the after open callbacks. This is necessary because with the bundled animations
15 have a set duration in the bundled CSS. Specify a delay of the same amount as the animation duration in so
16 more accurately fire the after open/close callbacks. Defaults 350, does not apply if animation is 'none',
17 after open callbacks are dispatched immediately
18
19 is_locked (boolean) : Set this to true to disable closing the modal via keypress or clicking the background. Beware that if
20 type != 'confirm' there will be no interface to dismiss the modal if is_locked = true, you'd have to
21 programmatically arrange to dismiss the modal. Confirm modals are always locked regardless of this option
22 Defaults to false
23
24 hide_close (boolean) : Set this to true to hide the close modal button. Key press and overlay click will still close the modal.
25 This method is best used when you want to put a custom close button inside the modal container space.
26
27 background (string) : Background overlay style. Defaults to '#000'
28 overlay_opacity (float) : Background overlay transparency. Defaults to 0.8
29 overlay_close (boolean) : Set this to false if you want to disable click to close on overlay background.
30
31 accessible_title (string) : Accessible title. Default 'Dialog Window'
32 start_open (boolean) : Set this to true to launch the Modaal window immediately on page open
33 fullscreen (boolean) : Set this to true to make the modaal fill the entire screen, false will default to own width/height attributes.
34 custom_class (string) : Fill in this string with a custom class that will be applied to the outer most modal wrapper.
35
36 width (integer) : Desired width of the modal. Required for iframe type. Defaults to undefined //TODO
37 height (integer) : Desired height of the modal. Required for iframe type. Defaults to undefined //TODO
38
39 background_scroll (boolean) : Set this to true to enable the page to scroll behind the open modal.
40
41 should_open (boolean|function) : Boolean or closure that returns a boolean to determine whether to open the modal or not.
42
43 close_text : String for close button text. Available for localisation and alternative languages to be used.
44 close_aria_label : String for close button aria-label attribute (value that screen readers will read out). Available for localisation and alternative languages to be used.
45
46 === Events ===
47 before_open (function) : Callback function executed before modal is opened
48 after_open (function) : Callback function executed after modal is opened
49 before_close (function) : Callback function executed before modal is closed
50 after_close (function) : Callback function executed after modal is closed
51 source (function(element, src)) : Callback function executed on the default source, it is intended to transform the
52 source (href in an AJAX modal or iframe). The function passes in the triggering element
53 as well as the default source depending of the modal type. The default output of the
54 function is an untransformed default source.
55
56
57 === Confirm Options & Events ===
58 confirm_button_text (string) : Text on the confirm button. Defaults to 'Confirm'
59 confirm_cancel_button_text (string) : Text on the confirm modal cancel button. Defaults to 'Cancel'
60 confirm_title (string) : Title for confirm modal. Default 'Confirm Title'
61 confirm_content (string) : HTML content for confirm message
62 confirm_callback (function) : Callback function for when the confirm button is pressed as opposed to cancel
63 confirm_cancel_callback (function) : Callback function for when the cancel button is pressed
64
65
66 === Gallery Options & Events ===
67 gallery_active_class (string) : Active class applied to the currently active image or image slide in a gallery 'gallery_active_item'
68 outer_controls (boolean) : Set to true to put the next/prev controls outside the Modaal wrapper, at the edges of the browser window.
69 before_image_change (function) : Callback function executed before the image slide changes in a gallery modal. Default function( current_item, incoming_item )
70 after_image_change (function) : Callback function executed after the image slide changes in a gallery modal. Default function ( current_item )
71
72
73 === AJAX Options & Events ===
74 loading_content (string) : HTML content for loading message. Default 'Loading &hellip;'
75 loading_class (string) : Class name to be applied while content is loaded via AJAX. Default 'is_loading'
76 ajax_error_class (string) : Class name to be applied when content has failed to load. Default is 'modaal-error'
77 ajax_success (function) : Callback for when AJAX content is loaded in
78
79
80 === SOCIAL CONTENT ===
81 instagram_id (string) : Unique photo ID for an Instagram photo.
82
83 */
84 ( function( $ ) {
85
86 var modaal_loading_spinner = '<div class="modaal-loading-spinner"><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div></div>'
87
88 var Modaal = {
89 init : function(options, elem) {
90 var self = this;
91
92 self.dom = $('body');
93
94 self.$elem = $(elem);
95 self.options = $.extend({}, $.fn.modaal.options, self.$elem.data(), options);
96 self.xhr = null;
97
98 // set up the scope
99 self.scope = {
100 is_open: false,
101 id: 'modaal_' + ( new Date().getTime() ) + ( Math.random().toString(16).substring(2) ),
102 source: self.options.content_source ? self.options.content_source : self.$elem.attr('href')
103 };
104
105 // add scope attribute to trigger element
106 self.$elem.attr('data-modaal-scope', self.scope.id);
107
108 // private options
109 self.private_options = {
110 active_class: 'is_active'
111 };
112
113 self.lastFocus = null;
114
115 // if is_locked
116 if ( self.options.is_locked || self.options.type == 'confirm' || self.options.hide_close ) {
117 self.scope.close_btn = '';
118 } else {
119 self.scope.close_btn = '<button type="button" class="modaal-close" id="modaal-close" aria-label="' + self.options.close_aria_label + '"><span>' + self.options.close_text + '</span></button>';
120 }
121
122 // reset animation_speed
123 if (self.options.animation === 'none' ){
124 self.options.animation_speed = 0;
125 self.options.after_callback_delay = 0;
126 }
127
128 // On click to open modal
129 $(elem).on('click.Modaal', function(e) {
130 e.preventDefault();
131 self.create_modaal(self, e);
132 });
133
134 // Define next/prev buttons
135 if (self.options.outer_controls === true) {
136 var mod_class = 'outer';
137 } else {
138 var mod_class = 'inner';
139 }
140 self.scope.prev_btn = '<button type="button" class="modaal-gallery-control modaal-gallery-prev modaal-gallery-prev-' + mod_class + '" id="modaal-gallery-prev" aria-label="Previous image (use left arrow to change)"><span>Previous Image</span></button>';
141 self.scope.next_btn = '<button type="button" class="modaal-gallery-control modaal-gallery-next modaal-gallery-next-' + mod_class + '" id="modaal-gallery-next" aria-label="Next image (use right arrow to change)"><span>Next Image</span></button>';
142
143 // Check for start_open
144 if (self.options.start_open === true ){
145 self.create_modaal( self );
146 }
147 },
148
149 // Initial create to determine which content type it requires
150 // ----------------------------------------------------------------
151 create_modaal : function(self, e) {
152 var self = this;
153 var source;
154
155 // Save last active state before modal
156 self.lastFocus = self.$elem;
157
158 if ( self.options.should_open === false || ( typeof self.options.should_open === 'function' && self.options.should_open() === false ) ) {
159 return;
160 }
161
162 // CB: before_open
163 self.options.before_open.call(self, e);
164
165 switch (self.options.type) {
166 case 'inline':
167 self.create_basic();
168 break;
169
170 case 'ajax':
171 source = self.options.source( self.$elem, self.scope.source );
172 self.fetch_ajax( source );
173 break;
174
175 case 'confirm':
176 self.options.is_locked = true;
177 self.create_confirm();
178 break;
179
180 case 'image':
181 self.create_image();
182 break;
183
184 case 'iframe':
185 source = self.options.source( self.$elem, self.scope.source );
186 self.create_iframe( source );
187 break;
188
189 case 'video':
190 self.create_video(self.scope.source);
191 break;
192
193 case 'instagram':
194 self.create_instagram();
195 break;
196 }
197
198 // call events to be watched (click, tab, keyup, keydown etc.)
199 self.watch_events();
200 },
201
202 // Watching Modal
203 // ----------------------------------------------------------------
204 watch_events : function() {
205 var self = this;
206
207 self.dom.off('click.Modaal keyup.Modaal keydown.Modaal');
208
209 // Body keydown
210 self.dom.on('keydown.Modaal', function(e) {
211 var key = e.keyCode;
212 var target = e.target;
213
214 // look for tab change and reset focus to modal window
215 // done in keydown so the check fires repeatedly when you hold the tab key down
216 if (key == 9 && self.scope.is_open) {
217 if (!$.contains(document.getElementById(self.scope.id), target) ) {
218 $('#' + self.scope.id).find('*[tabindex="0"]').focus();
219 }
220 }
221 });
222
223 // Body keyup
224 self.dom.on('keyup.Modaal', function(e) {
225 var key = e.keyCode;
226 var target = e.target;
227
228 if ( (e.shiftKey && e.keyCode == 9) && self.scope.is_open) {
229 // Watch for shift + tab key press. if open shift focus to close button.
230 if (!$.contains(document.getElementById(self.scope.id), target) ) {
231 $('#' + self.scope.id).find('.modaal-close').focus();
232 }
233 }
234
235 if ( !self.options.is_locked ){
236 // On escape key press close modal
237 if (key == 27 && self.scope.is_open ) {
238 if ( $(document.activeElement).is('input:not(:checkbox):not(:radio)') ) {
239 return false;
240 }
241
242 self.modaal_close();
243 return;
244 }
245 }
246
247 // is gallery open and images length is > 1
248 if ( self.options.type == 'image' ) {
249 // arrow left for back
250 if (key == 37 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-prev').hasClass('is_hidden')) ) {
251 self.gallery_update('prev');
252 }
253 // arrow right for next
254 if (key == 39 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-next').hasClass('is_hidden')) ) {
255 self.gallery_update('next');
256 }
257 return;
258 }
259 });
260
261 // Body click/touch
262 self.dom.on('click.Modaal', function(e) {
263 var trigger = $(e.target);
264
265 // General Controls: If it's not locked allow greedy close
266 if ( !self.options.is_locked ){
267 if ( (self.options.overlay_close && trigger.is('.modaal-inner-wrapper')) || trigger.is('.modaal-close') || trigger.closest('.modaal-close').length ) {
268 self.modaal_close();
269 return;
270 }
271 }
272
273 //Confirm Controls
274 if ( trigger.is('.modaal-confirm-btn' ) ){
275 // if 'OK' button is clicked, run confirm_callback()
276 if ( trigger.is('.modaal-ok') ) {
277 self.options.confirm_callback.call(self, self.lastFocus);
278 }
279
280 if ( trigger.is('.modaal-cancel') ) {
281 self.options.confirm_cancel_callback.call(self, self.lastFocus);
282 }
283 self.modaal_close();
284 return;
285 }
286
287 // Gallery Controls
288 if ( trigger.is( '.modaal-gallery-control' ) ){
289 // it not active, don't do nuthin!
290 if ( trigger.hasClass('is_hidden') ) {
291 return;
292 }
293
294 // trigger previous
295 if ( trigger.is('.modaal-gallery-prev') ) {
296 self.gallery_update('prev');
297 }
298 // trigger next
299 if ( trigger.is('.modaal-gallery-next') ) {
300 self.gallery_update('next');
301 }
302 return;
303 }
304 });
305 },
306
307 // Append markup into DOM
308 build_modal : function(content) {
309 var self = this;
310
311 // if is instagram
312 var igClass = '';
313 if ( self.options.type == 'instagram' ) {
314 igClass = ' modaal-instagram';
315 }
316
317 var wrap_class = (self.options.type == 'video') ? 'modaal-video-wrap' : 'modaal-content';
318
319 /*
320 modaal-start_none : fully hidden via display:none;
321 modaal-start_fade : hidden via opacity:0
322 modaal-start_slidedown : ...
323
324 */
325 var animation_class;
326 switch ( self.options.animation ) {
327 case 'fade' :
328 animation_class = ' modaal-start_fade';
329 break;
330 case 'slide-down' :
331 animation_class = ' modaal-start_slidedown';
332 break;
333 default :
334 animation_class = ' modaal-start_none'
335 }
336
337 // fullscreen check
338 var fullscreen_class = '';
339 if ( self.options.fullscreen ) {
340 fullscreen_class = ' modaal-fullscreen';
341 }
342
343 // custom class check
344 if ( self.options.custom_class !== '' || typeof(self.options.custom_class) !== 'undefined' ) {
345 self.options.custom_class = ' ' + self.options.custom_class;
346 }
347
348 // if width and heights exists and is typeof number
349 var dimensionsStyle = '';
350 if ( self.options.width && self.options.height && typeof self.options.width == 'number' && typeof self.options.height == 'number' ) {
351 // if width and height exist, and they are both numbers
352 dimensionsStyle = ' style="max-width:' + self.options.width + 'px;height:' + self.options.height + 'px;overflow:auto;"';
353 } else if ( self.options.width && typeof self.options.width == 'number' ) {
354 // if only width
355 dimensionsStyle = ' style="max-width:' + self.options.width + 'px;"';
356 } else if ( self.options.height && typeof self.options.height == 'number' ) {
357 // if only height
358 dimensionsStyle = ' style="height:' + self.options.height + 'px;overflow:auto;"';
359 }
360
361 // Reset dimensions style (width and height) for certain types
362 if ( self.options.type == 'image' || self.options.type == 'video' || self.options.type == 'instagram' || self.options.fullscreen ) {
363 dimensionsStyle = '';
364 }
365
366 // if is touch
367 // this is a bug fix for iOS to allow regular click events on div elements.
368 var touchTrigger = '';
369 if ( self.is_touch() ) {
370 touchTrigger = ' style="cursor:pointer;"'
371 }
372
373 var build_markup = '<div class="modaal-wrapper modaal-' + self.options.type + animation_class + igClass + fullscreen_class + self.options.custom_class + '" id="' + self.scope.id + '"><div class="modaal-outer-wrapper"><div class="modaal-inner-wrapper"' + touchTrigger + '>';
374
375 // hide if video
376 if (self.options.type != 'video') {
377 build_markup += '<div class="modaal-container"' + dimensionsStyle + '>';
378 }
379
380 // add the guts of the content
381 build_markup += '<div class="' + wrap_class + ' modaal-focus" aria-hidden="false" aria-label="' + self.options.accessible_title + ' - ' + self.options.close_aria_label + '" role="dialog">';
382
383 // If it's inline type, we want to clone content instead of dropping it straight in
384 if (self.options.type == 'inline') {
385 build_markup += '<div class="modaal-content-container" role="document"></div>';
386 } else {
387 // Drop in the content if it's not inline
388 build_markup += content;
389 }
390
391 // close wrap_class
392 build_markup += '</div>' + self.scope.close_btn;
393
394 // hide if video
395 if (self.options.type != 'video') {
396 build_markup += '</div>';
397 }
398
399 // close off modaal-inner-wrapper
400 build_markup += '</div>';
401
402 // If type is image AND outer_controls is true: add gallery next and previous controls.
403 if (self.options.type == 'image' && self.options.outer_controls === true) {
404 build_markup += self.scope.prev_btn + self.scope.next_btn;
405 }
406
407 // close off modaal-wrapper
408 build_markup += '</div></div>';
409
410 // append ajax modal markup to dom
411 if ($('#' + self.scope.id + '_overlay').length < 1) {
412 self.dom.append(build_markup);
413 }
414
415 // if inline, clone content into space
416 if (self.options.type == 'inline') {
417 content.appendTo('#' + self.scope.id + ' .modaal-content-container');
418 }
419
420 // Trigger overlay show (which triggers modal show)
421 self.modaal_overlay('show');
422 },
423
424 // Create Basic Inline Modal
425 // ----------------------------------------------------------------
426 create_basic : function() {
427 var self = this;
428 var target = $(self.scope.source);
429 var content = '';
430
431 if (target.length) {
432 content = target.contents().detach();
433 target.empty();
434 } else {
435 content = 'Content could not be loaded. Please check the source and try again.';
436 }
437
438 // now push content into markup
439 self.build_modal(content);
440 },
441
442 // Create Instagram Modal
443 // ----------------------------------------------------------------
444 create_instagram : function() {
445 var self = this;
446 var id = self.options.instagram_id;
447 var content = '';
448
449 var error_msg = 'Instagram photo couldn\'t be loaded, please check the embed code and try again.';
450
451 self.build_modal('<div class="modaal-content-container' + ( self.options.loading_class != '' ? ' ' + self.options.loading_class : '' ) + '">' + self.options.loading_content + '</div>' );
452
453 // ID exists, is not empty null or undefined.
454 if ( id != '' && id !== null && id !== undefined ) {
455 // set up oembed url
456 var ig_url = 'https://api.instagram.com/oembed?url=http://instagr.am/p/' + id + '/';
457
458 $.ajax({
459 url: ig_url,
460 dataType: "jsonp",
461 cache: false,
462 success: function (data) {
463
464 // Create temp dom element from which we'll clone into the modaal instance. This is required to bypass the unusual small thumb issue instagram oembed was serving up
465 self.dom.append('<div id="temp-ig" style="width:0;height:0;overflow:hidden;">' + data.html + '</div>');
466
467 // Check if it has loaded once before.
468 // This is to stop the Embeds.process from throwing and error the first time it's being loaded.
469 // private_options are individual to a modaal_scope so will not work across multiple scopes when checking if true, only that one item.
470 if ( self.dom.attr('data-igloaded') ) {
471 window.instgrm.Embeds.process();
472 } else {
473 // first time it's loaded, let's set a new private option to use next time it's opened.
474 self.dom.attr('data-igloaded', 'true');
475 }
476
477 // now set location for new content
478 // timeout is required as well to bypass the unusual small thumb issue instagram oembed was serving up
479 var target = '#' + self.scope.id + ' .modaal-content-container';
480 if ( $(target).length > 0) {
481 setTimeout(function() {
482 $('#temp-ig').contents().clone().appendTo( target );
483 $('#temp-ig').remove();
484 }, 1000);
485 }
486
487 },
488 error: function() {
489 content = error_msg;
490
491 // now set location for new content
492 var target = $('#' + self.scope.id + ' .modaal-content-container');
493 if ( target.length > 0) {
494 target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class );
495 target.html(content);
496 }
497 }
498 });
499
500 } else {
501 content = error_msg;
502 }
503
504 return false;
505 },
506
507 // Fetch Ajax Data
508 // ----------------------------------------------------------------
509 fetch_ajax : function(url) {
510 var self = this;
511 var content = '';
512
513 // If no accessible title, set it to 'Dialog Window'
514 if ( self.options.accessible_title == null ) {
515 self.options.accessible_title = 'Dialog Window'
516 }
517
518 if ( self.xhr !== null ){
519 self.xhr.abort();
520 self.xhr = null;
521 }
522
523 self.build_modal('<div class="modaal-content-container' + ( self.options.loading_class != '' ? ' ' + self.options.loading_class : '' ) + '">' + self.options.loading_content + '</div>' );
524
525 self.xhr = $.ajax(url, {
526 success: function(data) {
527 // content fetch is successful so push it into markup
528 var target = $('#' + self.scope.id).find('.modaal-content-container');
529 if ( target.length > 0){
530 target.removeClass( self.options.loading_class );
531 target.html( data );
532
533 self.options.ajax_success.call(self, target);
534 }
535 },
536 error: function( xhr ) {
537 // There were some errors so return an error message
538 if ( xhr.statusText == 'abort' ){
539 return;
540 }
541
542 var target = $('#' + self.scope.id + ' .modaal-content-container');
543 if ( target.length > 0){
544 target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class );
545 target.html( 'Content could not be loaded. Please check the source and try again.' );
546 }
547 }
548 });
549 },
550
551 // Create Confirm Modal
552 // ----------------------------------------------------------------
553 create_confirm : function() {
554 var self = this;
555 var content;
556
557 content = '<div class="modaal-content-container">' +
558 '<h1 id="modaal-title">' + self.options.confirm_title + '</h1>' +
559 '<div class="modaal-confirm-content">' + self.options.confirm_content + '</div>' +
560 '<div class="modaal-confirm-wrap">' +
561 '<button type="button" class="modaal-confirm-btn modaal-ok" aria-label="Confirm">' + self.options.confirm_button_text + '</button>' +
562 '<button type="button" class="modaal-confirm-btn modaal-cancel" aria-label="Cancel">' + self.options.confirm_cancel_button_text + '</button>' +
563 '</div>' +
564 '</div>' +
565 '</div>';
566
567 // now push content into markup
568 self.build_modal(content);
569 },
570
571 // Create Image/Gallery Modal
572 // ----------------------------------------------------------------
573 create_image : function() {
574 var self = this;
575 var content;
576
577 var modaal_image_markup = '';
578 var gallery_total;
579
580 // If has group attribute
581 if ( self.$elem.is('[data-group]') || self.$elem.is('[rel]') ) {
582
583 // find gallery groups
584 var use_group = self.$elem.is('[data-group]');
585 var gallery_group = use_group ? self.$elem.attr('data-group') : self.$elem.attr('rel');
586 var gallery_group_items = use_group ? $('[data-group="' + gallery_group + '"]') : $('[rel="' + gallery_group + '"]');
587
588 // remove any previous active attribute to any in the group
589 gallery_group_items.removeAttr('data-gallery-active', 'is_active');
590 // add active attribute to the item clicked
591 self.$elem.attr('data-gallery-active', 'is_active');
592
593 // how many in the grouping are there (-1 to connect with each function starting with 0)
594 gallery_total = gallery_group_items.length - 1;
595
596 // prepare array for gallery data
597 var gallery = [];
598
599 // start preparing markup
600 modaal_image_markup = '<div class="modaal-gallery-item-wrap">';
601
602 // loop each grouping item and push it into our gallery array
603 gallery_group_items.each(function(i, item) {
604 // setup default content
605 var img_src = '';
606 var img_alt = '';
607 var img_description = '';
608 var img_active = false;
609 var img_src_error = false;
610
611 var data_modaal_desc = item.getAttribute('data-modaal-desc');
612 var data_item_active = item.getAttribute('data-gallery-active');
613
614 // if item has inline custom source, use that instead of href. Fall back to href if available.
615 if ( $(item).attr('data-modaal-content-source') ) {
616 img_src = $(item).attr('data-modaal-content-source');
617 } else if ( $(item).attr('href') ) {
618 img_src = $(item).attr('href');
619 } else if ( $(item).attr('src') ) {
620 img_src = $(item).attr('src');
621 } else {
622 img_src = 'trigger requires href or data-modaal-content-source attribute';
623 img_src_error = true;
624 }
625
626 // Does it have a modaal description
627 if ( data_modaal_desc != '' && data_modaal_desc !== null && data_modaal_desc !== undefined ) {
628 img_alt = data_modaal_desc;
629 img_description = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image ' + (i+1) + ' - </span>' + data_modaal_desc.replace(/</g, "&lt;").replace(/>/g, "&gt;") + '</div>'
630 } else {
631 img_description = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image ' + (i+1) + '</span></div>';
632 }
633
634 // is it the active item
635 if ( data_item_active ) {
636 img_active = true
637 }
638
639 // set new object for values we want
640 var gallery_item = {
641 'url': img_src,
642 'alt': img_alt,
643 'rawdesc': data_modaal_desc,
644 'desc': img_description,
645 'active': img_active,
646 'src_error': img_src_error
647 };
648
649 // push object into gallery array
650 gallery.push( gallery_item );
651 });
652
653 // now loop through all items in the gallery and build up the markup
654 for (var i = 0; i < gallery.length; i++) {
655 // Set default active class, then check if array item active is true and update string for class
656 var is_active = '';
657 var aria_label = gallery[i].rawdesc ? 'Image: ' + gallery[i].rawdesc : 'Image ' + i + ' no description';
658
659 if ( gallery[i].active ) {
660 is_active = ' ' + self.private_options.active_class;
661 }
662
663 // if gallery item has source error, output message rather than undefined image
664 var image_output = gallery[i].src_error ? gallery[i].url : '<img src="' + gallery[i].url + '" alt=" " style="width:100%">';
665
666 // for each item build up the markup
667 modaal_image_markup += '<div class="modaal-gallery-item gallery-item-' + i + is_active + '" aria-label="' + aria_label + '">' +
668 image_output + gallery[i].desc +
669 '</div>';
670 }
671
672 // Close off the markup for the gallery
673 modaal_image_markup += '</div>';
674
675 // Add next and previous buttons if outside
676 if (self.options.outer_controls != true) {
677 modaal_image_markup += self.scope.prev_btn + self.scope.next_btn;
678 }
679 } else {
680 // This is only a single gallery item so let's grab the necessary values
681
682 // define the source, check if content_source option exists, and use that or fall back to href.
683 var this_img_src;
684 var img_src_error = false;
685 if ( self.$elem.attr('data-modaal-content-source') ) {
686 this_img_src = self.$elem.attr('data-modaal-content-source');
687 } else if ( self.$elem.attr('href') ) {
688 this_img_src = self.$elem.attr('href');
689 } else if ( self.$elem.attr('src') ) {
690 this_img_src = self.$elem.attr('src');
691 } else {
692 this_img_src = 'trigger requires href or data-modaal-content-source attribute';
693 img_src_error = true;
694 }
695
696 var this_img_alt_txt = '';
697 var this_img_alt = '';
698 var aria_label = '';
699
700 if ( self.$elem.attr('data-modaal-desc') ) {
701 aria_label = self.$elem.attr('data-modaal-desc');
702 this_img_alt_txt = self.$elem.attr('data-modaal-desc');
703 this_img_alt = '<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image - </span>' + this_img_alt_txt.replace(/</g, "&lt;").replace(/>/g, "&gt;") + '</div>';
704 } else {
705 aria_label = "Image with no description";
706 }
707
708 // if image item has source error, output message rather than undefined image
709 var image_output = img_src_error ? this_img_src : '<img src="' + this_img_src + '" alt=" " style="width:100%">';
710
711 // build up the html
712 modaal_image_markup = '<div class="modaal-gallery-item is_active" aria-label="' + aria_label + '">' +
713 image_output + this_img_alt +
714 '</div>';
715 }
716
717 // Update content variable
718 content = modaal_image_markup;
719
720 // now push content into markup
721 self.build_modal(content);
722
723 // setup next & prev buttons
724 if ( $('.modaal-gallery-item.is_active').is('.gallery-item-0') ) {
725 $('.modaal-gallery-prev').hide();
726 }
727 if ( $('.modaal-gallery-item.is_active').is('.gallery-item-' + gallery_total) ) {
728 $('.modaal-gallery-next').hide();
729 }
730 },
731
732 // Gallery Change Image
733 // ----------------------------------------------------------------
734 gallery_update : function(direction) {
735 var self = this;
736 var this_gallery = $('#' + self.scope.id);
737 var this_gallery_item = this_gallery.find('.modaal-gallery-item');
738 var this_gallery_total = this_gallery_item.length - 1;
739
740 // if single item, don't proceed
741 if ( this_gallery_total == 0 ) {
742 return false;
743 }
744
745 var prev_btn = this_gallery.find('.modaal-gallery-prev'),
746 next_btn = this_gallery.find('.modaal-gallery-next');
747
748 var duration = 250;
749
750 var new_img_w = 0,
751 new_img_h = 0;
752
753 // CB: Before image change
754 var current_item = this_gallery.find( '.modaal-gallery-item.' + self.private_options.active_class ),
755 incoming_item = ( direction == 'next' ? current_item.next( '.modaal-gallery-item' ) : current_item.prev( '.modaal-gallery-item' ) );
756 self.options.before_image_change.call(self, current_item, incoming_item);
757
758 // stop change if at start of end
759 if ( direction == 'prev' && this_gallery.find('.gallery-item-0').hasClass('is_active') ) {
760 return false;
761 } else if ( direction == 'next' && this_gallery.find('.gallery-item-' + this_gallery_total).hasClass('is_active') ) {
762 return false;
763 }
764
765
766 // lock dimensions
767 current_item.stop().animate({
768 opacity: 0
769 }, duration, function(){
770 // Move to appropriate image
771 incoming_item.addClass('is_next').css({
772 'position': 'absolute',
773 'display': 'block',
774 'opacity': 0
775 });
776
777 // Collect doc width
778 var doc_width = $(document).width();
779 var width_threshold = doc_width > 1140 ? 280 : 50;
780
781 // start toggle to 'is_next'
782 new_img_w = this_gallery.find('.modaal-gallery-item.is_next').width();
783 new_img_h = this_gallery.find('.modaal-gallery-item.is_next').height();
784
785 var new_natural_w = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalWidth');
786 var new_natural_h = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalHeight');
787
788 // if new image is wider than doc width
789 if ( new_natural_w > (doc_width - width_threshold) ) {
790 // set new width just below doc width
791 new_img_w = doc_width - width_threshold;
792
793 // Set temp widths so we can calulate the correct height;
794 this_gallery.find('.modaal-gallery-item.is_next').css({ 'width': new_img_w });
795 this_gallery.find('.modaal-gallery-item.is_next img').css({ 'width': new_img_w });
796
797 // Set new height variable
798 new_img_h = this_gallery.find('.modaal-gallery-item.is_next').find('img').height();
799 } else {
800 // new img is not wider than screen, so let's set the new dimensions
801 new_img_w = new_natural_w;
802 new_img_h = new_natural_h;
803 }
804
805 // resize gallery region
806 this_gallery.find('.modaal-gallery-item-wrap').stop().animate({
807 'width': new_img_w,
808 'height': new_img_h
809 }, duration, function() {
810 // hide old active image
811 current_item.removeClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeAttr('style');
812 current_item.find('img').removeAttr('style');
813
814 // show new image
815 incoming_item.addClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeClass('is_next').css('position','');
816
817 // animate in new image (now has the normal is_active class
818 incoming_item.stop().animate({
819 opacity: 1
820 }, duration, function(){
821 $(this).removeAttr('style').css({
822 'width': '100%'
823 });
824 $(this).find('img').css('width', '100%');
825
826 // remove dimension lock
827 this_gallery.find('.modaal-gallery-item-wrap').removeAttr('style');
828
829 // CB: After image change
830 self.options.after_image_change.call( self, incoming_item );
831 });
832
833 // Focus on the new gallery item
834 this_gallery.find('.modaal-gallery-item').removeAttr('tabindex');
835 this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class + '').attr('tabindex', '0').focus();
836
837 // hide/show next/prev
838 if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-0') ) {
839 prev_btn.stop().animate({
840 opacity: 0
841 }, 150, function(){
842 $(this).hide();
843 });
844 } else {
845 prev_btn.stop().css({
846 'display': 'block',
847 'opacity': prev_btn.css('opacity')
848 }).animate({
849 opacity: 1
850 }, 150);
851 }
852 if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-' + this_gallery_total) ) {
853 next_btn.stop().animate({
854 opacity: 0
855 }, 150, function(){
856 $(this).hide();
857 });
858 } else {
859 next_btn.stop().css({
860 'display': 'block',
861 'opacity': prev_btn.css('opacity')
862 }).animate({
863 opacity: 1
864 }, 150);
865 }
866 });
867 });
868 },
869
870 // Create Video Modal
871 // ----------------------------------------------------------------
872 create_video : function(url) {
873 var self = this;
874 var content;
875
876 // video markup
877 content = '<iframe src="' + url + '" class="modaal-video-frame" frameborder="0" allowfullscreen></iframe>';
878
879 // now push content into markup
880 self.build_modal('<div class="modaal-video-container">' + content + '</div>');
881 },
882
883 // Create iFrame Modal
884 // ----------------------------------------------------------------
885 create_iframe : function(url) {
886 var self = this;
887 var content;
888
889 if ( self.options.width !== null || self.options.width !== undefined || self.options.height !== null || self.options.height !== undefined ) {
890 // video markup
891 content = '<iframe src="' + url + '" class="modaal-iframe-elem" frameborder="0" allowfullscreen></iframe>';
892 } else {
893 content = '<div class="modaal-content-container">Please specify a width and height for your iframe</div>';
894 }
895
896 // now push content into markup
897 self.build_modal(content);
898 },
899
900 // Open Modaal
901 // ----------------------------------------------------------------
902 modaal_open : function() {
903 var self = this;
904 var modal_wrapper = $( '#' + self.scope.id );
905 var animation_type = self.options.animation;
906
907 if (animation_type === 'none' ){
908 modal_wrapper.removeClass('modaal-start_none');
909 self.options.after_open.call(self, modal_wrapper);
910 }
911
912 // Open with fade
913 if (animation_type === 'fade') {
914 modal_wrapper.removeClass('modaal-start_fade');
915 }
916
917 // Open with slide down
918 if (animation_type === 'slide-down') {
919 modal_wrapper.removeClass('modaal-start_slide_down');
920 }
921
922 var focusTarget = modal_wrapper;
923
924 // Switch focusTarget tabindex (switch from other modal if exists)
925 $('.modaal-wrapper *[tabindex=0]').removeAttr('tabindex');
926
927 if ( self.options.type == 'image' ) {
928 focusTarget = $('#' + self.scope.id).find('.modaal-gallery-item.' + self.private_options.active_class);
929
930 } else if ( modal_wrapper.find('.modaal-iframe-elem').length ) {
931 focusTarget = modal_wrapper.find('.modaal-iframe-elem');
932
933 } else if ( modal_wrapper.find('.modaal-video-wrap').length ) {
934 focusTarget = modal_wrapper.find('.modaal-video-wrap');
935
936 } else {
937 focusTarget = modal_wrapper.find('.modaal-focus');
938
939 }
940
941 // now set the focus
942 focusTarget.attr('tabindex', '0').focus();
943
944 // Run after_open
945 if (animation_type !== 'none') {
946 // CB: after_open
947 setTimeout(function() {
948 self.options.after_open.call(self, modal_wrapper)
949 }, self.options.after_callback_delay);
950 }
951 },
952
953 // Close Modal
954 // ----------------------------------------------------------------
955 modaal_close : function() {
956 var self = this;
957 var modal_wrapper = $( '#' + self.scope.id );
958
959 // CB: before_close
960 self.options.before_close.call(self, modal_wrapper);
961
962 if (self.xhr !== null){
963 self.xhr.abort();
964 self.xhr = null;
965 }
966
967 // Now we close the modal
968 if (self.options.animation === 'none' ){
969 modal_wrapper.addClass('modaal-start_none');
970 }
971
972 // Close with fade
973 if (self.options.animation === 'fade') {
974 modal_wrapper.addClass('modaal-start_fade');
975 }
976
977 // Close with slide up (using initial slide down)
978 if (self.options.animation === 'slide-down') {
979 modal_wrapper.addClass('modaal-start_slide_down');
980 }
981
982 // CB: after_close and remove
983 setTimeout(function() {
984 // clone inline content back to origin place
985 if (self.options.type == 'inline') {
986 $('#' + self.scope.id + ' .modaal-content-container').contents().detach().appendTo( self.scope.source )
987 }
988 // remove markup from dom
989 modal_wrapper.remove();
990 // CB: after_close
991 self.options.after_close.call(self);
992 // scope is now closed
993 self.scope.is_open = false;
994
995 }, self.options.after_callback_delay);
996
997 // Call overlay hide
998 self.modaal_overlay('hide');
999
1000 // Roll back to last focus state before modal open. If was closed programmatically, this might not be set
1001 if (self.lastFocus != null) {
1002 self.lastFocus.focus();
1003 }
1004 },
1005
1006 // Overlay control (accepts action for show or hide)
1007 // ----------------------------------------------------------------
1008 modaal_overlay : function(action) {
1009 var self = this;
1010
1011 if (action == 'show') {
1012 // Modal is open so update scope
1013 self.scope.is_open = true;
1014
1015 // set body to overflow hidden if background_scroll is false
1016 if (! self.options.background_scroll) {
1017 self.dom.addClass('modaal-noscroll');
1018 }
1019
1020 // append modaal overlay
1021 if ($('#' + self.scope.id + '_overlay').length < 1) {
1022 self.dom.append('<div class="modaal-overlay" id="' + self.scope.id + '_overlay"></div>');
1023 }
1024
1025 // now show
1026 $('#' + self.scope.id + '_overlay').css('background', self.options.background).stop().animate({
1027 opacity: self.options.overlay_opacity
1028 }, self.options.animation_speed, function(){
1029 // now open the modal
1030 self.modaal_open();
1031 });
1032
1033 } else if (action == 'hide') {
1034
1035 // now hide the overlay
1036 $('#' + self.scope.id + '_overlay').stop().animate({
1037 opacity: 0
1038 }, self.options.animation_speed, function(){
1039 // remove overlay from dom
1040 $(this).remove();
1041
1042 // remove body overflow lock
1043 self.dom.removeClass('modaal-noscroll');
1044 });
1045 }
1046 },
1047
1048 // Check if is touch
1049 // ----------------------------------------------------------------
1050 is_touch : function() {
1051 return 'ontouchstart' in window || navigator.maxTouchPoints;
1052 }
1053 };
1054
1055 // Define default object to store
1056 var modaal_existing_selectors = [];
1057
1058 // Declare the modaal jQuery method
1059 // ------------------------------------------------------------
1060 $.fn.modaal = function(options) {
1061 return this.each(function (i) {
1062 var existing_modaal = $(this).data('modaal');
1063
1064 if ( existing_modaal ){
1065 // Checking for string value, used for methods
1066 if (typeof(options) == 'string'){
1067 switch (options) {
1068 case 'open':
1069 // create the modal
1070 existing_modaal.create_modaal(existing_modaal);
1071 break;
1072 case 'close':
1073 existing_modaal.modaal_close();
1074 break;
1075 }
1076 }
1077 } else {
1078 // Not a string, so let's setup the modal ready to use
1079 var modaal = Object.create(Modaal);
1080 modaal.init(options, this);
1081 $.data(this, "modaal", modaal);
1082
1083 // push this select into existing selectors array which is referenced during modaal_dom_observer
1084 modaal_existing_selectors.push({
1085 'element': $(this).attr('class'),
1086 'options': options
1087 });
1088 }
1089 });
1090 };
1091
1092 // Default options
1093 // ------------------------------------------------------------
1094 $.fn.modaal.options = {
1095
1096 //General
1097 type: 'inline',
1098 content_source: null,
1099 animation: 'fade',
1100 animation_speed: 300,
1101 after_callback_delay: 350,
1102 is_locked: false,
1103 hide_close: false,
1104 background: '#000',
1105 overlay_opacity: '0.8',
1106 overlay_close: true,
1107 accessible_title: 'Dialog Window',
1108 start_open: false,
1109 fullscreen: false,
1110 custom_class: '',
1111 background_scroll: false,
1112 should_open: true,
1113 close_text: 'Close',
1114 close_aria_label: 'Close (Press escape to close)',
1115 width: null,
1116 height: null,
1117
1118 //Events
1119 before_open: function(){},
1120 after_open: function(){},
1121 before_close: function(){},
1122 after_close: function(){},
1123 source: function( element, src ){
1124 return src;
1125 },
1126
1127 //Confirm Modal
1128 confirm_button_text: 'Confirm', // text on confirm button
1129 confirm_cancel_button_text: 'Cancel',
1130 confirm_title: 'Confirm Title', // title for confirm modal
1131 confirm_content: '<p>This is the default confirm dialog content. Replace me through the options</p>', // html for confirm message
1132 confirm_callback: function() {},
1133 confirm_cancel_callback: function() {},
1134
1135
1136 //Gallery Modal
1137 gallery_active_class: 'gallery_active_item',
1138 outer_controls: false,
1139 before_image_change: function( current_item, incoming_item ) {},
1140 after_image_change: function( current_item ) {},
1141
1142 //Ajax Modal
1143 loading_content: modaal_loading_spinner,
1144 loading_class: 'is_loading',
1145 ajax_error_class: 'modaal-error',
1146 ajax_success: function(){},
1147
1148 //Instagram
1149 instagram_id: null
1150 };
1151
1152 // Check and Set Inline Options
1153 // ------------------------------------------------------------
1154 function modaal_inline_options(self) {
1155
1156 // new empty options
1157 var options = {};
1158 var inline_options = false;
1159
1160 // option: type
1161 if ( self.attr('data-modaal-type') ) {
1162 inline_options = true;
1163 options.type = self.attr('data-modaal-type');
1164 }
1165
1166 // option: type
1167 if ( self.attr('data-modaal-content-source') ) {
1168 inline_options = true;
1169 options.content_source = self.attr('data-modaal-content-source');
1170 }
1171
1172 // option: animation
1173 if ( self.attr('data-modaal-animation') ) {
1174 inline_options = true;
1175 options.animation = self.attr('data-modaal-animation');
1176 }
1177
1178 // option: animation_speed
1179 if ( self.attr('data-modaal-animation-speed') ) {
1180 inline_options = true;
1181 options.animation_speed = self.attr('data-modaal-animation-speed');
1182 }
1183
1184 // option: after_callback_delay
1185 if ( self.attr('data-modaal-after-callback-delay') ) {
1186 inline_options = true;
1187 options.after_callback_delay = self.attr('data-modaal-after-callback-delay');
1188 }
1189
1190 // option: is_locked
1191 if ( self.attr('data-modaal-is-locked') ) {
1192 inline_options = true;
1193 options.is_locked = (self.attr('data-modaal-is-locked') === 'true' ? true : false);
1194 }
1195
1196 // option: hide_close
1197 if ( self.attr('data-modaal-hide-close') ) {
1198 inline_options = true;
1199 options.hide_close = (self.attr('data-modaal-hide-close') === 'true' ? true : false);
1200 }
1201
1202 // option: background
1203 if ( self.attr('data-modaal-background') ) {
1204 inline_options = true;
1205 options.background = self.attr('data-modaal-background');
1206 }
1207
1208 // option: overlay_opacity
1209 if ( self.attr('data-modaal-overlay-opacity') ) {
1210 inline_options = true;
1211 options.overlay_opacity = self.attr('data-modaal-overlay-opacity');
1212 }
1213
1214 // option: overlay_close
1215 if ( self.attr('data-modaal-overlay-close') ) {
1216 inline_options = true;
1217 options.overlay_close = (self.attr('data-modaal-overlay-close') === 'false' ? false : true);
1218 }
1219
1220 // option: accessible_title
1221 if ( self.attr('data-modaal-accessible-title') ) {
1222 inline_options = true;
1223 options.accessible_title = self.attr('data-modaal-accessible-title');
1224 }
1225
1226 // option: start_open
1227 if ( self.attr('data-modaal-start-open') ) {
1228 inline_options = true;
1229 options.start_open = (self.attr('data-modaal-start-open') === 'true' ? true : false);
1230 }
1231
1232 // option: fullscreen
1233 if ( self.attr('data-modaal-fullscreen') ) {
1234 inline_options = true;
1235 options.fullscreen = (self.attr('data-modaal-fullscreen') === 'true' ? true : false);
1236 }
1237
1238 // option: custom_class
1239 if ( self.attr('data-modaal-custom-class') ) {
1240 inline_options = true;
1241 options.custom_class = self.attr('data-modaal-custom-class');
1242 }
1243
1244 // option: close_text
1245 if ( self.attr('data-modaal-close-text') ) {
1246 inline_options = true;
1247 options.close_text = self.attr('data-modaal-close-text');
1248 }
1249
1250 // option: close_aria_label
1251 if ( self.attr('data-modaal-close-aria-label') ) {
1252 inline_options = true;
1253 options.close_aria_label = self.attr('data-modaal-close-aria-label');
1254 }
1255
1256 // option: background_scroll
1257 if ( self.attr('data-modaal-background-scroll') ) {
1258 inline_options = true;
1259 options.background_scroll = (self.attr('data-modaal-background-scroll') === 'true' ? true : false);
1260 }
1261
1262 // option: width
1263 if ( self.attr('data-modaal-width') ) {
1264 inline_options = true;
1265 options.width = parseInt( self.attr('data-modaal-width') );
1266 }
1267
1268 // option: height
1269 if ( self.attr('data-modaal-height') ) {
1270 inline_options = true;
1271 options.height = parseInt( self.attr('data-modaal-height') );
1272 }
1273
1274 // option: confirm_button_text
1275 if ( self.attr('data-modaal-confirm-button-text') ) {
1276 inline_options = true;
1277 options.confirm_button_text = self.attr('data-modaal-confirm-button-text');
1278 }
1279
1280 // option: confirm_cancel_button_text
1281 if ( self.attr('data-modaal-confirm-cancel-button-text') ) {
1282 inline_options = true;
1283 options.confirm_cancel_button_text = self.attr('data-modaal-confirm-cancel-button-text');
1284 }
1285
1286 // option: confirm_title
1287 if ( self.attr('data-modaal-confirm-title') ) {
1288 inline_options = true;
1289 options.confirm_title = self.attr('data-modaal-confirm-title');
1290 }
1291
1292 // option: confirm_content
1293 if ( self.attr('data-modaal-confirm-content') ) {
1294 inline_options = true;
1295 options.confirm_content = self.attr('data-modaal-confirm-content');
1296 }
1297
1298 // option: gallery_active_class
1299 if ( self.attr('data-modaal-gallery-active-class') ) {
1300 inline_options = true;
1301 options.gallery_active_class = self.attr('data-modaal-gallery-active-class');
1302 }
1303
1304 // option: loading_content
1305 if ( self.attr('data-modaal-loading-content') ) {
1306 inline_options = true;
1307 options.loading_content = self.attr('data-modaal-loading-content');
1308 }
1309
1310 // option: loading_class
1311 if ( self.attr('data-modaal-loading-class') ) {
1312 inline_options = true;
1313 options.loading_class = self.attr('data-modaal-loading-class');
1314 }
1315
1316 // option: ajax_error_class
1317 if ( self.attr('data-modaal-ajax-error-class') ) {
1318 inline_options = true;
1319 options.ajax_error_class = self.attr('data-modaal-ajax-error-class');
1320 }
1321
1322 // option: start_open
1323 if ( self.attr('data-modaal-instagram-id') ) {
1324 inline_options = true;
1325 options.instagram_id = self.attr('data-modaal-instagram-id');
1326 }
1327
1328 // now set it up for the trigger, but only if inline_options is true
1329 if ( inline_options ) {
1330 self.modaal(options);
1331 }
1332 };
1333
1334 // On body load (or now, if already loaded), init any modaals defined inline
1335 // Ensure this is done after $.fn.modaal and default options are declared
1336 // ----------------------------------------------------------------
1337 $(function(){
1338
1339 var single_modaal = $('.modaal');
1340
1341 // Check for existing modaal elements
1342 if ( single_modaal.length ) {
1343 single_modaal.each(function() {
1344 var self = $(this);
1345 modaal_inline_options(self);
1346 });
1347 }
1348
1349 // Obvserve DOM mutations for newly added triggers
1350 var modaal_dom_observer = new MutationObserver(function(mutations) {
1351 mutations.forEach(function(mutation) {
1352 if (mutation.addedNodes && mutation.addedNodes.length > 0) {
1353 // element added to DOM
1354 var findElement = [].some.call(mutation.addedNodes, function(el) {
1355 var elm = $(el);
1356 if ( elm.is('a') || elm.is('button') ) {
1357
1358 if ( elm.hasClass('modaal') ) {
1359 // is inline Modaal, initialise options
1360 modaal_inline_options(elm);
1361 } else {
1362 // is not inline modaal. Check for existing selector
1363 modaal_existing_selectors.forEach(function(modaalSelector) {
1364 if ( modaalSelector.element == elm.attr('class') ) {
1365 $(elm).modaal( modaalSelector.options );
1366 return false;
1367 }
1368 });
1369 }
1370
1371 }
1372 });
1373 }
1374 });
1375 });
1376 var observer_config = {
1377 subtree: true,
1378 attributes: true,
1379 childList: true,
1380 characterData: true
1381 };
1382
1383 // pass in the target node, as well as the observer options
1384 setTimeout(function() {
1385 modaal_dom_observer.observe(document.body, observer_config);
1386 }, 500);
1387
1388 });
1389
1390 } ( jQuery, window, document ) );
...\ No newline at end of file ...\ No newline at end of file
1 /*!
2 Modaal - accessible modals - v0.4.4
3 by Humaan, for all humans.
4 http://humaan.com
5 */
6 !function(a){function t(a){var t={},o=!1;a.attr("data-modaal-type")&&(o=!0,t.type=a.attr("data-modaal-type")),a.attr("data-modaal-content-source")&&(o=!0,t.content_source=a.attr("data-modaal-content-source")),a.attr("data-modaal-animation")&&(o=!0,t.animation=a.attr("data-modaal-animation")),a.attr("data-modaal-animation-speed")&&(o=!0,t.animation_speed=a.attr("data-modaal-animation-speed")),a.attr("data-modaal-after-callback-delay")&&(o=!0,t.after_callback_delay=a.attr("data-modaal-after-callback-delay")),a.attr("data-modaal-is-locked")&&(o=!0,t.is_locked="true"===a.attr("data-modaal-is-locked")),a.attr("data-modaal-hide-close")&&(o=!0,t.hide_close="true"===a.attr("data-modaal-hide-close")),a.attr("data-modaal-background")&&(o=!0,t.background=a.attr("data-modaal-background")),a.attr("data-modaal-overlay-opacity")&&(o=!0,t.overlay_opacity=a.attr("data-modaal-overlay-opacity")),a.attr("data-modaal-overlay-close")&&(o=!0,t.overlay_close="false"!==a.attr("data-modaal-overlay-close")),a.attr("data-modaal-accessible-title")&&(o=!0,t.accessible_title=a.attr("data-modaal-accessible-title")),a.attr("data-modaal-start-open")&&(o=!0,t.start_open="true"===a.attr("data-modaal-start-open")),a.attr("data-modaal-fullscreen")&&(o=!0,t.fullscreen="true"===a.attr("data-modaal-fullscreen")),a.attr("data-modaal-custom-class")&&(o=!0,t.custom_class=a.attr("data-modaal-custom-class")),a.attr("data-modaal-close-text")&&(o=!0,t.close_text=a.attr("data-modaal-close-text")),a.attr("data-modaal-close-aria-label")&&(o=!0,t.close_aria_label=a.attr("data-modaal-close-aria-label")),a.attr("data-modaal-background-scroll")&&(o=!0,t.background_scroll="true"===a.attr("data-modaal-background-scroll")),a.attr("data-modaal-width")&&(o=!0,t.width=parseInt(a.attr("data-modaal-width"))),a.attr("data-modaal-height")&&(o=!0,t.height=parseInt(a.attr("data-modaal-height"))),a.attr("data-modaal-confirm-button-text")&&(o=!0,t.confirm_button_text=a.attr("data-modaal-confirm-button-text")),a.attr("data-modaal-confirm-cancel-button-text")&&(o=!0,t.confirm_cancel_button_text=a.attr("data-modaal-confirm-cancel-button-text")),a.attr("data-modaal-confirm-title")&&(o=!0,t.confirm_title=a.attr("data-modaal-confirm-title")),a.attr("data-modaal-confirm-content")&&(o=!0,t.confirm_content=a.attr("data-modaal-confirm-content")),a.attr("data-modaal-gallery-active-class")&&(o=!0,t.gallery_active_class=a.attr("data-modaal-gallery-active-class")),a.attr("data-modaal-loading-content")&&(o=!0,t.loading_content=a.attr("data-modaal-loading-content")),a.attr("data-modaal-loading-class")&&(o=!0,t.loading_class=a.attr("data-modaal-loading-class")),a.attr("data-modaal-ajax-error-class")&&(o=!0,t.ajax_error_class=a.attr("data-modaal-ajax-error-class")),a.attr("data-modaal-instagram-id")&&(o=!0,t.instagram_id=a.attr("data-modaal-instagram-id")),o&&a.modaal(t)}var o={init:function(t,o){var e=this;if(e.dom=a("body"),e.$elem=a(o),e.options=a.extend({},a.fn.modaal.options,e.$elem.data(),t),e.xhr=null,e.scope={is_open:!1,id:"modaal_"+(new Date).getTime()+Math.random().toString(16).substring(2),source:e.options.content_source?e.options.content_source:e.$elem.attr("href")},e.$elem.attr("data-modaal-scope",e.scope.id),e.private_options={active_class:"is_active"},e.lastFocus=null,e.options.is_locked||"confirm"==e.options.type||e.options.hide_close?e.scope.close_btn="":e.scope.close_btn='<button type="button" class="modaal-close" id="modaal-close" aria-label="'+e.options.close_aria_label+'"><span>'+e.options.close_text+"</span></button>","none"===e.options.animation&&(e.options.animation_speed=0,e.options.after_callback_delay=0),a(o).on("click.Modaal",function(a){a.preventDefault(),e.create_modaal(e,a)}),!0===e.options.outer_controls)var i="outer";else var i="inner";e.scope.prev_btn='<button type="button" class="modaal-gallery-control modaal-gallery-prev modaal-gallery-prev-'+i+'" id="modaal-gallery-prev" aria-label="Previous image (use left arrow to change)"><span>Previous Image</span></button>',e.scope.next_btn='<button type="button" class="modaal-gallery-control modaal-gallery-next modaal-gallery-next-'+i+'" id="modaal-gallery-next" aria-label="Next image (use right arrow to change)"><span>Next Image</span></button>',!0===e.options.start_open&&e.create_modaal(e)},create_modaal:function(a,t){var o,a=this;if(a.lastFocus=a.$elem,!1!==a.options.should_open&&("function"!=typeof a.options.should_open||!1!==a.options.should_open())){switch(a.options.before_open.call(a,t),a.options.type){case"inline":a.create_basic();break;case"ajax":o=a.options.source(a.$elem,a.scope.source),a.fetch_ajax(o);break;case"confirm":a.options.is_locked=!0,a.create_confirm();break;case"image":a.create_image();break;case"iframe":o=a.options.source(a.$elem,a.scope.source),a.create_iframe(o);break;case"video":a.create_video(a.scope.source);break;case"instagram":a.create_instagram()}a.watch_events()}},watch_events:function(){var t=this;t.dom.off("click.Modaal keyup.Modaal keydown.Modaal"),t.dom.on("keydown.Modaal",function(o){var e=o.keyCode,i=o.target;9==e&&t.scope.is_open&&(a.contains(document.getElementById(t.scope.id),i)||a("#"+t.scope.id).find('*[tabindex="0"]').focus())}),t.dom.on("keyup.Modaal",function(o){var e=o.keyCode,i=o.target;return o.shiftKey&&9==o.keyCode&&t.scope.is_open&&(a.contains(document.getElementById(t.scope.id),i)||a("#"+t.scope.id).find(".modaal-close").focus()),!t.options.is_locked&&27==e&&t.scope.is_open?!a(document.activeElement).is("input:not(:checkbox):not(:radio)")&&void t.modaal_close():"image"==t.options.type?(37==e&&t.scope.is_open&&!a("#"+t.scope.id+" .modaal-gallery-prev").hasClass("is_hidden")&&t.gallery_update("prev"),void(39==e&&t.scope.is_open&&!a("#"+t.scope.id+" .modaal-gallery-next").hasClass("is_hidden")&&t.gallery_update("next"))):void 0}),t.dom.on("click.Modaal",function(o){var e=a(o.target);if(!t.options.is_locked&&(t.options.overlay_close&&e.is(".modaal-inner-wrapper")||e.is(".modaal-close")||e.closest(".modaal-close").length))return void t.modaal_close();if(e.is(".modaal-confirm-btn"))return e.is(".modaal-ok")&&t.options.confirm_callback.call(t,t.lastFocus),e.is(".modaal-cancel")&&t.options.confirm_cancel_callback.call(t,t.lastFocus),void t.modaal_close();if(e.is(".modaal-gallery-control")){if(e.hasClass("is_hidden"))return;return e.is(".modaal-gallery-prev")&&t.gallery_update("prev"),void(e.is(".modaal-gallery-next")&&t.gallery_update("next"))}})},build_modal:function(t){var o=this,e="";"instagram"==o.options.type&&(e=" modaal-instagram");var i,l="video"==o.options.type?"modaal-video-wrap":"modaal-content";switch(o.options.animation){case"fade":i=" modaal-start_fade";break;case"slide-down":i=" modaal-start_slidedown";break;default:i=" modaal-start_none"}var n="";o.options.fullscreen&&(n=" modaal-fullscreen"),""===o.options.custom_class&&void 0===o.options.custom_class||(o.options.custom_class=" "+o.options.custom_class);var s="";o.options.width&&o.options.height&&"number"==typeof o.options.width&&"number"==typeof o.options.height?s=' style="max-width:'+o.options.width+"px;height:"+o.options.height+'px;overflow:auto;"':o.options.width&&"number"==typeof o.options.width?s=' style="max-width:'+o.options.width+'px;"':o.options.height&&"number"==typeof o.options.height&&(s=' style="height:'+o.options.height+'px;overflow:auto;"'),("image"==o.options.type||"video"==o.options.type||"instagram"==o.options.type||o.options.fullscreen)&&(s="");var d="";o.is_touch()&&(d=' style="cursor:pointer;"');var r='<div class="modaal-wrapper modaal-'+o.options.type+i+e+n+o.options.custom_class+'" id="'+o.scope.id+'"><div class="modaal-outer-wrapper"><div class="modaal-inner-wrapper"'+d+">";"video"!=o.options.type&&(r+='<div class="modaal-container"'+s+">"),r+='<div class="'+l+' modaal-focus" aria-hidden="false" aria-label="'+o.options.accessible_title+" - "+o.options.close_aria_label+'" role="dialog">',"inline"==o.options.type?r+='<div class="modaal-content-container" role="document"></div>':r+=t,r+="</div>"+o.scope.close_btn,"video"!=o.options.type&&(r+="</div>"),r+="</div>","image"==o.options.type&&!0===o.options.outer_controls&&(r+=o.scope.prev_btn+o.scope.next_btn),r+="</div></div>",a("#"+o.scope.id+"_overlay").length<1&&o.dom.append(r),"inline"==o.options.type&&t.appendTo("#"+o.scope.id+" .modaal-content-container"),o.modaal_overlay("show")},create_basic:function(){var t=this,o=a(t.scope.source),e="";o.length?(e=o.contents().detach(),o.empty()):e="Content could not be loaded. Please check the source and try again.",t.build_modal(e)},create_instagram:function(){var t=this,o=t.options.instagram_id,e="",i="Instagram photo couldn't be loaded, please check the embed code and try again.";if(t.build_modal('<div class="modaal-content-container'+(""!=t.options.loading_class?" "+t.options.loading_class:"")+'">'+t.options.loading_content+"</div>"),""!=o&&null!==o&&void 0!==o){var l="https://api.instagram.com/oembed?url=http://instagr.am/p/"+o+"/";a.ajax({url:l,dataType:"jsonp",cache:!1,success:function(o){t.dom.append('<div id="temp-ig" style="width:0;height:0;overflow:hidden;">'+o.html+"</div>"),t.dom.attr("data-igloaded")?window.instgrm.Embeds.process():t.dom.attr("data-igloaded","true");var e="#"+t.scope.id+" .modaal-content-container";a(e).length>0&&setTimeout(function(){a("#temp-ig").contents().clone().appendTo(e),a("#temp-ig").remove()},1e3)},error:function(){e=i;var o=a("#"+t.scope.id+" .modaal-content-container");o.length>0&&(o.removeClass(t.options.loading_class).addClass(t.options.ajax_error_class),o.html(e))}})}else e=i;return!1},fetch_ajax:function(t){var o=this;null==o.options.accessible_title&&(o.options.accessible_title="Dialog Window"),null!==o.xhr&&(o.xhr.abort(),o.xhr=null),o.build_modal('<div class="modaal-content-container'+(""!=o.options.loading_class?" "+o.options.loading_class:"")+'">'+o.options.loading_content+"</div>"),o.xhr=a.ajax(t,{success:function(t){var e=a("#"+o.scope.id).find(".modaal-content-container");e.length>0&&(e.removeClass(o.options.loading_class),e.html(t),o.options.ajax_success.call(o,e))},error:function(t){if("abort"!=t.statusText){var e=a("#"+o.scope.id+" .modaal-content-container");e.length>0&&(e.removeClass(o.options.loading_class).addClass(o.options.ajax_error_class),e.html("Content could not be loaded. Please check the source and try again."))}}})},create_confirm:function(){var a,t=this;a='<div class="modaal-content-container"><h1 id="modaal-title">'+t.options.confirm_title+'</h1><div class="modaal-confirm-content">'+t.options.confirm_content+'</div><div class="modaal-confirm-wrap"><button type="button" class="modaal-confirm-btn modaal-ok" aria-label="Confirm">'+t.options.confirm_button_text+'</button><button type="button" class="modaal-confirm-btn modaal-cancel" aria-label="Cancel">'+t.options.confirm_cancel_button_text+"</button></div></div></div>",t.build_modal(a)},create_image:function(){var t,o,e=this,i="";if(e.$elem.is("[data-group]")||e.$elem.is("[rel]")){var l=e.$elem.is("[data-group]"),n=l?e.$elem.attr("data-group"):e.$elem.attr("rel"),s=a(l?'[data-group="'+n+'"]':'[rel="'+n+'"]');s.removeAttr("data-gallery-active","is_active"),e.$elem.attr("data-gallery-active","is_active"),o=s.length-1;var d=[];i='<div class="modaal-gallery-item-wrap">',s.each(function(t,o){var e="",i="",l="",n=!1,s=!1,r=o.getAttribute("data-modaal-desc"),c=o.getAttribute("data-gallery-active");a(o).attr("data-modaal-content-source")?e=a(o).attr("data-modaal-content-source"):a(o).attr("href")?e=a(o).attr("href"):a(o).attr("src")?e=a(o).attr("src"):(e="trigger requires href or data-modaal-content-source attribute",s=!0),""!=r&&null!==r&&void 0!==r?(i=r,l='<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image '+(t+1)+" - </span>"+r.replace(/</g,"&lt;").replace(/>/g,"&gt;")+"</div>"):l='<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image '+(t+1)+"</span></div>",c&&(n=!0);var m={url:e,alt:i,rawdesc:r,desc:l,active:n,src_error:s};d.push(m)});for(var r=0;r<d.length;r++){var c="",m=d[r].rawdesc?"Image: "+d[r].rawdesc:"Image "+r+" no description";d[r].active&&(c=" "+e.private_options.active_class);var p=d[r].src_error?d[r].url:'<img src="'+d[r].url+'" alt=" " style="width:100%">';i+='<div class="modaal-gallery-item gallery-item-'+r+c+'" aria-label="'+m+'">'+p+d[r].desc+"</div>"}i+="</div>",1!=e.options.outer_controls&&(i+=e.scope.prev_btn+e.scope.next_btn)}else{var u,_=!1;e.$elem.attr("data-modaal-content-source")?u=e.$elem.attr("data-modaal-content-source"):e.$elem.attr("href")?u=e.$elem.attr("href"):e.$elem.attr("src")?u=e.$elem.attr("src"):(u="trigger requires href or data-modaal-content-source attribute",_=!0);var v="",f="",m="";e.$elem.attr("data-modaal-desc")?(m=e.$elem.attr("data-modaal-desc"),v=e.$elem.attr("data-modaal-desc"),f='<div class="modaal-gallery-label"><span class="modaal-accessible-hide">Image - </span>'+v.replace(/</g,"&lt;").replace(/>/g,"&gt;")+"</div>"):m="Image with no description";var p=_?u:'<img src="'+u+'" alt=" " style="width:100%">';i='<div class="modaal-gallery-item is_active" aria-label="'+m+'">'+p+f+"</div>"}t=i,e.build_modal(t),a(".modaal-gallery-item.is_active").is(".gallery-item-0")&&a(".modaal-gallery-prev").hide(),a(".modaal-gallery-item.is_active").is(".gallery-item-"+o)&&a(".modaal-gallery-next").hide()},gallery_update:function(t){var o=this,e=a("#"+o.scope.id),i=e.find(".modaal-gallery-item"),l=i.length-1;if(0==l)return!1;var n=e.find(".modaal-gallery-prev"),s=e.find(".modaal-gallery-next"),d=0,r=0,c=e.find(".modaal-gallery-item."+o.private_options.active_class),m="next"==t?c.next(".modaal-gallery-item"):c.prev(".modaal-gallery-item");return o.options.before_image_change.call(o,c,m),("prev"!=t||!e.find(".gallery-item-0").hasClass("is_active"))&&(("next"!=t||!e.find(".gallery-item-"+l).hasClass("is_active"))&&void c.stop().animate({opacity:0},250,function(){m.addClass("is_next").css({position:"absolute",display:"block",opacity:0});var t=a(document).width(),i=t>1140?280:50;d=e.find(".modaal-gallery-item.is_next").width(),r=e.find(".modaal-gallery-item.is_next").height();var p=e.find(".modaal-gallery-item.is_next img").prop("naturalWidth"),u=e.find(".modaal-gallery-item.is_next img").prop("naturalHeight");p>t-i?(d=t-i,e.find(".modaal-gallery-item.is_next").css({width:d}),e.find(".modaal-gallery-item.is_next img").css({width:d}),r=e.find(".modaal-gallery-item.is_next").find("img").height()):(d=p,r=u),e.find(".modaal-gallery-item-wrap").stop().animate({width:d,height:r},250,function(){c.removeClass(o.private_options.active_class+" "+o.options.gallery_active_class).removeAttr("style"),c.find("img").removeAttr("style"),m.addClass(o.private_options.active_class+" "+o.options.gallery_active_class).removeClass("is_next").css("position",""),m.stop().animate({opacity:1},250,function(){a(this).removeAttr("style").css({width:"100%"}),a(this).find("img").css("width","100%"),e.find(".modaal-gallery-item-wrap").removeAttr("style"),o.options.after_image_change.call(o,m)}),e.find(".modaal-gallery-item").removeAttr("tabindex"),e.find(".modaal-gallery-item."+o.private_options.active_class).attr("tabindex","0").focus(),e.find(".modaal-gallery-item."+o.private_options.active_class).is(".gallery-item-0")?n.stop().animate({opacity:0},150,function(){a(this).hide()}):n.stop().css({display:"block",opacity:n.css("opacity")}).animate({opacity:1},150),e.find(".modaal-gallery-item."+o.private_options.active_class).is(".gallery-item-"+l)?s.stop().animate({opacity:0},150,function(){a(this).hide()}):s.stop().css({display:"block",opacity:n.css("opacity")}).animate({opacity:1},150)})}))},create_video:function(a){var t,o=this;t='<iframe src="'+a+'" class="modaal-video-frame" frameborder="0" allowfullscreen></iframe>',o.build_modal('<div class="modaal-video-container">'+t+"</div>")},create_iframe:function(a){var t,o=this;t=null!==o.options.width||void 0!==o.options.width||null!==o.options.height||void 0!==o.options.height?'<iframe src="'+a+'" class="modaal-iframe-elem" frameborder="0" allowfullscreen></iframe>':'<div class="modaal-content-container">Please specify a width and height for your iframe</div>',o.build_modal(t)},modaal_open:function(){var t=this,o=a("#"+t.scope.id),e=t.options.animation;"none"===e&&(o.removeClass("modaal-start_none"),t.options.after_open.call(t,o)),"fade"===e&&o.removeClass("modaal-start_fade"),"slide-down"===e&&o.removeClass("modaal-start_slide_down");var i=o;a(".modaal-wrapper *[tabindex=0]").removeAttr("tabindex"),i="image"==t.options.type?a("#"+t.scope.id).find(".modaal-gallery-item."+t.private_options.active_class):o.find(".modaal-iframe-elem").length?o.find(".modaal-iframe-elem"):o.find(".modaal-video-wrap").length?o.find(".modaal-video-wrap"):o.find(".modaal-focus"),i.attr("tabindex","0").focus(),"none"!==e&&setTimeout(function(){t.options.after_open.call(t,o)},t.options.after_callback_delay)},modaal_close:function(){var t=this,o=a("#"+t.scope.id);t.options.before_close.call(t,o),null!==t.xhr&&(t.xhr.abort(),t.xhr=null),"none"===t.options.animation&&o.addClass("modaal-start_none"),"fade"===t.options.animation&&o.addClass("modaal-start_fade"),"slide-down"===t.options.animation&&o.addClass("modaal-start_slide_down"),setTimeout(function(){"inline"==t.options.type&&a("#"+t.scope.id+" .modaal-content-container").contents().detach().appendTo(t.scope.source),o.remove(),t.options.after_close.call(t),t.scope.is_open=!1},t.options.after_callback_delay),t.modaal_overlay("hide"),null!=t.lastFocus&&t.lastFocus.focus()},modaal_overlay:function(t){var o=this;"show"==t?(o.scope.is_open=!0,o.options.background_scroll||o.dom.addClass("modaal-noscroll"),a("#"+o.scope.id+"_overlay").length<1&&o.dom.append('<div class="modaal-overlay" id="'+o.scope.id+'_overlay"></div>'),a("#"+o.scope.id+"_overlay").css("background",o.options.background).stop().animate({opacity:o.options.overlay_opacity},o.options.animation_speed,function(){o.modaal_open()})):"hide"==t&&a("#"+o.scope.id+"_overlay").stop().animate({opacity:0},o.options.animation_speed,function(){a(this).remove(),o.dom.removeClass("modaal-noscroll")})},is_touch:function(){return"ontouchstart"in window||navigator.maxTouchPoints}},e=[];a.fn.modaal=function(t){return this.each(function(i){var l=a(this).data("modaal");if(l){if("string"==typeof t)switch(t){case"open":l.create_modaal(l);break;case"close":l.modaal_close()}}else{var n=Object.create(o);n.init(t,this),a.data(this,"modaal",n),e.push({element:a(this).attr("class"),options:t})}})},a.fn.modaal.options={type:"inline",content_source:null,animation:"fade",animation_speed:300,after_callback_delay:350,is_locked:!1,hide_close:!1,background:"#000",overlay_opacity:"0.8",overlay_close:!0,accessible_title:"Dialog Window",start_open:!1,fullscreen:!1,custom_class:"",background_scroll:!1,should_open:!0,close_text:"Close",close_aria_label:"Close (Press escape to close)",width:null,height:null,before_open:function(){},after_open:function(){},before_close:function(){},after_close:function(){},source:function(a,t){return t},confirm_button_text:"Confirm",confirm_cancel_button_text:"Cancel",confirm_title:"Confirm Title",confirm_content:"<p>This is the default confirm dialog content. Replace me through the options</p>",confirm_callback:function(){},confirm_cancel_callback:function(){},gallery_active_class:"gallery_active_item",outer_controls:!1,before_image_change:function(a,t){},after_image_change:function(a){},loading_content:'<div class="modaal-loading-spinner"><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div><div><div></div></div></div>',loading_class:"is_loading",ajax_error_class:"modaal-error",ajax_success:function(){},instagram_id:null},a(function(){var o=a(".modaal");o.length&&o.each(function(){t(a(this))});var i=new MutationObserver(function(o){o.forEach(function(o){if(o.addedNodes&&o.addedNodes.length>0){[].some.call(o.addedNodes,function(o){var i=a(o);(i.is("a")||i.is("button"))&&(i.hasClass("modaal")?t(i):e.forEach(function(t){if(t.element==i.attr("class"))return a(i).modaal(t.options),!1}))})}})}),l={subtree:!0,attributes:!0,childList:!0,characterData:!0};setTimeout(function(){i.observe(document.body,l)},500)})}(jQuery,window,document);
...\ No newline at end of file ...\ No newline at end of file
1 .sp-container{position:absolute;top:0;left:0;display:inline-block;z-index:9999994;overflow:hidden}.sp-original-input-container{position:relative;display:inline-flex}.sp-original-input-container input{margin:0!important}.sp-original-input-container .sp-add-on{width:40px;border-top-right-radius:0!important;border-bottom-right-radius:0!important}input.spectrum.with-add-on{border-top-left-radius:0;border-bottom-left-radius:0;border-left:0}.sp-original-input-container .sp-add-on .sp-colorize{height:100%;width:100%;border-radius:inherit}.sp-colorize-container{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.sp-container.sp-flat{position:relative}.sp-container,.sp-container *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.sp-top{position:relative;width:100%;display:inline-block}.sp-top-inner{position:absolute;top:0;left:0;bottom:0;right:0}.sp-color{position:absolute;top:0;left:0;bottom:0;right:20px!important}.sp-hue{position:absolute;top:0;right:0;bottom:0;width:12px;height:100%;left:initial!important}.sp-clear-enabled .sp-hue{top:15%;height:85%}.sp-fill{padding-top:80%}.sp-sat,.sp-val{position:absolute;top:0;left:0;right:0;bottom:0}.sp-alpha-enabled .sp-top{margin-bottom:28px!important}.sp-alpha-enabled .sp-alpha{display:block}.sp-alpha-handle{position:absolute;top:-3px;cursor:pointer;height:16px;border-radius:50%;width:16px;margin-right:5px;left:-2px;right:0;background:#f9f9f9;box-shadow:0 0 2px 0 #3a3a3a}.sp-alpha{display:none;position:absolute;bottom:-18px;right:0;left:0;height:10px}.sp-alpha-inner{border-radius:4px}.sp-clear{display:none}.sp-clear.sp-clear-display{background-position:center}.sp-clear-enabled .sp-clear{display:block;position:absolute;top:3px;right:0;bottom:0;cursor:pointer;left:initial;height:12px;width:12px}.sp-alpha,.sp-alpha-handle,.sp-clear,.sp-container,.sp-container button,.sp-container.sp-dragging .sp-input,.sp-dragger,.sp-preview,.sp-replacer,.sp-slider{-webkit-user-select:none;-moz-user-select:-moz-none;-o-user-select:none;user-select:none}.sp-container.sp-input-disabled .sp-input-container{display:none}.sp-container.sp-buttons-disabled .sp-button-container{display:none}.sp-container.sp-palette-buttons-disabled .sp-palette-button-container{display:none}.sp-palette-only .sp-picker-container{display:none}.sp-palette-disabled .sp-palette-container{display:none}.sp-initial-disabled .sp-initial{display:none}.sp-sat{background-image:-webkit-gradient(linear,0 0,100% 0,from(#fff),to(rgba(204,154,129,0)));background-image:-webkit-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-moz-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-o-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-ms-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:linear-gradient(to right,#fff,rgba(204,154,129,0))}.sp-val{border-radius:4px;background-image:-webkit-gradient(linear,0 100%,0 0,from(#000),to(rgba(204,154,129,0)));background-image:-webkit-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-moz-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-o-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-ms-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:linear-gradient(to top,#000,rgba(204,154,129,0))}.sp-hue{background:-moz-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:-ms-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:-o-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:-webkit-gradient(linear,left top,left bottom,from(red),color-stop(.17,#ff0),color-stop(.33,#0f0),color-stop(.5,#0ff),color-stop(.67,#00f),color-stop(.83,#f0f),to(red));background:-webkit-linear-gradient(top,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);background:linear-gradient(to bottom,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.sp-1{height:17%}.sp-2{height:16%}.sp-3{height:17%}.sp-4{height:17%}.sp-5{height:16%}.sp-6{height:17%}.sp-hidden{display:none!important}.sp-cf:after,.sp-cf:before{content:"";display:table}.sp-cf:after{clear:both}@media (max-device-width:480px){.sp-color{right:40%}.sp-hue{left:63%}.sp-fill{padding-top:60%}}.sp-dragger{border-radius:5px;height:10px;width:10px;border:1px solid #fff;cursor:pointer;position:absolute;top:0;left:0;margin-left:3px;margin-top:3px;box-shadow:0 0 2px 1px rgba(0,0,0,.2)}.sp-slider{position:absolute;top:0;cursor:pointer;height:16px;border-radius:50%;width:16px;left:-2px;background:#f9f9f9;box-shadow:0 0 2px 0 #3a3a3a;margin-top:8px}.sp-container{display:inline-flex;border-radius:0;background-color:#fff;padding:0;border-radius:4px;color:#000;box-shadow:0 0 0 1px rgba(99,114,130,.16),0 8px 16px rgba(27,39,51,.08)}.sp-clear,.sp-color,.sp-container,.sp-container button,.sp-container input,.sp-hue{font-size:12px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.sp-top{margin-bottom:10px}.sp-clear,.sp-color,.sp-hue,.sp-sat,.sp-val{border-radius:3px}.sp-input-container{margin-top:-5px}.sp-button-container.sp-cf,.sp-initial.sp-thumb.sp-cf,.sp-input-container.sp-cf{height:25px}.sp-picker-container .sp-cf{margin-bottom:10px}.sp-palette-row-initial>span:first-child{cursor:pointer}.sp-initial-disabled .sp-input-container{width:100%}.sp-input{padding:0 5px!important;margin:0;width:100%;box-shadow:none!important;height:100%!important;background:0 0;color:#3a3a3a;border-radius:2px!important;border:1px solid #e0e0e0!important;text-align:center;font-family:monospace;font-size:inherit!important}.sp-input:focus{border:1px solid orange}.sp-input.sp-validation-error{border:1px solid red;background:#fdd}.sp-palette-container,.sp-picker-container{position:relative;padding:10px}.sp-picker-container{width:200px;padding-bottom:0}.sp-palette-container{border-right:solid 1px #ccc}.sp-palette-only .sp-palette-container{border:0}.sp-palette .sp-thumb-el{display:block;position:relative;float:left;width:24px;height:15px;margin:3px;cursor:pointer;border:solid 2px transparent}.sp-palette .sp-thumb-el.sp-thumb-active,.sp-palette .sp-thumb-el:hover{border-color:orange}.sp-thumb-el{position:relative}.sp-initial{float:left}.sp-initial span{width:30px;height:25px;border:none;display:block;float:left;margin:0}.sp-initial .spe-thumb-el.sp-thumb-active{border-radius:0 5px 5px 0}.sp-initial .spe-thumb-el{border-radius:5px 0 0 5px}.sp-initial .sp-clear-display{background-position:center}.sp-button-container{float:right}.sp-palette-button-container{margin-top:10px}.sp-replacer{position:relative;overflow:hidden;cursor:pointer;display:inline-block;border-radius:3px;border:1px solid #aaa;color:#666;transition:border-color .3s;vertical-align:middle;width:3rem;height:1.5rem}.sp-replacer.sp-active,.sp-replacer:hover{border:1px solid #666;color:#000}.sp-replacer.sp-disabled{cursor:default;border-color:silver;color:silver}.sp-dd{position:absolute;font-size:10px;right:0;top:0;bottom:0;padding:0 2px;line-height:1.6rem;background-color:#fff}.sp-preview{position:relative;width:100%;height:100%;float:left;z-index:0}.sp-preview-inner{transition:background-color .2s}.sp-preview-inner.sp-clear-display{display:none}.sp-palette .sp-thumb-el{width:16px;height:16px;margin:3px;border:none;border-radius:3px}.sp-container button{border-radius:3px;border:none;background:0 0;line-height:1;padding:0 8px;height:25px;text-transform:capitalize;text-align:center;vertical-align:middle;cursor:pointer;color:#606c72;font-weight:700}.sp-container button.sp-choose{background-color:#3cab3b;color:#fff;margin-left:5px}.sp-container button:hover{opacity:.8}.sp-container button.sp-palette-toggle{width:100%;background-color:#f3f3f3;margin:0}.sp-palette span.sp-thumb-active,.sp-palette span:hover{border-color:#000}.sp-alpha,.sp-preview,.sp-thumb-el{position:relative;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.sp-alpha-inner,.sp-preview-inner,.sp-thumb-inner{display:block;position:absolute;top:0;left:0;bottom:0;right:0}.sp-palette .sp-thumb-inner{border-radius:3px;background-position:50% 50%;background-repeat:no-repeat}.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=)}.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=)}.sp-clear-display{background-repeat:no-repeat;background-position:center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABe0lEQVQokYXSsUtcQRTF4d8Jj+VhHSxkEQuLsEUKK0nhTBFTmLSSUhBCMCAWsmgIwWrBLk0akfwLCaSQKBJmtrIIISwpRFKIhViETScphGMzysMtvOVwvpm5d0bGNCuGWAOPgYdl6S8wSDn9b+bUhDHEKWAdeAFMANg+l/TV9ofcz6cjMIbYBvaBMds7QCqZ58CmpBNgPuV0DvAAIMyFGugWtJr7eTv38xEwkPRPErY7QDeG2LqFkjrAgu0dSd/KDVqSNmxvAZ8lfbS9AHRuYemnLWkv5XRVBrQMbAI/gTXgEzAJtJuwBVS2L2OIle03QA/4Lmkl5XQBXEqqbFcAVYFDYChpFngiqWf7l6TXKaezMt2Zkhk24THwG+jZriX9AFZvUAyxLbRke2D75O5zPAO+ADXwEtizjaRHwDvbTyUtppwOmicCHAJvbXcl9YA1SQDjtseA97YPRz7ATcUQp2y/kjRdevsjaTfldNrMjcDGBjXA3T96L7yvrgFzP69+0Ao/HAAAAABJRU5ErkJggg==)}
...\ No newline at end of file ...\ No newline at end of file
1 !function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports&&"object"==typeof module?module.exports=e(require("jquery")):e(jQuery)}(function(De,qe){"use strict";var e,Ie={beforeShow:a,move:a,change:a,show:a,hide:a,color:!1,flat:!1,type:"",showInput:!1,allowEmpty:!0,showButtons:!0,clickoutFiresChange:!0,showInitial:!1,showPalette:!0,showPaletteOnly:!1,hideAfterPaletteSelect:!1,togglePaletteOnly:!1,showSelectionPalette:!0,localStorageKey:!1,appendTo:"body",maxSelectionSize:8,locale:"en",cancelText:"cancel",chooseText:"choose",togglePaletteMoreText:"more",togglePaletteLessText:"less",clearText:"Clear Color Selection",noColorSelectedText:"No Color Selected",preferredFormat:"name",className:"",containerClassName:"",replacerClassName:"",showAlpha:!0,theme:"sp-light",palette:[["#000000","#444444","#5b5b5b","#999999","#bcbcbc","#eeeeee","#f3f6f4","#ffffff"],["#f44336","#744700","#ce7e00","#8fce00","#2986cc","#16537e","#6a329f","#c90076"],["#f4cccc","#fce5cd","#fff2cc","#d9ead3","#d0e0e3","#cfe2f3","#d9d2e9","#ead1dc"],["#ea9999","#f9cb9c","#ffe599","#b6d7a8","#a2c4c9","#9fc5e8","#b4a7d6","#d5a6bd"],["#e06666","#f6b26b","#ffd966","#93c47d","#76a5af","#6fa8dc","#8e7cc3","#c27ba0"],["#cc0000","#e69138","#f1c232","#6aa84f","#45818e","#3d85c6","#674ea7","#a64d79"],["#990000","#b45f06","#bf9000","#38761d","#134f5c","#0b5394","#351c75","#741b47"],["#660000","#783f04","#7f6000","#274e13","#0c343d","#073763","#20124d","#4c1130"]],selectionPalette:[],disabled:!1,offset:null},Ve=[],We=!!/msie/i.exec(window.navigator.userAgent),Be=((e=document.createElement("div").style).cssText="background-color:rgba(0,0,0,.5)",t(e.backgroundColor,"rgba")||t(e.backgroundColor,"hsla")),Ke=["<div class='sp-replacer'>","<div class='sp-preview'><div class='sp-preview-inner'></div></div>","<div class='sp-dd'>&#9660;</div>","</div>"].join(""),$e=function(){var e="";if(We)for(var t=1;t<=6;t++)e+="<div class='sp-"+t+"'></div>";return["<div class='sp-container sp-hidden'>","<div class='sp-palette-container'>","<div class='sp-palette sp-thumb sp-cf'></div>","<div class='sp-palette-button-container sp-cf'>","<button type='button' class='sp-palette-toggle'></button>","</div>","</div>","<div class='sp-picker-container'>","<div class='sp-top sp-cf'>","<div class='sp-fill'></div>","<div class='sp-top-inner'>","<div class='sp-color'>","<div class='sp-sat'>","<div class='sp-val'>","<div class='sp-dragger'></div>","</div>","</div>","</div>","<div class='sp-clear sp-clear-display'>","</div>","<div class='sp-hue'>","<div class='sp-slider'></div>",e,"</div>","</div>","<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>","</div>","<div class='sp-input-container sp-cf'>","<input class='sp-input' type='text' spellcheck='false' />","</div>","<div class='sp-initial sp-thumb sp-cf'></div>","<div class='sp-button-container sp-cf'>","<button class='sp-cancel' href='#'></button>","<button type='button' class='sp-choose'></button>","</div>","</div>","</div>"].join("")}();function t(e,t){return!!~(""+e).indexOf(t)}function Xe(e,t,a,o){for(var r=[],n=0;n<e.length;n++){var s=e[n];if(s){var i=tinycolor(s),l=i.toHsl().l<.5?"sp-thumb-el sp-thumb-dark":"sp-thumb-el sp-thumb-light";l+=tinycolor.equals(t,s)?" sp-thumb-active":"";var c=i.toString(o.preferredFormat||"rgb"),u=Be?"background-color:"+i.toRgbString():"filter:"+i.toFilter();r.push('<span title="'+c+'" data-color="'+i.toRgbString()+'" class="'+l+'"><span class="sp-thumb-inner" style="'+u+';"></span></span>')}else r.push('<span class="sp-thumb-el sp-clear-display" ><span class="sp-clear-palette-only" style="background-color: transparent;"></span></span>')}return"<div class='sp-cf "+a+"'>"+r.join("")+"</div>"}function n(e,t){var a,o,r,n,h=function(e,t){e.locale=e.locale||window.navigator.language,e.locale&&(e.locale=e.locale.split("-")[0].toLowerCase()),"en"!=e.locale&&De.spectrum.localization[e.locale]&&(e=De.extend({},De.spectrum.localization[e.locale],e));var a=De.extend({},Ie,e);return a.callbacks={move:Ge(a.move,t),change:Ge(a.change,t),show:Ge(a.show,t),hide:Ge(a.hide,t),beforeShow:Ge(a.beforeShow,t)},a}(t,e),s=h.type,d="flat"==s,i=h.showSelectionPalette,l=h.localStorageKey,c=h.theme,u=h.callbacks,f=(a=Qe,function(){var e=this,t=arguments;r&&clearTimeout(n),!r&&n||(n=setTimeout(function(){n=null,a.apply(e,t)},o))}),p=!(o=10),g=!1,b=0,m=0,v=0,x=0,y=0,T=0,w=0,_=0,k=0,P=0,C=1,S=[],M=[],z={},j=h.selectionPalette.slice(0),A=h.maxSelectionSize,R="sp-dragging",F=!1,H=null,L=e.ownerDocument,O=(L.body,De(e)),Q=!1,E=De($e,L).addClass(c),N=E.find(".sp-picker-container"),D=E.find(".sp-color"),q=E.find(".sp-dragger"),I=E.find(".sp-hue"),V=E.find(".sp-slider"),W=E.find(".sp-alpha-inner"),B=E.find(".sp-alpha"),K=E.find(".sp-alpha-handle"),$=E.find(".sp-input"),X=E.find(".sp-palette"),Y=E.find(".sp-initial"),G=E.find(".sp-cancel"),U=E.find(".sp-clear"),J=E.find(".sp-choose"),Z=E.find(".sp-palette-toggle"),ee=O.is("input"),te=(ee&&"color"===O.attr("type")&&Je(),ee&&"color"==s),ae=te?De(Ke).addClass(c).addClass(h.className).addClass(h.replacerClassName):De([]),oe=te?ae:O,re=ae.find(".sp-preview-inner"),ne=h.color||ee&&O.val(),se=!1,ie=h.preferredFormat,le=!h.showButtons||h.clickoutFiresChange,ce=!ne,ue=h.allowEmpty,fe=null,he=null,de=null,pe=null,ge=O.attr("id");if(ge!==qe&&0<ge.length){var be=De('label[for="'+ge+'"]');be.length&&be.on("click",function(e){return e.preventDefault(),O.spectrum("show"),!1})}function me(){if(h.showPaletteOnly&&(h.showPalette=!0),Z.text(h.showPaletteOnly?h.togglePaletteMoreText:h.togglePaletteLessText),h.palette){S=h.palette.slice(0),M=De.isArray(S[0])?S:[S],z={};for(var e=0;e<M.length;e++)for(var t=0;t<M[e].length;t++){var a=tinycolor(M[e][t]).toRgbString();z[a]=!0}h.showPaletteOnly&&!ne&&(ne=""===S[0][0]?S[0][0]:Object.keys(z)[0])}E.toggleClass("sp-flat",d),E.toggleClass("sp-input-disabled",!h.showInput),E.toggleClass("sp-alpha-enabled",h.showAlpha),E.toggleClass("sp-clear-enabled",ue),E.toggleClass("sp-buttons-disabled",!h.showButtons),E.toggleClass("sp-palette-buttons-disabled",!h.togglePaletteOnly),E.toggleClass("sp-palette-disabled",!h.showPalette),E.toggleClass("sp-palette-only",h.showPaletteOnly),E.toggleClass("sp-initial-disabled",!h.showInitial),E.addClass(h.className).addClass(h.containerClassName),Qe()}function ve(){if(l){try{var e=window.localStorage,t=e[l].split(",#");1<t.length&&(delete e[l],De.each(t,function(e,t){xe(t)}))}catch(e){}try{j=window.localStorage[l].split(";")}catch(e){}}}function xe(e){if(i){var t=tinycolor(e).toRgbString();if(!z[t]&&-1===De.inArray(t,j))for(j.push(t);j.length>A;)j.shift();if(l)try{window.localStorage[l]=j.join(";")}catch(e){}}}function ye(){var a=Re(),e=De.map(M,function(e,t){return Xe(e,a,"sp-palette-row sp-palette-row-"+t,h)});ve(),j&&e.push(Xe(function(){var e=[];if(h.showPalette)for(var t=0;t<j.length;t++){var a=tinycolor(j[t]).toRgbString();z[a]||e.push(j[t])}return e.reverse().slice(0,h.maxSelectionSize)}(),a,"sp-palette-row sp-palette-row-selection",h)),X.html(e.join(""))}function Te(){if(h.showInitial){var e=se,t=Re();Y.html(Xe([e,t],t,"sp-palette-row-initial",h))}}function we(){(m<=0||b<=0||x<=0)&&Qe(),g=!0,E.addClass(R),H=null,O.trigger("dragstart.spectrum",[Re()])}function _e(){g=!1,E.removeClass(R),O.trigger("dragstop.spectrum",[Re()])}function ke(e){if(F)F=!1;else if(null!==e&&""!==e||!ue){var t=tinycolor(e);t.isValid()?(Ae(t),Fe(),Oe()):$.addClass("sp-validation-error")}else Ae(null),Fe(),Oe()}function Pe(){(p?ze:Ce)()}function Ce(){var e=De.Event("beforeShow.spectrum");p?Qe():(O.trigger(e,[Re()]),!1===u.beforeShow(Re())||e.isDefaultPrevented()||(function(){for(var e=0;e<Ve.length;e++)Ve[e]&&Ve[e].hide()}(),p=!0,De(L).on("keydown.spectrum",Se),De(L).on("click.spectrum",Me),De(window).on("resize.spectrum",f),ae.addClass("sp-active"),E.removeClass("sp-hidden"),Qe(),He(),se=Re(),Te(),u.show(se),O.trigger("show.spectrum",[se])))}function Se(e){27===e.keyCode&&ze()}function Me(e){2!=e.button&&(g||(le?Oe(!0):je(),ze()))}function ze(){p&&!d&&(p=!1,De(L).off("keydown.spectrum",Se),De(L).off("click.spectrum",Me),De(window).off("resize.spectrum",f),ae.removeClass("sp-active"),E.addClass("sp-hidden"),u.hide(Re()),O.trigger("hide.spectrum",[Re()]))}function je(){Ae(se,!0),Oe(!0)}function Ae(e,t){var a,o;tinycolor.equals(e,Re())?He():(e&&e!==qe||!ue?(ce=!1,o=(a=tinycolor(e)).toHsv(),_=o.h%360/360,k=o.s,P=o.v,C=o.a):ce=!0,He(),a&&a.isValid()&&!t&&(ie=h.preferredFormat||a.getFormat()))}function Re(e){return e=e||{},ue&&ce?null:tinycolor.fromRatio({h:_,s:k,v:P,a:Math.round(1e3*C)/1e3},{format:e.format||ie})}function Fe(){He(),u.move(Re()),O.trigger("move.spectrum",[Re()])}function He(){$.removeClass("sp-validation-error"),Le();var e=tinycolor.fromRatio({h:_,s:1,v:1});D.css("background-color",e.toHexString());var t=ie;C<1&&(0!==C||"name"!==t)&&("hex"!==t&&"hex3"!==t&&"hex6"!==t&&"name"!==t||(t="rgb"));var a=Re({format:t}),o="";if(re.removeClass("sp-clear-display"),re.css("background-color","transparent"),!a&&ue)re.addClass("sp-clear-display");else{var r=a.toHexString(),n=a.toRgbString();if(Be||1===a.alpha?re.css("background-color",n):(re.css("background-color","transparent"),re.css("filter",a.toFilter())),h.showAlpha){var s=a.toRgb();s.a=0;var i=tinycolor(s).toRgbString(),l="linear-gradient(left, "+i+", "+r+")";We?W.css("filter",tinycolor(i).toFilter({gradientType:1},r)):(W.css("background","-webkit-"+l),W.css("background","-moz-"+l),W.css("background","-ms-"+l),W.css("background","linear-gradient(to right, "+i+", "+r+")"))}o=a.toString(t)}if(h.showInput&&$.val(o),O.val(o),"text"==h.type||"component"==h.type){var c=a;if(c&&he){var u=c.isLight()||c.getAlpha()<.4?"black":"white";he.css("background-color",c.toRgbString()).css("color",u)}else he.css("background-color",pe).css("color",de)}h.showPalette&&ye(),Te()}function Le(){var e=k,t=P;if(ue&&ce)K.hide(),V.hide(),q.hide();else{K.show(),V.show(),q.show();var a=e*b,o=m-t*m;a=Math.max(-v,Math.min(b-v,a-v)),o=Math.max(-v,Math.min(m-v,o-v)),q.css({top:o+"px",left:a+"px"});var r=C*y;K.css({left:r-T/2+"px"});var n=_*x;V.css({top:n-w+"px"})}}function Oe(e){var t=Re(),a=!tinycolor.equals(t,se);t&&(t.toString(ie),xe(t)),e&&a&&(u.change(t),F=!0,O.trigger("change",[t]))}function Qe(){var e,t,a,o,r,n,s,i,l,c,u,f;p&&(b=D.width(),m=D.height(),v=q.height(),I.width(),x=I.height(),w=V.height(),y=B.width(),T=K.width(),d||(E.css("position","absolute"),h.offset?E.offset(h.offset):E.offset((t=oe,a=(e=E).outerWidth(),o=e.outerHeight(),r=t.outerHeight(),n=e[0].ownerDocument,s=n.documentElement,i=s.clientWidth+De(n).scrollLeft(),l=s.clientHeight+De(n).scrollTop(),c=t.offset(),u=c.left,f=c.top,f+=r,u-=Math.min(u,i<u+a&&a<i?Math.abs(u+a-i):0),{top:f-=Math.min(f,l<f+o&&o<l?Math.abs(+(o+r)):0),bottom:c.bottom,left:u,right:c.right,width:c.width,height:c.height}))),Le(),h.showPalette&&ye(),O.trigger("reflow.spectrum"))}function Ee(){ze(),Q=!0,O.attr("disabled",!0),oe.addClass("sp-disabled")}!function(){if(We&&E.find("*:not(input)").attr("unselectable","on"),me(),fe=De('<span class="sp-original-input-container"></span>'),["margin"].forEach(function(e){fe.css(e,O.css(e))}),"block"==O.css("display")&&fe.css("display","flex"),te)O.after(ae).hide();else if("text"==s)fe.addClass("sp-colorize-container"),O.addClass("spectrum sp-colorize").wrap(fe);else if("component"==s){O.addClass("spectrum").wrap(fe);var e=De(["<div class='sp-colorize-container sp-add-on'>","<div class='sp-colorize'></div> ","</div>"].join(""));e.width(O.outerHeight()+"px").css("border-radius",O.css("border-radius")).css("border",O.css("border")),O.addClass("with-add-on").before(e)}if(he=O.parent().find(".sp-colorize"),de=he.css("color"),pe=he.css("background-color"),ue||U.hide(),d)O.after(E).hide();else{var t="parent"===h.appendTo?O.parent():De(h.appendTo);1!==t.length&&(t=De("body")),t.append(E)}function a(e){return e.data&&e.data.ignore?(Ae(De(e.target).closest(".sp-thumb-el").data("color")),Fe()):(Ae(De(e.target).closest(".sp-thumb-el").data("color")),Fe(),h.hideAfterPaletteSelect?(Oe(!0),ze()):Oe()),!1}ve(),oe.on("click.spectrum touchstart.spectrum",function(e){Q||Pe(),e.stopPropagation(),De(e.target).is("input")||e.preventDefault()}),!O.is(":disabled")&&!0!==h.disabled||Ee(),E.click(Ye),[$,O].forEach(function(t){t.change(function(){ke(t.val())}),t.on("paste",function(){setTimeout(function(){ke(t.val())},1)}),t.keydown(function(e){13==e.keyCode&&(ke(De(t).val()),t==O&&ze())})}),G.text(h.cancelText),G.on("click.spectrum",function(e){e.stopPropagation(),e.preventDefault(),je(),ze()}),U.attr("title",h.clearText),U.on("click.spectrum",function(e){e.stopPropagation(),e.preventDefault(),ce=!0,Fe(),d&&Oe(!0)}),J.text(h.chooseText),J.on("click.spectrum",function(e){e.stopPropagation(),e.preventDefault(),We&&$.is(":focus")&&$.trigger("change"),$.hasClass("sp-validation-error")||(Oe(!0),ze())}),Z.text(h.showPaletteOnly?h.togglePaletteMoreText:h.togglePaletteLessText),Z.on("click.spectrum",function(e){e.stopPropagation(),e.preventDefault(),h.showPaletteOnly=!h.showPaletteOnly,h.showPaletteOnly||d||E.css("left","-="+(N.outerWidth(!0)+5)),me()}),Ue(B,function(e,t,a){C=e/y,ce=!1,a.shiftKey&&(C=Math.round(10*C)/10),Fe()},we,_e),Ue(I,function(e,t){_=parseFloat(t/x),ce=!1,h.showAlpha||(C=1),Fe()},we,_e),Ue(D,function(e,t,a){if(a.shiftKey){if(!H){var o=k*b,r=m-P*m,n=Math.abs(e-o)>Math.abs(t-r);H=n?"x":"y"}}else H=null;var s=!H||"y"===H;H&&"x"!==H||(k=parseFloat(e/b)),s&&(P=parseFloat((m-t)/m)),ce=!1,h.showAlpha||(C=1),Fe()},we,_e),ne?(Ae(ne),He(),ie=tinycolor(ne).format||h.preferredFormat,xe(ne)):(""===ne&&Ae(ne),He()),d&&Ce();var o=We?"mousedown.spectrum":"click.spectrum touchstart.spectrum";X.on(o,".sp-thumb-el",a),Y.on(o,".sp-thumb-el:nth-child(1)",{ignore:!0},a)}();var Ne={show:Ce,hide:ze,toggle:Pe,reflow:Qe,option:function(e,t){return e===qe?De.extend({},h):t===qe?h[e]:(h[e]=t,"preferredFormat"===e&&(ie=h.preferredFormat),void me())},enable:function(){Q=!1,O.attr("disabled",!1),oe.removeClass("sp-disabled")},disable:Ee,offset:function(e){h.offset=e,Qe()},set:function(e){Ae(e),Oe()},get:Re,destroy:function(){O.show().removeClass("spectrum with-add-on sp-colorize"),oe.off("click.spectrum touchstart.spectrum"),E.remove(),ae.remove(),he&&he.css("background-color",pe).css("color",de);var e=O.closest(".sp-original-input-container");0<e.length&&e.after(O).remove(),Ve[Ne.id]=null},container:E};return Ne.id=Ve.push(Ne)-1,Ne}function a(){}function Ye(e){e.stopPropagation()}function Ge(e,t){var a=Array.prototype.slice,o=a.call(arguments,2);return function(){return e.apply(t,o.concat(a.call(arguments)))}}function Ue(s,i,t,e){i=i||function(){},t=t||function(){},e=e||function(){};var l=document,c=!1,u={},f=0,h=0,d="ontouchstart"in window,a={};function p(e){e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault(),e.returnValue=!1}function o(e){if(c){if(We&&l.documentMode<9&&!e.button)return g();var t=e.originalEvent&&e.originalEvent.touches&&e.originalEvent.touches[0],a=t&&t.pageX||e.pageX,o=t&&t.pageY||e.pageY,r=Math.max(0,Math.min(a-u.left,h)),n=Math.max(0,Math.min(o-u.top,f));d&&p(e),i.apply(s,[r,n,e])}}function g(){c&&(De(l).off(a),De(l.body).removeClass("sp-dragging"),setTimeout(function(){e.apply(s,arguments)},0)),c=!1}a.selectstart=p,a.dragstart=p,a["touchmove mousemove"]=o,a["touchend mouseup"]=g,De(s).on("touchstart mousedown",function(e){(e.which?3==e.which:2==e.button)||c||!1!==t.apply(s,arguments)&&(c=!0,f=De(s).height(),h=De(s).width(),u=De(s).offset(),De(l).on(a),De(l.body).addClass("sp-dragging"),o(e),p(e))})}function Je(){return De.fn.spectrum.inputTypeColorSupport()}var s="spectrum.id";De.fn.spectrum=function(a,e){if("string"!=typeof a)return this.spectrum("destroy").each(function(){var e=De.extend({},De(this).data(),a);De(this).is("input")?e.flat||"flat"==e.type?e.type="flat":"color"==De(this).attr("type")?e.type="color":e.type=e.type||"component":e.type="noInput";var t=n(this,e);De(this).data(s,t.id)});var o=this,r=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=Ve[De(this).data(s)];if(e){var t=e[a];if(!t)throw new Error("Spectrum: no such method: '"+a+"'");"get"==a?o=e.get():"container"==a?o=e.container:"option"==a?o=e.option.apply(e,r):"destroy"==a?(e.destroy(),De(this).removeData(s)):t.apply(e,r)}}),o},De.fn.spectrum.load=!0,De.fn.spectrum.loadOpts={},De.fn.spectrum.draggable=Ue,De.fn.spectrum.defaults=Ie,De.fn.spectrum.inputTypeColorSupport=function e(){if(void 0===e._cachedResult){var t=De("<input type='color'/>")[0];e._cachedResult="color"===t.type&&""!==t.value}return e._cachedResult},De.spectrum={},De.spectrum.localization={},De.spectrum.palettes={},De.fn.spectrum.processNativeColorInputs=function(){var e=De("input[type=color]");e.length&&!Je()&&e.spectrum({preferredFormat:"hex6"})},function(){var n=/^[\s,#]+/,s=/\s+$/,o=0,c=Math,i=c.round,u=c.min,f=c.max,e=c.random,h=function(e,t){if(t=t||{},(e=e||"")instanceof h)return e;if(!(this instanceof h))return new h(e,t);var a=function(e){var t={r:0,g:0,b:0},a=1,o=!1,r=!1;"string"==typeof e&&(e=function(e){e=e.replace(n,"").replace(s,"").toLowerCase();var t,a=!1;if(C[e])e=C[e],a=!0;else if("transparent"==e)return{r:0,g:0,b:0,a:0,format:"name"};if(t=Q.rgb.exec(e))return{r:t[1],g:t[2],b:t[3]};if(t=Q.rgba.exec(e))return{r:t[1],g:t[2],b:t[3],a:t[4]};if(t=Q.hsl.exec(e))return{h:t[1],s:t[2],l:t[3]};if(t=Q.hsla.exec(e))return{h:t[1],s:t[2],l:t[3],a:t[4]};if(t=Q.hsv.exec(e))return{h:t[1],s:t[2],v:t[3]};if(t=Q.hsva.exec(e))return{h:t[1],s:t[2],v:t[3],a:t[4]};if(t=Q.hex8.exec(e))return{a:function(e){return A(e)/255}(t[1]),r:A(t[2]),g:A(t[3]),b:A(t[4]),format:a?"name":"hex8"};if(t=Q.hex6.exec(e))return{r:A(t[1]),g:A(t[2]),b:A(t[3]),format:a?"name":"hex"};if(t=Q.hex3.exec(e))return{r:A(t[1]+""+t[1]),g:A(t[2]+""+t[2]),b:A(t[3]+""+t[3]),format:a?"name":"hex"};return!1}(e));"object"==typeof e&&(e.hasOwnProperty("r")&&e.hasOwnProperty("g")&&e.hasOwnProperty("b")?(t=function(e,t,a){return{r:255*z(e,255),g:255*z(t,255),b:255*z(a,255)}}(e.r,e.g,e.b),o=!0,r="%"===String(e.r).substr(-1)?"prgb":"rgb"):e.hasOwnProperty("h")&&e.hasOwnProperty("s")&&e.hasOwnProperty("v")?(e.s=F(e.s),e.v=F(e.v),t=function(e,t,a){e=6*z(e,360),t=z(t,100),a=z(a,100);var o=c.floor(e),r=e-o,n=a*(1-t),s=a*(1-r*t),i=a*(1-(1-r)*t),l=o%6;return{r:255*[a,s,n,n,i,a][l],g:255*[i,a,a,s,n,n][l],b:255*[n,n,i,a,a,s][l]}}(e.h,e.s,e.v),o=!0,r="hsv"):e.hasOwnProperty("h")&&e.hasOwnProperty("s")&&e.hasOwnProperty("l")&&(e.s=F(e.s),e.l=F(e.l),t=function(e,t,a){var o,r,n;function s(e,t,a){return a<0&&(a+=1),1<a&&--a,a<1/6?e+6*(t-e)*a:a<.5?t:a<2/3?e+(t-e)*(2/3-a)*6:e}if(e=z(e,360),t=z(t,100),a=z(a,100),0===t)o=r=n=a;else{var i=a<.5?a*(1+t):a+t-a*t,l=2*a-i;o=s(l,i,e+1/3),r=s(l,i,e),n=s(l,i,e-1/3)}return{r:255*o,g:255*r,b:255*n}}(e.h,e.s,e.l),o=!0,r="hsl"),e.hasOwnProperty("a")&&(a=e.a));return a=M(a),{ok:o,format:e.format||r,r:u(255,f(t.r,0)),g:u(255,f(t.g,0)),b:u(255,f(t.b,0)),a:a}}(e);this._originalInput=e,this._r=a.r,this._g=a.g,this._b=a.b,this._a=a.a,this._roundA=i(1e3*this._a)/1e3,this._format=t.format||a.format,this._gradientType=t.gradientType,this._r<1&&(this._r=i(this._r)),this._g<1&&(this._g=i(this._g)),this._b<1&&(this._b=i(this._b)),this._ok=a.ok,this._tc_id=o++};function r(e,t,a){e=z(e,255),t=z(t,255),a=z(a,255);var o,r,n=f(e,t,a),s=u(e,t,a),i=(n+s)/2;if(n==s)o=r=0;else{var l=n-s;switch(r=.5<i?l/(2-n-s):l/(n+s),n){case e:o=(t-a)/l+(t<a?6:0);break;case t:o=(a-e)/l+2;break;case a:o=(e-t)/l+4}o/=6}return{h:o,s:r,l:i}}function l(e,t,a){e=z(e,255),t=z(t,255),a=z(a,255);var o,r,n=f(e,t,a),s=u(e,t,a),i=n,l=n-s;if(r=0===n?0:l/n,n==s)o=0;else{switch(n){case e:o=(t-a)/l+(t<a?6:0);break;case t:o=(a-e)/l+2;break;case a:o=(e-t)/l+4}o/=6}return{h:o,s:r,v:i}}function t(e,t,a,o){var r=[R(i(e).toString(16)),R(i(t).toString(16)),R(i(a).toString(16))];return o&&r[0].charAt(0)==r[0].charAt(1)&&r[1].charAt(0)==r[1].charAt(1)&&r[2].charAt(0)==r[2].charAt(1)?r[0].charAt(0)+r[1].charAt(0)+r[2].charAt(0):r.join("")}function d(e,t,a,o){var r;return[R((r=o,Math.round(255*parseFloat(r)).toString(16))),R(i(e).toString(16)),R(i(t).toString(16)),R(i(a).toString(16))].join("")}function a(e,t){t=0===t?0:t||10;var a=h(e).toHsl();return a.s-=t/100,a.s=j(a.s),h(a)}function p(e,t){t=0===t?0:t||10;var a=h(e).toHsl();return a.s+=t/100,a.s=j(a.s),h(a)}function g(e){return h(e).desaturate(100)}function b(e,t){t=0===t?0:t||10;var a=h(e).toHsl();return a.l+=t/100,a.l=j(a.l),h(a)}function m(e,t){t=0===t?0:t||10;var a=h(e).toRgb();return a.r=f(0,u(255,a.r-i(-t/100*255))),a.g=f(0,u(255,a.g-i(-t/100*255))),a.b=f(0,u(255,a.b-i(-t/100*255))),h(a)}function v(e,t){t=0===t?0:t||10;var a=h(e).toHsl();return a.l-=t/100,a.l=j(a.l),h(a)}function x(e,t){var a=h(e).toHsl(),o=(i(a.h)+t)%360;return a.h=o<0?360+o:o,h(a)}function y(e){var t=h(e).toHsl();return t.h=(t.h+180)%360,h(t)}function T(e){var t=h(e).toHsl(),a=t.h;return[h(e),h({h:(a+120)%360,s:t.s,l:t.l}),h({h:(a+240)%360,s:t.s,l:t.l})]}function w(e){var t=h(e).toHsl(),a=t.h;return[h(e),h({h:(a+90)%360,s:t.s,l:t.l}),h({h:(a+180)%360,s:t.s,l:t.l}),h({h:(a+270)%360,s:t.s,l:t.l})]}function _(e){var t=h(e).toHsl(),a=t.h;return[h(e),h({h:(a+72)%360,s:t.s,l:t.l}),h({h:(a+216)%360,s:t.s,l:t.l})]}function k(e,t,a){t=t||6,a=a||30;var o=h(e).toHsl(),r=360/a,n=[h(e)];for(o.h=(o.h-(r*t>>1)+720)%360;--t;)o.h=(o.h+r)%360,n.push(h(o));return n}function P(e,t){t=t||6;for(var a=h(e).toHsv(),o=a.h,r=a.s,n=a.v,s=[],i=1/t;t--;)s.push(h({h:o,s:r,v:n})),n=(n+i)%1;return s}h.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},setAlpha:function(e){return this._a=M(e),this._roundA=i(1e3*this._a)/1e3,this},toHsv:function(){var e=l(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=l(this._r,this._g,this._b),t=i(360*e.h),a=i(100*e.s),o=i(100*e.v);return 1==this._a?"hsv("+t+", "+a+"%, "+o+"%)":"hsva("+t+", "+a+"%, "+o+"%, "+this._roundA+")"},toHsl:function(){var e=r(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=r(this._r,this._g,this._b),t=i(360*e.h),a=i(100*e.s),o=i(100*e.l);return 1==this._a?"hsl("+t+", "+a+"%, "+o+"%)":"hsla("+t+", "+a+"%, "+o+"%, "+this._roundA+")"},toHex:function(e){return t(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(){return d(this._r,this._g,this._b,this._a)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:i(this._r),g:i(this._g),b:i(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+i(this._r)+", "+i(this._g)+", "+i(this._b)+")":"rgba("+i(this._r)+", "+i(this._g)+", "+i(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:i(100*z(this._r,255))+"%",g:i(100*z(this._g,255))+"%",b:i(100*z(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+i(100*z(this._r,255))+"%, "+i(100*z(this._g,255))+"%, "+i(100*z(this._b,255))+"%)":"rgba("+i(100*z(this._r,255))+"%, "+i(100*z(this._g,255))+"%, "+i(100*z(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(S[t(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var t="#"+d(this._r,this._g,this._b,this._a),a=t,o=this._gradientType?"GradientType = 1, ":"";e&&(a=h(e).toHex8String());return"progid:DXImageTransform.Microsoft.gradient("+o+"startColorstr="+t+",endColorstr="+a+")"},toString:function(e){var t=!!e;e=e||this._format;var a=!1,o=this._a<1&&0<=this._a;return t||!o||"hex"!==e&&"hex6"!==e&&"hex3"!==e&&"name"!==e?("rgb"===e&&(a=this.toRgbString()),"prgb"===e&&(a=this.toPercentageRgbString()),"hex"!==e&&"hex6"!==e||(a=this.toHexString()),"hex3"===e&&(a=this.toHexString(!0)),"hex8"===e&&(a=this.toHex8String()),"name"===e&&(a=this.toName()),"hsl"===e&&(a=this.toHslString()),"hsv"===e&&(a=this.toHsvString()),a||this.toHexString()):"name"===e&&0===this._a?this.toName():this.toRgbString()},_applyModification:function(e,t){var a=e.apply(null,[this].concat([].slice.call(t)));return this._r=a._r,this._g=a._g,this._b=a._b,this.setAlpha(a._a),this},lighten:function(){return this._applyModification(b,arguments)},brighten:function(){return this._applyModification(m,arguments)},darken:function(){return this._applyModification(v,arguments)},desaturate:function(){return this._applyModification(a,arguments)},saturate:function(){return this._applyModification(p,arguments)},greyscale:function(){return this._applyModification(g,arguments)},spin:function(){return this._applyModification(x,arguments)},_applyCombination:function(e,t){return e.apply(null,[this].concat([].slice.call(t)))},analogous:function(){return this._applyCombination(k,arguments)},complement:function(){return this._applyCombination(y,arguments)},monochromatic:function(){return this._applyCombination(P,arguments)},splitcomplement:function(){return this._applyCombination(_,arguments)},triad:function(){return this._applyCombination(T,arguments)},tetrad:function(){return this._applyCombination(w,arguments)}},h.fromRatio=function(e,t){if("object"==typeof e){var a={};for(var o in e)e.hasOwnProperty(o)&&(a[o]="a"===o?e[o]:F(e[o]));e=a}return h(e,t)},h.equals=function(e,t){return!(!e||!t)&&h(e).toRgbString()==h(t).toRgbString()},h.random=function(){return h.fromRatio({r:e(),g:e(),b:e()})},h.mix=function(e,t,a){a=0===a?0:a||50;var o,r=h(e).toRgb(),n=h(t).toRgb(),s=a/100,i=2*s-1,l=n.a-r.a,c=1-(o=((o=i*l==-1?i:(i+l)/(1+i*l))+1)/2),u={r:n.r*o+r.r*c,g:n.g*o+r.g*c,b:n.b*o+r.b*c,a:n.a*s+r.a*(1-s)};return h(u)},h.readability=function(e,t){var a=h(e),o=h(t),r=a.toRgb(),n=o.toRgb(),s=a.getBrightness(),i=o.getBrightness(),l=Math.max(r.r,n.r)-Math.min(r.r,n.r)+Math.max(r.g,n.g)-Math.min(r.g,n.g)+Math.max(r.b,n.b)-Math.min(r.b,n.b);return{brightness:Math.abs(s-i),color:l}},h.isReadable=function(e,t){var a=h.readability(e,t);return 125<a.brightness&&500<a.color},h.mostReadable=function(e,t){for(var a=null,o=0,r=!1,n=0;n<t.length;n++){var s=h.readability(e,t[n]),i=125<s.brightness&&500<s.color,l=s.brightness/125*3+s.color/500;(i&&!r||i&&r&&o<l||!i&&!r&&o<l)&&(r=i,o=l,a=h(t[n]))}return a};var C=h.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},S=h.hexNames=function(e){var t={};for(var a in e)e.hasOwnProperty(a)&&(t[e[a]]=a);return t}(C);function M(e){return e=parseFloat(e),(isNaN(e)||e<0||1<e)&&(e=1),e}function z(e,t){var a;"string"==typeof(a=e)&&-1!=a.indexOf(".")&&1===parseFloat(a)&&(e="100%");var o,r="string"==typeof(o=e)&&-1!=o.indexOf("%");return e=u(t,f(0,parseFloat(e))),r&&(e=parseInt(e*t,10)/100),c.abs(e-t)<1e-6?1:e%t/parseFloat(t)}function j(e){return u(1,f(0,e))}function A(e){return parseInt(e,16)}function R(e){return 1==e.length?"0"+e:""+e}function F(e){return e<=1&&(e=100*e+"%"),e}var H,L,O,Q=(L="[\\s|\\(]+("+(H="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+H+")[,|\\s]+("+H+")\\s*\\)?",O="[\\s|\\(]+("+H+")[,|\\s]+("+H+")[,|\\s]+("+H+")[,|\\s]+("+H+")\\s*\\)?",{rgb:new RegExp("rgb"+L),rgba:new RegExp("rgba"+O),hsl:new RegExp("hsl"+L),hsla:new RegExp("hsla"+O),hsv:new RegExp("hsv"+L),hsva:new RegExp("hsva"+O),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});window.tinycolor=h}(),De(function(){De.fn.spectrum.load&&De.fn.spectrum.processNativeColorInputs()})}),jQuery.spectrum.localization.ar={cancelText:"إلغاء",chooseText:"إختار",clearText:"إرجاع الألوان على ما كانت",noColorSelectedText:"لم تختار أي لون",togglePaletteMoreText:"أكثر",togglePaletteLessText:"أقل"},jQuery.spectrum.localization.ca={cancelText:"Cancel·lar",chooseText:"Escollir",clearText:"Esborrar color seleccionat",noColorSelectedText:"Cap color seleccionat",togglePaletteMoreText:"Més",togglePaletteLessText:"Menys"},jQuery.spectrum.localization.cs={cancelText:"zrušit",chooseText:"vybrat",clearText:"Resetovat výměr barev",noColorSelectedText:"Žádná barva nebyla vybrána",togglePaletteMoreText:"více",togglePaletteLessText:"méně"},jQuery.spectrum.localization.de={cancelText:"Abbrechen",chooseText:"Wählen",clearText:"Farbauswahl zurücksetzen",noColorSelectedText:"Keine Farbe ausgewählt",togglePaletteMoreText:"Mehr",togglePaletteLessText:"Weniger"},jQuery.spectrum.localization.dk={cancelText:"annuller",chooseText:"Vælg"},jQuery.spectrum.localization.es={cancelText:"Cancelar",chooseText:"Elegir",clearText:"Borrar color seleccionado",noColorSelectedText:"Ningún color seleccionado",togglePaletteMoreText:"Más",togglePaletteLessText:"Menos"},jQuery.spectrum.localization.et={cancelText:"Katkesta",chooseText:"Vali",clearText:"Tühista värvivalik",noColorSelectedText:"Ühtki värvi pole valitud",togglePaletteMoreText:"Rohkem",togglePaletteLessText:"Vähem"},jQuery.spectrum.localization.fa={cancelText:"لغو",chooseText:"انتخاب",clearText:"تنظیم مجدد رنگ",noColorSelectedText:"هیچ رنگی انتخاب نشده است!",togglePaletteMoreText:"بیشتر",togglePaletteLessText:"کمتر"},jQuery.spectrum.localization.fi={cancelText:"Kumoa",chooseText:"Valitse"},jQuery.spectrum.localization.fr={cancelText:"Annuler",chooseText:"Valider",clearText:"Effacer couleur sélectionnée",noColorSelectedText:"Aucune couleur sélectionnée",togglePaletteMoreText:"Plus",togglePaletteLessText:"Moins"},jQuery.spectrum.localization.gr={cancelText:"Ακύρωση",chooseText:"Επιλογή",clearText:"Καθαρισμός επιλεγμένου χρώματος",noColorSelectedText:"Δεν έχει επιλεχθεί κάποιο χρώμα",togglePaletteMoreText:"Περισσότερα",togglePaletteLessText:"Λιγότερα"},jQuery.spectrum.localization.he={cancelText:"בטל בחירה",chooseText:"בחר צבע",clearText:"אפס בחירה",noColorSelectedText:"לא נבחר צבע",togglePaletteMoreText:"עוד צבעים",togglePaletteLessText:"פחות צבעים"},jQuery.spectrum.localization.hr={cancelText:"Odustani",chooseText:"Odaberi",clearText:"Poništi odabir",noColorSelectedText:"Niti jedna boja nije odabrana",togglePaletteMoreText:"Više",togglePaletteLessText:"Manje"},jQuery.spectrum.localization.hu={cancelText:"Mégsem",chooseText:"Mentés",clearText:"A színválasztás visszaállítása",noColorSelectedText:"Nincs szín kijelölve",togglePaletteMoreText:"Több",togglePaletteLessText:"Kevesebb"},jQuery.spectrum.localization.id={cancelText:"Batal",chooseText:"Pilih",clearText:"Hapus Pilihan Warna",noColorSelectedText:"Warna Tidak Dipilih",togglePaletteMoreText:"tambah",togglePaletteLessText:"kurangi"},jQuery.spectrum.localization.it={cancelText:"annulla",chooseText:"scegli",clearText:"Annulla selezione colore",noColorSelectedText:"Nessun colore selezionato"},jQuery.spectrum.localization.ja={cancelText:"中止",chooseText:"選択"},jQuery.spectrum.localization.ko={cancelText:"취소",chooseText:"선택",clearText:"선택 초기화",noColorSelectedText:"선택된 색상 없음",togglePaletteMoreText:"더보기",togglePaletteLessText:"줄이기"},jQuery.spectrum.localization.lt={cancelText:"Atšaukti",chooseText:"Pasirinkti",clearText:"Išvalyti pasirinkimą",noColorSelectedText:"Spalva nepasirinkta",togglePaletteMoreText:"Daugiau",togglePaletteLessText:"Mažiau"},jQuery.spectrum.localization["nb-no"]={cancelText:"Avbryte",chooseText:"Velg",clearText:"Tilbakestill",noColorSelectedText:"Farge er ikke valgt",togglePaletteMoreText:"Mer",togglePaletteLessText:"Mindre"},jQuery.spectrum.localization["nl-nl"]={cancelText:"Annuleer",chooseText:"Kies",clearText:"Wis kleur selectie",togglePaletteMoreText:"Meer",togglePaletteLessText:"Minder"},jQuery.spectrum.localization.pl={cancelText:"Anuluj",chooseText:"Wybierz",clearText:"Usuń wybór koloru",noColorSelectedText:"Nie wybrano koloru",togglePaletteMoreText:"Więcej",togglePaletteLessText:"Mniej"},jQuery.spectrum.localization["pt-br"]={cancelText:"Cancelar",chooseText:"Escolher",clearText:"Limpar cor selecionada",noColorSelectedText:"Nenhuma cor selecionada",togglePaletteMoreText:"Mais",togglePaletteLessText:"Menos"},jQuery.spectrum.localization["pt-pt"]={cancelText:"Cancelar",chooseText:"Escolher",clearText:"Limpar cor seleccionada",noColorSelectedText:"Nenhuma cor seleccionada",togglePaletteMoreText:"Mais",togglePaletteLessText:"Menos"},jQuery.spectrum.localization.ru={cancelText:"Отмена",chooseText:"Выбрать",clearText:"Сбросить",noColorSelectedText:"Цвет не выбран",togglePaletteMoreText:"Ещё",togglePaletteLessText:"Скрыть"},jQuery.spectrum.localization.sv={cancelText:"Avbryt",chooseText:"Välj"},jQuery.spectrum.localization.tr={cancelText:"iptal",chooseText:"tamam"},jQuery.spectrum.localization["zh-cn"]={cancelText:"取消",chooseText:"选择",clearText:"清除",togglePaletteMoreText:"更多选项",togglePaletteLessText:"隐藏",noColorSelectedText:"尚未选择任何颜色"},jQuery.spectrum.localization["zh-tw"]={cancelText:"取消",chooseText:"選擇",clearText:"清除",togglePaletteMoreText:"更多選項",togglePaletteLessText:"隱藏",noColorSelectedText:"尚未選擇任何顏色"};
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 /*
3 Plugin Name: Cookie Notice & Compliance for GDPR / CCPA
4 Description: Cookie Notice allows you to you elegantly inform users that your site uses cookies and helps you comply with GDPR, CCPA and other data privacy laws.
5 Version: 2.4.10
6 Author: Hu-manity.co
7 Author URI: https://hu-manity.co/
8 Plugin URI: https://cookie-compliance.co/
9 License: MIT License
10 License URI: https://opensource.org/licenses/MIT
11 Text Domain: cookie-notice
12 Domain Path: /languages
13
14 Cookie Notice
15 Copyright (C) 2023, Hu-manity.co - info@hu-manity.co
16
17 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 // exit if accessed directly
25 if ( ! defined( 'ABSPATH' ) )
26 exit;
27
28 /**
29 * Cookie Notice class.
30 *
31 * @class Cookie_Notice
32 * @version 2.4.10
33 */
34 class Cookie_Notice {
35
36 private $status_data = [
37 'status' => '',
38 'subscription' => 'basic',
39 'threshold_exceeded' => false
40 ];
41 private $x_api_key = 'hudft60djisdusdjwek';
42 private $app_host_url = 'https://app.hu-manity.co';
43 private $app_login_url = 'https://app.hu-manity.co/#/en/cc2/login';
44 private $app_dashboard_url = 'https://app.hu-manity.co/#/en/cc/dashboard';
45 private $account_api_url = 'https://account-api.hu-manity.co';
46 private $designer_api_url = 'https://designer-api.hu-manity.co';
47 private $transactional_api_url = 'https://transactional-api.hu-manity.co';
48 private $app_widget_url = '//cdn.hu-manity.co/hu-banner.min.js';
49 private $deactivaion_url = '';
50 private $network_admin = false;
51 private $plugin_network_active = false;
52 private static $_instance;
53 private $notices = [];
54 public $options = [];
55 public $network_options = [];
56 public $bot_detect;
57 public $dashboard;
58 public $frontend;
59 public $settings;
60 public $welcome;
61 public $welcome_api;
62 public $welcome_frontend;
63 public $db_version;
64
65 /**
66 * @var $defaults
67 */
68 public $defaults = [
69 'general' => [
70 'global_override' => false,
71 'global_cookie' => false,
72 'app_id' => '',
73 'app_key' => '',
74 'app_blocking' => true,
75 'conditional_active' => false,
76 'conditional_display' => 'hide',
77 'conditional_rules' => [],
78 'caching_compatibility' => true,
79 'debug_mode' => false,
80 'position' => 'bottom',
81 'message_text' => '',
82 'css_class' => '',
83 'accept_text' => '',
84 'refuse_text' => '',
85 'refuse_opt' => false,
86 'refuse_code' => '',
87 'refuse_code_head' => '',
88 'revoke_cookies' => false,
89 'revoke_cookies_opt' => 'automatic',
90 'revoke_message_text' => '',
91 'revoke_text' => '',
92 'redirection' => false,
93 'see_more' => false,
94 'link_target' => '_blank',
95 'link_position' => 'banner',
96 'time' => 'month',
97 'time_rejected' => 'month',
98 'hide_effect' => 'fade',
99 'on_scroll' => false,
100 'on_scroll_offset' => 100,
101 'on_click' => false,
102 'colors' => [
103 'text' => '#fff',
104 'button' => '#00a99d',
105 'bar' => '#32323a',
106 'bar_opacity' => 100
107 ],
108 'see_more_opt' => [
109 'text' => '',
110 'link_type' => 'page',
111 'id' => 0,
112 'link' => '',
113 'sync' => false
114 ],
115 'script_placement' => 'header',
116 'translate' => true,
117 'deactivation_delete' => false,
118 'update_version' => 8,
119 'update_notice' => true,
120 'update_notice_diss' => false,
121 'update_delay_date' => 0,
122 'update_threshold_date' => 0
123 ],
124 'data' => [
125 'status' => '',
126 'subscription' => 'basic',
127 'threshold_exceeded' => false
128 ],
129 'version' => '2.4.10'
130 ];
131
132 /**
133 * Disable object cloning.
134 *
135 * @return void
136 */
137 public function __clone() {}
138
139 /**
140 * Disable unserializing of the class.
141 *
142 * @return void
143 */
144 public function __wakeup() {}
145
146 /**
147 * Main plugin instance.
148 *
149 * @return object
150 */
151 public static function instance() {
152 if ( self::$_instance === null ) {
153 self::$_instance = new self();
154
155 add_action( 'init', [ self::$_instance, 'load_textdomain' ] );
156
157 self::$_instance->includes();
158
159 self::$_instance->bot_detect = new Cookie_Notice_Bot_Detect();
160 self::$_instance->dashboard = new Cookie_Notice_Dashboard();
161 self::$_instance->frontend = new Cookie_Notice_Frontend();
162 self::$_instance->settings = new Cookie_Notice_Settings();
163 self::$_instance->welcome = new Cookie_Notice_Welcome();
164 self::$_instance->welcome_api = new Cookie_Notice_Welcome_API();
165 self::$_instance->welcome_frontend = new Cookie_Notice_Welcome_Frontend();
166 }
167
168 return self::$_instance;
169 }
170
171 /**
172 * Class constructor.
173 *
174 * @return void
175 */
176 public function __construct() {
177 // define plugin constants
178 $this->define_constants();
179
180 // activation hooks
181 register_activation_hook( __FILE__, [ $this, 'activation' ] );
182 register_deactivation_hook( __FILE__, [ $this, 'deactivation' ] );
183
184 // set network data
185 $this->set_network_data();
186
187 $this->check_legacy_options();
188
189 // get options
190 if ( is_multisite() ) {
191 // get network options
192 $this->network_options = get_site_option( 'cookie_notice_options', $this->defaults['general'] );
193
194 if ( $this->is_network_admin() ) {
195 $options = $this->network_options;
196 } else {
197 $page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : '';
198
199 // settings page?
200 if ( is_admin() && $page === 'cookie-notice' ) {
201 // get current url path
202 $url_path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
203
204 if ( is_string( $url_path ) && basename( $url_path ) === 'admin.php' ) {
205 // get site options
206 $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
207 }
208 } else {
209 if ( $this->is_plugin_network_active() && $this->network_options['global_override'] )
210 $options = $this->network_options;
211 else
212 $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
213 }
214 }
215 } else
216 $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
217
218 // merge old options with new ones
219 $this->options['general'] = $this->multi_array_merge( $this->defaults['general'], $options );
220
221 if ( ! isset( $this->options['general']['see_more_opt']['sync'] ) )
222 $this->options['general']['see_more_opt']['sync'] = $this->defaults['general']['see_more_opt']['sync'];
223
224 // actions
225 add_action( 'plugins_loaded', [ $this, 'set_status_data' ] );
226 add_action( 'init', [ $this, 'register_shortcodes' ] );
227 add_action( 'init', [ $this, 'wpsc_add_cookie' ] );
228 add_action( 'init', [ $this, 'set_plugin_links' ] );
229 add_action( 'admin_init', [ $this, 'update_notice' ] );
230 add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
231 add_action( 'admin_footer', [ $this, 'deactivate_plugin_template' ] );
232 add_action( 'wp_ajax_cn_dismiss_notice', [ $this, 'ajax_dismiss_admin_notice' ] );
233 add_action( 'wp_ajax_cn-deactivate-plugin', [ $this, 'deactivate_plugin' ] );
234 }
235
236 /**
237 * Check legacy options.
238 *
239 * @return void
240 */
241 public function check_legacy_options() {
242 // multisite?
243 if ( is_multisite() ) {
244 // get network options
245 $site_options = get_site_option( 'cookie_notice_options', $this->defaults['general'] );
246
247 // update legacy options
248 $site_options = $this->update_legacy_options( $site_options );
249
250 // any changes?
251 if ( $site_options !== false )
252 update_site_option( 'cookie_notice_options', $site_options );
253 }
254
255 // get options
256 $options = get_option( 'cookie_notice_options', $this->defaults['general'] );
257
258 // update legacy options
259 $options = $this->update_legacy_options( $options );
260
261 // any changes?
262 if ( $options !== false )
263 update_option( 'cookie_notice_options', $options );
264 }
265
266 /**
267 * Maybe change legacy options.
268 *
269 * @param array $options
270 * @return false|array
271 */
272 public function update_legacy_options( $options ) {
273 $options_changed = false;
274
275 // check legacy parameters that were yes/no strings
276 foreach ( [ 'refuse_opt', 'on_scroll', 'on_click', 'deactivation_delete', 'see_more' ] as $param ) {
277 if ( array_key_exists( $param, $options ) && ! is_bool( $options[$param] ) ) {
278 $options[$param] = $options[$param] === 'yes';
279
280 $options_changed = true;
281 }
282 }
283
284 // check hide banner
285 if ( isset( $options['hide_banner'] ) ) {
286 if ( $options['hide_banner'] && ! isset( $options['conditional_active'] ) ) {
287 $options['conditional_active'] = true;
288 $options['conditional_display'] = 'hide';
289 $options['conditional_rules'] = [
290 1 => [
291 1 => [
292 'param' => 'user_type',
293 'operator' => 'equal',
294 'value' => 'logged_in'
295 ]
296 ]
297 ];
298 }
299
300 unset( $options['hide_banner'] );
301
302 $options_changed = true;
303 }
304
305 if ( $options_changed )
306 return $options;
307 else
308 return false;
309 }
310
311 /**
312 * Setup plugin constants.
313 *
314 * @return void
315 */
316 private function define_constants() {
317 define( 'COOKIE_NOTICE_URL', plugins_url( '', __FILE__ ) );
318 define( 'COOKIE_NOTICE_PATH', plugin_dir_path( __FILE__ ) );
319 define( 'COOKIE_NOTICE_BASENAME', plugin_basename( __FILE__ ) );
320 }
321
322 /**
323 * Set cookie compliance status data.
324 *
325 * @return void
326 */
327 public function set_status_data() {
328 $default_data = $this->defaults['data'];
329
330 if ( is_multisite() ) {
331 if ( $this->is_plugin_network_active() ) {
332 // network
333 if ( $this->is_network_admin() ) {
334 if ( $this->network_options['global_override'] )
335 $status_data = get_site_option( 'cookie_notice_status', $default_data );
336 else
337 $status_data = $default_data;
338 // site
339 } else {
340 if ( $this->network_options['global_override'] )
341 $status_data = get_site_option( 'cookie_notice_status', $default_data );
342 else
343 $status_data = get_option( 'cookie_notice_status', $default_data );
344 }
345 } else {
346 // network
347 if ( $this->is_network_admin() )
348 $status_data = $default_data;
349 // site
350 else
351 $status_data = get_option( 'cookie_notice_status', $default_data );
352 }
353 } else
354 $status_data = get_option( 'cookie_notice_status', $default_data );
355
356 // old status format?
357 if ( ! is_array( $status_data ) ) {
358 // update config data
359 $status_data = $this->welcome_api->get_app_config( '', true );
360 } else {
361 // merge database data with default data
362 $status_data = array_merge( $default_data, $status_data );
363 }
364
365 if ( $status_data['threshold_exceeded'] )
366 $this->options['general']['app_blocking'] = false;
367
368 // set status data
369 $this->status_data = [
370 'status' => $this->check_status( $status_data['status'] ),
371 'subscription' => $this->check_subscription( $status_data['subscription'] ),
372 'threshold_exceeded' => (bool) $status_data['threshold_exceeded']
373 ];
374 }
375
376 /**
377 * Get cookie compliance status.
378 *
379 * @return string
380 */
381 public function get_status() {
382 return $this->status_data['status'];
383 }
384
385 /**
386 * Check cookie compliance status.
387 *
388 * @param string $status
389 * @return string
390 */
391 public function check_status( $status ) {
392 $status = sanitize_key( $status );
393
394 return ! empty( $status ) && in_array( $status, [ 'active', 'pending' ], true ) ? $status : $this->defaults['data']['status'];
395 }
396
397 /**
398 * Get cookie compliance subscription.
399 *
400 * @return string
401 */
402 public function get_subscription() {
403 return $this->status_data['subscription'];
404 }
405
406 /**
407 * Check cookie compliance subscription.
408 *
409 * @param string $subscription
410 * @return string
411 */
412 public function check_subscription( $subscription ) {
413 $subscription = sanitize_key( $subscription );
414
415 return ! empty( $subscription ) && in_array( $subscription, [ 'basic', 'pro' ], true ) ? $subscription : $this->defaults['data']['subscription'];
416 }
417
418 /**
419 * Check whether the current threshold is exceeded.
420 *
421 * @return bool
422 */
423 public function threshold_exceeded() {
424 return $this->status_data['threshold_exceeded'];
425 }
426
427 /**
428 * Get endpoint URL.
429 *
430 * @param string $type
431 * @param string $query
432 * @return string
433 */
434 public function get_url( $type, $query = '' ) {
435 if ( $type === 'login' )
436 $url = $this->app_login_url;
437 elseif ( $type === 'dashboard' )
438 $url = $this->app_dashboard_url;
439 elseif ( $type === 'widget' )
440 $url = $this->app_widget_url;
441 elseif ( $type === 'host' )
442 $url = $this->app_host_url;
443 elseif ( $type === 'account_api' )
444 $url = $this->account_api_url;
445 elseif ( $type === 'designer_api' )
446 $url = $this->designer_api_url;
447 elseif ( $type === 'transactional_api' )
448 $url = $this->transactional_api_url;
449
450 return $url . ( $query !== '' ? $query : '' );
451 }
452
453 /**
454 * Get API key.
455 *
456 * @return string
457 */
458 public function get_api_key() {
459 return $this->x_api_key;
460 }
461
462 /**
463 * Check whether the current request is for the network administrative interface.
464 *
465 * @return bool
466 */
467 public function is_network_admin() {
468 return $this->network_admin;
469 }
470
471 /**
472 * Check whether the plugin is active for the entire network.
473 *
474 * @return bool
475 */
476 public function is_plugin_network_active() {
477 return $this->plugin_network_active;
478 }
479
480 /**
481 * Set network data.
482 *
483 * @return void
484 */
485 private function set_network_data() {
486 // load plugin.php file
487 if ( ! function_exists( 'is_plugin_active_for_network' ) )
488 require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
489
490 $cn_network = isset( $_POST['cn_network'] ) ? (int) $_POST['cn_network'] : false;
491
492 // bypass is_network_admin() to handle AJAX requests properly.
493 $this->network_admin = is_multisite() && ( is_network_admin() || ( wp_doing_ajax() && $cn_network === 1 ) );
494
495 // check whether the plugin is active for the entire network.
496 $this->plugin_network_active = is_plugin_active_for_network( COOKIE_NOTICE_BASENAME );
497 }
498
499 /**
500 * Include required files.
501 *
502 * @return void
503 */
504 private function includes() {
505 include_once( COOKIE_NOTICE_PATH . 'includes/bot-detect.php' );
506 include_once( COOKIE_NOTICE_PATH . 'includes/dashboard.php' );
507 include_once( COOKIE_NOTICE_PATH . 'includes/frontend.php' );
508 include_once( COOKIE_NOTICE_PATH . 'includes/functions.php' );
509 include_once( COOKIE_NOTICE_PATH . 'includes/settings.php' );
510 include_once( COOKIE_NOTICE_PATH . 'includes/welcome.php' );
511 include_once( COOKIE_NOTICE_PATH . 'includes/welcome-api.php' );
512 include_once( COOKIE_NOTICE_PATH . 'includes/welcome-frontend.php' );
513 }
514
515 /**
516 * Load textdomain.
517 *
518 * @return void
519 */
520 public function load_textdomain() {
521 load_plugin_textdomain( 'cookie-notice', false, dirname( COOKIE_NOTICE_BASENAME ) . '/languages/' );
522 }
523
524 /**
525 * Plugin activation.
526 *
527 * @global object $wpdb
528 *
529 * @param bool $network
530 * @return void
531 */
532 public function activation( $network ) {
533 // network activation?
534 if ( is_multisite() && $network ) {
535 // add network options
536 add_site_option( 'cookie_notice_options', $this->defaults['general'] );
537 add_site_option( 'cookie_notice_status', $this->defaults['data'] );
538 add_site_option( 'cookie_notice_version', $this->defaults['version'] );
539
540 global $wpdb;
541
542 // get all available sites
543 $blogs_ids = $wpdb->get_col( 'SELECT blog_id FROM ' . $wpdb->blogs );
544
545 foreach ( $blogs_ids as $blog_id ) {
546 // change to another site
547 switch_to_blog( (int) $blog_id );
548
549 // run current site activation process
550 $this->activate_site();
551
552 restore_current_blog();
553 }
554 } else
555 $this->activate_site();
556 }
557
558 /**
559 * Single site activation.
560 *
561 * @return void
562 */
563 public function activate_site() {
564 // add default options
565 add_option( 'cookie_notice_options', $this->defaults['general'], '', false );
566 add_option( 'cookie_notice_status', $this->defaults['data'], '', false );
567 add_option( 'cookie_notice_version', $this->defaults['version'], '', false );
568 }
569
570 /**
571 * Plugin deactivation.
572 *
573 * @global object $wpdb
574 *
575 * @param bool $network
576 * @return void
577 */
578 public function deactivation( $network ) {
579 // network deactivation?
580 if ( is_multisite() && $network ) {
581 $delete = $this->options['general']['global_override'] && $this->options['general']['deactivation_delete'];
582
583 // delete network options?
584 if ( $delete ) {
585 delete_site_option( 'cookie_notice_options' );
586 delete_site_option( 'cookie_notice_status' );
587 delete_site_option( 'cookie_notice_app_analytics' );
588 delete_site_option( 'cookie_notice_app_blocking' );
589 delete_site_option( 'cookie_notice_version' );
590 }
591
592 global $wpdb;
593
594 // get all available sites
595 $blogs_ids = $wpdb->get_col( 'SELECT blog_id FROM ' . $wpdb->blogs );
596
597 foreach ( $blogs_ids as $blog_id ) {
598 // change to another site
599 switch_to_blog( (int) $blog_id );
600
601 // run current site deactivation process
602 $this->deactivate_site( $delete );
603
604 restore_current_blog();
605 }
606 } else
607 $this->deactivate_site();
608 }
609
610 /**
611 * Single site deactivation.
612 *
613 * @param bool $force_deletion
614 * @return void
615 */
616 public function deactivate_site( $force_deletion = false ) {
617 // delete settings?
618 if ( $force_deletion || $this->options['general']['deactivation_delete'] ) {
619 // delete options
620 delete_option( 'cookie_notice_options' );
621 delete_option( 'cookie_notice_status' );
622 delete_option( 'cookie_notice_app_analytics' );
623 delete_option( 'cookie_notice_app_blocking' );
624 delete_option( 'cookie_notice_version' );
625
626 // delete transients if any
627 delete_transient( 'cookie_notice_app_token' );
628 delete_transient( 'cookie_notice_app_quick_config' );
629 delete_transient( 'cookie_notice_app_subscriptions' );
630 }
631
632 // remove wp super cache cookie
633 $this->wpsc_delete_cookie();
634 }
635
636 /**
637 * Update notice.
638 *
639 * @return void
640 */
641 public function update_notice() {
642 if ( ! current_user_can( 'install_plugins' ) )
643 return;
644
645 // bail an ajax
646 if ( wp_doing_ajax() )
647 return;
648
649 $network = $this->is_network_admin();
650
651 $current_update = 9;
652
653 // get current database version
654 if ( $network )
655 $current_db_version = get_site_option( 'cookie_notice_version', '1.0.0' );
656 else
657 $current_db_version = get_option( 'cookie_notice_version', '1.0.0' );
658
659 $this->db_version = $current_db_version;
660
661 if ( version_compare( $current_db_version, $this->defaults['version'], '<' ) ) {
662 if ( $this->options['general']['update_version'] < $current_update ) {
663 // check version, if update version is lower than plugin version, set update notice to true
664 $this->options['general']['update_version'] = $current_update;
665 $this->options['general']['update_notice'] = true;
666
667 // update options
668 if ( $network ) {
669 $this->options['general']['update_notice_diss'] = false;
670
671 update_site_option( 'cookie_notice_options', $this->options['general'] );
672 } else
673 update_option( 'cookie_notice_options', $this->options['general'] );
674 }
675
676 // update plugin version
677 if ( $network )
678 update_site_option( 'cookie_notice_version', $this->defaults['version'] );
679 else
680 update_option( 'cookie_notice_version', $this->defaults['version'], false );
681 }
682
683 // check page
684 $page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : '';
685
686 // if visiting settings, mark notice as read
687 if ( $page === 'cookie-notice' && ! empty( $_GET['welcome'] ) ) {
688 $this->options['general']['update_notice'] = false;
689
690 if ( $network ) {
691 $this->options['general']['update_notice_diss'] = true;
692
693 update_site_option( 'cookie_notice_options', $this->options['general'] );
694 } else
695 update_option( 'cookie_notice_options', $this->options['general'] );
696 }
697
698 if ( is_multisite() && ( ( $this->is_plugin_network_active() && ! $network && $this->network_options['global_override'] ) || ( $network && ! $this->is_plugin_network_active() ) ) )
699 $this->options['general']['update_notice'] = false;
700
701 // get cookie compliance status
702 $status = $this->get_status();
703
704 // show notice, if no compliance only
705 if ( $this->options['general']['update_notice'] === true && empty( $status ) ) {
706 $this->add_notice( '<div class="cn-notice-text"><h2>' . esc_html__( 'Facebook Tracking Pixel Illegal in EU?', 'cookie-notice' ) . '</h2><p>' . esc_html__( 'The Austrian Data Protection Authority recently declared that the use of Facebook\'s tracking pixel directly violates the GDPR. This decision could affect many websites in the European Union. To use Facebook Pixel, prior consent from visitors for tracking is required. Click "Run Compliance Check" to check if your website compliance with the latest privacy regulations.', 'cookie-notice' ) . '</p><p class="cn-notice-actions"><a href="' . esc_url( $network ? network_admin_url( 'admin.php?page=cookie-notice&welcome=1' ) : admin_url( 'admin.php?page=cookie-notice&welcome=1' ) ) . '" class="button button-primary cn-button">' . esc_html__( 'Run Compliance Check', 'cookie-notice' ) . '</a> <a href="#" class="button-link cn-notice-dismiss">' . esc_html__( 'Dismiss Notice', 'cookie-notice' ) . '</a></p></div>', 'error', 'div' );
707 }
708
709 // show threshold limit warning, compliance only
710 if ( $status === 'active' ) {
711 // get analytics data options
712 if ( $network )
713 $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
714 else
715 $analytics = get_option( 'cookie_notice_app_analytics', [] );
716
717 if ( is_multisite() && ( ( $network && ! $this->is_plugin_network_active() && ! $this->network_options['global_override'] ) || ( ! $network && $this->is_plugin_network_active() && $this->network_options['global_override'] ) ) )
718 $allow_notice = false;
719 else
720 $allow_notice = true;
721
722 if ( ! empty( $analytics ) && $allow_notice ) {
723 // cycle usage data
724 $cycle_usage = [
725 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
726 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
727 'end_date' => ! empty( $analytics['cycleUsage']->endDate ) ? date_create_from_format( '!Y-m-d', $analytics['cycleUsage']->endDate ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) ),
728 'last_updated' => ! empty( $analytics['lastUpdated'] ) ? date_create_from_format( 'Y-m-d H:i:s', $analytics['lastUpdated'] ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) )
729 ];
730
731 // if threshold in use
732 if ( $cycle_usage['threshold'] ) {
733 // if threshold exceeded and there was no notice before
734 if ( $cycle_usage['visits'] >= $cycle_usage['threshold'] && $cycle_usage['last_updated']->getTimestamp() < $cycle_usage['end_date']->getTimestamp() && $this->options['general']['update_threshold_date'] < $cycle_usage['end_date']->getTimestamp() ) {
735 $date_format = get_option( 'date_format' );
736
737 $upgrade_link = $this->get_url( 'dashboard', '?app-id=' . $this->options['general']['app_id'] . '&open-modal=payment' );
738 $threshold = $cycle_usage['threshold'];
739 $cycle_date = date_i18n( $date_format, $cycle_usage['end_date']->getTimestamp() );
740
741 $this->add_notice( '<div class="cn-notice-text" data-delay="' . esc_attr( $cycle_usage['end_date']->getTimestamp() ) . '"><h2>' . esc_html__( 'Cookie Compliance Warning', 'cookie-notice') . '</h2><p>' . sprintf( __( 'Your website has reached the <b>%1$s visits usage limit for the Cookie Compliance Free Plan</b>. Compliance services such as Consent Record Storage, Autoblocking, and Consent Analytics have been deactivated until current usage cycle ends on %2$s.', 'cookie-notice' ), $threshold, $cycle_date ) . '<br>' . sprintf( __( 'To reactivate compliance services now, <a href="%s" target="_blank">upgrade your domain to a Pro plan.</a>', 'cookie-notice' ) . '</p></div>', $upgrade_link ), 'cn-threshold error is-dismissible', 'div' );
742 }
743 }
744 }
745 }
746 }
747
748 /**
749 * Add admin notice.
750 *
751 * @param string $html
752 * @param string $status
753 * @param string $container
754 * @return void
755 */
756 private function add_notice( $html = '', $status = 'error', $container = '' ) {
757 $this->notices[] = [
758 'html' => $html,
759 'status' => $status,
760 'container' => ( ! empty( $container ) && in_array( $container, [ 'p', 'div' ] ) ? $container : '' )
761 ];
762
763 add_action( 'admin_notices', [ $this, 'display_notice' ], 0 );
764 add_action( 'network_admin_notices', [ $this, 'display_notice' ], 0 );
765 }
766
767 /**
768 * Print admin notices.
769 *
770 * @return void
771 */
772 public function display_notice() {
773 foreach( $this->notices as $notice ) {
774 echo '
775 <div id="cn-admin-notice" class="cn-notice notice notice-info ' . esc_attr( $notice['status'] ) . '">
776 ' . ( ! empty( $notice['container'] ) ? '<' . esc_attr( $notice['container'] ) . ' class="cn-notice-container">' : '' ) . '
777 ' . wp_kses_post( $notice['html'] ) . '
778 ' . ( ! empty( $notice['container'] ) ? '</' . esc_attr( $notice['container'] ) . ' class="cn-notice-container">' : '' ) . '
779 </div>';
780 }
781 }
782
783 /**
784 * Dismiss admin notice.
785 *
786 * @return void
787 */
788 public function ajax_dismiss_admin_notice() {
789 if ( ! current_user_can( 'install_plugins' ) )
790 return;
791
792 if ( wp_verify_nonce( $_POST['nonce'], 'cn_dismiss_notice' ) ) {
793 // get notice action
794 $notice_action = ! empty( $_POST['notice_action'] ) ? sanitize_key( $_POST['notice_action'] ) : 'dismiss';
795
796 $cn_network = isset( $_POST['cn_network'] ) ? (int) $_POST['cn_network'] : false;
797
798 // network?
799 $network = is_multisite() && $cn_network === 1;
800
801 switch ( $notice_action ) {
802 // threshold notice
803 case 'threshold':
804 // set delay period last cycle day
805 $delay = isset( $_POST['param'] ) ? (int) $_POST['param'] : 0;
806
807 $this->options['general']['update_threshold_date'] = $delay + DAY_IN_SECONDS;
808
809 // update options
810 if ( $network )
811 update_site_option( 'cookie_notice_options', $this->options['general'] );
812 else
813 update_option( 'cookie_notice_options', $this->options['general'] );
814 break;
815
816 // delay notice
817 case 'delay':
818 // set delay period to 1 week from now
819 $this->options['general']['update_delay_date'] = time() + 1209600;
820
821 // update options
822 if ( $network )
823 update_site_option( 'cookie_notice_options', $this->options['general'] );
824 else
825 update_option( 'cookie_notice_options', $this->options['general'] );
826 break;
827
828 // hide notice
829 case 'approve':
830 default:
831 $this->options['general']['update_notice'] = false;
832 $this->options['general']['update_delay_date'] = 0;
833
834 // update options
835 if ( $network ) {
836 $this->options['general']['update_notice_diss'] = true;
837
838 update_site_option( 'cookie_notice_options', $this->options['general'] );
839 } else
840 update_option( 'cookie_notice_options', $this->options['general'] );
841 }
842 }
843
844 exit;
845 }
846
847 /**
848 * Register shortcode.
849 *
850 * @return void
851 */
852 public function register_shortcodes() {
853 add_shortcode( 'cookies_accepted', [ $this, 'cookies_accepted_shortcode' ] );
854 add_shortcode( 'cookies_revoke', [ $this, 'cookies_revoke_shortcode' ] );
855 add_shortcode( 'cookies_policy_link', [ $this, 'cookies_policy_link_shortcode' ] );
856 }
857
858 /**
859 * Register cookies accepted shortcode.
860 *
861 * @param array $args
862 * @param string $content
863 * @return string
864 */
865 public function cookies_accepted_shortcode( $args, $content ) {
866 if ( $this->cookies_accepted() ) {
867 $scripts = html_entity_decode( trim( wp_kses( $content, $this->get_allowed_html() ) ) );
868
869 if ( ! empty( $scripts ) ) {
870 if ( preg_match_all( '/' . get_shortcode_regex() . '/', $content ) )
871 $scripts = do_shortcode( $scripts );
872
873 return $scripts;
874 }
875 }
876
877 return '';
878 }
879
880 /**
881 * Register cookies revoke shortcode.
882 *
883 * @param array $args
884 * @param string $content
885 * @return string
886 */
887 public function cookies_revoke_shortcode( $args, $content ) {
888 // get options
889 $options = $this->options['general'];
890
891 // WPML >= 3.2
892 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) )
893 $options['revoke_text'] = apply_filters( 'wpml_translate_single_string', $options['revoke_text'], 'Cookie Notice', 'Revoke button text' );
894 // WPML and Polylang compatibility
895 elseif ( function_exists( 'icl_t' ) )
896 $options['revoke_text'] = icl_t( 'Cookie Notice', 'Revoke button text', $options['revoke_text'] );
897
898 // defaults
899 $defaults = [
900 'title' => $options['revoke_text'],
901 'class' => $options['css_class']
902 ];
903
904 // combine shortcode arguments
905 $args = shortcode_atts( $defaults, $args );
906
907 if ( Cookie_Notice()->get_status() === 'active' )
908 $shortcode = '<a href="#" class="cn-revoke-cookie cn-button-inline cn-revoke-inline' . esc_attr( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '" title="' . esc_attr( $args['title'] ) . '" data-hu-action="cookies-notice-revoke">' . esc_html( $args['title'] ) . '</a>';
909 else
910 $shortcode = '<a href="#" class="cn-revoke-cookie cn-button-inline cn-revoke-inline' . esc_attr( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '" title="' . esc_attr( $args['title'] ) . '">' . esc_html( $args['title'] ) . '</a>';
911
912 return $shortcode;
913 }
914
915 /**
916 * Register cookies policy link shortcode.
917 *
918 * @param array $args
919 * @param string $content
920 * @return string
921 */
922 public function cookies_policy_link_shortcode( $args, $content ) {
923 // get options
924 $options = $this->options['general'];
925
926 // WPML >= 3.2
927 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
928 $options['see_more_opt']['text'] = apply_filters( 'wpml_translate_single_string', $options['see_more_opt']['text'], 'Cookie Notice', 'Privacy policy text' );
929 $options['see_more_opt']['link'] = apply_filters( 'wpml_translate_single_string', $options['see_more_opt']['link'], 'Cookie Notice', 'Custom link' );
930 // WPML and Polylang compatibility
931 } elseif ( function_exists( 'icl_t' ) ) {
932 $options['see_more_opt']['text'] = icl_t( 'Cookie Notice', 'Privacy policy text', $options['see_more_opt']['text'] );
933 $options['see_more_opt']['link'] = icl_t( 'Cookie Notice', 'Custom link', $options['see_more_opt']['link'] );
934 }
935
936 if ( $options['see_more_opt']['link_type'] === 'page' ) {
937 // multisite with global override?
938 if ( is_multisite() && $this->is_plugin_network_active() && $this->network_options['global_override'] ) {
939 // get main site id
940 $main_site_id = get_main_site_id();
941
942 // switch to main site
943 switch_to_blog( $main_site_id );
944
945 // update page id for current language if needed
946 if ( function_exists( 'icl_object_id' ) )
947 $options['see_more_opt']['id'] = icl_object_id( $options['see_more_opt']['id'], 'page', true );
948
949 // get main site privacy policy link
950 $permalink = get_permalink( $options['see_more_opt']['id'] );
951
952 // restore current site
953 restore_current_blog();
954 } else {
955 // update page id for current language if needed
956 if ( function_exists( 'icl_object_id' ) )
957 $options['see_more_opt']['id'] = icl_object_id( $options['see_more_opt']['id'], 'page', true );
958
959 // get privacy policy link
960 $permalink = get_permalink( $options['see_more_opt']['id'] );
961 }
962 }
963
964 // defaults
965 $defaults = [
966 'title' => $options['see_more_opt']['text'] !== '' ? $options['see_more_opt']['text'] : '&#x279c;',
967 'link' => $options['see_more_opt']['link_type'] === 'custom' ? $options['see_more_opt']['link'] : $permalink,
968 'class' => $options['css_class']
969 ];
970
971 // combine shortcode arguments
972 $args = shortcode_atts( $defaults, $args );
973
974 $shortcode = '<a href="' . esc_url( $args['link'] ) . '" target="' . esc_attr( $options['link_target'] ) . '" id="cn-more-info" class="cn-privacy-policy-link cn-link' . esc_attr( $args['class'] !== '' ? ' ' . $args['class'] : '' ) . '">' . esc_html( $args['title'] ) . '</a>';
975
976 return $shortcode;
977 }
978
979 /**
980 * Check if cookies are accepted.
981 *
982 * @return bool
983 */
984 public static function cookies_accepted() {
985 if ( Cookie_Notice()->get_status() === 'active' ) {
986 // get cookie
987 $cookies = isset( $_COOKIE['hu-consent'] ) ? json_decode( stripslashes( $_COOKIE['hu-consent'] ), true ) : [];
988
989 // valid cookie?
990 if ( json_last_error() === JSON_ERROR_NONE && ! empty( $cookies ) && is_array( $cookies ) && isset( $cookies['consent'] ) )
991 $result = (bool) $cookies['consent'];
992 else
993 $result = false;
994 } else
995 $result = isset( $_COOKIE['cookie_notice_accepted'] ) && $_COOKIE['cookie_notice_accepted'] === 'true';
996
997 return (bool) apply_filters( 'cn_is_cookie_accepted', $result );
998 }
999
1000 /**
1001 * Check if cookies are set.
1002 *
1003 * @return bool
1004 */
1005 public static function cookies_set() {
1006 if ( Cookie_Notice()->get_status() === 'active' )
1007 $result = isset( $_COOKIE['hu-consent'] );
1008 else
1009 $result = isset( $_COOKIE['cookie_notice_accepted'] );
1010
1011 return (bool) apply_filters( 'cn_is_cookie_set', $result );
1012 }
1013
1014 /**
1015 * Add WP Super Cache cookie.
1016 *
1017 * @return void
1018 */
1019 public function wpsc_add_cookie() {
1020 if ( Cookie_Notice()->get_status() === 'active' )
1021 do_action( 'wpsc_add_cookie', 'hu-consent' );
1022 else
1023 do_action( 'wpsc_add_cookie', 'cookie_notice_accepted' );
1024 }
1025
1026 /**
1027 * Delete WP Super Cache cookie.
1028 *
1029 * @return void
1030 */
1031 public function wpsc_delete_cookie() {
1032 if ( Cookie_Notice()->get_status() === 'active' )
1033 do_action( 'wpsc_delete_cookie', 'hu-consent' );
1034 else
1035 do_action( 'wpsc_delete_cookie', 'cookie_notice_accepted' );
1036 }
1037
1038 /**
1039 * Enqueue admin scripts and styles.
1040 *
1041 * @param string $page
1042 * @return void
1043 */
1044 public function admin_enqueue_scripts( $page ) {
1045 // plugins page?
1046 if ( $page === 'plugins.php' ) {
1047 add_thickbox();
1048
1049 wp_enqueue_script( 'cookie-notice-admin-plugins', COOKIE_NOTICE_URL . '/js/admin-plugins.js', [ 'jquery' ], $this->defaults['version'] );
1050
1051 wp_enqueue_style( 'cookie-notice-admin-plugins', COOKIE_NOTICE_URL . '/css/admin-plugins.css', [], $this->defaults['version'] );
1052
1053 // prepare script data
1054 $script_data = [
1055 'deactivate' => esc_html__( 'Cookie Notice & Compliance - Deactivation survey', 'cookie-notice' ),
1056 'nonce' => wp_create_nonce( 'cn-deactivate-plugin' )
1057 ];
1058
1059 wp_add_inline_script( 'cookie-notice-admin-plugins', 'var cnArgsPlugins = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
1060 }
1061
1062 // notice js and css
1063 wp_enqueue_script( 'cookie-notice-admin-notice', COOKIE_NOTICE_URL . '/js/admin-notice.js', [ 'jquery' ], Cookie_Notice()->defaults['version'] );
1064
1065 // prepare script data
1066 $script_data = [
1067 'ajaxURL' => admin_url( 'admin-ajax.php' ),
1068 'nonce' => wp_create_nonce( 'cn_dismiss_notice' ),
1069 'network' => $this->is_network_admin()
1070 ];
1071
1072 wp_add_inline_script( 'cookie-notice-admin-notice', 'var cnArgsNotice = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
1073
1074 wp_enqueue_style( 'cookie-notice-admin-notice', COOKIE_NOTICE_URL . '/css/admin-notice.css', [], Cookie_Notice()->defaults['version'] );
1075 }
1076
1077 /**
1078 * Set plugin links.
1079 *
1080 * @return void
1081 */
1082 public function set_plugin_links() {
1083 // filters
1084 add_filter( 'plugin_action_links', [ $this, 'plugin_action_links' ], 10, 2 );
1085 add_filter( 'network_admin_plugin_action_links', [ $this, 'plugin_action_links' ], 10, 2 );
1086 }
1087
1088 /**
1089 * Add links to settings page.
1090 *
1091 * @param array $links
1092 * @param string $file
1093 * @return array
1094 */
1095 public function plugin_action_links( $links, $file ) {
1096 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1097 return $links;
1098
1099 if ( $file === COOKIE_NOTICE_BASENAME ) {
1100 if ( ! empty( $links['deactivate'] ) ) {
1101 // link already contains class attribute?
1102 if ( preg_match( '/<a.*?class=(\'|")(.*?)(\'|").*?>/is', $links['deactivate'], $result ) === 1 )
1103 $links['deactivate'] = preg_replace( '/(<a.*?class=(?:\'|").*?)((?:\'|").*?>)/s', '$1 cn-deactivate-plugin-modal$2', $links['deactivate'] );
1104 else
1105 $links['deactivate'] = preg_replace( '/(<a.*?)>/s', '$1 class="cn-deactivate-plugin-modal">', $links['deactivate'] );
1106
1107 // link already contains href attribute?
1108 if ( preg_match( '/<a.*?href=(\'|")(.*?)(\'|").*?>/is', $links['deactivate'], $result ) === 1 ) {
1109 if ( ! empty( $result[2] ) )
1110 $this->deactivaion_url = $result[2];
1111 }
1112 }
1113
1114 // skip settings link if plugin is activated from main site
1115 if ( ! ( $this->is_network_admin() && ! $this->is_plugin_network_active() ) ) {
1116 $url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' );
1117
1118 // put settings link at start
1119 array_unshift( $links, sprintf( '<a href="%s">%s</a>', esc_url( $url ), esc_html__( 'Settings', 'cookie-notice' ) ) );
1120 }
1121
1122 // get cookie compliance status
1123 $status = $this->get_status();
1124
1125 if ( is_multisite() ) {
1126 $check_status = empty( $status ) && ( ( $this->is_network_admin() && $this->is_plugin_network_active() && $this->network_options['global_override'] ) || ( ! $this->is_network_admin() && ( ( $this->is_plugin_network_active() && ! $this->network_options['global_override'] ) || ! $this->is_plugin_network_active() ) ) );
1127 } else
1128 $check_status = empty( $status );
1129
1130 // add upgrade link
1131 if ( $check_status ) {
1132 $url = $this->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice&welcome=1' ) : admin_url( 'admin.php?page=cookie-notice&welcome=1' );
1133
1134 $links[] = sprintf( '<a href="%s" style="color: #20C19E; font-weight: bold">%s</a>', esc_url( $url ), esc_html__( 'Free Upgrade', 'cookie-notice' ) );
1135 }
1136 }
1137
1138 return $links;
1139 }
1140
1141 /**
1142 * Deactivation modal HTML template.
1143 *
1144 * @global string $pagenow
1145 *
1146 * @return void
1147 */
1148 public function deactivate_plugin_template() {
1149 global $pagenow;
1150
1151 // display only for plugins page
1152 if ( $pagenow !== 'plugins.php' )
1153 return;
1154
1155 echo '
1156 <div id="cn-deactivation-modal" style="display: none">
1157 <div id="cn-deactivation-container">
1158 <div id="cn-deactivation-body">
1159 <div class="cn-deactivation-options">
1160 <p><em>' . esc_html__( "We're sorry to see you go. Could you please tell us what happened?", 'cookie-notice' ) . '</em></p>
1161 <ul>';
1162
1163 foreach ( [
1164 '1' => esc_html__( "I couldn't figure out how to make it work.", 'cookie-notice' ),
1165 '2' => esc_html__( 'I found another plugin to use for the same task.', 'cookie-notice' ),
1166 '3' => esc_html__( 'The Cookie Compliance banner is too big.', 'cookie-notice' ),
1167 '4' => esc_html__( 'The Cookie Compliance consent choices (Silver, Gold, Platinum) are confusing.', 'cookie-notice' ),
1168 '5' => esc_html__( 'The Cookie Compliance default settings are too strict.', 'cookie-notice' ),
1169 '6' => esc_html__( 'The web application user interface is not clear to me.', 'cookie-notice' ),
1170 '7' => esc_html__( "Support isn't timely.", 'cookie-notice' ),
1171 '8' => esc_html__( 'Other', 'cookie-notice' )
1172 ] as $option => $text ) {
1173 echo '
1174 <li><label><input type="radio" name="cn_deactivation_option" value="' . esc_attr( $option ) . '" ' . checked( '8', $option, false ) . ' />' . esc_html( $text ) . '</label></li>';
1175 }
1176
1177 echo '
1178 </ul>
1179 </div>
1180 <div class="cn-deactivation-textarea">
1181 <textarea name="cn_deactivation_other"></textarea>
1182 </div>
1183 </div>
1184 <div id="cn-deactivation-footer">
1185 <a href="" class="button cn-deactivate-plugin-cancel">' . esc_html__( 'Cancel', 'cookie-notice' ) . '</a>
1186 <a href="' . esc_url( $this->deactivaion_url ) . '" class="button button-secondary cn-deactivate-plugin-simple">' . esc_html__( 'Deactivate', 'cookie-notice' ) . '</a>
1187 <a href="' . esc_url( $this->deactivaion_url ) . '" class="button button-primary right cn-deactivate-plugin-data">' . esc_html__( 'Deactivate & Submit', 'cookie-notice' ) . '</a>
1188 <span class="spinner"></span>
1189 </div>
1190 </div>
1191 </div>';
1192 }
1193
1194 /**
1195 * Send data about deactivation of the plugin.
1196 *
1197 * @return void
1198 */
1199 public function deactivate_plugin() {
1200 // check permissions
1201 if ( ! current_user_can( 'install_plugins' ) || wp_verify_nonce( $_POST['nonce'], 'cn-deactivate-plugin' ) === false )
1202 return;
1203
1204 if ( isset( $_POST['option_id'] ) ) {
1205 $option_id = (int) $_POST['option_id'];
1206
1207 // avoid fake submissions
1208 if ( $option_id === 8 ) {
1209 $other = isset( $_POST['other'] ) ? sanitize_textarea_field( $_POST['other'] ) : '';
1210
1211 // no reason?
1212 if ( $other === '' )
1213 wp_send_json_success();
1214 }
1215
1216 wp_remote_post(
1217 'https://hu-manity.co/wp-json/api/v1/forms/',
1218 [
1219 'timeout' => 15,
1220 'blocking' => true,
1221 'headers' => [],
1222 'body' => [
1223 'id' => 1,
1224 'option' => $option_id,
1225 'other' => $other,
1226 'referrer' => get_site_url()
1227 ]
1228 ]
1229 );
1230
1231 wp_send_json_success();
1232 }
1233
1234 wp_send_json_error();
1235 }
1236
1237 /**
1238 * Get allowed script blocking HTML.
1239 *
1240 * @return array
1241 */
1242 public function get_allowed_html() {
1243 return apply_filters(
1244 'cn_refuse_code_allowed_html',
1245 array_merge(
1246 wp_kses_allowed_html( 'post' ),
1247 [
1248 'script' => [
1249 'type' => true,
1250 'src' => true,
1251 'charset' => true,
1252 'async' => true
1253 ],
1254 'noscript' => [],
1255 'style' => [
1256 'type' => true
1257 ],
1258 'iframe' => [
1259 'src' => true,
1260 'height' => true,
1261 'width' => true,
1262 'frameborder' => true,
1263 'allowfullscreen' => true
1264 ]
1265 ]
1266 )
1267 );
1268 }
1269
1270 /**
1271 * Merge multidimensional associative arrays.
1272 * Works only with strings, integers and arrays as keys. Values can be any type but they have to have same type to be kept in the final array.
1273 * Every array should have the same type of elements. Only keys from $defaults array will be kept in the final array unless $siblings are not empty.
1274 * $siblings examples: array( '=>', 'only_first_level', 'first_level=>second_level', 'first_key=>next_key=>sibling' ) and so on.
1275 * Single '=>' means that all siblings of the highest level will be kept in the final array.
1276 *
1277 * @param array $defaults Array with defaults values
1278 * @param array $array Array to merge
1279 * @param bool|array $siblings Whether to allow "string" siblings to copy from $array if they do not exist in $defaults, false otherwise
1280 * @return array
1281 */
1282 public function multi_array_merge( $defaults, $array, $siblings = false ) {
1283 // make a copy for better performance and to prevent $default override in foreach
1284 $copy = $defaults;
1285
1286 // prepare siblings for recursive deeper level
1287 $new_siblings = [];
1288
1289 // allow siblings?
1290 if ( ! empty( $siblings ) && is_array( $siblings ) ) {
1291 foreach ( $siblings as $sibling ) {
1292 // highest level siblings
1293 if ( $sibling === '=>' ) {
1294 // copy all non-existent string siblings
1295 foreach( $array as $key => $value ) {
1296 if ( is_string( $key ) && ! array_key_exists( $key, $defaults ) ) {
1297 $defaults[$key] = null;
1298 }
1299 }
1300 // sublevel siblings
1301 } else {
1302 // explode siblings
1303 $ex = explode( '=>', $sibling );
1304
1305 // copy all non-existent siblings
1306 foreach ( array_keys( $array[$ex[0]] ) as $key ) {
1307 if ( ! array_key_exists( $key, $defaults[$ex[0]] ) )
1308 $defaults[$ex[0]][$key] = null;
1309 }
1310
1311 // more than one sibling child?
1312 if ( count( $ex ) > 1 )
1313 $new_siblings[$ex[0]] = [ substr_replace( $sibling, '', 0, strlen( $ex[0] . '=>' ) ) ];
1314 // no more sibling children
1315 else
1316 $new_siblings[$ex[0]] = false;
1317 }
1318 }
1319 }
1320
1321 // loop through first array
1322 foreach ( $defaults as $key => $value ) {
1323 // integer key?
1324 if ( is_int( $key ) ) {
1325 $copy = array_unique( array_merge( $defaults, $array ), SORT_REGULAR );
1326
1327 break;
1328 // string key?
1329 } elseif ( is_string( $key ) && isset( $array[$key] ) ) {
1330 // string, boolean, integer or null values?
1331 if ( ( is_string( $value ) && is_string( $array[$key] ) ) || ( is_bool( $value ) && is_bool( $array[$key] ) ) || ( is_int( $value ) && is_int( $array[$key] ) ) || is_null( $value ) )
1332 $copy[$key] = $array[$key];
1333 // arrays
1334 elseif ( is_array( $value ) && isset( $array[$key] ) && is_array( $array[$key] ) ) {
1335 if ( empty( $value ) )
1336 $copy[$key] = $array[$key];
1337 else
1338 $copy[$key] = $this->multi_array_merge( $defaults[$key], $array[$key], ( isset( $new_siblings[$key] ) ? $new_siblings[$key] : false ) );
1339 }
1340 }
1341 }
1342
1343 return $copy;
1344 }
1345
1346 /**
1347 * Indicate if current page is the Cookie Policy page.
1348 *
1349 * @return bool
1350 */
1351 public function is_cookie_policy_page() {
1352 // get privacy policy options
1353 $see_more = $this->options['general']['see_more_opt'];
1354
1355 // custom link?
1356 if ( $see_more['link_type'] !== 'page' )
1357 return false;
1358
1359 // get current object
1360 $current_page = sanitize_post( $GLOBALS['wp_the_query']->get_queried_object() );
1361
1362 // check if current page is privacy policy page
1363 return $current_page->post_name === get_post_field( 'post_name', $see_more['id'] );
1364 }
1365 }
1366
1367 /**
1368 * Initialize Cookie Notice.
1369 *
1370 * @return object
1371 */
1372 function Cookie_Notice() {
1373 static $instance;
1374
1375 // first call to instance() initializes the plugin
1376 if ( $instance === null || ! ( $instance instanceof Cookie_Notice ) )
1377 $instance = Cookie_Notice::instance();
1378
1379 return $instance;
1380 }
1381
1382 Cookie_Notice();
...\ No newline at end of file ...\ No newline at end of file
1 .cn-dashboard-container {
2 min-height: 130px;
3 margin: 0 -4px;
4 text-align: center;
5 position: relative;
6 display: flex;
7 flex-direction: column;
8 }
9
10 .cn-dashboard-container .spinner {
11 position: absolute;
12 left: 50%;
13 top: 40%;
14 margin-left: -10px;
15 z-index: 10;
16 }
17
18 .cn-dashboard-container.loading {
19 pointer-events: none;
20 }
21
22 .cn-dashboard-container.loading:after {
23 position: absolute;
24 content: '';
25 display: block;
26 height: 100%;
27 width: 100%;
28 top: 0;
29 left: 0;
30 background-color: rgba(255,255,255,0.8);
31 z-index: 1;
32 transition: all 0.2s;
33 }
34
35 .cn-dashboard_stats p.sub {
36 color: #8f8f8f;
37 font-size: 14px;
38 text-align: left;
39 padding-bottom: 3px;
40 border-bottom: 1px solid #ececec;
41 }
42
43 .cn-table-responsive {
44 overflow-x: auto;
45 -webkit-overflow-scrolling: touch;
46 }
47
48 .cn-table {
49 caption-side: bottom;
50 border-collapse: collapse;
51 width: 100%;
52 margin-bottom: 1rem;
53 color: inherit;
54 vertical-align: top;
55 border-color: #dee2e6;
56 text-align: left;
57 }
58
59 .cn-table > thead {
60 vertical-align: bottom;
61 color: #212529;
62 }
63
64 .cn-table > tbody {
65 vertical-align: inherit;
66 }
67
68 .cn-table tbody,
69 .cn-table td,
70 .cn-table tfoot,
71 .cn-table th,
72 .cn-table thead,
73 .cn-table tr {
74 border-color: inherit;
75 border-style: solid;
76 border-width: 0;
77 }
78
79 .cn-table th,
80 .cn-table td {
81 text-align: inherit;
82 text-align: -webkit-match-parent;
83 }
84
85 .cn-table th:first-child,
86 .cn-table td:first-child {
87 width: 1px;
88 white-space: nowrap;
89 }
90
91 .cn-table th:last-child,
92 .cn-table td:last-child {
93 text-align: right;
94 }
95
96 .cn-table .no-posts :last-child {
97 text-align: left;
98 }
99
100 .cn-table > :not(caption) > * > * {
101 padding: .5rem .5rem;
102 background-color: transparent;
103 border-bottom-width: 1px;
104 box-shadow: inset 0 0 0 9999px transparent;
105 }
106
107 #cn_dashboard_stats .inside {
108 margin: 0;
109 padding: 0;
110 }
111
112 .cn-accordion-toggle {
113 cursor: pointer;
114 line-height: 1;
115 position: relative;
116 font-size: 14px;
117 font-weight: 400;
118 line-height: 1;
119 margin: 0;
120 padding: 15px 15px 0;
121 color: #23282c;
122 }
123
124 .cn-accordion-title {
125 display: inline-block;
126 padding-right: 10px;
127 }
128
129 .cn-accordion-actions {
130 position: absolute;
131 top: 0;
132 right: 0;
133 z-index: 1;
134 padding: 11px 30px 11px 0;
135 height: 14px;
136 line-height: 1;
137 }
138
139 .cn-accordion-actions .cn-accordion-action,
140 .cn-accordion-actions .cn-accordion-action::before {
141 font-size: 14px;
142 height: 14px;
143 width: 14px;
144 color: #72777c;
145 }
146
147 .cn-tooltip {
148 position: relative;
149 }
150
151 .cn-tooltip-icon {
152 display: inline-block;
153 width: 16px;
154 cursor: help;
155 }
156
157 .cn-tooltip-icon::before {
158 color: #b4b9be;
159 content: "\f14c";
160 display: inline-block;
161 font: normal 16px/1 dashicons;
162 position: absolute;
163 text-decoration: none !important;
164 speak: none;
165 -webkit-font-smoothing: antialiased;
166 -moz-osx-font-smoothing: grayscale;
167 left: 0;
168 top: 2px;
169 }
170
171 .cn-according-header {
172 display: flex;
173 align-items: center;
174 justify-content: space-between;
175 }
176
177 .cn-accordion-content {
178 padding: 20px 20px 15px;
179 height: 100%;
180 }
181
182 .cn-collapsed .cn-accordion-toggle::before {
183 transform: rotate(180deg);
184 }
185
186 .cn-collapsed .cn-accordion-content {
187 display: none;
188 }
189
190 .cn-infobox-container {
191 display: flex;
192 flex-wrap: wrap;
193 border: 1px solid #eee;
194 }
195
196 .cn-infobox-container:not(:first-child) {
197 border-top-color: transparent;
198 }
199
200 .cn-infobox {
201 width: 50%;
202 padding: 12px 10px 10px 15px;
203 position: relative;
204 text-align: left;
205 box-sizing: border-box;
206 border-left: 1px solid transparent;
207 min-height: 135px;
208 }
209
210 #cn-visits-infobox-consents {
211 border-left-color: #eee;
212 }
213
214 #cn-visits-infobox-limits,
215 #cn-visits-chart-limits {
216 border-top-color: #eee;
217 }
218
219 .cn-infobox-notice {
220 width: 100%;
221 margin: 5px 10px 15px 15px;
222 padding: 15px 12px;
223 position: relative;
224 text-align: left;
225 box-sizing: border-box;
226 background: rgba(255, 193, 7, 0.05);
227 border: 1px solid rgb(255, 193, 7);
228 }
229
230 .cn-infobox-notice p {
231 margin-top: 0;
232 }
233
234 .cn-infobox-notice p:last-child {
235 margin-bottom: 0;
236 }
237
238 .cn-infobox-notice p b {
239 font-size: 15px;
240 color: #222;
241 }
242
243 .cn-infobox-title {
244 font-size: 16px;
245 color: #393f4c;
246 font-weight: 700;
247 margin-top: 0;
248 padding-right: 18px;
249 text-overflow: ellipsis;
250 overflow: hidden;
251 white-space: pre;
252 line-height: 1.2;
253 }
254
255 .cn-infobox-number {
256 font-size: 36px;
257 float: none;
258 font-weight: 400;
259 display: inline-block;
260 line-height: 1;
261 margin-top: 11px;
262 color: rgb(32, 193, 158);
263 }
264
265 .cn-infobox-subtitle {
266 margin-top: 22px;
267 color: #a4a9ae;
268 }
269
270 .cn-infobox-subtitle p {
271 margin: 0 0 5px;
272 }
273
274
275 .cn-infobox-tooltip {
276 position: absolute;
277 top: 12px;
278 right: 15px;
279 }
280
281 .cn-widget-block {
282 position: relative;
283 overflow: hidden;
284 }
285
286 #cn-dashboard-upgrade {
287 position: absolute;
288 left: 0;
289 top: 0;
290 height: 100%;
291 width: 100%;
292 overflow: hidden;
293 box-sizing: border-box;
294 background: rgba(255,255,255,0.8);
295 min-height: 400px;
296 }
297
298 #cn-dashboard-modal {
299 position: absolute;
300 top: 50%;
301 left: 50%;
302 transform: translate(-50%, -50%);
303 padding: 1.5em 3em;
304 box-shadow: 0 0 25px 10px rgba(0,0,0,0.1);
305 border-radius: 3px;
306 background-color: #fff;
307 text-align: center;
308 width: 22em;
309 }
310
311 #cn-dashboard-modal p {
312 margin: 0;
313 }
314
315 #cn-dashboard-modal h2 {
316 margin-bottom: 10px;
317 font-size: 21px;
318 }
319
320 .button.cn-button {
321 margin-top: 25px;
322 margin-bottom: 10px;
323 background-color: #20c19e;
324 border-color: #20c19e;
325 }
326
327 .button.cn-button:hover,
328 .button.cn-button:active,
329 .button.cn-button:focus {
330 background-color: #1ca98a;
331 border-color: #1ca98a;
332 }
333
334 .button.cn-button:focus {
335 box-shadow: 0 0 0 1px #fff, 0 0 0 3px #20c19e;
336 }
337
338 .cn-text-succcess {
339 color: #20c19e;
340 }
341
342 .cn-text-warning {
343 color: rgb(255, 193, 7);
344 }
345
346 .cn-text-danger {
347 color: rgb(200, 35, 51);
348 }
...\ No newline at end of file ...\ No newline at end of file
1 #cn-admin-notice.cn-notice {
2 border-left-color: #20c19e;
3 }
4 .cn-notice .cn-notice-container {
5 padding: 1em;
6 display: flex;
7 justify-content: space-between;
8 align-items: center;
9 }
10 .cn-notice .cn-notice-actions {
11 margin-bottom: 0;
12 }
13 .cn-notice .cn-notice-actions .button {
14 display: inline-block;
15 margin: 0.5em 0 0;
16 }
17 .cn-notice .cn-notice-text h2 {
18 margin-top: 0;
19 margin-bottom: 0.5em;
20 }
21 .cn-notice .cn-notice-dismiss {
22 margin-left: 1em;
23 }
24 .cn-notice .cn-notice-text strong {
25 color: #000;
26 }
27 .cn-notice .cn-notice-text p:last-child {
28 margin-bottom: 0;
29 }
30 .cn-notice .cn-notice-icon svg path {
31 fill: #666 !important;
32 }
33 @media only screen and (max-width: 960px) {
34 .cn-notice .cn-notice-container {
35 flex-direction: column;
36 align-items: initial;
37 }
38
39 .cn-notice .cn-notice-container .cn-notice-text {
40 order: 1;
41 padding-top: 1em;
42 }
43 }
...\ No newline at end of file ...\ No newline at end of file
1 .cn-deactivation-modal {
2 max-height: 500px;
3 overflow: hidden;
4 top: 50% !important;
5 transform: translateY(-50%);
6 }
7 .cn-deactivation-modal #TB_title {
8 padding: 13px 16px;
9 background: #f3f3f3;
10 }
11 .cn-deactivation-modal #TB_title > div {
12 padding: 0;
13 color: #000;
14 }
15 .cn-deactivation-modal #TB_ajaxContent {
16 width: auto !important;
17 height: calc(100% - 112px) !important;
18 padding: 0;
19 }
20 .cn-deactivation-modal #TB_closeAjaxWindow button {
21 right: 8px;
22 }
23 .cn-deactivation-options p:first-child {
24 margin-top: 0;
25 }
26 #cn-deactivation-container {
27 width: 100%;
28 }
29 #cn-deactivation-container textarea {
30 width: 100%;
31 min-height: 100px;
32 }
33 #cn-deactivation-body {
34 padding: 13px 16px;
35 }
36 #cn-deactivation-footer {
37 padding: 13px 16px;
38 position: absolute;
39 right: 0;
40 bottom: 0;
41 left: 0;
42 border-top: 1px solid #ddd;
43 background: #f3f3f3;
44 }
45 #cn-deactivation-footer .spinner {
46 float: none;
47 }
...\ No newline at end of file ...\ No newline at end of file
1 .cn-welcome-wrap #wpcontent {
2 padding-left: 0;
3 }
4
5 .cn-welcome-wrap .update-nag {
6 display: none;
7 }
8
9 .cn-welcome-wrap * {
10 box-sizing: border-box;
11 }
12
13 .cn-welcome-wrap #wpbody-content {
14 padding-bottom: 0;
15 }
16
17 .cn-welcome-wrap #wpfooter {
18 display: none !important;
19 }
20
21 #cn_upgrade_iframe iframe {
22 width: 100%;
23 height: 100%;
24 margin: 0;
25 border: 0;
26 padding: 0;
27 }
28
29 .cn-welcome-wrap {
30 display: flex;
31 height: calc(100vh - 32px);
32 margin: 0;
33 background: #fff;
34 color: #191e23;
35 /*
36 position: fixed;
37 width: calc(100% - 160px);
38 */
39 width: 100%;
40 }
41
42 .folded .cn-welcome-wrap {
43 width: calc(100% - 36px);
44 }
45
46 .cn-welcome-wrap h1,
47 .cn-welcome-wrap h2,
48 .cn-welcome-wrap h3,
49 .cn-welcome-wrap h4,
50 .cn-welcome-wrap h5 {
51 margin-top: 0;
52 }
53
54 .cn-content h1,
55 .cn-content h2,
56 .cn-content h3,
57 .cn-content h4,
58 .cn-content h5 {
59 color: #191e23;
60 padding: 0;
61 }
62
63 .cn-content h1,
64 .cn-content h2,
65 .cn-content h3,
66 .cn-content h4,
67 .cn-content h5 {
68 color: #191e23;
69 padding: 0;
70 }
71
72 .cn-sidebar h1,
73 .cn-sidebar h2,
74 .cn-sidebar h3,
75 .cn-sidebar h4,
76 .cn-sidebar h5 {
77 color: #fff;
78 }
79
80 .cn-content h1 + h2,
81 .cn-content h1 + h3 {
82 margin-top: 0.5em;
83 }
84
85 .cn-welcome-wrap h1 {
86 font-size: 4em;
87 line-height: 1.1;
88 }
89 .cn-welcome-wrap h2 {
90 font-size: 2em;
91 line-height: 1.1;
92 }
93 .cn-welcome-wrap h4 {
94 font-size: 1.5em;
95 }
96 .cn-welcome-wrap h5 {
97 font-size: 1.35em;
98 }
99
100 .cn-welcome-wrap a,
101 .cn-welcome-wrap .cn-btn {
102 transition: all 0.2s;
103 }
104
105 .cn-welcome-step-1 h3:first-child {
106 margin-bottom: 0;
107 }
108
109 .cn-welcome-step-1 .cn-content .cn-lead {
110 margin-top: 1.5em;
111 max-width: 100%;
112 }
113
114 .cn-welcome-step-1 .cn-content .cn-lead p:first-child {
115 margin-bottom: 1em;
116 }
117
118 .cn-welcome-step-1 .cn-content h1 {
119 margin-bottom: 5px;
120 }
121
122 .cn-welcome-step-1 .cn-content h2 {
123 margin-bottom: 1em;
124 }
125
126 .cn-welcome-step-1 .cn-content h4 {
127 margin-top: 1.5em;
128 }
129
130 .cn-welcome-step-1 .cn-sidebar .cn-lead {
131 margin-bottom: 1em;
132 }
133
134 .cn-welcome-step-1 .cn-sidebar .cn-inner,
135 .cn-welcome-step-1 .cn-content .cn-inner {
136 padding: 6em;
137 }
138
139 .cn-welcome-wrap.cn-welcome-step-1 .cn-sidebar {
140 width: 50%;
141 }
142
143 .cn-welcome-wrap.cn-welcome-step-1 .cn-content.cn-sidebar-visible {
144 width: 50%;
145 }
146
147 .cn-welcome-wrap .cn-content a.cn-link {
148 color: #20C19E;
149 text-decoration: none;
150 font-style: normal;
151 outline: none;
152 box-shadow: none;
153 }
154
155 .cn-welcome-wrap .cn-sidebar {
156 width: 25%;
157 min-height: 100%;
158 background: #35353F;
159 /*
160 background: rgba(7,137,145,0.7);
161 background: linear-gradient(145deg, rgba(7,137,145,.7), rgba(32,193,158,.7));
162 */
163 /*
164 display: flex;
165 justify-content: center;
166 align-items: center;
167 */
168 position: relative;
169 text-align: left;
170 overflow-y: scroll;
171 -ms-overflow-style: none; /* IE and Edge */
172 scrollbar-width: none; /* Firefox */
173 }
174
175 .cn-welcome-wrap .cn-content {
176 width: 100%;
177 min-height: 100%;
178 background-size: cover;
179 position: relative;
180 /*
181 display: flex;
182 justify-content: space-between;
183 align-items: center;
184 */
185 text-align: center;
186 overflow-y: scroll;
187 -ms-overflow-style: none; /* IE and Edge */
188 scrollbar-width: none; /* Firefox */
189 }
190
191 .cn-welcome-wrap .cn-content::-webkit-scrollbar,
192 .cn-welcome-wrap .cn-sidebar::-webkit-scrollbar {
193 width: 0;
194 height: 0;
195 }
196
197 .cn-welcome-wrap .cn-hero-image {
198 display: flex;
199 justify-content: center;
200 align-items: flex-start;
201 max-width: 70%;
202 margin: 2em auto;
203 }
204
205 .cn-welcome-wrap .cn-hero-image img {
206 align-self: center;
207 max-width: 600px;
208 }
209
210 .cn-welcome-wrap .cn-hero-image .cn-flex-item img {
211 max-width: 400px;
212 }
213
214 .cn-welcome-wrap .cn-flex-item {
215 flex-grow: 1;
216 flex-basis: 0;
217 }
218
219 .cn-welcome-wrap .cn-flex-item:first-child,
220 .cn-welcome-wrap .cn-flex-item:last-child {
221 flex-grow: 4;
222 }
223
224 .cn-welcome-wrap .cn-flex-item:nth-child(2) img {
225 margin-top: 130px;
226 }
227
228 .cn-welcome-wrap .cn-flex-item ul {
229 padding: 0;
230 margin: 0;
231 list-style: none;
232 font-size: 15px;
233 }
234
235 .cn-welcome-wrap .cn-flex-item ul li {
236 padding: 0;
237 font-size: 15px;
238 line-height: 1.1;
239 margin: 1em 0;
240 }
241
242 .cn-welcome-wrap .cn-flex-item ul li span {
243 display: inline-block;
244 position: relative;
245 padding-left: 20px;
246 }
247
248 .cn-welcome-wrap .cn-flex-item ul li span::before {
249 font-family: 'dashicons';
250 line-height: 1;
251 font-weight: 400;
252 font-style: normal;
253 text-transform: none;
254 text-rendering: auto;
255 font-size: 16px;
256 text-align: center;
257 display: block;
258 content: "\f15e";
259 position: absolute;
260 top: 2px;
261 left: 0;
262 line-height: 1;
263 width: 16px;
264 height: 16px;
265 margin: 0;
266 color: #20C19E;
267 background: none;
268 }
269
270 .cn-welcome-wrap .cn-flex-item ul li b {
271 font-weight: bold;
272 font-size: 16px;
273 }
274
275 .cn-welcome-wrap .cn-logo-container {
276 margin-bottom: 1em;
277 }
278
279 .cn-welcome-wrap .cn-logo-container > * {
280 vertical-align: middle;
281 margin-bottom: 0.5em;
282 }
283
284 .cn-welcome-wrap .cn-logo-container img {
285 display: inline-block;
286 }
287
288 .cn-welcome-wrap .cn-badge {
289 background: #ccc;
290 color: #191e23;
291 border-radius: 3px;
292 text-transform: uppercase;
293 line-height: 1;
294 display: inline-block;
295 padding: 5px;
296 margin-left: 5px;
297 margin-right: 5px;
298 }
299
300 .cn-welcome-wrap .cn-pricing-type .cn-badge {
301 font-size: 14px;
302 font-weight: bold;
303 color: #fff;
304 background: #20c19e;
305 padding: 2.5px 7.5px;
306 }
307
308 .cn-welcome-wrap .cn-pricing-type div:first-child {
309 border-right: 1px solid #ccc;
310 }
311
312 .cn-welcome-wrap.cn-welcome-step-2 .cn-content {
313 background-size: cover;
314 }
315
316 .cn-welcome-wrap.cn-welcome-step-3 .cn-content {
317 background-size: cover;
318 }
319
320 .cn-welcome-wrap.cn-welcome-step-4 .cn-content {
321 background-size: cover;
322 }
323
324 .cn-welcome-wrap .cn-content.cn-sidebar-visible {
325 width: 75%;
326 }
327
328 .cn-welcome-wrap .cn-content-header {
329 text-align: center;
330 margin-bottom: 2em;
331 line-height: 1em;
332 display: flex;
333 flex-direction: row;
334 }
335
336 .cn-welcome-wrap .cn-content-header:before,
337 .cn-welcome-wrap .cn-content-header:after {
338 content:'';
339 flex: 1 1;
340 margin: auto;
341 border-bottom: 1px solid rgba(255,255,255,.7);
342 }
343
344 .cn-welcome-wrap .cn-content-header:before {
345 margin-right: 1em;
346 }
347
348 .cn-welcome-wrap .cn-content-header:after {
349 margin-left: 1em;
350 }
351
352 .cn-welcome-wrap .cn-inner {
353 position: relative;
354 z-index: 1;
355 padding: 4em;
356 min-height: 100%;
357 width: 100%;
358 display: flex;
359 justify-content: space-between;
360 }
361
362 .cn-sidebar .cn-inner {
363 flex-direction: column;
364 justify-content: space-between;
365 padding-bottom: 2em;
366 }
367
368 .cn-content .cn-inner {
369 flex-direction: row;
370 justify-content: space-around;
371 align-items: center;
372 }
373
374 .cn-content .cn-lead {
375 margin: 0 auto;
376 max-width: 75%;
377 }
378
379 .cn-content .cn-lead p {
380 font-size: 1.3em;
381 margin: 0.5em 0;
382 }
383
384 .cn-content .cn-lead p:last-child {
385 margin-bottom: 0;
386 }
387
388 .cn-content .cn-content-full {
389 width: 100%;
390 }
391
392 .cn-sidebar {
393 color: #BBBBC0;
394 }
395
396 .cn-sidebar a,
397 .cn-sidebar em {
398 color: #20C19E;
399 text-decoration: none;
400 font-style: normal;
401 outline: none;
402 box-shadow: none;
403 }
404
405 .cn-sidebar a:hover {
406 text-decoration: underline;
407 }
408
409 .cn-sidebar .cn-lead {
410 margin-bottom: 2em;
411 }
412
413 .cn-sidebar .cn-lead b {
414 color: #fff;
415 font-weight: bold;
416 font-size: 15px;
417 }
418
419 .cn-sidebar .cn-lead p:last-child {
420 margin-bottom: 0;
421 }
422
423 .cn-sidebar .cn-buttons,
424 .cn-content .cn-buttons {
425 margin-top: 3em;
426 }
427
428 .cn-welcome-step-3 .cn-content .cn-buttons {
429 margin-top: 0;
430 }
431
432 .cn-header {
433 margin-bottom: 3em;
434 }
435
436 .cn-footer {
437 margin-top: 3em;
438 text-align: left;
439 }
440
441 .cn-footer .cn-btn.cn-skip-button {
442 color: #86868F;
443 font-weight: normal;
444 font-size: inherit;
445 text-decoration: none;
446 }
447
448 .cn-footer .cn-btn.cn-skip-button:hover {
449 color: #fff;
450 text-decoration: none;
451 }
452
453 .cn-footer a:hover {
454 color: #20C19E;
455 }
456
457 .cn-welcome-wrap .cn-pricing-type {
458 margin-top: 1em;
459 font-size: 1.2em;
460 display: flex;
461 justify-content: space-evenly;
462 align-items: baseline;
463 text-align: left;
464 }
465
466 .cn-welcome-wrap .cn-pricing-type > div {
467 flex: 1;
468 padding: 0 1em;
469 }
470
471 .cn-welcome-wrap .cn-pricing-type > div:nth-child(1) {
472 text-align: right;
473 }
474
475 .cn-welcome-wrap .cn-pricing-type label {
476 padding: 0;
477 margin: 0;
478 text-align: left;
479 position: relative;
480 display: inline-block;
481 }
482
483 .cn-welcome-wrap .cn-pricing-type label .cn-pricing-toggle {
484 margin-left: 1.5em;
485 }
486
487 .cn-welcome-wrap #cn-pricing-plans {
488 margin-top: 1em;
489 }
490
491 .cn-welcome-wrap .cn-pricing-select {
492 margin-top: 1.5em;
493 margin-bottom: 1.5em;
494 }
495
496 .cn-welcome-wrap .cn-pricing-table {
497 display: flex;
498 justify-content: center;
499 align-items: center;
500 margin-top: 3em;
501 }
502
503 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item {
504 margin: 0 1.5em 3em;
505 min-width: 300px;
506 }
507
508 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item h4 {
509 margin-bottom: 0.5em;
510 position: relative;
511 font-size: 1.3em;
512 }
513
514 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item h4:after {
515 content: '';
516 display: block;
517 width: 60px;
518 border-bottom: 1px solid #86868F;
519 margin: 1em auto 0;
520 }
521
522 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item button {
523 pointer-events: none;
524 }
525
526 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item:hover .cn-pricing-info {
527 border-color: rgba(0, 0, 0, 0.1);
528 }
529
530 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item .cn-pricing-info {
531 box-shadow: 0px 0px 13px 0px rgba(236, 236, 241, 1);
532 border: 1px solid transparent;
533 border-radius: 5px;
534 position: relative;
535 overflow: hidden;
536 }
537
538 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item input {
539 display: none;
540 }
541
542 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item input:checked + .cn-pricing-info {
543 border-color: #20C19E;
544 }
545
546 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item .cn-pricing-info > div {
547 padding: 2em 1.5em;
548 }
549
550 .cn-welcome-wrap .cn-pricing-table input#cn-pricing-plan-free + .cn-pricing-info .cn-plan-price {
551 color: #515151;
552 font-size: 1.25em;
553 line-height: 1.5em;
554 }
555
556 .cn-welcome-wrap .cn-pricing-table input#cn-pricing-plan-pro + .cn-pricing-info {
557 background-color: rgba(32,193,158,0.05);
558 }
559
560 .cn-welcome-wrap .cn-pricing-table input#cn-pricing-plan-pro + .cn-pricing-info .cn-plan-promo {
561 color: #fff;
562 background: #ffc107;
563 position: absolute;
564 left: 50%;
565 top: 0;
566 font-weight: bold;
567 font-size: 13px;
568 line-height: 1.1em;
569 text-transform: uppercase;
570 display: inline-block;
571 letter-spacing: 1px;
572 border-radius: 0 0 5px 5px;
573 padding: 0.25em 2em;
574 transform: translateX(-50%);
575 }
576
577 .cn-welcome-wrap .cn-pricing-table .cn-pricing-item .cn-pricing-info .cn-pricing-head {
578 border-bottom: 1px solid rgba(0, 0, 0, 0.05);
579 padding: 3em 1.5em 2.5em;
580 }
581
582 .cn-welcome-wrap .cn-pricing-table .cn-pricing-info div.cn-pricing-body {
583 padding-bottom: 0;
584 font-size: 14px;
585 text-align: left;
586 }
587
588 .cn-welcome-wrap .cn-pricing-table .cn-pricing-info div.cn-pricing-body p {
589 padding-left: 35px;
590 line-height: 1.5;
591 margin: 1em 0;
592 }
593
594 .cn-welcome-wrap .cn-pricing-table .cn-plan-pricing {
595 display: block;
596 font-size: 1.5em;
597 color: #515151;
598 }
599
600 .cn-welcome-wrap .cn-pricing-table .cn-plan-price {
601 font-size: 1.5em;
602 font-weight: bold;
603 line-height: 1.1;
604 color: #20C19E;
605 text-transform: uppercase;
606 }
607
608 .cn-welcome-wrap .cn-pricing-table .cn-plan-price sup {
609 font-weight: normal;
610 font-size: 0.5em;
611 color: #515151;
612 vertical-align: top;
613 }
614
615 .cn-welcome-wrap .cn-pricing-table .cn-plan-price sub {
616 font-weight: normal;
617 font-size: 0.5em;
618 color: #515151;
619 text-transform: none;
620 vertical-align: bottom;
621 }
622
623 .cn-welcome-wrap .cn-select-wrapper select {
624 background: #fff;
625 border: 1px solid #ccc;
626 color: #191e23;
627 border-radius: 25px;
628 padding: 7.5px 35px 7.5px 20px;
629 background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
630 background-repeat: no-repeat;
631 background-position: right 10px center;
632 background-size: 16px 12px;
633 }
634
635 .cn-welcome-wrap .cn-select-wrapper select:hover,
636 .cn-welcome-wrap .cn-select-wrapper select:focus {
637 color: inherit;
638 box-shadow: none;
639 }
640
641 .cn-welcome-wrap .cn-billing-wrapper {
642 font-weight: normal;
643 }
644
645 .cn-welcome-wrap .cn-billing-wrapper input {
646 display: none;
647 }
648
649 .cn-welcome-wrap .cn-billing-wrapper label {
650 position: relative;
651 display: inline-block;
652 padding: .5em 1em;
653 box-sizing: content-box;
654 }
655
656 .cn-welcome-wrap .cn-billing-wrapper input:checked + span {
657 color: #fff;
658 }
659
660 .cn-welcome-wrap .cn-billing-wrapper input:checked + span .cn-plan-overlay {
661 background-color: rgba(53,53,63,1);
662 }
663
664 .cn-welcome-wrap .cn-billing-wrapper .cn-plan-overlay {
665 border: none;
666 width: 100%;
667 height: 100%;
668 border-radius: 3px;
669 position: absolute;
670 left: 0;
671 top: 0;
672 transition: border-color 0.2s;
673 z-index: -1;
674 background-color: rgba(53,53,63,0.1);
675 }
676
677 .cn-welcome-wrap .cn-billing-wrapper :first-child > span .cn-plan-overlay {
678 border-top-right-radius: 0;
679 border-bottom-right-radius: 0;
680 }
681
682 .cn-welcome-wrap .cn-billing-wrapper :last-child > span .cn-plan-overlay {
683 border-top-left-radius: 0;
684 border-bottom-left-radius: 0;
685 }
686
687 .cn-btn {
688 border-radius: 3em;
689 padding: 1em 3em;
690 box-shadow: none;
691 border: 2px solid #20C19E;
692 outline: none;
693 background: #20C19E;
694 font-size: 15px;
695 font-weight: bold;
696 color: #fff;
697 cursor: pointer;
698 display: inline-block;
699 text-decoration: none;
700 }
701
702 .cn-btn:hover,
703 .cn-btn:focus {
704 box-shadow: none;
705 outline: none;
706 border: 2px solid #20C19E;
707 background: #20C19E;
708 color: #fff;
709 text-decoration: none !important;
710 }
711
712 .cn-btn.cn-btn-outline {
713 background: transparent;
714 color: #20C19E;
715 box-shadow: 0 0 15px 0 rgba(255,255,255,.4), inset 0 0 15px rgba(255,255,255,.4);
716 }
717
718 .cn-btn.cn-btn-outline:hover {
719 text-shadow: 0 0 10px rgba(255,255,255,.4), 0 0 20px rgba(255,255,255,.4), 0 0 30px rgba(255,255,255,.4), 0 0 40px rgba(255,255,255,.4);
720 }
721
722 .cn-btn.cn-btn-outline .cn-spinner::after {
723 border-color: #fff transparent #fff transparent;
724 }
725
726 .cn-btn.cn-btn-transparent,
727 .cn-btn.cn-btn-transparent:hover,
728 .cn-btn.cn-btn-transparent:focus {
729 box-shadow: none;
730 background: transparent;
731 color: #BBBBC0;
732 border-color: transparent;
733 }
734
735 .cn-btn.cn-btn-lg {
736 border-radius: 4em;
737 padding: 1.5em 4em;
738 font-size: 15px;
739 }
740
741 .cn-btn.cn-btn-link {
742 background: none;
743 border-color: transparent;
744 color: inherit;
745 padding: 0;
746 }
747
748 .cn-btn.cn-btn-secondary {
749 background-color:#ffc107;
750 border-color:#ffc107;
751 color:#3c434a
752 }
753
754 .cn-btn.cn-btn-secondary:active,
755 .cn-btn.cn-btn-secondary:focus,
756 .cn-btn.cn-btn-secondary:hover {
757 background-color:#ffca2c;
758 border-color:#ffca2c
759 }
760
761 .cn-top-bar {
762 display: flex;
763 justify-content: space-between;
764 align-items: center;
765 }
766
767 .cn-stepper {
768 padding: 1.5em;
769 margin: 1.5em -1.5em;
770 overflow-x: hidden;
771 overflow-y: auto;
772 display: flex;
773 justify-content: space-between;
774 }
775
776 .cn-stepper li {
777 position: relative;
778 display: flex;
779 flex: 1;
780 align-items: center;
781 transition: .2s;
782 margin: 0;
783 }
784
785 .cn-stepper li:not(:last-child):after {
786 position: relative;
787 flex: 1;
788 height: 1px;
789 margin: .35em 0 0 0;
790 content: '';
791 background-color: #86868F;
792 }
793
794 .cn-stepper li .cn-step {
795 cursor: default;
796 }
797
798 .cn-stepper li .cn-step .cn-circle {
799 display: inline-block;
800 width: 2em;
801 height: 2em;
802 line-height: 2em;
803 font-weight: bold;
804 color: #fff;
805 text-align: center;
806 background: #86868F;
807 border-radius: 50%;
808 }
809
810 .cn-stepper li.cn-completed .cn-step .cn-circle {
811 color: transparent;
812 background: #20C19E;
813 }
814 .cn-stepper li.cn-completed .cn-step .cn-circle:before{
815 font-family: dashicons;
816 line-height: 1;
817 font-weight: 400;
818 font-style: normal;
819 text-transform: none;
820 text-rendering: auto;
821 font-size: 14px;
822 text-align: center;
823 display: block;
824 content: "\f15e";
825 position: absolute;
826 top: 0;
827 left: -2px;
828 line-height: 2em;
829 width: 2em;
830 pointer-events: none;
831 transform: scale(1.25, 1.25);
832 color: #fff;
833 }
834
835 .cn-stepper li.cn-active .cn-step .cn-circle {
836 background: #20C19E;
837 }
838
839 .cn-features-list .cn-feature {
840 display: flex;
841 margin-bottom: 2em;
842 padding: 2em;
843 border: 1px solid rgba(255,255,255,0.1);
844 border-radius: 3px;
845 box-sizing: content-box;
846 background-color: rgba(255,255,255,0.1);
847 }
848
849 .cn-features-list .cn-feature:last-child {
850 margin-bottom: 0;
851 }
852
853 .cn-features-list .cn-feature img {
854 width: 48px;
855 height: 48px;
856 margin-right: 2em;
857 }
858 .cn-features-list .cn-feature h5 {
859 margin-bottom: 0.5em;
860 }
861
862 .cn-features-list .cn-feature-description p:last-child {
863 margin-bottom: 0;
864 }
865
866 .cn-form-container {
867 margin-left: -15px;
868 margin-right: -15px;
869 padding-left: 15px;
870 padding-right: 15px;
871 background: rgba(255,255,255,0.05);
872 padding-bottom: 1px;
873 }
874
875 .cn-form-header {
876 font-size: 15px;
877 font-style: normal;
878 font-weight: bold;
879 color: #fff;
880 width: 100%;
881 text-align: left;
882 margin: 0;
883 padding: 15px 0;
884 color: #fff;
885 }
886
887 .cn-small {
888 font-size: 12px;
889 }
890
891 .cn-form.cn-form-disabled[data-action="payment"] {
892 pointer-events: none;
893 opacity: 0.5;
894 }
895
896 .cn-form.cn-form-disabled .cn-accordion-collapse {
897 pointer-events: none;
898 }
899
900 .cn-welcome-wrap form {
901 position: relative;
902 margin: 0;
903 }
904
905 .cn-welcome-wrap form .cn-form-feedback {
906 position: relative;
907 margin-bottom: 1.5em;
908 color: #fff;
909 overflow-y: hidden;
910 max-height: 500px; /* approximate max height */
911 transition: all .3s cubic-bezier(0, 1, 0.5, 1);
912 transition-delay: 0.3s;
913 opacity: 1;
914 }
915
916 .cn-welcome-wrap form .cn-form-feedback p {
917 padding: 15px;
918 margin: 0;
919 }
920
921 .cn-welcome-wrap form .cn-form-feedback p.cn-error {
922 border: 1px solid #da2439;
923 border-radius: 3px;
924 background: rgba( 218,36,57, 0.5);
925 }
926
927 .cn-welcome-wrap form .cn-form-feedback p.cn-warning {
928 border: 1px solid #e78d26;
929 border-radius: 3px;
930 background: rgba( 231,141,38, 0.5);
931 }
932
933 .cn-welcome-wrap form .cn-form-feedback p.cn-message {
934 border: 1px solid #008000;
935 border-radius: 3px;
936 background: rgba( 0,128,0, 0.5);
937 }
938
939 .cn-welcome-wrap form .cn-form-feedback.cn-hidden {
940 max-height: 0;
941 margin-bottom: 0;
942 opacity: 0;
943 }
944
945 .cn-welcome-wrap form .cn-field:not(:last-child) {
946 position: relative;
947 margin: 0 0 0.5em;
948 }
949
950 .cn-welcome-wrap form .cn-field.cn-hidden {
951 display: none;
952 }
953
954 .cn-welcome-wrap form .cn-field.cn-field-half {
955 width: calc(50% - 0.5em);
956 display: inline-block;
957 margin: auto 0.25em;
958 }
959
960 .cn-welcome-wrap form .cn-field.cn-field-first {
961 margin-left: 0;
962 }
963
964 .cn-welcome-wrap form .cn-field.cn-field-last {
965 margin-right: 0;
966 }
967
968 .cn-welcome-wrap form label {
969 color: #fff;
970 margin: 0 0 0.5em;
971 display: block;
972 }
973
974 .cn-welcome-wrap form .cn-field > label {
975 color: #fff;
976 margin: 0 0 0.5em;
977 display: block;
978 font-weight: 700;
979 }
980
981 .cn-welcome-wrap form .cn-field.cn-field-submit {
982 margin: 1.5em 0 0 0;
983 }
984
985 .cn-welcome-wrap form input[type="text"],
986 .cn-welcome-wrap form input[type="password"],
987 .cn-welcome-wrap form input[type="checkbox"],
988 .cn-welcome-wrap form input[type="radio"],
989 .cn-welcome-wrap form select {
990 background: transparent;
991 border: 1px solid #86868F;
992 margin: 0;
993 padding: 0 15px;
994 color: #fff;
995 transition: border-color 0.2s;
996 }
997
998 .cn-welcome-wrap form select#cn-subscription-select option {
999 color: #35353f;
1000 }
1001
1002 .cn-welcome-wrap form select#cn-subscription-select option:disabled {
1003 background: #666;
1004 }
1005
1006 .cn-welcome-wrap form input[type="checkbox"],
1007 .cn-welcome-wrap form input[type="radio"] {
1008 transition: none;
1009 }
1010
1011 .cn-welcome-wrap form input[type="checkbox"] b,
1012 .cn-welcome-wrap form input[type="radio"] b {
1013 font-weight: 700;
1014 }
1015
1016 .cn-welcome-wrap form input[type="text"],
1017 .cn-welcome-wrap form input[type="password"],
1018 .cn-welcome-wrap form select {
1019 width: 100%;
1020 line-height: 3;
1021 }
1022
1023 .cn-welcome-wrap form .cn-select-wrapper {
1024 position: relative;
1025 margin: 0;
1026 }
1027 .cn-welcome-wrap form .cn-select-wrapper:after {
1028 font-family: dashicons;
1029 line-height: 1;
1030 font-weight: 400;
1031 font-style: normal;
1032 text-transform: none;
1033 text-rendering: auto;
1034 font-size: 18px;
1035 text-align: center;
1036 display: block;
1037 content: "\f347";
1038 position: absolute;
1039 top: 50%;
1040 margin-top: -9px;
1041 right: 15px;
1042 line-height: 1;
1043 pointer-events: none;
1044 color: #fff;
1045 }
1046
1047 .cn-welcome-wrap form .cn-checkbox-wrapper,
1048 .cn-welcome-wrap form .cn-radio-wrapper {
1049 position: relative;
1050 }
1051
1052 .cn-welcome-wrap form .cn-checkbox-wrapper label,
1053 .cn-welcome-wrap form .cn-radio-wrapper label {
1054 color: #BBBBC0;
1055 }
1056
1057 .cn-welcome-wrap form .cn-checkbox-wrapper.cn-horizontal-wrapper label,
1058 .cn-welcome-wrap form .cn-radio-wrapper.cn-horizontal-wrapper label {
1059 display: inline-block;
1060 margin-right: 0.5em;
1061 }
1062
1063 .cn-welcome-wrap form .cn-checkbox-wrapper.cn-horizontal-wrapper label:last-child,
1064 .cn-welcome-wrap form .cn-radio-wrapper.cn-horizontal-wrapper label:last-child {
1065 margin-right: 0;
1066 }
1067
1068 .cn-welcome-wrap .cn-checkbox-wrapper input,
1069 .cn-welcome-wrap .cn-radio-wrapper input {
1070 position: absolute;
1071 margin: 2px 0;
1072 }
1073
1074 .cn-welcome-wrap .cn-checkbox-wrapper input:focus,
1075 .cn-welcome-wrap .cn-radio-wrapper input:focus {
1076 border-color: #86868F;
1077 }
1078
1079 .cn-welcome-wrap .cn-checkbox-wrapper input:checked,
1080 .cn-welcome-wrap .cn-radio-wrapper input:checked {
1081 background: none;
1082 border-color: #20C19E;
1083 }
1084
1085 .cn-welcome-wrap .cn-checkbox-wrapper input:checked,
1086 .cn-welcome-wrap .cn-radio-wrapper input:checked {
1087 background: none;
1088 border-color: #20C19E;
1089 }
1090
1091 .cn-welcome-wrap .cn-checkbox-wrapper input:checked::before {
1092 font-family: dashicons;
1093 line-height: 1;
1094 font-weight: 400;
1095 font-style: normal;
1096 text-transform: none;
1097 text-rendering: auto;
1098 font-size: 14px;
1099 text-align: center;
1100 display: block;
1101 content: "\f15e";
1102 position: absolute;
1103 top: 0;
1104 left: 0;
1105 line-height: 1;
1106 width: 16px;
1107 height: 16px;
1108 margin: 0 auto 0 -1px;
1109 color: #fff;
1110 background: none;
1111 }
1112
1113 .cn-welcome-wrap form .cn-color-picker-wrapper input {
1114 border: none;
1115 }
1116
1117 .cn-welcome-wrap form .cn-color-picker-wrapper .sp-original-input-container {
1118 margin-left: 0;
1119 position: absolute;
1120 border: 1px solid rgba(255,255,255,1);
1121 border-radius: 0;
1122 }
1123
1124 .cn-welcome-wrap form .cn-color-picker-wrapper .sp-colorize-container {
1125 height: 16px;
1126 }
1127
1128 .cn-welcome-wrap form .cn-color-picker-wrapper input:checked::before {
1129 content: '';
1130 }
1131
1132 .cn-welcome-wrap .cn-radio-wrapper label input:checked::before {
1133 text-align: center;
1134 display: block;
1135 position: absolute;
1136 top: 2px;
1137 left: 2px;
1138 line-height: 1;
1139 width: 10px;
1140 height: 10px;
1141 margin: 0 auto;
1142 color: #fff;
1143 background: #20C19E;
1144 }
1145
1146 .cn-welcome-wrap .cn-checkbox-wrapper label > span,
1147 .cn-welcome-wrap .cn-radio-wrapper label > span {
1148 margin-left: 2em;
1149 display: block;
1150 }
1151
1152 .cn-welcome-wrap .cn-field-checkbox > label.cn-asterix::after {
1153 content: '*';
1154 right: 0;
1155 top: 0;
1156 line-height: 8px;
1157 padding-left: 3px;
1158 display: inline-block;
1159 }
1160
1161 .cn-welcome-wrap .cn-checkbox-wrapper label > span.cn-asterix::after,
1162 .cn-welcome-wrap .cn-radio-wrapper label > span.cn-asterix::after {
1163 content: '*';
1164 right: 0;
1165 top: 0;
1166 line-height: 8px;
1167 padding-left: 3px;
1168 display: inline-block;
1169 }
1170
1171 .cn-welcome-wrap form .cn-checkbox-image-wrapper label,
1172 .cn-welcome-wrap form .cn-radio-image-wrapper label {
1173 display: inline-block;
1174 margin: 0 0.25em;
1175 position: relative;
1176 }
1177
1178 .cn-welcome-wrap form .cn-checkbox-image-wrapper label.cn-asterix,
1179 .cn-welcome-wrap form .cn-radio-image-wrapper label.cn-asterix {
1180 padding-right: 8px;
1181 }
1182 .cn-welcome-wrap form .cn-checkbox-image-wrapper label.cn-asterix::after,
1183 .cn-welcome-wrap form .cn-radio-image-wrapper label.cn-asterix::after {
1184 content: '*';
1185 position: absolute;
1186 right: 0;
1187 top: 0;
1188 line-height: 8px;
1189 }
1190
1191 .cn-sidebar form .cn-checkbox-image-wrapper span,
1192 .cn-sidebar form .cn-radio-image-wrapper span {
1193 display: block;
1194 text-align: center;
1195 font-weight: 600;
1196 }
1197
1198 .cn-welcome-wrap form .cn-checkbox-image-wrapper label:first-child,
1199 .cn-welcome-wrap form .cn-radio-image-wrapper label:first-child {
1200 margin-left: 0;
1201 }
1202
1203 .cn-welcome-wrap form .cn-checkbox-image-wrapper label:last-child,
1204 .cn-welcome-wrap form .cn-radio-image-wrapper label:last-child {
1205 margin-right: 0;
1206 }
1207
1208 .cn-welcome-wrap form .cn-checkbox-image-wrapper input,
1209 .cn-welcome-wrap form .cn-radio-image-wrapper input {
1210 display: none;
1211 }
1212
1213 .cn-welcome-wrap form .cn-checkbox-image-wrapper input:checked + img,
1214 .cn-welcome-wrap form .cn-radio-image-wrapper input:checked + img {
1215 border-color: #20C19E;
1216 }
1217
1218 .cn-welcome-wrap form .cn-checkbox-image-wrapper img,
1219 .cn-welcome-wrap form .cn-radio-image-wrapper img {
1220 display: inline-block;
1221 padding: 0.5em;
1222 border: 2px solid #86868F;
1223 border-radius: 3px;
1224 box-sizing: content-box;
1225 }
1226
1227 .cn-checkbox-image-wrapper .gdpr {
1228 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC/ElEQVRoge2ZzZGjMBCFmcMet4rjHjlsANQmsGRgZ7BkMGRgZ7DOYMhgnME4A08GdgZ2AujbA41HiD8JEOawXUWVXUjd73WLVqsVBB4F+OlTv3cBciB7Ng4nAV6ADHjnSz6A7bOxPQQIh94Dd43AaSFodgKkFmNOGoHEYvwySw1IgJtFFHJgC6RD4GTJnedF2jQSAUfNqzfgMFFnAnxqOi9CvNc5UwzG1CWaQede03f1Bl6MhZqxz5l0Jot97BKBRH5nc3hLCETyO52qr1LqL4wjxWm5Akd/UMaJfOzdjpUs8xvYyXp8k//RcjA7Mf01MMVdE3IjyxyfvZyMLIVEIuoarGcZJhqOgY14bJITqO8VSd/AqobZy6T2UPUbi5RSH0op9EeW5igiguVAWZ50YxKvhRoZJ4MC/maCr56iKN5GEgi139EYHVailDpqYHMgKYpir5S6a5FIvQGYIuL9B3jjXapFYnUpOgiCIAC2mpcT872+lJ4Ab1hkqfQRuHslIB9wNHa+BYHrHAToOprKJuacJSgPLH+M1HmRtLkDdkqp95aU+tqb09tthcC5No/moeLcybKpMO5KmZbPydLON3HwzagSflQD9BIid/BI4gD2OpaA2DIbBan+8qC9sD5cOxD4FADZWAJir72kkAjE8sxN4FEGF0WRT4xAVtl1/X6sCQCZlpH6wDtHYHbpIFDVUskA+HUSUEqd9eKrB/xqCVQkNmb+X4SAy8fhmEYnEbDGJanKavDCBPoPWJSnsIvk2BvlAbr3RAaEssZPYx6blN2BK2obGFGX/bBf/EsLrm7SlL3J5k73ZMGmVS9MT5Qt8T0rulGhLHViyso3sZ20uvbif1kiKl5tuFSqI/WH+Gq78HUR4dytc7CRS86fLwo078YQQ5HFXKtLEOq3NMP53lVaNpPIcs4Fy0YB9S70LNdXpgGqjW5g3AvNlvgd+DUwb6vZmHT72aY8rtY+WgN4YI5+fh3cFPUNynqz8inUt//V7OpWAnwHNuZvH/IPPeDD9c6V9FUAAAAASUVORK5CYII=);
1229 background-repeat: no-repeat;
1230 background-position: center center;
1231 }
1232
1233 .cn-checkbox-image-wrapper .ccpa {
1234 background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAwCAYAAACScGMWAAACPElEQVRYheXYvXHbMBTAcY7AEbSA79Smskp30QiqkyLaQPQE8Qb2BtEG4QZil3Ry5ZZaAO/vAqANIwSJD1LmXXD3ToVE8sf3hEcQRVEUBXADfE+Mu2LOAVSkj/q/xj0sGVcvEgeUGTAvDlgBP4CD+Vyl4HaZuNa9WRH5JSK4oZT6CZQxuN+ZOBzYqQ9mxSkYmAuzcUqpyoE0InIUkWcng1UoLresWFlrOwCwczLa2EAispczWzvcxs5YzzXWDm4bistpwk1RfCypr2yppc3BVUvDXYAtsO7OsSRcbY5bAbfArYicrYu36Ob7Fj297wx8Ncf7JwewScGJSD3S00LjOJa9p0/E1SHlDQWm4rqmHI+LAKbgGsx/y23IMbiQVUos7g2G04yjcOYEObga2InIxQNrc3FjK2MvDtP7DOQYAIvGlcBzYub+WRKNwOJw5oRDvW8Ih4icImDxOHNiX3nHcF0GDwGwZJyvvCG4aZuwB9i31lsMbu/DAXsD9IZS6kEpVQ0FoQvPHlxfaU/jR15peGbuGf3mlhqHKYF95c0dj1MCY5ZV1wUy/uT4dOB2BtykwDmyNw0QOM6EyweS9547L/AKOID7VNwcLcUdf1Jxa3T27MjaDOoZL0m4AXRJ3uZ3Pg69p9fy/pxssVYW6GdxbrvJwjXoUnZh40oTFXrT53q4EXiNtYltkCkTaDoc71v734B9z/ex7WdSXHfxzcBvYsbfKXHlECwAd0H/JZ7MjX6ZDBcy0DPYBmyHbugVe8KbbhsHbZ0AAAAASUVORK5CYII=);
1235 background-repeat: no-repeat;
1236 background-position: center center;
1237 }
1238
1239 .cn-welcome-wrap form .cn-plan-wrapper {
1240 margin-bottom: 1em;
1241 }
1242
1243 .cn-welcome-wrap form .cn-plan-wrapper label > span {
1244 margin-left: 2em;
1245 }
1246
1247 .cn-welcome-wrap form .cn-plan-wrapper label {
1248 position: relative;
1249 display: block;
1250 padding: 1.25em 1em;
1251 box-sizing: content-box;
1252 }
1253
1254 .cn-welcome-wrap form .cn-plan-overlay {
1255 border: 1px solid #86868F;
1256 width: 100%;
1257 height: 100%;
1258 border-radius: 3px;
1259 position: absolute;
1260 left: 0;
1261 top: 0;
1262 transition: border-color 0.2s;
1263 z-index: 0;
1264 background-color: rgba(32,193,158,0);
1265 }
1266
1267 .cn-welcome-wrap form .cn-plan-wrapper .cn-disabled {
1268 pointer-events: none;
1269 opacity: 0.3;
1270 }
1271
1272 .cn-welcome-wrap form .cn-plan-wrapper input:checked + span .cn-plan-overlay {
1273 border-color: #20C19E;
1274 background-color: rgba(32,193,158,.1);
1275 }
1276
1277 .cn-welcome-wrap form .cn-plan-wrapper span .cn-plan-description {
1278 font-weight: normal;
1279 }
1280
1281 .cn-welcome-wrap form .cn-plan-wrapper span .cn-plan-description b {
1282 font-weight: bold;
1283 }
1284
1285 .cn-welcome-wrap form .cn-plan-wrapper input:checked + span {
1286 color: #fff;
1287 }
1288
1289 .cn-welcome-wrap form .cn-plan-name {
1290 display: block;
1291 font-size: 1.1em;
1292 font-weight: bold;
1293 color: #fff;
1294 }
1295
1296 .cn-welcome-wrap form .cn-plan-pricing {
1297 display: inline-block;
1298 font-size: 1.1em;
1299 float: right;
1300 color: #ccc;
1301 }
1302
1303 .cn-welcome-wrap form .cn-price-off {
1304 font-weight: bold;
1305 color: #20C19E;
1306 }
1307
1308 .cn-welcome-wrap form .cn-plan-price {
1309 font-weight: bold;
1310 }
1311
1312 .cn-welcome-wrap form input::placeholder,
1313 .cn-welcome-wrap form select::placeholder {
1314 color: #86868F;
1315 }
1316
1317 .cn-welcome-wrap form input:focus,
1318 .cn-welcome-wrap form select:focus {
1319 border-color: #20C19E;
1320 box-shadow: none;
1321 }
1322
1323 .cn-welcome-wrap form select:focus {
1324 color: #fff;
1325 }
1326
1327 .cn-welcome-wrap form select:hover {
1328 color: #fff;
1329 }
1330
1331 .cn-welcome-wrap .cn-nav {
1332 margin-top: 3em;
1333 }
1334
1335 .cn-welcome-wrap form .cn-nav {
1336 margin-top: 2.5em;
1337 }
1338
1339 .cn-welcome-wrap .cn-nav .cn-btn {
1340 margin: 0 0.25em;
1341 }
1342
1343 .cn-welcome-wrap .cn-nav .cn-btn:first-child {
1344 margin-left: 0;
1345 }
1346
1347 .cn-welcome-wrap .cn-nav .cn-btn:last-child {
1348 margin-right: 0;
1349 }
1350
1351 .cn-welcome-wrap #cn_preview_frame {
1352 width: 100%;
1353 height: 200px;
1354 border: 1px solid #86868F;
1355 margin-top: 2.5em;
1356 box-shadow: 0 0 10px 0 rgba(0,0,0,.3);
1357 position: relative;
1358 overflow: hidden;
1359 }
1360
1361 .cn-welcome-wrap #cn_preview_frame img {
1362 width: 100%;
1363 height: auto;
1364 display: block;
1365 filter: blur(3px) grayscale(100%);
1366 }
1367
1368 .cn-welcome-wrap #cn_preview_frame_wrapper {
1369 width: 400%;
1370 height: 400%;
1371 transform: scale(0.25) translate(-150%,-150%);
1372 pointer-events: none;
1373 }
1374
1375 .cn-welcome-wrap #cn_preview_frame_wrapper::after {
1376 content: '';
1377 display: block;
1378 width: 100%;
1379 height: 100%;
1380 background-color: rgba(0, 0, 0, 0);
1381 position: absolute;
1382 top: 0;
1383 left: 0;
1384 }
1385
1386 .cn-welcome-wrap #cn_preview_frame_wrapper iframe {
1387 width: 100%;
1388 height: 100%;
1389 filter: grayscale(100%);
1390 }
1391
1392 .cn-welcome-wrap #cn_preview_about {
1393 margin-bottom: 1.5em;
1394 }
1395
1396 .cn-welcome-wrap #cn_preview_about p {
1397 margin: 0;
1398 }
1399
1400 .cn-welcome-wrap #cn_preview_about p b {
1401 color: #fff;
1402 }
1403
1404 .cn-comparison {
1405 width: 100%;
1406 }
1407
1408 .cn-comparison tr:not(:last-child) {
1409 box-shadow: 0px 1px 1px rgba(255,255,255,.5);
1410 }
1411
1412 .cn-comparison th,
1413 .cn-comparison td {
1414 padding: 1em;
1415 }
1416
1417 .cn-comparison th {
1418 font-weight: bold;
1419 text-transform: uppercase;
1420 letter-spacing: 0.05em;
1421 }
1422
1423 .cn-spinner {
1424 display: inline-block;
1425 width: 14px;
1426 height: 14px;
1427 max-width: 0;
1428 opacity: 0;
1429 transition: opacity 0.2s, max-width 0.3s;
1430 }
1431 .cn-spinner.spin {
1432 max-width: 14px;
1433 opacity: 1;
1434 margin-right: 10px;
1435 }
1436 .cn-spinner:after {
1437 content: '';
1438 display: block;
1439 width: 12px;
1440 height: 12px;
1441 border-radius: 50%;
1442 border: 2px solid #fff;
1443 border-color: #fff transparent #fff transparent;
1444 animation: cn-spin 0.8s linear infinite;
1445 }
1446
1447 @keyframes cn-spin {
1448 0% {
1449 transform: rotate(0deg);
1450 }
1451 100% {
1452 transform: rotate(360deg);
1453 }
1454 }
1455
1456 @keyframes cn-fadeIn {
1457 from {
1458 opacity: 0;
1459 }
1460
1461 to {
1462 opacity: 1;
1463 }
1464 }
1465
1466 @keyframes cn-fadeOut {
1467 from {
1468 opacity: 1;
1469 }
1470
1471 to {
1472 opacity: 0;
1473 }
1474 }
1475
1476 @keyframes cn-slideIn {
1477 from {
1478 transform: translate3d(0, -100%, 0);
1479 visibility: visible;
1480 }
1481
1482 to {
1483 transform: translate3d(0, 0, 0);
1484 }
1485 }
1486
1487 @keyframes slideOut {
1488 from {
1489 transform: translate3d(0, 0, 0);
1490 }
1491
1492 to {
1493 visibility: hidden;
1494 transform: translate3d(0, -100%, 0);
1495 }
1496 }
1497
1498 .cn-sidebar.cn-theme-light {
1499 background: linear-gradient(-45deg, rgba(4,134,138,1), rgba(32,193,158,1));
1500 color: #fff;
1501 }
1502
1503 .cn-sidebar.cn-theme-light a,
1504 .cn-sidebar.cn-theme-light em {
1505 color: #fff;
1506 text-decoration: underline;
1507 }
1508
1509 .cn-sidebar.cn-theme-light a:hover,
1510 .cn-sidebar.cn-theme-light em:hover {
1511 text-decoration: none;
1512 }
1513
1514 .cn-sidebar.cn-theme-light .cn-btn:not(.cn-skip-button) {
1515 border-color: #fff;
1516 background-color: #fff;
1517 color: #191e23;
1518 }
1519
1520 .cn-sidebar.cn-theme-light .cn-btn:not(.cn-skip-button) .cn-spinner::after {
1521 border-color: #191e23 transparent #191e23 transparent;
1522 }
1523
1524 .cn-sidebar.cn-theme-light .cn-btn.cn-skip-button {
1525 color: rgba(255,255,255,0.5);
1526 }
1527
1528 .cn-sidebar.cn-theme-light .cn-btn.cn-skip-button:hover {
1529 color: rgba(255,255,255,1);
1530 }
1531
1532 .cn-sidebar.cn-theme-light #cn_iframe_preview {
1533 border-color: #fff;
1534 box-shadow: 0 0 10px 0 rgba(255,255,255,.3);
1535 }
1536
1537 .cn-sidebar.cn-theme-light form input[type="text"],
1538 .cn-sidebar.cn-theme-light form input[type="password"],
1539 .cn-sidebar.cn-theme-light form input[type="checkbox"],
1540 .cn-sidebar.cn-theme-light form input[type="radio"],
1541 .cn-sidebar.cn-theme-light form select {
1542 border-color: #fff;
1543 }
1544
1545 .cn-sidebar.cn-theme-light form .cn-checkbox-wrapper label,
1546 .cn-sidebar.cn-theme-light form .cn-radio-wrapper label {
1547 color: #fff;
1548 }
1549
1550 .cn-sidebar.cn-theme-light .cn-checkbox-image-wrapper input:checked + img,
1551 .cn-sidebar.cn-theme-light .cn-radio-image-wrapper input:checked + img {
1552 border-color: #fff;
1553 }
1554
1555 .cn-sidebar.cn-theme-light form .cn-checkbox-image-wrapper img,
1556 .cn-sidebar.cn-theme-light form .cn-radio-image-wrapper img {
1557 border-color: rgba(255,255,255,0.2);
1558 }
1559
1560 .cn-sidebar.cn-theme-light form .cn-radio-wrapper label input:checked::before {
1561 background-color: #fff;
1562 }
1563
1564 .cn-sidebar.cn-theme-light form input::placeholder,
1565 .cn-sidebar.cn-theme-light form select::placeholder {
1566 color: rgba(255,255,255,0.7);
1567 }
1568
1569 .cn-sidebar.cn-theme-light form input:focus,
1570 .cn-sidebar.cn-theme-light form select:focus {
1571 border-color: #fff;
1572 }
1573
1574 .cn-sidebar.cn-theme-light form .cn-plan-overlay {
1575 border-color: rgba(255,255,255,0.5);
1576 }
1577
1578 .cn-sidebar.cn-theme-light form .cn-plan-wrapper input:checked + span .cn-plan-overlay {
1579 border-color: rgba(255,255,255,1);
1580 background-color: rgba(255,255,255,.2);
1581 }
1582
1583 .cn-sidebar.cn-theme-light .cn-form-container {
1584 background: rgba(0,0,0,0.1);
1585 border: 1px solid rgba(255,255,255,.3);
1586 transition: all 0.2s;
1587 }
1588
1589 .cn-sidebar.cn-theme-light .cn-form-container.cn-collapsed {
1590 border-color: rgba(255,255,255,0);
1591 }
1592
1593 .cn-accordion .cn-accordion-item {
1594 overflow: hidden;
1595 border: 1px solid rgba(255,255,255,0.05);
1596 transition: border-color 0.2s;
1597 }
1598
1599 .cn-accordion .cn-accordion-item:focus {
1600 border-color: #20C19E;
1601 }
1602
1603 .cn-accordion .cn-accordion-item:not(:last-child) {
1604 margin-bottom: 0.5em;
1605 }
1606
1607 .cn-accordion .cn-accordion-item.cn-disabled {
1608 pointer-events: none;
1609 }
1610
1611 .cn-accordion .cn-accordion-item.cn-hidden {
1612 visibility: hidden;
1613 }
1614
1615 .cn-accordion .cn-accordion-item.cn-collapsed .cn-accordion-button {
1616 color: rgba(255,255,255,.7);
1617 }
1618
1619 .cn-accordion .cn-accordion-item.cn-collapsed .cn-accordion-button:hover {
1620 color: #fff;
1621 }
1622
1623 .cn-accordion .cn-accordion-button {
1624 text-align: left;
1625 font-size: 15px;
1626 font-style: normal;
1627 font-weight: bold;
1628 color: #fff;
1629 width: 100%;
1630 position: relative;
1631 border: none;
1632 outline: none;
1633 background: none;
1634 padding: 0;
1635 margin: 0;
1636 cursor: pointer;
1637 }
1638
1639 .cn-accordion .cn-accordion-button:hover {
1640 color: #fff;
1641 }
1642
1643 /*
1644 .cn-accordion .cn-accordion-button:after {
1645 font-family: dashicons;
1646 line-height: 1;
1647 font-weight: 400;
1648 font-style: normal;
1649 text-transform: none;
1650 text-rendering: auto;
1651 font-size: 18px;
1652 text-align: center;
1653 display: block;
1654 content: "\f347";
1655 position: absolute;
1656 top: 50%;
1657 margin-top: -9px;
1658 right: 0;
1659 line-height: 1;
1660 pointer-events: none;
1661 color: #fff;
1662 transform: rotate(180deg);
1663 transition: all 0.3s ease-in-out;
1664 }
1665
1666 .cn-accordion .cn-collapsed .cn-accordion-button:after {
1667 transform: rotate(0);
1668 }*/
1669
1670 .cn-accordion .cn-accordion-collapse {
1671 overflow-y: hidden;
1672 max-height: 1000px; /* approximate max height */
1673
1674 transition-property: all;
1675 transition-duration: .3s;
1676 transition-timing-function: ease-in-out;
1677 }
1678
1679 .cn-accordion .cn-accordion-collapse.cn-form {
1680 margin-bottom: 1.5em;
1681 }
1682
1683 .cn-accordion .cn-collapsed .cn-accordion-collapse {
1684 max-height: 0;
1685 margin-bottom: 0;
1686 }
1687
1688 #cn_card_number, #cn_expiration_date, #cn_cvv {
1689 background: transparent;
1690 border: 1px solid #86868F;
1691 border-radius: 3px;
1692 margin: 0;
1693 padding: 0 15px;
1694 color: #fff;
1695 transition: border-color 0.2s;
1696 height: 3em;
1697 box-shadow: none;
1698 }
1699
1700 #cn_card_number.braintree-hosted-fields-focused, #cn_expiration_date.braintree-hosted-fields-focused, #cn_cvv.braintree-hosted-fields-focused {
1701 border-color: #20C19E;
1702 background-color: transparent;
1703 box-shadow: none;
1704 }
1705
1706 #cn_card_number.braintree-hosted-fields-invalid, #cn_expiration_date.braintree-hosted-fields-invalid, #cn_cvv.braintree-hosted-fields-invalid {
1707 border-color: #DA2439;
1708 background-color: transparent;
1709 box-shadow: none;
1710 }
1711
1712 #cn_card_number.braintree-hosted-fields-valid {
1713 color: #fff;
1714 }
1715
1716 /* Loader */
1717
1718 .cn-welcome-wrap .has-loader:before {
1719 display: block;
1720 content: '';
1721 background: rgba(255,255,255,0);
1722 transition: all 0.2s;
1723 position: absolute;
1724 width: 100%;
1725 height: 100%;
1726 z-index: -1;
1727 }
1728 .cn-welcome-wrap .has-loader.cn-loading:before {
1729 /* background: rgba(32,193,158,.2); */
1730 background: rgba(255,255,255,.2);
1731 z-index: 99;
1732 }
1733
1734 .cn-welcome-wrap .has-loader > .cn-spinner {
1735 position: absolute;
1736 top: 50%;
1737 left: 50%;
1738 width: 21px;
1739 height: 21px;
1740 z-index: 100;
1741 }
1742
1743 .cn-welcome-wrap .has-loader > .cn-spinner:after {
1744 border: 3px solid #20C19E;
1745 border-color: #20C19E transparent #20C19E transparent;
1746 width: 21px;
1747 height: 21px;
1748 border-radius: 50%;
1749 opacity: 0;
1750 transition: all 0.3s;
1751 }
1752
1753 .cn-welcome-wrap .has-loader.cn-loading > .cn-spinner {
1754 max-width: 21px;
1755 opacity: 1;
1756 }
1757
1758 .cn-welcome-wrap .has-loader.cn-loading > .cn-spinner:after {
1759 opacity: 1;
1760 }
1761
1762 /* Progressbar */
1763
1764 .cn-welcome-wrap .cn-compliance-check {
1765 width: 100%;
1766 margin: 0 0 10px 0;
1767 }
1768
1769 .cn-welcome-wrap .cn-compliance-feedback {
1770 position: relative;
1771 margin-bottom: 1.5em;
1772 color: #fff;
1773 overflow-y: hidden;
1774 max-height: 500px; /* approximate max height */
1775 transition: all .3s cubic-bezier(0, 1, 0.5, 1);
1776 transition-delay: 0.3s;
1777 opacity: 1;
1778 }
1779
1780 .cn-welcome-wrap .cn-compliance-feedback p {
1781 padding: 15px;
1782 margin: 0;
1783 }
1784
1785 .cn-welcome-wrap .cn-compliance-feedback p.cn-error {
1786 border: 1px solid #da2439;
1787 border-radius: 3px;
1788 background: rgba( 218,36,57, 0.5);
1789 }
1790
1791 .cn-welcome-wrap .cn-compliance-feedback p.cn-error a {
1792 color: inherit;
1793 text-decoration: underline;
1794 }
1795
1796 .cn-welcome-wrap .cn-compliance-feedback p.cn-warning {
1797 border: 1px solid #e78d26;
1798 border-radius: 3px;
1799 background: rgba( 231,141,38, 0.5);
1800 }
1801
1802 .cn-welcome-wrap .cn-compliance-feedback p.cn-message {
1803 border: 1px solid #008000;
1804 border-radius: 3px;
1805 background: rgba( 0,128,0, 0.5);
1806 }
1807
1808 .cn-welcome-wrap .cn-compliance-feedback.cn-hidden {
1809 max-height: 0;
1810 margin-bottom: 0;
1811 opacity: 0;
1812 }
1813
1814 .cn-welcome-wrap .cn-compliance-feedback em {
1815 font-size: 15px;
1816 font-weight: bold;
1817 display: block;
1818 margin-bottom: 10px;
1819 color: inherit;
1820 }
1821
1822 .cn-welcome-wrap .cn-progressbar {
1823 height: 26px;
1824 margin: 0 0 20px;
1825 width: 100%;
1826 position: relative;
1827 }
1828
1829 .cn-welcome-wrap .cn-compliance-results .cn-compliance-item:not(:first-child) {
1830 margin-top: 10px;
1831 }
1832
1833 .cn-welcome-wrap .cn-compliance-results .cn-compliance-item p {
1834 display: flex;
1835 justify-content: space-between;
1836 margin: 0;
1837 }
1838
1839 .cn-welcome-wrap .cn-compliance-results .cn-compliance-item p:first-child {
1840 font-size: 15px;
1841 color: #fff;
1842 }
1843
1844 .cn-welcome-wrap .cn-compliance-results .cn-compliance-item p:last-child {
1845 }
1846
1847 .cn-welcome-wrap .cn-compliance-results .cn-compliance-label {
1848 }
1849
1850 .cn-welcome-wrap .cn-compliance-info {
1851 font-size: 15px;
1852 line-height: inherit;
1853 opacity: 0.5;
1854 cursor: pointer;
1855 }
1856
1857 .cn-welcome-wrap .cn-compliance-results .cn-compliance-status.cn-failed {
1858 color: red;
1859 }
1860
1861 .cn-welcome-wrap .cn-compliance-results .cn-compliance-status.cn-passed {
1862 color: #20C19E;
1863 }
1864
1865 .cn-welcome-wrap .cn-progress-label {
1866 position: absolute;
1867 left: 50%;
1868 transform: translateX(-50%);
1869 font-size: 14px;
1870 font-weight: bold;
1871 top: 3px;
1872 color: #fff;
1873 }
1874
1875 .cn-welcome-wrap .ui-progressbar {
1876 background: rgba(255,255,255,0.1);
1877 border-radius: 3px;
1878 }
1879
1880 .cn-welcome-wrap .ui-progressbar .ui-progressbar-value {
1881 background: #20C19E;
1882 height: 100%;
1883 border: 0 none;
1884 border-radius: 3px;
1885 margin: 3px 0;
1886 color: #fff;
1887 text-align: center;
1888 float: left;
1889 height: 20px;
1890 line-height: 20px;
1891 font-size: 20px;
1892 width: 0;
1893 min-width: 0;
1894 -webkit-transition: width .5s ease;
1895 -o-transition: width .5s ease;
1896 transition: width .5s ease;
1897 }
1898
1899 /* Modaal */
1900
1901 .cn-modal .modaal-content-container {
1902 padding: 0;
1903 }
1904
1905 .cn-modal .modaal-inner-wrapper {
1906 padding: 30px 30px 0;
1907 }
1908
1909 .modaal-overlay {
1910 z-index: 9998 !important;
1911 }
1912
1913 .cn-included,
1914 .cn-excluded {
1915 position: relative;
1916 }
1917
1918 .cn-included .cn-icon,
1919 .cn-excluded .cn-icon {
1920 box-sizing: border-box;
1921 position: absolute;
1922 left: 0;
1923 display: block;
1924 transform: scale(1);
1925 width: 22px;
1926 height: 22px;
1927 border: 2px solid;
1928 }
1929
1930 .cn-included .cn-icon {
1931 border-radius: 100px;
1932 color: #20C19E;
1933 }
1934
1935 .cn-included b {
1936 color: #20C19E;
1937 }
1938
1939 .cn-included .cn-icon::after {
1940 content: "";
1941 display: block;
1942 box-sizing: border-box;
1943 position: absolute;
1944 left: 3px;
1945 top: -1px;
1946 width: 6px;
1947 height: 10px;
1948 border-color: #20C19E;
1949 border-width: 0 2px 2px 0;
1950 border-style: solid;
1951 transform-origin: bottom left;
1952 transform: rotate(45deg);
1953 }
1954
1955 .cn-excluded .cn-icon {
1956 border-radius: 40px;
1957 color: #FF0000;
1958 }
1959
1960 .cn-excluded b {
1961 color: #FF0000;
1962 }
1963
1964 .cn-excluded .cn-icon::after,
1965 .cn-excluded .cn-icon::before {
1966 content: "";
1967 display: block;
1968 box-sizing: border-box;
1969 position: absolute;
1970 width: 12px;
1971 height: 2px;
1972 background: #FF0000;
1973 transform: rotate(45deg);
1974 border-radius: 5px;
1975 top: 8px;
1976 left: 3px;
1977 }
1978
1979 .cn-excluded .cn-icon::after {
1980 transform: rotate(-45deg);
1981 }
...\ No newline at end of file ...\ No newline at end of file
1 .cookie-notice-sidebar {
2 float:right;
3 width:280px;
4 margin:20px -300px 20px 20px;
5 position:relative
6 }
7 .cookie-notice-sidebar .inner {
8 padding:2em
9 }
10 .cookie-notice-sidebar>div:not(:last-child) {
11 margin-bottom:3em
12 }
13 .cookie-notice-sidebar .inner img {
14 max-width:80%;
15 height:auto;
16 display:block;
17 margin:20px auto
18 }
19 .cookie-notice-credits {
20 background:#fff;
21 box-shadow:0 0 0 1px rgba(0,0,0,.05)
22 }
23 .cookie-notice-credits .inner {
24 text-align:center;
25 margin:0
26 }
27 .button.cn-button {
28 background-color:#20c19e;
29 border-color:#20c19e
30 }
31 .button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover {
32 background-color:#1ca98a;
33 border-color:#1ca98a
34 }
35 .button.cn-button:focus {
36 box-shadow:0 0 0 1px #fff,0 0 0 3px #20c19e
37 }
38 .button.button-secondary.cn-button {
39 background-color:#ffc107;
40 border-color:#ffc107;
41 color:#3c434a
42 }
43 .button.button-secondary.cn-button:active,
44 .button.button-secondary.cn-button:focus,
45 .button.button-secondary.cn-button:hover {
46 background-color:#ffca2c;
47 border-color:#ffca2c
48 }
49 .button.button-secondary.cn-button:focus {
50 box-shadow:0 0 0 1px #fff,0 0 0 3px #ffc107
51 }
52 .cookie-notice-settings .cookie-notice-credits h2 {
53 border:none;
54 padding-bottom:0;
55 margin-top: 0;
56 }
57 .cookie-notice-credits h3 {
58 font-size:14px;
59 line-height:1.4;
60 margin:0;
61 padding:.66em 1.33em;
62 border-bottom:1px solid #eee
63 }
64 .cookie-notice-settings .df-credits form {
65 min-width:260px;
66 margin-bottom:1em
67 }
68 .cookie-notice-settings .df-credits form input {
69 margin:0;
70 padding:0
71 }
72 .cookie-notice-settings {
73 margin-right:300px
74 }
75 .cookie-notice-settings hr,.df-credits hr {
76 border:solid #eee;
77 border-width:1px 0 0;
78 clear:both;
79 height:0
80 }
81 .cookie-notice-settings form {
82 float:left;
83 min-width:463px;
84 width:100%
85 }
86 .cookie-notice-settings form.cn-options-disabled h2:not(:first-of-type),
87 .cookie-notice-settings form.cn-options-disabled table:not(:first-of-type),
88 form.cn-options-submit-disabled .submit {
89 opacity: 0.5;
90 pointer-events: none;
91 }
92 .cookie-notice-settings form h2 {
93 margin:1.5em 0;
94 padding-bottom:1em;
95 border-bottom:1px solid #ccc
96 }
97 .cookie-notice-settings .ui-button {
98 margin-bottom:5px
99 }
100 .cookie-notice-settings .description {
101 font-size:13px;
102 margin-bottom:8px
103 }
104 .cookie-notice-settings .description strong {
105 color:#444
106 }
107 #cn_colors label {
108 min-width:10em;
109 display:inline-block
110 }
111 #cn_colors div {
112 vertical-align:middle
113 }
114 #cn_refuse_code .nav-tab-wrapper {
115 padding-top:0
116 }
117 #cn_refuse_code .refuse-code-tab {
118 display:none
119 }
120 #cn_refuse_code .refuse-code-tab.active {
121 display:block
122 }
123 #cn_refuse_code .refuse-code-tab .description {
124 margin-top:10px
125 }
126 .cn_compliance_status {
127 margin-right:20px;
128 font-weight:700;
129 display:inline-block;
130 }
131 #cn_app_status {
132 margin-bottom:30px
133 }
134 #cn_app_status .cn-status {
135 text-transform:uppercase;
136 font-weight:700;
137 position:relative;
138 color:#999;
139 }
140 #cn_app_status .cn-status.cn-active {
141 color:#1ca98a
142 }
143 #cn_app_status .cn-status.cn-inactive {
144 color:red
145 }
146 #cn_colors_bar_opacity_range {
147 vertical-align:middle;
148 margin-right:10px
149 }
150 .cn-toggle-container .cn-toggle-item {
151 font-size:14px;
152 display:block;
153 margin-bottom:20px;
154 cursor:default
155 }
156 .cn-toggle-container .cn-toggle-item input {
157 display:none
158 }
159 .cn-toggle-container .cn-toggle-item span {
160 display:block
161 }
162 .cn-toggle-container .cn-toggle-item .cn-toggle-heading {
163 color:#2271b1;
164 transition-property:border,background,color;
165 transition-duration:.05s;
166 transition-timing-function:ease-in-out;
167 text-decoration:underline;
168 font-weight:600;
169 cursor:pointer;
170 position: relative;
171 padding-left: 20px;
172 }
173 .cn-toggle-container .cn-toggle-item .cn-toggle-heading:before {
174 border-style: solid;
175 border-width: 2px 2px 0 0;
176 content: '';
177 display: inline-block;
178 height: 6px;
179 width: 6px;
180 position: relative;
181 top: 5px;
182 left: 0;
183 vertical-align: top;
184 transform: rotate(45deg);
185 transition: transform 0.2s;
186 position: absolute;
187 }
188 .cn-toggle-container .cn-toggle-item .cn-toggle-body {
189 overflow:hidden;
190 transition:max-height .3s;
191 max-height:0;
192 margin-top:10px;
193 cursor:default;
194 padding-left: 20px;
195 }
196 .cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before {
197 transform: rotate(135deg);
198 }
199 .cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body {
200 max-height:100vh
201 }
202
203 .cn_fieldset_content {
204 margin-top: 10px;
205 }
206
207 @media only screen and (max-width:959px) {
208 .cookie-notice-sidebar {
209 width:100%;
210 float:none;
211 margin:20px 0
212 }
213 .cookie-notice-settings {
214 margin-right:0
215 }
216 }
217
218 .cn-pricing-info .cn-pricing-head h2 {
219 font-size: 23px;
220 font-weight: normal;
221 margin: 1em 0;
222 }
223
224 .cn-pricing-info .cn-pricing-body {
225 padding-bottom: 0;
226 font-size: 14px;
227 text-align: left;
228 margin: 2em 0;
229 }
230
231 .cn-pricing-info .cn-pricing-footer {
232 margin: 1em 0;
233 }
234
235 .cn-pricing-info div.cn-pricing-body p {
236 padding-left: 30px;
237 margin: 0.75em 0;
238 }
239
240 .cn-pricing-info div.cn-pricing-body .cn-icon {
241 position: absolute;
242 top: 0;
243 left: 0;
244 }
245
246 .cn-active,
247 .cn-inactive,
248 .cn-pending {
249 position: relative;
250 }
251
252 .cn-active .cn-icon,
253 .cn-inactive .cn-icon,
254 .cn-pending .cn-icon {
255 box-sizing: border-box;
256 position: relative;
257 left: 0;
258 top: 5px;
259 display: inline-block;
260 transform: scale(1);
261 width: 22px;
262 height: 22px;
263 border: 2px solid;
264 border-radius: 44px;
265 }
266
267 .cn-active .cn-icon {
268 color: #20C19E;
269 }
270
271 .cn-active .cn-icon::after {
272 border-color: #20C19E;
273 }
274
275 .cn-pending .cn-icon::after {
276 border-color: #999;
277 }
278
279 .cn-active .cn-icon::after,
280 .cn-pending .cn-icon::after {
281 content: "";
282 display: block;
283 box-sizing: border-box;
284 position: absolute;
285 left: 3px;
286 top: -1px;
287 width: 6px;
288 height: 10px;
289 border-width: 0 2px 2px 0;
290 border-style: solid;
291 transform-origin: bottom left;
292 transform: rotate(45deg);
293 }
294
295 .cn-inactive .cn-icon {
296 color: #FF0000;
297 }
298
299 .cn-inactive .cn-icon::after,
300 .cn-inactive .cn-icon::before {
301 content: "";
302 display: block;
303 box-sizing: border-box;
304 position: absolute;
305 width: 12px;
306 height: 2px;
307 background: #FF0000;
308 transform: rotate(45deg);
309 border-radius: 5px;
310 top: 8px;
311 left: 3px;
312 }
313
314 .cn-inactive .cn-icon::after {
315 transform: rotate(-45deg);
316 }
317
318 .cn-option-disabled label {
319 opacity: 0.5;
320 pointer-events: none;
321 }
322
323 .cn-warning {
324 color: #ffc107;
325 }
326
327 #cookie-notice-conditions .inside {
328 padding: 0;
329 margin: 6px 0;
330 }
331
332 #cookie-notice-conditions .widefat {
333 border: none;
334 box-shadow: none;
335 background: none;
336 }
337
338 #cookie-notice-conditions .widefat td.label {
339 width: 25%;
340 }
341
342 #cookie-notice-conditions .widefat h4 {
343 margin: 8px 0;
344 }
345
346 #cookie-notice-conditions .widefat h4.or-rules {
347 margin: 0 5px 0 0;
348 }
349
350 #cookie-notice-conditions .widefat td, #cookie-notice-conditions .widefat th {
351 padding: 0;
352 }
353
354 #cookie-notice-conditions .widefat .widefat {
355 margin-bottom: 0;
356 }
357
358 #cookie-notice-conditions .widefat .widefat td {
359 padding: 5px;
360 }
361
362 #cookie-notice-conditions .widefat .widefat td.param {
363 width: 30%;
364 padding-left: 0;
365 }
366
367 #cookie-notice-conditions .widefat .widefat td.value {
368 width: 30%;
369 text-align: center;
370 }
371
372 #cookie-notice-conditions .widefat .widefat td.value .spinner {
373 float: none;
374 margin: 0;
375 }
376
377 #cookie-notice-conditions .widefat .widefat td.operator {
378 width: 20%;
379 }
380
381 #cookie-notice-conditions .widefat .widefat td.remove {
382 min-width: 40px;
383 text-align: left;
384 padding: 0;
385 }
386
387 #cookie-notice-conditions .widefat .widefat td.remove a {
388 vertical-align: middle;
389 }
390
391 #cookie-notice-conditions .widefat .widefat select {
392 width: 98.95%;
393 }
394
395 #cookie-notice-conditions #rules-groups {
396 margin-bottom: 10px;
397 }
398
399 #cookie-notice-conditions .rules-group:last-child .or-rules,
400 #cookie-notice-conditions .rules-group:only-child .or-rules {
401 display: none;
402 }
...\ No newline at end of file ...\ No newline at end of file
1 .cookie-notice-sidebar{float:right;width:280px;margin:20px -300px 20px 20px;position:relative}.cookie-notice-sidebar .inner{padding:2em}.cookie-notice-sidebar>div:not(:last-child){margin-bottom:3em}.cookie-notice-sidebar .inner img{max-width:80%;height:auto;display:block;margin:20px auto}.cookie-notice-credits{background:#fff;box-shadow:0 0 0 1px rgba(0,0,0,.05)}.cookie-notice-credits .inner{text-align:center;margin:0}.button.cn-button{background-color:#20c19e;border-color:#20c19e}.button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover{background-color:#1ca98a;border-color:#1ca98a}.button.cn-button:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #20c19e}.button.button-secondary.cn-button{background-color:#ffc107;border-color:#ffc107;color:#3c434a}.button.button-secondary.cn-button:active,.button.button-secondary.cn-button:focus,.button.button-secondary.cn-button:hover{background-color:#ffca2c;border-color:#ffca2c}.button.button-secondary.cn-button:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #ffc107}.cookie-notice-settings .cookie-notice-credits h2{border:none;padding-bottom:0;margin-top:0}.cookie-notice-credits h3{font-size:14px;line-height:1.4;margin:0;padding:.66em 1.33em;border-bottom:1px solid #eee}.cookie-notice-settings .df-credits form{min-width:260px;margin-bottom:1em}.cookie-notice-settings .df-credits form input{margin:0;padding:0}.cookie-notice-settings{margin-right:300px}.cookie-notice-settings hr,.df-credits hr{border:solid #eee;border-width:1px 0 0;clear:both;height:0}.cookie-notice-settings form{float:left;min-width:463px;width:100%}.cookie-notice-settings form.cn-options-disabled h2:not(:first-of-type),.cookie-notice-settings form.cn-options-disabled table:not(:first-of-type),form.cn-options-submit-disabled .submit{opacity:.5;pointer-events:none}.cookie-notice-settings form h2{margin:1.5em 0;padding-bottom:1em;border-bottom:1px solid #ccc}.cookie-notice-settings .ui-button{margin-bottom:5px}.cookie-notice-settings .description{font-size:13px;margin-bottom:8px}.cookie-notice-settings .description strong{color:#444}#cn_colors label{min-width:10em;display:inline-block}#cn_colors div{vertical-align:middle}#cn_refuse_code .nav-tab-wrapper{padding-top:0}#cn_refuse_code .refuse-code-tab{display:none}#cn_refuse_code .refuse-code-tab.active{display:block}#cn_refuse_code .refuse-code-tab .description{margin-top:10px}.cn_compliance_status{margin-right:20px;font-weight:700;display:inline-block}#cn_app_status{margin-bottom:30px}#cn_app_status .cn-status{text-transform:uppercase;font-weight:700;position:relative;color:#999}#cn_app_status .cn-status.cn-active{color:#1ca98a}#cn_app_status .cn-status.cn-inactive{color:red}#cn_colors_bar_opacity_range{vertical-align:middle;margin-right:10px}.cn-toggle-container .cn-toggle-item{font-size:14px;display:block;margin-bottom:20px;cursor:default}.cn-toggle-container .cn-toggle-item input{display:none}.cn-toggle-container .cn-toggle-item span{display:block}.cn-toggle-container .cn-toggle-item .cn-toggle-heading{color:#2271b1;transition-property:border,background,color;transition-duration:.05s;transition-timing-function:ease-in-out;text-decoration:underline;font-weight:600;cursor:pointer;position:relative;padding-left:20px}.cn-toggle-container .cn-toggle-item .cn-toggle-heading:before{border-style:solid;border-width:2px 2px 0 0;content:'';display:inline-block;height:6px;width:6px;position:relative;top:5px;left:0;vertical-align:top;transform:rotate(45deg);transition:transform 0.2s;position:absolute}.cn-toggle-container .cn-toggle-item .cn-toggle-body{overflow:hidden;transition:max-height .3s;max-height:0;margin-top:10px;cursor:default;padding-left:20px}.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before{transform:rotate(135deg)}.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body{max-height:100vh}.cn_fieldset_content{margin-top:10px}@media only screen and (max-width:959px){.cookie-notice-sidebar{width:100%;float:none;margin:20px 0}.cookie-notice-settings{margin-right:0}}.cn-pricing-info .cn-pricing-head h2{font-size:23px;font-weight:400;margin:1em 0}.cn-pricing-info .cn-pricing-body{padding-bottom:0;font-size:14px;text-align:left;margin:2em 0}.cn-pricing-info .cn-pricing-footer{margin:1em 0}.cn-pricing-info div.cn-pricing-body p{padding-left:30px;margin:.75em 0}.cn-pricing-info div.cn-pricing-body .cn-icon{position:absolute;top:0;left:0}.cn-active,.cn-inactive,.cn-pending{position:relative}.cn-active .cn-icon,.cn-inactive .cn-icon,.cn-pending .cn-icon{box-sizing:border-box;position:relative;left:0;top:5px;display:inline-block;transform:scale(1);width:22px;height:22px;border:2px solid;border-radius:44px}.cn-active .cn-icon{color:#20C19E}.cn-active .cn-icon::after{border-color:#20C19E}.cn-pending .cn-icon::after{border-color:#999}.cn-active .cn-icon::after,.cn-pending .cn-icon::after{content:"";display:block;box-sizing:border-box;position:absolute;left:3px;top:-1px;width:6px;height:10px;border-width:0 2px 2px 0;border-style:solid;transform-origin:bottom left;transform:rotate(45deg)}.cn-inactive .cn-icon{color:red}.cn-inactive .cn-icon::after,.cn-inactive .cn-icon::before{content:"";display:block;box-sizing:border-box;position:absolute;width:12px;height:2px;background:red;transform:rotate(45deg);border-radius:5px;top:8px;left:3px}.cn-inactive .cn-icon::after{transform:rotate(-45deg)}.cn-option-disabled label{opacity:.5;pointer-events:none}.cn-warning{color:#ffc107}#cookie-notice-conditions .inside{padding:0;margin:6px 0}#cookie-notice-conditions .widefat{border:none;box-shadow:none;background:none}#cookie-notice-conditions .widefat td.label{width:25%}#cookie-notice-conditions .widefat h4{margin:8px 0}#cookie-notice-conditions .widefat h4.or-rules{margin:0 5px 0 0}#cookie-notice-conditions .widefat td,#cookie-notice-conditions .widefat th{padding:0}#cookie-notice-conditions .widefat .widefat{margin-bottom:0}#cookie-notice-conditions .widefat .widefat td{padding:5px}#cookie-notice-conditions .widefat .widefat td.param{width:30%;padding-left:0}#cookie-notice-conditions .widefat .widefat td.value{width:30%;text-align:center}#cookie-notice-conditions .widefat .widefat td.value .spinner{float:none;margin:0}#cookie-notice-conditions .widefat .widefat td.operator{width:20%}#cookie-notice-conditions .widefat .widefat td.remove{min-width:40px;text-align:left;padding:0}#cookie-notice-conditions .widefat .widefat td.remove a{vertical-align:middle}#cookie-notice-conditions .widefat .widefat select{width:98.95%}#cookie-notice-conditions #rules-groups{margin-bottom:10px}#cookie-notice-conditions .rules-group:last-child .or-rules,#cookie-notice-conditions .rules-group:only-child .or-rules{display:none}
...\ No newline at end of file ...\ No newline at end of file
1 #cookie-notice {
2 position: fixed;
3 min-width: 100%;
4 height: auto;
5 z-index: 100000;
6 font-size: 13px;
7 letter-spacing: 0;
8 line-height: 20px;
9 left: 0;
10 text-align: center;
11 /* border-top: 2px solid #fbb03b; */
12 font-weight: normal;
13 font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
14 }
15 #cookie-notice,
16 #cookie-notice * {
17 -webkit-box-sizing: border-box;
18 -moz-box-sizing: border-box;
19 box-sizing: border-box;
20 }
21 #cookie-notice.cn-animated {
22 -webkit-animation-duration: 0.5s !important;
23 animation-duration: 0.5s !important;
24 -webkit-animation-fill-mode: both;
25 animation-fill-mode: both;
26 }
27 #cookie-notice.cn-animated.cn-effect-none {
28 -webkit-animation-duration: 0.001s !important;
29 animation-duration: 0.001s !important;
30 }
31 #cookie-notice .cookie-notice-container {
32 display: block;
33 }
34 #cookie-notice.cookie-notice-hidden .cookie-notice-container {
35 display: none;
36 }
37 #cookie-notice .cookie-revoke-container {
38 display: block;
39 }
40 #cookie-notice.cookie-revoke-hidden .cookie-revoke-container {
41 display: none;
42 }
43 .cn-position-top {
44 top: 0;
45 }
46 .cn-position-bottom {
47 bottom: 0;
48 }
49 .cookie-notice-container {
50 padding: 15px 30px;
51 text-align: center;
52 width: 100%;
53 z-index: 2;
54 }
55 .cookie-revoke-container {
56 padding: 15px 30px;
57 width: 100%;
58 z-index: 1;
59 }
60 .cn-close-icon {
61 position: absolute;
62 right: 15px;
63 top: 50%;
64 margin-top: -10px;
65 width: 15px;
66 height: 15px;
67 opacity: 0.5;
68 padding: 10px;
69 outline: none;
70 cursor: pointer;
71 }
72 .cn-close-icon:hover {
73 opacity: 1;
74 }
75 .cn-close-icon:before,
76 .cn-close-icon:after {
77 position: absolute;
78 content: ' ';
79 height: 15px;
80 width: 2px;
81 top: 3px;
82 background-color: rgba(128,128,128,1);
83 }
84 .cn-close-icon:before {
85 transform: rotate(45deg);
86 }
87 .cn-close-icon:after {
88 transform: rotate(-45deg);
89 }
90 #cookie-notice .cn-revoke-cookie {
91 margin: 0;
92 }
93 #cookie-notice .cn-button {
94 margin: 0 0 0 10px;
95 display: inline-block;
96 }
97 #cookie-notice .cn-button:not(.cn-button-custom) {
98 font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
99 font-weight: normal;
100 font-size: 13px;
101 letter-spacing: 0.25px;
102 line-height: 20px;
103 margin: 0 0 0 10px;
104 text-align: center;
105 text-transform: none;
106 display: inline-block;
107 cursor: pointer;
108 touch-action: manipulation;
109 white-space: nowrap;
110 outline: none;
111 box-shadow: none;
112 text-shadow: none;
113 border: none;
114 -webkit-border-radius: 3px;
115 -moz-border-radius: 3px;
116 border-radius: 3px;
117 text-decoration: none;
118 padding: 8.5px 10px;
119 line-height: 1;
120 color: inherit;
121 }
122 .cn-text-container {
123 margin: 0 0 6px 0;
124 }
125 .cn-text-container,
126 .cn-buttons-container {
127 display: inline-block;
128 }
129 #cookie-notice.cookie-notice-visible.cn-effect-none,
130 #cookie-notice.cookie-revoke-visible.cn-effect-none {
131 -webkit-animation-name: fadeIn;
132 animation-name: fadeIn;
133 }
134 #cookie-notice.cn-effect-none {
135 -webkit-animation-name: fadeOut;
136 animation-name: fadeOut;
137 }
138 #cookie-notice.cookie-notice-visible.cn-effect-fade,
139 #cookie-notice.cookie-revoke-visible.cn-effect-fade {
140 -webkit-animation-name: fadeIn;
141 animation-name: fadeIn;
142 }
143 #cookie-notice.cn-effect-fade {
144 -webkit-animation-name: fadeOut;
145 animation-name: fadeOut;
146 }
147 #cookie-notice.cookie-notice-visible.cn-effect-slide,
148 #cookie-notice.cookie-revoke-visible.cn-effect-slide{
149 -webkit-animation-name: slideInUp;
150 animation-name: slideInUp;
151 }
152 #cookie-notice.cn-effect-slide {
153 -webkit-animation-name: slideOutDown;
154 animation-name: slideOutDown;
155 }
156 #cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,
157 #cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide {
158 -webkit-animation-name: slideInDown;
159 animation-name: slideInDown;
160 }
161 #cookie-notice.cn-position-top.cn-effect-slide {
162 -webkit-animation-name: slideOutUp;
163 animation-name: slideOutUp;
164 }
165 @-webkit-keyframes fadeIn {
166 from {
167 opacity: 0;
168 }
169
170 to {
171 opacity: 1;
172 }
173 }
174 @keyframes fadeIn {
175 from {
176 opacity: 0;
177 }
178
179 to {
180 opacity: 1;
181 }
182 }
183 @-webkit-keyframes fadeOut {
184 from {
185 opacity: 1;
186 }
187
188 to {
189 opacity: 0;
190 }
191 }
192 @keyframes fadeOut {
193 from {
194 opacity: 1;
195 }
196
197 to {
198 opacity: 0;
199 }
200 }
201 @-webkit-keyframes slideInUp {
202 from {
203 -webkit-transform: translate3d(0, 100%, 0);
204 transform: translate3d(0, 100%, 0);
205 visibility: visible;
206 }
207
208 to {
209 -webkit-transform: translate3d(0, 0, 0);
210 transform: translate3d(0, 0, 0);
211 }
212 }
213 @keyframes slideInUp {
214 from {
215 -webkit-transform: translate3d(0, 100%, 0);
216 transform: translate3d(0, 100%, 0);
217 visibility: visible;
218 }
219
220 to {
221 -webkit-transform: translate3d(0, 0, 0);
222 transform: translate3d(0, 0, 0);
223 }
224 }
225 @-webkit-keyframes slideOutDown {
226 from {
227 -webkit-transform: translate3d(0, 0, 0);
228 transform: translate3d(0, 0, 0);
229 }
230
231 to {
232 visibility: hidden;
233 -webkit-transform: translate3d(0, 100%, 0);
234 transform: translate3d(0, 100%, 0);
235 }
236 }
237 @keyframes slideOutDown {
238 from {
239 -webkit-transform: translate3d(0, 0, 0);
240 transform: translate3d(0, 0, 0);
241 }
242
243 to {
244 visibility: hidden;
245 -webkit-transform: translate3d(0, 100%, 0);
246 transform: translate3d(0, 100%, 0);
247 }
248 }
249 @-webkit-keyframes slideInDown {
250 from {
251 -webkit-transform: translate3d(0, -100%, 0);
252 transform: translate3d(0, -100%, 0);
253 visibility: visible;
254 }
255
256 to {
257 -webkit-transform: translate3d(0, 0, 0);
258 transform: translate3d(0, 0, 0);
259 }
260 }
261 @keyframes slideInDown {
262 from {
263 -webkit-transform: translate3d(0, -100%, 0);
264 transform: translate3d(0, -100%, 0);
265 visibility: visible;
266 }
267
268 to {
269 -webkit-transform: translate3d(0, 0, 0);
270 transform: translate3d(0, 0, 0);
271 }
272 }
273 @-webkit-keyframes slideOutUp {
274 from {
275 -webkit-transform: translate3d(0, 0, 0);
276 transform: translate3d(0, 0, 0);
277 }
278
279 to {
280 visibility: hidden;
281 -webkit-transform: translate3d(0, -100%, 0);
282 transform: translate3d(0, -100%, 0);
283 }
284 }
285 @keyframes slideOutUp {
286 from {
287 -webkit-transform: translate3d(0, 0, 0);
288 transform: translate3d(0, 0, 0);
289 }
290
291 to {
292 visibility: hidden;
293 -webkit-transform: translate3d(0, -100%, 0);
294 transform: translate3d(0, -100%, 0);
295 }
296 }
297 @media all and (max-width: 900px) {
298 .cookie-notice-container #cn-notice-text {
299 display: block;
300 }
301 .cookie-notice-container #cn-notice-buttons {
302 display: block;
303 }
304 #cookie-notice .cn-button {
305 margin: 0 5px 5px 5px;
306 }
307 }
308 @media all and (max-width: 480px) {
309 .cookie-notice-container,
310 .cookie-revoke-container {
311 padding: 15px 25px;
312 }
313 }
...\ No newline at end of file ...\ No newline at end of file
1 #cookie-notice{position:fixed;min-width:100%;height:auto;z-index:100000;font-size:13px;letter-spacing:0;line-height:20px;left:0;text-align:center;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif}#cookie-notice,#cookie-notice *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#cookie-notice.cn-animated{-webkit-animation-duration:0.5s!important;animation-duration:0.5s!important;-webkit-animation-fill-mode:both;animation-fill-mode:both}#cookie-notice.cn-animated.cn-effect-none{-webkit-animation-duration:0.001s!important;animation-duration:0.001s!important}#cookie-notice .cookie-notice-container{display:block}#cookie-notice.cookie-notice-hidden .cookie-notice-container{display:none}#cookie-notice .cookie-revoke-container{display:block}#cookie-notice.cookie-revoke-hidden .cookie-revoke-container{display:none}.cn-position-top{top:0}.cn-position-bottom{bottom:0}.cookie-notice-container{padding:15px 30px;text-align:center;width:100%;z-index:2}.cookie-revoke-container{padding:15px 30px;width:100%;z-index:1}.cn-close-icon{position:absolute;right:15px;top:50%;margin-top:-10px;width:15px;height:15px;opacity:.5;padding:10px;outline:none;cursor:pointer}.cn-close-icon:hover{opacity:1}.cn-close-icon:before,.cn-close-icon:after{position:absolute;content:' ';height:15px;width:2px;top:3px;background-color:rgba(128,128,128,1)}.cn-close-icon:before{transform:rotate(45deg)}.cn-close-icon:after{transform:rotate(-45deg)}#cookie-notice .cn-revoke-cookie{margin:0}#cookie-notice .cn-button{margin:0 0 0 10px;display:inline-block}#cookie-notice .cn-button:not(.cn-button-custom){font-family:-apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;font-weight:400;font-size:13px;letter-spacing:.25px;line-height:20px;margin:0 0 0 10px;text-align:center;text-transform:none;display:inline-block;cursor:pointer;touch-action:manipulation;white-space:nowrap;outline:none;box-shadow:none;text-shadow:none;border:none;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;text-decoration:none;padding:8.5px 10px;line-height:1;color:inherit}.cn-text-container{margin:0 0 6px 0}.cn-text-container,.cn-buttons-container{display:inline-block}#cookie-notice.cookie-notice-visible.cn-effect-none,#cookie-notice.cookie-revoke-visible.cn-effect-none{-webkit-animation-name:fadeIn;animation-name:fadeIn}#cookie-notice.cn-effect-none{-webkit-animation-name:fadeOut;animation-name:fadeOut}#cookie-notice.cookie-notice-visible.cn-effect-fade,#cookie-notice.cookie-revoke-visible.cn-effect-fade{-webkit-animation-name:fadeIn;animation-name:fadeIn}#cookie-notice.cn-effect-fade{-webkit-animation-name:fadeOut;animation-name:fadeOut}#cookie-notice.cookie-notice-visible.cn-effect-slide,#cookie-notice.cookie-revoke-visible.cn-effect-slide{-webkit-animation-name:slideInUp;animation-name:slideInUp}#cookie-notice.cn-effect-slide{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}#cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,#cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide{-webkit-animation-name:slideInDown;animation-name:slideInDown}#cookie-notice.cn-position-top.cn-effect-slide{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}@-webkit-keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeOut{from{opacity:1}to{opacity:0}}@keyframes fadeOut{from{opacity:1}to{opacity:0}}@-webkit-keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{from{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@-webkit-keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@-webkit-keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{from{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@-webkit-keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{from{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@media all and (max-width:900px){.cookie-notice-container #cn-notice-text{display:block}.cookie-notice-container #cn-notice-buttons{display:block}#cookie-notice .cn-button{margin:0 5px 5px 5px}}@media all and (max-width:480px){.cookie-notice-container,.cookie-revoke-container{padding:15px 25px}}
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 140 140" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;"><g><rect x="8.75" y="8.732" width="122.5" height="122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/><path d="M8.75,96.232l122.5,0" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/></g></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 140 140" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;"><g><rect x="8.75" y="8.733" width="122.5" height="122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/><rect x="39.375" y="39.349" width="61.25" height="61.268" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.8px;"/></g></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" viewBox="0 0 140 140" width="140" height="140"><g transform="matrix(5.833333333333333,0,0,5.833333333333333,0,0)"><path d="M1.500 1.497 L22.500 1.497 L22.500 22.497 L1.500 22.497 Z" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M7.5 1.497L7.5 22.497" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></g></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 140 140" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;"><g><rect x="8.75" y="8.733" width="122.5" height="122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/><path d="M96.25,8.733l0,122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/></g></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" viewBox="0 0 140 140" width="140" height="140"><g transform="matrix(5.833333333333333,0,0,5.833333333333333,0,0)"><path d="M1.500 1.497 L22.500 1.497 L22.500 22.497 L1.500 22.497 Z" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M1.5 7.497L22.5 7.497" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></g></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie_Notice_Bot_Detect class.
8 *
9 * Based on CrawlerDetect php class adjusted to PHP 5.2
10 * https://github.com/JayBizzle/Crawler-Detect/blob/master/src/CrawlerDetect.php
11 *
12 * @since 2.0.0
13 * @class Cookie_Notice_Bot_Detect
14 */
15 class Cookie_Notice_Bot_Detect {
16
17 /**
18 * The user agent.
19 *
20 * @var null
21 */
22 protected $user_agent = null;
23
24 /**
25 * Headers that contain a user agent.
26 *
27 * @var array
28 */
29 protected $http_headers = [];
30
31 /**
32 * Store regex matches.
33 *
34 * @var array
35 */
36 protected $matches = [];
37
38 /**
39 * Crawlers object.
40 *
41 * @var object
42 */
43 protected $crawlers = [];
44
45 /**
46 * Exclusions object.
47 *
48 * @var object
49 */
50 protected $exclusions = [];
51
52 /**
53 * Headers object.
54 *
55 * @var object
56 */
57 protected $ua_http_headers;
58
59 /**
60 * Class constructor.
61 *
62 * @return void
63 */
64 public function __construct() {
65 $this->crawlers = $this->get_crawlers_list();
66 $this->exclusions = $this->get_exclusions_list();
67
68 add_action( 'after_setup_theme', [ $this, 'init' ] );
69 }
70
71 /**
72 * Initialize class.
73 *
74 * @return void
75 */
76 public function init() {
77 // break on admin side
78 if ( is_admin() && ! wp_doing_ajax() )
79 return;
80
81 $this->ua_http_headers = $this->get_headers_list();
82 $this->set_http_headers();
83 $this->set_user_agent();
84 }
85
86 /**
87 * Set HTTP headers.
88 *
89 * @param array $http_headers
90 * @return void
91 */
92 public function set_http_headers( $http_headers = null ) {
93 // use global _SERVER if $http_headers aren't defined
94 if ( ! is_array( $http_headers ) || ! count( $http_headers ) )
95 $http_headers = $_SERVER;
96
97 // clear existing headers
98 $this->http_headers = [];
99
100 // only save HTTP headers - in PHP land, that means only _SERVER vars that start with HTTP_.
101 foreach ( $http_headers as $key => $value ) {
102 if ( substr( $key, 0, 5 ) === 'HTTP_' )
103 $this->http_headers[$key] = $value;
104 }
105 }
106
107 /**
108 * Return user agent headers.
109 *
110 * @return array
111 */
112 public function get_ua_http_headers() {
113 return $this->ua_http_headers;
114 }
115
116 /**
117 * Return the user agent.
118 *
119 * @return string
120 */
121 public function get_user_agent() {
122 return $this->user_agent;
123 }
124
125 /**
126 * Set the user agent.
127 *
128 * @param string $user_agent
129 * @return string
130 */
131 public function set_user_agent( $user_agent = null ) {
132 if ( false === empty( $user_agent ) )
133 return $this->user_agent = $user_agent;
134 else {
135 $this->user_agent = null;
136
137 foreach ( $this->get_ua_http_headers() as $alt_header ) {
138 if ( false === empty( $this->http_headers[$alt_header] ) ) // @todo: should use get_http_header(), but it would be slow.
139 $this->user_agent .= $this->http_headers[$alt_header] . ' ';
140 }
141
142 return $this->user_agent = ( ! empty( $this->user_agent ) ? trim( $this->user_agent ) : null );
143 }
144 }
145
146 /**
147 * Build the user agent regex.
148 *
149 * @return string
150 */
151 public function get_regex() {
152 return '(' . implode( '|', $this->crawlers ) . ')';
153 }
154
155 /**
156 * Build the replacement regex.
157 *
158 * @return string
159 */
160 public function get_exclusions() {
161 return '(' . implode( '|', $this->exclusions ) . ')';
162 }
163
164 /**
165 * Check user agent string against the regex.
166 *
167 * @param string $user_agent
168 * @return bool
169 */
170 public function is_crawler( $user_agent = null ) {
171 $agent = (string)( is_null( $user_agent ) ? $this->user_agent : $user_agent );
172 $agent = preg_replace( '/' . $this->get_exclusions() . '/i', '', $agent );
173
174 if ( strlen( trim( $agent ) ) === 0 )
175 return false;
176 else
177 $result = preg_match( '/' . $this->get_regex() . '/i', trim( $agent ), $matches );
178
179 if ( $matches )
180 $this->matches = $matches;
181
182 return (bool) $result;
183 }
184
185 /**
186 * Return the matches.
187 *
188 * @return string
189 */
190 public function get_matches() {
191 return isset( $this->matches[0] ) ? $this->matches[0] : null;
192 }
193
194 /**
195 * Return the regular expressions to match against the user agent.
196 *
197 * @return array
198 */
199 protected function get_crawlers_list() {
200 return [
201 ' YLT',
202 '^Aether',
203 '^Amazon Simple Notification Service Agent$',
204 '^Amazon-Route53-Health-Check-Service',
205 '^b0t$',
206 '^bluefish ',
207 '^Calypso v\/',
208 '^COMODO DCV',
209 '^Corax',
210 '^DangDang',
211 '^DavClnt',
212 '^DHSH',
213 '^docker\/[0-9]',
214 '^Expanse',
215 '^FDM ',
216 '^git\/',
217 '^Goose\/',
218 '^Grabber',
219 '^Gradle\/',
220 '^HTTPClient\/',
221 '^HTTPing',
222 '^Java\/',
223 '^Jeode\/',
224 '^Jetty\/',
225 '^Mail\/',
226 '^Mget',
227 '^Microsoft URL Control',
228 '^Mikrotik\/',
229 '^Netlab360',
230 '^NG\/[0-9\.]',
231 '^NING\/',
232 '^npm\/',
233 '^Nuclei',
234 '^PHP-AYMAPI\/',
235 '^PHP\/',
236 '^pip\/',
237 '^pnpm\/',
238 '^RMA\/',
239 '^Ruby|Ruby\/[0-9]',
240 '^Swurl ',
241 '^TLS tester ',
242 '^twine\/',
243 '^ureq',
244 '^VSE\/[0-9]',
245 '^WordPress\.com',
246 '^XRL\/[0-9]',
247 '^ZmEu',
248 '008\/',
249 '13TABS',
250 '192\.comAgent',
251 '2GDPR\/',
252 '2ip\.ru',
253 '404enemy',
254 '7Siters',
255 '80legs',
256 'a3logics\.in',
257 'A6-Indexer',
258 'Abonti',
259 'Aboundex',
260 'aboutthedomain',
261 'Accoona-AI-Agent',
262 'acebookexternalhit\/',
263 'acoon',
264 'acrylicapps\.com\/pulp',
265 'Acunetix',
266 'AdAuth\/',
267 'adbeat',
268 'AddThis',
269 'ADmantX',
270 'AdminLabs',
271 'adressendeutschland',
272 'adreview\/',
273 'adscanner',
274 'adstxt-worker',
275 'Adstxtaggregator',
276 'adstxt\.com',
277 'Adyen HttpClient',
278 'AffiliateLabz\/',
279 'affilimate-puppeteer',
280 'agentslug',
281 'AHC',
282 'aihit',
283 'aiohttp\/',
284 'Airmail',
285 'akka-http\/',
286 'akula\/',
287 'alertra',
288 'alexa site audit',
289 'Alibaba\.Security\.Heimdall',
290 'Alligator',
291 'allloadin',
292 'AllSubmitter',
293 'alyze\.info',
294 'amagit',
295 'Anarchie',
296 'AndroidDownloadManager',
297 'Anemone',
298 'AngleSharp',
299 'annotate_google',
300 'Anthill',
301 'Anturis Agent',
302 'Ant\.com',
303 'AnyEvent-HTTP\/',
304 'Apache Ant\/',
305 'Apache Droid',
306 'Apache OpenOffice',
307 'Apache-HttpAsyncClient',
308 'Apache-HttpClient',
309 'ApacheBench',
310 'Apexoo',
311 'apimon\.de',
312 'APIs-Google',
313 'AportWorm\/',
314 'AppBeat\/',
315 'AppEngine-Google',
316 'AppleSyndication',
317 'Aprc\/[0-9]',
318 'Arachmo',
319 'arachnode',
320 'Arachnophilia',
321 'aria2',
322 'Arukereso',
323 'asafaweb',
324 'Asana\/',
325 'Ask Jeeves',
326 'AskQuickly',
327 'ASPSeek',
328 'Asterias',
329 'Astute',
330 'asynchttp',
331 'Attach',
332 'attohttpc',
333 'autocite',
334 'AutomaticWPTester',
335 'Autonomy',
336 'awin\.com',
337 'AWS Security Scanner',
338 'axios\/',
339 'a\.pr-cy\.ru',
340 'B-l-i-t-z-B-O-T',
341 'Backlink-Ceck',
342 'backlink-check',
343 'BacklinkHttpStatus',
344 'BackStreet',
345 'BackupLand',
346 'BackWeb',
347 'Bad-Neighborhood',
348 'Badass',
349 'baidu\.com',
350 'Bandit',
351 'basicstate',
352 'BatchFTP',
353 'Battleztar Bazinga',
354 'baypup\/',
355 'BazQux',
356 'BBBike',
357 'BCKLINKS',
358 'BDFetch',
359 'BegunAdvertising',
360 'Bewica-security-scan',
361 'Bidtellect',
362 'BigBozz',
363 'Bigfoot',
364 'biglotron',
365 'BingLocalSearch',
366 'BingPreview',
367 'binlar',
368 'biNu image cacher',
369 'Bitacle',
370 'Bitrix link preview',
371 'biz_Directory',
372 'BKCTwitterUnshortener\/',
373 'Black Hole',
374 'Blackboard Safeassign',
375 'BlackWidow',
376 'BlockNote\.Net',
377 'BlogBridge',
378 'Bloglines',
379 'Bloglovin',
380 'BlogPulseLive',
381 'BlogSearch',
382 'Blogtrottr',
383 'BlowFish',
384 'boitho\.com-dc',
385 'Boost\.Beast',
386 'BPImageWalker',
387 'Braintree-Webhooks',
388 'Branch Metrics API',
389 'Branch-Passthrough',
390 'Brandprotect',
391 'BrandVerity',
392 'Brandwatch',
393 'Brodie\/',
394 'Browsershots',
395 'BUbiNG',
396 'Buck\/',
397 'Buddy',
398 'BuiltWith',
399 'Bullseye',
400 'BunnySlippers',
401 'Burf Search',
402 'Butterfly\/',
403 'BuzzSumo',
404 'CAAM\/[0-9]',
405 'CakePHP',
406 'Calculon',
407 'Canary%20Mail',
408 'CaretNail',
409 'catexplorador',
410 'CC Metadata Scaper',
411 'Cegbfeieh',
412 'censys',
413 'centuryb.o.t9[at]gmail.com',
414 'Cerberian Drtrs',
415 'CERT\.at-Statistics-Survey',
416 'cf-facebook',
417 'cg-eye',
418 'changedetection',
419 'ChangesMeter',
420 'Charlotte',
421 'chatterino-api-cache',
422 'CheckHost',
423 'checkprivacy',
424 'CherryPicker',
425 'ChinaClaw',
426 'Chirp\/',
427 'chkme\.com',
428 'Chlooe',
429 'Chromaxa',
430 'CirrusExplorer',
431 'CISPA Vulnerability Notification',
432 'CISPA Web Analyser',
433 'Citoid',
434 'CJNetworkQuality',
435 'Clarsentia',
436 'clips\.ua\.ac\.be',
437 'Cloud mapping',
438 'CloudEndure',
439 'CloudFlare-AlwaysOnline',
440 'Cloudflare-Healthchecks',
441 'Cloudinary',
442 'cmcm\.com',
443 'coccoc',
444 'cognitiveseo',
445 'ColdFusion',
446 'colly -',
447 'CommaFeed',
448 'Commons-HttpClient',
449 'commonscan',
450 'contactbigdatafr',
451 'contentkingapp',
452 'Contextual Code Sites Explorer',
453 'convera',
454 'CookieReports',
455 'copyright sheriff',
456 'CopyRightCheck',
457 'Copyscape',
458 'cortex\/',
459 'Cosmos4j\.feedback',
460 'Covario-IDS',
461 'Craw\/',
462 'Crescent',
463 'Criteo',
464 'Crowsnest',
465 'CSHttp',
466 'CSSCheck',
467 'Cula\/',
468 'curb',
469 'Curious George',
470 'curl',
471 'cuwhois\/',
472 'cybo\.com',
473 'DAP\/NetHTTP',
474 'DareBoost',
475 'DatabaseDriverMysqli',
476 'DataCha0s',
477 'DatadogSynthetics',
478 'Datafeedwatch',
479 'Datanyze',
480 'DataparkSearch',
481 'dataprovider',
482 'DataXu',
483 'Daum(oa)?[ \/][0-9]',
484 'dBpoweramp',
485 'ddline',
486 'deeris',
487 'delve\.ai',
488 'Demon',
489 'DeuSu',
490 'developers\.google\.com\/\+\/web\/snippet\/',
491 'Devil',
492 'Digg',
493 'Digincore',
494 'DigitalPebble',
495 'Dirbuster',
496 'Discourse Forum Onebox',
497 'Dispatch\/',
498 'Disqus\/',
499 'DittoSpyder',
500 'dlvr',
501 'DMBrowser',
502 'DNSPod-reporting',
503 'docoloc',
504 'Dolphin http client',
505 'DomainAppender',
506 'DomainLabz',
507 'Domains Project\/',
508 'Donuts Content Explorer',
509 'dotMailer content retrieval',
510 'dotSemantic',
511 'downforeveryoneorjustme',
512 'Download Wonder',
513 'downnotifier',
514 'DowntimeDetector',
515 'Drip',
516 'drupact',
517 'Drupal \(\+http:\/\/drupal\.org\/\)',
518 'DTS Agent',
519 'dubaiindex',
520 'DuplexWeb-Google',
521 'DynatraceSynthetic',
522 'EARTHCOM',
523 'Easy-Thumb',
524 'EasyDL',
525 'Ebingbong',
526 'ec2linkfinder',
527 'eCairn-Grabber',
528 'eCatch',
529 'ECCP',
530 'eContext\/',
531 'Ecxi',
532 'EirGrabber',
533 'ElectricMonk',
534 'elefent',
535 'EMail Exractor',
536 'EMail Wolf',
537 'EmailWolf',
538 'Embarcadero',
539 'Embed PHP Library',
540 'Embedly',
541 'endo\/',
542 'europarchive\.org',
543 'evc-batch',
544 'EventMachine HttpClient',
545 'Everwall Link Expander',
546 'Evidon',
547 'Evrinid',
548 'ExactSearch',
549 'ExaleadCloudview',
550 'Excel\/',
551 'exif',
552 'ExoRank',
553 'Exploratodo',
554 'Express WebPictures',
555 'Extreme Picture Finder',
556 'EyeNetIE',
557 'ezooms',
558 'facebookexternalhit',
559 'facebookexternalua',
560 'facebookplatform',
561 'fairshare',
562 'Faraday v',
563 'fasthttp',
564 'Faveeo',
565 'Favicon downloader',
566 'faviconarchive',
567 'faviconkit',
568 'FavOrg',
569 'Feed Wrangler',
570 'Feedable\/',
571 'Feedbin',
572 'FeedBooster',
573 'FeedBucket',
574 'FeedBunch\/',
575 'FeedBurner',
576 'feeder',
577 'Feedly',
578 'FeedshowOnline',
579 'Feedshow\/',
580 'Feedspot',
581 'FeedViewer\/',
582 'Feedwind\/',
583 'FeedZcollector',
584 'feeltiptop',
585 'Fetch API',
586 'Fetch\/[0-9]',
587 'Fever\/[0-9]',
588 'FHscan',
589 'Fiery%20Feeds',
590 'Filestack',
591 'Fimap',
592 'findlink',
593 'findthatfile',
594 'FlashGet',
595 'FlipboardBrowserProxy',
596 'FlipboardProxy',
597 'FlipboardRSS',
598 'Flock\/',
599 'Florienzh\/',
600 'fluffy',
601 'Flunky',
602 'flynxapp',
603 'forensiq',
604 'ForusP',
605 'FoundSeoTool',
606 'fragFINN\.de',
607 'free thumbnails',
608 'Freeuploader',
609 'FreshRSS',
610 'frontman',
611 'Funnelback',
612 'Fuzz Faster U Fool',
613 'G-i-g-a-b-o-t',
614 'g00g1e\.net',
615 'ganarvisitas',
616 'gdnplus\.com',
617 'geek-tools',
618 'Genieo',
619 'GentleSource',
620 'GetCode',
621 'Getintent',
622 'GetLinkInfo',
623 'getprismatic',
624 'GetRight',
625 'getroot',
626 'GetURLInfo\/',
627 'GetWeb',
628 'Geziyor',
629 'Ghost Inspector',
630 'GigablastOpenSource',
631 'GIS-LABS',
632 'github-camo',
633 'GitHub-Hookshot',
634 'github\.com',
635 'Go http package',
636 'Go [\d\.]* package http',
637 'Go!Zilla',
638 'Go-Ahead-Got-It',
639 'Go-http-client',
640 'go-mtasts\/',
641 'gobuster',
642 'gobyus',
643 'Gofeed',
644 'gofetch',
645 'Goldfire Server',
646 'GomezAgent',
647 'gooblog',
648 'Goodzer\/',
649 'Google AppsViewer',
650 'Google Desktop',
651 'Google favicon',
652 'Google Keyword Suggestion',
653 'Google Keyword Tool',
654 'Google Page Speed Insights',
655 'Google PP Default',
656 'Google Search Console',
657 'Google Web Preview',
658 'Google-Ads-Creatives-Assistant',
659 'Google-Ads-Overview',
660 'Google-Adwords',
661 'Google-Apps-Script',
662 'Google-Calendar-Importer',
663 'Google-HotelAdsVerifier',
664 'Google-HTTP-Java-Client',
665 'Google-InspectionTool',
666 'Google-Podcast',
667 'Google-Publisher-Plugin',
668 'Google-Read-Aloud',
669 'Google-SearchByImage',
670 'Google-Site-Verification',
671 'Google-SMTP-STS',
672 'Google-speakr',
673 'Google-Structured-Data-Testing-Tool',
674 'Google-Transparency-Report',
675 'google-xrawler',
676 'Google-Youtube-Links',
677 'GoogleDocs',
678 'GoogleHC\/',
679 'GoogleProber',
680 'GoogleProducer',
681 'GoogleSites',
682 'Gookey',
683 'GoSpotCheck',
684 'gosquared-thumbnailer',
685 'Gotit',
686 'GoZilla',
687 'grabify',
688 'GrabNet',
689 'Grafula',
690 'Grammarly',
691 'GrapeFX',
692 'GreatNews',
693 'Gregarius',
694 'GRequests',
695 'grokkit',
696 'grouphigh',
697 'grub-client',
698 'gSOAP\/',
699 'GT::WWW',
700 'GTmetrix',
701 'GuzzleHttp',
702 'gvfs\/',
703 'HAA(A)?RTLAND http client',
704 'Haansoft',
705 'hackney\/',
706 'Hadi Agent',
707 'HappyApps-WebCheck',
708 'Hardenize',
709 'Hatena',
710 'Havij',
711 'HaxerMen',
712 'HeadlessChrome',
713 'HEADMasterSEO',
714 'HeartRails_Capture',
715 'help@dataminr\.com',
716 'heritrix',
717 'Hexometer',
718 'historious',
719 'hkedcity',
720 'hledejLevne\.cz',
721 'Hloader',
722 'HMView',
723 'Holmes',
724 'HonesoSearchEngine',
725 'HootSuite Image proxy',
726 'Hootsuite-WebFeed',
727 'hosterstats',
728 'HostTracker',
729 'ht:\/\/check',
730 'htdig',
731 'HTMLparser',
732 'htmlyse',
733 'HTTP Banner Detection',
734 'http-get',
735 'HTTP-Header-Abfrage',
736 'http-kit',
737 'http-request\/',
738 'HTTP-Tiny',
739 'HTTP::Lite',
740 'http:\/\/www.neomo.de\/',
741 'HttpComponents',
742 'httphr',
743 'HTTPie',
744 'HTTPMon',
745 'httpRequest',
746 'httpscheck',
747 'httpssites_power',
748 'httpunit',
749 'HttpUrlConnection',
750 'http\.rb\/',
751 'HTTP_Compression_Test',
752 'http_get',
753 'http_request2',
754 'http_requester',
755 'httrack',
756 'huaweisymantec',
757 'HubSpot ',
758 'HubSpot-Link-Resolver',
759 'Humanlinks',
760 'i2kconnect\/',
761 'Iblog',
762 'ichiro',
763 'Id-search',
764 'IdeelaborPlagiaat',
765 'IDG Twitter Links Resolver',
766 'IDwhois\/',
767 'Iframely',
768 'igdeSpyder',
769 'iGooglePortal',
770 'IlTrovatore',
771 'Image Fetch',
772 'Image Sucker',
773 'ImageEngine\/',
774 'ImageVisu\/',
775 'Imagga',
776 'imagineeasy',
777 'imgsizer',
778 'InAGist',
779 'inbound\.li parser',
780 'InDesign%20CC',
781 'Indy Library',
782 'InetURL',
783 'infegy',
784 'infohelfer',
785 'InfoTekies',
786 'InfoWizards Reciprocal Link',
787 'inpwrd\.com',
788 'instabid',
789 'Instapaper',
790 'Integrity',
791 'integromedb',
792 'Intelliseek',
793 'InterGET',
794 'Internet Ninja',
795 'InternetSeer',
796 'internetVista monitor',
797 'internetwache',
798 'internet_archive',
799 'intraVnews',
800 'IODC',
801 'IOI',
802 'Inboxb0t',
803 'iplabel',
804 'ips-agent',
805 'IPS\/[0-9]',
806 'IPWorks HTTP\/S Component',
807 'iqdb\/',
808 'Iria',
809 'Irokez',
810 'isitup\.org',
811 'iskanie',
812 'isUp\.li',
813 'iThemes Sync\/',
814 'IZaBEE',
815 'iZSearch',
816 'JAHHO',
817 'janforman',
818 'Jaunt\/',
819 'Java.*outbrain',
820 'javelin\.io',
821 'Jbrofuzz',
822 'Jersey\/',
823 'JetCar',
824 'Jigsaw',
825 'Jobboerse',
826 'JobFeed discovery',
827 'Jobg8 URL Monitor',
828 'jobo',
829 'Jobrapido',
830 'Jobsearch1\.5',
831 'JoinVision Generic',
832 'JolokiaPwn',
833 'Joomla',
834 'Jorgee',
835 'JS-Kit',
836 'JungleKeyThumbnail',
837 'JustView',
838 'Kaspersky Lab CFR link resolver',
839 'Kelny\/',
840 'Kerrigan\/',
841 'KeyCDN',
842 'Keyword Density',
843 'Keywords Research',
844 'khttp\/',
845 'KickFire',
846 'KimonoLabs\/',
847 'Kml-Google',
848 'knows\.is',
849 'KOCMOHABT',
850 'kouio',
851 'kube-probe',
852 'kubectl',
853 'kulturarw3',
854 'KumKie',
855 'Larbin',
856 'Lavf\/',
857 'leakix\.net',
858 'LeechFTP',
859 'LeechGet',
860 'letsencrypt',
861 'Lftp',
862 'LibVLC',
863 'LibWeb',
864 'Libwhisker',
865 'libwww',
866 'Licorne',
867 'Liferea\/',
868 'Lighthouse',
869 'Lightspeedsystems',
870 'Likse',
871 'limber\.io',
872 'Link Valet',
873 'LinkAlarm\/',
874 'LinkAnalyser',
875 'linkCheck',
876 'linkdex',
877 'LinkExaminer',
878 'linkfluence',
879 'linkpeek',
880 'LinkPreview',
881 'LinkScan',
882 'LinksManager',
883 'LinkTiger',
884 'LinkWalker',
885 'link_thumbnailer',
886 'Lipperhey',
887 'Litemage_walker',
888 'livedoor ScreenShot',
889 'LoadImpactRload',
890 'localsearch-web',
891 'LongURL API',
892 'longurl-r-package',
893 'looid\.com',
894 'looksystems\.net',
895 'ltx71',
896 'lua-resty-http',
897 'Lucee \(CFML Engine\)',
898 'Lush Http Client',
899 'lwp-request',
900 'lwp-trivial',
901 'LWP::Simple',
902 'lycos',
903 'LYT\.SR',
904 'L\.webis',
905 'mabontland',
906 'MacOutlook\/',
907 'Mag-Net',
908 'MagpieRSS',
909 'Mail::STS',
910 'MailChimp',
911 'Mail\.Ru',
912 'Majestic12',
913 'makecontact\/',
914 'Mandrill',
915 'MapperCmd',
916 'marketinggrader',
917 'MarkMonitor',
918 'MarkWatch',
919 'Mass Downloader',
920 'masscan\/',
921 'Mata Hari',
922 'mattermost',
923 'Mediametric',
924 'Mediapartners-Google',
925 'mediawords',
926 'MegaIndex\.ru',
927 'MeltwaterNews',
928 'Melvil Rawi',
929 'MemGator',
930 'Metaspinner',
931 'MetaURI',
932 'MFC_Tear_Sample',
933 'Microsearch',
934 'Microsoft Data Access',
935 'Microsoft Office',
936 'Microsoft Outlook',
937 'Microsoft Windows Network Diagnostics',
938 'Microsoft-WebDAV-MiniRedir',
939 'Microsoft\.Data\.Mashup',
940 'MIDown tool',
941 'MIIxpc',
942 'Mindjet',
943 'Miniature\.io',
944 'Miniflux',
945 'mio_httpc',
946 'Miro-HttpClient',
947 'Mister PiX',
948 'mixdata dot com',
949 'mixed-content-scan',
950 'mixnode',
951 'Mnogosearch',
952 'mogimogi',
953 'Mojeek',
954 'Mojolicious \(Perl\)',
955 'Mollie',
956 'monitis',
957 'Monitority\/',
958 'Monit\/',
959 'montastic',
960 'MonTools',
961 'Moreover',
962 'Morfeus Fucking Scanner',
963 'Morning Paper',
964 'MovableType',
965 'mowser',
966 'Mrcgiguy',
967 'Mr\.4x3 Powered',
968 'MS Web Services Client Protocol',
969 'MSFrontPage',
970 'mShots',
971 'MuckRack\/',
972 'muhstik-scan',
973 'MVAClient',
974 'MxToolbox\/',
975 'myseosnapshot',
976 'nagios',
977 'Najdi\.si',
978 'Name Intelligence',
979 'NameFo\.com',
980 'Nameprotect',
981 'nationalarchives',
982 'Navroad',
983 'NearSite',
984 'Needle',
985 'Nessus',
986 'Net Vampire',
987 'NetAnts',
988 'NETCRAFT',
989 'NetLyzer',
990 'NetMechanic',
991 'NetNewsWire',
992 'Netpursual',
993 'netresearch',
994 'NetShelter ContentScan',
995 'Netsparker',
996 'NetSystemsResearch',
997 'nettle',
998 'NetTrack',
999 'Netvibes',
1000 'NetZIP',
1001 'Neustar WPM',
1002 'NeutrinoAPI',
1003 'NewRelicPinger',
1004 'NewsBlur .*Finder',
1005 'NewsGator',
1006 'newsme',
1007 'newspaper\/',
1008 'Nexgate Ruby Client',
1009 'NG-Search',
1010 'nghttp2',
1011 'Nibbler',
1012 'NICErsPRO',
1013 'NihilScio',
1014 'Nikto',
1015 'nineconnections',
1016 'NLNZ_IAHarvester',
1017 'Nmap Scripting Engine',
1018 'node-fetch',
1019 'node-superagent',
1020 'node-urllib',
1021 'Nodemeter',
1022 'NodePing',
1023 'node\.io',
1024 'nominet\.org\.uk',
1025 'nominet\.uk',
1026 'Norton-Safeweb',
1027 'Notifixious',
1028 'notifyninja',
1029 'NotionEmbedder',
1030 'nuhk',
1031 'nutch',
1032 'Nuzzel',
1033 'nWormFeedFinder',
1034 'nyawc\/',
1035 'Nymesis',
1036 'NYU',
1037 'Observatory\/',
1038 'Ocelli\/',
1039 'Octopus',
1040 'oegp',
1041 'Offline Explorer',
1042 'Offline Navigator',
1043 'OgScrper',
1044 'okhttp',
1045 'omgili',
1046 'OMSC',
1047 'Online Domain Tools',
1048 'Open Source RSS',
1049 'OpenCalaisSemanticProxy',
1050 'Openfind',
1051 'OpenLinkProfiler',
1052 'Openstat\/',
1053 'OpenVAS',
1054 'OPPO A33',
1055 'Optimizer',
1056 'Orbiter',
1057 'OrgProbe\/',
1058 'orion-semantics',
1059 'Outlook-Express',
1060 'Outlook-iOS',
1061 'Owler',
1062 'Owlin',
1063 'ownCloud News',
1064 'ow\.ly',
1065 'OxfordCloudService',
1066 'page scorer',
1067 'Page Valet',
1068 'page2rss',
1069 'PageFreezer',
1070 'PageGrabber',
1071 'PagePeeker',
1072 'PageScorer',
1073 'Pagespeed\/',
1074 'PageThing',
1075 'page_verifier',
1076 'Panopta',
1077 'panscient',
1078 'Papa Foto',
1079 'parsijoo',
1080 'Pavuk',
1081 'PayPal IPN',
1082 'pcBrowser',
1083 'Pcore-HTTP',
1084 'PDF24 URL To PDF',
1085 'Pearltrees',
1086 'PECL::HTTP',
1087 'peerindex',
1088 'Peew',
1089 'PeoplePal',
1090 'Perlu -',
1091 'PhantomJS Screenshoter',
1092 'PhantomJS\/',
1093 'Photon\/',
1094 'php-requests',
1095 'phpservermon',
1096 'Pi-Monster',
1097 'Picscout',
1098 'Picsearch',
1099 'PictureFinder',
1100 'Pimonster',
1101 'Pingability',
1102 'PingAdmin\.Ru',
1103 'Pingdom',
1104 'Pingoscope',
1105 'PingSpot',
1106 'ping\.blo\.gs',
1107 'pinterest\.com',
1108 'Pixray',
1109 'Pizilla',
1110 'Plagger\/',
1111 'Pleroma ',
1112 'Ploetz \+ Zeller',
1113 'Plukkie',
1114 'plumanalytics',
1115 'PocketImageCache',
1116 'PocketParser',
1117 'Pockey',
1118 'PodcastAddict\/',
1119 'POE-Component-Client-HTTP',
1120 'Polymail\/',
1121 'Pompos',
1122 'Porkbun',
1123 'Port Monitor',
1124 'postano',
1125 'postfix-mta-sts-resolver',
1126 'PostmanRuntime',
1127 'postplanner\.com',
1128 'PostPost',
1129 'postrank',
1130 'PowerPoint\/',
1131 'Prebid',
1132 'Prerender',
1133 'Priceonomics Analysis Engine',
1134 'PrintFriendly',
1135 'PritTorrent',
1136 'Prlog',
1137 'probethenet',
1138 'Project ?25499',
1139 'Project-Resonance',
1140 'prospectb2b',
1141 'Protopage',
1142 'ProWebWalker',
1143 'proximic',
1144 'PRTG Network Monitor',
1145 'pshtt, https scanning',
1146 'PTST ',
1147 'PTST\/[0-9]+',
1148 'Pump',
1149 'Python-httplib2',
1150 'python-httpx',
1151 'python-requests',
1152 'Python-urllib',
1153 'Qirina Hurdler',
1154 'QQDownload',
1155 'QrafterPro',
1156 'Qseero',
1157 'Qualidator',
1158 'QueryN Metasearch',
1159 'queuedriver',
1160 'quic-go-HTTP\/',
1161 'QuiteRSS',
1162 'Quora Link Preview',
1163 'Qwantify',
1164 'Radian6',
1165 'RadioPublicImageResizer',
1166 'Railgun\/',
1167 'RankActive',
1168 'RankFlex',
1169 'RankSonicSiteAuditor',
1170 'RapidLoad\/',
1171 'Re-re Studio',
1172 'ReactorNetty',
1173 'Readability',
1174 'RealDownload',
1175 'RealPlayer%20Downloader',
1176 'RebelMouse',
1177 'Recorder',
1178 'RecurPost\/',
1179 'redback\/',
1180 'ReederForMac',
1181 'Reeder\/',
1182 'ReGet',
1183 'RepoMonkey',
1184 'request\.js',
1185 'reqwest\/',
1186 'ResponseCodeTest',
1187 'RestSharp',
1188 'Riddler',
1189 'Rival IQ',
1190 'Robosourcer',
1191 'Robozilla',
1192 'ROI Hunter',
1193 'RPT-HTTPClient',
1194 'RSSMix\/',
1195 'RSSOwl',
1196 'RyowlEngine',
1197 'safe-agent-scanner',
1198 'SalesIntelligent',
1199 'Saleslift',
1200 'SAP NetWeaver Application Server',
1201 'SauceNAO',
1202 'SBIder',
1203 'sc-downloader',
1204 'scalaj-http',
1205 'Scamadviser-Frontend',
1206 'ScanAlert',
1207 'scan\.lol',
1208 'Scoop',
1209 'scooter',
1210 'ScopeContentAG-HTTP-Client',
1211 'ScoutJet',
1212 'ScoutURLMonitor',
1213 'ScrapeBox Page Scanner',
1214 'Scrapy',
1215 'Screaming',
1216 'ScreenShotService',
1217 'Scrubby',
1218 'Scrutiny\/',
1219 'Search37',
1220 'searchenginepromotionhelp',
1221 'Searchestate',
1222 'SearchExpress',
1223 'SearchSight',
1224 'SearchWP',
1225 'search\.thunderstone',
1226 'Seeker',
1227 'semanticdiscovery',
1228 'semanticjuice',
1229 'Semiocast HTTP client',
1230 'Semrush',
1231 'Sendsay\.Ru',
1232 'sentry\/',
1233 'SEO Browser',
1234 'Seo Servis',
1235 'seo-nastroj\.cz',
1236 'seo4ajax',
1237 'Seobility',
1238 'SEOCentro',
1239 'SeoCheck',
1240 'seocompany',
1241 'SEOkicks',
1242 'SEOlizer',
1243 'Seomoz',
1244 'SEOprofiler',
1245 'seoscanners',
1246 'SEOsearch',
1247 'seositecheckup',
1248 'SEOstats',
1249 'servernfo',
1250 'sexsearcher',
1251 'Seznam',
1252 'Shelob',
1253 'Shodan',
1254 'Shoppimon',
1255 'ShopWiki',
1256 'ShortLinkTranslate',
1257 'shortURL lengthener',
1258 'shrinktheweb',
1259 'Sideqik',
1260 'Siege',
1261 'SimplePie',
1262 'SimplyFast',
1263 'Siphon',
1264 'SISTRIX',
1265 'Site Sucker',
1266 'Site-Shot\/',
1267 'Site24x7',
1268 'SiteBar',
1269 'Sitebeam',
1270 'Sitebulb\/',
1271 'SiteCondor',
1272 'SiteExplorer',
1273 'SiteGuardian',
1274 'Siteimprove',
1275 'SiteIndexed',
1276 'Sitemap(s)? Generator',
1277 'SitemapGenerator',
1278 'SiteMonitor',
1279 'Siteshooter B0t',
1280 'SiteSnagger',
1281 'SiteSucker',
1282 'SiteTruth',
1283 'Sitevigil',
1284 'sitexy\.com',
1285 'SkypeUriPreview',
1286 'Slack\/',
1287 'sli-systems\.com',
1288 'slider\.com',
1289 'slurp',
1290 'SlySearch',
1291 'SmartDownload',
1292 'SMRF URL Expander',
1293 'SMUrlExpander',
1294 'Snake',
1295 'Snappy',
1296 'SnapSearch',
1297 'Snarfer\/',
1298 'SniffRSS',
1299 'sniptracker',
1300 'Snoopy',
1301 'SnowHaze Search',
1302 'sogou web',
1303 'SortSite',
1304 'Sottopop',
1305 'sovereign\.ai',
1306 'SpaceBison',
1307 'SpamExperts',
1308 'Spammen',
1309 'Spanner',
1310 'Spawning-AI',
1311 'spaziodati',
1312 'SPDYCheck',
1313 'Specificfeeds',
1314 'SpeedKit',
1315 'speedy',
1316 'SPEng',
1317 'Spinn3r',
1318 'spray-can',
1319 'Sprinklr ',
1320 'spyonweb',
1321 'sqlmap',
1322 'Sqlworm',
1323 'Sqworm',
1324 'SSL Labs',
1325 'ssl-tools',
1326 'StackRambler',
1327 'Statastico\/',
1328 'Statically-',
1329 'StatusCake',
1330 'Steeler',
1331 'Stratagems Kumo',
1332 'Stripe\/',
1333 'Stroke\.cz',
1334 'StudioFACA',
1335 'StumbleUpon',
1336 'suchen',
1337 'Sucuri',
1338 'summify',
1339 'SuperHTTP',
1340 'Surphace Scout',
1341 'Suzuran',
1342 'swcd ',
1343 'Symfony BrowserKit',
1344 'Symfony2 BrowserKit',
1345 'Synapse\/',
1346 'Syndirella\/',
1347 'SynHttpClient-Built',
1348 'Sysomos',
1349 'sysscan',
1350 'Szukacz',
1351 'T0PHackTeam',
1352 'tAkeOut',
1353 'Tarantula\/',
1354 'Taringa UGC',
1355 'TarmotGezgin',
1356 'tchelebi\.io',
1357 'techiaith\.cymru',
1358 'Teleport',
1359 'Telesoft',
1360 'Telesphoreo',
1361 'Telesphorep',
1362 'Tenon\.io',
1363 'teoma',
1364 'terrainformatica',
1365 'Test Certificate Info',
1366 'testuri',
1367 'Tetrahedron',
1368 'TextRazor Downloader',
1369 'The Drop Reaper',
1370 'The Expert HTML Source Viewer',
1371 'The Intraformant',
1372 'The Knowledge AI',
1373 'theinternetrules',
1374 'TheNomad',
1375 'Thinklab',
1376 'Thumbor',
1377 'Thumbshots',
1378 'ThumbSniper',
1379 'timewe\.net',
1380 'TinEye',
1381 'Tiny Tiny RSS',
1382 'TLSProbe\/',
1383 'Toata',
1384 'topster',
1385 'touche\.com',
1386 'Traackr\.com',
1387 'tracemyfile',
1388 'Trackuity',
1389 'TrapitAgent',
1390 'Trendiction',
1391 'Trendsmap',
1392 'trendspottr',
1393 'truwoGPS',
1394 'TryJsoup',
1395 'TulipChain',
1396 'Turingos',
1397 'Turnitin',
1398 'tweetedtimes',
1399 'Tweetminster',
1400 'Tweezler\/',
1401 'twibble',
1402 'Twice',
1403 'Twikle',
1404 'Twingly',
1405 'Twisted PageGetter',
1406 'Typhoeus',
1407 'ubermetrics-technologies',
1408 'uclassify',
1409 'UdmSearch',
1410 'ultimate_sitemap_parser',
1411 'unchaos',
1412 'unirest-java',
1413 'UniversalFeedParser',
1414 'unshortenit',
1415 'Unshorten\.It',
1416 'Untiny',
1417 'UnwindFetchor',
1418 'updated',
1419 'updown\.io daemon',
1420 'Upflow',
1421 'Uptimia',
1422 'URL Verifier',
1423 'Urlcheckr',
1424 'URLitor',
1425 'urlresolver',
1426 'Urlstat',
1427 'URLTester',
1428 'UrlTrends Ranking Updater',
1429 'URLy Warning',
1430 'URLy\.Warning',
1431 'URL\/Emacs',
1432 'Vacuum',
1433 'Vagabondo',
1434 'VB Project',
1435 'vBSEO',
1436 'VCI',
1437 'via ggpht\.com GoogleImageProxy',
1438 'Virusdie',
1439 'visionutils',
1440 'Visual Rights Group',
1441 'vkShare',
1442 'VoidEYE',
1443 'Voil',
1444 'voltron',
1445 'voyager\/',
1446 'VSAgent\/',
1447 'VSB-TUO\/',
1448 'Vulnbusters Meter',
1449 'VYU2',
1450 'w3af\.org',
1451 'W3C-checklink',
1452 'W3C-mobileOK',
1453 'W3C_Unicorn',
1454 'WAC-OFU',
1455 'WakeletLinkExpander',
1456 'WallpapersHD',
1457 'Wallpapers\/[0-9]+',
1458 'wangling',
1459 'Wappalyzer',
1460 'WatchMouse',
1461 'WbSrch\/',
1462 'WDT\.io',
1463 'Web Auto',
1464 'Web Collage',
1465 'Web Enhancer',
1466 'Web Fetch',
1467 'Web Fuck',
1468 'Web Pix',
1469 'Web Sauger',
1470 'Web spyder',
1471 'Web Sucker',
1472 'web-capture\.net',
1473 'Web-sniffer',
1474 'Webalta',
1475 'Webauskunft',
1476 'WebAuto',
1477 'WebCapture',
1478 'WebClient\/',
1479 'webcollage',
1480 'WebCookies',
1481 'WebCopier',
1482 'WebCorp',
1483 'WebDataStats',
1484 'WebDoc',
1485 'WebEnhancer',
1486 'WebFetch',
1487 'WebFuck',
1488 'WebGazer',
1489 'WebGo IS',
1490 'WebImageCollector',
1491 'WebImages',
1492 'WebIndex',
1493 'webkit2png',
1494 'WebLeacher',
1495 'webmastercoffee',
1496 'webmon ',
1497 'WebPix',
1498 'WebReaper',
1499 'WebSauger',
1500 'webscreenie',
1501 'Webshag',
1502 'Webshot',
1503 'Website Quester',
1504 'websitepulse agent',
1505 'WebsiteQuester',
1506 'Websnapr',
1507 'WebSniffer',
1508 'Webster',
1509 'WebStripper',
1510 'WebSucker',
1511 'webtech\/',
1512 'WebThumbnail',
1513 'Webthumb\/',
1514 'WebWhacker',
1515 'WebZIP',
1516 'WeLikeLinks',
1517 'WEPA',
1518 'WeSEE',
1519 'wf84',
1520 'Wfuzz\/',
1521 'wget',
1522 'WhatCMS',
1523 'WhatsApp',
1524 'WhatsMyIP',
1525 'WhatWeb',
1526 'WhereGoes\?',
1527 'Whibse',
1528 'WhoAPI\/',
1529 'WhoRunsCoinHive',
1530 'Whynder Magnet',
1531 'Windows-RSS-Platform',
1532 'WinHttp-Autoproxy-Service',
1533 'WinHTTP\/',
1534 'WinPodder',
1535 'wkhtmlto',
1536 'wmtips',
1537 'Woko',
1538 'Wolfram HTTPClient',
1539 'woorankreview',
1540 'WordupinfoSearch',
1541 'Word\/',
1542 'worldping-api',
1543 'wotbox',
1544 'WP Engine Install Performance API',
1545 'wpif',
1546 'wprecon\.com survey',
1547 'WPScan',
1548 'wscheck',
1549 'Wtrace',
1550 'WWW-Collector-E',
1551 'WWW-Mechanize',
1552 'WWW::Document',
1553 'WWW::Mechanize',
1554 'WWWOFFLE',
1555 'www\.monitor\.us',
1556 'x09Mozilla',
1557 'x22Mozilla',
1558 'XaxisSemanticsClassifier',
1559 'XenForo\/',
1560 'Xenu Link Sleuth',
1561 'XING-contenttabreceiver',
1562 'xpymep([0-9]?)\.exe',
1563 'Y!J-[A-Z][A-Z][A-Z]',
1564 'Yaanb',
1565 'yacy',
1566 'Yahoo Link Preview',
1567 'YahooCacheSystem',
1568 'YahooMailProxy',
1569 'YahooYSMcm',
1570 'YandeG',
1571 'Yandex(?!Search)',
1572 'yanga',
1573 'yeti',
1574 'Yo-yo',
1575 'Yoleo Consumer',
1576 'yomins\.com',
1577 'yoogliFetchAgent',
1578 'YottaaMonitor',
1579 'Your-Website-Sucks',
1580 'yourls\.org',
1581 'YoYs\.net',
1582 'YP\.PL',
1583 'Zabbix',
1584 'Zade',
1585 'Zao',
1586 'Zauba',
1587 'Zemanta Aggregator',
1588 'Zend\\Http\\Client',
1589 'Zend_Http_Client',
1590 'Zermelo',
1591 'Zeus ',
1592 'zgrab',
1593 'ZnajdzFoto',
1594 'ZnHTTP',
1595 'Zombie\.js',
1596 'Zoom\.Mac',
1597 'ZoteroTranslationServer',
1598 'ZyBorg',
1599 '[a-z0-9\-_]*(bot|crawl|archiver|transcoder|spider|uptime|validator|fetcher|cron|checker|reader|extractor|monitoring|analyzer|scraper)'
1600 ];
1601 }
1602
1603 /**
1604 * Return the list of strings to remove from the user agent before running the crawler regex.
1605 *
1606 * @return array
1607 */
1608 public function get_exclusions_list() {
1609 return [
1610 'Safari.[\d\.]*',
1611 'Firefox.[\d\.]*',
1612 ' Chrome.[\d\.]*',
1613 'Chromium.[\d\.]*',
1614 'MSIE.[\d\.]',
1615 'Opera\/[\d\.]*',
1616 'Mozilla.[\d\.]*',
1617 'AppleWebKit.[\d\.]*',
1618 'Trident.[\d\.]*',
1619 'Windows NT.[\d\.]*',
1620 'Android [\d\.]*',
1621 'Macintosh.',
1622 'Ubuntu',
1623 'Linux',
1624 '[ ]Intel',
1625 'Mac OS X [\d_]*',
1626 '(like )?Gecko(.[\d\.]*)?',
1627 'KHTML,',
1628 'CriOS.[\d\.]*',
1629 'CPU iPhone OS ([0-9_])* like Mac OS X',
1630 'CPU OS ([0-9_])* like Mac OS X',
1631 'iPod',
1632 'compatible',
1633 'x86_..',
1634 'i686',
1635 'x64',
1636 'X11',
1637 'rv:[\d\.]*',
1638 'Version.[\d\.]*',
1639 'WOW64',
1640 'Win64',
1641 'Dalvik.[\d\.]*',
1642 ' \.NET CLR [\d\.]*',
1643 'Presto.[\d\.]*',
1644 'Media Center PC',
1645 'BlackBerry',
1646 'Build',
1647 'Opera Mini\/\d{1,2}\.\d{1,2}\.[\d\.]*\/\d{1,2}\.',
1648 'Opera',
1649 ' \.NET[\d\.]*',
1650 'cubot',
1651 '; M bot',
1652 '; CRONO',
1653 '; B bot',
1654 '; IDbot',
1655 '; ID bot',
1656 '; POWER BOT',
1657 'OCTOPUS-CORE',
1658 'htc_botdugls',
1659 'super\/\d+\/Android\/\d+',
1660 ];
1661 }
1662
1663 /**
1664 * Return all possible HTTP headers that represent the User-Agent string.
1665 *
1666 * @return array
1667 */
1668 public function get_headers_list() {
1669 return [
1670 // The default User-Agent string.
1671 'HTTP_USER_AGENT',
1672 // Header can occur on devices using Opera Mini.
1673 'HTTP_X_OPERAMINI_PHONE_UA',
1674 // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
1675 'HTTP_X_DEVICE_USER_AGENT',
1676 'HTTP_X_ORIGINAL_USER_AGENT',
1677 'HTTP_X_SKYFIRE_PHONE',
1678 'HTTP_X_BOLT_PHONE_UA',
1679 'HTTP_DEVICE_STOCK_UA',
1680 'HTTP_X_UCBROWSER_DEVICE_UA',
1681 // Sometimes, bots (especially Google) use a genuine user agent, but fill this header in with their email address
1682 'HTTP_FROM',
1683 'HTTP_X_SCANNER' // Seen in use by Netsparker
1684 ];
1685 }
1686 }
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2
3 // exit if accessed directly
4 if ( ! defined( 'ABSPATH' ) )
5 exit;
6
7 /**
8 * Cookie_Notice_Dashboard class.
9 *
10 * @class Cookie_Notice_Dashboard
11 */
12 class Cookie_Notice_Dashboard {
13
14 /**
15 * Class constructor.
16 *
17 * @return void
18 */
19 public function __construct() {
20 // actions
21 add_action( 'wp_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
22 add_action( 'wp_network_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
23 add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts_styles' ] );
24
25 // site status
26 add_filter( 'site_status_tests', [ $this, 'add_tests' ] );
27 }
28
29 /**
30 * Initialize widget.
31 *
32 * @global array $wp_meta_boxes
33 *
34 * @return void
35 */
36 public function wp_dashboard_setup() {
37 // filter user_can_see_stats
38 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
39 return;
40
41 // get main instance
42 $cn = Cookie_Notice();
43
44 // check when to hide widget
45 if ( is_multisite() ) {
46 // site dashboard
47 if ( current_action() === 'wp_dashboard_setup' && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
48 return;
49
50 // network dashboard
51 if ( current_action() === 'wp_network_dashboard_setup' ) {
52 if ( $cn->is_plugin_network_active() ) {
53 if ( ! $cn->network_options['global_override'] )
54 return;
55 } else
56 return;
57 }
58 }
59
60 // check is it network admin
61 if ( $cn->is_network_admin() )
62 $dashboard_key = 'dashboard-network';
63 else
64 $dashboard_key = 'dashboard';
65
66 global $wp_meta_boxes;
67
68 // set widget key
69 $widget_key = 'cn_dashboard_stats';
70
71 // add dashboard chart widget
72 wp_add_dashboard_widget( $widget_key, __( 'Cookie Compliance', 'cookie-notice' ), [ $this, 'dashboard_widget' ] );
73
74 // get widgets
75 $normal_dashboard = $wp_meta_boxes[$dashboard_key]['normal']['core'];
76
77 // attempt to place the widget at the top
78 $widget_instance = [
79 $widget_key => $normal_dashboard[ $widget_key ]
80 ];
81
82 // remove new widget
83 unset( $normal_dashboard[ $widget_key ] );
84
85 // merge widgets
86 $sorted_dashboard = array_merge( $widget_instance, $normal_dashboard );
87
88 // update widgets
89 $wp_meta_boxes[$dashboard_key]['normal']['core'] = $sorted_dashboard;
90 }
91
92 /**
93 * Enqueue admin scripts and styles.
94 *
95 * @param string $pagenow
96 * @return void
97 */
98 public function admin_scripts_styles( $pagenow ) {
99 if ( $pagenow !== 'index.php' )
100 return;
101
102 // filter user_can_see_stats
103 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
104 return;
105
106 // get main instance
107 $cn = Cookie_Notice();
108
109 $date_format = get_option( 'date_format' );
110
111 if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
112 $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
113 else
114 $analytics = get_option( 'cookie_notice_app_analytics', [] );
115
116 // styles
117 wp_enqueue_style( 'cookie-notice-admin-dashboard', COOKIE_NOTICE_URL . '/css/admin-dashboard.css', [], $cn->defaults['version'] );
118 wp_enqueue_style( 'cookie-notice-microtip', COOKIE_NOTICE_URL . '/assets/microtip/microtip.min.css', [], $cn->defaults['version'] );
119
120 // bail if compliance is not active
121 if ( $cn->get_status() !== 'active' )
122 return;
123
124 // scripts
125 wp_register_script( 'cookie-notice-admin-chartjs', COOKIE_NOTICE_URL . '/assets/chartjs/chart.min.js', [ 'jquery' ], '4.3.2', true );
126 wp_enqueue_script( 'cookie-notice-admin-dashboard', COOKIE_NOTICE_URL . '/js/admin-dashboard.js', [ 'jquery', 'cookie-notice-admin-chartjs' ], $cn->defaults['version'], true );
127
128 // cycle usage data
129 $cycle_usage = [
130 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
131 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0
132 ];
133
134 // available visits, -1 for no pro plans
135 $cycle_usage['visits_available'] = $cycle_usage['threshold'] ? $cycle_usage['threshold'] - $cycle_usage['visits'] : -1;
136
137 // get used threshold info
138 if ( $cycle_usage['threshold'] > 0 ) {
139 $threshold_used = ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100;
140
141 if ( $threshold_used > 100 )
142 $threshold_used = 100;
143 } else
144 $threshold_used = 0;
145
146 $chartdata = [
147 'usage' => [
148 'type' => 'doughnut',
149 'data' => [
150 'labels' => [
151 _x( 'Used', 'threshold limit', 'cookie-notice' ),
152 _x( 'Free', 'threshold limit', 'cookie-notice' )
153 ],
154 'datasets' => [
155 [
156 'data' => [ $cycle_usage['visits'], $cycle_usage['visits_available'] ],
157 'backgroundColor' => [
158 'rgb(32, 193, 158)',
159 'rgb(235, 233, 235)'
160 ]
161 ]
162 ]
163 ]
164 ],
165 'consent-activity' => [
166 'type' => 'line'
167 ]
168 ];
169
170 // warning usage color
171 if ( $threshold_used > 80 && $threshold_used < 100 )
172 $chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(255, 193, 7)';
173 // danger usage color
174 elseif ( $threshold_used == 100 )
175 $chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(220, 53, 69)';
176
177 $data = [
178 'labels' => [],
179 'datasets' => [
180 0 => [
181 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 1 ),
182 'data' => [],
183 'fill' => true,
184 'backgroundColor' => 'rgba(196, 196, 196, 0.3)',
185 'borderColor' => 'rgba(196, 196, 196, 1)',
186 'borderWidth' => 1.2,
187 'borderDash' => [],
188 'pointBorderColor' => 'rgba(196, 196, 196, 1)',
189 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
190 'pointBorderWidth' => 1.2
191 ],
192 1 => [
193 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 2 ),
194 'data' => [],
195 'fill' => true,
196 'backgroundColor' => 'rgba(213, 181, 101, 0.3)',
197 'borderColor' => 'rgba(213, 181, 101, 1)',
198 'borderWidth' => 1.2,
199 'borderDash' => [],
200 'pointBorderColor' => 'rgba(213, 181, 101, 1)',
201 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
202 'pointBorderWidth' => 1.2
203 ],
204 2 => [
205 'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 3 ),
206 'data' => [],
207 'fill' => true,
208 'backgroundColor' => 'rgba(152, 145, 177, 0.3)',
209 'borderColor' => 'rgba(152, 145, 177, 1)',
210 'borderWidth' => 1.2,
211 'borderDash' => [],
212 'pointBorderColor' => 'rgba(152, 145, 177, 1)',
213 'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
214 'pointBorderWidth' => 1.2
215 ]
216 ]
217 ];
218
219 // generate chart days
220 $chart_date_format = 'j/m';
221
222 for ( $i = 30; $i >= 0; $i-- ) {
223 // set label
224 $data['labels'][] = date( $chart_date_format, strtotime( '-'. $i .' days' ) );
225
226 // reset datasets
227 $data['datasets'][0]['data'][] = 0;
228 $data['datasets'][1]['data'][] = 0;
229 $data['datasets'][2]['data'][] = 0;
230 }
231
232 if ( ! empty( $analytics['consentActivities'] ) && is_array( $analytics['consentActivities'] ) ) {
233 // set consent records in charts days
234 foreach ( $analytics['consentActivities'] as $index => $entry ) {
235 $time = date_i18n( $chart_date_format, strtotime( $entry->eventdt ) );
236 $i = array_search( $time, $data['labels'] );
237
238 if ( $i )
239 $data['datasets'][(int) $entry->consentlevel - 1]['data'][$i] = (int) $entry->totalrecd;
240 }
241 }
242
243 $chartdata['consent-activity']['data'] = $data;
244
245 // prepare script data
246 $script_data = [
247 'ajaxURL' => admin_url( 'admin-ajax.php' ),
248 'nonce' => wp_create_nonce( 'cn-dashboard-widget' ),
249 'nonceUser' => wp_create_nonce( 'cn-dashboard-user-options' ),
250 'charts' => $chartdata
251 ];
252
253 wp_add_inline_script( 'cookie-notice-admin-dashboard', 'var cnDashboardArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
254 }
255
256 /**
257 * Render dashboard widget.
258 *
259 * @return void
260 */
261 public function dashboard_widget() {
262 // get main instance
263 $cn = Cookie_Notice();
264
265 if ( $cn->is_network_admin() )
266 $upgrade_url = network_admin_url( 'admin.php?page=cookie-notice&welcome=1' );
267 else
268 $upgrade_url = admin_url( 'admin.php?page=cookie-notice&welcome=1' );
269
270 $html = '';
271
272 // compliance active, display chart
273 if ( $cn->get_status() === 'active' ) {
274 // get user options
275 $user_options = get_user_meta( get_current_user_id(), 'pvc_dashboard', true );
276
277 // empty options?
278 if ( empty( $user_options ) || ! is_array( $user_options ) )
279 $user_options = [];
280
281 // sanitize options
282 $user_options = map_deep( $user_options, 'sanitize_text_field' );
283
284 // get menu items
285 $menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : [];
286
287 $items = [
288 [
289 'id' => 'visits',
290 'title' => esc_html__( 'Traffic Overview', 'cookie-notice' ),
291 'description' => esc_html__( 'Displays the general visits information for your domain.', 'cookie-notice' )
292 ],
293 [
294 'id' => 'consent-activity',
295 'title' => esc_html__( 'Consent Activity', 'cookie-notice' ),
296 'description' => esc_html__( 'Displays the chart of the domain consent activity in the last 30 days.', 'cookie-notice' )
297 ]
298 ];
299
300 $html .= '
301 <div id="cn-dashboard-accordion" class="cn-accordion">';
302
303 foreach ( $items as $item ) {
304 $html .= $this->widget_item( $item, $menu_items );
305 }
306
307 $html .= '
308 </div>';
309 // compliance inactive, display image
310 } else {
311 $html .= '
312 <div id="cn-dashboard-accordion" class="cn-accordion cn-widget-block">
313 <img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-widget.png" alt="Cookie Compliance widget" />
314 <div id="cn-dashboard-upgrade">
315 <div id="cn-dashboard-modal">
316 <h2>' . esc_html__( 'View consent activity inside WordPress Dashboard', 'cookie-notice' ) . '</h2>
317 <p>' . esc_html__( 'Display information about the visits.', 'cookie-notice' ) . '</p>
318 <p>' . esc_html__( 'Get Consent logs data for the last 30 days.', 'cookie-notice' ) . '</p>
319 <p>' . esc_html__( 'Enable consent purpose categories, automatic cookie blocking and more.', 'cookie-notice' ) . '</p>
320 <p><a href="' . esc_url( $upgrade_url ) . '" class="button button-primary button-hero cn-button">' . esc_html__( 'Upgrade to Cookie Compliance', 'cookie-notice' ) . '</a></p>
321 </div>
322 </div>
323 </div>';
324 }
325
326 // allows a list of html entities such as
327 $allowed_html = wp_kses_allowed_html( 'post' );
328 $allowed_html['canvas'] = [
329 'id' => true,
330 'height' => true
331 ];
332
333 echo wp_kses( $html, $allowed_html );
334 }
335
336 /**
337 * Generate dashboard widget item HTML.
338 *
339 * @param array $item
340 * @param array $menu_items
341 * @return string
342 */
343 public function widget_item( $item, $menu_items ) {
344 return '
345 <div id="cn-' . esc_attr( $item['id'] ) . '" class="cn-accordion-item' . ( in_array( $item['id'], $menu_items, true ) ? ' cn-collapsed' : '' ) . '">
346 <div class="cn-accordion-header">
347 <div class="cn-accordion-toggle"><span class="cn-accordion-title">' . esc_html( $item['title'] ) . '</span><span class="cn-tooltip" aria-label="' . esc_attr( $item['description'] ) . '" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="cn-tooltip-icon"></span></span></div>
348 </div>
349 <div class="cn-accordion-content">
350 <div class="cn-dashboard-container">
351 <div class="cn-data-container">
352 ' . $this->widget_item_content( $item['id'] ) . '
353 <span class="spinner"></span>
354 </div>
355 </div>
356 </div>
357 </div>';
358 }
359
360 /**
361 * Generate dashboard widget item content HTML.
362 *
363 * @param array $item
364 * @return void
365 */
366 public function widget_item_content( $item ) {
367 $html = '';
368
369 switch ( $item ) {
370 case 'visits':
371 // get main instance
372 $cn = Cookie_Notice();
373
374 $date_format = get_option( 'date_format' );
375
376 // get analytics data options
377 if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
378 $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
379 else
380 $analytics = get_option( 'cookie_notice_app_analytics', [] );
381
382 // thirty days data
383 $thirty_days_usage = [
384 'visits' => ! empty( $analytics['thirtyDaysUsage']->visits ) ? (int) $analytics['thirtyDaysUsage']->visits : 0,
385 'consents' => 0,
386 'consents_updated' => ! empty( $analytics['lastUpdated'] ) ? date_create_from_format( 'Y-m-d H:i:s', $analytics['lastUpdated'] ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) )
387 ];
388
389 // set current timezone
390 $current_timezone = new DateTimeZone( $this->timezone_string() );
391
392 // update date
393 $thirty_days_usage['consents_updated']->setTimezone( $current_timezone );
394
395 if ( ! empty( $analytics['consentActivities'] ) ) {
396 foreach ( $analytics['consentActivities'] as $index => $entry ) {
397 $thirty_days_usage['consents'] += (int) $entry->totalrecd;
398 }
399 }
400
401 // cycle usage data
402 $cycle_usage = [
403 'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
404 'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
405 'days_to_go' => ! empty( $analytics['cycleUsage']->daysToGo ) ? (int) $analytics['cycleUsage']->daysToGo : 0,
406 'start_date' => ! empty( $analytics['cycleUsage']->startDate ) ? date_create_from_format( '!Y-m-d', $analytics['cycleUsage']->startDate ) : ''
407 ];
408
409 // get used threshold info
410 if ( $cycle_usage['threshold'] > 0 ) {
411 $threshold_used = ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100;
412
413 if ( $threshold_used > 100 )
414 $threshold_used = 100;
415 } else
416 $threshold_used = 0;
417
418 $html .= '
419 <div id="cn-dashboard-' . esc_attr( $item ) . '">
420 <div id="cn-' . esc_attr( $item ) . '-infobox-traffic-overview" class="cn-infobox-container">
421 <div id="cn-' . esc_attr( $item ) . '-infobox-visits" class="cn-infobox">
422 <div class="cn-infobox-title">' . esc_html__( 'Total Visits', 'cookie-notice' ) . '</div>
423 <div class="cn-infobox-number">' . esc_html( number_format_i18n( $thirty_days_usage['visits'], 0 ) ) . '</div>
424 <div class="cn-infobox-subtitle">' . esc_html__( 'Last 30 days', 'cookie-notice' ) . '</div>
425 </div>
426 <div id="cn-' . esc_attr( $item ) . '-infobox-consents" class="cn-infobox">
427 <div class="cn-infobox-title">' . esc_html__( 'Consent Logs', 'cookie-notice' ) . '</div>
428 <div class="cn-infobox-number">' . esc_html( number_format_i18n( $thirty_days_usage['consents'], 0 ) ) . '</div>
429 <div class="cn-infobox-subtitle">' . esc_html( sprintf( __( 'Updated %s', 'cookie-notice' ), date_i18n( $date_format, $thirty_days_usage['consents_updated']->getTimestamp() ) ) ) . '</div>
430 </div>
431 </div>';
432
433 if ( $cycle_usage['threshold'] ) {
434 $usage_class = 'success';
435
436 // warning usage color
437 if ( $threshold_used > 80 && $threshold_used < 100 )
438 $usage_class = 'warning';
439 // danger usage color
440 elseif ( $threshold_used === 100 )
441 $usage_class = 'danger';
442
443 $html .= '
444 <div id="cn-' . esc_attr( $item ) . '-infobox-traffic-usage" class="cn-infobox-container">
445 <div id="cn-' . esc_attr( $item ) . '-infobox-limits" class="cn-infobox">
446 <div class="cn-infobox-title">' . esc_html__( 'Traffic Usage', 'cookie-notice' ) . '</div>
447 <div class="cn-infobox-number cn-text-' . esc_attr( $usage_class ) . '">' . esc_html( number_format_i18n( $threshold_used, 1 ) ) . ' %</div>
448 <div class="cn-infobox-subtitle">
449 <p>' . esc_html( sprintf( __( 'Visits usage: %1$s / %2$s', 'cookie-notice' ), $cycle_usage['visits'], $cycle_usage['threshold'] ) ) . '</p>
450 <p>' . esc_html( sprintf( __( 'Cycle started: %s', 'cookie-notice' ), date_i18n( $date_format, $cycle_usage['start_date']->getTimestamp() ) ) ) . '</p>
451 <p>' . esc_html( sprintf( __( 'Days to go: %s', 'cookie-notice' ), $cycle_usage['days_to_go'] ) ) . '</p>
452 </div>
453 </div>
454 <div id="cn-' . esc_attr( $item ) . '-chart-limits" class="cn-infobox cn-chart-container">
455 <canvas id="cn-usage-chart" style="height: 100px"></canvas>
456 </div>';
457
458 /*
459 <div id="cn-' . $item . '-traffic-notice" class="cn-infobox-notice cn-traffic-' . $usage_class . '">
460 <p><b>' . __( 'Your domain has exceeded 90% of the usage limit.', 'cookie-notice' ) . '</b></p>
461 <p>' . sprintf(__( 'The banner will still display properly and consent record will be set in the browser. However the Autoblocking will be disabled and Consent Records will not be stored in the application until the current visits cycle resets (in %s days).', 'cookie-notice' ), $cycle_usage['days_to_go'] ) . '</p>
462 </div>
463 */
464
465 $html .= '
466 </div>';
467 }
468
469 $html .= '
470 </div>';
471 break;
472
473 case 'consent-activity':
474 $html .= '
475 <div id="cn-dashboard-' . esc_attr( $item ) . '">
476 <div id="cn-' . esc_attr( $item ) . '-chart-container cn-chart-container">
477 <canvas id="cn-' . esc_attr( $item ) . '-chart" style="height: 300px"></canvas>
478 </div>
479 </div>';
480 break;
481 }
482
483 return $html;
484 }
485
486 /**
487 * Add site test.
488 *
489 * @param array $tests
490 * @return array
491 */
492 public function add_tests( $tests ) {
493 $tests['direct']['cookie_compliance_status'] = [
494 'label' => esc_html__( 'Cookie Compliance Status', 'cookie-notice' ),
495 'test' => [ $this, 'test_cookie_compliance' ]
496 ];
497
498 return $tests;
499 }
500
501 /**
502 * Test for Cookie Compliance.
503 *
504 * @return array|void
505 */
506 public function test_cookie_compliance() {
507 if ( Cookie_Notice()->get_status() !== 'active' ) {
508 return [
509 'label' => esc_html__( 'Your site does not have Cookie Compliance', 'cookie-notice' ),
510 'status' => 'recommended',
511 'description' => esc_html__( "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws.", 'cookie-notice' ),
512 'actions' => sprintf( '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></p>', admin_url( 'admin.php?page=cookie-notice&welcome=1' ), esc_html__( 'Run Compliance Check', 'cookie-notice' ) ),
513 'test' => 'cookie_compliance_status',
514 'badge' => [
515 'label' => esc_html__( 'Cookie Notice', 'cookie-notice' ),
516 'color' => 'blue'
517 ]
518 ];
519 }
520 }
521
522 /**
523 * Retrieve the timezone of the site as a string.
524 *
525 * @return string
526 */
527 public function timezone_string() {
528 if ( function_exists( 'wp_timezone_string' ) )
529 return wp_timezone_string();
530
531 $timezone_string = get_option( 'timezone_string' );
532
533 if ( $timezone_string )
534 return $timezone_string;
535
536 $offset = (float) get_option( 'gmt_offset' );
537 $hours = (int) $offset;
538 $minutes = ( $offset - $hours );
539 $sign = ( $offset < 0 ) ? '-' : '+';
540 $abs_hour = abs( $hours );
541 $abs_mins = abs( $minutes * 60 );
542 $tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
543
544 return $tz_offset;
545 }
546 }
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie_Notice_Frontend class.
8 *
9 * @class Cookie_Notice_Frontend
10 */
11 class Cookie_Notice_Frontend {
12
13 /**
14 * Class constructor.
15 *
16 * @return void
17 */
18 public function __construct() {
19 // actions
20 add_action( 'init', [ $this, 'early_init' ], 9 );
21 add_action( 'wp', [ $this, 'init' ] );
22 }
23
24 /**
25 * Early initialization.
26 *
27 * @return void
28 */
29 public function early_init() {
30 // get main instance
31 $cn = Cookie_Notice();
32
33 // cookie compliance initialization
34 if ( $cn->get_status() === 'active' && $cn->options['general']['caching_compatibility'] ) {
35 // litespeed cache 3.0.0+ compatibility
36 if ( cn_is_plugin_active( 'litespeed' ) )
37 include_once( COOKIE_NOTICE_PATH . 'includes/modules/litespeed-cache/litespeed-cache.php' );
38
39 // sg optimizer 5.5.0+ compatibility
40 if ( cn_is_plugin_active( 'sgoptimizer' ) )
41 include_once( COOKIE_NOTICE_PATH . 'includes/modules/sg-optimizer/sg-optimizer.php' );
42
43 // wp rocket 3.8.0+ compatibility
44 if ( cn_is_plugin_active( 'wprocket' ) )
45 include_once( COOKIE_NOTICE_PATH . 'includes/modules/wp-rocket/wp-rocket.php' );
46 }
47 }
48
49 /**
50 * Initialize plugin.
51 *
52 * @return void
53 */
54 public function init() {
55 if ( is_admin() )
56 return;
57
58 // purge cache
59 if ( isset( $_GET['hu_purge_cache'] ) )
60 $this->purge_cache();
61
62 // get main instance
63 $cn = Cookie_Notice();
64
65 // is banner allowed to display?
66 if ( $this->maybe_display_banner() ) {
67 // cookie compliance initialization
68 if ( $cn->get_status() === 'active' ) {
69 add_action( 'wp_head', [ $this, 'add_cookie_compliance' ], 0 );
70
71 // is caching compatibility active?
72 if ( $cn->options['general']['caching_compatibility'] ) {
73 // autoptimize 2.4.0+
74 if ( cn_is_plugin_active( 'autoptimize' ) )
75 include_once( COOKIE_NOTICE_PATH . 'includes/modules/autoptimize/autoptimize.php' );
76 }
77
78 // is blocking active?
79 if ( $cn->options['general']['app_blocking'] ) {
80 // contact form 7 5.1.0+ recaptcha v3 compatibility
81 if ( cn_is_plugin_active( 'contactform7' ) )
82 include_once( COOKIE_NOTICE_PATH . 'includes/modules/contact-form-7/contact-form-7.php' );
83 }
84 // cookie notice initialization
85 } else {
86 // actions
87 add_action( 'wp_enqueue_scripts', [ $this, 'wp_enqueue_notice_scripts' ] );
88 add_action( 'wp_head', [ $this, 'wp_print_header_scripts' ] );
89 add_action( 'wp_print_footer_scripts', [ $this, 'wp_print_footer_scripts' ] );
90 add_action( 'wp_footer', [ $this, 'add_cookie_notice' ], 1000 );
91
92 // filters
93 add_filter( 'script_loader_tag', [ $this, 'wp_enqueue_script_async' ], 10, 3 );
94 add_filter( 'body_class', [ $this, 'change_body_class' ] );
95 }
96 }
97 }
98
99 /**
100 * Whether banner is allowed to display.
101 *
102 * @return bool
103 */
104 public function maybe_display_banner() {
105 // get main instance
106 $cn = Cookie_Notice();
107
108 // is cookie compliance active?
109 if ( $cn->get_status() === 'active' ) {
110 // elementor 1.3.0+ compatibility, needed early for is_preview_mode
111 if ( cn_is_plugin_active( 'elementor' ) )
112 include_once( COOKIE_NOTICE_PATH . 'includes/modules/elementor/elementor.php' );
113 }
114
115 // is it preview mode?
116 if ( $this->is_preview_mode() )
117 return false;
118
119 // is it a bot?
120 if ( $cn->bot_detect->is_crawler() )
121 return false;
122
123 // final check for conditional display
124 return $this->check_conditions();
125 }
126
127 /**
128 * Whether preview mode is active.
129 *
130 * @return bool
131 */
132 public function is_preview_mode() {
133 return isset( $_GET['cn_preview_mode'] ) || is_preview() || is_customize_preview() || defined( 'IFRAME_REQUEST' ) || ( function_exists( 'wp_is_json_request' ) && wp_is_json_request() ) || apply_filters( 'cn_is_preview_mode', false );
134 }
135
136 /**
137 * Check whether banner should be displayed based on specified conditions.
138 *
139 * @return bool
140 */
141 public function check_conditions() {
142 // get main instance
143 $cn = Cookie_Notice();
144
145 if ( ! $cn->options['general']['conditional_active'] )
146 return true;
147
148 // get conditions
149 $rules = $cn->options['general']['conditional_rules'];
150
151 // set access type
152 $access_type = $cn->options['general']['conditional_display'] === 'show';
153
154 // get object
155 $object = get_queried_object();
156
157 // no rules?
158 if ( empty( $rules ) )
159 $final_access = true;
160 else {
161 // check the rules
162 foreach( $rules as $index => $group ) {
163 $give_group_access = true;
164
165 foreach ( $group as $rule ) {
166 $give_rule_access = false;
167
168 switch ( $rule['param'] ) {
169 case 'page_type':
170 if ( ( $rule['operator'] === 'equal' && $rule['value'] === 'front' && is_front_page() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'front' && ! is_front_page() ) || ( $rule['operator'] === 'equal' && $rule['value'] === 'home' && is_home() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'home' && ! is_home() ) )
171 $give_rule_access = true;
172 break;
173
174 case 'page':
175 if ( ( $rule['operator'] === 'equal' && ! empty( $object ) && is_page( $object->ID ) && (int) $object->ID === (int) $rule['value'] ) || ( $rule['operator'] === 'not_equal' && ( empty( $object ) || ! is_page() || ( is_page() && ! empty( $object ) && $object->ID !== (int) $rule['value'] ) ) ) )
176 $give_rule_access = true;
177 break;
178
179 case 'post_type':
180 if ( ( $rule['operator'] === 'equal' && is_singular( $rule['value'] ) ) || ( $rule['operator'] === 'not_equal' && ! is_singular( $rule['value'] ) ) )
181 $give_rule_access = true;
182 break;
183
184 case 'post_type_archive':
185 if ( ( $rule['operator'] === 'equal' && is_post_type_archive( $rule['value'] ) ) || ( $rule['operator'] === 'not_equal' && ! is_post_type_archive( $rule['value'] ) ) )
186 $give_rule_access = true;
187 break;
188
189 case 'user_type':
190 if ( ( $rule['operator'] === 'equal' && $rule['value'] === 'logged_in' && is_user_logged_in() ) || ( $rule['operator'] === 'equal' && $rule['value'] === 'guest' && ! is_user_logged_in() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'logged_in' && ! is_user_logged_in() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'guest' && is_user_logged_in() ) )
191 $give_rule_access = true;
192 break;
193 }
194
195 // condition failed?
196 if ( ! $give_rule_access ) {
197 // group failed
198 $give_group_access = false;
199
200 // finish group checking
201 break;
202 }
203 }
204
205 // whole group successful?
206 if ( $give_group_access ) {
207 // set final access
208 $final_access = $access_type;
209
210 // finish rules checking
211 break;
212 } else
213 $final_access = ! $access_type;
214 }
215 }
216
217 return (bool) apply_filters( 'cn_conditional_display', $final_access, $object );
218 }
219
220 /**
221 * Run Cookie Compliance.
222 *
223 * @return void
224 */
225 public function add_cookie_compliance() {
226 // get main instance
227 $cn = Cookie_Notice();
228
229 // get site language
230 $locale = get_locale();
231 $locale_code = explode( '_', $locale );
232
233 // exceptions, norwegian
234 if ( in_array( $locale_code, [ 'nb', 'nn' ] ) )
235 $locale_code = 'no';
236
237 $options = apply_filters(
238 'cn_cookie_compliance_args',
239 [
240 'appID' => $cn->options['general']['app_id'],
241 'currentLanguage' => $locale_code[0],
242 'blocking' => ! is_user_logged_in() ? $cn->options['general']['app_blocking'] : false,
243 'globalCookie' => is_multisite() && $cn->options['general']['global_cookie'] && is_subdomain_install()
244 ]
245 );
246
247 // debug mode
248 if ( $cn->options['general']['debug_mode'] )
249 $options['debugMode'] = true;
250
251 // custom scripts?
252 if ( $cn->options['general']['app_blocking'] ) {
253 if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] )
254 $blocking = get_site_option( 'cookie_notice_app_blocking' );
255 else
256 $blocking = get_option( 'cookie_notice_app_blocking' );
257
258 $providers = ! empty( $blocking[ 'providers'] ) && is_array( $blocking[ 'providers'] ) ? $this->get_custom_items( $blocking[ 'providers'] ) : [];
259 $patterns = ! empty( $blocking[ 'patterns'] ) && is_array( $blocking[ 'patterns'] ) ? $this->get_custom_items( $blocking[ 'patterns' ] ) : [];
260
261 $options['customProviders'] = ! empty( $providers ) ? $providers : [];
262 $options['customPatterns'] = ! empty( $patterns ) ? $patterns : [];
263 }
264
265 // message output
266 $output = '
267 <!-- Cookie Compliance -->
268 <script type="text/javascript">
269 var huOptions = ' . wp_json_encode( $options ) . ';
270 </script>
271 <script type="text/javascript" src="' . esc_url( $cn->get_url( 'widget' ) ) . '"></script>';
272
273 echo apply_filters( 'cn_cookie_compliance_output', $output, $options );
274 }
275
276 /**
277 * Cookie notice output.
278 *
279 * @return void
280 */
281 public function add_cookie_notice() {
282 // get main instance
283 $cn = Cookie_Notice();
284
285 // WPML >= 3.2
286 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
287 $cn->options['general']['message_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['message_text'], 'Cookie Notice', 'Message in the notice' );
288 $cn->options['general']['accept_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['accept_text'], 'Cookie Notice', 'Button text' );
289 $cn->options['general']['refuse_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['refuse_text'], 'Cookie Notice', 'Refuse button text' );
290 $cn->options['general']['revoke_message_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['revoke_message_text'], 'Cookie Notice', 'Revoke message text' );
291 $cn->options['general']['revoke_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['revoke_text'], 'Cookie Notice', 'Revoke button text' );
292 $cn->options['general']['see_more_opt']['text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['see_more_opt']['text'], 'Cookie Notice', 'Privacy policy text' );
293 $cn->options['general']['see_more_opt']['link'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['see_more_opt']['link'], 'Cookie Notice', 'Custom link' );
294 // WPML and Polylang compatibility
295 } elseif ( function_exists( 'icl_t' ) ) {
296 $cn->options['general']['message_text'] = icl_t( 'Cookie Notice', 'Message in the notice', $cn->options['general']['message_text'] );
297 $cn->options['general']['accept_text'] = icl_t( 'Cookie Notice', 'Button text', $cn->options['general']['accept_text'] );
298 $cn->options['general']['refuse_text'] = icl_t( 'Cookie Notice', 'Refuse button text', $cn->options['general']['refuse_text'] );
299 $cn->options['general']['revoke_message_text'] = icl_t( 'Cookie Notice', 'Revoke message text', $cn->options['general']['revoke_message_text'] );
300 $cn->options['general']['revoke_text'] = icl_t( 'Cookie Notice', 'Revoke button text', $cn->options['general']['revoke_text'] );
301 $cn->options['general']['see_more_opt']['text'] = icl_t( 'Cookie Notice', 'Privacy policy text', $cn->options['general']['see_more_opt']['text'] );
302 $cn->options['general']['see_more_opt']['link'] = icl_t( 'Cookie Notice', 'Custom link', $cn->options['general']['see_more_opt']['link'] );
303 }
304
305 if ( $cn->options['general']['see_more_opt']['link_type'] === 'page' ) {
306 // multisite with global override?
307 if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
308 // get main site id
309 $main_site_id = get_main_site_id();
310
311 // switch to main site
312 switch_to_blog( $main_site_id );
313
314 // update page id for current language if needed
315 if ( function_exists( 'icl_object_id' ) )
316 $cn->options['general']['see_more_opt']['id'] = icl_object_id( $cn->options['general']['see_more_opt']['id'], 'page', true );
317
318 // get main site privacy policy link
319 $permalink = get_permalink( $cn->options['general']['see_more_opt']['id'] );
320
321 // restore current site
322 restore_current_blog();
323 } else {
324 // update page id for current language if needed
325 if ( function_exists( 'icl_object_id' ) )
326 $cn->options['general']['see_more_opt']['id'] = icl_object_id( $cn->options['general']['see_more_opt']['id'], 'page', true );
327
328 // get privacy policy link
329 $permalink = get_permalink( $cn->options['general']['see_more_opt']['id'] );
330 }
331 }
332
333 // get cookie container args
334 $options = apply_filters( 'cn_cookie_notice_args', [
335 'position' => $cn->options['general']['position'],
336 'css_class' => $cn->options['general']['css_class'],
337 'button_class' => 'cn-button',
338 'colors' => $cn->options['general']['colors'],
339 'message_text' => $cn->options['general']['message_text'],
340 'accept_text' => $cn->options['general']['accept_text'],
341 'refuse_text' => $cn->options['general']['refuse_text'],
342 'revoke_message_text' => $cn->options['general']['revoke_message_text'],
343 'revoke_text' => $cn->options['general']['revoke_text'],
344 'refuse_opt' => $cn->options['general']['refuse_opt'],
345 'revoke_cookies' => $cn->options['general']['revoke_cookies'],
346 'see_more' => $cn->options['general']['see_more'],
347 'see_more_opt' => $cn->options['general']['see_more_opt'],
348 'link_target' => $cn->options['general']['link_target'],
349 'link_position' => $cn->options['general']['link_position'],
350 'aria_label' => 'Cookie Notice'
351 ] );
352
353 // message output
354 $output = '
355 <!-- Cookie Notice plugin v' . esc_attr( $cn->defaults['version'] ) . ' by Hu-manity.co https://hu-manity.co/ -->
356 <div id="cookie-notice" role="dialog" class="cookie-notice-hidden cookie-revoke-hidden cn-position-' . esc_attr( $options['position'] ) . '" aria-label="' . esc_attr( $options['aria_label'] ) . '" style="background-color: __CN_BG_COLOR__">'
357 . '<div class="cookie-notice-container" style="color: ' . esc_attr( $options['colors']['text'] ) . '">'
358 . '<span id="cn-notice-text" class="cn-text-container">'. ( $options['see_more'] ? do_shortcode( $options['message_text'] ) : $options['message_text'] ) . '</span>'
359 . '<span id="cn-notice-buttons" class="cn-buttons-container"><a href="#" id="cn-accept-cookie" data-cookie-set="accept" class="cn-set-cookie ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['accept_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['accept_text'] ) . '</a>'
360 . ( $options['refuse_opt'] ? '<a href="#" id="cn-refuse-cookie" data-cookie-set="refuse" class="cn-set-cookie ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['refuse_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['refuse_text'] ) . '</a>' : '' )
361 . ( $options['see_more'] && $options['link_position'] === 'banner' ? '<a href="' . esc_url( $options['see_more_opt']['link_type'] === 'custom' ? $options['see_more_opt']['link'] : $permalink ) . '" target="' . esc_attr( $options['link_target'] ) . '" id="cn-more-info" class="cn-more-info ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['see_more_opt']['text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['see_more_opt']['text'] ) . '</a>' : '' )
362 . '</span><span id="cn-close-notice" data-cookie-set="accept" class="cn-close-icon" title="' . esc_attr( $options['refuse_text'] ) . '"></span>'
363 . '</div>
364 ' . ( $options['refuse_opt'] && $options['revoke_cookies'] ?
365 '<div class="cookie-revoke-container" style="color: ' . esc_attr( $options['colors']['text'] ) . '">'
366 . ( ! empty( $options['revoke_message_text'] ) ? '<span id="cn-revoke-text" class="cn-text-container">' . $options['revoke_message_text'] . '</span>' : '' )
367 . '<span id="cn-revoke-buttons" class="cn-buttons-container"><a href="#" class="cn-revoke-cookie ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['revoke_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['revoke_text'] ) . '</a></span>
368 </div>' : '' ) . '
369 </div>
370 <!-- / Cookie Notice plugin -->';
371
372 add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
373
374 $output = apply_filters( 'cn_cookie_notice_output', wp_kses_post( $output ), $options );
375
376 remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
377
378 // convert rgb color to hex
379 $bg_rgb_color = $this->hex2rgb( $options['colors']['bar'] );
380
381 // invalid color? use default
382 if ( $bg_rgb_color === false )
383 $bg_rgb_color = $this->hex2rgb( $cn->defaults['general']['colors']['bar'] );
384
385 // allow rgba background
386 echo str_replace( '__CN_BG_COLOR__', esc_attr( 'rgba(' . implode( ',', $bg_rgb_color ) . ',' . ( (int) $options['colors']['bar_opacity'] ) * 0.01 . ');' ), $output );
387
388 }
389
390 /**
391 * Add new properties to style safe list.
392 *
393 * @param array $styles
394 * @return array
395 */
396 public function allow_style_attributes( $styles ) {
397 $styles[] = 'display';
398
399 return $styles;
400 }
401
402 /**
403 * Convert HEX to RGB color.
404 *
405 * @param string $color
406 * @return bool|array
407 */
408 public function hex2rgb( $color ) {
409 if ( ! is_string( $color ) )
410 return false;
411
412 // with hash?
413 if ( $color[0] === '#' )
414 $color = substr( $color, 1 );
415
416 if ( sanitize_hex_color_no_hash( $color ) !== $color )
417 return false;
418
419 // 6 hex digits?
420 if ( strlen( $color ) === 6 )
421 list( $r, $g, $b ) = [ $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] ];
422 // 3 hex digits?
423 elseif ( strlen( $color ) === 3 )
424 list( $r, $g, $b ) = [ $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] ];
425 else
426 return false;
427
428 return [ 'r' => hexdec( $r ), 'g' => hexdec( $g ), 'b' => hexdec( $b ) ];
429 }
430
431 /**
432 * Load notice scripts and styles - frontend.
433 *
434 * @return void
435 */
436 public function wp_enqueue_notice_scripts() {
437 // get main instance
438 $cn = Cookie_Notice();
439
440 wp_enqueue_script( 'cookie-notice-front', COOKIE_NOTICE_URL . '/js/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], $cn->defaults['version'], isset( $cn->options['general']['script_placement'] ) && $cn->options['general']['script_placement'] === 'footer' );
441
442 // prepare script data
443 $script_data = [
444 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
445 'nonce' => wp_create_nonce( 'cn_save_cases' ),
446 'hideEffect' => $cn->options['general']['hide_effect'],
447 'position' => $cn->options['general']['position'],
448 'onScroll' => $cn->options['general']['on_scroll'],
449 'onScrollOffset' => (int) $cn->options['general']['on_scroll_offset'],
450 'onClick' => $cn->options['general']['on_click'],
451 'cookieName' => 'cookie_notice_accepted',
452 'cookieTime' => $cn->settings->times[$cn->options['general']['time']][1],
453 'cookieTimeRejected' => $cn->settings->times[$cn->options['general']['time_rejected']][1],
454 'globalCookie' => is_multisite() && $cn->options['general']['global_cookie'] && is_subdomain_install(),
455 'redirection' => $cn->options['general']['redirection'],
456 'cache' => defined( 'WP_CACHE' ) && WP_CACHE,
457 'revokeCookies' => $cn->options['general']['revoke_cookies'],
458 'revokeCookiesOpt' => $cn->options['general']['revoke_cookies_opt']
459 ];
460
461 wp_add_inline_script( 'cookie-notice-front', 'var cnArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
462
463 wp_enqueue_style( 'cookie-notice-front', COOKIE_NOTICE_URL . '/css/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css' );
464 }
465
466 /**
467 * Make a JavaScript Asynchronous.
468 *
469 * @param string $tag The original enqueued script tag
470 * @param string $handle The registered unique name of the script
471 * @param string $src
472 * @return string $tag
473 */
474 public function wp_enqueue_script_async( $tag, $handle, $src ) {
475 if ( $handle === 'cookie-notice-front' )
476 $tag = str_replace( '<script', '<script async', $tag );
477
478 return $tag;
479 }
480
481 /**
482 * Print non functional JavaScript in body.
483 *
484 * @return void
485 */
486 public function wp_print_footer_scripts() {
487 // get main instance
488 $cn = Cookie_Notice();
489
490 if ( $cn->cookies_accepted() ) {
491 $scripts = apply_filters( 'cn_refuse_code_scripts_html', $cn->options['general']['refuse_code'], 'body' );
492
493 if ( ! empty( $scripts ) )
494 echo html_entity_decode( wp_kses( $scripts, $cn->get_allowed_html() ) );
495 }
496 }
497
498 /**
499 * Print non functional JavaScript in header.
500 *
501 * @return void
502 */
503 public function wp_print_header_scripts() {
504 // get main instance
505 $cn = Cookie_Notice();
506
507 if ( $cn->cookies_accepted() ) {
508 $scripts = apply_filters( 'cn_refuse_code_scripts_html', $cn->options['general']['refuse_code_head'], 'head' );
509
510 if ( ! empty( $scripts ) )
511 echo html_entity_decode( wp_kses( $scripts, $cn->get_allowed_html() ) );
512 }
513 }
514
515 /**
516 * Get custom providers or patterns.
517 *
518 * @param array $items
519 * @return array
520 */
521 public function get_custom_items( $items ) {
522 $result = [];
523
524 if ( ! empty( $items ) && is_array( $items ) ) {
525 foreach ( $items as $index => $item ) {
526 if ( isset( $item->IsCustom ) && $item->IsCustom == true ) {
527 $sanitized_item = [];
528
529 foreach ( $item as $key => $value ) {
530 $sanitized_item[$key] = $this->sanitize_field( $value, $key );
531 }
532
533 $result[] = (object) $sanitized_item;
534 }
535 }
536 }
537
538 return $result;
539 }
540
541 /**
542 * Sanitize field.
543 *
544 * @param mixed $value
545 * @param string $key
546 * @return mixed
547 */
548 private function sanitize_field( $value, $key ) {
549 $sanitized_value = $value;
550
551 switch ( $key ) {
552 case 'CategoryID':
553 $sanitized_value = (int) $value;
554 break;
555
556 case 'IsCustom':
557 $sanitized_value = (bool) $value;
558 break;
559 }
560
561 return $sanitized_value;
562 }
563
564 /**
565 * Add new body classes.
566 *
567 * @param array $classes Body classes
568 * @return array
569 */
570 public function change_body_class( $classes ) {
571 if ( is_admin() )
572 return $classes;
573
574 if ( Cookie_Notice()->cookies_set() ) {
575 $classes[] = 'cookies-set';
576
577 if ( Cookie_Notice()->cookies_accepted() )
578 $classes[] = 'cookies-accepted';
579 else
580 $classes[] = 'cookies-refused';
581 } else
582 $classes[] = 'cookies-not-set';
583
584 return $classes;
585 }
586
587 /**
588 * Purge config cache.
589 *
590 * @return void
591 */
592 public function purge_cache() {
593 // get main instance
594 $cn = Cookie_Notice();
595
596 if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
597 $app_id = $cn->network_options['app_id'];
598 $app_key = $cn->network_options['app_key'];
599 } else {
600 $app_id = $cn->options['general']['app_id'];
601 $app_key = $cn->options['general']['app_key'];
602 }
603
604 // compliance active only
605 if ( $app_id !== '' && $app_key !== '' ) {
606 // request for new config data too
607 $cn->welcome_api->get_app_config( $app_id, true );
608 }
609 }
610 }
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Check if cookies are accepted.
8 *
9 * @return bool Whether cookies are accepted
10 */
11 if ( ! function_exists( 'cn_cookies_accepted' ) ) {
12 function cn_cookies_accepted() {
13 return (bool) Cookie_Notice::cookies_accepted();
14 }
15 }
16
17 /**
18 * Check if cookies are set.
19 *
20 * @return bool Whether cookies are set
21 */
22 if ( ! function_exists( 'cn_cookies_set' ) ) {
23 function cn_cookies_set() {
24 return (bool) Cookie_Notice::cookies_set();
25 }
26 }
27
28 /**
29 * Get active caching plugins.
30 *
31 * @param array $args
32 * @return array
33 */
34 function cn_get_active_caching_plugins( $args = [] ) {
35 if ( isset( $args['versions'] ) && $args['versions'] === true )
36 $version = true;
37 else
38 $version = false;
39
40 $active_plugins = [];
41
42 // autoptimize 2.4.0+
43 if ( cn_is_plugin_active( 'autoptimize' ) ) {
44 if ( $version )
45 $active_plugins['Autoptimize'] = '2.4.0';
46 else
47 $active_plugins[] = 'Autoptimize';
48 }
49
50 // litespeed 3.0.0+
51 if ( cn_is_plugin_active( 'litespeed' ) ) {
52 if ( $version )
53 $active_plugins['LiteSpeed Cache'] = '3.0.0';
54 else
55 $active_plugins[] = 'LiteSpeed Cache';
56 }
57
58 // siteground optimizer 5.5.0+
59 if ( cn_is_plugin_active( 'sgoptimizer' ) ) {
60 if ( $version )
61 $active_plugins['SiteGround Optimizer'] = '5.5.0';
62 else
63 $active_plugins[] = 'SiteGround Optimizer';
64 }
65
66 // wp fastest cache 1.0.0+
67 if ( cn_is_plugin_active( 'wpfastestcache' ) ) {
68 if ( $version )
69 $active_plugins['WP Fastest Cache'] = '1.0.0';
70 else
71 $active_plugins[] = 'WP Fastest Cache';
72 }
73
74 // wp rocket 3.8.0+
75 if ( cn_is_plugin_active( 'wprocket' ) ) {
76 if ( $version )
77 $active_plugins['WP Rocket'] = '3.8.0';
78 else
79 $active_plugins[] = 'WP Rocket';
80 }
81
82 // wp super cache 1.6.9+
83 // if ( cn_is_plugin_active( 'wpsupercache' ) ) {
84 // if ( $version )
85 // $active_plugins['WP Super Cache'] = '1.6.9';
86 // else
87 // $active_plugins[] = 'WP Super Cache';
88 // }
89
90 return $active_plugins;
91 }
92
93 /**
94 * Check whether specified plugin is active.
95 *
96 * @global object $siteground_optimizer_loader
97 * @global int $wpsc_version
98 *
99 * @return bool
100 */
101 function cn_is_plugin_active( $plugin = '' ) {
102 // no valid plugin?
103 if ( ! in_array( $plugin, [ 'autoptimize', 'litespeed', 'sgoptimizer', 'wpfastestcache', 'wprocket', 'wpsupercache', 'contactform7', 'elementor' ], true ) )
104 return false;
105
106 global $siteground_optimizer_loader;
107 global $wpsc_version;
108
109 // autoptimize 2.4.0+
110 if ( $plugin === 'autoptimize' && function_exists( 'autoptimize' ) && defined( 'AUTOPTIMIZE_PLUGIN_VERSION' ) && version_compare( AUTOPTIMIZE_PLUGIN_VERSION, '2.4', '>=' ) )
111 return true;
112 // litespeed 3.0.0+
113 elseif ( $plugin === 'litespeed' && class_exists( 'LiteSpeed\Core' ) && defined( 'LSCWP_CUR_V' ) && version_compare( LSCWP_CUR_V, '3.0', '>=' ) )
114 return true;
115 // siteground optimizer 5.5.0+
116 elseif ( $plugin === 'sgoptimizer' && ! empty( $siteground_optimizer_loader ) && is_object( $siteground_optimizer_loader ) && is_a( $siteground_optimizer_loader, 'SiteGround_Optimizer\Loader\Loader' ) && defined( '\SiteGround_Optimizer\VERSION' ) && version_compare( \SiteGround_Optimizer\VERSION, '5.5', '>=' ) )
117 return true;
118 // wp fastest cache 1.0.0+
119 elseif ( $plugin === 'wpfastestcache' && function_exists( 'wpfc_clear_all_cache' ) )
120 return true;
121 // wp rocket 3.8.0+
122 elseif ( $plugin === 'wprocket' && function_exists( 'rocket_init' ) && defined( 'WP_ROCKET_VERSION' ) && version_compare( WP_ROCKET_VERSION, '3.8', '>=' ) )
123 return true;
124 // wp super cache 1.6.9+
125 // elseif ( $plugin === 'wpsupercache' && ( ( ! empty( $wpsc_version ) && $wpsc_version >= 169 ) || ( defined( 'WPSC_VERSION' ) && version_compare( WPSC_VERSION, '1.6.9', '>=' ) ) ) )
126 // return true;
127 // contact form 5.1.0+
128 elseif ( $plugin === 'contactform7' && class_exists( 'WPCF7' ) && class_exists( 'WPCF7_RECAPTCHA' ) && defined( 'WPCF7_VERSION' ) && version_compare( WPCF7_VERSION, '5.1', '>=' ) )
129 return true;
130 // elementor 1.3.0+
131 elseif ( $plugin === 'elementor' && did_action( 'elementor/loaded' ) && defined( 'ELEMENTOR_VERSION' ) && version_compare( ELEMENTOR_VERSION, '1.3', '>=' ) )
132 return true;
133
134 return false;
135 }
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules Autoptimize class.
8 *
9 * Compatibility since: 2.4.0
10 *
11 * @class Cookie_Notice_Modules_Autoptimize
12 */
13 class Cookie_Notice_Modules_Autoptimize {
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_filter( 'autoptimize_filter_js_exclude', [ $this, 'exclude' ] );
22 }
23
24 /**
25 * Exclude JavaScript files or inline code.
26 *
27 * @param string $excludes
28 * @return string
29 */
30 function exclude( $excludes ) {
31 if ( empty( $excludes ) )
32 $new_excludes = [];
33 else {
34 $new_excludes = explode( ',', $excludes );
35 $new_excludes = array_filter( $new_excludes );
36 $new_excludes = array_map( 'trim', $new_excludes );
37 }
38
39 // not found huOptions?
40 if ( strpos( $excludes, 'huOptions' ) === false )
41 $new_excludes[] = 'huOptions';
42
43 // get widget url
44 $widget_url = basename( Cookie_Notice()->get_url( 'widget' ) );
45
46 // not found widget url?
47 if ( strpos( $excludes, $widget_url ) === false )
48 $new_excludes[] = $widget_url;
49
50 return implode( ', ', $new_excludes );
51 }
52 }
53
54 new Cookie_Notice_Modules_Autoptimize();
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules Contact Form 7 class.
8 *
9 * Compatibility since: 5.1.0 (recaptcha v3 only)
10 *
11 * @class Cookie_Notice_Modules_ContactForm7
12 */
13 class Cookie_Notice_Modules_ContactForm7 {
14
15 private $service;
16
17 /**
18 * Constructor.
19 *
20 * @return void
21 */
22 public function __construct() {
23 $this->service = WPCF7_RECAPTCHA::get_instance();
24
25 if ( $this->service->is_active() )
26 add_action( 'wp_enqueue_scripts', [ $this, 'contact_form_7_recaptcha' ], 21 );
27 }
28
29 /**
30 * Replace original recaptcha script from Contact Form 7.
31 *
32 * @return void
33 */
34 public function contact_form_7_recaptcha() {
35 // deregister original script
36 wp_deregister_script( 'wpcf7-recaptcha' );
37
38 // register new script
39 wp_register_script(
40 'wpcf7-recaptcha',
41 COOKIE_NOTICE_URL . '/includes/modules/contact-form-7/recaptcha.js',
42 [
43 'google-recaptcha',
44 'wp-polyfill'
45 ],
46 WPCF7_VERSION,
47 true
48 );
49
50 wp_enqueue_script( 'wpcf7-recaptcha' );
51
52 wp_localize_script(
53 'wpcf7-recaptcha',
54 'wpcf7_recaptcha',
55 [
56 'sitekey' => $this->service->get_sitekey(),
57 'actions' => apply_filters(
58 'wpcf7_recaptcha_actions',
59 [
60 'homepage' => 'homepage',
61 'contactform' => 'contactform'
62 ]
63 )
64 ]
65 );
66 }
67 }
68
69 new Cookie_Notice_Modules_ContactForm7();
...\ No newline at end of file ...\ No newline at end of file
1 ( function( window, document, undefined ) {
2
3 'use strict';
4
5 /**
6 * Initialize recaptcha.
7 *
8 * @return {void}
9 */
10 function initRecaptcha() {
11 wpcf7_recaptcha = {
12 ...( wpcf7_recaptcha ?? {} )
13 };
14
15 const siteKey = wpcf7_recaptcha.sitekey;
16 const { homepage, contactform } = wpcf7_recaptcha.actions;
17
18 const execute = options => {
19 const { action, func, params } = options;
20
21 grecaptcha.execute( siteKey, {
22 action,
23 } ).then( token => {
24 const event = new CustomEvent( 'wpcf7grecaptchaexecuted', {
25 detail: {
26 action,
27 token
28 }
29 } );
30
31 document.dispatchEvent( event );
32 } ).then( () => {
33 if ( typeof func === 'function' ) {
34 func( ...params );
35 }
36 } ).catch( error => console.error( error ) );
37 };
38
39 grecaptcha.ready( () => {
40 execute( {
41 action: homepage
42 } );
43 } );
44
45 document.addEventListener( 'change', event => {
46 execute( {
47 action: contactform
48 } );
49 } );
50
51 if ( typeof wpcf7 !== 'undefined' && typeof wpcf7.submit === 'function' ) {
52 const submit = wpcf7.submit;
53
54 wpcf7.submit = ( form, options = {} ) => {
55 execute( {
56 action: contactform,
57 func: submit,
58 params: [ form, options ]
59 } );
60 };
61 }
62
63 document.addEventListener( 'wpcf7grecaptchaexecuted', event => {
64 const fields = document.querySelectorAll( 'form.wpcf7-form input[name="_wpcf7_recaptcha_response"]' );
65
66 for ( let i = 0; i < fields.length; i++ ) {
67 let field = fields[ i ];
68
69 field.setAttribute( 'value', event.detail.token );
70 }
71 } );
72 }
73
74 /**
75 * Handle cookies-unblocked event.
76 *
77 * @return {void}
78 */
79 document.addEventListener( 'cookies-unblocked.hu', function( e ) {
80 e.detail.data.scripts.forEach( function( script ) {
81 // find google recaptcha in valid category
82 if ( script.id === 'google-recaptcha-js' && e.detail.categories[script.dataset.huCategory] === true ) {
83 script.onload = initRecaptcha;
84 script.onreadystatechange = initRecaptcha;
85 }
86 } );
87 }, false );
88
89 } )( window, document );
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules Elementor class.
8 *
9 * Compatibility since: 1.3.0
10 *
11 * @class Cookie_Notice_Modules_Elementor
12 */
13 class Cookie_Notice_Modules_Elementor {
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_filter( 'cn_is_preview_mode', [ $this, 'is_preview_mode' ] );
22 }
23
24 /**
25 * Whether elementor editor is active.
26 *
27 * @return bool
28 */
29 function is_preview_mode() {
30 return \Elementor\Plugin::$instance->preview->is_preview_mode();
31 }
32 }
33
34 new Cookie_Notice_Modules_Elementor();
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules LiteSpeed Cache class.
8 *
9 * Compatibility since: 3.0.0
10 *
11 * @class Cookie_Notice_Modules_LiteSpeedCache
12 */
13 class Cookie_Notice_Modules_LiteSpeedCache {
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_filter( 'litespeed_optimize_js_excludes', [ $this, 'exclude_js' ] );
22 add_filter( 'litespeed_optm_js_defer_exc ', [ $this, 'exclude_js' ] );
23 }
24
25 /**
26 * Exclude JavaScript external file and inline code.
27 *
28 * @param array $excludes
29 * @return array
30 */
31 function exclude_js( $excludes ) {
32 // add widget url
33 $excludes[] = basename( Cookie_Notice()->get_url( 'widget' ) );
34
35 // add widget inline code
36 $excludes[] = 'huOptions';
37
38 return $excludes;
39 }
40 }
41
42 new Cookie_Notice_Modules_LiteSpeedCache();
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules SiteGround Optimizer class.
8 *
9 * Compatibility since: 5.5.0
10 *
11 * @class Cookie_Notice_Modules_SGOptimizer
12 */
13 class Cookie_Notice_Modules_SGOptimizer {
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_filter( 'sgo_javascript_combine_excluded_external_paths', [ $this, 'exclude_script' ] );
22 add_filter( 'sgo_javascript_combine_excluded_inline_content', [ $this, 'exclude_code' ] );
23 }
24
25 /**
26 * Exclude JavaScript file.
27 *
28 * @param array $excludes
29 * @return array
30 */
31 function exclude_script( $excludes ) {
32 // add widget url
33 $excludes[] = basename( Cookie_Notice()->get_url( 'widget' ) );
34
35 return $excludes;
36 }
37
38 /**
39 * Exclude JavaScript inline code.
40 *
41 * @param array $excludes
42 * @return array
43 */
44 function exclude_code( $excludes ) {
45 // add widget inline code
46 $excludes[] = 'huOptions';
47
48 return $excludes;
49 }
50 }
51
52 new Cookie_Notice_Modules_SGOptimizer();
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules WP Fastest Cache class.
8 *
9 * Compatibility since: 1.0.0
10 *
11 * @class Cookie_Notice_Modules_WPFastestCache
12 */
13 class Cookie_Notice_Modules_WPFastestCache {
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_action( 'admin_init', [ $this, 'check_wpfc' ], 11 );
22 }
23
24 /**
25 * Compatibility with WP Fastest Cache plugin.
26 *
27 * @return void
28 */
29 public function check_wpfc() {
30 // is preloading enabled?
31 if ( isset( $GLOBALS['wp_fastest_cache_options']->wpFastestCachePreload ) )
32 $this->disable_preload( $GLOBALS['wp_fastest_cache_options'] );
33
34 // is caching enabled?
35 if ( isset( $GLOBALS['wp_fastest_cache_options']->wpFastestCacheStatus ) ) {
36 // update 2.4.9+
37 if ( version_compare( Cookie_Notice()->db_version, '2.4.9', '<=' ) )
38 $this->delete_cache();
39
40 add_action( 'updated_option', [ $this, 'check_updated_option' ], 10, 3 );
41 }
42 }
43
44 /**
45 * Delete cache files after updating Cookie Notice settings or status.
46 *
47 * @return void
48 */
49 public function check_updated_option( $option, $old_value, $new_value ) {
50 if ( $option === 'cookie_notice_status' || $option === 'cookie_notice_options' )
51 $this->delete_cache();
52 }
53
54 /**
55 * Disable preloading.
56 *
57 * @param object $options
58 * @return void
59 */
60 private function disable_preload( $options ) {
61 // disable preload
62 unset( $options->wpFastestCachePreload );
63
64 // delete preload option
65 delete_option( 'WpFastestCachePreLoad' );
66
67 // clear preload hook
68 wp_clear_scheduled_hook( 'wp_fastest_cache_Preload' );
69
70 // update options
71 update_option( 'WpFastestCache', json_encode( $options ) );
72 }
73
74 /**
75 * Delete all cache files.
76 *
77 * @return void
78 */
79 private function delete_cache() {
80 // check constant and function existence
81 if ( defined( 'WPFC_DISABLE_HOOK_CLEAR_ALL_CACHE' ) && WPFC_DISABLE_HOOK_CLEAR_ALL_CACHE && isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ) {
82 // bypass constant and call function directly
83 $GLOBALS['wp_fastest_cache']->deleteCache( true );
84 } else {
85 // call function normally
86 wpfc_clear_all_cache( true );
87 }
88 }
89 }
90
91 new Cookie_Notice_Modules_WPFastestCache();
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie Notice Modules WP Rocket Optimizer class.
8 *
9 * Compatibility since: 3.8.0
10 *
11 * @class Cookie_Notice_Modules_WPRocket
12 */
13 class Cookie_Notice_Modules_WPRocket {
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_filter( 'rocket_exclude_defer_js', [ $this, 'exclude_script' ] );
22 add_filter( 'rocket_defer_inline_exclusions ', [ $this, 'exclude_code' ] );
23 }
24
25 /**
26 * Exclude JavaScript file.
27 *
28 * @param array $excludes
29 * @return array
30 */
31 function exclude_script( $excludes ) {
32 // add widget url
33 $excludes[] = basename( Cookie_Notice()->get_url( 'widget' ) );
34
35 return $excludes;
36 }
37
38 /**
39 * Exclude JavaScript inline code.
40 *
41 * @param array $excludes
42 * @return array
43 */
44 function exclude_code( $excludes ) {
45 // add widget inline code
46 $excludes[] = 'huOptions';
47
48 return $excludes;
49 }
50 }
51
52 new Cookie_Notice_Modules_WPRocket();
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie_Notice_Settings class.
8 *
9 * @class Cookie_Notice_Settings
10 */
11 class Cookie_Notice_Settings {
12
13 public $parameters = [];
14 public $operators = [];
15 public $conditional_display_types = [];
16 public $positions = [];
17 public $styles = [];
18 public $revoke_opts = [];
19 public $links = [];
20 public $link_targets = [];
21 public $link_positions = [];
22 public $colors = [];
23 public $times = [];
24 public $effects = [];
25 public $script_placements = [];
26 public $level_names = [];
27 public $text_strings = [];
28 private $analytics_app_data = [];
29
30 /**
31 * Class constructor.
32 *
33 * @return void
34 */
35 public function __construct() {
36 // actions
37 add_action( 'admin_menu', [ $this, 'admin_menu_options' ] );
38 add_action( 'network_admin_menu', [ $this, 'admin_menu_options' ] );
39 add_action( 'after_setup_theme', [ $this, 'load_defaults' ] );
40 add_action( 'admin_init', [ $this, 'load_modules' ] );
41 add_action( 'admin_init', [ $this, 'validate_network_options' ], 9 );
42 add_action( 'admin_init', [ $this, 'register_settings' ] );
43 add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
44 add_action( 'admin_print_styles', [ $this, 'admin_print_styles' ] );
45 add_action( 'wp_ajax_cn_purge_cache', [ $this, 'ajax_purge_cache' ] );
46 add_action( 'wp_ajax_cn-get-group-rules-values', [ $this, 'get_group_rule_values' ] );
47 add_action( 'admin_notices', [ $this, 'settings_errors' ] );
48 add_action( 'network_admin_notices', [ $this, 'settings_errors' ] );
49 }
50
51 /**
52 * Load additional modules.
53 *
54 * @return void
55 */
56 public function load_modules() {
57 if ( Cookie_Notice()->options['general']['caching_compatibility'] ) {
58 // wp fastest cache
59 if ( cn_is_plugin_active( 'wpfastestcache' ) )
60 include_once( COOKIE_NOTICE_PATH . 'includes/modules/wp-fastest-cache/wp-fastest-cache.php' );
61 }
62 }
63
64 /**
65 * Load plugin defaults.
66 *
67 * @return void
68 */
69 public function load_defaults() {
70 $this->parameters = [
71 'page_type' => __( 'Page Type', 'cookie-notice' ),
72 'page' => __( 'Page', 'cookie-notice' ),
73 'post_type' => __( 'Post Type', 'cookie-notice' ),
74 'post_type_archive' => __( 'Post Type Archive', 'cookie-notice' ),
75 'user_type' => __( 'User Type', 'cookie-notice' )
76 ];
77
78 $this->operators = [
79 'equal' => __( 'is equal to', 'cookie-notice' ),
80 'not_equal' => __( 'is not equal to', 'cookie-notice' )
81 ];
82
83 $this->conditional_display_types = [
84 'hide' => __( 'Hide the banner', 'cookie-notice' ),
85 'show' => __( 'Show the banner', 'cookie-notice' )
86 ];
87
88 $this->positions = [
89 'top' => __( 'Top', 'cookie-notice' ),
90 'bottom' => __( 'Bottom', 'cookie-notice' )
91 ];
92
93 $this->styles = [
94 'none' => __( 'None', 'cookie-notice' ),
95 'wp-default' => __( 'Light', 'cookie-notice' ),
96 'bootstrap' => __( 'Dark', 'cookie-notice' )
97 ];
98
99 $this->revoke_opts = [
100 'automatic' => __( 'Automatic', 'cookie-notice' ),
101 'manual' => __( 'Manual', 'cookie-notice' )
102 ];
103
104 $this->links = [
105 'page' => __( 'Page link', 'cookie-notice' ),
106 'custom' => __( 'Custom link', 'cookie-notice' )
107 ];
108
109 $this->link_targets = [ '_blank', '_self' ];
110
111 $this->link_positions = [
112 'banner' => __( 'Banner', 'cookie-notice' ),
113 'message' => __( 'Message', 'cookie-notice' )
114 ];
115
116 $this->colors = [
117 'text' => __( 'Text color', 'cookie-notice' ),
118 'button' => __( 'Button color', 'cookie-notice' ),
119 'bar' => __( 'Bar color', 'cookie-notice' )
120 ];
121
122 $this->times = apply_filters(
123 'cn_cookie_expiry',
124 [
125 'hour' => [ __( 'An hour', 'cookie-notice' ), 3600 ],
126 'day' => [ __( '1 day', 'cookie-notice' ), 86400 ],
127 'week' => [ __( '1 week', 'cookie-notice' ), 604800 ],
128 'month' => [ __( '1 month', 'cookie-notice' ), 2592000 ],
129 '3months' => [ __( '3 months', 'cookie-notice' ), 7862400 ],
130 '6months' => [ __( '6 months', 'cookie-notice' ), 15811200 ],
131 'year' => [ __( '1 year', 'cookie-notice' ), 31536000 ],
132 'infinity' => [ __( 'infinity', 'cookie-notice' ), 2147483647 ]
133 ]
134 );
135
136 $this->effects = [
137 'none' => __( 'None', 'cookie-notice' ),
138 'fade' => __( 'Fade', 'cookie-notice' ),
139 'slide' => __( 'Slide', 'cookie-notice' )
140 ];
141
142 $this->script_placements = [
143 'header' => __( 'Header', 'cookie-notice' ),
144 'footer' => __( 'Footer', 'cookie-notice' )
145 ];
146
147 $this->level_names = [
148 1 => [
149 1 => __( 'Silver', 'cookie-notice' ),
150 2 => __( 'Gold', 'cookie-notice' ),
151 3 => __( 'Platinum', 'cookie-notice' )
152 ],
153 2 => [
154 1 => __( 'Private', 'cookie-notice' ),
155 2 => __( 'Balanced', 'cookie-notice' ),
156 3 => __( 'Personalized', 'cookie-notice' )
157 ],
158 3 => [
159 1 => __( 'Reject All', 'cookie-notice' ),
160 2 => __( 'Accept Some', 'cookie-notice' ),
161 3 => __( 'Accept All', 'cookie-notice' )
162 ]
163 ];
164
165 $this->text_strings = [
166 'saveBtnText' => __( 'Save my preferences', 'cookie-notice' ),
167 'privacyBtnText' => __( 'Privacy policy', 'cookie-notice' ),
168 'dontSellBtnText' => __( 'Do Not Sell', 'cookie-notice' ),
169 'customizeBtnText' => __( 'Preferences', 'cookie-notice' ),
170 'headingText' => __( "We believe your data is your property and support your right to privacy and transparency.", 'cookie-notice' ),
171 'bodyText' => __( "Select a Data Access Level and Duration to choose how we use and share your data.", 'cookie-notice' ),
172 'levelBodyText_1' => __( 'Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device.', 'cookie-notice' ),
173 'levelBodyText_2' => __( 'Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site.', 'cookie-notice' ),
174 'levelBodyText_3' => __( 'Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit.', 'cookie-notice' ),
175 'levelNameText_1' => $this->level_names[1][1],
176 'levelNameText_2' => $this->level_names[1][2],
177 'levelNameText_3' => $this->level_names[1][3],
178 'monthText' => __( 'month', 'cookie-notice' ),
179 'monthsText' => __( 'months', 'cookie-notice' )
180 ];
181
182 // get main instance
183 $cn = Cookie_Notice();
184
185 // set default text strings
186 $cn->defaults['general']['message_text'] = __( 'We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.', 'cookie-notice' );
187 $cn->defaults['general']['accept_text'] = __( 'Ok', 'cookie-notice' );
188 $cn->defaults['general']['refuse_text'] = __( 'No', 'cookie-notice' );
189 $cn->defaults['general']['revoke_message_text'] = __( 'You can revoke your consent any time using the Revoke consent button.', 'cookie-notice' );
190 $cn->defaults['general']['revoke_text'] = __( 'Revoke consent', 'cookie-notice' );
191 $cn->defaults['general']['see_more_opt']['text'] = __( 'Privacy policy', 'cookie-notice' );
192
193 // set translation strings on plugin activation
194 if ( $cn->options['general']['translate'] === true ) {
195 $cn->options['general']['translate'] = false;
196
197 $cn->options['general']['message_text'] = $cn->defaults['general']['message_text'];
198 $cn->options['general']['accept_text'] = $cn->defaults['general']['accept_text'];
199 $cn->options['general']['refuse_text'] = $cn->defaults['general']['refuse_text'];
200 $cn->options['general']['revoke_message_text'] = $cn->defaults['general']['revoke_message_text'];
201 $cn->options['general']['revoke_text'] = $cn->defaults['general']['revoke_text'];
202 $cn->options['general']['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text'];
203
204 if ( $cn->is_network_admin() )
205 update_site_option( 'cookie_notice_options', $cn->options['general'] );
206 else
207 update_option( 'cookie_notice_options', $cn->options['general'] );
208 }
209
210 // WPML >= 3.2
211 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
212 $this->register_wpml_strings();
213 // WPML and Polylang compatibility
214 } elseif ( function_exists( 'icl_register_string' ) ) {
215 icl_register_string( 'Cookie Notice', 'Message in the notice', $cn->options['general']['message_text'] );
216 icl_register_string( 'Cookie Notice', 'Button text', $cn->options['general']['accept_text'] );
217 icl_register_string( 'Cookie Notice', 'Refuse button text', $cn->options['general']['refuse_text'] );
218 icl_register_string( 'Cookie Notice', 'Revoke message text', $cn->options['general']['revoke_message_text'] );
219 icl_register_string( 'Cookie Notice', 'Revoke button text', $cn->options['general']['revoke_text'] );
220 icl_register_string( 'Cookie Notice', 'Privacy policy text', $cn->options['general']['see_more_opt']['text'] );
221 icl_register_string( 'Cookie Notice', 'Custom link', $cn->options['general']['see_more_opt']['link'] );
222 }
223 }
224
225 /**
226 * Add submenu.
227 *
228 * @return void
229 */
230 public function admin_menu_options() {
231 if ( current_action() === 'network_admin_menu' && ! Cookie_Notice()->is_plugin_network_active() )
232 return;
233
234 add_menu_page( __( 'Cookie Notice', 'cookie-notice' ), __( 'Cookies', 'cookie-notice' ), apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ), 'cookie-notice', [ $this, 'options_page' ], 'none', '99.300' );
235 }
236
237 /**
238 * Options page output.
239 *
240 * @return void
241 */
242 public function options_page() {
243 // get main instance
244 $cn = Cookie_Notice();
245
246 // get cookie compliance status
247 $status = $cn->get_status();
248 $subscription = $cn->get_subscription();
249 $upgrade_link = $cn->get_url( 'host', '?utm_campaign=upgrade+to+pro&utm_source=wordpress&utm_medium=link#/en/cc/dashboard?app-id=' . $cn->options['general']['app_id'] . '&open-modal=payment' );
250
251 echo '
252 <div class="wrap">
253 <h2>' . esc_html__( 'Cookie Notice & Compliance for GDPR/CCPA', 'cookie-notice' ) . '</h2>
254 <div class="cookie-notice-settings">
255 <div class="cookie-notice-sidebar">
256 <div class="cookie-notice-credits">
257 <div class="inside">
258 <div class="inner">';
259
260 // compliance enabled
261 if ( $status === 'active' ) {
262 echo '
263 <div class="cn-pricing-info">
264 <div class="cn-pricing-head">
265 <p>' . esc_html__( 'Your Cookie Compliance plan:', 'cookie-notice' ) . '</p>
266 <h2>' . esc_html( $subscription === 'pro' ? __( 'Professional', 'cookie-notice' ) : __( 'Basic', 'cookie-notice' ) ) . '</h2>
267 </div>
268 <div class="cn-pricing-body">
269 <p class="cn-active"><span class="cn-icon"></span>' . esc_html__( 'GDPR, CCPA, LGPD, PECR requirements', 'cookie-notice' ) . '</p>
270 <p class="cn-active"><span class="cn-icon"></span>' . esc_html__( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
271 <p class="' . ( $subscription === 'pro' ? 'cn-active' : 'cn-inactive' ) . '"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s visits', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
272 <p class="' . ( $subscription === 'pro' ? 'cn-active' : 'cn-inactive' ) . '"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sLifetime%s consent storage', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
273 <p class="' . ( $subscription === 'pro' ? 'cn-active' : 'cn-inactive' ) . '"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGoogle & Facebook%s consent modes', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
274 <p class="' . ( $subscription === 'pro' ? 'cn-active' : 'cn-inactive' ) . '"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGeolocation%s support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
275 <p class="' . ( $subscription === 'pro' ? 'cn-active' : 'cn-inactive' ) . '"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s languages', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
276 <p class="' . ( $subscription === 'pro' ? 'cn-active' : 'cn-inactive' ) . '"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sPriority%s Support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
277 </div>';
278
279 if ( $subscription !== 'pro' ) {
280 echo ' <div class="cn-pricing-footer">
281 <a href="' . esc_url( $upgrade_link ) . '" class="button button-secondary button-hero cn-button" target="_blank">' . esc_html__( 'Upgrade to Pro', 'cookie-notice' ) . '</a>
282 </div>';
283 }
284
285 echo ' </div>';
286 // compliance disabled
287 } else {
288 echo ' <h1><b>' . esc_html__( 'Protect your business', 'cookie-notice' ) . '</b></h1>
289 <h2>' . esc_html__( 'with Cookie Compliance&trade;', 'cookie-notice' ) . '</h2>
290 <div class="cn-lead">
291 <p>' . esc_html__( 'Deliver better consent experiences and comply with GDPR, CCPA and other data privacy laws more effectively.', 'cookie-notice' ) . '</p>
292 </div>
293 <img alt="' . esc_html__( 'Cookie Compliance dashboard', 'cookie-notice' ) . '" src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/screen-compliance.png">
294 <p><a href="https://cookie-compliance.co/?utm_campaign=learn+more&utm_source=wordpress&utm_medium=banner" class="button button-secondary button-hero cn-button" target="_blank">' . esc_html__( 'Learn more', 'cookie-notice' ) . '</a></p>';
295 }
296
297 echo '
298 </div>
299 </div>
300 </div>';
301
302 echo '
303 <div class="cookie-notice-faq">
304 <h2>' . esc_html__( 'F.A.Q.', 'cookie-notice' ) . '</h2>
305 <div class="cn-toggle-container">
306 <label for="cn-faq-1" class="cn-toggle-item">
307 <input id="cn-faq-1" type="checkbox" />
308 <span class="cn-toggle-heading">' . esc_html__( 'Does the Cookie Notice make my site fully compliant with GDPR?', 'cookie-notice' ) . '</span>
309 <span class="cn-toggle-body">' . esc_html__( 'It is not possible to provide the required technical compliance features using only a WordPress plugin. Features like consent record storage, purpose categories and script blocking that bring your site into full compliance with GDPR are only available through the Cookie Compliance integration.', 'cookie-notice' ) . '
310 </label>
311 <label for="cn-faq-2" class="cn-toggle-item">
312 <input id="cn-faq-2" type="checkbox" />
313 <span class="cn-toggle-heading">' . esc_html__( 'Does the Cookie Compliance integration make my site fully compliant with GDPR?', 'cookie-notice' ) . '</span>
314 <span class="cn-toggle-body">' . esc_html__( 'Yes! The plugin + web application version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions.', 'cookie-notice' ) . '</span>
315 </label>
316 <label for="cn-faq-3" class="cn-toggle-item">
317 <input id="cn-faq-3" type="checkbox" />
318 <span class="cn-toggle-heading">' . esc_html__( 'Is Cookie Compliance free?', 'cookie-notice' ) . '</span>
319 <span class="cn-toggle-body">' . esc_html__( 'Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website monthly traffic.', 'cookie-notice' ) . '</span>
320 </label>
321 <label for="cn-faq-4" class="cn-toggle-item">
322 <input id="cn-faq-4" type="checkbox" />
323 <span class="cn-toggle-heading">' . esc_html__( 'Where can I find pricing options?', 'cookie-notice' ) . '</span>
324 <span class="cn-toggle-body">' . esc_html__( 'You can learn more about the features and pricing by visiting the Cookie Compliance website here:', 'cookie-notice' ) . ' <a href="https://cookie-compliance.co/?utm_campaign=pricing+options&utm_source=wordpress&utm_medium=textlink" target="_blank">https://cookie-compliance.co</a></span>
325 </label>
326 </div>
327 </div>';
328
329 echo '
330 </div>';
331
332 // multisite?
333 if ( is_multisite() ) {
334 // network admin?
335 if ( $cn->is_network_admin() ) {
336 $form_class = ( $cn->is_plugin_network_active() && ! $cn->options['general']['global_override'] ? 'cn-options-disabled' : '' );
337 $form_page = 'admin.php?page=cookie-notice';
338 $hidden_input = '<input type="hidden" name="cn-network-settings" value="true" />';
339 // single network site
340 } else {
341 $form_class = ( $cn->is_plugin_network_active() && $cn->network_options['global_override'] ? 'cn-options-disabled cn-options-submit-disabled' : '' );
342 $form_page = 'options.php';
343 $hidden_input = '';
344 }
345 // single site
346 } else {
347 $form_class = '';
348 $form_page = 'options.php';
349 $hidden_input = '';
350 }
351
352 echo '
353 <form action="' . esc_attr( $form_page ) . '" method="post"' . ( $form_class !== '' ? ' class="' . esc_attr( $form_class ) . '"' : '' ) . '>';
354
355 settings_fields( 'cookie_notice_options' );
356
357 if ( $hidden_input !== '' ) {
358 $allowed_html = [
359 'input' => [
360 'type' => true,
361 'name' => true,
362 'value' => true
363 ]
364 ];
365
366 echo wp_kses( $hidden_input, $allowed_html );
367 }
368
369 echo '
370 <div class="cn-options">';
371
372 do_settings_sections( 'cookie_notice_options' );
373
374 echo ' </div>
375 <p class="submit">';
376 submit_button( '', 'primary', 'save_cookie_notice_options', false );
377
378 echo ' ';
379
380 submit_button( esc_html__( 'Reset to defaults', 'cookie-notice' ), 'secondary', 'reset_cookie_notice_options', false );
381 echo '
382 </p>
383 </form>
384 </div>
385 <div class="clear"></div>
386 </div>';
387 }
388
389 /**
390 * Regiseter plugin settings.
391 *
392 * @return void
393 */
394 public function register_settings() {
395 register_setting( 'cookie_notice_options', 'cookie_notice_options', [ $this, 'validate_options' ] );
396
397 // get main instance
398 $cn = Cookie_Notice();
399
400 $status = $cn->get_status();
401
402 // multisite?
403 if ( is_multisite() ) {
404 // network admin?
405 if ( $cn->is_network_admin() ) {
406 // network section
407 add_settings_section( 'cookie_notice_network', esc_html__( 'Network Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
408 add_settings_field( 'cn_global_override', esc_html__( 'Global Settings Override', 'cookie-notice' ), [ $this, 'cn_global_override' ], 'cookie_notice_options', 'cookie_notice_network' );
409 add_settings_field( 'cn_global_cookie', esc_html__( 'Global Cookie', 'cookie-notice' ), [ $this, 'cn_global_cookie' ], 'cookie_notice_options', 'cookie_notice_network' );
410 } elseif ( $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
411 // network section
412 add_settings_section( 'cookie_notice_network', esc_html__( 'Network Settings', 'cookie-notice' ), [ $this, 'cn_network_section' ], 'cookie_notice_options' );
413 add_settings_field( 'cn_dummy', '', '__return_empty_string', 'cookie_notice_options', 'cookie_notice_network' );
414
415 // get default status data
416 $default_data = $cn->defaults['data'];
417
418 // get real status of current site, not network since global_override is on
419 $status_data = get_option( 'cookie_notice_status', $default_data );
420
421 // old status format?
422 if ( ! is_array( $status_data ) ) {
423 // old value saved as string
424 if ( is_string( $status_data ) && $cn->check_status( $status_data ) ) {
425 // update status
426 $default_data['status'] = $status_data;
427 }
428
429 // set data
430 $status_data = $default_data;
431 }
432
433 // get valid status
434 $status = $cn->check_status( $status_data['status'] );
435 }
436 }
437
438 // compliance enabled
439 if ( $status === 'active' ) {
440 // compliance section
441 add_settings_section( 'cookie_notice_compliance', esc_html__( 'Compliance Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
442 add_settings_field( 'cn_app_status', esc_html__( 'Compliance status', 'cookie-notice' ), [ $this, 'cn_app_status' ], 'cookie_notice_options', 'cookie_notice_compliance' );
443 add_settings_field( 'cn_app_id', esc_html__( 'App ID', 'cookie-notice' ), [ $this, 'cn_app_id' ], 'cookie_notice_options', 'cookie_notice_compliance' );
444 add_settings_field( 'cn_app_key', esc_html__( 'App Key', 'cookie-notice' ), [ $this, 'cn_app_key' ], 'cookie_notice_options', 'cookie_notice_compliance' );
445
446 // configuration section
447 add_settings_section( 'cookie_notice_configuration', esc_html__( 'Miscellaneous Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
448 add_settings_field( 'cn_app_blocking', esc_html__( 'Autoblocking', 'cookie-notice' ), [ $this, 'cn_app_blocking' ], 'cookie_notice_options', 'cookie_notice_configuration' );
449 add_settings_field( 'cn_debug_mode', esc_html__( 'Debug mode', 'cookie-notice' ), [ $this, 'cn_debug_mode' ], 'cookie_notice_options', 'cookie_notice_configuration' );
450 add_settings_field( 'cn_caching_compatibility', esc_html__( 'Caching compatibility', 'cookie-notice' ), [ $this, 'cn_caching_compatibility' ], 'cookie_notice_options', 'cookie_notice_configuration' );
451 add_settings_field( 'cn_app_purge_cache', esc_html__( 'Cache', 'cookie-notice' ), [ $this, 'cn_app_purge_cache' ], 'cookie_notice_options', 'cookie_notice_configuration' );
452 add_settings_field( 'cn_conditional_display', esc_html__( 'Conditional display', 'cookie-notice' ), [ $this, 'cn_conditional_display' ], 'cookie_notice_options', 'cookie_notice_configuration' );
453 add_settings_field( 'cn_deactivation_delete', esc_html__( 'Deactivation', 'cookie-notice' ), [ $this, 'cn_deactivation_delete' ], 'cookie_notice_options', 'cookie_notice_configuration' );
454 // compliance disabled
455 } else {
456 // compliance section
457 add_settings_section( 'cookie_notice_compliance', esc_html__( 'Compliance Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
458 add_settings_field( 'cn_app_status', esc_html__( 'Compliance status', 'cookie-notice' ), [ $this, 'cn_app_status' ], 'cookie_notice_options', 'cookie_notice_compliance' );
459 add_settings_field( 'cn_app_id', esc_html__( 'App ID', 'cookie-notice' ), [ $this, 'cn_app_id' ], 'cookie_notice_options', 'cookie_notice_compliance' );
460 add_settings_field( 'cn_app_key', esc_html__( 'App Key', 'cookie-notice' ), [ $this, 'cn_app_key' ], 'cookie_notice_options', 'cookie_notice_compliance' );
461
462 // configuration section
463 add_settings_section( 'cookie_notice_configuration', esc_html__( 'Notice Settings', 'cookie-notice' ), '', 'cookie_notice_options' );
464 add_settings_field( 'cn_message_text', esc_html__( 'Message', 'cookie-notice' ), [ $this, 'cn_message_text' ], 'cookie_notice_options', 'cookie_notice_configuration' );
465 add_settings_field( 'cn_accept_text', esc_html__( 'Button text', 'cookie-notice' ), [ $this, 'cn_accept_text' ], 'cookie_notice_options', 'cookie_notice_configuration' );
466 add_settings_field( 'cn_see_more', esc_html__( 'Privacy policy', 'cookie-notice' ), [ $this, 'cn_see_more' ], 'cookie_notice_options', 'cookie_notice_configuration' );
467 add_settings_field( 'cn_refuse_opt', esc_html__( 'Refuse consent', 'cookie-notice' ), [ $this, 'cn_refuse_opt' ], 'cookie_notice_options', 'cookie_notice_configuration' );
468 add_settings_field( 'cn_revoke_opt', esc_html__( 'Revoke consent', 'cookie-notice' ), [ $this, 'cn_revoke_opt' ], 'cookie_notice_options', 'cookie_notice_configuration' );
469 add_settings_field( 'cn_refuse_code', esc_html__( 'Script blocking', 'cookie-notice' ), [ $this, 'cn_refuse_code' ], 'cookie_notice_options', 'cookie_notice_configuration' );
470 add_settings_field( 'cn_redirection', esc_html__( 'Reloading', 'cookie-notice' ), [ $this, 'cn_redirection' ], 'cookie_notice_options', 'cookie_notice_configuration' );
471 add_settings_field( 'cn_on_scroll', esc_html__( 'On scroll', 'cookie-notice' ), [ $this, 'cn_on_scroll' ], 'cookie_notice_options', 'cookie_notice_configuration' );
472 add_settings_field( 'cn_on_click', esc_html__( 'On click', 'cookie-notice' ), [ $this, 'cn_on_click' ], 'cookie_notice_options', 'cookie_notice_configuration' );
473 add_settings_field( 'cn_time', esc_html__( 'Accepted expiry', 'cookie-notice' ), [ $this, 'cn_time' ], 'cookie_notice_options', 'cookie_notice_configuration' );
474 add_settings_field( 'cn_time_rejected', esc_html__( 'Rejected expiry', 'cookie-notice' ), [ $this, 'cn_time_rejected' ], 'cookie_notice_options', 'cookie_notice_configuration' );
475 add_settings_field( 'cn_conditional_display', esc_html__( 'Conditional display', 'cookie-notice' ), [ $this, 'cn_conditional_display' ], 'cookie_notice_options', 'cookie_notice_configuration' );
476 add_settings_field( 'cn_script_placement', esc_html__( 'Script placement', 'cookie-notice' ), [ $this, 'cn_script_placement' ], 'cookie_notice_options', 'cookie_notice_configuration' );
477 add_settings_field( 'cn_deactivation_delete', esc_html__( 'Deactivation', 'cookie-notice' ), [ $this, 'cn_deactivation_delete' ], 'cookie_notice_options', 'cookie_notice_configuration' );
478
479 // design section
480 add_settings_section( 'cookie_notice_design', esc_html__( 'Notice Design', 'cookie-notice' ), '', 'cookie_notice_options' );
481 add_settings_field( 'cn_position', esc_html__( 'Position', 'cookie-notice' ), [ $this, 'cn_position' ], 'cookie_notice_options', 'cookie_notice_design' );
482 add_settings_field( 'cn_hide_effect', esc_html__( 'Animation', 'cookie-notice' ), [ $this, 'cn_hide_effect' ], 'cookie_notice_options', 'cookie_notice_design' );
483 add_settings_field( 'cn_colors', esc_html__( 'Colors', 'cookie-notice' ), [ $this, 'cn_colors' ], 'cookie_notice_options', 'cookie_notice_design' );
484 add_settings_field( 'cn_css_class', esc_html__( 'Button class', 'cookie-notice' ), [ $this, 'cn_css_class' ], 'cookie_notice_options', 'cookie_notice_design' );
485 }
486 }
487
488 /**
489 * Network settings override option.
490 *
491 * @return void
492 */
493 public function cn_global_override() {
494 echo '
495 <div id="cn_global_override">
496 <label><input type="checkbox" name="cookie_notice_options[global_override]" value="1" ' . checked( true, Cookie_Notice()->options['general']['global_override'], false ) . ' />' . esc_html__( 'Enable global network settings override.', 'cookie-notice' ) . '</label>
497 <p class="description">' . esc_html__( 'Every site in the network will use the same settings. Site administrators will not be able to change them.', 'cookie-notice' ) . '</p>
498 </div>';
499 }
500
501 /**
502 * Network cookie acceptance option.
503 *
504 * @return void
505 */
506 public function cn_global_cookie() {
507 $multi_folders = is_multisite() && ! is_subdomain_install();
508
509 // multisite with path-based network?
510 if ( $multi_folders )
511 $desc = __( 'This option works only for domain-based networks.', 'cookie-notice' );
512 else
513 $desc = '';
514
515 echo '
516 <div id="cn_global_cookie">
517 <label><input type="checkbox" name="cookie_notice_options[global_cookie]" value="1" ' . checked( true, Cookie_Notice()->options['general']['global_cookie'], false ) . ' ' . disabled( $multi_folders, true, false ) . ' />' . esc_html__( 'Enable global network cookie consent.', 'cookie-notice' ) . '</label>
518 <p class="description">' . esc_html__( 'Cookie consent in one of the network sites results in a consent in all of the sites on the network.', 'cookie-notice' ) . ( $desc !== '' ? ' ' . esc_html( $desc ) : '' ) . '</p>
519 </div>';
520 }
521
522 /**
523 * Network settings section.
524 *
525 * @return void
526 */
527 public function cn_network_section() {
528 echo '
529 <p>' . esc_html__( 'Global network settings override is active. Every site will use the same network settings. Please contact super administrator if you want to have more control over the settings.', 'cookie-notice' ) . '</p>';
530 }
531
532 /**
533 * Compliance status.
534 *
535 * @return void
536 */
537 public function cn_app_status() {
538 // get main instance
539 $cn = Cookie_Notice();
540
541 // get cookie compliance status
542 $app_status = $cn->get_status();
543
544 // get threshold status
545 $threshold_exceeded = $cn->threshold_exceeded();
546
547 switch ( $app_status ) {
548 case 'active':
549 echo '
550 <div id="cn_app_status">
551 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Notice', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
552 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Autoblocking', 'cookie-notice' ) . '</span>: <span class="cn-status ' . ( $threshold_exceeded ? 'cn-pending' : 'cn-active' ) . '"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
553 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
554 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
555 </div>
556 <div id="cn_app_actions">
557 <a href="' . esc_url( $cn->get_url( 'host', '?utm_campaign=configure&utm_source=wordpress&utm_medium=button#/en/cc/login' ) ) . '" class="button button-primary button-hero cn-button" target="_blank">' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '</a>
558 <p class="description">' . esc_html__( 'Log into the Cookie Compliance&trade; web application to configure the appearance and functionality of the banner.', 'cookie-notice' ) . '</p>
559 </div>';
560 break;
561
562 case 'pending':
563 echo '
564 <div id="cn_app_status">
565 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Notice', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
566 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Autoblocking', 'cookie-notice' ) . '</span>: <span class="cn-status cn-pending"><span class="cn-icon"></span> ' . esc_html__( 'Pending', 'cookie-notice' ) . '</span></div>
567 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . '</span>: <span class="cn-status cn-pending"><span class="cn-icon"></span> ' . esc_html__( 'Pending', 'cookie-notice' ) . '</span></div>
568 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-pending"><span class="cn-icon"></span> ' . esc_html__( 'Pending', 'cookie-notice' ) . '</span></div>
569 </div>
570 <div id="cn_app_actions">
571 <a href="' . esc_url( $cn->get_url( 'host', '?utm_campaign=configure&utm_source=wordpress&utm_medium=button#/en/cc/login' ) ) . '" class="button button-primary button-hero cn-button" target="_blank">' . esc_html__( 'Log in & configure', 'cookie-notice' ) . '</a>
572 <p class="description">' . esc_html__( 'Log into the Cookie Compliance&trade; web application and complete the setup process.', 'cookie-notice' ) . '</p>
573 </div>';
574 break;
575
576 default:
577 if ( $cn->is_network_admin() )
578 $url = network_admin_url( 'admin.php?page=cookie-notice' );
579 else
580 $url = admin_url( 'admin.php?page=cookie-notice' );
581
582 echo '
583 <div id="cn_app_status">
584 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Notice', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
585 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Autoblocking', 'cookie-notice' ) . '</span>: <span class="cn-status cn-inactive"><span class="cn-icon"></span> ' . esc_html__( 'Inactive', 'cookie-notice' ) . '</span></div>
586 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . '</span>: <span class="cn-status cn-inactive"><span class="cn-icon"></span> ' . esc_html__( 'Inactive', 'cookie-notice' ) . '</span></div>
587 <div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-inactive"><span class="cn-icon"></span> ' . esc_html__( 'Inactive', 'cookie-notice' ) . '</span></div>
588 </div>
589 <div id="cn_app_actions">
590 <a href="' . esc_url( $url ) . '" class="button button-primary button-hero cn-button cn-run-welcome">' . esc_html__( 'Add Compliance features', 'cookie-notice' ) . '</a>
591 <p class="description">' . sprintf( esc_html__( 'Sign up to %s and add GDPR, CCPA and other international data privacy laws compliance features.', 'cookie-notice' ), '<a href="https://cookie-compliance.co/?utm_campaign=sign-up&utm_source=wordpress&utm_medium=textlink" target="_blank">Cookie Compliance&trade;</a>' ) . '</p>
592 </div>';
593 break;
594 }
595 }
596
597 /**
598 * App ID option.
599 *
600 * @return void
601 */
602 public function cn_app_id() {
603 echo '
604 <div id="cn_app_id">
605 <input type="text" class="regular-text" name="cookie_notice_options[app_id]" value="' . esc_attr( Cookie_Notice()->options['general']['app_id'] ) . '" />
606 <p class="description">' . esc_html__( 'Enter your Cookie Compliance&trade; application ID.', 'cookie-notice' ) . '</p>
607 </div>';
608 }
609
610 /**
611 * App key option.
612 *
613 * @return void
614 */
615 public function cn_app_key() {
616 echo '
617 <div id="cn_app_key">
618 <input type="password" class="regular-text" name="cookie_notice_options[app_key]" value="' . esc_attr( Cookie_Notice()->options['general']['app_key'] ) . '" />
619 <p class="description">' . esc_html__( 'Enter your Cookie Compliance&trade; application secret key.', 'cookie-notice' ) . '</p>
620 </div>';
621 }
622
623 /**
624 * App autoblocking option.
625 *
626 * @return void
627 */
628 public function cn_app_blocking() {
629 // get main instance
630 $cn = Cookie_Notice();
631
632 $threshold_exceeded = $cn->threshold_exceeded();
633
634 echo '
635 <div id="cn_app_blocking"' . ( $threshold_exceeded ? ' class="cn-option-disabled"' : '' ) . '>
636 <label><input type="checkbox" name="cookie_notice_options[app_blocking]" value="1" ' . checked( true, $cn->options['general']['app_blocking'], false ) . ' ' . disabled( $threshold_exceeded, true, false ) . ' />' . esc_html__( 'Enable to automatically block 3rd party scripts before user consent is set.', 'cookie-notice' ) . '</label>' .
637 ( $threshold_exceeded ? '<p class="description"><span class="cn-warning">*</span> ' . esc_html__( 'This option has been temporarily disabled because your website has reached the usage limit for the Cookie Compliance Basic plan. It will become available again when the current visits cycle resets or you upgrade your website to a Professional plan.', 'cookie-notice' ) . '</p>' : '' ) .
638 '</div>';
639 }
640
641 /**
642 * Purge cache option.
643 *
644 * @return void
645 */
646 public function cn_app_purge_cache() {
647 echo '
648 <div id="cn_app_purge_cache">
649 <div class="cn-button-container">
650 <a href="#" class="button button-secondary">' . esc_html__( 'Purge Cache', 'cookie-notice' ) . '</a>
651 </div>
652 <p class="description">' . esc_html__( 'Click the Purge Cache button to refresh the app configuration.', 'cookie-notice' ) . '</p>
653 </div>';
654 }
655
656 /**
657 * Conditional display option.
658 *
659 * @return void
660 */
661 public function cn_conditional_display() {
662 // get main instance
663 $cn = Cookie_Notice();
664
665 echo '
666 <fieldset id="cn_conditional_display">
667 <label><input id="cn_conditional_display_opt" type="checkbox" name="cookie_notice_options[conditional_active]" value="1" ' . checked( true, $cn->options['general']['conditional_active'], false ) . ' />' . esc_html__( 'Enable conditional display of the banner.', 'cookie-notice' ) . '</label>
668
669 <div id="cn_conditional_display_opt_container"' . ( $cn->options['general']['conditional_active'] === false ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">
670 <div>
671 <select name="cookie_notice_options[conditional_display]">';
672
673 foreach ( $this->conditional_display_types as $type => $label ) {
674 echo '
675 <option value="' . esc_attr( $type ) . '" ' . selected( $type, $cn->options['general']['conditional_display'] ) . '>' . esc_html( $label ) . '</option>';
676 }
677
678 echo '
679 </select>
680 <p class="description">' . esc_html__( 'Determine what should happen when the following conditions are met.', 'cookie-notice' ) . '</p>
681 </div>';
682
683 // get allowed html
684 $allowed_html = wp_kses_allowed_html( 'post' );
685 $allowed_html['select'] = [
686 'name' => true,
687 'class' => true
688 ];
689 $allowed_html['option'] = [
690 'value' => true,
691 'selected' => true
692 ];
693
694 add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
695
696 echo wp_kses( $this->conditional_display( $cn->options['general']['conditional_rules'] ), $allowed_html );
697
698 remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
699
700 echo '
701 </div>
702 </fieldset>';
703 }
704
705 /**
706 * Debug mode option.
707 *
708 * @return void
709 */
710 public function cn_debug_mode() {
711 echo '
712 <div id="cn_debug_mode">
713 <label><input type="checkbox" name="cookie_notice_options[debug_mode]" value="1" ' . checked( true, Cookie_Notice()->options['general']['debug_mode'], false ) . ' />' . esc_html__( 'Enable to run the consent banner in debug mode.', 'cookie-notice' ) . '</label>
714 </div>';
715 }
716
717 /**
718 * Debug mode option.
719 *
720 * @return void
721 */
722 public function cn_caching_compatibility() {
723 // get main instance
724 $cn = Cookie_Notice();
725
726 $plugins_html = '';
727
728 // get active caching plugins
729 $active_plugins = cn_get_active_caching_plugins();
730
731 if ( ! empty( $active_plugins ) ) {
732 $active_plugins_html = [];
733
734 $plugins_html .= '<p class="description">' . esc_html__( 'Currently detected active caching plugins', 'cookie-notice' ) . ': ';
735
736 foreach ( $active_plugins as $plugin ) {
737 $active_plugins_html[] = '<code>' . esc_html( $plugin ) . '</code>';
738 }
739
740 $plugins_html .= implode( ', ', $active_plugins_html ) . '.</p>';
741 } else
742 $plugins_html .= '<p class="description">' . esc_html__( 'No compatible cache plugins found.', 'cookie-notice' ) . '</p>';
743
744 echo '
745 <div id="cn_caching_compatibility">
746 <label><input type="checkbox" name="cookie_notice_options[caching_compatibility]" value="1" ' . checked( true, $cn->options['general']['caching_compatibility'] && ! empty( $active_plugins ), false ) . ' ' . disabled( empty( $active_plugins ), true, false ) . ' />' . esc_html__( 'Enable to apply changes improving compatibility with caching plugins.', 'cookie-notice' ) . '</label>' . $plugins_html . '
747 </div>';
748 }
749
750 /**
751 * Cookie notice message option.
752 *
753 * @return void
754 */
755 public function cn_message_text() {
756 echo '
757 <div id="cn_message_text">
758 <textarea name="cookie_notice_options[message_text]" class="large-text" cols="50" rows="5">' . esc_textarea( Cookie_Notice()->options['general']['message_text'] ) . '</textarea>
759 <p class="description">' . esc_html__( 'Enter the cookie notice message.', 'cookie-notice' ) . '</p>
760 </div>';
761 }
762
763 /**
764 * Accept cookie label option.
765 *
766 * @return void
767 */
768 public function cn_accept_text() {
769 echo '
770 <div id="cn_accept_text">
771 <input type="text" class="regular-text" name="cookie_notice_options[accept_text]" value="' . esc_attr( Cookie_Notice()->options['general']['accept_text'] ) . '" />
772 <p class="description">' . esc_html__( 'The text of the option to accept the notice and make it disappear.', 'cookie-notice' ) . '</p>
773 </div>';
774 }
775
776 /**
777 * Toggle third party non functional cookies option.
778 *
779 * @return void
780 */
781 public function cn_refuse_opt() {
782 // get main instance
783 $cn = Cookie_Notice();
784
785 echo '
786 <fieldset>
787 <label><input id="cn_refuse_opt" type="checkbox" name="cookie_notice_options[refuse_opt]" value="1" ' . checked( true, $cn->options['general']['refuse_opt'], false ) . ' />' . esc_html__( 'Enable to give to the user the possibility to refuse third party non functional cookies.', 'cookie-notice' ) . '</label>
788 <div id="cn_refuse_opt_container"' . ( $cn->options['general']['refuse_opt'] === false ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">
789 <div id="cn_refuse_text">
790 <input type="text" class="regular-text" name="cookie_notice_options[refuse_text]" value="' . esc_attr( $cn->options['general']['refuse_text'] ) . '" />
791 <p class="description">' . esc_html__( 'The text of the button to refuse the consent.', 'cookie-notice' ) . '</p>
792 </div>
793 </div>
794 </fieldset>';
795 }
796
797 /**
798 * Non functional cookies code option.
799 *
800 * @return void
801 */
802 public function cn_refuse_code() {
803 // get main instance
804 $cn = Cookie_Notice();
805
806 $allowed_html = $cn->get_allowed_html();
807 $active = ! empty( $cn->options['general']['refuse_code'] ) && empty( $cn->options['general']['refuse_code_head'] ) ? 'body' : 'head';
808
809 echo '
810 <div id="cn_refuse_code">
811 <div id="cn_refuse_code_fields">
812 <h2 class="nav-tab-wrapper">
813 <a id="refuse_head-tab" class="nav-tab' . ( $active === 'head' ? ' nav-tab-active' : '' ) . '" href="#refuse_head">' . esc_html__( 'Head', 'cookie-notice' ) . '</a>
814 <a id="refuse_body-tab" class="nav-tab' . ( $active === 'body' ? ' nav-tab-active' : '' ) . '" href="#refuse_body">' . esc_html__( 'Body', 'cookie-notice' ) . '</a>
815 </h2>
816 <div id="refuse_head" class="refuse-code-tab' . ( $active === 'head' ? ' active' : '' ) . '">
817 <p class="description">' . esc_html__( 'The code to be used in your site header, before the closing head tag.', 'cookie-notice' ) . '</p>
818 <textarea name="cookie_notice_options[refuse_code_head]" class="large-text" cols="50" rows="8">' . html_entity_decode( trim( wp_kses( $cn->options['general']['refuse_code_head'], $allowed_html ) ) ) . '</textarea>
819 </div>
820 <div id="refuse_body" class="refuse-code-tab' . ( $active === 'body' ? ' active' : '' ) . '">
821 <p class="description">' . esc_html__( 'The code to be used in your site footer, before the closing body tag.', 'cookie-notice' ) . '</p>
822 <textarea name="cookie_notice_options[refuse_code]" class="large-text" cols="50" rows="8">' . html_entity_decode( trim( wp_kses( $cn->options['general']['refuse_code'], $allowed_html ) ) ) . '</textarea>
823 </div>
824 </div>
825 <p class="description">' . esc_html__( 'Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the notice is accepted.', 'cookie-notice' ) . '</br>' . sprintf( esc_html__( 'To get the user consent status use the %scn_cookies_accepted()%s function.', 'cookie-notice' ), '<code>', '</code>' ) . '</p>
826 </div>';
827 }
828
829 /**
830 * Revoke cookies option.
831 *
832 * @return void
833 */
834 public function cn_revoke_opt() {
835 // get main instance
836 $cn = Cookie_Notice();
837
838 echo '
839 <fieldset id="cn_revoke_opt">
840 <label><input id="cn_revoke_cookies" type="checkbox" name="cookie_notice_options[revoke_cookies]" value="1" ' . checked( true, $cn->options['general']['revoke_cookies'], false ) . ' />' . sprintf( esc_html__( 'Enable to give to the user the possibility to revoke their consent %s(requires "Refuse consent" option enabled)%s.', 'cookie-notice' ), '<i>', '</i>' ) . '</label>
841 <div id="cn_revoke_opt_container"' . ( $cn->options['general']['revoke_cookies'] ? '' : ' style="display: none"' ) . ' class="cn_fieldset_content">
842 <textarea name="cookie_notice_options[revoke_message_text]" class="large-text" cols="50" rows="2">' . esc_textarea( $cn->options['general']['revoke_message_text'] ) . '</textarea>
843 <p class="description">' . esc_html__( 'Enter the revoke message.', 'cookie-notice' ) . '</p>
844 <input type="text" class="regular-text" name="cookie_notice_options[revoke_text]" value="' . esc_attr( $cn->options['general']['revoke_text'] ) . '" />
845 <p class="description">' . esc_html__( 'The text of the button to revoke the consent.', 'cookie-notice' ) . '</p>';
846
847 foreach ( $this->revoke_opts as $value => $label ) {
848 echo '
849 <label><input id="cn_revoke_cookies-' . esc_attr( $value ) . '" type="radio" name="cookie_notice_options[revoke_cookies_opt]" value="' . esc_attr( $value ) . '" ' . checked( $value, $cn->options['general']['revoke_cookies_opt'], false ) . ' />' . esc_html( $label ) . '</label>';
850 }
851
852 echo '
853 <p class="description">' . sprintf( esc_html__( 'Select the method for displaying the revoke button - automatic (in the banner) or manual using %s[cookies_revoke]%s shortcode.', 'cookie-notice' ), '<code>', '</code>' ) . '</p>
854 </div>
855 </fieldset>';
856 }
857
858 /**
859 * Redirection on cookie accept option.
860 *
861 * @return void
862 */
863 public function cn_redirection() {
864 echo '
865 <div id="cn_redirection">
866 <label><input type="checkbox" name="cookie_notice_options[redirection]" value="1" ' . checked( true, Cookie_Notice()->options['general']['redirection'], false ) . ' />' . esc_html__( 'Enable to reload the page after the notice is accepted.', 'cookie-notice' ) . '</label>
867 </div>';
868 }
869
870 /**
871 * Privacy policy link option.
872 *
873 * @global string $wp_version
874 *
875 * @return void
876 */
877 public function cn_see_more() {
878 // get main instance
879 $cn = Cookie_Notice();
880
881 // get published pages
882 $pages = get_pages(
883 [
884 'sort_order' => 'ASC',
885 'sort_column' => 'post_title',
886 'hierarchical' => 0,
887 'child_of' => 0,
888 'parent' => -1,
889 'offset' => 0,
890 'post_type' => 'page',
891 'post_status' => 'publish'
892 ]
893 );
894
895 echo '
896 <fieldset>
897 <label><input id="cn_see_more" type="checkbox" name="cookie_notice_options[see_more]" value="1" ' . checked( true, $cn->options['general']['see_more'], false ) . ' />' . esc_html__( 'Enable privacy policy link.', 'cookie-notice' ) . '</label>
898 <div id="cn_see_more_opt"' . ( $cn->options['general']['see_more'] === false ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">
899 <input type="text" class="regular-text" name="cookie_notice_options[see_more_opt][text]" value="' . esc_attr( $cn->options['general']['see_more_opt']['text'] ) . '" />
900 <p class="description">' . esc_html__( 'The text of the privacy policy button.', 'cookie-notice' ) . '</p>
901 <div id="cn_see_more_opt_custom_link">';
902
903 foreach ( $this->links as $value => $label ) {
904 echo '
905 <label><input id="cn_see_more_link-' . esc_attr( $value ) . '" type="radio" name="cookie_notice_options[see_more_opt][link_type]" value="' . esc_attr( $value ) . '" ' . checked( $value, $cn->options['general']['see_more_opt']['link_type'], false ) . ' />' . esc_html( $label ) . '</label>';
906 }
907
908 echo '
909 </div>
910 <p class="description">' . esc_html__( 'Select where to redirect user for more information.', 'cookie-notice' ) . '</p>
911 <div id="cn_see_more_opt_page"' . ( $cn->options['general']['see_more_opt']['link_type'] === 'custom' ? ' style="display: none"' : '' ) . '>
912 <select name="cookie_notice_options[see_more_opt][id]">
913 <option value="0" ' . selected( 0, $cn->options['general']['see_more_opt']['id'], false ) . '>' . esc_html__( '-- select page --', 'cookie-notice' ) . '</option>';
914
915 if ( $pages ) {
916 foreach ( $pages as $page ) {
917 echo '
918 <option value="' . esc_attr( $page->ID ) . '" ' . selected( $page->ID, $cn->options['general']['see_more_opt']['id'], false ) . '>' . esc_html( $page->post_title ) . '</option>';
919 }
920 }
921
922 echo '
923 </select>
924 <p class="description">' . esc_html__( 'Select from one of your site\'s pages.', 'cookie-notice' ) . '</p>';
925
926 global $wp_version;
927
928 if ( version_compare( $wp_version, '4.9.6', '>=' ) ) {
929 echo '
930 <label><input id="cn_see_more_opt_sync" type="checkbox" name="cookie_notice_options[see_more_opt][sync]" value="1" ' . checked( true, $cn->options['general']['see_more_opt']['sync'], false ) . ' />' . esc_html__( 'Synchronize with WordPress Privacy Policy page.', 'cookie-notice' ) . '</label>';
931 }
932
933 echo '
934 </div>
935 <div id="cn_see_more_opt_link"' . ( $cn->options['general']['see_more_opt']['link_type'] === 'page' ? ' style="display: none"' : '' ) . '>
936 <input type="text" class="regular-text" name="cookie_notice_options[see_more_opt][link]" value="' . esc_attr( $cn->options['general']['see_more_opt']['link'] ) . '" />
937 <p class="description">' . esc_html__( 'Enter the full URL starting with http(s)://', 'cookie-notice' ) . '</p>
938 </div>
939 <div id="cn_see_more_link_target">';
940
941 foreach ( $this->link_targets as $target ) {
942 echo '
943 <label><input id="cn_see_more_link_target-' . esc_attr( $target ) . '" type="radio" name="cookie_notice_options[link_target]" value="' . esc_attr( $target ) . '" ' . checked( $target, $cn->options['general']['link_target'], false ) . ' />' . esc_html( $target ) . '</label>';
944 }
945
946 echo '
947 <p class="description">' . esc_html__( 'Select the privacy policy link target.', 'cookie-notice' ) . '</p>
948 </div>
949 <div id="cn_see_more_link_position">';
950
951 foreach ( $this->link_positions as $position => $label ) {
952 echo '
953 <label><input id="cn_see_more_link_position-' . esc_attr( $position ) . '" type="radio" name="cookie_notice_options[link_position]" value="' . esc_attr( $position ) . '" ' . checked( $position, $cn->options['general']['link_position'], false ) . ' />' . esc_html( $label ) . '</label>';
954 }
955
956 echo '
957 <p class="description">' . esc_html__( 'Select the privacy policy link position.', 'cookie-notice' ) . '</p>
958 </div>
959 </div>
960 </fieldset>';
961 }
962
963 /**
964 * Expiration time option.
965 *
966 * @return void
967 */
968 public function cn_time() {
969 echo '
970 <div id="cn_time">
971 <select name="cookie_notice_options[time]">';
972
973 foreach ( $this->times as $time => $arr ) {
974 echo '
975 <option value="' . esc_attr( $time ) . '" ' . selected( $time, Cookie_Notice()->options['general']['time'] ) . '>' . esc_html( $arr[0] ) . '</option>';
976 }
977
978 echo '
979 </select>
980 <p class="description">' . esc_html__( 'The amount of time that the cookie should be stored for when user accepts the notice.', 'cookie-notice' ) . '</p>
981 </div>';
982 }
983
984 /**
985 * Expiration time option.
986 *
987 * @return void
988 */
989 public function cn_time_rejected() {
990 echo '
991 <div id="cn_time_rejected">
992 <select name="cookie_notice_options[time_rejected]">';
993
994 foreach ( $this->times as $time => $arr ) {
995 echo '
996 <option value="' . esc_attr( $time ) . '" ' . selected( $time, Cookie_Notice()->options['general']['time_rejected'] ) . '>' . esc_html( $arr[0] ) . '</option>';
997 }
998
999 echo '
1000 </select>
1001 <p class="description">' . esc_html__( 'The amount of time that the cookie should be stored for when the user doesn\'t accept the notice.', 'cookie-notice' ) . '</p>
1002 </div>';
1003 }
1004
1005 /**
1006 * Script placement option.
1007 *
1008 * @return void
1009 */
1010 public function cn_script_placement() {
1011 echo '
1012 <div id="cn_script_placement">';
1013
1014 foreach ( $this->script_placements as $value => $label ) {
1015 echo '
1016 <label><input id="cn_script_placement-' . esc_attr( $value ) . '" type="radio" name="cookie_notice_options[script_placement]" value="' . esc_attr( $value ) . '" ' . checked( $value, Cookie_Notice()->options['general']['script_placement'], false ) . ' />' . esc_html( $label ) . '</label>';
1017 }
1018
1019 echo '
1020 <p class="description">' . esc_html__( 'Select where all the plugin scripts should be placed.', 'cookie-notice' ) . '</p>
1021 </div>';
1022 }
1023
1024 /**
1025 * Position option.
1026 *
1027 * @return void
1028 */
1029 public function cn_position() {
1030 echo '
1031 <div id="cn_position">';
1032
1033 foreach ( $this->positions as $value => $label ) {
1034 echo '
1035 <label><input id="cn_position-' . esc_attr( $value ) . '" type="radio" name="cookie_notice_options[position]" value="' . esc_attr( $value ) . '" ' . checked( $value, Cookie_Notice()->options['general']['position'], false ) . ' />' . esc_html( $label ) . '</label>';
1036 }
1037
1038 echo '
1039 <p class="description">' . esc_html__( 'Select location for the notice.', 'cookie-notice' ) . '</p>
1040 </div>';
1041 }
1042
1043 /**
1044 * Animation effect option.
1045 *
1046 * @return void
1047 */
1048 public function cn_hide_effect() {
1049 echo '
1050 <div id="cn_hide_effect">';
1051
1052 foreach ( $this->effects as $value => $label ) {
1053 echo '
1054 <label><input id="cn_hide_effect-' . esc_attr( $value ) . '" type="radio" name="cookie_notice_options[hide_effect]" value="' . esc_attr( $value ) . '" ' . checked( $value, Cookie_Notice()->options['general']['hide_effect'], false ) . ' />' . esc_html( $label ) . '</label>';
1055 }
1056
1057 echo '
1058 <p class="description">' . esc_html__( 'Select the animation style.', 'cookie-notice' ) . '</p>
1059 </div>';
1060 }
1061
1062 /**
1063 * On scroll option.
1064 *
1065 * @return void
1066 */
1067 public function cn_on_scroll() {
1068 // get main instance
1069 $cn = Cookie_Notice();
1070
1071 echo '
1072 <fieldset>
1073 <label><input id="cn_on_scroll" type="checkbox" name="cookie_notice_options[on_scroll]" value="1" ' . checked( true, $cn->options['general']['on_scroll'], false ) . ' />' . esc_html__( 'Enable to accept the notice when user scrolls.', 'cookie-notice' ) . '</label>
1074 <div id="cn_on_scroll_offset"' . ( $cn->options['general']['on_scroll'] === false || $cn->options['general']['on_scroll'] == false ? ' style="display: none"' : '' ) . ' class="cn_fieldset_content">
1075 <input type="number" min="0" class="small-text" name="cookie_notice_options[on_scroll_offset]" value="' . esc_attr( $cn->options['general']['on_scroll_offset'] ) . '" /> <span>px</span>
1076 <p class="description">' . esc_html__( 'Number of pixels user has to scroll to accept the notice and make it disappear.', 'cookie-notice' ) . '</p>
1077 </div>
1078 </fieldset>';
1079 }
1080
1081 /**
1082 * On click option.
1083 *
1084 * @return void
1085 */
1086 public function cn_on_click() {
1087 echo '
1088 <div id="cn_on_click">
1089 <label><input type="checkbox" name="cookie_notice_options[on_click]" value="1" ' . checked( true, Cookie_Notice()->options['general']['on_click'], false ) . ' />' . esc_html__( 'Enable to accept the notice on any click on the page.', 'cookie-notice' ) . '</label>
1090 </div>';
1091 }
1092
1093 /**
1094 * Delete plugin data on deactivation option.
1095 *
1096 * @return void
1097 */
1098 public function cn_deactivation_delete() {
1099 echo '
1100 <div id="cn_deactivation_delete">
1101 <label><input type="checkbox" name="cookie_notice_options[deactivation_delete]" value="1" ' . checked( true, Cookie_Notice()->options['general']['deactivation_delete'], false ) . '/>' . esc_html__( 'Enable if you want all plugin data to be deleted on deactivation.', 'cookie-notice' ) . '</label>
1102 </div>';
1103 }
1104
1105 /**
1106 * CSS style option.
1107 *
1108 * @return void
1109 */
1110 public function cn_css_class() {
1111 echo '
1112 <div id="cn_css_class">
1113 <input type="text" class="regular-text" name="cookie_notice_options[css_class]" value="' . esc_attr( Cookie_Notice()->options['general']['css_class'] ) . '" />
1114 <p class="description">' . esc_html__( 'Enter additional button CSS classes separated by spaces.', 'cookie-notice' ) . '</p>
1115 </div>';
1116 }
1117
1118 /**
1119 * Colors option.
1120 *
1121 * @return void
1122 */
1123 public function cn_colors() {
1124 // get main instance
1125 $cn = Cookie_Notice();
1126
1127 echo '
1128 <fieldset>
1129 <div id="cn_colors">';
1130
1131 foreach ( $this->colors as $value => $label ) {
1132 echo '
1133 <div id="cn_colors-' . esc_attr( $value ) . '"><label>' . esc_html( $label ) . '</label><br />
1134 <input class="cn_color" type="text" name="cookie_notice_options[colors][' . esc_attr( $value ) . ']" value="' . esc_attr( $cn->options['general']['colors'][$value] ) . '" />
1135 </div>';
1136 }
1137
1138 echo '
1139 <div id="cn_colors-bar_opacity"><label>' . esc_html__( 'Bar opacity', 'cookie-notice' ) . '</label><br />
1140 <div><input id="cn_colors_bar_opacity_range" class="cn_range" type="range" min="50" max="100" step="1" name="cookie_notice_options[colors][bar_opacity]" value="' . (int) $cn->options['general']['colors']['bar_opacity'] . '" onchange="cn_colors_bar_opacity_text.value = cn_colors_bar_opacity_range.value" /><input id="cn_colors_bar_opacity_text" class="small-text" type="number" onchange="cn_colors_bar_opacity_range.value = cn_colors_bar_opacity_text.value" min="50" max="100" value="' . (int) $cn->options['general']['colors']['bar_opacity'] . '" /></div>
1141 </div>';
1142
1143 echo '
1144 </div>
1145 </fieldset>';
1146 }
1147
1148 /**
1149 * Validate options.
1150 *
1151 * @param array $input
1152 * @return array
1153 */
1154 public function validate_options( $input ) {
1155 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1156 return $input;
1157
1158 // get main instance
1159 $cn = Cookie_Notice();
1160
1161 $is_network = $cn->is_network_admin();
1162
1163 if ( isset( $_POST['save_cookie_notice_options'] ) ) {
1164 // app id
1165 $input['app_id'] = isset( $input['app_id'] ) ? sanitize_key( $input['app_id'] ) : $cn->defaults['general']['app_id'];
1166
1167 // app key
1168 $input['app_key'] = isset( $input['app_key'] ) ? sanitize_key( $input['app_key'] ) : $cn->defaults['general']['app_key'];
1169
1170 // set app status
1171 if ( ! empty( $input['app_id'] ) && ! empty( $input['app_key'] ) ) {
1172 $app_data = $cn->welcome_api->get_app_config( $input['app_id'], true );
1173
1174 if ( $cn->check_status( $app_data['status'] ) === 'active' && $cn->options['general']['app_id'] !== $input['app_id'] ) {
1175 // get_app_analytics requires fresh app data
1176 $this->analytics_app_data = [
1177 'id' => $input['app_id'],
1178 'key' => $input['app_key']
1179 ];
1180
1181 // update analytics data
1182 $cn->welcome_api->get_app_analytics( $input['app_id'], true );
1183
1184 $this->analytics_app_data = [];
1185 }
1186 } else {
1187 if ( $is_network )
1188 update_site_option( 'cookie_notice_status', $cn->defaults['data'] );
1189 else
1190 update_option( 'cookie_notice_status', $cn->defaults['data'] );
1191 }
1192
1193 // app blocking
1194 $input['app_blocking'] = isset( $input['app_blocking'] ) && ! $cn->threshold_exceeded();
1195
1196 // conditional display
1197 $input['conditional_active'] = isset( $input['conditional_active'] );
1198
1199 $input['conditional_display'] = isset( $input['conditional_display'] ) ? sanitize_key( $input['conditional_display'] ) : $cn->defaults['general']['conditional_display'];
1200
1201 if ( ! in_array( $input['conditional_display'], array_keys( $this->conditional_display_types ), true ) )
1202 $input['conditional_display'] = $cn->defaults['general']['conditional_display'];
1203
1204 if ( ! empty( $input['conditional_rules'] ) && is_array( $input['conditional_rules'] ) ) {
1205 $group_id = $rule_id = 1;
1206 $rules = [];
1207
1208 foreach ( $input['conditional_rules'] as $group_number => $group ) {
1209 // skips template data or empty groups
1210 if ( (int) $group_number <= 0 || empty( $group ) )
1211 continue;
1212
1213 foreach ( $group as $rule ) {
1214 $param = sanitize_key( $rule['param'] );
1215 $operator = sanitize_key( $rule['operator'] );
1216 $value = sanitize_key( $rule['value'] );
1217
1218 if ( $this->check_rule( $param, $operator, $value ) ) {
1219 $rules[$group_id][$rule_id++] = [
1220 'param' => $param,
1221 'operator' => $operator,
1222 'value' => $value
1223 ];
1224 }
1225 }
1226
1227 $rule_id = 1;
1228 $group_id++;
1229 }
1230
1231 $input['conditional_rules'] = $rules;
1232 } else
1233 $input['conditional_rules'] = [];
1234
1235
1236 // debug mode
1237 $input['debug_mode'] = isset( $input['debug_mode'] );
1238
1239 // get active caching plugins
1240 $active_plugins = cn_get_active_caching_plugins();
1241
1242 // caching compatibility
1243 $input['caching_compatibility'] = isset( $input['caching_compatibility'] ) && ! empty( $active_plugins );
1244
1245 // position
1246 if ( isset( $input['position'] ) ) {
1247 $input['position'] = sanitize_key( $input['position'] );
1248
1249 if ( ! array_key_exists( $input['position'], $this->positions ) )
1250 $input['position'] = $cn->defaults['general']['position'];
1251 } else
1252 $input['position'] = $cn->defaults['general']['position'];
1253
1254 // text color
1255 if ( isset( $input['colors']['text'] ) ) {
1256 $input['colors']['text'] = sanitize_hex_color( $input['colors']['text'] );
1257
1258 if ( empty( $input['colors']['text'] ) )
1259 $input['colors']['text'] = $cn->defaults['general']['colors']['text'];
1260 } else
1261 $input['colors']['text'] = $cn->defaults['general']['colors']['text'];
1262
1263 // button color
1264 if ( isset( $input['colors']['button'] ) ) {
1265 $input['colors']['button'] = sanitize_hex_color( $input['colors']['button'] );
1266
1267 if ( empty( $input['colors']['button'] ) )
1268 $input['colors']['button'] = $cn->defaults['general']['colors']['button'];
1269 } else
1270 $input['colors']['button'] = $cn->defaults['general']['colors']['button'];
1271
1272 // bar color
1273 if ( isset( $input['colors']['bar'] ) ) {
1274 $input['colors']['bar'] = sanitize_hex_color( $input['colors']['bar'] );
1275
1276 if ( empty( $input['colors']['bar'] ) )
1277 $input['colors']['bar'] = $cn->defaults['general']['colors']['bar'];
1278 } else
1279 $input['colors']['bar'] = $cn->defaults['general']['colors']['bar'];
1280
1281 // bar opacity
1282 $input['colors']['bar_opacity'] = isset( $input['colors']['bar_opacity'] ) ? (int) $input['colors']['bar_opacity'] : $cn->defaults['general']['colors']['bar_opacity'];
1283
1284 if ( $input['colors']['bar_opacity'] < 50 || $input['colors']['bar_opacity'] > 100 )
1285 $input['colors']['bar_opacity'] = $cn->defaults['general']['colors']['bar_opacity'];
1286
1287 // message text
1288 if ( isset( $input['message_text'] ) ) {
1289 add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
1290
1291 $input['message_text'] = wp_kses_post( trim( $input['message_text'] ) );
1292
1293 remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
1294
1295 if ( $input['message_text'] === '' )
1296 $input['message_text'] = $cn->defaults['general']['message_text'];
1297 } else
1298 $input['message_text'] = $cn->defaults['general']['message_text'];
1299
1300 // accept button text
1301 if ( isset( $input['accept_text'] ) ) {
1302 $input['accept_text'] = sanitize_text_field( $input['accept_text'] );
1303
1304 if ( $input['accept_text'] === '' )
1305 $input['accept_text'] = $cn->defaults['general']['accept_text'];
1306 } else
1307 $input['accept_text'] = $cn->defaults['general']['accept_text'];
1308
1309 // refuse button text
1310 if ( isset( $input['refuse_text'] ) ) {
1311 $input['refuse_text'] = sanitize_text_field( $input['refuse_text'] );
1312
1313 if ( $input['refuse_text'] === '' )
1314 $input['refuse_text'] = $cn->defaults['general']['refuse_text'];
1315 } else
1316 $input['refuse_text'] = $cn->defaults['general']['refuse_text'];
1317
1318 // revoke message text
1319 if ( isset( $input['revoke_message_text'] ) ) {
1320 add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
1321
1322 $input['revoke_message_text'] = wp_kses_post( trim( $input['revoke_message_text'] ) );
1323
1324 remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
1325
1326 if ( $input['revoke_message_text'] === '' )
1327 $input['revoke_message_text'] = $cn->defaults['general']['revoke_message_text'];
1328 } else
1329 $input['revoke_message_text'] = $cn->defaults['general']['revoke_message_text'];
1330
1331 // revoke button text
1332 if ( isset( $input['revoke_text'] ) ) {
1333 $input['revoke_text'] = sanitize_text_field( $input['revoke_text'] );
1334
1335 if ( $input['revoke_text'] === '' )
1336 $input['revoke_text'] = $cn->defaults['general']['revoke_text'];
1337 } else
1338 $input['revoke_text'] = $cn->defaults['general']['revoke_text'];
1339
1340 // refuse consent
1341 $input['refuse_opt'] = isset( $input['refuse_opt'] );
1342
1343 // revoke consent
1344 $input['revoke_cookies'] = isset( $input['revoke_cookies'] );
1345
1346 // revoke consent type
1347 if ( isset( $input['revoke_cookies_opt'] ) ) {
1348 $input['revoke_cookies_opt'] = sanitize_key( $input['revoke_cookies_opt'] );
1349
1350 if ( ! array_key_exists( $input['revoke_cookies_opt'], $this->revoke_opts ) )
1351 $input['revoke_cookies_opt'] = $cn->defaults['general']['revoke_cookies_opt'];
1352 } else
1353 $input['revoke_cookies_opt'] = $cn->defaults['general']['revoke_cookies_opt'];
1354
1355 // get allowed html
1356 $allowed_html = $cn->get_allowed_html();
1357
1358 // body refuse code
1359 if ( isset( $input['refuse_code'] ) )
1360 $input['refuse_code'] = wp_kses( trim( $input['refuse_code'] ), $allowed_html );
1361 else
1362 $input['refuse_code'] = $cn->defaults['general']['refuse_code'];
1363
1364 // head refuse code
1365 if ( isset( $input['refuse_code_head'] ) )
1366 $input['refuse_code_head'] = wp_kses( trim( $input['refuse_code_head'] ), $allowed_html );
1367 else
1368 $input['refuse_code_head'] = $cn->defaults['general']['refuse_code_head'];
1369
1370 // css button class(es)
1371 if ( isset( $input['css_class'] ) ) {
1372 $input['css_class'] = trim( $input['css_class'] );
1373
1374 if ( $input['css_class'] !== '' ) {
1375 // more than 1 class?
1376 if ( strpos( $input['css_class'], ' ' ) !== false ) {
1377 // get unique valid html classes
1378 $input['css_class'] = array_unique( array_filter( array_map( 'sanitize_html_class', explode( ' ', $input['css_class'] ) ) ) );
1379
1380 if ( ! empty( $input['css_class'] ) )
1381 $input['css_class'] = implode( ' ', $input['css_class'] );
1382 else
1383 $input['css_class'] = $cn->defaults['general']['css_class'];
1384 // single class
1385 } else
1386 $input['css_class'] = sanitize_html_class( $input['css_class'] );
1387 }
1388 } else
1389 $input['css_class'] = $cn->defaults['general']['css_class'];
1390
1391 // accepted expiry
1392 if ( isset( $input['time'] ) ) {
1393 $input['time'] = sanitize_key( $input['time'] );
1394
1395 if ( ! array_key_exists( $input['time'], $this->times ) )
1396 $input['time'] = $cn->defaults['general']['time'];
1397 } else
1398 $input['time'] = $cn->defaults['general']['time'];
1399
1400 // rejected expiry
1401 if ( isset( $input['time_rejected'] ) ) {
1402 $input['time_rejected'] = sanitize_key( $input['time_rejected'] );
1403
1404 if ( ! array_key_exists( $input['time_rejected'], $this->times ) )
1405 $input['time_rejected'] = $cn->defaults['general']['time_rejected'];
1406 } else
1407 $input['time_rejected'] = $cn->defaults['general']['time_rejected'];
1408
1409 // script placement
1410 if ( isset( $input['script_placement'] ) ) {
1411 $input['script_placement'] = sanitize_key( $input['script_placement'] );
1412
1413 if ( ! array_key_exists( $input['script_placement'], $this->script_placements ) )
1414 $input['script_placement'] = $cn->defaults['general']['script_placement'];
1415 } else
1416 $input['script_placement'] = $cn->defaults['general']['script_placement'];
1417
1418 // hide effect
1419 if ( isset( $input['hide_effect'] ) ) {
1420 $input['hide_effect'] = sanitize_key( $input['hide_effect'] );
1421
1422 if ( ! array_key_exists( $input['hide_effect'], $this->effects ) )
1423 $input['hide_effect'] = $cn->defaults['general']['hide_effect'];
1424 } else
1425 $input['hide_effect'] = $cn->defaults['general']['hide_effect'];
1426
1427 // reloading
1428 $input['redirection'] = isset( $input['redirection'] );
1429
1430 // on scroll
1431 $input['on_scroll'] = isset( $input['on_scroll'] );
1432
1433 // on scroll offset
1434 $input['on_scroll_offset'] = isset( $input['on_scroll_offset'] ) ? (int) $input['on_scroll_offset'] : $cn->defaults['general']['on_scroll_offset'];
1435
1436 if ( $input['on_scroll_offset'] < 0 )
1437 $input['on_scroll_offset'] = 0;
1438
1439 // on click
1440 $input['on_click'] = isset( $input['on_click'] );
1441
1442 // deactivation
1443 $input['deactivation_delete'] = isset( $input['deactivation_delete'] );
1444
1445 // privacy policy
1446 $input['see_more'] = isset( $input['see_more'] );
1447
1448 // privacy policy link text
1449 if ( isset( $input['see_more_opt']['text'] ) ) {
1450 $input['see_more_opt']['text'] = sanitize_text_field( $input['see_more_opt']['text'] );
1451
1452 if ( $input['see_more_opt']['text'] === '' )
1453 $input['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text'];
1454 } else
1455 $input['see_more_opt']['text'] = $cn->defaults['general']['see_more_opt']['text'];
1456
1457 // privacy policy link type
1458 if ( isset( $input['see_more_opt']['link_type'] ) ) {
1459 $input['see_more_opt']['link_type'] = sanitize_key( $input['see_more_opt']['link_type'] );
1460
1461 if ( ! array_key_exists( $input['see_more_opt']['link_type'], $this->links ) )
1462 $input['see_more_opt']['link_type'] = $cn->defaults['general']['see_more_opt']['link_type'];
1463 } else
1464 $input['see_more_opt']['link_type'] = $cn->defaults['general']['see_more_opt']['link_type'];
1465
1466 if ( $input['see_more_opt']['link_type'] === 'custom' )
1467 $input['see_more_opt']['link'] = $input['see_more'] && isset( $input['see_more_opt']['link'] ) ? esc_url_raw( $input['see_more_opt']['link'] ) : '';
1468 elseif ( $input['see_more_opt']['link_type'] === 'page' ) {
1469 $input['see_more_opt']['id'] = $input['see_more'] && isset( $input['see_more_opt']['id'] ) ? (int) $input['see_more_opt']['id'] : 0;
1470 $input['see_more_opt']['sync'] = isset( $input['see_more_opt']['sync'] );
1471
1472 if ( $input['see_more_opt']['sync'] )
1473 update_option( 'wp_page_for_privacy_policy', $input['see_more_opt']['id'] );
1474 }
1475
1476 // privacy policy link target
1477 if ( isset( $input['link_target'] ) ) {
1478 $input['link_target'] = sanitize_key( $input['link_target'] );
1479
1480 if ( ! array_key_exists( $input['link_target'], $this->link_targets ) )
1481 $input['link_target'] = $cn->defaults['general']['link_target'];
1482 } else
1483 $input['link_target'] = $cn->defaults['general']['link_target'];
1484
1485 // policy policy link position
1486 if ( isset( $input['link_position'] ) ) {
1487 $input['link_position'] = sanitize_key( $input['link_position'] );
1488
1489 if ( ! array_key_exists( $input['link_position'], $this->link_positions ) )
1490 $input['link_position'] = $cn->defaults['general']['link_position'];
1491 } else
1492 $input['link_position'] = $cn->defaults['general']['link_position'];
1493
1494 // message link position?
1495 if ( $input['see_more'] && $input['link_position'] === 'message' && strpos( $input['message_text'], '[cookies_policy_link' ) === false )
1496 $input['message_text'] .= ' [cookies_policy_link]';
1497
1498 $input['update_version'] = $cn->options['general']['update_version'];
1499 $input['update_notice'] = $cn->options['general']['update_notice'];
1500
1501 $input['translate'] = false;
1502
1503 // WPML >= 3.2
1504 if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
1505 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Message in the notice', $input['message_text'] );
1506 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Button text', $input['accept_text'] );
1507 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Refuse button text', $input['refuse_text'] );
1508 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke message text', $input['revoke_message_text'] );
1509 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Revoke button text', $input['revoke_text'] );
1510 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Privacy policy text', $input['see_more_opt']['text'] );
1511
1512 if ( $input['see_more_opt']['link_type'] === 'custom' )
1513 do_action( 'wpml_register_single_string', 'Cookie Notice', 'Custom link', $input['see_more_opt']['link'] );
1514 }
1515
1516 add_settings_error( 'cn_cookie_notice_options', 'save_cookie_notice_options', esc_html__( 'Settings saved.', 'cookie-notice' ), 'updated' );
1517 } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) {
1518 $input = $cn->defaults['general'];
1519
1520 add_settings_error( 'cn_cookie_notice_options', 'reset_cookie_notice_options', esc_html__( 'Settings restored to defaults.', 'cookie-notice' ), 'updated' );
1521
1522 // network area?
1523 if ( $is_network ) {
1524 // set app data
1525 update_site_option( 'cookie_notice_status', $cn->defaults['data'] );
1526 } else {
1527 // set app data
1528 update_option( 'cookie_notice_status', $cn->defaults['data'] );
1529 }
1530 }
1531
1532 return $input;
1533 }
1534
1535 /**
1536 * Validate network options.
1537 *
1538 * @return void
1539 */
1540 public function validate_network_options() {
1541 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1542 return;
1543
1544 // get main instance
1545 $cn = Cookie_Notice();
1546
1547 // global network page?
1548 if ( $cn->is_network_admin() && isset( $_POST['cn-network-settings'] ) ) {
1549 // network settings
1550 if ( ! empty( $_POST['cookie_notice_options'] ) && check_admin_referer( 'cookie_notice_options-options', '_wpnonce' ) !== false ) {
1551 if ( isset( $_POST['save_cookie_notice_options'] ) ) {
1552 // validate options
1553 $data = $this->validate_options( $_POST['cookie_notice_options'] );
1554
1555 // check network settings
1556 $data['global_override'] = isset( $_POST['cookie_notice_options']['global_override'] );
1557 $data['global_cookie'] = isset( $_POST['cookie_notice_options']['global_cookie'] );
1558 $data['update_notice_diss'] = $cn->options['general']['update_notice_diss'];
1559
1560 if ( $data['global_override'] && ! $cn->options['general']['update_notice_diss'] )
1561 $data['update_notice'] = true;
1562 else
1563 $data['update_notice'] = false;
1564
1565 // update database
1566 update_site_option( 'cookie_notice_options', $data );
1567
1568 // update settings
1569 $cn->options['general'] = $cn->multi_array_merge( $cn->defaults['general'], get_site_option( 'cookie_notice_options', $cn->defaults['general'] ) );
1570 } elseif ( isset( $_POST['reset_cookie_notice_options'] ) ) {
1571 $cn->defaults['general']['update_notice'] = false;
1572 $cn->defaults['general']['update_notice_diss'] = false;
1573
1574 // silent options validation
1575 $this->validate_options( $cn->defaults['general'] );
1576
1577 // update database
1578 update_site_option( 'cookie_notice_options', $cn->defaults['general'] );
1579
1580 // update settings
1581 $cn->options['general'] = $cn->defaults['general'];
1582 }
1583 }
1584
1585 // update status of cookie compliance
1586 $cn->set_status_data();
1587 }
1588 }
1589
1590 /**
1591 * Load scripts and styles - admin.
1592 *
1593 * @return void
1594 */
1595 public function admin_enqueue_scripts( $page ) {
1596 if ( $page === 'toplevel_page_cookie-notice' ) {
1597 // get main instance
1598 $cn = Cookie_Notice();
1599
1600 wp_enqueue_script( 'cookie-notice-admin', COOKIE_NOTICE_URL . '/js/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [ 'jquery', 'wp-color-picker' ], $cn->defaults['version'] );
1601
1602 // prepare script data
1603 $script_data = [
1604 'ajaxURL' => admin_url( 'admin-ajax.php' ),
1605 'nonce' => wp_create_nonce( 'cn-purge-cache' ),
1606 'nonceConditional' => wp_create_nonce( 'cn-get-group-values' ),
1607 'network' => $cn->is_network_admin(),
1608 'resetToDefaults' => esc_html__( 'Are you sure you want to reset these settings to defaults?', 'cookie-notice' )
1609 ];
1610
1611 wp_add_inline_script( 'cookie-notice-admin', 'var cnArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
1612
1613 wp_enqueue_style( 'wp-color-picker' );
1614 }
1615
1616 wp_enqueue_style( 'cookie-notice-admin', COOKIE_NOTICE_URL . '/css/admin' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css' );
1617 }
1618
1619 /**
1620 * Load admin style inline, for menu icon only.
1621 *
1622 * @return void
1623 */
1624 public function admin_print_styles() {
1625 echo '
1626 <style>
1627 a.toplevel_page_cookie-notice .wp-menu-image {
1628 background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAzMjEgMzIxIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zOnNlcmlmPSJodHRwOi8vd3d3LnNlcmlmLmNvbS8iIHN0eWxlPSJmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLW1pdGVybGltaXQ6MjsiPjxwYXRoIGQ9Ik0zMTcuMjc4LDEzMC40NTFjLTAuODEyLC00LjMwMiAtNC4zMDEsLTcuNTYyIC04LjY0MiwtOC4wODFjLTQuMzU0LC0wLjUyMiAtOC41MDYsMS44MjkgLTEwLjMwNyw1LjgyMmMtMy4xNyw3LjAwMyAtMTAuMTMzLDExLjg3MyAtMTguMjA1LDExLjg2NGMtOC45NTUsMC4wMjIgLTE2LjUxNywtNi4wMjEgLTE5LjAzOCwtMTQuMzE1Yy0xLjUyMSwtNS4wNjMgLTYuNzI0LC04LjA2NCAtMTEuODY1LC02Ljg2M2MtMy4xNjMsMC43NDEgLTYuMTU0LDEuMTcyIC05LjEyNSwxLjE3MmMtMjIuMDM5LC0wLjA0MyAtMzkuOTc2LC0xNy45NzkgLTQwLjAxNSwtNDAuMDE5Yy0wLC0yLjk3IDAuNDMsLTUuOTYyIDEuMTY5LC05LjExM2MxLjIxMiwtNS4xNDEgLTEuNzk5LC0xMC4zNTMgLTYuODYsLTExLjg3M2MtOC4yOTUsLTIuNTEzIC0xNC4zMzcsLTEwLjA3NSAtMTQuMzE5LC0xOS4wMjljLTAuMDA5LC04LjA4MiA0Ljg2NCwtMTUuMDM2IDExLjg2NywtMTguMjA4YzMuOTkxLC0xLjc5OCA2LjM0MSwtNS45NjMgNS44MjIsLTEwLjMwNGMtMC41MjIsLTQuMzUxIC0zLjc4MywtNy44NDMgLTguMDg0LC04LjY1MmMtOS41NDMsLTEuNzkyIC0xOS40MjYsLTIuODUyIC0yOS42MTEsLTIuODUyYy04OC4yOTUsMC4wMjIgLTE2MC4wNDMsNzEuNzcgLTE2MC4wNjUsMTYwLjA2NWMwLjAyMiw4OC4yOTUgNzEuNzcsMTYwLjA0MyAxNjAuMDY1LDE2MC4wNjVjODguMjk1LC0wLjAyMiAxNjAuMDQzLC03MS43NyAxNjAuMDY1LC0xNjAuMDY1Yy0wLC0xMC4xODQgLTEuMDYzLC0yMC4wNjcgLTIuODUyLC0yOS42MTRabS01OC4yMjMsMTI4LjYwNGMtMjUuNDAxLDI1LjM4IC02MC4zNTUsNDEuMDY2IC05OC45OSw0MS4wNjZjLTM4LjYzNSwwIC03My41ODgsLTE1LjY4NiAtOTguOTg5LC00MS4wNjZjLTI1LjM4LC0yNS40MDEgLTQxLjA2NiwtNjAuMzU1IC00MS4wNjYsLTk4Ljk5Yy0wLC0zOC42MzUgMTUuNjg2LC03My41ODggNDEuMDY2LC05OC45ODljMjUuNDAxLC0yNS4zOCA2MC4zNTQsLTQxLjA2NiA5OC45ODksLTQxLjA2NmMxLjgwMSwwIDMuNTYsMC4xODkgNS4zNTIsMC4yNjhjLTMuMzQzLDUuODIzIC01LjM0MywxMi41MjcgLTUuMzUyLDE5LjczOGMwLjAxOCwxNC45MzUgOC4zMDQsMjcuNzQyIDIwLjM3OSwzNC41NzVjLTAuMTkyLDEuNzggLTAuMzczLDMuNTYgLTAuMzczLDUuNDRjMC4wMjIsMzMuMTI1IDI2LjkwMyw2MC4wMDcgNjAuMDI1LDYwLjAyNWMxLjg4LDAgMy42NjQsLTAuMTggNS40NDMsLTAuMzY5YzYuODMzLDEyLjA2NSAxOS42MjgsMjAuMzU2IDM0LjU3MiwyMC4zNzhjNy4yMTUsLTAuMDA5IDEzLjkxNiwtMi4wMTEgMTkuNzQxLC01LjM1MmMwLjA4LDEuNzggMC4yNjksMy41NTEgMC4yNjksNS4zNTJjLTAsMzguNjM1IC0xNS42ODYsNzMuNTg5IC00MS4wNjYsOTguOTlabS01OC45NzQsLTE4Ljk1OWMtMCwxMS4wNTIgLTguOTU4LDIwLjAxIC0yMC4wMSwyMC4wMWMtMTEuMDQ4LC0wIC0yMC4wMDUsLTguOTU4IC0yMC4wMDUsLTIwLjAxYy0wLC0xMS4wNDkgOC45NTcsLTIwLjAwNiAyMC4wMDUsLTIwLjAwNmMxMS4wNTIsLTAgMjAuMDEsOC45NTcgMjAuMDEsMjAuMDA2Wm0tODAuMDMxLC0xMC4wMDVjMCw1LjUyNiAtNC40NzksMTAuMDA1IC0xMC4wMDUsMTAuMDA1Yy01LjUyNiwtMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjMgNC40NzksLTEwLjAwMSAxMC4wMDUsLTEwLjAwMWM1LjUyNiwtMCAxMC4wMDUsNC40NzggMTAuMDA1LDEwLjAwMVptMTQwLjA1NSwtMjAuMDA2YzAsNS41MjYgLTQuNDc5LDEwLjAwNSAtMTAuMDA1LDEwLjAwNWMtNS41MjUsMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjYgNC40OCwtMTAuMDA1IDEwLjAwNSwtMTAuMDA1YzUuNTI2LDAgMTAuMDA1LDQuNDc5IDEwLjAwNSwxMC4wMDVabS0xNjAuMDY0LC01MC4wMmMtMCwxMS4wNDggLTguOTU3LDIwLjAwNiAtMjAuMDEsMjAuMDA2Yy0xMS4wNDgsMCAtMjAuMDA1LC04Ljk1OCAtMjAuMDA1LC0yMC4wMDZjLTAsLTExLjA1MiA4Ljk1NywtMjAuMDEgMjAuMDA1LC0yMC4wMWMxMS4wNTMsMCAyMC4wMSw4Ljk1OCAyMC4wMSwyMC4wMVptODAuMDMsMTAuMDA1YzAsNS41MjMgLTQuNDc4LDEwLjAwMSAtMTAuMDAxLDEwLjAwMWMtNS41MjYsMCAtMTAuMDA1LC00LjQ3OCAtMTAuMDA1LC0xMC4wMDFjMCwtNS41MjYgNC40NzksLTEwLjAwNSAxMC4wMDUsLTEwLjAwNWM1LjUyMywwIDEwLjAwMSw0LjQ3OSAxMC4wMDEsMTAuMDA1Wm0xMTUuNDkzLC02OS40MDZjMCw1LjUyNiAtNC40NzksMTAuMDA1IC0xMC4wMDUsMTAuMDA1Yy01LjUyNiwtMCAtMTAuMDA1LC00LjQ3OSAtMTAuMDA1LC0xMC4wMDVjMCwtNS41MjYgNC40NzksLTEwLjAwNSAxMC4wMDUsLTEwLjAwNWM1LjUyNiwtMCAxMC4wMDUsNC40NzkgMTAuMDA1LDEwLjAwNVptLTM1LjUyMywtMTkuODc0Yy0wLDExLjUwMyAtOS4zMjUsMjAuODI4IC0yMC44MjgsMjAuODI4Yy0xMS41MDQsLTAgLTIwLjgyOSwtOS4zMjUgLTIwLjgyOSwtMjAuODI4Yy0wLC0xMS41MDMgOS4zMjUsLTIwLjgyOCAyMC44MjksLTIwLjgyOGMxMS41MDMsLTAgMjAuODI4LDkuMzI1IDIwLjgyOCwyMC44MjhabS0xMTkuOTg1LC0wLjc1OWMtMCwxMS4wNTIgLTguOTU3LDIwLjAxIC0yMC4wMDYsMjAuMDFjLTExLjA1MiwtMCAtMjAuMDA5LC04Ljk1OCAtMjAuMDA5LC0yMC4wMWMtMCwtMTEuMDQ4IDguOTU3LC0yMC4wMDYgMjAuMDA5LC0yMC4wMDZjMTEuMDQ5LC0wIDIwLjAwNiw4Ljk1OCAyMC4wMDYsMjAuMDA2WiIgc3R5bGU9ImZpbGw6I2ZmZjtmaWxsLXJ1bGU6bm9uemVybzsiLz48L3N2Zz4=);
1629 background-position: center center;
1630 background-repeat: no-repeat;
1631 background-size: 18px auto;
1632 }
1633 </style>
1634 ';
1635 }
1636
1637 /**
1638 * Register WPML (>= 3.2) strings if needed.
1639 *
1640 * @global object $wpdb
1641 *
1642 * @return void
1643 */
1644 private function register_wpml_strings() {
1645 // get main instance
1646 $cn = Cookie_Notice();
1647
1648 global $wpdb;
1649
1650 // prepare strings
1651 $strings = [
1652 'Message in the notice' => $cn->options['general']['message_text'],
1653 'Button text' => $cn->options['general']['accept_text'],
1654 'Refuse button text' => $cn->options['general']['refuse_text'],
1655 'Revoke message text' => $cn->options['general']['revoke_message_text'],
1656 'Revoke button text' => $cn->options['general']['revoke_text'],
1657 'Privacy policy text' => $cn->options['general']['see_more_opt']['text'],
1658 'Custom link' => $cn->options['general']['see_more_opt']['link']
1659 ];
1660
1661 // get query results
1662 $results = $wpdb->get_col( $wpdb->prepare( "SELECT name FROM " . $wpdb->prefix . "icl_strings WHERE context = %s", 'Cookie Notice' ) );
1663
1664 // check results
1665 foreach( $strings as $string => $value ) {
1666 // string does not exist?
1667 if ( ! in_array( $string, $results, true ) ) {
1668 // register string
1669 do_action( 'wpml_register_single_string', 'Cookie Notice', $string, $value );
1670 }
1671 }
1672 }
1673
1674 /**
1675 * Display errors and notices.
1676 *
1677 * @global string $pagenow
1678 *
1679 * @return void
1680 */
1681 public function settings_errors() {
1682 global $pagenow;
1683
1684 // force display notices in top menu settings page
1685 if ( $pagenow === 'options-general.php' )
1686 return;
1687
1688 settings_errors( 'cn_cookie_notice_options' );
1689 }
1690
1691 /**
1692 * Save compliance config caching.
1693 *
1694 * @return void
1695 */
1696 public function ajax_purge_cache() {
1697 // valid nonce?
1698 if ( ! check_ajax_referer( 'cn-purge-cache', 'nonce' ) )
1699 exit;
1700
1701 // check capability
1702 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
1703 exit;
1704
1705 // request for new config data
1706 Cookie_Notice()->welcome_api->get_app_config( '', true );
1707
1708 exit;
1709 }
1710
1711 /**
1712 * Generate conditions.
1713 *
1714 * @param array $groups
1715 * @return string
1716 */
1717 public function conditional_display( $groups ) {
1718 $group_template = '
1719 <div%s>
1720 <table class="widefat">
1721 <tbody>
1722 %s
1723 </tbody>
1724 </table>
1725 <h4 class="or-rules">' . esc_html__( 'or', 'cookie-notice' ) . '</h4>
1726 </div>';
1727
1728 $rule_template = '
1729 <tr data-rule-id="__RULE_ID__" %s>
1730 <td class="param">
1731 <select class="rule-type" name="cookie_notice_options[conditional_rules][__GROUP_ID__][__RULE_ID__][param]">
1732 %s
1733 </select>
1734 </td>
1735 <td class="operator">
1736 <select name="cookie_notice_options[conditional_rules][__GROUP_ID__][__RULE_ID__][operator]">
1737 %s
1738 </select>
1739 </td>
1740 <td class="value">
1741 <span class="spinner" style="display: none"></span>
1742 <select name="cookie_notice_options[conditional_rules][__GROUP_ID__][__RULE_ID__][value]">
1743 %s
1744 </select>
1745 </td>
1746 <td class="remove">
1747 <a href="#" class="dashicons dashicons-no-alt remove-rule"></a>
1748 </td>
1749 </tr>';
1750
1751 $html = sprintf(
1752 $group_template,
1753 ' class="rules-group" id="rules-group-template" style="display: none"',
1754 sprintf(
1755 $rule_template,
1756 ' class="rule_template"',
1757 $this->prepare_parameters(),
1758 $this->prepare_operators(),
1759 $this->prepare_values( 'page_type' )
1760 )
1761 ) . '
1762 <div id="cookie-notice-conditions">
1763 <table class="widefat">
1764 <tbody>
1765 <tr>
1766 <td>
1767 <div id="rules-groups">';
1768
1769 if ( ! empty( $groups ) ) {
1770 foreach ( $groups as $group_id => $group ) {
1771 $html_rules = '';
1772
1773 foreach ( $group as $rule_id => $rule ) {
1774 $html_rules .= sprintf(
1775 str_replace(
1776 [ '__GROUP_ID__', '__RULE_ID__' ],
1777 [ (int) $group_id, (int) $rule_id ],
1778 $rule_template
1779 ),
1780 '',
1781 $this->prepare_parameters( $rule['param'] ),
1782 $this->prepare_operators( $rule['operator'] ),
1783 $this->prepare_values( $rule['param'], $rule['value'] )
1784 );
1785 }
1786
1787 $html .= sprintf( str_replace( '__GROUP_ID__', $group_id, $group_template ), ' class="rules-group" id="rules-group-' . $group_id . '"', $html_rules );
1788 }
1789 }
1790
1791 $html .= ' </div>
1792 <a class="add-rule-group button button-primary" href="#">' . esc_html__( '+ Add rule', 'cookie-notice' ) . '</a>
1793 <p class="description">' . esc_html__( 'Create a set of rules to define the exact conditions for displaying or hiding the banner.', 'cookie-notice' ) . '</p>
1794 </td>
1795 </tr>
1796 </tbody>
1797 </table>
1798 </div>';
1799
1800 return $html;
1801 }
1802
1803 /**
1804 * Prepare condition parameters.
1805 *
1806 * @param string $selected
1807 * @return string
1808 */
1809 public function prepare_parameters( $selected = 'page_type' ) {
1810 $html = '';
1811
1812 foreach ( $this->parameters as $id => $element ) {
1813 $html .= '<option value="' . esc_attr( $id ) . '" ' . selected( $id, $selected, false ) . '>' . esc_html( $element ) . '</option>';
1814 }
1815
1816 return $html;
1817 }
1818
1819 /**
1820 * Prepare condition operators.
1821 *
1822 * @param string $selected
1823 * @return string
1824 */
1825 public function prepare_operators( $selected = 'equal' ) {
1826 $html = '';
1827
1828 foreach ( $this->operators as $id => $operator ) {
1829 $html .= '<option value="' . esc_attr( $id ) . '" ' . selected( $id, $selected, false ) . '>' . esc_html( $operator ) . '</option>';
1830 }
1831
1832 return $html;
1833 }
1834
1835 /**
1836 * Prepare condition values.
1837 *
1838 * @param string $type
1839 * @param string $selected
1840 * @return string
1841 */
1842 public function prepare_values( $type = '', $selected = '' ) {
1843 $type = sanitize_key( $type );
1844 $selected = sanitize_key( $selected );
1845 $html = '';
1846
1847 switch ( sanitize_key( $type ) ) {
1848 case 'page':
1849 $pages = $this->get_pages();
1850
1851 if ( ! empty( $pages ) ) {
1852 foreach ( $pages as $page_id => $page_title ) {
1853 $html .= '<option value="' . esc_attr( $page_id ) . '" ' . selected( $page_id, $selected, false ) . '>' . esc_html( $page_title ) . '</option>';
1854 }
1855 }
1856 break;
1857
1858 case 'page_type':
1859 $page_types = $this->get_page_types();
1860
1861 if ( ! empty( $page_types ) ) {
1862 foreach ( $page_types as $page_type => $label ) {
1863 $html .= '<option value="' . esc_attr( $page_type ) . '" ' . selected( $page_type, $selected, false ) . '>' . esc_html( $label ) . '</option>';
1864 }
1865 }
1866 break;
1867
1868 case 'post_type':
1869 $post_types = $this->get_post_types();
1870
1871 if ( ! empty( $post_types ) ) {
1872 foreach ( $post_types as $post_type => $label ) {
1873 $html .= '<option value="' . esc_attr( $post_type ) . '" ' . selected( $post_type, $selected, false ) . '>' . esc_html( $label ) . '</option>';
1874 }
1875 }
1876 break;
1877
1878 case 'user_type':
1879 $user_types = $this->get_user_types();
1880
1881 if ( ! empty( $user_types ) ) {
1882 foreach ( $user_types as $user_type => $username ) {
1883 $html .= '<option value="' . esc_attr( $user_type ) . '" ' . selected( $user_type, $selected, false ) . '>' . esc_html( $username ).'</option>';
1884 }
1885 }
1886 break;
1887
1888 case 'post_type_archive':
1889 $post_type_archives = $this->get_post_type_archives();
1890
1891 if ( ! empty( $post_type_archives ) ) {
1892 foreach ( $post_type_archives as $post_type => $archive_name ) {
1893 $html .= '<option value="' . esc_attr( $post_type ) . '" ' . selected( $post_type, $selected, false ) . '>' . esc_html( $archive_name ) . '</option>';
1894 }
1895 } else
1896 $html .= '<option value="__none__">' . esc_html__( '-- no public archives --', 'cookie-notice' ) . '</option>';
1897 }
1898
1899 return $html;
1900 }
1901
1902 /**
1903 * Check condition rule.
1904 *
1905 * @param string $type
1906 * @param string $operator
1907 * @param string $value
1908 * @return bool
1909 */
1910 public function check_rule( $type = '', $operator = '', $value = '' ) {
1911 if ( ! isset( $this->operators[$operator] ) )
1912 return false;
1913
1914 switch( $type ) {
1915 case 'page':
1916 $pages = $this->get_pages();
1917
1918 $valid_rule = ! empty( $pages[$value] );
1919 break;
1920
1921 case 'page_type':
1922 $page_types = $this->get_page_types();
1923
1924 $valid_rule = ! empty( $page_types[$value] );
1925 break;
1926
1927 case 'post_type':
1928 $post_types = $this->get_post_types();
1929
1930 $valid_rule = ! empty( $post_types[$value] );
1931 break;
1932
1933 case 'user_type':
1934 $user_types = $this->get_user_types();
1935
1936 $valid_rule = ! empty( $user_types[$value] );
1937 break;
1938
1939 case 'post_type_archive':
1940 $post_type_archives = $this->get_post_type_archives();
1941
1942 $valid_rule = ! empty( $post_type_archives[$value] );
1943 break;
1944
1945 default:
1946 $valid_rule = false;
1947 }
1948
1949 return $valid_rule;
1950 }
1951
1952 /**
1953 * Get page types.
1954 *
1955 * @return array
1956 */
1957 public function get_pages() {
1958 $pages = [];
1959
1960 // default arguments
1961 $args = [
1962 'post_type' => 'page',
1963 'post__not_in' => [],
1964 'nopaging' => true,
1965 'posts_per_page' => -1,
1966 'orderby' => 'title',
1967 'order' => 'asc',
1968 'suppress_filters' => false,
1969 'no_found_rows' => true,
1970 'cache_results' => false,
1971 'post_status' => [ 'publish', 'private', 'future' ]
1972 ];
1973
1974 // get static home pages
1975 $homepage = (int) get_option( 'page_for_posts', 0 );
1976 $posts_page = (int) get_option( 'page_on_front', 0 );
1977
1978 // check homepage
1979 if ( $homepage > 0 )
1980 $args['post__not_in'][] = $homepage;
1981
1982 // check posts page
1983 if ( $posts_page > 0 )
1984 $args['post__not_in'][] = $posts_page;
1985
1986 $query = new WP_Query( $args );
1987
1988 if ( ! empty( $query->posts ) ) {
1989 foreach ( $query->posts as $page ) {
1990 $page_id = (int) $page->ID;
1991
1992 $pages[$page_id] = trim( $page->post_title ) === '' ? sprintf( __( 'Untitled Page %d', 'cookie-notice' ), $page_id ) : $page->post_title;
1993 }
1994 }
1995
1996 return $pages;
1997 }
1998
1999 /**
2000 * Get page types.
2001 *
2002 * @return array
2003 */
2004 public function get_page_types() {
2005 return [
2006 'front' => __( 'Front Page', 'cookie-notice' ),
2007 'home' => __( 'Home Page', 'cookie-notice' )
2008 ];
2009 }
2010
2011 /**
2012 * Get user types.
2013 *
2014 * @return array
2015 */
2016 public function get_user_types() {
2017 return [
2018 'logged_in' => __( 'Logged in', 'cookie-notice' ),
2019 'guest' => __( 'Guest', 'cookie-notice' )
2020 ];
2021 }
2022
2023 /**
2024 * Get public post types.
2025 *
2026 * @return array
2027 */
2028 public function get_post_types() {
2029 // get public post types
2030 $post_types = get_post_types(
2031 [
2032 'public' => true
2033 ],
2034 'objects',
2035 'and'
2036 );
2037
2038 $data = [];
2039
2040 if ( ! empty( $post_types ) ) {
2041 foreach ( $post_types as $key => $post_type ) {
2042 $data[$key] = $post_type->labels->singular_name;
2043 }
2044 }
2045
2046 asort( $data, SORT_STRING );
2047
2048 return $data;
2049 }
2050
2051 /**
2052 * Get public post type archives.
2053 *
2054 * @return array
2055 */
2056 public function get_post_type_archives() {
2057 // get public post types with archives
2058 $post_types = get_post_types(
2059 [
2060 'has_archive' => true,
2061 'public' => true
2062 ],
2063 'objects',
2064 'and'
2065 );
2066
2067 $archives = [];
2068
2069 if ( ! empty( $post_types ) ) {
2070 foreach ( $post_types as $key => $post_type ) {
2071 $archives[$key] = $post_type->labels->name;
2072 }
2073 }
2074
2075 // sort archives alphabetically
2076 asort( $archives, SORT_STRING );
2077
2078 return $archives;
2079 }
2080
2081 /**
2082 * Get group rule values.
2083 *
2084 * @return void
2085 */
2086 public function get_group_rule_values() {
2087 if ( isset( $_POST['action'], $_POST['cn_param'], $_POST['cn_nonce'] ) && wp_verify_nonce( $_POST['cn_nonce'], 'cn-get-group-values' ) !== false ) {
2088 echo wp_json_encode(
2089 [
2090 'select' => $this->prepare_values( sanitize_key( $_POST['cn_param'] ) )
2091 ]
2092 );
2093 }
2094
2095 exit;
2096 }
2097
2098 /**
2099 *
2100 */
2101 public function get_analytics_app_data() {
2102 return $this->analytics_app_data;
2103 }
2104
2105 /**
2106 * Add new properties to style safe list.
2107 *
2108 * @param array $styles
2109 * @return array
2110 */
2111 public function allow_style_attributes( $styles ) {
2112 $styles[] = 'display';
2113
2114 return $styles;
2115 }
2116 }
1 <?php
2
3 // exit if accessed directly
4 if ( ! defined( 'ABSPATH' ) )
5 exit;
6
7 /**
8 * Cookie_Notice_Welcome_API class.
9 *
10 * @class Cookie_Notice_Welcome_API
11 */
12 class Cookie_Notice_Welcome_API {
13
14 /**
15 * Constructor.
16 *
17 * @return void
18 */
19 public function __construct() {
20 // actions
21 add_action( 'init', [ $this, 'check_cron' ] );
22 add_action( 'cookie_notice_get_app_analytics', [ $this, 'get_app_analytics' ] );
23 add_action( 'cookie_notice_get_app_config', [ $this, 'get_app_config' ] );
24 add_action( 'wp_ajax_cn_api_request', [ $this, 'api_request' ] );
25 }
26
27 /**
28 * Ajax API request.
29 *
30 * @return void
31 */
32 public function api_request() {
33 // check capabilities
34 if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
35 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
36
37 // check main nonce
38 if ( ! check_ajax_referer( 'cookie-notice-welcome', 'nonce' ) )
39 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
40
41 // get request
42 $request = isset( $_POST['request'] ) ? sanitize_key( $_POST['request'] ) : '';
43
44 // no valid request?
45 if ( ! in_array( $request, [ 'register', 'login', 'configure', 'select_plan', 'payment', 'get_bt_init_token', 'use_license' ], true ) )
46 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
47
48 $special_actions = [ 'register', 'login', 'configure', 'payment' ];
49
50 // payment nonce
51 if ( $request === 'payment' )
52 $nonce = isset( $_POST['cn_payment_nonce'] ) ? sanitize_key( $_POST['cn_payment_nonce'] ) : '';
53 // special nonce
54 elseif ( in_array( $request, $special_actions, true ) )
55 $nonce = isset( $_POST['cn_nonce'] ) ? sanitize_key( $_POST['cn_nonce'] ) : '';
56
57 // check additional nonce
58 if ( in_array( $request, $special_actions, true ) && ! wp_verify_nonce( $nonce, 'cn_api_' . $request ) )
59 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
60
61 $errors = [];
62 $response = false;
63
64 // get main instance
65 $cn = Cookie_Notice();
66
67 // get site language
68 $locale = get_locale();
69 $locale_code = explode( '_', $locale );
70
71 // check network
72 $network = $cn->is_network_admin();
73
74 // get app token data
75 if ( $network )
76 $data_token = get_site_transient( 'cookie_notice_app_token' );
77 else
78 $data_token = get_transient( 'cookie_notice_app_token' );
79
80 $admin_email = ! empty( $data_token->email ) ? $data_token->email : '';
81 $app_id = $cn->options['general']['app_id'];
82
83 $params = [];
84
85 switch ( $request ) {
86 case 'use_license':
87 $subscriptionID = isset( $_POST['subscriptionID'] ) ? (int) $_POST['subscriptionID'] : 0;
88
89 $result = $this->request(
90 'assign_subscription',
91 [
92 'AppID' => $app_id,
93 'subscriptionID' => $subscriptionID
94 ]
95 );
96
97 // errors?
98 if ( ! empty( $result->message ) ) {
99 $response = [ 'error' => $result->message ];
100 break;
101 } else
102 $response = $result;
103
104 break;
105
106 case 'get_bt_init_token':
107 $result = $this->request( 'get_token' );
108
109 // is token available?
110 if ( ! empty( $result->token ) )
111 $response = [ 'token' => $result->token ];
112 break;
113
114 case 'payment':
115 $error = [ 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
116
117 // empty data?
118 if ( empty( $_POST['payment_nonce'] ) || empty( $_POST['plan'] ) || empty( $_POST['method'] ) ) {
119 $response = $error;
120 break;
121 }
122
123 // validate plan and payment method
124 $available_plans = [
125 'compliance_monthly_notrial',
126 'compliance_monthly_5',
127 'compliance_monthly_10',
128 'compliance_monthly_20',
129 'compliance_yearly_notrial',
130 'compliance_yearly_5',
131 'compliance_yearly_10',
132 'compliance_yearly_20'
133 ];
134
135 $available_payment_methods = [
136 'credit_card',
137 'paypal'
138 ];
139
140 $plan = sanitize_key( $_POST['plan'] );
141
142 if ( ! in_array( $_POST['plan'], $available_plans, true ) )
143 $plan = false;
144
145 $method = sanitize_key( $_POST['method'] );
146
147 if ( ! in_array( $_POST['method'], $available_payment_methods, true ) )
148 $method = false;
149
150 // valid plan and payment method?
151 if ( empty( $plan ) || empty( $method ) ) {
152 $response = [ 'error' => esc_html__( 'Empty plan or payment method data.', 'cookie-notice' ) ];
153 break;
154 }
155
156 $result = $this->request(
157 'get_customer',
158 [
159 'AppID' => $app_id,
160 'PlanId' => $plan
161 ]
162 );
163
164 // user found?
165 if ( ! empty( $result->id ) ) {
166 $customer = $result;
167 // create user
168 } else {
169 $result = $this->request(
170 'create_customer',
171 [
172 'AppID' => $app_id,
173 'AdminID' => $admin_email, // remove later - AdminID from API response
174 'PlanId' => $plan,
175 'paymentMethodNonce' => sanitize_key( $_POST['payment_nonce'] )
176 ]
177 );
178
179 if ( ! empty( $result->success ) )
180 $customer = $result->customer;
181 else
182 $customer = $result;
183 }
184
185 // user created/received?
186 if ( empty( $customer->id ) ) {
187 $response = [ 'error' => esc_html__( 'Unable to create customer data.', 'cookie-notice' ) ];
188 break;
189 }
190
191 // selected payment method
192 $payment_method = false;
193
194 // get payment identifier (email or 4 digits)
195 $identifier = isset( $_POST['cn_payment_identifier'] ) ? sanitize_text_field( $_POST['cn_payment_identifier'] ) : '';
196
197 // customer available payment methods
198 $payment_methods = ! empty( $customer->paymentMethods ) ? $customer->paymentMethods : [];
199
200 // try to find payment method
201 if ( ! empty( $payment_methods ) && is_array( $payment_methods ) ) {
202 foreach ( $payment_methods as $pm ) {
203 // paypal
204 if ( isset( $pm->email ) && $pm->email === $identifier )
205 $payment_method = $pm;
206 // credit card
207 elseif ( isset( $pm->last4 ) && $pm->last4 === $identifier )
208 $payment_method = $pm;
209 }
210 }
211
212 // if payment method was not identified, create it
213 if ( ! $payment_method ) {
214 $result = $this->request(
215 'create_payment_method',
216 [
217 'AppID' => $app_id,
218 'paymentMethodNonce' => sanitize_key( $_POST['payment_nonce'] )
219 ]
220 );
221
222 // payment method created successfully?
223 if ( ! empty( $result->success ) ) {
224 $payment_method = $result->paymentMethod;
225 } else {
226 $response = [ 'error' => esc_html__( 'Unable to create payment mehotd.', 'cookie-notice' ) ];
227 break;
228 }
229 }
230
231 if ( ! isset( $payment_method->token ) ) {
232 $response = [ 'error' => esc_html__( 'No payment method token.', 'cookie-notice' ) ];
233 break;
234 }
235
236 // @todo: check if subscription exists
237 $subscription = $this->request(
238 'create_subscription',
239 [
240 'AppID' => $app_id,
241 'PlanId' => $plan,
242 'paymentMethodToken' => $payment_method->token
243 ]
244 );
245
246 // subscription assigned?
247 if ( ! empty( $subscription->error ) ) {
248 $response = $subscription->error;
249 break;
250 }
251
252 $status_data = $cn->defaults['data'];
253
254 // update app status
255 if ( $network ) {
256 $status_data = get_site_option( 'cookie_notice_status', $status_data );
257 $status_data['subscription'] = 'pro';
258
259 update_site_option( 'cookie_notice_status', $status_data );
260 } else {
261 $status_data = get_option( 'cookie_notice_status', $status_data );
262 $status_data['subscription'] = 'pro';
263
264 update_option( 'cookie_notice_status', $status_data );
265 }
266
267 $response = $app_id;
268 break;
269
270 case 'register':
271 // check terms
272 $terms = isset( $_POST['terms'] );
273
274 // no terms?
275 if ( ! $terms ) {
276 $response = [ 'error' => esc_html__( 'Please accept the Terms of Service to proceed.', 'cookie-notice' ) ];
277 break;
278 }
279
280 // check email
281 $email = isset( $_POST['email'] ) ? is_email( $_POST['email'] ) : false;
282
283 // empty email?
284 if ( ! $email ) {
285 $response = [ 'error' => esc_html__( 'Email is not allowed to be empty.', 'cookie-notice' ) ];
286 break;
287 }
288
289 // check passwords
290 $pass = ! empty( $_POST['pass'] ) ? stripslashes( $_POST['pass'] ) : '';
291 $pass2 = ! empty( $_POST['pass2'] ) ? stripslashes( $_POST['pass2'] ) : '';
292
293 // empty password?
294 if ( ! $pass || ! is_string( $pass ) ) {
295 $response = [ 'error' => esc_html__( 'Password is not allowed to be empty.', 'cookie-notice' ) ];
296 break;
297 }
298
299 // invalid password?
300 if ( preg_match( '/^(?=.*[A-Z])(?=.*\d)[\w !"#$%&\'()*\+,\-.\/:;<=>?@\[\]^\`\{\|\}\~\\\\]{8,}$/', $pass ) !== 1 ) {
301 $response = [ 'error' => esc_html__( 'The password contains illegal characters or does not meet the conditions.', 'cookie-notice' ) ];
302 break;
303 }
304
305 // no match?
306 if ( $pass !== $pass2 ) {
307 $response = [ 'error' => esc_html__( 'Passwords do not match.', 'cookie-notice' ) ];
308 break;
309 }
310
311 $params = [
312 'AdminID' => $email,
313 'Password' => $pass,
314 'Language' => ! empty( $_POST['language'] ) ? sanitize_key( $_POST['language'] ) : 'en'
315 ];
316
317 $response = $this->request( 'register', $params );
318
319 // errors?
320 if ( ! empty( $response->error ) )
321 break;
322
323 // errors?
324 if ( ! empty( $response->message ) ) {
325 $response->error = $response->message;
326 break;
327 }
328
329 // ok, so log in now
330 $params = [
331 'AdminID' => $email,
332 'Password' => $pass
333 ];
334
335 $response = $this->request( 'login', $params );
336
337 // errors?
338 if ( ! empty( $response->error ) )
339 break;
340
341 // errors?
342 if ( ! empty( $response->message ) ) {
343 $response->error = $response->message;
344 break;
345 }
346
347 // token in response?
348 if ( empty( $response->data->token ) ) {
349 $response = [ 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
350 break;
351 }
352
353 // set token
354 if ( $network )
355 set_site_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
356 else
357 set_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
358
359 // multisite?
360 if ( is_multisite() ) {
361 switch_to_blog( 1 );
362 $site_title = get_bloginfo( 'name' );
363 $site_url = network_site_url();
364 $site_description = get_bloginfo( 'description' );
365 restore_current_blog();
366 } else {
367 $site_title = get_bloginfo( 'name' );
368 $site_url = get_home_url();
369 $site_description = get_bloginfo( 'description' );
370 }
371
372 // create new app, no need to check existing
373 $params = [
374 'DomainName' => $site_title,
375 'DomainUrl' => $site_url
376 ];
377
378 if ( ! empty( $site_description ) )
379 $params['DomainDescription'] = $site_description;
380
381 $response = $this->request( 'app_create', $params );
382
383 // errors?
384 if ( ! empty( $response->message ) ) {
385 $response->error = $response->message;
386 break;
387 }
388
389 // data in response?
390 if ( empty( $response->data->AppID ) || empty( $response->data->SecretKey ) ) {
391 $response = [ 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
392 break;
393 } else {
394 $app_id = $response->data->AppID;
395 $secret_key = $response->data->SecretKey;
396 }
397
398 // update options: app id and secret key
399 $cn->options['general'] = wp_parse_args( [ 'app_id' => $app_id, 'app_key' => $secret_key ], $cn->options['general'] );
400
401 if ( $network ) {
402 $cn->options['general']['global_override'] = true;
403
404 update_site_option( 'cookie_notice_options', $cn->options['general'] );
405
406 // get options
407 $app_config = get_site_transient( 'cookie_notice_app_quick_config' );
408 } else {
409 update_option( 'cookie_notice_options', $cn->options['general'] );
410
411 // get options
412 $app_config = get_transient( 'cookie_notice_app_quick_config' );
413 }
414
415 // create quick config
416 $params = ! empty( $app_config ) && is_array( $app_config ) ? $app_config : [];
417
418 // cast to objects
419 if ( $params ) {
420 $new_params = [];
421
422 foreach ( $params as $key => $array ) {
423 $object = new stdClass();
424
425 foreach ( $array as $subkey => $value ) {
426 $new_params[$key] = $object;
427 $new_params[$key]->{$subkey} = $value;
428 }
429 }
430
431 $params = $new_params;
432 }
433
434 $params['AppID'] = $app_id;
435
436 // @todo When mutliple default languages are supported
437 $params['DefaultLanguage'] = 'en';
438
439 if ( ! array_key_exists( 'text', $params ) )
440 $params['text'] = new stdClass();
441
442 // add privacy policy url
443 $params['text']->privacyPolicyUrl = get_privacy_policy_url();
444
445 // add translations if needed
446 if ( $locale_code[0] !== 'en' )
447 $params['Languages'] = [ $locale_code[0] ];
448
449 $response = $this->request( 'quick_config', $params );
450 $status_data = $cn->defaults['data'];
451
452 if ( $response->status === 200 ) {
453 // notify publish app
454 $params = [
455 'AppID' => $app_id
456 ];
457
458 $response = $this->request( 'notify_app', $params );
459
460 if ( $response->status === 200 ) {
461 $response = true;
462 $status_data['status'] = 'active';
463
464 // update app status
465 if ( $network )
466 update_site_option( 'cookie_notice_status', $status_data );
467 else
468 update_option( 'cookie_notice_status', $status_data );
469 } else {
470 $status_data['status'] = 'pending';
471
472 // update app status
473 if ( $network )
474 update_site_option( 'cookie_notice_status', $status_data );
475 else
476 update_option( 'cookie_notice_status', $status_data );
477
478 // errors?
479 if ( ! empty( $response->error ) )
480 break;
481
482 // errors?
483 if ( ! empty( $response->message ) ) {
484 $response->error = $response->message;
485 break;
486 }
487 }
488 } else {
489 $status_data['status'] = 'pending';
490
491 // update app status
492 if ( $network )
493 update_site_option( 'cookie_notice_status', $status_data );
494 else
495 update_option( 'cookie_notice_status', $status_data );
496
497 // errors?
498 if ( ! empty( $response->error ) ) {
499 $response->error = $response->error;
500 break;
501 }
502
503 // errors?
504 if ( ! empty( $response->message ) ) {
505 $response->error = $response->message;
506 break;
507 }
508 }
509
510 break;
511
512 case 'login':
513 // check email
514 $email = isset( $_POST['email'] ) ? is_email( $_POST['email'] ) : false;
515
516 // invalid email?
517 if ( ! $email ) {
518 $response = [ 'error' => esc_html__( 'Email is not allowed to be empty.', 'cookie-notice' ) ];
519 break;
520 }
521
522 // check password
523 $pass = ! empty( $_POST['pass'] ) ? preg_replace( '/[^\w !"#$%&\'()*\+,\-.\/:;<=>?@\[\]^\`\{\|\}\~\\\\]/', '', $_POST['pass'] ) : '';
524
525 // empty password?
526 if ( ! $pass ) {
527 $response = [ 'error' => esc_html__( 'Password is not allowed to be empty.', 'cookie-notice' ) ];
528 break;
529 }
530
531 $params = [
532 'AdminID' => $email,
533 'Password' => $pass
534 ];
535
536 $response = $this->request( $request, $params );
537
538 // errors?
539 if ( ! empty( $response->error ) )
540 break;
541
542 // errors?
543 if ( ! empty( $response->message ) ) {
544 $response->error = $response->message;
545 break;
546 }
547
548 // token in response?
549 if ( empty( $response->data->token ) ) {
550 $response = [ 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
551 break;
552 }
553
554 // set token
555 if ( $network )
556 set_site_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
557 else
558 set_transient( 'cookie_notice_app_token', $response->data, 24 * HOUR_IN_SECONDS );
559
560 // get apps and check if one for the current domain already exists
561 $response = $this->request( 'list_apps', [] );
562
563 // errors?
564 if ( ! empty( $response->message ) ) {
565 $response->error = $response->message;
566 break;
567 }
568
569 $apps_list = [];
570 $app_exists = false;
571
572 // multisite?
573 if ( is_multisite() ) {
574 switch_to_blog( 1 );
575 $site_title = get_bloginfo( 'name' );
576 $site_url = network_site_url();
577 $site_description = get_bloginfo( 'description' );
578 restore_current_blog();
579 } else {
580 $site_title = get_bloginfo( 'name' );
581 $site_url = get_home_url();
582 $site_description = get_bloginfo( 'description' );
583 }
584
585 // apps added, check if current one exists
586 if ( ! empty( $response->data ) ) {
587 $apps_list = (array) $response->data;
588
589 foreach ( $apps_list as $index => $app ) {
590 $site_without_http = trim( str_replace( [ 'http://', 'https://' ], '', $site_url ), '/' );
591
592 if ( $app->DomainUrl === $site_without_http ) {
593 $app_exists = $app;
594
595 continue;
596 }
597 }
598 }
599
600 // if no app, create one
601 if ( ! $app_exists ) {
602 // create new app
603 $params = [
604 'DomainName' => $site_title,
605 'DomainUrl' => $site_url,
606 ];
607
608 if ( ! empty( $site_description ) )
609 $params['DomainDescription'] = $site_description;
610
611 $response = $this->request( 'app_create', $params );
612
613 // errors?
614 if ( ! empty( $response->message ) ) {
615 $response->error = $response->message;
616 break;
617 }
618
619 $app_exists = $response->data;
620 }
621
622 // check if we have the valid app data
623 if ( empty( $app_exists->AppID ) || empty( $app_exists->SecretKey ) ) {
624 $response = [ 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
625 break;
626 }
627
628 // get subscriptions
629 $subscriptions = [];
630
631 $params = [
632 'AppID' => $app_exists->AppID
633 ];
634
635 $response = $this->request( 'get_subscriptions', $params );
636
637 // errors?
638 if ( ! empty( $response->error ) ) {
639 $response->error = $response->error;
640 break;
641 } else
642 $subscriptions = map_deep( (array) $response->data, 'sanitize_text_field' );
643
644 // set subscriptions data
645 if ( $network )
646 set_site_transient( 'cookie_notice_app_subscriptions', $subscriptions, 24 * HOUR_IN_SECONDS );
647 else
648 set_transient( 'cookie_notice_app_subscriptions', $subscriptions, 24 * HOUR_IN_SECONDS );
649
650 // update options: app ID and secret key
651 $cn->options['general'] = wp_parse_args( [ 'app_id' => $app_exists->AppID, 'app_key' => $app_exists->SecretKey ], $cn->options['general'] );
652
653 if ( $network ) {
654 $cn->options['general']['global_override'] = true;
655
656 update_site_option( 'cookie_notice_options', $cn->options['general'] );
657 } else {
658 update_option( 'cookie_notice_options', $cn->options['general'] );
659 }
660
661 // create quick config
662 $params = [
663 'AppID' => $app_exists->AppID,
664 'DefaultLanguage' => 'en',
665 'text' => new stdClass()
666 ];
667
668 // add privacy policy url
669 $params['text']->privacyPolicyUrl = get_privacy_policy_url();
670
671 // add translations if needed
672 if ( $locale_code[0] !== 'en' )
673 $params['Languages'] = [ $locale_code[0] ];
674
675 $response = $this->request( 'quick_config', $params );
676 $status_data = $cn->defaults['data'];
677
678 if ( $response->status === 200 ) {
679 // @todo notify publish app
680 $params = [
681 'AppID' => $app_exists->AppID
682 ];
683
684 $response = $this->request( 'notify_app', $params );
685
686 if ( $response->status === 200 ) {
687 $response = true;
688 $status_data['status'] = 'active';
689
690 // update app status
691 if ( $network )
692 update_site_option( 'cookie_notice_status', $status_data );
693 else
694 update_option( 'cookie_notice_status', $status_data );
695 } else {
696 $status_data['status'] = 'pending';
697
698 // update app status
699 if ( $network )
700 update_site_option( 'cookie_notice_status', $status_data );
701 else
702 update_option( 'cookie_notice_status', $status_data );
703
704 // errors?
705 if ( ! empty( $response->error ) )
706 break;
707
708 // errors?
709 if ( ! empty( $response->message ) ) {
710 $response->error = $response->message;
711 break;
712 }
713 }
714 } else {
715 $status_data['status'] = 'pending';
716
717 // update app status
718 if ( $network )
719 update_site_option( 'cookie_notice_status', $status_data );
720 else
721 update_option( 'cookie_notice_status', $status_data );
722
723 // errors?
724 if ( ! empty( $response->error ) ) {
725 $response->error = $response->error;
726 break;
727 }
728
729 // errors?
730 if ( ! empty( $response->message ) ) {
731 $response->error = $response->message;
732 break;
733 }
734 }
735
736 // all ok, return subscriptions
737 $response = (object) [];
738 $response->subscriptions = $subscriptions;
739 break;
740
741 case 'configure':
742 $fields = [
743 'cn_position',
744 'cn_color_primary',
745 'cn_color_background',
746 'cn_color_border',
747 'cn_color_text',
748 'cn_color_heading',
749 'cn_color_button_text',
750 'cn_laws',
751 'cn_naming',
752 'cn_privacy_paper',
753 'cn_privacy_contact'
754 ];
755
756 $options = [];
757
758 // loop through potential config form fields
759 foreach ( $fields as $field ) {
760 switch ( $field ) {
761 case 'cn_position':
762 // sanitize position
763 $position = isset( $_POST[$field] ) ? sanitize_key( $_POST[$field] ) : '';
764
765 // valid position?
766 if ( in_array( $position, [ 'bottom', 'top', 'left', 'right', 'center' ], true ) )
767 $options['design']['position'] = $position;
768 else
769 $options['design']['position'] = 'bottom';
770 break;
771
772 case 'cn_color_primary':
773 // sanitize color
774 $color = isset( $_POST[$field] ) ? sanitize_hex_color( $_POST[$field] ) : '';
775
776 // valid color?
777 if ( empty( $color ) )
778 $options['design']['primaryColor'] = '#20c19e';
779 else
780 $options['design']['primaryColor'] = $color;
781 break;
782
783 case 'cn_color_background':
784 // sanitize color
785 $color = isset( $_POST[$field] ) ? sanitize_hex_color( $_POST[$field] ) : '';
786
787 // valid color?
788 if ( empty( $color ) )
789 $options['design']['bannerColor'] = '#ffffff';
790 else
791 $options['design']['bannerColor'] = $color;
792 break;
793
794 case 'cn_color_border':
795 // sanitize color
796 $color = isset( $_POST[$field] ) ? sanitize_hex_color( $_POST[$field] ) : '';
797
798 // valid color?
799 if ( empty( $color ) )
800 $options['design']['borderColor'] = '#5e6a74';
801 else
802 $options['design']['borderColor'] = $color;
803 break;
804
805 case 'cn_color_text':
806 // sanitize color
807 $color = isset( $_POST[$field] ) ? sanitize_hex_color( $_POST[$field] ) : '';
808
809 // valid color?
810 if ( empty( $color ) )
811 $options['design']['textColor'] = '#434f58';
812 else
813 $options['design']['textColor'] = $color;
814 break;
815
816 case 'cn_color_heading':
817 // sanitize color
818 $color = isset( $_POST[$field] ) ? sanitize_hex_color( $_POST[$field] ) : '';
819
820 // valid color?
821 if ( empty( $color ) )
822 $options['design']['headingColor'] = '#434f58';
823 else
824 $options['design']['headingColor'] = $color;
825 break;
826
827 case 'cn_color_button_text':
828 // sanitize color
829 $color = isset( $_POST[$field] ) ? sanitize_hex_color( $_POST[$field] ) : '';
830
831 // valid color?
832 if ( empty( $color ) )
833 $options['design']['btnTextColor'] = '#ffffff';
834 else
835 $options['design']['btnTextColor'] = $color;
836 break;
837
838 case 'cn_laws':
839 $new_options = [];
840
841 // any data?
842 if ( ! empty( $_POST[$field] ) && is_array( $_POST[$field] ) ) {
843 $options['laws'] = array_map( 'sanitize_text_field', $_POST[$field] );
844
845 foreach ( $options['laws'] as $law ) {
846 if ( in_array( $law, [ 'gdpr', 'ccpa' ], true ) )
847 $new_options[$law] = true;
848 }
849 }
850
851 $options['laws'] = $new_options;
852
853 // GDPR
854 if ( array_key_exists( 'gdpr', $options['laws'] ) )
855 $options['config']['privacyPolicyLink'] = true;
856 else
857 $options['config']['privacyPolicyLink'] = false;
858
859 // CCPA
860 if ( array_key_exists( 'ccpa', $options['laws'] ) )
861 $options['config']['dontSellLink'] = true;
862 else
863 $options['config']['dontSellLink'] = false;
864 break;
865
866 case 'cn_naming':
867 $naming = isset( $_POST[$field] ) ? (int) $_POST[$field] : 1;
868 $naming = in_array( $naming, [ 1, 2, 3 ] ) ? $naming : 1;
869
870 // english only for now
871 $level_names = [
872 1 => [
873 1 => 'Silver',
874 2 => 'Gold',
875 3 => 'Platinum'
876 ],
877 2 => [
878 1 => 'Private',
879 2 => 'Balanced',
880 3 => 'Personalized'
881 ],
882 3 => [
883 1 => 'Reject All',
884 2 => 'Accept Some',
885 3 => 'Accept All'
886 ]
887 ];
888
889 $options['text'] = [
890 'levelNameText_1' => $level_names[$naming][1],
891 'levelNameText_2' => $level_names[$naming][2],
892 'levelNameText_3' => $level_names[$naming][3]
893 ];
894 break;
895
896 case 'cn_privacy_paper':
897 $options['config']['privacyPaper'] = false; // isset( $_POST[$field] );
898 break;
899
900 case 'cn_privacy_contact':
901 $options['config']['privacyContact'] = false; // isset( $_POST[$field] );
902 break;
903 }
904 }
905
906 // set options
907 if ( $network )
908 set_site_transient( 'cookie_notice_app_quick_config', $options, 24 * HOUR_IN_SECONDS );
909 else
910 set_transient( 'cookie_notice_app_quick_config', $options, 24 * HOUR_IN_SECONDS );
911 break;
912
913 case 'select_plan':
914 break;
915 }
916
917 echo wp_json_encode( $response );
918 exit;
919 }
920
921 /**
922 * API request.
923 *
924 * @param string $request The requested action.
925 * @param array $params Parameters for the API action.
926 * @return string|array
927 */
928 private function request( $request = '', $params = [] ) {
929 // get main instance
930 $cn = Cookie_Notice();
931
932 $api_args = [
933 'timeout' => 60,
934 'sslverify' => false,
935 'headers' => [
936 'x-api-key' => $cn->get_api_key()
937 ]
938 ];
939 $api_params = [];
940 $json = false;
941
942 // check network
943 $network = $cn->is_network_admin();
944
945 // get app token data
946 if ( $network )
947 $data_token = get_site_transient( 'cookie_notice_app_token' );
948 else
949 $data_token = get_transient( 'cookie_notice_app_token' );
950
951 $api_token = ! empty( $data_token->token ) ? $data_token->token : '';
952
953 switch ( $request ) {
954 case 'register':
955 $api_url = $cn->get_url( 'account_api', '/api/account/account/registration' );
956 $api_args['method'] = 'POST';
957 break;
958
959 case 'login':
960 $api_url = $cn->get_url( 'account_api', '/api/account/account/login' );
961 $api_args['method'] = 'POST';
962 break;
963
964 case 'list_apps':
965 $api_url = $cn->get_url( 'account_api', '/api/account/app/list' );
966 $api_args['method'] = 'GET';
967 $api_args['headers'] = array_merge(
968 $api_args['headers'],
969 [
970 'Authorization' => 'Bearer ' . $api_token
971 ]
972 );
973 break;
974
975 case 'app_create':
976 $api_url = $cn->get_url( 'account_api', '/api/account/app/add' );
977 $api_args['method'] = 'POST';
978 $api_args['headers'] = array_merge(
979 $api_args['headers'],
980 [
981 'Authorization' => 'Bearer ' . $api_token
982 ]
983 );
984 break;
985
986 case 'get_analytics':
987 $api_url = $cn->get_url( 'transactional_api', '/api/transactional/analytics/analytics-data' );
988 $api_args['method'] = 'GET';
989
990 $diff_data = $cn->settings->get_analytics_app_data();
991
992 if ( ! empty( $diff_data ) ) {
993 $app_data = [
994 'app-id' => $diff_data['id'],
995 'app-secret-key' => $diff_data['key']
996 ];
997 } else {
998 $app_data = [
999 'app-id' => $cn->options['general']['app_id'],
1000 'app-secret-key' => $cn->options['general']['app_key']
1001 ];
1002 }
1003
1004 $api_args['headers'] = array_merge( $api_args['headers'], $app_data );
1005 break;
1006
1007 case 'get_config':
1008 $api_url = $cn->get_url( 'designer_api', '/api/designer/user-design-live' );
1009 $api_args['method'] = 'GET';
1010 break;
1011
1012 case 'quick_config':
1013 $json = true;
1014 $api_url = $cn->get_url( 'designer_api', '/api/designer/user-design/quick' );
1015 $api_args['method'] = 'POST';
1016 $api_args['headers'] = array_merge(
1017 $api_args['headers'],
1018 [
1019 'Authorization' => 'Bearer ' . $api_token,
1020 'Content-Type' => 'application/json; charset=utf-8'
1021 ]
1022 );
1023 break;
1024
1025 case 'notify_app':
1026 $json = true;
1027 $api_url = $cn->get_url( 'account_api', '/api/account/app/notifyAppPublished' );
1028 $api_args['method'] = 'POST';
1029 $api_args['headers'] = array_merge(
1030 $api_args['headers'],
1031 [
1032 'Authorization' => 'Bearer ' . $api_token,
1033 'Content-Type' => 'application/json; charset=utf-8'
1034 ]
1035 );
1036 break;
1037
1038 // braintree init token
1039 case 'get_token':
1040 $api_url = $cn->get_url( 'account_api', '/api/account/braintree' );
1041 $api_args['method'] = 'GET';
1042 $api_args['headers'] = array_merge(
1043 $api_args['headers'],
1044 [
1045 'Authorization' => 'Bearer ' . $api_token
1046 ]
1047 );
1048 break;
1049
1050 // braintree get customer
1051 case 'get_customer':
1052 $json = true;
1053 $api_url = $cn->get_url( 'account_api', '/api/account/braintree/findcustomer' );
1054 $api_args['method'] = 'POST';
1055 $api_args['data_format'] = 'body';
1056 $api_args['headers'] = array_merge(
1057 $api_args['headers'],
1058 [
1059 'Authorization' => 'Bearer ' . $api_token,
1060 'Content-Type' => 'application/json; charset=utf-8'
1061 ]
1062 );
1063 break;
1064
1065 // braintree create customer in vault
1066 case 'create_customer':
1067 $json = true;
1068 $api_url = $cn->get_url( 'account_api', '/api/account/braintree/createcustomer' );
1069 $api_args['method'] = 'POST';
1070 $api_args['headers'] = array_merge(
1071 $api_args['headers'],
1072 [
1073 'Authorization' => 'Bearer ' . $api_token,
1074 'Content-Type' => 'application/json; charset=utf-8'
1075 ]
1076 );
1077 break;
1078
1079 // braintree get subscriptions
1080 case 'get_subscriptions':
1081 $json = true;
1082 $api_url = $cn->get_url( 'account_api', '/api/account/braintree/subscriptionlists' );
1083 $api_args['method'] = 'POST';
1084 $api_args['headers'] = array_merge(
1085 $api_args['headers'],
1086 [
1087 'Authorization' => 'Bearer ' . $api_token,
1088 'Content-Type' => 'application/json; charset=utf-8'
1089 ]
1090 );
1091 break;
1092
1093 // braintree create subscription
1094 case 'create_subscription':
1095 $json = true;
1096 $api_url = $cn->get_url( 'account_api', '/api/account/braintree/createsubscription' );
1097 $api_args['method'] = 'POST';
1098 $api_args['headers'] = array_merge(
1099 $api_args['headers'],
1100 [
1101 'Authorization' => 'Bearer ' . $api_token,
1102 'Content-Type' => 'application/json; charset=utf-8'
1103 ]
1104 );
1105 break;
1106
1107 // braintree assign subscription
1108 case 'assign_subscription':
1109 $json = true;
1110 $api_url = $cn->get_url( 'account_api', '/api/account/braintree/assignsubscription' );
1111 $api_args['method'] = 'POST';
1112 $api_args['headers'] = array_merge(
1113 $api_args['headers'],
1114 [
1115 'Authorization' => 'Bearer ' . $api_token,
1116 'Content-Type' => 'application/json; charset=utf-8'
1117 ]
1118 );
1119 break;
1120
1121 // braintree create payment method
1122 case 'create_payment_method':
1123 $json = true;
1124 $api_url = $cn->get_url( 'account_api', '/api/account/braintree/createpaymentmethod' );
1125 $api_args['method'] = 'POST';
1126 $api_args['headers'] = array_merge(
1127 $api_args['headers'],
1128 [
1129 'Authorization' => 'Bearer ' . $api_token,
1130 'Content-Type' => 'application/json; charset=utf-8'
1131 ]
1132 );
1133 break;
1134 }
1135
1136 if ( ! empty( $params ) && is_array( $params ) ) {
1137 foreach ( $params as $key => $param ) {
1138 if ( is_object( $param ) )
1139 $api_params[$key] = $param;
1140 elseif ( is_array( $param ) )
1141 $api_params[$key] = array_map( 'sanitize_text_field', $param );
1142 elseif ( $key === 'Password' && ( $request === 'register' || $request === 'login' ) )
1143 $api_params[$key] = preg_replace( '/[^\w !"#$%&\'()*\+,\-.\/:;<=>?@\[\]^\`\{\|\}\~\\\\]/', '', $param );
1144 else
1145 $api_params[$key] = sanitize_text_field( $param );
1146 }
1147
1148 if ( $json )
1149 $api_args['body'] = wp_json_encode( $api_params );
1150 else
1151 $api_args['body'] = $api_params;
1152 }
1153
1154 $response = wp_remote_request( $api_url, $api_args );
1155
1156 if ( is_wp_error( $response ) )
1157 $result = [ 'error' => $response->get_error_message() ];
1158 else {
1159 $content_type = wp_remote_retrieve_header( $response, 'Content-Type' );
1160
1161 // html response, means error
1162 if ( $content_type == 'text/html' )
1163 $result = [ 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ) ];
1164 else {
1165 $result = wp_remote_retrieve_body( $response );
1166
1167 // detect json or array
1168 $result = is_array( $result ) ? $result : json_decode( $result );
1169 }
1170 }
1171
1172 return $result;
1173 }
1174
1175 /**
1176 * Check whether WP Cron needs to add new task.
1177 *
1178 * @return void
1179 */
1180 public function check_cron() {
1181 // get main instance
1182 $cn = Cookie_Notice();
1183
1184 if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
1185 $app_id = $cn->network_options['app_id'];
1186 $app_key = $cn->network_options['app_key'];
1187 } else {
1188 $app_id = $cn->options['general']['app_id'];
1189 $app_key = $cn->options['general']['app_key'];
1190 }
1191
1192 // compliance active only
1193 if ( $app_id !== '' && $app_key !== '' ) {
1194 if ( $cn->get_status() === 'active' )
1195 $recurrence = 'daily';
1196 else
1197 $recurrence = 'hourly';
1198
1199 // set schedule if needed
1200 if ( ! wp_next_scheduled( 'cookie_notice_get_app_analytics' ) )
1201 wp_schedule_event( time(), 'hourly', 'cookie_notice_get_app_analytics' );
1202
1203 // set schedule if needed
1204 if ( ! wp_next_scheduled( 'cookie_notice_get_app_config' ) )
1205 wp_schedule_event( time(), $recurrence, 'cookie_notice_get_app_config' );
1206 } else {
1207 // remove schedule if needed
1208 if ( wp_next_scheduled( 'cookie_notice_get_app_analytics' ) )
1209 wp_clear_scheduled_hook( 'cookie_notice_get_app_analytics' );
1210
1211 // remove schedule if needed
1212 if ( wp_next_scheduled( 'cookie_notice_get_app_config' ) )
1213 wp_clear_scheduled_hook( 'cookie_notice_get_app_config' );
1214 }
1215 }
1216
1217 /**
1218 * Get app analytics.
1219 *
1220 * @param string $app_id
1221 * @param bool $force_update
1222 * @return void
1223 */
1224 public function get_app_analytics( $app_id = '', $force_update = false ) {
1225 // get main instance
1226 $cn = Cookie_Notice();
1227
1228 $allow_one_cron_per_hour = false;
1229
1230 if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
1231 if ( empty( $app_id ) )
1232 $app_id = $cn->network_options['app_id'];
1233
1234 $network = true;
1235 $allow_one_cron_per_hour = true;
1236 } else {
1237 if ( empty( $app_id ) )
1238 $app_id = $cn->options['general']['app_id'];
1239
1240 $network = false;
1241 }
1242
1243 // in global override mode allow only one cron per hour
1244 if ( $allow_one_cron_per_hour && ! $force_update ) {
1245 $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
1246
1247 // analytics data?
1248 if ( ! empty( $analytics ) ) {
1249 $updated = strtotime( $analytics['lastUpdated'] );
1250
1251 // last updated less than an hour?
1252 if ( $updated !== false && current_time( 'timestamp', true ) - $updated < 3600 )
1253 return;
1254 }
1255 }
1256
1257 $response = $this->request(
1258 'get_analytics',
1259 [
1260 'AppID' => $app_id
1261 ]
1262 );
1263
1264 // get analytics
1265 if ( ! empty( $response->data ) ) {
1266 $result = map_deep( (array) $response->data, 'sanitize_text_field' );
1267
1268 // add time updated
1269 $result['lastUpdated'] = date( 'Y-m-d H:i:s', current_time( 'timestamp', true ) );
1270
1271 // get default status data
1272 $status_data = $cn->defaults['data'];
1273
1274 // update status
1275 $status_data['status'] = $cn->get_status();
1276
1277 // update subscription
1278 $status_data['subscription'] = $cn->get_subscription();
1279
1280 if ( $status_data['status'] === 'active' && $status_data['subscription'] === 'basic' ) {
1281 $threshold = ! empty( $result['cycleUsage']->threshold ) ? (int) $result['cycleUsage']->threshold : 0;
1282 $visits = ! empty( $result['cycleUsage']->visits ) ? (int) $result['cycleUsage']->visits : 0;
1283
1284 if ( $visits >= $threshold && $threshold > 0 )
1285 $status_data['threshold_exceeded'] = true;
1286 }
1287
1288 if ( $network ) {
1289 update_site_option( 'cookie_notice_app_analytics', $result );
1290 update_site_option( 'cookie_notice_status', $status_data );
1291 } else {
1292 update_option( 'cookie_notice_app_analytics', $result, false );
1293 update_option( 'cookie_notice_status', $status_data, false );
1294 }
1295 }
1296 }
1297
1298 /**
1299 * Get app config.
1300 *
1301 * @param string $app_id
1302 * @param bool $force_update
1303 * @return void|array
1304 */
1305 public function get_app_config( $app_id = '', $force_update = false ) {
1306 // get main instance
1307 $cn = Cookie_Notice();
1308
1309 $allow_one_cron_per_hour = false;
1310
1311 if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['global_override'] ) {
1312 if ( empty( $app_id ) )
1313 $app_id = $cn->network_options['app_id'];
1314
1315 $network = true;
1316 $allow_one_cron_per_hour = true;
1317 } else {
1318 if ( empty( $app_id ) )
1319 $app_id = $cn->options['general']['app_id'];
1320
1321 $network = false;
1322 }
1323
1324 // in global override mode allow only one cron per hour
1325 if ( $allow_one_cron_per_hour && ! $force_update ) {
1326 $blocking = get_site_option( 'cookie_notice_app_blocking', [] );
1327
1328 // analytics data?
1329 if ( ! empty( $blocking ) ) {
1330 $updated = strtotime( $blocking['lastUpdated'] );
1331
1332 // last updated less than an hour?
1333 if ( $updated !== false && current_time( 'timestamp', true ) - $updated < 3600 )
1334 return;
1335 }
1336 }
1337
1338 // get config
1339 $response = $this->request(
1340 'get_config',
1341 [
1342 'AppID' => $app_id
1343 ]
1344 );
1345
1346 // get status data
1347 $status_data = $cn->defaults['data'];
1348
1349 // get config
1350 if ( ! empty( $response->data ) ) {
1351 // sanitize data
1352 $result_raw = map_deep( (array) $response->data, 'sanitize_text_field' );
1353
1354 // set status
1355 $status_data['status'] = 'active';
1356
1357 // check subscription
1358 if ( ! empty( $result_raw['SubscriptionType'] ) )
1359 $status_data['subscription'] = $cn->check_subscription( strtolower( $result_raw['SubscriptionType'] ) );
1360
1361 if ( $status_data['subscription'] === 'basic' ) {
1362 // get analytics data options
1363 if ( $network )
1364 $analytics = get_site_option( 'cookie_notice_app_analytics', [] );
1365 else
1366 $analytics = get_option( 'cookie_notice_app_analytics', [] );
1367
1368 if ( ! empty( $analytics ) ) {
1369 $threshold = ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0;
1370 $visits = ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0;
1371
1372 if ( $visits >= $threshold && $threshold > 0 )
1373 $status_data['threshold_exceeded'] = true;
1374 }
1375 }
1376
1377 // process blocking data
1378 $result = [
1379 'categories' => ! empty( $result_raw['DefaultCategoryJSON'] ) && is_array( $result_raw['DefaultCategoryJSON'] ) ? $result_raw['DefaultCategoryJSON'] : [],
1380 'providers' => ! empty( $result_raw['DefaultProviderJSON'] ) && is_array( $result_raw['DefaultProviderJSON'] ) ? $result_raw['DefaultProviderJSON'] : [],
1381 'patterns' => ! empty( $result_raw['DefaultCookieJSON'] ) && is_array( $result_raw['DefaultCookieJSON'] ) ? $result_raw['DefaultCookieJSON'] : [],
1382 'lastUpdated' => date( 'Y-m-d H:i:s', current_time( 'timestamp', true ) )
1383 ];
1384
1385 if ( $network )
1386 update_site_option( 'cookie_notice_app_blocking', $result );
1387 else
1388 update_option( 'cookie_notice_app_blocking', $result, false );
1389 } else {
1390 if ( ! empty( $response->error ) ) {
1391 if ( $response->error == 'App is not puplised yet' )
1392 $status_data['status'] = 'pending';
1393 else
1394 $status_data['status'] = '';
1395 }
1396 }
1397
1398 if ( $network )
1399 update_site_option( 'cookie_notice_status', $status_data );
1400 else
1401 update_option( 'cookie_notice_status', $status_data, false );
1402
1403 return $status_data;
1404 }
1405 }
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie_Notice_Welcome_Frontend class.
8 *
9 * @class Cookie_Notice_Welcome_Frontend
10 */
11 class Cookie_Notice_Welcome_Frontend {
12
13 private $preview_mode = false;
14
15 /**
16 * Constructor.
17 *
18 * @return void
19 */
20 public function __construct() {
21 add_action( 'after_setup_theme', [ $this, 'preview_init' ], 1 );
22 }
23
24 /**
25 * Initialize preview mode.
26 *
27 * @return void
28 */
29 public function preview_init() {
30 // check preview mode
31 $this->preview_mode = isset( $_GET['cn_preview_mode'] ) ? (int) $_GET['cn_preview_mode'] : false;
32
33 if ( $this->preview_mode !== false ) {
34 // filters
35 add_filter( 'show_admin_bar', '__return_false' );
36 add_filter( 'cn_cookie_notice_output', '__return_false', 1000 );
37
38 // actions
39 add_action( 'wp_enqueue_scripts', [ $this, 'wp_dequeue_scripts' ] );
40
41 // only in live preview
42 if ( $this->preview_mode === 1 ) {
43 add_action( 'wp_enqueue_scripts', [ $this, 'wp_enqueue_scripts' ] );
44 add_action( 'wp_head', [ $this, 'wp_head_scripts' ], 0 );
45 }
46 }
47 }
48
49 /**
50 * Load scripts and styles.
51 *
52 * @return void
53 */
54 public function wp_enqueue_scripts() {
55 // get main instance
56 $cn = Cookie_Notice();
57
58 // show only in live preview
59 if ( $this->preview_mode === 1 ) {
60 wp_enqueue_script( 'cookie-notice-welcome-frontend', COOKIE_NOTICE_URL . '/js/front-welcome.js', [ 'jquery', 'underscore' ], $cn->defaults['version'] );
61
62 // prepare script data
63 $script_data = [
64 'previewMode' => $this->preview_mode,
65 'allowedURLs' => $this->get_allowed_urls(),
66 'levelNames' => $cn->settings->level_names,
67 'textStrings' => $cn->settings->text_strings
68 ];
69
70 wp_add_inline_script( 'cookie-notice-welcome-frontend', 'var cnFrontWelcome = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
71 }
72 }
73
74 /**
75 * Unload scripts and styles.
76 *
77 * @return void
78 */
79 public function wp_dequeue_scripts() {
80 // deregister native cookie notice script
81 wp_dequeue_script( 'cookie-notice-front' );
82 }
83
84 /**
85 * Load cookie compliance script.
86 *
87 * @return void
88 */
89 public function wp_head_scripts() {
90 $options = [
91 'currentLanguage' => 'en',
92 'previewMode' => true,
93 'debugMode' => true,
94 'config' => [
95 'privacyPaper' => true,
96 'privacyContact' => true
97 ]
98 ];
99
100 echo '
101 <!-- Cookie Compliance -->
102 <script type="text/javascript">
103 var huOptions = ' . wp_json_encode( $options ) . ';
104 </script>
105 <script type="text/javascript" src="' . esc_url( Cookie_Notice()->get_url( 'widget' ) ) . '"></script>
106 <style>.hu-preview-mode #hu::after {content: "";position: fixed;width: 100%;height: 100%;display: block;top: 0;left: 0}</style>';
107 }
108
109 /**
110 * Get URLs allowed to be previewed.
111 *
112 * @return array
113 */
114 public function get_allowed_urls() {
115 $allowed_urls = [ home_url( '/' ) ];
116
117 if ( is_ssl() && ! $this->is_cross_domain() )
118 $allowed_urls[] = home_url( '/', 'https' );
119
120 return $allowed_urls;
121 }
122
123 /**
124 * Determines whether the admin and the frontend are on different domains.
125 *
126 * @return bool
127 */
128 public function is_cross_domain() {
129 $admin_origin = wp_parse_url( admin_url() );
130 $home_origin = wp_parse_url( home_url() );
131
132 return ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
133 }
134 }
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) )
4 exit;
5
6 /**
7 * Cookie_Notice_Welcome class.
8 *
9 * @class Cookie_Notice_Welcome
10 */
11 class Cookie_Notice_Welcome {
12
13 private $pricing_monthly = [];
14 private $pricing_yearly = [];
15
16 /**
17 * Constructor.
18 *
19 * @return void
20 */
21 public function __construct() {
22 // actions
23 add_action( 'plugins_loaded', [ $this, 'allow_protocols' ] );
24 add_action( 'admin_init', [ $this, 'init' ] );
25 add_action( 'admin_init', [ $this, 'welcome' ] );
26 add_action( 'wp_ajax_cn_welcome_screen', [ $this, 'welcome_screen' ] );
27 }
28
29 /**
30 * Allow new protocols.
31 *
32 * @return void
33 */
34 function allow_protocols() {
35 // allow only ajax calls
36 if ( ! wp_doing_ajax() )
37 return;
38
39 // get action
40 $action = isset( $_REQUEST['action'] ) ? sanitize_key( $_REQUEST['action'] ) : '';
41
42 // welcome screen?
43 if ( $action === 'cn_welcome_screen' )
44 add_filter( 'kses_allowed_protocols', [ $this, 'allow_data_protocol' ] );
45 }
46
47 /**
48 * Add new properties to style safe list.
49 *
50 * @param array $styles
51 * @return array
52 */
53 public function allow_style_attributes( $styles ) {
54 $styles[] = 'display';
55
56 return $styles;
57 }
58
59 /**
60 * Add data protocol to image source.
61 *
62 * @param array $protocols
63 * @return array
64 */
65 public function allow_data_protocol( $protocols ) {
66 $protocols[] = 'data';
67
68 return $protocols;
69 }
70
71 /**
72 * Load defaults.
73 *
74 * @return void
75 */
76 public function init() {
77 $this->pricing_monthly = [
78 'compliance_monthly_notrial' => '14.95',
79 'compliance_monthly_5' => '29.95',
80 'compliance_monthly_10' => '49.95',
81 'compliance_monthly_20' => '69.95'
82 ];
83
84 $this->pricing_yearly = [
85 'compliance_yearly_notrial' => '149.50',
86 'compliance_yearly_5' => '299.50',
87 'compliance_yearly_10' => '499.50',
88 'compliance_yearly_20' => '699.50'
89 ];
90 }
91
92 /**
93 * Load scripts and styles - admin.
94 *
95 * @return void
96 */
97 public function admin_enqueue_scripts( $page ) {
98 // get main instance
99 $cn = Cookie_Notice();
100
101 if ( $cn->check_status( $cn->get_status() ) )
102 return;
103
104 // styles
105 wp_enqueue_style( 'dashicons' );
106 wp_enqueue_style( 'cookie-notice-modaal', COOKIE_NOTICE_URL . '/assets/modaal/css/modaal.min.css', [], $cn->defaults['version'] );
107 wp_enqueue_style( 'cookie-notice-spectrum', COOKIE_NOTICE_URL . '/assets/spectrum/spectrum.min.css', [], $cn->defaults['version'] );
108 wp_enqueue_style( 'cookie-notice-microtip', COOKIE_NOTICE_URL . '/assets/microtip/microtip.min.css', [], $cn->defaults['version'] );
109
110 // scripts
111 wp_enqueue_script( 'cookie-notice-modaal', COOKIE_NOTICE_URL . '/assets/modaal/js/modaal.min.js', [], $cn->defaults['version'] );
112 wp_enqueue_script( 'cookie-notice-spectrum', COOKIE_NOTICE_URL . '/assets/spectrum/spectrum.min.js', [], $cn->defaults['version'] );
113 wp_enqueue_script( 'cookie-notice-welcome', COOKIE_NOTICE_URL . '/js/admin-welcome.js', [ 'jquery', 'jquery-ui-core', 'jquery-ui-progressbar' ], $cn->defaults['version'] );
114 wp_enqueue_script( 'cookie-notice-braintree-client', 'https://js.braintreegateway.com/web/3.71.0/js/client.min.js', [], null, false );
115 wp_enqueue_script( 'cookie-notice-braintree-hostedfields', 'https://js.braintreegateway.com/web/3.71.0/js/hosted-fields.min.js', [], null, false );
116 wp_enqueue_script( 'cookie-notice-braintree-paypal', 'https://js.braintreegateway.com/web/3.71.0/js/paypal-checkout.min.js', [], null, false );
117
118 // check network
119 $network = $cn->is_network_admin();
120
121 // prepare script data
122 $script_data = [
123 'ajaxURL' => admin_url( 'admin-ajax.php' ),
124 'network' => $network,
125 'nonce' => wp_create_nonce( 'cookie-notice-welcome' ),
126 'cnNonce' => wp_create_nonce( 'cookie-notice-welcome' ),
127 'initModal' => $network ? get_site_transient( 'cn_show_welcome' ) : get_transient( 'cn_show_welcome' ), // welcome modal
128 'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ),
129 'statusPassed' => esc_html__( 'Passed', 'cookie-notice' ),
130 'statusFailed' => esc_html__( 'Failed', 'cookie-notice' ),
131 'paidMonth' => esc_html__( 'monthly', 'cookie-notice' ),
132 'paidYear' => esc_html__( 'yearly', 'cookie-notice' ),
133 'pricingMonthly' => $this->pricing_monthly,
134 'pricingYearly' => $this->pricing_yearly,
135 'complianceStatus' => $cn->get_status(),
136 'complianceFailed' => sprintf( esc_html__( '%sCompliance Failed!%sYour website does not achieve minimum viable compliance. %sSign up to Cookie Compliance%s to bring your site into compliance with the latest data privacy rules and regulations.', 'cookie-notice' ), '<em>', '</em>', '<b><a href="#" class="cn-sign-up">', '</a></b>' ),
137 'compliancePassed' => sprintf( esc_html__( '%sCompliance Passed!%sCongratulations. Your website meets minimum viable compliance.', 'cookie-notice' ), '<em>', '</em>' ),
138 'licensesAvailable' => esc_html__( 'available', 'cookie-notice' ),
139 'invalidFields' => esc_html__( 'Please fill all the required fields.', 'cookie-notice' )
140 ];
141
142 // delete the show modal transient
143 if ( $network )
144 delete_site_transient( 'cn_show_welcome' );
145 else
146 delete_transient( 'cn_show_welcome' );
147
148 wp_add_inline_script( 'cookie-notice-welcome', 'var cnWelcomeArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
149
150 wp_enqueue_style( 'cookie-notice-welcome', COOKIE_NOTICE_URL . '/css/admin-welcome.css' );
151 }
152
153 /**
154 * Send user to the welcome page on first activation.
155 *
156 * @global string $pagenow
157 *
158 * @return void
159 */
160 public function welcome() {
161 global $pagenow;
162
163 if ( $pagenow !== 'admin.php' )
164 return;
165
166 // get page
167 $page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : '';
168
169 if ( $page !== 'cookie-notice' )
170 return;
171
172 // bail if bulk activating or within an iframe
173 if ( isset( $_GET['activate-multi'] ) || defined( 'IFRAME_REQUEST' ) )
174 return;
175
176 // get action
177 $action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
178
179 // get plugin
180 $plugin = isset( $_GET['plugin'] ) ? sanitize_file_name( $_GET['plugin'] ) : '';
181
182 if ( $action === 'upgrade-plugin' && strpos( $plugin, 'cookie-notice.php' ) !== false )
183 return;
184
185 add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
186 add_action( 'admin_footer', [ $this, 'admin_footer' ] );
187 }
188
189 /**
190 * Welcome modal container.
191 *
192 * @return void
193 */
194 public function admin_footer() {
195 echo '<button id="cn-modal-trigger" style="display:none"></button>';
196 }
197
198 /**
199 * Render welcome screen sidebar step.
200 *
201 * @param int|string $screen
202 * @param bool $echo
203 * @return string|void
204 */
205 public function welcome_screen( $screen, $echo = true ) {
206 if ( ! current_user_can( 'install_plugins' ) )
207 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
208
209 $sidebars = [ 'about', 'login', 'register', 'configure', 'success' ];
210 $steps = [ 1, 2, 3, 4 ];
211 $screens = array_merge( $sidebars, $steps );
212
213 if ( ! empty( $screen ) ) {
214 if ( is_numeric( $screen ) )
215 $screen = (int) $screen;
216 else
217 $screen = sanitize_key( $screen );
218 } else
219 $screen = '';
220
221 if ( empty( $screen ) || ! in_array( $screen, $screens, true ) ) {
222 if ( isset( $_REQUEST['screen'] ) ) {
223 if ( is_numeric( $_REQUEST['screen'] ) )
224 $screen = (int) $_REQUEST['screen'];
225 else
226 $screen = sanitize_key( $_REQUEST['screen'] );
227 } else
228 $screen = '';
229
230 if ( ! in_array( $screen, $screens, true ) )
231 $screen = '';
232 }
233
234 if ( empty( $screen ) )
235 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
236
237 if ( wp_doing_ajax() && ! check_ajax_referer( 'cookie-notice-welcome', 'nonce' ) )
238 wp_die( _( 'You do not have permission to access this page.', 'cookie-notice' ) );
239
240 // step screens
241 if ( in_array( $screen, $steps ) ) {
242 $html = '
243 <div class="wrap full-width-layout cn-welcome-wrap cn-welcome-step-' . esc_attr( $screen ) . ' has-loader">';
244
245 if ( $screen == 1 ) {
246 $html .= $this->welcome_screen( 'about', false );
247
248 $html .= '
249 <div class="cn-content cn-sidebar-visible">
250 <div class="cn-inner">
251 <div class="cn-content-full">
252 <h1><b>Cookie Compliance&trade;</b></h1>
253 <h2>' . esc_html__( 'The next generation of Cookie Notice', 'cookie-notice' ) . '</h2>
254 <div class="cn-lead">
255 <p><b>' . esc_html__( 'Cookie Compliance is a free web application that enables websites to take a proactive approach to data protection and consent laws.', 'cookie-notice' ) . '</b></p>
256 <div class="cn-hero-image">
257 <div class="cn-flex-item">
258 <img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/screen-compliance.png" alt="Cookie Notice dashboard" />
259 </div>
260 </div>
261 <p>' . sprintf( esc_html__( 'It is the first solution to offer %sintentional consent%s, a new consent framework that incorporates the latest guidelines from over 100+ countries, and emerging standards from leading international organizations like the IEEE.', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
262 <p>' . sprintf( esc_html__( 'Cookie Notice includes %sseamless integration%s with Cookie Compliance to help your site comply with the latest updates to existing consent laws and provide a beautiful, multi-level experience to engage visitors in data privacy decisions.', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
263 </div>';
264 $html .= '
265 <div class="cn-buttons">
266 <button type="button" class="cn-btn cn-btn-lg cn-screen-button" data-screen="2"><span class="cn-spinner"></span>' . esc_html__( 'Sign up to Cookie Compliance', 'cookie-notice' ) . '</button><br />
267 <button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . esc_html__( 'Skip for now', 'cookie-notice' ) . '</button>
268 </div>
269 ';
270
271 $html .= '
272 </div>
273 </div>
274 </div>';
275 } elseif ( $screen == 2 ) {
276 $html .= $this->welcome_screen( 'configure', false );
277
278 $html .= '
279 <div id="cn_upgrade_iframe" class="cn-content cn-sidebar-visible has-loader cn-loading"><span class="cn-spinner"></span>
280 <iframe id="cn_iframe_id" src="' . esc_url( home_url( '/?cn_preview_mode=1' ) ) . '"></iframe>
281 </div>';
282 } elseif ( $screen == 3 ) {
283 $html .= $this->welcome_screen( 'register', false );
284
285 $html .= '
286 <div class="cn-content cn-sidebar-visible">
287 <div class="cn-inner">
288 <div class="cn-content-full">
289 <h1><b>Cookie Compliance&trade;</b></h1>
290 <h2>' . esc_html__( 'The next generation of Cookie Notice', 'cookie-notice' ) . '</h2>
291 <div class="cn-lead">
292 <p>' . esc_html__( 'Take a proactive approach to data protection and consent laws by signing up for Cookie Compliance account. Then select a limited Basic Plan for free or get one of the Professional Plans for unlimited visits, consent storage, languages and customizations.', 'cookie-notice' ) . '</p>
293 </div>';
294
295 $html .= '
296 <h3 class="cn-pricing-select">' . esc_html__( 'Compliance Plans', 'cookie-notice' ) . ':</h3>
297 <div class="cn-pricing-type cn-radio-wrapper">
298 <div>
299 <label for="pricing-type-monthly"><input id="pricing-type-monthly" type="radio" name="cn_pricing_type" value="monthly" checked><span class="cn-pricing-toggle toggle-left"><span class="cn-label">' . esc_html__( 'Monthly', 'cookie-notice' ) . '</span></span></label>
300 </div>
301 <div>
302 <label for="pricing-type-yearly"><input id="pricing-type-yearly" type="radio" name="cn_pricing_type" value="yearly"><span class="cn-pricing-toggle toggle-right"><span class="cn-label">' . esc_html__( 'Yearly', 'cookie-notice' ) . '<span class="cn-badge">' . esc_html__( 'Save 12%', 'cookie-notice' ) . '</span></span></span></label>
303 </div>
304 </div>
305 <div class="cn-pricing-table">
306 <label class="cn-pricing-item cn-pricing-plan-free" for="cn-pricing-plan-free">
307 <input id="cn-pricing-plan-free" type="radio" name="cn_pricing" value="free">
308 <div class="cn-pricing-info">
309 <div class="cn-pricing-head">
310 <h4>' . esc_html__( 'Basic', 'cookie-notice' ) . '</h4>
311 <span class="cn-plan-pricing"><span class="cn-plan-price">' . esc_html__( 'Free', 'cookie-notice' ) . '</span></span>
312 </div>
313 <div class="cn-pricing-body">
314 <p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'GDPR, CCPA, LGPD, PECR requirements', 'cookie-notice' ) . '</p>
315 <p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
316 <p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s1,000%s visits / month', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
317 <p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s30 days%s consent storage', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
318 <p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGoogle & Facebook%s consent modes', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
319 <p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGeolocation%s support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
320 <p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s1 additional%s language', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
321 <p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sBasic%s Support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
322 </div>
323 <div class="cn-pricing-footer">
324 <button type="button" class="cn-btn cn-btn-outline">' . esc_html__( 'Start Basic', 'cookie-notice' ) . '</button>
325 </div>
326 </div>
327 </label>
328 <label class="cn-pricing-item cn-pricing-plan-pro" for="cn-pricing-plan-pro">
329 <input id="cn-pricing-plan-pro" type="radio" name="cn_pricing" value="pro">
330 <div class="cn-pricing-info">
331 <div class="cn-pricing-head">
332 <h4>' . esc_html__( 'Professional', 'cookie-notice' ) . '</h4>
333 <span class="cn-plan-pricing"><span class="cn-plan-price"><sup>$ </sup><span class="cn-plan-amount">' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '</span><sub> / <span class="cn-plan-period">' . esc_html__( 'monthly', 'cookie-notice' ) . '</span></sub></span></span>
334 <span class="cn-plan-promo">' . esc_html__( 'Recommended', 'cookie-notice' ) . '</span>
335 <div class="cn-select-wrapper">
336 <select name="cn_pricing_plan" class="form-select" aria-label="' . esc_html__( 'Pricing options', 'cookie-notice' ) . '" id="cn-pricing-plans">
337 <option value="compliance_monthly_notrial" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 1, 'cookie-notice' ), 1 ) ) . '</option>
338 <option value="compliance_monthly_5" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_5'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 5, 'cookie-notice' ), 5 ) ) . '</option>
339 <option value="compliance_monthly_10" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_10'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 10, 'cookie-notice' ), 10 ) ) . '</option>
340 <option value="compliance_monthly_20" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_20'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 20, 'cookie-notice' ), 20 ) ) . '</option>
341 </select>
342 </div>
343 </div>
344 <div class="cn-pricing-body">
345 <p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'GDPR, CCPA, LGPD, PECR requirements', 'cookie-notice' ) . '</p>
346 <p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
347 <p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s visits', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
348 <p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sLifetime%s consent storage', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
349 <p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGoogle & Facebook%s consent modes', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
350 <p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGeolocation%s support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
351 <p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s languages', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
352 <p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sPriority%s Support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
353 </div>
354 <div class="cn-pricing-footer">
355 <button type="button" class="cn-btn cn-btn-secondary">' . esc_html__( 'Start Professional', 'cookie-notice' ) . '</button>
356 </div>
357 </div>
358 </label>
359 </div>
360 <div class="cn-buttons">
361 <button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . esc_html__( "I don’t want to create an account now", 'cookie-notice' ) . '</button>
362 </div>';
363
364 $html .= '
365 </div>
366 </div>
367 </div>';
368 } elseif ( $screen == 4 ) {
369 $html .= $this->welcome_screen( 'success', false );
370
371 // get main instance
372 $cn = Cookie_Notice();
373 $subscription = $cn->get_subscription();
374
375 $html .= '
376 <div class="cn-content cn-sidebar-visible">
377 <div class="cn-inner">
378 <div class="cn-content-full">
379 <h1><b>' . esc_html__( 'Congratulations', 'cookie-notice' ) . '</b></h1>
380 <h2>' . ( $subscription === 'pro' ? esc_html__( 'You have successfully signed up to a Professional plan.', 'cookie-notice' ) : esc_html__( 'You have successfully signed up to a limited, Basic plan.', 'cookie-notice' ) ) . '</h2>
381 <div class="cn-lead">
382 <p>' . esc_html__( 'Log in to your Cookie Compliance account and continue configuring your Privacy Experience.', 'cookie-notice' ) . '</p>
383 </div>
384 <div class="cn-buttons">
385 <a href="' . esc_url( $cn->get_url( 'host', '?utm_campaign=configure&utm_source=wordpress&utm_medium=button#/en/cc/login' ) ) . '" class="cn-btn cn-btn-lg" target="_blank">' . esc_html__( 'Go to Application', 'cookie-notice' ) . '</a>
386 </div>
387 </div>
388 </div>
389 </div>';
390 }
391
392 $html .= '
393 </div>';
394 // sidebar screens
395 } elseif ( in_array( $screen, $sidebars ) ) {
396 $html = '';
397
398 if ( $screen === 'about' ) {
399 $theme = wp_get_theme();
400
401 $html .= '
402 <div class="cn-sidebar cn-sidebar-left has-loader">
403 <div class="cn-inner">
404 <div class="cn-header">
405 <div class="cn-top-bar">
406 <div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-notice-logo.png" alt="Cookie Notice logo" /></div>
407 </div>
408 </div>
409 <div class="cn-body">
410 <h2>' . esc_html__( 'Compliance check', 'cookie-notice' ) . '</h2>
411 <div class="cn-lead"><p>' . esc_html__( 'This is a Compliance Check to determine your site’s compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws.', 'cookie-notice' ) . '</p></div>
412 <div id="cn_preview_about">
413 <p>' . esc_html__( 'Site URL', 'cookie-notice' ) . ': <b>' . esc_url( home_url() ) . '</b></p>
414 <p>' . esc_html__( 'Site Name', 'cookie-notice' ) . ': <b>' . esc_html( get_bloginfo( 'name' ) ) . '</b></p>
415 </div>
416 <div class="cn-compliance-check">
417 <div class="cn-progressbar"><div class="cn-progress-label">' . esc_html__( 'Checking...', 'cookie-notice' ) . '</div></div>
418 <div class="cn-compliance-feedback cn-hidden"></div>
419 <div class="cn-compliance-results">
420 <div class="cn-compliance-item"><p><span class="cn-compliance-label">' . esc_html__( 'Cookie Notice', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Notifies visitors that site uses cookies.', 'cookie-notice' ) . '</span></p></div>
421 <div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Autoblocking', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Non-essential cookies blocked until consent is registered.', 'cookie-notice' ) . '</span></p></div>
422 <div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Separate consent requested per purpose of use.', 'cookie-notice' ) . '</span></p></div>
423 <div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Proof-of-consent stored in secure audit format.', 'cookie-notice' ) . '</span></p></div>
424 </div>
425 </div>
426 ' /* <div id="cn_preview_frame"><img src=" ' . esc_url( $theme->get_screenshot() ) . '" /></div>
427 . '<div id="cn_preview_frame"><div id="cn_preview_frame_wrapper"><iframe id="cn_iframe_id" src="' . home_url( '/?cn_preview_mode=0' ) . '" scrolling="no" frameborder="0"></iframe></div></div> */ . '
428 </div>';
429 } elseif ( $screen === 'configure' ) {
430 $html .= '
431 <div class="cn-sidebar cn-sidebar-left has-loader cn-theme-light">
432 <div class="cn-inner">
433 <div class="cn-header">
434 <div class="cn-top-bar">
435 <div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-notice-logo.png" alt="Cookie Notice logo" /></div>
436 </div>
437 </div>
438 <div class="cn-body">
439 <h2>' . esc_html__( 'Live Setup', 'cookie-notice' ) . '</h2>
440 <div class="cn-lead"><p>' . esc_html__( 'Configure your Cookie Notice & Compliance design and compliance features through the options below. Click Apply Setup to save the configuration and go to selecting your preferred cookie solution.', 'cookie-notice' ) . '</p></div>
441 <form method="post" id="cn-form-configure" class="cn-form" action="" data-action="configure">
442 <div class="cn-accordion">
443 <div class="cn-accordion-item cn-form-container" tabindex="-1">
444 <div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">' . esc_html__( 'Banner Compliance', 'cookie-notice' ) . '</button></div>
445 <div class="cn-accordion-collapse cn-form">
446 <div class="cn-form-feedback cn-hidden"></div>' .
447 /*
448 <div class="cn-field cn-field-select">
449 <label for="cn_location">' . __( 'What is the location of your business/organization?', 'cookie-notice' ) . '​</label>
450 <div class="cn-select-wrapper">
451 <select id="cn_location" name="cn_location">
452 <option value="0">' . __( 'Select location', 'cookie-notice' ) . '</option>';
453
454 foreach ( Cookie_Notice()->settings->countries as $country_code => $country_name ) {
455 $html .= '<option value="' . $country_code . '">' . $country_name . '</option>';
456 }
457
458 $html .= '
459 </select>
460 </div>
461 </div>
462 */
463 '
464 <div id="cn_laws" class="cn-field cn-field-checkbox">
465 <label>' . esc_html__( 'Select the laws that apply to your business', 'cookie-notice' ) . ':</label>
466 <div class="cn-checkbox-image-wrapper">
467 <label for="cn_laws_gdpr"><input id="cn_laws_gdpr" type="checkbox" name="cn_laws" value="gdpr" title="' . esc_attr__( 'GDPR', 'cookie-notice' ) . '" checked><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC/ElEQVRoge2ZzZGjMBCFmcMet4rjHjlsANQmsGRgZ7BkMGRgZ7DOYMhgnME4A08GdgZ2AujbA41HiD8JEOawXUWVXUjd73WLVqsVBB4F+OlTv3cBciB7Ng4nAV6ADHjnSz6A7bOxPQQIh94Dd43AaSFodgKkFmNOGoHEYvwySw1IgJtFFHJgC6RD4GTJnedF2jQSAUfNqzfgMFFnAnxqOi9CvNc5UwzG1CWaQede03f1Bl6MhZqxz5l0Jot97BKBRH5nc3hLCETyO52qr1LqL4wjxWm5Akd/UMaJfOzdjpUs8xvYyXp8k//RcjA7Mf01MMVdE3IjyxyfvZyMLIVEIuoarGcZJhqOgY14bJITqO8VSd/AqobZy6T2UPUbi5RSH0op9EeW5igiguVAWZ50YxKvhRoZJ4MC/maCr56iKN5GEgi139EYHVailDpqYHMgKYpir5S6a5FIvQGYIuL9B3jjXapFYnUpOgiCIAC2mpcT872+lJ4Ab1hkqfQRuHslIB9wNHa+BYHrHAToOprKJuacJSgPLH+M1HmRtLkDdkqp95aU+tqb09tthcC5No/moeLcybKpMO5KmZbPydLON3HwzagSflQD9BIid/BI4gD2OpaA2DIbBan+8qC9sD5cOxD4FADZWAJir72kkAjE8sxN4FEGF0WRT4xAVtl1/X6sCQCZlpH6wDtHYHbpIFDVUskA+HUSUEqd9eKrB/xqCVQkNmb+X4SAy8fhmEYnEbDGJanKavDCBPoPWJSnsIvk2BvlAbr3RAaEssZPYx6blN2BK2obGFGX/bBf/EsLrm7SlL3J5k73ZMGmVS9MT5Qt8T0rulGhLHViyso3sZ20uvbif1kiKl5tuFSqI/WH+Gq78HUR4dytc7CRS86fLwo078YQQ5HFXKtLEOq3NMP53lVaNpPIcs4Fy0YB9S70LNdXpgGqjW5g3AvNlvgd+DUwb6vZmHT72aY8rtY+WgN4YI5+fh3cFPUNynqz8inUt//V7OpWAnwHNuZvH/IPPeDD9c6V9FUAAAAASUVORK5CYII=" width="24" height="24"><span>' . esc_html__( 'GDPR', 'cookie-notice' ) . '</span></label>
468 <label for="cn_laws_ccpa"><input id="cn_laws_ccpa" type="checkbox" name="cn_laws" value="ccpa" title="' . esc_attr__( 'CCPA', 'cookie-notice' ) . '"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAwCAYAAACScGMWAAACPElEQVRYheXYvXHbMBTAcY7AEbSA79Smskp30QiqkyLaQPQE8Qb2BtEG4QZil3Ry5ZZaAO/vAqANIwSJD1LmXXD3ToVE8sf3hEcQRVEUBXADfE+Mu2LOAVSkj/q/xj0sGVcvEgeUGTAvDlgBP4CD+Vyl4HaZuNa9WRH5JSK4oZT6CZQxuN+ZOBzYqQ9mxSkYmAuzcUqpyoE0InIUkWcng1UoLresWFlrOwCwczLa2EAispczWzvcxs5YzzXWDm4bistpwk1RfCypr2yppc3BVUvDXYAtsO7OsSRcbY5bAbfArYicrYu36Ob7Fj297wx8Ncf7JwewScGJSD3S00LjOJa9p0/E1SHlDQWm4rqmHI+LAKbgGsx/y23IMbiQVUos7g2G04yjcOYEObga2InIxQNrc3FjK2MvDtP7DOQYAIvGlcBzYub+WRKNwOJw5oRDvW8Ih4icImDxOHNiX3nHcF0GDwGwZJyvvCG4aZuwB9i31lsMbu/DAXsD9IZS6kEpVQ0FoQvPHlxfaU/jR15peGbuGf3mlhqHKYF95c0dj1MCY5ZV1wUy/uT4dOB2BtykwDmyNw0QOM6EyweS9547L/AKOID7VNwcLcUdf1Jxa3T27MjaDOoZL0m4AXRJ3uZ3Pg69p9fy/pxssVYW6GdxbrvJwjXoUnZh40oTFXrT53q4EXiNtYltkCkTaDoc71v734B9z/ex7WdSXHfxzcBvYsbfKXHlECwAd0H/JZ7MjX6ZDBcy0DPYBmyHbugVe8KbbhsHbZ0AAAAASUVORK5CYII=" width="24" height="24"><span>' . esc_html__( 'CCPA', 'cookie-notice' ) . '</span></label>
469 </div>
470 </div>
471 <div id="cn_naming" class="cn-field cn-field-radio">
472 <label class="cn-asterix">' . esc_html__( 'Select a naming style for the consent choices', 'cookie-notice' ) . ':</label>
473 <div class="cn-radio-wrapper">
474 <label for="cn_naming_1"><input id="cn_naming_1" type="radio" name="cn_naming" value="1" checked><span>' . esc_html__( 'Silver, Gold, Platinum (Default)​', 'cookie-notice' ) . '</span></label>
475 <label for="cn_naming_2"><input id="cn_naming_2" type="radio" name="cn_naming" value="2"><span>' . esc_html__( 'Private, Balanced, Personalized', 'cookie-notice' ) . '</span></label>
476 <label for="cn_naming_3"><input id="cn_naming_3" type="radio" name="cn_naming" value="3"><span>' . esc_html__( 'Reject All, Accept Some, Accept All​', 'cookie-notice' ) . '</span></label>
477 </div>
478 </div>
479 <div class="cn-field cn-field-checkbox">
480 <label>' . esc_html__( 'Select additional information to include in the banner: *', 'cookie-notice' ) . '</label>
481 <div class="cn-checkbox-wrapper">
482 <label for="cn_privacy_paper"><input id="cn_privacy_paper" type="checkbox" name="cn_privacy_paper" value="1"><span>' . sprintf( esc_html__( 'Display %sPrivacy Paper%s to provide helpful data privacy and consent information to visitors.', 'cookie-notice' ), '<b>', '</b>' ) . '</span></label>
483 <label for="cn_privacy_contact"><input id="cn_privacy_contact" type="checkbox" name="cn_privacy_contact" value="1"><span>' . sprintf( esc_html__( 'Display %sPrivacy Contact%s to provide Data Controller contact information and links to external data privacy resources.', 'cookie-notice' ), '<b>', '</b>' ) . '</span></label>
484 </div>
485 </div>
486 <div class="cn-small">* ' . esc_html__( 'available for Cookie Compliance&trade; Pro plans only', 'cookie-notice' ) . '</div>
487 </div>
488 </div>
489 <div class="cn-accordion-item cn-form-container cn-collapsed" tabindex="-1">
490 <div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">' . esc_html__( 'Banner Design', 'cookie-notice' ) . '</button></div>
491 <div class="cn-accordion-collapse cn-form">
492 <div class="cn-form-feedback cn-hidden"></div>
493 <div class="cn-field cn-field-radio-image">
494 <label>' . esc_html__( 'Select your preferred display position', 'cookie-notice' ) . '​:</label>
495 <div class="cn-radio-image-wrapper">
496 <label for="cn_position_bottom"><input id="cn_position_bottom" type="radio" name="cn_position" value="bottom" title="' . esc_attr__( 'Bottom', 'cookie-notice' ) . '" checked><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-bottom.png" width="24" height="24"></label>
497 <label for="cn_position_top"><input id="cn_position_top" type="radio" name="cn_position" value="top" title="' . esc_attr__( 'Top', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-top.png" width="24" height="24"></label>
498 <label for="cn_position_left"><input id="cn_position_left" type="radio" name="cn_position" value="left" title="' . esc_attr__( 'Left', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-left.png" width="24" height="24"></label>
499 <label for="cn_position_right"><input id="cn_position_right" type="radio" name="cn_position" value="right" title="' . esc_attr__( 'Right', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-right.png" width="24" height="24"></label>
500 <label for="cn_position_center"><input id="cn_position_center" type="radio" name="cn_position" value="center" title="' . esc_attr__( 'Center', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-center.png" width="24" height="24"></label>
501 </div>
502 </div>
503 <div class="cn-field cn-fieldset">
504 <label>' . esc_html__( 'Adjust the banner color scheme', 'cookie-notice' ) . '​:</label>
505 <div class="cn-checkbox-wrapper cn-color-picker-wrapper">
506 <label for="cn_color_primary"><input id="cn_color_primary" class="cn-color-picker" type="checkbox" name="cn_color_primary" value="#20c19e"><span>' . esc_html__( 'Color of the buttons and interactive elements.', 'cookie-notice' ) . '</span></label>
507 <label for="cn_color_background"><input id="cn_color_background" class="cn-color-picker" type="checkbox" name="cn_color_background" value="#ffffff"><span>' . esc_html__( 'Color of the banner background.', 'cookie-notice' ) . '</span></label>
508 <label for="cn_color_text"><input id="cn_color_text" class="cn-color-picker" type="checkbox" name="cn_color_text" value="#434f58"><span>' . esc_html__( 'Color of the body text.', 'cookie-notice' ) . '</span></label>
509 <label for="cn_color_border"><input id="cn_color_border" class="cn-color-picker" type="checkbox" name="cn_color_border" value="#5e6a74"><span>' . esc_html__( 'Color of the borders and inactive elements.', 'cookie-notice' ) . '</span></label>
510 <label for="cn_color_heading"><input id="cn_color_heading" class="cn-color-picker" type="checkbox" name="cn_color_heading" value="#434f58"><span>' . esc_html__( 'Color of the heading text.', 'cookie-notice' ) . '</span></label>
511 <label for="cn_color_button_text"><input id="cn_color_button_text" class="cn-color-picker" type="checkbox" name="cn_color_button_text" value="#ffffff"><span>' . esc_html__( 'Color of the button text.', 'cookie-notice' ) . '</span></label>
512 </div>
513 </div>
514 <div class="cn-small">* ' . esc_html__( 'available for Cookie Compliance&trade; Pro plans only', 'cookie-notice' ) . '</div>
515 </div>
516 </div>
517 </div>
518 <div class="cn-field cn-field-submit cn-nav">
519 <button type="button" class="cn-btn cn-screen-button" data-screen="3"><span class="cn-spinner"></span>' . esc_html__( 'Apply Setup', 'cookie-notice' ) . '</button>
520 </div>';
521
522 $html .= wp_nonce_field( 'cn_api_configure', 'cn_nonce', true, false );
523
524 $html .= '
525 </form>
526 </div>';
527 } elseif ( $screen === 'register' ) {
528 $html .= '
529 <div class="cn-sidebar cn-sidebar-left has-loader">
530 <div class="cn-inner">
531 <div class="cn-header">
532 <div class="cn-top-bar">
533 <div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-notice-logo.png" alt="Cookie Notice logo" /></div>
534 </div>
535 </div>
536 <div class="cn-body">
537 <h2>' . esc_html__( 'Compliance account', 'cookie-notice' ) . '</h2>
538 <div class="cn-lead">
539 <p>' . esc_html__( 'Create a Cookie Compliance&trade; account and select your preferred plan.', 'cookie-notice' ) . '</p>
540 </div>
541 <div class="cn-accordion">
542 <div id="cn-accordion-account" class="cn-accordion-item cn-form-container" tabindex="-1">
543 <div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">1. ' . esc_html__( 'Create Account', 'cookie-notice' ) . '</button></div>
544 <div class="cn-accordion-collapse">
545 <form method="post" class="cn-form" action="" data-action="register">
546 <div class="cn-form-feedback cn-hidden"></div>
547 <div class="cn-field cn-field-text">
548 <input type="text" name="email" value="" tabindex="1" placeholder="' . esc_attr__( 'Email address', 'cookie-notice' ) . '">
549 </div>
550 <div class="cn-field cn-field-text">
551 <input type="password" name="pass" value="" tabindex="2" autocomplete="off" placeholder="' . esc_attr__( 'Password', 'cookie-notice' ) . '">
552 <span>' . esc_html( 'Minimum eight characters, at least one capital letter and one number are required.', 'cookie-notice' ) . '</span>
553 </div>
554 <div class="cn-field cn-field-text">
555 <input type="password" name="pass2" value="" tabindex="3" autocomplete="off" placeholder="' . esc_attr__( 'Confirm Password', 'cookie-notice' ) . '">
556 </div>
557 <div class="cn-field cn-field-checkbox">
558 <div class="cn-checkbox-wrapper">
559 <label for="cn_terms"><input id="cn_terms" type="checkbox" name="terms" value="1"><span>' . sprintf( esc_html__( 'I have read and agree to the %sTerms of Service%s', 'cookie-notice' ), '<a href="https://cookie-compliance.co/terms-of-service/?utm_campaign=accept-terms&utm_source=wordpress&utm_medium=link" target="_blank">', '</a>' ) . '</span></label>
560 </div>
561 </div>
562 <div class="cn-field cn-field-submit cn-nav">
563 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Sign Up', 'cookie-notice' ) . '</button>
564 </div>';
565
566 // get site language
567 $locale = get_locale();
568 $locale_code = explode( '_', $locale );
569
570 $html .= '
571 <input type="hidden" name="language" value="' . esc_attr( $locale_code[0] ) . '" />';
572
573 $html .= wp_nonce_field( 'cn_api_register', 'cn_nonce', true, false );
574
575 $html .= '
576 </form>
577 <p>' . esc_html__( 'Already have an account?', 'cookie-notice' ) . ' <a href="#" class="cn-screen-button" data-screen="login">' . esc_html__( 'Sign in', 'cookie-notice' ). '</a></p>
578 </div>
579 </div>';
580
581 $html .= '
582 <div id="cn-accordion-billing" class="cn-accordion-item cn-form-container cn-collapsed cn-disabled" tabindex="-1">
583 <div class="cn-accordion-header cn-form-header">
584 <button class="cn-accordion-button" type="button">2. ' . esc_html__( 'Select Plan', 'cookie-notice' ) . '</button>
585 </div>
586 <form method="post" class="cn-accordion-collapse cn-form cn-form-disabled" action="" data-action="payment">
587 <div class="cn-form-feedback cn-hidden"></div>
588 <div class="cn-field cn-field-radio">
589 <div class="cn-radio-wrapper cn-plan-wrapper">
590 <label for="cn-field-plan-free" class="cn-pricing-plan-free"><input id="cn-field-plan-free" type="radio" name="plan" value="free" checked><span><span class="cn-plan-description">' . esc_html__( 'Basic', 'cookie-notice' ) . '</span><span class="cn-plan-pricing"><span class="cn-plan-price">Free</span></span><span class="cn-plan-overlay"></span></span></label>
591 <label for="cn-field-plan-pro" class="cn-pricing-plan-pro"><input id="cn-field-plan-pro" type="radio" name="plan" value="compliance_monthly_notrial"><span><span class="cn-plan-description">' . sprintf( esc_html__( '%sProfessional%s', 'cookie-notice' ), '<b>', '</b>' ) . ' - <span class="cn-plan-period">' . esc_html__( 'monthly', 'cookie-notice' ) . '</span></span><span class="cn-plan-pricing"><span class="cn-plan-price">$<span class="cn-plan-amount">' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '</span></span></span><span class="cn-plan-overlay"></span></span></label>
592 </div>
593 </div>
594 <div class="cn-field cn-fieldset" id="cn_submit_free">
595 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Confirm', 'cookie-notice' ) . '</button>
596 </div>
597 <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_pro">
598 <input type="hidden" name="cn_payment_identifier" value="" />
599 <div class="cn-field cn-field-radio">
600 <label>' . esc_html__( 'Payment Method', 'cookie-notice' ) . '</label>
601 <div class="cn-radio-wrapper cn-horizontal-wrapper">
602 <label for="cn_field_method_credit_card"><input id="cn_field_method_credit_card" type="radio" name="method" value="credit_card" checked><span>' . esc_html__( 'Credit Card', 'cookie-notice' ) . '</span></label>
603 <label for="cn_field_method_paypal"><input id="cn_field_method_paypal" type="radio" name="method" value="paypal"><span>' . esc_html__( 'PayPal', 'cookie-notice' ) . '</span></label>
604 </div>
605 </div>
606 <div class="cn-fieldset" id="cn_payment_method_credit_card">
607 <input type="hidden" name="payment_nonce" value="" />
608 <div class="cn-field cn-field-text">
609 <label for="cn_card_number">' . esc_html__( 'Card Number', 'cookie-notice' ) . '</label>
610 <div id="cn_card_number"></div>
611 </div>
612 <div class="cn-field cn-field-text cn-field-half cn-field-first">
613 <label for="cn_expiration_date">' . esc_html__( 'Expiration Date', 'cookie-notice' ) . '</label>
614 <div id="cn_expiration_date"></div>
615 </div>
616 <div class="cn-field cn-field-text cn-field-half cn-field-last">
617 <label for="cn_cvv">' . esc_html__( 'CVC/CVV', 'cookie-notice' ) . '</label>
618 <div id="cn_cvv"></div>
619 </div>
620 <div class="cn-field cn-field-submit cn-nav">
621 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Submit', 'cookie-notice' ) . '</button>
622 </div>
623 </div>
624 <div class="cn-fieldset" id="cn_payment_method_paypal" style="display: none">
625 <div id="cn_paypal_button"></div>
626 </div>
627 </div>';
628
629 $html .= wp_nonce_field( 'cn_api_payment', 'cn_payment_nonce', true, false );
630
631 $html .= '
632 </form>
633 </div>
634 </div>
635 </div>';
636 } elseif ( $screen === 'login' ) {
637 $html .= '
638 <div class="cn-sidebar cn-sidebar-left has-loader">
639 <div class="cn-inner">
640 <div class="cn-header">
641 <div class="cn-top-bar">
642 <div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-notice-logo.png" alt="Cookie Notice logo" /></div>
643 </div>
644 </div>
645 <div class="cn-body">
646 <h2>' . esc_html__( 'Compliance Sign in', 'cookie-notice' ) . '</h2>
647 <div class="cn-lead">
648 <p>' . esc_html__( 'Sign in to your existing Cookie Compliance&trade; account and select your preferred plan.', 'cookie-notice' ) . '</p>
649 </div>
650 <div class="cn-accordion">
651 <div id="cn-accordion-account" class="cn-accordion-item cn-form-container" tabindex="-1">
652 <div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">1. ' . esc_html__( 'Account Login', 'cookie-notice' ) . '</button></div>
653 <div class="cn-accordion-collapse">
654 <form method="post" class="cn-form" action="" data-action="login">
655 <div class="cn-form-feedback cn-hidden"></div>
656 <div class="cn-field cn-field-text">
657 <input type="text" name="email" value="" tabindex="1" placeholder="' . esc_attr__( 'Email address', 'cookie-notice' ) . '">
658 </div>
659 <div class="cn-field cn-field-text">
660 <input type="password" name="pass" value="" tabindex="2" autocomplete="off" placeholder="' . esc_attr__( 'Password', 'cookie-notice' ) . '">
661 </div>
662 <div class="cn-field cn-field-submit cn-nav">
663 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" ' . /* data-screen="4" */ '><span class="cn-spinner"></span>' . esc_html__( 'Sign in', 'cookie-notice' ) . '</button>
664 </div>';
665
666 // get site language
667 $locale = get_locale();
668 $locale_code = explode( '_', $locale );
669
670 $html .= '
671 <input type="hidden" name="language" value="' . esc_attr( $locale_code[0] ) . '" />';
672
673 $html .= wp_nonce_field( 'cn_api_login', 'cn_nonce', true, false );
674
675 $html .= '
676 </form>
677 <p>' . esc_html__( 'Don\'t have an account yet?', 'cookie-notice' ) . ' <a href="#" class="cn-screen-button" data-screen="register">' . esc_html__( 'Sign up', 'cookie-notice' ) . '</a></p>
678 </div>
679 </div>
680 <div id="cn-accordion-billing" class="cn-accordion-item cn-form-container cn-collapsed cn-disabled" tabindex="-1">
681 <div class="cn-accordion-header cn-form-header">
682 <button class="cn-accordion-button" type="button">2. ' . esc_html__( 'Select Plan', 'cookie-notice' ) . '</button>
683 </div>
684 <form method="post" class="cn-accordion-collapse cn-form cn-form-disabled" action="" data-action="payment">
685 <div class="cn-form-feedback cn-hidden"></div>
686 <div class="cn-field cn-field-radio">
687 <div class="cn-radio-wrapper cn-plan-wrapper">
688 <label for="cn-field-plan-free" class="cn-pricing-plan-free"><input id="cn-field-plan-free" type="radio" name="plan" value="free" checked><span><span class="cn-plan-description">' . esc_html__( 'Basic', 'cookie-notice' ) . '</span><span class="cn-plan-pricing"><span class="cn-plan-price">Free</span></span><span class="cn-plan-overlay"></span></span></label>
689 <label for="cn-field-plan-pro" class="cn-pricing-plan-pro"><input id="cn-field-plan-pro" type="radio" name="plan" value="compliance_monthly_notrial"><span><span class="cn-plan-description">' . sprintf( esc_html__( '%sProfessional%s', 'cookie-notice' ), '<b>', '</b>' ) . ' - <span class="cn-plan-period">' . esc_html__( 'monthly', 'cookie-notice' ) . '</span></span><span class="cn-plan-pricing"><span class="cn-plan-price">$<span class="cn-plan-amount">' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '</span></span></span><span class="cn-plan-overlay"></span></span></label>
690 <label for="cn-field-plan-license" class="cn-pricing-plan-license cn-disabled">
691 <input id="cn-field-plan-license" type="radio" name="plan" value="license"><span><span class="cn-plan-description">' . esc_html__( 'Use License', 'cookie-notice' ) . '</span><span class="cn-plan-pricing"><span class="cn-plan-price"><span class="cn-plan-amount">0</span> ' . esc_html__( 'available', 'cookie-notice' ) . '</span></span><span class="cn-plan-overlay"></span></span>
692 </label>
693 </div>
694 </div>
695 <div class="cn-field cn-fieldset" id="cn_submit_free">
696 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Confirm', 'cookie-notice' ) . '</button>
697 </div>
698 <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_pro">
699 <input type="hidden" name="cn_payment_identifier" value="" />
700 <div class="cn-field cn-field-radio">
701 <label>' . esc_html__( 'Payment Method', 'cookie-notice' ) . '</label>
702 <div class="cn-radio-wrapper cn-horizontal-wrapper">
703 <label for="cn_field_method_credit_card"><input id="cn_field_method_credit_card" type="radio" name="method" value="credit_card" checked><span>' . esc_html__( 'Credit Card', 'cookie-notice' ) . '</span></label>
704 <label for="cn_field_method_paypal"><input id="cn_field_method_paypal" type="radio" name="method" value="paypal"><span>' . esc_html__( 'PayPal', 'cookie-notice' ) . '</span></label>
705 </div>
706 </div>
707 <div class="cn-fieldset" id="cn_payment_method_credit_card">
708 <input type="hidden" name="payment_nonce" value="" />
709 <div class="cn-field cn-field-text">
710 <label for="cn_card_number">' . esc_html__( 'Card Number', 'cookie-notice' ) . '</label>
711 <div id="cn_card_number"></div>
712 </div>
713 <div class="cn-field cn-field-text cn-field-half cn-field-first">
714 <label for="cn_expiration_date">' . esc_html__( 'Expiration Date', 'cookie-notice' ) . '</label>
715 <div id="cn_expiration_date"></div>
716 </div>
717 <div class="cn-field cn-field-text cn-field-half cn-field-last">
718 <label for="cn_cvv">' . esc_html__( 'CVC/CVV', 'cookie-notice' ) . '</label>
719 <div id="cn_cvv"></div>
720 </div>
721 <div class="cn-field cn-field-submit cn-nav">
722 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Submit', 'cookie-notice' ) . '</button>
723 </div>
724 </div>
725 <div class="cn-fieldset" id="cn_payment_method_paypal" style="display: none">
726 <div id="cn_paypal_button"></div>
727 </div>
728 </div>
729 <div class="cn-field cn-fieldset cn-hidden" id="cn_submit_license">
730 <div class="cn-field cn-field-select" id="cn-subscriptions-list">
731 <label for="cn-subscription-select">' . esc_html__( 'Select subscription', 'cookie-notice' ) . '​</label>
732 <select name="cn_subscription_id" class="form-select" aria-label="' . esc_attr__( 'Licenses', 'cookie-notice' ) . '" id="cn-subscription-select">
733 </select>
734 </div><br>
735 <button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Confirm', 'cookie-notice' ) . '</button>
736 </div>';
737
738 $html .= wp_nonce_field( 'cn_api_payment', 'cn_payment_nonce', true, false );
739
740 $html .= '
741 </form>
742 </div>
743 </div>
744 </div>';
745 } elseif ( $screen === 'success' ) {
746 $html .= '
747 <div class="cn-sidebar cn-sidebar-left has-loader">
748 <div class="cn-inner">
749 <div class="cn-header">
750 <div class="cn-top-bar">
751 <div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-notice-logo.png" alt="Cookie Notice logo" /></div>
752 </div>
753 </div>
754 <div class="cn-body">
755 <h2>' . esc_html__( 'Success!', 'cookie-notice' ) . '</h2>
756 <div class="cn-lead"><p><b>' . esc_html__( 'You have successfully integrated your website to Cookie Compliance&trade;', 'cookie-notice' ) . '</b></p><p>' . sprintf( esc_html__( 'Go to Cookie Compliance application now. Or access it anytime from your %sCookie Notice settings page%s.', 'cookie-notice' ), '<a href="' . esc_url( Cookie_Notice()->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' ) ) . '">', '</a>' ) . '</p></div>
757 </div>';
758 }
759
760
761
762 $html .= '
763 <div class="cn-footer">';
764 /*
765 switch ( $screen ) {
766 case 'about':
767 $html .= '<a href="' . esc_url( admin_url( 'admin.php?page=cookie-notice' ) ) . '" class="cn-btn cn-btn-link cn-skip-button">' . __( 'Skip Live Setup', 'cookie-notice' ) . '</a>';
768 break;
769 case 'success':
770 $html .= '<a href="' . esc_url( get_dashboard_url() ) . '" class="cn-btn cn-btn-link cn-skip-button">' . __( 'WordPress Dashboard', 'cookie-notice' ) . '</a>';
771 break;
772 default:
773 $html .= '<a href="' . esc_url( admin_url( 'admin.php?page=cookie-notice' ) ) . '" class="cn-btn cn-btn-link cn-skip-button">' . __( 'Skip for now', 'cookie-notice' ) . '</a>';
774 break;
775 }
776 */
777 $html .= '
778 </div>
779 </div>
780 </div>';
781 }
782
783 if ( $echo ) {
784 // get allowed html
785 $allowed_html = wp_kses_allowed_html( 'post' );
786 $allowed_html['div']['tabindex'] = true;
787 $allowed_html['button']['tabindex'] = true;
788 $allowed_html['iframe'] = [
789 'id' => true,
790 'src' => true
791 ];
792 $allowed_html['form'] = [
793 'id' => true,
794 'class' => true,
795 'action' => true,
796 'data-action' => true
797 ];
798 $allowed_html['select'] = [
799 'name' => true,
800 'class' => true,
801 'id' => true,
802 'aria-label' => true
803 ];
804 $allowed_html['option'] = [
805 'value' => true,
806 'data-price' => true
807 ];
808 $allowed_html['input'] = [
809 'id' => true,
810 'type' => true,
811 'name' => true,
812 'class' => true,
813 'value' => true,
814 'tabindex' => true,
815 'autocomplete' => true,
816 'checked' => true,
817 'placeholder' => true,
818 'title' => true
819 ];
820
821 add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
822
823 // echo wp_kses( $html, $allowed_html );
824 echo $html;
825
826 remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
827 } else
828 return $html;
829
830 if ( wp_doing_ajax() )
831 exit();
832 }
833 }
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 // Silence is golden.
...\ No newline at end of file ...\ No newline at end of file
1 ( function( $ ) {
2
3 // ready event
4 $( function() {
5 var charts = cnDashboardArgs.charts;
6
7 if ( Object.entries(charts).length > 0 ) {
8 for ( const [key, config] of Object.entries( charts ) ) {
9 // create canvas
10 var canvas = document.getElementById( 'cn-' + key + '-chart' );
11
12 if ( canvas ) {
13 // options per chart type
14 var options = {
15 doughnut: {
16 responsive: true,
17 plugins: {
18 legend: {
19 position: 'top',
20 }
21 },
22 hover: {
23 mode: 'label'
24 },
25 layout: {
26 padding: 0
27 }
28 },
29 line: {
30 scales: {
31 x: {
32 display: true,
33 title: {
34 display: false
35 }
36 },
37 y: {
38 display: true,
39 grace: 0,
40 beginAtZero: true,
41 title: {
42 display: false
43 },
44 ticks: {
45 precision: 0,
46 maxTicksLimit: 12
47 }
48 }
49 }
50 }
51 }
52
53 config.options = options.hasOwnProperty( config.type ) ? options[config.type] : {};
54
55 var chart = new Chart( canvas, config );
56
57 chart.update();
58 }
59 }
60 }
61 } );
62
63 } )( jQuery );
...\ No newline at end of file ...\ No newline at end of file
1 ( function( $ ) {
2
3 // ready event
4 $( function() {
5 // save dismiss state // .is-dismissible
6 $( '.cn-notice' ).on( 'click', '.notice-dismiss, .cn-notice-dismiss', function( e ) {
7 var notice_action = 'dismiss';
8 var param = '';
9
10 if ( $( e.currentTarget ).hasClass( 'cn-approve' ) )
11 notice_action = 'approve';
12 else if ( $( e.currentTarget ).hasClass( 'cn-delay' ) )
13 notice_action = 'delay';
14 else if ( $( e.delegateTarget ).hasClass( 'cn-threshold' ) ) {
15 notice_action = 'threshold';
16
17 var delay = $( e.delegateTarget ).find( '.cn-notice-text' ).data( 'delay' );
18
19 param = parseInt( delay );
20 }
21
22 $.ajax( {
23 url: cnArgsNotice.ajaxURL,
24 type: 'POST',
25 dataType: 'json',
26 data: {
27 action: 'cn_dismiss_notice',
28 notice_action: notice_action,
29 nonce: cnArgsNotice.nonce,
30 param: param,
31 cn_network: cnArgsNotice.network ? 1 : 0
32 }
33 } );
34
35 $( e.delegateTarget ).slideUp( 'fast' );
36 } );
37 } );
38
39 } )( jQuery );
...\ No newline at end of file ...\ No newline at end of file
1 ( function( $ ) {
2
3 // ready event
4 $( function() {
5 // cancel deactivation
6 $( document ).on( 'click', '.cn-deactivate-plugin-cancel', function( e ) {
7 tb_remove();
8
9 return false;
10 } );
11
12 // simple deactivation
13 $( document ).on( 'click', '.cn-deactivate-plugin-simple', function( e ) {
14 // display spinner
15 $( '#cn-deactivation-footer .spinner' ).addClass( 'is-active' );
16 } );
17
18 // deactivation with sending data
19 $( document ).on( 'click', '.cn-deactivate-plugin-data', function( e ) {
20 var spinner = $( '#cn-deactivation-footer .spinner' );
21 var url = $( this ).attr( 'href' );
22
23 // display spinner
24 spinner.addClass( 'is-active' );
25
26 // submit data
27 $.post( ajaxurl, {
28 action: 'cn-deactivate-plugin',
29 option_id: $( 'input[name="cn_deactivation_option"]:checked' ).val(),
30 other: $( 'textarea[name="cn_deactivation_other"]' ).val(),
31 nonce: cnArgsPlugins.nonce
32 } ).done( function( response ) {
33 // deactivate plugin
34 window.location.href = url;
35 } ).fail( function() {
36 // deactivate plugin
37 window.location.href = url;
38 } );
39
40 return false;
41 } );
42
43 // click on deactivation link
44 $( document ).on( 'click', '.cn-deactivate-plugin-modal', function( e ) {
45 tb_show( cnArgsPlugins.deactivate, '#TB_inline?inlineId=cn-deactivation-modal&modal=false' );
46
47 setTimeout( function() {
48 var modalBox = $( '#cn-deactivation-container' ).closest( '#TB_window' );
49
50 if ( modalBox.length > 0 ) {
51 $( modalBox ).addClass( 'cn-deactivation-modal' );
52 $( modalBox ).find( '#TB_closeWindowButton' ).on( 'blur' );
53 }
54 }, 0 );
55
56 return false;
57 } );
58
59 // change radio
60 $( document ).on( 'change', 'input[name="cn_deactivation_option"]', function( e ) {
61 var last = $( 'input[name="cn_deactivation_option"]' ).last().get( 0 );
62
63 // last element?
64 if ( $( this ).get( 0 ) === last )
65 $( '.cn-deactivation-textarea textarea' ).prop( 'disabled', false );
66 else
67 $( '.cn-deactivation-textarea textarea' ).prop( 'disabled', true );
68 } );
69 } );
70
71 } )( jQuery );
...\ No newline at end of file ...\ No newline at end of file
1 ( function( $ ) {
2
3 // ready event
4 $( function() {
5 var btClient = false;
6 var btCreditCardsInitialized = false;
7 var btPayPalInitialized = false;
8
9 var btInit = function() {
10 var result = btInitToken();
11
12 if ( result !== false && btCreditCardsInitialized === false ) {
13 // ajax was successful
14 result.done( function( response ) {
15 // token received
16 try {
17 // parse response
18 data = JSON.parse( response );
19
20 // first step, init braintree client
21 btClient = braintree.client.create( {
22 authorization: data.token
23 } );
24
25 btInitPaymentMethod( 'credit_card' );
26 // token failed
27 } catch ( e ) {
28 btGatewayFail( 'btInit catch' );
29 }
30 // ajax failed
31 } ).fail( function() {
32 btGatewayFail( 'btInit AJAX failed' );
33 } );
34 }
35 }
36
37 var btInitToken = function() {
38 // payment screen?
39 var paymentEl = $( '.cn-sidebar form[data-action="payment"]' );
40
41 // init braintree
42 if ( paymentEl.length ) {
43 paymentEl.addClass( 'cn-form-disabled' );
44
45 if ( typeof braintree !== 'undefined' ) {
46 var ajaxArgs = {
47 action: 'cn_api_request',
48 request: 'get_bt_init_token',
49 nonce: cnWelcomeArgs.nonce
50 };
51
52 // network area?
53 if ( cnWelcomeArgs.network === '1' )
54 ajaxArgs.cn_network = 1;
55
56 return $.ajax( {
57 url: cnWelcomeArgs.ajaxURL,
58 type: 'POST',
59 dataType: 'html',
60 data: ajaxArgs
61 } );
62 } else
63 return false;
64 } else
65 return false;
66 }
67
68 var btInitPaymentMethod = function( type ) {
69 if ( btClient !== false ) {
70 if ( type === 'credit_card' && btCreditCardsInitialized === false ) {
71 $( 'form.cn-form[data-action="payment"]' ).addClass( 'cn-form-disabled' );
72
73 btClient.then( btCreditCardsInit ).then( btHostedFieldsInstance ).catch( btGatewayFail );
74 } else if ( type === 'paypal' && btPayPalInitialized === false ) {
75 $( 'form.cn-form[data-action="payment"]' ).addClass( 'cn-form-disabled' );
76
77 btClient.then( btPaypalCheckoutInit ).then( btPaypalCheckoutSDK ).then( btPaypalCheckoutInstance ).then( btPaypalCheckoutButton ).catch( btGatewayFail );
78 }
79 } else
80 btGatewayFail( 'btInitPaymentMethod btClient is false' );
81 }
82
83 var btCreditCardsInit = function( clientInstance ) {
84 return braintree.hostedFields.create( {
85 client: clientInstance,
86 styles: {
87 'input': {
88 'font-size': '14px',
89 'font-family': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
90 'color': '#fff'
91 },
92 ':focus': {
93 'color': '#fff'
94 },
95 "::placeholder": {
96 'color': '#aaa'
97 }
98 },
99 fields: {
100 number: {
101 'selector': '#cn_card_number',
102 'placeholder': '0000 0000 0000 0000'
103 },
104 expirationDate: {
105 'selector': '#cn_expiration_date',
106 'placeholder': 'MM / YY'
107 },
108 cvv: {
109 'selector': '#cn_cvv',
110 'placeholder': '123'
111 }
112 }
113 } );
114 }
115
116 var btHostedFieldsInstance = function( hostedFieldsInstance ) {
117 btCreditCardsInitialized = true;
118
119 var form = $( 'form.cn-form[data-action="payment"]' );
120
121 form.removeClass( 'cn-form-disabled' );
122
123 form.on( 'submit', function() {
124 if ( form.hasClass( 'cn-payment-in-progress' ) )
125 return false;
126
127 form.find( '.cn-form-feedback' ).addClass( 'cn-hidden' );
128
129 // spin the spinner, if exists
130 if ( form.find( '.cn-spinner' ).length )
131 form.find( '.cn-spinner' ).addClass( 'spin' );
132
133 var invalidForm = false;
134 var state = hostedFieldsInstance.getState();
135
136 // check hosted fields
137 Object.keys( state.fields ).forEach( function( field ) {
138 if ( ! state.fields[field].isValid ) {
139 $( state.fields[field].container ).addClass( 'braintree-hosted-fields-invalid' );
140
141 invalidForm = true;
142 }
143 } );
144
145 if ( invalidForm ) {
146 setTimeout( function() {
147 cnDisplayError( cnWelcomeArgs.invalidFields, form );
148
149 // spin the spinner, if exists
150 if ( form.find( '.cn-spinner' ).length )
151 form.find( '.cn-spinner' ).removeClass( 'spin' );
152 }, 500 );
153
154 return false;
155 }
156
157 hostedFieldsInstance.tokenize( function( err, payload ) {
158 if ( err ) {
159 cnDisplayError( cnWelcomeArgs.error );
160
161 return false;
162 } else {
163 form.addClass( 'cn-payment-in-progress' );
164 form.find( 'input[name="payment_nonce"]' ).val( payload.nonce );
165 form.find( 'input[name="cn_payment_identifier"]' ).val( payload.details.lastFour );
166
167 $( '#cn_submit_pro' ).find( '.cn-screen-button[data-screen="4"]' ).trigger( 'click' );
168 }
169 } );
170
171 return false;
172 } );
173 }
174
175 var btPaypalCheckoutInit = function( clientInstance ) {
176 return braintree.paypalCheckout.create( {
177 client: clientInstance
178 } );
179 }
180
181 var btPaypalCheckoutSDK = function( paypalCheckoutInstance ) {
182 return paypalCheckoutInstance.loadPayPalSDK( {
183 vault: true,
184 intent: 'tokenize'
185 } );
186 }
187
188 var btPaypalCheckoutInstance = function( paypalCheckoutInstance ) {
189 var form = $( 'form.cn-form[data-action="payment"]' );
190
191 return paypal.Buttons( {
192 fundingSource: paypal.FUNDING.PAYPAL,
193 createBillingAgreement: function() {
194 form.addClass( 'cn-form-disabled' );
195
196 return paypalCheckoutInstance.createPayment( {
197 flow: 'vault',
198 intent: 'tokenize',
199 currency: 'EUR'
200 } );
201 },
202 onApprove: function( data, actions ) {
203 return paypalCheckoutInstance.tokenizePayment( data ).then( function( payload ) {
204 form.addClass( 'cn-payment-in-progress' );
205 form.find( 'input[name="payment_nonce"]' ).val( payload.nonce );
206 form.find( 'input[name="cn_payment_identifier"]' ).val( payload.details.email );
207
208 $( '#cn_submit_pro' ).find( '.cn-screen-button[data-screen="4"]' ).trigger( 'click' );
209 } );
210 },
211 onCancel: function( data ) {
212 form.removeClass( 'cn-form-disabled' );
213 },
214 onError: function( err ) {
215 form.removeClass( 'cn-form-disabled' );
216 }
217 } ).render( '#cn_paypal_button' );
218 }
219
220 var btPaypalCheckoutButton = function() {
221 btPayPalInitialized = true;
222
223 $( 'form.cn-form[data-action="payment"]' ).removeClass( 'cn-form-disabled' );
224 }
225
226 var btGatewayFail = function( error ) {
227 if ( typeof error !== 'undefined' )
228 console.log( error );
229
230 cnDisplayError( cnWelcomeArgs.error );
231 }
232
233 var cnDisplayError = function( message, form ) {
234 if ( typeof form === 'undefined' )
235 form = $( 'form.cn-form[data-action="payment"]' );
236
237 form.find( '.cn-form-feedback' ).html( '<p class="cn-error">' + message + '</p>' ).removeClass( 'cn-hidden' );
238 }
239
240 var cnWelcomeScreen = function( target ) {
241 var screen = $( target ).data( 'screen' );
242 var steps = [1, 2, 3, 4];
243 var sidebars = ['login', 'register', 'configure', 'payment'];
244
245 // continue with screen loading
246 var requestData = {
247 action: 'cn_welcome_screen',
248 nonce: cnWelcomeArgs.nonce
249 };
250
251 if ( $.inArray( screen, steps ) !== -1 ) {
252 var container = $( '.cn-welcome-wrap' );
253
254 requestData.screen = screen;
255 } else if ( $.inArray( screen, sidebars ) !== -1 ) {
256 var container = $( '.cn-sidebar' );
257
258 requestData.screen = screen;
259 } else
260 return false;
261
262 // network area?
263 if ( cnWelcomeArgs.network === '1' )
264 requestData.cn_network = 1;
265
266 // add loading overlay
267 $( container ).addClass( 'cn-loading' );
268
269 $.ajax( {
270 url: cnWelcomeArgs.ajaxURL,
271 type: 'POST',
272 dataType: 'html',
273 data: requestData
274 } ).done( function( response ) {
275 $( container ).replaceWith( response );
276 } ).fail( function( jqXHR, textStatus, errorThrown ) {
277 //
278 } ).always( function( response ) {
279 // remove spinner
280 $( container ).removeClass( 'cn-loading' );
281
282 // trigger event
283 var event = $.Event( 'screen-loaded' );
284
285 $( document ).trigger( event );
286 } );
287
288 return this;
289 };
290
291 var cnWelcomeForm = function( form ) {
292 var formAction = $( form[0] ).data( 'action' );
293 var formResult = null;
294 var formData = {
295 action: 'cn_api_request',
296 nonce: cnWelcomeArgs.nonce
297 };
298
299 // clear feedback
300 $( form[0] ).find( '.cn-form-feedback' ).addClass( 'cn-hidden' );
301
302 // build request data
303 formData.request = formAction;
304
305 // convert form data to object
306 $( form[0] ).serializeArray().map( function( x ) {
307 // exception for checkboxes
308 if ( x.name === 'cn_laws' ) {
309 var arrayVal = typeof formData[x.name] !== 'undefined' ? formData[x.name] : [];
310
311 arrayVal.push( x.value );
312
313 formData[x.name] = arrayVal;
314 } else
315 formData[x.name] = x.value;
316 } );
317
318 // network area?
319 if ( cnWelcomeArgs.network === '1' )
320 formData.cn_network = 1;
321
322 formResult = $.ajax( {
323 url: cnWelcomeArgs.ajaxURL,
324 type: 'POST',
325 dataType: 'json',
326 data: formData
327 } );
328
329 return formResult;
330 };
331
332 // handle screen loading
333 $( document ).on( 'click', '.cn-screen-button', function( e ) {
334 var form = $( e.target ).closest( 'form' );
335 var result = false;
336
337 // spin the spinner, if exists
338 if ( $( e.target ).find( '.cn-spinner' ).length )
339 $( e.target ).find( '.cn-spinner' ).addClass( 'spin' );
340
341 // no form?
342 if ( form.length === 0 )
343 return cnWelcomeScreen( e.target );
344
345 var formData = {};
346 var formDataset = $( form[0] ).data();
347 var formAction = formDataset.hasOwnProperty( 'action' ) ? formDataset.action : '';
348
349 // get form data
350 $( form[0] ).serializeArray().map( function( x ) {
351 // exception for checkboxes
352 if ( x.name === 'cn_laws' ) {
353 var arrayVal = typeof formData[x.name] !== 'undefined' ? formData[x.name] : [];
354
355 arrayVal.push( x.value );
356
357 formData[x.name] = arrayVal;
358 } else
359 formData[x.name] = x.value;
360 } );
361
362 // payment?
363 if ( formAction === 'payment' ) {
364 // free
365 if ( formData.plan === 'free' ) {
366 // load screen
367 cnWelcomeScreen( e.target );
368
369 return false;
370 // licesne
371 } else if ( formData.plan === 'license' ) {
372 // payment screen?
373 var paymentEl = $( '.cn-sidebar form[data-action="payment"]' );
374
375 // disable form
376 if ( paymentEl.length )
377 paymentEl.addClass( 'cn-form-disabled' );
378
379 // get subscription ID
380 var subscriptionID = formData.hasOwnProperty( 'cn_subscription_id' ) ? parseInt( formData.cn_subscription_id ) : 0;
381
382 var ajaxArgs = {
383 action: 'cn_api_request',
384 request: 'use_license',
385 subscriptionID: subscriptionID,
386 nonce: cnWelcomeArgs.nonce
387 };
388
389 // network area?
390 if ( cnWelcomeArgs.network === '1' )
391 ajaxArgs.cn_network = 1;
392
393 // assign license request
394 result = $.ajax( {
395 url: cnWelcomeArgs.ajaxURL,
396 type: 'POST',
397 dataType: 'json',
398 data: ajaxArgs
399 } );
400
401 // process license
402 result.done( function( response ) {
403 // error
404 if ( response.hasOwnProperty( 'error' ) ) {
405 cnDisplayError( response.error, $( form[0] ) );
406
407 return false;
408 // message
409 } else {
410 var targetEl = $( '#cn_submit_license' ).find( '.cn-screen-button[data-screen="4"]' );
411
412 // open next screen
413 cnWelcomeScreen( targetEl );
414
415 return result;
416 }
417 } );
418
419 // remove spinner
420 result.always( function( response ) {
421 if ( $( e.target ).find( '.cn-spinner' ).length )
422 $( e.target ).find( '.cn-spinner' ).removeClass( 'spin' );
423
424 // enable form
425 if ( paymentEl.length )
426 paymentEl.removeClass( 'cn-form-disabled' );
427 } );
428 // pro
429 } else {
430 // only credit cards
431 if ( $( form[0] ).find( 'input[name="payment_nonce"]' ).val() === '' ) {
432 form.trigger( 'submit' );
433
434 return false;
435 }
436 }
437 // other forms
438 } else
439 e.preventDefault();
440
441 // break here on license payment
442 if ( formAction === 'payment' && formData.plan === 'license' )
443 return result;
444
445 // get form and process it
446 result = cnWelcomeForm( form );
447
448 result.done( function( response ) {
449 // error
450 if ( response.hasOwnProperty( 'error' ) ) {
451 cnDisplayError( response.error, $( form[0] ) );
452
453 return false;
454 // message
455 } else if ( response.hasOwnProperty( 'message' ) ) {
456 cnDisplayError( response.message, $( form[0] ) );
457
458 return false;
459 // all good
460 } else {
461 switch ( formAction ) {
462 // logged in, go to success or billing
463 case 'login':
464 // register complete, go to success or billing
465 case 'register':
466 // if there are any subscriptions
467 if ( response.hasOwnProperty( 'subscriptions' ) ) {
468 var subscriptions = response.subscriptions;
469
470 if ( subscriptions.length > 0 ) {
471 var available = 0;
472
473 for ( i = 0; i < subscriptions.length; i ++ ) {
474 var subscriptionID = subscriptions[i].subscriptionid;
475 var licensesAvailable = parseInt( subscriptions[i].availablelicense );
476 var subscriptionText = subscriptions[i].VendorSubscriptionID + ' - ' + licensesAvailable + ' ' + cnWelcomeArgs.licensesAvailable;
477
478 var subscriptionOption = $( '<option value="' + subscriptionID + '">' + subscriptionText + '</option>' );
479
480 if ( licensesAvailable == 0 ) {
481 $( subscriptionOption ).attr( 'disabled', 'true');
482 }
483
484 $( '#cn-subscription-select' ).append( subscriptionOption );
485
486 available += licensesAvailable;
487 }
488
489 if ( available > 0 ) {
490 $( '.cn-pricing-plan-license' ).removeClass( 'cn-disabled' );
491 $( '.cn-pricing-plan-license' ).find( '.cn-plan-amount' ).text( available );
492 }
493 }
494 }
495
496 var accountPlan = formData.hasOwnProperty( 'plan' ) ? formData.plan : 'free';
497
498 // trigger payment
499 var accordionItem = $( form[0] ).closest( '.cn-accordion-item' );
500
501 // collapse account
502 $( accordionItem ).addClass( 'cn-collapsed cn-disabled' );
503
504 // show billing
505 $( accordionItem ).next().removeClass( 'cn-disabled' ).removeClass( 'cn-collapsed' );
506 $( accordionItem ).find( 'form' ).removeClass( 'cn-form-disabled' );
507
508 // init braintree after payment screen is loaded via AJAX
509 btInit();
510 break;
511
512 case 'configure':
513 default:
514 // load screen
515 cnWelcomeScreen( e.target );
516 break;
517 }
518 }
519 } );
520
521 result.always( function( response ) {
522 if ( $( e.target ).find( '.cn-spinner' ).length )
523 $( e.target ).find( '.cn-spinner' ).removeClass( 'spin' );
524
525 // after invalid payment?
526 if ( formAction === 'payment' ) {
527 $( form[0] ).removeClass( 'cn-payment-in-progress' );
528 $( form[0] ).find( 'input[name="payment_nonce"]' ).val( '' );
529 }
530 } );
531
532 return result;
533 } );
534
535 //
536 $( document ).on( 'screen-loaded', function() {
537 var configureFields = $( '#cn-form-configure' ).serializeArray() || [];
538 var frame = window.frames[ 'cn_iframe_id' ];
539
540 if ( configureFields.length > 0 ) {
541 $( configureFields ).each( function( index, field ) {
542 } );
543 }
544 } );
545
546 // change payment method
547 $( document ).on( 'change', 'input[name="method"]', function() {
548 var input = $( this );
549
550 $( '#cn_payment_method_credit_card, #cn_payment_method_paypal' ).toggle();
551
552 input.closest( 'form' ).find( '.cn-form-feedback' ).addClass( 'cn-hidden' );
553
554 // init payment method if needed
555 btInitPaymentMethod( input.val() );
556 } );
557
558 //
559 $( document ).on( 'click', '.cn-accordion > .cn-accordion-item .cn-accordion-button', function() {
560 var accordionItem = $( this ).closest( '.cn-accordion-item' );
561 var activeItem = $( this ).closest( '.cn-accordion' ).find( '.cn-accordion-item:not(.cn-collapsed)' );
562
563 if ( $( accordionItem ).hasClass( 'cn-collapsed' ) ) {
564 $( activeItem ).addClass( 'cn-collapsed' );
565 $( accordionItem ).removeClass( 'cn-collapsed' );
566 }
567
568 return false;
569 } );
570
571 // live preview
572 $( document ).on( 'change', 'input[name="cn_position"]', function() {
573 var val = $( this ).val();
574 var frame = window.frames['cn_iframe_id'];
575
576 frame.contentWindow.postMessage( {call: 'position', value: val} );
577 } );
578
579 $( document ).on( 'change', 'input[name="cn_laws"]', function() {
580 var val = [];
581
582 $( 'input[name="cn_laws"]:checked' ).each( function() {
583 val.push( $( this ).val() );
584 } );
585
586 var frame = window.frames['cn_iframe_id'];
587
588 frame.contentWindow.postMessage( {call: 'laws', value: val} );
589 } );
590
591 $( document ).on( 'change', 'input[name="cn_naming"]', function() {
592 var val = [];
593
594 $( 'input[name="cn_naming"]:checked' ).each( function() {
595 val.push( $( this ).val() );
596 } );
597
598 var frame = window.frames['cn_iframe_id'];
599
600 frame.contentWindow.postMessage( {call: 'naming', value: val} );
601 } );
602
603 $( document ).on( 'change', 'input[name="cn_privacy_paper"]', function() {
604 var val = $( this ).prop( 'checked' );
605 var frame = window.frames['cn_iframe_id'];
606
607 frame.contentWindow.postMessage( {call: 'privacy_paper', value: val} );
608 } );
609
610 $( document ).on( 'change', 'input[name="cn_privacy_contact"]', function() {
611 var val = $( this ).prop( 'checked' );
612 var frame = window.frames['cn_iframe_id'];
613
614 frame.contentWindow.postMessage( {call: 'privacy_contact', value: val} );
615 } );
616
617 $( document ).on( 'change', 'input[name="cn_color_primary"]', function() {
618 var val = $( this ).val();
619 var frame = window.frames['cn_iframe_id'];
620
621 frame.contentWindow.postMessage( {call: 'color_primary', value: val} );
622 } );
623
624 $( document ).on( 'change', 'input[name="cn_color_background"]', function() {
625 var val = $( this ).val();
626 var frame = window.frames['cn_iframe_id'];
627
628 frame.contentWindow.postMessage( {call: 'color_background', value: val} );
629 } );
630
631 $( document ).on( 'change', 'input[name="cn_color_border"]', function() {
632 var val = $( this ).val();
633 var frame = window.frames['cn_iframe_id'];
634
635 frame.contentWindow.postMessage( {call: 'color_border', value: val} );
636 } );
637
638 $( document ).on( 'change', 'input[name="cn_color_text"]', function() {
639 var val = $( this ).val();
640 var frame = window.frames['cn_iframe_id'];
641
642 frame.contentWindow.postMessage( {call: 'color_text', value: val} );
643 } );
644
645 $( document ).on( 'change', 'input[name="cn_color_heading"]', function() {
646 var val = $( this ).val();
647 var frame = window.frames['cn_iframe_id'];
648
649 frame.contentWindow.postMessage( {call: 'color_heading', value: val} );
650 } );
651
652 $( document ).on( 'change', 'input[name="cn_color_button_text"]', function() {
653 var val = $( this ).val();
654 var frame = window.frames['cn_iframe_id'];
655
656 frame.contentWindow.postMessage( {call: 'color_button_text', value: val} );
657 } );
658
659 // handle monthly / yearly payment plan
660 $( document ).on( 'change', 'input[name="cn_pricing_type"]', function() {
661 // pricing plans
662 var plansMonthly = cnWelcomeArgs.pricingMonthly;
663 var plansYearly = cnWelcomeArgs.pricingYearly;
664
665 var pricingOptions = $( '#cn-pricing-plans option' );
666 var checked = $( 'input[name="cn_pricing_type"]:checked' ).val();
667
668 var names = Object.keys( checked === 'yearly' ? plansYearly : plansMonthly );
669 var pricing = Object.values( checked === 'yearly' ? plansYearly : plansMonthly );
670
671 if ( checked === 'yearly' )
672 $( '.cn-plan-period' ).text( cnWelcomeArgs.paidYear );
673 else
674 $( '.cn-plan-period' ).text( cnWelcomeArgs.paidMonth );
675
676 // replace options
677 var i = 0;
678
679 for ( var property in pricing ) {
680 var option = pricingOptions[i];
681
682 $( option ).val( names[i] );
683 $( option ).attr( 'data-price', pricing[i] );
684 i++;
685 }
686
687 // trigger plan selection
688 $( 'select[name="cn_pricing_plan"]' ).trigger( 'change' );
689 } );
690
691 // handle pro plan selection
692 $( document ).on( 'change', 'select[name="cn_pricing_plan"]', function() {
693 var el = $( '#cn-pricing-plans' );
694 var selected = $( el ).find( 'option:selected' );
695
696 // update price
697 $( '.cn-pricing-plan-pro .cn-plan-amount' ).text( $( selected ).attr( 'data-price' ) );
698
699 var availablePlans = ['free'];
700
701 // merge with pro plans
702 availablePlans = availablePlans.concat( Object.keys( cnWelcomeArgs.pricingMonthly ) );
703 availablePlans = availablePlans.concat( Object.keys( cnWelcomeArgs.pricingYearly ) );
704
705 var input = $( this );
706 var inputVal = input.val();
707
708 inputVal = availablePlans.indexOf( inputVal ) !== -1 ? inputVal : 'free';
709
710 if ( inputVal === 'free' ) {
711 $( '#cn_submit_free' ).removeClass( 'cn-hidden' );
712 $( '#cn_submit_pro' ).addClass( 'cn-hidden' );
713
714 $( document ).find( '#cn-field-plan-free' ).prop( 'checked', true );
715 $( document ).find( '#cn-pricing-plan-free' ).prop( 'checked', true );
716 } else {
717 $( '#cn_submit_free' ).addClass( 'cn-hidden' );
718 $( '#cn_submit_pro' ).removeClass( 'cn-hidden' );
719
720 $( document ).find( '#cn-field-plan-pro' ).val( inputVal ).prop( 'checked', true );
721 $( document ).find( '#cn-pricing-plan-pro' ).prop( 'checked', true );
722 }
723 } );
724
725 // handle free / pro / license selection
726 $( document ).on( 'change', 'input[name="plan"]', function() {
727 var input = $( this ),
728 inputVal = input.val();
729
730 if ( inputVal === 'free' ) {
731 $( '#cn_submit_free' ).removeClass( 'cn-hidden' );
732 $( '#cn_submit_pro' ).addClass( 'cn-hidden' );
733 $( '#cn_submit_license' ).addClass( 'cn-hidden' );
734
735 $( document ).find( '#cn-pricing-plan-free' ).prop( 'checked', true );
736 } else if ( inputVal === 'license' ) {
737 $( '#cn_submit_free' ).addClass( 'cn-hidden' );
738 $( '#cn_submit_pro' ).addClass( 'cn-hidden' );
739 $( '#cn_submit_license' ).removeClass( 'cn-hidden' );
740
741 $( document ).find( '#cn-pricing-plan-free' ).prop( 'checked', false );
742 $( document ).find( '#cn-pricing-plan-pro' ).prop( 'checked', false );
743 } else {
744 $( '#cn_submit_free' ).addClass( 'cn-hidden' );
745 $( '#cn_submit_pro' ).removeClass( 'cn-hidden' );
746 $( '#cn_submit_license' ).addClass( 'cn-hidden' );
747
748 $( document ).find( '#cn-pricing-plan-pro' ).prop( 'checked', true );
749 }
750 } );
751
752 // highlight form
753 $( document ).on( 'click', 'input[name="cn_pricing"]', function() {
754 $( '.cn-accordion .cn-accordion-item:first-child:not(.cn-collapsed)' ).focus();
755 } );
756
757 // select plan payment
758 $( document ).on( 'change', 'input[name="cn_pricing"]', function() {
759 var input = $( this ),
760 inputVal = input.val();
761
762 if ( inputVal === 'free' ) {
763 $( '#cn_submit_free' ).removeClass( 'cn-hidden' );
764 $( '#cn_submit_pro' ).addClass( 'cn-hidden' );
765
766 $( document ).find( '#cn-field-plan-free' ).prop( 'checked', true );
767 } else {
768 $( '#cn_submit_free' ).addClass( 'cn-hidden' );
769 $( '#cn_submit_pro' ).removeClass( 'cn-hidden' );
770
771 $( document ).find( '#cn-field-plan-pro' ).prop( 'checked', true );
772 }
773
774 } );
775
776 // color picker
777 initSpectrum();
778
779 // init welcome modal
780 if ( cnWelcomeArgs.initModal == true )
781 initModal();
782
783 } );
784
785 $( document ).on( 'ajaxComplete', function() {
786 // color picker
787 initSpectrum();
788 } );
789
790 function initSpectrum() {
791 $( '.cn-color-picker' ).spectrum( {
792 showInput: true,
793 showInitial: true,
794 allowEmpty: false,
795 showAlpha: false
796 } );
797 }
798
799 function initModal() {
800 var progressbar,
801 timerId,
802 modal = $( "#cn-modal-trigger" );
803
804 if ( modal ) {
805 $( "#cn-modal-trigger" ).modaal( {
806 content_source: cnWelcomeArgs.ajaxURL + '?action=cn_welcome_screen' + '&nonce=' + cnWelcomeArgs.nonce + '&screen=1',
807 type: 'ajax',
808 width: 1600,
809 custom_class: 'cn-modal',
810 // is_locked: true
811 ajax_success: function() {
812 progressbar = $( document ).find( '.cn-progressbar' );
813
814 if ( progressbar ) {
815 timerId = initProgressBar( progressbar );
816 }
817 },
818 before_close: function() {
819 clearInterval( timerId );
820
821 var currentStep = $( '.cn-welcome-wrap' );
822
823 // reload if on success screen
824 if ( currentStep.length > 0 ) {
825 if ( $( currentStep[0] ).hasClass( 'cn-welcome-step-4' ) === true )
826 window.location.reload( true );
827 }
828 },
829 after_close: function() {
830 progressbar = $( document ).find( '.cn-progressbar' );
831
832 $( progressbar ).progressbar( "destroy" );
833 }
834 } );
835
836 $( modal ).trigger( 'click' );
837
838 $( document ).on( 'click', '.cn-skip-button', function( e ) {
839 $( '#modaal-close' ).trigger( 'click' );
840 } );
841 }
842 }
843
844 function initProgressBar( progressbar ) {
845 var progressbarObj,
846 progressLabel = $( document ).find( '.cn-progress-label' ),
847 complianceResults = $( document ).find( '.cn-compliance-results' ),
848 currentProgress = 0,
849 timerId;
850
851 if ( progressbar ) {
852 $( document ).on( 'click', '.cn-screen-button', function( e ) {
853 e.preventDefault();
854
855 clearInterval( timerId );
856 } );
857
858 $( progressbar ).progressbar( {
859 value: 5,
860 max: 100,
861 create: function( event, ui ) {
862 timerId = setInterval( function() {
863 // increment progress bar
864 currentProgress += 5;
865
866 // update progressbar
867 progressbar.progressbar( 'value', currentProgress );
868
869 var lastItem = $( complianceResults ).find( 'div:visible' ).last(),
870 lastItemText = $( lastItem ).find( '.cn-compliance-status' ).text();
871
872 $( lastItem ).find( '.cn-compliance-status' ).text( lastItemText + ' .' );
873
874 switch ( currentProgress ) {
875 case 25:
876 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-passed' ).text( cnWelcomeArgs.statusPassed );
877
878 $( lastItem ).next().slideDown( 200 );
879 break;
880 case 50:
881 if ( cnWelcomeArgs.complianceStatus === 'active' ) {
882 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-passed' ).text( cnWelcomeArgs.statusPassed );
883 } else {
884 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-failed' ).text( cnWelcomeArgs.statusFailed );
885 }
886
887 $( lastItem ).next().slideDown( 200 );
888 break;
889 case 75:
890 if ( cnWelcomeArgs.complianceStatus === 'active' ) {
891 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-passed' ).text( cnWelcomeArgs.statusPassed );
892 } else {
893 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-failed' ).text( cnWelcomeArgs.statusFailed );
894 }
895
896 $( lastItem ).next().slideDown( 200 );
897 break;
898 case 100:
899 if ( cnWelcomeArgs.complianceStatus === 'active' ) {
900 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-passed' ).text( cnWelcomeArgs.statusPassed );
901 } else {
902 $( lastItem ).find( '.cn-compliance-status' ).addClass( 'cn-failed' ).text( cnWelcomeArgs.statusFailed );
903 }
904 break;
905 }
906
907 // complete
908 if ( currentProgress >= 100 )
909 clearInterval( timerId );
910 }, 300 );
911 },
912 change: function( event, ui ) {
913 progressLabel.text( progressbar.progressbar( 'value' ) + '%' );
914 },
915 complete: function( event, ui ) {
916 setTimeout( function() {
917 if ( cnWelcomeArgs.complianceStatus )
918 $( '.cn-compliance-check' ).find( '.cn-compliance-feedback' ).html( '<p class="cn-message">' + cnWelcomeArgs.compliancePassed + '</p>' ).removeClass( 'cn-hidden' );
919 else
920 $( '.cn-compliance-check' ).find( '.cn-compliance-feedback' ).html( '<p class="cn-error">' + cnWelcomeArgs.complianceFailed + '</p>' ).removeClass( 'cn-hidden' );
921 }, 500 );
922 }
923 } );
924
925 progressbarObj = $( progressbar ).progressbar( "instance" );
926
927 return timerId;
928 }
929 }
930
931 $( document ).on( 'click', '.cn-run-upgrade, .cn-run-welcome', function( e ) {
932 e.preventDefault();
933
934 // modal
935 initModal();
936 } );
937
938 $( document ).ready( function() {
939 var welcome = false;
940
941 welcome = cnGetUrlParam( 'welcome' );
942
943 if ( welcome ) {
944 // modal
945 initModal();
946 }
947 } );
948
949 $( document ).on( 'click', '.cn-sign-up', function( e ) {
950 e.preventDefault();
951
952 $( '.cn-screen-button' ).trigger( 'click' );
953 } );
954
955 var cnGetUrlParam = function cnGetUrlParam( parameter ) {
956 var pageURL = window.location.search.substring( 1 ),
957 urlVars = pageURL.split( '&' ),
958 parameterName,
959 i;
960
961 for ( i = 0; i < urlVars.length; i ++ ) {
962 parameterName = urlVars[i].split( '=' );
963
964 if ( parameterName[0] === parameter )
965 return typeof parameterName[1] === undefined ? true : decodeURIComponent( parameterName[1] );
966 }
967
968 return false;
969 };
970
971 } )( jQuery );
...\ No newline at end of file ...\ No newline at end of file
1 ( function( $ ) {
2
3 // ready event
4 $( function() {
5 // initialize color picker
6 $( '.cn_color' ).wpColorPicker();
7
8 // purge cache
9 $( '#cn_app_purge_cache a' ).on( 'click', function( e ) {
10 e.preventDefault();
11
12 var el = this;
13
14 $( el ).parent().addClass( 'loading' ).append( '<span class="spinner is-active" style="float: none"></span>' );
15
16 var ajaxArgs = {
17 action: 'cn_purge_cache',
18 nonce: cnArgs.nonce
19 };
20
21 // network area?
22 if ( cnArgs.network )
23 ajaxArgs.cn_network = 1;
24
25 $.ajax( {
26 url: cnArgs.ajaxURL,
27 type: 'POST',
28 dataType: 'json',
29 data: ajaxArgs
30 } ).always( function( result ) {
31 $( el ).parent().find( '.spinner' ).remove();
32 } );
33 } );
34
35 // global override
36 $( 'input[name="cookie_notice_options[global_override]"]' ).on( 'change', function() {
37 $( '.cookie-notice-settings form' ).toggleClass( 'cn-options-disabled' );
38 } );
39
40 // refuse option
41 $( '#cn_refuse_opt' ).on( 'change', function() {
42 if ( $( this ).is( ':checked' ) )
43 $( '#cn_refuse_opt_container' ).slideDown( 'fast' );
44 else
45 $( '#cn_refuse_opt_container' ).slideUp( 'fast' );
46 } );
47
48 // revoke option
49 $( '#cn_revoke_cookies' ).on( 'change', function() {
50 if ( $( this ).is( ':checked' ) )
51 $( '#cn_revoke_opt_container' ).slideDown( 'fast' );
52 else
53 $( '#cn_revoke_opt_container' ).slideUp( 'fast' );
54 } );
55
56 // privacy policy option
57 $( '#cn_see_more' ).on( 'change', function() {
58 if ( $( this ).is( ':checked' ) )
59 $( '#cn_see_more_opt' ).slideDown( 'fast' );
60 else
61 $( '#cn_see_more_opt' ).slideUp( 'fast' );
62 } );
63
64 // on scroll option
65 $( '#cn_on_scroll' ).on( 'change', function() {
66 if ( $( this ).is( ':checked' ) )
67 $( '#cn_on_scroll_offset' ).slideDown( 'fast' );
68 else
69 $( '#cn_on_scroll_offset' ).slideUp( 'fast' );
70 } );
71
72 // conditional display option
73 $( '#cn_conditional_display_opt' ).on( 'change', function() {
74 if ( $( this ).is( ':checked' ) )
75 $( '#cn_conditional_display_opt_container' ).slideDown( 'fast' );
76 else
77 $( '#cn_conditional_display_opt_container' ).slideUp( 'fast' );
78 } );
79
80 // privacy policy link
81 $( '#cn_see_more_link-custom, #cn_see_more_link-page' ).on( 'change', function() {
82 if ( $( '#cn_see_more_link-custom:checked' ).val() === 'custom' ) {
83 $( '#cn_see_more_opt_page' ).slideUp( 'fast', function() {
84 $( '#cn_see_more_opt_link' ).slideDown( 'fast' );
85 } );
86 } else if ( $( '#cn_see_more_link-page:checked' ).val() === 'page' ) {
87 $( '#cn_see_more_opt_link' ).slideUp( 'fast', function() {
88 $( '#cn_see_more_opt_page' ).slideDown( 'fast' );
89 } );
90 }
91 } );
92
93 // script blocking
94 $( '#cn_refuse_code_fields' ).find( 'a' ).on( 'click', function( e ) {
95 e.preventDefault();
96
97 $( '#cn_refuse_code_fields' ).find( 'a' ).removeClass( 'nav-tab-active' );
98 $( '.refuse-code-tab' ).removeClass( 'active' );
99
100 var id = $( this ).attr( 'id' ).replace( '-tab', '' );
101
102 $( '#' + id ).addClass( 'active' );
103 $( this ).addClass( 'nav-tab-active' );
104 } );
105
106 // add new group of rules
107 $( document ).on( 'click', '.add-rule-group', function( e ) {
108 e.preventDefault();
109
110 var html = $( '#rules-group-template' ).html();
111 var group = $( '#rules-groups' );
112 var groups = group.find( '.rules-group' );
113 var groupID = ( groups.length > 0 ? parseInt( groups.last().attr( 'id' ).split( '-' )[2] ) + 1 : 1 );
114
115 html = html.replace( /__GROUP_ID__/g, groupID );
116 html = html.replace( /__RULE_ID__/g, 1 );
117
118 group.append( '<div class="rules-group" id="rules-group-' + groupID + '">' + html + '</div>' );
119 group.find( '.rules-group' ).last().fadeIn( 'fast' );
120 } );
121
122 // remove single rule or group
123 $( document ).on( 'click', '.remove-rule', function( e ) {
124 e.preventDefault();
125
126 var number = $( this ).closest( 'tbody' ).find( 'tr' ).length;
127
128 if ( number === 1 ) {
129 $( this ).closest( '.rules-group' ).fadeOut( 'fast', function() {
130 $( this ).remove();
131 } );
132 } else {
133 $( this ).closest( 'tr' ).fadeOut( 'fast', function() {
134 $( this ).remove();
135 } );
136 }
137 } );
138
139 // handle changing values for specified type of rules
140 $( document ).on( 'change', '.rule-type', function() {
141 var el = $( this );
142 var td = el.closest( 'tr' ).find( 'td.value' );
143 var select = td.find( 'select' );
144 var spinner = td.find( '.spinner' );
145
146 select.hide();
147 spinner.fadeIn( 'fast' ).css( 'visibility', 'visible' );
148
149 $.post( ajaxurl, {
150 action: 'cn-get-group-rules-values',
151 cn_param: el.val(),
152 cn_nonce: cnArgs.nonceConditional
153 } ).done( function( data ) {
154 spinner.hide().css( 'visibility', 'hidden' );
155
156 try {
157 var response = $.parseJSON( data );
158
159 // replace old select options with new ones
160 select.fadeIn( 'fast' ).find( 'option' ).remove().end().append( response.select );
161 } catch( e ) {
162 //
163 }
164 } ).fail(function() {
165 //
166 } );
167 } );
168 } );
169
170 $( document ).on( 'click', 'input#reset_cookie_notice_options', function() {
171 return confirm( cnArgs.resetToDefaults );
172 } );
173
174 } )( jQuery );
...\ No newline at end of file ...\ No newline at end of file
1 !function(e){e(function(){e(".cn_color").wpColorPicker(),e("#cn_app_purge_cache a").on("click",function(n){n.preventDefault();var o=this;e(o).parent().addClass("loading").append('<span class="spinner is-active" style="float: none"></span>');var t={action:"cn_purge_cache",nonce:cnArgs.nonce};cnArgs.network&&(t.cn_network=1),e.ajax({url:cnArgs.ajaxURL,type:"POST",dataType:"json",data:t}).always(function(n){e(o).parent().find(".spinner").remove()})}),e('input[name="cookie_notice_options[global_override]"]').on("change",function(){e(".cookie-notice-settings form").toggleClass("cn-options-disabled")}),e("#cn_refuse_opt").on("change",function(){e(this).is(":checked")?e("#cn_refuse_opt_container").slideDown("fast"):e("#cn_refuse_opt_container").slideUp("fast")}),e("#cn_revoke_cookies").on("change",function(){e(this).is(":checked")?e("#cn_revoke_opt_container").slideDown("fast"):e("#cn_revoke_opt_container").slideUp("fast")}),e("#cn_see_more").on("change",function(){e(this).is(":checked")?e("#cn_see_more_opt").slideDown("fast"):e("#cn_see_more_opt").slideUp("fast")}),e("#cn_on_scroll").on("change",function(){e(this).is(":checked")?e("#cn_on_scroll_offset").slideDown("fast"):e("#cn_on_scroll_offset").slideUp("fast")}),e("#cn_conditional_display_opt").on("change",function(){e(this).is(":checked")?e("#cn_conditional_display_opt_container").slideDown("fast"):e("#cn_conditional_display_opt_container").slideUp("fast")}),e("#cn_see_more_link-custom, #cn_see_more_link-page").on("change",function(){"custom"===e("#cn_see_more_link-custom:checked").val()?e("#cn_see_more_opt_page").slideUp("fast",function(){e("#cn_see_more_opt_link").slideDown("fast")}):"page"===e("#cn_see_more_link-page:checked").val()&&e("#cn_see_more_opt_link").slideUp("fast",function(){e("#cn_see_more_opt_page").slideDown("fast")})}),e("#cn_refuse_code_fields").find("a").on("click",function(n){n.preventDefault(),e("#cn_refuse_code_fields").find("a").removeClass("nav-tab-active"),e(".refuse-code-tab").removeClass("active");var o=e(this).attr("id").replace("-tab","");e("#"+o).addClass("active"),e(this).addClass("nav-tab-active")}),e(document).on("click",".add-rule-group",function(n){n.preventDefault();var o=e("#rules-group-template").html(),t=e("#rules-groups"),s=t.find(".rules-group"),c=s.length>0?parseInt(s.last().attr("id").split("-")[2])+1:1;o=(o=o.replace(/__GROUP_ID__/g,c)).replace(/__RULE_ID__/g,1),t.append('<div class="rules-group" id="rules-group-'+c+'">'+o+"</div>"),t.find(".rules-group").last().fadeIn("fast")}),e(document).on("click",".remove-rule",function(n){n.preventDefault(),1===e(this).closest("tbody").find("tr").length?e(this).closest(".rules-group").fadeOut("fast",function(){e(this).remove()}):e(this).closest("tr").fadeOut("fast",function(){e(this).remove()})}),e(document).on("change",".rule-type",function(){var n=e(this),o=n.closest("tr").find("td.value"),t=o.find("select"),s=o.find(".spinner");t.hide(),s.fadeIn("fast").css("visibility","visible"),e.post(ajaxurl,{action:"cn-get-group-rules-values",cn_param:n.val(),cn_nonce:cnArgs.nonceConditional}).done(function(n){s.hide().css("visibility","hidden");try{var o=e.parseJSON(n);t.fadeIn("fast").find("option").remove().end().append(o.select)}catch(c){}}).fail(function(){})})}),e(document).on("click","input#reset_cookie_notice_options",function(){return confirm(cnArgs.resetToDefaults)})}(jQuery);
...\ No newline at end of file ...\ No newline at end of file
1 ( function( $ ) {
2
3 // ready event
4 $( function() {
5 var cnHiddenElements = {};
6
7 // listen for the load
8 document.addEventListener( 'load.hu', function( e ) {
9 // set widget text strings
10 hu.setTexts( cnFrontWelcome.textStrings );
11 } );
12
13 // listen for the reload
14 document.addEventListener( 'reload.hu', function( e ) {
15 var container = $( '#hu' );
16 var customOptions = { config: {
17 dontSellLink: true,
18 privacyPolicyLink: true,
19 privacyPaper: true,
20 privacyContact: true
21 } };
22
23 // set widget options
24 hu.setOptions( customOptions );
25 } );
26
27 // listen for the display
28 document.addEventListener( 'display.hu', function( e ) {
29 var val = [];
30 var container = $( '#hu' );
31 var customOptions = { config: {
32 // make it empty
33 } };
34
35 $( parent.document ).find( 'input[name="cn_laws"]:checked' ).each( function() {
36 val.push( $( this ).val() );
37 } );
38
39 // hide paper and contact
40 if ( $( parent.document ).find( 'input[name="cn_privacy_paper"]' ).prop( 'checked' ) === true )
41 $( container ).find( '#hu-cookies-paper' ).show();
42 else
43 $( container ).find( '#hu-cookies-paper' ).hide();
44
45 if ( $( parent.document ).find( 'input[name="cn_privacy_contact"]' ).prop( 'checked' ) === true )
46 $( container ).find( '#hu-cookies-contact' ).show();
47 else
48 $( container ).find( '#hu-cookies-contact' ).hide();
49
50 if ( $.inArray( 'ccpa', val ) !== -1 ) {
51 var htmlElement = $( $( container ).find( '#hu-cookies-notice-dontsell-btn' ) );
52
53 if ( htmlElement.length === 0 ) {
54 $( '#hu-policy-links' ).append( cnHiddenElements.ccpa );
55
56 delete cnHiddenElements.ccpa;
57 }
58
59 $.extend( customOptions.config, { dontSellLink: true } );
60 } else {
61 var htmlElement = $( $( container ).find( '#hu-cookies-notice-dontsell-btn' ) );
62
63 // add to hidden elements
64 if ( htmlElement ) {
65 cnHiddenElements['ccpa'] = htmlElement;
66
67 // remove el
68 $( htmlElement ).remove();
69 }
70
71 $.extend( customOptions.config, { dontSellLink: false } );
72 }
73
74 if ( $.inArray( 'gdpr', val ) !== -1 ) {
75 var htmlElement = $( $( container ).find( '#hu-cookies-notice-privacy-btn' ) );
76
77 if ( htmlElement.length === 0 ) {
78 $( '#hu-policy-links' ).prepend( cnHiddenElements.gdpr );
79
80 delete cnHiddenElements.gdpr;
81 }
82
83 $.extend( customOptions.config, { privacyPolicyLink: true } );
84 } else {
85 var htmlElement = $( $( container ).find( '#hu-cookies-notice-privacy-btn' ) );
86
87 // add to hidden elements
88 if ( htmlElement ) {
89 cnHiddenElements['gdpr'] = htmlElement;
90
91 // remove el
92 $( htmlElement ).remove();
93 }
94
95 $.extend( customOptions.config, { privacyPolicyLink: false } );
96 }
97
98 // set widget options
99 hu.setOptions( customOptions );
100 } );
101
102 // listen for the parent
103 window.addEventListener( 'message', function( event ) {
104 var iframe = $( parent.document ).find( '#cn_iframe_id' );
105 var form = $( parent.document ).find( '#cn-form-configure' );
106
107 // add spinner
108 $( iframe ).closest( '.has-loader' ).addClass( 'cn-loading' ).append( '<span class="cn-spinner"></span>' );
109
110 // lock options
111 $( form ).addClass( 'cn-form-disabled' );
112
113 // emit loader
114 window.setTimeout( function() {
115 if ( typeof event.data == 'object' ) {
116 var container = $( '#hu' );
117 var option = event.data.call;
118 var customOptions = {};
119 var customTexts = {};
120
121 switch ( option ) {
122 case 'position':
123 $( container ).removeClass( 'hu-position-bottom hu-position-top hu-position-left hu-position-right hu-position-center' );
124 $( container ).addClass( 'hu-position-' + event.data.value );
125
126 customOptions = { design: { position: event.data.value } }
127 break;
128
129 case 'naming':
130 var level1 = $( '.hu-cookies-notice-consent-choices-1' );
131 var level2 = $( '.hu-cookies-notice-consent-choices-2' );
132 var level3 = $( '.hu-cookies-notice-consent-choices-3' );
133 var text1 = cnFrontWelcome.levelNames[event.data.value][1];
134 var text2 = cnFrontWelcome.levelNames[event.data.value][2];
135 var text3 = cnFrontWelcome.levelNames[event.data.value][3];
136
137 // apply text to dom elements
138 $( level1 ).find( '.hu-toggle-label' ).text( text1 );
139 $( level2 ).find( '.hu-toggle-label' ).text( text2 );
140 $( level3 ).find( '.hu-toggle-label' ).text( text3 );
141
142 // apply text to text strings
143 customTexts = {
144 levelNameText_1: text1,
145 levelNameText_2: text2,
146 levelNameText_3: text3
147 }
148 break;
149
150 case 'laws':
151 customOptions.config = {}
152
153 if ( $.inArray( 'ccpa', event.data.value ) !== -1 ) {
154 var htmlElement = $( container ).find( '#hu-cookies-notice-dontsell-btn' );
155
156 if ( htmlElement.length === 0 ) {
157 $( '#hu-policy-links' ).append( cnHiddenElements.ccpa );
158
159 delete cnHiddenElements.ccpa;
160 }
161
162 $.extend( customOptions.config, { dontSellLink: true } );
163 } else {
164 var htmlElement = $( container ).find( '#hu-cookies-notice-dontsell-btn' );
165
166 // add to hidden elements
167 if ( htmlElement && ! cnHiddenElements.hasOwnProperty( 'ccpa' ) ) {
168 cnHiddenElements['ccpa'] = htmlElement;
169
170 // remove el
171 $( htmlElement ).remove();
172 }
173
174 $.extend( customOptions.config, { dontSellLink: false } );
175 }
176
177 if ( $.inArray( 'gdpr', event.data.value ) !== -1 ) {
178 var htmlElement = $( container ).find( '#hu-cookies-notice-privacy-btn' );
179
180 if ( htmlElement.length === 0 ) {
181 $( '#hu-policy-links' ).prepend( cnHiddenElements.gdpr );
182
183 delete cnHiddenElements.gdpr;
184 }
185
186 $.extend( customOptions.config, { privacyPolicyLink: true } );
187 } else {
188 var htmlElement = $( container ).find( '#hu-cookies-notice-privacy-btn' );
189
190 // add to hidden elements
191 if ( htmlElement && ! cnHiddenElements.hasOwnProperty( 'gdpr' ) ) {
192 cnHiddenElements['gdpr'] = htmlElement;
193
194 // remove el
195 $( htmlElement ).remove();
196 }
197
198 $.extend( customOptions.config, { privacyPolicyLink: false } );
199 }
200
201 break;
202
203 case 'privacy_paper':
204 var value = event.data.value === true;
205 var htmlElement = $( container ).find( '#hu-cookies-paper' );
206
207 if ( value )
208 $( htmlElement ).show();
209 else
210 $( htmlElement ).hide();
211
212 $.extend( customOptions.config, { privacyPaper: value } );
213 break;
214
215 case 'privacy_contact':
216 var value = event.data.value === true;
217 var htmlElement = $( container ).find( '#hu-cookies-contact');
218
219 if ( value )
220 $( htmlElement ).show();
221 else
222 $( htmlElement ).hide();
223
224 $.extend( customOptions.config, { privacyContact: value } );
225 break;
226
227 case 'color_primary':
228 var iframeContents = $( iframe ).contents()[0];
229
230 iframeContents.documentElement.style.setProperty( '--hu-primaryColor', event.data.value );
231 customOptions = { design: { primaryColor: event.data.value } }
232 break;
233
234 case 'color_background':
235 var iframeContents = $( iframe ).contents()[0];
236
237 iframeContents.documentElement.style.setProperty( '--hu-bannerColor', event.data.value );
238 customOptions = { design: { bannerColor: event.data.value } }
239 break;
240
241 case 'color_border':
242 var iframeContents = $( iframe ).contents()[0];
243
244 iframeContents.documentElement.style.setProperty( '--hu-borderColor', event.data.value );
245 customOptions = { design: { borderColor: event.data.value } }
246 break;
247
248 case 'color_text':
249 var iframeContents = $( iframe ).contents()[0];
250
251 iframeContents.documentElement.style.setProperty( '--hu-textColor', event.data.value );
252 customOptions = { design: { textColor: event.data.value } }
253 break;
254
255 case 'color_heading':
256 var iframeContents = $( iframe ).contents()[0];
257
258 iframeContents.documentElement.style.setProperty( '--hu-headingColor', event.data.value );
259 customOptions = { design: { headingColor: event.data.value } }
260 break;
261
262 case 'color_button_text':
263 var iframeContents = $( iframe ).contents()[0];
264
265 iframeContents.documentElement.style.setProperty( '--hu-btnTextColor', event.data.value );
266 customOptions = { design: { btnTextColor: event.data.value } }
267 break;
268 }
269
270 // set widget options
271 hu.setOptions( customOptions );
272
273 // set widget texts
274 hu.setTexts( customTexts );
275 }
276
277 // remove spinner
278 $( iframe ).closest( '.has-loader' ).find( '.cn-spinner' ).remove();
279 $( iframe ).closest( '.has-loader' ).removeClass( 'cn-loading' );
280
281 // unlock options
282 $( form ).removeClass( 'cn-form-disabled' );
283 }, 500 );
284 }, false );
285
286 // is it iframe?
287 if ( document !== parent.document && typeof cnFrontWelcome !== 'undefined' && cnFrontWelcome.previewMode ) {
288 var iframe = $( parent.document ).find( '#cn_iframe_id' );
289
290 // inject links into initial document
291 $( document.body ).find( 'a[href], area[href]' ).each( function() {
292 cnAddPreviewModeToLink( this, iframe );
293 } );
294
295 // inject links into initial document
296 $( document.body ).find( 'form' ).each( function() {
297 cnAddPreviewModeToForm( this, iframe );
298 } );
299
300 // inject links for new elements added to the page
301 if ( typeof MutationObserver !== 'undefined' ) {
302 var observer = new MutationObserver( function( mutations ) {
303 _.each( mutations, function( mutation ) {
304 $( mutation.target ).find( 'a[href], area[href]' ).each( function() {
305 cnAddPreviewModeToLink( this, iframe );
306 } );
307
308 $( mutation.target ).find( 'form' ).each( function() {
309 cnAddPreviewModeToForm( this, iframe );
310 } );
311 } );
312 } );
313
314 observer.observe( document.documentElement, {
315 childList: true,
316 subtree: true
317 } );
318 } else {
319 // If mutation observers aren't available, fallback to just-in-time injection.
320 $( document.documentElement ).on( 'click focus mouseover', 'a[href], area[href]', function() {
321 cnAddPreviewModeToLink( this, iframe );
322 } );
323 }
324
325 // remove spinner
326 $( iframe ).closest( '.has-loader' ).find( '.cn-spinner' ).remove();
327 $( iframe ).closest( '.has-loader' ).removeClass( 'cn-loading' );
328 }
329 } );
330
331 /**
332 * Inject preview mode parameter into specific links on the frontend.
333 */
334 function cnAddPreviewModeToLink( element, iframe ) {
335 var params, $element = $( element );
336
337 // skip elements with no href attribute
338 if ( ! element.hasAttribute( 'href' ) )
339 return;
340
341 // skip links in admin bar
342 if ( $element.closest( '#wpadminbar' ).length )
343 return;
344
345 // ignore links with href="#", href="#id", or non-HTTP protocols (e.g. javascript: and mailto:)
346 if ( '#' === $element.attr( 'href' ).substr( 0, 1 ) || ! /^https?:$/.test( element.protocol ) )
347 return;
348
349 // make sure links in preview use HTTPS if parent frame uses HTTPS.
350 // if ( api.settings.channel && 'https' === api.preview.scheme.get() && 'http:' === element.protocol && -1 !== api.settings.url.allowedHosts.indexOf( element.host ) )
351 // element.protocol = 'https:';
352
353 // ignore links with special class
354 if ( $element.hasClass( 'wp-playlist-caption' ) )
355 return;
356
357 // check special links
358 if ( ! cnIsLinkPreviewable( element ) )
359 return;
360
361 $( element ).on( 'click', function() {
362 $( iframe ).closest( '.has-loader' ).addClass( 'cn-loading' );
363 } );
364
365 // parse query string
366 params = cnParseQueryString( element.search.substring( 1 ) );
367
368 // set preview mode
369 params.cn_preview_mode = 1;
370
371 element.search = $.param( params );
372 }
373
374 /**
375 * Inject preview mode parameter into specific forms on the frontend.
376 */
377 function cnAddPreviewModeToForm( element, iframe ) {
378 var input = document.createElement( 'input' );
379
380 input.setAttribute( 'type', 'hidden' );
381 input.setAttribute( 'name', 'cn_preview_mode' );
382 input.setAttribute( 'value', 1 );
383
384 element.appendChild( input );
385 }
386
387 /**
388 * Parse query string.
389 */
390 function cnParseQueryString( string ) {
391 var params = {};
392
393 _.each( string.split( '&' ), function( pair ) {
394 var parts, key, value;
395
396 parts = pair.split( '=', 2 );
397
398 if ( ! parts[0] )
399 return;
400
401 key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) );
402 key = key.replace( / /g, '_' );
403
404 if ( _.isUndefined( parts[1] ) )
405 value = null;
406 else
407 value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) );
408
409 params[ key ] = value;
410 } );
411
412 return params;
413 }
414
415 /**
416 * Whether the supplied link is previewable.
417 */
418 function cnIsLinkPreviewable( element ) {
419 var matchesAllowedUrl, parsedAllowedUrl, elementHost;
420
421 if ( 'javascript:' === element.protocol )
422 return true;
423
424 // only web urls can be previewed
425 if ( element.protocol !== 'https:' && element.protocol !== 'http:' )
426 return false;
427
428 elementHost = element.host.replace( /:(80|443)$/, '' );
429 parsedAllowedUrl = document.createElement( 'a' );
430 matchesAllowedUrl = ! _.isUndefined( _.find( cnFrontWelcome.allowedURLs, function( allowedUrl ) {
431 parsedAllowedUrl.href = allowedUrl;
432
433 return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host.replace( /:(80|443)$/, '' ) === elementHost && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) );
434 } ) );
435
436 if ( ! matchesAllowedUrl )
437 return false;
438
439 // skip wp login and signup pages
440 if ( /\/wp-(login|signup)\.php$/.test( element.pathname ) )
441 return false;
442
443 // allow links to admin ajax as faux frontend URLs
444 if ( /\/wp-admin\/admin-ajax\.php$/.test( element.pathname ) )
445 return false;
446
447 // disallow links to admin, includes, and content
448 if ( /\/wp-(admin|includes|content)(\/|$)/.test( element.pathname ) )
449 return false;
450
451 return true;
452 };
453
454 } )( jQuery );
...\ No newline at end of file ...\ No newline at end of file
1 // CustomEvent polyfil for IE support
2 ( function() {
3
4 if ( typeof window.CustomEvent === "function" )
5 return false;
6
7 function CustomEvent( event, params ) {
8 params = params || { bubbles: false, cancelable: false, detail: undefined };
9
10 var evt = document.createEvent( 'CustomEvent' );
11
12 evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
13
14 return evt;
15 }
16
17 CustomEvent.prototype = window.Event.prototype;
18
19 window.CustomEvent = CustomEvent;
20 } )();
21
22 // ClassList polyfil for IE/Safari support
23 ( function() {
24 var regExp = function ( name ) {
25 return new RegExp( '(^| )' + name + '( |$)' );
26 };
27
28 var forEach = function ( list, fn, scope ) {
29 for ( var i = 0; i < list.length; i++ ) {
30 fn.call( scope, list[i] );
31 }
32 };
33
34 function ClassList( element ) {
35 this.element = element;
36 }
37
38 ClassList.prototype = {
39 add: function() {
40 forEach( arguments, function ( name ) {
41 if ( !this.contains( name ) ) {
42 this.element.className += this.element.className.length > 0 ? ' ' + name : name;
43 }
44 }, this );
45 },
46 remove: function() {
47 forEach( arguments, function ( name ) {
48 this.element.className =
49 this.element.className.replace( regExp( name ), '' );
50 }, this );
51 },
52 toggle: function ( name ) {
53 return this.contains( name )
54 ? ( this.remove( name ), false ) : ( this.add( name ), true );
55 },
56 contains: function ( name ) {
57 return regExp( name ).test( this.element.className );
58 },
59 // bonus..
60 replace: function ( oldName, newName ) {
61 this.remove( oldName ), this.add( newName );
62 }
63 };
64
65 // IE8/9, Safari
66 if ( !( 'classList' in Element.prototype ) ) {
67 Object.defineProperty( Element.prototype, 'classList', {
68 get: function() {
69 return new ClassList( this );
70 }
71 } );
72 }
73
74 if ( window.DOMTokenList && DOMTokenList.prototype.replace == null )
75 DOMTokenList.prototype.replace = ClassList.prototype.replace;
76 } )();
77
78 // cookieNotice
79 ( function ( window, document, undefined ) {
80
81 var cookieNotice = new function() {
82 // cookie status
83 this.cookiesAccepted = null;
84
85 // notice container
86 this.noticeContainer = null;
87
88 // set cookie value
89 this.setStatus = function ( cookieValue ) {
90 var _this = this;
91 var cookieDomain = '';
92 var cookiePath = '';
93 var date = new Date();
94 var laterDate = new Date();
95
96 // remove listening to scroll event
97 if ( cnArgs.onScroll )
98 window.removeEventListener( 'scroll', this.handleScroll );
99
100 // set cookie type and expiry time in seconds
101 if ( cookieValue === 'accept' ) {
102 cookieValue = 'true';
103 laterDate.setTime( parseInt( date.getTime() ) + parseInt( cnArgs.cookieTime ) * 1000 );
104 } else {
105 cookieValue = 'false';
106 laterDate.setTime( parseInt( date.getTime() ) + parseInt( cnArgs.cookieTimeRejected ) * 1000 );
107 }
108
109 if ( cnArgs.globalCookie )
110 cookieDomain = this.getDomain( document.location.hostname );
111
112 // get domain path in localhost
113 if ( document.location.hostname === 'localhost' )
114 cookiePath = document.location.pathname.split( '/' )[1];
115
116 var secureValue = '';
117
118 if ( document.location.protocol === 'https:' )
119 secureValue = ';secure';
120
121 // set cookie
122 document.cookie = cnArgs.cookieName + '=' + cookieValue + ';expires=' + laterDate.toUTCString() + ';path=/' + cookiePath + ';domain=' + cookieDomain + secureValue;
123
124 // update global status
125 this.cookiesAccepted = cookieValue === 'true';
126
127 // trigger custom event
128 var event = new CustomEvent(
129 'setCookieNotice',
130 {
131 detail: {
132 value: cookieValue,
133 time: date,
134 expires: laterDate,
135 data: cnArgs
136 }
137 }
138 );
139
140 document.dispatchEvent( event );
141
142 this.setBodyClass( [ 'cookies-set', cookieValue === 'true' ? 'cookies-accepted' : 'cookies-refused' ] );
143
144 this.hideCookieNotice();
145
146 // show revoke notice if enabled
147 if ( cnArgs.revokeCookiesOpt === 'automatic' ) {
148 // show cookie notice after the revoke is hidden
149 this.noticeContainer.addEventListener( 'animationend', function handler() {
150 _this.noticeContainer.removeEventListener( 'animationend', handler );
151 _this.showRevokeNotice();
152 } );
153 this.noticeContainer.addEventListener( 'webkitAnimationEnd', function handler() {
154 _this.noticeContainer.removeEventListener( 'webkitAnimationEnd', handler );
155 _this.showRevokeNotice();
156 } );
157 }
158
159 // redirect?
160 if ( cnArgs.redirection && ( ( cookieValue === 'true' && this.cookiesAccepted === null ) || ( cookieValue !== this.cookiesAccepted && this.cookiesAccepted !== null ) ) ) {
161 var url = window.location.protocol + '//',
162 hostname = window.location.host + '/' + window.location.pathname;
163
164 // is cache enabled?
165 if ( cnArgs.cache ) {
166 url = url + hostname.replace( '//', '/' ) + ( window.location.search === '' ? '?' : window.location.search + '&' ) + 'cn-reloaded=1' + window.location.hash;
167
168 window.location.href = url;
169 } else {
170 url = url + hostname.replace( '//', '/' ) + window.location.search + window.location.hash;
171
172 window.location.reload( true );
173 }
174
175 return;
176 }
177 };
178
179 // get domain
180 this.getDomain = function( url ) {
181 var regex = new RegExp( /https?:\/\// );
182
183 if ( ! regex.test( url ) )
184 url = 'http://' + url;
185
186 var parts = new URL( url ).hostname.split( '.' );
187
188 return parts.slice( 0 ).slice( -( parts.length === 4 ? 3 : 2 ) ).join( '.' );
189 }
190
191 // get cookie value
192 this.getStatus = function ( bool ) {
193 var value = "; " + document.cookie,
194 parts = value.split( '; cookie_notice_accepted=' );
195
196 if ( parts.length === 2 ) {
197 var val = parts.pop().split( ';' ).shift();
198
199 if ( bool )
200 return val === 'true';
201 else
202 return val;
203 } else
204 return null;
205 };
206
207 // display cookie notice
208 this.showCookieNotice = function() {
209 var _this = this;
210
211 // trigger custom event
212 var event = new CustomEvent(
213 'showCookieNotice',
214 {
215 detail: {
216 data: cnArgs
217 }
218 }
219 );
220
221 document.dispatchEvent( event );
222
223 this.noticeContainer.classList.remove( 'cookie-notice-hidden' );
224 this.noticeContainer.classList.add( 'cn-animated' );
225 this.noticeContainer.classList.add( 'cookie-notice-visible' );
226
227 // detect animation
228 this.noticeContainer.addEventListener( 'animationend', function handler() {
229 _this.noticeContainer.removeEventListener( 'animationend', handler );
230 _this.noticeContainer.classList.remove( 'cn-animated' );
231 } );
232 this.noticeContainer.addEventListener( 'webkitAnimationEnd', function handler() {
233 _this.noticeContainer.removeEventListener( 'webkitAnimationEnd', handler );
234 _this.noticeContainer.classList.remove( 'cn-animated' );
235 } );
236 };
237
238 // hide cookie notice
239 this.hideCookieNotice = function() {
240 var _this = this;
241
242 // trigger custom event
243 var event = new CustomEvent(
244 'hideCookieNotice',
245 {
246 detail: {
247 data: cnArgs
248 }
249 }
250 );
251
252 document.dispatchEvent( event );
253
254 this.noticeContainer.classList.add( 'cn-animated' );
255 this.noticeContainer.classList.remove( 'cookie-notice-visible' );
256
257 // detect animation
258 this.noticeContainer.addEventListener( 'animationend', function handler() {
259 _this.noticeContainer.removeEventListener( 'animationend', handler );
260 _this.noticeContainer.classList.remove( 'cn-animated' );
261 _this.noticeContainer.classList.add( 'cookie-notice-hidden' );
262 } );
263 this.noticeContainer.addEventListener( 'webkitAnimationEnd', function handler() {
264 _this.noticeContainer.removeEventListener( 'webkitAnimationEnd', handler );
265 _this.noticeContainer.classList.remove( 'cn-animated' );
266 _this.noticeContainer.classList.add( 'cookie-notice-hidden' );
267 } );
268 };
269
270 // display revoke notice
271 this.showRevokeNotice = function() {
272 var _this = this;
273
274 // trigger custom event
275 var event = new CustomEvent(
276 'showRevokeNotice',
277 {
278 detail: {
279 data: cnArgs
280 }
281 }
282 );
283
284 document.dispatchEvent( event );
285
286 this.noticeContainer.classList.remove( 'cookie-revoke-hidden' );
287 this.noticeContainer.classList.add( 'cn-animated' );
288 this.noticeContainer.classList.add( 'cookie-revoke-visible' );
289
290 // detect animation
291 this.noticeContainer.addEventListener( 'animationend', function handler() {
292 _this.noticeContainer.removeEventListener( 'animationend', handler );
293 _this.noticeContainer.classList.remove( 'cn-animated' );
294 } );
295 this.noticeContainer.addEventListener( 'webkitAnimationEnd', function handler() {
296 _this.noticeContainer.removeEventListener( 'webkitAnimationEnd', handler );
297 _this.noticeContainer.classList.remove( 'cn-animated' );
298 } );
299 };
300
301 // hide revoke notice
302 this.hideRevokeNotice = function() {
303 var _this = this;
304
305 // trigger custom event
306 var event = new CustomEvent(
307 'hideRevokeNotice',
308 {
309 detail: {
310 data: cnArgs
311 }
312 }
313 );
314
315 document.dispatchEvent( event );
316
317 this.noticeContainer.classList.add( 'cn-animated' );
318 this.noticeContainer.classList.remove( 'cookie-revoke-visible' );
319
320 // detect animation
321 this.noticeContainer.addEventListener( 'animationend', function handler() {
322 _this.noticeContainer.removeEventListener( 'animationend', handler );
323 _this.noticeContainer.classList.remove( 'cn-animated' );
324 _this.noticeContainer.classList.add( 'cookie-revoke-hidden' );
325 } );
326 this.noticeContainer.addEventListener( 'webkitAnimationEnd', function handler() {
327 _this.noticeContainer.removeEventListener( 'webkitAnimationEnd', handler );
328 _this.noticeContainer.classList.remove( 'cn-animated' );
329 _this.noticeContainer.classList.add( 'cookie-revoke-hidden' );
330 } );
331 };
332
333 // change body classes
334 this.setBodyClass = function ( classes ) {
335 // remove body classes
336 document.body.classList.remove( 'cookies-revoke' );
337 document.body.classList.remove( 'cookies-accepted' );
338 document.body.classList.remove( 'cookies-refused' );
339 document.body.classList.remove( 'cookies-set' );
340 document.body.classList.remove( 'cookies-not-set' );
341
342 // add body classes
343 for ( var i = 0; i < classes.length; i++ ) {
344 document.body.classList.add( classes[i] );
345 }
346 };
347
348 // handle mouse scrolling
349 this.handleScroll = function() {
350 var scrollTop = window.pageYOffset || ( document.documentElement || document.body.parentNode || document.body ).scrollTop
351
352 // accept cookie
353 if ( scrollTop > parseInt( cnArgs.onScrollOffset ) )
354 this.setStatus( 'accept' );
355 };
356
357 // cross browser compatible closest function
358 this.getClosest = function ( elem, selector ) {
359 // element.matches() polyfill
360 if ( !Element.prototype.matches ) {
361 Element.prototype.matches =
362 Element.prototype.matchesSelector ||
363 Element.prototype.mozMatchesSelector ||
364 Element.prototype.msMatchesSelector ||
365 Element.prototype.oMatchesSelector ||
366 Element.prototype.webkitMatchesSelector ||
367 function ( s ) {
368 var matches = ( this.document || this.ownerDocument ).querySelectorAll( s ),
369 i = matches.length;
370 while ( --i >= 0 && matches.item( i ) !== this ) {
371 }
372 return i > -1;
373 };
374 }
375
376 // get the closest matching element
377 for ( ; elem && elem !== document; elem = elem.parentNode ) {
378 if ( elem.matches( selector ) )
379 return elem;
380 }
381
382 return null;
383 };
384
385 // check if displaye in an iframe
386 this.inIframe = function() {
387 try {
388 return window.self !== window.top;
389 } catch (e) {
390 return true;
391 }
392 }
393
394 // initialize
395 this.init = function() {
396 var _this = this;
397
398 // bail if in iframe
399 if ( this.inIframe() === true )
400 return;
401
402 this.cookiesAccepted = this.getStatus( true );
403 this.noticeContainer = document.getElementById( 'cookie-notice' );
404
405 // no container?
406 if ( ! this.noticeContainer )
407 return;
408
409 var cookieButtons = document.getElementsByClassName( 'cn-set-cookie' ),
410 revokeButtons = document.getElementsByClassName( 'cn-revoke-cookie' ),
411 closeIcon = document.getElementById( 'cn-close-notice' );
412
413 // add effect class
414 this.noticeContainer.classList.add( 'cn-effect-' + cnArgs.hideEffect );
415
416 // check cookies status
417 if ( this.cookiesAccepted === null ) {
418 // handle on scroll
419 if ( cnArgs.onScroll )
420 window.addEventListener( 'scroll', function ( e ) {
421 _this.handleScroll();
422 } );
423
424 // handle on click
425 if ( cnArgs.onClick )
426 window.addEventListener( 'click', function ( e ) {
427 var outerContainer = _this.getClosest( e.target, '#cookie-notice' );
428
429 // accept notice if clicked element is not inside the container
430 if ( outerContainer === null )
431 _this.setStatus( 'accept' );
432 }, true );
433
434 this.setBodyClass( [ 'cookies-not-set' ] );
435
436 // show cookie notice
437 this.showCookieNotice();
438 } else {
439 this.setBodyClass( [ 'cookies-set', this.cookiesAccepted === true ? 'cookies-accepted' : 'cookies-refused' ] );
440
441 // show revoke notice if enabled
442 if ( cnArgs.revokeCookies && cnArgs.revokeCookiesOpt === 'automatic' )
443 this.showRevokeNotice();
444 }
445
446 // handle cookie buttons click
447 for ( var i = 0; i < cookieButtons.length; i++ ) {
448 cookieButtons[i].addEventListener( 'click', function ( e ) {
449 e.preventDefault();
450 // Chrome double click event fix
451 e.stopPropagation();
452
453 _this.setStatus( this.dataset.cookieSet );
454 } );
455 }
456
457 // handle close icon
458 if ( closeIcon !== null ) {
459 closeIcon.addEventListener( 'click', function ( e ) {
460 e.preventDefault();
461 // Chrome double click event fix
462 e.stopPropagation();
463
464 _this.setStatus( 'reject' );
465 } );
466 }
467
468 // handle revoke buttons click
469 for ( var i = 0; i < revokeButtons.length; i++ ) {
470 revokeButtons[i].addEventListener( 'click', function ( e ) {
471 e.preventDefault();
472
473 // hide revoke notice
474 if ( _this.noticeContainer.classList.contains( 'cookie-revoke-visible' ) ) {
475 _this.hideRevokeNotice();
476
477 // show cookie notice after the revoke is hidden
478 _this.noticeContainer.addEventListener( 'animationend', function handler() {
479 _this.noticeContainer.removeEventListener( 'animationend', handler );
480 _this.showCookieNotice();
481 } );
482 _this.noticeContainer.addEventListener( 'webkitAnimationEnd', function handler() {
483 _this.noticeContainer.removeEventListener( 'webkitAnimationEnd', handler );
484 _this.showCookieNotice();
485 } );
486 // show cookie notice
487 } else if ( _this.noticeContainer.classList.contains( 'cookie-notice-hidden' ) && _this.noticeContainer.classList.contains( 'cookie-revoke-hidden' ) )
488 _this.showCookieNotice();
489 } );
490 }
491 };
492 }
493
494 // initialize plugin
495 window.addEventListener( 'load', function() {
496 cookieNotice.init();
497 }, false );
498
499 } )( window, document, undefined );
...\ No newline at end of file ...\ No newline at end of file
1 !function(){if("function"==typeof window.CustomEvent)return!1;function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}e.prototype=window.Event.prototype,window.CustomEvent=e}(),function(){var e=function(e){return RegExp("(^| )"+e+"( |$)")},t=function(e,t,n){for(var i=0;i<e.length;i++)t.call(n,e[i])};function n(e){this.element=e}n.prototype={add:function(){t(arguments,function(e){this.contains(e)||(this.element.className+=this.element.className.length>0?" "+e:e)},this)},remove:function(){t(arguments,function(t){this.element.className=this.element.className.replace(e(t),"")},this)},toggle:function(e){return this.contains(e)?(this.remove(e),!1):(this.add(e),!0)},contains:function(t){return e(t).test(this.element.className)},replace:function(e,t){this.remove(e),this.add(t)}},"classList"in Element.prototype||Object.defineProperty(Element.prototype,"classList",{get:function(){return new n(this)}}),window.DOMTokenList&&null==DOMTokenList.prototype.replace&&(DOMTokenList.prototype.replace=n.prototype.replace)}(),function(e,t,n){var i=new function(){this.cookiesAccepted=null,this.noticeContainer=null,this.setStatus=function(n){var i=this,o="",s="",c=new Date,a=new Date;cnArgs.onScroll&&e.removeEventListener("scroll",this.handleScroll),"accept"===n?(n="true",a.setTime(parseInt(c.getTime())+1e3*parseInt(cnArgs.cookieTime))):(n="false",a.setTime(parseInt(c.getTime())+1e3*parseInt(cnArgs.cookieTimeRejected))),cnArgs.globalCookie&&(o=this.getDomain(t.location.hostname)),"localhost"===t.location.hostname&&(s=t.location.pathname.split("/")[1]);var r="";"https:"===t.location.protocol&&(r=";secure"),t.cookie=cnArgs.cookieName+"="+n+";expires="+a.toUTCString()+";path=/"+s+";domain="+o+r,this.cookiesAccepted="true"===n;var d=new CustomEvent("setCookieNotice",{detail:{value:n,time:c,expires:a,data:cnArgs}});if(t.dispatchEvent(d),this.setBodyClass(["cookies-set","true"===n?"cookies-accepted":"cookies-refused"]),this.hideCookieNotice(),"automatic"===cnArgs.revokeCookiesOpt&&(this.noticeContainer.addEventListener("animationend",function e(){i.noticeContainer.removeEventListener("animationend",e),i.showRevokeNotice()}),this.noticeContainer.addEventListener("webkitAnimationEnd",function e(){i.noticeContainer.removeEventListener("webkitAnimationEnd",e),i.showRevokeNotice()})),cnArgs.redirection&&("true"===n&&null===this.cookiesAccepted||n!==this.cookiesAccepted&&null!==this.cookiesAccepted)){var l=e.location.protocol+"//",h=e.location.host+"/"+e.location.pathname;cnArgs.cache?(l=l+h.replace("//","/")+(""===e.location.search?"?":e.location.search+"&")+"cn-reloaded=1"+e.location.hash,e.location.href=l):(l=l+h.replace("//","/")+e.location.search+e.location.hash,e.location.reload(!0));return}},this.getDomain=function(e){RegExp(/https?:\/\//).test(e)||(e="http://"+e);var t=new URL(e).hostname.split(".");return t.slice(0).slice(-(4===t.length?3:2)).join(".")},this.getStatus=function(e){var n=("; "+t.cookie).split("; cookie_notice_accepted=");if(2!==n.length)return null;var i=n.pop().split(";").shift();return e?"true"===i:i},this.showCookieNotice=function(){var e=this,n=new CustomEvent("showCookieNotice",{detail:{data:cnArgs}});t.dispatchEvent(n),this.noticeContainer.classList.remove("cookie-notice-hidden"),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.add("cookie-notice-visible"),this.noticeContainer.addEventListener("animationend",function t(){e.noticeContainer.removeEventListener("animationend",t),e.noticeContainer.classList.remove("cn-animated")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function t(){e.noticeContainer.removeEventListener("webkitAnimationEnd",t),e.noticeContainer.classList.remove("cn-animated")})},this.hideCookieNotice=function(){var e=this,n=new CustomEvent("hideCookieNotice",{detail:{data:cnArgs}});t.dispatchEvent(n),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.remove("cookie-notice-visible"),this.noticeContainer.addEventListener("animationend",function t(){e.noticeContainer.removeEventListener("animationend",t),e.noticeContainer.classList.remove("cn-animated"),e.noticeContainer.classList.add("cookie-notice-hidden")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function t(){e.noticeContainer.removeEventListener("webkitAnimationEnd",t),e.noticeContainer.classList.remove("cn-animated"),e.noticeContainer.classList.add("cookie-notice-hidden")})},this.showRevokeNotice=function(){var e=this,n=new CustomEvent("showRevokeNotice",{detail:{data:cnArgs}});t.dispatchEvent(n),this.noticeContainer.classList.remove("cookie-revoke-hidden"),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.add("cookie-revoke-visible"),this.noticeContainer.addEventListener("animationend",function t(){e.noticeContainer.removeEventListener("animationend",t),e.noticeContainer.classList.remove("cn-animated")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function t(){e.noticeContainer.removeEventListener("webkitAnimationEnd",t),e.noticeContainer.classList.remove("cn-animated")})},this.hideRevokeNotice=function(){var e=this,n=new CustomEvent("hideRevokeNotice",{detail:{data:cnArgs}});t.dispatchEvent(n),this.noticeContainer.classList.add("cn-animated"),this.noticeContainer.classList.remove("cookie-revoke-visible"),this.noticeContainer.addEventListener("animationend",function t(){e.noticeContainer.removeEventListener("animationend",t),e.noticeContainer.classList.remove("cn-animated"),e.noticeContainer.classList.add("cookie-revoke-hidden")}),this.noticeContainer.addEventListener("webkitAnimationEnd",function t(){e.noticeContainer.removeEventListener("webkitAnimationEnd",t),e.noticeContainer.classList.remove("cn-animated"),e.noticeContainer.classList.add("cookie-revoke-hidden")})},this.setBodyClass=function(e){t.body.classList.remove("cookies-revoke"),t.body.classList.remove("cookies-accepted"),t.body.classList.remove("cookies-refused"),t.body.classList.remove("cookies-set"),t.body.classList.remove("cookies-not-set");for(var n=0;n<e.length;n++)t.body.classList.add(e[n])},this.handleScroll=function(){(e.pageYOffset||(t.documentElement||t.body.parentNode||t.body).scrollTop)>parseInt(cnArgs.onScrollOffset)&&this.setStatus("accept")},this.getClosest=function(e,n){for(Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(e){for(var t=(this.document||this.ownerDocument).querySelectorAll(e),n=t.length;--n>=0&&t.item(n)!==this;);return n>-1});e&&e!==t;e=e.parentNode)if(e.matches(n))return e;return null},this.inIframe=function(){try{return e.self!==e.top}catch(t){return!0}},this.init=function(){var n=this;if(!0!==this.inIframe()&&(this.cookiesAccepted=this.getStatus(!0),this.noticeContainer=t.getElementById("cookie-notice"),this.noticeContainer)){var i=t.getElementsByClassName("cn-set-cookie"),o=t.getElementsByClassName("cn-revoke-cookie"),s=t.getElementById("cn-close-notice");this.noticeContainer.classList.add("cn-effect-"+cnArgs.hideEffect),null===this.cookiesAccepted?(cnArgs.onScroll&&e.addEventListener("scroll",function(e){n.handleScroll()}),cnArgs.onClick&&e.addEventListener("click",function(e){null===n.getClosest(e.target,"#cookie-notice")&&n.setStatus("accept")},!0),this.setBodyClass(["cookies-not-set"]),this.showCookieNotice()):(this.setBodyClass(["cookies-set",!0===this.cookiesAccepted?"cookies-accepted":"cookies-refused"]),cnArgs.revokeCookies&&"automatic"===cnArgs.revokeCookiesOpt&&this.showRevokeNotice());for(var c=0;c<i.length;c++)i[c].addEventListener("click",function(e){e.preventDefault(),e.stopPropagation(),n.setStatus(this.dataset.cookieSet)});null!==s&&s.addEventListener("click",function(e){e.preventDefault(),e.stopPropagation(),n.setStatus("reject")});for(var c=0;c<o.length;c++)o[c].addEventListener("click",function(e){e.preventDefault(),n.noticeContainer.classList.contains("cookie-revoke-visible")?(n.hideRevokeNotice(),n.noticeContainer.addEventListener("animationend",function e(){n.noticeContainer.removeEventListener("animationend",e),n.showCookieNotice()}),n.noticeContainer.addEventListener("webkitAnimationEnd",function e(){n.noticeContainer.removeEventListener("webkitAnimationEnd",e),n.showCookieNotice()})):n.noticeContainer.classList.contains("cookie-notice-hidden")&&n.noticeContainer.classList.contains("cookie-revoke-hidden")&&n.showCookieNotice()})}}};e.addEventListener("load",function(){i.init()},!1)}(window,document,void 0);
...\ No newline at end of file ...\ No newline at end of file
1 #, fuzzy
2 msgid ""
3 msgstr ""
4 "Project-Id-Version: Cookie Notice\n"
5 "POT-Creation-Date: 2023-08-21 13:19+0200\n"
6 "PO-Revision-Date: 2015-03-24 11:30+0100\n"
7 "Last-Translator: Bartosz Arendt <info@dfactory.eu>\n"
8 "Language-Team: dFactory <info@dfactory.eu>\n"
9 "Language: en\n"
10 "MIME-Version: 1.0\n"
11 "Content-Type: text/plain; charset=UTF-8\n"
12 "Content-Transfer-Encoding: 8bit\n"
13 "X-Generator: Poedit 3.3.2\n"
14 "X-Poedit-KeywordsList: gettext;gettext_noop;__;_e;_n;esc_html__;esc_html_e\n"
15 "X-Poedit-Basepath: .\n"
16 "X-Poedit-SourceCharset: UTF-8\n"
17 "X-Poedit-SearchPath-0: ..\n"
18
19 #: ../cookie-notice.php:706
20 msgid "Facebook Tracking Pixel Illegal in EU?"
21 msgstr ""
22
23 #: ../cookie-notice.php:706
24 msgid "The Austrian Data Protection Authority recently declared that the use of Facebook's tracking pixel directly violates the GDPR. This decision could affect many websites in the European Union. To use Facebook Pixel, prior consent from visitors for tracking is required. Click \"Run Compliance Check\" to check if your website compliance with the latest privacy regulations."
25 msgstr ""
26
27 #: ../cookie-notice.php:706 ../includes/dashboard.php:512
28 msgid "Run Compliance Check"
29 msgstr ""
30
31 #: ../cookie-notice.php:706
32 msgid "Dismiss Notice"
33 msgstr ""
34
35 #: ../cookie-notice.php:741
36 msgid "Cookie Compliance Warning"
37 msgstr ""
38
39 #: ../cookie-notice.php:741
40 #, php-format
41 msgid "Your website has reached the <b>%1$s visits usage limit for the Cookie Compliance Free Plan</b>. Compliance services such as Consent Record Storage, Autoblocking, and Consent Analytics have been deactivated until current usage cycle ends on %2$s."
42 msgstr ""
43
44 #: ../cookie-notice.php:741
45 #, php-format
46 msgid "To reactivate compliance services now, <a href=\"%s\" target=\"_blank\">upgrade your domain to a Pro plan.</a>"
47 msgstr ""
48
49 #: ../cookie-notice.php:1055
50 msgid "Cookie Notice & Compliance - Deactivation survey"
51 msgstr ""
52
53 #: ../cookie-notice.php:1119
54 msgid "Settings"
55 msgstr ""
56
57 #: ../cookie-notice.php:1134
58 msgid "Free Upgrade"
59 msgstr ""
60
61 #: ../cookie-notice.php:1160
62 msgid "We're sorry to see you go. Could you please tell us what happened?"
63 msgstr ""
64
65 #: ../cookie-notice.php:1164
66 msgid "I couldn't figure out how to make it work."
67 msgstr ""
68
69 #: ../cookie-notice.php:1165
70 msgid "I found another plugin to use for the same task."
71 msgstr ""
72
73 #: ../cookie-notice.php:1166
74 msgid "The Cookie Compliance banner is too big."
75 msgstr ""
76
77 #: ../cookie-notice.php:1167
78 msgid "The Cookie Compliance consent choices (Silver, Gold, Platinum) are confusing."
79 msgstr ""
80
81 #: ../cookie-notice.php:1168
82 msgid "The Cookie Compliance default settings are too strict."
83 msgstr ""
84
85 #: ../cookie-notice.php:1169
86 msgid "The web application user interface is not clear to me."
87 msgstr ""
88
89 #: ../cookie-notice.php:1170
90 msgid "Support isn't timely."
91 msgstr ""
92
93 #: ../cookie-notice.php:1171
94 msgid "Other"
95 msgstr ""
96
97 #: ../cookie-notice.php:1185
98 msgid "Cancel"
99 msgstr ""
100
101 #: ../cookie-notice.php:1186
102 msgid "Deactivate"
103 msgstr ""
104
105 #: ../cookie-notice.php:1187
106 msgid "Deactivate & Submit"
107 msgstr ""
108
109 #: ../includes/dashboard.php:72
110 msgid "Cookie Compliance"
111 msgstr ""
112
113 #: ../includes/dashboard.php:181 ../includes/dashboard.php:193
114 #: ../includes/dashboard.php:205
115 #, php-format
116 msgid "Level %s"
117 msgstr ""
118
119 #: ../includes/dashboard.php:290
120 msgid "Traffic Overview"
121 msgstr ""
122
123 #: ../includes/dashboard.php:291
124 msgid "Displays the general visits information for your domain."
125 msgstr ""
126
127 #: ../includes/dashboard.php:295
128 msgid "Consent Activity"
129 msgstr ""
130
131 #: ../includes/dashboard.php:296
132 msgid "Displays the chart of the domain consent activity in the last 30 days."
133 msgstr ""
134
135 #: ../includes/dashboard.php:316
136 msgid "View consent activity inside WordPress Dashboard"
137 msgstr ""
138
139 #: ../includes/dashboard.php:317
140 msgid "Display information about the visits."
141 msgstr ""
142
143 #: ../includes/dashboard.php:318
144 msgid "Get Consent logs data for the last 30 days."
145 msgstr ""
146
147 #: ../includes/dashboard.php:319
148 msgid "Enable consent purpose categories, automatic cookie blocking and more."
149 msgstr ""
150
151 #: ../includes/dashboard.php:320
152 msgid "Upgrade to Cookie Compliance"
153 msgstr ""
154
155 #: ../includes/dashboard.php:422
156 msgid "Total Visits"
157 msgstr ""
158
159 #: ../includes/dashboard.php:424
160 msgid "Last 30 days"
161 msgstr ""
162
163 #: ../includes/dashboard.php:427
164 msgid "Consent Logs"
165 msgstr ""
166
167 #: ../includes/dashboard.php:429
168 #, php-format
169 msgid "Updated %s"
170 msgstr ""
171
172 #: ../includes/dashboard.php:446
173 msgid "Traffic Usage"
174 msgstr ""
175
176 #: ../includes/dashboard.php:449
177 #, php-format
178 msgid "Visits usage: %1$s / %2$s"
179 msgstr ""
180
181 #: ../includes/dashboard.php:450
182 #, php-format
183 msgid "Cycle started: %s"
184 msgstr ""
185
186 #: ../includes/dashboard.php:451
187 #, php-format
188 msgid "Days to go: %s"
189 msgstr ""
190
191 #: ../includes/dashboard.php:494
192 msgid "Cookie Compliance Status"
193 msgstr ""
194
195 #: ../includes/dashboard.php:509
196 msgid "Your site does not have Cookie Compliance"
197 msgstr ""
198
199 #: ../includes/dashboard.php:511
200 msgid "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws."
201 msgstr ""
202
203 #: ../includes/dashboard.php:515 ../includes/settings.php:234
204 #: ../includes/welcome.php:420
205 msgid "Cookie Notice"
206 msgstr ""
207
208 #: ../includes/settings.php:71
209 msgid "Page Type"
210 msgstr ""
211
212 #: ../includes/settings.php:72
213 msgid "Page"
214 msgstr ""
215
216 #: ../includes/settings.php:73
217 msgid "Post Type"
218 msgstr ""
219
220 #: ../includes/settings.php:74
221 msgid "Post Type Archive"
222 msgstr ""
223
224 #: ../includes/settings.php:75
225 msgid "User Type"
226 msgstr ""
227
228 #: ../includes/settings.php:79
229 msgid "is equal to"
230 msgstr ""
231
232 #: ../includes/settings.php:80
233 msgid "is not equal to"
234 msgstr ""
235
236 #: ../includes/settings.php:84
237 msgid "Hide the banner"
238 msgstr ""
239
240 #: ../includes/settings.php:85
241 msgid "Show the banner"
242 msgstr ""
243
244 #: ../includes/settings.php:89
245 msgid "Top"
246 msgstr ""
247
248 #: ../includes/settings.php:90
249 msgid "Bottom"
250 msgstr ""
251
252 #: ../includes/settings.php:94 ../includes/settings.php:137
253 msgid "None"
254 msgstr ""
255
256 #: ../includes/settings.php:95
257 msgid "Light"
258 msgstr ""
259
260 #: ../includes/settings.php:96
261 msgid "Dark"
262 msgstr ""
263
264 #: ../includes/settings.php:100
265 msgid "Automatic"
266 msgstr ""
267
268 #: ../includes/settings.php:101
269 msgid "Manual"
270 msgstr ""
271
272 #: ../includes/settings.php:105
273 msgid "Page link"
274 msgstr ""
275
276 #: ../includes/settings.php:106
277 msgid "Custom link"
278 msgstr ""
279
280 #: ../includes/settings.php:112
281 msgid "Banner"
282 msgstr ""
283
284 #: ../includes/settings.php:113 ../includes/settings.php:464
285 msgid "Message"
286 msgstr ""
287
288 #: ../includes/settings.php:117
289 msgid "Text color"
290 msgstr ""
291
292 #: ../includes/settings.php:118
293 msgid "Button color"
294 msgstr ""
295
296 #: ../includes/settings.php:119
297 msgid "Bar color"
298 msgstr ""
299
300 #: ../includes/settings.php:125
301 msgid "An hour"
302 msgstr ""
303
304 #: ../includes/settings.php:126
305 msgid "1 day"
306 msgstr ""
307
308 #: ../includes/settings.php:127
309 msgid "1 week"
310 msgstr ""
311
312 #: ../includes/settings.php:128
313 msgid "1 month"
314 msgstr ""
315
316 #: ../includes/settings.php:129
317 msgid "3 months"
318 msgstr ""
319
320 #: ../includes/settings.php:130
321 msgid "6 months"
322 msgstr ""
323
324 #: ../includes/settings.php:131
325 msgid "1 year"
326 msgstr ""
327
328 #: ../includes/settings.php:132
329 msgid "infinity"
330 msgstr ""
331
332 #: ../includes/settings.php:138
333 msgid "Fade"
334 msgstr ""
335
336 #: ../includes/settings.php:139
337 msgid "Slide"
338 msgstr ""
339
340 #: ../includes/settings.php:143
341 msgid "Header"
342 msgstr ""
343
344 #: ../includes/settings.php:144
345 msgid "Footer"
346 msgstr ""
347
348 #: ../includes/settings.php:149
349 msgid "Silver"
350 msgstr ""
351
352 #: ../includes/settings.php:150
353 msgid "Gold"
354 msgstr ""
355
356 #: ../includes/settings.php:151
357 msgid "Platinum"
358 msgstr ""
359
360 #: ../includes/settings.php:154
361 msgid "Private"
362 msgstr ""
363
364 #: ../includes/settings.php:155
365 msgid "Balanced"
366 msgstr ""
367
368 #: ../includes/settings.php:156
369 msgid "Personalized"
370 msgstr ""
371
372 #: ../includes/settings.php:159
373 msgid "Reject All"
374 msgstr ""
375
376 #: ../includes/settings.php:160
377 msgid "Accept Some"
378 msgstr ""
379
380 #: ../includes/settings.php:161
381 msgid "Accept All"
382 msgstr ""
383
384 #: ../includes/settings.php:166
385 msgid "Save my preferences"
386 msgstr ""
387
388 #: ../includes/settings.php:167 ../includes/settings.php:191
389 #: ../includes/settings.php:466
390 msgid "Privacy policy"
391 msgstr ""
392
393 #: ../includes/settings.php:168
394 msgid "Do Not Sell"
395 msgstr ""
396
397 #: ../includes/settings.php:169
398 msgid "Preferences"
399 msgstr ""
400
401 #: ../includes/settings.php:170
402 msgid "We believe your data is your property and support your right to privacy and transparency."
403 msgstr ""
404
405 #: ../includes/settings.php:171
406 msgid "Select a Data Access Level and Duration to choose how we use and share your data."
407 msgstr ""
408
409 #: ../includes/settings.php:172
410 msgid "Highest level of privacy. Data accessed for necessary site operations only. Data shared with 3rd parties to ensure the site is secure and works on your device."
411 msgstr ""
412
413 #: ../includes/settings.php:173
414 msgid "Balanced experience. Data accessed for content personalisation and site optimisation. Data shared with 3rd parties may be used to track and store your preferences for this site."
415 msgstr ""
416
417 #: ../includes/settings.php:174
418 msgid "Highest level of personalisation. Data accessed to make ads and media more relevant. Data shared with 3rd parties may be use to track you on this site and other sites you visit."
419 msgstr ""
420
421 #: ../includes/settings.php:178
422 msgid "month"
423 msgstr ""
424
425 #: ../includes/settings.php:179
426 msgid "months"
427 msgstr ""
428
429 #: ../includes/settings.php:186
430 msgid "We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it."
431 msgstr ""
432
433 #: ../includes/settings.php:187
434 msgid "Ok"
435 msgstr ""
436
437 #: ../includes/settings.php:188
438 msgid "No"
439 msgstr ""
440
441 #: ../includes/settings.php:189
442 msgid "You can revoke your consent any time using the Revoke consent button."
443 msgstr ""
444
445 #: ../includes/settings.php:190 ../includes/settings.php:468
446 msgid "Revoke consent"
447 msgstr ""
448
449 #: ../includes/settings.php:234
450 msgid "Cookies"
451 msgstr ""
452
453 #: ../includes/settings.php:253
454 msgid "Cookie Notice & Compliance for GDPR/CCPA"
455 msgstr ""
456
457 #: ../includes/settings.php:265
458 msgid "Your Cookie Compliance plan:"
459 msgstr ""
460
461 #: ../includes/settings.php:266 ../includes/welcome.php:332
462 msgid "Professional"
463 msgstr ""
464
465 #: ../includes/settings.php:266 ../includes/welcome.php:310
466 #: ../includes/welcome.php:590 ../includes/welcome.php:688
467 msgid "Basic"
468 msgstr ""
469
470 #: ../includes/settings.php:269 ../includes/welcome.php:314
471 #: ../includes/welcome.php:345
472 msgid "GDPR, CCPA, LGPD, PECR requirements"
473 msgstr ""
474
475 #: ../includes/settings.php:270 ../includes/welcome.php:315
476 #: ../includes/welcome.php:346
477 msgid "Consent Analytics Dashboard"
478 msgstr ""
479
480 #: ../includes/settings.php:271 ../includes/welcome.php:347
481 #, php-format
482 msgid "%sUnlimited%s visits"
483 msgstr ""
484
485 #: ../includes/settings.php:272 ../includes/welcome.php:348
486 #, php-format
487 msgid "%sLifetime%s consent storage"
488 msgstr ""
489
490 #: ../includes/settings.php:273 ../includes/welcome.php:318
491 #: ../includes/welcome.php:349
492 #, php-format
493 msgid "%sGoogle & Facebook%s consent modes"
494 msgstr ""
495
496 #: ../includes/settings.php:274 ../includes/welcome.php:319
497 #: ../includes/welcome.php:350
498 #, php-format
499 msgid "%sGeolocation%s support"
500 msgstr ""
501
502 #: ../includes/settings.php:275 ../includes/welcome.php:351
503 #, php-format
504 msgid "%sUnlimited%s languages"
505 msgstr ""
506
507 #: ../includes/settings.php:276 ../includes/welcome.php:352
508 #, php-format
509 msgid "%sPriority%s Support"
510 msgstr ""
511
512 #: ../includes/settings.php:281
513 msgid "Upgrade to Pro"
514 msgstr ""
515
516 #: ../includes/settings.php:288
517 msgid "Protect your business"
518 msgstr ""
519
520 #: ../includes/settings.php:289
521 msgid "with Cookie Compliance&trade;"
522 msgstr ""
523
524 #: ../includes/settings.php:291
525 msgid "Deliver better consent experiences and comply with GDPR, CCPA and other data privacy laws more effectively."
526 msgstr ""
527
528 #: ../includes/settings.php:293
529 msgid "Cookie Compliance dashboard"
530 msgstr ""
531
532 #: ../includes/settings.php:294
533 msgid "Learn more"
534 msgstr ""
535
536 #: ../includes/settings.php:304
537 msgid "F.A.Q."
538 msgstr ""
539
540 #: ../includes/settings.php:308
541 msgid "Does the Cookie Notice make my site fully compliant with GDPR?"
542 msgstr ""
543
544 #: ../includes/settings.php:309
545 msgid "It is not possible to provide the required technical compliance features using only a WordPress plugin. Features like consent record storage, purpose categories and script blocking that bring your site into full compliance with GDPR are only available through the Cookie Compliance integration."
546 msgstr ""
547
548 #: ../includes/settings.php:313
549 msgid "Does the Cookie Compliance integration make my site fully compliant with GDPR?"
550 msgstr ""
551
552 #: ../includes/settings.php:314
553 msgid "Yes! The plugin + web application version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions."
554 msgstr ""
555
556 #: ../includes/settings.php:318
557 msgid "Is Cookie Compliance free?"
558 msgstr ""
559
560 #: ../includes/settings.php:319
561 msgid "Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website monthly traffic."
562 msgstr ""
563
564 #: ../includes/settings.php:323
565 msgid "Where can I find pricing options?"
566 msgstr ""
567
568 #: ../includes/settings.php:324
569 msgid "You can learn more about the features and pricing by visiting the Cookie Compliance website here:"
570 msgstr ""
571
572 #: ../includes/settings.php:380
573 msgid "Reset to defaults"
574 msgstr ""
575
576 #: ../includes/settings.php:407 ../includes/settings.php:412
577 msgid "Network Settings"
578 msgstr ""
579
580 #: ../includes/settings.php:408
581 msgid "Global Settings Override"
582 msgstr ""
583
584 #: ../includes/settings.php:409
585 msgid "Global Cookie"
586 msgstr ""
587
588 #: ../includes/settings.php:441 ../includes/settings.php:457
589 msgid "Compliance Settings"
590 msgstr ""
591
592 #: ../includes/settings.php:442 ../includes/settings.php:458
593 msgid "Compliance status"
594 msgstr ""
595
596 #: ../includes/settings.php:443 ../includes/settings.php:459
597 msgid "App ID"
598 msgstr ""
599
600 #: ../includes/settings.php:444 ../includes/settings.php:460
601 msgid "App Key"
602 msgstr ""
603
604 #: ../includes/settings.php:447
605 msgid "Miscellaneous Settings"
606 msgstr ""
607
608 #: ../includes/settings.php:448 ../includes/settings.php:552
609 #: ../includes/settings.php:566 ../includes/settings.php:585
610 #: ../includes/welcome.php:421
611 msgid "Autoblocking"
612 msgstr ""
613
614 #: ../includes/settings.php:449
615 msgid "Debug mode"
616 msgstr ""
617
618 #: ../includes/settings.php:450
619 msgid "Caching compatibility"
620 msgstr ""
621
622 #: ../includes/settings.php:451
623 msgid "Cache"
624 msgstr ""
625
626 #: ../includes/settings.php:452 ../includes/settings.php:475
627 msgid "Conditional display"
628 msgstr ""
629
630 #: ../includes/settings.php:453 ../includes/settings.php:477
631 msgid "Deactivation"
632 msgstr ""
633
634 #: ../includes/settings.php:463
635 msgid "Notice Settings"
636 msgstr ""
637
638 #: ../includes/settings.php:465
639 msgid "Button text"
640 msgstr ""
641
642 #: ../includes/settings.php:467
643 msgid "Refuse consent"
644 msgstr ""
645
646 #: ../includes/settings.php:469
647 msgid "Script blocking"
648 msgstr ""
649
650 #: ../includes/settings.php:470
651 msgid "Reloading"
652 msgstr ""
653
654 #: ../includes/settings.php:471
655 msgid "On scroll"
656 msgstr ""
657
658 #: ../includes/settings.php:472
659 msgid "On click"
660 msgstr ""
661
662 #: ../includes/settings.php:473
663 msgid "Accepted expiry"
664 msgstr ""
665
666 #: ../includes/settings.php:474
667 msgid "Rejected expiry"
668 msgstr ""
669
670 #: ../includes/settings.php:476
671 msgid "Script placement"
672 msgstr ""
673
674 #: ../includes/settings.php:480
675 msgid "Notice Design"
676 msgstr ""
677
678 #: ../includes/settings.php:481
679 msgid "Position"
680 msgstr ""
681
682 #: ../includes/settings.php:482
683 msgid "Animation"
684 msgstr ""
685
686 #: ../includes/settings.php:483
687 msgid "Colors"
688 msgstr ""
689
690 #: ../includes/settings.php:484
691 msgid "Button class"
692 msgstr ""
693
694 #: ../includes/settings.php:496
695 msgid "Enable global network settings override."
696 msgstr ""
697
698 #: ../includes/settings.php:497
699 msgid "Every site in the network will use the same settings. Site administrators will not be able to change them."
700 msgstr ""
701
702 #: ../includes/settings.php:511
703 msgid "This option works only for domain-based networks."
704 msgstr ""
705
706 #: ../includes/settings.php:517
707 msgid "Enable global network cookie consent."
708 msgstr ""
709
710 #: ../includes/settings.php:518
711 msgid "Cookie consent in one of the network sites results in a consent in all of the sites on the network."
712 msgstr ""
713
714 #: ../includes/settings.php:529
715 msgid "Global network settings override is active. Every site will use the same network settings. Please contact super administrator if you want to have more control over the settings."
716 msgstr ""
717
718 #: ../includes/settings.php:551 ../includes/settings.php:565
719 #: ../includes/settings.php:584
720 msgid "Notice"
721 msgstr ""
722
723 #: ../includes/settings.php:551 ../includes/settings.php:552
724 #: ../includes/settings.php:553 ../includes/settings.php:554
725 #: ../includes/settings.php:565 ../includes/settings.php:584
726 msgid "Active"
727 msgstr ""
728
729 #: ../includes/settings.php:553 ../includes/settings.php:567
730 #: ../includes/settings.php:586 ../includes/welcome.php:422
731 msgid "Cookie Categories"
732 msgstr ""
733
734 #: ../includes/settings.php:554 ../includes/settings.php:568
735 #: ../includes/settings.php:587 ../includes/welcome.php:423
736 msgid "Proof-of-Consent"
737 msgstr ""
738
739 #: ../includes/settings.php:557
740 msgid "Log in & Configure"
741 msgstr ""
742
743 #: ../includes/settings.php:558
744 msgid "Log into the Cookie Compliance&trade; web application to configure the appearance and functionality of the banner."
745 msgstr ""
746
747 #: ../includes/settings.php:566 ../includes/settings.php:567
748 #: ../includes/settings.php:568
749 msgid "Pending"
750 msgstr ""
751
752 #: ../includes/settings.php:571
753 msgid "Log in & configure"
754 msgstr ""
755
756 #: ../includes/settings.php:572
757 msgid "Log into the Cookie Compliance&trade; web application and complete the setup process."
758 msgstr ""
759
760 #: ../includes/settings.php:585 ../includes/settings.php:586
761 #: ../includes/settings.php:587
762 msgid "Inactive"
763 msgstr ""
764
765 #: ../includes/settings.php:590
766 msgid "Add Compliance features"
767 msgstr ""
768
769 #: ../includes/settings.php:591
770 #, php-format
771 msgid "Sign up to %s and add GDPR, CCPA and other international data privacy laws compliance features."
772 msgstr ""
773
774 #: ../includes/settings.php:606
775 msgid "Enter your Cookie Compliance&trade; application ID."
776 msgstr ""
777
778 #: ../includes/settings.php:619
779 msgid "Enter your Cookie Compliance&trade; application secret key."
780 msgstr ""
781
782 #: ../includes/settings.php:636
783 msgid "Enable to automatically block 3rd party scripts before user consent is set."
784 msgstr ""
785
786 #: ../includes/settings.php:637
787 msgid "This option has been temporarily disabled because your website has reached the usage limit for the Cookie Compliance Basic plan. It will become available again when the current visits cycle resets or you upgrade your website to a Professional plan."
788 msgstr ""
789
790 #: ../includes/settings.php:650
791 msgid "Purge Cache"
792 msgstr ""
793
794 #: ../includes/settings.php:652
795 msgid "Click the Purge Cache button to refresh the app configuration."
796 msgstr ""
797
798 #: ../includes/settings.php:667
799 msgid "Enable conditional display of the banner."
800 msgstr ""
801
802 #: ../includes/settings.php:680
803 msgid "Determine what should happen when the following conditions are met."
804 msgstr ""
805
806 #: ../includes/settings.php:713
807 msgid "Enable to run the consent banner in debug mode."
808 msgstr ""
809
810 #: ../includes/settings.php:734
811 msgid "Currently detected active caching plugins"
812 msgstr ""
813
814 #: ../includes/settings.php:742
815 msgid "No compatible cache plugins found."
816 msgstr ""
817
818 #: ../includes/settings.php:746
819 msgid "Enable to apply changes improving compatibility with caching plugins."
820 msgstr ""
821
822 #: ../includes/settings.php:759
823 msgid "Enter the cookie notice message."
824 msgstr ""
825
826 #: ../includes/settings.php:772
827 msgid "The text of the option to accept the notice and make it disappear."
828 msgstr ""
829
830 #: ../includes/settings.php:787
831 msgid "Enable to give to the user the possibility to refuse third party non functional cookies."
832 msgstr ""
833
834 #: ../includes/settings.php:791
835 msgid "The text of the button to refuse the consent."
836 msgstr ""
837
838 #: ../includes/settings.php:813
839 msgid "Head"
840 msgstr ""
841
842 #: ../includes/settings.php:814
843 msgid "Body"
844 msgstr ""
845
846 #: ../includes/settings.php:817
847 msgid "The code to be used in your site header, before the closing head tag."
848 msgstr ""
849
850 #: ../includes/settings.php:821
851 msgid "The code to be used in your site footer, before the closing body tag."
852 msgstr ""
853
854 #: ../includes/settings.php:825
855 msgid "Enter non functional cookies Javascript code here (for e.g. Google Analitycs) to be used after the notice is accepted."
856 msgstr ""
857
858 #: ../includes/settings.php:825
859 #, php-format
860 msgid "To get the user consent status use the %scn_cookies_accepted()%s function."
861 msgstr ""
862
863 #: ../includes/settings.php:840
864 #, php-format
865 msgid "Enable to give to the user the possibility to revoke their consent %s(requires \"Refuse consent\" option enabled)%s."
866 msgstr ""
867
868 #: ../includes/settings.php:843
869 msgid "Enter the revoke message."
870 msgstr ""
871
872 #: ../includes/settings.php:845
873 msgid "The text of the button to revoke the consent."
874 msgstr ""
875
876 #: ../includes/settings.php:853
877 #, php-format
878 msgid "Select the method for displaying the revoke button - automatic (in the banner) or manual using %s[cookies_revoke]%s shortcode."
879 msgstr ""
880
881 #: ../includes/settings.php:866
882 msgid "Enable to reload the page after the notice is accepted."
883 msgstr ""
884
885 #: ../includes/settings.php:897
886 msgid "Enable privacy policy link."
887 msgstr ""
888
889 #: ../includes/settings.php:900
890 msgid "The text of the privacy policy button."
891 msgstr ""
892
893 #: ../includes/settings.php:910
894 msgid "Select where to redirect user for more information."
895 msgstr ""
896
897 #: ../includes/settings.php:913
898 msgid "-- select page --"
899 msgstr ""
900
901 #: ../includes/settings.php:924
902 msgid "Select from one of your site's pages."
903 msgstr ""
904
905 #: ../includes/settings.php:930
906 msgid "Synchronize with WordPress Privacy Policy page."
907 msgstr ""
908
909 #: ../includes/settings.php:937
910 msgid "Enter the full URL starting with http(s)://"
911 msgstr ""
912
913 #: ../includes/settings.php:947
914 msgid "Select the privacy policy link target."
915 msgstr ""
916
917 #: ../includes/settings.php:957
918 msgid "Select the privacy policy link position."
919 msgstr ""
920
921 #: ../includes/settings.php:980
922 msgid "The amount of time that the cookie should be stored for when user accepts the notice."
923 msgstr ""
924
925 #: ../includes/settings.php:1001
926 msgid "The amount of time that the cookie should be stored for when the user doesn't accept the notice."
927 msgstr ""
928
929 #: ../includes/settings.php:1020
930 msgid "Select where all the plugin scripts should be placed."
931 msgstr ""
932
933 #: ../includes/settings.php:1039
934 msgid "Select location for the notice."
935 msgstr ""
936
937 #: ../includes/settings.php:1058
938 msgid "Select the animation style."
939 msgstr ""
940
941 #: ../includes/settings.php:1073
942 msgid "Enable to accept the notice when user scrolls."
943 msgstr ""
944
945 #: ../includes/settings.php:1076
946 msgid "Number of pixels user has to scroll to accept the notice and make it disappear."
947 msgstr ""
948
949 #: ../includes/settings.php:1089
950 msgid "Enable to accept the notice on any click on the page."
951 msgstr ""
952
953 #: ../includes/settings.php:1101
954 msgid "Enable if you want all plugin data to be deleted on deactivation."
955 msgstr ""
956
957 #: ../includes/settings.php:1114
958 msgid "Enter additional button CSS classes separated by spaces."
959 msgstr ""
960
961 #: ../includes/settings.php:1139
962 msgid "Bar opacity"
963 msgstr ""
964
965 #: ../includes/settings.php:1516
966 msgid "Settings saved."
967 msgstr ""
968
969 #: ../includes/settings.php:1520
970 msgid "Settings restored to defaults."
971 msgstr ""
972
973 #: ../includes/settings.php:1608
974 msgid "Are you sure you want to reset these settings to defaults?"
975 msgstr ""
976
977 #: ../includes/settings.php:1725
978 msgid "or"
979 msgstr ""
980
981 #: ../includes/settings.php:1792
982 msgid "+ Add rule"
983 msgstr ""
984
985 #: ../includes/settings.php:1793
986 msgid "Create a set of rules to define the exact conditions for displaying or hiding the banner."
987 msgstr ""
988
989 #: ../includes/settings.php:1896
990 msgid "-- no public archives --"
991 msgstr ""
992
993 #: ../includes/settings.php:1992
994 #, php-format
995 msgid "Untitled Page %d"
996 msgstr ""
997
998 #: ../includes/settings.php:2006
999 msgid "Front Page"
1000 msgstr ""
1001
1002 #: ../includes/settings.php:2007
1003 msgid "Home Page"
1004 msgstr ""
1005
1006 #: ../includes/settings.php:2018
1007 msgid "Logged in"
1008 msgstr ""
1009
1010 #: ../includes/settings.php:2019
1011 msgid "Guest"
1012 msgstr ""
1013
1014 #: ../includes/welcome-api.php:35 ../includes/welcome-api.php:39
1015 #: ../includes/welcome-api.php:46 ../includes/welcome-api.php:59
1016 #: ../includes/welcome.php:207 ../includes/welcome.php:235
1017 #: ../includes/welcome.php:238
1018 msgid "You do not have permission to access this page."
1019 msgstr ""
1020
1021 #: ../includes/welcome-api.php:115 ../includes/welcome-api.php:349
1022 #: ../includes/welcome-api.php:391 ../includes/welcome-api.php:550
1023 #: ../includes/welcome-api.php:624 ../includes/welcome-api.php:1163
1024 #: ../includes/welcome.php:128
1025 msgid "Unexpected error occurred. Please try again later."
1026 msgstr ""
1027
1028 #: ../includes/welcome-api.php:152
1029 msgid "Empty plan or payment method data."
1030 msgstr ""
1031
1032 #: ../includes/welcome-api.php:187
1033 msgid "Unable to create customer data."
1034 msgstr ""
1035
1036 #: ../includes/welcome-api.php:226
1037 msgid "Unable to create payment mehotd."
1038 msgstr ""
1039
1040 #: ../includes/welcome-api.php:232
1041 msgid "No payment method token."
1042 msgstr ""
1043
1044 #: ../includes/welcome-api.php:276
1045 msgid "Please accept the Terms of Service to proceed."
1046 msgstr ""
1047
1048 #: ../includes/welcome-api.php:285 ../includes/welcome-api.php:518
1049 msgid "Email is not allowed to be empty."
1050 msgstr ""
1051
1052 #: ../includes/welcome-api.php:295 ../includes/welcome-api.php:527
1053 msgid "Password is not allowed to be empty."
1054 msgstr ""
1055
1056 #: ../includes/welcome-api.php:301
1057 msgid "The password contains illegal characters or does not meet the conditions."
1058 msgstr ""
1059
1060 #: ../includes/welcome-api.php:307
1061 msgid "Passwords do not match."
1062 msgstr ""
1063
1064 #: ../includes/welcome.php:129
1065 msgid "Passed"
1066 msgstr ""
1067
1068 #: ../includes/welcome.php:130
1069 msgid "Failed"
1070 msgstr ""
1071
1072 #: ../includes/welcome.php:131 ../includes/welcome.php:333
1073 #: ../includes/welcome.php:591 ../includes/welcome.php:689
1074 msgid "monthly"
1075 msgstr ""
1076
1077 #: ../includes/welcome.php:132
1078 msgid "yearly"
1079 msgstr ""
1080
1081 #: ../includes/welcome.php:136
1082 #, php-format
1083 msgid "%sCompliance Failed!%sYour website does not achieve minimum viable compliance. %sSign up to Cookie Compliance%s to bring your site into compliance with the latest data privacy rules and regulations."
1084 msgstr ""
1085
1086 #: ../includes/welcome.php:137
1087 #, php-format
1088 msgid "%sCompliance Passed!%sCongratulations. Your website meets minimum viable compliance."
1089 msgstr ""
1090
1091 #: ../includes/welcome.php:138 ../includes/welcome.php:691
1092 msgid "available"
1093 msgstr ""
1094
1095 #: ../includes/welcome.php:139
1096 msgid "Please fill all the required fields."
1097 msgstr ""
1098
1099 #: ../includes/welcome.php:253 ../includes/welcome.php:290
1100 msgid "The next generation of Cookie Notice"
1101 msgstr ""
1102
1103 #: ../includes/welcome.php:255
1104 msgid "Cookie Compliance is a free web application that enables websites to take a proactive approach to data protection and consent laws."
1105 msgstr ""
1106
1107 #: ../includes/welcome.php:261
1108 #, php-format
1109 msgid "It is the first solution to offer %sintentional consent%s, a new consent framework that incorporates the latest guidelines from over 100+ countries, and emerging standards from leading international organizations like the IEEE."
1110 msgstr ""
1111
1112 #: ../includes/welcome.php:262
1113 #, php-format
1114 msgid "Cookie Notice includes %sseamless integration%s with Cookie Compliance to help your site comply with the latest updates to existing consent laws and provide a beautiful, multi-level experience to engage visitors in data privacy decisions."
1115 msgstr ""
1116
1117 #: ../includes/welcome.php:266
1118 msgid "Sign up to Cookie Compliance"
1119 msgstr ""
1120
1121 #: ../includes/welcome.php:267
1122 msgid "Skip for now"
1123 msgstr ""
1124
1125 #: ../includes/welcome.php:292
1126 msgid "Take a proactive approach to data protection and consent laws by signing up for Cookie Compliance account. Then select a limited Basic Plan for free or get one of the Professional Plans for unlimited visits, consent storage, languages and customizations."
1127 msgstr ""
1128
1129 #: ../includes/welcome.php:296
1130 msgid "Compliance Plans"
1131 msgstr ""
1132
1133 #: ../includes/welcome.php:299
1134 msgid "Monthly"
1135 msgstr ""
1136
1137 #: ../includes/welcome.php:302
1138 msgid "Yearly"
1139 msgstr ""
1140
1141 #: ../includes/welcome.php:302
1142 msgid "Save 12%"
1143 msgstr ""
1144
1145 #: ../includes/welcome.php:311
1146 msgid "Free"
1147 msgstr ""
1148
1149 #: ../includes/welcome.php:316
1150 #, php-format
1151 msgid "%s1,000%s visits / month"
1152 msgstr ""
1153
1154 #: ../includes/welcome.php:317
1155 #, php-format
1156 msgid "%s30 days%s consent storage"
1157 msgstr ""
1158
1159 #: ../includes/welcome.php:320
1160 #, php-format
1161 msgid "%s1 additional%s language"
1162 msgstr ""
1163
1164 #: ../includes/welcome.php:321
1165 #, php-format
1166 msgid "%sBasic%s Support"
1167 msgstr ""
1168
1169 #: ../includes/welcome.php:324
1170 msgid "Start Basic"
1171 msgstr ""
1172
1173 #: ../includes/welcome.php:334
1174 msgid "Recommended"
1175 msgstr ""
1176
1177 #: ../includes/welcome.php:336
1178 msgid "Pricing options"
1179 msgstr ""
1180
1181 #: ../includes/welcome.php:337 ../includes/welcome.php:338
1182 #: ../includes/welcome.php:339 ../includes/welcome.php:340
1183 #, php-format
1184 msgid "%s domain license"
1185 msgstr ""
1186
1187 #: ../includes/welcome.php:355
1188 msgid "Start Professional"
1189 msgstr ""
1190
1191 #: ../includes/welcome.php:361
1192 msgid "I don’t want to create an account now"
1193 msgstr ""
1194
1195 #: ../includes/welcome.php:379
1196 msgid "Congratulations"
1197 msgstr ""
1198
1199 #: ../includes/welcome.php:380
1200 msgid "You have successfully signed up to a Professional plan."
1201 msgstr ""
1202
1203 #: ../includes/welcome.php:380
1204 msgid "You have successfully signed up to a limited, Basic plan."
1205 msgstr ""
1206
1207 #: ../includes/welcome.php:382
1208 msgid "Log in to your Cookie Compliance account and continue configuring your Privacy Experience."
1209 msgstr ""
1210
1211 #: ../includes/welcome.php:385
1212 msgid "Go to Application"
1213 msgstr ""
1214
1215 #: ../includes/welcome.php:410
1216 msgid "Compliance check"
1217 msgstr ""
1218
1219 #: ../includes/welcome.php:411
1220 msgid "This is a Compliance Check to determine your site’s compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws."
1221 msgstr ""
1222
1223 #: ../includes/welcome.php:413
1224 msgid "Site URL"
1225 msgstr ""
1226
1227 #: ../includes/welcome.php:414
1228 msgid "Site Name"
1229 msgstr ""
1230
1231 #: ../includes/welcome.php:417
1232 msgid "Checking..."
1233 msgstr ""
1234
1235 #: ../includes/welcome.php:420
1236 msgid "Notifies visitors that site uses cookies."
1237 msgstr ""
1238
1239 #: ../includes/welcome.php:421
1240 msgid "Non-essential cookies blocked until consent is registered."
1241 msgstr ""
1242
1243 #: ../includes/welcome.php:422
1244 msgid "Separate consent requested per purpose of use."
1245 msgstr ""
1246
1247 #: ../includes/welcome.php:423
1248 msgid "Proof-of-consent stored in secure audit format."
1249 msgstr ""
1250
1251 #: ../includes/welcome.php:439
1252 msgid "Live Setup"
1253 msgstr ""
1254
1255 #: ../includes/welcome.php:440
1256 msgid "Configure your Cookie Notice & Compliance design and compliance features through the options below. Click Apply Setup to save the configuration and go to selecting your preferred cookie solution."
1257 msgstr ""
1258
1259 #: ../includes/welcome.php:444
1260 msgid "Banner Compliance"
1261 msgstr ""
1262
1263 #: ../includes/welcome.php:465
1264 msgid "Select the laws that apply to your business"
1265 msgstr ""
1266
1267 #: ../includes/welcome.php:467
1268 msgid "GDPR"
1269 msgstr ""
1270
1271 #: ../includes/welcome.php:468
1272 msgid "CCPA"
1273 msgstr ""
1274
1275 #: ../includes/welcome.php:472
1276 msgid "Select a naming style for the consent choices"
1277 msgstr ""
1278
1279 #: ../includes/welcome.php:474
1280 msgid "Silver, Gold, Platinum (Default)​"
1281 msgstr ""
1282
1283 #: ../includes/welcome.php:475
1284 msgid "Private, Balanced, Personalized"
1285 msgstr ""
1286
1287 #: ../includes/welcome.php:476
1288 msgid "Reject All, Accept Some, Accept All​"
1289 msgstr ""
1290
1291 #: ../includes/welcome.php:480
1292 msgid "Select additional information to include in the banner: *"
1293 msgstr ""
1294
1295 #: ../includes/welcome.php:482
1296 #, php-format
1297 msgid "Display %sPrivacy Paper%s to provide helpful data privacy and consent information to visitors."
1298 msgstr ""
1299
1300 #: ../includes/welcome.php:483
1301 #, php-format
1302 msgid "Display %sPrivacy Contact%s to provide Data Controller contact information and links to external data privacy resources."
1303 msgstr ""
1304
1305 #: ../includes/welcome.php:486 ../includes/welcome.php:514
1306 msgid "available for Cookie Compliance&trade; Pro plans only"
1307 msgstr ""
1308
1309 #: ../includes/welcome.php:490
1310 msgid "Banner Design"
1311 msgstr ""
1312
1313 #: ../includes/welcome.php:494
1314 msgid "Select your preferred display position"
1315 msgstr ""
1316
1317 #: ../includes/welcome.php:504
1318 msgid "Adjust the banner color scheme"
1319 msgstr ""
1320
1321 #: ../includes/welcome.php:506
1322 msgid "Color of the buttons and interactive elements."
1323 msgstr ""
1324
1325 #: ../includes/welcome.php:507
1326 msgid "Color of the banner background."
1327 msgstr ""
1328
1329 #: ../includes/welcome.php:508
1330 msgid "Color of the body text."
1331 msgstr ""
1332
1333 #: ../includes/welcome.php:509
1334 msgid "Color of the borders and inactive elements."
1335 msgstr ""
1336
1337 #: ../includes/welcome.php:510
1338 msgid "Color of the heading text."
1339 msgstr ""
1340
1341 #: ../includes/welcome.php:511
1342 msgid "Color of the button text."
1343 msgstr ""
1344
1345 #: ../includes/welcome.php:519
1346 msgid "Apply Setup"
1347 msgstr ""
1348
1349 #: ../includes/welcome.php:537
1350 msgid "Compliance account"
1351 msgstr ""
1352
1353 #: ../includes/welcome.php:539
1354 msgid "Create a Cookie Compliance&trade; account and select your preferred plan."
1355 msgstr ""
1356
1357 #: ../includes/welcome.php:543
1358 msgid "Create Account"
1359 msgstr ""
1360
1361 #: ../includes/welcome.php:559
1362 #, php-format
1363 msgid "I have read and agree to the %sTerms of Service%s"
1364 msgstr ""
1365
1366 #: ../includes/welcome.php:563
1367 msgid "Sign Up"
1368 msgstr ""
1369
1370 #: ../includes/welcome.php:577
1371 msgid "Already have an account?"
1372 msgstr ""
1373
1374 #: ../includes/welcome.php:577 ../includes/welcome.php:663
1375 msgid "Sign in"
1376 msgstr ""
1377
1378 #: ../includes/welcome.php:584 ../includes/welcome.php:682
1379 msgid "Select Plan"
1380 msgstr ""
1381
1382 #: ../includes/welcome.php:591 ../includes/welcome.php:689
1383 #, php-format
1384 msgid "%sProfessional%s"
1385 msgstr ""
1386
1387 #: ../includes/welcome.php:595 ../includes/welcome.php:696
1388 #: ../includes/welcome.php:735
1389 msgid "Confirm"
1390 msgstr ""
1391
1392 #: ../includes/welcome.php:600 ../includes/welcome.php:701
1393 msgid "Payment Method"
1394 msgstr ""
1395
1396 #: ../includes/welcome.php:602 ../includes/welcome.php:703
1397 msgid "Credit Card"
1398 msgstr ""
1399
1400 #: ../includes/welcome.php:603 ../includes/welcome.php:704
1401 msgid "PayPal"
1402 msgstr ""
1403
1404 #: ../includes/welcome.php:609 ../includes/welcome.php:710
1405 msgid "Card Number"
1406 msgstr ""
1407
1408 #: ../includes/welcome.php:613 ../includes/welcome.php:714
1409 msgid "Expiration Date"
1410 msgstr ""
1411
1412 #: ../includes/welcome.php:617 ../includes/welcome.php:718
1413 msgid "CVC/CVV"
1414 msgstr ""
1415
1416 #: ../includes/welcome.php:621 ../includes/welcome.php:722
1417 msgid "Submit"
1418 msgstr ""
1419
1420 #: ../includes/welcome.php:646
1421 msgid "Compliance Sign in"
1422 msgstr ""
1423
1424 #: ../includes/welcome.php:648
1425 msgid "Sign in to your existing Cookie Compliance&trade; account and select your preferred plan."
1426 msgstr ""
1427
1428 #: ../includes/welcome.php:652
1429 msgid "Account Login"
1430 msgstr ""
1431
1432 #: ../includes/welcome.php:677
1433 msgid "Don't have an account yet?"
1434 msgstr ""
1435
1436 #: ../includes/welcome.php:677
1437 msgid "Sign up"
1438 msgstr ""
1439
1440 #: ../includes/welcome.php:691
1441 msgid "Use License"
1442 msgstr ""
1443
1444 #: ../includes/welcome.php:731
1445 msgid "Select subscription"
1446 msgstr ""
1447
1448 #: ../includes/welcome.php:755
1449 msgid "Success!"
1450 msgstr ""
1451
1452 #: ../includes/welcome.php:756
1453 msgid "You have successfully integrated your website to Cookie Compliance&trade;"
1454 msgstr ""
1455
1456 #: ../includes/welcome.php:756
1457 #, php-format
1458 msgid "Go to Cookie Compliance application now. Or access it anytime from your %sCookie Notice settings page%s."
1459 msgstr ""
1 === Cookie Notice & Compliance for GDPR / CCPA ===
2 Contributors: humanityco
3 Tags: gdpr, ccpa, cookies, consent, compliance, privacy
4 Requires at least: 4.9.6
5 Requires PHP: 5.4
6 Tested up to: 6.3
7 Stable tag: 2.4.10
8 License: MIT License
9 License URI: http://opensource.org/licenses/MIT
10
11 Cookie Notice allows you to you elegantly inform users that your site uses cookies and helps you comply with GDPR, CCPA and other data privacy laws.
12
13 == Description ==
14
15 <strong>Cookie Notice</strong> provides a simple, customizable website banner that can be used to help your website comply with certain cookie consent requirements under the EU GDPR cookie law and CCPA regulations and includes <strong>seamless integration</strong> with Cookie Compliance to help your site comply with the latest updates to existing consent laws.
16
17 <strong>Cookie Compliance</strong> is a fully featured Consent Management Platform (CMP) that provides automated compliance features and enhanced design controls in a state-of-the-art web application. Cookie Compliance enables websites to <strong>take a proactive approach to data protection and consent laws</strong>. It is the first solution to offer Intentional Consent, a new consent framework that incorporates the latest guidelines from over 100+ countries, and emerging standards from leading international organizations like the IEEE and European Center for Digital Rights (noyb.eu). Cookie Compliance provides a beautiful, multi-level experience and includes new choices and controls for site visitors to better understand and engage in data privacy decisions.
18
19 > Our Cookie Compliance web application introduces a more ethical, proactive way to capture and manage consent. This early version of the emerging Intentional Consent framework is a result of Hu-manity.co’s ongoing work with top Fortune 500 companies, governments, and standards organizations, who believe that the imbalanced relationship between consumers and corporations is unsustainable when it comes to data privacy and consent online. We are making it available for all website owners and operators who share this belief and support our mission to eliminate the dark patterns in online consent.<br>
20 > Matt Sinderbrand - Chief Platform Officer, Hu-manity.co
21
22 ## Cookie Notice (plugin only)
23
24 Cookie Notice provides a simple, customizable website banner to help your website comply with certain cookie consent requirements.
25
26 = Banner features: =
27
28 * Customizable notice message
29 * Consent on click, scroll or close
30 * Multiple cookie expiry options
31 * Link to Privacy Policy page
32 * WordPress Privacy Policy page synchronization
33 * WPML and Polylang compatible
34 * SEO friendly
35
36 ## Cookie Compliance (plugin + web application)
37
38 Cookie Compliance gives you access to the most up-to-date formatting guidelines and technical compliance requirements for over 100 countries and legal jurisdictions.
39
40 = Banner features: =
41
42 * <strong>Intentional Consent</strong> provides 3 equal buttons to give site visitors the ability to accept none, some, or all cookies through packaged choices called Data Access Levels. Data Access Levels improve consent conversion and eliminate the dark pattern of deceptive, non-equal choices in the first layer. <em>Complies with equal choice principle prescribed under GDPR and other data protection laws.</em>
43 * <strong>Consent duration selector</strong> gives visitor control over how long their consent remains valid for your site. <em>Enables your site to align with recent guidelines from EU Data Protection Authorities, which state that cookie consent should be valid for no longer than a period of 6 months.</em>
44 * <strong>Cookie purpose categories</strong> make it easy for website visitors to customize their consent by category. <em>Complies with affirmative, opt-in consent requirements prescribed under GDPR and other data protection laws.</em>
45 * <strong>Consent metrics</strong> displays the visitor's consent record and a list of blocked / allowed 3rd parties directly in the expanded level of the banner. <em>Complies with latest guidance from EU Data Protection Authorities like CNIL (France) and ICO (UK). </em>
46 * <strong>Customizable Privacy Paper</strong> provides helpful information to improve visitor comprehension and understanding of the data sharing risks and benefits. Allows you to summarize core components of your sites privacy notice and <em>aligns with the informed principle prescribed by GDPR rules for valid consent capture. </em>
47 * <strong>Configurable Privacy Contact</strong> allows you to provide contact information for a business’ data privacy admin, as well as helpful links to data subject request forms and other data privacy resources. <em>Aligns with the informed principle prescribed by GDPR rules for valid consent capture.</em>
48
49 = Web Application features: =
50
51 * <strong>Consent analytics dashboard</strong> shows event data for number of visits and provides a “trust score” to help you track how site visitors are setting their consent. Make adjustments to your banner to improve your cookie acceptance rate and monitor progress via the consent activity graph.
52 * <strong>Default configurations</strong> for GDPR, CCPA and more help to remove dark patterns and allow for quick and easy deployment of the consent banner without any guesswork. Customize the design of any default configuration to match the look and feel of your site.
53 * <strong>Automatic script blocking</strong> blocks all non-essential cookie scripts and iFrames by default and <em>complies with valid consent rules under GDPR and other data protection laws</em>; in order to be compliant, your site must record visitor consent before setting or sending cookies.
54 * <strong>Consent record storage</strong> automatically stores a record of each consent and makes these records available for export. <em>Complies with proof-of-consent requirements prescribed under GDPR and other data protection laws.</em>
55 * <strong>Multilingual support</strong> automatically translates all banner text strings and allows you to provide custom translations for every text field to ensure visitors get a consistent consent experience.
56 * <strong>Multidomain management</strong> allows you to manage additional Free or Professional domains under a single account and enables you to customize banner configuration and design for each domain independently.
57
58 = Cookie Compliance proactive approach: =
59
60 For all businesses, the resources required to stay ahead of the latest regulations increases with the passage of each new law. With enforcement of compliance violations increasing daily, we believe it is critical for us as a trusted consent vendor to do everything in our power to help you stay ahead of these laws and remove the risk to your business
61
62 <strong>Cookie Compliance covers all current and upcoming regulations:</strong>
63
64 * GDPR (EU)
65 * ePrivacy Directive (EU)
66 * ePrivacy Regulation (EU)
67 * PECR (UK)
68 * LGPD (Brazil)
69 * PIPEDA (Canada)
70 * PDPB (India)
71 * CCPA (California, US)
72 * VCDPA (Virginia, US)
73 * Colorado Privacy Act (US)
74 * CPRA (California, US)
75
76 <strong>Cookie Compliance incorporates all recent formatting guidance:</strong>
77
78 * European Data Protection Supervisor (EDPS)
79 * ICO (United Kingdom)
80 * CNIL (France)
81 * GPDP (Italy)
82 * BfDl (Germany)
83 * AEPD (Spain)
84 * European Center for Digital Rights (noyb.eu)
85
86 <strong>Cookie Compliance targets dark patterns</strong>
87
88 Dark Patterns are user interface (UI) techniques that push site visitors to make decisions (such as agreeing to the installation of cookies on their devices) that they might not otherwise make. The most common Dark Pattern is the lack of an equal “reject all” button on the first layer of the consent notice. Dark Patterns are explicitly banned under GDPR and other data protection laws.
89
90 As a part of our proactive approach, Cookie Compliance is configured by default to prevent Dark Patterns through our unique Intentional Consent design.
91
92 == Installation ==
93
94 1. Install Cookie Notice either via the WordPress.org plugin directory, or by uploading the files to your server
95 2. Activate the plugin through the 'Plugins' menu in WordPress
96 3. Go to the Cookie Notice settings and set your options.
97 4. Click "Add Compliance features" button to start Cookie Compliance integration.
98 5. Create Cookie Compliance account and select plan.
99 6. Log in to Cookie Compliance web application anytime to customize the settings.
100
101 == Frequently Asked Questions ==
102
103 = Is Cookie Notice free? =
104 Yes! Cookie Notice is a free software.
105
106 = Is Cookie Compliance free? =
107 Yes, but with limits. Cookie Compliance includes both free and paid plans to choose from depending on your needs and your website traffic.
108
109 = Does the Cookie Notice make my site fully compliant with GDPR or US Privacy Laws? =
110 No. The plugin-only version DOES NOT include technical compliance features such as automatic script blocking, consent purpose categories, or consent record storage. These features are only available through the Cookie Compliance integration.
111
112 = Does the Cookie Compiance integration make my site fully compliant with GDPR and US Privacy Laws? =
113 Yes! The plugin + web appliaction version includes technical compliance features to meet requirements for over 100 countries and legal jurisdictions.
114
115 == Screenshots ==
116
117 1. Cookie Notice settings, Compliance itegration inactive
118 2. Cookie Notice settings, Compliance itegration active
119 3. Cookie Compliance dashboard overview
120 4. Cookie Compliance settings
121
122 == Changelog ==
123
124 = 2.4.10 =
125 * New: Option to enable/disable caching compatibility
126 * New: WP Fastest Cache plugin compatibility
127 * Fix: Potential security issue with purging cache
128 * Fix: Improved refreshing Compliance analytics data
129 * Tweak: Chart.js updated to 4.3.2
130
131 = 2.4.9 =
132 * New: WP Rocket plugin compatibility
133 * New: LiteSpeed Cache plugin compatibility
134 * New: Google Consent Mode support (Cookie Compliance only)
135 * New: Facebook Pixel Consent Mode support (Cookie Compliance only)
136
137 = 2.4.8 =
138 * New: Added Pages to Conditional display
139 * Fix: Homepage display issue
140 * Fix: Background color issue
141 * Tweak: Improved WP Rocket support
142 * Tweak: Improved SG Optimizer support
143
144 = 2.4.7 =
145 * New: Conditional display of the banner
146 * Tweak: Improved sanitization and validation of data
147 * Tweak: PHP 8.1 and 8.2 compatibility
148 * Tweak: Added async attribute when autoblocking is disabled
149
150 = 2.4.6 =
151 * Fix: Cookie Compliance inactive status issue
152
153 = 2.4.5 =
154 * Tweak: Remove the notice from the Elementor page builder
155 * Tweak: Remove the notice from widgets screen
156 * Fix: Improved Contact Form 7 reCaptcha compatibility
157
158 = 2.4.4 =
159 * Fix: Undefined index: status and subscription
160
161 = 2.4.3 =
162 * Fix: Deprecated preg_replace() notice in PHP 8.1
163
164 = 2.4.2 =
165 * New: Compatibility with Autoptimize plugin
166 * Fix: Improved Contact Form 7 reCaptcha support
167 * Fix: Fixed non-static method cookies_set()
168
169 = 2.4.1 =
170 * New: Contact Form 7 reCaptcha support
171 * Tweak: Switched health status from critical to recommended when Cookie Compliance is not integrated
172 * Tweak: Add SimeSite=Lax for created cookies
173
174 = 2.4.0 =
175 * New: Advanced Multisite support
176 * Fix: Polylang translation not working for shortcode
177 * Fix: Parse error: syntax error, unexpected ‘[‘
178
179 = 2.3.1 =
180 * New: Option to run consent banner in debug mode
181 * Fix: Invalid validation of dismissable notices
182
183 = 2.3.0 =
184 * New: Compliance Multi-license pricing options
185 * Tweak: WordPress 6.0 compatibility
186
187 = 2.2.3 =
188 * Fix: Undefined notice in WP dashboard
189 * Fix: Close icon event not firing
190 * Tweak: Remove aria-label from the close icon
191 * Tweak: CSS tweaks in the admin
192
193 = 2.2.2 =
194 * Fix: Uncrawlable close notice link
195 * Tweak: WordPress 5.9 compatibility
196 * Tweak: Prevent displaying the notice in an iframe
197 * Tweak: Send site language to a web app on signup
198
199 = 2.2.1 =
200 * Fix: Missing variable definition in frontend
201
202 = 2.2.0 =
203 * New: Option to hide banner for logged in users (Compliance only)
204
205 = 2.1.5 =
206 * Tweak: Additional sanitization applied
207
208 = 2.1.4 =
209 * Fix: Wordpress 5.8 widgets compatibility
210
211 = 2.1.3 =
212 * Fix: HTML attributes removed from text strings
213 * Tweak: Improved sanitization of options
214
215 = 2.1.2 =
216 * Tweak: Improved escaping of button labels
217
218 = 2.1.1 =
219 * Fix: Security bug related to compliance caching
220
221 = 2.1.0 =
222 * New: Introducing Cookie Compliance Free plan
223
224 = 2.0.4 =
225 * Fix: Undefined constant HOURS_IN_SECONDS
226 * Fix: Button style none adding CSS classes "cn-set-cookie cn-button"
227 * Tweak: Switched the behavior of close icon from accept to reject
228 * Tweak: Minified frontend and admin js files
229
230 = 2.0.3 =
231 * Fix: Cookies accepted function issue when Compliance activated
232
233 = 2.0.2 =
234 * Tweak: UI/UX improvements
235
236 = 2.0.1 =
237 * Fix: Pending Compliance update blocking the notice
238 * Fix: PHP Warning: Cannot modify header information
239 * Tweak: UI/UX fixes for the settings screen
240
241 = 2.0.0 =
242 * New: Introducing Cookie Compliance for GDPR/CCPA
243
244 = 1.3.2 =
245 * Tweak: Speed up Corona Banner loading by moving JS file to footer with async parameter
246 * Tweak: Improve buttons CSS padding
247 * Tweak: Accessibility improvements on links
248
249 = 1.3.1 =
250 * Fix: Unable to select Privacy policy link
251 * Fix: Blank Cookies policy link in a message
252 * Fix: Undefined index: on_click
253 * Tweak: Adjusted default opacity back to 100
254
255 = 1.3.0 =
256 * New: Introducing Corona Banner that displays data about Coronavirus pandemia and five steps recommended by the WHO (World Health Organization)
257 * New: Option to set bar opacity
258 * New: Accept the notice with close icon
259 * Fix: Policy link added to message without policy option enabled
260
261 = 1.2.51 =
262 * Fix: Problems with iOS and OK/Reject button
263 * Tweak: Added Separate cookie expiry for Reject, props Carlos Buchart
264
265 = 1.2.50 =
266 * Fix: The body css class always set to "cookies-refused"
267 * Tweak: Improve IE & Safari CustomEvent and ClassList support
268 * Tweak: Change the plugin js init event
269
270 = 1.2.49 =
271 * New: Option to accept the notice with any page click
272 * Tweak: Remove jQuery dependency
273 * Tweak: Swtich from jQuery to CSS3 animations
274 * Tweak: Improve the CSS and HTML structure
275
276 = 1.2.48 =
277 * Fix: HTML tags stripped from cookie message
278 * Fix: Link target not accepted in inline privacy link
279
280 = 1.2.47 =
281 * New: Option to select the privacy policy link position
282 * Tweak: Do not relad the page on refuse button click
283 * Tweak: Added aria-label attribute to cookie notice container
284
285 = 1.2.46 =
286 * Tweak: Remove WP Super Cache cookie on deactivation
287 * Tweak: Remove plugin version from the db on deactivation
288
289 = 1.2.45 =
290 * Tweak: Improved WP Super Cache support
291 * Tweak: CSS container style issue and media query for mobile
292
293 = 1.2.44 =
294 * Fix: The text of the revoke button ignored in shortcode
295 * Fix: Revoke consent button not displayed automatically in top position
296 * Tweak: Add shortcode parsing for content of [cookies_accepted], thanks to [dsturm](https://github.com/dsturm)
297
298 = 1.2.43 =
299 * New: Option to revoke the user consent
300 * New: Script blocking extended to header and footer
301 * New: Synchronization with WordPress 4.9.6 Privacy Policy page
302 * New: Custom button class option
303 * Tweak: Added 1 hour cookie expiry option
304
305 = 1.2.42 =
306 * New: Introducing [cookies_accepted][/cookies_accepted] shortcode
307 * Fix: Infinite cookie expiry issue
308
309 = 1.2.41 =
310 * Fix: Infinite redirection loop with scroll enabled
311
312 = 1.2.40 =
313 * Fix: Div align center on some themes
314 * Tweak: Extended list of allowed HTML tags in refuse code
315 * Tweak: Minified CSS and JS
316
317 = 1.2.39 =
318 * New: Option to reload the page after cookies are accepted
319
320 = 1.2.38 =
321 * Tweak: Move frontend cookie js functions before the document ready call, thanks to [fgreinus](https://github.com/fgreinus)
322 * Tweak: Adjust functional javascript code handling
323 * Fix: Chhromium infinity expiration date not valid
324 * Fix: Remove deprecated screen_icon() function
325
326 = 1.2.37 =
327 * Tweak: Add aria landmark role="banner"
328 * Tweak: Extend cn_cookie_notice_args with button class
329
330 = 1.2.36.1 =
331 * Fix: Repository upload issue with 1.2.36
332
333 = 1.2.36 =
334 * Fix: String translation support for WMPL 3.2+
335 * Fix: Global var possible conflict with other plugins
336 * Tweak: Add $options array to "cn_cookie_notice_output" filter, thanks to [chesio](https://github.com/chesio).
337 * Tweak: Removed local translation files in favor of WP repository translations.
338
339 = 1.2.35 =
340 * Tweak: Use html_entity_decode on non-functional code block
341 * Tweak: get_pages() function placement optimization
342 * Tweak: Filterable manage cookie notice capability
343
344 = 1.2.34 =
345 * Fix: Empty href in links HTML validation issue
346
347 = 1.2.33 =
348 * New: Greek translation thanks to Elias Stefanidis
349
350 = 1.2.32 =
351 * Fix: Accept cookie button hidden on acceptance instead of the cookie message container
352
353 = 1.2.31 =
354 * New: Non functional Javascript code field
355 * Fix: Minified Javascript caching issue
356
357 = 1.2.30 =
358 * Fix: jQuery error after accepting cookies
359
360 = 1.2.29 =
361 * Tweak: Add class to body element when displayed
362 * Tweak: Italian translation update
363
364 = 1.2.28 =
365 * New: Option to set on scroll offset
366
367 = 1.2.27 =
368 * Tweak: Correctly remove scroll event, limit possible conflicts
369 * Tweak: Italian translation update
370
371 = 1.2.26 =
372 * Fix: Accept cookies on scroll option working unchecked.
373 * Fix: call_user_func() warning on lower version of WP
374
375 = 1.2.25 =
376 * New: Option to accept cookies on scroll, thanks to [Cristian Pascottini](http://cristian.pascottini.net/)
377
378 = 1.2.24 =
379 * New: Option to refuse to accept cookies
380 * New: setCookieNotice custom jQuery event
381 * Tweak: Italian translation updated, thanks to Luca Speranza
382
383 = 1.2.23 =
384 * New: Finnish translation, thanks to [Daniel Storgards](www.danielstorgards.com)
385
386 = 1.2.22 =
387 * Tweak: Swedish translation updated, thx to Ove Kaufeldt
388
389 = 1.2.21 =
390 * New: Plugin development moved to [dFactory GitHub Repository](https://github.com/dfactoryplugins)
391 * Tweak: Code cleanup
392
393 = 1.2.20 =
394 * New: Option to select scripts placement, header or footer
395
396 = 1.2.19 =
397 * New: Danish translation, thanks to Lui Wallentin Gottler
398
399 = 1.2.18.1 =
400 * Fix: Quick fix for 1.2.18 print_r in code
401
402 = 1.2.18 =
403 * New: More info link target option
404 * Tweak: Additional HTML ids, for more flexible customization
405
406 = 1.2.17 =
407 * New: Hebrew translation, thanks to [Ahrale Shrem](http://atar4u.com/)
408
409 = 1.2.16 =
410 * Tweak: Dutch translation missing due to a typo
411
412 = 1.2.15 =
413 * New: Danish translation, thanks to Hans C. Jorgensen
414 * Fix: Notice bar not visible if no animation selected
415
416 = 1.2.14 =
417 * New: Hungarian translation, thanks to [Surbma](http://surbma.hu)
418
419 = 1.2.13 =
420 * New: Croatian translation, thanks to [Marko Beus](http://www.markobeus.com/)
421
422 = 1.2.12 =
423 * New: Slovenian translation, thanks to Thomas Cuk
424
425 = 1.2.11 =
426 * New: Swedish translation, thanks to [Daniel Storgards](http://www.danielstorgards.com/)
427
428 = 1.2.10 =
429 * New: Italian translation, thanks to [Luca](http://www.lucacicca.it)
430 * Tweak: Confirmed WP 4.0 compatibility
431
432 = 1.2.9.1 =
433 * Tweak: Enable HTML in cookie message text
434 * New: Option to donate this plugin :)
435
436 = 1.2.8 =
437 * New: Czech translation, thanks to [Adam Laita](http://laita.cz)
438
439 = 1.2.7 =
440 * New: French translation, thanks to [Laura Orsal](http://www.traductrice-independante.fr)
441 * New: Deleting plugin settings on deactivation as an option
442
443 = 1.2.6 =
444 * New: German translation, thanks to Alex Ernst
445
446 = 1.2.5 =
447 * New: Spanish translation, thanks to Fernando Blasco
448
449 = 1.2.4 =
450 * New: Added filter hooks to customize where and how display the cookie notice
451
452 = 1.2.3 =
453 * New: Portuguese translation, thanks to Luis Maia
454
455 = 1.2.2 =
456 * Fix: Read more linking to default site language in WPML & Polylang
457
458 = 1.2.1 =
459 * Tweak: UI improvements for WP 3.8
460
461 = 1.2.0 =
462 * Fix: Cookie not saving in IE
463 * Fix: Notice hidden under Admin bar bug
464 * Tweak: Improved WPML & Polylang compatibility
465
466 = 1.1.0 =
467 * New: Rewritten cookie setting method to pure JS
468 * Fix: Compatibility with WP Super Cache and other caching plugins
469
470 = 1.0.2 =
471 * New: Dutch translation, thanks to Heleen van den Bos
472
473 = 1.0.1 =
474 * Tweak: Changed setting cookie mode from AJAX to JS driven
475
476 = 1.0.0 =
477 Initial release
478
479 == Upgrade Notice ==
480
481 = 2.4.10 =
482 New: Option to enable/disable caching compatibility, WP Fastest Cache plugin compatibility, Fix: Potential security issue with purging cache
...\ No newline at end of file ...\ No newline at end of file
1 <!-- BLOCKED -->
...\ No newline at end of file ...\ No newline at end of file
...@@ -96,11 +96,17 @@ class Mandrill { ...@@ -96,11 +96,17 @@ class Mandrill {
96 if( 200 == $response_code ) { 96 if( 200 == $response_code ) {
97 return $body; 97 return $body;
98 } else { 98 } else {
99 $code = 'Unknown' ? !array_key_exists('code', $body) : $body['code']; 99 if( !is_array( $body ) ) {
100 $message = 'Unknown' ? !array_key_exists('message', $body) : $body['message'];; 100 $code = 'Unknown';
101 $message = 'Unknown';
102 } else {
103 $code = 'Unknown' ? !array_key_exists('code', $body) : $body['code'];
104 $message = 'Unknown' ? !array_key_exists('message', $body) : $body['message'];
105 }
101 106
102 error_log("wpMandrill Error: Error {$code}: {$message}"); 107 error_log("wpMandrill Error: Error {$code}: {$message}");
103 throw new Mandrill_Exception( "wpMandrill Error: {$code}: {$message}", $response_code); 108 throw new Mandrill_Exception("wpMandrill Error: {$code}: {$message}", $response_code);
109
104 } 110 }
105 } 111 }
106 112
......
...@@ -1073,9 +1073,11 @@ class wpMandrill { ...@@ -1073,9 +1073,11 @@ class wpMandrill {
1073 * saved stats if found... and if there's none saved, it creates it directly from Mandrill. 1073 * saved stats if found... and if there's none saved, it creates it directly from Mandrill.
1074 */ 1074 */
1075 static function getCurrentStats() { 1075 static function getCurrentStats() {
1076 if( array_key_exists('fetch_new', $_GET) && $_GET['fetch_new']=='asap'){ 1076 if( is_array($_GET) ){
1077 $stats = self::saveProcessedStats(); 1077 if( array_key_exists('fetch_new', $_GET) && $_GET['fetch_new']=='asap'){
1078 return $stats; 1078 $stats = self::saveProcessedStats();
1079 return $stats;
1080 }
1079 } 1081 }
1080 1082
1081 $stats = get_transient('wpmandrill-stats'); 1083 $stats = get_transient('wpmandrill-stats');
......
...@@ -3,8 +3,8 @@ Contributors: MillerMediaNow, mikemm01, MC_Will, MC_Amanda, cornelraiu-1, crstau ...@@ -3,8 +3,8 @@ Contributors: MillerMediaNow, mikemm01, MC_Will, MC_Amanda, cornelraiu-1, crstau
3 Tags: mandrill, mailchimp, transactional email, email, email reliability, smtp, wp_mail, email templates 3 Tags: mandrill, mailchimp, transactional email, email, email reliability, smtp, wp_mail, email templates
4 Requires PHP: 5.6 4 Requires PHP: 5.6
5 Requires at least: 3.0 5 Requires at least: 3.0
6 Tested up to: 5.9 6 Tested up to: 6.1.1
7 Stable tag: 1.3 7 Stable tag: 1.3.1
8 License: GPLv2 8 License: GPLv2
9 9
10 The Send Emails with Mandrill plugin sends emails that are generated by WordPress through Mandrill, a transactional email service powered by MailChimp. 10 The Send Emails with Mandrill plugin sends emails that are generated by WordPress through Mandrill, a transactional email service powered by MailChimp.
...@@ -112,6 +112,9 @@ If your account has more than 20 senders registered or more than 40 tags used, t ...@@ -112,6 +112,9 @@ If your account has more than 20 senders registered or more than 40 tags used, t
112 4. Dashboard widget Settings 112 4. Dashboard widget Settings
113 113
114 == Changelog == 114 == Changelog ==
115 = 1.3.1 =
116 * Check for error messages parameters before processing (was throwing an error)
117
115 = 1.3 = 118 = 1.3 =
116 * Added setting to turn off Dashboard Widget 119 * Added setting to turn off Dashboard Widget
117 * Added ability to manually fetch new data from Reports screen 120 * Added ability to manually fetch new data from Reports screen
......
...@@ -4,7 +4,7 @@ Plugin Name: Send E-mails with Mandrill ...@@ -4,7 +4,7 @@ Plugin Name: Send E-mails with Mandrill
4 Description: Send e-mails using Mandrill. This is a forked version of the now unsupported plugin <a href="https://wordpress.org/plugins/wpmandrill/">wpMandrill</a>. 4 Description: Send e-mails using Mandrill. This is a forked version of the now unsupported plugin <a href="https://wordpress.org/plugins/wpmandrill/">wpMandrill</a>.
5 Author: Miller Media ( Matt Miller ) 5 Author: Miller Media ( Matt Miller )
6 Author URI: http://www.millermedia.io 6 Author URI: http://www.millermedia.io
7 Version: 1.3 7 Version: 1.3.1
8 Requires PHP: 5.6 8 Requires PHP: 5.6
9 Text Domain: send-emails-with-mandrill 9 Text Domain: send-emails-with-mandrill
10 */ 10 */
...@@ -32,7 +32,7 @@ if ( ! defined( 'ABSPATH' ) ) exit; ...@@ -32,7 +32,7 @@ if ( ! defined( 'ABSPATH' ) ) exit;
32 32
33 // Define plugin constants 33 // Define plugin constants
34 if ( !defined('SEWM_VERSION')) 34 if ( !defined('SEWM_VERSION'))
35 define( 'SEWM_VERSION', '1.3' ); 35 define( 'SEWM_VERSION', '1.3.1' );
36 36
37 if ( !defined( 'SEWM_BASE' ) ) 37 if ( !defined( 'SEWM_BASE' ) )
38 define( 'SEWM_BASE', plugin_basename( __FILE__ ) ); 38 define( 'SEWM_BASE', plugin_basename( __FILE__ ) );
...@@ -46,4 +46,4 @@ if ( !defined( 'SEWM_PATH' ) ) ...@@ -46,4 +46,4 @@ if ( !defined( 'SEWM_PATH' ) )
46 include( plugin_dir_path( __FILE__ ) . 'lib/pluginActivation.class.php'); 46 include( plugin_dir_path( __FILE__ ) . 'lib/pluginActivation.class.php');
47 include( plugin_dir_path( __FILE__ ) . 'lib/wpMandrill.class.php'); 47 include( plugin_dir_path( __FILE__ ) . 'lib/wpMandrill.class.php');
48 48
49 wpMandrill::on_load();
...\ No newline at end of file ...\ No newline at end of file
49 wpMandrill::on_load();
......
1 <?php
2 /**
3 * The template for displaying 404 pages (not found)
4 *
5 * @package Understrap
6 */
7
8 // Exit if accessed directly.
9 defined( 'ABSPATH' ) || exit;
10
11 get_header();
12
13 $container = get_theme_mod( 'understrap_container_type' );
14 ?>
15
16 <div class="wrapper" id="error-404-wrapper" style="background-image:url('wp-content/uploads/2023/08/iStock-1090668452_Recoloured-scaled.jpg');">
17
18 <div class="<?php echo esc_attr( $container ); ?>" id="content" tabindex="-1">
19
20 <div class="row">
21
22 <div class="col-md-12 content-area" id="primary">
23
24 <main class="site-main" id="main">
25
26 <section class="error-404 not-found">
27
28 <header class="page-header">
29
30 <h1 class="page-title"><?php esc_html_e( '404', 'understrap' ); ?></h1>
31
32 </header><!-- .page-header -->
33
34 <div class="page-content">
35
36 <p><?php esc_html_e( 'Oops! That page can&rsquo;t be found. It looks like nothing was found at this location.', 'understrap' ); ?></p>
37
38
39
40 <?php if ( 1 == 2 ) : // Only show the widget if site has multiple categories. ?>
41
42 <?php get_search_form(); ?>
43
44 <?php the_widget( 'WP_Widget_Recent_Posts' ); ?>
45
46 <div class="widget widget_categories">
47
48 <h2 class="widget-title"><?php esc_html_e( 'Most Used Categories', 'understrap' ); ?></h2>
49
50 <ul>
51 <?php
52 wp_list_categories(
53 array(
54 'orderby' => 'count',
55 'order' => 'DESC',
56 'show_count' => 1,
57 'title_li' => '',
58 'number' => 10,
59 )
60 );
61 ?>
62 </ul>
63
64 </div><!-- .widget -->
65
66 <?php endif; ?>
67
68 <?php
69
70
71 ?>
72
73 </div><!-- .page-content -->
74
75 </section><!-- .error-404 -->
76
77 </main>
78
79 </div><!-- #primary -->
80
81 </div><!-- .row -->
82
83 </div><!-- #content -->
84
85 </div><!-- #error-404-wrapper -->
86
87 <?php
88 get_footer();
...@@ -15588,6 +15588,49 @@ body, html { ...@@ -15588,6 +15588,49 @@ body, html {
15588 gap: 0px; 15588 gap: 0px;
15589 } 15589 }
15590 } 15590 }
15591 .grecaptcha-badge {
15592 display: none !important;
15593 }
15594
15595 div#error-404-wrapper {
15596 min-height: 100vh;
15597 background-size: cover;
15598 background-repeat: no-repeat;
15599 background-position: 0% 100%;
15600 }
15601
15602 .error-404 {
15603 padding-top: 160px;
15604 padding-bottom: 100px;
15605 text-align: center;
15606 }
15607 .error-404 h1, .error-404 .h1 {
15608 font-size: 300px;
15609 line-height: 300px;
15610 margin-bottom: 20px;
15611 }
15612 @media (max-width: 786px) {
15613 .error-404 h1, .error-404 .h1 {
15614 font-size: 150px;
15615 line-height: 150px;
15616 }
15617 }
15618 .error-404 p {
15619 color: #000;
15620 width: 70%;
15621 margin: auto;
15622 font-size: 26px;
15623 line-height: 40px;
15624 font-weight: 700;
15625 background-color: rgba(255, 255, 255, 0.7);
15626 }
15627 @media (max-width: 786px) {
15628 .error-404 p {
15629 font-size: 20px;
15630 line-height: 26px;
15631 }
15632 }
15633
15591 .has-blue-color, 15634 .has-blue-color,
15592 .has-blue-color:visited { 15635 .has-blue-color:visited {
15593 color: #0d6efd; 15636 color: #0d6efd;
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1
1 @import url("https://use.typekit.net/lov0ylb.css"); 2 @import url("https://use.typekit.net/lov0ylb.css");
2 3
3 4
...@@ -125,4 +126,44 @@ body,html{ ...@@ -125,4 +126,44 @@ body,html{
125 .extra-wide{ 126 .extra-wide{
126 gap:0px; 127 gap:0px;
127 } 128 }
129 }
130
131 .grecaptcha-badge{
132 display: none !important;
133 }
134 div#error-404-wrapper {
135 min-height: 100vh;
136 background-size: cover;
137 background-repeat: no-repeat;
138 background-position: 0% 100%;
139
140 }
141 .error-404{
142 padding-top: 160px;
143 padding-bottom: 100px;
144 text-align: center;
145
146 h1{
147 font-size: 300px;
148 line-height: 300px;
149 margin-bottom: 20px;
150 @media (max-width: 786px) {
151 font-size: 150px;
152 line-height: 150px;
153 }
154 }
155 p{
156 color: #000;
157 width: 70%;
158 margin: auto;
159 font-size: 26px;
160 line-height: 40px;
161 font-weight: 700;
162 background-color: rgba(255,255,255,.7);
163 @media (max-width: 786px) {
164 font-size: 20px;
165 line-height: 26px;
166 }
167
168 }
128 } 169 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 Author: the Understrap Contributors 5 Author: the Understrap Contributors
6 Author URI: https://github.com/understrap/understrap-child/graphs/contributors 6 Author URI: https://github.com/understrap/understrap-child/graphs/contributors
7 Template: understrap 7 Template: understrap
8 Version: 1.2.13 8 Version: 1.2.14
9 License: GNU General Public License v2 or later 9 License: GNU General Public License v2 or later
10 License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 License URI: http://www.gnu.org/licenses/gpl-2.0.html
11 Text Domain: understrap-child 11 Text Domain: understrap-child
......