Version Description
This is the first version of this plugin. It is a tool for your convenience. Rollback at your own risk!
Download this release
Release Info
Developer | dlocc |
Plugin | WP Rollback |
Version | 1.0 |
Comparing to | |
See all releases |
Version 1.0
- assets/css/magnific-popup.css +484 -0
- assets/css/wp-rollback.css +110 -0
- assets/images/wprb-icon-final.svg +33 -0
- assets/images/wprb-logo.png +0 -0
- assets/js/jquery.magnific-popup.js +2060 -0
- assets/js/jquery.magnific-popup.min.js +4 -0
- assets/js/themes-wp-rollback.js +179 -0
- assets/js/wp-rollback.js +91 -0
- includes/class-rollback-plugin-upgrader.php +75 -0
- includes/class-rollback-theme-upgrader.php +80 -0
- includes/rollback-action.php +37 -0
- includes/rollback-menu.php +129 -0
- languages/wp-rollback.pot +117 -0
- license.txt +281 -0
- readme.txt +117 -0
- wp-rollback.php +695 -0
assets/css/magnific-popup.css
ADDED
@@ -0,0 +1,484 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Magnific Popup CSS */
|
2 |
+
.white-popup {
|
3 |
+
position: relative;
|
4 |
+
background: #FFF;
|
5 |
+
padding: 20px;
|
6 |
+
width: auto;
|
7 |
+
max-width: 500px;
|
8 |
+
margin: 20px auto;
|
9 |
+
}
|
10 |
+
|
11 |
+
.mfp-bg {
|
12 |
+
top: 0;
|
13 |
+
left: 0;
|
14 |
+
width: 100%;
|
15 |
+
height: 100%;
|
16 |
+
z-index: 9998;
|
17 |
+
overflow: hidden;
|
18 |
+
position: fixed;
|
19 |
+
background: #0b0b0b;
|
20 |
+
opacity: 0.8;
|
21 |
+
filter: alpha(opacity=80);
|
22 |
+
}
|
23 |
+
|
24 |
+
.mfp-wrap {
|
25 |
+
top: 0;
|
26 |
+
left: 0;
|
27 |
+
width: 100%;
|
28 |
+
height: 100%;
|
29 |
+
z-index: 9999;
|
30 |
+
position: fixed;
|
31 |
+
outline: none !important;
|
32 |
+
-webkit-backface-visibility: hidden;
|
33 |
+
}
|
34 |
+
|
35 |
+
.mfp-container {
|
36 |
+
text-align: center;
|
37 |
+
position: absolute;
|
38 |
+
width: 100%;
|
39 |
+
height: 100%;
|
40 |
+
left: 0;
|
41 |
+
top: 0;
|
42 |
+
padding: 0 8px;
|
43 |
+
-webkit-box-sizing: border-box;
|
44 |
+
-moz-box-sizing: border-box;
|
45 |
+
box-sizing: border-box;
|
46 |
+
}
|
47 |
+
|
48 |
+
.mfp-container:before {
|
49 |
+
content: '';
|
50 |
+
display: inline-block;
|
51 |
+
height: 100%;
|
52 |
+
vertical-align: middle;
|
53 |
+
}
|
54 |
+
|
55 |
+
.mfp-align-top .mfp-container:before {
|
56 |
+
display: none;
|
57 |
+
}
|
58 |
+
|
59 |
+
.mfp-content {
|
60 |
+
position: relative;
|
61 |
+
display: inline-block;
|
62 |
+
vertical-align: middle;
|
63 |
+
margin: 0 auto;
|
64 |
+
text-align: left;
|
65 |
+
z-index: 1045;
|
66 |
+
}
|
67 |
+
|
68 |
+
.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content {
|
69 |
+
width: 100%;
|
70 |
+
cursor: auto;
|
71 |
+
}
|
72 |
+
|
73 |
+
.mfp-ajax-cur {
|
74 |
+
cursor: progress;
|
75 |
+
}
|
76 |
+
|
77 |
+
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
|
78 |
+
cursor: -moz-zoom-out;
|
79 |
+
cursor: -webkit-zoom-out;
|
80 |
+
cursor: zoom-out;
|
81 |
+
}
|
82 |
+
|
83 |
+
.mfp-zoom {
|
84 |
+
cursor: pointer;
|
85 |
+
cursor: -webkit-zoom-in;
|
86 |
+
cursor: -moz-zoom-in;
|
87 |
+
cursor: zoom-in;
|
88 |
+
}
|
89 |
+
|
90 |
+
.mfp-auto-cursor .mfp-content {
|
91 |
+
cursor: auto;
|
92 |
+
}
|
93 |
+
|
94 |
+
.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter {
|
95 |
+
-webkit-user-select: none;
|
96 |
+
-moz-user-select: none;
|
97 |
+
user-select: none;
|
98 |
+
}
|
99 |
+
|
100 |
+
.mfp-loading.mfp-figure {
|
101 |
+
display: none;
|
102 |
+
}
|
103 |
+
|
104 |
+
.mfp-hide {
|
105 |
+
display: none !important;
|
106 |
+
}
|
107 |
+
|
108 |
+
.mfp-preloader {
|
109 |
+
color: #CCC;
|
110 |
+
position: absolute;
|
111 |
+
top: 50%;
|
112 |
+
width: auto;
|
113 |
+
text-align: center;
|
114 |
+
margin-top: -0.8em;
|
115 |
+
left: 8px;
|
116 |
+
right: 8px;
|
117 |
+
z-index: 1044;
|
118 |
+
}
|
119 |
+
|
120 |
+
.mfp-preloader a {
|
121 |
+
color: #CCC;
|
122 |
+
}
|
123 |
+
|
124 |
+
.mfp-preloader a:hover {
|
125 |
+
color: #FFF;
|
126 |
+
}
|
127 |
+
|
128 |
+
.mfp-s-ready .mfp-preloader {
|
129 |
+
display: none;
|
130 |
+
}
|
131 |
+
|
132 |
+
.mfp-s-error .mfp-content {
|
133 |
+
display: none;
|
134 |
+
}
|
135 |
+
|
136 |
+
button.mfp-close, button.mfp-arrow {
|
137 |
+
overflow: visible;
|
138 |
+
cursor: pointer;
|
139 |
+
background: transparent;
|
140 |
+
border: 0;
|
141 |
+
-webkit-appearance: none;
|
142 |
+
display: block;
|
143 |
+
outline: none;
|
144 |
+
padding: 0;
|
145 |
+
z-index: 1046;
|
146 |
+
-webkit-box-shadow: none;
|
147 |
+
box-shadow: none;
|
148 |
+
}
|
149 |
+
|
150 |
+
button::-moz-focus-inner {
|
151 |
+
padding: 0;
|
152 |
+
border: 0;
|
153 |
+
}
|
154 |
+
|
155 |
+
.mfp-close {
|
156 |
+
width: 44px;
|
157 |
+
height: 44px;
|
158 |
+
line-height: 44px;
|
159 |
+
position: absolute;
|
160 |
+
right: 0;
|
161 |
+
top: 0;
|
162 |
+
text-decoration: none;
|
163 |
+
text-align: center;
|
164 |
+
opacity: 0.65;
|
165 |
+
filter: alpha(opacity=65);
|
166 |
+
padding: 0 0 18px 10px;
|
167 |
+
color: #FFF;
|
168 |
+
font-style: normal;
|
169 |
+
font-size: 28px;
|
170 |
+
font-family: Arial, Baskerville, monospace;
|
171 |
+
}
|
172 |
+
|
173 |
+
.mfp-close:hover, .mfp-close:focus {
|
174 |
+
opacity: 1;
|
175 |
+
filter: alpha(opacity=100);
|
176 |
+
}
|
177 |
+
|
178 |
+
.mfp-close:active {
|
179 |
+
top: 1px;
|
180 |
+
}
|
181 |
+
|
182 |
+
.mfp-close-btn-in .mfp-close {
|
183 |
+
color: #333;
|
184 |
+
}
|
185 |
+
|
186 |
+
.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close {
|
187 |
+
color: #FFF;
|
188 |
+
right: -6px;
|
189 |
+
text-align: right;
|
190 |
+
padding-right: 6px;
|
191 |
+
width: 100%;
|
192 |
+
}
|
193 |
+
|
194 |
+
.mfp-counter {
|
195 |
+
position: absolute;
|
196 |
+
top: 0;
|
197 |
+
right: 0;
|
198 |
+
color: #CCC;
|
199 |
+
font-size: 12px;
|
200 |
+
line-height: 18px;
|
201 |
+
white-space: nowrap;
|
202 |
+
}
|
203 |
+
|
204 |
+
.mfp-arrow {
|
205 |
+
position: absolute;
|
206 |
+
opacity: 0.65;
|
207 |
+
filter: alpha(opacity=65);
|
208 |
+
margin: 0;
|
209 |
+
top: 50%;
|
210 |
+
margin-top: -55px;
|
211 |
+
padding: 0;
|
212 |
+
width: 90px;
|
213 |
+
height: 110px;
|
214 |
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
215 |
+
}
|
216 |
+
|
217 |
+
.mfp-arrow:active {
|
218 |
+
margin-top: -54px;
|
219 |
+
}
|
220 |
+
|
221 |
+
.mfp-arrow:hover, .mfp-arrow:focus {
|
222 |
+
opacity: 1;
|
223 |
+
filter: alpha(opacity=100);
|
224 |
+
}
|
225 |
+
|
226 |
+
.mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a {
|
227 |
+
content: '';
|
228 |
+
display: block;
|
229 |
+
width: 0;
|
230 |
+
height: 0;
|
231 |
+
position: absolute;
|
232 |
+
left: 0;
|
233 |
+
top: 0;
|
234 |
+
margin-top: 35px;
|
235 |
+
margin-left: 35px;
|
236 |
+
border: medium inset transparent;
|
237 |
+
}
|
238 |
+
|
239 |
+
.mfp-arrow:after, .mfp-arrow .mfp-a {
|
240 |
+
border-top-width: 13px;
|
241 |
+
border-bottom-width: 13px;
|
242 |
+
top: 8px;
|
243 |
+
}
|
244 |
+
|
245 |
+
.mfp-arrow:before, .mfp-arrow .mfp-b {
|
246 |
+
border-top-width: 21px;
|
247 |
+
border-bottom-width: 21px;
|
248 |
+
opacity: 0.7;
|
249 |
+
}
|
250 |
+
|
251 |
+
.mfp-arrow-left {
|
252 |
+
left: 0;
|
253 |
+
}
|
254 |
+
|
255 |
+
.mfp-arrow-left:after, .mfp-arrow-left .mfp-a {
|
256 |
+
border-right: 17px solid #FFF;
|
257 |
+
margin-left: 31px;
|
258 |
+
}
|
259 |
+
|
260 |
+
.mfp-arrow-left:before, .mfp-arrow-left .mfp-b {
|
261 |
+
margin-left: 25px;
|
262 |
+
border-right: 27px solid #3F3F3F;
|
263 |
+
}
|
264 |
+
|
265 |
+
.mfp-arrow-right {
|
266 |
+
right: 0;
|
267 |
+
}
|
268 |
+
|
269 |
+
.mfp-arrow-right:after, .mfp-arrow-right .mfp-a {
|
270 |
+
border-left: 17px solid #FFF;
|
271 |
+
margin-left: 39px;
|
272 |
+
}
|
273 |
+
|
274 |
+
.mfp-arrow-right:before, .mfp-arrow-right .mfp-b {
|
275 |
+
border-left: 27px solid #3F3F3F;
|
276 |
+
}
|
277 |
+
|
278 |
+
.mfp-iframe-holder {
|
279 |
+
padding-top: 40px;
|
280 |
+
padding-bottom: 40px;
|
281 |
+
}
|
282 |
+
|
283 |
+
.mfp-iframe-holder .mfp-content {
|
284 |
+
line-height: 0;
|
285 |
+
width: 100%;
|
286 |
+
max-width: 900px;
|
287 |
+
}
|
288 |
+
|
289 |
+
.mfp-iframe-holder .mfp-close {
|
290 |
+
top: -40px;
|
291 |
+
}
|
292 |
+
|
293 |
+
.mfp-iframe-scaler {
|
294 |
+
width: 100%;
|
295 |
+
height: 0;
|
296 |
+
overflow: hidden;
|
297 |
+
padding-top: 56.25%;
|
298 |
+
}
|
299 |
+
|
300 |
+
.mfp-iframe-scaler iframe {
|
301 |
+
position: absolute;
|
302 |
+
display: block;
|
303 |
+
top: 0;
|
304 |
+
left: 0;
|
305 |
+
width: 100%;
|
306 |
+
height: 100%;
|
307 |
+
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
308 |
+
background: #000;
|
309 |
+
}
|
310 |
+
|
311 |
+
/* Main image in popup */
|
312 |
+
img.mfp-img {
|
313 |
+
width: auto;
|
314 |
+
max-width: 100%;
|
315 |
+
height: auto;
|
316 |
+
display: block;
|
317 |
+
line-height: 0;
|
318 |
+
-webkit-box-sizing: border-box;
|
319 |
+
-moz-box-sizing: border-box;
|
320 |
+
box-sizing: border-box;
|
321 |
+
padding: 40px 0 40px;
|
322 |
+
margin: 0 auto;
|
323 |
+
}
|
324 |
+
|
325 |
+
/* The shadow behind the image */
|
326 |
+
.mfp-figure {
|
327 |
+
line-height: 0;
|
328 |
+
}
|
329 |
+
|
330 |
+
.mfp-figure:after {
|
331 |
+
content: '';
|
332 |
+
position: absolute;
|
333 |
+
left: 0;
|
334 |
+
top: 40px;
|
335 |
+
bottom: 40px;
|
336 |
+
display: block;
|
337 |
+
right: 0;
|
338 |
+
width: auto;
|
339 |
+
height: auto;
|
340 |
+
z-index: -1;
|
341 |
+
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
342 |
+
background: #444;
|
343 |
+
}
|
344 |
+
|
345 |
+
.mfp-figure small {
|
346 |
+
color: #BDBDBD;
|
347 |
+
display: block;
|
348 |
+
font-size: 12px;
|
349 |
+
line-height: 14px;
|
350 |
+
}
|
351 |
+
|
352 |
+
.mfp-figure figure {
|
353 |
+
margin: 0;
|
354 |
+
}
|
355 |
+
|
356 |
+
.mfp-bottom-bar {
|
357 |
+
margin-top: -36px;
|
358 |
+
position: absolute;
|
359 |
+
top: 100%;
|
360 |
+
left: 0;
|
361 |
+
width: 100%;
|
362 |
+
cursor: auto;
|
363 |
+
}
|
364 |
+
|
365 |
+
.mfp-title {
|
366 |
+
text-align: left;
|
367 |
+
line-height: 18px;
|
368 |
+
color: #F3F3F3;
|
369 |
+
word-wrap: break-word;
|
370 |
+
padding-right: 36px;
|
371 |
+
}
|
372 |
+
|
373 |
+
.mfp-image-holder .mfp-content {
|
374 |
+
max-width: 100%;
|
375 |
+
}
|
376 |
+
|
377 |
+
.mfp-gallery .mfp-image-holder .mfp-figure {
|
378 |
+
cursor: pointer;
|
379 |
+
}
|
380 |
+
|
381 |
+
@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
|
382 |
+
/**
|
383 |
+
* Remove all paddings around the image on small screen
|
384 |
+
*/
|
385 |
+
.mfp-img-mobile .mfp-image-holder {
|
386 |
+
padding-left: 0;
|
387 |
+
padding-right: 0;
|
388 |
+
}
|
389 |
+
|
390 |
+
.mfp-img-mobile img.mfp-img {
|
391 |
+
padding: 0;
|
392 |
+
}
|
393 |
+
|
394 |
+
.mfp-img-mobile .mfp-figure:after {
|
395 |
+
top: 0;
|
396 |
+
bottom: 0;
|
397 |
+
}
|
398 |
+
|
399 |
+
.mfp-img-mobile .mfp-figure small {
|
400 |
+
display: inline;
|
401 |
+
margin-left: 5px;
|
402 |
+
}
|
403 |
+
|
404 |
+
.mfp-img-mobile .mfp-bottom-bar {
|
405 |
+
background: rgba(0, 0, 0, 0.6);
|
406 |
+
bottom: 0;
|
407 |
+
margin: 0;
|
408 |
+
top: auto;
|
409 |
+
padding: 3px 5px;
|
410 |
+
position: fixed;
|
411 |
+
-webkit-box-sizing: border-box;
|
412 |
+
-moz-box-sizing: border-box;
|
413 |
+
box-sizing: border-box;
|
414 |
+
}
|
415 |
+
|
416 |
+
.mfp-img-mobile .mfp-bottom-bar:empty {
|
417 |
+
padding: 0;
|
418 |
+
}
|
419 |
+
|
420 |
+
.mfp-img-mobile .mfp-counter {
|
421 |
+
right: 5px;
|
422 |
+
top: 3px;
|
423 |
+
}
|
424 |
+
|
425 |
+
.mfp-img-mobile .mfp-close {
|
426 |
+
top: 0;
|
427 |
+
right: 0;
|
428 |
+
width: 35px;
|
429 |
+
height: 35px;
|
430 |
+
line-height: 35px;
|
431 |
+
background: rgba(0, 0, 0, 0.6);
|
432 |
+
position: fixed;
|
433 |
+
text-align: center;
|
434 |
+
padding: 0;
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
+
@media all and (max-width: 900px) {
|
439 |
+
.mfp-arrow {
|
440 |
+
-webkit-transform: scale(0.75);
|
441 |
+
transform: scale(0.75);
|
442 |
+
}
|
443 |
+
|
444 |
+
.mfp-arrow-left {
|
445 |
+
-webkit-transform-origin: 0;
|
446 |
+
transform-origin: 0;
|
447 |
+
}
|
448 |
+
|
449 |
+
.mfp-arrow-right {
|
450 |
+
-webkit-transform-origin: 100%;
|
451 |
+
transform-origin: 100%;
|
452 |
+
}
|
453 |
+
|
454 |
+
.mfp-container {
|
455 |
+
padding-left: 6px;
|
456 |
+
padding-right: 6px;
|
457 |
+
}
|
458 |
+
}
|
459 |
+
|
460 |
+
.mfp-ie7 .mfp-img {
|
461 |
+
padding: 0;
|
462 |
+
}
|
463 |
+
|
464 |
+
.mfp-ie7 .mfp-bottom-bar {
|
465 |
+
width: 600px;
|
466 |
+
left: 50%;
|
467 |
+
margin-left: -300px;
|
468 |
+
margin-top: 5px;
|
469 |
+
padding-bottom: 5px;
|
470 |
+
}
|
471 |
+
|
472 |
+
.mfp-ie7 .mfp-container {
|
473 |
+
padding: 0;
|
474 |
+
}
|
475 |
+
|
476 |
+
.mfp-ie7 .mfp-content {
|
477 |
+
padding-top: 44px;
|
478 |
+
}
|
479 |
+
|
480 |
+
.mfp-ie7 .mfp-close {
|
481 |
+
top: 0;
|
482 |
+
right: 0;
|
483 |
+
padding-top: 0;
|
484 |
+
}
|
assets/css/wp-rollback.css
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* WP Rollback Styles
|
3 |
+
*/
|
4 |
+
|
5 |
+
.wpr-content-wrap {
|
6 |
+
max-width: 805px;
|
7 |
+
}
|
8 |
+
|
9 |
+
.wpr-content-wrap h2 {
|
10 |
+
padding: 0 0 15px 0;
|
11 |
+
}
|
12 |
+
|
13 |
+
.wpr-content-wrap h2 img {
|
14 |
+
width: 40px;
|
15 |
+
position: relative;
|
16 |
+
top: 11px;
|
17 |
+
margin-right: 10px;
|
18 |
+
}
|
19 |
+
|
20 |
+
.wpr-content-wrap p {
|
21 |
+
font-size: 18px;
|
22 |
+
margin-top: 10px;
|
23 |
+
}
|
24 |
+
|
25 |
+
.wpr-content-wrap p span {
|
26 |
+
font-style: italic;
|
27 |
+
color: #000;
|
28 |
+
font-weight: 600;
|
29 |
+
}
|
30 |
+
|
31 |
+
.rollback-form {
|
32 |
+
|
33 |
+
}
|
34 |
+
|
35 |
+
.wpr-versions-wrap {
|
36 |
+
padding-left: 20px;
|
37 |
+
}
|
38 |
+
|
39 |
+
.rollback-form label {
|
40 |
+
display: block;
|
41 |
+
padding: 8px 0;
|
42 |
+
font-size: 16px;
|
43 |
+
}
|
44 |
+
|
45 |
+
.rollback-form label input {
|
46 |
+
margin-right: 5px;
|
47 |
+
}
|
48 |
+
|
49 |
+
.wpr-submit-wrap {
|
50 |
+
margin: 25px 0 0;
|
51 |
+
border-top: 1px solid #DADADA;
|
52 |
+
padding: 20px 0 30px;
|
53 |
+
max-width: 765px;
|
54 |
+
}
|
55 |
+
|
56 |
+
.rollback-form .current-version {
|
57 |
+
text-transform: lowercase;
|
58 |
+
font-size: 12px;
|
59 |
+
font-style: italic;
|
60 |
+
color: #AEAEAE;
|
61 |
+
margin-left: 14px;
|
62 |
+
}
|
63 |
+
|
64 |
+
.wpr-selected {
|
65 |
+
font-weight: bold;
|
66 |
+
}
|
67 |
+
|
68 |
+
.wpr-rollback-disabled.magnific-popup.button-primary {
|
69 |
+
opacity: 0.6;
|
70 |
+
cursor: default;
|
71 |
+
background: #B5B5B5;
|
72 |
+
border-color: #6B6B6B;
|
73 |
+
-webkit-box-shadow: inset 0 1px 0 rgba(249, 251, 252, 0.5), 0 1px 0 rgba( 0, 0, 0, 0.15 );
|
74 |
+
box-shadow: inset 0 1px 0 rgba(249, 251, 252, 0.5), 0 1px 0 rgba( 0, 0, 0, 0.15 );
|
75 |
+
color: #777;
|
76 |
+
text-decoration: none;
|
77 |
+
}
|
78 |
+
|
79 |
+
.button-primary {
|
80 |
+
margin-right: 5px !important;
|
81 |
+
}
|
82 |
+
|
83 |
+
/* Modal */
|
84 |
+
|
85 |
+
#wpr-modal-confirm {
|
86 |
+
|
87 |
+
}
|
88 |
+
|
89 |
+
#wpr-modal-confirm .button-primary {
|
90 |
+
margin-right: 5px;
|
91 |
+
}
|
92 |
+
|
93 |
+
.wpr-error {
|
94 |
+
background: #fff;
|
95 |
+
border-left: 4px solid #FFB800;
|
96 |
+
-webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
|
97 |
+
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
|
98 |
+
margin: 20px 0;
|
99 |
+
padding: 1px 12px;
|
100 |
+
}
|
101 |
+
|
102 |
+
.wpr-error p {
|
103 |
+
margin: 0.5em 0;
|
104 |
+
padding: 2px;
|
105 |
+
}
|
106 |
+
|
107 |
+
.wpr-rollback-intro {
|
108 |
+
font-size: 18px;
|
109 |
+
margin-top: 0;
|
110 |
+
}
|
assets/images/wprb-icon-final.svg
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
3 |
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
4 |
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
5 |
+
width="89.23px" height="100px" viewBox="0 0 89.23 100" enable-background="new 0 0 89.23 100" xml:space="preserve">
|
6 |
+
<path fill="#464342" d="M16.196,68.183c-1.398,0.656-1.515,0.518-3.173,1.23c1.898,4.219,4.532,7.676,7.89,10.79
|
7 |
+
c0.578-0.766,1.33-1.663,1.987-2.611C20.031,74.901,17.825,71.949,16.196,68.183z"/>
|
8 |
+
<path fill="#464342" d="M44.213,21.495c-18.771,0-34.042,15.27-34.042,34.041c0,3.354,0.573,6.886,1.481,9.949
|
9 |
+
c0.961-0.427,1.881-0.604,3.26-1.188l-1.306-8.762c-0.054-3.254,0.952-8.649,2.65-12.456l14.6,40
|
10 |
+
c-1.733-0.843-3.118-1.677-4.625-2.782c-0.73,1.015-0.974,1.19-2.079,2.646c5.1,3.763,11.132,6.162,17.822,6.579
|
11 |
+
c0-0.84,0-2.406,0-3.466c-2.259-0.155-4.31-0.544-6.409-1.161l9.184-26.683l9.406,25.773c0.063,0.151,0.139,0.289,0.22,0.422
|
12 |
+
c-2.61,0.918-5.382,1.49-8.26,1.669V86.5c0,1.084,0,1.935,0,3.022c17.887-0.991,32.139-15.855,32.139-33.987
|
13 |
+
C78.254,36.765,62.982,21.495,44.213,21.495z M48.431,41.185c1.841-0.097,3.503-0.29,3.503-0.29
|
14 |
+
c1.646-0.196,1.454-2.619-0.195-2.523c0,0-4.958,0.389-8.16,0.389c-3.006,0-8.059-0.389-8.059-0.389
|
15 |
+
c-1.651-0.096-1.845,2.425-0.194,2.523c0,0,1.561,0.193,3.21,0.29l4.768,13.065l-6.699,20.087L25.46,41.185
|
16 |
+
c1.844-0.097,3.502-0.29,3.502-0.29c1.648-0.196,1.454-2.619-0.195-2.523c0,0-4.957,0.389-8.157,0.389
|
17 |
+
c-0.574,0-1.251-0.013-1.971-0.037c5.473-8.309,14.879-13.795,25.573-13.795c7.967,0,15.222,3.047,20.666,8.036
|
18 |
+
c-0.131-0.008-0.259-0.024-0.395-0.024c-3.007,0-5.141,2.62-5.141,5.432c0,2.523,1.457,4.656,3.007,7.179
|
19 |
+
c1.163,2.038,2.523,4.656,2.523,8.44c0,2.62-1.008,5.659-2.329,9.895L59.49,74.084L48.431,41.185z M59.6,81.989l9.347-27.027
|
20 |
+
c1.746-4.366,2.329-7.858,2.329-10.962c0-1.126-0.076-2.172-0.207-3.147c2.389,4.359,3.747,9.362,3.747,14.683
|
21 |
+
C74.816,66.825,68.698,76.685,59.6,81.989z"/>
|
22 |
+
<g>
|
23 |
+
<path fill="#464342" d="M44.055,11.836V1.196L14.095,18.493l29.959,17.296V25.151c16.979,0,30.793,13.812,30.793,30.791
|
24 |
+
c0,16.28-12.701,29.641-28.713,30.716v13.34c23.36-1.089,42.027-20.431,42.027-44.056C88.162,31.622,68.376,11.836,44.055,11.836z"
|
25 |
+
/>
|
26 |
+
<path fill="#464342" d="M17.346,91.01c6.901,5.272,15.396,8.559,24.628,8.99V86.659c-5.979-0.403-11.487-2.528-16.05-5.872
|
27 |
+
L17.346,91.01z"/>
|
28 |
+
<path fill="#464342" d="M15.897,68.367L3.361,72.931c2.468,5.887,6.178,11.131,10.842,15.33l8.876-10.566
|
29 |
+
C23.44,78.153,17.183,71.27,15.897,68.367z"/>
|
30 |
+
<path fill="#464342" d="M14.477,64.456c-0.597-2.065-0.989-4.216-1.137-6.434H0c0.177,3.813,0.85,7.495,1.938,10.997L14.477,64.456
|
31 |
+
z"/>
|
32 |
+
</g>
|
33 |
+
</svg>
|
assets/images/wprb-logo.png
ADDED
Binary file
|
assets/js/jquery.magnific-popup.js
ADDED
@@ -0,0 +1,2060 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*! Magnific Popup - v1.0.0 - 2015-01-03
|
2 |
+
* http://dimsemenov.com/plugins/magnific-popup/
|
3 |
+
* Copyright (c) 2015 Dmitry Semenov; */
|
4 |
+
;(function (factory) {
|
5 |
+
if (typeof define === 'function' && define.amd) {
|
6 |
+
// AMD. Register as an anonymous module.
|
7 |
+
define(['jquery'], factory);
|
8 |
+
} else if (typeof exports === 'object') {
|
9 |
+
// Node/CommonJS
|
10 |
+
factory(require('jquery'));
|
11 |
+
} else {
|
12 |
+
// Browser globals
|
13 |
+
factory(window.jQuery || window.Zepto);
|
14 |
+
}
|
15 |
+
}(function($) {
|
16 |
+
|
17 |
+
/*>>core*/
|
18 |
+
/**
|
19 |
+
*
|
20 |
+
* Magnific Popup Core JS file
|
21 |
+
*
|
22 |
+
*/
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Private static constants
|
27 |
+
*/
|
28 |
+
var CLOSE_EVENT = 'Close',
|
29 |
+
BEFORE_CLOSE_EVENT = 'BeforeClose',
|
30 |
+
AFTER_CLOSE_EVENT = 'AfterClose',
|
31 |
+
BEFORE_APPEND_EVENT = 'BeforeAppend',
|
32 |
+
MARKUP_PARSE_EVENT = 'MarkupParse',
|
33 |
+
OPEN_EVENT = 'Open',
|
34 |
+
CHANGE_EVENT = 'Change',
|
35 |
+
NS = 'mfp',
|
36 |
+
EVENT_NS = '.' + NS,
|
37 |
+
READY_CLASS = 'mfp-ready',
|
38 |
+
REMOVING_CLASS = 'mfp-removing',
|
39 |
+
PREVENT_CLOSE_CLASS = 'mfp-prevent-close';
|
40 |
+
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Private vars
|
44 |
+
*/
|
45 |
+
/*jshint -W079 */
|
46 |
+
var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
|
47 |
+
MagnificPopup = function(){},
|
48 |
+
_isJQ = !!(window.jQuery),
|
49 |
+
_prevStatus,
|
50 |
+
_window = $(window),
|
51 |
+
_document,
|
52 |
+
_prevContentType,
|
53 |
+
_wrapClasses,
|
54 |
+
_currPopupType;
|
55 |
+
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Private functions
|
59 |
+
*/
|
60 |
+
var _mfpOn = function(name, f) {
|
61 |
+
mfp.ev.on(NS + name + EVENT_NS, f);
|
62 |
+
},
|
63 |
+
_getEl = function(className, appendTo, html, raw) {
|
64 |
+
var el = document.createElement('div');
|
65 |
+
el.className = 'mfp-'+className;
|
66 |
+
if(html) {
|
67 |
+
el.innerHTML = html;
|
68 |
+
}
|
69 |
+
if(!raw) {
|
70 |
+
el = $(el);
|
71 |
+
if(appendTo) {
|
72 |
+
el.appendTo(appendTo);
|
73 |
+
}
|
74 |
+
} else if(appendTo) {
|
75 |
+
appendTo.appendChild(el);
|
76 |
+
}
|
77 |
+
return el;
|
78 |
+
},
|
79 |
+
_mfpTrigger = function(e, data) {
|
80 |
+
mfp.ev.triggerHandler(NS + e, data);
|
81 |
+
|
82 |
+
if(mfp.st.callbacks) {
|
83 |
+
// converts "mfpEventName" to "eventName" callback and triggers it if it's present
|
84 |
+
e = e.charAt(0).toLowerCase() + e.slice(1);
|
85 |
+
if(mfp.st.callbacks[e]) {
|
86 |
+
mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
|
87 |
+
}
|
88 |
+
}
|
89 |
+
},
|
90 |
+
_getCloseBtn = function(type) {
|
91 |
+
if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
|
92 |
+
mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
|
93 |
+
_currPopupType = type;
|
94 |
+
}
|
95 |
+
return mfp.currTemplate.closeBtn;
|
96 |
+
},
|
97 |
+
// Initialize Magnific Popup only when called at least once
|
98 |
+
_checkInstance = function() {
|
99 |
+
if(!$.magnificPopup.instance) {
|
100 |
+
/*jshint -W020 */
|
101 |
+
mfp = new MagnificPopup();
|
102 |
+
mfp.init();
|
103 |
+
$.magnificPopup.instance = mfp;
|
104 |
+
}
|
105 |
+
},
|
106 |
+
// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
|
107 |
+
supportsTransitions = function() {
|
108 |
+
var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
|
109 |
+
v = ['ms','O','Moz','Webkit']; // 'v' for vendor
|
110 |
+
|
111 |
+
if( s['transition'] !== undefined ) {
|
112 |
+
return true;
|
113 |
+
}
|
114 |
+
|
115 |
+
while( v.length ) {
|
116 |
+
if( v.pop() + 'Transition' in s ) {
|
117 |
+
return true;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
return false;
|
122 |
+
};
|
123 |
+
|
124 |
+
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Public functions
|
128 |
+
*/
|
129 |
+
MagnificPopup.prototype = {
|
130 |
+
|
131 |
+
constructor: MagnificPopup,
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Initializes Magnific Popup plugin.
|
135 |
+
* This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
|
136 |
+
*/
|
137 |
+
init: function() {
|
138 |
+
var appVersion = navigator.appVersion;
|
139 |
+
mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1;
|
140 |
+
mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1;
|
141 |
+
mfp.isLowIE = mfp.isIE7 || mfp.isIE8;
|
142 |
+
mfp.isAndroid = (/android/gi).test(appVersion);
|
143 |
+
mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
|
144 |
+
mfp.supportsTransition = supportsTransitions();
|
145 |
+
|
146 |
+
// We disable fixed positioned lightbox on devices that don't handle it nicely.
|
147 |
+
// If you know a better way of detecting this - let me know.
|
148 |
+
mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
|
149 |
+
_document = $(document);
|
150 |
+
|
151 |
+
mfp.popupsCache = {};
|
152 |
+
},
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Opens popup
|
156 |
+
* @param data [description]
|
157 |
+
*/
|
158 |
+
open: function(data) {
|
159 |
+
|
160 |
+
var i;
|
161 |
+
|
162 |
+
if(data.isObj === false) {
|
163 |
+
// convert jQuery collection to array to avoid conflicts later
|
164 |
+
mfp.items = data.items.toArray();
|
165 |
+
|
166 |
+
mfp.index = 0;
|
167 |
+
var items = data.items,
|
168 |
+
item;
|
169 |
+
for(i = 0; i < items.length; i++) {
|
170 |
+
item = items[i];
|
171 |
+
if(item.parsed) {
|
172 |
+
item = item.el[0];
|
173 |
+
}
|
174 |
+
if(item === data.el[0]) {
|
175 |
+
mfp.index = i;
|
176 |
+
break;
|
177 |
+
}
|
178 |
+
}
|
179 |
+
} else {
|
180 |
+
mfp.items = $.isArray(data.items) ? data.items : [data.items];
|
181 |
+
mfp.index = data.index || 0;
|
182 |
+
}
|
183 |
+
|
184 |
+
// if popup is already opened - we just update the content
|
185 |
+
if(mfp.isOpen) {
|
186 |
+
mfp.updateItemHTML();
|
187 |
+
return;
|
188 |
+
}
|
189 |
+
|
190 |
+
mfp.types = [];
|
191 |
+
_wrapClasses = '';
|
192 |
+
if(data.mainEl && data.mainEl.length) {
|
193 |
+
mfp.ev = data.mainEl.eq(0);
|
194 |
+
} else {
|
195 |
+
mfp.ev = _document;
|
196 |
+
}
|
197 |
+
|
198 |
+
if(data.key) {
|
199 |
+
if(!mfp.popupsCache[data.key]) {
|
200 |
+
mfp.popupsCache[data.key] = {};
|
201 |
+
}
|
202 |
+
mfp.currTemplate = mfp.popupsCache[data.key];
|
203 |
+
} else {
|
204 |
+
mfp.currTemplate = {};
|
205 |
+
}
|
206 |
+
|
207 |
+
|
208 |
+
|
209 |
+
mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
|
210 |
+
mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;
|
211 |
+
|
212 |
+
if(mfp.st.modal) {
|
213 |
+
mfp.st.closeOnContentClick = false;
|
214 |
+
mfp.st.closeOnBgClick = false;
|
215 |
+
mfp.st.showCloseBtn = false;
|
216 |
+
mfp.st.enableEscapeKey = false;
|
217 |
+
}
|
218 |
+
|
219 |
+
|
220 |
+
// Building markup
|
221 |
+
// main containers are created only once
|
222 |
+
if(!mfp.bgOverlay) {
|
223 |
+
|
224 |
+
// Dark overlay
|
225 |
+
mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
|
226 |
+
mfp.close();
|
227 |
+
});
|
228 |
+
|
229 |
+
mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
|
230 |
+
if(mfp._checkIfClose(e.target)) {
|
231 |
+
mfp.close();
|
232 |
+
}
|
233 |
+
});
|
234 |
+
|
235 |
+
mfp.container = _getEl('container', mfp.wrap);
|
236 |
+
}
|
237 |
+
|
238 |
+
mfp.contentContainer = _getEl('content');
|
239 |
+
if(mfp.st.preloader) {
|
240 |
+
mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
|
241 |
+
}
|
242 |
+
|
243 |
+
|
244 |
+
// Initializing modules
|
245 |
+
var modules = $.magnificPopup.modules;
|
246 |
+
for(i = 0; i < modules.length; i++) {
|
247 |
+
var n = modules[i];
|
248 |
+
n = n.charAt(0).toUpperCase() + n.slice(1);
|
249 |
+
mfp['init'+n].call(mfp);
|
250 |
+
}
|
251 |
+
_mfpTrigger('BeforeOpen');
|
252 |
+
|
253 |
+
|
254 |
+
if(mfp.st.showCloseBtn) {
|
255 |
+
// Close button
|
256 |
+
if(!mfp.st.closeBtnInside) {
|
257 |
+
mfp.wrap.append( _getCloseBtn() );
|
258 |
+
} else {
|
259 |
+
_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
|
260 |
+
values.close_replaceWith = _getCloseBtn(item.type);
|
261 |
+
});
|
262 |
+
_wrapClasses += ' mfp-close-btn-in';
|
263 |
+
}
|
264 |
+
}
|
265 |
+
|
266 |
+
if(mfp.st.alignTop) {
|
267 |
+
_wrapClasses += ' mfp-align-top';
|
268 |
+
}
|
269 |
+
|
270 |
+
|
271 |
+
|
272 |
+
if(mfp.fixedContentPos) {
|
273 |
+
mfp.wrap.css({
|
274 |
+
overflow: mfp.st.overflowY,
|
275 |
+
overflowX: 'hidden',
|
276 |
+
overflowY: mfp.st.overflowY
|
277 |
+
});
|
278 |
+
} else {
|
279 |
+
mfp.wrap.css({
|
280 |
+
top: _window.scrollTop(),
|
281 |
+
position: 'absolute'
|
282 |
+
});
|
283 |
+
}
|
284 |
+
if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
|
285 |
+
mfp.bgOverlay.css({
|
286 |
+
height: _document.height(),
|
287 |
+
position: 'absolute'
|
288 |
+
});
|
289 |
+
}
|
290 |
+
|
291 |
+
|
292 |
+
|
293 |
+
if(mfp.st.enableEscapeKey) {
|
294 |
+
// Close on ESC key
|
295 |
+
_document.on('keyup' + EVENT_NS, function(e) {
|
296 |
+
if(e.keyCode === 27) {
|
297 |
+
mfp.close();
|
298 |
+
}
|
299 |
+
});
|
300 |
+
}
|
301 |
+
|
302 |
+
_window.on('resize' + EVENT_NS, function() {
|
303 |
+
mfp.updateSize();
|
304 |
+
});
|
305 |
+
|
306 |
+
|
307 |
+
if(!mfp.st.closeOnContentClick) {
|
308 |
+
_wrapClasses += ' mfp-auto-cursor';
|
309 |
+
}
|
310 |
+
|
311 |
+
if(_wrapClasses)
|
312 |
+
mfp.wrap.addClass(_wrapClasses);
|
313 |
+
|
314 |
+
|
315 |
+
// this triggers recalculation of layout, so we get it once to not to trigger twice
|
316 |
+
var windowHeight = mfp.wH = _window.height();
|
317 |
+
|
318 |
+
|
319 |
+
var windowStyles = {};
|
320 |
+
|
321 |
+
if( mfp.fixedContentPos ) {
|
322 |
+
if(mfp._hasScrollBar(windowHeight)){
|
323 |
+
var s = mfp._getScrollbarSize();
|
324 |
+
if(s) {
|
325 |
+
windowStyles.marginRight = s;
|
326 |
+
}
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
if(mfp.fixedContentPos) {
|
331 |
+
if(!mfp.isIE7) {
|
332 |
+
windowStyles.overflow = 'hidden';
|
333 |
+
} else {
|
334 |
+
// ie7 double-scroll bug
|
335 |
+
$('body, html').css('overflow', 'hidden');
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
|
340 |
+
|
341 |
+
var classesToadd = mfp.st.mainClass;
|
342 |
+
if(mfp.isIE7) {
|
343 |
+
classesToadd += ' mfp-ie7';
|
344 |
+
}
|
345 |
+
if(classesToadd) {
|
346 |
+
mfp._addClassToMFP( classesToadd );
|
347 |
+
}
|
348 |
+
|
349 |
+
// add content
|
350 |
+
mfp.updateItemHTML();
|
351 |
+
|
352 |
+
_mfpTrigger('BuildControls');
|
353 |
+
|
354 |
+
// remove scrollbar, add margin e.t.c
|
355 |
+
$('html').css(windowStyles);
|
356 |
+
|
357 |
+
// add everything to DOM
|
358 |
+
mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) );
|
359 |
+
|
360 |
+
// Save last focused element
|
361 |
+
mfp._lastFocusedEl = document.activeElement;
|
362 |
+
|
363 |
+
// Wait for next cycle to allow CSS transition
|
364 |
+
setTimeout(function() {
|
365 |
+
|
366 |
+
if(mfp.content) {
|
367 |
+
mfp._addClassToMFP(READY_CLASS);
|
368 |
+
mfp._setFocus();
|
369 |
+
} else {
|
370 |
+
// if content is not defined (not loaded e.t.c) we add class only for BG
|
371 |
+
mfp.bgOverlay.addClass(READY_CLASS);
|
372 |
+
}
|
373 |
+
|
374 |
+
// Trap the focus in popup
|
375 |
+
_document.on('focusin' + EVENT_NS, mfp._onFocusIn);
|
376 |
+
|
377 |
+
}, 16);
|
378 |
+
|
379 |
+
mfp.isOpen = true;
|
380 |
+
mfp.updateSize(windowHeight);
|
381 |
+
_mfpTrigger(OPEN_EVENT);
|
382 |
+
|
383 |
+
return data;
|
384 |
+
},
|
385 |
+
|
386 |
+
/**
|
387 |
+
* Closes the popup
|
388 |
+
*/
|
389 |
+
close: function() {
|
390 |
+
if(!mfp.isOpen) return;
|
391 |
+
_mfpTrigger(BEFORE_CLOSE_EVENT);
|
392 |
+
|
393 |
+
mfp.isOpen = false;
|
394 |
+
// for CSS3 animation
|
395 |
+
if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) {
|
396 |
+
mfp._addClassToMFP(REMOVING_CLASS);
|
397 |
+
setTimeout(function() {
|
398 |
+
mfp._close();
|
399 |
+
}, mfp.st.removalDelay);
|
400 |
+
} else {
|
401 |
+
mfp._close();
|
402 |
+
}
|
403 |
+
},
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Helper for close() function
|
407 |
+
*/
|
408 |
+
_close: function() {
|
409 |
+
_mfpTrigger(CLOSE_EVENT);
|
410 |
+
|
411 |
+
var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';
|
412 |
+
|
413 |
+
mfp.bgOverlay.detach();
|
414 |
+
mfp.wrap.detach();
|
415 |
+
mfp.container.empty();
|
416 |
+
|
417 |
+
if(mfp.st.mainClass) {
|
418 |
+
classesToRemove += mfp.st.mainClass + ' ';
|
419 |
+
}
|
420 |
+
|
421 |
+
mfp._removeClassFromMFP(classesToRemove);
|
422 |
+
|
423 |
+
if(mfp.fixedContentPos) {
|
424 |
+
var windowStyles = {marginRight: ''};
|
425 |
+
if(mfp.isIE7) {
|
426 |
+
$('body, html').css('overflow', '');
|
427 |
+
} else {
|
428 |
+
windowStyles.overflow = '';
|
429 |
+
}
|
430 |
+
$('html').css(windowStyles);
|
431 |
+
}
|
432 |
+
|
433 |
+
_document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
|
434 |
+
mfp.ev.off(EVENT_NS);
|
435 |
+
|
436 |
+
// clean up DOM elements that aren't removed
|
437 |
+
mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
|
438 |
+
mfp.bgOverlay.attr('class', 'mfp-bg');
|
439 |
+
mfp.container.attr('class', 'mfp-container');
|
440 |
+
|
441 |
+
// remove close button from target element
|
442 |
+
if(mfp.st.showCloseBtn &&
|
443 |
+
(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
|
444 |
+
if(mfp.currTemplate.closeBtn)
|
445 |
+
mfp.currTemplate.closeBtn.detach();
|
446 |
+
}
|
447 |
+
|
448 |
+
|
449 |
+
if(mfp._lastFocusedEl) {
|
450 |
+
$(mfp._lastFocusedEl).focus(); // put tab focus back
|
451 |
+
}
|
452 |
+
mfp.currItem = null;
|
453 |
+
mfp.content = null;
|
454 |
+
mfp.currTemplate = null;
|
455 |
+
mfp.prevHeight = 0;
|
456 |
+
|
457 |
+
_mfpTrigger(AFTER_CLOSE_EVENT);
|
458 |
+
},
|
459 |
+
|
460 |
+
updateSize: function(winHeight) {
|
461 |
+
|
462 |
+
if(mfp.isIOS) {
|
463 |
+
// fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
|
464 |
+
var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
|
465 |
+
var height = window.innerHeight * zoomLevel;
|
466 |
+
mfp.wrap.css('height', height);
|
467 |
+
mfp.wH = height;
|
468 |
+
} else {
|
469 |
+
mfp.wH = winHeight || _window.height();
|
470 |
+
}
|
471 |
+
// Fixes #84: popup incorrectly positioned with position:relative on body
|
472 |
+
if(!mfp.fixedContentPos) {
|
473 |
+
mfp.wrap.css('height', mfp.wH);
|
474 |
+
}
|
475 |
+
|
476 |
+
_mfpTrigger('Resize');
|
477 |
+
|
478 |
+
},
|
479 |
+
|
480 |
+
/**
|
481 |
+
* Set content of popup based on current index
|
482 |
+
*/
|
483 |
+
updateItemHTML: function() {
|
484 |
+
var item = mfp.items[mfp.index];
|
485 |
+
|
486 |
+
// Detach and perform modifications
|
487 |
+
mfp.contentContainer.detach();
|
488 |
+
|
489 |
+
if(mfp.content)
|
490 |
+
mfp.content.detach();
|
491 |
+
|
492 |
+
if(!item.parsed) {
|
493 |
+
item = mfp.parseEl( mfp.index );
|
494 |
+
}
|
495 |
+
|
496 |
+
var type = item.type;
|
497 |
+
|
498 |
+
_mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
|
499 |
+
// BeforeChange event works like so:
|
500 |
+
// _mfpOn('BeforeChange', function(e, prevType, newType) { });
|
501 |
+
|
502 |
+
mfp.currItem = item;
|
503 |
+
|
504 |
+
|
505 |
+
|
506 |
+
|
507 |
+
|
508 |
+
if(!mfp.currTemplate[type]) {
|
509 |
+
var markup = mfp.st[type] ? mfp.st[type].markup : false;
|
510 |
+
|
511 |
+
// allows to modify markup
|
512 |
+
_mfpTrigger('FirstMarkupParse', markup);
|
513 |
+
|
514 |
+
if(markup) {
|
515 |
+
mfp.currTemplate[type] = $(markup);
|
516 |
+
} else {
|
517 |
+
// if there is no markup found we just define that template is parsed
|
518 |
+
mfp.currTemplate[type] = true;
|
519 |
+
}
|
520 |
+
}
|
521 |
+
|
522 |
+
if(_prevContentType && _prevContentType !== item.type) {
|
523 |
+
mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
|
524 |
+
}
|
525 |
+
|
526 |
+
var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
|
527 |
+
mfp.appendContent(newContent, type);
|
528 |
+
|
529 |
+
item.preloaded = true;
|
530 |
+
|
531 |
+
_mfpTrigger(CHANGE_EVENT, item);
|
532 |
+
_prevContentType = item.type;
|
533 |
+
|
534 |
+
// Append container back after its content changed
|
535 |
+
mfp.container.prepend(mfp.contentContainer);
|
536 |
+
|
537 |
+
_mfpTrigger('AfterChange');
|
538 |
+
},
|
539 |
+
|
540 |
+
|
541 |
+
/**
|
542 |
+
* Set HTML content of popup
|
543 |
+
*/
|
544 |
+
appendContent: function(newContent, type) {
|
545 |
+
mfp.content = newContent;
|
546 |
+
|
547 |
+
if(newContent) {
|
548 |
+
if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
|
549 |
+
mfp.currTemplate[type] === true) {
|
550 |
+
// if there is no markup, we just append close button element inside
|
551 |
+
if(!mfp.content.find('.mfp-close').length) {
|
552 |
+
mfp.content.append(_getCloseBtn());
|
553 |
+
}
|
554 |
+
} else {
|
555 |
+
mfp.content = newContent;
|
556 |
+
}
|
557 |
+
} else {
|
558 |
+
mfp.content = '';
|
559 |
+
}
|
560 |
+
|
561 |
+
_mfpTrigger(BEFORE_APPEND_EVENT);
|
562 |
+
mfp.container.addClass('mfp-'+type+'-holder');
|
563 |
+
|
564 |
+
mfp.contentContainer.append(mfp.content);
|
565 |
+
},
|
566 |
+
|
567 |
+
|
568 |
+
|
569 |
+
|
570 |
+
/**
|
571 |
+
* Creates Magnific Popup data object based on given data
|
572 |
+
* @param {int} index Index of item to parse
|
573 |
+
*/
|
574 |
+
parseEl: function(index) {
|
575 |
+
var item = mfp.items[index],
|
576 |
+
type;
|
577 |
+
|
578 |
+
if(item.tagName) {
|
579 |
+
item = { el: $(item) };
|
580 |
+
} else {
|
581 |
+
type = item.type;
|
582 |
+
item = { data: item, src: item.src };
|
583 |
+
}
|
584 |
+
|
585 |
+
if(item.el) {
|
586 |
+
var types = mfp.types;
|
587 |
+
|
588 |
+
// check for 'mfp-TYPE' class
|
589 |
+
for(var i = 0; i < types.length; i++) {
|
590 |
+
if( item.el.hasClass('mfp-'+types[i]) ) {
|
591 |
+
type = types[i];
|
592 |
+
break;
|
593 |
+
}
|
594 |
+
}
|
595 |
+
|
596 |
+
item.src = item.el.attr('data-mfp-src');
|
597 |
+
if(!item.src) {
|
598 |
+
item.src = item.el.attr('href');
|
599 |
+
}
|
600 |
+
}
|
601 |
+
|
602 |
+
item.type = type || mfp.st.type || 'inline';
|
603 |
+
item.index = index;
|
604 |
+
item.parsed = true;
|
605 |
+
mfp.items[index] = item;
|
606 |
+
_mfpTrigger('ElementParse', item);
|
607 |
+
|
608 |
+
return mfp.items[index];
|
609 |
+
},
|
610 |
+
|
611 |
+
|
612 |
+
/**
|
613 |
+
* Initializes single popup or a group of popups
|
614 |
+
*/
|
615 |
+
addGroup: function(el, options) {
|
616 |
+
var eHandler = function(e) {
|
617 |
+
e.mfpEl = this;
|
618 |
+
mfp._openClick(e, el, options);
|
619 |
+
};
|
620 |
+
|
621 |
+
if(!options) {
|
622 |
+
options = {};
|
623 |
+
}
|
624 |
+
|
625 |
+
var eName = 'click.magnificPopup';
|
626 |
+
options.mainEl = el;
|
627 |
+
|
628 |
+
if(options.items) {
|
629 |
+
options.isObj = true;
|
630 |
+
el.off(eName).on(eName, eHandler);
|
631 |
+
} else {
|
632 |
+
options.isObj = false;
|
633 |
+
if(options.delegate) {
|
634 |
+
el.off(eName).on(eName, options.delegate , eHandler);
|
635 |
+
} else {
|
636 |
+
options.items = el;
|
637 |
+
el.off(eName).on(eName, eHandler);
|
638 |
+
}
|
639 |
+
}
|
640 |
+
},
|
641 |
+
_openClick: function(e, el, options) {
|
642 |
+
var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;
|
643 |
+
|
644 |
+
|
645 |
+
if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) {
|
646 |
+
return;
|
647 |
+
}
|
648 |
+
|
649 |
+
var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;
|
650 |
+
|
651 |
+
if(disableOn) {
|
652 |
+
if($.isFunction(disableOn)) {
|
653 |
+
if( !disableOn.call(mfp) ) {
|
654 |
+
return true;
|
655 |
+
}
|
656 |
+
} else { // else it's number
|
657 |
+
if( _window.width() < disableOn ) {
|
658 |
+
return true;
|
659 |
+
}
|
660 |
+
}
|
661 |
+
}
|
662 |
+
|
663 |
+
if(e.type) {
|
664 |
+
e.preventDefault();
|
665 |
+
|
666 |
+
// This will prevent popup from closing if element is inside and popup is already opened
|
667 |
+
if(mfp.isOpen) {
|
668 |
+
e.stopPropagation();
|
669 |
+
}
|
670 |
+
}
|
671 |
+
|
672 |
+
|
673 |
+
options.el = $(e.mfpEl);
|
674 |
+
if(options.delegate) {
|
675 |
+
options.items = el.find(options.delegate);
|
676 |
+
}
|
677 |
+
mfp.open(options);
|
678 |
+
},
|
679 |
+
|
680 |
+
|
681 |
+
/**
|
682 |
+
* Updates text on preloader
|
683 |
+
*/
|
684 |
+
updateStatus: function(status, text) {
|
685 |
+
|
686 |
+
if(mfp.preloader) {
|
687 |
+
if(_prevStatus !== status) {
|
688 |
+
mfp.container.removeClass('mfp-s-'+_prevStatus);
|
689 |
+
}
|
690 |
+
|
691 |
+
if(!text && status === 'loading') {
|
692 |
+
text = mfp.st.tLoading;
|
693 |
+
}
|
694 |
+
|
695 |
+
var data = {
|
696 |
+
status: status,
|
697 |
+
text: text
|
698 |
+
};
|
699 |
+
// allows to modify status
|
700 |
+
_mfpTrigger('UpdateStatus', data);
|
701 |
+
|
702 |
+
status = data.status;
|
703 |
+
text = data.text;
|
704 |
+
|
705 |
+
mfp.preloader.html(text);
|
706 |
+
|
707 |
+
mfp.preloader.find('a').on('click', function(e) {
|
708 |
+
e.stopImmediatePropagation();
|
709 |
+
});
|
710 |
+
|
711 |
+
mfp.container.addClass('mfp-s-'+status);
|
712 |
+
_prevStatus = status;
|
713 |
+
}
|
714 |
+
},
|
715 |
+
|
716 |
+
|
717 |
+
/*
|
718 |
+
"Private" helpers that aren't private at all
|
719 |
+
*/
|
720 |
+
// Check to close popup or not
|
721 |
+
// "target" is an element that was clicked
|
722 |
+
_checkIfClose: function(target) {
|
723 |
+
|
724 |
+
if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
|
725 |
+
return;
|
726 |
+
}
|
727 |
+
|
728 |
+
var closeOnContent = mfp.st.closeOnContentClick;
|
729 |
+
var closeOnBg = mfp.st.closeOnBgClick;
|
730 |
+
|
731 |
+
if(closeOnContent && closeOnBg) {
|
732 |
+
return true;
|
733 |
+
} else {
|
734 |
+
|
735 |
+
// We close the popup if click is on close button or on preloader. Or if there is no content.
|
736 |
+
if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
|
737 |
+
return true;
|
738 |
+
}
|
739 |
+
|
740 |
+
// if click is outside the content
|
741 |
+
if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) {
|
742 |
+
if(closeOnBg) {
|
743 |
+
// last check, if the clicked element is in DOM, (in case it's removed onclick)
|
744 |
+
if( $.contains(document, target) ) {
|
745 |
+
return true;
|
746 |
+
}
|
747 |
+
}
|
748 |
+
} else if(closeOnContent) {
|
749 |
+
return true;
|
750 |
+
}
|
751 |
+
|
752 |
+
}
|
753 |
+
return false;
|
754 |
+
},
|
755 |
+
_addClassToMFP: function(cName) {
|
756 |
+
mfp.bgOverlay.addClass(cName);
|
757 |
+
mfp.wrap.addClass(cName);
|
758 |
+
},
|
759 |
+
_removeClassFromMFP: function(cName) {
|
760 |
+
this.bgOverlay.removeClass(cName);
|
761 |
+
mfp.wrap.removeClass(cName);
|
762 |
+
},
|
763 |
+
_hasScrollBar: function(winHeight) {
|
764 |
+
return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
|
765 |
+
},
|
766 |
+
_setFocus: function() {
|
767 |
+
(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
|
768 |
+
},
|
769 |
+
_onFocusIn: function(e) {
|
770 |
+
if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
|
771 |
+
mfp._setFocus();
|
772 |
+
return false;
|
773 |
+
}
|
774 |
+
},
|
775 |
+
_parseMarkup: function(template, values, item) {
|
776 |
+
var arr;
|
777 |
+
if(item.data) {
|
778 |
+
values = $.extend(item.data, values);
|
779 |
+
}
|
780 |
+
_mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );
|
781 |
+
|
782 |
+
$.each(values, function(key, value) {
|
783 |
+
if(value === undefined || value === false) {
|
784 |
+
return true;
|
785 |
+
}
|
786 |
+
arr = key.split('_');
|
787 |
+
if(arr.length > 1) {
|
788 |
+
var el = template.find(EVENT_NS + '-'+arr[0]);
|
789 |
+
|
790 |
+
if(el.length > 0) {
|
791 |
+
var attr = arr[1];
|
792 |
+
if(attr === 'replaceWith') {
|
793 |
+
if(el[0] !== value[0]) {
|
794 |
+
el.replaceWith(value);
|
795 |
+
}
|
796 |
+
} else if(attr === 'img') {
|
797 |
+
if(el.is('img')) {
|
798 |
+
el.attr('src', value);
|
799 |
+
} else {
|
800 |
+
el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' );
|
801 |
+
}
|
802 |
+
} else {
|
803 |
+
el.attr(arr[1], value);
|
804 |
+
}
|
805 |
+
}
|
806 |
+
|
807 |
+
} else {
|
808 |
+
template.find(EVENT_NS + '-'+key).html(value);
|
809 |
+
}
|
810 |
+
});
|
811 |
+
},
|
812 |
+
|
813 |
+
_getScrollbarSize: function() {
|
814 |
+
// thx David
|
815 |
+
if(mfp.scrollbarSize === undefined) {
|
816 |
+
var scrollDiv = document.createElement("div");
|
817 |
+
scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
|
818 |
+
document.body.appendChild(scrollDiv);
|
819 |
+
mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
|
820 |
+
document.body.removeChild(scrollDiv);
|
821 |
+
}
|
822 |
+
return mfp.scrollbarSize;
|
823 |
+
}
|
824 |
+
|
825 |
+
}; /* MagnificPopup core prototype end */
|
826 |
+
|
827 |
+
|
828 |
+
|
829 |
+
|
830 |
+
/**
|
831 |
+
* Public static functions
|
832 |
+
*/
|
833 |
+
$.magnificPopup = {
|
834 |
+
instance: null,
|
835 |
+
proto: MagnificPopup.prototype,
|
836 |
+
modules: [],
|
837 |
+
|
838 |
+
open: function(options, index) {
|
839 |
+
_checkInstance();
|
840 |
+
|
841 |
+
if(!options) {
|
842 |
+
options = {};
|
843 |
+
} else {
|
844 |
+
options = $.extend(true, {}, options);
|
845 |
+
}
|
846 |
+
|
847 |
+
|
848 |
+
options.isObj = true;
|
849 |
+
options.index = index || 0;
|
850 |
+
return this.instance.open(options);
|
851 |
+
},
|
852 |
+
|
853 |
+
close: function() {
|
854 |
+
return $.magnificPopup.instance && $.magnificPopup.instance.close();
|
855 |
+
},
|
856 |
+
|
857 |
+
registerModule: function(name, module) {
|
858 |
+
if(module.options) {
|
859 |
+
$.magnificPopup.defaults[name] = module.options;
|
860 |
+
}
|
861 |
+
$.extend(this.proto, module.proto);
|
862 |
+
this.modules.push(name);
|
863 |
+
},
|
864 |
+
|
865 |
+
defaults: {
|
866 |
+
|
867 |
+
// Info about options is in docs:
|
868 |
+
// http://dimsemenov.com/plugins/magnific-popup/documentation.html#options
|
869 |
+
|
870 |
+
disableOn: 0,
|
871 |
+
|
872 |
+
key: null,
|
873 |
+
|
874 |
+
midClick: false,
|
875 |
+
|
876 |
+
mainClass: '',
|
877 |
+
|
878 |
+
preloader: true,
|
879 |
+
|
880 |
+
focus: '', // CSS selector of input to focus after popup is opened
|
881 |
+
|
882 |
+
closeOnContentClick: false,
|
883 |
+
|
884 |
+
closeOnBgClick: true,
|
885 |
+
|
886 |
+
closeBtnInside: true,
|
887 |
+
|
888 |
+
showCloseBtn: true,
|
889 |
+
|
890 |
+
enableEscapeKey: true,
|
891 |
+
|
892 |
+
modal: false,
|
893 |
+
|
894 |
+
alignTop: false,
|
895 |
+
|
896 |
+
removalDelay: 0,
|
897 |
+
|
898 |
+
prependTo: null,
|
899 |
+
|
900 |
+
fixedContentPos: 'auto',
|
901 |
+
|
902 |
+
fixedBgPos: 'auto',
|
903 |
+
|
904 |
+
overflowY: 'auto',
|
905 |
+
|
906 |
+
closeMarkup: '<button title="%title%" type="button" class="mfp-close">×</button>',
|
907 |
+
|
908 |
+
tClose: 'Close (Esc)',
|
909 |
+
|
910 |
+
tLoading: 'Loading...'
|
911 |
+
|
912 |
+
}
|
913 |
+
};
|
914 |
+
|
915 |
+
|
916 |
+
|
917 |
+
$.fn.magnificPopup = function(options) {
|
918 |
+
_checkInstance();
|
919 |
+
|
920 |
+
var jqEl = $(this);
|
921 |
+
|
922 |
+
// We call some API method of first param is a string
|
923 |
+
if (typeof options === "string" ) {
|
924 |
+
|
925 |
+
if(options === 'open') {
|
926 |
+
var items,
|
927 |
+
itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
|
928 |
+
index = parseInt(arguments[1], 10) || 0;
|
929 |
+
|
930 |
+
if(itemOpts.items) {
|
931 |
+
items = itemOpts.items[index];
|
932 |
+
} else {
|
933 |
+
items = jqEl;
|
934 |
+
if(itemOpts.delegate) {
|
935 |
+
items = items.find(itemOpts.delegate);
|
936 |
+
}
|
937 |
+
items = items.eq( index );
|
938 |
+
}
|
939 |
+
mfp._openClick({mfpEl:items}, jqEl, itemOpts);
|
940 |
+
} else {
|
941 |
+
if(mfp.isOpen)
|
942 |
+
mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
|
943 |
+
}
|
944 |
+
|
945 |
+
} else {
|
946 |
+
// clone options obj
|
947 |
+
options = $.extend(true, {}, options);
|
948 |
+
|
949 |
+
/*
|
950 |
+
* As Zepto doesn't support .data() method for objects
|
951 |
+
* and it works only in normal browsers
|
952 |
+
* we assign "options" object directly to the DOM element. FTW!
|
953 |
+
*/
|
954 |
+
if(_isJQ) {
|
955 |
+
jqEl.data('magnificPopup', options);
|
956 |
+
} else {
|
957 |
+
jqEl[0].magnificPopup = options;
|
958 |
+
}
|
959 |
+
|
960 |
+
mfp.addGroup(jqEl, options);
|
961 |
+
|
962 |
+
}
|
963 |
+
return jqEl;
|
964 |
+
};
|
965 |
+
|
966 |
+
|
967 |
+
//Quick benchmark
|
968 |
+
/*
|
969 |
+
var start = performance.now(),
|
970 |
+
i,
|
971 |
+
rounds = 1000;
|
972 |
+
|
973 |
+
for(i = 0; i < rounds; i++) {
|
974 |
+
|
975 |
+
}
|
976 |
+
console.log('Test #1:', performance.now() - start);
|
977 |
+
|
978 |
+
start = performance.now();
|
979 |
+
for(i = 0; i < rounds; i++) {
|
980 |
+
|
981 |
+
}
|
982 |
+
console.log('Test #2:', performance.now() - start);
|
983 |
+
*/
|
984 |
+
|
985 |
+
|
986 |
+
/*>>core*/
|
987 |
+
|
988 |
+
/*>>inline*/
|
989 |
+
|
990 |
+
var INLINE_NS = 'inline',
|
991 |
+
_hiddenClass,
|
992 |
+
_inlinePlaceholder,
|
993 |
+
_lastInlineElement,
|
994 |
+
_putInlineElementsBack = function() {
|
995 |
+
if(_lastInlineElement) {
|
996 |
+
_inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
|
997 |
+
_lastInlineElement = null;
|
998 |
+
}
|
999 |
+
};
|
1000 |
+
|
1001 |
+
$.magnificPopup.registerModule(INLINE_NS, {
|
1002 |
+
options: {
|
1003 |
+
hiddenClass: 'hide', // will be appended with `mfp-` prefix
|
1004 |
+
markup: '',
|
1005 |
+
tNotFound: 'Content not found'
|
1006 |
+
},
|
1007 |
+
proto: {
|
1008 |
+
|
1009 |
+
initInline: function() {
|
1010 |
+
mfp.types.push(INLINE_NS);
|
1011 |
+
|
1012 |
+
_mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
|
1013 |
+
_putInlineElementsBack();
|
1014 |
+
});
|
1015 |
+
},
|
1016 |
+
|
1017 |
+
getInline: function(item, template) {
|
1018 |
+
|
1019 |
+
_putInlineElementsBack();
|
1020 |
+
|
1021 |
+
if(item.src) {
|
1022 |
+
var inlineSt = mfp.st.inline,
|
1023 |
+
el = $(item.src);
|
1024 |
+
|
1025 |
+
if(el.length) {
|
1026 |
+
|
1027 |
+
// If target element has parent - we replace it with placeholder and put it back after popup is closed
|
1028 |
+
var parent = el[0].parentNode;
|
1029 |
+
if(parent && parent.tagName) {
|
1030 |
+
if(!_inlinePlaceholder) {
|
1031 |
+
_hiddenClass = inlineSt.hiddenClass;
|
1032 |
+
_inlinePlaceholder = _getEl(_hiddenClass);
|
1033 |
+
_hiddenClass = 'mfp-'+_hiddenClass;
|
1034 |
+
}
|
1035 |
+
// replace target inline element with placeholder
|
1036 |
+
_lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
|
1037 |
+
}
|
1038 |
+
|
1039 |
+
mfp.updateStatus('ready');
|
1040 |
+
} else {
|
1041 |
+
mfp.updateStatus('error', inlineSt.tNotFound);
|
1042 |
+
el = $('<div>');
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
item.inlineElement = el;
|
1046 |
+
return el;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
mfp.updateStatus('ready');
|
1050 |
+
mfp._parseMarkup(template, {}, item);
|
1051 |
+
return template;
|
1052 |
+
}
|
1053 |
+
}
|
1054 |
+
});
|
1055 |
+
|
1056 |
+
/*>>inline*/
|
1057 |
+
|
1058 |
+
/*>>ajax*/
|
1059 |
+
var AJAX_NS = 'ajax',
|
1060 |
+
_ajaxCur,
|
1061 |
+
_removeAjaxCursor = function() {
|
1062 |
+
if(_ajaxCur) {
|
1063 |
+
$(document.body).removeClass(_ajaxCur);
|
1064 |
+
}
|
1065 |
+
},
|
1066 |
+
_destroyAjaxRequest = function() {
|
1067 |
+
_removeAjaxCursor();
|
1068 |
+
if(mfp.req) {
|
1069 |
+
mfp.req.abort();
|
1070 |
+
}
|
1071 |
+
};
|
1072 |
+
|
1073 |
+
$.magnificPopup.registerModule(AJAX_NS, {
|
1074 |
+
|
1075 |
+
options: {
|
1076 |
+
settings: null,
|
1077 |
+
cursor: 'mfp-ajax-cur',
|
1078 |
+
tError: '<a href="%url%">The content</a> could not be loaded.'
|
1079 |
+
},
|
1080 |
+
|
1081 |
+
proto: {
|
1082 |
+
initAjax: function() {
|
1083 |
+
mfp.types.push(AJAX_NS);
|
1084 |
+
_ajaxCur = mfp.st.ajax.cursor;
|
1085 |
+
|
1086 |
+
_mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
|
1087 |
+
_mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
|
1088 |
+
},
|
1089 |
+
getAjax: function(item) {
|
1090 |
+
|
1091 |
+
if(_ajaxCur) {
|
1092 |
+
$(document.body).addClass(_ajaxCur);
|
1093 |
+
}
|
1094 |
+
|
1095 |
+
mfp.updateStatus('loading');
|
1096 |
+
|
1097 |
+
var opts = $.extend({
|
1098 |
+
url: item.src,
|
1099 |
+
success: function(data, textStatus, jqXHR) {
|
1100 |
+
var temp = {
|
1101 |
+
data:data,
|
1102 |
+
xhr:jqXHR
|
1103 |
+
};
|
1104 |
+
|
1105 |
+
_mfpTrigger('ParseAjax', temp);
|
1106 |
+
|
1107 |
+
mfp.appendContent( $(temp.data), AJAX_NS );
|
1108 |
+
|
1109 |
+
item.finished = true;
|
1110 |
+
|
1111 |
+
_removeAjaxCursor();
|
1112 |
+
|
1113 |
+
mfp._setFocus();
|
1114 |
+
|
1115 |
+
setTimeout(function() {
|
1116 |
+
mfp.wrap.addClass(READY_CLASS);
|
1117 |
+
}, 16);
|
1118 |
+
|
1119 |
+
mfp.updateStatus('ready');
|
1120 |
+
|
1121 |
+
_mfpTrigger('AjaxContentAdded');
|
1122 |
+
},
|
1123 |
+
error: function() {
|
1124 |
+
_removeAjaxCursor();
|
1125 |
+
item.finished = item.loadError = true;
|
1126 |
+
mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
|
1127 |
+
}
|
1128 |
+
}, mfp.st.ajax.settings);
|
1129 |
+
|
1130 |
+
mfp.req = $.ajax(opts);
|
1131 |
+
|
1132 |
+
return '';
|
1133 |
+
}
|
1134 |
+
}
|
1135 |
+
});
|
1136 |
+
|
1137 |
+
|
1138 |
+
|
1139 |
+
|
1140 |
+
|
1141 |
+
|
1142 |
+
|
1143 |
+
/*>>ajax*/
|
1144 |
+
|
1145 |
+
/*>>image*/
|
1146 |
+
var _imgInterval,
|
1147 |
+
_getTitle = function(item) {
|
1148 |
+
if(item.data && item.data.title !== undefined)
|
1149 |
+
return item.data.title;
|
1150 |
+
|
1151 |
+
var src = mfp.st.image.titleSrc;
|
1152 |
+
|
1153 |
+
if(src) {
|
1154 |
+
if($.isFunction(src)) {
|
1155 |
+
return src.call(mfp, item);
|
1156 |
+
} else if(item.el) {
|
1157 |
+
return item.el.attr(src) || '';
|
1158 |
+
}
|
1159 |
+
}
|
1160 |
+
return '';
|
1161 |
+
};
|
1162 |
+
|
1163 |
+
$.magnificPopup.registerModule('image', {
|
1164 |
+
|
1165 |
+
options: {
|
1166 |
+
markup: '<div class="mfp-figure">'+
|
1167 |
+
'<div class="mfp-close"></div>'+
|
1168 |
+
'<figure>'+
|
1169 |
+
'<div class="mfp-img"></div>'+
|
1170 |
+
'<figcaption>'+
|
1171 |
+
'<div class="mfp-bottom-bar">'+
|
1172 |
+
'<div class="mfp-title"></div>'+
|
1173 |
+
'<div class="mfp-counter"></div>'+
|
1174 |
+
'</div>'+
|
1175 |
+
'</figcaption>'+
|
1176 |
+
'</figure>'+
|
1177 |
+
'</div>',
|
1178 |
+
cursor: 'mfp-zoom-out-cur',
|
1179 |
+
titleSrc: 'title',
|
1180 |
+
verticalFit: true,
|
1181 |
+
tError: '<a href="%url%">The image</a> could not be loaded.'
|
1182 |
+
},
|
1183 |
+
|
1184 |
+
proto: {
|
1185 |
+
initImage: function() {
|
1186 |
+
var imgSt = mfp.st.image,
|
1187 |
+
ns = '.image';
|
1188 |
+
|
1189 |
+
mfp.types.push('image');
|
1190 |
+
|
1191 |
+
_mfpOn(OPEN_EVENT+ns, function() {
|
1192 |
+
if(mfp.currItem.type === 'image' && imgSt.cursor) {
|
1193 |
+
$(document.body).addClass(imgSt.cursor);
|
1194 |
+
}
|
1195 |
+
});
|
1196 |
+
|
1197 |
+
_mfpOn(CLOSE_EVENT+ns, function() {
|
1198 |
+
if(imgSt.cursor) {
|
1199 |
+
$(document.body).removeClass(imgSt.cursor);
|
1200 |
+
}
|
1201 |
+
_window.off('resize' + EVENT_NS);
|
1202 |
+
});
|
1203 |
+
|
1204 |
+
_mfpOn('Resize'+ns, mfp.resizeImage);
|
1205 |
+
if(mfp.isLowIE) {
|
1206 |
+
_mfpOn('AfterChange', mfp.resizeImage);
|
1207 |
+
}
|
1208 |
+
},
|
1209 |
+
resizeImage: function() {
|
1210 |
+
var item = mfp.currItem;
|
1211 |
+
if(!item || !item.img) return;
|
1212 |
+
|
1213 |
+
if(mfp.st.image.verticalFit) {
|
1214 |
+
var decr = 0;
|
1215 |
+
// fix box-sizing in ie7/8
|
1216 |
+
if(mfp.isLowIE) {
|
1217 |
+
decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
|
1218 |
+
}
|
1219 |
+
item.img.css('max-height', mfp.wH-decr);
|
1220 |
+
}
|
1221 |
+
},
|
1222 |
+
_onImageHasSize: function(item) {
|
1223 |
+
if(item.img) {
|
1224 |
+
|
1225 |
+
item.hasSize = true;
|
1226 |
+
|
1227 |
+
if(_imgInterval) {
|
1228 |
+
clearInterval(_imgInterval);
|
1229 |
+
}
|
1230 |
+
|
1231 |
+
item.isCheckingImgSize = false;
|
1232 |
+
|
1233 |
+
_mfpTrigger('ImageHasSize', item);
|
1234 |
+
|
1235 |
+
if(item.imgHidden) {
|
1236 |
+
if(mfp.content)
|
1237 |
+
mfp.content.removeClass('mfp-loading');
|
1238 |
+
|
1239 |
+
item.imgHidden = false;
|
1240 |
+
}
|
1241 |
+
|
1242 |
+
}
|
1243 |
+
},
|
1244 |
+
|
1245 |
+
/**
|
1246 |
+
* Function that loops until the image has size to display elements that rely on it asap
|
1247 |
+
*/
|
1248 |
+
findImageSize: function(item) {
|
1249 |
+
|
1250 |
+
var counter = 0,
|
1251 |
+
img = item.img[0],
|
1252 |
+
mfpSetInterval = function(delay) {
|
1253 |
+
|
1254 |
+
if(_imgInterval) {
|
1255 |
+
clearInterval(_imgInterval);
|
1256 |
+
}
|
1257 |
+
// decelerating interval that checks for size of an image
|
1258 |
+
_imgInterval = setInterval(function() {
|
1259 |
+
if(img.naturalWidth > 0) {
|
1260 |
+
mfp._onImageHasSize(item);
|
1261 |
+
return;
|
1262 |
+
}
|
1263 |
+
|
1264 |
+
if(counter > 200) {
|
1265 |
+
clearInterval(_imgInterval);
|
1266 |
+
}
|
1267 |
+
|
1268 |
+
counter++;
|
1269 |
+
if(counter === 3) {
|
1270 |
+
mfpSetInterval(10);
|
1271 |
+
} else if(counter === 40) {
|
1272 |
+
mfpSetInterval(50);
|
1273 |
+
} else if(counter === 100) {
|
1274 |
+
mfpSetInterval(500);
|
1275 |
+
}
|
1276 |
+
}, delay);
|
1277 |
+
};
|
1278 |
+
|
1279 |
+
mfpSetInterval(1);
|
1280 |
+
},
|
1281 |
+
|
1282 |
+
getImage: function(item, template) {
|
1283 |
+
|
1284 |
+
var guard = 0,
|
1285 |
+
|
1286 |
+
// image load complete handler
|
1287 |
+
onLoadComplete = function() {
|
1288 |
+
if(item) {
|
1289 |
+
if (item.img[0].complete) {
|
1290 |
+
item.img.off('.mfploader');
|
1291 |
+
|
1292 |
+
if(item === mfp.currItem){
|
1293 |
+
mfp._onImageHasSize(item);
|
1294 |
+
|
1295 |
+
mfp.updateStatus('ready');
|
1296 |
+
}
|
1297 |
+
|
1298 |
+
item.hasSize = true;
|
1299 |
+
item.loaded = true;
|
1300 |
+
|
1301 |
+
_mfpTrigger('ImageLoadComplete');
|
1302 |
+
|
1303 |
+
}
|
1304 |
+
else {
|
1305 |
+
// if image complete check fails 200 times (20 sec), we assume that there was an error.
|
1306 |
+
guard++;
|
1307 |
+
if(guard < 200) {
|
1308 |
+
setTimeout(onLoadComplete,100);
|
1309 |
+
} else {
|
1310 |
+
onLoadError();
|
1311 |
+
}
|
1312 |
+
}
|
1313 |
+
}
|
1314 |
+
},
|
1315 |
+
|
1316 |
+
// image error handler
|
1317 |
+
onLoadError = function() {
|
1318 |
+
if(item) {
|
1319 |
+
item.img.off('.mfploader');
|
1320 |
+
if(item === mfp.currItem){
|
1321 |
+
mfp._onImageHasSize(item);
|
1322 |
+
mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
|
1323 |
+
}
|
1324 |
+
|
1325 |
+
item.hasSize = true;
|
1326 |
+
item.loaded = true;
|
1327 |
+
item.loadError = true;
|
1328 |
+
}
|
1329 |
+
},
|
1330 |
+
imgSt = mfp.st.image;
|
1331 |
+
|
1332 |
+
|
1333 |
+
var el = template.find('.mfp-img');
|
1334 |
+
if(el.length) {
|
1335 |
+
var img = document.createElement('img');
|
1336 |
+
img.className = 'mfp-img';
|
1337 |
+
if(item.el && item.el.find('img').length) {
|
1338 |
+
img.alt = item.el.find('img').attr('alt');
|
1339 |
+
}
|
1340 |
+
item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
|
1341 |
+
img.src = item.src;
|
1342 |
+
|
1343 |
+
// without clone() "error" event is not firing when IMG is replaced by new IMG
|
1344 |
+
// TODO: find a way to avoid such cloning
|
1345 |
+
if(el.is('img')) {
|
1346 |
+
item.img = item.img.clone();
|
1347 |
+
}
|
1348 |
+
|
1349 |
+
img = item.img[0];
|
1350 |
+
if(img.naturalWidth > 0) {
|
1351 |
+
item.hasSize = true;
|
1352 |
+
} else if(!img.width) {
|
1353 |
+
item.hasSize = false;
|
1354 |
+
}
|
1355 |
+
}
|
1356 |
+
|
1357 |
+
mfp._parseMarkup(template, {
|
1358 |
+
title: _getTitle(item),
|
1359 |
+
img_replaceWith: item.img
|
1360 |
+
}, item);
|
1361 |
+
|
1362 |
+
mfp.resizeImage();
|
1363 |
+
|
1364 |
+
if(item.hasSize) {
|
1365 |
+
if(_imgInterval) clearInterval(_imgInterval);
|
1366 |
+
|
1367 |
+
if(item.loadError) {
|
1368 |
+
template.addClass('mfp-loading');
|
1369 |
+
mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
|
1370 |
+
} else {
|
1371 |
+
template.removeClass('mfp-loading');
|
1372 |
+
mfp.updateStatus('ready');
|
1373 |
+
}
|
1374 |
+
return template;
|
1375 |
+
}
|
1376 |
+
|
1377 |
+
mfp.updateStatus('loading');
|
1378 |
+
item.loading = true;
|
1379 |
+
|
1380 |
+
if(!item.hasSize) {
|
1381 |
+
item.imgHidden = true;
|
1382 |
+
template.addClass('mfp-loading');
|
1383 |
+
mfp.findImageSize(item);
|
1384 |
+
}
|
1385 |
+
|
1386 |
+
return template;
|
1387 |
+
}
|
1388 |
+
}
|
1389 |
+
});
|
1390 |
+
|
1391 |
+
|
1392 |
+
|
1393 |
+
/*>>image*/
|
1394 |
+
|
1395 |
+
/*>>zoom*/
|
1396 |
+
var hasMozTransform,
|
1397 |
+
getHasMozTransform = function() {
|
1398 |
+
if(hasMozTransform === undefined) {
|
1399 |
+
hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
|
1400 |
+
}
|
1401 |
+
return hasMozTransform;
|
1402 |
+
};
|
1403 |
+
|
1404 |
+
$.magnificPopup.registerModule('zoom', {
|
1405 |
+
|
1406 |
+
options: {
|
1407 |
+
enabled: false,
|
1408 |
+
easing: 'ease-in-out',
|
1409 |
+
duration: 300,
|
1410 |
+
opener: function(element) {
|
1411 |
+
return element.is('img') ? element : element.find('img');
|
1412 |
+
}
|
1413 |
+
},
|
1414 |
+
|
1415 |
+
proto: {
|
1416 |
+
|
1417 |
+
initZoom: function() {
|
1418 |
+
var zoomSt = mfp.st.zoom,
|
1419 |
+
ns = '.zoom',
|
1420 |
+
image;
|
1421 |
+
|
1422 |
+
if(!zoomSt.enabled || !mfp.supportsTransition) {
|
1423 |
+
return;
|
1424 |
+
}
|
1425 |
+
|
1426 |
+
var duration = zoomSt.duration,
|
1427 |
+
getElToAnimate = function(image) {
|
1428 |
+
var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
|
1429 |
+
transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
|
1430 |
+
cssObj = {
|
1431 |
+
position: 'fixed',
|
1432 |
+
zIndex: 9999,
|
1433 |
+
left: 0,
|
1434 |
+
top: 0,
|
1435 |
+
'-webkit-backface-visibility': 'hidden'
|
1436 |
+
},
|
1437 |
+
t = 'transition';
|
1438 |
+
|
1439 |
+
cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;
|
1440 |
+
|
1441 |
+
newImg.css(cssObj);
|
1442 |
+
return newImg;
|
1443 |
+
},
|
1444 |
+
showMainContent = function() {
|
1445 |
+
mfp.content.css('visibility', 'visible');
|
1446 |
+
},
|
1447 |
+
openTimeout,
|
1448 |
+
animatedImg;
|
1449 |
+
|
1450 |
+
_mfpOn('BuildControls'+ns, function() {
|
1451 |
+
if(mfp._allowZoom()) {
|
1452 |
+
|
1453 |
+
clearTimeout(openTimeout);
|
1454 |
+
mfp.content.css('visibility', 'hidden');
|
1455 |
+
|
1456 |
+
// Basically, all code below does is clones existing image, puts in on top of the current one and animated it
|
1457 |
+
|
1458 |
+
image = mfp._getItemToZoom();
|
1459 |
+
|
1460 |
+
if(!image) {
|
1461 |
+
showMainContent();
|
1462 |
+
return;
|
1463 |
+
}
|
1464 |
+
|
1465 |
+
animatedImg = getElToAnimate(image);
|
1466 |
+
|
1467 |
+
animatedImg.css( mfp._getOffset() );
|
1468 |
+
|
1469 |
+
mfp.wrap.append(animatedImg);
|
1470 |
+
|
1471 |
+
openTimeout = setTimeout(function() {
|
1472 |
+
animatedImg.css( mfp._getOffset( true ) );
|
1473 |
+
openTimeout = setTimeout(function() {
|
1474 |
+
|
1475 |
+
showMainContent();
|
1476 |
+
|
1477 |
+
setTimeout(function() {
|
1478 |
+
animatedImg.remove();
|
1479 |
+
image = animatedImg = null;
|
1480 |
+
_mfpTrigger('ZoomAnimationEnded');
|
1481 |
+
}, 16); // avoid blink when switching images
|
1482 |
+
|
1483 |
+
}, duration); // this timeout equals animation duration
|
1484 |
+
|
1485 |
+
}, 16); // by adding this timeout we avoid short glitch at the beginning of animation
|
1486 |
+
|
1487 |
+
|
1488 |
+
// Lots of timeouts...
|
1489 |
+
}
|
1490 |
+
});
|
1491 |
+
_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
|
1492 |
+
if(mfp._allowZoom()) {
|
1493 |
+
|
1494 |
+
clearTimeout(openTimeout);
|
1495 |
+
|
1496 |
+
mfp.st.removalDelay = duration;
|
1497 |
+
|
1498 |
+
if(!image) {
|
1499 |
+
image = mfp._getItemToZoom();
|
1500 |
+
if(!image) {
|
1501 |
+
return;
|
1502 |
+
}
|
1503 |
+
animatedImg = getElToAnimate(image);
|
1504 |
+
}
|
1505 |
+
|
1506 |
+
|
1507 |
+
animatedImg.css( mfp._getOffset(true) );
|
1508 |
+
mfp.wrap.append(animatedImg);
|
1509 |
+
mfp.content.css('visibility', 'hidden');
|
1510 |
+
|
1511 |
+
setTimeout(function() {
|
1512 |
+
animatedImg.css( mfp._getOffset() );
|
1513 |
+
}, 16);
|
1514 |
+
}
|
1515 |
+
|
1516 |
+
});
|
1517 |
+
|
1518 |
+
_mfpOn(CLOSE_EVENT+ns, function() {
|
1519 |
+
if(mfp._allowZoom()) {
|
1520 |
+
showMainContent();
|
1521 |
+
if(animatedImg) {
|
1522 |
+
animatedImg.remove();
|
1523 |
+
}
|
1524 |
+
image = null;
|
1525 |
+
}
|
1526 |
+
});
|
1527 |
+
},
|
1528 |
+
|
1529 |
+
_allowZoom: function() {
|
1530 |
+
return mfp.currItem.type === 'image';
|
1531 |
+
},
|
1532 |
+
|
1533 |
+
_getItemToZoom: function() {
|
1534 |
+
if(mfp.currItem.hasSize) {
|
1535 |
+
return mfp.currItem.img;
|
1536 |
+
} else {
|
1537 |
+
return false;
|
1538 |
+
}
|
1539 |
+
},
|
1540 |
+
|
1541 |
+
// Get element postion relative to viewport
|
1542 |
+
_getOffset: function(isLarge) {
|
1543 |
+
var el;
|
1544 |
+
if(isLarge) {
|
1545 |
+
el = mfp.currItem.img;
|
1546 |
+
} else {
|
1547 |
+
el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
|
1548 |
+
}
|
1549 |
+
|
1550 |
+
var offset = el.offset();
|
1551 |
+
var paddingTop = parseInt(el.css('padding-top'),10);
|
1552 |
+
var paddingBottom = parseInt(el.css('padding-bottom'),10);
|
1553 |
+
offset.top -= ( $(window).scrollTop() - paddingTop );
|
1554 |
+
|
1555 |
+
|
1556 |
+
/*
|
1557 |
+
|
1558 |
+
Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.
|
1559 |
+
|
1560 |
+
*/
|
1561 |
+
var obj = {
|
1562 |
+
width: el.width(),
|
1563 |
+
// fix Zepto height+padding issue
|
1564 |
+
height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
|
1565 |
+
};
|
1566 |
+
|
1567 |
+
// I hate to do this, but there is no another option
|
1568 |
+
if( getHasMozTransform() ) {
|
1569 |
+
obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
|
1570 |
+
} else {
|
1571 |
+
obj.left = offset.left;
|
1572 |
+
obj.top = offset.top;
|
1573 |
+
}
|
1574 |
+
return obj;
|
1575 |
+
}
|
1576 |
+
|
1577 |
+
}
|
1578 |
+
});
|
1579 |
+
|
1580 |
+
|
1581 |
+
|
1582 |
+
/*>>zoom*/
|
1583 |
+
|
1584 |
+
/*>>iframe*/
|
1585 |
+
|
1586 |
+
var IFRAME_NS = 'iframe',
|
1587 |
+
_emptyPage = '//about:blank',
|
1588 |
+
|
1589 |
+
_fixIframeBugs = function(isShowing) {
|
1590 |
+
if(mfp.currTemplate[IFRAME_NS]) {
|
1591 |
+
var el = mfp.currTemplate[IFRAME_NS].find('iframe');
|
1592 |
+
if(el.length) {
|
1593 |
+
// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
|
1594 |
+
if(!isShowing) {
|
1595 |
+
el[0].src = _emptyPage;
|
1596 |
+
}
|
1597 |
+
|
1598 |
+
// IE8 black screen bug fix
|
1599 |
+
if(mfp.isIE8) {
|
1600 |
+
el.css('display', isShowing ? 'block' : 'none');
|
1601 |
+
}
|
1602 |
+
}
|
1603 |
+
}
|
1604 |
+
};
|
1605 |
+
|
1606 |
+
$.magnificPopup.registerModule(IFRAME_NS, {
|
1607 |
+
|
1608 |
+
options: {
|
1609 |
+
markup: '<div class="mfp-iframe-scaler">'+
|
1610 |
+
'<div class="mfp-close"></div>'+
|
1611 |
+
'<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
|
1612 |
+
'</div>',
|
1613 |
+
|
1614 |
+
srcAction: 'iframe_src',
|
1615 |
+
|
1616 |
+
// we don't care and support only one default type of URL by default
|
1617 |
+
patterns: {
|
1618 |
+
youtube: {
|
1619 |
+
index: 'youtube.com',
|
1620 |
+
id: 'v=',
|
1621 |
+
src: '//www.youtube.com/embed/%id%?autoplay=1'
|
1622 |
+
},
|
1623 |
+
vimeo: {
|
1624 |
+
index: 'vimeo.com/',
|
1625 |
+
id: '/',
|
1626 |
+
src: '//player.vimeo.com/video/%id%?autoplay=1'
|
1627 |
+
},
|
1628 |
+
gmaps: {
|
1629 |
+
index: '//maps.google.',
|
1630 |
+
src: '%id%&output=embed'
|
1631 |
+
}
|
1632 |
+
}
|
1633 |
+
},
|
1634 |
+
|
1635 |
+
proto: {
|
1636 |
+
initIframe: function() {
|
1637 |
+
mfp.types.push(IFRAME_NS);
|
1638 |
+
|
1639 |
+
_mfpOn('BeforeChange', function(e, prevType, newType) {
|
1640 |
+
if(prevType !== newType) {
|
1641 |
+
if(prevType === IFRAME_NS) {
|
1642 |
+
_fixIframeBugs(); // iframe if removed
|
1643 |
+
} else if(newType === IFRAME_NS) {
|
1644 |
+
_fixIframeBugs(true); // iframe is showing
|
1645 |
+
}
|
1646 |
+
}// else {
|
1647 |
+
// iframe source is switched, don't do anything
|
1648 |
+
//}
|
1649 |
+
});
|
1650 |
+
|
1651 |
+
_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
|
1652 |
+
_fixIframeBugs();
|
1653 |
+
});
|
1654 |
+
},
|
1655 |
+
|
1656 |
+
getIframe: function(item, template) {
|
1657 |
+
var embedSrc = item.src;
|
1658 |
+
var iframeSt = mfp.st.iframe;
|
1659 |
+
|
1660 |
+
$.each(iframeSt.patterns, function() {
|
1661 |
+
if(embedSrc.indexOf( this.index ) > -1) {
|
1662 |
+
if(this.id) {
|
1663 |
+
if(typeof this.id === 'string') {
|
1664 |
+
embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
|
1665 |
+
} else {
|
1666 |
+
embedSrc = this.id.call( this, embedSrc );
|
1667 |
+
}
|
1668 |
+
}
|
1669 |
+
embedSrc = this.src.replace('%id%', embedSrc );
|
1670 |
+
return false; // break;
|
1671 |
+
}
|
1672 |
+
});
|
1673 |
+
|
1674 |
+
var dataObj = {};
|
1675 |
+
if(iframeSt.srcAction) {
|
1676 |
+
dataObj[iframeSt.srcAction] = embedSrc;
|
1677 |
+
}
|
1678 |
+
mfp._parseMarkup(template, dataObj, item);
|
1679 |
+
|
1680 |
+
mfp.updateStatus('ready');
|
1681 |
+
|
1682 |
+
return template;
|
1683 |
+
}
|
1684 |
+
}
|
1685 |
+
});
|
1686 |
+
|
1687 |
+
|
1688 |
+
|
1689 |
+
/*>>iframe*/
|
1690 |
+
|
1691 |
+
/*>>gallery*/
|
1692 |
+
/**
|
1693 |
+
* Get looped index depending on number of slides
|
1694 |
+
*/
|
1695 |
+
var _getLoopedId = function(index) {
|
1696 |
+
var numSlides = mfp.items.length;
|
1697 |
+
if(index > numSlides - 1) {
|
1698 |
+
return index - numSlides;
|
1699 |
+
} else if(index < 0) {
|
1700 |
+
return numSlides + index;
|
1701 |
+
}
|
1702 |
+
return index;
|
1703 |
+
},
|
1704 |
+
_replaceCurrTotal = function(text, curr, total) {
|
1705 |
+
return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
|
1706 |
+
};
|
1707 |
+
|
1708 |
+
$.magnificPopup.registerModule('gallery', {
|
1709 |
+
|
1710 |
+
options: {
|
1711 |
+
enabled: false,
|
1712 |
+
arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
|
1713 |
+
preload: [0,2],
|
1714 |
+
navigateByImgClick: true,
|
1715 |
+
arrows: true,
|
1716 |
+
|
1717 |
+
tPrev: 'Previous (Left arrow key)',
|
1718 |
+
tNext: 'Next (Right arrow key)',
|
1719 |
+
tCounter: '%curr% of %total%'
|
1720 |
+
},
|
1721 |
+
|
1722 |
+
proto: {
|
1723 |
+
initGallery: function() {
|
1724 |
+
|
1725 |
+
var gSt = mfp.st.gallery,
|
1726 |
+
ns = '.mfp-gallery',
|
1727 |
+
supportsFastClick = Boolean($.fn.mfpFastClick);
|
1728 |
+
|
1729 |
+
mfp.direction = true; // true - next, false - prev
|
1730 |
+
|
1731 |
+
if(!gSt || !gSt.enabled ) return false;
|
1732 |
+
|
1733 |
+
_wrapClasses += ' mfp-gallery';
|
1734 |
+
|
1735 |
+
_mfpOn(OPEN_EVENT+ns, function() {
|
1736 |
+
|
1737 |
+
if(gSt.navigateByImgClick) {
|
1738 |
+
mfp.wrap.on('click'+ns, '.mfp-img', function() {
|
1739 |
+
if(mfp.items.length > 1) {
|
1740 |
+
mfp.next();
|
1741 |
+
return false;
|
1742 |
+
}
|
1743 |
+
});
|
1744 |
+
}
|
1745 |
+
|
1746 |
+
_document.on('keydown'+ns, function(e) {
|
1747 |
+
if (e.keyCode === 37) {
|
1748 |
+
mfp.prev();
|
1749 |
+
} else if (e.keyCode === 39) {
|
1750 |
+
mfp.next();
|
1751 |
+
}
|
1752 |
+
});
|
1753 |
+
});
|
1754 |
+
|
1755 |
+
_mfpOn('UpdateStatus'+ns, function(e, data) {
|
1756 |
+
if(data.text) {
|
1757 |
+
data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
|
1758 |
+
}
|
1759 |
+
});
|
1760 |
+
|
1761 |
+
_mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
|
1762 |
+
var l = mfp.items.length;
|
1763 |
+
values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
|
1764 |
+
});
|
1765 |
+
|
1766 |
+
_mfpOn('BuildControls' + ns, function() {
|
1767 |
+
if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
|
1768 |
+
var markup = gSt.arrowMarkup,
|
1769 |
+
arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
|
1770 |
+
arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);
|
1771 |
+
|
1772 |
+
var eName = supportsFastClick ? 'mfpFastClick' : 'click';
|
1773 |
+
arrowLeft[eName](function() {
|
1774 |
+
mfp.prev();
|
1775 |
+
});
|
1776 |
+
arrowRight[eName](function() {
|
1777 |
+
mfp.next();
|
1778 |
+
});
|
1779 |
+
|
1780 |
+
// Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b)
|
1781 |
+
if(mfp.isIE7) {
|
1782 |
+
_getEl('b', arrowLeft[0], false, true);
|
1783 |
+
_getEl('a', arrowLeft[0], false, true);
|
1784 |
+
_getEl('b', arrowRight[0], false, true);
|
1785 |
+
_getEl('a', arrowRight[0], false, true);
|
1786 |
+
}
|
1787 |
+
|
1788 |
+
mfp.container.append(arrowLeft.add(arrowRight));
|
1789 |
+
}
|
1790 |
+
});
|
1791 |
+
|
1792 |
+
_mfpOn(CHANGE_EVENT+ns, function() {
|
1793 |
+
if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);
|
1794 |
+
|
1795 |
+
mfp._preloadTimeout = setTimeout(function() {
|
1796 |
+
mfp.preloadNearbyImages();
|
1797 |
+
mfp._preloadTimeout = null;
|
1798 |
+
}, 16);
|
1799 |
+
});
|
1800 |
+
|
1801 |
+
|
1802 |
+
_mfpOn(CLOSE_EVENT+ns, function() {
|
1803 |
+
_document.off(ns);
|
1804 |
+
mfp.wrap.off('click'+ns);
|
1805 |
+
|
1806 |
+
if(mfp.arrowLeft && supportsFastClick) {
|
1807 |
+
mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick();
|
1808 |
+
}
|
1809 |
+
mfp.arrowRight = mfp.arrowLeft = null;
|
1810 |
+
});
|
1811 |
+
|
1812 |
+
},
|
1813 |
+
next: function() {
|
1814 |
+
mfp.direction = true;
|
1815 |
+
mfp.index = _getLoopedId(mfp.index + 1);
|
1816 |
+
mfp.updateItemHTML();
|
1817 |
+
},
|
1818 |
+
prev: function() {
|
1819 |
+
mfp.direction = false;
|
1820 |
+
mfp.index = _getLoopedId(mfp.index - 1);
|
1821 |
+
mfp.updateItemHTML();
|
1822 |
+
},
|
1823 |
+
goTo: function(newIndex) {
|
1824 |
+
mfp.direction = (newIndex >= mfp.index);
|
1825 |
+
mfp.index = newIndex;
|
1826 |
+
mfp.updateItemHTML();
|
1827 |
+
},
|
1828 |
+
preloadNearbyImages: function() {
|
1829 |
+
var p = mfp.st.gallery.preload,
|
1830 |
+
preloadBefore = Math.min(p[0], mfp.items.length),
|
1831 |
+
preloadAfter = Math.min(p[1], mfp.items.length),
|
1832 |
+
i;
|
1833 |
+
|
1834 |
+
for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
|
1835 |
+
mfp._preloadItem(mfp.index+i);
|
1836 |
+
}
|
1837 |
+
for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
|
1838 |
+
mfp._preloadItem(mfp.index-i);
|
1839 |
+
}
|
1840 |
+
},
|
1841 |
+
_preloadItem: function(index) {
|
1842 |
+
index = _getLoopedId(index);
|
1843 |
+
|
1844 |
+
if(mfp.items[index].preloaded) {
|
1845 |
+
return;
|
1846 |
+
}
|
1847 |
+
|
1848 |
+
var item = mfp.items[index];
|
1849 |
+
if(!item.parsed) {
|
1850 |
+
item = mfp.parseEl( index );
|
1851 |
+
}
|
1852 |
+
|
1853 |
+
_mfpTrigger('LazyLoad', item);
|
1854 |
+
|
1855 |
+
if(item.type === 'image') {
|
1856 |
+
item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
|
1857 |
+
item.hasSize = true;
|
1858 |
+
}).on('error.mfploader', function() {
|
1859 |
+
item.hasSize = true;
|
1860 |
+
item.loadError = true;
|
1861 |
+
_mfpTrigger('LazyLoadError', item);
|
1862 |
+
}).attr('src', item.src);
|
1863 |
+
}
|
1864 |
+
|
1865 |
+
|
1866 |
+
item.preloaded = true;
|
1867 |
+
}
|
1868 |
+
}
|
1869 |
+
});
|
1870 |
+
|
1871 |
+
/*
|
1872 |
+
Touch Support that might be implemented some day
|
1873 |
+
|
1874 |
+
addSwipeGesture: function() {
|
1875 |
+
var startX,
|
1876 |
+
moved,
|
1877 |
+
multipleTouches;
|
1878 |
+
|
1879 |
+
return;
|
1880 |
+
|
1881 |
+
var namespace = '.mfp',
|
1882 |
+
addEventNames = function(pref, down, move, up, cancel) {
|
1883 |
+
mfp._tStart = pref + down + namespace;
|
1884 |
+
mfp._tMove = pref + move + namespace;
|
1885 |
+
mfp._tEnd = pref + up + namespace;
|
1886 |
+
mfp._tCancel = pref + cancel + namespace;
|
1887 |
+
};
|
1888 |
+
|
1889 |
+
if(window.navigator.msPointerEnabled) {
|
1890 |
+
addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
|
1891 |
+
} else if('ontouchstart' in window) {
|
1892 |
+
addEventNames('touch', 'start', 'move', 'end', 'cancel');
|
1893 |
+
} else {
|
1894 |
+
return;
|
1895 |
+
}
|
1896 |
+
_window.on(mfp._tStart, function(e) {
|
1897 |
+
var oE = e.originalEvent;
|
1898 |
+
multipleTouches = moved = false;
|
1899 |
+
startX = oE.pageX || oE.changedTouches[0].pageX;
|
1900 |
+
}).on(mfp._tMove, function(e) {
|
1901 |
+
if(e.originalEvent.touches.length > 1) {
|
1902 |
+
multipleTouches = e.originalEvent.touches.length;
|
1903 |
+
} else {
|
1904 |
+
//e.preventDefault();
|
1905 |
+
moved = true;
|
1906 |
+
}
|
1907 |
+
}).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) {
|
1908 |
+
if(moved && !multipleTouches) {
|
1909 |
+
var oE = e.originalEvent,
|
1910 |
+
diff = startX - (oE.pageX || oE.changedTouches[0].pageX);
|
1911 |
+
|
1912 |
+
if(diff > 20) {
|
1913 |
+
mfp.next();
|
1914 |
+
} else if(diff < -20) {
|
1915 |
+
mfp.prev();
|
1916 |
+
}
|
1917 |
+
}
|
1918 |
+
});
|
1919 |
+
},
|
1920 |
+
*/
|
1921 |
+
|
1922 |
+
|
1923 |
+
/*>>gallery*/
|
1924 |
+
|
1925 |
+
/*>>retina*/
|
1926 |
+
|
1927 |
+
var RETINA_NS = 'retina';
|
1928 |
+
|
1929 |
+
$.magnificPopup.registerModule(RETINA_NS, {
|
1930 |
+
options: {
|
1931 |
+
replaceSrc: function(item) {
|
1932 |
+
return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
|
1933 |
+
},
|
1934 |
+
ratio: 1 // Function or number. Set to 1 to disable.
|
1935 |
+
},
|
1936 |
+
proto: {
|
1937 |
+
initRetina: function() {
|
1938 |
+
if(window.devicePixelRatio > 1) {
|
1939 |
+
|
1940 |
+
var st = mfp.st.retina,
|
1941 |
+
ratio = st.ratio;
|
1942 |
+
|
1943 |
+
ratio = !isNaN(ratio) ? ratio : ratio();
|
1944 |
+
|
1945 |
+
if(ratio > 1) {
|
1946 |
+
_mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
|
1947 |
+
item.img.css({
|
1948 |
+
'max-width': item.img[0].naturalWidth / ratio,
|
1949 |
+
'width': '100%'
|
1950 |
+
});
|
1951 |
+
});
|
1952 |
+
_mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
|
1953 |
+
item.src = st.replaceSrc(item, ratio);
|
1954 |
+
});
|
1955 |
+
}
|
1956 |
+
}
|
1957 |
+
|
1958 |
+
}
|
1959 |
+
}
|
1960 |
+
});
|
1961 |
+
|
1962 |
+
/*>>retina*/
|
1963 |
+
|
1964 |
+
/*>>fastclick*/
|
1965 |
+
/**
|
1966 |
+
* FastClick event implementation. (removes 300ms delay on touch devices)
|
1967 |
+
* Based on https://developers.google.com/mobile/articles/fast_buttons
|
1968 |
+
*
|
1969 |
+
* You may use it outside the Magnific Popup by calling just:
|
1970 |
+
*
|
1971 |
+
* $('.your-el').mfpFastClick(function() {
|
1972 |
+
* console.log('Clicked!');
|
1973 |
+
* });
|
1974 |
+
*
|
1975 |
+
* To unbind:
|
1976 |
+
* $('.your-el').destroyMfpFastClick();
|
1977 |
+
*
|
1978 |
+
*
|
1979 |
+
* Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound.
|
1980 |
+
* If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick
|
1981 |
+
*
|
1982 |
+
*/
|
1983 |
+
|
1984 |
+
(function() {
|
1985 |
+
var ghostClickDelay = 1000,
|
1986 |
+
supportsTouch = 'ontouchstart' in window,
|
1987 |
+
unbindTouchMove = function() {
|
1988 |
+
_window.off('touchmove'+ns+' touchend'+ns);
|
1989 |
+
},
|
1990 |
+
eName = 'mfpFastClick',
|
1991 |
+
ns = '.'+eName;
|
1992 |
+
|
1993 |
+
|
1994 |
+
// As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way
|
1995 |
+
$.fn.mfpFastClick = function(callback) {
|
1996 |
+
|
1997 |
+
return $(this).each(function() {
|
1998 |
+
|
1999 |
+
var elem = $(this),
|
2000 |
+
lock;
|
2001 |
+
|
2002 |
+
if( supportsTouch ) {
|
2003 |
+
|
2004 |
+
var timeout,
|
2005 |
+
startX,
|
2006 |
+
startY,
|
2007 |
+
pointerMoved,
|
2008 |
+
point,
|
2009 |
+
numPointers;
|
2010 |
+
|
2011 |
+
elem.on('touchstart' + ns, function(e) {
|
2012 |
+
pointerMoved = false;
|
2013 |
+
numPointers = 1;
|
2014 |
+
|
2015 |
+
point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0];
|
2016 |
+
startX = point.clientX;
|
2017 |
+
startY = point.clientY;
|
2018 |
+
|
2019 |
+
_window.on('touchmove'+ns, function(e) {
|
2020 |
+
point = e.originalEvent ? e.originalEvent.touches : e.touches;
|
2021 |
+
numPointers = point.length;
|
2022 |
+
point = point[0];
|
2023 |
+
if (Math.abs(point.clientX - startX) > 10 ||
|
2024 |
+
Math.abs(point.clientY - startY) > 10) {
|
2025 |
+
pointerMoved = true;
|
2026 |
+
unbindTouchMove();
|
2027 |
+
}
|
2028 |
+
}).on('touchend'+ns, function(e) {
|
2029 |
+
unbindTouchMove();
|
2030 |
+
if(pointerMoved || numPointers > 1) {
|
2031 |
+
return;
|
2032 |
+
}
|
2033 |
+
lock = true;
|
2034 |
+
e.preventDefault();
|
2035 |
+
clearTimeout(timeout);
|
2036 |
+
timeout = setTimeout(function() {
|
2037 |
+
lock = false;
|
2038 |
+
}, ghostClickDelay);
|
2039 |
+
callback();
|
2040 |
+
});
|
2041 |
+
});
|
2042 |
+
|
2043 |
+
}
|
2044 |
+
|
2045 |
+
elem.on('click' + ns, function() {
|
2046 |
+
if(!lock) {
|
2047 |
+
callback();
|
2048 |
+
}
|
2049 |
+
});
|
2050 |
+
});
|
2051 |
+
};
|
2052 |
+
|
2053 |
+
$.fn.destroyMfpFastClick = function() {
|
2054 |
+
$(this).off('touchstart' + ns + ' click' + ns);
|
2055 |
+
if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns);
|
2056 |
+
};
|
2057 |
+
})();
|
2058 |
+
|
2059 |
+
/*>>fastclick*/
|
2060 |
+
_checkInstance(); }));
|
assets/js/jquery.magnific-popup.min.js
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
/*! Magnific Popup - v1.0.0 - 2015-01-03
|
2 |
+
* http://dimsemenov.com/plugins/magnific-popup/
|
3 |
+
* Copyright (c) 2015 Dmitry Semenov; */
|
4 |
+
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h="Close",i="BeforeClose",j="AfterClose",k="BeforeAppend",l="MarkupParse",m="Open",n="Change",o="mfp",p="."+o,q="mfp-ready",r="mfp-removing",s="mfp-prevent-close",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new t,b.init(),a.magnificPopup.instance=b)},B=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};t.prototype={constructor:t,init:function(){var c=navigator.appVersion;b.isIE7=-1!==c.indexOf("MSIE 7."),b.isIE8=-1!==c.indexOf("MSIE 8."),b.isLowIE=b.isIE7||b.isIE8,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",b.ev=c.mainEl&&c.mainEl.length?c.mainEl.eq(0):d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x("bg").on("click"+p,function(){b.close()}),b.wrap=x("wrap").attr("tabindex",-1).on("click"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x("container",b.wrap)),b.contentContainer=x("content"),b.st.preloader&&(b.preloader=x("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b["init"+j].call(b)}y("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(z())),b.st.alignTop&&(f+=" mfp-align-top"),b.wrap.css(b.fixedContentPos?{overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}:{top:v.scrollTop(),position:"absolute"}),(b.st.fixedBgPos===!1||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup"+p,function(a){27===a.keyCode&&b.close()}),v.on("resize"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):n.overflow="hidden");var r=b.st.mainClass;return b.isIE7&&(r+=" mfp-ie7"),r&&b._addClassToMFP(r),b.updateItemHTML(),y("BuildControls"),a("html").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on("focusin"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var c=r+" "+q+" ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup"+p+" focusin"+p),b.ev.off(p),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||v.height();b.fixedContentPos||b.wrap.css("height",b.wH),y("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(y("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=b.st[d]?b.st[d].markup:!1;y("FirstMarkupParse",f),b.currTemplate[d]=f?a(f):!0}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(".mfp-close").length||b.content.append(z()):b.content=a:b.content="",y(k),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,y("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var f=void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||2!==c.which&&!c.ctrlKey&&!c.metaKey){var g=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};y("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void 0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(a,c){if(void 0===c||c===!1)return!0;if(e=a.split("_"),e.length>1){var d=b.find(p+"-"+e[0]);if(d.length>0){var f=e[1];"replaceWith"===f?d[0]!==c[0]&&d.replaceWith(c):"img"===f?d.is("img")?d.attr("src",c):d.replaceWith('<img src="'+c+'" class="'+d.attr("class")+'" />'):d.attr(e[1],c)}}else b.find(p+"-"+a).html(c)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading..."}},a.fn.magnificPopup=function(c){A();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery",g=Boolean(a.fn.mfpFastClick);return b.direction=!0,c&&c.enabled?(f+=" mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s),h=g?"mfpFastClick":"click";e[h](function(){b.prev()}),f[h](function(){b.next()}),b.isIE7&&(x("b",e[0],!1,!0),x("a",e[0],!1,!0),x("b",f[0],!1,!0),x("a",f[0],!1,!0)),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowLeft&&g&&b.arrowLeft.add(b.arrowRight).destroyMfpFastClick(),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),function(){var b=1e3,c="ontouchstart"in window,d=function(){v.off("touchmove"+f+" touchend"+f)},e="mfpFastClick",f="."+e;a.fn.mfpFastClick=function(e){return a(this).each(function(){var g,h=a(this);if(c){var i,j,k,l,m,n;h.on("touchstart"+f,function(a){l=!1,n=1,m=a.originalEvent?a.originalEvent.touches[0]:a.touches[0],j=m.clientX,k=m.clientY,v.on("touchmove"+f,function(a){m=a.originalEvent?a.originalEvent.touches:a.touches,n=m.length,m=m[0],(Math.abs(m.clientX-j)>10||Math.abs(m.clientY-k)>10)&&(l=!0,d())}).on("touchend"+f,function(a){d(),l||n>1||(g=!0,a.preventDefault(),clearTimeout(i),i=setTimeout(function(){g=!1},b),e())})})}h.on("click"+f,function(){g||e()})})},a.fn.destroyMfpFastClick=function(){a(this).off("touchstart"+f+" click"+f),c&&v.off("touchmove"+f+" touchend"+f)}}(),A()});
|
assets/js/themes-wp-rollback.js
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Theme Specific WP Rollback
|
3 |
+
*
|
4 |
+
* @description: Adds a rollback option to themes
|
5 |
+
* @copyright: http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
6 |
+
*/
|
7 |
+
var wpr_vars;
|
8 |
+
jQuery.noConflict();
|
9 |
+
|
10 |
+
(function ( $ ) {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Content Change DOM Event Listenter
|
14 |
+
*
|
15 |
+
* @see: http://stackoverflow.com/questions/3233991/jquery-watch-div/3234646#3234646
|
16 |
+
* @param callback
|
17 |
+
* @returns {*}
|
18 |
+
*/
|
19 |
+
jQuery.fn.contentChange = function ( callback ) {
|
20 |
+
var elms = jQuery( this );
|
21 |
+
elms.each(
|
22 |
+
function ( i ) {
|
23 |
+
var elm = jQuery( this );
|
24 |
+
elm.data( "lastContents", elm.html() );
|
25 |
+
window.watchContentChange = window.watchContentChange ? window.watchContentChange : [];
|
26 |
+
window.watchContentChange.push( {"element": elm, "callback": callback} );
|
27 |
+
}
|
28 |
+
);
|
29 |
+
return elms;
|
30 |
+
};
|
31 |
+
setInterval( function () {
|
32 |
+
if ( window.watchContentChange ) {
|
33 |
+
for ( i in window.watchContentChange ) {
|
34 |
+
if ( window.watchContentChange[i].element.data( "lastContents" ) != window.watchContentChange[i].element.html() ) {
|
35 |
+
window.watchContentChange[i].callback.apply( window.watchContentChange[i].element );
|
36 |
+
window.watchContentChange[i].element.data( "lastContents", window.watchContentChange[i].element.html() )
|
37 |
+
}
|
38 |
+
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}, 150 );
|
42 |
+
|
43 |
+
//On DOM Ready
|
44 |
+
$( function () {
|
45 |
+
var themes;
|
46 |
+
themes = wp.themes = wp.themes || {};
|
47 |
+
themes.data = _wpThemeSettings;
|
48 |
+
|
49 |
+
//On clicking a theme template
|
50 |
+
$( '.theme-overlay' ).contentChange( function ( e ) {
|
51 |
+
|
52 |
+
//get theme name that was clicked
|
53 |
+
var clicked_theme = wpr_get_parameter_by_name( 'theme' );
|
54 |
+
|
55 |
+
//check that rollback button hasn't been placed
|
56 |
+
if ( is_rollback_btn_there() ) {
|
57 |
+
//button is there, bail
|
58 |
+
return false;
|
59 |
+
}
|
60 |
+
|
61 |
+
//pass off to rollback function
|
62 |
+
wpr_theme_rollback( clicked_theme );
|
63 |
+
|
64 |
+
|
65 |
+
} );
|
66 |
+
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Check to see if Rollback button is in place
|
70 |
+
*
|
71 |
+
* @returns {boolean}
|
72 |
+
*/
|
73 |
+
function is_rollback_btn_there() {
|
74 |
+
|
75 |
+
if ( $( '.wpr-theme-rollback' ).length > 0 ) {
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
return false;
|
79 |
+
|
80 |
+
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Is Theme WordPress.org?
|
85 |
+
*
|
86 |
+
* @description Rollback only supports WordPress.org themes
|
87 |
+
*/
|
88 |
+
function wpr_theme_rollback( theme ) {
|
89 |
+
|
90 |
+
var theme_data = wpr_get_theme_data( theme );
|
91 |
+
|
92 |
+
//ensure this theme can be rolled back (not premium, etc)
|
93 |
+
if ( theme_data !== null && typeof theme_data.hasRollback !== 'undefined' && theme_data.hasRollback !== false ) {
|
94 |
+
|
95 |
+
var active_theme = $( '.theme-overlay' ).hasClass( 'active' );
|
96 |
+
|
97 |
+
|
98 |
+
var rollback_btn_html = '<a href="' + encodeURI( 'index.php?page=wp-rollback&type=theme&theme_file=' + theme + '¤t_version=' + theme_data.version + '&rollback_name=' + theme_data.name + '' ) + '" style="position:absolute;right: ' + (active_theme === true ? '5px' : '80px') + '; bottom: 5px;" class="button wpr-theme-rollback">' + wpr_vars.text_rollback_label + '</a>';
|
99 |
+
|
100 |
+
$( '.theme-wrap' ).find( '.theme-actions' ).append( rollback_btn_html );
|
101 |
+
|
102 |
+
} else {
|
103 |
+
//Can't roll back this theme, display the
|
104 |
+
$( '.theme-wrap' ).find( '.theme-actions' ).append( '<span class="no-rollback" style="position: absolute;left: 23px;bottom: 16px;font-size: 12px;font-style: italic;color: rgb(181, 181, 181);">' + wpr_vars.text_not_rollbackable + '</span>' );
|
105 |
+
}
|
106 |
+
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get Theme Data
|
111 |
+
*
|
112 |
+
* @description Loops through the wp.themes.data.themes object, finds a match, and returns the data
|
113 |
+
* @param theme
|
114 |
+
* @returns {*}
|
115 |
+
*/
|
116 |
+
function wpr_get_theme_data( theme ) {
|
117 |
+
var theme_data = wp.themes.data.themes;
|
118 |
+
|
119 |
+
//Loop through complete theme data to find this current theme's data
|
120 |
+
for ( var i = 0, len = theme_data.length; i < len; i++ ) {
|
121 |
+
if ( theme_data[i].id === theme ) {
|
122 |
+
return theme_data[i]; // Return as soon as the object is found
|
123 |
+
}
|
124 |
+
}
|
125 |
+
return null; // The object was not found
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* JS Ready Query String (Helper)
|
130 |
+
*
|
131 |
+
* Kinda dirty but whatever...
|
132 |
+
*
|
133 |
+
* @see: http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
|
134 |
+
* @param name
|
135 |
+
* @returns {string}
|
136 |
+
*/
|
137 |
+
function wpr_get_parameter_by_name( name ) {
|
138 |
+
name = name.replace( /[\[]/, "\\[" ).replace( /[\]]/, "\\]" );
|
139 |
+
var regex = new RegExp( "[\\?&]" + name + "=([^&#]*)" ),
|
140 |
+
results = regex.exec( location.search );
|
141 |
+
return results === null ? "" : decodeURIComponent( results[1].replace( /\+/g, " " ) );
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Get Parameter from Focused Theme
|
146 |
+
*
|
147 |
+
* @returns {*}
|
148 |
+
*/
|
149 |
+
function wpr_get_parameter_from_focused_theme() {
|
150 |
+
var focused_theme = wp.themes.focusedTheme;
|
151 |
+
var name = $( focused_theme ).find( '.theme-name' ).attr( 'id' );
|
152 |
+
|
153 |
+
if ( typeof name !== 'undefined' ) {
|
154 |
+
name = name.replace( '-name', '' );
|
155 |
+
} else {
|
156 |
+
return false;
|
157 |
+
}
|
158 |
+
|
159 |
+
return name;
|
160 |
+
}
|
161 |
+
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Theme Rollback Button Clicked
|
165 |
+
*
|
166 |
+
* @description Send them over to
|
167 |
+
*/
|
168 |
+
$( 'body' ).on( 'click', '.wpr-theme-rollback', function ( e ) {
|
169 |
+
|
170 |
+
window.location = $( this ).attr( 'href' );
|
171 |
+
|
172 |
+
} );
|
173 |
+
|
174 |
+
|
175 |
+
|
176 |
+
} );
|
177 |
+
|
178 |
+
|
179 |
+
})( jQuery );
|
assets/js/wp-rollback.js
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* WP Rollback Scripts
|
3 |
+
*
|
4 |
+
* @description:
|
5 |
+
* @copyright: http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
6 |
+
*/
|
7 |
+
|
8 |
+
var wpr_vars;
|
9 |
+
|
10 |
+
jQuery.noConflict();
|
11 |
+
(function ( $ ) {
|
12 |
+
|
13 |
+
//On DOM Ready
|
14 |
+
$( function () {
|
15 |
+
|
16 |
+
var form = $( '.rollback-form' );
|
17 |
+
var form_labels = $( 'label', form.get( 0 ) );
|
18 |
+
var form_submit_btn = $( '.magnific-popup' );
|
19 |
+
|
20 |
+
//On Element Click
|
21 |
+
form_labels.on( 'click', function () {
|
22 |
+
|
23 |
+
//add a selected class
|
24 |
+
form_labels.removeClass( 'wpr-selected' );
|
25 |
+
form_submit_btn.removeClass( 'wpr-rollback-disabled' );
|
26 |
+
$( this ).addClass( 'wpr-selected' );
|
27 |
+
|
28 |
+
//ensure the radio button always gets clicked
|
29 |
+
$( this ).find( 'input' ).prop( 'checked', true );
|
30 |
+
|
31 |
+
} );
|
32 |
+
|
33 |
+
//Modal
|
34 |
+
form_submit_btn.on( 'click', function () {
|
35 |
+
|
36 |
+
var rollback_form_vals = form.serializeArray();
|
37 |
+
|
38 |
+
var rollback_version = form.find( 'input[name="plugin_version"]:checked' ).val();
|
39 |
+
if ( !rollback_version ) {
|
40 |
+
rollback_version = form.find( 'input[name="theme_version"]:checked' ).val();
|
41 |
+
}
|
42 |
+
var installed_version = form.find( 'input[name="installed_version"]' ).val();
|
43 |
+
var new_version = form.find( 'input[name="new_version"]' ).val();
|
44 |
+
var rollback_name = form.find( 'input[name="rollback_name"]' ).val();
|
45 |
+
|
46 |
+
//Ensure a version is selected
|
47 |
+
if ( !rollback_version ) {
|
48 |
+
|
49 |
+
alert( wpr_vars.version_missing );
|
50 |
+
$.magnificPopup.close(); //just for good measure
|
51 |
+
|
52 |
+
} else {
|
53 |
+
|
54 |
+
//Passed
|
55 |
+
$.magnificPopup.open( {
|
56 |
+
items : {
|
57 |
+
src : $( '#wpr-modal-confirm' ), // can be a HTML string, jQuery object, or CSS selector
|
58 |
+
type: 'inline'
|
59 |
+
},
|
60 |
+
closeBtnInside: false,
|
61 |
+
callbacks : {
|
62 |
+
open: function () {
|
63 |
+
|
64 |
+
$( 'span.wpr-plugin-name' ).text( rollback_name );
|
65 |
+
$( 'span.wpr-installed-version' ).text( installed_version );
|
66 |
+
$( 'span.wpr-new-version' ).text( rollback_version );
|
67 |
+
|
68 |
+
}
|
69 |
+
}
|
70 |
+
} );
|
71 |
+
|
72 |
+
|
73 |
+
}
|
74 |
+
|
75 |
+
} );
|
76 |
+
|
77 |
+
//Modal Close
|
78 |
+
$( '.wpr-close' ).on( 'click', function ( e ) {
|
79 |
+
e.preventDefault();
|
80 |
+
$.magnificPopup.close();
|
81 |
+
} );
|
82 |
+
//Modal Confirm (GO! GO! GO!)
|
83 |
+
$( '.wpr-go' ).on( 'click', function ( e ) {
|
84 |
+
//submit form
|
85 |
+
form.submit();
|
86 |
+
} );
|
87 |
+
|
88 |
+
} );
|
89 |
+
|
90 |
+
|
91 |
+
})( jQuery );
|
includes/class-rollback-plugin-upgrader.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WP Rollback Plugin Upgrader
|
4 |
+
*
|
5 |
+
* @description: Class that extends the WP Core Plugin_Upgrader found in core to do rollbacks
|
6 |
+
* @copyright : http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
7 |
+
* @since : 1.0.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
// Exit if accessed directly
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
+
}
|
14 |
+
|
15 |
+
//kick things off
|
16 |
+
class WP_Rollback_Plugin_Upgrader extends Plugin_Upgrader {
|
17 |
+
|
18 |
+
public function rollback( $plugin, $args = array() ) {
|
19 |
+
|
20 |
+
$defaults = array(
|
21 |
+
'clear_update_cache' => true,
|
22 |
+
);
|
23 |
+
$parsed_args = wp_parse_args( $args, $defaults );
|
24 |
+
|
25 |
+
$this->init();
|
26 |
+
$this->upgrade_strings();
|
27 |
+
|
28 |
+
// TODO: Add final check to make sure plugin exists
|
29 |
+
if ( 0 ) {
|
30 |
+
$this->skin->before();
|
31 |
+
$this->skin->set_result( false );
|
32 |
+
$this->skin->error( 'up_to_date' );
|
33 |
+
$this->skin->after();
|
34 |
+
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
|
38 |
+
$plugin_slug = $this->skin->plugin;
|
39 |
+
|
40 |
+
$plugin_version = $this->skin->options['version'];
|
41 |
+
|
42 |
+
$download_endpoint = 'https://downloads.wordpress.org/plugin/';
|
43 |
+
|
44 |
+
$url = $download_endpoint . $plugin_slug . '.' . $plugin_version . '.zip';
|
45 |
+
|
46 |
+
add_filter( 'upgrader_pre_install', array( $this, 'deactivate_plugin_before_upgrade' ), 10, 2 );
|
47 |
+
add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ), 10, 4 );
|
48 |
+
|
49 |
+
$this->run( array(
|
50 |
+
'package' => $url,
|
51 |
+
'destination' => WP_PLUGIN_DIR,
|
52 |
+
'clear_destination' => true,
|
53 |
+
'clear_working' => true,
|
54 |
+
'hook_extra' => array(
|
55 |
+
'plugin' => $plugin,
|
56 |
+
'type' => 'plugin',
|
57 |
+
'action' => 'update',
|
58 |
+
),
|
59 |
+
) );
|
60 |
+
|
61 |
+
// Cleanup our hooks, in case something else does a upgrade on this connection.
|
62 |
+
remove_filter( 'upgrader_pre_install', array( $this, 'deactivate_plugin_before_upgrade' ) );
|
63 |
+
remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ) );
|
64 |
+
|
65 |
+
if ( ! $this->result || is_wp_error( $this->result ) ) {
|
66 |
+
return $this->result;
|
67 |
+
}
|
68 |
+
|
69 |
+
// Force refresh of plugin update information
|
70 |
+
wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );
|
71 |
+
|
72 |
+
return true;
|
73 |
+
}
|
74 |
+
|
75 |
+
}
|
includes/class-rollback-theme-upgrader.php
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WP Rollback Theme Upgrader
|
4 |
+
*
|
5 |
+
* @description: Class that extends the WP Core Theme_Upgrader found in core to do rollbacks
|
6 |
+
* @copyright : http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
7 |
+
* @since : 1.0.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
// Exit if accessed directly
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
+
}
|
14 |
+
|
15 |
+
//kick things off
|
16 |
+
class WP_Rollback_Theme_Upgrader extends Theme_Upgrader {
|
17 |
+
|
18 |
+
public function rollback( $theme, $args = array() ) {
|
19 |
+
|
20 |
+
$defaults = array(
|
21 |
+
'clear_update_cache' => true,
|
22 |
+
);
|
23 |
+
$parsed_args = wp_parse_args( $args, $defaults );
|
24 |
+
|
25 |
+
$this->init();
|
26 |
+
$this->upgrade_strings();
|
27 |
+
|
28 |
+
if ( 0 ) {
|
29 |
+
$this->skin->before();
|
30 |
+
$this->skin->set_result( false );
|
31 |
+
$this->skin->error( 'up_to_date' );
|
32 |
+
$this->skin->after();
|
33 |
+
|
34 |
+
return false;
|
35 |
+
}
|
36 |
+
|
37 |
+
$theme_slug = $this->skin->theme;
|
38 |
+
|
39 |
+
$theme_version = $this->skin->options['version'];
|
40 |
+
|
41 |
+
$download_endpoint = 'https://downloads.wordpress.org/theme/';
|
42 |
+
|
43 |
+
$url = $download_endpoint . $theme_slug . '.' . $theme_version . '.zip';
|
44 |
+
|
45 |
+
|
46 |
+
add_filter( 'upgrader_pre_install', array( $this, 'current_before' ), 10, 2 );
|
47 |
+
add_filter( 'upgrader_post_install', array( $this, 'current_after' ), 10, 2 );
|
48 |
+
add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ), 10, 4 );
|
49 |
+
|
50 |
+
//'source_selection' => array($this, 'source_selection'), //there's a trac ticket to move up the directory for zip's which are made a bit differently, useful for non-.org plugins.
|
51 |
+
|
52 |
+
$this->run( array(
|
53 |
+
'package' => $url,
|
54 |
+
'destination' => get_theme_root(),
|
55 |
+
'clear_destination' => true,
|
56 |
+
'clear_working' => true,
|
57 |
+
'hook_extra' => array(
|
58 |
+
'theme' => $theme,
|
59 |
+
'type' => 'theme',
|
60 |
+
'action' => 'update',
|
61 |
+
),
|
62 |
+
) );
|
63 |
+
|
64 |
+
|
65 |
+
remove_filter( 'upgrader_pre_install', array( $this, 'current_before' ) );
|
66 |
+
remove_filter( 'upgrader_post_install', array( $this, 'current_after' ) );
|
67 |
+
remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ) );
|
68 |
+
|
69 |
+
if ( ! $this->result || is_wp_error( $this->result ) ) {
|
70 |
+
return $this->result;
|
71 |
+
}
|
72 |
+
|
73 |
+
// Force refresh of theme update information
|
74 |
+
wp_clean_themes_cache( $parsed_args['clear_update_cache'] );
|
75 |
+
|
76 |
+
return true;
|
77 |
+
|
78 |
+
}
|
79 |
+
|
80 |
+
}
|
includes/rollback-action.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Rollback Action
|
4 |
+
*/
|
5 |
+
|
6 |
+
// Exit if accessed directly
|
7 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
8 |
+
exit;
|
9 |
+
}
|
10 |
+
|
11 |
+
$nonce = 'upgrade-plugin_' . $this->plugin_slug;
|
12 |
+
$url = 'index.php?page=wp-rollback&plugin_file=' . $args['plugin_file'] . 'action=upgrade-plugin';
|
13 |
+
$plugin = $this->plugin_slug;
|
14 |
+
$version = $args['plugin_version'];
|
15 |
+
|
16 |
+
//Theme rollback
|
17 |
+
if ( isset( $_GET['theme_file'] ) ) {
|
18 |
+
|
19 |
+
//theme specific vars
|
20 |
+
$nonce = 'upgrade-theme_' . $_GET['theme_file'];
|
21 |
+
$url = 'index.php?page=wp-rollback&theme_file=' . $args['theme_file'] . 'action=upgrade-theme';
|
22 |
+
$version = $_GET['theme_version'];
|
23 |
+
$theme = $_GET['theme_file'];
|
24 |
+
|
25 |
+
$upgrader = new WP_Rollback_Theme_Upgrader( new Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme', 'version' ) ) );
|
26 |
+
|
27 |
+
$upgrader->rollback( $_GET['theme_file'] );
|
28 |
+
|
29 |
+
} elseif ( isset( $_GET['plugin_file'] ) ) {
|
30 |
+
//This is a plugin rollback
|
31 |
+
$upgrader = new WP_Rollback_Plugin_Upgrader( new Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin', 'version' ) ) );
|
32 |
+
|
33 |
+
$upgrader->rollback( $this->plugin_file );
|
34 |
+
} else {
|
35 |
+
_e( 'This rollback request is missing proper query string. Please contact support.', 'wpr' );
|
36 |
+
}
|
37 |
+
|
includes/rollback-menu.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Rollback Menu
|
4 |
+
*
|
5 |
+
* @description Provides the rollback screen view with releases and
|
6 |
+
*
|
7 |
+
*/
|
8 |
+
|
9 |
+
|
10 |
+
//Ensure we have our necessary query strings
|
11 |
+
if ( ( ! isset( $_GET['type'] ) && ! isset( $_GET['theme'] ) ) || ( ! isset( $_GET['type'] ) && ! isset( $_GET['plugin_file'] ) ) ) {
|
12 |
+
wp_die( __( 'WP Rollback is missing necessary parameters to continue. Please contact support.', 'wpr' ) );
|
13 |
+
}
|
14 |
+
|
15 |
+
$theme_rollback = $_GET['type'] == 'theme' ? true : false;
|
16 |
+
$plugin_rollback = $_GET['type'] == 'plugin' ? true : false;
|
17 |
+
$plugins = get_plugins();
|
18 |
+
?>
|
19 |
+
<div class="wrap">
|
20 |
+
|
21 |
+
<div class="wpr-content-wrap">
|
22 |
+
|
23 |
+
<h2><img src="<?php echo WP_ROLLBACK_PLUGIN_URL; ?>/assets/images/wprb-icon-final.svg" onerror="this.onerror=null; this.src='<?php echo WP_ROLLBACK_PLUGIN_URL; ?>/assets/images/wprb-logo.png'"><?php _e( 'WP Rollback', 'wpr' ); ?></h2>
|
24 |
+
|
25 |
+
<p><?php echo apply_filters( 'wpr_rollback_description', sprintf( __( 'Please select which %1$s version you would like to rollback to from the releases listed below. You currently have version %2$s installed of %3$s.', 'wpr' ), '<span class="type">' . ( $theme_rollback == true ? 'theme' : 'plugin' ) . '</span>', '<span class="current-version">' . $args['current_version'] . '</span>', '<span class="rollback-name">' . $args['rollback_name'] . '</span>' ) ); ?></p>
|
26 |
+
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<?php if ( isset( $args['plugin_file'] ) && in_array( $args['plugin_file'], array_keys( $plugins ) ) ) {
|
30 |
+
$versions = WP_Rollback()->versions_select( 'plugin' );
|
31 |
+
} elseif ( $theme_rollback == true && isset( $_GET['theme_file'] ) ) {
|
32 |
+
//theme rollback: set up our theme vars
|
33 |
+
$svn_tags = WP_Rollback()->get_svn_tags( 'theme', $_GET['theme_file'] );
|
34 |
+
$this->set_svn_versions_data( $svn_tags );
|
35 |
+
$this->current_version = $_GET['current_version'];
|
36 |
+
$versions = WP_Rollback()->versions_select( 'theme' );
|
37 |
+
|
38 |
+
} else {
|
39 |
+
//Fallback check
|
40 |
+
wp_die( 'Oh no! We\'re missing required rollback query strings. Please contact support so we can check this bug out and squash it!', 'wpr' );
|
41 |
+
}
|
42 |
+
?>
|
43 |
+
|
44 |
+
<form name="check_for_rollbacks" class="rollback-form" action="<?php echo admin_url( '/index.php' ); ?>">
|
45 |
+
<?php
|
46 |
+
//Output Versions
|
47 |
+
if ( ! empty( $versions ) ) { ?>
|
48 |
+
|
49 |
+
<div class="wpr-versions-wrap">
|
50 |
+
|
51 |
+
<?php
|
52 |
+
do_action( 'wpr_pre_versions' );
|
53 |
+
|
54 |
+
echo apply_filters( 'wpr_versions_output', $versions );
|
55 |
+
|
56 |
+
do_action( 'wpr_post_version' ); ?>
|
57 |
+
|
58 |
+
</div>
|
59 |
+
|
60 |
+
<?php } ?>
|
61 |
+
|
62 |
+
<div class="wpr-submit-wrap">
|
63 |
+
<a href="#wpr-modal-confirm" class="magnific-popup button-primary wpr-rollback-disabled"><?php _e( 'Rollback', 'wpr' ); ?></a>
|
64 |
+
<input type="submit" value="<?php _e( 'Cancel', 'wpr' ); ?>" class="button" />
|
65 |
+
</div>
|
66 |
+
<?php do_action( 'wpr_hidden_fields' ); ?>
|
67 |
+
<input type="hidden" name="page" value="wp-rollback">
|
68 |
+
<?php
|
69 |
+
//Important: We need the appropriate file to perform a rollback
|
70 |
+
if ( $plugin_rollback == true ) { ?>
|
71 |
+
<input type="hidden" name="plugin_file" value="<?php echo $args['plugin_file']; ?>">
|
72 |
+
<?php } else { ?>
|
73 |
+
<input type="hidden" name="theme_file" value="<?php echo $_GET['theme_file']; ?>">
|
74 |
+
<?php } ?>
|
75 |
+
<input type="hidden" name="rollback_name" value="<?php echo $args['rollback_name']; ?>">
|
76 |
+
<input type="hidden" name="installed_version" value="<?php echo $args['current_version']; ?>">
|
77 |
+
|
78 |
+
|
79 |
+
<div id="wpr-modal-confirm" class="white-popup mfp-hide">
|
80 |
+
<div class="wpr-modal-inner">
|
81 |
+
<p class="wpr-rollback-intro"><?php
|
82 |
+
_e( 'Are you sure you want to perform the following rollback?', 'wpr' );
|
83 |
+
?></p>
|
84 |
+
|
85 |
+
<div class="rollback-details">
|
86 |
+
<table class="widefat">
|
87 |
+
<tbody>
|
88 |
+
<?php do_action( 'wpr_pre_rollback_table' ); ?>
|
89 |
+
<tr>
|
90 |
+
<td class="row-title">
|
91 |
+
<label for="tablecell"><?php if ( $plugin_rollback == true ) {
|
92 |
+
_e( 'Plugin Name:', 'wpr' );
|
93 |
+
} else {
|
94 |
+
_e( 'Theme Name:', 'wpr' );
|
95 |
+
} ?></label>
|
96 |
+
</td>
|
97 |
+
<td><span class="wpr-plugin-name"></span></td>
|
98 |
+
</tr>
|
99 |
+
<tr class="alternate">
|
100 |
+
<td class="row-title">
|
101 |
+
<label for="tablecell"><?php _e( 'Installed Version:', 'wpr' ); ?></label>
|
102 |
+
</td>
|
103 |
+
<td><span class="wpr-installed-version"></span></td>
|
104 |
+
</tr>
|
105 |
+
<tr>
|
106 |
+
<td class="row-title">
|
107 |
+
<label for="tablecell"><?php _e( 'New Version:', 'wpr' ); ?></label>
|
108 |
+
</td>
|
109 |
+
<td><span class="wpr-new-version"></span></td>
|
110 |
+
</tr>
|
111 |
+
<?php do_action( 'wpr_post_rollback_table' ); ?>
|
112 |
+
</tbody>
|
113 |
+
</table>
|
114 |
+
</div>
|
115 |
+
<div class="wpr-error">
|
116 |
+
<p><?php
|
117 |
+
_e( '<strong>Notice:</strong> We strongly recommend you perform a test rollback on a staging site and create a complete backup of your WordPress files and database prior to performing a rollback. We are not responsible for any misuse, deletions, white screens, fatal errors, or any other issue arising from using this plugin.', 'wpr' );
|
118 |
+
?></p>
|
119 |
+
</div>
|
120 |
+
<?php do_action( 'wpr_pre_rollback_buttons' ); ?>
|
121 |
+
<input type="submit" value="<?php _e( 'Rollback', 'wpr' ); ?>" class="button-primary wpr-go" />
|
122 |
+
<a href="#" class="button wpr-close"><?php _e( 'Cancel', 'wpr' ); ?></a>
|
123 |
+
<?php do_action( 'wpr_post_rollback_buttons' ); ?>
|
124 |
+
</div>
|
125 |
+
</div>
|
126 |
+
|
127 |
+
</form>
|
128 |
+
|
129 |
+
</div>
|
languages/wp-rollback.pot
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
msgid ""
|
2 |
+
msgstr ""
|
3 |
+
"Project-Id-Version: WP Rollback\n"
|
4 |
+
"POT-Creation-Date: 2015-05-12 14:31-0800\n"
|
5 |
+
"PO-Revision-Date: 2015-05-12 14:32-0800\n"
|
6 |
+
"Last-Translator: \n"
|
7 |
+
"Language-Team: WordImpress <info@wordimpress.com>\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"X-Generator: Poedit 1.7.6\n"
|
12 |
+
"X-Poedit-Basepath: ..\n"
|
13 |
+
"X-Poedit-SourceCharset: UTF-8\n"
|
14 |
+
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
|
15 |
+
"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
|
16 |
+
"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
|
17 |
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
18 |
+
"X-Poedit-SearchPath-0: .\n"
|
19 |
+
"X-Poedit-SearchPathExcluded-0: *.js\n"
|
20 |
+
|
21 |
+
#: includes/rollback-action.php:35
|
22 |
+
msgid ""
|
23 |
+
"This rollback request is missing proper query string. Please contact support."
|
24 |
+
msgstr ""
|
25 |
+
|
26 |
+
#: includes/rollback-menu.php:12
|
27 |
+
msgid ""
|
28 |
+
"WP Rollback is missing necessary parameters to continue. Please contact "
|
29 |
+
"support."
|
30 |
+
msgstr ""
|
31 |
+
|
32 |
+
#: includes/rollback-menu.php:23
|
33 |
+
msgid "WP Rollback"
|
34 |
+
msgstr ""
|
35 |
+
|
36 |
+
#: includes/rollback-menu.php:25
|
37 |
+
#, php-format
|
38 |
+
msgid ""
|
39 |
+
"Please select which %1$s version you would like to rollback to from the "
|
40 |
+
"releases listed below. You currently have version %2$s installed of %3$s."
|
41 |
+
msgstr ""
|
42 |
+
|
43 |
+
#: includes/rollback-menu.php:63 includes/rollback-menu.php:121
|
44 |
+
#: wp-rollback.php:211 wp-rollback.php:455 wp-rollback.php:515
|
45 |
+
msgid "Rollback"
|
46 |
+
msgstr ""
|
47 |
+
|
48 |
+
#: includes/rollback-menu.php:64 includes/rollback-menu.php:122
|
49 |
+
msgid "Cancel"
|
50 |
+
msgstr ""
|
51 |
+
|
52 |
+
#: includes/rollback-menu.php:82
|
53 |
+
msgid "Are you sure you want to perform the following rollback?"
|
54 |
+
msgstr ""
|
55 |
+
|
56 |
+
#: includes/rollback-menu.php:92
|
57 |
+
msgid "Plugin Name:"
|
58 |
+
msgstr ""
|
59 |
+
|
60 |
+
#: includes/rollback-menu.php:94
|
61 |
+
msgid "Theme Name:"
|
62 |
+
msgstr ""
|
63 |
+
|
64 |
+
#: includes/rollback-menu.php:101
|
65 |
+
msgid "Installed Version:"
|
66 |
+
msgstr ""
|
67 |
+
|
68 |
+
#: includes/rollback-menu.php:107
|
69 |
+
msgid "New Version:"
|
70 |
+
msgstr ""
|
71 |
+
|
72 |
+
#: includes/rollback-menu.php:117
|
73 |
+
msgid ""
|
74 |
+
"<strong>Notice:</strong> We strongly recommend you perform a test rollback "
|
75 |
+
"on a staging site and create a complete backup of your WordPress files and "
|
76 |
+
"database prior to performing a rollback. We are not responsible for any "
|
77 |
+
"misuse, deletions, white screens, fatal errors, or any other issue arising "
|
78 |
+
"from using this plugin."
|
79 |
+
msgstr ""
|
80 |
+
|
81 |
+
#: wp-rollback.php:122 wp-rollback.php:134
|
82 |
+
msgid "Cheatin’ huh?"
|
83 |
+
msgstr ""
|
84 |
+
|
85 |
+
#: wp-rollback.php:212
|
86 |
+
msgid "No Rollback Available: This is a non-WordPress.org theme."
|
87 |
+
msgstr ""
|
88 |
+
|
89 |
+
#: wp-rollback.php:213
|
90 |
+
msgid "Loading..."
|
91 |
+
msgstr ""
|
92 |
+
|
93 |
+
#: wp-rollback.php:232
|
94 |
+
msgid "Please select a version number to perform a rollback."
|
95 |
+
msgstr ""
|
96 |
+
|
97 |
+
#: wp-rollback.php:280
|
98 |
+
msgid ""
|
99 |
+
"You do not have sufficient permissions to perform rollbacks for this site."
|
100 |
+
msgstr ""
|
101 |
+
|
102 |
+
#: wp-rollback.php:402
|
103 |
+
msgid "Installed Version"
|
104 |
+
msgstr ""
|
105 |
+
|
106 |
+
#: wp-rollback.php:627
|
107 |
+
msgid ""
|
108 |
+
"An unexpected error occurred. Something may be wrong with WordPress.org or "
|
109 |
+
"this server’s configuration. If you continue to have problems, please "
|
110 |
+
"try the <a href=\"https://wordpress.org/support/\">support forums</a>."
|
111 |
+
msgstr ""
|
112 |
+
|
113 |
+
#: wp-rollback.php:627
|
114 |
+
msgid ""
|
115 |
+
"(WordPress could not establish a secure connection to WordPress.org. Please "
|
116 |
+
"contact your server administrator.)"
|
117 |
+
msgstr ""
|
license.txt
ADDED
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
GNU GENERAL PUBLIC LICENSE
|
2 |
+
Version 2, June 1991
|
3 |
+
|
4 |
+
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
5 |
+
51 Franklin St, Fifth Floor, Boston, MA 02110, USA
|
6 |
+
|
7 |
+
Everyone is permitted to copy and distribute verbatim copies
|
8 |
+
of this license document, but changing it is not allowed.
|
9 |
+
|
10 |
+
Preamble
|
11 |
+
|
12 |
+
The licenses for most software are designed to take away your
|
13 |
+
freedom to share and change it. By contrast, the GNU General Public
|
14 |
+
License is intended to guarantee your freedom to share and change free
|
15 |
+
software--to make sure the software is free for all its users. This
|
16 |
+
General Public License applies to most of the Free Software
|
17 |
+
Foundation's software and to any other program whose authors commit to
|
18 |
+
using it. (Some other Free Software Foundation software is covered by
|
19 |
+
the GNU Library General Public License instead.) You can apply it to
|
20 |
+
your programs, too.
|
21 |
+
|
22 |
+
When we speak of free software, we are referring to freedom, not
|
23 |
+
price. Our General Public Licenses are designed to make sure that you
|
24 |
+
have the freedom to distribute copies of free software (and charge for
|
25 |
+
this service if you wish), that you receive source code or can get it
|
26 |
+
if you want it, that you can change the software or use pieces of it
|
27 |
+
in new free programs; and that you know you can do these things.
|
28 |
+
|
29 |
+
To protect your rights, we need to make restrictions that forbid
|
30 |
+
anyone to deny you these rights or to ask you to surrender the rights.
|
31 |
+
These restrictions translate to certain responsibilities for you if you
|
32 |
+
distribute copies of the software, or if you modify it.
|
33 |
+
|
34 |
+
For example, if you distribute copies of such a program, whether
|
35 |
+
gratis or for a fee, you must give the recipients all the rights that
|
36 |
+
you have. You must make sure that they, too, receive or can get the
|
37 |
+
source code. And you must show them these terms so they know their
|
38 |
+
rights.
|
39 |
+
|
40 |
+
We protect your rights with two steps: (1) copyright the software, and
|
41 |
+
(2) offer you this license which gives you legal permission to copy,
|
42 |
+
distribute and/or modify the software.
|
43 |
+
|
44 |
+
Also, for each author's protection and ours, we want to make certain
|
45 |
+
that everyone understands that there is no warranty for this free
|
46 |
+
software. If the software is modified by someone else and passed on, we
|
47 |
+
want its recipients to know that what they have is not the original, so
|
48 |
+
that any problems introduced by others will not reflect on the original
|
49 |
+
authors' reputations.
|
50 |
+
|
51 |
+
Finally, any free program is threatened constantly by software
|
52 |
+
patents. We wish to avoid the danger that redistributors of a free
|
53 |
+
program will individually obtain patent licenses, in effect making the
|
54 |
+
program proprietary. To prevent this, we have made it clear that any
|
55 |
+
patent must be licensed for everyone's free use or not licensed at all.
|
56 |
+
|
57 |
+
The precise terms and conditions for copying, distribution and
|
58 |
+
modification follow.
|
59 |
+
|
60 |
+
GNU GENERAL PUBLIC LICENSE
|
61 |
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
62 |
+
|
63 |
+
0. This License applies to any program or other work which contains
|
64 |
+
a notice placed by the copyright holder saying it may be distributed
|
65 |
+
under the terms of this General Public License. The "Program", below,
|
66 |
+
refers to any such program or work, and a "work based on the Program"
|
67 |
+
means either the Program or any derivative work under copyright law:
|
68 |
+
that is to say, a work containing the Program or a portion of it,
|
69 |
+
either verbatim or with modifications and/or translated into another
|
70 |
+
language. (Hereinafter, translation is included without limitation in
|
71 |
+
the term "modification".) Each licensee is addressed as "you".
|
72 |
+
|
73 |
+
Activities other than copying, distribution and modification are not
|
74 |
+
covered by this License; they are outside its scope. The act of
|
75 |
+
running the Program is not restricted, and the output from the Program
|
76 |
+
is covered only if its contents constitute a work based on the
|
77 |
+
Program (independent of having been made by running the Program).
|
78 |
+
Whether that is true depends on what the Program does.
|
79 |
+
|
80 |
+
1. You may copy and distribute verbatim copies of the Program's
|
81 |
+
source code as you receive it, in any medium, provided that you
|
82 |
+
conspicuously and appropriately publish on each copy an appropriate
|
83 |
+
copyright notice and disclaimer of warranty; keep intact all the
|
84 |
+
notices that refer to this License and to the absence of any warranty;
|
85 |
+
and give any other recipients of the Program a copy of this License
|
86 |
+
along with the Program.
|
87 |
+
|
88 |
+
You may charge a fee for the physical act of transferring a copy, and
|
89 |
+
you may at your option offer warranty protection in exchange for a fee.
|
90 |
+
|
91 |
+
2. You may modify your copy or copies of the Program or any portion
|
92 |
+
of it, thus forming a work based on the Program, and copy and
|
93 |
+
distribute such modifications or work under the terms of Section 1
|
94 |
+
above, provided that you also meet all of these conditions:
|
95 |
+
|
96 |
+
a) You must cause the modified files to carry prominent notices
|
97 |
+
stating that you changed the files and the date of any change.
|
98 |
+
|
99 |
+
b) You must cause any work that you distribute or publish, that in
|
100 |
+
whole or in part contains or is derived from the Program or any
|
101 |
+
part thereof, to be licensed as a whole at no charge to all third
|
102 |
+
parties under the terms of this License.
|
103 |
+
|
104 |
+
c) If the modified program normally reads commands interactively
|
105 |
+
when run, you must cause it, when started running for such
|
106 |
+
interactive use in the most ordinary way, to print or display an
|
107 |
+
announcement including an appropriate copyright notice and a
|
108 |
+
notice that there is no warranty (or else, saying that you provide
|
109 |
+
a warranty) and that users may redistribute the program under
|
110 |
+
these conditions, and telling the user how to view a copy of this
|
111 |
+
License. (Exception: if the Program itself is interactive but
|
112 |
+
does not normally print such an announcement, your work based on
|
113 |
+
the Program is not required to print an announcement.)
|
114 |
+
|
115 |
+
These requirements apply to the modified work as a whole. If
|
116 |
+
identifiable sections of that work are not derived from the Program,
|
117 |
+
and can be reasonably considered independent and separate works in
|
118 |
+
themselves, then this License, and its terms, do not apply to those
|
119 |
+
sections when you distribute them as separate works. But when you
|
120 |
+
distribute the same sections as part of a whole which is a work based
|
121 |
+
on the Program, the distribution of the whole must be on the terms of
|
122 |
+
this License, whose permissions for other licensees extend to the
|
123 |
+
entire whole, and thus to each and every part regardless of who wrote it.
|
124 |
+
Thus, it is not the intent of this section to claim rights or contest
|
125 |
+
your rights to work written entirely by you; rather, the intent is to
|
126 |
+
exercise the right to control the distribution of derivative or
|
127 |
+
collective works based on the Program.
|
128 |
+
|
129 |
+
In addition, mere aggregation of another work not based on the Program
|
130 |
+
with the Program (or with a work based on the Program) on a volume of
|
131 |
+
a storage or distribution medium does not bring the other work under
|
132 |
+
the scope of this License.
|
133 |
+
|
134 |
+
3. You may copy and distribute the Program (or a work based on it,
|
135 |
+
under Section 2) in object code or executable form under the terms of
|
136 |
+
Sections 1 and 2 above provided that you also do one of the following:
|
137 |
+
|
138 |
+
a) Accompany it with the complete corresponding machine-readable
|
139 |
+
source code, which must be distributed under the terms of Sections
|
140 |
+
1 and 2 above on a medium customarily used for software interchange; or,
|
141 |
+
|
142 |
+
b) Accompany it with a written offer, valid for at least three
|
143 |
+
years, to give any third party, for a charge no more than your
|
144 |
+
cost of physically performing source distribution, a complete
|
145 |
+
machine-readable copy of the corresponding source code, to be
|
146 |
+
distributed under the terms of Sections 1 and 2 above on a medium
|
147 |
+
customarily used for software interchange; or,
|
148 |
+
|
149 |
+
c) Accompany it with the information you received as to the offer
|
150 |
+
to distribute corresponding source code. (This alternative is
|
151 |
+
allowed only for noncommercial distribution and only if you
|
152 |
+
received the program in object code or executable form with such
|
153 |
+
an offer, in accord with Subsection b above.)
|
154 |
+
|
155 |
+
The source code for a work means the preferred form of the work for
|
156 |
+
making modifications to it. For an executable work, complete source
|
157 |
+
code means all the source code for all modules it contains, plus any
|
158 |
+
associated interface definition files, plus the scripts used to
|
159 |
+
control compilation and installation of the executable. However, as a
|
160 |
+
special exception, the source code distributed need not include
|
161 |
+
anything that is normally distributed (in either source or binary
|
162 |
+
form) with the major components (compiler, kernel, and so on) of the
|
163 |
+
operating system on which the executable runs, unless that component
|
164 |
+
itself accompanies the executable.
|
165 |
+
|
166 |
+
If distribution of executable or object code is made by offering
|
167 |
+
access to copy from a designated place, then offering equivalent
|
168 |
+
access to copy the source code from the same place counts as
|
169 |
+
distribution of the source code, even though third parties are not
|
170 |
+
compelled to copy the source along with the object code.
|
171 |
+
|
172 |
+
4. You may not copy, modify, sublicense, or distribute the Program
|
173 |
+
except as expressly provided under this License. Any attempt
|
174 |
+
otherwise to copy, modify, sublicense or distribute the Program is
|
175 |
+
void, and will automatically terminate your rights under this License.
|
176 |
+
However, parties who have received copies, or rights, from you under
|
177 |
+
this License will not have their licenses terminated so long as such
|
178 |
+
parties remain in full compliance.
|
179 |
+
|
180 |
+
5. You are not required to accept this License, since you have not
|
181 |
+
signed it. However, nothing else grants you permission to modify or
|
182 |
+
distribute the Program or its derivative works. These actions are
|
183 |
+
prohibited by law if you do not accept this License. Therefore, by
|
184 |
+
modifying or distributing the Program (or any work based on the
|
185 |
+
Program), you indicate your acceptance of this License to do so, and
|
186 |
+
all its terms and conditions for copying, distributing or modifying
|
187 |
+
the Program or works based on it.
|
188 |
+
|
189 |
+
6. Each time you redistribute the Program (or any work based on the
|
190 |
+
Program), the recipient automatically receives a license from the
|
191 |
+
original licensor to copy, distribute or modify the Program subject to
|
192 |
+
these terms and conditions. You may not impose any further
|
193 |
+
restrictions on the recipients' exercise of the rights granted herein.
|
194 |
+
You are not responsible for enforcing compliance by third parties to
|
195 |
+
this License.
|
196 |
+
|
197 |
+
7. If, as a consequence of a court judgment or allegation of patent
|
198 |
+
infringement or for any other reason (not limited to patent issues),
|
199 |
+
conditions are imposed on you (whether by court order, agreement or
|
200 |
+
otherwise) that contradict the conditions of this License, they do not
|
201 |
+
excuse you from the conditions of this License. If you cannot
|
202 |
+
distribute so as to satisfy simultaneously your obligations under this
|
203 |
+
License and any other pertinent obligations, then as a consequence you
|
204 |
+
may not distribute the Program at all. For example, if a patent
|
205 |
+
license would not permit royalty-free redistribution of the Program by
|
206 |
+
all those who receive copies directly or indirectly through you, then
|
207 |
+
the only way you could satisfy both it and this License would be to
|
208 |
+
refrain entirely from distribution of the Program.
|
209 |
+
|
210 |
+
If any portion of this section is held invalid or unenforceable under
|
211 |
+
any particular circumstance, the balance of the section is intended to
|
212 |
+
apply and the section as a whole is intended to apply in other
|
213 |
+
circumstances.
|
214 |
+
|
215 |
+
It is not the purpose of this section to induce you to infringe any
|
216 |
+
patents or other property right claims or to contest validity of any
|
217 |
+
such claims; this section has the sole purpose of protecting the
|
218 |
+
integrity of the free software distribution system, which is
|
219 |
+
implemented by public license practices. Many people have made
|
220 |
+
generous contributions to the wide range of software distributed
|
221 |
+
through that system in reliance on consistent application of that
|
222 |
+
system; it is up to the author/donor to decide if he or she is willing
|
223 |
+
to distribute software through any other system and a licensee cannot
|
224 |
+
impose that choice.
|
225 |
+
|
226 |
+
This section is intended to make thoroughly clear what is believed to
|
227 |
+
be a consequence of the rest of this License.
|
228 |
+
|
229 |
+
8. If the distribution and/or use of the Program is restricted in
|
230 |
+
certain countries either by patents or by copyrighted interfaces, the
|
231 |
+
original copyright holder who places the Program under this License
|
232 |
+
may add an explicit geographical distribution limitation excluding
|
233 |
+
those countries, so that distribution is permitted only in or among
|
234 |
+
countries not thus excluded. In such case, this License incorporates
|
235 |
+
the limitation as if written in the body of this License.
|
236 |
+
|
237 |
+
9. The Free Software Foundation may publish revised and/or new versions
|
238 |
+
of the General Public License from time to time. Such new versions will
|
239 |
+
be similar in spirit to the present version, but may differ in detail to
|
240 |
+
address new problems or concerns.
|
241 |
+
|
242 |
+
Each version is given a distinguishing version number. If the Program
|
243 |
+
specifies a version number of this License which applies to it and "any
|
244 |
+
later version", you have the option of following the terms and conditions
|
245 |
+
either of that version or of any later version published by the Free
|
246 |
+
Software Foundation. If the Program does not specify a version number of
|
247 |
+
this License, you may choose any version ever published by the Free Software
|
248 |
+
Foundation.
|
249 |
+
|
250 |
+
10. If you wish to incorporate parts of the Program into other free
|
251 |
+
programs whose distribution conditions are different, write to the author
|
252 |
+
to ask for permission. For software which is copyrighted by the Free
|
253 |
+
Software Foundation, write to the Free Software Foundation; we sometimes
|
254 |
+
make exceptions for this. Our decision will be guided by the two goals
|
255 |
+
of preserving the free status of all derivatives of our free software and
|
256 |
+
of promoting the sharing and reuse of software generally.
|
257 |
+
|
258 |
+
NO WARRANTY
|
259 |
+
|
260 |
+
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
261 |
+
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
262 |
+
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
263 |
+
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
264 |
+
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
265 |
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
266 |
+
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
267 |
+
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
268 |
+
REPAIR OR CORRECTION.
|
269 |
+
|
270 |
+
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
271 |
+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
272 |
+
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
273 |
+
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
274 |
+
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
275 |
+
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
276 |
+
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
277 |
+
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
278 |
+
POSSIBILITY OF SUCH DAMAGES.
|
279 |
+
|
280 |
+
END OF TERMS AND CONDITIONS
|
281 |
+
|
readme.txt
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== WP Rollback ===
|
2 |
+
Contributors: wordimpress, dlocc, drrobotnik, webdevmattcrom
|
3 |
+
Tags: rollback, revert, downgrade, version, plugins, themes, version, versions, backup, backups, revision, revisions
|
4 |
+
Requires at least: 3.8
|
5 |
+
Donate Link: https://wordimpress.com
|
6 |
+
Tested up to: 4.2.2
|
7 |
+
Stable tag: 1.0
|
8 |
+
License: GPLv3
|
9 |
+
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
+
|
11 |
+
Rollback (or forward) any WordPress.org plugin or theme like a boss.
|
12 |
+
|
13 |
+
== Description ==
|
14 |
+
|
15 |
+
Quickly and easily rollback any theme or plugin from WordPress.org to any previous (or newer) version without any of the manual fuss. Works just like the plugin updater, except you're rolling back (or forward) to a specific version. No need for manually downloading and FTPing the files or learning Subversion. This plugin takes care of the trouble for you.
|
16 |
+
|
17 |
+
= Rollback WordPress.org Plugins and Themes =
|
18 |
+
|
19 |
+
While it's considered best practice to always keep your WordPress plugins and themes updated, we understand there are times you may need to quickly revert to a previous version. This plugin makes that process as easy as a few mouse clicks. Simply select the version of the plugin or theme that you'd like to rollback to, confirm, and in a few moments you'll be using the version requested. No more fumbling to find the version, downloading, unzipping, FTPing, learning Subversion or hair pulling.
|
20 |
+
|
21 |
+
= Muy Importante (Very Important): Always Test and Backup =
|
22 |
+
|
23 |
+
**Important Disclaimer:** This plugin is not intended to be used without first taking the proper precautions to ensure zero data loss or site downtime. Always be sure you have first tested the rollback on a staging or development site prior to using WP Rollback on a live site.
|
24 |
+
|
25 |
+
We provide no (zero) assurances, guarantees, or warrenties that the plugin, theme, or WordPress version you are downgrading to will work as you expect. Use this plugin at your own risk.
|
26 |
+
|
27 |
+
= Translation Ready =
|
28 |
+
|
29 |
+
Do you speak another language? Want to contribute in a meaninful way to WP Rollback? There's no better way than to help us translate the plugin. This plugin is translation ready. Simply use the wp-rollback.pot file and your favorite translation tool. Once finished, please reach out to us on the WordPress.org forums or better yet, submit a pull request on the [Github Repo](https://github.com/WordImpress/WP-Rollback/).
|
30 |
+
|
31 |
+
= Support and Documentation =
|
32 |
+
|
33 |
+
We answer all support requests [on the WordPress.org support forum](https://wordpress.org/support/plugin/wp-rollback).
|
34 |
+
|
35 |
+
WP Rollback was created to be as intuitive to the natural WordPress experience as possible. There are is no dedicated setting page or option panels. We believe that once you activate WP Rollback, you'll quickly discover exactly how it works without question.
|
36 |
+
|
37 |
+
**BUT!!**
|
38 |
+
|
39 |
+
We do have documentation on the plugin [Github Wiki](https://github.com/WordImpress/WP-Rollback/wiki).
|
40 |
+
|
41 |
+
== Installation ==
|
42 |
+
|
43 |
+
= Minimum Requirements =
|
44 |
+
|
45 |
+
* WordPress 3.8 or greater
|
46 |
+
* PHP version 5.3 or greater
|
47 |
+
* MySQL version 5.0 or greater
|
48 |
+
|
49 |
+
= Automatic installation =
|
50 |
+
|
51 |
+
Automatic installation is the easiest option as WordPress handles the file transfers itself and you don't need to leave your web browser. To do an automatic install of WP Rollback, log in to your WordPress dashboard, navigate to the Plugins menu and click Add New.
|
52 |
+
|
53 |
+
In the search field type "WP Rollback" and click Search Plugins. Once you have found the plugin you can view details about it such as the the point release, rating and description. Most importantly of course, you can install it by simply clicking "Install Now".
|
54 |
+
|
55 |
+
= Manual installation =
|
56 |
+
|
57 |
+
The manual installation method involves downloading our donation plugin and uploading it to your server via your favorite FTP application. The WordPress codex contains [instructions on how to do this here](http://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation).
|
58 |
+
|
59 |
+
= Updating =
|
60 |
+
|
61 |
+
Automatic updates should work like a charm; as always though, ensure you backup your site just in case.
|
62 |
+
|
63 |
+
== Frequently Asked Questions ==
|
64 |
+
|
65 |
+
= Is this plugin safe to use? =
|
66 |
+
Short answer = Yes. Longer answer = It depends on how you use it.
|
67 |
+
|
68 |
+
WP Rollback is completely safe because all it does is take publicly available versions of the plugins you already have on your site and install the version that you designate. There is no other kinds of trickery or fancy offsite calls or anything.
|
69 |
+
|
70 |
+
**BUT!!!**
|
71 |
+
|
72 |
+
It depends on you. We absolutely do NOT recommend rolling back any plugins or themes on a live site. Test the rollback locally first, have backups, use all the best practice tools available to you. This is intended to make rolling back easier, that's all.
|
73 |
+
|
74 |
+
= Why isn't there a rollback button next to X plugin or theme? =
|
75 |
+
|
76 |
+
WP Rollback only works with plugins or themes installed from the WordPress Repository. If you don't see the rollback link, then most likely that plugin or theme is not found on WordPress.org. This plugin does not support plugins from Github, ThemeForest, or other sources other than the WordPress.org Repo.
|
77 |
+
|
78 |
+
= I rolled my [insert plugin name] back to version X.X and now my site is broken. This is your fault. =
|
79 |
+
|
80 |
+
Nope. We warned you in **bold** print several times in many places. And our plugin delivered exactly what it said it would do. May the gods of the Internet pity your broken site's soul.
|
81 |
+
|
82 |
+
= Where is the complete documentation located? =
|
83 |
+
|
84 |
+
The documentation for this plugin is located on our [Github Wiki](https://github.com/WordImpress/WP-Rollback/wiki). This is where we make regular updates.
|
85 |
+
|
86 |
+
= Can this plugin be translated? =
|
87 |
+
|
88 |
+
Yes! All strings are internationalized and ready to be translated. Simply use the languages/wp-rollback.pot file and your favorite translation tool. Once finished, please reach out to us on the WordPress.org forums or better yet, submit a pull request on the [Github Repo](https://github.com/WordImpress/WP-Rollback/).
|
89 |
+
|
90 |
+
== Screenshots ==
|
91 |
+
|
92 |
+
1. The Rollback link on the Plugins page.
|
93 |
+
|
94 |
+
2. The Rollback Versions page for a plugin.
|
95 |
+
|
96 |
+
3. The Update plugin screen.
|
97 |
+
|
98 |
+
4. The Rollback button on the Theme Modal popup.
|
99 |
+
|
100 |
+
5. The Rollback Versions page for a theme.
|
101 |
+
|
102 |
+
6. The Rollback modal confirmation popup.
|
103 |
+
|
104 |
+
7. The Update theme screen.
|
105 |
+
|
106 |
+
== Upgrade Notice ==
|
107 |
+
|
108 |
+
This is the first version of this plugin. It is a tool for your convenience. Rollback at your own risk!
|
109 |
+
|
110 |
+
== Changelog ==
|
111 |
+
|
112 |
+
= 1.0 =
|
113 |
+
|
114 |
+
* Initial plugin release. Yippee!
|
115 |
+
* Adds "Rollback" link to all plugins from the WordPress repo on the plugin screen.
|
116 |
+
* Adds "Rollback" link to all themes from the WordPress repo inside the modal details screen.
|
117 |
+
* The "Rollback" page allows you to choose which version you want to rollback to.
|
wp-rollback.php
ADDED
@@ -0,0 +1,695 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin Name: WP Rollback
|
4 |
+
* Plugin URI: http://wordimpress.com
|
5 |
+
* Description: Rollback any WordPress.org plugin or theme like a boss.
|
6 |
+
* Author: WordImpress
|
7 |
+
* Author URI: http://wordimpress.com
|
8 |
+
* Version: 1.0
|
9 |
+
* Text Domain: wpr
|
10 |
+
* Domain Path: languages
|
11 |
+
*
|
12 |
+
* WP Rollback is free software: you can redistribute it and/or modify
|
13 |
+
* it under the terms of the GNU General Public License as published by
|
14 |
+
* the Free Software Foundation, either version 2 of the License, or
|
15 |
+
* any later version.
|
16 |
+
*
|
17 |
+
* WP Rollback is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with WP Rollback. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*
|
25 |
+
*/
|
26 |
+
|
27 |
+
// Exit if accessed directly
|
28 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
29 |
+
exit;
|
30 |
+
}
|
31 |
+
|
32 |
+
if ( ! class_exists( 'WP Rollback' ) ) : /**
|
33 |
+
* Main WP Rollback Class
|
34 |
+
*
|
35 |
+
* @since 1.0
|
36 |
+
*/ {
|
37 |
+
final class WP_Rollback {
|
38 |
+
/** Singleton *************************************************************/
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @var WP_Rollback The one and only
|
42 |
+
* @since 1.0
|
43 |
+
*/
|
44 |
+
private static $instance;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* WP_Rollback Settings Object
|
48 |
+
*
|
49 |
+
* @var object
|
50 |
+
* @since 1.0
|
51 |
+
*/
|
52 |
+
public $wpr_settings;
|
53 |
+
|
54 |
+
public $plugins_repo = 'http://plugins.svn.wordpress.org';
|
55 |
+
|
56 |
+
public $themes_repo = 'http://themes.svn.wordpress.org';
|
57 |
+
|
58 |
+
public $plugin_file;
|
59 |
+
|
60 |
+
public $plugin_slug;
|
61 |
+
|
62 |
+
public $versions;
|
63 |
+
|
64 |
+
public $current_version;
|
65 |
+
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Main WP_Rollback Instance
|
69 |
+
*
|
70 |
+
* Insures that only one instance of WP Rollback exists in memory at any one
|
71 |
+
* time. Also prevents needing to define globals all over the place.
|
72 |
+
*
|
73 |
+
* @since 1.0
|
74 |
+
* @static
|
75 |
+
* @staticvar array $instance
|
76 |
+
* @uses WP_Rollback::setup_constants() Setup the constants needed
|
77 |
+
* @uses WP_Rollback::includes() Include the required files
|
78 |
+
* @uses WP_Rollback::load_textdomain() load the language files
|
79 |
+
* @see WP_Rollback()
|
80 |
+
* @return WP_Rollback
|
81 |
+
*/
|
82 |
+
public static function instance() {
|
83 |
+
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof WP_Rollback ) && is_admin() ) {
|
84 |
+
self::$instance = new WP_Rollback;
|
85 |
+
self::$instance->setup_constants();
|
86 |
+
self::$instance->setup_vars();
|
87 |
+
|
88 |
+
//i18n
|
89 |
+
add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
|
90 |
+
//Admin
|
91 |
+
add_action( 'admin_enqueue_scripts', array( self::$instance, 'scripts' ) );
|
92 |
+
add_action( 'admin_menu', array( self::$instance, 'admin_menu' ), 20 );
|
93 |
+
add_action( 'pre_current_active_plugins', array(
|
94 |
+
self::$instance,
|
95 |
+
'pre_current_active_plugins'
|
96 |
+
), 20, 1 );
|
97 |
+
add_action( 'wp_ajax_is_wordpress_theme', array( self::$instance, 'is_wordpress_theme' ) );
|
98 |
+
add_action( 'set_site_transient_update_themes', array( self::$instance, 'wpr_theme_updates_list' ) );
|
99 |
+
|
100 |
+
add_filter( 'wp_prepare_themes_for_js', array( self::$instance, 'wpr_prepare_themes_js' ) );
|
101 |
+
add_filter( 'plugin_action_links', array( self::$instance, 'plugin_action_links' ), 20, 4 );
|
102 |
+
|
103 |
+
self::$instance->includes();
|
104 |
+
|
105 |
+
}
|
106 |
+
|
107 |
+
return self::$instance;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Throw error on object clone
|
112 |
+
*
|
113 |
+
* The whole idea of the singleton design pattern is that there is a single
|
114 |
+
* object therefore, we don't want the object to be cloned.
|
115 |
+
*
|
116 |
+
* @since 1.0
|
117 |
+
* @access protected
|
118 |
+
* @return void
|
119 |
+
*/
|
120 |
+
public function __clone() {
|
121 |
+
// Cloning instances of the class is forbidden
|
122 |
+
_doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'wpr' ), '1.0' );
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Disable unserializing of the class
|
127 |
+
*
|
128 |
+
* @since 1.0
|
129 |
+
* @access protected
|
130 |
+
* @return void
|
131 |
+
*/
|
132 |
+
public function __wakeup() {
|
133 |
+
// Unserializing instances of the class is forbidden
|
134 |
+
_doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'wpr' ), '1.0' );
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Setup plugin constants
|
139 |
+
*
|
140 |
+
* @access private
|
141 |
+
* @since 1.0
|
142 |
+
* @return void
|
143 |
+
*/
|
144 |
+
private function setup_constants() {
|
145 |
+
|
146 |
+
// Plugin version
|
147 |
+
if ( ! defined( 'WP_ROLLBACK_VERSION' ) ) {
|
148 |
+
define( 'WP_ROLLBACK_VERSION', '1.0' );
|
149 |
+
}
|
150 |
+
|
151 |
+
// Plugin Folder Path
|
152 |
+
if ( ! defined( 'WP_ROLLBACK_PLUGIN_DIR' ) ) {
|
153 |
+
define( 'WP_ROLLBACK_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
|
154 |
+
}
|
155 |
+
|
156 |
+
// Plugin Folder URL
|
157 |
+
if ( ! defined( 'WP_ROLLBACK_PLUGIN_URL' ) ) {
|
158 |
+
define( 'WP_ROLLBACK_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
159 |
+
}
|
160 |
+
|
161 |
+
// Plugin Root File
|
162 |
+
if ( ! defined( 'WP_ROLLBACK_PLUGIN_FILE' ) ) {
|
163 |
+
define( 'WP_ROLLBACK_PLUGIN_FILE', __FILE__ );
|
164 |
+
}
|
165 |
+
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Setup Variables
|
170 |
+
*
|
171 |
+
* @access private
|
172 |
+
* @description:
|
173 |
+
*/
|
174 |
+
private function setup_vars() {
|
175 |
+
$this->set_plugin_slug();
|
176 |
+
|
177 |
+
$svn_tags = $this->get_svn_tags( 'plugin', $this->plugin_slug );
|
178 |
+
$this->set_svn_versions_data( $svn_tags );
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Include required files
|
183 |
+
*
|
184 |
+
* @access private
|
185 |
+
* @since 1.0
|
186 |
+
* @return void
|
187 |
+
*/
|
188 |
+
private function includes() {
|
189 |
+
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Enqueue Admin Scripts
|
194 |
+
*
|
195 |
+
* @access private
|
196 |
+
* @since 1.0
|
197 |
+
*
|
198 |
+
* @param $hook
|
199 |
+
*
|
200 |
+
* @return void
|
201 |
+
*
|
202 |
+
*/
|
203 |
+
public function scripts( $hook ) {
|
204 |
+
|
205 |
+
if ( $hook === 'themes.php' ) {
|
206 |
+
wp_enqueue_script( 'wp_rollback_themes_script', plugin_dir_url( __FILE__ ) . 'assets/js/themes-wp-rollback.js', array( 'jquery' ), false, true );
|
207 |
+
//Localize for i18n
|
208 |
+
wp_localize_script( 'wp_rollback_themes_script', 'wpr_vars', array(
|
209 |
+
'ajaxurl' => admin_url(),
|
210 |
+
'ajax_loader' => admin_url( 'images/spinner.gif' ),
|
211 |
+
'text_rollback_label' => __( 'Rollback', 'wpr' ),
|
212 |
+
'text_not_rollbackable' => __( 'No Rollback Available: This is a non-WordPress.org theme.', 'wpr' ),
|
213 |
+
'text_loading_rollback' => __( 'Loading...', 'wpr' ),
|
214 |
+
) );
|
215 |
+
}
|
216 |
+
|
217 |
+
if ( $hook !== 'dashboard_page_wp-rollback' ) {
|
218 |
+
return;
|
219 |
+
}
|
220 |
+
|
221 |
+
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
222 |
+
|
223 |
+
wp_enqueue_style( 'wp_rollback_css', plugin_dir_url( __FILE__ ) . 'assets/css/wp-rollback.css' );
|
224 |
+
wp_enqueue_style( 'wp_rollback_modal_css', plugin_dir_url( __FILE__ ) . 'assets/css/magnific-popup.css' );
|
225 |
+
wp_enqueue_script( 'wp_rollback_modal', plugin_dir_url( __FILE__ ) . 'assets/js/jquery.magnific-popup' . $suffix . '.js', array( 'jquery' ) );
|
226 |
+
wp_enqueue_script( 'wp_rollback_script', plugin_dir_url( __FILE__ ) . 'assets/js/wp-rollback.js', array( 'jquery' ) );
|
227 |
+
wp_enqueue_script( 'updates' );
|
228 |
+
|
229 |
+
//Localize for i18n
|
230 |
+
wp_localize_script( 'wp_rollback_script', 'wpr_vars', array(
|
231 |
+
'ajaxurl' => admin_url(),
|
232 |
+
'version_missing' => __( 'Please select a version number to perform a rollback.', 'wpr' ),
|
233 |
+
) );
|
234 |
+
|
235 |
+
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Loads the plugin language files
|
240 |
+
*
|
241 |
+
* @access public
|
242 |
+
* @since 1.0
|
243 |
+
* @return void
|
244 |
+
*/
|
245 |
+
public function load_textdomain() {
|
246 |
+
|
247 |
+
// Set filter for plugin's languages directory
|
248 |
+
$wpr_lang_dir = dirname( plugin_basename( WP_ROLLBACK_PLUGIN_FILE ) ) . '/languages/';
|
249 |
+
$wpr_lang_dir = apply_filters( 'wpr_languages_directory', $wpr_lang_dir );
|
250 |
+
|
251 |
+
// Traditional WordPress plugin locale filter
|
252 |
+
$locale = apply_filters( 'plugin_locale', get_locale(), 'wpr' );
|
253 |
+
$mofile = sprintf( '%1$s-%2$s.mo', 'wpr', $locale );
|
254 |
+
|
255 |
+
// Setup paths to current locale file
|
256 |
+
$mofile_local = $wpr_lang_dir . $mofile;
|
257 |
+
$mofile_global = WP_LANG_DIR . '/wp-rollback/' . $mofile;
|
258 |
+
|
259 |
+
if ( file_exists( $mofile_global ) ) {
|
260 |
+
// Look in global /wp-content/languages/wpr folder
|
261 |
+
load_textdomain( 'wpr', $mofile_global );
|
262 |
+
} elseif ( file_exists( $mofile_local ) ) {
|
263 |
+
// Look in local /wp-content/plugins/wpr/languages/ folder
|
264 |
+
load_textdomain( 'wpr', $mofile_local );
|
265 |
+
} else {
|
266 |
+
// Load the default language files
|
267 |
+
load_plugin_textdomain( 'wpr', false, $wpr_lang_dir );
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* HTML
|
273 |
+
*
|
274 |
+
* @description: FILL ME IN
|
275 |
+
*
|
276 |
+
*/
|
277 |
+
public function html() {
|
278 |
+
|
279 |
+
if ( ! current_user_can( 'update_plugins' ) ) {
|
280 |
+
wp_die( __( 'You do not have sufficient permissions to perform rollbacks for this site.', 'wpr' ) );
|
281 |
+
}
|
282 |
+
|
283 |
+
//Get the necessary class
|
284 |
+
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
|
285 |
+
|
286 |
+
$defaults = apply_filters( 'wpr_rollback_html_args', array(
|
287 |
+
'page' => 'wp-rollback',
|
288 |
+
'plugin_file' => '',
|
289 |
+
'action' => '',
|
290 |
+
'plugin_version' => '',
|
291 |
+
'plugin' => ''
|
292 |
+
) );
|
293 |
+
|
294 |
+
$args = wp_parse_args( $_GET, $defaults );
|
295 |
+
|
296 |
+
if ( ! empty( $args['plugin_version'] ) ) {
|
297 |
+
//Plugin: rolling back
|
298 |
+
include WP_ROLLBACK_PLUGIN_DIR . '/includes/class-rollback-plugin-upgrader.php';
|
299 |
+
include WP_ROLLBACK_PLUGIN_DIR . '/includes/rollback-action.php';
|
300 |
+
} elseif ( ! empty( $args['theme_version'] ) ) {
|
301 |
+
//Theme: rolling back
|
302 |
+
include WP_ROLLBACK_PLUGIN_DIR . '/includes/class-rollback-theme-upgrader.php';
|
303 |
+
include WP_ROLLBACK_PLUGIN_DIR . '/includes/rollback-action.php';
|
304 |
+
} else {
|
305 |
+
//This is the menu
|
306 |
+
include WP_ROLLBACK_PLUGIN_DIR . '/includes/rollback-menu.php';
|
307 |
+
}
|
308 |
+
|
309 |
+
}
|
310 |
+
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Get Subversion Tags
|
314 |
+
*
|
315 |
+
* @description cURLs wp.org repo to get the proper tags
|
316 |
+
*
|
317 |
+
* @param $type
|
318 |
+
* @param $slug
|
319 |
+
*
|
320 |
+
* @return null|string
|
321 |
+
*/
|
322 |
+
private function get_svn_tags( $type, $slug ) {
|
323 |
+
|
324 |
+
$url = $this->plugins_repo . '/' . $this->plugin_slug . '/tags/';
|
325 |
+
|
326 |
+
//is this a theme svn request?
|
327 |
+
if ( $type == 'theme' ) {
|
328 |
+
$url = $this->themes_repo . '/' . $slug;
|
329 |
+
}
|
330 |
+
|
331 |
+
$response = wp_remote_get( $url );
|
332 |
+
|
333 |
+
//Do we have an error?
|
334 |
+
if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
|
335 |
+
return null;
|
336 |
+
}
|
337 |
+
|
338 |
+
//Nope: Return that bad boy
|
339 |
+
return wp_remote_retrieve_body( $response );
|
340 |
+
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Set SVN Version Data
|
345 |
+
*
|
346 |
+
* @description FILL ME IN
|
347 |
+
*
|
348 |
+
* @param $html
|
349 |
+
*
|
350 |
+
* @return array|bool
|
351 |
+
*/
|
352 |
+
private function set_svn_versions_data( $html ) {
|
353 |
+
|
354 |
+
if ( ! $html ) {
|
355 |
+
return false;
|
356 |
+
}
|
357 |
+
|
358 |
+
$DOM = new DOMDocument;
|
359 |
+
$DOM->loadHTML( $html );
|
360 |
+
|
361 |
+
$versions = array();
|
362 |
+
|
363 |
+
$items = $DOM->getElementsByTagName( 'a' );
|
364 |
+
|
365 |
+
foreach ( $items as $item ) {
|
366 |
+
$href = str_replace( '/', '', $item->getAttribute( 'href' ) ); //Remove trailing slash
|
367 |
+
|
368 |
+
if ( strpos( $href, 'http' ) === false && $href !== '..' ) {
|
369 |
+
$versions[] = $href;
|
370 |
+
}
|
371 |
+
}
|
372 |
+
|
373 |
+
$this->versions = array_reverse( $versions );
|
374 |
+
|
375 |
+
return $versions;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Versions Select
|
380 |
+
*
|
381 |
+
* @description Outputs the version radio buttons to select a rollback; types = 'plugin' or 'theme'
|
382 |
+
*
|
383 |
+
* @param $type
|
384 |
+
*
|
385 |
+
* @return bool|string
|
386 |
+
*/
|
387 |
+
public function versions_select( $type ) {
|
388 |
+
|
389 |
+
if ( ! $this->versions ) {
|
390 |
+
return false;
|
391 |
+
}
|
392 |
+
|
393 |
+
$versions_html = '';
|
394 |
+
|
395 |
+
//Loop through versions and output in a radio list
|
396 |
+
foreach ( $this->versions as $version ) {
|
397 |
+
|
398 |
+
$versions_html .= '<label><input type="radio" value="' . $version . '" name="' . $type . '_version">' . $version;
|
399 |
+
|
400 |
+
//Is this the current version?
|
401 |
+
if ( $version === $this->current_version ) {
|
402 |
+
$versions_html .= '<span class="current-version">' . __( 'Installed Version', 'wpr' ) . '</span>';
|
403 |
+
}
|
404 |
+
|
405 |
+
$versions_html .= '</label>';
|
406 |
+
|
407 |
+
|
408 |
+
}
|
409 |
+
|
410 |
+
return $versions_html;
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Set Plugin Slug
|
415 |
+
*
|
416 |
+
* @return bool
|
417 |
+
*/
|
418 |
+
private function set_plugin_slug() {
|
419 |
+
|
420 |
+
if ( ! isset( $_GET['plugin_file'] ) ) {
|
421 |
+
return false;
|
422 |
+
}
|
423 |
+
|
424 |
+
if ( isset( $_GET['current_version'] ) ) {
|
425 |
+
$curr_version = explode( ' ', $_GET['current_version'] );
|
426 |
+
$this->current_version = apply_filters( 'wpr_current_version', $curr_version[0] );
|
427 |
+
}
|
428 |
+
|
429 |
+
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
430 |
+
|
431 |
+
$plugin_file = WP_PLUGIN_DIR . '/' . $_GET['plugin_file'];
|
432 |
+
|
433 |
+
$plugin_data = get_plugin_data( $plugin_file, false, false );
|
434 |
+
|
435 |
+
//the plugin slug is the base directory name without the path to the main file
|
436 |
+
$plugin_slug = explode( '/', plugin_basename( $plugin_file ) );
|
437 |
+
|
438 |
+
$this->plugin_file = apply_filters( 'wpr_plugin_file', $plugin_file );
|
439 |
+
$this->plugin_slug = apply_filters( 'wpr_plugin_slug', $plugin_slug[0] );
|
440 |
+
|
441 |
+
return $plugin_slug;
|
442 |
+
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* Admin Menu
|
447 |
+
*
|
448 |
+
* @description: Adds a 'hidden' menu item that is activated when the user elects to rollback
|
449 |
+
*/
|
450 |
+
public function admin_menu() {
|
451 |
+
|
452 |
+
//Only show menu item when necessary (user is interacting with plugin, ie rolling back something)
|
453 |
+
if ( isset( $_GET['page'] ) && $_GET['page'] == 'wp-rollback' ) {
|
454 |
+
//Add it in a native WP way, like WP updates do... (a dashboard page)
|
455 |
+
add_dashboard_page( __( 'Rollback', 'wpr' ), __( 'Rollback', 'wpr' ), 'update_plugins', 'wp-rollback', array(
|
456 |
+
self::$instance,
|
457 |
+
'html'
|
458 |
+
) );
|
459 |
+
}
|
460 |
+
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Pre-Current Active Plugins
|
465 |
+
*
|
466 |
+
* @param $plugins
|
467 |
+
*
|
468 |
+
* @return mixed
|
469 |
+
*/
|
470 |
+
public function pre_current_active_plugins( $plugins ) {
|
471 |
+
$updated = $plugins;
|
472 |
+
foreach ( $updated as $key => $value ) {
|
473 |
+
$updated[ $key ] = $value;
|
474 |
+
$updated[ $key ]['rollback'] = true;
|
475 |
+
}
|
476 |
+
|
477 |
+
return $updated;
|
478 |
+
}
|
479 |
+
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Plugin Action Links
|
483 |
+
*
|
484 |
+
* @description Adds a "rollback" link into the plugins listing page w/ appropriate query strings
|
485 |
+
*
|
486 |
+
* @param $actions
|
487 |
+
* @param $plugin_file
|
488 |
+
* @param $plugin_data
|
489 |
+
* @param $context
|
490 |
+
*
|
491 |
+
* @return array $actions
|
492 |
+
*/
|
493 |
+
public function plugin_action_links( $actions, $plugin_file, $plugin_data, $context ) {
|
494 |
+
|
495 |
+
//Base rollback URL
|
496 |
+
$rollback_url = 'index.php?page=wp-rollback&type=plugin&plugin_file=' . $plugin_file;
|
497 |
+
|
498 |
+
//Filter for other devs
|
499 |
+
$plugin_data = apply_filters( 'wpr_plugin_data', $plugin_data );
|
500 |
+
|
501 |
+
//If plugin is missing package data do not output Rollback option
|
502 |
+
if ( ! isset( $plugin_data['package'] ) ) {
|
503 |
+
return $actions;
|
504 |
+
}
|
505 |
+
|
506 |
+
//Add in the current version for later reference
|
507 |
+
if ( isset( $plugin_data['Version'] ) ) {
|
508 |
+
$rollback_url = add_query_arg( apply_filters( 'wpr_plugin_query_args', array(
|
509 |
+
'current_version' => urlencode( $plugin_data['Version'] ),
|
510 |
+
'rollback_name' => urlencode( $plugin_data['Name'] ),
|
511 |
+
) ), $rollback_url );
|
512 |
+
}
|
513 |
+
|
514 |
+
//Final Output
|
515 |
+
$actions['rollback'] = apply_filters( 'wpr_plugin_markup', '<a href="' . esc_url( $rollback_url ) . '">' . __( 'Rollback', 'wpr' ) . '</a>' );
|
516 |
+
|
517 |
+
return apply_filters( 'wpr_plugin_action_links', $actions );
|
518 |
+
|
519 |
+
}
|
520 |
+
|
521 |
+
|
522 |
+
/**
|
523 |
+
* Is WordPress Theme?
|
524 |
+
*
|
525 |
+
* @description Queryies the WordPress.org API via theme's slug to see if this theme is on WordPress
|
526 |
+
* @return bool
|
527 |
+
* @TODO Set transient here to speed up future checks?
|
528 |
+
*/
|
529 |
+
public function is_wordpress_theme() {
|
530 |
+
|
531 |
+
$url = add_query_arg( 'request[slug]', $_POST['theme'], 'https://api.wordpress.org/themes/info/1.1/?action=theme_information' );
|
532 |
+
$wp_api = wp_remote_get( $url );
|
533 |
+
|
534 |
+
if ( ! is_wp_error( $wp_api ) ) {
|
535 |
+
if ( isset( $wp_api['body'] ) && strlen( $wp_api['body'] ) > 0 && $wp_api['body'] !== 'false' ) {
|
536 |
+
echo 'wp';
|
537 |
+
} else {
|
538 |
+
echo 'non-wp';
|
539 |
+
}
|
540 |
+
} else {
|
541 |
+
echo 'error';
|
542 |
+
}
|
543 |
+
|
544 |
+
wp_die(); // this is required to terminate immediately and return a proper response
|
545 |
+
|
546 |
+
}
|
547 |
+
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Plugin Row Meta
|
551 |
+
*
|
552 |
+
* @param $plugin_meta
|
553 |
+
* @param $plugin_file
|
554 |
+
* @param $plugin_data
|
555 |
+
* @param $status
|
556 |
+
*
|
557 |
+
* @return mixed
|
558 |
+
*/
|
559 |
+
public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $status ) {
|
560 |
+
return $plugin_meta;
|
561 |
+
}
|
562 |
+
|
563 |
+
|
564 |
+
/**
|
565 |
+
* Updates theme list
|
566 |
+
*
|
567 |
+
* @description
|
568 |
+
*
|
569 |
+
* @return bool
|
570 |
+
*/
|
571 |
+
function wpr_theme_updates_list() {
|
572 |
+
|
573 |
+
include( ABSPATH . WPINC . '/version.php' ); // include an unmodified $wp_version
|
574 |
+
|
575 |
+
//Bounce out if improperly called
|
576 |
+
if ( defined( 'WP_INSTALLING' ) || ! is_admin() ) {
|
577 |
+
return false;
|
578 |
+
}
|
579 |
+
|
580 |
+
|
581 |
+
$expiration = 12 * HOUR_IN_SECONDS;
|
582 |
+
$installed_themes = wp_get_themes();
|
583 |
+
|
584 |
+
$last_update = get_site_transient( 'update_themes' );
|
585 |
+
if ( ! is_object( $last_update ) ) {
|
586 |
+
set_site_transient( 'rollback_themes', time(), $expiration );
|
587 |
+
}
|
588 |
+
|
589 |
+
$themes = $checked = $request = array();
|
590 |
+
|
591 |
+
// Put slug of current theme into request.
|
592 |
+
$request['active'] = get_option( 'stylesheet' );
|
593 |
+
|
594 |
+
foreach ( $installed_themes as $theme ) {
|
595 |
+
$checked[ $theme->get_stylesheet() ] = $theme->get( 'Version' );
|
596 |
+
|
597 |
+
$themes[ $theme->get_stylesheet() ] = array(
|
598 |
+
'Name' => $theme->get( 'Name' ),
|
599 |
+
'Title' => $theme->get( 'Name' ),
|
600 |
+
'Version' => '0.0.0.0.0.0',
|
601 |
+
'Author' => $theme->get( 'Author' ),
|
602 |
+
'Author URI' => $theme->get( 'AuthorURI' ),
|
603 |
+
'Template' => $theme->get_template(),
|
604 |
+
'Stylesheet' => $theme->get_stylesheet(),
|
605 |
+
);
|
606 |
+
}
|
607 |
+
|
608 |
+
$request['themes'] = $themes;
|
609 |
+
|
610 |
+
$timeout = 3 + (int) ( count( $themes ) / 10 );
|
611 |
+
|
612 |
+
$options = array(
|
613 |
+
'timeout' => $timeout,
|
614 |
+
'body' => array(
|
615 |
+
'themes' => wp_json_encode( $request ),
|
616 |
+
),
|
617 |
+
'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
|
618 |
+
);
|
619 |
+
|
620 |
+
$url = $http_url = 'http://api.wordpress.org/themes/update-check/1.1/';
|
621 |
+
if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) {
|
622 |
+
$url = set_url_scheme( $url, 'https' );
|
623 |
+
}
|
624 |
+
|
625 |
+
$raw_response = wp_remote_post( $url, $options );
|
626 |
+
if ( $ssl && is_wp_error( $raw_response ) ) {
|
627 |
+
trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
|
628 |
+
$raw_response = wp_remote_post( $http_url, $options );
|
629 |
+
}
|
630 |
+
|
631 |
+
set_site_transient( 'rollback_themes', time(), $expiration );
|
632 |
+
|
633 |
+
if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) ) {
|
634 |
+
return false;
|
635 |
+
}
|
636 |
+
|
637 |
+
$new_update = new stdClass;
|
638 |
+
$new_update->last_checked = time();
|
639 |
+
$new_update->checked = $checked;
|
640 |
+
|
641 |
+
$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
|
642 |
+
|
643 |
+
if ( is_array( $response ) ) {
|
644 |
+
$new_update->response = $response['themes'];
|
645 |
+
}
|
646 |
+
|
647 |
+
set_site_transient( 'rollback_themes', $new_update );
|
648 |
+
}
|
649 |
+
|
650 |
+
|
651 |
+
/**
|
652 |
+
* Prepare Themes JS
|
653 |
+
*
|
654 |
+
* @param $prepared_themes
|
655 |
+
*
|
656 |
+
* @return array
|
657 |
+
*/
|
658 |
+
function wpr_prepare_themes_js( $prepared_themes ) {
|
659 |
+
$themes = array();
|
660 |
+
$wp_themes = get_site_transient( 'rollback_themes' );
|
661 |
+
$rollbacks = $wp_themes->response;
|
662 |
+
|
663 |
+
foreach ( $prepared_themes as $key => $value ) {
|
664 |
+
$themes[ $key ] = $prepared_themes[ $key ];
|
665 |
+
$themes[ $key ]['hasRollback'] = isset( $rollbacks[ $key ] );
|
666 |
+
}
|
667 |
+
|
668 |
+
return $themes;
|
669 |
+
}
|
670 |
+
|
671 |
+
|
672 |
+
}
|
673 |
+
}
|
674 |
+
|
675 |
+
endif; // End if class_exists check
|
676 |
+
|
677 |
+
|
678 |
+
/**
|
679 |
+
* The main function responsible for returning the one true WP Rollback
|
680 |
+
* Instance to functions everywhere.
|
681 |
+
*
|
682 |
+
* Use this function like you would a global variable, except without needing
|
683 |
+
* to declare the global.
|
684 |
+
*
|
685 |
+
* Example: <?php $wp_rollback = WP_Rollback(); ?>
|
686 |
+
*
|
687 |
+
* @since 1.0
|
688 |
+
* @return object The one true WP Rollback Instance
|
689 |
+
*/
|
690 |
+
function WP_Rollback() {
|
691 |
+
return WP_Rollback::instance();
|
692 |
+
}
|
693 |
+
|
694 |
+
// Get WP Rollback Running
|
695 |
+
WP_Rollback();
|