Robin image optimizer — save money on image compression - Version 1.0.7

Version Description

  • Fixed: Images are saved in a size 0 bytes
  • Fixed: Trying to backup file with empty filename
  • Fixed: Curl replacement for file_get_contents
  • Fixed: Statistics
Download this release

Release Info

Developer webcraftic
Plugin Icon 128x128 Robin image optimizer — save money on image compression
Version 1.0.7
Comparing to
See all releases

Version 1.0.7

Files changed (151) hide show
  1. admin/activation.php +41 -0
  2. admin/assets/css/base-statistic.css +351 -0
  3. admin/assets/css/base-statistic.less +414 -0
  4. admin/assets/css/index.php +0 -0
  5. admin/assets/css/media.css +215 -0
  6. admin/assets/css/statistic.css +372 -0
  7. admin/assets/img/Spinner-1s-33px.gif +0 -0
  8. admin/assets/index.php +0 -0
  9. admin/assets/js/Chart.min.js +10 -0
  10. admin/assets/js/bulk-optimozation.js +117 -0
  11. admin/assets/js/index.php +0 -0
  12. admin/assets/js/restore-backup.js +47 -0
  13. admin/assets/js/single-optimization.js +56 -0
  14. admin/assets/js/statistic.js +36 -0
  15. admin/boot.php +33 -0
  16. admin/index.php +1 -0
  17. admin/pages/index.php +0 -0
  18. admin/pages/log.php +109 -0
  19. admin/pages/settings.php +415 -0
  20. admin/pages/statistic.php +357 -0
  21. includes/class.plugin.php +260 -0
  22. includes/classes/class.attachment.php +416 -0
  23. includes/classes/class.backup.php +266 -0
  24. includes/classes/class.cron.php +113 -0
  25. includes/classes/class.image-processor-abstract.php +71 -0
  26. includes/classes/class.image-processor-resmush.php +96 -0
  27. includes/classes/class.image-statistic.php +164 -0
  28. includes/classes/class.logger.php +88 -0
  29. includes/classes/class.media-library.php +504 -0
  30. includes/classes/index.php +0 -0
  31. includes/functions.php +48 -0
  32. includes/index.php +0 -0
  33. index.php +0 -0
  34. languages/index.php +0 -0
  35. languages/robin-image-optimizer-ru_RU.mo +0 -0
  36. languages/robin-image-optimizer-ru_RU.po +502 -0
  37. languages/robin-image-optimizer.pot +447 -0
  38. libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css +11 -0
  39. libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css +11 -0
  40. libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css +11 -0
  41. libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css +25 -0
  42. libs/factory/bootstrap/assets/css-min/bootstrap.datepicker.min.css +17 -0
  43. libs/factory/bootstrap/assets/css-min/bootstrap.ectoplasm.min.css +11 -0
  44. libs/factory/bootstrap/assets/css-min/bootstrap.form-group.min.css +11 -0
  45. libs/factory/bootstrap/assets/css-min/bootstrap.light.min.css +11 -0
  46. libs/factory/bootstrap/assets/css-min/bootstrap.midnight.min.css +11 -0
  47. libs/factory/bootstrap/assets/css-min/bootstrap.ocean.min.css +11 -0
  48. libs/factory/bootstrap/assets/css-min/bootstrap.separator.min.css +11 -0
  49. libs/factory/bootstrap/assets/css-min/bootstrap.sunrise.min.css +11 -0
  50. libs/factory/bootstrap/assets/css-min/control.checkbox.min.css +11 -0
  51. libs/factory/bootstrap/assets/css-min/control.dropdown.min.css +11 -0
  52. libs/factory/bootstrap/assets/css-min/control.multiple-textbox.min.css +11 -0
  53. libs/factory/bootstrap/assets/css-min/holder.more-link.min.css +11 -0
  54. libs/factory/bootstrap/assets/images/loader-sm-f6f6f6.gif +0 -0
  55. libs/factory/bootstrap/assets/images/loader-sm-tr.gif +0 -0
  56. libs/factory/bootstrap/assets/js-min/bootstrap.dropdown.min.js +10 -0
  57. libs/factory/bootstrap/assets/js-min/bootstrap.tooltip.min.js +10 -0
  58. libs/factory/bootstrap/assets/js-min/control.checkbox.min.js +10 -0
  59. libs/factory/bootstrap/assets/js-min/control.dropdown.min.js +10 -0
  60. libs/factory/bootstrap/assets/js-min/control.list.min.js +10 -0
  61. libs/factory/bootstrap/assets/js-min/control.multiple-textbox.min.js +10 -0
  62. libs/factory/bootstrap/boot.php +37 -0
  63. libs/factory/bootstrap/includes/functions.php +292 -0
  64. libs/factory/clearfy/boot.php +37 -0
  65. libs/factory/clearfy/includes/class.configurate.php +67 -0
  66. libs/factory/clearfy/includes/class.helpers.php +180 -0
  67. libs/factory/clearfy/langs/wbcr_factory_clearfy_203-fr-FR.mo +0 -0
  68. libs/factory/clearfy/langs/wbcr_factory_clearfy_203-fr-FR.po +129 -0
  69. libs/factory/clearfy/langs/wbcr_factory_clearfy_203-ru_RU.mo +0 -0
  70. libs/factory/clearfy/langs/wbcr_factory_clearfy_203-ru_RU.po +124 -0
  71. libs/factory/clearfy/pages/more-features.php +148 -0
  72. libs/factory/core/boot.php +40 -0
  73. libs/factory/core/includes/activation/activator.class.php +187 -0
  74. libs/factory/core/includes/activation/update.class.php +38 -0
  75. libs/factory/core/includes/assets-managment/assets-list.class.php +173 -0
  76. libs/factory/core/includes/assets-managment/script-list.class.php +97 -0
  77. libs/factory/core/includes/assets-managment/style-list.class.php +51 -0
  78. libs/factory/core/includes/base.class.php +378 -0
  79. libs/factory/core/includes/functions.php +169 -0
  80. libs/factory/core/includes/plugin.class.php +913 -0
  81. libs/factory/core/includes/request.class.php +126 -0
  82. libs/factory/forms/assets/css/editor.css +12 -0
  83. libs/factory/forms/assets/standard-controls.js +146 -0
  84. libs/factory/forms/boot.php +271 -0
  85. libs/factory/forms/controls/checkbox.php +177 -0
  86. libs/factory/forms/controls/color-and-opacity.php +88 -0
  87. libs/factory/forms/controls/color.php +62 -0
  88. libs/factory/forms/controls/customs/html.php +45 -0
  89. libs/factory/forms/controls/customs/separator.php +35 -0
  90. libs/factory/forms/controls/datepicker-range.php +106 -0
  91. libs/factory/forms/controls/dropdown-and-colors.php +116 -0
  92. libs/factory/forms/controls/dropdown.php +388 -0
  93. libs/factory/forms/controls/font.php +270 -0
  94. libs/factory/forms/controls/google-font.php +152 -0
  95. libs/factory/forms/controls/gradient.php +103 -0
  96. libs/factory/forms/controls/hidden.php +50 -0
  97. libs/factory/forms/controls/holders/accordion-item.php +63 -0
  98. libs/factory/forms/controls/holders/accordion.php +58 -0
  99. libs/factory/forms/controls/holders/columns.php +99 -0
  100. libs/factory/forms/controls/holders/control-group-item.php +76 -0
  101. libs/factory/forms/controls/holders/control-group.php +97 -0
  102. libs/factory/forms/controls/holders/div.php +67 -0
  103. libs/factory/forms/controls/holders/form-group.php +71 -0
  104. libs/factory/forms/controls/holders/more-link.php +75 -0
  105. libs/factory/forms/controls/holders/tab-item.php +68 -0
  106. libs/factory/forms/controls/holders/tab.php +139 -0
  107. libs/factory/forms/controls/integer.php +160 -0
  108. libs/factory/forms/controls/list.php +230 -0
  109. libs/factory/forms/controls/multiple-textbox.php +120 -0
  110. libs/factory/forms/controls/paddings-editor.php +82 -0
  111. libs/factory/forms/controls/pattern.php +181 -0
  112. libs/factory/forms/controls/radio-colors.php +111 -0
  113. libs/factory/forms/controls/radio.php +85 -0
  114. libs/factory/forms/controls/textarea.php +85 -0
  115. libs/factory/forms/controls/textbox.php +83 -0
  116. libs/factory/forms/controls/url.php +43 -0
  117. libs/factory/forms/controls/wp-editor.php +95 -0
  118. libs/factory/forms/includes/complex-control.class.php +133 -0
  119. libs/factory/forms/includes/control-holder.class.php +173 -0
  120. libs/factory/forms/includes/control.class.php +422 -0
  121. libs/factory/forms/includes/custom-element.class.php +46 -0
  122. libs/factory/forms/includes/form-element.class.php +423 -0
  123. libs/factory/forms/includes/form-layout.class.php +123 -0
  124. libs/factory/forms/includes/form.class.php +694 -0
  125. libs/factory/forms/includes/holder.class.php +170 -0
  126. libs/factory/forms/includes/html-builder.class.php +137 -0
  127. libs/factory/forms/includes/providers/meta-value-provider.class.php +303 -0
  128. libs/factory/forms/includes/providers/options-value-provider.class.php +94 -0
  129. libs/factory/forms/includes/providers/value-provider.interface.php +62 -0
  130. libs/factory/forms/langs/wbcr_factory_forms_407-fr-FR.mo +0 -0
  131. libs/factory/forms/langs/wbcr_factory_forms_407-fr-FR.po +104 -0
  132. libs/factory/forms/langs/wbcr_factory_forms_407-ru_RU.mo +0 -0
  133. libs/factory/forms/langs/wbcr_factory_forms_407-ru_RU.po +95 -0
  134. libs/factory/forms/layouts/bootstrap-3/bootstrap-3.php +217 -0
  135. libs/factory/pages/boot.php +40 -0
  136. libs/factory/pages/includes/admin-page.class.php +459 -0
  137. libs/factory/pages/includes/page.class.php +140 -0
  138. libs/factory/pages/langs/wbcr_factory_pages_407-fr_FR.mo +0 -0
  139. libs/factory/pages/langs/wbcr_factory_pages_407-fr_FR.po +99 -0
  140. libs/factory/pages/langs/wbcr_factory_pages_407-ru_RU.mo +0 -0
  141. libs/factory/pages/langs/wbcr_factory_pages_407-ru_RU.po +99 -0
  142. libs/factory/pages/pages.php +87 -0
  143. libs/factory/pages/templates/assets/css/impressive.page.template.css +430 -0
  144. libs/factory/pages/templates/assets/css/impressive.page.template.less +510 -0
  145. libs/factory/pages/templates/assets/img/5-stars22.png +0 -0
  146. libs/factory/pages/templates/assets/img/paypal-donate.png +0 -0
  147. libs/factory/pages/templates/assets/img/webcraftic-plugin-icon.png +0 -0
  148. libs/factory/pages/templates/impressive-page.class.php +908 -0
  149. readme.txt +109 -0
  150. robin-image-optimizer.php +85 -0
  151. uninstall.php +17 -0
admin/activation.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Activator for the Robin image optimizer
5
+ *
6
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
7
+ * @copyright (c) 09.09.2017, Webcraftic
8
+ * @see Factory406_Activator
9
+ * @version 1.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ class WIO_Activation extends Wbcr_Factory406_Activator {
18
+
19
+ /**
20
+ * Runs activation actions.
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ public function activate()
25
+ {
26
+ WIO_Plugin::app()->updateOption('backup_origin_images', 1);
27
+ WIO_Plugin::app()->updateOption('save_exif_data', 1);
28
+ }
29
+
30
+ /**
31
+ * Runs activation actions.
32
+ *
33
+ * @since 1.0.0
34
+ */
35
+ public function deactivate()
36
+ {
37
+ if( wp_next_scheduled('wio_optimize_images') ) {
38
+ wp_clear_scheduled_hook('wio_optimize_images');
39
+ }
40
+ }
41
+ }
admin/assets/css/base-statistic.css ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Styles for the Widget to be displayed in the Clearfy plugin
3
+
4
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
+ * @copyright Webcraftic 13.06.2018
6
+ */
7
+ #WBCR {
8
+ /* Number display */
9
+ /* Number and bars */
10
+ /* Doughnut */
11
+ /* Widget */
12
+ /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
13
+ .wio-overview-chart-container {
14
+ float: none;
15
+ margin-right: 0;
16
+ }
17
+ }
18
+
19
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
20
+ .wio-overview-chart-container {
21
+ float: none;
22
+ margin-right: 0;
23
+ }
24
+
25
+ .wio-doughnut-legend {
26
+ margin-top: 18px;
27
+ }
28
+
29
+ .wio-global-optim-phrase {
30
+ padding-top: 0;
31
+ width: auto;
32
+ }
33
+ }*/
34
+ }
35
+ #WBCR .wio-clear {
36
+ clear: both;
37
+ }
38
+ #WBCR .wio-columns {
39
+ overflow: hidden;
40
+ padding: 15px 0;
41
+ counter-reset: cols;
42
+ }
43
+ #WBCR .wio-columns [class^="col-"] {
44
+ float: left;
45
+ -webkit-box-sizing: border-box;
46
+ -moz-box-sizing: border-box;
47
+ box-sizing: border-box;
48
+ }
49
+ #WBCR .wio-columns .col-1-3 {
50
+ width: 33.333%;
51
+ padding-left: 28px;
52
+ }
53
+ #WBCR .wio-columns .col-2-3 {
54
+ width: 66.666%;
55
+ padding-left: 28px;
56
+ }
57
+ #WBCR .wio-columns .col-1-2 {
58
+ width: 50%;
59
+ padding: 0 20px;
60
+ }
61
+ #WBCR .wio-columns .col-statistics.col-statistics {
62
+ width: 60%;
63
+ }
64
+ #WBCR .wio-columns .col-chart.col-chart {
65
+ width: 40%;
66
+ position: relative;
67
+ padding: 20px;
68
+ font-size: 12px;
69
+ text-transform: uppercase;
70
+ background: #f1f1f1b3;
71
+ color: #abacaf;
72
+ font-weight: bold;
73
+ border-radius: 5px;
74
+ margin-top: 10px;
75
+ text-align: left;
76
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
77
+ }
78
+ #WBCR .wio-col {
79
+ float: left;
80
+ width: 50%;
81
+ box-sizing: border-box;
82
+ -webkit-flex-basis: 50%;
83
+ -ms-flex-preferred-size: 50%;
84
+ flex-basis: 50%;
85
+ }
86
+ #WBCR .wio-col {
87
+ padding-right: 20px;
88
+ }
89
+ #WBCR .wio-col + .wio-col {
90
+ padding-right: 0;
91
+ padding-left: 50px;
92
+ }
93
+ #WBCR .wio-col:target {
94
+ animation: wiohello 1s 3 linear backwards;
95
+ }
96
+ #WBCR .wio-number-you-optimized {
97
+ margin-bottom: 1.35em;
98
+ overflow: hidden;
99
+ }
100
+ #WBCR .wio-number-you-optimized #wio-total-optimized-attachments-pct {
101
+ color: #828282;
102
+ }
103
+ #WBCR .wio-number-you-optimized .wio-number {
104
+ display: table-cell;
105
+ padding-right: 15px;
106
+ font-size: 48px;
107
+ font-weight: bold;
108
+ line-height: 1;
109
+ vertical-align: middle;
110
+ white-space: nowrap;
111
+ color: #828282;
112
+ }
113
+ #WBCR .wio-number-you-optimized .wio-text {
114
+ display: table-cell;
115
+ vertical-align: middle;
116
+ overflow: hidden;
117
+ font-size: 12px;
118
+ color: #828282;
119
+ }
120
+ #WBCR .wio-number-you-optimized > p {
121
+ display: table;
122
+ }
123
+ #WBCR .wio-bars {
124
+ padding-right: 15px;
125
+ }
126
+ #WBCR .wio-bars p {
127
+ font-size: 12px;
128
+ margin-bottom: 5px;
129
+ }
130
+ #WBCR .wio-bars + .wio-number-you-optimized {
131
+ border-bottom: 0;
132
+ padding-top: 0.85em;
133
+ }
134
+ #WBCR .wio-bars + .wio-number-you-optimized p {
135
+ color: #72a53b;
136
+ }
137
+ #WBCR .wio-bar-negative .wio-progress {
138
+ background: #D2D3D6;
139
+ }
140
+ #WBCR .wio-bar-negative .wio-barnb {
141
+ color: #9d9fa5;
142
+ }
143
+ #WBCR .wio-progress {
144
+ height: 8px;
145
+ transition: width .3s;
146
+ /*.wio-bar-negative {
147
+ width: 92% !important;
148
+ }*/
149
+ }
150
+ #WBCR .wio-bar-positive .wio-progress {
151
+ background: #8CC152;
152
+ }
153
+ #WBCR .wio-bar-positive .wio-barnb {
154
+ color: #72a53b;
155
+ }
156
+ #WBCR .wio-bar-primary .wio-progress {
157
+ background: #8CC152;
158
+ }
159
+ #WBCR .wio-bar-primary .wio-barnb {
160
+ color: #72a53b;
161
+ }
162
+ #WBCR .wio-right-outside-number .wio-barnb {
163
+ display: block;
164
+ margin-right: -5.25em;
165
+ text-align: right;
166
+ font-weight: bold;
167
+ line-height: .8;
168
+ }
169
+ #WBCR .wio-chart {
170
+ position: relative;
171
+ top: 1px;
172
+ display: inline-block;
173
+ vertical-align: middle;
174
+ }
175
+ #WBCR .wio-chart-container {
176
+ position: relative;
177
+ display: inline-block;
178
+ margin-right: 5px;
179
+ }
180
+ #WBCR .wio-chart-container canvas {
181
+ display: block;
182
+ }
183
+ #WBCR .wio-overview-chart-container {
184
+ float: left;
185
+ margin-right: 20px;
186
+ }
187
+ #WBCR .wio-chart-percent {
188
+ position: absolute;
189
+ left: 0;
190
+ right: 0;
191
+ top: 50%;
192
+ margin-top: -0.5em;
193
+ line-height: 0.8;
194
+ text-align: center;
195
+ font-size: 54px;
196
+ font-weight: bold;
197
+ color: #afafaf;
198
+ }
199
+ #WBCR .wio-chart-percent span {
200
+ font-size: 20px;
201
+ vertical-align: super;
202
+ }
203
+ #WBCR #wio-overview-chart-legend {
204
+ overflow: hidden;
205
+ }
206
+ #WBCR .wio-doughnut-legend li {
207
+ display: inline-block;
208
+ position: relative;
209
+ margin-bottom: 15px;
210
+ border-radius: 5px;
211
+ padding: 3px 8px 2px 31px;
212
+ font-size: 9px;
213
+ cursor: default;
214
+ -webkit-transition: background-color 200ms ease-in-out;
215
+ -moz-transition: background-color 200ms ease-in-out;
216
+ -o-transition: background-color 200ms ease-in-out;
217
+ transition: background-color 200ms ease-in-out;
218
+ }
219
+ #WBCR .wio-doughnut-legend li span {
220
+ display: block;
221
+ position: absolute;
222
+ left: 0;
223
+ top: 0;
224
+ width: 25px;
225
+ height: 25px;
226
+ border-radius: 50%;
227
+ }
228
+ #WBCR .wio-optimize-button {
229
+ width: 180px;
230
+ padding: 12px 30px;
231
+ background: #c9deb2;
232
+ color: #586549;
233
+ border: 0;
234
+ box-shadow: none;
235
+ font-size: 14px;
236
+ text-transform: uppercase !important;
237
+ font-weight: bold;
238
+ border-radius: 4px;
239
+ outline: none;
240
+ }
241
+ #WBCR .wio-optimize-button:active {
242
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
243
+ }
244
+ #WBCR .wio-optimize-button.wio-running {
245
+ color: #a57b3c;
246
+ background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
247
+ }
248
+ #WBCR .wio-global-optim-phrase {
249
+ width: 180px;
250
+ padding-top: 20px;
251
+ font-size: 14px;
252
+ text-align: center;
253
+ }
254
+ #WBCR .wio-total-percent {
255
+ color: #587f2e;
256
+ }
257
+ #WBCR #wio-start-msg-top,
258
+ #WBCR #wio-start-msg-right,
259
+ #WBCR #wio-start-msg-complete {
260
+ display: none;
261
+ }
262
+ #WBCR .wio-text-left {
263
+ text-align: left;
264
+ }
265
+ #WBCR span.wio-num {
266
+ display: inline !important;
267
+ position: inherit !important;
268
+ }
269
+ #WBCR .wio-image-optimize-board {
270
+ padding-bottom: 0 !important;
271
+ }
272
+ #WBCR .wio-page-statistic {
273
+ padding-left: 40px;
274
+ }
275
+ #WBCR .wio-page-statistic .wio-chart-percent {
276
+ margin-top: -1.1em;
277
+ }
278
+ #WBCR .wio-widget {
279
+ padding: 0 !important;
280
+ }
281
+ #WBCR .wio-widget .wio-chart-percent {
282
+ font-size: 44px;
283
+ line-height: 1;
284
+ }
285
+ #WBCR .wio-widget .wio-bars {
286
+ width: 60%;
287
+ margin-left: 155px;
288
+ }
289
+ #WBCR .wio-widget .col-chart.col-chart {
290
+ width: 100%;
291
+ }
292
+ #WBCR .wio-widget .col-controls {
293
+ width: 45%;
294
+ padding-left: 5px;
295
+ padding-top: 110px;
296
+ }
297
+ #WBCR .wio-widget .wio-doughnut-legend {
298
+ /*padding-top:30px;*/
299
+ text-align: left;
300
+ }
301
+ #WBCR .wio-widget .wio-widget-bottom {
302
+ display: table;
303
+ padding-top: 20px !important;
304
+ width: 100%;
305
+ text-align: right;
306
+ }
307
+ #WBCR .wio-widget .wio-widget-bottom li {
308
+ display: table-cell;
309
+ }
310
+ #WBCR .wio-widget .wio-widget-bottom li:first-child {
311
+ text-align: left;
312
+ }
313
+ @media (max-width: 830px) {
314
+ #WBCR .wio [class^="col-"] {
315
+ float: none;
316
+ margin-bottom: 1.5em;
317
+ }
318
+ #WBCR .wio .col-1-3,
319
+ #WBCR .wio .col-1-2 {
320
+ width: auto;
321
+ padding: 0 28px;
322
+ clear: both;
323
+ padding-top: 1em;
324
+ }
325
+ }
326
+ @keyframes wiohello {
327
+ 0%,
328
+ 100% {
329
+ background: #FFF;
330
+ }
331
+ 50% {
332
+ background: #F4F7F9;
333
+ }
334
+ }
335
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
336
+ #WBCR .wio-columns .col-statistics.col-statistics,
337
+ #WBCR .wio-columns .col-chart.col-chart {
338
+ width: 50%;
339
+ }
340
+ }
341
+ @media (max-width: 808px) {
342
+ #WBCR .wio-columns .col-statistics.col-statistics,
343
+ #WBCR .wio-columns .col-chart.col-chart {
344
+ width: auto;
345
+ float: none;
346
+ padding: 0;
347
+ }
348
+ #WBCR .wio-columns .col-chart.col-chart {
349
+ margin-top: 3em;
350
+ }
351
+ }
admin/assets/css/base-statistic.less ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Styles for the Widget to be displayed in the Clearfy plugin
3
+
4
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
5
+ * @copyright Webcraftic 13.06.2018
6
+ */
7
+
8
+ @positiveColor: #8CC152;
9
+ @negativeColor: #D2D3D6;
10
+ @neutralColor: #828282;
11
+
12
+ #WBCR {
13
+ .wio-clear {
14
+ clear: both;
15
+ }
16
+
17
+ .wio-columns {
18
+ overflow: hidden;
19
+ padding: 15px 0;
20
+ counter-reset: cols;
21
+
22
+ [class^="col-"] {
23
+ float: left;
24
+ -webkit-box-sizing: border-box;
25
+ -moz-box-sizing: border-box;
26
+ box-sizing: border-box;
27
+ }
28
+
29
+ .col-1-3 {
30
+ width: 33.333%;
31
+ padding-left: 28px;
32
+ }
33
+
34
+ .col-2-3 {
35
+ width: 66.666%;
36
+ padding-left: 28px
37
+ }
38
+
39
+ .col-1-2 {
40
+ width: 50%;
41
+ padding: 0 20px;
42
+ }
43
+
44
+ .col-statistics.col-statistics {
45
+ width: 60%;
46
+ }
47
+
48
+ .col-chart.col-chart {
49
+ width: 40%;
50
+ position: relative;
51
+ padding: 20px;
52
+ font-size: 12px;
53
+ text-transform: uppercase;
54
+ background: #f1f1f1b3;
55
+ color: #abacaf;
56
+ font-weight: bold;
57
+ border-radius: 5px;
58
+ margin-top: 10px;
59
+ text-align: left;
60
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
61
+ }
62
+ }
63
+
64
+ .wio-col {
65
+ float: left;
66
+ width: 50%;
67
+ box-sizing: border-box;
68
+ -webkit-flex-basis: 50%;
69
+ -ms-flex-preferred-size: 50%;
70
+ flex-basis: 50%;
71
+ }
72
+
73
+ .wio-col {
74
+ padding-right: 20px;
75
+ }
76
+
77
+ .wio-col + .wio-col {
78
+ padding-right: 0;
79
+ padding-left: 50px;
80
+ }
81
+
82
+ .wio-col:target {
83
+ animation: wiohello 1s 3 linear backwards;
84
+ }
85
+
86
+ /* Number display */
87
+ .wio-number-you-optimized {
88
+ margin-bottom: 1.35em;
89
+ overflow: hidden;
90
+
91
+ #wio-total-optimized-attachments-pct {
92
+ color: @neutralColor;
93
+ }
94
+
95
+ .wio-number {
96
+ display: table-cell;
97
+ padding-right: 15px;
98
+ font-size: 48px;
99
+ font-weight: bold;
100
+ line-height: 1;
101
+ vertical-align: middle;
102
+ white-space: nowrap;
103
+ color: @neutralColor;
104
+ }
105
+
106
+ .wio-text {
107
+ display: table-cell;
108
+ vertical-align: middle;
109
+ overflow: hidden;
110
+ font-size: 12px;
111
+ color: @neutralColor;
112
+ }
113
+
114
+ & > p {
115
+ display: table;
116
+ }
117
+ }
118
+
119
+ /* Number and bars */
120
+ .wio-bars {
121
+ padding-right: 15px;
122
+ }
123
+
124
+ .wio-bars p {
125
+ font-size: 12px;
126
+ margin-bottom: 5px;
127
+ }
128
+
129
+ .wio-bars + .wio-number-you-optimized {
130
+ border-bottom: 0;
131
+ padding-top: 0.85em;
132
+ }
133
+
134
+ .wio-bars + .wio-number-you-optimized p {
135
+ color: darken(@positiveColor, 10);
136
+ }
137
+
138
+ .wio-bar-negative {
139
+ .wio-progress {
140
+ background: @negativeColor;
141
+ }
142
+ .wio-barnb {
143
+ color: darken(@negativeColor, 20);
144
+ }
145
+ }
146
+
147
+ .wio-progress {
148
+ height: 8px;
149
+ transition: width .3s;
150
+
151
+ /*.wio-bar-negative {
152
+ width: 92% !important;
153
+ }*/
154
+ }
155
+
156
+ .wio-bar-positive {
157
+ .wio-progress {
158
+ background: @positiveColor;
159
+ }
160
+ .wio-barnb {
161
+ color: darken(@positiveColor, 10);
162
+ }
163
+ }
164
+
165
+ .wio-bar-primary {
166
+ .wio-progress {
167
+ background: @positiveColor;
168
+ }
169
+ .wio-barnb {
170
+ color: darken(@positiveColor, 10);
171
+ }
172
+ }
173
+
174
+ .wio-right-outside-number .wio-barnb {
175
+ display: block;
176
+ margin-right: -5.25em;
177
+ text-align: right;
178
+ font-weight: bold;
179
+ line-height: .8;
180
+ }
181
+
182
+ /* Doughnut */
183
+ .wio-chart {
184
+ position: relative;
185
+ top: 1px;
186
+ display: inline-block;
187
+ vertical-align: middle;
188
+ }
189
+
190
+ .wio-chart-container {
191
+ position: relative;
192
+ display: inline-block;
193
+ margin-right: 5px;
194
+ }
195
+
196
+ .wio-chart-container canvas {
197
+ display: block;
198
+ }
199
+
200
+ .wio-overview-chart-container {
201
+ float: left;
202
+ margin-right: 20px;
203
+ }
204
+
205
+ .wio-chart-percent {
206
+ position: absolute;
207
+ left: 0;
208
+ right: 0;
209
+ top: 50%;
210
+ margin-top: -.5em;
211
+ line-height: 0.8;
212
+ text-align: center;
213
+ font-size: 54px;
214
+ font-weight: bold;
215
+ color: #afafaf;
216
+ }
217
+
218
+ .wio-chart-percent span {
219
+ font-size: 20px;
220
+ vertical-align: super;
221
+ }
222
+
223
+ #wio-overview-chart-legend {
224
+ overflow: hidden;
225
+ }
226
+
227
+ .wio-doughnut-legend li {
228
+ display: inline-block;
229
+ position: relative;
230
+ margin-bottom: 15px;
231
+ border-radius: 5px;
232
+ padding: 3px 8px 2px 31px;
233
+ font-size: 9px;
234
+ cursor: default;
235
+ -webkit-transition: background-color 200ms ease-in-out;
236
+ -moz-transition: background-color 200ms ease-in-out;
237
+ -o-transition: background-color 200ms ease-in-out;
238
+ transition: background-color 200ms ease-in-out;
239
+ }
240
+
241
+ .wio-doughnut-legend li span {
242
+ display: block;
243
+ position: absolute;
244
+ left: 0;
245
+ top: 0;
246
+ width: 25px;
247
+ height: 25px;
248
+ border-radius: 50%;
249
+ }
250
+
251
+ .wio-optimize-button {
252
+ width: 180px;
253
+ padding: 12px 30px;
254
+ background: #c9deb2;
255
+ color: #586549;
256
+ border: 0;
257
+ box-shadow: none;
258
+ font-size: 14px;
259
+ text-transform: uppercase !important;
260
+ font-weight: bold;
261
+ border-radius: 4px;
262
+ outline: none;
263
+
264
+ &:active {
265
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
266
+ }
267
+ &.wio-running {
268
+ color: #a57b3c;
269
+ background: #fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
270
+ }
271
+ }
272
+
273
+ .wio-global-optim-phrase {
274
+ width: 180px;
275
+ padding-top: 20px;
276
+ font-size: 14px;
277
+ text-align: center;
278
+ }
279
+
280
+ .wio-total-percent {
281
+ color: darken(@positiveColor, 20);
282
+ }
283
+
284
+ #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
285
+ display: none;
286
+ }
287
+
288
+ .wio-text-left {
289
+ text-align: left;
290
+ }
291
+
292
+ span.wio-num {
293
+ display: inline !important;
294
+ position: inherit !important;
295
+ }
296
+
297
+ /* Widget */
298
+ .wio-image-optimize-board {
299
+ padding-bottom: 0 !important;
300
+ }
301
+
302
+ .wio-page-statistic {
303
+ padding-left: 40px;
304
+
305
+ .wio-chart-percent {
306
+ margin-top: -1.1em;
307
+ }
308
+ }
309
+
310
+ .wio-widget {
311
+ padding: 0 !important;
312
+
313
+ .wio-chart-percent {
314
+ font-size: 44px;
315
+ line-height: 1;
316
+ }
317
+ .wio-bars {
318
+ width: 60%;
319
+ margin-left: 155px;
320
+ }
321
+ .col-chart.col-chart {
322
+ width: 100%;
323
+ }
324
+ .col-controls {
325
+ width: 45%;
326
+ padding-left: 5px;
327
+ padding-top: 110px
328
+ }
329
+ .wio-doughnut-legend {
330
+ /*padding-top:30px;*/
331
+ text-align: left;
332
+ }
333
+ .wio-widget-bottom {
334
+ display: table;
335
+ padding-top: 20px !important;
336
+ width: 100%;
337
+ text-align: right;
338
+ }
339
+ .wio-widget-bottom li {
340
+ display: table-cell;
341
+ }
342
+ .wio-widget-bottom li:first-child {
343
+ text-align: left;
344
+ }
345
+ }
346
+
347
+ @media (max-width: 830px) {
348
+ .wio [class^="col-"] {
349
+ float: none;
350
+ margin-bottom: 1.5em;
351
+ }
352
+
353
+ .wio .col-1-3,
354
+ .wio .col-1-2 {
355
+ width: auto;
356
+ padding: 0 28px;
357
+ clear: both;
358
+ padding-top: 1em;
359
+ }
360
+ }
361
+
362
+ @keyframes wiohello {
363
+ 0%, 100% {
364
+ background: #FFF;
365
+ }
366
+ 50% {
367
+ background: #F4F7F9;
368
+ }
369
+ }
370
+
371
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
372
+ .wio-columns {
373
+ .col-statistics.col-statistics, .col-chart.col-chart {
374
+ width: 50%;
375
+ }
376
+ }
377
+
378
+ }
379
+
380
+ @media (max-width: 808px) {
381
+ .wio-columns {
382
+ .col-statistics.col-statistics, .col-chart.col-chart {
383
+ width: auto;
384
+ float: none;
385
+ padding: 0;
386
+ }
387
+ .col-chart.col-chart {
388
+ margin-top: 3em;
389
+ }
390
+ }
391
+ }
392
+ /*@media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
393
+ .wio-overview-chart-container {
394
+ float: none;
395
+ margin-right: 0;
396
+ }
397
+ }
398
+
399
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
400
+ .wio-overview-chart-container {
401
+ float: none;
402
+ margin-right: 0;
403
+ }
404
+
405
+ .wio-doughnut-legend {
406
+ margin-top: 18px;
407
+ }
408
+
409
+ .wio-global-optim-phrase {
410
+ padding-top: 0;
411
+ width: auto;
412
+ }
413
+ }*/
414
+ }
admin/assets/css/index.php ADDED
File without changes
admin/assets/css/media.css ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * == Custom column & Metabox
3
+ */
4
+ .column-wio_optimized_file.column-wio_optimized_file {
5
+ width: 300px;
6
+ text-align: center;
7
+ vertical-align: middle;
8
+ }
9
+ .column-wio_optimized_file > * {
10
+ max-width: 235px;
11
+ margin: 0 auto;
12
+ }
13
+ @media (min-width: 1151px) and (max-width: 1800px) {
14
+ .column-wio_optimized_file.column-wio_optimized_file {
15
+ width: 235px;
16
+ }
17
+ }
18
+ @media (min-width: 783px) and (max-width: 1150px) {
19
+ .column-wio_optimized_file.column-wio_optimized_file {
20
+ width: 13em;
21
+ }
22
+ table.media .column-title .has-media-icon ~ .row-actions.row-actions {
23
+ margin-left: 0;
24
+ }
25
+ }
26
+ @media (max-width: 782px) {
27
+ table.media .column-wio_optimized_file.column-wio_optimized_file {
28
+ text-align: left;
29
+ }
30
+ table.media .wio-datas-more-action,
31
+ table.media .wio-datas-actions-links {
32
+ text-align: center;
33
+ }
34
+ table.media .column-wio_optimized_file > *,
35
+ table.media .column-wio_optimized_file .wio-datas-actions-links a {
36
+ max-width: 100%;
37
+ margin-left: 0;
38
+ }
39
+ }
40
+ @media (min-width: 783px) and (max-width: 1150px), (max-width: 360px) {
41
+ table.media .wio-hide-if-small {
42
+ position: absolute;
43
+ margin: -1px;
44
+ padding: 0;
45
+ height: 1px;
46
+ width: 1px;
47
+ overflow: hidden;
48
+ clip: rect(0 0 0 0);
49
+ border: 0;
50
+ word-wrap: normal !important; /* Many screen reader and browser combinations announce broken words as they would appear visually. */
51
+ }
52
+ }
53
+ .compat-field-wio .label {
54
+ vertical-align: top;
55
+ }
56
+ .compat-field-wio ul.wio-datas-list {
57
+ margin-top: 7px;
58
+ font-size: 11px;
59
+ }
60
+ ul.wio-datas-list.wio-datas-list {
61
+ margin: 0 auto;
62
+ color: #555;
63
+ font-size: 10px;
64
+ }
65
+ ul.wio-datas-list .big {
66
+ font-size: 12px;
67
+ color: #40B1D0;
68
+ }
69
+ .wio-data-item {
70
+ overflow: hidden;
71
+ }
72
+ li.wio-data-item {
73
+ clear: both;
74
+ margin-bottom: 2px;
75
+ }
76
+ ul.wio-datas-list .wio-data-item span.data,
77
+ ul.wio-datas-list .wio-data-item strong {
78
+ float: left;
79
+ width: 50%;
80
+ -webkit-box-sizing: border-box;
81
+ -moz-box-sizing: border-box;
82
+ box-sizing: border-box;
83
+ }
84
+ ul.wio-datas-list .wio-data-item span.data {
85
+ text-align: left;
86
+ padding-right: 5px;
87
+ }
88
+ .compat-field-wio .wio-datas-list .wio-data-item .data {
89
+ width: 130px;
90
+ text-align: left;
91
+ font-weight: bold;
92
+ }
93
+ ul.wio-datas-list .wio-data-item strong {
94
+ text-align: left;
95
+ padding-left: 5px;
96
+ }
97
+ .media-sidebar .wio-datas-list .wio-data-item .data {
98
+ width: auto;
99
+ float: none;
100
+ }
101
+ .media-sidebar .wio-datas-list .wio-data-item strong {
102
+ display: inline-block;
103
+ width: auto;
104
+ float: none;
105
+ }
106
+ .media-sidebar .wio-datas-list .wio-data-item .wio-chart {
107
+ float: left;
108
+ }
109
+ .wio-datas-more-action.wio-datas-more-action {
110
+ margin: .4em auto;
111
+ background: linear-gradient(to bottom, transparent, transparent 49%, rgba(0,0,0,.075) 50%, rgba(0,0,0,.075) 58%, transparent 58%, transparent);
112
+ }
113
+ .wio-datas-more-action a {
114
+ display: inline-block;
115
+ padding: 0 5px;
116
+ background: #40B1D0;
117
+ color: #FFF;
118
+ text-transform: uppercase;
119
+ font-size: 9px;
120
+ font-weight: bold;
121
+ line-height: 1.9;
122
+ text-decoration: none;
123
+ }
124
+ .wio-datas-more-action a.is-open {
125
+ background: #555;
126
+ }
127
+ .wio-datas-more-action a.is-open .dashicons {
128
+ transform: rotate(180deg);
129
+ }
130
+ .wio-datas-more-action a .dashicons {
131
+ font-size: 14px;
132
+ vertical-align: middle;
133
+ line-height: .8;
134
+ }
135
+ .wio-datas-more-action a .dashicons:before {
136
+ vertical-align: middle;
137
+ line-height: 20px;
138
+ }
139
+ .wio-datas-more-action .the-text {
140
+ display: inline-block;
141
+ vertical-align: middle;
142
+ height: auto;
143
+ line-height: inherit;
144
+ }
145
+
146
+ ul.wio-datas-details.wio-datas-details {
147
+ margin: .7em auto;
148
+ }
149
+ .wio-datas-details strong {
150
+ color: #40B1D0;
151
+ }
152
+ .wio-datas-details .original {
153
+ color: #555;
154
+ }
155
+
156
+ .wio-datas-actions-links {
157
+ overflow: hidden;
158
+ border-top: 2px solid transparent;
159
+ padding-top: 5px;
160
+ font-size: 8px;
161
+ }
162
+ .nggform .wio-datas-actions-links {
163
+ position: relative;
164
+ z-index: 2;
165
+ }
166
+ .nggform .row-actions {
167
+ z-index: 1;
168
+ }
169
+ .wio-datas-actions-links a {
170
+ position: relative;
171
+ display: inline-block;
172
+ padding-left: 17px;
173
+ text-decoration: none;
174
+ font-weight: 600;
175
+ }
176
+ .compat-field-wio .wio-datas-actions-links {
177
+ max-width: 300px;
178
+ }
179
+ .misc-pub-wio .wio-datas-actions-links {
180
+ border-top: 2px solid #f2f2f2;
181
+ padding-bottom: 5px;
182
+ }
183
+ /* Library */
184
+ .column-wio_optimized_file .wio-datas-actions-links a {
185
+ margin: 0 .7em;
186
+ padding-left: 15px;
187
+ }
188
+
189
+ /* Media edition */
190
+ .compat-field-wio .wio-datas-actions-links a,
191
+ .misc-pub-wio .wio-datas-actions-links a {
192
+ font-size: 10px;
193
+ float: left;
194
+ width: 50%;
195
+ }
196
+ .media-sidebar .compat-field-wio .wio-datas-actions-links a,
197
+ .submitbox .misc-pub-wio .wio-datas-actions-links a {
198
+ display: block;
199
+ width: auto;
200
+ float: none;
201
+ }
202
+ .wio-datas-actions-links a:only-child {
203
+ float: none;
204
+ width: auto;
205
+ }
206
+ .wio-datas-details.is-open + .wio-datas-actions-links {
207
+ border-top-color: rgba(0,0,0,.075);
208
+ }
209
+ .wio-datas-actions-links .dashicons {
210
+ position: absolute;
211
+ left: 0; top: 4px;
212
+ width: 12px;
213
+ margin-right: 2px;
214
+ font-size: 11px;
215
+ }
admin/assets/css/statistic.css ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * == Columns
3
+ */
4
+ .wio-columns {
5
+ overflow: hidden;
6
+ padding: 15px 0;
7
+ counter-reset: cols;
8
+ }
9
+ .wio-columns [class^="col-"] {
10
+ float: left;
11
+ -webkit-box-sizing: border-box;
12
+ -moz-box-sizing: border-box;
13
+ box-sizing: border-box;
14
+ }
15
+ .wio-columns .col-1-3 {
16
+ width: 33.333%;
17
+ padding-left: 28px;
18
+ }
19
+ .wio .col-2-3 {
20
+ width: 66.666%;
21
+ padding-left: 28px
22
+ }
23
+ .wio .col-1-2 {
24
+ width: 50%;
25
+ padding: 0 20px;
26
+ }
27
+
28
+ @media (max-width: 830px) {
29
+ .wio [class^="col-"] {
30
+ float: none;
31
+ margin-bottom: 1.5em;
32
+ }
33
+ .wio .col-1-3,
34
+ .wio .col-1-2 {
35
+ width: auto;
36
+ padding: 0 28px;
37
+ clear: both;
38
+ padding-top: 1em;
39
+ }
40
+ }
41
+
42
+ /* Col, behavior depending on parent */
43
+ .wio-col {
44
+ float: left;
45
+ width: 50%;
46
+ box-sizing: border-box;
47
+ -webkit-flex-basis: 50%;
48
+ -ms-flex-preferred-size: 50%;
49
+ flex-basis: 50%;
50
+ }
51
+ .wio-col {
52
+ padding-right: 20px;
53
+ }
54
+ .wio-col + .wio-col {
55
+ padding-right: 0;
56
+ padding-left: 50px;
57
+ }
58
+
59
+ .wio-col:target {
60
+ animation: wiohello 1s 3 linear backwards;
61
+ }
62
+
63
+ @keyframes wiohello {
64
+ 0%, 100% {
65
+ background: #FFF;
66
+ }
67
+ 50% {
68
+ background: #F4F7F9;
69
+ }
70
+ }
71
+
72
+ .wio-columns .col-statistics.col-statistics {
73
+ width: 60%;
74
+ }
75
+ @media (max-width: 1520px) and (min-width: 1381px), (max-width: 1086px) {
76
+ .wio-columns .col-statistics.col-statistics,
77
+ .wio-columns .col-chart.col-chart {
78
+ width: 50%;
79
+ }
80
+ }
81
+ @media (max-width: 808px) {
82
+ .wio-columns .col-statistics.col-statistics,
83
+ .wio-columns .col-chart.col-chart {
84
+ width: auto;
85
+ float: none;
86
+ padding: 0;
87
+ }
88
+ .wio-columns .col-chart.col-chart {
89
+ margin-top: 3em;
90
+ }
91
+ }
92
+
93
+ /* Number display */
94
+ .wio-number-you-optimized {
95
+ margin-bottom: 1.35em;
96
+ overflow: hidden;
97
+ }
98
+ .wio-number-you-optimized .number {
99
+ display: table-cell;
100
+ padding-right: 15px;
101
+ font-size: 48px;
102
+ font-weight: bold;
103
+ line-height: 1;
104
+ vertical-align: middle;
105
+ white-space: nowrap;
106
+ color: #000;
107
+ }
108
+ .wio-number-you-optimized [id="wio-total-optimized-attachments-pct"] {
109
+ color: #40B1D0;
110
+ }
111
+ .wio-number-you-optimized .text {
112
+ display: table-cell;
113
+ vertical-align: middle;
114
+ overflow: hidden;
115
+ font-size: 12px;
116
+ color: #626E7B;
117
+ }
118
+ .wio-number-you-optimized > p {
119
+ display: table;
120
+ }
121
+
122
+ /* Number and bars */
123
+ .wio-bars {
124
+ padding-right: 15px;
125
+ }
126
+ .wio-bars p {
127
+ font-size: 12px;
128
+ margin-bottom: 5px;
129
+ }
130
+ .wio-bars + .wio-number-you-optimized {
131
+ border-bottom: 0;
132
+ padding-top: 0.85em;
133
+ }
134
+ .wio-bars + .wio-number-you-optimized p {
135
+ color: #46b1ce;
136
+ }
137
+
138
+ .wio-bar-negative .wio-progress {
139
+ background: #D2D3D6;
140
+ }
141
+ .wio-bar-negative .wio-barnb {
142
+ color: #7A8996;
143
+ }
144
+ .wio-bar-neutral .wio-progress {
145
+ background: #F5A623;
146
+ }
147
+ .wio-space-left .wio-bar-negative .wio-progress {
148
+ background: #C51162;
149
+ }
150
+
151
+ .wio-progress {
152
+ height: 8px;
153
+ }
154
+ .wio-progress {
155
+ transition: width .3s;
156
+ }
157
+ .wio-bar-positive .wio-progress {
158
+ background: #8CC152;
159
+ }
160
+ .wio-bar-positive .wio-barnb {
161
+ color: #8CC152;
162
+ }
163
+ .wio-bar-primary .wio-progress {
164
+ background: #8bc34a;
165
+ }
166
+ .wio-bar-primary .wio-barnb {
167
+ color: #8bc34a;
168
+ }
169
+
170
+ .right-outside-number .wio-barnb {
171
+ display: block;
172
+ margin-right: -5.25em;
173
+ text-align: right;
174
+ font-weight: bold;
175
+ line-height: .8;
176
+ }
177
+
178
+
179
+ /* Doughnut */
180
+ .wio-chart {
181
+ position: relative;
182
+ top: 1px;
183
+ display: inline-block;
184
+ vertical-align: middle;
185
+ }
186
+ .wio-chart-container {
187
+ position: relative;
188
+ display: inline-block;
189
+ margin-right: 5px;
190
+ }
191
+ .wio-chart-container canvas {
192
+ display: block;
193
+ }
194
+
195
+ .wio-overview-chart-container {
196
+ float: left;
197
+ margin-right: 20px;
198
+ }
199
+
200
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
201
+ .wio-overview-chart-container {
202
+ float: none;
203
+ margin-right: 0;
204
+ }
205
+ }
206
+
207
+ .wio-chart-percent {
208
+ position: absolute;
209
+ left: 0; right: 0;
210
+ top: 50%;
211
+ margin-top: -.5em;
212
+ line-height: 1;
213
+ text-align: center;
214
+ font-size: 55px;
215
+ font-weight: bold;
216
+ color: #afafaf;
217
+ }
218
+ .wio-chart-percent span {
219
+ font-size: 20px;
220
+ vertical-align: super;
221
+ }
222
+
223
+ #wio-overview-chart-legend {
224
+ overflow: hidden;
225
+ }
226
+
227
+ .imagify-doughnut-legend {
228
+ margin-top: 38px;
229
+ list-style: none;
230
+ }
231
+
232
+ .wio-doughnut-legend li {
233
+ display: inline-block;
234
+ padding-left: 30px;
235
+ position: relative;
236
+ margin-bottom: 15px;
237
+ border-radius: 5px;
238
+ padding: 3px 8px 2px 31px;
239
+ font-size: 13px;
240
+ cursor: default;
241
+ -webkit-transition: background-color 200ms ease-in-out;
242
+ -moz-transition: background-color 200ms ease-in-out;
243
+ -o-transition: background-color 200ms ease-in-out;
244
+ transition: background-color 200ms ease-in-out;
245
+ }
246
+
247
+ .wio-doughnut-legend li span {
248
+ display: block;
249
+ position: absolute;
250
+ left: 0; top: 0;
251
+ width: 25px;
252
+ height: 25px;
253
+ border-radius: 50%;
254
+ }
255
+ @media (max-width: 1380px) and (min-width: 1246px), (max-width: 380px) {
256
+ .wio-overview-chart-container {
257
+ float: none;
258
+ margin-right: 0;
259
+ }
260
+ .wio-doughnut-legend {
261
+ margin-top: 18px;
262
+ }
263
+ .wio-global-optim-phrase {
264
+ padding-top: 0;
265
+ width: auto;
266
+ }
267
+ }
268
+ .wio-global-optim-phrase {
269
+ width: 180px;
270
+ padding-top: 20px;
271
+ font-size: 14px;
272
+ text-align: center;
273
+ }
274
+
275
+ .wio-clear {
276
+ clear: both;
277
+ }
278
+
279
+ .wio-total-percent {
280
+ color: #46b1ce;
281
+ }
282
+
283
+ .wio-columns .col-chart.col-chart {
284
+ width: 40%;
285
+ position: relative;
286
+ padding: 20px;
287
+ font-size: 12px;
288
+ text-transform: uppercase;
289
+ background: #f1f1f1b3;
290
+ color: #abacaf;
291
+ font-weight: bold;
292
+ border-radius: 5px;
293
+ margin-top: 10px;
294
+ text-align: left;
295
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
296
+ }
297
+
298
+ .wio-image-optimize-board {
299
+ padding-bottom: 0 !important;
300
+ }
301
+
302
+ .wio-optimize-button {
303
+ width: 180px;
304
+ padding: 12px 30px;
305
+ background: #c9deb2;
306
+ color: #586549;
307
+ border: 0;
308
+ box-shadow: none;
309
+ font-size: 16px;
310
+ text-transform: uppercase !important;
311
+ font-weight: bold;
312
+ border-radius: 4px;
313
+ outline: none;
314
+ }
315
+
316
+ .wio-optimize-button:active {
317
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.5);
318
+ }
319
+
320
+ .wio-optimize-button.running {
321
+ color: #a57b3c;
322
+ background:#fdd599 url("../img/Spinner-1s-33px.gif") 10px center no-repeat;
323
+ }
324
+
325
+ .wio-widget-bottom {
326
+ display: table;
327
+ padding-top:20px !important;
328
+ width: 100%;
329
+ text-align: right;
330
+ }
331
+ .wio-widget-bottom li {
332
+ display: table-cell;
333
+ }
334
+ .wio-widget-bottom li:first-child {
335
+ text-align: left;
336
+ }
337
+
338
+ .wio-imagify-widget {
339
+ padding: 0 !important;
340
+ }
341
+
342
+ .wio-imagify-widget .wio-bars {
343
+ width: 60%;
344
+ margin-left: 155px;
345
+ }
346
+
347
+ .wio-imagify-widget .col-chart.col-chart {
348
+ width: 100%;
349
+ }
350
+ .wio-imagify-widget .col-controls {
351
+ width: 45%;
352
+ padding-left:5px;
353
+ padding-top:110px
354
+ }
355
+
356
+ .wio-imagify-widget .wio-doughnut-legend {
357
+ /*padding-top:30px;*/
358
+ text-align:left;
359
+ }
360
+
361
+ #wio-start-msg-top, #wio-start-msg-right, #wio-start-msg-complete {
362
+ display:none;
363
+ }
364
+
365
+ .wio-text-left {
366
+ text-align:left;
367
+ }
368
+
369
+ span.wio-num {
370
+ display:inline !important;
371
+ position:inherit !important;
372
+ }
admin/assets/img/Spinner-1s-33px.gif ADDED
Binary file
admin/assets/index.php ADDED
File without changes
admin/assets/js/Chart.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Chart.js
3
+ * http://chartjs.org/
4
+ * Version: 2.7.2
5
+ *
6
+ * Copyright 2018 Chart.js Contributors
7
+ * Released under the MIT license
8
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
9
+ */
10
+ !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,i,n){function a(r,s){if(!i[r]){if(!e[r]){var l="function"==typeof require&&require;if(!s&&l)return l(r,!0);if(o)return o(r,!0);var u=new Error("Cannot find module '"+r+"'");throw u.code="MODULE_NOT_FOUND",u}var d=i[r]={exports:{}};e[r][0].call(d.exports,function(t){var i=e[r][1][t];return a(i||t)},d,d.exports,t,e,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;r<n.length;r++)a(n[r]);return a}({1:[function(t,e,i){},{}],2:[function(t,e,i){var n=t(6);function a(t){if(t){var e=[0,0,0],i=1,a=t.match(/^#([a-fA-F0-9]{3})$/i);if(a){a=a[1];for(var o=0;o<e.length;o++)e[o]=parseInt(a[o]+a[o],16)}else if(a=t.match(/^#([a-fA-F0-9]{6})$/i)){a=a[1];for(o=0;o<e.length;o++)e[o]=parseInt(a.slice(2*o,2*o+2),16)}else if(a=t.match(/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(o=0;o<e.length;o++)e[o]=parseInt(a[o+1]);i=parseFloat(a[4])}else if(a=t.match(/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i)){for(o=0;o<e.length;o++)e[o]=Math.round(2.55*parseFloat(a[o+1]));i=parseFloat(a[4])}else if(a=t.match(/(\w+)/)){if("transparent"==a[1])return[0,0,0,0];if(!(e=n[a[1]]))return}for(o=0;o<e.length;o++)e[o]=d(e[o],0,255);return i=i||0==i?d(i,0,1):1,e[3]=i,e}}function o(t){if(t){var e=t.match(/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var i=parseFloat(e[4]);return[d(parseInt(e[1]),0,360),d(parseFloat(e[2]),0,100),d(parseFloat(e[3]),0,100),d(isNaN(i)?1:i,0,1)]}}}function r(t){if(t){var e=t.match(/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/);if(e){var i=parseFloat(e[4]);return[d(parseInt(e[1]),0,360),d(parseFloat(e[2]),0,100),d(parseFloat(e[3]),0,100),d(isNaN(i)?1:i,0,1)]}}}function s(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function l(t,e){return"rgba("+Math.round(t[0]/255*100)+"%, "+Math.round(t[1]/255*100)+"%, "+Math.round(t[2]/255*100)+"%, "+(e||t[3]||1)+")"}function u(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function d(t,e,i){return Math.min(Math.max(e,t),i)}function c(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}e.exports={getRgba:a,getHsla:o,getRgb:function(t){var e=a(t);return e&&e.slice(0,3)},getHsl:function(t){var e=o(t);return e&&e.slice(0,3)},getHwb:r,getAlpha:function(t){var e=a(t);{if(e)return e[3];if(e=o(t))return e[3];if(e=r(t))return e[3]}},hexString:function(t){return"#"+c(t[0])+c(t[1])+c(t[2])},rgbString:function(t,e){if(e<1||t[3]&&t[3]<1)return s(t,e);return"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:s,percentString:function(t,e){if(e<1||t[3]&&t[3]<1)return l(t,e);var i=Math.round(t[0]/255*100),n=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+i+"%, "+n+"%, "+a+"%)"},percentaString:l,hslString:function(t,e){if(e<1||t[3]&&t[3]<1)return u(t,e);return"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:u,hwbString:function(t,e){void 0===e&&(e=void 0!==t[3]?t[3]:1);return"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return h[t.slice(0,3)]}};var h={};for(var f in n)h[n[f]]=f},{6:6}],3:[function(t,e,i){var n=t(5),a=t(2),o=function(t){return t instanceof o?t:this instanceof o?(this.valid=!1,this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1},void("string"==typeof t?(e=a.getRgba(t))?this.setValues("rgb",e):(e=a.getHsla(t))?this.setValues("hsl",e):(e=a.getHwb(t))&&this.setValues("hwb",e):"object"==typeof t&&(void 0!==(e=t).r||void 0!==e.red?this.setValues("rgb",e):void 0!==e.l||void 0!==e.lightness?this.setValues("hsl",e):void 0!==e.v||void 0!==e.value?this.setValues("hsv",e):void 0!==e.w||void 0!==e.whiteness?this.setValues("hwb",e):void 0===e.c&&void 0===e.cyan||this.setValues("cmyk",e)))):new o(t);var e};o.prototype={isValid:function(){return this.valid},rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t=(t%=360)<0?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],i=0;i<t.length;i++){var n=t[i]/255;e[i]=n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),i=t.luminosity();return e>i?(e+.05)/(i+.05):(i+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,i=(e[0]+t)%360;return e[0]=i<0?360+i:i,this.setValues("hsl",e),this},mix:function(t,e){var i=this,n=t,a=void 0===e?.5:e,o=2*a-1,r=i.alpha()-n.alpha(),s=((o*r==-1?o:(o+r)/(1+o*r))+1)/2,l=1-s;return this.rgb(s*i.red()+l*n.red(),s*i.green()+l*n.green(),s*i.blue()+l*n.blue()).alpha(i.alpha()*a+n.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,i=new o,n=this.values,a=i.values;for(var r in n)n.hasOwnProperty(r)&&(t=n[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return i}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,i={},n=0;n<t.length;n++)i[t.charAt(n)]=e[t][n];return 1!==e.alpha&&(i.a=e.alpha),i},o.prototype.setValues=function(t,e){var i,a,o=this.values,r=this.spaces,s=this.maxes,l=1;if(this.valid=!0,"alpha"===t)l=e;else if(e.length)o[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(i=0;i<t.length;i++)o[t][i]=e[t.charAt(i)];l=e.a}else if(void 0!==e[r[t][0]]){var u=r[t];for(i=0;i<t.length;i++)o[t][i]=e[u[i]];l=e.alpha}if(o.alpha=Math.max(0,Math.min(1,void 0===l?o.alpha:l)),"alpha"===t)return!1;for(i=0;i<t.length;i++)a=Math.max(0,Math.min(s[t][i],o[t][i])),o[t][i]=Math.round(a);for(var d in r)d!==t&&(o[d]=n[t][d](o[t]));return!0},o.prototype.setSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i),this)},o.prototype.setChannel=function(t,e,i){var n=this.values[t];return void 0===i?n[e]:i===n[e]?this:(n[e]=i,this.setValues(t,n),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,i){function n(t){var e,i,n=t[0]/255,a=t[1]/255,o=t[2]/255,r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r;return s==r?e=0:n==s?e=(a-o)/l:a==s?e=2+(o-n)/l:o==s&&(e=4+(n-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),i=(r+s)/2,[e,100*(s==r?0:i<=.5?l/(s+r):l/(2-s-r)),100*i]}function a(t){var e,i,n=t[0],a=t[1],o=t[2],r=Math.min(n,a,o),s=Math.max(n,a,o),l=s-r;return i=0==s?0:l/s*1e3/10,s==r?e=0:n==s?e=(a-o)/l:a==s?e=2+(o-n)/l:o==s&&(e=4+(n-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),[e,i,s/255*1e3/10]}function o(t){var e=t[0],i=t[1],a=t[2];return[n(t)[0],100*(1/255*Math.min(e,Math.min(i,a))),100*(a=1-1/255*Math.max(e,Math.max(i,a)))]}function s(t){var e,i=t[0]/255,n=t[1]/255,a=t[2]/255;return[100*((1-i-(e=Math.min(1-i,1-n,1-a)))/(1-e)||0),100*((1-n-e)/(1-e)||0),100*((1-a-e)/(1-e)||0),100*e]}function l(t){return C[JSON.stringify(t)]}function u(t){var e=t[0]/255,i=t[1]/255,n=t[2]/255;return[100*(.4124*(e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)+.1805*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)),100*(.2126*e+.7152*i+.0722*n),100*(.0193*e+.1192*i+.9505*n)]}function d(t){var e=u(t),i=e[0],n=e[1],a=e[2];return n/=100,a/=108.883,i=(i/=95.047)>.008856?Math.pow(i,1/3):7.787*i+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(i-n),200*(n-(a=a>.008856?Math.pow(a,1/3):7.787*a+16/116))]}function c(t){var e,i,n,a,o,r=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return[o=255*l,o,o];e=2*l-(i=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(n=r+1/3*-(u-1))<0&&n++,n>1&&n--,o=6*n<1?e+6*(i-e)*n:2*n<1?i:3*n<2?e+(i-e)*(2/3-n)*6:e,a[u]=255*o;return a}function h(t){var e=t[0]/60,i=t[1]/100,n=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*n*(1-i),s=255*n*(1-i*o),l=255*n*(1-i*(1-o));n*=255;switch(a){case 0:return[n,l,r];case 1:return[s,n,r];case 2:return[r,n,l];case 3:return[r,s,n];case 4:return[l,r,n];case 5:return[n,r,s]}}function f(t){var e,i,n,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),n=6*o-(e=Math.floor(6*o)),0!=(1&e)&&(n=1-n),a=s+n*((i=1-l)-s),e){default:case 6:case 0:r=i,g=a,b=s;break;case 1:r=a,g=i,b=s;break;case 2:r=s,g=i,b=a;break;case 3:r=s,g=a,b=i;break;case 4:r=a,g=s,b=i;break;case 5:r=i,g=s,b=a}return[255*r,255*g,255*b]}function p(t){var e=t[0]/100,i=t[1]/100,n=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,i*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a))]}function m(t){var e,i,n,a=t[0]/100,o=t[1]/100,r=t[2]/100;return i=-.9689*a+1.8758*o+.0415*r,n=.0557*a+-.204*o+1.057*r,e=(e=3.2406*a+-1.5372*o+-.4986*r)>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,[255*(e=Math.min(Math.max(0,e),1)),255*(i=Math.min(Math.max(0,i),1)),255*(n=Math.min(Math.max(0,n),1))]}function v(t){var e=t[0],i=t[1],n=t[2];return i/=100,n/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116)-16,500*(e-i),200*(i-(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116))]}function x(t){var e,i,n,a,o=t[0],r=t[1],s=t[2];return o<=8?a=(i=100*o/903.3)/100*7.787+16/116:(i=100*Math.pow((o+16)/116,3),a=Math.pow(i/100,1/3)),[e=e/95.047<=.008856?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),i,n=n/108.883<=.008859?n=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3)]}function y(t){var e,i=t[0],n=t[1],a=t[2];return(e=360*Math.atan2(a,n)/2/Math.PI)<0&&(e+=360),[i,Math.sqrt(n*n+a*a),e]}function k(t){return m(x(t))}function M(t){var e,i=t[0],n=t[1];return e=t[2]/360*2*Math.PI,[i,n*Math.cos(e),n*Math.sin(e)]}function w(t){return S[t]}e.exports={rgb2hsl:n,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return y(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e=t[0],i=t[1]/100,n=t[2]/100;if(0===n)return[0,0,0];return[e,100*(2*(i*=(n*=2)<=1?n:2-n)/(n+i)),100*((n+i)/2)]},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,i,n=t[0],a=t[1]/100,o=t[2]/100;return e=a*o,[n,100*(e=(e/=(i=(2-a)*o)<=1?i:2-i)||0),100*(i/=2)]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return n(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:p,cmyk2hsl:function(t){return n(p(t))},cmyk2hsv:function(t){return a(p(t))},cmyk2hwb:function(t){return o(p(t))},cmyk2keyword:function(t){return l(p(t))},keyword2rgb:w,keyword2hsl:function(t){return n(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:m,xyz2lab:v,xyz2lch:function(t){return y(v(t))},lab2xyz:x,lab2rgb:k,lab2lch:y,lch2lab:M,lch2xyz:function(t){return x(M(t))},lch2rgb:function(t){return k(M(t))}};var S={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},C={};for(var _ in S)C[JSON.stringify(S[_])]=_},{}],5:[function(t,e,i){var n=t(4),a=function(){return new u};for(var o in n){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),n[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),s=r[1],l=r[2];(a[s]=a[s]||{})[l]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var i=n[t](e);if("string"==typeof i||void 0===i)return i;for(var a=0;a<i.length;a++)i[a]=Math.round(i[a]);return i}}(o)}var u=function(){this.convs={}};u.prototype.routeSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i))},u.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},u.prototype.getValues=function(t){var e=this.convs[t];if(!e){var i=this.space,n=this.convs[i];e=a[i][t](n),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){u.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{4:4}],6:[function(t,e,i){"use strict";e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,i){var n=t(29)();n.helpers=t(45),t(27)(n),n.defaults=t(25),n.Element=t(26),n.elements=t(40),n.Interaction=t(28),n.layouts=t(30),n.platform=t(48),n.plugins=t(31),n.Ticks=t(34),t(22)(n),t(23)(n),t(24)(n),t(33)(n),t(32)(n),t(35)(n),t(55)(n),t(53)(n),t(54)(n),t(56)(n),t(57)(n),t(58)(n),t(15)(n),t(16)(n),t(17)(n),t(18)(n),t(19)(n),t(20)(n),t(21)(n),t(8)(n),t(9)(n),t(10)(n),t(11)(n),t(12)(n),t(13)(n),t(14)(n);var a=t(49);for(var o in a)a.hasOwnProperty(o)&&n.plugins.register(a[o]);n.platform.initialize(),e.exports=n,"undefined"!=typeof window&&(window.Chart=n),n.Legend=a.legend._element,n.Title=a.title._element,n.pluginService=n.plugins,n.PluginBase=n.Element.extend({}),n.canvasHelpers=n.helpers.canvas,n.layoutService=n.layouts},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,40:40,45:45,48:48,49:49,53:53,54:54,55:55,56:56,57:57,58:58,8:8,9:9}],8:[function(t,e,i){"use strict";e.exports=function(t){t.Bar=function(e,i){return i.type="bar",new t(e,i)}}},{}],9:[function(t,e,i){"use strict";e.exports=function(t){t.Bubble=function(e,i){return i.type="bubble",new t(e,i)}}},{}],10:[function(t,e,i){"use strict";e.exports=function(t){t.Doughnut=function(e,i){return i.type="doughnut",new t(e,i)}}},{}],11:[function(t,e,i){"use strict";e.exports=function(t){t.Line=function(e,i){return i.type="line",new t(e,i)}}},{}],12:[function(t,e,i){"use strict";e.exports=function(t){t.PolarArea=function(e,i){return i.type="polarArea",new t(e,i)}}},{}],13:[function(t,e,i){"use strict";e.exports=function(t){t.Radar=function(e,i){return i.type="radar",new t(e,i)}}},{}],14:[function(t,e,i){"use strict";e.exports=function(t){t.Scatter=function(e,i){return i.type="scatter",new t(e,i)}}},{}],15:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),n._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var i="";return t.length>0&&(t[0].yLabel?i=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(i=e.labels[t[0].index])),i},label:function(t,e){return(e.datasets[t.datasetIndex].label||"")+": "+t.xLabel}},mode:"index",axis:"y"}}),e.exports=function(t){t.controllers.bar=t.DatasetController.extend({dataElementType:a.Rectangle,initialize:function(){var e;t.DatasetController.prototype.initialize.apply(this,arguments),(e=this.getMeta()).stack=this.getDataset().stack,e.bar=!0},update:function(t){var e,i,n=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,i=n.length;e<i;++e)this.updateElement(n[e],e,t)},updateElement:function(t,e,i){var n=this,a=n.chart,r=n.getMeta(),s=n.getDataset(),l=t.custom||{},u=a.options.elements.rectangle;t._xScale=n.getScaleForId(r.xAxisID),t._yScale=n.getScaleForId(r.yAxisID),t._datasetIndex=n.index,t._index=e,t._model={datasetLabel:s.label,label:a.data.labels[e],borderSkipped:l.borderSkipped?l.borderSkipped:u.borderSkipped,backgroundColor:l.backgroundColor?l.backgroundColor:o.valueAtIndexOrDefault(s.backgroundColor,e,u.backgroundColor),borderColor:l.borderColor?l.borderColor:o.valueAtIndexOrDefault(s.borderColor,e,u.borderColor),borderWidth:l.borderWidth?l.borderWidth:o.valueAtIndexOrDefault(s.borderWidth,e,u.borderWidth)},n.updateElementGeometry(t,e,i),t.pivot()},updateElementGeometry:function(t,e,i){var n=this,a=t._model,o=n.getValueScale(),r=o.getBasePixel(),s=o.isHorizontal(),l=n._ruler||n.getRuler(),u=n.calculateBarValuePixels(n.index,e),d=n.calculateBarIndexPixels(n.index,e,l);a.horizontal=s,a.base=i?r:u.base,a.x=s?i?r:u.head:d.center,a.y=s?d.center:i?r:u.head,a.height=s?d.size:void 0,a.width=s?void 0:d.size},getValueScaleId:function(){return this.getMeta().yAxisID},getIndexScaleId:function(){return this.getMeta().xAxisID},getValueScale:function(){return this.getScaleForId(this.getValueScaleId())},getIndexScale:function(){return this.getScaleForId(this.getIndexScaleId())},_getStacks:function(t){var e,i,n=this.chart,a=this.getIndexScale().options.stacked,o=void 0===t?n.data.datasets.length:t+1,r=[];for(e=0;e<o;++e)(i=n.getDatasetMeta(e)).bar&&n.isDatasetVisible(e)&&(!1===a||!0===a&&-1===r.indexOf(i.stack)||void 0===a&&(void 0===i.stack||-1===r.indexOf(i.stack)))&&r.push(i.stack);return r},getStackCount:function(){return this._getStacks().length},getStackIndex:function(t,e){var i=this._getStacks(t),n=void 0!==e?i.indexOf(e):-1;return-1===n?i.length-1:n},getRuler:function(){var t,e,i=this.getIndexScale(),n=this.getStackCount(),a=this.index,r=i.isHorizontal(),s=r?i.left:i.top,l=s+(r?i.width:i.height),u=[];for(t=0,e=this.getMeta().data.length;t<e;++t)u.push(i.getPixelForValue(null,t,a));return{min:o.isNullOrUndef(i.options.barThickness)?function(t,e){var i,n,a,o,r=t.isHorizontal()?t.width:t.height,s=t.getTicks();for(a=1,o=e.length;a<o;++a)r=Math.min(r,e[a]-e[a-1]);for(a=0,o=s.length;a<o;++a)n=t.getPixelForTick(a),r=a>0?Math.min(r,n-i):r,i=n;return r}(i,u):-1,pixels:u,start:s,end:l,stackCount:n,scale:i}},calculateBarValuePixels:function(t,e){var i,n,a,o,r,s,l=this.chart,u=this.getMeta(),d=this.getValueScale(),c=l.data.datasets,h=d.getRightValue(c[t].data[e]),f=d.options.stacked,g=u.stack,p=0;if(f||void 0===f&&void 0!==g)for(i=0;i<t;++i)(n=l.getDatasetMeta(i)).bar&&n.stack===g&&n.controller.getValueScaleId()===d.id&&l.isDatasetVisible(i)&&(a=d.getRightValue(c[i].data[e]),(h<0&&a<0||h>=0&&a>0)&&(p+=a));return o=d.getPixelForValue(p),{size:s=((r=d.getPixelForValue(p+h))-o)/2,base:o,head:r,center:r+s/2}},calculateBarIndexPixels:function(t,e,i){var n,a,r,s,l,u,d,c,h,f,g,p,m,v,b,x,y,k=i.scale.options,M="flex"===k.barThickness?(h=e,g=k,m=(f=i).pixels,v=m[h],b=h>0?m[h-1]:null,x=h<m.length-1?m[h+1]:null,y=g.categoryPercentage,null===b&&(b=v-(null===x?f.end-v:x-v)),null===x&&(x=v+v-b),p=v-(v-b)/2*y,{chunk:(x-b)/2*y/f.stackCount,ratio:g.barPercentage,start:p}):(n=e,a=i,u=(r=k).barThickness,d=a.stackCount,c=a.pixels[n],o.isNullOrUndef(u)?(s=a.min*r.categoryPercentage,l=r.barPercentage):(s=u*d,l=1),{chunk:s/d,ratio:l,start:c-s/2}),w=this.getStackIndex(t,this.getMeta().stack),S=M.start+M.chunk*w+M.chunk/2,C=Math.min(o.valueOrDefault(k.maxBarThickness,1/0),M.chunk*M.ratio);return{base:S-C/2,head:S+C/2,center:S,size:C}},draw:function(){var t=this.chart,e=this.getValueScale(),i=this.getMeta().data,n=this.getDataset(),a=i.length,r=0;for(o.canvas.clipArea(t.ctx,t.chartArea);r<a;++r)isNaN(e.getRightValue(n.data[r]))||i[r].draw();o.canvas.unclipArea(t.ctx)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},a=t._model;a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o.valueAtIndexOrDefault(e.hoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:o.valueAtIndexOrDefault(e.hoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o.valueAtIndexOrDefault(e.hoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},a=t._model,r=this.chart.options.elements.rectangle;a.backgroundColor=n.backgroundColor?n.backgroundColor:o.valueAtIndexOrDefault(e.backgroundColor,i,r.backgroundColor),a.borderColor=n.borderColor?n.borderColor:o.valueAtIndexOrDefault(e.borderColor,i,r.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:o.valueAtIndexOrDefault(e.borderWidth,i,r.borderWidth)}}),t.controllers.horizontalBar=t.controllers.bar.extend({getValueScaleId:function(){return this.getMeta().xAxisID},getIndexScaleId:function(){return this.getMeta().yAxisID}})}},{25:25,40:40,45:45}],16:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("bubble",{hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(){return""},label:function(t,e){var i=e.datasets[t.datasetIndex].label||"",n=e.datasets[t.datasetIndex].data[t.index];return i+": ("+t.xLabel+", "+t.yLabel+", "+n.r+")"}}}}),e.exports=function(t){t.controllers.bubble=t.DatasetController.extend({dataElementType:a.Point,update:function(t){var e=this,i=e.getMeta().data;o.each(i,function(i,n){e.updateElement(i,n,t)})},updateElement:function(t,e,i){var n=this,a=n.getMeta(),o=t.custom||{},r=n.getScaleForId(a.xAxisID),s=n.getScaleForId(a.yAxisID),l=n._resolveElementOptions(t,e),u=n.getDataset().data[e],d=n.index,c=i?r.getPixelForDecimal(.5):r.getPixelForValue("object"==typeof u?u:NaN,e,d),h=i?s.getBasePixel():s.getPixelForValue(u,e,d);t._xScale=r,t._yScale=s,t._options=l,t._datasetIndex=d,t._index=e,t._model={backgroundColor:l.backgroundColor,borderColor:l.borderColor,borderWidth:l.borderWidth,hitRadius:l.hitRadius,pointStyle:l.pointStyle,radius:i?0:l.radius,skip:o.skip||isNaN(c)||isNaN(h),x:c,y:h},t.pivot()},setHoverStyle:function(t){var e=t._model,i=t._options;e.backgroundColor=o.valueOrDefault(i.hoverBackgroundColor,o.getHoverColor(i.backgroundColor)),e.borderColor=o.valueOrDefault(i.hoverBorderColor,o.getHoverColor(i.borderColor)),e.borderWidth=o.valueOrDefault(i.hoverBorderWidth,i.borderWidth),e.radius=i.radius+i.hoverRadius},removeHoverStyle:function(t){var e=t._model,i=t._options;e.backgroundColor=i.backgroundColor,e.borderColor=i.borderColor,e.borderWidth=i.borderWidth,e.radius=i.radius},_resolveElementOptions:function(t,e){var i,n,a,r=this.chart,s=r.data.datasets[this.index],l=t.custom||{},u=r.options.elements.point,d=o.options.resolve,c=s.data[e],h={},f={chart:r,dataIndex:e,dataset:s,datasetIndex:this.index},g=["backgroundColor","borderColor","borderWidth","hoverBackgroundColor","hoverBorderColor","hoverBorderWidth","hoverRadius","hitRadius","pointStyle"];for(i=0,n=g.length;i<n;++i)h[a=g[i]]=d([l[a],s[a],u[a]],f,e);return h.radius=d([l.radius,c?c.r:void 0,s.radius,u.radius],f,e),h}})}},{25:25,40:40,45:45}],17:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("doughnut",{animation:{animateRotate:!0,animateScale:!1},hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,n=i.datasets,a=i.labels;if(n.length)for(var o=0;o<n[0].data.length;++o)e.push('<li><span style="background-color:'+n[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(i,n){var a=t.getDatasetMeta(0),r=e.datasets[0],s=a.data[n],l=s&&s.custom||{},u=o.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:i,fillStyle:l.backgroundColor?l.backgroundColor:u(r.backgroundColor,n,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(r.borderColor,n,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(r.borderWidth,n,d.borderWidth),hidden:isNaN(r.data[n])||a.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var i,n,a,o=e.index,r=this.chart;for(i=0,n=(r.data.datasets||[]).length;i<n;++i)(a=r.getDatasetMeta(i)).data[o]&&(a.data[o].hidden=!a.data[o].hidden);r.update()}},cutoutPercentage:50,rotation:-.5*Math.PI,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){var i=e.labels[t.index],n=": "+e.datasets[t.datasetIndex].data[t.index];return o.isArray(i)?(i=i.slice())[0]+=n:i+=n,i}}}}),n._set("pie",o.clone(n.doughnut)),n._set("pie",{cutoutPercentage:0}),e.exports=function(t){t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,getRingIndex:function(t){for(var e=0,i=0;i<t;++i)this.chart.isDatasetVisible(i)&&++e;return e},update:function(t){var e=this,i=e.chart,n=i.chartArea,a=i.options,r=a.elements.arc,s=n.right-n.left-r.borderWidth,l=n.bottom-n.top-r.borderWidth,u=Math.min(s,l),d={x:0,y:0},c=e.getMeta(),h=a.cutoutPercentage,f=a.circumference;if(f<2*Math.PI){var g=a.rotation%(2*Math.PI),p=(g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0))+f,m=Math.cos(g),v=Math.sin(g),b=Math.cos(p),x=Math.sin(p),y=g<=0&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,k=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,M=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,w=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,S=h/100,C=M?-1:Math.min(m*(m<0?1:S),b*(b<0?1:S)),_=w?-1:Math.min(v*(v<0?1:S),x*(x<0?1:S)),D=y?1:Math.max(m*(m>0?1:S),b*(b>0?1:S)),I=k?1:Math.max(v*(v>0?1:S),x*(x>0?1:S)),P=.5*(D-C),A=.5*(I-_);u=Math.min(s/P,l/A),d={x:-.5*(D+C),y:-.5*(I+_)}}i.borderWidth=e.getMaxBorderWidth(c.data),i.outerRadius=Math.max((u-i.borderWidth)/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:0,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=d.x*i.outerRadius,i.offsetY=d.y*i.outerRadius,c.total=e.calculateTotal(),e.outerRadius=i.outerRadius-i.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-i.radiusLength,0),o.each(c.data,function(i,n){e.updateElement(i,n,t)})},updateElement:function(t,e,i){var n=this,a=n.chart,r=a.chartArea,s=a.options,l=s.animation,u=(r.left+r.right)/2,d=(r.top+r.bottom)/2,c=s.rotation,h=s.rotation,f=n.getDataset(),g=i&&l.animateRotate?0:t.hidden?0:n.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),p=i&&l.animateScale?0:n.innerRadius,m=i&&l.animateScale?0:n.outerRadius,v=o.valueAtIndexOrDefault;o.extend(t,{_datasetIndex:n.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:m,innerRadius:p,label:v(f.label,e,a.data.labels[e])}});var b=t._model;this.removeHoverStyle(t),i&&l.animateRotate||(b.startAngle=0===e?s.rotation:n.getMeta().data[e-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),i=this.getMeta(),n=0;return o.each(i.data,function(i,a){t=e.data[a],isNaN(t)||i.hidden||(n+=Math.abs(t))}),n},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){for(var e,i,n=0,a=this.index,o=t.length,r=0;r<o;r++)e=t[r]._model?t[r]._model.borderWidth:0,n=(i=t[r]._chart?t[r]._chart.config.data.datasets[a].hoverBorderWidth:0)>(n=e>n?e:n)?i:n;return n}})}},{25:25,40:40,45:45}],18:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return o.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var i,n,a,r=this,s=r.getMeta(),l=s.dataset,u=s.data||[],d=r.chart.options,c=d.elements.line,h=r.getScaleForId(s.yAxisID),f=r.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=r.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:o.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:o.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:o.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),i=0,n=u.length;i<n;++i)r.updateElement(u[i],i,t);for(g&&0!==l._model.tension&&r.updateBezierControlPoints(),i=0,n=u.length;i<n;++i)u[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,n=this.getDataset(),a=t.custom||{};return a.backgroundColor?i=a.backgroundColor:n.pointBackgroundColor?i=o.valueAtIndexOrDefault(n.pointBackgroundColor,e,i):n.backgroundColor&&(i=n.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,n=this.getDataset(),a=t.custom||{};return a.borderColor?i=a.borderColor:n.pointBorderColor?i=o.valueAtIndexOrDefault(n.pointBorderColor,e,i):n.borderColor&&(i=n.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,n=this.getDataset(),a=t.custom||{};return isNaN(a.borderWidth)?!isNaN(n.pointBorderWidth)||o.isArray(n.pointBorderWidth)?i=o.valueAtIndexOrDefault(n.pointBorderWidth,e,i):isNaN(n.borderWidth)||(i=n.borderWidth):i=a.borderWidth,i},updateElement:function(t,e,i){var n,a,r=this,s=r.getMeta(),l=t.custom||{},u=r.getDataset(),d=r.index,c=u.data[e],h=r.getScaleForId(s.yAxisID),f=r.getScaleForId(s.xAxisID),g=r.chart.options.elements.point;void 0!==u.radius&&void 0===u.pointRadius&&(u.pointRadius=u.radius),void 0!==u.hitRadius&&void 0===u.pointHitRadius&&(u.pointHitRadius=u.hitRadius),n=f.getPixelForValue("object"==typeof c?c:NaN,e,d),a=i?h.getBasePixel():r.calculatePointY(c,e,d),t._xScale=f,t._yScale=h,t._datasetIndex=d,t._index=e,t._model={x:n,y:a,skip:l.skip||isNaN(n)||isNaN(a),radius:l.radius||o.valueAtIndexOrDefault(u.pointRadius,e,g.radius),pointStyle:l.pointStyle||o.valueAtIndexOrDefault(u.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,steppedLine:!!s.dataset._model&&s.dataset._model.steppedLine,hitRadius:l.hitRadius||o.valueAtIndexOrDefault(u.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,i){var n,a,o,r=this.chart,s=this.getMeta(),l=this.getScaleForId(s.yAxisID),u=0,d=0;if(l.options.stacked){for(n=0;n<i;n++)if(a=r.data.datasets[n],"line"===(o=r.getDatasetMeta(n)).type&&o.yAxisID===l.id&&r.isDatasetVisible(n)){var c=Number(l.getRightValue(a.data[e]));c<0?d+=c||0:u+=c||0}var h=Number(l.getRightValue(t));return h<0?l.getPixelForValue(d+h):l.getPixelForValue(u+h)}return l.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,i,n,a=this.getMeta(),r=this.chart.chartArea,s=a.data||[];function l(t,e,i){return Math.max(Math.min(t,i),e)}if(a.dataset._model.spanGaps&&(s=s.filter(function(t){return!t._model.skip})),"monotone"===a.dataset._model.cubicInterpolationMode)o.splineCurveMonotone(s);else for(t=0,e=s.length;t<e;++t)i=s[t]._model,n=o.splineCurve(o.previousItem(s,t)._model,i,o.nextItem(s,t)._model,a.dataset._model.tension),i.controlPointPreviousX=n.previous.x,i.controlPointPreviousY=n.previous.y,i.controlPointNextX=n.next.x,i.controlPointNextY=n.next.y;if(this.chart.options.elements.line.capBezierPoints)for(t=0,e=s.length;t<e;++t)(i=s[t]._model).controlPointPreviousX=l(i.controlPointPreviousX,r.left,r.right),i.controlPointPreviousY=l(i.controlPointPreviousY,r.top,r.bottom),i.controlPointNextX=l(i.controlPointNextX,r.left,r.right),i.controlPointNextY=l(i.controlPointNextY,r.top,r.bottom)},draw:function(){var t=this.chart,i=this.getMeta(),n=i.data||[],a=t.chartArea,r=n.length,s=0;for(o.canvas.clipArea(t.ctx,a),e(this.getDataset(),t.options)&&i.dataset.draw(),o.canvas.unclipArea(t.ctx);s<r;++s)n[s].draw(a)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},a=t._model;a.radius=n.hoverRadius||o.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor||o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,o.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor||o.valueAtIndexOrDefault(e.pointHoverBorderColor,i,o.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth||o.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},r=t._model;void 0!==i.radius&&void 0===i.pointRadius&&(i.pointRadius=i.radius),r.radius=a.radius||o.valueAtIndexOrDefault(i.pointRadius,n,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,n),r.borderColor=e.getPointBorderColor(t,n),r.borderWidth=e.getPointBorderWidth(t,n)}})}},{25:25,40:40,45:45}],19:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("polarArea",{scale:{type:"radialLinear",angleLines:{display:!1},gridLines:{circular:!0},pointLabels:{display:!1},ticks:{beginAtZero:!0}},animation:{animateRotate:!0,animateScale:!0},startAngle:-.5*Math.PI,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,n=i.datasets,a=i.labels;if(n.length)for(var o=0;o<n[0].data.length;++o)e.push('<li><span style="background-color:'+n[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(i,n){var a=t.getDatasetMeta(0),r=e.datasets[0],s=a.data[n].custom||{},l=o.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:i,fillStyle:s.backgroundColor?s.backgroundColor:l(r.backgroundColor,n,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(r.borderColor,n,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(r.borderWidth,n,u.borderWidth),hidden:isNaN(r.data[n])||a.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var i,n,a,o=e.index,r=this.chart;for(i=0,n=(r.data.datasets||[]).length;i<n;++i)(a=r.getDatasetMeta(i)).data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}}),e.exports=function(t){t.controllers.polarArea=t.DatasetController.extend({dataElementType:a.Arc,linkScales:o.noop,update:function(t){var e=this,i=e.chart,n=i.chartArea,a=e.getMeta(),r=i.options,s=r.elements.arc,l=Math.min(n.right-n.left,n.bottom-n.top);i.outerRadius=Math.max((l-s.borderWidth/2)/2,0),i.innerRadius=Math.max(r.cutoutPercentage?i.outerRadius/100*r.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),e.outerRadius=i.outerRadius-i.radiusLength*e.index,e.innerRadius=e.outerRadius-i.radiusLength,a.count=e.countVisibleElements(),o.each(a.data,function(i,n){e.updateElement(i,n,t)})},updateElement:function(t,e,i){for(var n=this,a=n.chart,r=n.getDataset(),s=a.options,l=s.animation,u=a.scale,d=a.data.labels,c=n.calculateCircumference(r.data[e]),h=u.xCenter,f=u.yCenter,g=0,p=n.getMeta(),m=0;m<e;++m)isNaN(r.data[m])||p.data[m].hidden||++g;var v=s.startAngle,b=t.hidden?0:u.getDistanceFromCenterForValue(r.data[e]),x=v+c*g,y=x+(t.hidden?0:c),k=l.animateScale?0:u.getDistanceFromCenterForValue(r.data[e]);o.extend(t,{_datasetIndex:n.index,_index:e,_scale:u,_model:{x:h,y:f,innerRadius:0,outerRadius:i?k:b,startAngle:i&&l.animateRotate?v:x,endAngle:i&&l.animateRotate?v:y,label:o.valueAtIndexOrDefault(d,e,d[e])}}),n.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),e=this.getMeta(),i=0;return o.each(e.data,function(e,n){isNaN(t.data[n])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:o.noop,update:function(t){var e=this,i=e.getMeta(),n=i.dataset,a=i.data,r=n.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),o.extend(i.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:r.tension?r.tension:o.valueOrDefault(s.lineTension,l.tension),backgroundColor:r.backgroundColor?r.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:s.borderWidth||l.borderWidth,borderColor:r.borderColor?r.borderColor:s.borderColor||l.borderColor,fill:r.fill?r.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:r.borderDash?r.borderDash:s.borderDash||l.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),i.dataset.pivot(),o.each(a,function(i,n){e.updateElement(i,n,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,i){var n=this,a=t.custom||{},r=n.getDataset(),s=n.chart.scale,l=n.chart.options.elements.point,u=s.getPointPositionForValue(e,r.data[e]);void 0!==r.radius&&void 0===r.pointRadius&&(r.pointRadius=r.radius),void 0!==r.hitRadius&&void 0===r.pointHitRadius&&(r.pointHitRadius=r.hitRadius),o.extend(t,{_datasetIndex:n.index,_index:e,_scale:s,_model:{x:i?s.xCenter:u.x,y:i?s.yCenter:u.y,tension:a.tension?a.tension:o.valueOrDefault(r.lineTension,n.chart.options.elements.line.tension),radius:a.radius?a.radius:o.valueAtIndexOrDefault(r.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:o.valueAtIndexOrDefault(r.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:o.valueAtIndexOrDefault(r.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:o.valueAtIndexOrDefault(r.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:o.valueAtIndexOrDefault(r.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:o.valueAtIndexOrDefault(r.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();o.each(e.data,function(i,n){var a=i._model,r=o.splineCurve(o.previousItem(e.data,n,!0)._model,a,o.nextItem(e.data,n,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),i.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,a=t._model;a.radius=i.hoverRadius?i.hoverRadius:o.valueAtIndexOrDefault(e.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),a.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:o.valueAtIndexOrDefault(e.pointHoverBackgroundColor,n,o.getHoverColor(a.backgroundColor)),a.borderColor=i.hoverBorderColor?i.hoverBorderColor:o.valueAtIndexOrDefault(e.pointHoverBorderColor,n,o.getHoverColor(a.borderColor)),a.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:o.valueAtIndexOrDefault(e.pointHoverBorderWidth,n,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,a=t._model,r=this.chart.options.elements.point;a.radius=i.radius?i.radius:o.valueAtIndexOrDefault(e.pointRadius,n,r.radius),a.backgroundColor=i.backgroundColor?i.backgroundColor:o.valueAtIndexOrDefault(e.pointBackgroundColor,n,r.backgroundColor),a.borderColor=i.borderColor?i.borderColor:o.valueAtIndexOrDefault(e.pointBorderColor,n,r.borderColor),a.borderWidth=i.borderWidth?i.borderWidth:o.valueAtIndexOrDefault(e.pointBorderWidth,n,r.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,i){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45);n._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:o.noop,onComplete:o.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,i,n){var a,o,r=this.animations;for(e.chart=t,n||(t.animating=!0),a=0,o=r.length;a<o;++a)if(r[a].chart===t)return void(r[a]=e);r.push(e),1===r.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var e=o.findIndex(this.animations,function(e){return e.chart===t});-1!==e&&(this.animations.splice(e,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=o.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),i=0;t.dropFrames>1&&(i=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+i);var n=Date.now();t.dropFrames+=(n-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,i,n=this.animations,a=0;a<n.length;)i=(e=n[a]).chart,e.currentStep=(e.currentStep||0)+t,e.currentStep=Math.min(e.currentStep,e.numSteps),o.callback(e.render,[i,e],i),o.callback(e.onAnimationProgress,[e],i),e.currentStep>=e.numSteps?(o.callback(e.onAnimationComplete,[e],i),i.animating=!1,n.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(28),r=t(30),s=t(48),l=t(31);e.exports=function(t){function e(t){return"top"===t||"bottom"===t}t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(e,i){var o,r,l=this;(r=(o=(o=i)||{}).data=o.data||{}).datasets=r.datasets||[],r.labels=r.labels||[],o.options=a.configMerge(n.global,n[o.type],o.options||{}),i=o;var u=s.acquireContext(e,i),d=u&&u.canvas,c=d&&d.height,h=d&&d.width;l.id=a.uid(),l.ctx=u,l.canvas=d,l.config=i,l.width=h,l.height=c,l.aspectRatio=c?h/c:null,l.options=i.options,l._bufferedRender=!1,l.chart=l,l.controller=l,t.instances[l.id]=l,Object.defineProperty(l,"data",{get:function(){return l.config.data},set:function(t){l.config.data=t}}),u&&d?(l.initialize(),l.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,i=e.options,n=e.canvas,o=i.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(a.getMaximumWidth(n))),s=Math.max(0,Math.floor(o?r/o:a.getMaximumHeight(n)));if((e.width!==r||e.height!==s)&&(n.width=e.width=r,n.height=e.height=s,n.style.width=r+"px",n.style.height=s+"px",a.retinaScale(e,i.devicePixelRatio),!t)){var u={width:r,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},i=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),i&&(i.id=i.id||"scale")},buildOrUpdateScales:function(){var i=this,n=i.options,o=i.scales||{},r=[],s=Object.keys(o).reduce(function(t,e){return t[e]=!1,t},{});n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,l=r.id,u=a.valueOrDefault(r.type,n.dtype);e(r.position)!==e(n.dposition)&&(r.position=n.dposition),s[l]=!0;var d=null;if(l in o&&o[l].type===u)(d=o[l]).options=r,d.ctx=i.ctx,d.chart=i;else{var c=t.scaleService.getScaleConstructor(u);if(!c)return;d=new c({id:l,type:u,options:r,ctx:i.ctx,chart:i}),o[d.id]=d}d.mergeTicksOptions(),n.isDefault&&(i.scale=d)}),a.each(s,function(t,e){t||delete o[e]}),i.scales=o,t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,i=[],n=[];return a.each(e.data.datasets,function(a,o){var r=e.getDatasetMeta(o),s=a.type||e.config.type;if(r.type&&r.type!==s&&(e.destroyDatasetMeta(o),r=e.getDatasetMeta(o)),r.type=s,i.push(r.type),r.controller)r.controller.updateIndex(o),r.controller.linkScales();else{var l=t.controllers[r.type];if(void 0===l)throw new Error('"'+r.type+'" is not a chart type.');r.controller=new l(e,o),n.push(r.controller)}},e),n},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,i){t.getDatasetMeta(i).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(e){var i,n,o=this;if(e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]}),n=(i=o).options,a.each(i.scales,function(t){r.removeBox(i,t)}),n=a.configMerge(t.defaults.global,t.defaults[i.config.type],n),i.options=i.config.options=n,i.ensureScalesHaveIDs(),i.buildOrUpdateScales(),i.tooltip._options=n.tooltips,i.tooltip.initialize(),l._invalidate(o),!1!==l.notify(o,"beforeUpdate")){o.tooltip._data=o.data;var s=o.buildOrUpdateControllers();a.each(o.data.datasets,function(t,e){o.getDatasetMeta(e).controller.buildOrUpdateElements()},o),o.updateLayout(),o.options.animation&&o.options.animation.duration&&a.each(s,function(t){t.reset()}),o.updateDatasets(),o.tooltip.initialize(),o.lastActive=[],l.notify(o,"afterUpdate"),o._bufferedRender?o._bufferedRequest={duration:e.duration,easing:e.easing,lazy:e.lazy}:o.render(e)}},updateLayout:function(){!1!==l.notify(this,"beforeLayout")&&(r.update(this,this.width,this.height),l.notify(this,"afterScaleUpdate"),l.notify(this,"afterLayout"))},updateDatasets:function(){if(!1!==l.notify(this,"beforeDatasetsUpdate")){for(var t=0,e=this.data.datasets.length;t<e;++t)this.updateDataset(t);l.notify(this,"afterDatasetsUpdate")}},updateDataset:function(t){var e=this.getDatasetMeta(t),i={meta:e,index:t};!1!==l.notify(this,"beforeDatasetUpdate",[i])&&(e.controller.update(),l.notify(this,"afterDatasetUpdate",[i]))},render:function(e){var i=this;e&&"object"==typeof e||(e={duration:e,lazy:arguments[1]});var n=e.duration,o=e.lazy;if(!1!==l.notify(i,"beforeRender")){var r=i.options.animation,s=function(t){l.notify(i,"afterRender"),a.callback(r&&r.onComplete,[t],i)};if(r&&(void 0!==n&&0!==n||void 0===n&&0!==r.duration)){var u=new t.Animation({numSteps:(n||r.duration)/16.66,easing:e.easing||r.easing,render:function(t,e){var i=a.easing.effects[e.easing],n=e.currentStep,o=n/e.numSteps;t.draw(i(o),o,n)},onAnimationProgress:r.onProgress,onAnimationComplete:s});t.animationService.addAnimation(i,u,n,o)}else i.draw(),s(new t.Animation({numSteps:0,chart:i}));return i}},draw:function(t){var e=this;e.clear(),a.isNullOrUndef(t)&&(t=1),e.transition(t),!1!==l.notify(e,"beforeDraw",[t])&&(a.each(e.boxes,function(t){t.draw(e.chartArea)},e),e.scale&&e.scale.draw(),e.drawDatasets(t),e._drawTooltip(t),l.notify(e,"afterDraw",[t]))},transition:function(t){for(var e=0,i=(this.data.datasets||[]).length;e<i;++e)this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.transition(t);this.tooltip.transition(t)},drawDatasets:function(t){var e=this;if(!1!==l.notify(e,"beforeDatasetsDraw",[t])){for(var i=(e.data.datasets||[]).length-1;i>=0;--i)e.isDatasetVisible(i)&&e.drawDataset(i,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var i=this.getDatasetMeta(t),n={meta:i,index:t,easingValue:e};!1!==l.notify(this,"beforeDatasetDraw",[n])&&(i.controller.draw(e),l.notify(this,"afterDatasetDraw",[n]))},_drawTooltip:function(t){var e=this.tooltip,i={tooltip:e,easingValue:t};!1!==l.notify(this,"beforeTooltipDraw",[i])&&(e.draw(),l.notify(this,"afterTooltipDraw",[i]))},getElementAtEvent:function(t){return o.modes.single(this,t)},getElementsAtEvent:function(t){return o.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return o.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,i){var n=o.modes[e];return"function"==typeof n?n(this,t,i):[]},getDatasetAtEvent:function(t){return o.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var i=e._meta[this.id];return i||(i=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,i=this.data.datasets.length;e<i;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroyDatasetMeta:function(t){var e=this.id,i=this.data.datasets[t],n=i._meta&&i._meta[e];n&&(n.controller.destroy(),delete i._meta[e])},destroy:function(){var e,i,n=this,o=n.canvas;for(n.stop(),e=0,i=n.data.datasets.length;e<i;++e)n.destroyDatasetMeta(e);o&&(n.unbindEvents(),a.canvas.clear(n),s.releaseContext(n.ctx),n.canvas=null,n.ctx=null),l.notify(n,"destroy"),delete t.instances[n.id]},toBase64Image:function(){return this.canvas.toDataURL.apply(this.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this,e=t._listeners={},i=function(){t.eventHandler.apply(t,arguments)};a.each(t.options.events,function(n){s.addEventListener(t,n,i),e[n]=i}),t.options.responsive&&(i=function(){t.resize()},s.addEventListener(t,"resize",i),e.resize=i)},unbindEvents:function(){var t=this,e=t._listeners;e&&(delete t._listeners,a.each(e,function(e,i){s.removeEventListener(t,i,e)}))},updateHoverStyle:function(t,e,i){var n,a,o,r=i?"setHoverStyle":"removeHoverStyle";for(a=0,o=t.length;a<o;++a)(n=t[a])&&this.getDatasetMeta(n._datasetIndex).controller[r](n)},eventHandler:function(t){var e=this,i=e.tooltip;if(!1!==l.notify(e,"beforeEvent",[t])){e._bufferedRender=!0,e._bufferedRequest=null;var n=e.handleEvent(t);i&&(n=i._start?i.handleEvent(t):n|i.handleEvent(t)),l.notify(e,"afterEvent",[t]);var a=e._bufferedRequest;return a?e.render(a):n&&!e.animating&&(e.stop(),e.render(e.options.hover.animationDuration,!0)),e._bufferedRender=!1,e._bufferedRequest=null,e}},handleEvent:function(t){var e,i=this,n=i.options||{},o=n.hover;return i.lastActive=i.lastActive||[],"mouseout"===t.type?i.active=[]:i.active=i.getElementsAtEventForMode(t,o.mode,o),a.callback(n.onHover||n.hover.onHover,[t.native,i.active],i),"mouseup"!==t.type&&"click"!==t.type||n.onClick&&n.onClick.call(i,t.native,i.active),i.lastActive.length&&i.updateHoverStyle(i.lastActive,o.mode,!1),i.active.length&&o.mode&&i.updateHoverStyle(i.active,o.mode,!0),e=!a.arrayEquals(i.active,i.lastActive),i.lastActive=i.active,e}}),t.Controller=t}},{25:25,28:28,30:30,31:31,45:45,48:48}],24:[function(t,e,i){"use strict";var n=t(45);e.exports=function(t){var e=["push","pop","shift","splice","unshift"];function i(t,i){var n=t._chartjs;if(n){var a=n.listeners,o=a.indexOf(i);-1!==o&&a.splice(o,1),a.length>0||(e.forEach(function(e){delete t[e]}),delete t._chartjs)}}t.DatasetController=function(t,e){this.initialize(t,e)},n.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){this.chart=t,this.index=e,this.linkScales(),this.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),i=t.getDataset();null!==e.xAxisID&&e.xAxisID in t.chart.scales||(e.xAxisID=i.xAxisID||t.chart.options.scales.xAxes[0].id),null!==e.yAxisID&&e.yAxisID in t.chart.scales||(e.yAxisID=i.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&i(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,i=this.getMeta(),n=this.getDataset().data||[],a=i.data;for(t=0,e=n.length;t<e;++t)a[t]=a[t]||this.createMetaData(t);i.dataset=i.dataset||this.createMetaDataset()},addElementAndReset:function(t){var e=this.createMetaData(t);this.getMeta().data.splice(t,0,e),this.updateElement(e,t,!0)},buildOrUpdateElements:function(){var t,a,o=this,r=o.getDataset(),s=r.data||(r.data=[]);o._data!==s&&(o._data&&i(o._data,o),a=o,(t=s)._chartjs?t._chartjs.listeners.push(a):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[a]}}),e.forEach(function(e){var i="onData"+e.charAt(0).toUpperCase()+e.slice(1),a=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value:function(){var e=Array.prototype.slice.call(arguments),o=a.apply(this,e);return n.each(t._chartjs.listeners,function(t){"function"==typeof t[i]&&t[i].apply(t,e)}),o}})})),o._data=s),o.resyncElements()},update:n.noop,transition:function(t){for(var e=this.getMeta(),i=e.data||[],n=i.length,a=0;a<n;++a)i[a].transition(t);e.dataset&&e.dataset.transition(t)},draw:function(){var t=this.getMeta(),e=t.data||[],i=e.length,n=0;for(t.dataset&&t.dataset.draw();n<i;++n)e[n].draw()},removeHoverStyle:function(t,e){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=n.valueAtIndexOrDefault,s=t._model;s.backgroundColor=o.backgroundColor?o.backgroundColor:r(i.backgroundColor,a,e.backgroundColor),s.borderColor=o.borderColor?o.borderColor:r(i.borderColor,a,e.borderColor),s.borderWidth=o.borderWidth?o.borderWidth:r(i.borderWidth,a,e.borderWidth)},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},o=n.valueAtIndexOrDefault,r=n.getHoverColor,s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(e.hoverBackgroundColor,i,r(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(e.hoverBorderColor,i,r(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(e.hoverBorderWidth,i,s.borderWidth)},resyncElements:function(){var t=this.getMeta(),e=this.getDataset().data,i=t.data.length,n=e.length;n<i?t.data.splice(n,i-n):n>i&&this.insertElements(i,n-i)},insertElements:function(t,e){for(var i=0;i<e;++i)this.addElementAndReset(t+i)},onDataPush:function(){this.insertElements(this.getDataset().data.length-1,arguments.length)},onDataPop:function(){this.getMeta().data.pop()},onDataShift:function(){this.getMeta().data.shift()},onDataSplice:function(t,e){this.getMeta().data.splice(t,e),this.insertElements(t,arguments.length-2)},onDataUnshift:function(){this.insertElements(0,arguments.length)}}),t.DatasetController.extend=n.inherits}},{45:45}],25:[function(t,e,i){"use strict";var n=t(45);e.exports={_set:function(t,e){return n.merge(this[t]||(this[t]={}),e)}}},{45:45}],26:[function(t,e,i){"use strict";var n=t(3),a=t(45);var o=function(t){a.extend(this,t),this.initialize.apply(this,arguments)};a.extend(o.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=a.clone(t._model)),t._start={},t},transition:function(t){var e=this,i=e._model,a=e._start,o=e._view;return i&&1!==t?(o||(o=e._view={}),a||(a=e._start={}),function(t,e,i,a){var o,r,s,l,u,d,c,h,f,g=Object.keys(i);for(o=0,r=g.length;o<r;++o)if(d=i[s=g[o]],e.hasOwnProperty(s)||(e[s]=d),(l=e[s])!==d&&"_"!==s[0]){if(t.hasOwnProperty(s)||(t[s]=l),(c=typeof d)==typeof(u=t[s]))if("string"===c){if((h=n(u)).valid&&(f=n(d)).valid){e[s]=f.mix(h,a).rgbString();continue}}else if("number"===c&&isFinite(u)&&isFinite(d)){e[s]=u+(d-u)*a;continue}e[s]=d}}(a,o,i,t),e):(e._view=i,e._start=null,e)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return a.isNumber(this._model.x)&&a.isNumber(this._model.y)}}),o.extend=a.inherits,e.exports=o},{3:3,45:45}],27:[function(t,e,i){"use strict";var n=t(3),a=t(25),o=t(45);e.exports=function(t){function e(t,e,i){var n;return"string"==typeof t?(n=parseInt(t,10),-1!==t.indexOf("%")&&(n=n/100*e.parentNode[i])):n=t,n}function i(t){return null!=t&&"none"!==t}function r(t,n,a){var o=document.defaultView,r=t.parentNode,s=o.getComputedStyle(t)[n],l=o.getComputedStyle(r)[n],u=i(s),d=i(l),c=Number.POSITIVE_INFINITY;return u||d?Math.min(u?e(s,t,a):c,d?e(l,r,a):c):"none"}o.configMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,i,n,a){var r=i[e]||{},s=n[e];"scales"===e?i[e]=o.scaleMerge(r,s):"scale"===e?i[e]=o.merge(r,[t.scaleService.getScaleDefaults(s.type),s]):o._merger(e,i,n,a)}})},o.scaleMerge=function(){return o.merge(o.clone(arguments[0]),[].slice.call(arguments,1),{merger:function(e,i,n,a){if("xAxes"===e||"yAxes"===e){var r,s,l,u=n[e].length;for(i[e]||(i[e]=[]),r=0;r<u;++r)l=n[e][r],s=o.valueOrDefault(l.type,"xAxes"===e?"category":"linear"),r>=i[e].length&&i[e].push({}),!i[e][r].type||l.type&&l.type!==i[e][r].type?o.merge(i[e][r],[t.scaleService.getScaleDefaults(s),l]):o.merge(i[e][r],l)}else o._merger(e,i,n,a)}})},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var i=[];return o.each(t,function(t){e(t)&&i.push(t)}),i},o.findIndex=Array.prototype.findIndex?function(t,e,i){return t.findIndex(e,i)}:function(t,e,i){i=void 0===i?t:i;for(var n=0,a=t.length;n<a;++n)if(e.call(i,t[n],n,t))return n;return-1},o.findNextWhere=function(t,e,i){o.isNullOrUndef(i)&&(i=-1);for(var n=i+1;n<t.length;n++){var a=t[n];if(e(a))return a}},o.findPreviousWhere=function(t,e,i){o.isNullOrUndef(i)&&(i=t.length);for(var n=i-1;n>=0;n--){var a=t[n];if(e(a))return a}},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,i){return Math.abs(t-e)<i},o.almostWhole=function(t,e){var i=Math.round(t);return i-e<t&&i+e>t},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0===(t=+t)||isNaN(t)?t:t>0?1:-1},o.log10=Math.log10?function(t){return Math.log10(t)}:function(t){var e=Math.log(t)*Math.LOG10E,i=Math.round(e);return t===Math.pow(10,i)?i:e},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var i=e.x-t.x,n=e.y-t.y,a=Math.sqrt(i*i+n*n),o=Math.atan2(n,i);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},o.aliasPixel=function(t){return t%2==0?0:.5},o.splineCurve=function(t,e,i,n){var a=t.skip?e:t,o=e,r=i.skip?e:i,s=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),l=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),u=s/(s+l),d=l/(s+l),c=n*(u=isNaN(u)?0:u),h=n*(d=isNaN(d)?0:d);return{previous:{x:o.x-c*(r.x-a.x),y:o.y-c*(r.y-a.y)},next:{x:o.x+h*(r.x-a.x),y:o.y+h*(r.y-a.y)}}},o.EPSILON=Number.EPSILON||1e-14,o.splineCurveMonotone=function(t){var e,i,n,a,r,s,l,u,d,c=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),h=c.length;for(e=0;e<h;++e)if(!(n=c[e]).model.skip){if(i=e>0?c[e-1]:null,(a=e<h-1?c[e+1]:null)&&!a.model.skip){var f=a.model.x-n.model.x;n.deltaK=0!==f?(a.model.y-n.model.y)/f:0}!i||i.model.skip?n.mK=n.deltaK:!a||a.model.skip?n.mK=i.deltaK:this.sign(i.deltaK)!==this.sign(n.deltaK)?n.mK=0:n.mK=(i.deltaK+n.deltaK)/2}for(e=0;e<h-1;++e)n=c[e],a=c[e+1],n.model.skip||a.model.skip||(o.almostEquals(n.deltaK,0,this.EPSILON)?n.mK=a.mK=0:(r=n.mK/n.deltaK,s=a.mK/n.deltaK,(u=Math.pow(r,2)+Math.pow(s,2))<=9||(l=3/Math.sqrt(u),n.mK=r*l*n.deltaK,a.mK=s*l*n.deltaK)));for(e=0;e<h;++e)(n=c[e]).model.skip||(i=e>0?c[e-1]:null,a=e<h-1?c[e+1]:null,i&&!i.model.skip&&(d=(n.model.x-i.model.x)/3,n.model.controlPointPreviousX=n.model.x-d,n.model.controlPointPreviousY=n.model.y-d*n.mK),a&&!a.model.skip&&(d=(a.model.x-n.model.x)/3,n.model.controlPointNextX=n.model.x+d,n.model.controlPointNextY=n.model.y+d*n.mK))},o.nextItem=function(t,e,i){return i?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,i){return i?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},o.niceNum=function(t,e){var i=Math.floor(o.log10(t)),n=t/Math.pow(10,i);return(e?n<1.5?1:n<3?2:n<7?5:10:n<=1?1:n<=2?2:n<=5?5:10)*Math.pow(10,i)},o.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},o.getRelativePosition=function(t,e){var i,n,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,s=r.getBoundingClientRect(),l=a.touches;l&&l.length>0?(i=l[0].clientX,n=l[0].clientY):(i=a.clientX,n=a.clientY);var u=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return{x:i=Math.round((i-s.left-u)/f*r.width/e.currentDevicePixelRatio),y:n=Math.round((n-s.top-d)/g*r.height/e.currentDevicePixelRatio)}},o.getConstraintWidth=function(t){return r(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return r(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var i=parseInt(o.getStyle(e,"padding-left"),10),n=parseInt(o.getStyle(e,"padding-right"),10),a=e.clientWidth-i-n,r=o.getConstraintWidth(t);return isNaN(r)?a:Math.min(a,r)},o.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var i=parseInt(o.getStyle(e,"padding-top"),10),n=parseInt(o.getStyle(e,"padding-bottom"),10),a=e.clientHeight-i-n,r=o.getConstraintHeight(t);return isNaN(r)?a:Math.min(a,r)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t,e){var i=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==i){var n=t.canvas,a=t.height,o=t.width;n.height=a*i,n.width=o*i,t.ctx.scale(i,i),n.style.height||n.style.width||(n.style.height=a+"px",n.style.width=o+"px")}},o.fontString=function(t,e,i){return e+" "+t+"px "+i},o.longestText=function(t,e,i,n){var a=(n=n||{}).data=n.data||{},r=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(a=n.data={},r=n.garbageCollect=[],n.font=e),t.font=e;var s=0;o.each(i,function(e){null!=e&&!0!==o.isArray(e)?s=o.measureText(t,a,r,s,e):o.isArray(e)&&o.each(e,function(e){null==e||o.isArray(e)||(s=o.measureText(t,a,r,s,e))})});var l=r.length/2;if(l>i.length){for(var u=0;u<l;u++)delete a[r[u]];r.splice(0,l)}return s},o.measureText=function(t,e,i,n,a){var o=e[a];return o||(o=e[a]=t.measureText(a).width,i.push(a)),o>n&&(n=o),n},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.color=n?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),n(t)}:function(t){return console.error("Color.js not found!"),t},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{25:25,3:3,45:45}],28:[function(t,e,i){"use strict";var n=t(45);function a(t,e){return t.native?{x:t.x,y:t.y}:n.getRelativePosition(t,e)}function o(t,e){var i,n,a,o,r;for(n=0,o=t.data.datasets.length;n<o;++n)if(t.isDatasetVisible(n))for(a=0,r=(i=t.getDatasetMeta(n)).data.length;a<r;++a){var s=i.data[a];s._view.skip||e(s)}}function r(t,e){var i=[];return o(t,function(t){t.inRange(e.x,e.y)&&i.push(t)}),i}function s(t,e,i,n){var a=Number.POSITIVE_INFINITY,r=[];return o(t,function(t){if(!i||t.inRange(e.x,e.y)){var o=t.getCenterPoint(),s=n(e,o);s<a?(r=[t],a=s):s===a&&r.push(t)}}),r}function l(t){var e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,n){var a=e?Math.abs(t.x-n.x):0,o=i?Math.abs(t.y-n.y):0;return Math.sqrt(Math.pow(a,2)+Math.pow(o,2))}}function u(t,e,i){var n=a(e,t);i.axis=i.axis||"x";var o=l(i.axis),u=i.intersect?r(t,n):s(t,n,!1,o),d=[];return u.length?(t.data.datasets.forEach(function(e,i){if(t.isDatasetVisible(i)){var n=t.getDatasetMeta(i).data[u[0]._index];n&&!n._view.skip&&d.push(n)}}),d):[]}e.exports={modes:{single:function(t,e){var i=a(e,t),n=[];return o(t,function(t){if(t.inRange(i.x,i.y))return n.push(t),n}),n.slice(0,1)},label:u,index:u,dataset:function(t,e,i){var n=a(e,t);i.axis=i.axis||"xy";var o=l(i.axis),u=i.intersect?r(t,n):s(t,n,!1,o);return u.length>0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return u(t,e,{intersect:!1})},point:function(t,e){return r(t,a(e,t))},nearest:function(t,e,i){var n=a(e,t);i.axis=i.axis||"xy";var o=l(i.axis),r=s(t,n,i.intersect,o);return r.length>1&&r.sort(function(t,e){var i=t.getArea()-e.getArea();return 0===i&&(i=t._datasetIndex-e._datasetIndex),i}),r.slice(0,1)},x:function(t,e,i){var n=a(e,t),r=[],s=!1;return o(t,function(t){t.inXRange(n.x)&&r.push(t),t.inRange(n.x,n.y)&&(s=!0)}),i.intersect&&!s&&(r=[]),r},y:function(t,e,i){var n=a(e,t),r=[],s=!1;return o(t,function(t){t.inYRange(n.y)&&r.push(t),t.inRange(n.x,n.y)&&(s=!0)}),i.intersect&&!s&&(r=[]),r}}}},{45:45}],29:[function(t,e,i){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,i){"use strict";var n=t(45);function a(t,e){return n.where(t,function(t){return t.position===e})}function o(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,i){var n=e?i:t,a=e?t:i;return n.weight===a.weight?n._tmpIndex_-a._tmpIndex_:n.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}e.exports={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure:function(t,e,i){for(var n,a=["fullWidth","position","weight"],o=a.length,r=0;r<o;++r)n=a[r],i.hasOwnProperty(n)&&(e[n]=i[n])},update:function(t,e,i){if(t){var r=t.options.layout||{},s=n.options.toPadding(r.padding),l=s.left,u=s.right,d=s.top,c=s.bottom,h=a(t.boxes,"left"),f=a(t.boxes,"right"),g=a(t.boxes,"top"),p=a(t.boxes,"bottom"),m=a(t.boxes,"chartArea");o(h,!0),o(f,!1),o(g,!0),o(p,!1);var v=e-l-u,b=i-d-c,x=b/2,y=(e-v/2)/(h.length+f.length),k=(i-x)/(g.length+p.length),M=v,w=b,S=[];n.each(h.concat(f,g,p),function(t){var e,i=t.isHorizontal();i?(e=t.update(t.fullWidth?v:M,k),w-=e.height):(e=t.update(y,w),M-=e.width),S.push({horizontal:i,minSize:e,box:t})});var C=0,_=0,D=0,I=0;n.each(g.concat(p),function(t){if(t.getPadding){var e=t.getPadding();C=Math.max(C,e.left),_=Math.max(_,e.right)}}),n.each(h.concat(f),function(t){if(t.getPadding){var e=t.getPadding();D=Math.max(D,e.top),I=Math.max(I,e.bottom)}});var P=l,A=u,T=d,F=c;n.each(h.concat(f),N),n.each(h,function(t){P+=t.width}),n.each(f,function(t){A+=t.width}),n.each(g.concat(p),N),n.each(g,function(t){T+=t.height}),n.each(p,function(t){F+=t.height}),n.each(h.concat(f),function(t){var e=n.findNextWhere(S,function(e){return e.box===t}),i={left:0,right:0,top:T,bottom:F};e&&t.update(e.minSize.width,w,i)}),P=l,A=u,T=d,F=c,n.each(h,function(t){P+=t.width}),n.each(f,function(t){A+=t.width}),n.each(g,function(t){T+=t.height}),n.each(p,function(t){F+=t.height});var O=Math.max(C-P,0);P+=O,A+=Math.max(_-A,0);var R=Math.max(D-T,0);T+=R,F+=Math.max(I-F,0);var L=i-T-F,z=e-P-A;z===M&&L===w||(n.each(h,function(t){t.height=L}),n.each(f,function(t){t.height=L}),n.each(g,function(t){t.fullWidth||(t.width=z)}),n.each(p,function(t){t.fullWidth||(t.width=z)}),w=L,M=z);var B=l+O,W=d+R;n.each(h.concat(g),V),B+=M,W+=w,n.each(f,V),n.each(p,V),t.chartArea={left:P,top:T,right:P+M,bottom:T+w},n.each(m,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(M,w)})}function N(t){var e=n.findNextWhere(S,function(e){return e.box===t});if(e)if(t.isHorizontal()){var i={left:Math.max(P,C),right:Math.max(A,_),top:0,bottom:0};t.update(t.fullWidth?v:M,b/2,i)}else t.update(e.minSize.width,w)}function V(t){t.isHorizontal()?(t.left=t.fullWidth?l:P,t.right=t.fullWidth?e-u:P+M,t.top=W,t.bottom=W+t.height,W=t.bottom):(t.left=B,t.right=B+t.width,t.top=T,t.bottom=T+w,B=t.right)}}}},{45:45}],31:[function(t,e,i){"use strict";var n=t(25),a=t(45);n._set("global",{plugins:{}}),e.exports={_plugins:[],_cacheId:0,register:function(t){var e=this._plugins;[].concat(t).forEach(function(t){-1===e.indexOf(t)&&e.push(t)}),this._cacheId++},unregister:function(t){var e=this._plugins;[].concat(t).forEach(function(t){var i=e.indexOf(t);-1!==i&&e.splice(i,1)}),this._cacheId++},clear:function(){this._plugins=[],this._cacheId++},count:function(){return this._plugins.length},getAll:function(){return this._plugins},notify:function(t,e,i){var n,a,o,r,s,l=this.descriptors(t),u=l.length;for(n=0;n<u;++n)if("function"==typeof(s=(o=(a=l[n]).plugin)[e])&&((r=[t].concat(i||[])).push(a.options),!1===s.apply(o,r)))return!1;return!0},descriptors:function(t){var e=t.$plugins||(t.$plugins={});if(e.id===this._cacheId)return e.descriptors;var i=[],o=[],r=t&&t.config||{},s=r.options&&r.options.plugins||{};return this._plugins.concat(r.plugins||[]).forEach(function(t){if(-1===i.indexOf(t)){var e=t.id,r=s[e];!1!==r&&(!0===r&&(r=a.clone(n.global.plugins[e])),i.push(t),o.push({plugin:t,options:r||{}}))}}),e.descriptors=o,e.id=this._cacheId,o},_invalidate:function(t){delete t.$plugins}}},{25:25,45:45}],32:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=t(34);function s(t){var e,i,n=[];for(e=0,i=t.length;e<i;++e)n.push(t[e].label);return n}function l(t,e,i){var n=t.getPixelForTick(e);return i&&(n-=0===e?(t.getPixelForTick(1)-n)/2:(n-t.getPixelForTick(e-1))/2),n}n._set("scale",{display:!0,position:"left",offset:!1,gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",zeroLineBorderDash:[],zeroLineBorderDashOffset:0,offsetGridLines:!1,borderDash:[],borderDashOffset:0},scaleLabel:{display:!1,labelString:"",lineHeight:1.2,padding:{top:4,bottom:4}},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:0,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:r.formatters.values,minor:{},major:{}}}),e.exports=function(t){function e(t,e,i){return o.isArray(e)?o.longestText(t,i,e):t.measureText(e).width}function i(t){var e=o.valueOrDefault,i=n.global,a=e(t.fontSize,i.defaultFontSize),r=e(t.fontStyle,i.defaultFontStyle),s=e(t.fontFamily,i.defaultFontFamily);return{size:a,style:r,family:s,font:o.fontString(a,r,s)}}function r(t){return o.options.toLineHeight(o.valueOrDefault(t.lineHeight,1.2),o.valueOrDefault(t.fontSize,n.global.defaultFontSize))}t.Scale=a.extend({getPadding:function(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}},getTicks:function(){return this._ticks},mergeTicksOptions:function(){var t=this.options.ticks;for(var e in!1===t.minor&&(t.minor={display:!1}),!1===t.major&&(t.major={display:!1}),t)"major"!==e&&"minor"!==e&&(void 0===t.minor[e]&&(t.minor[e]=t[e]),void 0===t.major[e]&&(t.major[e]=t[e]))},beforeUpdate:function(){o.callback(this.options.beforeUpdate,[this])},update:function(t,e,i){var n,a,r,s,l,u,d=this;for(d.beforeUpdate(),d.maxWidth=t,d.maxHeight=e,d.margins=o.extend({left:0,right:0,top:0,bottom:0},i),d.longestTextCache=d.longestTextCache||{},d.beforeSetDimensions(),d.setDimensions(),d.afterSetDimensions(),d.beforeDataLimits(),d.determineDataLimits(),d.afterDataLimits(),d.beforeBuildTicks(),l=d.buildTicks()||[],d.afterBuildTicks(),d.beforeTickToLabelConversion(),r=d.convertTicksToLabels(l)||d.ticks,d.afterTickToLabelConversion(),d.ticks=r,n=0,a=r.length;n<a;++n)s=r[n],(u=l[n])?u.label=s:l.push(u={label:s,major:!1});return d._ticks=l,d.beforeCalculateTickRotation(),d.calculateTickRotation(),d.afterCalculateTickRotation(),d.beforeFit(),d.fit(),d.afterFit(),d.afterUpdate(),d.minSize},afterUpdate:function(){o.callback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){o.callback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){o.callback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){o.callback(this.options.beforeDataLimits,[this])},determineDataLimits:o.noop,afterDataLimits:function(){o.callback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){o.callback(this.options.beforeBuildTicks,[this])},buildTicks:o.noop,afterBuildTicks:function(){o.callback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){o.callback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this.options.ticks;this.ticks=this.ticks.map(t.userCallback||t.callback,this)},afterTickToLabelConversion:function(){o.callback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){o.callback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var t=this,e=t.ctx,n=t.options.ticks,a=s(t._ticks),r=i(n);e.font=r.font;var l=n.minRotation||0;if(a.length&&t.options.display&&t.isHorizontal())for(var u,d=o.longestText(e,r.font,a,t.longestTextCache),c=d,h=t.getPixelForTick(1)-t.getPixelForTick(0)-6;c>h&&l<n.maxRotation;){var f=o.toRadians(l);if(u=Math.cos(f),Math.sin(f)*d>t.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){o.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){o.callback(this.options.beforeFit,[this])},fit:function(){var t=this,n=t.minSize={width:0,height:0},a=s(t._ticks),l=t.options,u=l.ticks,d=l.scaleLabel,c=l.gridLines,h=l.display,f=t.isHorizontal(),g=i(u),p=l.gridLines.tickMarkLength;if(n.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?p:0,n.height=f?h&&c.drawTicks?p:0:t.maxHeight,d.display&&h){var m=r(d)+o.options.toPadding(d.padding).height;f?n.height+=m:n.width+=m}if(u.display&&h){var v=o.longestText(t.ctx,g.font,a,t.longestTextCache),b=o.numberOfLabelLines(a),x=.5*g.size,y=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var k=o.toRadians(t.labelRotation),M=Math.cos(k),w=Math.sin(k)*v+g.size*b+x*(b-1)+x;n.height=Math.min(t.maxHeight,n.height+w+y),t.ctx.font=g.font;var S=e(t.ctx,a[0],g.font),C=e(t.ctx,a[a.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===l.position?M*S+3:M*x+3,t.paddingRight="bottom"===l.position?M*x+3:M*C+3):(t.paddingLeft=S/2+3,t.paddingRight=C/2+3)}else u.mirror?v=0:v+=y+x,n.width=Math.min(t.maxWidth,n.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=n.width,t.height=n.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){o.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(o.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:o.noop,getPixelForValue:o.noop,getValueForPixel:o.noop,getPixelForTick:function(t){var e=this,i=e.options.offset;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(i?0:1),1),a=n*t+e.paddingLeft;i&&(a+=n/2);var o=e.left+Math.round(a);return o+=e.isFullWidth()?e.margins.left:0}var r=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(r/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,n=e.left+Math.round(i);return n+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,i,n,a,r=this,s=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=o.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),s&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),i=0;i<u;i++)n=t[i],(e>1&&i%e>0||i%e==0&&i+e>=u)&&i!==u-1&&delete n.label,f.push(n);return f},draw:function(t){var e=this,a=e.options;if(a.display){var s=e.ctx,u=n.global,d=a.ticks.minor,c=a.ticks.major||d,h=a.gridLines,f=a.scaleLabel,g=0!==e.labelRotation,p=e.isHorizontal(),m=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=o.valueOrDefault(d.fontColor,u.defaultFontColor),b=i(d),x=o.valueOrDefault(c.fontColor,u.defaultFontColor),y=i(c),k=h.drawTicks?h.tickMarkLength:0,M=o.valueOrDefault(f.fontColor,u.defaultFontColor),w=i(f),S=o.options.toPadding(f.padding),C=o.toRadians(e.labelRotation),_=[],D=e.options.gridLines.lineWidth,I="right"===a.position?e.right:e.right-D-k,P="right"===a.position?e.right+k:e.right,A="bottom"===a.position?e.top+D:e.bottom-k-D,T="bottom"===a.position?e.top+D+k:e.bottom+D;if(o.each(m,function(i,n){if(!o.isNullOrUndef(i.label)){var r,s,c,f,v,b,x,y,M,w,S,F,O,R,L=i.label;n===e.zeroLineIndex&&a.offset===h.offsetGridLines?(r=h.zeroLineWidth,s=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(r=o.valueAtIndexOrDefault(h.lineWidth,n),s=o.valueAtIndexOrDefault(h.color,n),c=o.valueOrDefault(h.borderDash,u.borderDash),f=o.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var z="middle",B="middle",W=d.padding;if(p){var N=k+W;"bottom"===a.position?(B=g?"middle":"top",z=g?"right":"center",R=e.top+N):(B=g?"middle":"bottom",z=g?"left":"center",R=e.bottom-N);var V=l(e,n,h.offsetGridLines&&m.length>1);V<e.left&&(s="rgba(0,0,0,0)"),V+=o.aliasPixel(r),O=e.getPixelForTick(n)+d.labelOffset,v=x=M=S=V,b=A,y=T,w=t.top,F=t.bottom+D}else{var E,H="left"===a.position;d.mirror?(z=H?"left":"right",E=W):(z=H?"right":"left",E=k+W),O=H?e.right-E:e.left+E;var j=l(e,n,h.offsetGridLines&&m.length>1);j<e.top&&(s="rgba(0,0,0,0)"),j+=o.aliasPixel(r),R=e.getPixelForTick(n)+d.labelOffset,v=I,x=P,M=t.left,S=t.right+D,b=y=w=F=j}_.push({tx1:v,ty1:b,tx2:x,ty2:y,x1:M,y1:w,x2:S,y2:F,labelX:O,labelY:R,glWidth:r,glColor:s,glBorderDash:c,glBorderDashOffset:f,rotation:-1*C,label:L,major:i.major,textBaseline:B,textAlign:z})}}),o.each(_,function(t){if(h.display&&(s.save(),s.lineWidth=t.glWidth,s.strokeStyle=t.glColor,s.setLineDash&&(s.setLineDash(t.glBorderDash),s.lineDashOffset=t.glBorderDashOffset),s.beginPath(),h.drawTicks&&(s.moveTo(t.tx1,t.ty1),s.lineTo(t.tx2,t.ty2)),h.drawOnChartArea&&(s.moveTo(t.x1,t.y1),s.lineTo(t.x2,t.y2)),s.stroke(),s.restore()),d.display){s.save(),s.translate(t.labelX,t.labelY),s.rotate(t.rotation),s.font=t.major?y.font:b.font,s.fillStyle=t.major?x:v,s.textBaseline=t.textBaseline,s.textAlign=t.textAlign;var i=t.label;if(o.isArray(i))for(var n=i.length,a=1.5*b.size,r=e.isHorizontal()?0:-a*(n-1)/2,l=0;l<n;++l)s.fillText(""+i[l],0,r),r+=a;else s.fillText(i,0,0);s.restore()}}),f.display){var F,O,R=0,L=r(f)/2;if(p)F=e.left+(e.right-e.left)/2,O="bottom"===a.position?e.bottom-L-S.bottom:e.top+L+S.top;else{var z="left"===a.position;F=z?e.left+L+S.top:e.right-L-S.top,O=e.top+(e.bottom-e.top)/2,R=z?-.5*Math.PI:.5*Math.PI}s.save(),s.translate(F,O),s.rotate(R),s.textAlign="center",s.textBaseline="middle",s.fillStyle=M,s.font=w.font,s.fillText(f.labelString,0,0),s.restore()}if(h.drawBorder){s.lineWidth=o.valueAtIndexOrDefault(h.lineWidth,0),s.strokeStyle=o.valueAtIndexOrDefault(h.color,0);var B=e.left,W=e.right+D,N=e.top,V=e.bottom+D,E=o.aliasPixel(s.lineWidth);p?(N=V="top"===a.position?e.bottom:e.top,N+=E,V+=E):(B=W="left"===a.position?e.right:e.left,B+=E,W+=E),s.beginPath(),s.moveTo(B,N),s.lineTo(W,V),s.stroke()}}}})}},{25:25,26:26,34:34,45:45}],33:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(30);e.exports=function(t){t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,e,i){this.constructors[t]=e,this.defaults[t]=a.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(t){return this.defaults.hasOwnProperty(t)?a.merge({},[n.scale,this.defaults[t]]):{}},updateScaleDefaults:function(t,e){this.defaults.hasOwnProperty(t)&&(this.defaults[t]=a.extend(this.defaults[t],e))},addScalesToLayout:function(t){a.each(t.scales,function(e){e.fullWidth=e.options.fullWidth,e.position=e.options.position,e.weight=e.options.weight,o.addBox(t,e)})}}}},{25:25,30:30,45:45}],34:[function(t,e,i){"use strict";var n=t(45);e.exports={formatters:{values:function(t){return n.isArray(t)?t:""+t},linear:function(t,e,i){var a=i.length>3?i[2]-i[1]:i[1]-i[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=n.log10(Math.abs(a)),r="";if(0!==t){var s=-1*Math.floor(o);s=Math.max(Math.min(s,20),0),r=t.toFixed(s)}else r="0";return r},logarithmic:function(t,e,i){var a=t/Math.pow(10,Math.floor(n.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===i.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45);n._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:o.noop,title:function(t,e){var i="",n=e.labels,a=n?n.length:0;if(t.length>0){var o=t[0];o.xLabel?i=o.xLabel:a>0&&o.index<a&&(i=n[o.index])}return i},afterTitle:o.noop,beforeBody:o.noop,beforeLabel:o.noop,label:function(t,e){var i=e.datasets[t.datasetIndex].label||"";return i&&(i+=": "),i+=t.yLabel},labelColor:function(t,e){var i=e.getDatasetMeta(t.datasetIndex).data[t.index]._view;return{borderColor:i.borderColor,backgroundColor:i.backgroundColor}},labelTextColor:function(){return this._options.bodyFontColor},afterLabel:o.noop,afterBody:o.noop,beforeFooter:o.noop,footer:o.noop,afterFooter:o.noop}}}),e.exports=function(t){function e(t,e){var i=o.color(t);return i.alpha(e*i.alpha()).rgbaString()}function i(t,e){return e&&(o.isArray(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function r(t){var e=n.global,i=o.valueOrDefault;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,bodyFontColor:t.bodyFontColor,_bodyFontFamily:i(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:i(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:i(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:i(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:i(t.titleFontStyle,e.defaultFontStyle),titleFontSize:i(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:i(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:i(t.footerFontStyle,e.defaultFontStyle),footerFontSize:i(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}t.Tooltip=a.extend({initialize:function(){this._model=r(this._options),this._lastActive=[]},getTitle:function(){var t=this._options.callbacks,e=t.beforeTitle.apply(this,arguments),n=t.title.apply(this,arguments),a=t.afterTitle.apply(this,arguments),o=[];return o=i(o=i(o=i(o,e),n),a)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var n=this,a=n._options.callbacks,r=[];return o.each(t,function(t){var o={before:[],lines:[],after:[]};i(o.before,a.beforeLabel.call(n,t,e)),i(o.lines,a.label.call(n,t,e)),i(o.after,a.afterLabel.call(n,t,e)),r.push(o)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return o.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this._options.callbacks,e=t.beforeFooter.apply(this,arguments),n=t.footer.apply(this,arguments),a=t.afterFooter.apply(this,arguments),o=[];return o=i(o=i(o=i(o,e),n),a)},update:function(e){var i,n,a,s,l,u,d,c,h,f,g,p,m,v,b,x,y,k,M,w,S=this,C=S._options,_=S._model,D=S._model=r(C),I=S._active,P=S._data,A={xAlign:_.xAlign,yAlign:_.yAlign},T={x:_.x,y:_.y},F={width:_.width,height:_.height},O={x:_.caretX,y:_.caretY};if(I.length){D.opacity=1;var R=[],L=[];O=t.Tooltip.positioners[C.position].call(S,I,S._eventPosition);var z=[];for(i=0,n=I.length;i<n;++i)z.push((x=I[i],y=void 0,k=void 0,void 0,void 0,y=x._xScale,k=x._yScale||x._scale,M=x._index,w=x._datasetIndex,{xLabel:y?y.getLabelForIndex(M,w):"",yLabel:k?k.getLabelForIndex(M,w):"",index:M,datasetIndex:w,x:x._model.x,y:x._model.y}));C.filter&&(z=z.filter(function(t){return C.filter(t,P)})),C.itemSort&&(z=z.sort(function(t,e){return C.itemSort(t,e,P)})),o.each(z,function(t){R.push(C.callbacks.labelColor.call(S,t,S._chart)),L.push(C.callbacks.labelTextColor.call(S,t,S._chart))}),D.title=S.getTitle(z,P),D.beforeBody=S.getBeforeBody(z,P),D.body=S.getBody(z,P),D.afterBody=S.getAfterBody(z,P),D.footer=S.getFooter(z,P),D.x=Math.round(O.x),D.y=Math.round(O.y),D.caretPadding=C.caretPadding,D.labelColors=R,D.labelTextColors=L,D.dataPoints=z,A=function(t,e){var i,n,a,o,r,s=t._model,l=t._chart,u=t._chart.chartArea,d="center",c="center";s.y<e.height?c="top":s.y>l.height-e.height&&(c="bottom");var h=(u.left+u.right)/2,f=(u.top+u.bottom)/2;"center"===c?(i=function(t){return t<=h},n=function(t){return t>h}):(i=function(t){return t<=e.width/2},n=function(t){return t>=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},o=function(t){return t-e.width-s.caretSize-s.caretPadding<0},r=function(t){return t<=f?"top":"bottom"},i(s.x)?(d="left",a(s.x)&&(d="center",c=r(s.y))):n(s.x)&&(d="right",o(s.x)&&(d="center",c=r(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:c}}(this,F=function(t,e){var i=t._chart.ctx,n=2*e.yPadding,a=0,r=e.body,s=r.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);s+=e.beforeBody.length+e.afterBody.length;var l=e.title.length,u=e.footer.length,d=e.titleFontSize,c=e.bodyFontSize,h=e.footerFontSize;n+=l*d,n+=l?(l-1)*e.titleSpacing:0,n+=l?e.titleMarginBottom:0,n+=s*c,n+=s?(s-1)*e.bodySpacing:0,n+=u?e.footerMarginTop:0,n+=u*h,n+=u?(u-1)*e.footerSpacing:0;var f=0,g=function(t){a=Math.max(a,i.measureText(t).width+f)};return i.font=o.fontString(d,e._titleFontStyle,e._titleFontFamily),o.each(e.title,g),i.font=o.fontString(c,e._bodyFontStyle,e._bodyFontFamily),o.each(e.beforeBody.concat(e.afterBody),g),f=e.displayColors?c+2:0,o.each(r,function(t){o.each(t.before,g),o.each(t.lines,g),o.each(t.after,g)}),f=0,i.font=o.fontString(h,e._footerFontStyle,e._footerFontFamily),o.each(e.footer,g),{width:a+=2*e.xPadding,height:n}}(this,D)),a=D,s=F,l=A,u=S._chart,d=a.x,c=a.y,h=a.caretSize,f=a.caretPadding,g=a.cornerRadius,p=l.xAlign,m=l.yAlign,v=h+f,b=g+f,"right"===p?d-=s.width:"center"===p&&((d-=s.width/2)+s.width>u.width&&(d=u.width-s.width),d<0&&(d=0)),"top"===m?c+=v:c-="bottom"===m?s.height+v:s.height/2,"center"===m?"left"===p?d+=v:"right"===p&&(d-=v):"left"===p?d-=b:"right"===p&&(d+=b),T={x:d,y:c}}else D.opacity=0;return D.xAlign=A.xAlign,D.yAlign=A.yAlign,D.x=T.x,D.y=T.y,D.width=F.width,D.height=F.height,D.caretX=O.x,D.caretY=O.y,S._model=D,e&&C.custom&&C.custom.call(S,D),S},drawCaret:function(t,e){var i=this._chart.ctx,n=this._view,a=this.getCaretPosition(t,e,n);i.lineTo(a.x1,a.y1),i.lineTo(a.x2,a.y2),i.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,i){var n,a,o,r,s,l,u=i.caretSize,d=i.cornerRadius,c=i.xAlign,h=i.yAlign,f=t.x,g=t.y,p=e.width,m=e.height;if("center"===h)s=g+m/2,"left"===c?(a=(n=f)-u,o=n,r=s+u,l=s-u):(a=(n=f+p)+u,o=n,r=s-u,l=s+u);else if("left"===c?(n=(a=f+d+u)-u,o=a+u):"right"===c?(n=(a=f+p-d-u)-u,o=a+u):(n=(a=i.caretX)-u,o=a+u),"top"===h)s=(r=g)-u,l=r;else{s=(r=g+m)+u,l=r;var v=o;o=n,n=v}return{x1:n,x2:a,x3:o,y1:r,y2:s,y3:l}},drawTitle:function(t,i,n,a){var r=i.title;if(r.length){n.textAlign=i._titleAlign,n.textBaseline="top";var s,l,u=i.titleFontSize,d=i.titleSpacing;for(n.fillStyle=e(i.titleFontColor,a),n.font=o.fontString(u,i._titleFontStyle,i._titleFontFamily),s=0,l=r.length;s<l;++s)n.fillText(r[s],t.x,t.y),t.y+=u+d,s+1===r.length&&(t.y+=i.titleMarginBottom-d)}},drawBody:function(t,i,n,a){var r=i.bodyFontSize,s=i.bodySpacing,l=i.body;n.textAlign=i._bodyAlign,n.textBaseline="top",n.font=o.fontString(r,i._bodyFontStyle,i._bodyFontFamily);var u=0,d=function(e){n.fillText(e,t.x+u,t.y),t.y+=r+s};n.fillStyle=e(i.bodyFontColor,a),o.each(i.beforeBody,d);var c=i.displayColors;u=c?r+2:0,o.each(l,function(s,l){var u=e(i.labelTextColors[l],a);n.fillStyle=u,o.each(s.before,d),o.each(s.lines,function(o){c&&(n.fillStyle=e(i.legendColorBackground,a),n.fillRect(t.x,t.y,r,r),n.lineWidth=1,n.strokeStyle=e(i.labelColors[l].borderColor,a),n.strokeRect(t.x,t.y,r,r),n.fillStyle=e(i.labelColors[l].backgroundColor,a),n.fillRect(t.x+1,t.y+1,r-2,r-2),n.fillStyle=u),d(o)}),o.each(s.after,d)}),u=0,o.each(i.afterBody,d),t.y-=s},drawFooter:function(t,i,n,a){var r=i.footer;r.length&&(t.y+=i.footerMarginTop,n.textAlign=i._footerAlign,n.textBaseline="top",n.fillStyle=e(i.footerFontColor,a),n.font=o.fontString(i.footerFontSize,i._footerFontStyle,i._footerFontFamily),o.each(r,function(e){n.fillText(e,t.x,t.y),t.y+=i.footerFontSize+i.footerSpacing}))},drawBackground:function(t,i,n,a,o){n.fillStyle=e(i.backgroundColor,o),n.strokeStyle=e(i.borderColor,o),n.lineWidth=i.borderWidth;var r=i.xAlign,s=i.yAlign,l=t.x,u=t.y,d=a.width,c=a.height,h=i.cornerRadius;n.beginPath(),n.moveTo(l+h,u),"top"===s&&this.drawCaret(t,a),n.lineTo(l+d-h,u),n.quadraticCurveTo(l+d,u,l+d,u+h),"center"===s&&"right"===r&&this.drawCaret(t,a),n.lineTo(l+d,u+c-h),n.quadraticCurveTo(l+d,u+c,l+d-h,u+c),"bottom"===s&&this.drawCaret(t,a),n.lineTo(l+h,u+c),n.quadraticCurveTo(l,u+c,l,u+c-h),"center"===s&&"left"===r&&this.drawCaret(t,a),n.lineTo(l,u+h),n.quadraticCurveTo(l,u,l+h,u),n.closePath(),n.fill(),i.borderWidth>0&&n.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var i={width:e.width,height:e.height},n={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,o=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&o&&(this.drawBackground(n,e,t,i,a),n.x+=e.xPadding,n.y+=e.yPadding,this.drawTitle(n,e,t,a),this.drawBody(n,e,t,a),this.drawFooter(n,e,t,a))}},handleEvent:function(t){var e,i=this,n=i._options;return i._lastActive=i._lastActive||[],"mouseout"===t.type?i._active=[]:i._active=i._chart.getElementsAtEventForMode(t,n.mode,n),(e=!o.arrayEquals(i._active,i._lastActive))&&(i._lastActive=i._active,(n.enabled||n.custom)&&(i._eventPosition={x:t.x,y:t.y},i.update(!0),i.pivot())),e}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,i,n=0,a=0,o=0;for(e=0,i=t.length;e<i;++e){var r=t[e];if(r&&r.hasValue()){var s=r.tooltipPosition();n+=s.x,a+=s.y,++o}}return{x:Math.round(n/o),y:Math.round(a/o)}},nearest:function(t,e){var i,n,a,r=e.x,s=e.y,l=Number.POSITIVE_INFINITY;for(i=0,n=t.length;i<n;++i){var u=t[i];if(u&&u.hasValue()){var d=u.getCenterPoint(),c=o.distanceBetweenPoints(e,d);c<l&&(l=c,a=u)}}if(a){var h=a.tooltipPosition();r=h.x,s=h.y}return{x:r,y:s}}}}},{25:25,26:26,45:45}],36:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45);n._set("global",{elements:{arc:{backgroundColor:n.global.defaultColor,borderColor:"#fff",borderWidth:2}}}),e.exports=a.extend({inLabelRange:function(t){var e=this._view;return!!e&&Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2)},inRange:function(t,e){var i=this._view;if(i){for(var n=o.getAngleFromPoint(i,{x:t,y:e}),a=n.angle,r=n.distance,s=i.startAngle,l=i.endAngle;l<s;)l+=2*Math.PI;for(;a>l;)a-=2*Math.PI;for(;a<s;)a+=2*Math.PI;var u=a>=s&&a<=l,d=r>=i.innerRadius&&r<=i.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,i=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,i=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}},draw:function(){var t=this._chart.ctx,e=this._view,i=e.startAngle,n=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,i,n),t.arc(e.x,e.y,e.innerRadius,n,i,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=n.global;n._set("global",{elements:{line:{tension:.4,backgroundColor:r.defaultColor,borderWidth:3,borderColor:r.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,i,n,a=this._view,s=this._chart.ctx,l=a.spanGaps,u=this._children.slice(),d=r.elements.line,c=-1;for(this._loop&&u.length&&u.push(u[0]),s.save(),s.lineCap=a.borderCapStyle||d.borderCapStyle,s.setLineDash&&s.setLineDash(a.borderDash||d.borderDash),s.lineDashOffset=a.borderDashOffset||d.borderDashOffset,s.lineJoin=a.borderJoinStyle||d.borderJoinStyle,s.lineWidth=a.borderWidth||d.borderWidth,s.strokeStyle=a.borderColor||r.defaultColor,s.beginPath(),c=-1,t=0;t<u.length;++t)e=u[t],i=o.previousItem(u,t),n=e._view,0===t?n.skip||(s.moveTo(n.x,n.y),c=t):(i=-1===c?i:u[c],n.skip||(c!==t-1&&!l||-1===c?s.moveTo(n.x,n.y):o.canvas.lineTo(s,i._view,e._view),c=t));s.stroke(),s.restore()}})},{25:25,26:26,45:45}],38:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=n.global.defaultColor;function s(t){var e=this._view;return!!e&&Math.abs(t-e.x)<e.radius+e.hitRadius}n._set("global",{elements:{point:{radius:3,pointStyle:"circle",backgroundColor:r,borderColor:r,borderWidth:1,hitRadius:1,hoverRadius:4,hoverBorderWidth:1}}}),e.exports=a.extend({inRange:function(t,e){var i=this._view;return!!i&&Math.pow(t-i.x,2)+Math.pow(e-i.y,2)<Math.pow(i.hitRadius+i.radius,2)},inLabelRange:s,inXRange:s,inYRange:function(t){var e=this._view;return!!e&&Math.abs(t-e.y)<e.radius+e.hitRadius},getCenterPoint:function(){var t=this._view;return{x:t.x,y:t.y}},getArea:function(){return Math.PI*Math.pow(this._view.radius,2)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(t){var e=this._view,i=this._model,a=this._chart.ctx,s=e.pointStyle,l=e.radius,u=e.x,d=e.y,c=o.color,h=0;e.skip||(a.strokeStyle=e.borderColor||r,a.lineWidth=o.valueOrDefault(e.borderWidth,n.global.elements.point.borderWidth),a.fillStyle=e.backgroundColor||r,void 0!==t&&(i.x<t.left||1.01*t.right<i.x||i.y<t.top||1.01*t.bottom<i.y)&&(i.x<t.left?h=(u-i.x)/(t.left-i.x):1.01*t.right<i.x?h=(i.x-u)/(i.x-t.right):i.y<t.top?h=(d-i.y)/(t.top-i.y):1.01*t.bottom<i.y&&(h=(i.y-d)/(i.y-t.bottom)),h=Math.round(100*h)/100,a.strokeStyle=c(a.strokeStyle).alpha(h).rgbString(),a.fillStyle=c(a.fillStyle).alpha(h).rgbString()),o.canvas.drawPoint(a,s,l,u,d))}})},{25:25,26:26,45:45}],39:[function(t,e,i){"use strict";var n=t(25),a=t(26);function o(t){return void 0!==t._view.width}function r(t){var e,i,n,a,r=t._view;if(o(t)){var s=r.width/2;e=r.x-s,i=r.x+s,n=Math.min(r.y,r.base),a=Math.max(r.y,r.base)}else{var l=r.height/2;e=Math.min(r.x,r.base),i=Math.max(r.x,r.base),n=r.y-l,a=r.y+l}return{left:e,top:n,right:i,bottom:a}}n._set("global",{elements:{rectangle:{backgroundColor:n.global.defaultColor,borderColor:n.global.defaultColor,borderSkipped:"bottom",borderWidth:0}}}),e.exports=a.extend({draw:function(){var t,e,i,n,a,o,r,s=this._chart.ctx,l=this._view,u=l.borderWidth;if(l.horizontal?(t=l.base,e=l.x,i=l.y-l.height/2,n=l.y+l.height/2,a=e>t?1:-1,o=1,r=l.borderSkipped||"left"):(t=l.x-l.width/2,e=l.x+l.width/2,i=l.y,a=1,o=(n=l.base)>i?1:-1,r=l.borderSkipped||"bottom"),u){var d=Math.min(Math.abs(t-e),Math.abs(i-n)),c=(u=u>d?d:u)/2,h=t+("left"!==r?c*a:0),f=e+("right"!==r?-c*a:0),g=i+("top"!==r?c*o:0),p=n+("bottom"!==r?-c*o:0);h!==f&&(i=g,n=p),g!==p&&(t=h,e=f)}s.beginPath(),s.fillStyle=l.backgroundColor,s.strokeStyle=l.borderColor,s.lineWidth=u;var m=[[t,n],[t,i],[e,i],[e,n]],v=["bottom","left","top","right"].indexOf(r,0);function b(t){return m[(v+t)%4]}-1===v&&(v=0);var x=b(0);s.moveTo(x[0],x[1]);for(var y=1;y<4;y++)x=b(y),s.lineTo(x[0],x[1]);s.fill(),u&&s.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=!1;if(this._view){var n=r(this);i=t>=n.left&&t<=n.right&&e>=n.top&&e<=n.bottom}return i},inLabelRange:function(t,e){if(!this._view)return!1;var i=r(this);return o(this)?t>=i.left&&t<=i.right:e>=i.top&&e<=i.bottom},inXRange:function(t){var e=r(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=r(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,i=this._view;return o(this)?(t=i.x,e=(i.y+i.base)/2):(t=(i.x+i.base)/2,e=i.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,i){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,i){"use strict";var n=t(42);i=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,i,n,a,o){if(o){var r=Math.min(o,n/2),s=Math.min(o,a/2);t.moveTo(e+r,i),t.lineTo(e+n-r,i),t.quadraticCurveTo(e+n,i,e+n,i+s),t.lineTo(e+n,i+a-s),t.quadraticCurveTo(e+n,i+a,e+n-r,i+a),t.lineTo(e+r,i+a),t.quadraticCurveTo(e,i+a,e,i+a-s),t.lineTo(e,i+s),t.quadraticCurveTo(e,i,e+r,i)}else t.rect(e,i,n,a)},drawPoint:function(t,e,i,n,a){var o,r,s,l,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(o=e.toString())&&"[object HTMLCanvasElement]"!==o){if(!(isNaN(i)||i<=0)){switch(e){default:t.beginPath(),t.arc(n,a,i,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(r=3*i/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(n-r/2,a+u/3),t.lineTo(n+r/2,a+u/3),t.lineTo(n,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*i,t.beginPath(),t.fillRect(n-d,a-d,2*d,2*d),t.strokeRect(n-d,a-d,2*d,2*d);break;case"rectRounded":var c=i/Math.SQRT2,h=n-c,f=a-c,g=Math.SQRT2*i;t.beginPath(),this.roundedRect(t,h,f,g,g,i/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*i,t.beginPath(),t.moveTo(n-d,a),t.lineTo(n,a+d),t.lineTo(n+d,a),t.lineTo(n,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(n,a+i),t.lineTo(n,a-i),t.moveTo(n-i,a),t.lineTo(n+i,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*i,l=Math.sin(Math.PI/4)*i,t.moveTo(n-s,a-l),t.lineTo(n+s,a+l),t.moveTo(n-s,a+l),t.lineTo(n+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(n,a+i),t.lineTo(n,a-i),t.moveTo(n-i,a),t.lineTo(n+i,a),s=Math.cos(Math.PI/4)*i,l=Math.sin(Math.PI/4)*i,t.moveTo(n-s,a-l),t.lineTo(n+s,a+l),t.moveTo(n-s,a+l),t.lineTo(n+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(n-i,a),t.lineTo(n+i,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(n,a),t.lineTo(n+i,a),t.closePath()}t.stroke()}}else t.drawImage(e,n-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,i,n){if(i.steppedLine)return"after"===i.steppedLine&&!n||"after"!==i.steppedLine&&n?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y),void t.lineTo(i.x,i.y);i.tension?t.bezierCurveTo(n?e.controlPointPreviousX:e.controlPointNextX,n?e.controlPointPreviousY:e.controlPointNextY,n?i.controlPointNextX:i.controlPointPreviousX,n?i.controlPointNextY:i.controlPointPreviousY,i.x,i.y):t.lineTo(i.x,i.y)}};n.clear=i.clear,n.drawRoundedRectangle=function(t){t.beginPath(),i.roundedRect.apply(i,arguments),t.closePath()}},{42:42}],42:[function(t,e,i){"use strict";var n,a={noop:function(){},uid:(n=0,function(){return n++}),isNullOrUndef:function(t){return null==t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,i){return a.valueOrDefault(a.isArray(t)?t[e]:t,i)},callback:function(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)},each:function(t,e,i,n){var o,r,s;if(a.isArray(t))if(r=t.length,n)for(o=r-1;o>=0;o--)e.call(i,t[o],o);else for(o=0;o<r;o++)e.call(i,t[o],o);else if(a.isObject(t))for(r=(s=Object.keys(t)).length,o=0;o<r;o++)e.call(i,t[s[o]],s[o])},arrayEquals:function(t,e){var i,n,o,r;if(!t||!e||t.length!==e.length)return!1;for(i=0,n=t.length;i<n;++i)if(o=t[i],r=e[i],o instanceof Array&&r instanceof Array){if(!a.arrayEquals(o,r))return!1}else if(o!==r)return!1;return!0},clone:function(t){if(a.isArray(t))return t.map(a.clone);if(a.isObject(t)){for(var e={},i=Object.keys(t),n=i.length,o=0;o<n;++o)e[i[o]]=a.clone(t[i[o]]);return e}return t},_merger:function(t,e,i,n){var o=e[t],r=i[t];a.isObject(o)&&a.isObject(r)?a.merge(o,r,n):e[t]=a.clone(r)},_mergerIf:function(t,e,i){var n=e[t],o=i[t];a.isObject(n)&&a.isObject(o)?a.mergeIf(n,o):e.hasOwnProperty(t)||(e[t]=a.clone(o))},merge:function(t,e,i){var n,o,r,s,l,u=a.isArray(e)?e:[e],d=u.length;if(!a.isObject(t))return t;for(n=(i=i||{}).merger||a._merger,o=0;o<d;++o)if(e=u[o],a.isObject(e))for(l=0,s=(r=Object.keys(e)).length;l<s;++l)n(r[l],t,e,i);return t},mergeIf:function(t,e){return a.merge(t,e,{merger:a._mergerIf})},extend:function(t){for(var e=function(e,i){t[i]=e},i=1,n=arguments.length;i<n;++i)a.each(arguments[i],e);return t},inherits:function(t){var e=this,i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},n=function(){this.constructor=i};return n.prototype=e.prototype,i.prototype=new n,i.extend=a.inherits,t&&a.extend(i.prototype,t),i.__super__=e.prototype,i}};e.exports=a,a.callCallback=a.callback,a.indexOf=function(t,e,i){return Array.prototype.indexOf.call(t,e,i)},a.getValueOrDefault=a.valueOrDefault,a.getValueAtIndexOrDefault=a.valueAtIndexOrDefault},{}],43:[function(t,e,i){"use strict";var n=t(42),a={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return(t-=1)*t*t+1},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-((t-=1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return t*t*t*t*t},easeOutQuint:function(t){return(t-=1)*t*t*t*t+1},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return 1-Math.cos(t*(Math.PI/2))},easeOutSine:function(t){return Math.sin(t*(Math.PI/2))},easeInOutSine:function(t){return-.5*(Math.cos(Math.PI*t)-1)},easeInExpo:function(t){return 0===t?0:Math.pow(2,10*(t-1))},easeOutExpo:function(t){return 1===t?1:1-Math.pow(2,-10*t)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*--t))},easeInCirc:function(t){return t>=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1===t?1:(i||(i=.3),n<1?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),-n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i))},easeOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1===t?1:(i||(i=.3),n<1?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),n*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/i)+1)},easeInOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:2==(t/=.5)?1:(i||(i=.45),n<1?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),t<1?n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*-.5:n*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/i)*.5+1)},easeInBack:function(t){return t*t*(2.70158*t-1.70158)},easeOutBack:function(t){return(t-=1)*t*(2.70158*t+1.70158)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},n.easingEffects=a},{42:42}],44:[function(t,e,i){"use strict";var n=t(42);e.exports={toLineHeight:function(t,e){var i=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,i,a,o;return n.isObject(t)?(e=+t.top||0,i=+t.right||0,a=+t.bottom||0,o=+t.left||0):e=i=a=o=+t||0,{top:e,right:i,bottom:a,left:o,height:e+a,width:o+i}},resolve:function(t,e,i){var a,o,r;for(a=0,o=t.length;a<o;++a)if(void 0!==(r=t[a])&&(void 0!==e&&"function"==typeof r&&(r=r(e)),void 0!==i&&n.isArray(r)&&(r=r[i]),void 0!==r))return r}}},{42:42}],45:[function(t,e,i){"use strict";e.exports=t(42),e.exports.easing=t(43),e.exports.canvas=t(41),e.exports.options=t(44)},{41:41,42:42,43:43,44:44}],46:[function(t,e,i){e.exports={acquireContext:function(t){return t&&t.canvas&&(t=t.canvas),t&&t.getContext("2d")||null}}},{}],47:[function(t,e,i){"use strict";var n=t(45),a="$chartjs",o="chartjs-",r=o+"render-monitor",s=o+"render-animation",l=["animationstart","webkitAnimationStart"],u={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function d(t,e){var i=n.getStyle(t,e),a=i&&i.match(/^(\d+)(\.\d+)?px$/);return a?Number(a[1]):void 0}var c=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};function h(t,e,i){t.addEventListener(e,i,c)}function f(t,e,i){t.removeEventListener(e,i,c)}function g(t,e,i,n,a){return{type:t,chart:e,native:a||null,x:void 0!==i?i:null,y:void 0!==n?n:null}}function p(t,e,i){var u,d,c,f,p,m,v,b,x=t[a]||(t[a]={}),y=x.resizer=function(t){var e=document.createElement("div"),i=o+"size-monitor",n="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;";e.style.cssText=n,e.className=i,e.innerHTML='<div class="'+i+'-expand" style="'+n+'"><div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div></div><div class="'+i+'-shrink" style="'+n+'"><div style="position:absolute;width:200%;height:200%;left:0; top:0"></div></div>';var a=e.childNodes[0],r=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,r.scrollLeft=1e6,r.scrollTop=1e6};var s=function(){e._reset(),t()};return h(a,"scroll",s.bind(a,"expand")),h(r,"scroll",s.bind(r,"shrink")),e}((u=function(){if(x.resizer)return e(g("resize",i))},c=!1,f=[],function(){f=Array.prototype.slice.call(arguments),d=d||this,c||(c=!0,n.requestAnimFrame.call(window,function(){c=!1,u.apply(d,f)}))}));m=function(){if(x.resizer){var e=t.parentNode;e&&e!==y.parentNode&&e.insertBefore(y,e.firstChild),y._reset()}},v=(p=t)[a]||(p[a]={}),b=v.renderProxy=function(t){t.animationName===s&&m()},n.each(l,function(t){h(p,t,b)}),v.reflow=!!p.offsetParent,p.classList.add(r)}function m(t){var e,i,o,s=t[a]||{},u=s.resizer;delete s.resizer,i=(e=t)[a]||{},(o=i.renderProxy)&&(n.each(l,function(t){f(e,t,o)}),delete i.renderProxy),e.classList.remove(r),u&&u.parentNode&&u.parentNode.removeChild(u)}e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t,e,i,n="from{opacity:0.99}to{opacity:1}";e="@-webkit-keyframes "+s+"{"+n+"}@keyframes "+s+"{"+n+"}."+r+"{-webkit-animation:"+s+" 0.001s;animation:"+s+" 0.001s;}",i=(t=this)._style||document.createElement("style"),t._style||(t._style=i,e="/* Chart.js */\n"+e,i.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(i)),i.appendChild(document.createTextNode(e))},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){var i=t.style,n=t.getAttribute("height"),o=t.getAttribute("width");if(t[a]={initial:{height:n,width:o,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",null===o||""===o){var r=d(t,"width");void 0!==r&&(t.width=r)}if(null===n||""===n)if(""===t.style.height)t.height=t.width/(e.options.aspectRatio||2);else{var s=d(t,"height");void 0!==r&&(t.height=s)}}(t,e),i):null},releaseContext:function(t){var e=t.canvas;if(e[a]){var i=e[a].initial;["height","width"].forEach(function(t){var a=i[t];n.isNullOrUndef(a)?e.removeAttribute(t):e.setAttribute(t,a)}),n.each(i.style||{},function(t,i){e.style[i]=t}),e.width=e.width,delete e[a]}},addEventListener:function(t,e,i){var o=t.canvas;if("resize"!==e){var r=i[a]||(i[a]={});h(o,e,(r.proxies||(r.proxies={}))[t.id+"_"+e]=function(e){var a,o,r,s;i((o=t,r=u[(a=e).type]||a.type,s=n.getRelativePosition(a,o),g(r,o,s.x,s.y,a)))})}else p(o,i,t)},removeEventListener:function(t,e,i){var n=t.canvas;if("resize"!==e){var o=((i[a]||{}).proxies||{})[t.id+"_"+e];o&&f(n,e,o)}else m(n)}},n.addEvent=h,n.removeEvent=f},{45:45}],48:[function(t,e,i){"use strict";var n=t(45),a=t(46),o=t(47),r=o._enabled?o:a;e.exports=n.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},r)},{45:45,46:46,47:47}],49:[function(t,e,i){"use strict";e.exports={},e.exports.filler=t(50),e.exports.legend=t(51),e.exports.title=t(52)},{50:50,51:51,52:52}],50:[function(t,e,i){"use strict";var n=t(25),a=t(40),o=t(45);n._set("global",{plugins:{filler:{propagate:!0}}});var r={dataset:function(t){var e=t.fill,i=t.chart,n=i.getDatasetMeta(e),a=n&&i.isDatasetVisible(e)&&n.dataset._children||[],o=a.length||0;return o?function(t,e){return e<o&&a[e]._view||null}:null},boundary:function(t){var e=t.boundary,i=e?e.x:null,n=e?e.y:null;return function(t){return{x:null===i?t.x:i,y:null===n?t.y:n}}}};function s(t,e,i){var n,a=t._model||{},o=a.fill;if(void 0===o&&(o=!!a.backgroundColor),!1===o||null===o)return!1;if(!0===o)return"origin";if(n=parseFloat(o,10),isFinite(n)&&Math.floor(n)===n)return"-"!==o[0]&&"+"!==o[0]||(n=e+n),!(n===e||n<0||n>=i)&&n;switch(o){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return o;default:return!1}}function l(t){var e,i=t.el._model||{},n=t.el._scale||{},a=t.fill,o=null;if(isFinite(a))return null;if("start"===a?o=void 0===i.scaleBottom?n.bottom:i.scaleBottom:"end"===a?o=void 0===i.scaleTop?n.top:i.scaleTop:void 0!==i.scaleZero?o=i.scaleZero:n.getBasePosition?o=n.getBasePosition():n.getBasePixel&&(o=n.getBasePixel()),null!=o){if(void 0!==o.x&&void 0!==o.y)return o;if("number"==typeof o&&isFinite(o))return{x:(e=n.isHorizontal())?o:null,y:e?null:o}}return null}function u(t,e,i){var n,a=t[e].fill,o=[e];if(!i)return a;for(;!1!==a&&-1===o.indexOf(a);){if(!isFinite(a))return a;if(!(n=t[a]))return!1;if(n.visible)return a;o.push(a),a=n.fill}return!1}function d(t){return t&&!t.skip}function c(t,e,i,n,a){var r;if(n&&a){for(t.moveTo(e[0].x,e[0].y),r=1;r<n;++r)o.canvas.lineTo(t,e[r-1],e[r]);for(t.lineTo(i[a-1].x,i[a-1].y),r=a-1;r>0;--r)o.canvas.lineTo(t,i[r],i[r-1],!0)}}e.exports={id:"filler",afterDatasetsUpdate:function(t,e){var i,n,o,d,c,h,f,g=(t.data.datasets||[]).length,p=e.propagate,m=[];for(n=0;n<g;++n)d=null,(o=(i=t.getDatasetMeta(n)).dataset)&&o._model&&o instanceof a.Line&&(d={visible:t.isDatasetVisible(n),fill:s(o,n,g),chart:t,el:o}),i.$filler=d,m.push(d);for(n=0;n<g;++n)(d=m[n])&&(d.fill=u(m,n,p),d.boundary=l(d),d.mapper=(void 0,f=void 0,h=(c=d).fill,f="dataset",!1===h?null:(isFinite(h)||(f="boundary"),r[f](c))))},beforeDatasetDraw:function(t,e){var i=e.meta.$filler;if(i){var a=t.ctx,r=i.el,s=r._view,l=r._children||[],u=i.mapper,h=s.backgroundColor||n.global.defaultColor;u&&h&&l.length&&(o.canvas.clipArea(a,t.chartArea),function(t,e,i,n,a,o){var r,s,l,u,h,f,g,p=e.length,m=n.spanGaps,v=[],b=[],x=0,y=0;for(t.beginPath(),r=0,s=p+!!o;r<s;++r)h=i(u=e[l=r%p]._view,l,n),f=d(u),g=d(h),f&&g?(x=v.push(u),y=b.push(h)):x&&y&&(m?(f&&v.push(u),g&&b.push(h)):(c(t,v,b,x,y),x=y=0,v=[],b=[]));c(t,v,b,x,y),t.closePath(),t.fillStyle=a,t.fill()}(a,l,u,s,h,r._loop),o.canvas.unclipArea(a))}}}},{25:25,40:40,45:45}],51:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=t(30),s=o.noop;function l(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}n._set("global",{legend:{display:!0,position:"top",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var i=e.datasetIndex,n=this.chart,a=n.getDatasetMeta(i);a.hidden=null===a.hidden?!n.data.datasets[i].hidden:null,n.update()},onHover:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data;return o.isArray(e.datasets)?e.datasets.map(function(e,i){return{text:e.label,fillStyle:o.isArray(e.backgroundColor)?e.backgroundColor[0]:e.backgroundColor,hidden:!t.isDatasetVisible(i),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,pointStyle:e.pointStyle,datasetIndex:i}},this):[]}}},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var i=0;i<t.data.datasets.length;i++)e.push('<li><span style="background-color:'+t.data.datasets[i].backgroundColor+'"></span>'),t.data.datasets[i].label&&e.push(t.data.datasets[i].label),e.push("</li>");return e.push("</ul>"),e.join("")}});var u=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,i){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=e,n.margins=i,n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeBuildLabels(),n.buildLabels(),n.afterBuildLabels(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},i=o.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(i=i.filter(function(i){return e.filter(i,t.chart.data)})),t.options.reverse&&i.reverse(),t.legendItems=i},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,e=t.options,i=e.labels,a=e.display,r=t.ctx,s=n.global,u=o.valueOrDefault,d=u(i.fontSize,s.defaultFontSize),c=u(i.fontStyle,s.defaultFontStyle),h=u(i.fontFamily,s.defaultFontFamily),f=o.fontString(d,c,h),g=t.legendHitBoxes=[],p=t.minSize,m=t.isHorizontal();if(m?(p.width=t.maxWidth,p.height=a?10:0):(p.width=a?10:0,p.height=t.maxHeight),a)if(r.font=f,m){var v=t.lineWidths=[0],b=t.legendItems.length?d+i.padding:0;r.textAlign="left",r.textBaseline="top",o.each(t.legendItems,function(e,n){var a=l(i,d)+d/2+r.measureText(e.text).width;v[v.length-1]+a+i.padding>=t.width&&(b+=d+i.padding,v[v.length]=t.left),g[n]={left:0,top:0,width:a,height:d},v[v.length-1]+=a+i.padding}),p.height+=b}else{var x=i.padding,y=t.columnWidths=[],k=i.padding,M=0,w=0,S=d+x;o.each(t.legendItems,function(t,e){var n=l(i,d)+d/2+r.measureText(t.text).width;w+S>p.height&&(k+=M+i.padding,y.push(M),M=0,w=0),M=Math.max(M,n),w+=S,g[e]={left:0,top:0,width:n,height:d}}),k+=M,y.push(M),p.width+=k}t.width=p.width,t.height=p.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,i=e.labels,a=n.global,r=a.elements.line,s=t.width,u=t.lineWidths;if(e.display){var d,c=t.ctx,h=o.valueOrDefault,f=h(i.fontColor,a.defaultFontColor),g=h(i.fontSize,a.defaultFontSize),p=h(i.fontStyle,a.defaultFontStyle),m=h(i.fontFamily,a.defaultFontFamily),v=o.fontString(g,p,m);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var b=l(i,g),x=t.legendHitBoxes,y=t.isHorizontal();d=y?{x:t.left+(s-u[0])/2,y:t.top+i.padding,line:0}:{x:t.left+i.padding,y:t.top+i.padding,line:0};var k=g+i.padding;o.each(t.legendItems,function(n,l){var f,p,m,v,M,w=c.measureText(n.text).width,S=b+g/2+w,C=d.x,_=d.y;y?C+S>=s&&(_=d.y+=k,d.line++,C=d.x=t.left+(s-u[d.line])/2):_+k>t.bottom&&(C=d.x=C+t.columnWidths[d.line]+i.padding,_=d.y=t.top+i.padding,d.line++),function(t,i,n){if(!(isNaN(b)||b<=0)){c.save(),c.fillStyle=h(n.fillStyle,a.defaultColor),c.lineCap=h(n.lineCap,r.borderCapStyle),c.lineDashOffset=h(n.lineDashOffset,r.borderDashOffset),c.lineJoin=h(n.lineJoin,r.borderJoinStyle),c.lineWidth=h(n.lineWidth,r.borderWidth),c.strokeStyle=h(n.strokeStyle,a.defaultColor);var s=0===h(n.lineWidth,r.borderWidth);if(c.setLineDash&&c.setLineDash(h(n.lineDash,r.borderDash)),e.labels&&e.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=i+u;o.canvas.drawPoint(c,n.pointStyle,l,d,f)}else s||c.strokeRect(t,i,b,g),c.fillRect(t,i,b,g);c.restore()}}(C,_,n),x[l].left=C,x[l].top=_,f=n,p=w,v=b+(m=g/2)+C,M=_+m,c.fillText(f.text,v,M),f.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(v,M),c.lineTo(v+p,M),c.stroke()),y?d.x+=S+i.padding:d.y+=k})}},handleEvent:function(t){var e=this,i=e.options,n="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===n){if(!i.onHover)return}else{if("click"!==n)return;if(!i.onClick)return}var o=t.x,r=t.y;if(o>=e.left&&o<=e.right&&r>=e.top&&r<=e.bottom)for(var s=e.legendHitBoxes,l=0;l<s.length;++l){var u=s[l];if(o>=u.left&&o<=u.left+u.width&&r>=u.top&&r<=u.top+u.height){if("click"===n){i.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===n){i.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}});function d(t,e){var i=new u({ctx:t.ctx,options:e,chart:t});r.configure(t,i,e),r.addBox(t,i),t.legend=i}e.exports={id:"legend",_element:u,beforeInit:function(t){var e=t.options.legend;e&&d(t,e)},beforeUpdate:function(t){var e=t.options.legend,i=t.legend;e?(o.mergeIf(e,n.global.legend),i?(r.configure(t,i,e),i.options=e):d(t,e)):i&&(r.removeBox(t,i),delete t.legend)},afterEvent:function(t,e){var i=t.legend;i&&i.handleEvent(e)}}},{25:25,26:26,30:30,45:45}],52:[function(t,e,i){"use strict";var n=t(25),a=t(26),o=t(45),r=t(30),s=o.noop;n._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}});var l=a.extend({initialize:function(t){o.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:s,update:function(t,e,i){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=e,n.margins=i,n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeBuildLabels(),n.buildLabels(),n.afterBuildLabels(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:s,afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,e=o.valueOrDefault,i=t.options,a=i.display,r=e(i.fontSize,n.global.defaultFontSize),s=t.minSize,l=o.isArray(i.text)?i.text.length:1,u=o.options.toLineHeight(i.lineHeight,r),d=a?l*u+2*i.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:s,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,i=o.valueOrDefault,a=t.options,r=n.global;if(a.display){var s,l,u,d=i(a.fontSize,r.defaultFontSize),c=i(a.fontStyle,r.defaultFontStyle),h=i(a.fontFamily,r.defaultFontFamily),f=o.fontString(d,c,h),g=o.options.toLineHeight(a.lineHeight,d),p=g/2+a.padding,m=0,v=t.top,b=t.left,x=t.bottom,y=t.right;e.fillStyle=i(a.fontColor,r.defaultFontColor),e.font=f,t.isHorizontal()?(l=b+(y-b)/2,u=v+p,s=y-b):(l="left"===a.position?b+p:y-p,u=v+(x-v)/2,s=x-v,m=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(m),e.textAlign="center",e.textBaseline="middle";var k=a.text;if(o.isArray(k))for(var M=0,w=0;w<k.length;++w)e.fillText(k[w],0,M,s),M+=g;else e.fillText(k,0,0,s);e.restore()}}});function u(t,e){var i=new l({ctx:t.ctx,options:e,chart:t});r.configure(t,i,e),r.addBox(t,i),t.titleBlock=i}e.exports={id:"title",_element:l,beforeInit:function(t){var e=t.options.title;e&&u(t,e)},beforeUpdate:function(t){var e=t.options.title,i=t.titleBlock;e?(o.mergeIf(e,n.global.title),i?(r.configure(t,i,e),i.options=e):u(t,e)):i&&(r.removeBox(t,i),delete t.titleBlock)}}},{25:25,26:26,30:30,45:45}],53:[function(t,e,i){"use strict";e.exports=function(t){var e=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t,e=this,i=e.getLabels();e.minIndex=0,e.maxIndex=i.length-1,void 0!==e.options.ticks.min&&(t=i.indexOf(e.options.ticks.min),e.minIndex=-1!==t?t:e.minIndex),void 0!==e.options.ticks.max&&(t=i.indexOf(e.options.ticks.max),e.maxIndex=-1!==t?t:e.maxIndex),e.min=i[e.minIndex],e.max=i[e.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var i=this,n=i.chart.data,a=i.isHorizontal();return n.yLabels&&!a?i.getRightValue(n.datasets[e].data[t]):i.ticks[t-i.minIndex]},getPixelForValue:function(t,e){var i,n=this,a=n.options.offset,o=Math.max(n.maxIndex+1-n.minIndex-(a?0:1),1);if(null!=t&&(i=n.isHorizontal()?t.x:t.y),void 0!==i||void 0!==t&&isNaN(e)){t=i||t;var r=n.getLabels().indexOf(t);e=-1!==r?r:e}if(n.isHorizontal()){var s=n.width/o,l=s*(e-n.minIndex);return a&&(l+=s/2),n.left+Math.round(l)}var u=n.height/o,d=u*(e-n.minIndex);return a&&(d+=u/2),n.top+Math.round(d)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,i=e.options.offset,n=Math.max(e._ticks.length-(i?0:1),1),a=e.isHorizontal(),o=(a?e.width:e.height)/n;return t-=a?e.left:e.top,i&&(t-=o/2),(t<=0?0:Math.round(t/o))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",e,{position:"bottom"})}},{}],54:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:o.formatters.linear}},i=t.LinearScaleBase.extend({determineDataLimits:function(){var t=this,e=t.options,i=t.chart,n=i.data.datasets,o=t.isHorizontal();function r(e){return o?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null;var s=e.stacked;if(void 0===s&&a.each(n,function(t,e){if(!s){var n=i.getDatasetMeta(e);i.isDatasetVisible(e)&&r(n)&&void 0!==n.stack&&(s=!0)}}),e.stacked||s){var l={};a.each(n,function(n,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===e.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&r(s)&&a.each(n.data,function(i,n){var a=+t.getRightValue(i);isNaN(a)||s.data[n].hidden||(d[n]=d[n]||0,c[n]=c[n]||0,e.relativePoints?d[n]=100:a<0?c[n]+=a:d[n]+=a)})}),a.each(l,function(e){var i=e.positiveValues.concat(e.negativeValues),n=a.min(i),o=a.max(i);t.min=null===t.min?n:Math.min(t.min,n),t.max=null===t.max?o:Math.max(t.max,o)})}else a.each(n,function(e,n){var o=i.getDatasetMeta(n);i.isDatasetVisible(n)&&r(o)&&a.each(e.data,function(e,i){var n=+t.getRightValue(e);isNaN(n)||o.data[i].hidden||(null===t.min?t.min=n:n<t.min&&(t.min=n),null===t.max?t.max=n:n>t.max&&(t.max=n))})});t.min=isFinite(t.min)&&!isNaN(t.min)?t.min:0,t.max=isFinite(t.max)&&!isNaN(t.max)?t.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this.options.ticks;if(this.isHorizontal())t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.width/50));else{var i=a.valueOrDefault(e.fontSize,n.global.defaultFontSize);t=Math.min(e.maxTicksLimit?e.maxTicksLimit:11,Math.ceil(this.height/(2*i)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e=this,i=e.start,n=+e.getRightValue(t),a=e.end-i;return e.isHorizontal()?e.left+e.width/a*(n-i):e.bottom-e.height/a*(n-i)},getValueForPixel:function(t){var e=this,i=e.isHorizontal(),n=i?e.width:e.height,a=(i?t-e.left:e.bottom-t)/n;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",i,e)}},{25:25,34:34,45:45}],55:[function(t,e,i){"use strict";var n=t(45);e.exports=function(t){var e=n.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var i=n.sign(t.min),a=n.sign(t.max);i<0&&a<0?t.max=0:i>0&&a>0&&(t.min=0)}var o=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),o!==r&&t.min>=t.max&&(o?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,i=t.getTickLimit(),a={maxTicks:i=Math.max(2,i),min:e.min,max:e.max,stepSize:n.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=function(t,e){var i,a=[];if(t.stepSize&&t.stepSize>0)i=t.stepSize;else{var o=n.niceNum(e.max-e.min,!1);i=n.niceNum(o/(t.maxTicks-1),!0)}var r=Math.floor(e.min/i)*i,s=Math.ceil(e.max/i)*i;t.min&&t.max&&t.stepSize&&n.almostWhole((t.max-t.min)/t.stepSize,i/1e3)&&(r=t.min,s=t.max);var l=(s-r)/i;l=n.almostEquals(l,Math.round(l),i/1e3)?Math.round(l):Math.ceil(l);var u=1;i<1&&(u=Math.pow(10,i.toString().length-2),r=Math.round(r*u)/u,s=Math.round(s*u)/u),a.push(void 0!==t.min?t.min:r);for(var d=1;d<l;++d)a.push(Math.round((r+d*i)*u)/u);return a.push(void 0!==t.max?t.max:s),a}(a,t);t.handleDirectionalChanges(),t.max=n.max(o),t.min=n.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{45:45}],56:[function(t,e,i){"use strict";var n=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},i=t.Scale.extend({determineDataLimits:function(){var t=this,e=t.options,i=t.chart,a=i.data.datasets,o=t.isHorizontal();function r(e){return o?e.xAxisID===t.id:e.yAxisID===t.id}t.min=null,t.max=null,t.minNotZero=null;var s=e.stacked;if(void 0===s&&n.each(a,function(t,e){if(!s){var n=i.getDatasetMeta(e);i.isDatasetVisible(e)&&r(n)&&void 0!==n.stack&&(s=!0)}}),e.stacked||s){var l={};n.each(a,function(a,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===e.stacked&&void 0===s.stack?o:"",s.stack].join(".");i.isDatasetVisible(o)&&r(s)&&(void 0===l[u]&&(l[u]=[]),n.each(a.data,function(e,i){var n=l[u],a=+t.getRightValue(e);isNaN(a)||s.data[i].hidden||a<0||(n[i]=n[i]||0,n[i]+=a)}))}),n.each(l,function(e){if(e.length>0){var i=n.min(e),a=n.max(e);t.min=null===t.min?i:Math.min(t.min,i),t.max=null===t.max?a:Math.max(t.max,a)}})}else n.each(a,function(e,a){var o=i.getDatasetMeta(a);i.isDatasetVisible(a)&&r(o)&&n.each(e.data,function(e,i){var n=+t.getRightValue(e);isNaN(n)||o.data[i].hidden||n<0||(null===t.min?t.min=n:n<t.min&&(t.min=n),null===t.max?t.max=n:n>t.max&&(t.max=n),0!==n&&(null===t.minNotZero||n<t.minNotZero)&&(t.minNotZero=n))})});this.handleTickRangeOptions()},handleTickRangeOptions:function(){var t=this,e=t.options.ticks,i=n.valueOrDefault;t.min=i(e.min,t.min),t.max=i(e.max,t.max),t.min===t.max&&(0!==t.min&&null!==t.min?(t.min=Math.pow(10,Math.floor(n.log10(t.min))-1),t.max=Math.pow(10,Math.floor(n.log10(t.max))+1)):(t.min=1,t.max=10)),null===t.min&&(t.min=Math.pow(10,Math.floor(n.log10(t.max))-1)),null===t.max&&(t.max=0!==t.min?Math.pow(10,Math.floor(n.log10(t.min))+1):10),null===t.minNotZero&&(t.min>0?t.minNotZero=t.min:t.max<1?t.minNotZero=Math.pow(10,Math.floor(n.log10(t.max))):t.minNotZero=1)},buildTicks:function(){var t=this,e=t.options.ticks,i=!t.isHorizontal(),a={min:e.min,max:e.max},o=t.ticks=function(t,e){var i,a,o=[],r=n.valueOrDefault,s=r(t.min,Math.pow(10,Math.floor(n.log10(e.min)))),l=Math.floor(n.log10(e.max)),u=Math.ceil(e.max/Math.pow(10,l));0===s?(i=Math.floor(n.log10(e.minNotZero)),a=Math.floor(e.minNotZero/Math.pow(10,i)),o.push(s),s=a*Math.pow(10,i)):(i=Math.floor(n.log10(s)),a=Math.floor(s/Math.pow(10,i)));for(var d=i<0?Math.pow(10,Math.abs(i)):1;o.push(s),10==++a&&(a=1,d=++i>=0?1:d),s=Math.round(a*Math.pow(10,i)*d)/d,i<l||i===l&&a<u;);var c=r(t.max,s);return o.push(c),o}(a,t);t.max=n.max(o),t.min=n.min(o),e.reverse?(i=!i,t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max),i&&o.reverse()},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t){return this.getPixelForValue(this.tickValues[t])},_getFirstTickValue:function(t){var e=Math.floor(n.log10(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},getPixelForValue:function(e){var i,a,o,r,s,l=this,u=l.options.ticks.reverse,d=n.log10,c=l._getFirstTickValue(l.minNotZero),h=0;return e=+l.getRightValue(e),u?(o=l.end,r=l.start,s=-1):(o=l.start,r=l.end,s=1),l.isHorizontal()?(i=l.width,a=u?l.right:l.left):(i=l.height,s*=-1,a=u?l.top:l.bottom),e!==o&&(0===o&&(i-=h=n.getValueOrDefault(l.options.ticks.fontSize,t.defaults.global.defaultFontSize),o=c),0!==e&&(h+=i/(d(r)-d(o))*(d(e)-d(o))),a+=s*h),a},getValueForPixel:function(e){var i,a,o,r,s=this,l=s.options.ticks.reverse,u=n.log10,d=s._getFirstTickValue(s.minNotZero);if(l?(a=s.end,o=s.start):(a=s.start,o=s.end),s.isHorizontal()?(i=s.width,r=l?s.right-e:e-s.left):(i=s.height,r=l?e-s.top:s.bottom-e),r!==a){if(0===a){var c=n.getValueOrDefault(s.options.ticks.fontSize,t.defaults.global.defaultFontSize);r-=c,i-=c,a=d}r*=u(o)-u(a),r/=i,r=Math.pow(10,u(a)+r)}return r}});t.scaleService.registerScaleType("logarithmic",i,e)}},{34:34,45:45}],57:[function(t,e,i){"use strict";var n=t(25),a=t(45),o=t(34);e.exports=function(t){var e=n.global,i={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:o.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function r(t){var e=t.options;return e.angleLines.display||e.pointLabels.display?t.chart.data.labels.length:0}function s(t){var i=t.options.pointLabels,n=a.valueOrDefault(i.fontSize,e.defaultFontSize),o=a.valueOrDefault(i.fontStyle,e.defaultFontStyle),r=a.valueOrDefault(i.fontFamily,e.defaultFontFamily);return{size:n,style:o,family:r,font:a.fontString(n,o,r)}}function l(t,e,i,n,a){return t===n||t===a?{start:e-i/2,end:e+i/2}:t<n||t>a?{start:e-i-5,end:e}:{start:e,end:e+i+5}}function u(t,e,i,n){if(a.isArray(e))for(var o=i.y,r=1.5*n,s=0;s<e.length;++s)t.fillText(e[s],i.x,o),o+=r;else t.fillText(e,i.x,i.y)}function d(t){return a.isNumber(t)?t:0}var c=t.LinearScaleBase.extend({setDimensions:function(){var t=this,i=t.options,n=i.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var o=a.min([t.height,t.width]),r=a.valueOrDefault(n.fontSize,e.defaultFontSize);t.drawingArea=i.display?o/2-(r/2+n.backdropPaddingY):o/2},determineDataLimits:function(){var t=this,e=t.chart,i=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY;a.each(e.data.datasets,function(o,r){if(e.isDatasetVisible(r)){var s=e.getDatasetMeta(r);a.each(o.data,function(e,a){var o=+t.getRightValue(e);isNaN(o)||s.data[a].hidden||(i=Math.min(o,i),n=Math.max(o,n))})}}),t.min=i===Number.POSITIVE_INFINITY?0:i,t.max=n===Number.NEGATIVE_INFINITY?0:n,t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,i=a.valueOrDefault(t.fontSize,e.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*i)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,e;this.options.pointLabels.display?function(t){var e,i,n,o=s(t),u=Math.min(t.height/2,t.width/2),d={r:t.width,l:0,t:t.height,b:0},c={};t.ctx.font=o.font,t._pointLabelSizes=[];var h,f,g,p=r(t);for(e=0;e<p;e++){n=t.getPointPosition(e,u),h=t.ctx,f=o.size,g=t.pointLabels[e]||"",i=a.isArray(g)?{w:a.longestText(h,h.font,g),h:g.length*f+1.5*(g.length-1)*f}:{w:h.measureText(g).width,h:f},t._pointLabelSizes[e]=i;var m=t.getIndexAngle(e),v=a.toDegrees(m)%360,b=l(v,n.x,i.w,0,180),x=l(v,n.y,i.h,90,270);b.start<d.l&&(d.l=b.start,c.l=m),b.end>d.r&&(d.r=b.end,c.r=m),x.start<d.t&&(d.t=x.start,c.t=m),x.end>d.b&&(d.b=x.end,c.b=m)}t.setReductions(u,d,c)}(this):(t=this,e=Math.min(t.height/2,t.width/2),t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0))},setReductions:function(t,e,i){var n=e.l/Math.sin(i.l),a=Math.max(e.r-this.width,0)/Math.sin(i.r),o=-e.t/Math.cos(i.t),r=-Math.max(e.b-this.height,0)/Math.cos(i.b);n=d(n),a=d(a),o=d(o),r=d(r),this.drawingArea=Math.min(Math.round(t-(n+a)/2),Math.round(t-(o+r)/2)),this.setCenterPoint(n,a,o,r)},setCenterPoint:function(t,e,i,n){var a=this,o=a.width-e-a.drawingArea,r=t+a.drawingArea,s=i+a.drawingArea,l=a.height-n-a.drawingArea;a.xCenter=Math.round((r+o)/2+a.left),a.yCenter=Math.round((s+l)/2+a.top)},getIndexAngle:function(t){return t*(2*Math.PI/r(this))+(this.chart.options&&this.chart.options.startAngle?this.chart.options.startAngle:0)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var i=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*i:(t-e.min)*i},getPointPosition:function(t,e){var i=this.getIndexAngle(t)-Math.PI/2;return{x:Math.round(Math.cos(i)*e)+this.xCenter,y:Math.round(Math.sin(i)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this.min,e=this.max;return this.getPointPositionForValue(0,this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0)},draw:function(){var t=this,i=t.options,n=i.gridLines,o=i.ticks,l=a.valueOrDefault;if(i.display){var d=t.ctx,c=this.getIndexAngle(0),h=l(o.fontSize,e.defaultFontSize),f=l(o.fontStyle,e.defaultFontStyle),g=l(o.fontFamily,e.defaultFontFamily),p=a.fontString(h,f,g);a.each(t.ticks,function(i,s){if(s>0||o.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[s]);if(n.display&&0!==s&&function(t,e,i,n){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(e.color,n-1),o.lineWidth=a.valueAtIndexOrDefault(e.lineWidth,n-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=r(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u<s;u++)l=t.getPointPosition(u,i),o.lineTo(l.x,l.y);o.closePath(),o.stroke()}}(t,n,u,s),o.display){var f=l(o.fontColor,e.defaultFontColor);if(d.font=p,d.save(),d.translate(t.xCenter,t.yCenter),d.rotate(c),o.showLabelBackdrop){var g=d.measureText(i).width;d.fillStyle=o.backdropColor,d.fillRect(-g/2-o.backdropPaddingX,-u-h/2-o.backdropPaddingY,g+2*o.backdropPaddingX,h+2*o.backdropPaddingY)}d.textAlign="center",d.textBaseline="middle",d.fillStyle=f,d.fillText(i,0,-u),d.restore()}}}),(i.angleLines.display||i.pointLabels.display)&&function(t){var i=t.ctx,n=t.options,o=n.angleLines,l=n.pointLabels;i.lineWidth=o.lineWidth,i.strokeStyle=o.color;var d,c,h,f,g=t.getDistanceFromCenterForValue(n.ticks.reverse?t.min:t.max),p=s(t);i.textBaseline="top";for(var m=r(t)-1;m>=0;m--){if(o.display){var v=t.getPointPosition(m,g);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(v.x,v.y),i.stroke(),i.closePath()}if(l.display){var b=t.getPointPosition(m,g+5),x=a.valueAtIndexOrDefault(l.fontColor,m,e.defaultFontColor);i.font=p.font,i.fillStyle=x;var y=t.getIndexAngle(m),k=a.toDegrees(y);i.textAlign=0===(f=k)||180===f?"center":f<180?"left":"right",d=k,c=t._pointLabelSizes[m],h=b,90===d||270===d?h.y-=c.h/2:(d>270||d<90)&&(h.y-=c.h),u(i,t.pointLabels[m]||"",b,p.size)}}}(t)}}});t.scaleService.registerScaleType("radialLinear",c,i)}},{25:25,34:34,45:45}],58:[function(t,e,i){"use strict";var n=t(1);n="function"==typeof n?n:window.moment;var a=t(25),o=t(45),r=Number.MIN_SAFE_INTEGER||-9007199254740991,s=Number.MAX_SAFE_INTEGER||9007199254740991,l={millisecond:{common:!0,size:1,steps:[1,2,5,10,20,50,100,250,500]},second:{common:!0,size:1e3,steps:[1,2,5,10,30]},minute:{common:!0,size:6e4,steps:[1,2,5,10,30]},hour:{common:!0,size:36e5,steps:[1,2,3,6,12]},day:{common:!0,size:864e5,steps:[1,2,5]},week:{common:!1,size:6048e5,steps:[1,2,3,4]},month:{common:!0,size:2628e6,steps:[1,2,3]},quarter:{common:!1,size:7884e6,steps:[1,2,3,4]},year:{common:!0,size:3154e7}},u=Object.keys(l);function d(t,e){return t-e}function c(t){var e,i,n,a={},o=[];for(e=0,i=t.length;e<i;++e)a[n=t[e]]||(a[n]=!0,o.push(n));return o}function h(t,e,i,n){var a=function(t,e,i){for(var n,a,o,r=0,s=t.length-1;r>=0&&r<=s;){if(a=t[(n=r+s>>1)-1]||null,o=t[n],!a)return{lo:null,hi:o};if(o[e]<i)r=n+1;else{if(!(a[e]>i))return{lo:a,hi:o};s=n-1}}return{lo:o,hi:null}}(t,e,i),o=a.lo?a.hi?a.lo:t[t.length-2]:t[0],r=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=r[e]-o[e],l=s?(i-o[e])/s:0,u=(r[n]-o[n])*l;return o[n]+u}function f(t,e){var i=e.parser,a=e.parser||e.format;return"function"==typeof i?i(t):"string"==typeof t&&"string"==typeof a?n(t,a):(t instanceof n||(t=n(t)),t.isValid()?t:"function"==typeof a?a(t):t)}function g(t,e){if(o.isNullOrUndef(t))return null;var i=e.options.time,n=f(e.getRightValue(t),i);return n.isValid()?(i.round&&n.startOf(i.round),n.valueOf()):null}function p(t){for(var e=u.indexOf(t)+1,i=u.length;e<i;++e)if(l[u[e]].common)return u[e]}function m(t,e,i,a){var r,d=a.time,c=d.unit||function(t,e,i,n){var a,o,r,d=u.length;for(a=u.indexOf(t);a<d-1;++a)if(r=(o=l[u[a]]).steps?o.steps[o.steps.length-1]:s,o.common&&Math.ceil((i-e)/(r*o.size))<=n)return u[a];return u[d-1]}(d.minUnit,t,e,i),h=p(c),f=o.valueOrDefault(d.stepSize,d.unitStepSize),g="week"===c&&d.isoWeekday,m=a.ticks.major.enabled,v=l[c],b=n(t),x=n(e),y=[];for(f||(f=function(t,e,i,n){var a,o,r,s=e-t,u=l[i],d=u.size,c=u.steps;if(!c)return Math.ceil(s/(n*d));for(a=0,o=c.length;a<o&&(r=c[a],!(Math.ceil(s/(d*r))<=n));++a);return r}(t,e,c,i)),g&&(b=b.isoWeekday(g),x=x.isoWeekday(g)),b=b.startOf(g?"day":c),(x=x.startOf(g?"day":c))<e&&x.add(1,c),r=n(b),m&&h&&!g&&!d.round&&(r.startOf(h),r.add(~~((b-r)/(v.size*f))*f,c));r<x;r.add(f,c))y.push(+r);return y.push(+r),y}e.exports=function(t){var e=t.Scale.extend({initialize:function(){if(!n)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");this.mergeTicksOptions(),t.Scale.prototype.initialize.call(this)},update:function(){var e=this.options;return e.time&&e.time.format&&console.warn("options.time.format is deprecated and replaced by options.time.parser."),t.Scale.prototype.update.apply(this,arguments)},getRightValue:function(e){return e&&void 0!==e.t&&(e=e.t),t.Scale.prototype.getRightValue.call(this,e)},determineDataLimits:function(){var t,e,i,a,l,u,h=this,f=h.chart,p=h.options.time,m=p.unit||"day",v=s,b=r,x=[],y=[],k=[];for(t=0,i=f.data.labels.length;t<i;++t)k.push(g(f.data.labels[t],h));for(t=0,i=(f.data.datasets||[]).length;t<i;++t)if(f.isDatasetVisible(t))if(l=f.data.datasets[t].data,o.isObject(l[0]))for(y[t]=[],e=0,a=l.length;e<a;++e)u=g(l[e],h),x.push(u),y[t][e]=u;else x.push.apply(x,k),y[t]=k.slice(0);else y[t]=[];k.length&&(k=c(k).sort(d),v=Math.min(v,k[0]),b=Math.max(b,k[k.length-1])),x.length&&(x=c(x).sort(d),v=Math.min(v,x[0]),b=Math.max(b,x[x.length-1])),v=g(p.min,h)||v,b=g(p.max,h)||b,v=v===s?+n().startOf(m):v,b=b===r?+n().endOf(m)+1:b,h.min=Math.min(v,b),h.max=Math.max(v+1,b),h._horizontal=h.isHorizontal(),h._table=[],h._timestamps={data:x,datasets:y,labels:k}},buildTicks:function(){var t,e,i,a,o,r,s,d,c,v,b,x,y=this,k=y.min,M=y.max,w=y.options,S=w.time,C=[],_=[];switch(w.ticks.source){case"data":C=y._timestamps.data;break;case"labels":C=y._timestamps.labels;break;case"auto":default:C=m(k,M,y.getLabelCapacity(k),w)}for("ticks"===w.bounds&&C.length&&(k=C[0],M=C[C.length-1]),k=g(S.min,y)||k,M=g(S.max,y)||M,t=0,e=C.length;t<e;++t)(i=C[t])>=k&&i<=M&&_.push(i);return y.min=k,y.max=M,y._unit=S.unit||function(t,e,i,a){var o,r,s=n.duration(n(a).diff(n(i)));for(o=u.length-1;o>=u.indexOf(e);o--)if(r=u[o],l[r].common&&s.as(r)>=t.length)return r;return u[e?u.indexOf(e):0]}(_,S.minUnit,y.min,y.max),y._majorUnit=p(y._unit),y._table=function(t,e,i,n){if("linear"===n||!t.length)return[{time:e,pos:0},{time:i,pos:1}];var a,o,r,s,l,u=[],d=[e];for(a=0,o=t.length;a<o;++a)(s=t[a])>e&&s<i&&d.push(s);for(d.push(i),a=0,o=d.length;a<o;++a)l=d[a+1],r=d[a-1],s=d[a],void 0!==r&&void 0!==l&&Math.round((l+r)/2)===s||u.push({time:s,pos:a/(o-1)});return u}(y._timestamps.data,k,M,w.distribution),y._offsets=(a=y._table,o=_,r=k,s=M,b=0,x=0,(d=w).offset&&o.length&&(d.time.min||(c=o.length>1?o[1]:s,v=o[0],b=(h(a,"time",c,"pos")-h(a,"time",v,"pos"))/2),d.time.max||(c=o[o.length-1],v=o.length>1?o[o.length-2]:r,x=(h(a,"time",c,"pos")-h(a,"time",v,"pos"))/2)),{left:b,right:x}),y._labelFormat=function(t,e){var i,n,a,o=t.length;for(i=0;i<o;i++){if(0!==(n=f(t[i],e)).millisecond())return"MMM D, YYYY h:mm:ss.SSS a";0===n.second()&&0===n.minute()&&0===n.hour()||(a=!0)}return a?"MMM D, YYYY h:mm:ss a":"MMM D, YYYY"}(y._timestamps.data,S),function(t,e){var i,a,o,r,s=[];for(i=0,a=t.length;i<a;++i)o=t[i],r=!!e&&o===+n(o).startOf(e),s.push({value:o,major:r});return s}(_,y._majorUnit)},getLabelForIndex:function(t,e){var i=this.chart.data,n=this.options.time,a=i.labels&&t<i.labels.length?i.labels[t]:"",r=i.datasets[e].data[t];return o.isObject(r)&&(a=this.getRightValue(r)),n.tooltipFormat?f(a,n).format(n.tooltipFormat):"string"==typeof a?a:f(a,n).format(this._labelFormat)},tickFormatFunction:function(t,e,i,n){var a=this.options,r=t.valueOf(),s=a.time.displayFormats,l=s[this._unit],u=this._majorUnit,d=s[u],c=t.clone().startOf(u).valueOf(),h=a.ticks.major,f=h.enabled&&u&&d&&r===c,g=t.format(n||(f?d:l)),p=f?h:a.ticks.minor,m=o.valueOrDefault(p.callback,p.userCallback);return m?m(g,e,i):g},convertTicksToLabels:function(t){var e,i,a=[];for(e=0,i=t.length;e<i;++e)a.push(this.tickFormatFunction(n(t[e].value),e,t));return a},getPixelForOffset:function(t){var e=this,i=e._horizontal?e.width:e.height,n=e._horizontal?e.left:e.top,a=h(e._table,"time",t,"pos");return n+i*(e._offsets.left+a)/(e._offsets.left+1+e._offsets.right)},getPixelForValue:function(t,e,i){var n=null;if(void 0!==e&&void 0!==i&&(n=this._timestamps.datasets[i][e]),null===n&&(n=g(t,this)),null!==n)return this.getPixelForOffset(n)},getPixelForTick:function(t){var e=this.getTicks();return t>=0&&t<e.length?this.getPixelForOffset(e[t].value):null},getValueForPixel:function(t){var e=this,i=e._horizontal?e.width:e.height,a=e._horizontal?e.left:e.top,o=(i?(t-a)/i:0)*(e._offsets.left+1+e._offsets.left)-e._offsets.right,r=h(e._table,"pos",o,"time");return n(r)},getLabelWidth:function(t){var e=this.options.ticks,i=this.ctx.measureText(t).width,n=o.toRadians(e.maxRotation),r=Math.cos(n),s=Math.sin(n);return i*r+o.valueOrDefault(e.fontSize,a.global.defaultFontSize)*s},getLabelCapacity:function(t){var e=this,i=e.options.time.displayFormats.millisecond,a=e.tickFormatFunction(n(t),0,[],i),o=e.getLabelWidth(a),r=e.isHorizontal()?e.width:e.height,s=Math.floor(r/o);return s>0?s:1}});t.scaleService.registerScaleType("time",e,{position:"bottom",distribution:"linear",bounds:"data",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}})}},{1:1,25:25,45:45}]},{},[7])(7)});
admin/assets/js/bulk-optimozation.js ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($){
2
+ var ajaxUrl = ajaxurl;
3
+
4
+ $('#wio-start-optimization').on('click', function(){
5
+ if ( $(this).hasClass( 'wio-nobackup' ) ) {
6
+ result = confirm( $(this).attr('data-confirm') );
7
+ if ( ! result ) {
8
+ return false;
9
+ }
10
+ }
11
+ $(this).toggleClass( 'wio-running' );
12
+ var cron_mode = 0;
13
+ if ( $(this).hasClass( 'wio-cron-mode' ) ) {
14
+ cron_mode = 1;
15
+ }
16
+ if ( ! cron_mode ) {
17
+ $('#wio-start-msg-top').show();
18
+ }
19
+
20
+ var ai_data = {
21
+ 'action': 'wio_process_images',
22
+ '_wpnonce': $('#wio-iph-nonce').val(),
23
+ 'cron_mode': 0,
24
+ };
25
+ if ( ! cron_mode ) {
26
+ send_post_data(ai_data);
27
+ } else {
28
+ ai_data.cron_mode = 1;
29
+ toggle_cron(ai_data);
30
+ }
31
+
32
+ if ( $(this).hasClass( 'wio-running' ) ) {
33
+ $(this).text( $(this).attr('data-stop') );
34
+ if ( ! cron_mode ) {
35
+ $('#wio-start-msg-top').show();
36
+ }
37
+ } else {
38
+ $(this).text( $(this).attr('data-start') );
39
+ if ( ! cron_mode ) {
40
+ $('#wio-start-msg-top').hide();
41
+ }
42
+ }
43
+ });
44
+
45
+ function send_post_data(data){
46
+ if ( $('#wio-start-optimization').hasClass( 'wio-running' ) ) {
47
+
48
+ $.post(ajaxUrl, data, function(response) {
49
+
50
+ if ( ! response.end ) {
51
+ $('#wio-total-unoptimized').text( response.remain );
52
+ send_post_data(data);
53
+ } else {
54
+ if ( response.msg ) {
55
+ alert( response.msg );
56
+ $('#wio-start-msg-top').hide();
57
+ $('#wio-start-optimization').hide();
58
+ return false;
59
+ }
60
+ $('#wio-total-unoptimized').text( response.remain );
61
+ $('#wio-start-msg-complete').show();
62
+ $('#wio-start-msg-top').hide();
63
+ $('#wio-start-optimization').hide();
64
+ }
65
+ redraw_statistics( response.statistic );
66
+ });
67
+ }
68
+ }
69
+
70
+ function toggle_cron(data) {
71
+ $.post(ajaxUrl, data, function(response) {
72
+
73
+ });
74
+ }
75
+
76
+ function redraw_statistics( statistic ) {
77
+ $('#wio-main-chart').attr('data-unoptimized', statistic.unoptimized )
78
+ .attr('data-optimized', statistic.optimized )
79
+ .attr('data-errors', statistic.error );
80
+ $('#wio-total-optimized-attachments').text(statistic.optimized); // optimized
81
+ $('#wio-original-size').text( bytesToSize( statistic.original_size ) );
82
+ $('#wio-optimized-size').text( bytesToSize( statistic.optimized_size ) );
83
+ $('#wio-total-optimized-attachments-pct').text(statistic.save_size_percent + '%');
84
+ $('#wio-overview-chart-percent').html(statistic.optimized_percent + '<span>%</span>');
85
+ $('.wio-total-percent').text(statistic.optimized_percent + '%');
86
+ $('#wio-optimized-bar').css('width', statistic.percent_line + '%');
87
+
88
+ $('#wio-unoptimized-num').text( statistic.unoptimized );
89
+ $('#wio-optimized-num').text( statistic.optimized );
90
+ $('#wio-error-num').text( statistic.error );
91
+
92
+ window.wio_chart.data.datasets[0].data[0] = statistic.unoptimized; // unoptimized
93
+ window.wio_chart.data.datasets[0].data[1] = statistic.optimized; // optimized
94
+ window.wio_chart.data.datasets[0].data[2] = statistic.error; // errors
95
+ window.wio_chart.update();
96
+ }
97
+
98
+ function bytesToSize(bytes) {
99
+ var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
100
+ if (bytes == 0) return '0 Byte';
101
+ var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
102
+ return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
103
+ }
104
+
105
+ $('#wio-level-buttons button').on('click', function() {
106
+ var ai_data = {
107
+ 'action': 'wio_settings_update_level',
108
+ '_wpnonce': $('#wio-iph-nonce').val(),
109
+ 'level': $(this).attr('data-level')
110
+ };
111
+ $.post(ajaxUrl, ai_data, function(response) {
112
+
113
+ });
114
+ });
115
+
116
+
117
+ });
admin/assets/js/index.php ADDED
File without changes
admin/assets/js/restore-backup.js ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($){
2
+ var ajaxUrl = ajaxurl;
3
+
4
+ $('#wio-restore-backup-btn').on('click', function() {
5
+ result = confirm( $(this).attr('data-confirm') );
6
+ if ( ! result ) {
7
+ return false;
8
+ }
9
+ $(this).hide();
10
+ $('#wio-restore-backup-progress').show();
11
+ var ai_data = {
12
+ 'total' : '?',
13
+ 'action': 'wio_restore_backup',
14
+ '_wpnonce': $('#wio-iph-nonce').val(),
15
+ };
16
+ send_post_data(ai_data);
17
+ return false;
18
+ });
19
+
20
+ $('#wio-clear-backup-btn').on('click', function() {
21
+ $('#wio-restore-backup-msg').hide();
22
+ result = confirm( $(this).attr('data-confirm') );
23
+ if ( ! result ) {
24
+ return false;
25
+ }
26
+ var data = {
27
+ 'action': 'wio_clear_backup',
28
+ '_wpnonce': $('#wio-iph-nonce').val(),
29
+ };
30
+ $.post(ajaxUrl, data, function(response) {
31
+ $('#wio-clear-backup-msg').show();
32
+ });
33
+ });
34
+
35
+ function send_post_data(data){
36
+ $.post(ajaxUrl, data, function(response) {
37
+ if ( ! response.end ) {
38
+ data.total = response.total;
39
+ send_post_data(data);
40
+ $('#wio-restore-backup-progress').find('.progress-bar').css( 'width', response.percent + '%' );
41
+ } else {
42
+ $('#wio-restore-backup-progress').find('.progress-bar').css( 'width', '100%' );
43
+ $('#wio-restore-backup-msg').show();
44
+ }
45
+ });
46
+ }
47
+ });
admin/assets/js/single-optimization.js ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+ var ajaxUrl = ajaxurl;
3
+
4
+ $(document).on('click', '.wio-reoptimize', function() {
5
+ var ai_data = {
6
+ 'action' : 'wio_reoptimize_image',
7
+ 'id' : $(this).attr('data-id'),
8
+ 'level' : $(this).attr('data-level')
9
+ };
10
+ var td = $(this).closest('td');
11
+ var msg = $(this).attr( 'data-waiting-label' );
12
+ td.html('<p>'+msg+'</p>');
13
+ $.post(ajaxUrl, ai_data, function(response) {
14
+ td.html(response);
15
+ var btn = $('.wio-reoptimize').first();
16
+
17
+ if ( btn.closest('.media-frame-content').length ) {
18
+ if ( btn.closest('table').find('.wio-datas-list').length ) {
19
+ var diminsionName = $('.dimensions').find('strong').clone();
20
+ var fileSizeName = $('.file-size').find('strong').clone();
21
+ var diminsionSize = btn.closest('table').find('.wio-datas-list').data('dimensions');
22
+ var fileSize = btn.closest('table').find('.wio-datas-list').data('size');
23
+ $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
24
+ $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
25
+ }
26
+ }
27
+ });
28
+ return false;
29
+ });
30
+
31
+ $(document).on('click', '.button-wio-restore', function() {
32
+ var ai_data = {
33
+ 'action' : 'wio_restore_image',
34
+ 'id' : $(this).attr('data-id')
35
+ };
36
+ var td = $(this).closest('td');
37
+ var msg = $(this).attr( 'data-waiting-label' );
38
+ td.html('<p>'+msg+'</p>');
39
+ $.post(ajaxUrl, ai_data, function(response) {
40
+ td.html(response);
41
+ var btn = $('.wio-reoptimize');
42
+ if ( btn.closest('.media-frame-content').length ) {
43
+ if ( btn.length ) {
44
+ btn = btn.first();
45
+ var diminsionName = $('.dimensions').find('strong').clone();
46
+ var fileSizeName = $('.file-size').find('strong').clone();
47
+ var diminsionSize = btn.data('dimensions');
48
+ var fileSize = btn.data('size');
49
+ $('.dimensions').html(diminsionName.get(0).outerHTML + ' ' + diminsionSize);
50
+ $('.file-size').html(fileSizeName.get(0).outerHTML + ' ' + fileSize);
51
+ }
52
+ }
53
+ });
54
+ return false;
55
+ });
56
+ });
admin/assets/js/statistic.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($) {
2
+
3
+ var chat_html_id = 'wio-main-chart';
4
+ var ctx = document.getElementById( chat_html_id );
5
+ window.wio_chart = new Chart( ctx, {
6
+ type: 'doughnut',
7
+ data: {
8
+ datasets: [{
9
+ data: [
10
+ $( '#' + chat_html_id ).attr( 'data-unoptimized' ),
11
+ $( '#' + chat_html_id ).attr( 'data-optimized' ),
12
+ $( '#' + chat_html_id ).attr( 'data-errors' ),
13
+ ],
14
+ backgroundColor: [
15
+ '#d6d6d6',
16
+ '#8bc34a',
17
+ '#f1b1b6',
18
+ ],
19
+ borderWidth: 0,
20
+ label: 'Dataset 1'
21
+ }],
22
+ },
23
+ options: {
24
+ legend: {
25
+ display: false
26
+ },
27
+ events: [],
28
+ animation: {
29
+ easing: 'easeOutBounce'
30
+ },
31
+ responsive: false,
32
+ cutoutPercentage: 80
33
+ }
34
+ } );
35
+
36
+ });
admin/boot.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin boot
4
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
5
+ * @copyright Webcraftic 25.05.2017
6
+ * @version 1.0
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if( !defined('ABSPATH') ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Виджет отзывов
16
+ *
17
+ * @param string $page_url
18
+ * @param string $plugin_name
19
+ * @return string
20
+ */
21
+ function wio_rating_widget_url($page_url, $plugin_name)
22
+ {
23
+ if( !defined('LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON') && ($plugin_name == WIO_Plugin::app()->getPluginName()) ) {
24
+ return 'https://wordpress.org/support/plugin/robin-image-optimizer/reviews/#new-post';
25
+ }
26
+
27
+ return $page_url;
28
+ }
29
+
30
+ add_filter('wbcr_factory_pages_407_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2);
31
+
32
+
33
+
admin/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php
admin/pages/index.php ADDED
File without changes
admin/pages/log.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The page Error logs
5
+ *
6
+ * @since 1.0.0
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if( !defined('ABSPATH') ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Класс отвечает за работу страницы логов
16
+ * @author Eugene Jokerov <jokerov@gmail.com>
17
+ * @copyright (c) 2018, Webcraftic
18
+ * @version 1.0
19
+ */
20
+ class WIO_LogPage extends Wbcr_FactoryPages407_ImpressiveThemplate {
21
+
22
+ /**
23
+ * The id of the page in the admin menu.
24
+ *
25
+ * Mainly used to navigate between pages.
26
+ * @see FactoryPages407_AdminPage
27
+ *
28
+ * @since 1.0.0
29
+ * @var string
30
+ */
31
+ public $id = 'io_logs'; // Уникальный идентификатор страницы
32
+ public $page_menu_dashicon = 'dashicons-admin-tools'; // Иконка для закладки страницы, дашикон
33
+ public $page_parent_page = null; // Уникальный идентификатор родительской страницы
34
+ public $type = 'page';
35
+
36
+ /**
37
+ * @param Wbcr_Factory406_Plugin $plugin
38
+ */
39
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
40
+ {
41
+ $this->menu_title = __('Error Log', 'robin-image-optimizer');
42
+ parent::__construct($plugin);
43
+ }
44
+
45
+ /**
46
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
47
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
48
+ * @return string
49
+ */
50
+ public function getMenuScope()
51
+ {
52
+ if( defined('WBCR_CLEARFY_PLUGIN_ACTIVE') ) {
53
+ $this->page_parent_page = 'image_optimizer';
54
+
55
+ return 'wbcr_clearfy';
56
+ }
57
+
58
+ return $this->plugin->getPluginName();
59
+ }
60
+
61
+ /**
62
+ * Requests assets (js and css) for the page.
63
+ *
64
+ * @see Wbcr_FactoryPages407_AdminPage
65
+ *
66
+ * @since 1.0.0
67
+ * @return void
68
+ */
69
+ public function assets($scripts, $styles)
70
+ {
71
+ parent::assets($scripts, $styles);
72
+
73
+ // Add Clearfy styles for HMWP pages
74
+ if( defined('WBCR_CLEARFY_PLUGIN_ACTIVE') ) {
75
+ $this->styles->add(WCL_PLUGIN_URL . '/admin/assets/css/general.css');
76
+ }
77
+ }
78
+
79
+ // Метод позволяет менять заголовок меню, в зависимости от сборки плагина.
80
+ public function getMenuTitle()
81
+ {
82
+ return defined('LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON')
83
+ ? __('Image optimizer', 'robin-image-optimizer')
84
+ : __('Error Log', 'robin-image-optimizer');
85
+ }
86
+
87
+ /**
88
+ * Вывод страницы лога
89
+ */
90
+ public function showPageContent()
91
+ {
92
+ $logger = WIO_Plugin::app()->getLogger();
93
+ ?>
94
+ <div class="wbcr-factory-page-group-header" style="margin-top:0;">
95
+ <strong><?php _e('Error Log', 'robin-image-optimizer') ?></strong>
96
+
97
+ <p>
98
+ <?php _e('In this section, you can track image optimization errors. Sending this log to us, will help in solving possible optimization issues.', 'robin-image-optimizer') ?>
99
+ </p>
100
+ </div>
101
+
102
+ <div class="wbcr-factory-page-group-body" style="padding:20px">
103
+ <textarea style="width:70%; height:800px;">
104
+ <?php echo esc_attr($logger->get()); ?>
105
+ </textarea>
106
+ </div>
107
+ <?php
108
+ }
109
+ }
admin/pages/settings.php ADDED
@@ -0,0 +1,415 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The page Settings.
5
+ *
6
+ * @since 1.0.0
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Класс отвечает за работу страницы настроек
16
+ * @author Eugene Jokerov <jokerov@gmail.com>
17
+ * @copyright (c) 2018, Webcraftic
18
+ * @version 1.0
19
+ */
20
+ class WIO_SettingsPage extends Wbcr_FactoryPages407_ImpressiveThemplate {
21
+
22
+ /**
23
+ * The id of the page in the admin menu.
24
+ *
25
+ * Mainly used to navigate between pages.
26
+ * @see FactoryPages407_AdminPage
27
+ *
28
+ * @since 1.0.0
29
+ * @var string
30
+ */
31
+ public $id = 'io_settings'; // Уникальный идентификатор страницы
32
+ public $page_menu_dashicon = 'dashicons-admin-generic'; // Иконка для закладки страницы, дашикон
33
+ public $page_parent_page = null; // Уникальный идентификатор родительской страницы
34
+
35
+ /**
36
+ * @param Wbcr_Factory406_Plugin $plugin
37
+ */
38
+ public function __construct( Wbcr_Factory406_Plugin $plugin ) {
39
+ // Заголовок страницы
40
+ $this->menu_title = __( 'Main Settings', 'robin-image-optimizer' );
41
+ parent::__construct( $plugin );
42
+ $this->hooks();
43
+ }
44
+
45
+ /**
46
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
47
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
48
+ * @return string
49
+ */
50
+ public function getMenuScope() {
51
+ if(defined('WBCR_CLEARFY_PLUGIN_ACTIVE')) {
52
+ $this->page_parent_page = 'image_optimizer';
53
+ return 'wbcr_clearfy';
54
+ }
55
+
56
+ return $this->plugin->getPluginName();
57
+ }
58
+
59
+ public function hooks() {
60
+ add_action( 'wp_ajax_wio_restore_backup', array( $this, 'ajaxRestoreBackup' ) );
61
+ add_action( 'wp_ajax_wio_clear_backup', array( $this, 'ajaxClearBackupDir' ) );
62
+ add_action( 'wp_ajax_wio_settings_update_level', array( $this, 'ajaxUpdateLevel' ) );
63
+ }
64
+
65
+ /**
66
+ * AJAX обработчик массовой оптимизации изображений со страницы статистики
67
+ */
68
+ public function ajaxRestoreBackup() {
69
+ check_admin_referer( 'wio-iph' );
70
+ $max_process_per_request = 5;
71
+ $total = $_POST['total'];
72
+ $media_library = WIO_Plugin::app()->getMediaLibrary();
73
+ if ( $total == '?' ) {
74
+ $total = $media_library->getOptimizedCount();
75
+ }
76
+ $restored_data = $media_library->restoreAllFromBackup( $max_process_per_request );
77
+
78
+ $restored_data['total'] = $total;
79
+ if ( $total ) {
80
+ $restored_data['percent'] = 100 - ( $restored_data['remain'] * 100 / $total );
81
+ } else {
82
+ $restored_data['percent'] = 0;
83
+ }
84
+ // если изображения закончились - посылаем команду завершения
85
+ if ( $restored_data['remain'] <= 0 ) {
86
+ $restored_data['end'] = true;
87
+ }
88
+ wp_send_json( $restored_data );
89
+ }
90
+
91
+ /**
92
+ * AJAX обработчик очистки папки с бекапами
93
+ */
94
+ public function ajaxClearBackupDir() {
95
+ check_admin_referer( 'wio-iph' );
96
+ $backup = WIO_Plugin::app()->getBackup();
97
+ $backup->removeBackupDir();
98
+ wp_send_json( true );
99
+ }
100
+
101
+ /**
102
+ * AJAX обработчик массовой сохранения уровня сжатия
103
+ */
104
+ public function ajaxUpdateLevel() {
105
+ check_admin_referer( 'wio-iph' );
106
+ $level = $_POST['level'];
107
+ if ( ! $level ) {
108
+ die();
109
+ }
110
+ if ( ! in_array( $level, array( 'normal', 'aggresive', 'ultra' ) ) ) {
111
+ die();
112
+ }
113
+ WIO_Plugin::app()->updateOption( 'image_optimization_level' , $level );
114
+ die();
115
+ }
116
+
117
+ /**
118
+ * Подключаем скрипты и стили для страницы
119
+ *
120
+ * @see Wbcr_FactoryPages407_AdminPage
121
+ *
122
+ * @since 1.0.0
123
+ * @return void
124
+ */
125
+ public function assets( $scripts, $styles ) {
126
+ parent::assets( $scripts, $styles );
127
+ $this->scripts->add( WIO_PLUGIN_URL . '/admin/assets/js/restore-backup.js' );
128
+
129
+ // Add Clearfy styles for HMWP pages
130
+ if( defined('WBCR_CLEARFY_PLUGIN_ACTIVE') ) {
131
+ $this->styles->add(WCL_PLUGIN_URL . '/admin/assets/css/general.css');
132
+ }
133
+ }
134
+
135
+
136
+ /**
137
+ * Выводим предупреждения
138
+ *
139
+ */
140
+ protected function warningNotice() {
141
+ $upload_dir = wp_upload_dir();
142
+ if ( ! is_writable( $upload_dir['basedir'] ) ) {
143
+ $this->printErrorNotice( __( 'Folder wp-content/uploads/ is unavailable for writing', 'robin-image-optimizer' ) );
144
+ }
145
+ $wio_backup = $upload_dir['basedir'] . '/wio_backup/';
146
+ if ( file_exists( $wio_backup ) and ! is_writable( $wio_backup ) ) {
147
+ $this->printErrorNotice( __( 'Folder wp-content/uploads/wio-backup/ is unavailable for writing', 'robin-image-optimizer' ) );
148
+ }
149
+ if ( defined( 'DISABLE_WP_CRON' ) and DISABLE_WP_CRON == true ) {
150
+ $this->printErrorNotice( __( 'Cron is disabled in wp-config.php', 'robin-image-optimizer' ) );
151
+ }
152
+ }
153
+
154
+
155
+ /**
156
+ * Метод должен передать массив опций для создания формы с полями.
157
+ * Созданием страницы и формы занимается фреймворк
158
+ *
159
+ * @since 1.0.0
160
+ * @return mixed[]
161
+ */
162
+ public function getOptions() {
163
+ $options = array();
164
+
165
+ $options[] = array(
166
+ 'type' => 'html',
167
+ 'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Main Settings', 'robin-image-optimizer' ) . '</strong><p>' . __( 'This section you can set main images optimization settings.', 'robin-image-optimizer' ) . '</p></div>'
168
+ );
169
+
170
+ // Радио переключатель
171
+ $options[] = array(
172
+ 'type' => 'dropdown',
173
+ 'name' => 'image_optimization_level',
174
+ 'way' => 'buttons',
175
+ 'title' => __( 'Compression mode', 'robin-image-optimizer' ),
176
+ 'data' => array(
177
+ array(
178
+ 'normal',
179
+ __( 'Normal', 'robin-image-optimizer' ),
180
+ __( 'This mode provides lossless compression and your images will be optimized without visible changes. If you want an ideal image quality, we recommend this mode. The size of the files will be reduced approximately 2 times. If this is not enough for you, try other modes.', 'robin-image-optimizer' )
181
+ ),
182
+ array(
183
+ 'aggresive',
184
+ __( 'Medium', 'robin-image-optimizer' ),
185
+ __( 'This mode provides an ideal optimization of your images without significant quality loss. The file size will be reduced approximately 5 times with a slight decrease in image quality. In most cases that cannot be seen with the naked eye.', 'robin-image-optimizer' )
186
+ ),
187
+ array(
188
+ 'ultra',
189
+ __( 'High', 'robin-image-optimizer' ),
190
+ __( 'This mode will use all available optimization methods for maximum image compression. The file size will be reduced approximately 7 times. The quality of some images may deteriorate slightly. Use this mode if you need the maximum weight reduction, and you are ready to accept the loss of image quality.', 'robin-image-optimizer' )
191
+ )
192
+ ),
193
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
194
+ 'hint' => __( 'Select the compression mode appropriate for your case.', 'robin-image-optimizer' ),
195
+ 'default' => 'normal',
196
+ /*'events' => array(
197
+ 'disable_certain_post_types_comments' => array(
198
+ 'show' => '.factory-control-disable_comments_for_post_types, #wbcr-clearfy-comments-base-options'
199
+ ),
200
+ 'enable_comments' => array(
201
+ 'show' => '#wbcr-clearfy-comments-base-options',
202
+ 'hide' => '.factory-control-disable_comments_for_post_types'
203
+ ),
204
+ 'disable_comments' => array(
205
+ 'hide' => '.factory-control-disable_comments_for_post_types, #wbcr-clearfy-comments-base-options'
206
+ )
207
+ )*/
208
+ );
209
+
210
+ // Переключатель
211
+ $options[] = array(
212
+ 'type' => 'checkbox',
213
+ 'way' => 'buttons',
214
+ 'name' => 'auto_optimize_when_upload',
215
+ 'title' => __( 'Auto optimization on upload', 'robin-image-optimizer' ),
216
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
217
+ 'hint' => __( 'Automatically compress all images that you upload directly to the WordPress media library, when editing pages and posts or using themes and plugins.', 'robin-image-optimizer' ),
218
+ 'default' => false
219
+ );
220
+
221
+ // Переключатель
222
+ $options[] = array(
223
+ 'type' => 'checkbox',
224
+ 'way' => 'buttons',
225
+ 'name' => 'backup_origin_images',
226
+ 'title' => __( 'Backup images', 'robin-image-optimizer' ),
227
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
228
+ 'hint' => __( 'Before optimizing, all your images will be saved in a separate folder for future recovery.', 'robin-image-optimizer' ),
229
+ 'default' => true
230
+ );
231
+
232
+ // Переключатель
233
+ $options[] = array(
234
+ 'type' => 'checkbox',
235
+ 'way' => 'buttons',
236
+ 'name' => 'error_log',
237
+ 'title' => __( 'Error Log', 'robin-image-optimizer' ),
238
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
239
+ 'hint' => __( 'Enable error logging. The log will be displayed on a separate tab.', 'robin-image-optimizer' ),
240
+ 'default' => false
241
+ );
242
+
243
+ // восстановление
244
+ $options[] = array(
245
+ 'type' => 'html',
246
+ 'html' => array( $this, 'rollbackButton' ),
247
+ );
248
+
249
+ // Переключатель
250
+ $options[] = array(
251
+ 'type' => 'checkbox',
252
+ 'way' => 'buttons',
253
+ 'name' => 'save_exif_data',
254
+ 'title' => __( 'Leave EXIF data', 'robin-image-optimizer' ),
255
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
256
+ 'hint' => __( 'EXIF is information stored in photos: camera model, shutter speed, exposure compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended data. If your project is dedicated to photography and you need to display this data, then enable this option.', 'robin-image-optimizer' ),
257
+ 'default' => true
258
+ );
259
+
260
+ $options[] = array(
261
+ 'type' => 'html',
262
+ 'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Here you can specify additional image optimization options.', 'robin-image-optimizer' ) . '</p></div>'
263
+ );
264
+
265
+ // Переключатель
266
+ $options[] = array(
267
+ 'type' => 'checkbox',
268
+ 'way' => 'buttons',
269
+ 'name' => 'resize_larger',
270
+ 'title' => __( 'Resizing large images', 'robin-image-optimizer' ),
271
+ 'layout' => array('hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
272
+ 'hint' => __( 'When you upload images from a camera or stock, they may be too high resolution and it is not necessary for web. The option allows you to automatically change images resolution on upload.', 'robin-image-optimizer' ),
273
+ 'default' => false,
274
+ // когда чекбокс включен показываем поле с классом .factory-control-resize_larger_w
275
+ 'eventsOn' => array(
276
+ 'show' => '.factory-control-resize_larger_w'
277
+ ),
278
+ // когда чекбокс выключен, скрываем поле с классом .factory-control-resize_larger_w
279
+ 'eventsOff' => array(
280
+ 'hide' => '.factory-control-resize_larger_w'
281
+ )
282
+ );
283
+
284
+ // Текстовое поле
285
+ $options[] = array(
286
+ 'type' => 'textbox',
287
+ 'name' => 'resize_larger_w',
288
+ 'title' => __( 'Enter the maximum size (px)', 'robin-image-optimizer' ),
289
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
290
+ 'hint' => __( 'Set the maximum images resolution on the long side. For horizontal images, this will be the width, and for vertical images - the height. The resolution of the images will be changed proportionally according to the set value.', 'robin-image-optimizer' ),
291
+ 'default' => '1600'
292
+ );
293
+
294
+ // получаем зарегистрированные размеры изображений
295
+ $wp_image_sizes = wio_get_image_sizes();
296
+ $wio_image_sizes = array();
297
+ foreach( $wp_image_sizes as $key => $value ) {
298
+ $wio_image_sizes[] = array(
299
+ $key,
300
+ $key . ' - ' . $value['width'] . 'x' . $value['height'],
301
+ );
302
+ }
303
+
304
+ $options[] = array(
305
+ 'type' => 'list',
306
+ 'way' => 'checklist',
307
+ 'name' => 'allowed_sizes_thumbnail',
308
+ 'title' => __( 'Optimize thumbnails', 'robin-image-optimizer' ),
309
+ 'data' => $wio_image_sizes,
310
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
311
+ 'hint' => __( 'Choose which sizes of thumbnails should be optimized and uncheck those that do not need optimization.', 'robin-image-optimizer' ),
312
+ 'default' => 'thumbnail,medium'
313
+ );
314
+
315
+ // cron
316
+ $options[] = array(
317
+ 'type' => 'html',
318
+ 'html' => '<div class="wbcr-factory-page-group-header"><strong>' . __( 'Scheduled optimization', 'robin-image-optimizer' ) . '</strong><p>' . __( 'Schedule your images optimization.', 'robin-image-optimizer' ) . '</p></div>'
319
+ );
320
+
321
+ // автооптимизация
322
+ $options[] = array(
323
+ 'type' => 'checkbox',
324
+ 'way' => 'buttons',
325
+ 'name' => 'image_autooptimize_mode',
326
+ 'title' => __( 'Enable Scheduled Optimization', 'robin-image-optimizer' ),
327
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
328
+ 'hint' => __( 'You can enable image optimization on schedule. The plugin will optimize specified number of images automatically after selected time.', 'robin-image-optimizer' ),
329
+ 'default' => false,
330
+ 'eventsOn' => array(
331
+ 'show' => '#wbcr-io-shedule-options'
332
+ ),
333
+ 'eventsOff' => array(
334
+ 'hide' => '#wbcr-io-shedule-options'
335
+ )
336
+ );
337
+
338
+ $group_items[] = array(
339
+ 'type' => 'dropdown',
340
+ 'way' => 'buttons',
341
+ 'name' => 'image_autooptimize_shedule_time',
342
+ 'data' => array(
343
+ array( 'wio_1_min', __( '1 min', 'robin-image-optimizer' ) ),
344
+ array( 'wio_2_min', __( '2 min', 'robin-image-optimizer' ) ),
345
+ array( 'wio_5_min', __( '5 min', 'robin-image-optimizer' ) ),
346
+ array( 'wio_10_min', __( '10 min', 'robin-image-optimizer' ) ),
347
+ array( 'wio_30_min', __( '30 min', 'robin-image-optimizer' ) ),
348
+ array( 'wio_hourly', __( 'Hour', 'robin-image-optimizer' ) ),
349
+ array( 'wio_daily', __( 'Day', 'robin-image-optimizer' ) ),
350
+ ),
351
+ 'default' => 'wio_5_min',
352
+ 'title' => __( 'Run every', 'robin-image-optimizer' ),
353
+ 'hint' => __( 'Select time at which the task will be repeated.', 'robin-image-optimizer' )
354
+ );
355
+
356
+
357
+ $group_items[] = array(
358
+ 'type' => 'textbox',
359
+ 'name' => 'image_autooptimize_items_number_per_interation',
360
+ 'title' => __( 'Images per iteration', 'robin-image-optimizer' ),
361
+ 'layout' => array( 'hint-type' => 'icon', 'hint-icon-color' => 'grey' ),
362
+ 'hint' => __( 'Specify the number of images that will be optimized during the job. For example, if you enter 5 and select 5 min, the plugin will optimize 5 images every 5 minutes.', 'robin-image-optimizer' ),
363
+ 'default' => '3'
364
+ );
365
+
366
+ $options[] = array(
367
+ 'type' => 'div',
368
+ 'id' => 'wbcr-io-shedule-options',
369
+ 'items' => $group_items
370
+ );
371
+
372
+ $formOptions = array();
373
+
374
+ $formOptions[] = array(
375
+ 'type' => 'form-group',
376
+ 'items' => $options,
377
+ //'cssClass' => 'postbox'
378
+ );
379
+
380
+ return apply_filters( 'wbcr_wio_settings_form_options', $formOptions );
381
+ }
382
+
383
+ /**
384
+ * Кнопка восстановления изображений
385
+ *
386
+ */
387
+ public function rollbackButton() {
388
+ ?>
389
+ <div class="form-group form-group-checkbox factory-control-save_exif_data">
390
+ <label for="wbcr_io_save_exif_data" class="col-sm-6 control-label">
391
+ <?php _e( 'Manage backups', 'robin-image-optimizer' ); ?>
392
+ <span class="factory-hint-icon factory-hint-icon-grey" data-toggle="factory-tooltip" data-placement="right" title="" data-original-title="<?php _e( 'You can restore the original images from a backup or clear them.', 'robin-image-optimizer' ); ?>">
393
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt="">
394
+ </span>
395
+ </label>
396
+ <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
397
+ <div class="control-group col-sm-6">
398
+ <div class="factory-buttons-way btn-group">
399
+ <a class="btn btn-default" id="wio-restore-backup-btn" data-confirm="<?php _e( 'Are you sure?', 'robin-image-optimizer' ); ?>" href="#"><?php _e( 'Restore', 'robin-image-optimizer' ); ?></a>
400
+ <a class="btn btn-default" id="wio-clear-backup-btn" data-confirm="<?php _e( 'Are you sure that you want to clear image backups folder?', 'robin-image-optimizer' ); ?>" href="#"><?php _e( 'Clear Backup', 'robin-image-optimizer' ); ?></a>
401
+ </div>
402
+ <div class="progress" id="wio-restore-backup-progress" style="display:none;">
403
+ <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">
404
+
405
+ </div>
406
+ </div>
407
+ <p id="wio-restore-backup-msg" style="display:none;"><?php _e( 'Restore completed.', 'robin-image-optimizer' ); ?></p>
408
+ <p id="wio-clear-backup-msg" style="display:none;"><?php _e( 'The backup folder was cleared.', 'robin-image-optimizer' ); ?></p>
409
+ </div>
410
+ </div>
411
+
412
+ <?php
413
+ }
414
+
415
+ }
admin/pages/statistic.php ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The page Settings.
5
+ *
6
+ * @since 1.0.0
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ /**
15
+ * Класс отвечает за работу страницы статистики
16
+ * @author Eugene Jokerov <jokerov@gmail.com>
17
+ * @copyright (c) 2018, Webcraftic
18
+ * @version 1.0
19
+ */
20
+ class WIO_StatisticPage extends Wbcr_FactoryPages407_ImpressiveThemplate {
21
+
22
+ /**
23
+ * The id of the page in the admin menu.
24
+ *
25
+ * Mainly used to navigate between pages.
26
+ * @see FactoryPages407_AdminPage
27
+ *
28
+ * @since 1.0.0
29
+ * @var string
30
+ */
31
+ public $id = 'image_optimizer'; // Уникальный идентификатор страницы
32
+ public $type = 'page'; // Этот произвольный тип страницы
33
+ public $plugin;
34
+
35
+ /**
36
+ * @var int
37
+ */
38
+ public $page_menu_position = 20;
39
+ public $page_parent_page = null; // Уникальный идентификатор родительской страницы
40
+ public $page_menu_dashicon = 'dashicons-chart-line'; // Иконка для закладки страницы, дашикон
41
+
42
+ /**
43
+ * @param Wbcr_Factory406_Plugin $plugin
44
+ */
45
+ public function __construct( Wbcr_Factory406_Plugin $plugin ) {
46
+ $this->menu_title = __( 'Robin image optimizer', 'robin-image-optimizer' );
47
+
48
+ // Если плагин загружен, как самостоятельный, то мы меняем настройки страницы и делаем ее внешней,
49
+ // а не внутренней страницей родительского плагина. Внешнии страницы добавляются в Wordpress меню "Общие"
50
+
51
+ if( ! defined( 'LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON' ) ) {
52
+ // true - внутреняя, false- внешняя страница
53
+ $this->internal = false;
54
+ // меню к которому, нужно прикрепить ссылку на страницу
55
+ $this->menu_target = 'options-general.php';
56
+ // Если true, добавляет ссылку "Настройки", рядом с действиями активации, деактивации плагина, на странице плагинов.
57
+ $this->add_link_to_plugin_actions = true;
58
+ }
59
+
60
+ $this->plugin = $plugin;
61
+ $this->hooks();
62
+
63
+ parent::__construct( $plugin );
64
+
65
+ }
66
+
67
+ /**
68
+ * Подменяем простраинство имен для меню плагина, если активирован плагин Clearfy
69
+ * Меню текущего плагина будет добавлено в общее меню Clearfy
70
+ * @return string
71
+ */
72
+ public function getMenuScope() {
73
+ if(defined('WBCR_CLEARFY_PLUGIN_ACTIVE')) {
74
+ $this->internal = true;
75
+ return 'wbcr_clearfy';
76
+ }
77
+
78
+ return $this->plugin->getPluginName();
79
+ }
80
+
81
+ // Метод позволяет менять заголовок меню, в зависимости от сборки плагина.
82
+ public function getMenuTitle() {
83
+ return defined('WBCR_CLEARFY_PLUGIN_ACTIVE')
84
+ ? __( 'Image optimizer', 'robin-image-optimizer' )
85
+ : __( 'General', 'robin-image-optimizer' );
86
+ }
87
+
88
+ /**
89
+ * Устанавливаем хуки
90
+ */
91
+ public function hooks() {
92
+ add_action( 'wp_ajax_wio_process_images', array( $this, 'ajaxProcessImages' ) );
93
+ add_action( 'wbcr_clearfy_quick_boards', array( $this, 'widget' ) );
94
+ add_action( 'wbcr_clearfy_page_enqueue_scripts', array($this, 'registerWidgetScripts'), 10, 3 );
95
+ }
96
+
97
+
98
+ /**
99
+ * AJAX обработчик массовой оптимизации изображений со страницы статистики
100
+ */
101
+ public function ajaxProcessImages() {
102
+ $cron_mode = (bool) $_REQUEST['cron_mode'];
103
+ if ( $cron_mode ) {
104
+ $cron_running = WIO_Plugin::app()->getOption( 'cron_running', false );
105
+ if ( $cron_running ) {
106
+ WIO_Plugin::app()->updateOption( 'cron_running', false );
107
+ } else {
108
+ WIO_Plugin::app()->updateOption( 'cron_running', true );
109
+ }
110
+ wp_send_json( true );
111
+ die();
112
+ }
113
+ $max_process_per_request = 5;
114
+ $media_library = WIO_Plugin::app()->getMediaLibrary();
115
+ $optimized_data = $media_library->processUnoptimizedAttachments( $max_process_per_request );
116
+
117
+ // если изображения закончились - посылаем команду завершения
118
+ if ( $optimized_data['remain'] <= 0 ) {
119
+ $optimized_data['end'] = true;
120
+ }
121
+ wp_send_json( $optimized_data );
122
+ }
123
+
124
+ /**
125
+ * Подключаем скрипты и стили для страницы
126
+ *
127
+ * @see Wbcr_FactoryPages407_AdminPage
128
+ *
129
+ * @since 1.0.0
130
+ * @return void
131
+ */
132
+ public function assets($scripts, $styles) {
133
+ parent::assets($scripts, $styles);
134
+
135
+ $this->styles->add( WIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
136
+
137
+ $this->scripts->add( WIO_PLUGIN_URL . '/admin/assets/js/Chart.min.js' );
138
+ $this->scripts->add( WIO_PLUGIN_URL . '/admin/assets/js/statistic.js' );
139
+ $this->scripts->add( WIO_PLUGIN_URL . '/admin/assets/js/bulk-optimozation.js' );
140
+
141
+ // Add Clearfy styles for HMWP pages
142
+ if( defined('WBCR_CLEARFY_PLUGIN_ACTIVE') ) {
143
+ $this->styles->add(WCL_PLUGIN_URL . '/admin/assets/css/general.css');
144
+ }
145
+ }
146
+
147
+
148
+
149
+ /**
150
+ * Prints the content of the page
151
+ *
152
+ * @see libs\factory\pages\themplates\FactoryPages407_ImpressiveThemplate
153
+ */
154
+ public function showPageContent() {
155
+ ?>
156
+ <?php
157
+ $statistics = WIO_Plugin::app()->getImageStatistics();
158
+ $image_statistics = $statistics->get();
159
+ $backup_origin_images = WIO_Plugin::app()->getOption( 'backup_origin_images', false );
160
+ $logger = WIO_Plugin::app()->getLogger();
161
+ //$logger->add( 'Тестовая ошибка' );
162
+ ?>
163
+ <div class="wbcr-factory-page-group-header" style="margin-top:0;">
164
+ <strong><?php _e( 'Image optimization dashboard', 'robin-image-optimizer' ) ?></strong>
165
+
166
+ <p>
167
+ <?php _e( 'Monitor image optimization statistics and run on demand or scheduled optimization.', 'robin-image-optimizer' ) ?>
168
+ </p>
169
+ </div>
170
+
171
+ <div class="wbcr-factory-page-group-body" style="padding:20px">
172
+
173
+ <div class="wio-columns wio-page-statistic">
174
+
175
+ <div>
176
+ <div class="wio-chart-container wio-overview-chart-container">
177
+ <canvas id="wio-main-chart" width="180" height="180" data-unoptimized="<?php echo esc_attr( $image_statistics['unoptimized'] ); ?>" data-optimized="<?php echo esc_attr( $image_statistics['optimized'] ); ?>" data-errors="<?php echo esc_attr( $image_statistics['error'] ); ?>" style="display: block;"></canvas>
178
+ <div id="wio-overview-chart-percent" class="wio-chart-percent"><?php echo esc_attr( $image_statistics['optimized_percent'] ); ?><span>%</span></div>
179
+ <p class="wio-global-optim-phrase wio-clear">
180
+ <?php _e( 'You optimized', 'robin-image-optimizer' ); ?> <span class="wio-total-percent"><?php echo esc_attr( $image_statistics['optimized_percent'] ); ?>%</span> <?php _e( "of your website's images", 'robin-image-optimizer' ); ?>
181
+ </p>
182
+ </div>
183
+
184
+ <div style="margin-left:200px;">
185
+ <div id="wio-overview-chart-legend">
186
+ <ul class="wio-doughnut-legend">
187
+ <li><span style="background-color:#d6d6d6"></span><?php _e( 'Unoptimized', 'robin-image-optimizer' ); ?> - <span class="wio-num" id="wio-unoptimized-num"><?php echo esc_attr( $image_statistics['unoptimized'] ); ?></span></li>
188
+ <li><span style="background-color:#8bc34a"></span><?php _e( 'Optimized', 'robin-image-optimizer' ); ?> - <span class="wio-num" id="wio-optimized-num"><?php echo esc_attr( $image_statistics['optimized'] ); ?></span></li>
189
+ <li><span style="background-color:#f1b1b6"></span><?php _e( 'Error', 'robin-image-optimizer' ); ?> - <span class="wio-num" id="wio-error-num"><?php echo esc_attr( $image_statistics['error'] ); ?></span></li>
190
+ </ul>
191
+ </div>
192
+ <h3 class="screen-reader-text"><?php _e( 'Statistics', 'robin-image-optimizer' ); ?></h3>
193
+
194
+ <!--<div class="wio-number-you-optimized">
195
+ <p>
196
+ <span id="wio-total-optimized-attachments" class="wio-number"><?php echo esc_attr( $image_statistics['optimized'] ); ?></span>
197
+ <span class="wio-text">
198
+ <?php _e( "that's the number of original images<br> you optimized with Image Optimizer", 'robin-image-optimizer' ); ?>
199
+ </span>
200
+ </p>
201
+ </div>-->
202
+
203
+ <div class="wio-bars" style="width: 90%">
204
+ <p><?php _e( 'Original size', 'robin-image-optimizer' ); ?></p>
205
+ <div class="wio-bar-negative base-transparent wio-right-outside-number">
206
+ <div id="wio-original-bar" class="wio-progress" style="width: 100%"><span class="wio-barnb" id="wio-original-size"><?php echo esc_attr( $statistics->convertToReadableSize( $image_statistics['original_size'] ) ); ?></span></div>
207
+ </div>
208
+
209
+ <p><?php _e( 'Optimized size', 'robin-image-optimizer' ); ?></p>
210
+ <div class="wio-bar-primary base-transparent wio-right-outside-number">
211
+ <div id="wio-optimized-bar" class="wio-progress" style="width: <?php echo ( $image_statistics['percent_line'] ) ? esc_attr( $image_statistics['percent_line'] ) : 100; ?>%"><span class="wio-barnb" id="wio-optimized-size"><?php echo esc_attr( $statistics->convertToReadableSize( $image_statistics['optimized_size'] ) ); ?></span></div>
212
+ </div>
213
+
214
+ </div>
215
+
216
+ <div class="wio-number-you-optimized">
217
+ <p>
218
+ <span id="wio-total-optimized-attachments-pct" class="wio-number"><?php echo esc_attr( $image_statistics['save_size_percent'] ); ?>%</span>
219
+ <span class="wio-text">
220
+ <?php _e( "that's the size you saved <br>by using Image Optimizer", 'robin-image-optimizer' ); ?>
221
+ </span>
222
+ </p>
223
+ </div>
224
+ </div>
225
+ </div>
226
+
227
+ <div>
228
+ <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
229
+
230
+ <p>
231
+ <?php $this->button(); ?>
232
+ <span id="wio-start-msg-complete"><?php _e( 'All images from the media library are optimized.', 'robin-image-optimizer' ); ?></span>
233
+ </p>
234
+ <p id="wio-start-msg-top"><?php _e( 'Optimization in progress. Remained', 'robin-image-optimizer' ); ?> <span id="wio-total-unoptimized"><?php echo esc_attr( $image_statistics['unoptimized'] ); ?></span> <?php _e( 'images.', 'robin-image-optimizer' ); ?></p>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ <?php
239
+ }
240
+
241
+ /**
242
+ * Кнопка запуска оптимизации
243
+ *
244
+ */
245
+ public function button() {
246
+ $backup_origin_images = WIO_Plugin::app()->getOption( 'backup_origin_images', false );
247
+ $is_cron_mode = WIO_Plugin::app()->getOption( 'image_autooptimize_mode', false );
248
+ $button_classes = array(
249
+ 'wio-optimize-button'
250
+ );
251
+ if( ! $backup_origin_images ) {
252
+ $button_classes[] = 'wio-nobackup';
253
+ }
254
+ $button_name = __( 'Run', 'robin-image-optimizer' );
255
+ if( $is_cron_mode ) {
256
+ $button_classes[] = 'wio-cron-mode';
257
+ $cron_running = WIO_Plugin::app()->getOption( 'cron_running', false );
258
+ if ( $cron_running ) {
259
+ $button_classes[] = 'wio-running';
260
+ $button_name = __( 'Stop', 'robin-image-optimizer' );
261
+ } else {
262
+ $button_name = __( 'Run', 'robin-image-optimizer' );
263
+ }
264
+ }
265
+ ?>
266
+ <button type="button" id="wio-start-optimization" data-confirm="<?php _e( 'Do you want to start optimization without backup?', 'robin-image-optimizer' ); ?>" data-start="<?php _e( 'Resume', 'robin-image-optimizer' ); ?>" data-stop="<?php _e( 'Stop', 'robin-image-optimizer' ); ?>" class="<?php echo join( ' ', $button_classes ); ?>"><?php echo esc_attr( $button_name ); ?></button>
267
+ <?php
268
+ }
269
+
270
+ /**
271
+ * @param string $page_id
272
+ * @param Wbcr_Factory406_ScriptList $scripts
273
+ * @param Wbcr_Factory406_StyleList $styles
274
+ */
275
+ public function registerWidgetScripts($page_id, $scripts, $styles) {
276
+ if($page_id == 'quick_start-wbcr_clearfy') {
277
+ // Add scripts
278
+ $scripts->add(WIO_PLUGIN_URL . '/admin/assets/js/Chart.min.js');
279
+ $scripts->add(WIO_PLUGIN_URL . '/admin/assets/js/bulk-optimozation.js');
280
+ $scripts->add(WIO_PLUGIN_URL . '/admin/assets/js/statistic.js');
281
+
282
+ // Add styles
283
+ $styles->add(WIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css');
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Виджет для clearfy
289
+ *
290
+ */
291
+ public function widget() {
292
+
293
+ $statistics = WIO_Plugin::app()->getImageStatistics();
294
+ $image_statistics = $statistics->get();
295
+ $backup_origin_images = WIO_Plugin::app()->getOption( 'backup_origin_images', false );
296
+ $default_level = WIO_Plugin::app()->getOption( 'image_optimization_level' , 'normal' );
297
+ ?>
298
+
299
+ <div class="col-sm-12">
300
+ <div class="wio-image-optimize-board wbcr-clearfy-board">
301
+ <h4 class="wio-text-left"><?php _e( 'Images optimization', 'robin-image-optimizer' ); ?></h4>
302
+ <div class="wio-columns wio-widget">
303
+
304
+
305
+ <div class="wio-col col-chart">
306
+ <div class="wio-chart-container wio-overview-chart-container">
307
+ <canvas id="wio-main-chart" width="130" height="130" data-unoptimized="<?php echo esc_attr( $image_statistics['unoptimized'] ); ?>" data-optimized="<?php echo esc_attr( $image_statistics['optimized'] ); ?>" data-errors="<?php echo esc_attr( $image_statistics['error'] ); ?>" style="display: block;"></canvas>
308
+ <div id="wio-overview-chart-percent" class="wio-chart-percent"><?php echo esc_attr( $image_statistics['optimized_percent'] ); ?><span>%</span></div>
309
+ </div>
310
+ <div id="wio-overview-chart-legend">
311
+ <ul class="wio-doughnut-legend">
312
+ <li><span style="background-color:#d6d6d6"></span><?php _e( 'Unoptimized', 'robin-image-optimizer' ); ?> - <span class="wio-num" id="wio-unoptimized-num"><?php echo esc_attr( $image_statistics['unoptimized'] ); ?></span></li>
313
+ <li><span style="background-color:#8bc34a"></span><?php _e( 'Optimized', 'robin-image-optimizer' ); ?> - <span class="wio-num" id="wio-optimized-num"><?php echo esc_attr( $image_statistics['optimized'] ); ?></span></li>
314
+ <li><span style="background-color:#f1b1b6"></span><?php _e( 'Error', 'robin-image-optimizer' ); ?> - <span class="wio-num" id="wio-error-num"><?php echo esc_attr( $image_statistics['error'] ); ?></span></li>
315
+ </ul>
316
+ </div>
317
+ <div class="wio-bars">
318
+ <p><?php _e( 'Original size', 'robin-image-optimizer' ); ?></p>
319
+ <div class="wio-bar-negative base-transparent wio-right-outside-number">
320
+ <div id="wio-original-bar" class="wio-progress" style="width: 100%"><span class="wio-barnb" id="wio-original-size"><?php echo esc_attr( $statistics->convertToReadableSize( $image_statistics['original_size'] ) ); ?></span></div>
321
+ </div>
322
+
323
+ <p><?php _e( 'Optimized size', 'robin-image-optimizer' ); ?></p>
324
+ <div class="wio-bar-primary base-transparent wio-right-outside-number">
325
+ <div id="wio-optimized-bar" class="wio-progress" style="width: <?php echo ( $image_statistics['percent_line'] ) ? esc_attr( $image_statistics['percent_line'] ) : 100; ?>%"><span class="wio-barnb" id="wio-optimized-size"><?php echo esc_attr( $statistics->convertToReadableSize( $image_statistics['optimized_size'] ) ); ?></span></div>
326
+ </div>
327
+
328
+ </div>
329
+ </div>
330
+ <ul class="wio-widget-bottom">
331
+ <li>
332
+ <input type="hidden" value="<?php echo wp_create_nonce( 'wio-iph' ) ?>" id="wio-iph-nonce">
333
+
334
+ <p>
335
+ <?php $this->button(); ?>
336
+ <span id="wio-start-msg-complete"><?php _e( 'All images from the media library are optimized.', 'robin-image-optimizer' ); ?></span>
337
+ </p>
338
+ <p id="wio-start-msg-top"><?php _e( 'Optimization in progress. Remained', 'robin-image-optimizer' ); ?> <span id="wio-total-unoptimized"><?php echo esc_attr( $image_statistics['unoptimized'] ); ?></span></p>
339
+ </li>
340
+ <li>
341
+
342
+ <div class="factory-dropdown factory-from-control-dropdown factory-buttons-way" data-way="buttons">
343
+ <div id="wio-level-buttons" class="btn-group factory-buttons-group">
344
+ <button type="button" data-level="normal" class="btn btn-default btn-small <?php if( $default_level == 'normal' ) : ?>active<?php endif; ?>"><?php _e( 'Normal', 'robin-image-optimizer' ); ?></button>
345
+ <button type="button" data-level="aggresive" class="btn btn-default btn-small <?php if( $default_level == 'aggresive' ) : ?>active<?php endif; ?>"><?php _e( 'Medium', 'robin-image-optimizer' ); ?></button>
346
+ <button type="button" data-level="ultra" class="btn btn-default btn-small <?php if( $default_level == 'ultra' ) : ?>active<?php endif; ?>"><?php _e( 'High', 'robin-image-optimizer' ); ?></button>
347
+ </div>
348
+ </div>
349
+ </li>
350
+ </ul>
351
+ </div>
352
+ </div>
353
+ </div>
354
+ <?php
355
+ }
356
+
357
+ }
includes/class.plugin.php ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Основной класс плагина
4
+ * @author Webcraftic <wordpress.webraftic@gmail.com>
5
+ * @copyright (c) 19.02.2018, Webcraftic
6
+ * @version 1.0
7
+ */
8
+
9
+ // Exit if accessed directly
10
+ if( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
+
14
+ if( ! class_exists( 'WIO_Plugin' ) ) {
15
+ if( ! class_exists( 'WIO_PluginFactory' ) ) {
16
+ // Этот плагин может быть аддоном плагина Clearfy, если он загружен, как аддон, то мы не подключаем фреймворк,
17
+ // а наследуем функции фреймворка от плагина Clearfy. Если плагин скомпилирован, как отдельный плагин, то он использует собственный фреймворк для работы.
18
+ // Константа LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON утсанавливается в классе libs/factory/core/includes/Wbcr_Factory406_Plugin
19
+
20
+ if( defined( 'LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON' ) ) {
21
+ class WIO_PluginFactory {
22
+
23
+ }
24
+ } else {
25
+ class WIO_PluginFactory extends Wbcr_Factory406_Plugin {
26
+
27
+ }
28
+ }
29
+ }
30
+
31
+ class WIO_Plugin extends WIO_PluginFactory {
32
+
33
+ /**
34
+ * @var Wbcr_Factory406_Plugin
35
+ */
36
+ private static $app;
37
+
38
+ /**
39
+ * @var bool
40
+ */
41
+ private $as_addon;
42
+
43
+ /**
44
+ * @var WIO_Cron
45
+ */
46
+ private $cron;
47
+
48
+ /**
49
+ * @var WIO_Media_Library
50
+ */
51
+ private $media_library;
52
+
53
+ /**
54
+ * @var WIO_Image_Processor_Resmush
55
+ */
56
+ private $image_processor;
57
+
58
+ /**
59
+ * @var WIO_Image_Statistic
60
+ */
61
+ private $statistic;
62
+
63
+ /**
64
+ * @var WIO_Logger
65
+ */
66
+ private $logger;
67
+
68
+ /**
69
+ * @var WIO_Backup
70
+ */
71
+ private $backup;
72
+
73
+ /**
74
+ * @param string $plugin_path
75
+ * @param array $data
76
+ * @throws Exception
77
+ */
78
+ public function __construct( $plugin_path, $data ) {
79
+ $this->as_addon = isset( $data['as_addon'] ) ? true : false;
80
+
81
+ if( $this->as_addon ) {
82
+ $plugin_parent = isset( $data['plugin_parent'] ) ? $data['plugin_parent'] : null;
83
+
84
+ if( ! ( $plugin_parent instanceof Wbcr_Factory406_Plugin ) ) {
85
+ throw new Exception( __( 'An invalid instance of the class was passed.', 'robin-image-optimizer' ) );
86
+ }
87
+
88
+ // Если плагин загружен, как аддон, то мы передаем в app ссылку на класс родителя
89
+ self::$app = $plugin_parent;
90
+ } else {
91
+ // Если плагин самостоятельный, то записываем в app сслыку на текущий класс
92
+ self::$app = $this;
93
+
94
+ parent::__construct( $plugin_path, $data );
95
+ }
96
+
97
+ $this->init();
98
+ $this->setTextDomain();
99
+ $this->setModules();
100
+
101
+ if( is_admin() ) {
102
+ $this->initActivation();
103
+ add_action('plugins_loaded', array($this, 'adminScripts'));
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Подключение необходимых php файлов и инициализация
109
+ *
110
+ * @return void
111
+ */
112
+ protected function init() {
113
+ require_once( WIO_PLUGIN_DIR . '/includes/functions.php' );
114
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.attachment.php' );
115
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.media-library.php' );
116
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.image-processor-abstract.php' );
117
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.image-processor-resmush.php' ); // resmush api
118
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.cron.php' );
119
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.image-statistic.php' );
120
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.backup.php' );
121
+ require_once( WIO_PLUGIN_DIR . '/includes/classes/class.logger.php' );
122
+
123
+ $this->media_library = new WIO_Media_Library;
124
+ $this->cron = new WIO_Cron;
125
+ }
126
+
127
+ /**
128
+ * Статический метод для быстрого доступа к информации о плагине, а также часто использумых методах.
129
+ *
130
+ * Пример:
131
+ * WIO_Plugin::app()->getOption()
132
+ * WIO_Plugin::app()->updateOption()
133
+ * WIO_Plugin::app()->deleteOption()
134
+ * WIO_Plugin::app()->getPluginName()
135
+ *
136
+ * @return Wbcr_Factory406_Plugin
137
+ */
138
+ public static function app() {
139
+ return self::$app;
140
+ }
141
+
142
+ /**
143
+ * Устанавливаем текстовый домен
144
+ */
145
+ protected function setTextDomain() {
146
+ // Localization plugin
147
+ load_plugin_textdomain('robin-image-optimizer', false, dirname( WIO_PLUGIN_BASE ) . '/languages/' );
148
+ }
149
+
150
+ /**
151
+ * Подключаем модули фреймворка
152
+ */
153
+ protected function setModules() {
154
+ if( ! $this->as_addon ) {
155
+ self::app()->load( array(
156
+ // Модуль отвечает за подключение скриптов и стилей для интерфейса
157
+ array( 'libs/factory/bootstrap', 'factory_bootstrap_406', 'admin' ),
158
+ // Модуль отвечает за создание форм и полей
159
+ array( 'libs/factory/forms', 'factory_forms_407', 'admin' ),
160
+ // Модуль отвечает за создание шаблонов страниц плагина
161
+ array( 'libs/factory/pages', 'factory_pages_407', 'admin'),
162
+ // Модуль в котором хранится общий функционал плагина Clearfy и его аддонов
163
+ array( 'libs/factory/clearfy', 'factory_clearfy_203', 'all' )
164
+ ) );
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Инициализируем активацию плагина
170
+ */
171
+ protected function initActivation()
172
+ {
173
+ include_once(WIO_PLUGIN_DIR . '/admin/activation.php');
174
+ $this->registerActivation('WIO_Activation');
175
+ }
176
+
177
+ /**
178
+ * Регистрируем страницы плагина
179
+ */
180
+ private function registerPages() {
181
+
182
+ $admin_path = WIO_PLUGIN_DIR . '/admin/pages';
183
+
184
+ // Пример основной страницы настроек
185
+ self::app()->registerPage( 'WIO_SettingsPage', $admin_path . '/settings.php' );
186
+
187
+ // Пример внутренней страницы настроек
188
+ self::app()->registerPage( 'WIO_StatisticPage', $admin_path . '/statistic.php' );
189
+
190
+ if ( self::app()->getOption( 'error_log' , false ) ) {
191
+ self::app()->registerPage( 'WIO_LogPage', $admin_path . '/log.php' );
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Подключаем функции бекенда
197
+ */
198
+ public function adminScripts() {
199
+ require(WIO_PLUGIN_DIR . '/admin/boot.php');
200
+ $this->registerPages();
201
+ }
202
+
203
+ /**
204
+ * Метод возвращает объект, отвечающий за оптимизацию изображений через API сторонних сервисов
205
+ *
206
+ * @return WIO_Image_Processor_Resmush
207
+ */
208
+ public function getImageProcessor() {
209
+ if ( ! $this->image_processor ) {
210
+ $this->image_processor = new WIO_Image_Processor_Resmush();
211
+ }
212
+ return $this->image_processor;
213
+ }
214
+
215
+ /**
216
+ * Метод возвращает объект, отвечающий за работу со статистическими данными по оптимизации изображений
217
+ *
218
+ * @return WIO_Image_Statistic
219
+ */
220
+ public function getImageStatistics() {
221
+ if ( ! $this->statistic ) {
222
+ $this->statistic = new WIO_Image_Statistic();
223
+ }
224
+ return $this->statistic;
225
+ }
226
+
227
+ /**
228
+ * Метод возвращает объект, отвечающий за работу логами
229
+ *
230
+ * @return WIO_Logger
231
+ */
232
+ public function getLogger() {
233
+ if ( ! $this->logger ) {
234
+ $this->logger = new WIO_Logger();
235
+ }
236
+ return $this->logger;
237
+ }
238
+
239
+ /**
240
+ * Метод возвращает объект, отвечающий за работу с резервными копиями
241
+ *
242
+ * @return WIO_Backup
243
+ */
244
+ public function getBackup() {
245
+ if ( ! $this->backup ) {
246
+ $this->backup = new WIO_Backup();
247
+ }
248
+ return $this->backup;
249
+ }
250
+
251
+ /**
252
+ * Метод возвращает объект, отвечающий за работу с медиабиблиотекой
253
+ *
254
+ * @return WIO_Media_Library
255
+ */
256
+ public function getMediaLibrary() {
257
+ return $this->media_library;
258
+ }
259
+ }
260
+ }
includes/classes/class.attachment.php ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы с wordpress attachment
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_Attachment {
15
+
16
+ /**
17
+ * @var int
18
+ */
19
+ private $id;
20
+
21
+ /**
22
+ * @var array meta-данные
23
+ */
24
+ private $attachment_meta;
25
+
26
+ /**
27
+ * @var array массив с данными о папке uploads
28
+ */
29
+ private $wp_upload_dir;
30
+
31
+ /**
32
+ * @var string
33
+ */
34
+ private $url;
35
+
36
+ /**
37
+ * @var string
38
+ */
39
+ private $path;
40
+
41
+ /**
42
+ * @var string
43
+ */
44
+ private $backup_path = '';
45
+ /**
46
+ * @var string
47
+ */
48
+ private $backup_dir = '';
49
+
50
+ /**
51
+ * Инициализация аттачмента
52
+ *
53
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
54
+ * @param array|false $attachment_meta метаданные аттачмента
55
+ */
56
+ public function __construct( $attachment_id, $attachment_meta = false ) {
57
+ $this->id = $attachment_id;
58
+ $this->wp_upload_dir = wp_upload_dir();
59
+ $this->attachment_meta = $attachment_meta;
60
+ if ( ! $attachment_meta ) {
61
+ $this->attachment_meta = wp_get_attachment_metadata( $this->id );
62
+ }
63
+ $this->url = $this->wp_upload_dir['baseurl'] . '/' . $this->attachment_meta['file'];
64
+ $this->path = $this->wp_upload_dir['basedir'] . '/' . $this->attachment_meta['file'];
65
+ }
66
+
67
+ public function writeLog($message) {
68
+ $error = PHP_EOL.'============================================'. PHP_EOL;
69
+ $error .= $message. PHP_EOL;
70
+ $error .= "[is_optimized] ". ($this->isOptimized() ? 'true' : 'false'). PHP_EOL;
71
+ $error .= "[is_need_resize] ". ($this->isNeedResize() ? 'true' : 'false'). PHP_EOL;
72
+ $error .= "[attachment_id] ".$this->id. PHP_EOL;
73
+ $error .= "[image size] ".$this->attachment_meta['width'].'x'.$this->attachment_meta['height']. PHP_EOL;
74
+ $error .= "[file] ".$this->attachment_meta['file']. PHP_EOL;
75
+
76
+ foreach($this->attachment_meta['sizes'] as $size_type => $size_info) {
77
+ $message .= "['.$size_type.'] ".$size_info['width'].'x'.$size_info['height']. PHP_EOL;
78
+ $message .= "['.$size_type.'] ".$size_info['mime-type']. PHP_EOL;
79
+ }
80
+ $error .= '============================================'. PHP_EOL;
81
+
82
+ $logger = WIO_Plugin::app()->getLogger();
83
+ $logger->add( $error );
84
+ }
85
+
86
+ /**
87
+ * Оптимизация аттачмента
88
+ *
89
+ * @param string $optimization_level уровень оптимизации изображения
90
+ */
91
+ public function optimize( $optimization_level = '' ) {
92
+ $errors_count = 0;
93
+ $optimized_count = 0;
94
+ $original_size = 0;
95
+ $optimized_size = 0;
96
+ // сначала бекапим
97
+ $is_image_backuped = $this->backup();
98
+
99
+ if ( is_wp_error( $is_image_backuped ) ) {
100
+ $error_msg = $is_image_backuped->get_error_message() . PHP_EOL;
101
+ $this->writeLog( $error_msg );
102
+
103
+ return array(
104
+ 'errors_count' => 1,
105
+ 'original_size' => 0,
106
+ 'optimized_size' => 0,
107
+ 'optimized_count' => 0,
108
+ );
109
+ }
110
+ clearstatcache(); // на всякий случай очистим кеш файловой статистики
111
+ $original_main_size = filesize( $this->get( 'path' ) );
112
+ // если файл большой - изменяем размер
113
+ if ( $this->isNeedResize() ) {
114
+ $this->resize();
115
+ }
116
+ $image_processor = WIO_Plugin::app()->getImageProcessor();
117
+ if ( ! $optimization_level ) {
118
+ $optimization_level = WIO_Plugin::app()->getOption( 'image_optimization_level' , 'normal' );
119
+ }
120
+ $optimized_img_data = $image_processor->process( array(
121
+ 'image_url' => $this->get( 'url' ),
122
+ 'image_path' => $this->get( 'path' ),
123
+ 'quality' => $image_processor->quality( $optimization_level ),
124
+ 'save_exif' => WIO_Plugin::app()->getOption( 'save_exif_data' , false ),
125
+ ) );
126
+ // проверяем на ошибку
127
+ if ( is_wp_error( $optimized_img_data ) ) {
128
+ $errors_count++;
129
+ $error_msg = $optimized_img_data->get_error_message();
130
+ $this->writeLog( $error_msg );
131
+ update_post_meta( $this->get( 'id' ), 'wio_error', $error_msg );
132
+ } else {
133
+ //скачиваем и заменяем картинку
134
+ $image_downloaded = $this->replaceOriginalFile( $optimized_img_data['optimized_img_url'] );
135
+ if ( $image_downloaded ) {
136
+ // оптимизируем дополнительные размеры
137
+ $optimized_img_sizes_data = $this->optimizeImageSizes();
138
+ //просчитываем статистику
139
+ $original_size += $original_main_size;
140
+ $optimized_size += $optimized_img_data['optimized_size'];
141
+ $thumbnails_count = 0;
142
+
143
+ // добавляем к статистике данные по оптимизации доп размеров
144
+ if ( $optimized_img_sizes_data ) {
145
+ $original_size += $optimized_img_sizes_data['original_size'];
146
+ $optimized_size += $optimized_img_sizes_data['optimized_size'];
147
+ $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
148
+ }
149
+ update_post_meta( $this->get( 'id' ), 'wio_thumbnails_count', $thumbnails_count );
150
+ update_post_meta( $this->get( 'id' ), 'wio_optimized_size', $optimized_size );
151
+ update_post_meta( $this->get( 'id' ), 'wio_original_size', $original_size );
152
+ update_post_meta( $this->get( 'id' ), 'wio_original_main_size', $original_main_size );
153
+ update_post_meta( $this->get( 'id' ), 'wio_optimization_level', $optimization_level );
154
+ update_post_meta( $this->get( 'id' ), 'wio_backuped', $is_image_backuped );
155
+
156
+ delete_post_meta( $this->get( 'id' ), 'wio_error' );
157
+ } else {
158
+ $errors_count++;
159
+ $error_msg = __( 'Не удалось получить оптимизированное изображение с удалённого сервера', 'robin-image-optimizer' );
160
+ $this->writeLog( $error_msg );
161
+ update_post_meta( $this->get( 'id' ), 'wio_error', $error_msg );
162
+ }
163
+ }
164
+ update_post_meta( $this->get( 'id' ), 'wio_optimized', 1 );
165
+
166
+ return array(
167
+ 'errors_count' => $errors_count,
168
+ 'original_size' => $original_size,
169
+ 'optimized_size' => $optimized_size,
170
+ 'optimized_count' => $optimized_count,
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Метод проверяет, оптимизирован ли аттачмент
176
+ *
177
+ * @return bool
178
+ */
179
+ public function isOptimized() {
180
+ $optimized = get_post_meta( $this->get( 'id' ), 'wio_optimized', true );
181
+ if ( ! $optimized ) {
182
+ return false;
183
+ }
184
+ return true;
185
+ }
186
+
187
+ /**
188
+ * Возвращает все размеры аттачмента, которые нужно оптимизировать
189
+ *
190
+ * @return array
191
+ */
192
+ public function getAllowedSizes() {
193
+ $allowed_sizes = WIO_Plugin::app()->getOption( 'allowed_sizes_thumbnail' , 'thumbnail,medium' );
194
+ if ( ! $allowed_sizes ) {
195
+ return false;
196
+ }
197
+ $allowed_sizes = explode( ',', $allowed_sizes );
198
+ return $allowed_sizes;
199
+ }
200
+
201
+ /**
202
+ * Оптимизация других размеров аттачмента
203
+ */
204
+ public function optimizeImageSizes() {
205
+ $allowed_sizes = $this->getAllowedSizes();
206
+ if ( ! $allowed_sizes ) {
207
+ return false;
208
+ }
209
+
210
+ $image_processor = WIO_Plugin::app()->getImageProcessor();
211
+ $quality = WIO_Plugin::app()->getOption( 'image_optimization_level' , 'normal' );
212
+ $exif = WIO_Plugin::app()->getOption( 'save_exif_data' , false );
213
+
214
+ $original_size = 0;
215
+ $optimized_size = 0;
216
+ $errors_count = 0;
217
+ $optimized_count = 0;
218
+ foreach ( $allowed_sizes as $image_size ) {
219
+ $url = $this->getImageSizeUrl( $image_size );
220
+ $path = $this->getImageSizePath( $image_size );
221
+ if ( ! $url or ! $path ) {
222
+ continue;
223
+ }
224
+ $optimized_img_data = $image_processor->process( array(
225
+ 'image_url' => $url,
226
+ 'image_path' => $path,
227
+ 'quality' => $image_processor->quality( $quality ),
228
+ 'save_exif' => $exif,
229
+ ) );
230
+ // проверяем на ошибку
231
+ if ( is_wp_error( $optimized_img_data ) ) {
232
+ $errors_count++;
233
+ } else {
234
+ //скачиваем и заменяем картинку
235
+ $this->replaceOriginalFile( $optimized_img_data['optimized_img_url'], $image_size );
236
+
237
+ //просчитываем статистику
238
+ $original_size += $optimized_img_data['src_size'];
239
+ $optimized_size += $optimized_img_data['optimized_size'];
240
+ $optimized_count++;
241
+ }
242
+ }
243
+ return array(
244
+ 'errors_count' => $errors_count,
245
+ 'original_size' => $original_size,
246
+ 'optimized_size' => $optimized_size,
247
+ 'thumbnails_count' => $optimized_count
248
+ );
249
+ }
250
+
251
+ /**
252
+ * Возвращает путь
253
+ *
254
+ * @param string $image_size Размер(thumbnail, medium ... )
255
+ * @return string
256
+ */
257
+ public function getPath( $image_size = '' ) {
258
+ if ( ! $image_size ) {
259
+ $path = $this->path;
260
+ } else {
261
+ $path = $this->getImageSizePath( $image_size );
262
+ }
263
+ return $path;
264
+ }
265
+
266
+ /**
267
+ * Заменяет оригинальный файл на оптимизированный
268
+ *
269
+ * @param string $optimized_img_url URL оптимизированного изображения
270
+ * @param string $image_size Размер(thumbnail, medium ... )
271
+ */
272
+ public function replaceOriginalFile( $optimized_img_url, $image_size = '' ) {
273
+ //$logger = WIO_Plugin::app()->getLogger();
274
+
275
+ $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
276
+ if ( ! $optimized_file ) {
277
+ return false;
278
+ }
279
+ $attachment_size_path = $this->getPath( $image_size );
280
+ if ( ! is_file( $attachment_size_path ) ) {
281
+ return false;
282
+ }
283
+
284
+ file_put_contents( $attachment_size_path, $optimized_file );
285
+ return true;
286
+ }
287
+
288
+ protected function remoteDownloadImage( $url ) {
289
+ if ( ! function_exists( 'curl_version' ) ) {
290
+ return file_get_contents( $url );
291
+ }
292
+
293
+ $ch = curl_init();
294
+ curl_setopt( $ch, CURLOPT_HEADER, 0 );
295
+ curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
296
+ curl_setopt( $ch, CURLOPT_URL, $url );
297
+
298
+ $image_body = curl_exec( $ch );
299
+ $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
300
+ if ( $http_code != '200' ) {
301
+ $image_body = false;
302
+ }
303
+ curl_close( $ch );
304
+
305
+ return $image_body;
306
+ }
307
+
308
+ /**
309
+ * Возвращает свойство аттачмента
310
+ *
311
+ * @param string $property имя свойства
312
+ * @return mixed
313
+ */
314
+ public function get( $property ) {
315
+ if ( isset( $this->$property ) ) {
316
+ return $this->$property;
317
+ }
318
+ return false;
319
+ }
320
+
321
+ /**
322
+ * Возвращает URL изображения по указанному размеру
323
+ *
324
+ * @param string $size - размер изображения(thumbnail,medium,large...)
325
+ * @return srting
326
+ */
327
+ public function getImageSizeUrl( $size = 'thumbnail' ) {
328
+ if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
329
+ return false;
330
+ }
331
+ $url = str_replace( basename( $this->url ), $this->attachment_meta['sizes'][ $size ]['file'], $this->url );
332
+ return $url;
333
+ }
334
+
335
+ /**
336
+ * Возвращает путь к изображению по указанному размеру
337
+ *
338
+ * @param string $size - размер изображения(thumbnail,medium,large...)
339
+ * @return srting
340
+ */
341
+ public function getImageSizePath( $size = 'thumbnail' ) {
342
+ if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
343
+ return false;
344
+ }
345
+ $path = str_replace( basename( $this->path ), $this->attachment_meta['sizes'][ $size ]['file'], $this->path );
346
+ return $path;
347
+ }
348
+
349
+ /**
350
+ * Проверка необходимости делать рисайз
351
+ *
352
+ */
353
+ protected function isNeedResize() {
354
+ $resize_large_images = WIO_Plugin::app()->getOption( 'resize_larger' , true );
355
+ if ( ! $resize_large_images ) {
356
+ return false;
357
+ }
358
+
359
+ $file_size = filesize( $this->path );
360
+ $max_size = 1024 * 1024 * 5; // 5 Мб
361
+ if ( $file_size >= $max_size ) {
362
+ return true;
363
+ }
364
+ return false;
365
+ }
366
+
367
+ /**
368
+ * Изменяет размер изображения
369
+ *
370
+ */
371
+ protected function resize() {
372
+ $resize_larger_side = WIO_Plugin::app()->getOption( 'resize_larger_w' , 1600 );
373
+ $image = wp_get_image_editor( $this->path );
374
+ if ( ! is_wp_error( $image ) ) {
375
+ $current_size = $image->get_size();
376
+ $new_width = 0;
377
+ $new_height = 0;
378
+ // определяем большую сторону и по ней маштабируем
379
+ if ( $current_size['width'] >= $current_size['height'] ) {
380
+ $new_width = $resize_larger_side;
381
+ $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
382
+ } else {
383
+ $new_height = $resize_larger_side;
384
+ $new_width = round( $current_size['width'] * $new_height / $current_size['height'] );
385
+ }
386
+ $image->resize( $new_width, $new_height, false );
387
+ $image->save( $this->path );
388
+ $this->attachment_meta['width'] = $new_width;
389
+ $this->attachment_meta['height'] = $new_height;
390
+ $this->attachment_meta['old_width'] = $current_size['width'];
391
+ $this->attachment_meta['old_height'] = $current_size['height'];
392
+ wp_update_attachment_metadata( $this->id, $this->attachment_meta );
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Делает резервную копию
398
+ *
399
+ * @return true|WP_Error
400
+ */
401
+ protected function backup() {
402
+ $backup = WIO_Plugin::app()->getBackup();
403
+ return $backup->backupAttachment( $this );
404
+ }
405
+
406
+ /**
407
+ * Восстанавливает файлы из резервной копии
408
+ *
409
+ * @return true|WP_Error
410
+ */
411
+ public function restore() {
412
+ $backup = WIO_Plugin::app()->getBackup();
413
+ return $backup->restoreAttachment( $this );
414
+ }
415
+
416
+ }
includes/classes/class.backup.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы с резервным копированием изображений
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_Backup {
15
+
16
+ /**
17
+ * @var string
18
+ */
19
+ protected $backup_dir;
20
+
21
+ /**
22
+ * @var string
23
+ */
24
+ protected $backup_dir_name = 'wio_backup';
25
+
26
+ /**
27
+ * @var array
28
+ */
29
+ protected $wp_upload_dir;
30
+
31
+ /**
32
+ * Инициализация бекапа
33
+ */
34
+ public function __construct() {
35
+ $this->wp_upload_dir = wp_upload_dir();
36
+ $this->backup_dir = $this->getBackupDir();
37
+ }
38
+
39
+ /**
40
+ * Проверка возможности записи в папку аплоад
41
+ */
42
+ public function isUploadWritable() {
43
+ $upload_dir = $this->wp_upload_dir['basedir'];
44
+ if ( is_dir( $upload_dir ) and is_writable( $upload_dir ) ) {
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+
50
+ /**
51
+ * Проверка возможности записи в папку бекап
52
+ */
53
+ public function isBackupWritable() {
54
+ $backup_dir = $this->getBackupDir();
55
+ if ( is_wp_error( $backup_dir ) ) {
56
+ return false;
57
+ }
58
+ if ( is_writable( $backup_dir ) ) {
59
+ return true;
60
+ }
61
+ return false;
62
+ }
63
+
64
+ /**
65
+ * Путь к папке с бекапами
66
+ *
67
+ * @return string|WP_Error
68
+ */
69
+ public function getBackupDir() {
70
+ if ( $this->backup_dir ) {
71
+ return $this->backup_dir;
72
+ }
73
+ $dir = $this->wp_upload_dir['basedir'] . '/' . $this->backup_dir_name . '/';
74
+ if ( ! is_dir( $dir ) ) {
75
+ // создаём
76
+ if( ! mkdir( $dir ) ) {
77
+ return new WP_Error( 'backup_dir_error', __( 'Unable to create backup folder.', 'robin-image-optimizer' ) );
78
+ }
79
+ }
80
+ return $dir;
81
+ }
82
+
83
+ /**
84
+ * Очищает папку с резервными копиями
85
+ *
86
+ */
87
+ public function removeBackupDir() {
88
+ $backup_dir = $this->getBackupDir();
89
+ if ( is_dir( $backup_dir ) ) {
90
+ $this->rmDir( $backup_dir );
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Удаляет папку со всем содержимым
96
+ *
97
+ * @param string $dir папка
98
+ */
99
+ protected function rmDir( $dir ) {
100
+ if ( is_dir( $dir ) ) {
101
+ $scn = scandir( $dir );
102
+ foreach ( $scn as $files ) {
103
+ if ( $files !== '.' ) {
104
+ if ( $files !== '..' ) {
105
+ if ( ! is_dir( $dir . '/' . $files ) ) {
106
+ unlink( $dir . '/' . $files );
107
+ } else {
108
+ $this->rmDir( $dir . '/' . $files );
109
+ rmdir( $dir . '/' . $files );
110
+ }
111
+ }
112
+ }
113
+ }
114
+ rmdir( $dir );
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Получает путь к папке с резервными копиями
120
+ *
121
+ * @param array $attachment_meta метаданные аттачмента
122
+ * @return string
123
+ */
124
+ public function getAttachmentBackupDir( $attachment_meta ) {
125
+ $backup_dir = $this->getBackupDir();
126
+ $file_subdirs = explode( '/', $attachment_meta['file'] );
127
+ array_pop( $file_subdirs ); // убираем имя файла
128
+ foreach ( $file_subdirs as $subdir_name ) {
129
+ $backup_dir .= $subdir_name . '/';
130
+ if ( ! is_dir( $backup_dir ) ) {
131
+ if( ! mkdir( $backup_dir ) ) {
132
+ return new WP_Error( 'backup_dir_subdir_error', __( 'Unable to create backup subfolder.', 'robin-image-optimizer' ) );
133
+ }
134
+ }
135
+ }
136
+ return $backup_dir;
137
+ }
138
+
139
+ /**
140
+ * Делаем резервную копию аттачмента
141
+ *
142
+ * @param WIO_Attachment $wio_attachment аттачмент
143
+ * @return bool|WP_Error
144
+ */
145
+ public function backupAttachment( $wio_attachment ) {
146
+ $backup_origin_images = WIO_Plugin::app()->getOption( 'backup_origin_images' , false );
147
+ if ( ! $backup_origin_images ) {
148
+ return false; // если бекап не требуется
149
+ }
150
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
151
+ if ( is_wp_error( $backup_dir ) ) {
152
+ return $backup_dir;
153
+ }
154
+ $full = $this->backupAttachmentSize( $wio_attachment );
155
+ if ( is_wp_error( $full ) ) {
156
+ return $full;
157
+ }
158
+ $allowed_sizes = $wio_attachment->getAllowedSizes();
159
+ if ( $allowed_sizes ) {
160
+ foreach ( $allowed_sizes as $image_size ) {
161
+ $size_backup = $this->backupAttachmentSize( $wio_attachment, $image_size );
162
+ if ( is_wp_error( $size_backup ) ) {
163
+ return $size_backup;
164
+ }
165
+ }
166
+ }
167
+ return true;
168
+ }
169
+
170
+ /**
171
+ * Восстанавливаем аттачмент из резервной копии
172
+ *
173
+ * @param WIO_Attachment $wio_attachment аттачмент
174
+ * @return bool|WP_Error
175
+ */
176
+ public function restoreAttachment( $wio_attachment ) {
177
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
178
+ if ( is_wp_error( $backup_dir ) ) {
179
+ return $backup_dir;
180
+ }
181
+ $full = $this->restoreAttachmentSize( $wio_attachment );
182
+ $attachment_meta = wp_get_attachment_metadata( $wio_attachment->get( 'id' ) );
183
+ if ( isset( $attachment_meta['old_width'] ) and isset( $attachment_meta['old_width'] ) ) {
184
+ $attachment_meta['width'] = $attachment_meta['old_width'];
185
+ $attachment_meta['height'] = $attachment_meta['old_height'];
186
+ wp_update_attachment_metadata( $wio_attachment->get( 'id' ), $attachment_meta );
187
+ }
188
+ if ( is_wp_error( $full ) ) {
189
+ return $full;
190
+ }
191
+ $allowed_sizes = $wio_attachment->getAllowedSizes();
192
+ if ( $allowed_sizes ) {
193
+ foreach ( $allowed_sizes as $image_size ) {
194
+ $size_backup = $this->restoreAttachmentSize( $wio_attachment, $image_size );
195
+ }
196
+ }
197
+ return true;
198
+ }
199
+
200
+ /**
201
+ * Резервное копирование файла аттачмента
202
+ *
203
+ * @param WIO_Attachment $wio_attachment аттачмент
204
+ * @param string $image_size Размер(thumbnail, medium ... )
205
+ * @return bool|WP_Error
206
+ */
207
+ protected function backupAttachmentSize( $wio_attachment, $image_size = '' ) {
208
+ if ( $image_size ) {
209
+ $original_file = $wio_attachment->getImageSizePath( $image_size );
210
+ } else {
211
+ $original_file = $wio_attachment->get( 'path' );
212
+ }
213
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
214
+ // проверить запись в папку
215
+ if ( is_wp_error( $backup_dir ) ) {
216
+ return $backup_dir;
217
+ }
218
+ if ( ! $original_file ) {
219
+ // бывает такое, что размера превьюшки нет в базе данных.
220
+ // это не считается ошибкой, поэтому сразу пропускаем
221
+ return false;
222
+ }
223
+ $backup_file = $backup_dir . basename( $original_file );
224
+ if ( is_file( $original_file ) ) {
225
+ $copy = copy( $original_file, $backup_file );
226
+ }
227
+ return true;
228
+ }
229
+
230
+ /**
231
+ * Восстановление файла аттачмента из резервной копии
232
+ *
233
+ * @param WIO_Attachment $wio_attachment аттачмент
234
+ * @param string $image_size Размер(thumbnail, medium ... )
235
+ * @return bool|WP_Error
236
+ */
237
+ protected function restoreAttachmentSize( $wio_attachment, $image_size = '' ) {
238
+ if ( $image_size ) {
239
+ $original_file = $wio_attachment->getImageSizePath( $image_size );
240
+ } else {
241
+ $original_file = $wio_attachment->get( 'path' );
242
+ }
243
+ $backup_dir = $this->getAttachmentBackupDir( $wio_attachment->get( 'attachment_meta' ) );
244
+ if ( is_wp_error( $backup_dir ) ) {
245
+ return $backup_dir;
246
+ }
247
+ if ( ! $original_file ) {
248
+ // бывает такое, что размера превьюшки нет в базе данных.
249
+ // это не считается ошибкой, поэтому сразу пропускаем
250
+ return false;
251
+ }
252
+ $backup_file = $backup_dir . basename( $original_file );
253
+ $backup_file_exists = is_file( $backup_file );
254
+ if ( $backup_file_exists ) {
255
+ $restored = copy( $backup_file, $original_file );
256
+ unlink( $backup_file ); // удаляем файл из бекапа
257
+ } else {
258
+ $restored = false;
259
+ $logger = WIO_Plugin::app()->getLogger();
260
+ $error_msg = __( 'Невозможно восстановить из резервной копии. Файла нет.', 'robin-image-optimizer' );
261
+ $logger->add( $error_msg . 'Attachment_id: ' . $wio_attachment->get( 'id' ) . ' file: ' . $backup_file );
262
+ }
263
+ return $restored;
264
+ }
265
+
266
+ }
includes/classes/class.cron.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы оптимизации по расписанию
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_Cron {
15
+
16
+ /**
17
+ * Инициализация оптимизации по расписанию
18
+ */
19
+ public function __construct() {
20
+ $this->hooks();
21
+ $this->check();
22
+ }
23
+
24
+ /**
25
+ * Подключение хуков
26
+ */
27
+ private function hooks() {
28
+ add_filter( 'cron_schedules', array( $this, 'intervals' ) );
29
+ add_action( 'wio_optimize_images', array( $this, 'process' ) );
30
+ }
31
+
32
+ /**
33
+ * Проверка текущего статуса cron задачи и синхронизация с кнопкой в настройках.
34
+ * Включение и выключение cron задачи в зависимости от настроек
35
+ */
36
+ private function check() {
37
+ $is_cron_mode = WIO_Plugin::app()->getOption( 'image_autooptimize_mode', false );
38
+ $cron_running = WIO_Plugin::app()->getOption( 'cron_running', false );
39
+ if ( $is_cron_mode and $cron_running ) {
40
+ $this->start();
41
+ } else {
42
+ $this->stop();
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Кастомные интервалы выполнения cron задачи
48
+ *
49
+ * @param array $intervals Зарегистророванные интервалы
50
+ *
51
+ * @return array $intervals Новые интервалы
52
+ */
53
+ public function intervals( $intervals ) {
54
+ $intervals['wio_1_min'] = array(
55
+ 'interval' => 60,
56
+ 'display' => __( '1 min', 'robin-image-optimizer' ),
57
+ );
58
+ $intervals['wio_2_min'] = array(
59
+ 'interval' => 60 * 2,
60
+ 'display' => __( '2 min', 'robin-image-optimizer' ),
61
+ );
62
+ $intervals['wio_5_min'] = array(
63
+ 'interval' => 60 * 5,
64
+ 'display' => __( '5 min', 'robin-image-optimizer' ),
65
+ );
66
+ $intervals['wio_10_min'] = array(
67
+ 'interval' => 60 * 10,
68
+ 'display' => __( '10 min', 'robin-image-optimizer' ),
69
+ );
70
+ $intervals['wio_30_min'] = array(
71
+ 'interval' => 60 * 30,
72
+ 'display' => __( '30 min', 'robin-image-optimizer' ),
73
+ );
74
+ $intervals['wio_hourly'] = array(
75
+ 'interval' => 60 * 60,
76
+ 'display' => __( '60 min', 'robin-image-optimizer' ),
77
+ );
78
+ $intervals['wio_daily'] = array(
79
+ 'interval' => 60 * 60 * 24,
80
+ 'display' => __( 'daily', 'robin-image-optimizer' ),
81
+ );
82
+ return $intervals;
83
+ }
84
+
85
+ /**
86
+ * Запуск задачи
87
+ */
88
+ public function start() {
89
+ $interval = WIO_Plugin::app()->getOption( 'image_autooptimize_shedule_time' , 'wio_5_min' );
90
+ if ( ! wp_next_scheduled( 'wio_optimize_images' ) ) {
91
+ wp_schedule_event( time(), $interval, 'wio_optimize_images' );
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Остановка задачи
97
+ */
98
+ public function stop() {
99
+ if ( wp_next_scheduled( 'wio_optimize_images' ) ) {
100
+ wp_clear_scheduled_hook( 'wio_optimize_images' );
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Метод оптимизирует изображения при выполнении cron задачи
106
+ */
107
+ public function process() {
108
+ $max_process_per_request = WIO_Plugin::app()->getOption( 'image_autooptimize_items_number_per_interation' , 5 );
109
+ $media_library = WIO_Plugin::app()->getMediaLibrary();
110
+ $optimized_data = $media_library->processUnoptimizedAttachments( $max_process_per_request );
111
+ }
112
+
113
+ }
includes/classes/class.image-processor-abstract.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Базовый класс для обработки изображений через API сторонних сервисов
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ abstract class WIO_Image_Processor_Abstract {
15
+
16
+ /**
17
+ * Оптимизация изображения
18
+ *
19
+ * @param array $params параметры оптимизации изображения
20
+ */
21
+ abstract function process( $params );
22
+
23
+ /**
24
+ * Качество изображения
25
+ * Метод конвертирует качество из настроек плагина в формат сервиса оптимизации
26
+ *
27
+ * @param mixed $quality качество
28
+ */
29
+ abstract function quality( $quality );
30
+
31
+ /**
32
+ * HTTP запрос к API стороннего сервиса
33
+ *
34
+ * @param $url URL для запроса
35
+ * @return string
36
+ */
37
+ protected function request( $url, $post_fields = false ) {
38
+ // проверяем, доступен ли CURL
39
+ if ( function_exists( 'curl_version' ) ) {
40
+ return $this->curlRequest( $url, $post_fields );
41
+ } else {
42
+ return file_get_contents( $url );
43
+ }
44
+ }
45
+
46
+ /**
47
+ * HTTP запрос к API стороннего сервиса с использованием библиотеки CURL
48
+ *
49
+ * @param $url URL для запроса
50
+ * @return string|WP_Error
51
+ */
52
+ protected function curlRequest( $url, $post_fields = false ) {
53
+ $ch = curl_init();
54
+ $timeout = 5;
55
+ curl_setopt( $ch, CURLOPT_URL, $url );
56
+ curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
57
+ curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
58
+ if ( $post_fields ) {
59
+ curl_setopt( $ch, CURLOPT_POST, 1 );
60
+ curl_setopt( $ch, CURLOPT_POSTFIELDS, $post_fields );
61
+ }
62
+ $responce = curl_exec( $ch );
63
+
64
+ if( curl_errno( $ch ) ) {
65
+ $responce = new WP_Error( 'http_error', curl_error( $ch ) );
66
+ }
67
+ curl_close( $ch );
68
+ return $responce;
69
+ }
70
+
71
+ }
includes/classes/class.image-processor-resmush.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для оптимизации изображений через API сервиса Resmush
10
+ * @see https://resmush.it/api
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
+ */
15
+ class WIO_Image_Processor_Resmush extends WIO_Image_Processor_Abstract {
16
+
17
+ /**
18
+ * @var string
19
+ */
20
+ protected $api_url = 'http://api.resmush.it/ws.php';
21
+
22
+ /**
23
+ * Оптимизация изображения
24
+ *
25
+ * @param array $params входные параметры оптимизации изображения
26
+ * @return array|WP_Error
27
+ */
28
+ public function process( $params ) {
29
+ /**
30
+ * @var array параметры оптимизации по умолчанию
31
+ */
32
+ $default_params = array(
33
+ 'image_url' => '', // ссылка на исходное изображение
34
+ 'quality' => 100, // качество сжатия: 100 - максимальное, 0 - минимум
35
+ 'save_exif' => false, // сохранять ли EXIF данные
36
+ );
37
+ $params = wp_parse_args( $params, $default_params );
38
+ $query = array(
39
+ 'qlty' => $params['quality'],
40
+ );
41
+
42
+ if ( $params['save_exif'] ) {
43
+ $query['exif'] = true;
44
+ }
45
+ if ( function_exists( 'curl_version' ) ) {
46
+ if ( class_exists( 'CURLFile' ) ) {
47
+ $query['files'] = new \CURLFile( realpath( $params['image_path'] ) );
48
+ } else {
49
+ $query['files'] = '@' . realpath( $params['image_path'] );
50
+ }
51
+ $responce = $this->request( $this->api_url, $query );
52
+ } else {
53
+ $query['img'] = $params['image_url'];
54
+ $url = $this->api_url . '?' . http_build_query( $query );
55
+ $responce = $this->request( $url );
56
+ }
57
+ $optimized_image_data = array();
58
+ if ( is_wp_error( $responce ) ) {
59
+ $optimized_image_data = $responce;
60
+ } else {
61
+ $responce = json_decode( $responce );
62
+ if ( isset( $responce->error ) ) {
63
+ $optimized_image_data = new WP_Error( 'api_error', $responce->error_long );
64
+ } else {
65
+ $optimized_image_data = array(
66
+ 'optimized_img_url' => $responce->dest,
67
+ 'src_size' => $responce->src_size,
68
+ 'optimized_size' => $responce->dest_size,
69
+ 'optimized_percent' => $responce->percent
70
+ );
71
+ }
72
+ }
73
+
74
+ return $optimized_image_data;
75
+ }
76
+
77
+ /**
78
+ * Качество изображения
79
+ * Метод конвертирует качество из настроек плагина в формат сервиса resmush
80
+ *
81
+ * @param mixed $quality качество
82
+ * @return int
83
+ */
84
+ public function quality( $quality = 100 ) {
85
+ if ( $quality == 'normal' ) {
86
+ return 92;
87
+ }
88
+ if ( $quality == 'aggresive' ) {
89
+ return 60;
90
+ }
91
+ if ( $quality == 'ultra' ) {
92
+ return 40;
93
+ }
94
+ return 100;
95
+ }
96
+ }
includes/classes/class.image-statistic.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы со статистическими данными по оптимизации изображений
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_Image_Statistic {
15
+
16
+ /**
17
+ * @var array
18
+ */
19
+ protected $statistic;
20
+
21
+ /**
22
+ * Инициализация статистики
23
+ */
24
+ public function __construct() {
25
+ $this->statistic = $this->load();
26
+ }
27
+
28
+ /**
29
+ * Возвращает статистические данные
30
+ *
31
+ * @return array
32
+ */
33
+ public function get() {
34
+ return $this->statistic;
35
+ }
36
+
37
+ /**
38
+ * Добавляет новые данные к текущей статистике
39
+ * К текущим числам добавляются новые
40
+ *
41
+ * @param string $field Поле, к которому добавляем значение
42
+ * @param int $value добавляемое значение
43
+ */
44
+ public function addToField( $field, $value ) {
45
+ if ( isset( $this->statistic[ $field ] ) ) {
46
+ $this->statistic[ $field ] = $this->statistic[ $field ] + $value;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Вычитает данные из текущей статистики
52
+ * Из текущего числа вычитается
53
+ *
54
+ * @param string $field Поле, из которого вычитается значение
55
+ * @param int $value вычитаемое значение
56
+ */
57
+ public function deductFromField( $field, $value ) {
58
+ if ( isset( $this->statistic[ $field ] ) ) {
59
+ $this->statistic[ $field ] = $this->statistic[ $field ] - $value;
60
+ if ( $this->statistic[ $field ] < 0 ) {
61
+ $this->statistic[ $field ] = 0;
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Сохранение статистики
68
+ */
69
+ public function save() {
70
+ WIO_Plugin::app()->updateOption( 'optimized_count', $this->statistic['optimized'] );
71
+ WIO_Plugin::app()->updateOption( 'error_count', $this->statistic['error'] );
72
+ WIO_Plugin::app()->updateOption( 'original_size', $this->statistic['original_size'] );
73
+ WIO_Plugin::app()->updateOption( 'optimized_size', $this->statistic['optimized_size'] );
74
+ }
75
+
76
+ /**
77
+ * Загрузка статистики и расчёт некоторых параметров
78
+ *
79
+ * @return array
80
+ */
81
+ public function load() {
82
+ $original_size = WIO_Plugin::app()->getOption( 'original_size', 0 );
83
+ $optimized_size = WIO_Plugin::app()->getOption( 'optimized_size', 0 );
84
+ $args = array(
85
+ 'post_type' => 'attachment',
86
+ 'post_status' => 'inherit',
87
+ 'post_mime_type' => array( 'image/jpeg', 'image/gif', 'image/png' ),
88
+ 'numberposts' => 1,
89
+ );
90
+ $unoptimized_args = array(
91
+ 'post_type' => 'attachment',
92
+ 'post_status' => 'inherit',
93
+ 'post_mime_type' => array( 'image/jpeg', 'image/gif', 'image/png' ),
94
+ 'posts_per_page' => 1,
95
+ 'meta_query' => array(
96
+ array(
97
+ 'key' => 'wio_optimized',
98
+ 'compare' => 'NOT EXISTS',
99
+ ),
100
+ )
101
+ );
102
+ $error_args = array(
103
+ 'post_type' => 'attachment',
104
+ 'post_status' => 'inherit',
105
+ 'post_mime_type' => array( 'image/jpeg', 'image/gif', 'image/png' ),
106
+ 'posts_per_page' => 1,
107
+ 'meta_query' => array(
108
+ array(
109
+ 'key' => 'wio_error',
110
+ 'compare' => 'EXISTS',
111
+ ),
112
+ )
113
+ );
114
+ $unoptimized_args = apply_filters( 'wio_unoptimized_args', $unoptimized_args );
115
+ $total_query = new WP_Query( $args );
116
+ $unoptimized_query = new WP_Query( $unoptimized_args );
117
+ $error_query = new WP_Query( $error_args );
118
+ $error_count = $error_query->found_posts;
119
+ $total_images = $total_query->found_posts;
120
+ $unoptimized = $unoptimized_query->found_posts;
121
+ if ( $optimized_size and $original_size ) {
122
+ $percent_diff = round( ( $original_size - $optimized_size ) * 100 / $original_size, 1 );
123
+ $percent_diff_line = round( $optimized_size * 100 / $original_size, 0 );
124
+ } else {
125
+ $percent_diff = 0;
126
+ $percent_diff_line = 100;
127
+ }
128
+ $optimized_exists_images_count = $total_images - $unoptimized - $error_count; // оптимизированные картинки, которые сейчас есть в медиабиблиотеке
129
+ if ( $total_images ) {
130
+ $optimized_images_percent = round( $optimized_exists_images_count * 100 / $total_images );
131
+ } else {
132
+ $optimized_images_percent = 0;
133
+ }
134
+
135
+ return array(
136
+ 'original' => $total_images,
137
+ 'optimized' => $optimized_exists_images_count,
138
+ 'optimized_percent' => $optimized_images_percent,
139
+ 'percent_line' => $percent_diff_line,
140
+ 'unoptimized' => $unoptimized,
141
+ 'optimized_size' => $optimized_size,
142
+ 'original_size' => $original_size,
143
+ 'save_size_percent' => $percent_diff,
144
+ 'error' => $error_count,
145
+ );
146
+ }
147
+
148
+ /**
149
+ * Пересчёт размера файла в байтах на человекопонятный вид
150
+ *
151
+ * Пример: вводим 67894 байт, получаем 67.8 KB
152
+ * Пример: вводим 6789477 байт, получаем 6.7 MB
153
+ * @param int $size размер файла в байтах
154
+ * @return string
155
+ */
156
+ public function convertToReadableSize( $size ){
157
+ if ( ! $size ) return 0;
158
+ $base = log( $size ) / log( 1024 );
159
+ $suffix = array( '', 'KB', 'MB', 'GB', 'TB' );
160
+ $f_base = floor( $base );
161
+ return round( pow( 1024, $base - floor( $base ) ), 2 ) . ' ' . $suffix[ $f_base ];
162
+ }
163
+
164
+ }
includes/classes/class.logger.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для логирования ошибок
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_Logger {
15
+
16
+ /**
17
+ * @var string
18
+ */
19
+ private $log_file;
20
+
21
+ /**
22
+ * @var string
23
+ */
24
+ private $upload_dir;
25
+
26
+ /**
27
+ * Инициализация логгера
28
+ */
29
+ public function __construct() {
30
+ $wp_upload_dir = wp_upload_dir();
31
+ $this->upload_dir = $wp_upload_dir['basedir'];
32
+ $this->log_file = $wp_upload_dir['basedir'] . '/wio.log';
33
+ }
34
+
35
+ /**
36
+ * Получает строку со всеми логами
37
+ *
38
+ * @return string
39
+ */
40
+ public function get() {
41
+ $log = '';
42
+ if ( is_file( $this->log_file ) ) {
43
+ $log = file_get_contents( $this->log_file );
44
+ }
45
+ return $log;
46
+ }
47
+
48
+ /**
49
+ * Добавляет сообщение в лог
50
+ *
51
+ * @param string $msg сообщение
52
+ */
53
+ public function add( $msg ) {
54
+ if ( ! $this->is_writable() ) {
55
+ return false;
56
+ }
57
+ $msg = trim( $msg );
58
+ $msg = date( 'd-m-Y H:i' ) . ' ' . $msg;
59
+ $msg .= PHP_EOL;
60
+ file_put_contents( $this->log_file, $msg, FILE_APPEND );
61
+ return true;
62
+ }
63
+
64
+ /**
65
+ * Очищает лог
66
+ */
67
+ public function clear() {
68
+ if ( ! $this->is_writable() ) {
69
+ return false;
70
+ }
71
+ file_put_contents( $this->log_file, '' );
72
+ }
73
+
74
+ /**
75
+ * Проверка возможности записи в лог
76
+ *
77
+ * @return bool
78
+ */
79
+ public function is_writable() {
80
+ if ( is_file( $this->log_file ) and ! is_writable( $this->log_file ) ) {
81
+ return false;
82
+ }
83
+ if ( ! is_writable( $this->upload_dir ) ) {
84
+ return false;
85
+ }
86
+ return true;
87
+ }
88
+ }
includes/classes/class.media-library.php ADDED
@@ -0,0 +1,504 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Exit if accessed directly
4
+ if( !defined('ABSPATH') ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Класс для работы с wordpress media library
10
+ * @author Eugene Jokerov <jokerov@gmail.com>
11
+ * @copyright (c) 2018, Webcraftic
12
+ * @version 1.0
13
+ */
14
+ class WIO_Media_Library {
15
+
16
+ /**
17
+ * Инициализация
18
+ */
19
+ public function __construct()
20
+ {
21
+ $this->filters();
22
+ }
23
+
24
+ /**
25
+ * Установка хуков
26
+ */
27
+ protected function filters()
28
+ {
29
+ // оптимизация при загрузке в медиабиблилтеку
30
+ if( WIO_Plugin::app()->getOption('auto_optimize_when_upload', false) ) {
31
+ add_filter('wp_generate_attachment_metadata', array($this, 'optimizeImageAttachment'), 10, 2);
32
+ }
33
+ // соло оптимизация
34
+ add_filter('attachment_fields_to_edit', array($this, 'attachmentEditorFields'), 1000, 2);
35
+ add_filter('manage_media_columns', array($this, 'addMediaColumn'));
36
+ add_action('manage_media_custom_column', array($this, 'manageMediaColumn'), 10, 2);
37
+ add_action('wp_ajax_wio_reoptimize_image', array($this, 'reoptimizeImageAttachment'));
38
+ add_action('wp_ajax_wio_restore_image', array($this, 'restoreImageAttachment'));
39
+ add_action('admin_enqueue_scripts', array($this, 'enqueueMeadiaScripts'), 10);
40
+ }
41
+
42
+
43
+ /**
44
+ * Оптимизация при загрузке в медиабиблилтеку
45
+ *
46
+ * @param array $metadata метаданные аттачмента
47
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
48
+ * @return array $metadata Метаданные аттачмента
49
+ */
50
+ public function optimizeImageAttachment($metadata, $attachment_id)
51
+ {
52
+ $backup = WIO_Plugin::app()->getBackup();
53
+ $backup_origin_images = WIO_Plugin::app()->getOption('backup_origin_images', false);
54
+ if( $backup_origin_images and !$backup->isBackupWritable() ) {
55
+ return $metadata;
56
+ }
57
+ $wio_attachment = new WIO_Attachment($attachment_id, $metadata);
58
+ $attachment_optimized_data = $wio_attachment->optimize();
59
+
60
+ $original_size = $attachment_optimized_data['original_size'];
61
+ $optimized_size = $attachment_optimized_data['optimized_size'];
62
+ $errors_count = $attachment_optimized_data['errors_count'];
63
+
64
+ $image_statistics = WIO_Plugin::app()->getImageStatistics();
65
+ $image_statistics->addToField('optimized_size', $optimized_size);
66
+ $image_statistics->addToField('original_size', $original_size);
67
+ $image_statistics->addToField('error', $errors_count);
68
+ $image_statistics->addToField('optimized', 1);
69
+ $image_statistics->save();
70
+
71
+ return $metadata;
72
+ }
73
+
74
+ /**
75
+ * Переоптимизация аттачмента. AJAX
76
+ *
77
+ */
78
+ public function reoptimizeImageAttachment()
79
+ {
80
+ $attachment_id = $_POST['id'];
81
+ $backup = WIO_Plugin::app()->getBackup();
82
+ $backup_origin_images = WIO_Plugin::app()->getOption('backup_origin_images', false);
83
+ if( $backup_origin_images and !$backup->isBackupWritable() ) {
84
+ echo $this->getMediaColumnContent($attachment_id);
85
+ die();
86
+ }
87
+ wp_suspend_cache_addition(true);
88
+ $default_level = WIO_Plugin::app()->getOption('image_optimization_level', 'normal');
89
+ $level = isset($_POST['level'])
90
+ ? $_POST['level']
91
+ : $default_level;
92
+ $wio_attachment = new WIO_Attachment($attachment_id);
93
+ $image_statistics = WIO_Plugin::app()->getImageStatistics();
94
+ if( $wio_attachment->isOptimized() ) {
95
+ $wio_attachment->restore();
96
+ $optimized_size = get_post_meta($attachment_id, 'wio_optimized_size', true);
97
+ $original_size = get_post_meta($attachment_id, 'wio_original_size', true);
98
+ $image_statistics->deductFromField('optimized_size', $optimized_size);
99
+ $image_statistics->deductFromField('original_size', $original_size);
100
+ }
101
+ $attachment_optimized_data = $wio_attachment->optimize($level);
102
+ $original_size = $attachment_optimized_data['original_size'];
103
+ $optimized_size = $attachment_optimized_data['optimized_size'];
104
+ $errors_count = $attachment_optimized_data['errors_count'];
105
+ $image_statistics->addToField('optimized_size', $optimized_size);
106
+ $image_statistics->addToField('original_size', $original_size);
107
+ $image_statistics->addToField('error', $errors_count);
108
+ $image_statistics->addToField('optimized', 1);
109
+ $image_statistics->save();
110
+
111
+ echo $this->getMediaColumnContent($attachment_id);
112
+ die();
113
+ }
114
+
115
+ /**
116
+ * Восстановление аттачмента из резервной копии. AJAX
117
+ *
118
+ */
119
+ public function restoreImageAttachment()
120
+ {
121
+ wp_suspend_cache_addition(true);
122
+ $attachment_id = $_POST['id'];
123
+
124
+ $wio_attachment = new WIO_Attachment($attachment_id);
125
+ $image_statistics = WIO_Plugin::app()->getImageStatistics();
126
+ if( $wio_attachment->isOptimized() ) {
127
+ $restored = $wio_attachment->restore();
128
+ if( !is_wp_error($restored) ) {
129
+ $optimized_size = get_post_meta($attachment_id, 'wio_optimized_size', true);
130
+ $original_size = get_post_meta($attachment_id, 'wio_original_size', true);
131
+ delete_post_meta($attachment_id, 'wio_optimized');
132
+ delete_post_meta($attachment_id, 'wio_error');
133
+ $image_statistics->deductFromField('optimized_size', $optimized_size);
134
+ $image_statistics->deductFromField('original_size', $original_size);
135
+ $image_statistics->save();
136
+ }
137
+ }
138
+
139
+ echo $this->getMediaColumnContent($attachment_id);
140
+ die();
141
+ }
142
+
143
+ /**
144
+ * Обработка неоптимизированных изображений
145
+ *
146
+ * @param int $max_process_per_request кол-во аттачментов за 1 запуск
147
+ * @return array
148
+ */
149
+ public function processUnoptimizedAttachments($max_process_per_request)
150
+ {
151
+ $backup = WIO_Plugin::app()->getBackup();
152
+ $backup_origin_images = WIO_Plugin::app()->getOption('backup_origin_images', false);
153
+ if( $backup_origin_images and !$backup->isBackupWritable() ) {
154
+ return array(
155
+ 'end' => true,
156
+ 'msg' => __('No access for writing backups.', 'robin-image-optimizer'),
157
+ );
158
+ }
159
+ if( !$backup->isUploadWritable() ) {
160
+ return array(
161
+ 'end' => true,
162
+ 'msg' => __('The uploads folder is not writable.', 'robin-image-optimizer'),
163
+ );
164
+ }
165
+ $args = array(
166
+ 'post_type' => 'attachment',
167
+ 'post_status' => 'inherit',
168
+ 'post_mime_type' => array('image/jpeg', 'image/gif', 'image/png'),
169
+ 'posts_per_page' => 1,
170
+ 'meta_query' => array(
171
+ array(
172
+ 'key' => 'wio_optimized',
173
+ 'compare' => 'NOT EXISTS',
174
+ ),
175
+ array(
176
+ 'key' => 'wio_error',
177
+ 'compare' => 'NOT EXISTS',
178
+ ),
179
+ )
180
+ );
181
+ $args = apply_filters('wio_unoptimized_args', $args);
182
+ //выборка неоптимизированных изображений
183
+ $args['posts_per_page'] = $max_process_per_request;
184
+ $attachments = new WP_Query($args);
185
+ $total = $attachments->found_posts;
186
+
187
+ $attachments_count = 0;
188
+ if( isset($attachments->posts) ) {
189
+ $attachments_count = count($attachments->posts);
190
+ }
191
+ $image_processor = WIO_Plugin::app()->getImageProcessor();
192
+ $upload_dir = wp_upload_dir();
193
+ $original_size = 0;
194
+ $optimized_size = 0;
195
+ $errors_count = 0;
196
+ $optimized_count = 0;
197
+
198
+ // обработка
199
+ if( $attachments_count ) {
200
+ foreach($attachments->posts as $attachment) {
201
+ $wio_attachment = new WIO_Attachment($attachment->ID);
202
+ $attachment_optimized_data = $wio_attachment->optimize();
203
+ $original_size = $original_size + $attachment_optimized_data['original_size'];
204
+ $optimized_size = $optimized_size + $attachment_optimized_data['optimized_size'];
205
+ $errors_count = $errors_count + $attachment_optimized_data['errors_count'];
206
+ $optimized_count = $optimized_count + $attachment_optimized_data['optimized_count'];
207
+ }
208
+ }
209
+
210
+ $image_statistics = WIO_Plugin::app()->getImageStatistics();
211
+ $image_statistics->addToField('optimized_size', $optimized_size);
212
+ $image_statistics->addToField('original_size', $original_size);
213
+ $image_statistics->addToField('error', $errors_count);
214
+ $image_statistics->addToField('optimized', $optimized_count);
215
+ $image_statistics->save();
216
+
217
+ $remain = $total - $attachments_count;
218
+ if( $remain <= 0 ) {
219
+ $remain = 0;
220
+ }
221
+ $responce = array(
222
+ 'remain' => $remain,
223
+ 'end' => false,
224
+ 'statistic' => $image_statistics->load(),
225
+ );
226
+
227
+ return $responce;
228
+ }
229
+
230
+ /**
231
+ * Восстановление из резервной копии
232
+ *
233
+ * @param int $max_process_per_request кол-во аттачментов за 1 запуск
234
+ * @return array
235
+ */
236
+ public function restoreAllFromBackup($max_process_per_request)
237
+ {
238
+ WIO_Plugin::app()->updateOption('cron_running', false); // останавливаем крон
239
+ $args = array(
240
+ 'post_type' => 'attachment',
241
+ 'post_status' => 'inherit',
242
+ 'post_mime_type' => array('image/jpeg', 'image/gif', 'image/png'),
243
+ 'posts_per_page' => 1,
244
+ 'meta_query' => array(
245
+ array(
246
+ 'key' => 'wio_optimized',
247
+ 'compare' => 'EXISTS',
248
+ ),
249
+ array(
250
+ 'key' => 'wio_error',
251
+ 'compare' => 'NOT EXISTS',
252
+ ),
253
+ )
254
+ );
255
+ $args['posts_per_page'] = $max_process_per_request;
256
+ $attachments = new WP_Query($args);
257
+ $total = $attachments->found_posts;
258
+ $attachments_count = 0;
259
+ if( isset($attachments->posts) ) {
260
+ $attachments_count = count($attachments->posts);
261
+ }
262
+
263
+ $image_statistics = WIO_Plugin::app()->getImageStatistics();
264
+ $logger = WIO_Plugin::app()->getLogger();
265
+ $original_size = 0;
266
+ $optimized_size = 0;
267
+ // обработка
268
+ if( $attachments_count ) {
269
+ foreach($attachments->posts as $attachment) {
270
+ $wio_attachment = new WIO_Attachment($attachment->ID);
271
+ // восстанавливаем файл
272
+ $restore_data = $wio_attachment->restore();
273
+ if( is_wp_error($restore_data) ) {
274
+ update_post_meta($attachment->ID, 'wio_error', $restore_data->get_error_message());
275
+ continue;
276
+ }
277
+ // снимаем отметку об оптимизации
278
+ delete_post_meta($attachment->ID, 'wio_optimized');
279
+ // вычитаем из статистики и обновляем статистику
280
+ $attachment_optimized_size = get_post_meta($attachment->ID, 'wio_optimized_size', true);
281
+ $attachment_original_size = get_post_meta($attachment->ID, 'wio_original_size', true);
282
+ $original_size = $original_size + $attachment_original_size;
283
+ $optimized_size = $optimized_size + $attachment_optimized_size;
284
+ }
285
+ }
286
+ //$image_statistics->deductFromField( 'optimized', $attachments_count );
287
+ $image_statistics->deductFromField('optimized_size', $optimized_size);
288
+ $image_statistics->deductFromField('original_size', $original_size);
289
+ $image_statistics->save();
290
+ $remain = $total - $attachments_count;
291
+
292
+ return array(
293
+ 'remain' => $remain,
294
+ );
295
+ }
296
+
297
+ /**
298
+ * Кол-во оптимизированных изображений
299
+ *
300
+ * @return int
301
+ */
302
+ public function getOptimizedCount()
303
+ {
304
+ $args = array(
305
+ 'post_type' => 'attachment',
306
+ 'post_status' => 'inherit',
307
+ 'post_mime_type' => array('image/jpeg', 'image/gif', 'image/png'),
308
+ 'posts_per_page' => 1,
309
+ 'meta_query' => array(
310
+ array(
311
+ 'key' => 'wio_optimized',
312
+ 'compare' => 'EXISTS',
313
+ ),
314
+ )
315
+ );
316
+ $attachments = new WP_Query($args);
317
+ $total = $attachments->found_posts;
318
+
319
+ return $total;
320
+ }
321
+
322
+ /**
323
+ * Add "Image Optimizer" column in the Media Uploader
324
+ *
325
+ * @param array $form_fields An array of attachment form fields.
326
+ * @param object $post The WP_Post attachment object.
327
+ * @return array
328
+ */
329
+ public function attachmentEditorFields($form_fields, $post)
330
+ {
331
+ global $pagenow;
332
+
333
+ if( 'post.php' === $pagenow ) {
334
+ return $form_fields;
335
+ }
336
+
337
+ $form_fields['wio'] = array(
338
+ 'label' => 'Image Optimizer',
339
+ 'input' => 'html',
340
+ 'html' => $this->getMediaColumnContent($post->ID),
341
+ 'show_in_edit' => true,
342
+ 'show_in_modal' => true,
343
+ );
344
+
345
+ return $form_fields;
346
+ }
347
+
348
+ /**
349
+ * Add "wio" column in upload.php.
350
+ *
351
+ * @param array $columns An array of columns displayed in the Media list table.
352
+ * @return array
353
+ */
354
+ public function addMediaColumn($columns)
355
+ {
356
+ $columns['wio_optimized_file'] = __('Image optimizer', 'image optimizer');
357
+
358
+ return $columns;
359
+ }
360
+
361
+ /**
362
+ * Add content to the "wio" columns in upload.php.
363
+ *
364
+ * @param string $column_name Name of the custom column.
365
+ * @param int $attachment_id Attachment ID.
366
+ */
367
+ public function manageMediaColumn($column_name, $attachment_id)
368
+ {
369
+ if( 'wio_optimized_file' !== $column_name ) {
370
+ return;
371
+ }
372
+ echo $this->getMediaColumnContent($attachment_id);
373
+ }
374
+
375
+ /**
376
+ * Выводит блок статистики для аттачмента в медиабиблиотеке
377
+ *
378
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
379
+ */
380
+ public function getMediaColumnContent($attachment_id)
381
+ {
382
+ ob_start();
383
+ $is_optimized = get_post_meta($attachment_id, 'wio_optimized', true);
384
+ $attach_meta = wp_get_attachment_metadata($attachment_id);
385
+ $attach_dimensions = '0 x 0';
386
+ if ( isset( $attach_meta['width'] ) and isset( $attach_meta['height'] ) ) {
387
+ $attach_dimensions = $attach_meta['width'] . ' × ' . $attach_meta['height'];
388
+ }
389
+ clearstatcache();
390
+ $attachment_file_size = filesize(get_attached_file($attachment_id));
391
+ if( $is_optimized ) {
392
+ $optimized_size = get_post_meta($attachment_id, 'wio_optimized_size', true);
393
+ $original_size = get_post_meta($attachment_id, 'wio_original_size', true);
394
+ $original_main_size = get_post_meta($attachment_id, 'wio_original_main_size', true);
395
+ $thumbnails_optimized = get_post_meta($attachment_id, 'wio_thumbnails_count', true);
396
+ if( !$original_main_size ) {
397
+ $original_main_size = $original_size;
398
+ }
399
+ $optimization_level = get_post_meta($attachment_id, 'wio_optimization_level', true);
400
+ $error_msg = get_post_meta($attachment_id, 'wio_error', true);
401
+ $backuped = get_post_meta($attachment_id, 'wio_backuped', true);
402
+ $diff_percent = 0;
403
+ $diff_percent_all = 0;
404
+ if( $attachment_file_size and $original_main_size ) {
405
+ $diff_percent = round(($original_main_size - $attachment_file_size) * 100 / $original_main_size);
406
+ }
407
+ if( $optimized_size and $original_size ) {
408
+ $diff_percent_all = round(($original_size - $optimized_size) * 100 / $original_size);
409
+ }
410
+ ?>
411
+
412
+
413
+ <ul class="wio-datas-list" data-size="<?php echo esc_attr(size_format($attachment_file_size)); ?>" data-dimensions="<?php echo esc_attr($attach_dimensions); ?>">
414
+ <li class="wio-data-item"><span class="data"><?php _e('New Filesize:', 'robin-image-optimizer'); ?></span>
415
+ <strong class="big"><?php echo esc_attr(size_format($attachment_file_size)); ?></strong></li>
416
+ <li class="wio-data-item">
417
+ <span class="data"><?php _e('Original Saving:', 'robin-image-optimizer'); ?></span>
418
+ <strong>
419
+ <span class="wio-chart-value"><?php echo esc_attr($diff_percent); ?></span>%
420
+ </strong>
421
+ </li>
422
+ <li class="wio-data-item">
423
+ <span class="data"><?php _e('Original Filesize:', 'robin-image-optimizer'); ?></span>
424
+ <strong class="original"><?php echo esc_attr(size_format($original_main_size)); ?></strong>
425
+ </li>
426
+ <li class="wio-data-item"><span class="data"><?php _e('Level:', 'robin-image-optimizer'); ?></span>
427
+ <strong>
428
+ <?php
429
+ if ( ! $error_msg ) {
430
+ if( $optimization_level == 'normal' ) {
431
+ echo __('Normal', 'robin-image-optimizer');
432
+ } else if( $optimization_level == 'aggresive' ) {
433
+ echo __('Aggresive', 'robin-image-optimizer');
434
+ } else {
435
+ echo __('Ultra', 'robin-image-optimizer');
436
+ }
437
+ }
438
+ ?>
439
+ </strong>
440
+ </li>
441
+ <li class="wio-data-item">
442
+ <span class="data"><?php _e('Thumbnails Optimized:', 'robin-image-optimizer'); ?></span>
443
+ <strong class="original"><?php echo intval($thumbnails_optimized); ?></strong>
444
+ </li>
445
+ <li class="wio-data-item">
446
+ <span class="data"><?php _e('Overall Saving:', 'robin-image-optimizer'); ?></span>
447
+ <strong class="original"><?php echo esc_attr($diff_percent_all); ?>%</strong>
448
+ </li>
449
+ <?php if( $error_msg ) : ?>
450
+ <li class="wio-data-item">
451
+ <span class="data"><?php _e('Error Message:', 'robin-image-optimizer'); ?></span>
452
+ <strong><?php echo esc_attr($error_msg); ?></strong></li>
453
+ <?php endif; ?>
454
+ </ul>
455
+ <div class="wio-datas-actions-links" style="display:inline;">
456
+ <?php if( $optimization_level != 'normal' ) : ?>
457
+ <a data-id="<?php echo esc_attr($attachment_id); ?>" data-level="normal" href="#" class="wio-reoptimize button-wio-manual-override-upload" data-waiting-label="<?php _e('Optimization in progress', 'robin-image-optimizer'); ?>">
458
+ <span class="dashicons dashicons-admin-generic"></span><span class="wio-hide-if-small"><?php _e('Re-Optimize to', 'robin-image-optimizer'); ?> </span><?php _e('Normal', 'robin-image-optimizer'); ?>
459
+ <span class="wio-hide-if-small"></span>
460
+ </a>
461
+ <?php endif; ?>
462
+ <?php if( $optimization_level != 'aggresive' ) : ?>
463
+ <a data-id="<?php echo esc_attr($attachment_id); ?>" data-level="aggresive" href="#" class="wio-reoptimize button-wio-manual-override-upload" data-waiting-label="<?php _e('Optimization in progress', 'robin-image-optimizer'); ?>">
464
+ <span class="dashicons dashicons-admin-generic"></span><span class="wio-hide-if-small"><?php _e('Re-Optimize to', 'robin-image-optimizer'); ?> </span><?php _e('Medium', 'robin-image-optimizer'); ?>
465
+ <span class="wio-hide-if-small"></span>
466
+ </a>
467
+ <?php endif; ?>
468
+ <?php if( $optimization_level != 'ultra' ) : ?>
469
+ <a data-id="<?php echo esc_attr($attachment_id); ?>" data-level="ultra" href="#" class="wio-reoptimize button-wio-manual-override-upload" data-waiting-label="<?php _e('Optimization in progress', 'robin-image-optimizer'); ?>">
470
+ <span class="dashicons dashicons-admin-generic"></span><span class="wio-hide-if-small"><?php _e('Re-Optimize to', 'robin-image-optimizer'); ?> </span><?php _e('High', 'robin-image-optimizer'); ?>
471
+ <span class="wio-hide-if-small"></span>
472
+ </a>
473
+ <?php endif; ?>
474
+ <?php if( $backuped ) : ?>
475
+ <a href="#" data-id="<?php echo esc_attr($attachment_id); ?>" class="button-wio-restore attachment-has-backup" data-waiting-label="<?php _e('Recovery in progress', 'robin-image-optimizer'); ?>"><span class="dashicons dashicons-image-rotate"></span><?php _e('Restore original', 'robin-image-optimizer'); ?>
476
+ </a>
477
+ <?php endif; ?>
478
+ </div>
479
+ <!-- .wio-datas-actions-links -->
480
+
481
+ <?php
482
+ } else {
483
+ ?>
484
+ <button type="button" data-id="<?php echo esc_attr($attachment_id); ?>" data-level="" class="wio-reoptimize button button-primary button-large" data-waiting-label="<?php _e('Optimization in progress', 'robin-image-optimizer'); ?>" data-size="<?php echo esc_attr(size_format($attachment_file_size)); ?>" data-dimensions="<?php echo esc_attr($attach_dimensions); ?>"><?php _e('Optimize', 'robin-image-optimizer'); ?></button>
485
+ <?php
486
+ }
487
+
488
+ return ob_get_clean();
489
+ }
490
+
491
+ /**
492
+ * Добавляем стили и скрипты в медиабиблиотеку
493
+ */
494
+ public function enqueueMeadiaScripts($hook)
495
+ {
496
+ if( $hook != 'upload.php' ) {
497
+ return;
498
+ }
499
+ wp_enqueue_style('wio-install-addons', WIO_PLUGIN_URL . '/admin/assets/css/media.css', array(), WIO_Plugin::app()
500
+ ->getPluginVersion());
501
+ wp_enqueue_script('wio-install-addons', WIO_PLUGIN_URL . '/admin/assets/js/single-optimization.js', array('jquery'), WIO_Plugin::app()
502
+ ->getPluginVersion());
503
+ }
504
+ }
includes/classes/index.php ADDED
File without changes
includes/functions.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Get size information for all currently-registered image sizes.
5
+ *
6
+ * @global $_wp_additional_image_sizes
7
+ * @uses get_intermediate_image_sizes()
8
+ * @return array $sizes Data for all currently-registered image sizes.
9
+ */
10
+ function wio_get_image_sizes() {
11
+ global $_wp_additional_image_sizes;
12
+
13
+ $sizes = array();
14
+
15
+ foreach ( get_intermediate_image_sizes() as $_size ) {
16
+ if ( in_array( $_size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
17
+ $sizes[ $_size ]['width'] = get_option( "{$_size}_size_w" );
18
+ $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
19
+ $sizes[ $_size ]['crop'] = (bool) get_option( "{$_size}_crop" );
20
+ } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
21
+ $sizes[ $_size ] = array(
22
+ 'width' => $_wp_additional_image_sizes[ $_size ]['width'],
23
+ 'height' => $_wp_additional_image_sizes[ $_size ]['height'],
24
+ 'crop' => $_wp_additional_image_sizes[ $_size ]['crop'],
25
+ );
26
+ }
27
+ }
28
+
29
+ return $sizes;
30
+ }
31
+
32
+ /**
33
+ * Пересчёт размера файла в байтах на человекопонятный вид
34
+ *
35
+ * Пример: вводим 67894 байт, получаем 67.8 KB
36
+ * Пример: вводим 6789477 байт, получаем 6.7 MB
37
+ * @param int $size размер файла в байтах
38
+ * @return string
39
+ */
40
+ function wio_convert_bytes( $size ){
41
+ if ( ! $size ) return 0;
42
+ $base = log( $size ) / log( 1024 );
43
+ $suffix = array( '', 'KB', 'MB', 'GB', 'TB' );
44
+ $f_base = floor( $base );
45
+ return round( pow( 1024, $base - floor( $base ) ), 2 ) . ' ' . $suffix[ $f_base ];
46
+ }
47
+
48
+
includes/index.php ADDED
File without changes
index.php ADDED
File without changes
languages/index.php ADDED
File without changes
languages/robin-image-optimizer-ru_RU.mo ADDED
Binary file
languages/robin-image-optimizer-ru_RU.po ADDED
@@ -0,0 +1,502 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Image optimizer\n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2018-06-25 21:12+0000\n"
6
+ "PO-Revision-Date: 2018-06-25 21:13+0000\n"
7
+ "Last-Translator: Alexander Parfilov <alexparfilov@gmail.com>\n"
8
+ "Language-Team: Русский\n"
9
+ "Language: ru_RU\n"
10
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10 >= 2 && "
11
+ "n%10<=4 &&(n%100<10||n%100 >= 20)? 1 : 2);\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Loco https://localise.biz/"
16
+
17
+ #: image-optimizer.php:106
18
+ msgid "Webcraftic Image optimizer"
19
+ msgstr "Webcraftic Image optimizer"
20
+
21
+ #: includes/class.plugin.php:85
22
+ msgid "An invalid instance of the class was passed."
23
+ msgstr "Был принят недопустимый экземпляр класса."
24
+
25
+ #: admin/pages/log.php:40 admin/pages/log.php:66 admin/pages/log.php:76
26
+ #: admin/pages/settings.php:217
27
+ msgid "Error Log"
28
+ msgstr "Журнал ошибок"
29
+
30
+ #. Name of the plugin
31
+ #: admin/pages/log.php:65 admin/pages/statistic.php:41
32
+ #: admin/pages/statistic.php:69
33
+ msgid "Image optimizer"
34
+ msgstr "Image optimizer"
35
+
36
+ #: admin/pages/log.php:79
37
+ msgid ""
38
+ "In this section, you can track image optimization errors. Sending this log "
39
+ "to us, will help in solving possible optimization issues."
40
+ msgstr ""
41
+ "В этом разделе вы можете отследить ошибки оптимизации изображений. Отправка "
42
+ "этого лога нам, поможет в решении возможных проблем с оптимизацией."
43
+
44
+ #: admin/pages/settings.php:40 admin/pages/settings.php:147
45
+ msgid "Main Settings"
46
+ msgstr "Основные настройки"
47
+
48
+ #: admin/pages/settings.php:123
49
+ msgid "Folder wp-content/uploads/ is unavailable for writing"
50
+ msgstr "Папка wp-content/uploads/ недоступна для записи"
51
+
52
+ #: admin/pages/settings.php:127
53
+ msgid "Folder wp-content/uploads/wio-backup/ is unavailable for writing"
54
+ msgstr "Папка wp-content/uploads/wio-backup/ недоступна для записи"
55
+
56
+ #: admin/pages/settings.php:130
57
+ msgid "Cron is disabled in wp-config.php"
58
+ msgstr "Crom отключен в wp-config.php"
59
+
60
+ #: admin/pages/settings.php:147
61
+ msgid "This section you can set main images optimization settings."
62
+ msgstr ""
63
+ "В этом разделе вы можете настроить основные параметры оптимизации "
64
+ "изображений."
65
+
66
+ #: admin/pages/settings.php:155
67
+ msgid "Compression mode"
68
+ msgstr "Режим сжатия"
69
+
70
+ #: admin/pages/settings.php:159 admin/pages/statistic.php:324
71
+ #: includes/classes/class.media-library.php:396
72
+ msgid "Normal"
73
+ msgstr "Нормальный"
74
+
75
+ #: admin/pages/settings.php:160
76
+ msgid ""
77
+ "This mode provides lossless compression and your images will be optimized "
78
+ "without visible changes. If you want an ideal image quality, we recommend "
79
+ "this mode. The size of the files will be reduced approximately 2 times. If "
80
+ "this is not enough for you, try other modes."
81
+ msgstr ""
82
+ "Этот режим обеспечивает сжатие без потерь и ваши изображения будут "
83
+ "оптимизированы без видимых изменений. Если вы хотите идеальное качество "
84
+ "изображений, мы рекомендуем этот режим. Размер фалов уменьшится "
85
+ "приблизительно в 2 раза. Если вам этого недостаточно, попробуйте другие "
86
+ "режимы."
87
+
88
+ #: admin/pages/settings.php:164 admin/pages/statistic.php:325
89
+ #: includes/classes/class.media-library.php:401
90
+ msgid "Medium"
91
+ msgstr "Средний"
92
+
93
+ #: admin/pages/settings.php:165
94
+ msgid ""
95
+ "This mode provides an ideal optimization of your images without significant "
96
+ "quality loss. The file size will be reduced approximately 5 times with a "
97
+ "slight decrease in image quality. In most cases that cannot be seen with the "
98
+ "naked eye."
99
+ msgstr ""
100
+ "Этот режим обеспечивает идеальную оптимизацию ваших изображений без "
101
+ "существенных потерь качества. Размер файлов уменьшиться приблизительно в 5 "
102
+ "раз при незначительном снижении качества изображений. Чаще всего, "
103
+ "невооружённым взглядом это даже не заметно."
104
+
105
+ #: admin/pages/settings.php:169 admin/pages/statistic.php:326
106
+ #: includes/classes/class.media-library.php:406
107
+ msgid "High"
108
+ msgstr "Высокий"
109
+
110
+ #: admin/pages/settings.php:170
111
+ msgid ""
112
+ "This mode will use all available optimization methods for maximum image "
113
+ "compression. The file size will be reduced approximately 7 times. The "
114
+ "quality of some images may deteriorate slightly. Use this mode if you need "
115
+ "the maximum weight reduction, and you are ready to accept the loss of image "
116
+ "quality."
117
+ msgstr ""
118
+ "Этот режим будет использовать все доступные методы оптимизации для "
119
+ "максимального сжатия изображения. Размер файлов уменьшится приблизительно в "
120
+ "7 раз. Качество некоторых изображений может немного ухудшиться. Используйте "
121
+ "этот режим, если вам требуется максимальное снижение веса, и вы готовы "
122
+ "смириться с потерей качества изображений."
123
+
124
+ #: admin/pages/settings.php:174
125
+ msgid "Select the compression mode appropriate for your case."
126
+ msgstr "Выберите режим сжатия, подходящий для вашей ситуации."
127
+
128
+ #: admin/pages/settings.php:195
129
+ msgid "Auto optimization on upload"
130
+ msgstr "Автоматическая оптимизация изображений при загрузке"
131
+
132
+ #: admin/pages/settings.php:197
133
+ msgid ""
134
+ "Automatically compress all images that you upload directly to the WordPress "
135
+ "media library, when editing pages and posts or using themes and plugins."
136
+ msgstr ""
137
+ "Автоматическое сжатие всех изображений, которые вы загружаете в "
138
+ "медиабиблиотеку WordPress напрямую, при редактировании страниц и записей или "
139
+ "с использованием тем и плагинов."
140
+
141
+ #: admin/pages/settings.php:206
142
+ msgid "Backup images"
143
+ msgstr "Резервное копирование изображений"
144
+
145
+ #: admin/pages/settings.php:208
146
+ msgid ""
147
+ "Before optimizing, all your images will be saved in a separate folder for "
148
+ "future recovery."
149
+ msgstr ""
150
+ "Перед началом оптимизации, все ваши изображения будут сохранены в отдельной "
151
+ "папке для возможности восстановления в будущем."
152
+
153
+ #: admin/pages/settings.php:219
154
+ msgid "Enable error logging. The log will be displayed on a separate tab."
155
+ msgstr ""
156
+ "Включить ведение журнала ошибок. Он будет отображаться на отдельной вкладке."
157
+
158
+ #: admin/pages/settings.php:234
159
+ msgid "Leave EXIF data"
160
+ msgstr "Оставлять данные EXIF"
161
+
162
+ #: admin/pages/settings.php:236
163
+ msgid ""
164
+ "EXIF is information stored in photos: camera model, shutter speed, exposure "
165
+ "compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended "
166
+ "data. If your project is dedicated to photography and you need to display "
167
+ "this data, then enable this option."
168
+ msgstr ""
169
+ "EXIF - это информация, хранящаяся в фотографиях: модель камеры, скорость "
170
+ "затвора, компенсация экспозиции, ISO, GPS и т. Д. По умолчанию плагин "
171
+ "удаляет расширенные данные EXIF. Если ваш проект посвящён фотографии и вам "
172
+ "нужно отображать эти данные, то включите эту опцию."
173
+
174
+ #: admin/pages/settings.php:242
175
+ msgid "Optimization"
176
+ msgstr "Оптимизация"
177
+
178
+ #: admin/pages/settings.php:242
179
+ msgid "Here you can specify additional image optimization options."
180
+ msgstr ""
181
+ "Здесь вы можете задать дополнительные параметры оптимизации изображений."
182
+
183
+ #: admin/pages/settings.php:250
184
+ msgid "Resizing large images"
185
+ msgstr "Изменение размера больших изображений"
186
+
187
+ #: admin/pages/settings.php:252
188
+ msgid ""
189
+ "When you upload images from a camera or stock, they may be too high "
190
+ "resolution and it is not necessary for web. The option allows you to "
191
+ "automatically change images resolution on upload."
192
+ msgstr ""
193
+ "Когда вы закачиваете изображения с камеры или фотостока, они могут быть "
194
+ "слишком высокого разрешения и для веба это не нужно. Опция позволяет "
195
+ "автоматически изменять разрешение изображений при загрузке."
196
+
197
+ #: admin/pages/settings.php:268
198
+ msgid "Enter the maximum size (px)"
199
+ msgstr "Введите максимальный размер (px)"
200
+
201
+ #: admin/pages/settings.php:270
202
+ msgid ""
203
+ "Set the maximum images resolution on the long side. For horizontal images, "
204
+ "this will be the width, and for vertical images - the height. The resolution "
205
+ "of the images will be changed proportionally according to the set value."
206
+ msgstr ""
207
+ "Задайте максимальное разрешение изображений по длинной стороне. Для "
208
+ "горизонтальных изображений это будет ширина, а для вертикальных — высота. "
209
+ "Разрешение изображений будет изменено пропорционально в соответствии с "
210
+ "заданным значением."
211
+
212
+ #: admin/pages/settings.php:288
213
+ msgid "Optimize thumbnails"
214
+ msgstr "Оптимизировать миниатюры"
215
+
216
+ #: admin/pages/settings.php:291
217
+ msgid ""
218
+ "Choose which sizes of thumbnails should be optimized and uncheck those that "
219
+ "do not need optimization."
220
+ msgstr ""
221
+ "Выберите какие размеры миниатюр следует оптимизировать и снимите галочки с "
222
+ "тех, оптимизация которых не нужна."
223
+
224
+ #: admin/pages/settings.php:298
225
+ msgid "Scheduled optimization"
226
+ msgstr "Оптимизация по расписанию"
227
+
228
+ #: admin/pages/settings.php:298
229
+ msgid "Schedule your images optimization."
230
+ msgstr "Настройка оптимизации изображений по расписанию."
231
+
232
+ #: admin/pages/settings.php:306
233
+ msgid "Enable Scheduled Optimization"
234
+ msgstr "Включить оптимизацию по расписанию"
235
+
236
+ #: admin/pages/settings.php:308
237
+ msgid ""
238
+ "You can enable image optimization on schedule. The plugin will optimize "
239
+ "specified number of images automatically after selected time."
240
+ msgstr ""
241
+ "Вы можете включить оптимизацию изображений по расписанию. Через выбранное "
242
+ "время плагин будет оптимизировать заданное количество изображений "
243
+ "автоматически."
244
+
245
+ #: admin/pages/settings.php:323 includes/classes/class.cron.php:56
246
+ msgid "1 min"
247
+ msgstr "1 мин"
248
+
249
+ #: admin/pages/settings.php:324 includes/classes/class.cron.php:60
250
+ msgid "2 min"
251
+ msgstr "2 мин"
252
+
253
+ #: admin/pages/settings.php:325 includes/classes/class.cron.php:64
254
+ msgid "5 min"
255
+ msgstr "5 мин"
256
+
257
+ #: admin/pages/settings.php:326 includes/classes/class.cron.php:68
258
+ msgid "10 min"
259
+ msgstr "10 мин"
260
+
261
+ #: admin/pages/settings.php:327 includes/classes/class.cron.php:72
262
+ msgid "30 min"
263
+ msgstr "30 мин"
264
+
265
+ #: admin/pages/settings.php:328
266
+ msgid "Hour"
267
+ msgstr "1 час"
268
+
269
+ #: admin/pages/settings.php:329
270
+ msgid "Day"
271
+ msgstr "1 день"
272
+
273
+ #: admin/pages/settings.php:332
274
+ msgid "Run every"
275
+ msgstr "Запускать через"
276
+
277
+ #: admin/pages/settings.php:333
278
+ msgid "Select time at which the task will be repeated."
279
+ msgstr "Выберите время, через которое будет повторяться задание."
280
+
281
+ #: admin/pages/settings.php:340
282
+ msgid "Images per iteration"
283
+ msgstr "Количество изображений за итерацию"
284
+
285
+ #: admin/pages/settings.php:342
286
+ msgid ""
287
+ "Specify the number of images that will be optimized during the job. For "
288
+ "example, if you enter 5 and select 5 min, the plugin will optimize 5 images "
289
+ "every 5 minutes."
290
+ msgstr ""
291
+ "Задайте количество изображений, которое будут оптимизировано во время "
292
+ "выполнения задания. Например, если вы введёте 5 и выберете 5 мин., то плагин "
293
+ "будет оптимизировать 5 изображений каждые 5 минут."
294
+
295
+ #: admin/pages/settings.php:371
296
+ msgid "Manage backups"
297
+ msgstr "Управление резервными копиями"
298
+
299
+ #: admin/pages/settings.php:372
300
+ msgid "You can restore the original images from a backup or clear them."
301
+ msgstr ""
302
+ "Вы можете восстановить оригинальные изображения из резервной копии или "
303
+ "очистить их."
304
+
305
+ #: admin/pages/settings.php:379
306
+ msgid "Are you sure?"
307
+ msgstr "Вы уверены?"
308
+
309
+ #: admin/pages/settings.php:379
310
+ msgid "Restore"
311
+ msgstr "Восстановить"
312
+
313
+ #: admin/pages/settings.php:380
314
+ msgid "Are you sure that you want to clear image backups folder?"
315
+ msgstr ""
316
+ "Вы действительно хотите очистить папку с резервными копиями изображений?"
317
+
318
+ #: admin/pages/settings.php:380
319
+ msgid "Clear Backup"
320
+ msgstr "Очистить резервные копии"
321
+
322
+ #: admin/pages/settings.php:387
323
+ msgid "Restore completed."
324
+ msgstr "Восстановление завершено."
325
+
326
+ #: admin/pages/settings.php:388
327
+ msgid "The backup folder was cleared."
328
+ msgstr "Папка с резервными копиями очищена."
329
+
330
+ #: admin/pages/statistic.php:70
331
+ msgid "General"
332
+ msgstr "Основные"
333
+
334
+ #: admin/pages/statistic.php:144
335
+ msgid "Image optimization dashboard"
336
+ msgstr "Панель управления оптимизацией изображений"
337
+
338
+ #: admin/pages/statistic.php:147
339
+ msgid ""
340
+ "Monitor image optimization statistics and run on demand or scheduled "
341
+ "optimization."
342
+ msgstr ""
343
+ "Отслеживайте статистику оптимизации изображений и запускайте оптимизацию по "
344
+ "требованию или по расписанию."
345
+
346
+ #: admin/pages/statistic.php:160
347
+ msgid "You optimized"
348
+ msgstr "Вы оптимизировали"
349
+
350
+ #: admin/pages/statistic.php:160
351
+ msgid "of your website's images"
352
+ msgstr "изображений сайта"
353
+
354
+ #: admin/pages/statistic.php:167 admin/pages/statistic.php:292
355
+ msgid "Unoptimized"
356
+ msgstr "Не оптимизировано"
357
+
358
+ #: admin/pages/statistic.php:168 admin/pages/statistic.php:293
359
+ msgid "Optimized"
360
+ msgstr "Оптимизировано"
361
+
362
+ #: admin/pages/statistic.php:169 admin/pages/statistic.php:294
363
+ msgid "Error"
364
+ msgstr "Ошибка"
365
+
366
+ #: admin/pages/statistic.php:172
367
+ msgid "Statistics"
368
+ msgstr "Статистика"
369
+
370
+ #: admin/pages/statistic.php:178
371
+ msgid ""
372
+ "that's the number of original images<br> you optimized with Image Optimizer"
373
+ msgstr ""
374
+ "количество исходных изображений<br> которые вы оптимизировали с Image "
375
+ "Optimizer"
376
+
377
+ #: admin/pages/statistic.php:184 admin/pages/statistic.php:298
378
+ msgid "Original size"
379
+ msgstr "Оригинальный размер"
380
+
381
+ #: admin/pages/statistic.php:189 admin/pages/statistic.php:303
382
+ msgid "Optimized size"
383
+ msgstr "Оптимизированный размер"
384
+
385
+ #: admin/pages/statistic.php:200
386
+ msgid "that's the size you saved <br>by using Image Optimizer"
387
+ msgstr ""
388
+ "вы сохранили благодаря<br>\n"
389
+ "Image Optimizer"
390
+
391
+ #: admin/pages/statistic.php:212 admin/pages/statistic.php:316
392
+ msgid "All images from the media library are optimized."
393
+ msgstr "Все изображения из медиабиблиотеки оптимизированы."
394
+
395
+ #: admin/pages/statistic.php:214 admin/pages/statistic.php:318
396
+ msgid "Optimization in progress. Remained"
397
+ msgstr "Идёт оптимизация. Осталось"
398
+
399
+ #: admin/pages/statistic.php:214
400
+ msgid "images."
401
+ msgstr "изображений."
402
+
403
+ #: admin/pages/statistic.php:234 admin/pages/statistic.php:242
404
+ msgid "Run"
405
+ msgstr "Запустить"
406
+
407
+ #: admin/pages/statistic.php:240 admin/pages/statistic.php:246
408
+ msgid "Stop"
409
+ msgstr "Остановить"
410
+
411
+ #: admin/pages/statistic.php:246
412
+ msgid "Do you want to start optimization without backup?"
413
+ msgstr "Вы хотите начать оптимизацию без возможности восстановления?"
414
+
415
+ #: admin/pages/statistic.php:246
416
+ msgid "Resume"
417
+ msgstr "Возобновить"
418
+
419
+ #: admin/pages/statistic.php:281
420
+ msgid "Images optimization"
421
+ msgstr "Оптимизация изображений"
422
+
423
+ #: includes/classes/class.backup.php:77
424
+ msgid "Unable to create backup folder."
425
+ msgstr "Невозможно создать папку для резервного копирования."
426
+
427
+ #: includes/classes/class.backup.php:132
428
+ msgid "Unable to create backup subfolder."
429
+ msgstr "Невозможно создать подпапку для резервного копирования."
430
+
431
+ #: includes/classes/class.cron.php:76
432
+ msgid "60 min"
433
+ msgstr "60 мин"
434
+
435
+ #: includes/classes/class.cron.php:80
436
+ msgid "daily"
437
+ msgstr "ежедневно"
438
+
439
+ #: includes/classes/class.media-library.php:148
440
+ msgid "No access for writing backups."
441
+ msgstr "Нет доступа для записи резервных копий."
442
+
443
+ #: includes/classes/class.media-library.php:154
444
+ msgid "The uploads folder is not writable."
445
+ msgstr "Папка uploads недоступна для записи."
446
+
447
+ #: includes/classes/class.media-library.php:380
448
+ msgid "New Filesize:"
449
+ msgstr "Новый размер:"
450
+
451
+ #: includes/classes/class.media-library.php:382
452
+ msgid "Original Saving:"
453
+ msgstr "Сжатие:"
454
+
455
+ #: includes/classes/class.media-library.php:387
456
+ msgid "Original Filesize:"
457
+ msgstr "Размер оригинала:"
458
+
459
+ #: includes/classes/class.media-library.php:388
460
+ msgid "Level:"
461
+ msgstr "Уровень:"
462
+
463
+ #: includes/classes/class.media-library.php:390
464
+ msgid "Error Message:"
465
+ msgstr "Сообщение об ошибке:"
466
+
467
+ #: includes/classes/class.media-library.php:395
468
+ #: includes/classes/class.media-library.php:400
469
+ #: includes/classes/class.media-library.php:405
470
+ #: includes/classes/class.media-library.php:418
471
+ msgid "Optimization in progress"
472
+ msgstr "Выполняется оптимизация"
473
+
474
+ #: includes/classes/class.media-library.php:396
475
+ #: includes/classes/class.media-library.php:401
476
+ #: includes/classes/class.media-library.php:406
477
+ msgid "Re-Optimize to"
478
+ msgstr "Пережать в"
479
+
480
+ #: includes/classes/class.media-library.php:410
481
+ msgid "Recovery in progress"
482
+ msgstr "Восстанавливается"
483
+
484
+ #: includes/classes/class.media-library.php:410
485
+ msgid "Restore original"
486
+ msgstr "Восстановить оригинал"
487
+
488
+ #: includes/classes/class.media-library.php:418
489
+ msgid "Optimize"
490
+ msgstr "Оптимизировать"
491
+
492
+ #. Description of the plugin
493
+ msgid ""
494
+ "Optimize images without losing quality, speed up your website load, improve "
495
+ "SEO and save money on server and CDN bandwidth."
496
+ msgstr ""
497
+ "Оптимизируйте изображения без потери качества, ускоряйте загрузку сайта, "
498
+ "улучшайте SEO и экономьте на трафик сервера и CDN."
499
+
500
+ #. Author of the plugin
501
+ msgid "Webcraftic <wordpress.webraftic@gmail.com>"
502
+ msgstr "Webcraftic <wordpress.webraftic@gmail.com>"
languages/robin-image-optimizer.pot ADDED
@@ -0,0 +1,447 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #, fuzzy
2
+ msgid ""
3
+ msgstr ""
4
+ "Project-Id-Version: Image optimizer\n"
5
+ "Report-Msgid-Bugs-To: \n"
6
+ "POT-Creation-Date: 2018-06-25 21:12+0000\n"
7
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
8
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
9
+ "Language-Team: \n"
10
+ "Language: \n"
11
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
12
+ "MIME-Version: 1.0\n"
13
+ "Content-Type: text/plain; charset=UTF-8\n"
14
+ "Content-Transfer-Encoding: 8bit\n"
15
+ "X-Generator: Loco https://localise.biz/"
16
+
17
+ #: image-optimizer.php:106
18
+ msgid "Webcraftic Image optimizer"
19
+ msgstr ""
20
+
21
+ #: includes/class.plugin.php:85
22
+ msgid "An invalid instance of the class was passed."
23
+ msgstr ""
24
+
25
+ #: admin/pages/log.php:40 admin/pages/log.php:66 admin/pages/log.php:76
26
+ #: admin/pages/settings.php:217
27
+ msgid "Error Log"
28
+ msgstr ""
29
+
30
+ #. Name of the plugin
31
+ #: admin/pages/log.php:65 admin/pages/statistic.php:41
32
+ #: admin/pages/statistic.php:69
33
+ msgid "Image optimizer"
34
+ msgstr ""
35
+
36
+ #: admin/pages/log.php:79
37
+ msgid ""
38
+ "In this section, you can track image optimization errors. Sending this log "
39
+ "to us, will help in solving possible optimization issues."
40
+ msgstr ""
41
+
42
+ #: admin/pages/settings.php:40 admin/pages/settings.php:147
43
+ msgid "Main Settings"
44
+ msgstr ""
45
+
46
+ #: admin/pages/settings.php:123
47
+ msgid "Folder wp-content/uploads/ is unavailable for writing"
48
+ msgstr ""
49
+
50
+ #: admin/pages/settings.php:127
51
+ msgid "Folder wp-content/uploads/wio-backup/ is unavailable for writing"
52
+ msgstr ""
53
+
54
+ #: admin/pages/settings.php:130
55
+ msgid "Cron is disabled in wp-config.php"
56
+ msgstr ""
57
+
58
+ #: admin/pages/settings.php:147
59
+ msgid "This section you can set main images optimization settings."
60
+ msgstr ""
61
+
62
+ #: admin/pages/settings.php:155
63
+ msgid "Compression mode"
64
+ msgstr ""
65
+
66
+ #: admin/pages/settings.php:159 admin/pages/statistic.php:324
67
+ #: includes/classes/class.media-library.php:396
68
+ msgid "Normal"
69
+ msgstr ""
70
+
71
+ #: admin/pages/settings.php:160
72
+ msgid ""
73
+ "This mode provides lossless compression and your images will be optimized "
74
+ "without visible changes. If you want an ideal image quality, we recommend "
75
+ "this mode. The size of the files will be reduced approximately 2 times. If "
76
+ "this is not enough for you, try other modes."
77
+ msgstr ""
78
+
79
+ #: admin/pages/settings.php:164 admin/pages/statistic.php:325
80
+ #: includes/classes/class.media-library.php:401
81
+ msgid "Medium"
82
+ msgstr ""
83
+
84
+ #: admin/pages/settings.php:165
85
+ msgid ""
86
+ "This mode provides an ideal optimization of your images without significant "
87
+ "quality loss. The file size will be reduced approximately 5 times with a "
88
+ "slight decrease in image quality. In most cases that cannot be seen with the "
89
+ "naked eye."
90
+ msgstr ""
91
+
92
+ #: admin/pages/settings.php:169 admin/pages/statistic.php:326
93
+ #: includes/classes/class.media-library.php:406
94
+ msgid "High"
95
+ msgstr ""
96
+
97
+ #: admin/pages/settings.php:170
98
+ msgid ""
99
+ "This mode will use all available optimization methods for maximum image "
100
+ "compression. The file size will be reduced approximately 7 times. The "
101
+ "quality of some images may deteriorate slightly. Use this mode if you need "
102
+ "the maximum weight reduction, and you are ready to accept the loss of image "
103
+ "quality."
104
+ msgstr ""
105
+
106
+ #: admin/pages/settings.php:174
107
+ msgid "Select the compression mode appropriate for your case."
108
+ msgstr ""
109
+
110
+ #: admin/pages/settings.php:195
111
+ msgid "Auto optimization on upload"
112
+ msgstr ""
113
+
114
+ #: admin/pages/settings.php:197
115
+ msgid ""
116
+ "Automatically compress all images that you upload directly to the WordPress "
117
+ "media library, when editing pages and posts or using themes and plugins."
118
+ msgstr ""
119
+
120
+ #: admin/pages/settings.php:206
121
+ msgid "Backup images"
122
+ msgstr ""
123
+
124
+ #: admin/pages/settings.php:208
125
+ msgid ""
126
+ "Before optimizing, all your images will be saved in a separate folder for "
127
+ "future recovery."
128
+ msgstr ""
129
+
130
+ #: admin/pages/settings.php:219
131
+ msgid "Enable error logging. The log will be displayed on a separate tab."
132
+ msgstr ""
133
+
134
+ #: admin/pages/settings.php:234
135
+ msgid "Leave EXIF data"
136
+ msgstr ""
137
+
138
+ #: admin/pages/settings.php:236
139
+ msgid ""
140
+ "EXIF is information stored in photos: camera model, shutter speed, exposure "
141
+ "compensation, ISO, GPS, etc. By default, the plugin removes EXIF extended "
142
+ "data. If your project is dedicated to photography and you need to display "
143
+ "this data, then enable this option."
144
+ msgstr ""
145
+
146
+ #: admin/pages/settings.php:242
147
+ msgid "Optimization"
148
+ msgstr ""
149
+
150
+ #: admin/pages/settings.php:242
151
+ msgid "Here you can specify additional image optimization options."
152
+ msgstr ""
153
+
154
+ #: admin/pages/settings.php:250
155
+ msgid "Resizing large images"
156
+ msgstr ""
157
+
158
+ #: admin/pages/settings.php:252
159
+ msgid ""
160
+ "When you upload images from a camera or stock, they may be too high "
161
+ "resolution and it is not necessary for web. The option allows you to "
162
+ "automatically change images resolution on upload."
163
+ msgstr ""
164
+
165
+ #: admin/pages/settings.php:268
166
+ msgid "Enter the maximum size (px)"
167
+ msgstr ""
168
+
169
+ #: admin/pages/settings.php:270
170
+ msgid ""
171
+ "Set the maximum images resolution on the long side. For horizontal images, "
172
+ "this will be the width, and for vertical images - the height. The resolution "
173
+ "of the images will be changed proportionally according to the set value."
174
+ msgstr ""
175
+
176
+ #: admin/pages/settings.php:288
177
+ msgid "Optimize thumbnails"
178
+ msgstr ""
179
+
180
+ #: admin/pages/settings.php:291
181
+ msgid ""
182
+ "Choose which sizes of thumbnails should be optimized and uncheck those that "
183
+ "do not need optimization."
184
+ msgstr ""
185
+
186
+ #: admin/pages/settings.php:298
187
+ msgid "Scheduled optimization"
188
+ msgstr ""
189
+
190
+ #: admin/pages/settings.php:298
191
+ msgid "Schedule your images optimization."
192
+ msgstr ""
193
+
194
+ #: admin/pages/settings.php:306
195
+ msgid "Enable Scheduled Optimization"
196
+ msgstr ""
197
+
198
+ #: admin/pages/settings.php:308
199
+ msgid ""
200
+ "You can enable image optimization on schedule. The plugin will optimize "
201
+ "specified number of images automatically after selected time."
202
+ msgstr ""
203
+
204
+ #: admin/pages/settings.php:323 includes/classes/class.cron.php:56
205
+ msgid "1 min"
206
+ msgstr ""
207
+
208
+ #: admin/pages/settings.php:324 includes/classes/class.cron.php:60
209
+ msgid "2 min"
210
+ msgstr ""
211
+
212
+ #: admin/pages/settings.php:325 includes/classes/class.cron.php:64
213
+ msgid "5 min"
214
+ msgstr ""
215
+
216
+ #: admin/pages/settings.php:326 includes/classes/class.cron.php:68
217
+ msgid "10 min"
218
+ msgstr ""
219
+
220
+ #: admin/pages/settings.php:327 includes/classes/class.cron.php:72
221
+ msgid "30 min"
222
+ msgstr ""
223
+
224
+ #: admin/pages/settings.php:328
225
+ msgid "Hour"
226
+ msgstr ""
227
+
228
+ #: admin/pages/settings.php:329
229
+ msgid "Day"
230
+ msgstr ""
231
+
232
+ #: admin/pages/settings.php:332
233
+ msgid "Run every"
234
+ msgstr ""
235
+
236
+ #: admin/pages/settings.php:333
237
+ msgid "Select time at which the task will be repeated."
238
+ msgstr ""
239
+
240
+ #: admin/pages/settings.php:340
241
+ msgid "Images per iteration"
242
+ msgstr ""
243
+
244
+ #: admin/pages/settings.php:342
245
+ msgid ""
246
+ "Specify the number of images that will be optimized during the job. For "
247
+ "example, if you enter 5 and select 5 min, the plugin will optimize 5 images "
248
+ "every 5 minutes."
249
+ msgstr ""
250
+
251
+ #: admin/pages/settings.php:371
252
+ msgid "Manage backups"
253
+ msgstr ""
254
+
255
+ #: admin/pages/settings.php:372
256
+ msgid "You can restore the original images from a backup or clear them."
257
+ msgstr ""
258
+
259
+ #: admin/pages/settings.php:379
260
+ msgid "Are you sure?"
261
+ msgstr ""
262
+
263
+ #: admin/pages/settings.php:379
264
+ msgid "Restore"
265
+ msgstr ""
266
+
267
+ #: admin/pages/settings.php:380
268
+ msgid "Are you sure that you want to clear image backups folder?"
269
+ msgstr ""
270
+
271
+ #: admin/pages/settings.php:380
272
+ msgid "Clear Backup"
273
+ msgstr ""
274
+
275
+ #: admin/pages/settings.php:387
276
+ msgid "Restore completed."
277
+ msgstr ""
278
+
279
+ #: admin/pages/settings.php:388
280
+ msgid "The backup folder was cleared."
281
+ msgstr ""
282
+
283
+ #: admin/pages/statistic.php:70
284
+ msgid "General"
285
+ msgstr ""
286
+
287
+ #: admin/pages/statistic.php:144
288
+ msgid "Image optimization dashboard"
289
+ msgstr ""
290
+
291
+ #: admin/pages/statistic.php:147
292
+ msgid ""
293
+ "Monitor image optimization statistics and run on demand or scheduled "
294
+ "optimization."
295
+ msgstr ""
296
+
297
+ #: admin/pages/statistic.php:160
298
+ msgid "You optimized"
299
+ msgstr ""
300
+
301
+ #: admin/pages/statistic.php:160
302
+ msgid "of your website's images"
303
+ msgstr ""
304
+
305
+ #: admin/pages/statistic.php:167 admin/pages/statistic.php:292
306
+ msgid "Unoptimized"
307
+ msgstr ""
308
+
309
+ #: admin/pages/statistic.php:168 admin/pages/statistic.php:293
310
+ msgid "Optimized"
311
+ msgstr ""
312
+
313
+ #: admin/pages/statistic.php:169 admin/pages/statistic.php:294
314
+ msgid "Error"
315
+ msgstr ""
316
+
317
+ #: admin/pages/statistic.php:172
318
+ msgid "Statistics"
319
+ msgstr ""
320
+
321
+ #: admin/pages/statistic.php:178
322
+ msgid ""
323
+ "that's the number of original images<br> you optimized with Image Optimizer"
324
+ msgstr ""
325
+
326
+ #: admin/pages/statistic.php:184 admin/pages/statistic.php:298
327
+ msgid "Original size"
328
+ msgstr ""
329
+
330
+ #: admin/pages/statistic.php:189 admin/pages/statistic.php:303
331
+ msgid "Optimized size"
332
+ msgstr ""
333
+
334
+ #: admin/pages/statistic.php:200
335
+ msgid "that's the size you saved <br>by using Image Optimizer"
336
+ msgstr ""
337
+
338
+ #: admin/pages/statistic.php:212 admin/pages/statistic.php:316
339
+ msgid "All images from the media library are optimized."
340
+ msgstr ""
341
+
342
+ #: admin/pages/statistic.php:214 admin/pages/statistic.php:318
343
+ msgid "Optimization in progress. Remained"
344
+ msgstr ""
345
+
346
+ #: admin/pages/statistic.php:214
347
+ msgid "images."
348
+ msgstr ""
349
+
350
+ #: admin/pages/statistic.php:234 admin/pages/statistic.php:242
351
+ msgid "Run"
352
+ msgstr ""
353
+
354
+ #: admin/pages/statistic.php:240 admin/pages/statistic.php:246
355
+ msgid "Stop"
356
+ msgstr ""
357
+
358
+ #: admin/pages/statistic.php:246
359
+ msgid "Do you want to start optimization without backup?"
360
+ msgstr ""
361
+
362
+ #: admin/pages/statistic.php:246
363
+ msgid "Resume"
364
+ msgstr ""
365
+
366
+ #: admin/pages/statistic.php:281
367
+ msgid "Images optimization"
368
+ msgstr ""
369
+
370
+ #: includes/classes/class.backup.php:77
371
+ msgid "Unable to create backup folder."
372
+ msgstr ""
373
+
374
+ #: includes/classes/class.backup.php:132
375
+ msgid "Unable to create backup subfolder."
376
+ msgstr ""
377
+
378
+ #: includes/classes/class.cron.php:76
379
+ msgid "60 min"
380
+ msgstr ""
381
+
382
+ #: includes/classes/class.cron.php:80
383
+ msgid "daily"
384
+ msgstr ""
385
+
386
+ #: includes/classes/class.media-library.php:148
387
+ msgid "No access for writing backups."
388
+ msgstr ""
389
+
390
+ #: includes/classes/class.media-library.php:154
391
+ msgid "The uploads folder is not writable."
392
+ msgstr ""
393
+
394
+ #: includes/classes/class.media-library.php:380
395
+ msgid "New Filesize:"
396
+ msgstr ""
397
+
398
+ #: includes/classes/class.media-library.php:382
399
+ msgid "Original Saving:"
400
+ msgstr ""
401
+
402
+ #: includes/classes/class.media-library.php:387
403
+ msgid "Original Filesize:"
404
+ msgstr ""
405
+
406
+ #: includes/classes/class.media-library.php:388
407
+ msgid "Level:"
408
+ msgstr ""
409
+
410
+ #: includes/classes/class.media-library.php:390
411
+ msgid "Error Message:"
412
+ msgstr ""
413
+
414
+ #: includes/classes/class.media-library.php:395
415
+ #: includes/classes/class.media-library.php:400
416
+ #: includes/classes/class.media-library.php:405
417
+ #: includes/classes/class.media-library.php:418
418
+ msgid "Optimization in progress"
419
+ msgstr ""
420
+
421
+ #: includes/classes/class.media-library.php:396
422
+ #: includes/classes/class.media-library.php:401
423
+ #: includes/classes/class.media-library.php:406
424
+ msgid "Re-Optimize to"
425
+ msgstr ""
426
+
427
+ #: includes/classes/class.media-library.php:410
428
+ msgid "Recovery in progress"
429
+ msgstr ""
430
+
431
+ #: includes/classes/class.media-library.php:410
432
+ msgid "Restore original"
433
+ msgstr ""
434
+
435
+ #: includes/classes/class.media-library.php:418
436
+ msgid "Optimize"
437
+ msgstr ""
438
+
439
+ #. Description of the plugin
440
+ msgid ""
441
+ "Optimize images without losing quality, speed up your website load, improve "
442
+ "SEO and save money on server and CDN bandwidth."
443
+ msgstr ""
444
+
445
+ #. Author of the plugin
446
+ msgid "Webcraftic <wordpress.webraftic@gmail.com>"
447
+ msgstr ""
libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .factory-accordion{margin:0 0 30px;border-top:1px solid #DDD;border-right:1px solid #DDD;border-left:1px solid #DDD;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.factory-bootstrap-406 .factory-accordion>h3{border-bottom:1px solid #DDD;cursor:pointer;padding:8px 15px;margin:0}.factory-bootstrap-406 .factory-accordion>div{display:none;margin:0;border-bottom:1px solid #DDD}.factory-bootstrap-406 .factory-accordion-item{display:none}.factory-bootstrap-406 .inner-factory-accordion-item{padding:10px 0}.factory-bootstrap-406 .factory-accordion>h3.active:hover{cursor:default}
libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#e1a948;border-color:#d39323;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ecc88a,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8be74,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#db9825;border-color:#bd831f;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#d1cdc7!important;background:#db9825!important;border-color:#bd831f!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#e1a948;border-color:#d39323}
libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#c7a589;border-color:#b78a66;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e0cdbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #d7bfac,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#ba906d;border-color:#ae7d55;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#d1cbc7!important;background:#ba906d!important;border-color:#ae7d55!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#c7a589;border-color:#b78a66}
libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 article,.factory-bootstrap-406 aside,.factory-bootstrap-406 details,.factory-bootstrap-406 figcaption,.factory-bootstrap-406 figure,.factory-bootstrap-406 footer,.factory-bootstrap-406 header,.factory-bootstrap-406 hgroup,.factory-bootstrap-406 main,.factory-bootstrap-406 nav,.factory-bootstrap-406 section,.factory-bootstrap-406 summary{display:block}.factory-bootstrap-406 audio,.factory-bootstrap-406 canvas,.factory-bootstrap-406 video{display:inline-block}.factory-bootstrap-406 audio:not([controls]){display:none;height:0}.factory-bootstrap-406 [hidden],.factory-bootstrap-406 template{display:none}.factory-bootstrap-406 body{margin:0}.factory-bootstrap-406 a{background:0 0}.factory-bootstrap-406 a:focus{outline:thin dotted}.factory-bootstrap-406 a:active,.factory-bootstrap-406 a:hover{outline:0}.factory-bootstrap-406 h1{margin:.67em 0}.factory-bootstrap-406 b,.factory-bootstrap-406 strong{font-weight:700}.factory-bootstrap-406 dfn{font-style:italic}.factory-bootstrap-406 hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-406 mark{color:#000;background:#ff0}.factory-bootstrap-406 code,.factory-bootstrap-406 kbd,.factory-bootstrap-406 pre,.factory-bootstrap-406 samp{font-size:1em}.factory-bootstrap-406 pre{white-space:pre-wrap}.factory-bootstrap-406 q{quotes:"\201C" "\201D" "\2018" "\2019"}.factory-bootstrap-406 sub,.factory-bootstrap-406 sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}.factory-bootstrap-406 sup{top:-.5em}.factory-bootstrap-406 sub{bottom:-.25em}.factory-bootstrap-406 img{border:0}.factory-bootstrap-406 svg:not(:root){overflow:hidden}.factory-bootstrap-406 figure{margin:0}.factory-bootstrap-406 button,.factory-bootstrap-406 input,.factory-bootstrap-406 select,.factory-bootstrap-406 textarea{margin:0}.factory-bootstrap-406 button,.factory-bootstrap-406 select{text-transform:none}.factory-bootstrap-406 select{padding-right:4px!important}.factory-bootstrap-406 button,.factory-bootstrap-406 input[type=reset],.factory-bootstrap-406 input[type=submit],html .factory-bootstrap-406 input[type=button]{cursor:pointer;-webkit-appearance:button}.factory-bootstrap-406 button[disabled],html .factory-bootstrap-406 input[disabled]{cursor:default}.factory-bootstrap-406 input[type=checkbox],.factory-bootstrap-406 input[type=radio]{padding:0;box-sizing:border-box}.factory-bootstrap-406 input[type=search]{-webkit-appearance:textfield}.factory-bootstrap-406 input[type=search]::-webkit-search-cancel-button,.factory-bootstrap-406 input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.factory-bootstrap-406 button::-moz-focus-inner,.factory-bootstrap-406 input::-moz-focus-inner{padding:0;border:0}.factory-bootstrap-406 textarea{overflow:auto;vertical-align:top}.factory-bootstrap-406 table{border-collapse:collapse;border-spacing:0}@media print{.factory-bootstrap-406 *{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}.factory-bootstrap-406 a,.factory-bootstrap-406 a:visited{text-decoration:underline}.factory-bootstrap-406 a[href]:after{content:" (" attr(href) ")"}.factory-bootstrap-406 abbr[title]:after{content:" (" attr(title) ")"}.factory-bootstrap-406 a[href^="javascript:"]:after,.factory-bootstrap-406 a[href^="#"]:after{content:""}.factory-bootstrap-406 blockquote,.factory-bootstrap-406 pre{border:1px solid #999;page-break-inside:avoid}.factory-bootstrap-406 thead{display:table-header-group}.factory-bootstrap-406 img,.factory-bootstrap-406 tr{page-break-inside:avoid}.factory-bootstrap-406 img{max-width:100%!important}@page{margin:2cm .5cm}.factory-bootstrap-406 h2,.factory-bootstrap-406 h3,.factory-bootstrap-406 p{orphans:3;widows:3}.factory-bootstrap-406 h2,.factory-bootstrap-406 h3{page-break-after:avoid}.factory-bootstrap-406 select{background:#fff!important}.factory-bootstrap-406 .navbar{display:none}.factory-bootstrap-406 .table td,.factory-bootstrap-406 .table th{background-color:#fff!important}.factory-bootstrap-406 .btn>.caret,.factory-bootstrap-406 .dropup>.btn>.caret{border-top-color:#000!important}.factory-bootstrap-406 .label{border:1px solid #000}.factory-bootstrap-406 .table{border-collapse:collapse!important}.factory-bootstrap-406 .table-bordered td,.factory-bootstrap-406 .table-bordered th{border:1px solid #ddd!important}}.factory-bootstrap-406 *,.factory-bootstrap-406 :after,.factory-bootstrap-406 :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html .factory-bootstrap-406{-webkit-tap-highlight-color:rgba(0,0,0,0)}.factory-bootstrap-406 body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}.factory-bootstrap-406 button,.factory-bootstrap-406 input,.factory-bootstrap-406 select,.factory-bootstrap-406 textarea{font-family:inherit;font-size:inherit;line-height:inherit}.factory-bootstrap-406 img{vertical-align:middle}.factory-bootstrap-406 .img-responsive{display:block;height:auto;max-width:100%}.factory-bootstrap-406 .img-rounded{border-radius:6px}.factory-bootstrap-406 .img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-406 .img-circle{border-radius:50%}.factory-bootstrap-406 hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.factory-bootstrap-406 .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.factory-bootstrap-406 .h1,.factory-bootstrap-406 .h2,.factory-bootstrap-406 .h3,.factory-bootstrap-406 .h4,.factory-bootstrap-406 .h5,.factory-bootstrap-406 .h6,.factory-bootstrap-406 h1,.factory-bootstrap-406 h2,.factory-bootstrap-406 h3,.factory-bootstrap-406 h4,.factory-bootstrap-406 h5,.factory-bootstrap-406 h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}.factory-bootstrap-406 .h1 .small,.factory-bootstrap-406 .h1 small,.factory-bootstrap-406 .h2 .small,.factory-bootstrap-406 .h2 small,.factory-bootstrap-406 .h3 .small,.factory-bootstrap-406 .h3 small,.factory-bootstrap-406 .h4 .small,.factory-bootstrap-406 .h4 small,.factory-bootstrap-406 .h5 .small,.factory-bootstrap-406 .h5 small,.factory-bootstrap-406 .h6 .small,.factory-bootstrap-406 .h6 small,.factory-bootstrap-406 h1 .small,.factory-bootstrap-406 h1 small,.factory-bootstrap-406 h2 .small,.factory-bootstrap-406 h2 small,.factory-bootstrap-406 h3 .small,.factory-bootstrap-406 h3 small,.factory-bootstrap-406 h4 .small,.factory-bootstrap-406 h4 small,.factory-bootstrap-406 h5 .small,.factory-bootstrap-406 h5 small,.factory-bootstrap-406 h6 .small,.factory-bootstrap-406 h6 small{font-weight:400;line-height:1;color:#999}.factory-bootstrap-406 h1,.factory-bootstrap-406 h2,.factory-bootstrap-406 h3{margin-top:20px;margin-bottom:10px}.factory-bootstrap-406 h1 .small,.factory-bootstrap-406 h1 small,.factory-bootstrap-406 h2 .small,.factory-bootstrap-406 h2 small,.factory-bootstrap-406 h3 .small,.factory-bootstrap-406 h3 small{font-size:65%}.factory-bootstrap-406 h4,.factory-bootstrap-406 h5,.factory-bootstrap-406 h6{margin-top:10px;margin-bottom:10px}.factory-bootstrap-406 h4 .small,.factory-bootstrap-406 h4 small,.factory-bootstrap-406 h5 .small,.factory-bootstrap-406 h5 small,.factory-bootstrap-406 h6 .small,.factory-bootstrap-406 h6 small{font-size:75%}.factory-bootstrap-406 .h1,.factory-bootstrap-406 h1{font-size:36px}.factory-bootstrap-406 .h2,.factory-bootstrap-406 h2{font-size:30px}.factory-bootstrap-406 .h3,.factory-bootstrap-406 h3{font-size:24px}.factory-bootstrap-406 .h4,.factory-bootstrap-406 h4{font-size:18px}.factory-bootstrap-406 .h5,.factory-bootstrap-406 h5{font-size:14px}.factory-bootstrap-406 .h6,.factory-bootstrap-406 h6{font-size:12px}.factory-bootstrap-406 p{margin:0 0 10px}.factory-bootstrap-406 .lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.factory-bootstrap-406 .small,.factory-bootstrap-406 small{font-size:85%}.factory-bootstrap-406 cite{font-style:normal}.factory-bootstrap-406 .text-muted{color:#999}.factory-bootstrap-406 .text-primary{color:#428bca}.factory-bootstrap-406 .text-primary:hover{color:#3071a9}.factory-bootstrap-406 .text-warning{color:#8a6d3b}.factory-bootstrap-406 .text-warning:hover{color:#66512c}.factory-bootstrap-406 .text-danger{color:#a94442}.factory-bootstrap-406 .text-danger:hover{color:#843534}.factory-bootstrap-406 .text-success{color:#3c763d}.factory-bootstrap-406 .text-success:hover{color:#2b542c}.factory-bootstrap-406 .text-info{color:#31708f}.factory-bootstrap-406 .text-info:hover{color:#245269}.factory-bootstrap-406 .text-left{text-align:left}.factory-bootstrap-406 .text-right{text-align:right}.factory-bootstrap-406 .text-center{text-align:center}.factory-bootstrap-406 .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}.factory-bootstrap-406 ol,.factory-bootstrap-406 ul{margin-top:0;margin-bottom:10px}.factory-bootstrap-406 ol ol,.factory-bootstrap-406 ol ul,.factory-bootstrap-406 ul ol,.factory-bootstrap-406 ul ul{margin-bottom:0}.factory-bootstrap-406 .list-inline,.factory-bootstrap-406 .list-unstyled{padding-left:0;list-style:none}.factory-bootstrap-406 .list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.factory-bootstrap-406 .list-inline>li:first-child{padding-left:0}.factory-bootstrap-406 dl{margin-top:0;margin-bottom:20px}.factory-bootstrap-406 dd,.factory-bootstrap-406 dt{line-height:1.428571429}.factory-bootstrap-406 dt{font-weight:700}.factory-bootstrap-406 dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:after,.dl-horizontal dd:before{display:table;content:" "}.dl-horizontal dd:after{clear:both}}.factory-bootstrap-406 abbr[data-original-title],.factory-bootstrap-406 abbr[title]{cursor:help;border-bottom:1px dotted #999}.factory-bootstrap-406 .initialism{font-size:90%;text-transform:uppercase}.factory-bootstrap-406 blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}.factory-bootstrap-406 blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}.factory-bootstrap-406 blockquote p:last-child{margin-bottom:0}.factory-bootstrap-406 blockquote .small,.factory-bootstrap-406 blockquote small{display:block;line-height:1.428571429;color:#999}.factory-bootstrap-406 blockquote .small:before,.factory-bootstrap-406 blockquote small:before{content:'\2014 \00A0'}.factory-bootstrap-406 blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}.factory-bootstrap-406 blockquote.pull-right .small,.factory-bootstrap-406 blockquote.pull-right p,.factory-bootstrap-406 blockquote.pull-right small{text-align:right}.factory-bootstrap-406 blockquote.pull-right .small:before,.factory-bootstrap-406 blockquote.pull-right small:before{content:''}.factory-bootstrap-406 blockquote.pull-right .small:after,.factory-bootstrap-406 blockquote.pull-right small:after{content:'\00A0 \2014'}.factory-bootstrap-406 blockquote:after,.factory-bootstrap-406 blockquote:before{content:""}.factory-bootstrap-406 address{margin-bottom:20px;font-style:normal;line-height:1.428571429}.factory-bootstrap-406 code,.factory-bootstrap-406 kbd,.factory-bootstrap-406 pre,.factory-bootstrap-406 samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}.factory-bootstrap-406 code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}.factory-bootstrap-406 pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-406 pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.factory-bootstrap-406 .pre-scrollable{max-height:340px;overflow-y:scroll}.factory-bootstrap-406 .container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.factory-bootstrap-406 .container:after,.factory-bootstrap-406 .container:before{display:table;content:" "}.factory-bootstrap-406 .container:after{clear:both}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.factory-bootstrap-406 .row{margin-right:-15px;margin-left:-15px}.factory-bootstrap-406 .row:after,.factory-bootstrap-406 .row:before{display:table;content:" "}.factory-bootstrap-406 .row:after{clear:both}.factory-bootstrap-406 .col-lg-1,.factory-bootstrap-406 .col-lg-10,.factory-bootstrap-406 .col-lg-11,.factory-bootstrap-406 .col-lg-12,.factory-bootstrap-406 .col-lg-2,.factory-bootstrap-406 .col-lg-3,.factory-bootstrap-406 .col-lg-4,.factory-bootstrap-406 .col-lg-5,.factory-bootstrap-406 .col-lg-6,.factory-bootstrap-406 .col-lg-7,.factory-bootstrap-406 .col-lg-8,.factory-bootstrap-406 .col-lg-9,.factory-bootstrap-406 .col-md-1,.factory-bootstrap-406 .col-md-10,.factory-bootstrap-406 .col-md-11,.factory-bootstrap-406 .col-md-12,.factory-bootstrap-406 .col-md-2,.factory-bootstrap-406 .col-md-3,.factory-bootstrap-406 .col-md-4,.factory-bootstrap-406 .col-md-5,.factory-bootstrap-406 .col-md-6,.factory-bootstrap-406 .col-md-7,.factory-bootstrap-406 .col-md-8,.factory-bootstrap-406 .col-md-9,.factory-bootstrap-406 .col-sm-1,.factory-bootstrap-406 .col-sm-10,.factory-bootstrap-406 .col-sm-11,.factory-bootstrap-406 .col-sm-12,.factory-bootstrap-406 .col-sm-2,.factory-bootstrap-406 .col-sm-3,.factory-bootstrap-406 .col-sm-4,.factory-bootstrap-406 .col-sm-5,.factory-bootstrap-406 .col-sm-6,.factory-bootstrap-406 .col-sm-7,.factory-bootstrap-406 .col-sm-8,.factory-bootstrap-406 .col-sm-9,.factory-bootstrap-406 .col-xs-1,.factory-bootstrap-406 .col-xs-10,.factory-bootstrap-406 .col-xs-11,.factory-bootstrap-406 .col-xs-12,.factory-bootstrap-406 .col-xs-2,.factory-bootstrap-406 .col-xs-3,.factory-bootstrap-406 .col-xs-4,.factory-bootstrap-406 .col-xs-5,.factory-bootstrap-406 .col-xs-6,.factory-bootstrap-406 .col-xs-7,.factory-bootstrap-406 .col-xs-8,.factory-bootstrap-406 .col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.factory-bootstrap-406 .col-xs-1,.factory-bootstrap-406 .col-xs-10,.factory-bootstrap-406 .col-xs-11,.factory-bootstrap-406 .col-xs-12,.factory-bootstrap-406 .col-xs-2,.factory-bootstrap-406 .col-xs-3,.factory-bootstrap-406 .col-xs-4,.factory-bootstrap-406 .col-xs-5,.factory-bootstrap-406 .col-xs-6,.factory-bootstrap-406 .col-xs-7,.factory-bootstrap-406 .col-xs-8,.factory-bootstrap-406 .col-xs-9{float:left}.factory-bootstrap-406 .col-xs-12{width:100%}.factory-bootstrap-406 .col-xs-11{width:91.66666666666666%}.factory-bootstrap-406 .col-xs-10{width:83.33333333333334%}.factory-bootstrap-406 .col-xs-9{width:75%}.factory-bootstrap-406 .col-xs-8{width:66.66666666666666%}.factory-bootstrap-406 .col-xs-7{width:58.333333333333336%}.factory-bootstrap-406 .col-xs-6{width:50%}.factory-bootstrap-406 .col-xs-5{width:41.66666666666667%}.factory-bootstrap-406 .col-xs-4{width:33.33333333333333%}.factory-bootstrap-406 .col-xs-3{width:25%}.factory-bootstrap-406 .col-xs-2{width:16.666666666666664%}.factory-bootstrap-406 .col-xs-1{width:8.333333333333332%}.factory-bootstrap-406 .col-xs-pull-12{right:100%}.factory-bootstrap-406 .col-xs-pull-11{right:91.66666666666666%}.factory-bootstrap-406 .col-xs-pull-10{right:83.33333333333334%}.factory-bootstrap-406 .col-xs-pull-9{right:75%}.factory-bootstrap-406 .col-xs-pull-8{right:66.66666666666666%}.factory-bootstrap-406 .col-xs-pull-7{right:58.333333333333336%}.factory-bootstrap-406 .col-xs-pull-6{right:50%}.factory-bootstrap-406 .col-xs-pull-5{right:41.66666666666667%}.factory-bootstrap-406 .col-xs-pull-4{right:33.33333333333333%}.factory-bootstrap-406 .col-xs-pull-3{right:25%}.factory-bootstrap-406 .col-xs-pull-2{right:16.666666666666664%}.factory-bootstrap-406 .col-xs-pull-1{right:8.333333333333332%}.factory-bootstrap-406 .col-xs-pull-0{right:0}.factory-bootstrap-406 .col-xs-push-12{left:100%}.factory-bootstrap-406 .col-xs-push-11{left:91.66666666666666%}.factory-bootstrap-406 .col-xs-push-10{left:83.33333333333334%}.factory-bootstrap-406 .col-xs-push-9{left:75%}.factory-bootstrap-406 .col-xs-push-8{left:66.66666666666666%}.factory-bootstrap-406 .col-xs-push-7{left:58.333333333333336%}.factory-bootstrap-406 .col-xs-push-6{left:50%}.factory-bootstrap-406 .col-xs-push-5{left:41.66666666666667%}.factory-bootstrap-406 .col-xs-push-4{left:33.33333333333333%}.factory-bootstrap-406 .col-xs-push-3{left:25%}.factory-bootstrap-406 .col-xs-push-2{left:16.666666666666664%}.factory-bootstrap-406 .col-xs-push-1{left:8.333333333333332%}.factory-bootstrap-406 .col-xs-push-0{left:0}.factory-bootstrap-406 .col-xs-offset-12{margin-left:100%}.factory-bootstrap-406 .col-xs-offset-11{margin-left:91.66666666666666%}.factory-bootstrap-406 .col-xs-offset-10{margin-left:83.33333333333334%}.factory-bootstrap-406 .col-xs-offset-9{margin-left:75%}.factory-bootstrap-406 .col-xs-offset-8{margin-left:66.66666666666666%}.factory-bootstrap-406 .col-xs-offset-7{margin-left:58.333333333333336%}.factory-bootstrap-406 .col-xs-offset-6{margin-left:50%}.factory-bootstrap-406 .col-xs-offset-5{margin-left:41.66666666666667%}.factory-bootstrap-406 .col-xs-offset-4{margin-left:33.33333333333333%}.factory-bootstrap-406 .col-xs-offset-3{margin-left:25%}.factory-bootstrap-406 .col-xs-offset-2{margin-left:16.666666666666664%}.factory-bootstrap-406 .col-xs-offset-1{margin-left:8.333333333333332%}.factory-bootstrap-406 .col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}.factory-bootstrap-406 table{max-width:100%;background-color:transparent}.factory-bootstrap-406 th{text-align:left}.factory-bootstrap-406 .table{width:100%;margin-bottom:20px}.factory-bootstrap-406 .table>tbody>tr>td,.factory-bootstrap-406 .table>tbody>tr>th,.factory-bootstrap-406 .table>tfoot>tr>td,.factory-bootstrap-406 .table>tfoot>tr>th,.factory-bootstrap-406 .table>thead>tr>td,.factory-bootstrap-406 .table>thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.factory-bootstrap-406 .table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.factory-bootstrap-406 .table>caption+thead>tr:first-child>td,.factory-bootstrap-406 .table>caption+thead>tr:first-child>th,.factory-bootstrap-406 .table>colgroup+thead>tr:first-child>td,.factory-bootstrap-406 .table>colgroup+thead>tr:first-child>th,.factory-bootstrap-406 .table>thead:first-child>tr:first-child>td,.factory-bootstrap-406 .table>thead:first-child>tr:first-child>th{border-top:0}.factory-bootstrap-406 .table>tbody+tbody{border-top:2px solid #ddd}.factory-bootstrap-406 .table .table{background-color:#fff}.factory-bootstrap-406 .table-condensed>tbody>tr>td,.factory-bootstrap-406 .table-condensed>tbody>tr>th,.factory-bootstrap-406 .table-condensed>tfoot>tr>td,.factory-bootstrap-406 .table-condensed>tfoot>tr>th,.factory-bootstrap-406 .table-condensed>thead>tr>td,.factory-bootstrap-406 .table-condensed>thead>tr>th{padding:5px}.factory-bootstrap-406 .table-bordered,.factory-bootstrap-406 .table-bordered>tbody>tr>td,.factory-bootstrap-406 .table-bordered>tbody>tr>th,.factory-bootstrap-406 .table-bordered>tfoot>tr>td,.factory-bootstrap-406 .table-bordered>tfoot>tr>th,.factory-bootstrap-406 .table-bordered>thead>tr>td,.factory-bootstrap-406 .table-bordered>thead>tr>th{border:1px solid #ddd}.factory-bootstrap-406 .table-bordered>thead>tr>td,.factory-bootstrap-406 .table-bordered>thead>tr>th{border-bottom-width:2px}.factory-bootstrap-406 .table-striped>tbody>tr:nth-child(odd)>td,.factory-bootstrap-406 .table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.factory-bootstrap-406 .table-hover>tbody>tr:hover>td,.factory-bootstrap-406 .table-hover>tbody>tr:hover>th{background-color:#f5f5f5}.factory-bootstrap-406 table col[class*=col-]{position:static;display:table-column;float:none}.factory-bootstrap-406 table td[class*=col-],.factory-bootstrap-406 table th[class*=col-]{display:table-cell;float:none}.factory-bootstrap-406 .table>tbody>.active>td,.factory-bootstrap-406 .table>tbody>.active>th,.factory-bootstrap-406 .table>tbody>tr>.active,.factory-bootstrap-406 .table>tfoot>.active>td,.factory-bootstrap-406 .table>tfoot>.active>th,.factory-bootstrap-406 .table>tfoot>tr>.active,.factory-bootstrap-406 .table>thead>.active>td,.factory-bootstrap-406 .table>thead>.active>th,.factory-bootstrap-406 .table>thead>tr>.active{background-color:#f5f5f5}.factory-bootstrap-406 .table-hover>tbody>.active:hover>td,.factory-bootstrap-406 .table-hover>tbody>.active:hover>th,.factory-bootstrap-406 .table-hover>tbody>tr>.active:hover{background-color:#e8e8e8}.factory-bootstrap-406 .table>tbody>.success>td,.factory-bootstrap-406 .table>tbody>.success>th,.factory-bootstrap-406 .table>tbody>tr>.success,.factory-bootstrap-406 .table>tfoot>.success>td,.factory-bootstrap-406 .table>tfoot>.success>th,.factory-bootstrap-406 .table>tfoot>tr>.success,.factory-bootstrap-406 .table>thead>.success>td,.factory-bootstrap-406 .table>thead>.success>th,.factory-bootstrap-406 .table>thead>tr>.success{background-color:#dff0d8}.factory-bootstrap-406 .table-hover>tbody>.success:hover>td,.factory-bootstrap-406 .table-hover>tbody>.success:hover>th,.factory-bootstrap-406 .table-hover>tbody>tr>.success:hover{background-color:#d0e9c6}.factory-bootstrap-406 .table>tbody>.danger>td,.factory-bootstrap-406 .table>tbody>.danger>th,.factory-bootstrap-406 .table>tbody>tr>.danger,.factory-bootstrap-406 .table>tfoot>.danger>td,.factory-bootstrap-406 .table>tfoot>.danger>th,.factory-bootstrap-406 .table>tfoot>tr>.danger,.factory-bootstrap-406 .table>thead>.danger>td,.factory-bootstrap-406 .table>thead>.danger>th,.factory-bootstrap-406 .table>thead>tr>.danger{background-color:#f2dede}.factory-bootstrap-406 .table-hover>tbody>.danger:hover>td,.factory-bootstrap-406 .table-hover>tbody>.danger:hover>th,.factory-bootstrap-406 .table-hover>tbody>tr>.danger:hover{background-color:#ebcccc}.factory-bootstrap-406 .table>tbody>.warning>td,.factory-bootstrap-406 .table>tbody>.warning>th,.factory-bootstrap-406 .table>tbody>tr>.warning,.factory-bootstrap-406 .table>tfoot>.warning>td,.factory-bootstrap-406 .table>tfoot>.warning>th,.factory-bootstrap-406 .table>tfoot>tr>.warning,.factory-bootstrap-406 .table>thead>.warning>td,.factory-bootstrap-406 .table>thead>.warning>th,.factory-bootstrap-406 .table>thead>tr>.warning{background-color:#fcf8e3}.factory-bootstrap-406 .table-hover>tbody>.warning:hover>td,.factory-bootstrap-406 .table-hover>tbody>.warning:hover>th,.factory-bootstrap-406 .table-hover>tbody>tr>.warning:hover{background-color:#faf2cc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}.factory-bootstrap-406 fieldset{padding:0;margin:0;border:0}.factory-bootstrap-406 legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5;-moz-box-sizing:content-box;box-sizing:content-box}.factory-bootstrap-406 label{display:inline-block;margin-bottom:5px;font-weight:700}.factory-bootstrap-406 input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.factory-bootstrap-406 input[type=checkbox],.factory-bootstrap-406 input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}.factory-bootstrap-406 input[type=file]{display:block}.factory-bootstrap-406 select[multiple],.factory-bootstrap-406 select[size]{height:auto}.factory-bootstrap-406 select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}.factory-bootstrap-406 input[type=checkbox]:focus,.factory-bootstrap-406 input[type=file]:focus,.factory-bootstrap-406 input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-406 input[type=number]::-webkit-inner-spin-button,.factory-bootstrap-406 input[type=number]::-webkit-outer-spin-button{height:auto}.factory-bootstrap-406 output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.factory-bootstrap-406 .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.factory-bootstrap-406 .form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-406 .form-control:-moz-placeholder{color:#999}.factory-bootstrap-406 .form-control::-moz-placeholder{color:#999;opacity:1}.factory-bootstrap-406 .form-control:-ms-input-placeholder{color:#999}.factory-bootstrap-406 .form-control::-webkit-input-placeholder{color:#999}.factory-bootstrap-406 .form-control[disabled],.factory-bootstrap-406 .form-control[readonly],.factory-bootstrap-406 fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}.factory-bootstrap-406 textarea.form-control{height:auto}.factory-bootstrap-406 .form-group{margin-bottom:15px}.factory-bootstrap-406 .checkbox,.factory-bootstrap-406 .radio{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.factory-bootstrap-406 .checkbox label,.factory-bootstrap-406 .radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.factory-bootstrap-406 .checkbox input[type=checkbox],.factory-bootstrap-406 .checkbox-inline input[type=checkbox],.factory-bootstrap-406 .radio input[type=radio],.factory-bootstrap-406 .radio-inline input[type=radio]{float:left;margin-left:-20px}.factory-bootstrap-406 .checkbox+.checkbox,.factory-bootstrap-406 .radio+.radio{margin-top:-5px}.factory-bootstrap-406 .checkbox-inline,.factory-bootstrap-406 .radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.factory-bootstrap-406 .checkbox-inline+.checkbox-inline,.factory-bootstrap-406 .radio-inline+.radio-inline{margin-top:0;margin-left:10px}.factory-bootstrap-406 .checkbox-inline[disabled],.factory-bootstrap-406 .checkbox[disabled],.factory-bootstrap-406 .radio-inline[disabled],.factory-bootstrap-406 .radio[disabled],.factory-bootstrap-406 fieldset[disabled] .checkbox,.factory-bootstrap-406 fieldset[disabled] .checkbox-inline,.factory-bootstrap-406 fieldset[disabled] .radio,.factory-bootstrap-406 fieldset[disabled] .radio-inline,.factory-bootstrap-406 fieldset[disabled] input[type=checkbox],.factory-bootstrap-406 fieldset[disabled] input[type=radio],.factory-bootstrap-406 input[type=checkbox][disabled],.factory-bootstrap-406 input[type=radio][disabled]{cursor:not-allowed}.factory-bootstrap-406 .input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-406 select.input-sm{height:30px;line-height:30px}.factory-bootstrap-406 textarea.input-sm{height:auto}.factory-bootstrap-406 .input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-406 select.input-lg{height:46px;line-height:46px}.factory-bootstrap-406 textarea.input-lg{height:auto}.factory-bootstrap-406 .has-warning .checkbox,.factory-bootstrap-406 .has-warning .checkbox-inline,.factory-bootstrap-406 .has-warning .control-label,.factory-bootstrap-406 .has-warning .help-block,.factory-bootstrap-406 .has-warning .radio,.factory-bootstrap-406 .has-warning .radio-inline{color:#8a6d3b}.factory-bootstrap-406 .has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-406 .has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.factory-bootstrap-406 .has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.factory-bootstrap-406 .has-error .checkbox,.factory-bootstrap-406 .has-error .checkbox-inline,.factory-bootstrap-406 .has-error .control-label,.factory-bootstrap-406 .has-error .help-block,.factory-bootstrap-406 .has-error .radio,.factory-bootstrap-406 .has-error .radio-inline{color:#a94442}.factory-bootstrap-406 .controls{display:block}.factory-bootstrap-406 .has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-406 .has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.factory-bootstrap-406 .has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.factory-bootstrap-406 .has-success .checkbox,.factory-bootstrap-406 .has-success .checkbox-inline,.factory-bootstrap-406 .has-success .control-label,.factory-bootstrap-406 .has-success .help-block,.factory-bootstrap-406 .has-success .radio,.factory-bootstrap-406 .has-success .radio-inline{color:#3c763d}.factory-bootstrap-406 .has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-406 .has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.factory-bootstrap-406 .has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.factory-bootstrap-406 .form-control-static{margin-bottom:0}.factory-bootstrap-406 .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;font-weight:400}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .checkbox,.form-inline .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{float:none;margin-left:0}}.factory-bootstrap-406 .form-horizontal .checkbox,.factory-bootstrap-406 .form-horizontal .checkbox-inline,.factory-bootstrap-406 .form-horizontal .control-label,.factory-bootstrap-406 .form-horizontal .radio,.factory-bootstrap-406 .form-horizontal .radio-inline{position:relative;padding-top:7px;margin-top:0;margin-bottom:0}.factory-bootstrap-406 .form-horizontal .control-label{max-width:200px}.factory-bootstrap-406 .form-horizontal .checkbox,.factory-bootstrap-406 .form-horizontal .radio{min-height:27px}.factory-bootstrap-406 .form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.factory-bootstrap-406 .form-horizontal .form-group:after,.factory-bootstrap-406 .form-horizontal .form-group:before{display:table;content:" "}.factory-bootstrap-406 .form-horizontal .form-group:after{clear:both}.factory-bootstrap-406 .form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.factory-bootstrap-406 .btn{display:inline-block;padding:5px 12px;margin-bottom:0;font-size:13px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.factory-bootstrap-406 .btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.factory-bootstrap-406 .btn{text-decoration:none}.factory-bootstrap-406 .btn:focus,.factory-bootstrap-406 .btn:hover{color:#333;text-decoration:none}.factory-bootstrap-406 .btn.disabled,.factory-bootstrap-406 .btn[disabled],.factory-bootstrap-406 fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-406 .btn-default.active,.factory-bootstrap-406 .btn-default:active,.factory-bootstrap-406 .btn-default:focus,.factory-bootstrap-406 .btn-default:hover,.factory-bootstrap-406 .open .dropdown-toggle.btn-default{background:#fafafa;border-color:#999;color:#222}.factory-bootstrap-406 .btn-default.active,.factory-bootstrap-406 .btn-default:active,.factory-bootstrap-406 .open .dropdown-toggle.btn-default{background-image:none}.factory-bootstrap-406 .btn-default.disabled,.factory-bootstrap-406 .btn-default.disabled.active,.factory-bootstrap-406 .btn-default.disabled:active,.factory-bootstrap-406 .btn-default.disabled:focus,.factory-bootstrap-406 .btn-default.disabled:hover,.factory-bootstrap-406 .btn-default[disabled],.factory-bootstrap-406 .btn-default[disabled].active,.factory-bootstrap-406 .btn-default[disabled]:active,.factory-bootstrap-406 .btn-default[disabled]:focus,.factory-bootstrap-406 .btn-default[disabled]:hover,.factory-bootstrap-406 fieldset[disabled] .btn-default,.factory-bootstrap-406 fieldset[disabled] .btn-default.active,.factory-bootstrap-406 fieldset[disabled] .btn-default:active,.factory-bootstrap-406 fieldset[disabled] .btn-default:focus,.factory-bootstrap-406 fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.factory-bootstrap-406 .btn-default .badge{color:#fff;background-color:#fff}.factory-bootstrap-406 .btn-primary.active,.factory-bootstrap-406 .btn-primary:active,.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover,.factory-bootstrap-406 .open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.factory-bootstrap-406 .btn-primary.active,.factory-bootstrap-406 .btn-primary:active,.factory-bootstrap-406 .open .dropdown-toggle.btn-primary{background-image:none}.factory-bootstrap-406 .btn-primary.disabled,.factory-bootstrap-406 .btn-primary.disabled.active,.factory-bootstrap-406 .btn-primary.disabled:active,.factory-bootstrap-406 .btn-primary.disabled:focus,.factory-bootstrap-406 .btn-primary.disabled:hover,.factory-bootstrap-406 .btn-primary[disabled],.factory-bootstrap-406 .btn-primary[disabled].active,.factory-bootstrap-406 .btn-primary[disabled]:active,.factory-bootstrap-406 .btn-primary[disabled]:focus,.factory-bootstrap-406 .btn-primary[disabled]:hover,.factory-bootstrap-406 fieldset[disabled] .btn-primary,.factory-bootstrap-406 fieldset[disabled] .btn-primary.active,.factory-bootstrap-406 fieldset[disabled] .btn-primary:active,.factory-bootstrap-406 fieldset[disabled] .btn-primary:focus,.factory-bootstrap-406 fieldset[disabled] .btn-primary:hover{background-color:#428bca;border-color:#357ebd}.factory-bootstrap-406 .btn-primary .badge{color:#428bca;background-color:#fff}.factory-bootstrap-406 .btn-warning{color:#fff;background-color:#f0ad4e}.factory-bootstrap-406 .btn-warning.active,.factory-bootstrap-406 .btn-warning:active,.factory-bootstrap-406 .btn-warning:focus,.factory-bootstrap-406 .btn-warning:hover,.factory-bootstrap-406 .open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.factory-bootstrap-406 .btn-warning.active,.factory-bootstrap-406 .btn-warning:active,.factory-bootstrap-406 .open .dropdown-toggle.btn-warning{background-image:none}.factory-bootstrap-406 .btn-warning.disabled,.factory-bootstrap-406 .btn-warning.disabled.active,.factory-bootstrap-406 .btn-warning.disabled:active,.factory-bootstrap-406 .btn-warning.disabled:focus,.factory-bootstrap-406 .btn-warning.disabled:hover,.factory-bootstrap-406 .btn-warning[disabled],.factory-bootstrap-406 .btn-warning[disabled].active,.factory-bootstrap-406 .btn-warning[disabled]:active,.factory-bootstrap-406 .btn-warning[disabled]:focus,.factory-bootstrap-406 .btn-warning[disabled]:hover,.factory-bootstrap-406 fieldset[disabled] .btn-warning,.factory-bootstrap-406 fieldset[disabled] .btn-warning.active,.factory-bootstrap-406 fieldset[disabled] .btn-warning:active,.factory-bootstrap-406 fieldset[disabled] .btn-warning:focus,.factory-bootstrap-406 fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.factory-bootstrap-406 .btn-warning .badge{color:#f0ad4e;background-color:#fff}.factory-bootstrap-406 .btn-success{color:#fff;background-color:#5cb85c}.factory-bootstrap-406 .btn-success.active,.factory-bootstrap-406 .btn-success:active,.factory-bootstrap-406 .btn-success:focus,.factory-bootstrap-406 .btn-success:hover,.factory-bootstrap-406 .open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.factory-bootstrap-406 .btn-success.active,.factory-bootstrap-406 .btn-success:active,.factory-bootstrap-406 .open .dropdown-toggle.btn-success{background-image:none}.factory-bootstrap-406 .btn-success.disabled,.factory-bootstrap-406 .btn-success.disabled.active,.factory-bootstrap-406 .btn-success.disabled:active,.factory-bootstrap-406 .btn-success.disabled:focus,.factory-bootstrap-406 .btn-success.disabled:hover,.factory-bootstrap-406 .btn-success[disabled],.factory-bootstrap-406 .btn-success[disabled].active,.factory-bootstrap-406 .btn-success[disabled]:active,.factory-bootstrap-406 .btn-success[disabled]:focus,.factory-bootstrap-406 .btn-success[disabled]:hover,.factory-bootstrap-406 fieldset[disabled] .btn-success,.factory-bootstrap-406 fieldset[disabled] .btn-success.active,.factory-bootstrap-406 fieldset[disabled] .btn-success:active,.factory-bootstrap-406 fieldset[disabled] .btn-success:focus,.factory-bootstrap-406 fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.factory-bootstrap-406 .btn-success .badge{color:#5cb85c;background-color:#fff}.factory-bootstrap-406 .btn-info{color:#fff;background-color:#5bc0de}.factory-bootstrap-406 .btn-info.active,.factory-bootstrap-406 .btn-info:active,.factory-bootstrap-406 .btn-info:focus,.factory-bootstrap-406 .btn-info:hover,.factory-bootstrap-406 .open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.factory-bootstrap-406 .btn-info.active,.factory-bootstrap-406 .btn-info:active,.factory-bootstrap-406 .open .dropdown-toggle.btn-info{background-image:none}.factory-bootstrap-406 .btn-info.disabled,.factory-bootstrap-406 .btn-info.disabled.active,.factory-bootstrap-406 .btn-info.disabled:active,.factory-bootstrap-406 .btn-info.disabled:focus,.factory-bootstrap-406 .btn-info.disabled:hover,.factory-bootstrap-406 .btn-info[disabled],.factory-bootstrap-406 .btn-info[disabled].active,.factory-bootstrap-406 .btn-info[disabled]:active,.factory-bootstrap-406 .btn-info[disabled]:focus,.factory-bootstrap-406 .btn-info[disabled]:hover,.factory-bootstrap-406 fieldset[disabled] .btn-info,.factory-bootstrap-406 fieldset[disabled] .btn-info.active,.factory-bootstrap-406 fieldset[disabled] .btn-info:active,.factory-bootstrap-406 fieldset[disabled] .btn-info:focus,.factory-bootstrap-406 fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.factory-bootstrap-406 .btn-info .badge{color:#5bc0de;background-color:#fff}.factory-bootstrap-406 .btn-link{font-weight:400;color:#428bca;cursor:pointer;border-radius:0}.factory-bootstrap-406 .btn-link,.factory-bootstrap-406 .btn-link:active,.factory-bootstrap-406 .btn-link[disabled],.factory-bootstrap-406 fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-406 .btn-link,.factory-bootstrap-406 .btn-link:active,.factory-bootstrap-406 .btn-link:focus,.factory-bootstrap-406 .btn-link:hover{border-color:transparent}.factory-bootstrap-406 .btn-link:focus,.factory-bootstrap-406 .btn-link:hover{color:#2a6496;text-decoration:underline;background-color:transparent}.factory-bootstrap-406 .btn-link[disabled]:focus,.factory-bootstrap-406 .btn-link[disabled]:hover,.factory-bootstrap-406 fieldset[disabled] .btn-link:focus,.factory-bootstrap-406 fieldset[disabled] .btn-link:hover{color:#999;text-decoration:none}.factory-bootstrap-406 .btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-406 .btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-406 .btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-406 .btn-block{display:block;width:100%;padding-right:0;padding-left:0}.factory-bootstrap-406 .btn-block+.btn-block{margin-top:5px}.factory-bootstrap-406 input[type=button].btn-block,.factory-bootstrap-406 input[type=reset].btn-block,.factory-bootstrap-406 input[type=submit].btn-block{width:100%}.factory-bootstrap-406 .fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.factory-bootstrap-406 .fade.in{opacity:1}.factory-bootstrap-406 .collapse{display:none}.factory-bootstrap-406 .collapse.in{display:block}.factory-bootstrap-406 .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular) format('svg')}.factory-bootstrap-406 .glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale}.factory-bootstrap-406 .glyphicon:empty{width:1em}.factory-bootstrap-406 .glyphicon-asterisk:before{content:"\2a"}.factory-bootstrap-406 .glyphicon-plus:before{content:"\2b"}.factory-bootstrap-406 .glyphicon-euro:before{content:"\20ac"}.factory-bootstrap-406 .glyphicon-minus:before{content:"\2212"}.factory-bootstrap-406 .glyphicon-cloud:before{content:"\2601"}.factory-bootstrap-406 .glyphicon-envelope:before{content:"\2709"}.factory-bootstrap-406 .glyphicon-pencil:before{content:"\270f"}.factory-bootstrap-406 .glyphicon-glass:before{content:"\e001"}.factory-bootstrap-406 .glyphicon-music:before{content:"\e002"}.factory-bootstrap-406 .glyphicon-search:before{content:"\e003"}.factory-bootstrap-406 .glyphicon-heart:before{content:"\e005"}.factory-bootstrap-406 .glyphicon-star:before{content:"\e006"}.factory-bootstrap-406 .glyphicon-star-empty:before{content:"\e007"}.factory-bootstrap-406 .glyphicon-user:before{content:"\e008"}.factory-bootstrap-406 .glyphicon-film:before{content:"\e009"}.factory-bootstrap-406 .glyphicon-th-large:before{content:"\e010"}.factory-bootstrap-406 .glyphicon-th:before{content:"\e011"}.factory-bootstrap-406 .glyphicon-th-list:before{content:"\e012"}.factory-bootstrap-406 .glyphicon-ok:before{content:"\e013"}.factory-bootstrap-406 .glyphicon-remove:before{content:"\e014"}.factory-bootstrap-406 .glyphicon-zoom-in:before{content:"\e015"}.factory-bootstrap-406 .glyphicon-zoom-out:before{content:"\e016"}.factory-bootstrap-406 .glyphicon-off:before{content:"\e017"}.factory-bootstrap-406 .glyphicon-signal:before{content:"\e018"}.factory-bootstrap-406 .glyphicon-cog:before{content:"\e019"}.factory-bootstrap-406 .glyphicon-trash:before{content:"\e020"}.factory-bootstrap-406 .glyphicon-home:before{content:"\e021"}.factory-bootstrap-406 .glyphicon-file:before{content:"\e022"}.factory-bootstrap-406 .glyphicon-time:before{content:"\e023"}.factory-bootstrap-406 .glyphicon-road:before{content:"\e024"}.factory-bootstrap-406 .glyphicon-download-alt:before{content:"\e025"}.factory-bootstrap-406 .glyphicon-download:before{content:"\e026"}.factory-bootstrap-406 .glyphicon-upload:before{content:"\e027"}.factory-bootstrap-406 .glyphicon-inbox:before{content:"\e028"}.factory-bootstrap-406 .glyphicon-play-circle:before{content:"\e029"}.factory-bootstrap-406 .glyphicon-repeat:before{content:"\e030"}.factory-bootstrap-406 .glyphicon-refresh:before{content:"\e031"}.factory-bootstrap-406 .glyphicon-list-alt:before{content:"\e032"}.factory-bootstrap-406 .glyphicon-lock:before{content:"\e033"}.factory-bootstrap-406 .glyphicon-flag:before{content:"\e034"}.factory-bootstrap-406 .glyphicon-headphones:before{content:"\e035"}.factory-bootstrap-406 .glyphicon-volume-off:before{content:"\e036"}.factory-bootstrap-406 .glyphicon-volume-down:before{content:"\e037"}.factory-bootstrap-406 .glyphicon-volume-up:before{content:"\e038"}.factory-bootstrap-406 .glyphicon-qrcode:before{content:"\e039"}.factory-bootstrap-406 .glyphicon-barcode:before{content:"\e040"}.factory-bootstrap-406 .glyphicon-tag:before{content:"\e041"}.factory-bootstrap-406 .glyphicon-tags:before{content:"\e042"}.factory-bootstrap-406 .glyphicon-book:before{content:"\e043"}.factory-bootstrap-406 .glyphicon-bookmark:before{content:"\e044"}.factory-bootstrap-406 .glyphicon-print:before{content:"\e045"}.factory-bootstrap-406 .glyphicon-camera:before{content:"\e046"}.factory-bootstrap-406 .glyphicon-font:before{content:"\e047"}.factory-bootstrap-406 .glyphicon-bold:before{content:"\e048"}.factory-bootstrap-406 .glyphicon-italic:before{content:"\e049"}.factory-bootstrap-406 .glyphicon-text-height:before{content:"\e050"}.factory-bootstrap-406 .glyphicon-text-width:before{content:"\e051"}.factory-bootstrap-406 .glyphicon-align-left:before{content:"\e052"}.factory-bootstrap-406 .glyphicon-align-center:before{content:"\e053"}.factory-bootstrap-406 .glyphicon-align-right:before{content:"\e054"}.factory-bootstrap-406 .glyphicon-align-justify:before{content:"\e055"}.factory-bootstrap-406 .glyphicon-list:before{content:"\e056"}.factory-bootstrap-406 .glyphicon-indent-left:before{content:"\e057"}.factory-bootstrap-406 .glyphicon-indent-right:before{content:"\e058"}.factory-bootstrap-406 .glyphicon-facetime-video:before{content:"\e059"}.factory-bootstrap-406 .glyphicon-picture:before{content:"\e060"}.factory-bootstrap-406 .glyphicon-map-marker:before{content:"\e062"}.factory-bootstrap-406 .glyphicon-adjust:before{content:"\e063"}.factory-bootstrap-406 .glyphicon-tint:before{content:"\e064"}.factory-bootstrap-406 .glyphicon-edit:before{content:"\e065"}.factory-bootstrap-406 .glyphicon-share:before{content:"\e066"}.factory-bootstrap-406 .glyphicon-check:before{content:"\e067"}.factory-bootstrap-406 .glyphicon-move:before{content:"\e068"}.factory-bootstrap-406 .glyphicon-step-backward:before{content:"\e069"}.factory-bootstrap-406 .glyphicon-fast-backward:before{content:"\e070"}.factory-bootstrap-406 .glyphicon-backward:before{content:"\e071"}.factory-bootstrap-406 .glyphicon-play:before{content:"\e072"}.factory-bootstrap-406 .glyphicon-pause:before{content:"\e073"}.factory-bootstrap-406 .glyphicon-stop:before{content:"\e074"}.factory-bootstrap-406 .glyphicon-forward:before{content:"\e075"}.factory-bootstrap-406 .glyphicon-fast-forward:before{content:"\e076"}.factory-bootstrap-406 .glyphicon-step-forward:before{content:"\e077"}.factory-bootstrap-406 .glyphicon-eject:before{content:"\e078"}.factory-bootstrap-406 .glyphicon-chevron-left:before{content:"\e079"}.factory-bootstrap-406 .glyphicon-chevron-right:before{content:"\e080"}.factory-bootstrap-406 .glyphicon-plus-sign:before{content:"\e081"}.factory-bootstrap-406 .glyphicon-minus-sign:before{content:"\e082"}.factory-bootstrap-406 .glyphicon-remove-sign:before{content:"\e083"}.factory-bootstrap-406 .glyphicon-ok-sign:before{content:"\e084"}.factory-bootstrap-406 .glyphicon-question-sign:before{content:"\e085"}.factory-bootstrap-406 .glyphicon-info-sign:before{content:"\e086"}.factory-bootstrap-406 .glyphicon-screenshot:before{content:"\e087"}.factory-bootstrap-406 .glyphicon-remove-circle:before{content:"\e088"}.factory-bootstrap-406 .glyphicon-ok-circle:before{content:"\e089"}.factory-bootstrap-406 .glyphicon-ban-circle:before{content:"\e090"}.factory-bootstrap-406 .glyphicon-arrow-left:before{content:"\e091"}.factory-bootstrap-406 .glyphicon-arrow-right:before{content:"\e092"}.factory-bootstrap-406 .glyphicon-arrow-up:before{content:"\e093"}.factory-bootstrap-406 .glyphicon-arrow-down:before{content:"\e094"}.factory-bootstrap-406 .glyphicon-share-alt:before{content:"\e095"}.factory-bootstrap-406 .glyphicon-resize-full:before{content:"\e096"}.factory-bootstrap-406 .glyphicon-resize-small:before{content:"\e097"}.factory-bootstrap-406 .glyphicon-exclamation-sign:before{content:"\e101"}.factory-bootstrap-406 .glyphicon-gift:before{content:"\e102"}.factory-bootstrap-406 .glyphicon-leaf:before{content:"\e103"}.factory-bootstrap-406 .glyphicon-fire:before{content:"\e104"}.factory-bootstrap-406 .glyphicon-eye-open:before{content:"\e105"}.factory-bootstrap-406 .glyphicon-eye-close:before{content:"\e106"}.factory-bootstrap-406 .glyphicon-warning-sign:before{content:"\e107"}.factory-bootstrap-406 .glyphicon-plane:before{content:"\e108"}.factory-bootstrap-406 .glyphicon-calendar:before{content:"\e109"}.factory-bootstrap-406 .glyphicon-random:before{content:"\e110"}.factory-bootstrap-406 .glyphicon-comment:before{content:"\e111"}.factory-bootstrap-406 .glyphicon-magnet:before{content:"\e112"}.factory-bootstrap-406 .glyphicon-chevron-up:before{content:"\e113"}.factory-bootstrap-406 .glyphicon-chevron-down:before{content:"\e114"}.factory-bootstrap-406 .glyphicon-retweet:before{content:"\e115"}.factory-bootstrap-406 .glyphicon-shopping-cart:before{content:"\e116"}.factory-bootstrap-406 .glyphicon-folder-close:before{content:"\e117"}.factory-bootstrap-406 .glyphicon-folder-open:before{content:"\e118"}.factory-bootstrap-406 .glyphicon-resize-vertical:before{content:"\e119"}.factory-bootstrap-406 .glyphicon-resize-horizontal:before{content:"\e120"}.factory-bootstrap-406 .glyphicon-hdd:before{content:"\e121"}.factory-bootstrap-406 .glyphicon-bullhorn:before{content:"\e122"}.factory-bootstrap-406 .glyphicon-bell:before{content:"\e123"}.factory-bootstrap-406 .glyphicon-certificate:before{content:"\e124"}.factory-bootstrap-406 .glyphicon-thumbs-up:before{content:"\e125"}.factory-bootstrap-406 .glyphicon-thumbs-down:before{content:"\e126"}.factory-bootstrap-406 .glyphicon-hand-right:before{content:"\e127"}.factory-bootstrap-406 .glyphicon-hand-left:before{content:"\e128"}.factory-bootstrap-406 .glyphicon-hand-up:before{content:"\e129"}.factory-bootstrap-406 .glyphicon-hand-down:before{content:"\e130"}.factory-bootstrap-406 .glyphicon-circle-arrow-right:before{content:"\e131"}.factory-bootstrap-406 .glyphicon-circle-arrow-left:before{content:"\e132"}.factory-bootstrap-406 .glyphicon-circle-arrow-up:before{content:"\e133"}.factory-bootstrap-406 .glyphicon-circle-arrow-down:before{content:"\e134"}.factory-bootstrap-406 .glyphicon-globe:before{content:"\e135"}.factory-bootstrap-406 .glyphicon-wrench:before{content:"\e136"}.factory-bootstrap-406 .glyphicon-tasks:before{content:"\e137"}.factory-bootstrap-406 .glyphicon-filter:before{content:"\e138"}.factory-bootstrap-406 .glyphicon-briefcase:before{content:"\e139"}.factory-bootstrap-406 .glyphicon-fullscreen:before{content:"\e140"}.factory-bootstrap-406 .glyphicon-dashboard:before{content:"\e141"}.factory-bootstrap-406 .glyphicon-paperclip:before{content:"\e142"}.factory-bootstrap-406 .glyphicon-heart-empty:before{content:"\e143"}.factory-bootstrap-406 .glyphicon-link:before{content:"\e144"}.factory-bootstrap-406 .glyphicon-phone:before{content:"\e145"}.factory-bootstrap-406 .glyphicon-pushpin:before{content:"\e146"}.factory-bootstrap-406 .glyphicon-usd:before{content:"\e148"}.factory-bootstrap-406 .glyphicon-gbp:before{content:"\e149"}.factory-bootstrap-406 .glyphicon-sort:before{content:"\e150"}.factory-bootstrap-406 .glyphicon-sort-by-alphabet:before{content:"\e151"}.factory-bootstrap-406 .glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.factory-bootstrap-406 .glyphicon-sort-by-order:before{content:"\e153"}.factory-bootstrap-406 .glyphicon-sort-by-order-alt:before{content:"\e154"}.factory-bootstrap-406 .glyphicon-sort-by-attributes:before{content:"\e155"}.factory-bootstrap-406 .glyphicon-sort-by-attributes-alt:before{content:"\e156"}.factory-bootstrap-406 .glyphicon-unchecked:before{content:"\e157"}.factory-bootstrap-406 .glyphicon-expand:before{content:"\e158"}.factory-bootstrap-406 .glyphicon-collapse-down:before{content:"\e159"}.factory-bootstrap-406 .glyphicon-collapse-up:before{content:"\e160"}.factory-bootstrap-406 .glyphicon-log-in:before{content:"\e161"}.factory-bootstrap-406 .glyphicon-flash:before{content:"\e162"}.factory-bootstrap-406 .glyphicon-log-out:before{content:"\e163"}.factory-bootstrap-406 .glyphicon-new-window:before{content:"\e164"}.factory-bootstrap-406 .glyphicon-record:before{content:"\e165"}.factory-bootstrap-406 .glyphicon-save:before{content:"\e166"}.factory-bootstrap-406 .glyphicon-open:before{content:"\e167"}.factory-bootstrap-406 .glyphicon-saved:before{content:"\e168"}.factory-bootstrap-406 .glyphicon-import:before{content:"\e169"}.factory-bootstrap-406 .glyphicon-export:before{content:"\e170"}.factory-bootstrap-406 .glyphicon-send:before{content:"\e171"}.factory-bootstrap-406 .glyphicon-floppy-disk:before{content:"\e172"}.factory-bootstrap-406 .glyphicon-floppy-saved:before{content:"\e173"}.factory-bootstrap-406 .glyphicon-floppy-remove:before{content:"\e174"}.factory-bootstrap-406 .glyphicon-floppy-save:before{content:"\e175"}.factory-bootstrap-406 .glyphicon-floppy-open:before{content:"\e176"}.factory-bootstrap-406 .glyphicon-credit-card:before{content:"\e177"}.factory-bootstrap-406 .glyphicon-transfer:before{content:"\e178"}.factory-bootstrap-406 .glyphicon-cutlery:before{content:"\e179"}.factory-bootstrap-406 .glyphicon-header:before{content:"\e180"}.factory-bootstrap-406 .glyphicon-compressed:before{content:"\e181"}.factory-bootstrap-406 .glyphicon-earphone:before{content:"\e182"}.factory-bootstrap-406 .glyphicon-phone-alt:before{content:"\e183"}.factory-bootstrap-406 .glyphicon-tower:before{content:"\e184"}.factory-bootstrap-406 .glyphicon-stats:before{content:"\e185"}.factory-bootstrap-406 .glyphicon-sd-video:before{content:"\e186"}.factory-bootstrap-406 .glyphicon-hd-video:before{content:"\e187"}.factory-bootstrap-406 .glyphicon-subtitles:before{content:"\e188"}.factory-bootstrap-406 .glyphicon-sound-stereo:before{content:"\e189"}.factory-bootstrap-406 .glyphicon-sound-dolby:before{content:"\e190"}.factory-bootstrap-406 .glyphicon-sound-5-1:before{content:"\e191"}.factory-bootstrap-406 .glyphicon-sound-6-1:before{content:"\e192"}.factory-bootstrap-406 .glyphicon-sound-7-1:before{content:"\e193"}.factory-bootstrap-406 .glyphicon-copyright-mark:before{content:"\e194"}.factory-bootstrap-406 .glyphicon-registration-mark:before{content:"\e195"}.factory-bootstrap-406 .glyphicon-cloud-download:before{content:"\e197"}.factory-bootstrap-406 .glyphicon-cloud-upload:before{content:"\e198"}.factory-bootstrap-406 .glyphicon-tree-conifer:before{content:"\e199"}.factory-bootstrap-406 .glyphicon-tree-deciduous:before{content:"\e200"}.factory-bootstrap-406 .caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.factory-bootstrap-406 .dropdown{position:relative}.factory-bootstrap-406 .dropdown-toggle:focus{outline:0}.factory-bootstrap-406 .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.factory-bootstrap-406 .dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-406 .dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-406 .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.factory-bootstrap-406 .dropdown-menu>li>a:focus,.factory-bootstrap-406 .dropdown-menu>li>a:hover{color:#262626;text-decoration:none}.factory-bootstrap-406 .dropdown-menu>.active>a,.factory-bootstrap-406 .dropdown-menu>.active>a:focus,.factory-bootstrap-406 .dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0}.factory-bootstrap-406 .dropdown-menu>.disabled>a,.factory-bootstrap-406 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-406 .dropdown-menu>.disabled>a:hover{color:#999}.factory-bootstrap-406 .dropdown-menu>.disabled>a:focus,.factory-bootstrap-406 .dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-406 .open>.dropdown-menu{display:block}.factory-bootstrap-406 .open>a{outline:0}.factory-bootstrap-406 .dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.factory-bootstrap-406 .dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.factory-bootstrap-406 .pull-right>.dropdown-menu{right:0;left:auto}.factory-bootstrap-406 .dropup .caret,.factory-bootstrap-406 .navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.factory-bootstrap-406 .dropup .dropdown-menu,.factory-bootstrap-406 .navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.factory-bootstrap-406 .btn-group,.factory-bootstrap-406 .btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.factory-bootstrap-406 .btn-group-vertical>.btn,.factory-bootstrap-406 .btn-group>.btn{position:relative;float:left}.factory-bootstrap-406 .btn-group-vertical>.btn.active,.factory-bootstrap-406 .btn-group-vertical>.btn:active,.factory-bootstrap-406 .btn-group-vertical>.btn:focus,.factory-bootstrap-406 .btn-group-vertical>.btn:hover,.factory-bootstrap-406 .btn-group>.btn.active,.factory-bootstrap-406 .btn-group>.btn:active,.factory-bootstrap-406 .btn-group>.btn:focus,.factory-bootstrap-406 .btn-group>.btn:hover{z-index:2}.factory-bootstrap-406 .btn-group-vertical>.btn:focus,.factory-bootstrap-406 .btn-group>.btn:focus{outline:0}.factory-bootstrap-406 .btn-group .btn+.btn,.factory-bootstrap-406 .btn-group .btn+.btn-group,.factory-bootstrap-406 .btn-group .btn-group+.btn,.factory-bootstrap-406 .btn-group .btn-group+.btn-group{margin-left:-1px}.factory-bootstrap-406 .btn-toolbar:after,.factory-bootstrap-406 .btn-toolbar:before{display:table;content:" "}.factory-bootstrap-406 .btn-toolbar:after{clear:both}.factory-bootstrap-406 .btn-toolbar .btn-group{float:left}.factory-bootstrap-406 .btn-toolbar>.btn+.btn,.factory-bootstrap-406 .btn-toolbar>.btn+.btn-group,.factory-bootstrap-406 .btn-toolbar>.btn-group+.btn,.factory-bootstrap-406 .btn-toolbar>.btn-group+.btn-group{margin-left:5px}.factory-bootstrap-406 .btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.factory-bootstrap-406 .btn-group>.btn:first-child{margin-left:0}.factory-bootstrap-406 .btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-406 .btn-group>.btn:last-child:not(:first-child),.factory-bootstrap-406 .btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .btn-group>.btn-group{float:left}.factory-bootstrap-406 .btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-406 .btn-group>.btn-group:first-child>.btn:last-child,.factory-bootstrap-406 .btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-406 .btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .btn-group .dropdown-toggle:active,.factory-bootstrap-406 .btn-group.open .dropdown-toggle{outline:0}.factory-bootstrap-406 .btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-406 .btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-406 .btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-406 .btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.factory-bootstrap-406 .btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.factory-bootstrap-406 .btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.factory-bootstrap-406 .btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.factory-bootstrap-406 .btn-group{border:4px solid #f9f9f9;border-radius:4px}.factory-bootstrap-406 .btn-group .btn.active.value{text-shadow:none;color:#fff;background-color:#33aad5;-webkit-box-shadow:inset 0 1px 1px #0074a2;box-shadow:inset 0 1px 3px #0074a2;border-top:1px solid #0074a2;border-bottom:1px solid #0074a2;border-left:1px solid #0074a2}.factory-bootstrap-406 .btn .caret{margin-left:0}.factory-bootstrap-406 .btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.factory-bootstrap-406 .dropup .btn-lg .caret{border-width:0 5px 5px}.factory-bootstrap-406 .btn-group-vertical>.btn,.factory-bootstrap-406 .btn-group-vertical>.btn-group,.factory-bootstrap-406 .btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.factory-bootstrap-406 .btn-group-vertical>.btn-group:after,.factory-bootstrap-406 .btn-group-vertical>.btn-group:before{display:table;content:" "}.factory-bootstrap-406 .btn-group-vertical>.btn-group:after{clear:both}.factory-bootstrap-406 .btn-group-vertical>.btn-group>.btn{float:none}.factory-bootstrap-406 .btn-group-vertical>.btn+.btn,.factory-bootstrap-406 .btn-group-vertical>.btn+.btn-group,.factory-bootstrap-406 .btn-group-vertical>.btn-group+.btn,.factory-bootstrap-406 .btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.factory-bootstrap-406 .btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-406 .btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-406 .btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.factory-bootstrap-406 .btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.factory-bootstrap-406 .btn-group-vertical>.btn-group:first-child>.btn:last-child,.factory-bootstrap-406 .btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-406 .btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.factory-bootstrap-406 .btn-group-justified>.btn,.factory-bootstrap-406 .btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.factory-bootstrap-406 .btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=checkbox],[data-toggle=buttons]>.btn>input[type=radio]{display:none}.factory-bootstrap-406 .input-group{position:relative;display:table;border-collapse:separate}.factory-bootstrap-406 .input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.factory-bootstrap-406 .input-group .form-control{width:100%;margin-bottom:0}.factory-bootstrap-406 .input-group-lg>.form-control,.factory-bootstrap-406 .input-group-lg>.input-group-addon,.factory-bootstrap-406 .input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.factory-bootstrap-406 select.input-group-lg>.form-control,.factory-bootstrap-406 select.input-group-lg>.input-group-addon,.factory-bootstrap-406 select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}.factory-bootstrap-406 textarea.input-group-lg>.form-control,.factory-bootstrap-406 textarea.input-group-lg>.input-group-addon,.factory-bootstrap-406 textarea.input-group-lg>.input-group-btn>.btn{height:auto}.factory-bootstrap-406 .input-group-sm>.form-control,.factory-bootstrap-406 .input-group-sm>.input-group-addon,.factory-bootstrap-406 .input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.factory-bootstrap-406 select.input-group-sm>.form-control,.factory-bootstrap-406 select.input-group-sm>.input-group-addon,.factory-bootstrap-406 select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}.factory-bootstrap-406 textarea.input-group-sm>.form-control,.factory-bootstrap-406 textarea.input-group-sm>.input-group-addon,.factory-bootstrap-406 textarea.input-group-sm>.input-group-btn>.btn{height:auto}.factory-bootstrap-406 .input-group .form-control,.factory-bootstrap-406 .input-group-addon,.factory-bootstrap-406 .input-group-btn{display:table-cell}.factory-bootstrap-406 .input-group .form-control:not(:first-child):not(:last-child),.factory-bootstrap-406 .input-group-addon:not(:first-child):not(:last-child),.factory-bootstrap-406 .input-group-btn:not(:first-child):not(:last-child){border-radius:0}.factory-bootstrap-406 .input-group-addon,.factory-bootstrap-406 .input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.factory-bootstrap-406 .input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.factory-bootstrap-406 .input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.factory-bootstrap-406 .input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.factory-bootstrap-406 .input-group-addon input[type=checkbox],.factory-bootstrap-406 .input-group-addon input[type=radio]{margin-top:0}.factory-bootstrap-406 .input-group .form-control:first-child,.factory-bootstrap-406 .input-group-addon:first-child,.factory-bootstrap-406 .input-group-btn:first-child>.btn,.factory-bootstrap-406 .input-group-btn:first-child>.dropdown-toggle,.factory-bootstrap-406 .input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.factory-bootstrap-406 .input-group-addon:first-child{border-right:0}.factory-bootstrap-406 .input-group .form-control:last-child,.factory-bootstrap-406 .input-group-addon:last-child,.factory-bootstrap-406 .input-group-btn:first-child>.btn:not(:first-child),.factory-bootstrap-406 .input-group-btn:last-child>.btn,.factory-bootstrap-406 .input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .input-group-addon:last-child{border-left:0}.factory-bootstrap-406 .input-group-btn{position:relative;white-space:nowrap}.factory-bootstrap-406 .input-group-btn:first-child>.btn{margin-right:-1px}.factory-bootstrap-406 .input-group-btn:last-child>.btn{margin-left:-1px}.factory-bootstrap-406 .input-group-btn>.btn{position:relative}.factory-bootstrap-406 .input-group-btn>.btn+.btn{margin-left:-4px}.factory-bootstrap-406 .input-group-btn>.btn:active,.factory-bootstrap-406 .input-group-btn>.btn:hover{z-index:2}.factory-bootstrap-406 .nav{padding-left:0;margin-bottom:0;list-style:none}.factory-bootstrap-406 .nav:after,.factory-bootstrap-406 .nav:before{display:table;content:" "}.factory-bootstrap-406 .nav:after{clear:both}.factory-bootstrap-406 .nav>li{position:relative;display:block}.factory-bootstrap-406 .nav>li>a{position:relative;display:block;padding:10px 15px}.factory-bootstrap-406 .nav>li>a:focus,.factory-bootstrap-406 .nav>li>a:hover{text-decoration:none;background-color:#eee}.factory-bootstrap-406 .nav>li.disabled>a{color:#999}.factory-bootstrap-406 .nav>li.disabled>a:focus,.factory-bootstrap-406 .nav>li.disabled>a:hover{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.factory-bootstrap-406 .nav .open>a,.factory-bootstrap-406 .nav .open>a:focus,.factory-bootstrap-406 .nav .open>a:hover{background-color:#eee;border-color:#428bca}.factory-bootstrap-406 .nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.factory-bootstrap-406 .nav>li>a>img{max-width:none}.factory-bootstrap-406 .nav-tabs{border-bottom:1px solid #ddd}.factory-bootstrap-406 .nav-tabs>li{float:left;margin-bottom:-1px}.factory-bootstrap-406 .nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.factory-bootstrap-406 .nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.factory-bootstrap-406 .nav-tabs>li.active>a,.factory-bootstrap-406 .nav-tabs>li.active>a:focus,.factory-bootstrap-406 .nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.factory-bootstrap-406 .nav-tabs.nav-justified{width:100%;border-bottom:0}.factory-bootstrap-406 .nav-tabs.nav-justified>li{float:none}.factory-bootstrap-406 .nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.factory-bootstrap-406 .nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.factory-bootstrap-406 .nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.factory-bootstrap-406 .nav-tabs.nav-justified>.active>a,.factory-bootstrap-406 .nav-tabs.nav-justified>.active>a:focus,.factory-bootstrap-406 .nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.factory-bootstrap-406 .nav-pills>li{float:left}.factory-bootstrap-406 .nav-pills>li>a{border-radius:4px}.factory-bootstrap-406 .nav-pills>li+li{margin-left:2px}.factory-bootstrap-406 .nav-pills>li.active>a,.factory-bootstrap-406 .nav-pills>li.active>a:focus,.factory-bootstrap-406 .nav-pills>li.active>a:hover{color:#fff;background-color:#428bca}.factory-bootstrap-406 .nav-stacked>li{float:none}.factory-bootstrap-406 .nav-stacked>li+li{margin-top:2px;margin-left:0}.factory-bootstrap-406 .nav-justified{width:100%}.factory-bootstrap-406 .nav-justified>li{float:none}.factory-bootstrap-406 .nav-justified>li>a{margin-bottom:5px;text-align:center}.factory-bootstrap-406 .nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.factory-bootstrap-406 .nav-tabs-justified{border-bottom:0}.factory-bootstrap-406 .nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.factory-bootstrap-406 .nav-tabs-justified>.active>a,.factory-bootstrap-406 .nav-tabs-justified>.active>a:focus,.factory-bootstrap-406 .nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.factory-bootstrap-406 .tab-content>.tab-pane{display:none}.factory-bootstrap-406 .tab-content>.active{display:block}.factory-bootstrap-406 .nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.factory-bootstrap-406 .navbar:after,.factory-bootstrap-406 .navbar:before{display:table;content:" "}.factory-bootstrap-406 .navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:4px}}.factory-bootstrap-406 .navbar-header:after,.factory-bootstrap-406 .navbar-header:before{display:table;content:" "}.factory-bootstrap-406 .navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.factory-bootstrap-406 .navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.factory-bootstrap-406 .navbar-collapse:after,.factory-bootstrap-406 .navbar-collapse:before{display:table;content:" "}.factory-bootstrap-406 .navbar-collapse:after{clear:both}.factory-bootstrap-406 .navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.factory-bootstrap-406 .container>.navbar-collapse,.factory-bootstrap-406 .container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.factory-bootstrap-406 .navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.factory-bootstrap-406 .navbar-fixed-bottom,.factory-bootstrap-406 .navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.factory-bootstrap-406 .navbar-fixed-top{top:0;border-width:0 0 1px}.factory-bootstrap-406 .navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.factory-bootstrap-406 .navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px}.factory-bootstrap-406 .navbar-brand:focus,.factory-bootstrap-406 .navbar-brand:hover{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.factory-bootstrap-406 .navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.factory-bootstrap-406 .navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.factory-bootstrap-406 .navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.factory-bootstrap-406 .navbar-nav{margin:7.5px -15px}.factory-bootstrap-406 .navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.factory-bootstrap-406 .navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form select.form-control{width:auto}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{float:none;margin-left:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.factory-bootstrap-406 .navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.factory-bootstrap-406 .navbar-nav.pull-right>li>.dropdown-menu,.factory-bootstrap-406 .navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.factory-bootstrap-406 .navbar-btn{margin-top:8px;margin-bottom:8px}.factory-bootstrap-406 .navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.factory-bootstrap-406 .navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.factory-bootstrap-406 .navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.factory-bootstrap-406 .navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.factory-bootstrap-406 .navbar-default .navbar-brand{color:#777}.factory-bootstrap-406 .navbar-default .navbar-brand:focus,.factory-bootstrap-406 .navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.factory-bootstrap-406 .navbar-default .navbar-nav>li>a,.factory-bootstrap-406 .navbar-default .navbar-text{color:#777}.factory-bootstrap-406 .navbar-default .navbar-nav>li>a:focus,.factory-bootstrap-406 .navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.factory-bootstrap-406 .navbar-default .navbar-nav>.active>a,.factory-bootstrap-406 .navbar-default .navbar-nav>.active>a:focus,.factory-bootstrap-406 .navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.factory-bootstrap-406 .navbar-default .navbar-nav>.disabled>a,.factory-bootstrap-406 .navbar-default .navbar-nav>.disabled>a:focus,.factory-bootstrap-406 .navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.factory-bootstrap-406 .navbar-default .navbar-toggle{border-color:#ddd}.factory-bootstrap-406 .navbar-default .navbar-toggle:focus,.factory-bootstrap-406 .navbar-default .navbar-toggle:hover{background-color:#ddd}.factory-bootstrap-406 .navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.factory-bootstrap-406 .navbar-default .navbar-collapse,.factory-bootstrap-406 .navbar-default .navbar-form{border-color:#e7e7e7}.factory-bootstrap-406 .navbar-default .navbar-nav>.open>a,.factory-bootstrap-406 .navbar-default .navbar-nav>.open>a:focus,.factory-bootstrap-406 .navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.factory-bootstrap-406 .navbar-default .navbar-link{color:#777}.factory-bootstrap-406 .navbar-default .navbar-link:hover{color:#333}.factory-bootstrap-406 .navbar-inverse{background-color:#222;border-color:#080808}.factory-bootstrap-406 .navbar-inverse .navbar-brand{color:#999}.factory-bootstrap-406 .navbar-inverse .navbar-brand:focus,.factory-bootstrap-406 .navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.factory-bootstrap-406 .navbar-inverse .navbar-nav>li>a,.factory-bootstrap-406 .navbar-inverse .navbar-text{color:#999}.factory-bootstrap-406 .navbar-inverse .navbar-nav>li>a:focus,.factory-bootstrap-406 .navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.factory-bootstrap-406 .navbar-inverse .navbar-nav>.active>a,.factory-bootstrap-406 .navbar-inverse .navbar-nav>.active>a:focus,.factory-bootstrap-406 .navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.factory-bootstrap-406 .navbar-inverse .navbar-nav>.disabled>a,.factory-bootstrap-406 .navbar-inverse .navbar-nav>.disabled>a:focus,.factory-bootstrap-406 .navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.factory-bootstrap-406 .navbar-inverse .navbar-toggle{border-color:#333}.factory-bootstrap-406 .navbar-inverse .navbar-toggle:focus,.factory-bootstrap-406 .navbar-inverse .navbar-toggle:hover{background-color:#333}.factory-bootstrap-406 .navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.factory-bootstrap-406 .navbar-inverse .navbar-collapse,.factory-bootstrap-406 .navbar-inverse .navbar-form{border-color:#101010}.factory-bootstrap-406 .navbar-inverse .navbar-nav>.open>a,.factory-bootstrap-406 .navbar-inverse .navbar-nav>.open>a:focus,.factory-bootstrap-406 .navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.factory-bootstrap-406 .navbar-inverse .navbar-link{color:#999}.factory-bootstrap-406 .navbar-inverse .navbar-link:hover{color:#fff}.factory-bootstrap-406 .breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.factory-bootstrap-406 .breadcrumb>li{display:inline-block}.factory-bootstrap-406 .breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.factory-bootstrap-406 .breadcrumb>.active{color:#999}.factory-bootstrap-406 .pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.factory-bootstrap-406 .pagination>li{display:inline}.factory-bootstrap-406 .pagination>li>a,.factory-bootstrap-406 .pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.factory-bootstrap-406 .pagination>li:first-child>a,.factory-bootstrap-406 .pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.factory-bootstrap-406 .pagination>li:last-child>a,.factory-bootstrap-406 .pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.factory-bootstrap-406 .pagination>li>a:focus,.factory-bootstrap-406 .pagination>li>a:hover,.factory-bootstrap-406 .pagination>li>span:focus,.factory-bootstrap-406 .pagination>li>span:hover{background-color:#eee}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#1e8cbe;border-color:#0074a2}.factory-bootstrap-406 .pagination>.disabled>a,.factory-bootstrap-406 .pagination>.disabled>a:focus,.factory-bootstrap-406 .pagination>.disabled>a:hover,.factory-bootstrap-406 .pagination>.disabled>span,.factory-bootstrap-406 .pagination>.disabled>span:focus,.factory-bootstrap-406 .pagination>.disabled>span:hover{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.factory-bootstrap-406 .pagination-lg>li>a,.factory-bootstrap-406 .pagination-lg>li>span{padding:10px 16px;font-size:18px}.factory-bootstrap-406 .pagination-lg>li:first-child>a,.factory-bootstrap-406 .pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.factory-bootstrap-406 .pagination-lg>li:last-child>a,.factory-bootstrap-406 .pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.factory-bootstrap-406 .pagination-sm>li>a,.factory-bootstrap-406 .pagination-sm>li>span{padding:5px 10px;font-size:12px}.factory-bootstrap-406 .pagination-sm>li:first-child>a,.factory-bootstrap-406 .pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.factory-bootstrap-406 .pagination-sm>li:last-child>a,.factory-bootstrap-406 .pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.factory-bootstrap-406 .pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.factory-bootstrap-406 .pager:after,.factory-bootstrap-406 .pager:before{display:table;content:" "}.factory-bootstrap-406 .pager:after{clear:both}.factory-bootstrap-406 .pager li{display:inline}.factory-bootstrap-406 .pager li>a,.factory-bootstrap-406 .pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.factory-bootstrap-406 .pager li>a:focus,.factory-bootstrap-406 .pager li>a:hover{text-decoration:none;background-color:#eee}.factory-bootstrap-406 .pager .next>a,.factory-bootstrap-406 .pager .next>span{float:right}.factory-bootstrap-406 .pager .previous>a,.factory-bootstrap-406 .pager .previous>span{float:left}.factory-bootstrap-406 .pager .disabled>a,.factory-bootstrap-406 .pager .disabled>a:focus,.factory-bootstrap-406 .pager .disabled>a:hover,.factory-bootstrap-406 .pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.factory-bootstrap-406 .label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.factory-bootstrap-406 .label[href]:focus,.factory-bootstrap-406 .label[href]:hover{color:#fff;text-decoration:none;cursor:pointer}.factory-bootstrap-406 .label:empty{display:none}.factory-bootstrap-406 .btn .label{position:relative;top:-1px}.factory-bootstrap-406 .label-default{background-color:#999}.factory-bootstrap-406 .label-default[href]:focus,.factory-bootstrap-406 .label-default[href]:hover{background-color:gray}.factory-bootstrap-406 .label-primary{background-color:#428bca}.factory-bootstrap-406 .label-primary[href]:focus,.factory-bootstrap-406 .label-primary[href]:hover{background-color:#3071a9}.factory-bootstrap-406 .label-success{background-color:#5cb85c}.factory-bootstrap-406 .label-success[href]:focus,.factory-bootstrap-406 .label-success[href]:hover{background-color:#449d44}.factory-bootstrap-406 .label-info{background-color:#5bc0de}.factory-bootstrap-406 .label-info[href]:focus,.factory-bootstrap-406 .label-info[href]:hover{background-color:#31b0d5}.factory-bootstrap-406 .label-warning{background-color:#f0ad4e}.factory-bootstrap-406 .label-warning[href]:focus,.factory-bootstrap-406 .label-warning[href]:hover{background-color:#ec971f}.factory-bootstrap-406 .label-danger{background-color:#d9534f}.factory-bootstrap-406 .label-danger[href]:focus,.factory-bootstrap-406 .label-danger[href]:hover{background-color:#c9302c}.factory-bootstrap-406 .badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.factory-bootstrap-406 .badge:empty{display:none}.factory-bootstrap-406 .btn .badge{position:relative;top:-1px}.factory-bootstrap-406 a.badge:focus,.factory-bootstrap-406 a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.factory-bootstrap-406 .nav-pills>.active>a>.badge,.factory-bootstrap-406 a.list-group-item.active>.badge{color:#428bca;background-color:#fff}.factory-bootstrap-406 .nav-pills>li>a>.badge{margin-left:3px}.factory-bootstrap-406 .jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.factory-bootstrap-406 .jumbotron .h1,.factory-bootstrap-406 .jumbotron h1{line-height:1;color:inherit}.factory-bootstrap-406 .jumbotron p{line-height:1.4}.factory-bootstrap-406 .container .jumbotron{border-radius:6px}.factory-bootstrap-406 .jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.factory-bootstrap-406 .thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.factory-bootstrap-406 .thumbnail a>img,.factory-bootstrap-406 .thumbnail>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}.factory-bootstrap-406 a.thumbnail.active,.factory-bootstrap-406 a.thumbnail:focus,.factory-bootstrap-406 a.thumbnail:hover{border-color:#428bca}.factory-bootstrap-406 .thumbnail .caption{padding:9px;color:#333}.factory-bootstrap-406 .alert{border:1px solid transparent;border-radius:4px}.factory-bootstrap-406 .alert h4{margin-top:0;color:inherit}.factory-bootstrap-406 .alert .alert-link{font-weight:700}.factory-bootstrap-406 .alert>p,.factory-bootstrap-406 .alert>ul{margin-bottom:0}.factory-bootstrap-406 .alert>p+p{margin-top:5px}.factory-bootstrap-406 .alert-dismissable{padding-right:35px}.factory-bootstrap-406 .alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.factory-bootstrap-406 .alert-info{color:#31708f;background-color:#d9edf7}.factory-bootstrap-406 .alert-info hr{border-top-color:#a6e1ec}.factory-bootstrap-406 .alert-info .alert-link{color:#245269}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.factory-bootstrap-406 .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.factory-bootstrap-406 .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#2ea2cc;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.factory-bootstrap-406 .progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.factory-bootstrap-406 .progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.factory-bootstrap-406 .progress-bar-success{background-color:#5cb85c}.factory-bootstrap-406 .progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-406 .progress-bar-info{background-color:#5bc0de}.factory-bootstrap-406 .progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-406 .progress-bar-warning{background-color:#f0ad4e}.factory-bootstrap-406 .progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-406 .progress-bar-danger{background-color:#d9534f}.factory-bootstrap-406 .progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.factory-bootstrap-406 .media,.factory-bootstrap-406 .media-body{overflow:hidden;zoom:1}.factory-bootstrap-406 .media,.factory-bootstrap-406 .media .media{margin-top:15px}.factory-bootstrap-406 .media:first-child{margin-top:0}.factory-bootstrap-406 .media-object{display:block}.factory-bootstrap-406 .media-heading{margin:0 0 5px}.factory-bootstrap-406 .media>.pull-left{margin-right:10px}.factory-bootstrap-406 .media>.pull-right{margin-left:10px}.factory-bootstrap-406 .media-list{padding-left:0;list-style:none}.factory-bootstrap-406 .list-group{padding-left:0;margin-bottom:20px}.factory-bootstrap-406 .list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.factory-bootstrap-406 .list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.factory-bootstrap-406 .list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.factory-bootstrap-406 .list-group-item>.badge{float:right}.factory-bootstrap-406 .list-group-item>.badge+.badge{margin-right:5px}.factory-bootstrap-406 a.list-group-item{color:#555}.factory-bootstrap-406 a.list-group-item .list-group-item-heading{color:#333}.factory-bootstrap-406 a.list-group-item:focus,.factory-bootstrap-406 a.list-group-item:hover{text-decoration:none;background-color:#f5f5f5}.factory-bootstrap-406 a.list-group-item.active,.factory-bootstrap-406 a.list-group-item.active:focus,.factory-bootstrap-406 a.list-group-item.active:hover{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.factory-bootstrap-406 a.list-group-item.active .list-group-item-heading,.factory-bootstrap-406 a.list-group-item.active:focus .list-group-item-heading,.factory-bootstrap-406 a.list-group-item.active:hover .list-group-item-heading{color:inherit}.factory-bootstrap-406 a.list-group-item.active .list-group-item-text,.factory-bootstrap-406 a.list-group-item.active:focus .list-group-item-text,.factory-bootstrap-406 a.list-group-item.active:hover .list-group-item-text{color:#e1edf7}.factory-bootstrap-406 .list-group-item-heading{margin-top:0;margin-bottom:5px}.factory-bootstrap-406 .list-group-item-text{margin-bottom:0;line-height:1.3}.factory-bootstrap-406 .panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px}.factory-bootstrap-406 .panel-body{padding:15px}.factory-bootstrap-406 .panel-body:after,.factory-bootstrap-406 .panel-body:before{display:table;content:" "}.factory-bootstrap-406 .panel-body:after{clear:both}.factory-bootstrap-406 .panel>.list-group{margin-bottom:0}.factory-bootstrap-406 .panel>.list-group .list-group-item{border-width:1px 0}.factory-bootstrap-406 .panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.factory-bootstrap-406 .panel>.list-group .list-group-item:last-child{border-bottom:0}.factory-bootstrap-406 .panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.factory-bootstrap-406 .panel>.table,.factory-bootstrap-406 .panel>.table-responsive>.table{margin-bottom:0}.factory-bootstrap-406 .panel>.panel-body+.table,.factory-bootstrap-406 .panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.factory-bootstrap-406 .panel>.table>tbody:first-child td,.factory-bootstrap-406 .panel>.table>tbody:first-child th{border-top:0}.factory-bootstrap-406 .panel>.table-bordered,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered{border:0}.factory-bootstrap-406 .panel>.table-bordered>tbody>tr>td:first-child,.factory-bootstrap-406 .panel>.table-bordered>tbody>tr>th:first-child,.factory-bootstrap-406 .panel>.table-bordered>tfoot>tr>td:first-child,.factory-bootstrap-406 .panel>.table-bordered>tfoot>tr>th:first-child,.factory-bootstrap-406 .panel>.table-bordered>thead>tr>td:first-child,.factory-bootstrap-406 .panel>.table-bordered>thead>tr>th:first-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.factory-bootstrap-406 .panel>.table-bordered>tbody>tr>td:last-child,.factory-bootstrap-406 .panel>.table-bordered>tbody>tr>th:last-child,.factory-bootstrap-406 .panel>.table-bordered>tfoot>tr>td:last-child,.factory-bootstrap-406 .panel>.table-bordered>tfoot>tr>th:last-child,.factory-bootstrap-406 .panel>.table-bordered>thead>tr>td:last-child,.factory-bootstrap-406 .panel>.table-bordered>thead>tr>th:last-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.factory-bootstrap-406 .panel>.table-bordered>tbody>tr:last-child>td,.factory-bootstrap-406 .panel>.table-bordered>tbody>tr:last-child>th,.factory-bootstrap-406 .panel>.table-bordered>tfoot>tr:last-child>td,.factory-bootstrap-406 .panel>.table-bordered>tfoot>tr:last-child>th,.factory-bootstrap-406 .panel>.table-bordered>thead>tr:last-child>td,.factory-bootstrap-406 .panel>.table-bordered>thead>tr:last-child>th,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.factory-bootstrap-406 .panel>.table-responsive>.table-bordered>thead>tr:last-child>th{border-bottom:0}.factory-bootstrap-406 .panel>.table-responsive{margin-bottom:0;border:0}.factory-bootstrap-406 .panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.factory-bootstrap-406 .panel-heading>.dropdown .dropdown-toggle{color:inherit}.factory-bootstrap-406 .panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.factory-bootstrap-406 .panel-title>a{color:inherit}.factory-bootstrap-406 .panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.factory-bootstrap-406 .panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.factory-bootstrap-406 .panel-group .panel+.panel{margin-top:5px}.factory-bootstrap-406 .panel-group .panel-heading{border-bottom:0}.factory-bootstrap-406 .panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.factory-bootstrap-406 .panel-group .panel-footer{border-top:0}.factory-bootstrap-406 .panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.factory-bootstrap-406 .panel-default{border-color:#ddd}.factory-bootstrap-406 .panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.factory-bootstrap-406 .panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.factory-bootstrap-406 .panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.factory-bootstrap-406 .panel-primary{border-color:#428bca}.factory-bootstrap-406 .panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.factory-bootstrap-406 .panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.factory-bootstrap-406 .panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.factory-bootstrap-406 .panel-success{border-color:#d6e9c6}.factory-bootstrap-406 .panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.factory-bootstrap-406 .panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.factory-bootstrap-406 .panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.factory-bootstrap-406 .panel-warning{border-color:#faebcc}.factory-bootstrap-406 .panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.factory-bootstrap-406 .panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.factory-bootstrap-406 .panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.factory-bootstrap-406 .panel-danger{border-color:#ebccd1}.factory-bootstrap-406 .panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.factory-bootstrap-406 .panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.factory-bootstrap-406 .panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.factory-bootstrap-406 .panel-info{border-color:#bce8f1}.factory-bootstrap-406 .panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.factory-bootstrap-406 .panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.factory-bootstrap-406 .panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.factory-bootstrap-406 .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px}.factory-bootstrap-406 .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.factory-bootstrap-406 .well-lg{padding:24px;border-radius:6px}.factory-bootstrap-406 .well-sm{padding:9px;border-radius:3px}.factory-bootstrap-406 .close{float:right;font-size:14px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.3;filter:alpha(opacity=30)}.factory-bootstrap-406 .alert .close{position:relative;top:-8px;right:-7px}.factory-bootstrap-406 .close:focus,.factory-bootstrap-406 .close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-406 button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.factory-bootstrap-406 .modal-open{overflow:hidden}.factory-bootstrap-406 .modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll;width:auto;margin-left:0;background-color:transparent;border:0}.factory-bootstrap-406 .modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.factory-bootstrap-406 .modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.factory-bootstrap-406 .modal-dialog{position:relative;z-index:1050;width:auto;margin:10px}.factory-bootstrap-406 .modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box}.factory-bootstrap-406 .modal-backdrop,.factory-bootstrap-406-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.factory-bootstrap-406 .modal-backdrop.fade,.factory-bootstrap-406-modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.factory-bootstrap-406 .modal-backdrop.in,.factory-bootstrap-406-modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-406 .modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.factory-bootstrap-406 .modal-header .close{margin-top:-2px}.factory-bootstrap-406 .modal-title{margin:0;line-height:1.428571429}.factory-bootstrap-406 .modal-body{position:relative;padding:20px;max-height:none}.factory-bootstrap-406 .modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.factory-bootstrap-406 .modal-footer:after,.factory-bootstrap-406 .modal-footer:before{display:table;content:" "}.factory-bootstrap-406 .modal-footer:after{clear:both}.factory-bootstrap-406 .modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.factory-bootstrap-406 .modal-footer .btn-group .btn+.btn{margin-left:-1px}.factory-bootstrap-406 .modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.factory-bootstrap-406 .modal-dialog{width:600px;margin:30px auto}.factory-bootstrap-406 .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}}.factory-bootstrap-406 .tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.factory-bootstrap-406 .tooltip.in{opacity:.9;filter:alpha(opacity=90)}.factory-bootstrap-406 .tooltip.top{padding:5px 0;margin-top:-3px}.factory-bootstrap-406 .tooltip.right{padding:0 5px;margin-left:3px}.factory-bootstrap-406 .tooltip.bottom{padding:5px 0;margin-top:3px}.factory-bootstrap-406 .tooltip.left{padding:0 5px;margin-left:-3px}.factory-bootstrap-406 .tooltip-inner{width:400px;padding:15px 20px;color:#fff;text-align:left;text-decoration:none;background-color:#673ab7;border-radius:3px}.factory-bootstrap-406 .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.factory-bootstrap-406 .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-406 .tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-406 .tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#673ab7;border-width:5px 5px 0}.factory-bootstrap-406 .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#673ab7;border-width:5px 5px 5px 0}.factory-bootstrap-406 .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#673ab7;border-width:5px 0 5px 5px}.factory-bootstrap-406 .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-406 .tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-406 .tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#673ab7;border-width:0 5px 5px}.factory-bootstrap-406 .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);background-clip:padding-box}.factory-bootstrap-406 .popover.top{margin-top:-10px}.factory-bootstrap-406 .popover.right{margin-left:10px}.factory-bootstrap-406 .popover.bottom{margin-top:10px}.factory-bootstrap-406 .popover.left{margin-left:-10px}.factory-bootstrap-406 .popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.factory-bootstrap-406 .popover-content{padding:9px 14px}.factory-bootstrap-406 .popover .arrow,.factory-bootstrap-406 .popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.factory-bootstrap-406 .popover .arrow{border-width:11px}.factory-bootstrap-406 .popover .arrow:after{border-width:10px;content:""}.factory-bootstrap-406 .popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.factory-bootstrap-406 .popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.factory-bootstrap-406 .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.factory-bootstrap-406 .popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.factory-bootstrap-406 .popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);border-top-width:0}.factory-bootstrap-406 .popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.factory-bootstrap-406 .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,.25);border-right-width:0}.factory-bootstrap-406 .popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.factory-bootstrap-406 .carousel{position:relative}.factory-bootstrap-406 .carousel-inner{position:relative;width:100%;overflow:hidden}.factory-bootstrap-406 .carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.factory-bootstrap-406 .carousel-inner>.item>a>img,.factory-bootstrap-406 .carousel-inner>.item>img{display:block;height:auto;max-width:100%;line-height:1}.factory-bootstrap-406 .carousel-inner>.active,.factory-bootstrap-406 .carousel-inner>.next,.factory-bootstrap-406 .carousel-inner>.prev{display:block}.factory-bootstrap-406 .carousel-inner>.active{left:0}.factory-bootstrap-406 .carousel-inner>.next,.factory-bootstrap-406 .carousel-inner>.prev{position:absolute;top:0;width:100%}.factory-bootstrap-406 .carousel-inner>.next{left:100%}.factory-bootstrap-406 .carousel-inner>.prev{left:-100%}.factory-bootstrap-406 .carousel-inner>.next.left,.factory-bootstrap-406 .carousel-inner>.prev.right{left:0}.factory-bootstrap-406 .carousel-inner>.active.left{left:-100%}.factory-bootstrap-406 .carousel-inner>.active.right{left:100%}.factory-bootstrap-406 .carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);opacity:.5;filter:alpha(opacity=50)}.factory-bootstrap-406 .carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.factory-bootstrap-406 .carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.factory-bootstrap-406 .carousel-control:focus,.factory-bootstrap-406 .carousel-control:hover{color:#fff;text-decoration:none;outline:0;opacity:.9;filter:alpha(opacity=90)}.factory-bootstrap-406 .carousel-control .glyphicon-chevron-left,.factory-bootstrap-406 .carousel-control .glyphicon-chevron-right,.factory-bootstrap-406 .carousel-control .icon-next,.factory-bootstrap-406 .carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.factory-bootstrap-406 .carousel-control .glyphicon-chevron-left,.factory-bootstrap-406 .carousel-control .icon-prev{left:50%}.factory-bootstrap-406 .carousel-control .glyphicon-chevron-right,.factory-bootstrap-406 .carousel-control .icon-next{right:50%}.factory-bootstrap-406 .carousel-control .icon-next,.factory-bootstrap-406 .carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.factory-bootstrap-406 .carousel-control .icon-prev:before{content:'\2039'}.factory-bootstrap-406 .carousel-control .icon-next:before{content:'\203a'}.factory-bootstrap-406 .carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.factory-bootstrap-406 .carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.factory-bootstrap-406 .carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.factory-bootstrap-406 .carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.factory-bootstrap-406 .carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.factory-bootstrap-406 .clearfix:after,.factory-bootstrap-406 .clearfix:before{display:table;content:" "}.factory-bootstrap-406 .clearfix:after{clear:both}.factory-bootstrap-406 .center-block{display:block;margin-right:auto;margin-left:auto}.factory-bootstrap-406 .pull-right{float:right!important}.factory-bootstrap-406 .pull-left{float:left!important}.factory-bootstrap-406 .hide{display:none!important}.factory-bootstrap-406 .show{display:block!important}.factory-bootstrap-406 .invisible{visibility:hidden}.factory-bootstrap-406 .text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.factory-bootstrap-406 .hidden{display:none!important;visibility:hidden!important}.factory-bootstrap-406 .affix{position:fixed}@-ms-viewport{width:device-width}.factory-bootstrap-406 .visible-lg,.factory-bootstrap-406 .visible-md,.factory-bootstrap-406 .visible-sm,.factory-bootstrap-406 .visible-xs,.factory-bootstrap-406 td.visible-lg,.factory-bootstrap-406 td.visible-md,.factory-bootstrap-406 td.visible-sm,.factory-bootstrap-406 td.visible-xs,.factory-bootstrap-406 th.visible-lg,.factory-bootstrap-406 th.visible-md,.factory-bootstrap-406 th.visible-sm,.factory-bootstrap-406 th.visible-xs,.factory-bootstrap-406 tr.visible-lg,.factory-bootstrap-406 tr.visible-md,.factory-bootstrap-406 tr.visible-sm,.factory-bootstrap-406 tr.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}table.visible-xs.visible-sm{display:table}tr.visible-xs.visible-sm{display:table-row!important}td.visible-xs.visible-sm,th.visible-xs.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}table.visible-xs.visible-md{display:table}tr.visible-xs.visible-md{display:table-row!important}td.visible-xs.visible-md,th.visible-xs.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-xs.visible-lg{display:block!important}table.visible-xs.visible-lg{display:table}tr.visible-xs.visible-lg{display:table-row!important}td.visible-xs.visible-lg,th.visible-xs.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-sm.visible-xs{display:block!important}table.visible-sm.visible-xs{display:table}tr.visible-sm.visible-xs{display:table-row!important}td.visible-sm.visible-xs,th.visible-sm.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}table.visible-sm.visible-md{display:table}tr.visible-sm.visible-md{display:table-row!important}td.visible-sm.visible-md,th.visible-sm.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-sm.visible-lg{display:block!important}table.visible-sm.visible-lg{display:table}tr.visible-sm.visible-lg{display:table-row!important}td.visible-sm.visible-lg,th.visible-sm.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-md.visible-xs{display:block!important}table.visible-md.visible-xs{display:table}tr.visible-md.visible-xs{display:table-row!important}td.visible-md.visible-xs,th.visible-md.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}table.visible-md.visible-sm{display:table}tr.visible-md.visible-sm{display:table-row!important}td.visible-md.visible-sm,th.visible-md.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-md.visible-lg{display:block!important}table.visible-md.visible-lg{display:table}tr.visible-md.visible-lg{display:table-row!important}td.visible-md.visible-lg,th.visible-md.visible-lg{display:table-cell!important}}@media (max-width:767px){.visible-lg.visible-xs{display:block!important}table.visible-lg.visible-xs{display:table}tr.visible-lg.visible-xs{display:table-row!important}td.visible-lg.visible-xs,th.visible-lg.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}table.visible-lg.visible-sm{display:table}tr.visible-lg.visible-sm{display:table-row!important}td.visible-lg.visible-sm,th.visible-lg.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}table.visible-lg.visible-md{display:table}tr.visible-lg.visible-md{display:table-row!important}td.visible-lg.visible-md,th.visible-lg.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}.factory-bootstrap-406 .hidden-xs{display:block!important}.factory-bootstrap-406 table.hidden-xs{display:table}.factory-bootstrap-406 tr.hidden-xs{display:table-row!important}.factory-bootstrap-406 td.hidden-xs,.factory-bootstrap-406 th.hidden-xs{display:table-cell!important}@media (max-width:767px){.hidden-xs,td.hidden-xs,th.hidden-xs,tr.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,td.hidden-xs.hidden-md,th.hidden-xs.hidden-md,tr.hidden-xs.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg{display:none!important}}.factory-bootstrap-406 .hidden-sm{display:block!important}.factory-bootstrap-406 table.hidden-sm{display:table}.factory-bootstrap-406 tr.hidden-sm{display:table-row!important}.factory-bootstrap-406 td.hidden-sm,.factory-bootstrap-406 th.hidden-sm{display:table-cell!important}@media (max-width:767px){.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,td.hidden-sm,th.hidden-sm,tr.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,td.hidden-sm.hidden-md,th.hidden-sm.hidden-md,tr.hidden-sm.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg{display:none!important}}.factory-bootstrap-406 .hidden-md{display:block!important}.factory-bootstrap-406 table.hidden-md{display:table}.factory-bootstrap-406 tr.hidden-md{display:table-row!important}.factory-bootstrap-406 td.hidden-md,.factory-bootstrap-406 th.hidden-md{display:table-cell!important}@media (max-width:767px){.hidden-md.hidden-xs,td.hidden-md.hidden-xs,th.hidden-md.hidden-xs,tr.hidden-md.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,td.hidden-md.hidden-sm,th.hidden-md.hidden-sm,tr.hidden-md.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,td.hidden-md,th.hidden-md,tr.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-md.hidden-lg,td.hidden-md.hidden-lg,th.hidden-md.hidden-lg,tr.hidden-md.hidden-lg{display:none!important}}.factory-bootstrap-406 .hidden-lg{display:block!important}.factory-bootstrap-406 table.hidden-lg{display:table}.factory-bootstrap-406 tr.hidden-lg{display:table-row!important}.factory-bootstrap-406 td.hidden-lg,.factory-bootstrap-406 th.hidden-lg{display:table-cell!important}@media (max-width:767px){.factory-bootstrap-406 .hidden-lg.hidden-xs,.factory-bootstrap-406 td.hidden-lg.hidden-xs,.factory-bootstrap-406 th.hidden-lg.hidden-xs,.factory-bootstrap-406 tr.hidden-lg.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.factory-bootstrap-406 .hidden-lg.hidden-sm,.factory-bootstrap-406 td.hidden-lg.hidden-sm,.factory-bootstrap-406 th.hidden-lg.hidden-sm,.factory-bootstrap-406 tr.hidden-lg.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.factory-bootstrap-406 .hidden-lg.hidden-md,.factory-bootstrap-406 td.hidden-lg.hidden-md,.factory-bootstrap-406 th.hidden-lg.hidden-md,.factory-bootstrap-406 tr.hidden-lg.hidden-md{display:none!important}}@media (min-width:1200px){.factory-bootstrap-406 .hidden-lg,.factory-bootstrap-406 td.hidden-lg,.factory-bootstrap-406 th.hidden-lg,.factory-bootstrap-406 tr.hidden-lg{display:none!important}}.factory-bootstrap-406 .visible-print,.factory-bootstrap-406 td.visible-print,.factory-bootstrap-406 th.visible-print,.factory-bootstrap-406 tr.visible-print{display:none!important}@media print{.factory-bootstrap-406 .visible-print{display:block!important}.factory-bootstrap-406 table.visible-print{display:table}.factory-bootstrap-406 tr.visible-print{display:table-row!important}.factory-bootstrap-406 td.visible-print,.factory-bootstrap-406 th.visible-print{display:table-cell!important}.factory-bootstrap-406 .hidden-print,.factory-bootstrap-406 td.hidden-print,.factory-bootstrap-406 th.hidden-print,.factory-bootstrap-406 tr.hidden-print{display:none!important}}/*!
12
+ * Factory Default Bootstrap Theme
13
+ *
14
+ * The code is based on Bootstrap v2.1.1
15
+ *
16
+ * Bootstrap v3.0.3 (http://getbootstrap.com)
17
+ * Copyright 2013 Twitter, Inc.
18
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
19
+ *
20
+ * @author Paul Kashtanoff <paul@byonepress.com>
21
+ * @copyright (c) 2013, OnePress Ltd
22
+ *
23
+ * @package factory-bootstrap
24
+ * @since 1.0.0
25
+ */.factory-bootstrap-406 .btn-danger,.factory-bootstrap-406 .btn-default,.factory-bootstrap-406 .btn-info,.factory-bootstrap-406 .btn-primary,.factory-bootstrap-406 .btn-success,.factory-bootstrap-406 .btn-warning{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.factory-bootstrap-406 .btn-danger.active,.factory-bootstrap-406 .btn-danger:active,.factory-bootstrap-406 .btn-default.active,.factory-bootstrap-406 .btn-default:active,.factory-bootstrap-406 .btn-info.active,.factory-bootstrap-406 .btn-info:active,.factory-bootstrap-406 .btn-primary.active,.factory-bootstrap-406 .btn-primary:active,.factory-bootstrap-406 .btn-success.active,.factory-bootstrap-406 .btn-success:active,.factory-bootstrap-406 .btn-warning.active,.factory-bootstrap-406 .btn-warning:active{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.1);box-shadow:inset 0 1px 1px rgba(0,0,0,.1)}.factory-bootstrap-406 .btn.active,.factory-bootstrap-406 .btn:active{background-image:none}.factory-bootstrap-406 .btn-default{color:#555;border-color:#ccc;background:#f7f7f7;-webkit-box-shadow:inset 0 1px 0 #fff,0 1px 0 rgba(0,0,0,.08);box-shadow:inset 0 1px 0 #fff,0 1px 0 rgba(0,0,0,.08);vertical-align:top}.factory-bootstrap-406 .btn-default.active,.factory-bootstrap-406 .btn-default:active{background-color:#fff;border-color:#dbdbdb}.factory-bootstrap-406 .btn-gold{font-weight:700;padding:7px 12px;cursor:pointer;line-height:16px;display:inline-block;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;box-shadow:#e3e3e3 0 1px 1px;-moz-box-shadow:0 1px 1px rgba(000,000,000,.1),inset 0 1px 1px rgba(255,255,255,.7);-webkit-box-shadow:0 1px 1px rgba(000,000,000,.1),inset 0 1px 1px rgba(255,255,255,.7);text-shadow:1px 1px 0 #ffe8b2;color:#7c5d1b;border:1px solid #d6a437;background:#feeb80}.factory-bootstrap-406 .btn-gold:focus,.factory-bootstrap-406 .btn-gold:hover{background:#fef0a1}.factory-bootstrap-406 .btn-gold.active,.factory-bootstrap-406 .btn-gold:active{background:#fef0a1;-webkit-box-shadow:inset 0 3px 8px 0 #f8ba36;box-shadow:inset 0 3px 8px 0 #f8ba36}.factory-bootstrap-406 .btn-primary{background:#2ea2cc;border-color:#0074a2;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.5),0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 rgba(120,200,230,.5),0 1px 0 rgba(0,0,0,.15);color:#fff;text-decoration:none}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#1e8cbe;border-color:#0074a2;-webkit-box-shadow:inset 0 1px 0 rgba(120,200,230,.6);box-shadow:inset 0 1px 0 rgba(120,200,230,.6);color:#fff}.factory-bootstrap-406 .btn-primary.active,.factory-bootstrap-406 .btn-primary:active{background-color:#2d6ca2;border-color:#2b669a}.factory-bootstrap-406 .btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-406 .btn-success:focus,.factory-bootstrap-406 .btn-success:hover{background-color:#419641;background-position:0 -15px}.factory-bootstrap-406 .btn-success.active,.factory-bootstrap-406 .btn-success:active{background-color:#419641;border-color:#3e8f3e}.factory-bootstrap-406 .btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-406 .btn-warning:focus,.factory-bootstrap-406 .btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.factory-bootstrap-406 .btn-warning.active,.factory-bootstrap-406 .btn-warning:active{background-color:#eb9316;border-color:#e38d13}.factory-bootstrap-406 .btn-danger{color:#fff;background:#d9534f;border-color:#d43f3a}.factory-bootstrap-406 .btn-danger.active,.factory-bootstrap-406 .btn-danger:active,.factory-bootstrap-406 .btn-danger:focus,.factory-bootstrap-406 .btn-danger:hover,.factory-bootstrap-406 .open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.factory-bootstrap-406 .btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-406 .btn-info:focus,.factory-bootstrap-406 .btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.factory-bootstrap-406 .btn-info.active,.factory-bootstrap-406 .btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.factory-bootstrap-406 .img-thumbnail,.factory-bootstrap-406 .thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.factory-bootstrap-406 .dropdown-menu>li>a:focus,.factory-bootstrap-406 .dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.factory-bootstrap-406 .dropdown-menu>.active>a,.factory-bootstrap-406 .dropdown-menu>.active>a:focus,.factory-bootstrap-406 .dropdown-menu>.active>a:hover{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.factory-bootstrap-406 .navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.factory-bootstrap-406 .navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.factory-bootstrap-406 .navbar-brand,.factory-bootstrap-406 .navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.factory-bootstrap-406 .navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.factory-bootstrap-406 .navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.factory-bootstrap-406 .navbar-inverse .navbar-brand,.factory-bootstrap-406 .navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.factory-bootstrap-406 .navbar-fixed-bottom,.factory-bootstrap-406 .navbar-fixed-top,.factory-bootstrap-406 .navbar-static-top{border-radius:0}.factory-bootstrap-406 .alert{-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.factory-bootstrap-406 .alert .actions{padding-top:10px}.factory-bootstrap-406 .alert-success{color:#3c763d;background-color:#dff0d8;border-bottom:2px solid #c8e5bc}.factory-bootstrap-406 .alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0)}.factory-bootstrap-406 .alert{text-shadow:none;box-shadow:none;margin:0;margin-top:10px;margin-bottom:10px;padding:10px}.factory-bootstrap-406 .alert-normal,.factory-bootstrap-406 .alert-warning{background:#fcf8e3;color:#8a6d3b;border:1px solid #b8823b}.factory-bootstrap-406 .alert-danger{background:#cf4944;color:#fff;border-bottom:2px solid #b23e3a}.factory-bootstrap-406 .alert-danger a:not(.btn),.factory-bootstrap-406 .alert-error a:not(.btn){color:#fff}.factory-bootstrap-406 .progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.factory-bootstrap-406 .progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.factory-bootstrap-406 .progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.factory-bootstrap-406 .progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.factory-bootstrap-406 .progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.factory-bootstrap-406 .progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.factory-bootstrap-406 .list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.factory-bootstrap-406 .list-group-item.active,.factory-bootstrap-406 .list-group-item.active:focus,.factory-bootstrap-406 .list-group-item.active:hover{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0)}.factory-bootstrap-406 .panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.factory-bootstrap-406 .panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.factory-bootstrap-406 .panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.factory-bootstrap-406 .panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.factory-bootstrap-406 .panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.factory-bootstrap-406 .panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.factory-bootstrap-406 .panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.factory-bootstrap-406 .well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}.factory-bootstrap-406 .factory-after{margin-left:7px;display:inline-block}.factory-bootstrap-406 .factory-hidden{display:none}.factory-bootstrap-406 .factory-ajax-loader{width:25px;height:25px;background:url(../assets/images/loader-sm-tr.gif)}.factory-control-error{background-color:rgba(0,0,0,.8);white-space:normal;z-index:10;font-weight:400;line-height:150%;border-radius:4px;color:#fff;font-size:13px;margin-top:5px;padding:4px 10px 3px;max-width:500px;display:inline-block}.factory-control-error i{margin:0 7px 0 1px}
libs/factory/bootstrap/assets/css-min/bootstrap.datepicker.min.css ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ /*!
12
+ * Datepicker for Bootstrap v1.5.0-dev (https://github.com/eternicode/bootstrap-datepicker)
13
+ *
14
+ * Copyright 2012 Stefan Petre
15
+ * Improvements by Andrew Rowls
16
+ * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
17
+ */.datepicker{border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker.datepicker-rtl{direction:rtl}.datepicker.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-top:0;border-bottom-color:rgba(0,0,0,.2);position:absolute}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:before{left:6px}.datepicker-dropdown.datepicker-orient-left:after{left:7px}.datepicker-dropdown.datepicker-orient-right:before{right:6px}.datepicker-dropdown.datepicker-orient-right:after{right:7px}.datepicker-dropdown.datepicker-orient-top:before{top:-7px}.datepicker-dropdown.datepicker-orient-top:after{top:-6px}.datepicker-dropdown.datepicker-orient-bottom:before{bottom:-7px;border-bottom:0;border-top:7px solid #999}.datepicker-dropdown.datepicker-orient-bottom:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff}.datepicker>div{display:none}.datepicker.days .datepicker-days,.datepicker.months .datepicker-months,.datepicker.years .datepicker-years{display:block}.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker table tr td,.datepicker table tr th{text-align:center;width:30px;height:30px;border-radius:4px;border:0}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day.focused,.datepicker table tr td.day:hover{background:#eee;cursor:pointer}.datepicker table tr td.new,.datepicker table tr td.old{color:#999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td.today,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today:hover{color:#000;background-color:#ffdb99;border-color:#ffb733}.datepicker table tr td.today.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:focus,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.disabled:hover:focus,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today:active,.datepicker table tr td.today:focus,.datepicker table tr td.today:hover,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover:active,.datepicker table tr td.today:hover:focus,.datepicker table tr td.today:hover:hover,.open .dropdown-toggle.datepicker table tr td.today,.open .dropdown-toggle.datepicker table tr td.today.disabled,.open .dropdown-toggle.datepicker table tr td.today.disabled:hover,.open .dropdown-toggle.datepicker table tr td.today:hover{color:#000;background-color:#ffcd70;border-color:#f59e00}.datepicker table tr td.today.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today:active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover:active,.open .dropdown-toggle.datepicker table tr td.today,.open .dropdown-toggle.datepicker table tr td.today.disabled,.open .dropdown-toggle.datepicker table tr td.today.disabled:hover,.open .dropdown-toggle.datepicker table tr td.today:hover{background-image:none}.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled.disabled.active,.datepicker table tr td.today.disabled.disabled:active,.datepicker table tr td.today.disabled.disabled:focus,.datepicker table tr td.today.disabled.disabled:hover,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:focus,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today.disabled:hover.disabled.active,.datepicker table tr td.today.disabled:hover.disabled:active,.datepicker table tr td.today.disabled:hover.disabled:focus,.datepicker table tr td.today.disabled:hover.disabled:hover,.datepicker table tr td.today.disabled:hover[disabled],.datepicker table tr td.today.disabled:hover[disabled].active,.datepicker table tr td.today.disabled:hover[disabled]:active,.datepicker table tr td.today.disabled:hover[disabled]:focus,.datepicker table tr td.today.disabled:hover[disabled]:hover,.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today.disabled[disabled].active,.datepicker table tr td.today.disabled[disabled]:active,.datepicker table tr td.today.disabled[disabled]:focus,.datepicker table tr td.today.disabled[disabled]:hover,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today:hover.disabled.active,.datepicker table tr td.today:hover.disabled:active,.datepicker table tr td.today:hover.disabled:focus,.datepicker table tr td.today:hover.disabled:hover,.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today:hover[disabled].active,.datepicker table tr td.today:hover[disabled]:active,.datepicker table tr td.today:hover[disabled]:focus,.datepicker table tr td.today:hover[disabled]:hover,.datepicker table tr td.today[disabled],.datepicker table tr td.today[disabled].active,.datepicker table tr td.today[disabled]:active,.datepicker table tr td.today[disabled]:focus,.datepicker table tr td.today[disabled]:hover,fieldset[disabled] .datepicker table tr td.today,fieldset[disabled] .datepicker table tr td.today.active,fieldset[disabled] .datepicker table tr td.today.disabled,fieldset[disabled] .datepicker table tr td.today.disabled.active,fieldset[disabled] .datepicker table tr td.today.disabled:active,fieldset[disabled] .datepicker table tr td.today.disabled:focus,fieldset[disabled] .datepicker table tr td.today.disabled:hover,fieldset[disabled] .datepicker table tr td.today.disabled:hover.active,fieldset[disabled] .datepicker table tr td.today.disabled:hover:active,fieldset[disabled] .datepicker table tr td.today.disabled:hover:focus,fieldset[disabled] .datepicker table tr td.today.disabled:hover:hover,fieldset[disabled] .datepicker table tr td.today:active,fieldset[disabled] .datepicker table tr td.today:focus,fieldset[disabled] .datepicker table tr td.today:hover,fieldset[disabled] .datepicker table tr td.today:hover.active,fieldset[disabled] .datepicker table tr td.today:hover:active,fieldset[disabled] .datepicker table tr td.today:hover:focus,fieldset[disabled] .datepicker table tr td.today:hover:hover{background-color:#ffdb99;border-color:#ffb733}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover,.datepicker table tr td.range:hover{background:#eee;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today:hover{color:#000;background-color:#f7ca77;border-color:#f1a417;border-radius:0}.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:focus,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.disabled:hover:focus,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:focus,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today:hover:focus,.datepicker table tr td.range.today:hover:hover,.open .dropdown-toggle.datepicker table tr td.range.today,.open .dropdown-toggle.datepicker table tr td.range.today.disabled,.open .dropdown-toggle.datepicker table tr td.range.today.disabled:hover,.open .dropdown-toggle.datepicker table tr td.range.today:hover{color:#000;background-color:#f4bb51;border-color:#bf800c}.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover:active,.open .dropdown-toggle.datepicker table tr td.range.today,.open .dropdown-toggle.datepicker table tr td.range.today.disabled,.open .dropdown-toggle.datepicker table tr td.range.today.disabled:hover,.open .dropdown-toggle.datepicker table tr td.range.today:hover{background-image:none}.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled.disabled.active,.datepicker table tr td.range.today.disabled.disabled:active,.datepicker table tr td.range.today.disabled.disabled:focus,.datepicker table tr td.range.today.disabled.disabled:hover,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:focus,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today.disabled:hover.disabled.active,.datepicker table tr td.range.today.disabled:hover.disabled:active,.datepicker table tr td.range.today.disabled:hover.disabled:focus,.datepicker table tr td.range.today.disabled:hover.disabled:hover,.datepicker table tr td.range.today.disabled:hover[disabled],.datepicker table tr td.range.today.disabled:hover[disabled].active,.datepicker table tr td.range.today.disabled:hover[disabled]:active,.datepicker table tr td.range.today.disabled:hover[disabled]:focus,.datepicker table tr td.range.today.disabled:hover[disabled]:hover,.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today.disabled[disabled].active,.datepicker table tr td.range.today.disabled[disabled]:active,.datepicker table tr td.range.today.disabled[disabled]:focus,.datepicker table tr td.range.today.disabled[disabled]:hover,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today:hover.disabled.active,.datepicker table tr td.range.today:hover.disabled:active,.datepicker table tr td.range.today:hover.disabled:focus,.datepicker table tr td.range.today:hover.disabled:hover,.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today:hover[disabled].active,.datepicker table tr td.range.today:hover[disabled]:active,.datepicker table tr td.range.today:hover[disabled]:focus,.datepicker table tr td.range.today:hover[disabled]:hover,.datepicker table tr td.range.today[disabled],.datepicker table tr td.range.today[disabled].active,.datepicker table tr td.range.today[disabled]:active,.datepicker table tr td.range.today[disabled]:focus,.datepicker table tr td.range.today[disabled]:hover,fieldset[disabled] .datepicker table tr td.range.today,fieldset[disabled] .datepicker table tr td.range.today.active,fieldset[disabled] .datepicker table tr td.range.today.disabled,fieldset[disabled] .datepicker table tr td.range.today.disabled.active,fieldset[disabled] .datepicker table tr td.range.today.disabled:active,fieldset[disabled] .datepicker table tr td.range.today.disabled:focus,fieldset[disabled] .datepicker table tr td.range.today.disabled:hover,fieldset[disabled] .datepicker table tr td.range.today.disabled:hover.active,fieldset[disabled] .datepicker table tr td.range.today.disabled:hover:active,fieldset[disabled] .datepicker table tr td.range.today.disabled:hover:focus,fieldset[disabled] .datepicker table tr td.range.today.disabled:hover:hover,fieldset[disabled] .datepicker table tr td.range.today:active,fieldset[disabled] .datepicker table tr td.range.today:focus,fieldset[disabled] .datepicker table tr td.range.today:hover,fieldset[disabled] .datepicker table tr td.range.today:hover.active,fieldset[disabled] .datepicker table tr td.range.today:hover:active,fieldset[disabled] .datepicker table tr td.range.today:hover:focus,fieldset[disabled] .datepicker table tr td.range.today:hover:hover{background-color:#f7ca77;border-color:#f1a417}.datepicker table tr td.selected,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected:hover{color:#fff;background-color:#999;border-color:#555;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:focus,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.disabled:hover:focus,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected:active,.datepicker table tr td.selected:focus,.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected:hover:focus,.datepicker table tr td.selected:hover:hover,.open .dropdown-toggle.datepicker table tr td.selected,.open .dropdown-toggle.datepicker table tr td.selected.disabled,.open .dropdown-toggle.datepicker table tr td.selected.disabled:hover,.open .dropdown-toggle.datepicker table tr td.selected:hover{color:#fff;background-color:#858585;border-color:#373737}.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover:active,.open .dropdown-toggle.datepicker table tr td.selected,.open .dropdown-toggle.datepicker table tr td.selected.disabled,.open .dropdown-toggle.datepicker table tr td.selected.disabled:hover,.open .dropdown-toggle.datepicker table tr td.selected:hover{background-image:none}.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled.disabled.active,.datepicker table tr td.selected.disabled.disabled:active,.datepicker table tr td.selected.disabled.disabled:focus,.datepicker table tr td.selected.disabled.disabled:hover,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:focus,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected.disabled:hover.disabled.active,.datepicker table tr td.selected.disabled:hover.disabled:active,.datepicker table tr td.selected.disabled:hover.disabled:focus,.datepicker table tr td.selected.disabled:hover.disabled:hover,.datepicker table tr td.selected.disabled:hover[disabled],.datepicker table tr td.selected.disabled:hover[disabled].active,.datepicker table tr td.selected.disabled:hover[disabled]:active,.datepicker table tr td.selected.disabled:hover[disabled]:focus,.datepicker table tr td.selected.disabled:hover[disabled]:hover,.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected.disabled[disabled].active,.datepicker table tr td.selected.disabled[disabled]:active,.datepicker table tr td.selected.disabled[disabled]:focus,.datepicker table tr td.selected.disabled[disabled]:hover,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected:hover.disabled.active,.datepicker table tr td.selected:hover.disabled:active,.datepicker table tr td.selected:hover.disabled:focus,.datepicker table tr td.selected:hover.disabled:hover,.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected:hover[disabled].active,.datepicker table tr td.selected:hover[disabled]:active,.datepicker table tr td.selected:hover[disabled]:focus,.datepicker table tr td.selected:hover[disabled]:hover,.datepicker table tr td.selected[disabled],.datepicker table tr td.selected[disabled].active,.datepicker table tr td.selected[disabled]:active,.datepicker table tr td.selected[disabled]:focus,.datepicker table tr td.selected[disabled]:hover,fieldset[disabled] .datepicker table tr td.selected,fieldset[disabled] .datepicker table tr td.selected.active,fieldset[disabled] .datepicker table tr td.selected.disabled,fieldset[disabled] .datepicker table tr td.selected.disabled.active,fieldset[disabled] .datepicker table tr td.selected.disabled:active,fieldset[disabled] .datepicker table tr td.selected.disabled:focus,fieldset[disabled] .datepicker table tr td.selected.disabled:hover,fieldset[disabled] .datepicker table tr td.selected.disabled:hover.active,fieldset[disabled] .datepicker table tr td.selected.disabled:hover:active,fieldset[disabled] .datepicker table tr td.selected.disabled:hover:focus,fieldset[disabled] .datepicker table tr td.selected.disabled:hover:hover,fieldset[disabled] .datepicker table tr td.selected:active,fieldset[disabled] .datepicker table tr td.selected:focus,fieldset[disabled] .datepicker table tr td.selected:hover,fieldset[disabled] .datepicker table tr td.selected:hover.active,fieldset[disabled] .datepicker table tr td.selected:hover:active,fieldset[disabled] .datepicker table tr td.selected:hover:focus,fieldset[disabled] .datepicker table tr td.selected:hover:hover{background-color:#999;border-color:#555}.datepicker table tr td.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active:hover{color:#fff;background-color:#428bca;border-color:#357ebd;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.active.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:focus,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.disabled:hover:focus,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active:active,.datepicker table tr td.active:focus,.datepicker table tr td.active:hover,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover:active,.datepicker table tr td.active:hover:focus,.datepicker table tr td.active:hover:hover,.open .dropdown-toggle.datepicker table tr td.active,.open .dropdown-toggle.datepicker table tr td.active.disabled,.open .dropdown-toggle.datepicker table tr td.active.disabled:hover,.open .dropdown-toggle.datepicker table tr td.active:hover{color:#fff;background-color:#3276b1;border-color:#285e8e}.datepicker table tr td.active.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active:active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover:active,.open .dropdown-toggle.datepicker table tr td.active,.open .dropdown-toggle.datepicker table tr td.active.disabled,.open .dropdown-toggle.datepicker table tr td.active.disabled:hover,.open .dropdown-toggle.datepicker table tr td.active:hover{background-image:none}.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled.disabled.active,.datepicker table tr td.active.disabled.disabled:active,.datepicker table tr td.active.disabled.disabled:focus,.datepicker table tr td.active.disabled.disabled:hover,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:focus,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active.disabled:hover.disabled.active,.datepicker table tr td.active.disabled:hover.disabled:active,.datepicker table tr td.active.disabled:hover.disabled:focus,.datepicker table tr td.active.disabled:hover.disabled:hover,.datepicker table tr td.active.disabled:hover[disabled],.datepicker table tr td.active.disabled:hover[disabled].active,.datepicker table tr td.active.disabled:hover[disabled]:active,.datepicker table tr td.active.disabled:hover[disabled]:focus,.datepicker table tr td.active.disabled:hover[disabled]:hover,.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active.disabled[disabled].active,.datepicker table tr td.active.disabled[disabled]:active,.datepicker table tr td.active.disabled[disabled]:focus,.datepicker table tr td.active.disabled[disabled]:hover,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active:hover.disabled.active,.datepicker table tr td.active:hover.disabled:active,.datepicker table tr td.active:hover.disabled:focus,.datepicker table tr td.active:hover.disabled:hover,.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active:hover[disabled].active,.datepicker table tr td.active:hover[disabled]:active,.datepicker table tr td.active:hover[disabled]:focus,.datepicker table tr td.active:hover[disabled]:hover,.datepicker table tr td.active[disabled],.datepicker table tr td.active[disabled].active,.datepicker table tr td.active[disabled]:active,.datepicker table tr td.active[disabled]:focus,.datepicker table tr td.active[disabled]:hover,fieldset[disabled] .datepicker table tr td.active,fieldset[disabled] .datepicker table tr td.active.active,fieldset[disabled] .datepicker table tr td.active.disabled,fieldset[disabled] .datepicker table tr td.active.disabled.active,fieldset[disabled] .datepicker table tr td.active.disabled:active,fieldset[disabled] .datepicker table tr td.active.disabled:focus,fieldset[disabled] .datepicker table tr td.active.disabled:hover,fieldset[disabled] .datepicker table tr td.active.disabled:hover.active,fieldset[disabled] .datepicker table tr td.active.disabled:hover:active,fieldset[disabled] .datepicker table tr td.active.disabled:hover:focus,fieldset[disabled] .datepicker table tr td.active.disabled:hover:hover,fieldset[disabled] .datepicker table tr td.active:active,fieldset[disabled] .datepicker table tr td.active:focus,fieldset[disabled] .datepicker table tr td.active:hover,fieldset[disabled] .datepicker table tr td.active:hover.active,fieldset[disabled] .datepicker table tr td.active:hover:active,fieldset[disabled] .datepicker table tr td.active:hover:focus,fieldset[disabled] .datepicker table tr td.active:hover:hover{background-color:#428bca;border-color:#357ebd}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;border-radius:4px}.datepicker table tr td span:hover{background:#eee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active:hover{color:#fff;background-color:#428bca;border-color:#357ebd;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:focus,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.disabled:hover:focus,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active:active,.datepicker table tr td span.active:focus,.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active:hover:focus,.datepicker table tr td span.active:hover:hover,.open .dropdown-toggle.datepicker table tr td span.active,.open .dropdown-toggle.datepicker table tr td span.active.disabled,.open .dropdown-toggle.datepicker table tr td span.active.disabled:hover,.open .dropdown-toggle.datepicker table tr td span.active:hover{color:#fff;background-color:#3276b1;border-color:#285e8e}.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover:active,.open .dropdown-toggle.datepicker table tr td span.active,.open .dropdown-toggle.datepicker table tr td span.active.disabled,.open .dropdown-toggle.datepicker table tr td span.active.disabled:hover,.open .dropdown-toggle.datepicker table tr td span.active:hover{background-image:none}.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled.disabled.active,.datepicker table tr td span.active.disabled.disabled:active,.datepicker table tr td span.active.disabled.disabled:focus,.datepicker table tr td span.active.disabled.disabled:hover,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:focus,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active.disabled:hover.disabled.active,.datepicker table tr td span.active.disabled:hover.disabled:active,.datepicker table tr td span.active.disabled:hover.disabled:focus,.datepicker table tr td span.active.disabled:hover.disabled:hover,.datepicker table tr td span.active.disabled:hover[disabled],.datepicker table tr td span.active.disabled:hover[disabled].active,.datepicker table tr td span.active.disabled:hover[disabled]:active,.datepicker table tr td span.active.disabled:hover[disabled]:focus,.datepicker table tr td span.active.disabled:hover[disabled]:hover,.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active.disabled[disabled].active,.datepicker table tr td span.active.disabled[disabled]:active,.datepicker table tr td span.active.disabled[disabled]:focus,.datepicker table tr td span.active.disabled[disabled]:hover,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active:hover.disabled.active,.datepicker table tr td span.active:hover.disabled:active,.datepicker table tr td span.active:hover.disabled:focus,.datepicker table tr td span.active:hover.disabled:hover,.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active:hover[disabled].active,.datepicker table tr td span.active:hover[disabled]:active,.datepicker table tr td span.active:hover[disabled]:focus,.datepicker table tr td span.active:hover[disabled]:hover,.datepicker table tr td span.active[disabled],.datepicker table tr td span.active[disabled].active,.datepicker table tr td span.active[disabled]:active,.datepicker table tr td span.active[disabled]:focus,.datepicker table tr td span.active[disabled]:hover,fieldset[disabled] .datepicker table tr td span.active,fieldset[disabled] .datepicker table tr td span.active.active,fieldset[disabled] .datepicker table tr td span.active.disabled,fieldset[disabled] .datepicker table tr td span.active.disabled.active,fieldset[disabled] .datepicker table tr td span.active.disabled:active,fieldset[disabled] .datepicker table tr td span.active.disabled:focus,fieldset[disabled] .datepicker table tr td span.active.disabled:hover,fieldset[disabled] .datepicker table tr td span.active.disabled:hover.active,fieldset[disabled] .datepicker table tr td span.active.disabled:hover:active,fieldset[disabled] .datepicker table tr td span.active.disabled:hover:focus,fieldset[disabled] .datepicker table tr td span.active.disabled:hover:hover,fieldset[disabled] .datepicker table tr td span.active:active,fieldset[disabled] .datepicker table tr td span.active:focus,fieldset[disabled] .datepicker table tr td span.active:hover,fieldset[disabled] .datepicker table tr td span.active:hover.active,fieldset[disabled] .datepicker table tr td span.active:hover:active,fieldset[disabled] .datepicker table tr td span.active:hover:focus,fieldset[disabled] .datepicker table tr td span.active:hover:hover{background-color:#428bca;border-color:#357ebd}.datepicker table tr td span.new,.datepicker table tr td span.old{color:#999}.datepicker .datepicker-switch{width:145px}.datepicker tfoot tr th,.datepicker thead tr:first-child th{cursor:pointer}.datepicker tfoot tr th:hover,.datepicker thead tr:first-child th:hover{background:#eee}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.datepicker thead tr:first-child .cw{cursor:default;background-color:transparent}.input-group.date .input-group-addon{cursor:pointer}.input-daterange{width:100%}.input-daterange input{text-align:center}.input-daterange input:first-child{border-radius:3px 0 0 3px}.input-daterange input:last-child{border-radius:0 3px 3px 0}.input-daterange .input-group-addon{width:auto;min-width:16px;padding:4px 5px;font-weight:400;line-height:1.42857143;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:solid #ccc;border-width:1px 0;margin-left:-5px;margin-right:-5px}.datepicker.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;color:#333;font-size:13px;line-height:1.42857143}.datepicker.datepicker-inline td,.datepicker.datepicker-inline th,.datepicker.dropdown-menu td,.datepicker.dropdown-menu th{padding:0 5px}
libs/factory/bootstrap/assets/css-min/bootstrap.ectoplasm.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#a3b745;border-color:#839237;color:#fff;-webkit-box-shadow:inset 0 1px 0 #c0cd7b,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #c0cd7b,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#89993a;border-color:#727f30;color:#fff;-webkit-box-shadow:inset 0 1px 0 #b7c669,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #b7c669,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#89993a;border-color:#727f30;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#cfd1c7!important;background:#89993a!important;border-color:#727f30!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#a3b745;border-color:#839237}
libs/factory/bootstrap/assets/css-min/bootstrap.form-group.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .factory-form-group .factory-legend{padding:9px 12px;background-color:#f9f9f9}.factory-bootstrap-406 .factory-form-group .factory-title{font-weight:700;font-size:14px;line-height:14px;color:#555;margin:0}.factory-bootstrap-406 .factory-form-group .factory-hint-icon{display:block;width:16px;height:16px;line-height:13px;padding:0;font-size:11px;text-align:center;position:absolute;top:-5px;right:-3px;color:#fff;background:#E91E63;border-radius:3px}.factory-bootstrap-406 .factory-form-group .factory-hint-icon.factory-hint-icon-green{background:#8bc34a}.factory-bootstrap-406 .factory-form-group .factory-hint-icon.factory-hint-icon-grey{background:#9e9e9e}.factory-bootstrap-406 .factory-form-group .factory-hint-icon.factory-hint-icon-red{background:#E91E63}.factory-bootstrap-406 .factory-form-group .factory-hint{margin:0;font-size:12px;line-height:16px;margin-top:6px}.factory-bootstrap-406 .factory-form-group+.factory-form-group{margin-top:30px}.factory-bootstrap-406 .factory-form-group legend+.control-group{margin-top:0}
libs/factory/bootstrap/assets/css-min/bootstrap.light.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#04a4cc;border-color:#037c9a;color:#fff;-webkit-box-shadow:inset 0 1px 0 #22cffb,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #22cffb,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#0384a4;border-color:#036881;color:#fff;-webkit-box-shadow:inset 0 1px 0 #09cafa,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #09cafa,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#0384a4;border-color:#036881;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#c7cfd1!important;background:#0384a4!important;border-color:#036881!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#04a4cc;border-color:#037c9a}
libs/factory/bootstrap/assets/css-min/bootstrap.midnight.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#e14d43;border-color:#d02a21;color:#fff;-webkit-box-shadow:inset 0 1px 0 #ec8a85,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #ec8a85,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#d92c23;border-color:#ba251e;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8756f,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8756f,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#d92c23;border-color:#ba251e;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#d1c7c7!important;background:#d92c23!important;border-color:#ba251e!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#e14d43;border-color:#d02a21}
libs/factory/bootstrap/assets/css-min/bootstrap.ocean.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#9ebaa0;border-color:#80a583;color:#fff;-webkit-box-shadow:inset 0 1px 0 #cbdacc,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #cbdacc,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#86a988;border-color:#719a74;color:#fff;-webkit-box-shadow:inset 0 1px 0 #bccfbd,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #bccfbd,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#86a988;border-color:#719a74;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#c7d1c8!important;background:#86a988!important;border-color:#719a74!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#9ebaa0;border-color:#80a583}
libs/factory/bootstrap/assets/css-min/bootstrap.separator.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .factory-separator{border-bottom:1px solid #f9f9f9;border-top:1px solid #d1d1d1;margin-bottom:25px}
libs/factory/bootstrap/assets/css-min/bootstrap.sunrise.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .btn-primary{background:#dd823b;border-color:#c36822;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e8ab7c,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e8ab7c,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:focus,.factory-bootstrap-406 .btn-primary:hover{background:#cc6c23;border-color:#ad5c1e;color:#fff;-webkit-box-shadow:inset 0 1px 0 #e59d66,0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 #e59d66,0 1px 0 rgba(0,0,0,.15)}.factory-bootstrap-406 .btn-primary:active{background:#cc6c23;border-color:#ad5c1e;color:#fff;-webkit-box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5);box-shadow:inset 0 2px 5px -3px rgba(0,0,0,.5)}.factory-bootstrap-406 .btn-primary:disabled,.factory-bootstrap-406 .btn-primary[disabled]{color:#d1cbc7!important;background:#cc6c23!important;border-color:#ad5c1e!important;text-shadow:none!important}.factory-bootstrap-406 .btn-group .btn.active.value{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}.factory-bootstrap-406 .pagination>.active>a,.factory-bootstrap-406 .pagination>.active>a:focus,.factory-bootstrap-406 .pagination>.active>a:hover,.factory-bootstrap-406 .pagination>.active>span,.factory-bootstrap-406 .pagination>.active>span:focus,.factory-bootstrap-406 .pagination>.active>span:hover{background-color:#dd823b;border-color:#c36822}
libs/factory/bootstrap/assets/css-min/control.checkbox.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ #side-sortables .factory-bootstrap-406 .factory-buttons-way{float:right;position:relative;top:-25px;left:5px;border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-406 .factory-buttons-way{border:3px solid #f9f9f9;border-radius:4px}.factory-bootstrap-406 .factory-buttons-way button{padding-left:10px;padding-right:10px}.factory-bootstrap-406 .factory-buttons-way .factory-on.active{text-shadow:none;color:#fff;background-color:#33aad5;-webkit-box-shadow:inset 0 1px 1px #0074a2;box-shadow:inset 0 1px 3px #0074a2;border-top:1px solid #0074a2;border-bottom:1px solid #0074a2;border-left:1px solid #0074a2}.factory-bootstrap-406 .factory-checkbox-tumbler-hint{margin-top:5px}.factory-bootstrap-406 .factory-checkbox-tumbler-hint .factory-tumbler-content{display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.admin-color-blue .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.admin-color-coffee .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.admin-color-ectoplasm .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.admin-color-midnight .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.admin-color-ocean .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.admin-color-sunrise .factory-bootstrap-406 .factory-buttons-way .factory-on.active{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}
libs/factory/bootstrap/assets/css-min/control.dropdown.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .fa{margin-right:6px;position:relative}.factory-bootstrap-406 .factory-dropdown.factory-buttons-way{border:0;border-radius:0}.factory-bootstrap-406 .factory-hints .factory-hint{margin-top:5px;display:inline-block;background-color:#ffd;padding:1px 5px}.admin-color-light .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#04a4cc;-webkit-box-shadow:inset 0 1px 2px #037c9a;box-shadow:inset 0 1px 2px #037c9a;border-top:1px solid #037c9a;border-bottom:1px solid #037c9a;border-left:1px solid #037c9a}.admin-color-blue .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#e1a948;-webkit-box-shadow:inset 0 1px 2px #d39323;box-shadow:inset 0 1px 2px #d39323;border-top:1px solid #d39323;border-bottom:1px solid #d39323;border-left:1px solid #d39323}.admin-color-coffee .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#c7a589;-webkit-box-shadow:inset 0 1px 2px #b78a66;box-shadow:inset 0 1px 2px #b78a66;border-top:1px solid #b78a66;border-bottom:1px solid #b78a66;border-left:1px solid #b78a66}.admin-color-ectoplasm .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#a3b745;-webkit-box-shadow:inset 0 1px 2px #839237;box-shadow:inset 0 1px 2px #839237;border-top:1px solid #839237;border-bottom:1px solid #839237;border-left:1px solid #839237}.admin-color-midnight .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#e14d43;-webkit-box-shadow:inset 0 1px 2px #d02a21;box-shadow:inset 0 1px 2px #d02a21;border-top:1px solid #d02a21;border-bottom:1px solid #d02a21;border-left:1px solid #d02a21}.admin-color-ocean .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#9ebaa0;-webkit-box-shadow:inset 0 1px 2px #80a583;box-shadow:inset 0 1px 2px #80a583;border-top:1px solid #80a583;border-bottom:1px solid #80a583;border-left:1px solid #80a583}.admin-color-sunrise .factory-bootstrap-406 .factory-dropdown.factory-buttons-way .active{background-color:#dd823b;-webkit-box-shadow:inset 0 1px 2px #c36822;box-shadow:inset 0 1px 2px #c36822;border-top:1px solid #c36822;border-bottom:1px solid #c36822;border-left:1px solid #c36822}.factory-bootstrap-406 .factory-dropdown.factory-ddslick-way .dd-select{background-color:#fff!important}.factory-bootstrap-406 .factory-dropdown.factory-ddslick-way label{margin-bottom:1px}.factory-bootstrap-406 .factory-dropdown.factory-ddslick-way .dd-option,.factory-bootstrap-406 .factory-dropdown.factory-ddslick-way .dd-selected{padding:8px 12px 8px 11px!important}
libs/factory/bootstrap/assets/css-min/control.multiple-textbox.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .factory-mtextbox-item{position:relative;margin-bottom:5px}.factory-bootstrap-406 .factory-mtextbox-item input,.factory-mtextbox-remove-item{display:inline-block}.factory-bootstrap-406 .factory-mtextbox-item .factory-mtextbox-remove-item{position:absolute;top:0;right:0;bottom:0;width:40px;border-radius:0 3px 3px 0;outline:0}.factory-bootstrap-406 .factory-mtextbox-item .factory-mtextbox-remove-item:focus,.factory-bootstrap-406 .factory-mtextbox-item .factory-mtextbox-remove-item:hover{box-shadow:none;outline:0}.factory-bootstrap-406 .factory-mtextbox-add-item{display:block;margin-top:10px}
libs/factory/bootstrap/assets/css-min/holder.more-link.min.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+
11
+ .factory-bootstrap-406 .factory-more-link-content{border-top:1px dashed #DDD;padding-top:25px;width:100%;padding-right:20px;position:relative}.factory-bootstrap-406 .factory-tab .factory-more-link-show{display:inline-block;text-decoration:none;border-bottom:1px dotted #21759b;position:relative}.factory-bootstrap-406 .factory-tab .factory-more-link-show:hover{border-color:#d54e21}.factory-bootstrap-406 .factory-tab .factory-more-link-hide{position:absolute;margin-top:-35px;background-color:#fff;padding:0 5px;right:20px;color:#bbb;text-decoration:none}.factory-bootstrap-406 .factory-tab .factory-more-link-hide:hover{color:#999}
libs/factory/bootstrap/assets/images/loader-sm-f6f6f6.gif ADDED
Binary file
libs/factory/bootstrap/assets/images/loader-sm-tr.gif ADDED
Binary file
libs/factory/bootstrap/assets/js-min/bootstrap.dropdown.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+ +function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=factory-dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}},a.fn.factoryBootstrap406_dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.factoryBootstrap406_dropdown.Constructor=f,a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery);
libs/factory/bootstrap/assets/js-min/bootstrap.tooltip.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+ +function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;if("top"==b&&j!=f&&(c=!0,a.top=a.top+f-j),/bottom|top/.test(b)){var k=0;a.left<0&&(k=-2*a.left,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach()}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.$element.trigger("hidden.bs."+this.type),this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this},a(function(){a('[data-toggle="factory-tooltip"]').tooltip({html:!0})})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.checkbox.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+ !function(a){var b=function(b){var c=this;this.$element=a(b),this.$result=this.$element.find(".factory-result"),this.$on=this.$element.find(".factory-on"),this.$off=this.$element.find(".factory-off");var d=this.$element.is(".factory-tumbler"),e=this.$element.is(".factory-has-tumbler-hint"),f=this.$element.data("tumbler-function"),g=this.$element.data("tumbler-delay");g||(g=3e3),this.callByPath=function(a,b){for(var c=a.split("."),d=window,e=0;e<c.length;e++)d=d[c[e]];d.apply(d,b)},this.$on.click(function(){return c.$off.removeClass("active"),c.$on.addClass("active"),d?setTimeout(function(){c.$on.removeClass("active"),c.$off.addClass("active");var a=e?c.$element.next():null;f?c.callByPath(f,[c.$element,a]):e&&(c.$element.next().fadeIn(300),setTimeout(function(){c.$element.next().fadeOut(500)},g))},300):(c.$result.attr("checked","checked"),c.$result.val(1),c.$result.trigger("change")),!1}),this.$off.click(function(){return c.$on.removeClass("active"),c.$off.addClass("active"),d?setTimeout(function(){c.$off.removeClass("active"),c.$on.addClass("active");var a=e?c.$element.next():null;f?c.callByPath(f,[c.$element,a]):e&&(c.$element.next().fadeIn(300),setTimeout(function(){c.$element.next().fadeOut(500)},g))},300):(c.$result.removeAttr("checked"),c.$result.val(0),c.$result.trigger("change")),!1}),this.hashCode=function(a){var b=0;if(!a||0===a.length)return b;for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);b=(b<<5)-b+d,b&=b}return b=b.toString(16),b=b.replace("-","")},this.executeEvents=function(a){(void 0!==window.__factory_checkbox_control_events_off_data||void 0!==window.__factory_checkbox_control_events_on_data)&&(a.change(function(){c.eventsProcess(a)}),c.eventsProcess(a))},this.eventsProcess=function(b){var d=b.attr("name"),e=b.prop("checked"),f=window.__factory_checkbox_control_events_on_data[d],g=window.__factory_checkbox_control_events_off_data[d];if(f||g){var h,i;void 0===window.__factory_checkbox_control_detach_elements&&(window.__factory_checkbox_control_detach_elements={}),h=window.__factory_checkbox_control_detach_elements,i=e?f:g;for(var j in i)if(i.hasOwnProperty(j)){var k,l=i[j];a.isArray(l)||(k=c.hashCode(d+l));var m;switch(j){case"hide":"string"==typeof l&&a(l).hide(0);break;case"show":"string"==typeof l&&a(l).fadeIn(200);break;case"detach":"string"==typeof l&&a(l).each(function(b){h[k]||(h[k]={}),h[k][b]||(h[k][b]={}),h[k][b].recovery_contanier=a(this).parent(),h[k][b].element=a(this).clone(!0),a(this).remove()});break;case"recovery":if(h[k]){for(var n in h[k])h[k].hasOwnProperty(n)&&h[k][n].recovery_contanier&&h[k][n].element&&h[k][n].recovery_contanier.append(h[k][n].element);delete h[k]}break;case"removeClasses":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&l[m]&&a(m).removeClass(l[m]);break;case"addClasses":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&l[m]&&a(m).addClass(l[m]);break;case"setValue":if("object"==typeof l)for(m in l)l.hasOwnProperty(m)&&void 0!==l[m]&&null!==l[m]&&(console.log(l[m]),a(m).val(l[m]))}}}},this.executeEvents(this.$result)};a.fn.factoryBootstrap406_checkboxControl=function(c){if("string"==typeof c){var d=a(this).data("factory.checkbox.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.checkbox.control");d||c.data("factory.checkbox.control",d=new b(this))})},a.fn.factoryBootstrap406_checkboxControl.Constructor=b,a(function(){a(".factory-bootstrap-406 .factory-checkbox.factory-buttons-way").factoryBootstrap406_checkboxControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.dropdown.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+ !function(a){var b=function(b){var c=this;if(this.$element=a(b),this.way=this.$element.data("way"),this.name=this.$element.data("name")||this.$element.attr("name"),this.hashCode=function(a){var b=0;if(!a||0===a.length)return b;for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);b=(b<<5)-b+d,b&=b}return b=b.toString(16),b=b.replace("-","")},this.executeEvents=function(a){void 0!==window.factory_dropdown_control_events_data&&(a.change(function(){c.eventsProcess(a)}),c.eventsProcess(a))},this.eventsProcess=function(b){var d=b.attr("name"),e=b.val(),f=window.factory_dropdown_control_events_data[d];if(f&&f[e]){var g;void 0===window.__factory_dropdown_control_detach_elements&&(window.__factory_dropdown_control_detach_elements={}),g=window.__factory_dropdown_control_detach_elements;for(var h in f[e])if(f[e].hasOwnProperty(h)){var i,j=f[e][h];switch(a.isArray(j)||(i=c.hashCode(d+j)),h){case"hide":"string"==typeof j&&a(j).hide(0);break;case"show":"string"==typeof j&&a(j).fadeIn(200);break;case"detach":"string"==typeof j&&a(j).each(function(b){g[i]||(g[i]={}),g[i][b]||(g[i][b]={}),g[i][b].recovery_contanier=a(this).parent(),g[i][b].element=a(this).clone(!0),a(this).remove()});break;case"recovery":if(g[i]){for(var k in g[i])g[i].hasOwnProperty(k)&&g[i][k].recovery_contanier&&g[i][k].element&&g[i][k].recovery_contanier.append(g[i][k].element);delete g[i]}break;case"removeClasses":if("object"==typeof j)for(var l in j)j.hasOwnProperty(l)&&j[l]&&a(l).removeClass(j[l]);break;case"addClasses":if("object"==typeof j)for(var l in j)j.hasOwnProperty(l)&&j[l]&&a(l).addClass(j[l])}}}},"buttons"===this.way)this.$result=this.$element.find(".factory-result"),this.$hints=this.$element.find(".factory-hints"),this.$buttons=this.$element.find(".btn"),c.executeEvents(this.$result),this.$buttons.click(function(){var b=a(this).data("value");return c.$buttons.removeClass("active"),a(this).addClass("active"),c.$hints.find(".factory-hint").hide(),c.$hints.find(".factory-hint-"+b).fadeIn(),c.$result.val(b),c.$result.trigger("change"),!1});else if("ddslick"===this.way){c.executeEvents(c.$element.find(".factory-result"));var d=window["factory_"+this.name+"_data"],e=this.$element.find(".factory-ddslick"),f=this.$element.data("width")||300,g=this.$element.data("align")||"right";a(d).each(function(){return this.imageHoverSrc?void(a("<img/>")[0].src=this.imageHoverSrc):!0}),e.ddslick({data:d,width:f,imagePosition:g,selectText:"- select -",onSelected:function(a){a.selectedData.imageHoverSrc&&c.$element.find(".dd-selected-image").attr("src",a.selectedData.imageHoverSrc);var b=c.$element.find(".factory-result").val(a.selectedData.value);b.change()}})}else{c.executeEvents(this.$element),this.$hints=this.$element.next(),this.$hints.hasClass("factory-hints")&&(this.$element.change(function(){return c.updateHints(),!1}),this.updateHints=function(){var a=c.$element.val();c.$hints.find(".factory-hint").hide(),c.$hints.find(".factory-hint-"+a).show()},c.updateHints()),this.getAjaxData=function(){var a=c.$element.data("ajax-data-id");return window[a]},this.loadData=function(){var b=c.getAjaxData();a.ajax({url:b.url,data:b.data,dataType:"json",success:function(a){return a.error?c.showError(a.error):void c.fill(a.items)},error:function(a){console&&console.log&&console.log(a.responseText),c.showError("Unexpected error occurred during the ajax request.")},complete:function(){c.removeLoader()}})},this.fill=function(a){this.clearList();var b=c.getAjaxData();if(a&&a.length)for(var d in a){var e=a[d];c.addListItem(e)}else this.$element.append("<option>"+b.emptyList+"</li>");this.$element.trigger("factory-loaded")},this.clearList=function(){this.$element.html("")},this.addListItem=function(b){var d=a("<option />").attr("value",b.value).text(b.title).appendTo(this.$element),e=c.getAjaxData();e.selected&&e.selected==b.value&&d.attr("selected","selected")},this.showError=function(b){this.clearList();var d=a("<div class='factory-control-error'></div>").append(a("<i class='fa fa-exclamation-triangle'></i>")).append(b),e=c.getAjaxData();this.$element.append("<option>"+e.emptyList+"</li>"),this.$element.after(d),this.$element.addClass("factory-has-error")},this.removeLoader=function(){this.$element.removeClass("factory-hidden");var b=c.getAjaxData();a(b.loader).remove()};var h=this.$element.data("ajax");h&&this.loadData()}};a.fn.factoryBootstrap406_dropdownControl=function(c){if("string"==typeof c){var d=a(this).data("factory.dropdown.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.dropdown.control");d||c.data("factory.dropdown.control",d=new b(this))})},a.fn.factoryBootstrap406_dropdownControl.Constructor=b,a(function(){a(".factory-bootstrap-406 .factory-dropdown").factoryBootstrap406_dropdownControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.list.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+ !function(a){var b=function(b){var c=this;if(this.$element=a(b),this.way=this.$element.data("way"),this.name=this.$element.data("name"),"checklist"===this.way){this.getAjaxData=function(){var a=c.$element.data("ajax-data-id");return window[a]},this.loadData=function(){var b=c.getAjaxData();a.ajax({url:b.url,data:b.data,dataType:"json",success:function(a){return a.error?c.showError(a.error):void c.fill(a.items)},error:function(){c.showError("Unexpected error occurred during the ajax request.")},complete:function(){c.removeLoader()}})},this.fill=function(a){this.clearList();var b=c.getAjaxData();if(a&&a.length){this.$element.removeClass("factory-empty");for(var d in a){var e=a[d];c.addListItem(e)}}else this.$element.addClass("factory-empty"),this.$element.append("<li>"+b.emptyList+"</li>")},this.clearList=function(){this.$element.html("")},this.addListItem=function(b){var d=a("<li>"),e=a("<label>").attr("for","factory-checklist-"+c.name+"-"+b.value).appendTo(d),f=a("<span>").appendTo(e),g=a("<input />").attr("type","checkbox").attr("name",c.name+"[]").val(b.value).attr("id","factory-checklist-"+c.name+"-"+b.value).appendTo(f),h=(a("<span>"+b.title+"</span>").appendTo(e),c.getAjaxData());h.selected.length&&a.inArray(b.value,h.selected)>=0&&g.attr("checked","checked"),this.$element.append(d)},this.showError=function(b){this.$element.html("").append(a("<i class='fa fa-exclamation-triangle'></i>")).append(b),this.$element.addClass("factory-list-error")},this.removeLoader=function(){this.$element.removeClass("factory-hidden");var b=c.getAjaxData();a(b.loader).remove()};var d=this.$element.data("ajax");d&&this.loadData()}};a.fn.factoryBootstrap406_listControl=function(c){if("string"==typeof c){var d=a(this).data("factory.list.control");return d?d[c]():null}return this.each(function(){var c=a(this),d=c.data("factory.list.control");d||c.data("factory.list.control",d=new b(this))})},a.fn.factoryBootstrap406_listControl.Constructor=b,a(function(){a(".factory-bootstrap-406 .factory-list").factoryBootstrap406_listControl()})}(jQuery);
libs/factory/bootstrap/assets/js-min/control.multiple-textbox.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Bootstrap generator - v1.0.1, 2018-02-26
3
+ * Webcraftic factory build
4
+ *
5
+ * Copyright 2018, Alex Kovalev <alex.kovalevv@gmail.com>, Webcraftic <wordpress.webraftic@gmail.com>
6
+ * Site: http://webcraftic.com
7
+ * Support: http://webcraftic.com/contact-us/
8
+ */
9
+
10
+ !function(a){"use strict";var b=function(b){this.$element=a(b);var c=a(".factory-mtextbox-item",this.$element).eq(0).clone(!0);a(".factory-mtextbox-add-item",this.$element).on("click",function(){var b=a(this).closest(".factory-multiple-textbox-group").find(".factory-mtextbox-items"),d=c.clone(!0),e=a('<button class="btn btn-default btn-small factory-mtextbox-remove-item"><i class="fa fa-times" aria-hidden="true"></i></button>');return b.append(d.append(e)),d.find('input[type="text"]').val("").focus(),!1}),a(document).on("click",".factory-mtextbox-remove-item",function(){return a(this).closest(".factory-mtextbox-item").remove(),!1})};a.fn.factoryBootstrap406_MultipleTextboxControl=function(){return this.each(function(){new b(this)})},a(function(){a(".factory-bootstrap-406 .factory-multiple-textbox-group").factoryBootstrap406_MultipleTextboxControl()})}(jQuery);
libs/factory/bootstrap/boot.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Factory Bootstrap
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-bootstrap
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ // module provides function only for the admin area
18
+ if( !is_admin() ) {
19
+ return;
20
+ }
21
+
22
+ if( defined('FACTORY_BOOTSTRAP_406_LOADED') ) {
23
+ return;
24
+ }
25
+ define('FACTORY_BOOTSTRAP_406_LOADED', true);
26
+
27
+ define('FACTORY_BOOTSTRAP_406_DIR', dirname(__FILE__));
28
+ define('FACTORY_BOOTSTRAP_406_URL', plugins_url(null, __FILE__));
29
+
30
+ // sets version of admin interface
31
+ define('FACTORY_BOOTSTRAP_406_VERSION', 'FACTORY_BOOTSTRAP_406');
32
+
33
+ if( !defined('FACTORY_FLAT_ADMIN') ) {
34
+ define('FACTORY_FLAT_ADMIN', true);
35
+ }
36
+
37
+ include_once(FACTORY_BOOTSTRAP_406_DIR . '/includes/functions.php');
libs/factory/bootstrap/includes/functions.php ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file manages assets of the Factory Bootstap.
4
+ *
5
+ * @author Alex Kovalev <alex@byonepress.com>
6
+ * @author Paul Kashtanoff <paul@byonepress.com>
7
+ * @copyright (c) 2018, OnePress Ltd
8
+ *
9
+ * @package factory-bootstrap
10
+ * @since 1.0.0
11
+ */
12
+
13
+ add_action('wbcr_factory_bootstrap_406_plugin_created', 'wbcr_factory_bootstrap_406_plugin_created');
14
+
15
+ /**
16
+ * @param Wbcr_Factory406_Plugin $plugin
17
+ */
18
+ function wbcr_factory_bootstrap_406_plugin_created($plugin)
19
+ {
20
+ $manager = new Wbcr_FactoryBootstrap406_Manager($plugin);
21
+ $plugin->setBootstap($manager);
22
+ }
23
+
24
+ if( !class_exists('Wbcr_FactoryBootstrap406_Manager') ) {
25
+
26
+ /**
27
+ * The Bootstrap Manager class.
28
+ *
29
+ * @since 3.2.0
30
+ */
31
+ class Wbcr_FactoryBootstrap406_Manager {
32
+
33
+ /**
34
+ * A plugin for which the manager was created.
35
+ *
36
+ * @since 3.2.0
37
+ * @var Wbcr_Factory406_Plugin
38
+ */
39
+ public $plugin;
40
+
41
+ /**
42
+ * Contains scripts to include.
43
+ *
44
+ * @since 3.2.0
45
+ * @var string[]
46
+ */
47
+ public $scripts = array();
48
+
49
+ /**
50
+ * Contains styles to include.
51
+ *
52
+ * @since 3.2.0
53
+ * @var string[]
54
+ */
55
+ public $styles = array();
56
+
57
+ /**
58
+ * Createas a new instance of the license api for a given plugin.
59
+ *
60
+ * @since 1.0.0
61
+ */
62
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
63
+ {
64
+ $this->plugin = $plugin;
65
+
66
+ add_action('admin_enqueue_scripts', array($this, 'loadAssets'));
67
+ add_filter('admin_body_class', array($this, 'adminBodyClass'));
68
+ }
69
+
70
+ /**
71
+ * Includes the Bootstrap scripts.
72
+ * @since 3.2.0
73
+ * @param array|string $scripts
74
+ */
75
+ public function enqueueScript($scripts)
76
+ {
77
+ if( is_array($scripts) ) {
78
+ foreach($scripts as $script) {
79
+ if( !in_array($script, $this->scripts) ) {
80
+ $this->scripts[] = $script;
81
+ }
82
+ }
83
+ } else {
84
+ if( !in_array($scripts, $this->scripts) ) {
85
+ $this->scripts[] = $scripts;
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * * Includes the Bootstrap styles.
92
+ *
93
+ * @since 3.2.0
94
+ * @param array|string $styles
95
+ */
96
+ public function enqueueStyle($styles)
97
+ {
98
+
99
+ if( is_array($styles) ) {
100
+ foreach($styles as $style) {
101
+ if( !in_array($style, $this->styles) ) {
102
+ $this->styles[] = $style;
103
+ }
104
+ }
105
+ } else {
106
+ if( !in_array($styles, $this->styles) ) {
107
+ $this->styles[] = $styles;
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Loads Bootstrap assets.
114
+ *
115
+ * @see admin_enqueue_scripts
116
+ *
117
+ * @since 3.2.0
118
+ * @return void
119
+ */
120
+ public function loadAssets($hook)
121
+ {
122
+
123
+ do_action('wbcr_factory_406_bootstrap_enqueue_scripts', $hook);
124
+ do_action('wbcr_factory_406_bootstrap_enqueue_scripts_' . $this->plugin->getPluginName(), $hook);
125
+
126
+ $dependencies = array();
127
+ if( !empty($this->scripts) ) {
128
+ $dependencies[] = 'jquery';
129
+ $dependencies[] = 'jquery-ui-core';
130
+ $dependencies[] = 'jquery-ui-widget';
131
+ }
132
+
133
+ foreach($this->scripts as $script) {
134
+ switch( $script ) {
135
+ case 'plugin.iris':
136
+ $dependencies[] = 'jquery-ui-widget';
137
+ $dependencies[] = 'jquery-ui-slider';
138
+ $dependencies[] = 'jquery-ui-draggable';
139
+ break;
140
+ }
141
+ }
142
+
143
+ if( !empty($this->scripts) ) {
144
+ $this->enqueueScripts($this->scripts, 'js', $dependencies);
145
+ }
146
+ if( !empty($this->styles) ) {
147
+ $this->enqueueScripts($this->styles, 'css', $dependencies);
148
+ }
149
+
150
+ $user_id = get_current_user_id();
151
+ $color_name = get_user_meta($user_id, 'admin_color', true);
152
+
153
+ if( $color_name !== 'fresh' ) {
154
+ if( file_exists(FACTORY_BOOTSTRAP_406_DIR . '/assets/flat/css/bootstrap.' . $color_name . '.css') ) {
155
+ wp_enqueue_style('wbcr-factory-bootstrap-406-colors', FACTORY_BOOTSTRAP_406_URL . '/assets/flat/css/bootstrap.' . $color_name . '.css');
156
+ }
157
+ }
158
+
159
+ if( $color_name == 'light' ) {
160
+ $primary_dark = '#037c9a';
161
+ $primary_light = '#04a4cc';
162
+ } elseif( $color_name == 'blue' ) {
163
+ $primary_dark = '#d39323';
164
+ $primary_light = '#e1a948';
165
+ } elseif( $color_name == 'coffee' ) {
166
+ $primary_dark = '#b78a66';
167
+ $primary_light = '#c7a589';
168
+ } elseif( $color_name == 'ectoplasm' ) {
169
+ $primary_dark = '#839237';
170
+ $primary_light = '#a3b745';
171
+ } elseif( $color_name == 'ocean' ) {
172
+ $primary_dark = '#80a583';
173
+ $primary_light = '#9ebaa0';
174
+ } elseif( $color_name == 'midnight' ) {
175
+ $primary_dark = '#d02a21';
176
+ $primary_light = '#e14d43';
177
+ } elseif( $color_name == 'sunrise' ) {
178
+ $primary_dark = '#c36822';
179
+ $primary_light = '#dd823b';
180
+ } else {
181
+ $primary_dark = '#0074a2';
182
+ $primary_light = '#2ea2cc';
183
+ }
184
+
185
+ ?>
186
+
187
+ <script>
188
+ if( !window.factory ) {
189
+ window.factory = {};
190
+ }
191
+ if( !window.factory.factoryBootstrap406 ) {
192
+ window.factory.factoryBootstrap406 = {};
193
+ }
194
+ window.factory.factoryBootstrap406.colors = {
195
+ primaryDark: '<?php echo $primary_dark ?>',
196
+ primaryLight: '<?php echo $primary_light ?>'
197
+ };
198
+ </script>
199
+ <?php
200
+ }
201
+
202
+ /**
203
+ * @param array $sripts
204
+ * @param string $type
205
+ * @param array $dependencies
206
+ */
207
+ protected function enqueueScripts(array $sripts, $type = 'js', array $dependencies)
208
+ {
209
+
210
+ $is_first = true;
211
+ $cache_id = md5(implode(',', $this->scripts) . $type . $this->plugin->getPluginVersion());
212
+ $cache_dir_path = FACTORY_BOOTSTRAP_406_DIR . '/assets/cache/';
213
+ $cache_dir_url = FACTORY_BOOTSTRAP_406_URL . '/assets/cache/';
214
+
215
+ $cache_filepath = $cache_dir_path . $cache_id . ".min." . $type;
216
+ $cache_fileurl = $cache_dir_url . $cache_id . ".min." . $type;
217
+
218
+ if( file_exists($cache_filepath) ) {
219
+ if( $type == 'js' ) {
220
+ wp_enqueue_script('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion());
221
+ } else {
222
+ wp_enqueue_style('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, array(), $this->plugin->getPluginVersion());
223
+ }
224
+ } else {
225
+ $cache_dir_exists = false;
226
+ if( !file_exists($cache_dir_path) ) {
227
+ if( @mkdir($cache_dir_path, 0777) && is_writable($cache_dir_path) ) {
228
+ $cache_dir_exists = true;
229
+ }
230
+ } else {
231
+ if( is_writable($cache_dir_path) ) {
232
+ $cache_dir_exists = true;
233
+ }
234
+ }
235
+
236
+ $concat_files = array();
237
+ foreach($sripts as $script_to_load) {
238
+ $script_to_load = sanitize_text_field($script_to_load);
239
+ if( $cache_dir_exists ) {
240
+ $fname = FACTORY_BOOTSTRAP_406_DIR . "/assets/$type-min/$script_to_load.min." . $type;
241
+ if( file_exists($fname) ) {
242
+ $f = @fopen($fname, 'r');
243
+ $concat_files[] = @fread($f, filesize($fname));
244
+ @fclose($f);
245
+ }
246
+ } else {
247
+ if( $type == 'js' ) {
248
+ wp_enqueue_script(md5($script_to_load), FACTORY_BOOTSTRAP_406_URL . "/assets/$type-min/$script_to_load.min." . $type, $is_first
249
+ ? $dependencies
250
+ : false, $this->plugin->getPluginVersion());
251
+ } else {
252
+ wp_enqueue_style(md5($script_to_load), FACTORY_BOOTSTRAP_406_URL . "/assets/$type-min/$script_to_load.min." . $type, array(), $this->plugin->getPluginVersion());
253
+ }
254
+ $is_first = false;
255
+ }
256
+ }
257
+
258
+ if( $cache_dir_exists && !empty($concat_files) ) {
259
+
260
+ $cf = @fopen($cache_filepath, 'w');
261
+ $write_content = implode(PHP_EOL, $concat_files);
262
+ @fwrite($cf, $write_content);
263
+ @fclose($cf);
264
+
265
+ if( file_exists($cache_filepath) ) {
266
+ if( $type == 'js' ) {
267
+ wp_enqueue_script('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, $dependencies, $this->plugin->getPluginVersion());
268
+ } else {
269
+ wp_enqueue_style('wbcr-factory-bootstrap-' . $cache_id, $cache_fileurl, array(), $this->plugin->getPluginVersion());
270
+ }
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+ /**
277
+ * Adds the body classes: 'factory-flat or 'factory-volumetric'.
278
+ *
279
+ * @since 3.2.0
280
+ * @param string $classes
281
+ * @return string
282
+ */
283
+ public function adminBodyClass($classes)
284
+ {
285
+ $classes .= FACTORY_FLAT_ADMIN
286
+ ? ' factory-flat '
287
+ : ' factory-volumetric ';
288
+
289
+ return $classes;
290
+ }
291
+ }
292
+ }
libs/factory/clearfy/boot.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Factory clearfy
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package clearfy
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( defined('FACTORY_CLEARFY_203_LOADED') ) {
18
+ return;
19
+ }
20
+ define('FACTORY_CLEARFY_203_LOADED', true);
21
+
22
+ define('FACTORY_CLEARFY_203_DIR', dirname(__FILE__));
23
+ define('FACTORY_CLEARFY_203_URL', plugins_url(null, __FILE__));
24
+
25
+ load_plugin_textdomain('wbcr_factory_clearfy_203', false, dirname(plugin_basename(__FILE__)) . '/langs');
26
+
27
+ require(FACTORY_CLEARFY_203_DIR . '/includes/class.helpers.php');
28
+ require(FACTORY_CLEARFY_203_DIR . '/includes/class.configurate.php');
29
+
30
+ // module provides function only for the admin area
31
+ if( !is_admin() ) {
32
+ return;
33
+ }
34
+
35
+ if( defined('FACTORY_PAGES_407_LOADED') ) {
36
+ require(FACTORY_CLEARFY_203_DIR . '/pages/more-features.php');
37
+ }
libs/factory/clearfy/includes/class.configurate.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Configurate clearfy plugins
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package clearfy
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryClearfy203_Configurate') ) {
18
+
19
+ abstract class Wbcr_FactoryClearfy203_Configurate {
20
+
21
+ /**
22
+ * @param Wbcr_Factory406_Plugin $plugin
23
+ */
24
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
25
+ {
26
+ $this->plugin = $plugin;
27
+ $this->registerActionsAndFilters();
28
+ }
29
+
30
+ /**
31
+ * Registers filters and actions
32
+ * @return mixed
33
+ */
34
+ abstract protected function registerActionsAndFilters();
35
+
36
+ /**
37
+ * Get options with namespace
38
+ *
39
+ * @param $option_name
40
+ * @param bool $default
41
+ * @return mixed|void
42
+ */
43
+ public function getOption($option_name, $default = false)
44
+ {
45
+ return $this->plugin->getOption($option_name, $default);
46
+ }
47
+
48
+ /**
49
+ * @param $option_name
50
+ * @param $value
51
+ * @return bool
52
+ */
53
+ public function updateOption($option_name, $value)
54
+ {
55
+ $this->plugin->updateOption($option_name, $value);
56
+ }
57
+
58
+ /**
59
+ * @param $option_name
60
+ * @return bool
61
+ */
62
+ public function deleteOption($option_name)
63
+ {
64
+ $this->plugin->deleteOption($option_name);
65
+ }
66
+ }
67
+ }
libs/factory/clearfy/includes/class.helpers.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Helpers functions
5
+ *
6
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
7
+ * @copyright (c) 2018, Webcraftic Ltd
8
+ *
9
+ * @package clearfy
10
+ * @since 1.0.0
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if( !defined('ABSPATH') ) {
15
+ exit;
16
+ }
17
+
18
+ if( !class_exists('WbcrFactoryClearfy203_Helpers') ) {
19
+ class WbcrFactoryClearfy203_Helpers {
20
+
21
+ /**
22
+ * Is permalink enabled?
23
+ * @global WP_Rewrite $wp_rewrite
24
+ * @since 1.0.0
25
+ * @return bool
26
+ */
27
+ public static function isPermalink()
28
+ {
29
+ global $wp_rewrite;
30
+
31
+ if( !isset($wp_rewrite) || !is_object($wp_rewrite) || !$wp_rewrite->using_permalinks() ) {
32
+ return false;
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ /**
39
+ * Display 404 page to bump bots and bad guys
40
+ *
41
+ * @param bool $simple If true force displaying basic 404 page
42
+ */
43
+ public static function setError404()
44
+ {
45
+ global $wp_query;
46
+
47
+ if( function_exists('status_header') ) {
48
+ status_header('404');
49
+ nocache_headers();
50
+ }
51
+
52
+ if( $wp_query && is_object($wp_query) ) {
53
+ $wp_query->set_404();
54
+ get_template_part(404);
55
+ } else {
56
+ global $pagenow;
57
+
58
+ $pagenow = 'index.php';
59
+
60
+ if( !defined('WP_USE_THEMES') ) {
61
+ define('WP_USE_THEMES', true);
62
+ }
63
+
64
+ wp();
65
+
66
+ $_SERVER['REQUEST_URI'] = self::userTrailingslashit('/hmwp_404');
67
+
68
+ require_once(ABSPATH . WPINC . '/template-loader.php');
69
+ }
70
+
71
+ exit();
72
+ }
73
+
74
+ public static function useTrailingSlashes()
75
+ {
76
+ return ('/' === substr(get_option('permalink_structure'), -1, 1));
77
+ }
78
+
79
+ public static function userTrailingslashit($string)
80
+ {
81
+ return self::useTrailingSlashes()
82
+ ? trailingslashit($string)
83
+ : untrailingslashit($string);
84
+ }
85
+
86
+ /**
87
+ * Returns true if a needle can be found in a haystack
88
+ *
89
+ * @param string $string
90
+ * @param string $find
91
+ * @param bool $case_sensitive
92
+ * @return bool
93
+ */
94
+ public static function strContains($string, $find, $case_sensitive = true)
95
+ {
96
+ if( empty($string) || empty($find) ) {
97
+ return false;
98
+ }
99
+
100
+ $pos = $case_sensitive
101
+ ? strpos($string, $find)
102
+ : stripos($string, $find);
103
+
104
+ return !($pos === false);
105
+ }
106
+
107
+ /**
108
+ * Tests if a text starts with an given string.
109
+ *
110
+ * @param string $string
111
+ * @param string $find
112
+ * @param bool $case_sensitive
113
+ * @return bool
114
+ */
115
+ public static function strStartsWith($string, $find, $case_sensitive = true)
116
+ {
117
+ if( $case_sensitive ) {
118
+ return strpos($string, $find) === 0;
119
+ }
120
+
121
+ return stripos($string, $find) === 0;
122
+ }
123
+
124
+ /**
125
+ * Tests if a text ends with an given string.
126
+ *
127
+ * @param $string
128
+ * @param $find
129
+ * @param bool $case_sensitive
130
+ * @return bool
131
+ */
132
+ public static function strEndsWith($string, $find, $case_sensitive = true)
133
+ {
134
+ $expected_position = strlen($string) - strlen($find);
135
+
136
+ if( $case_sensitive ) {
137
+ return strrpos($string, $find, 0) === $expected_position;
138
+ }
139
+
140
+ return strripos($string, $find, 0) === $expected_position;
141
+ }
142
+
143
+ public static function arrayMergeInsert(array $arr, array $inserted, $position = 'bottom', $key = null)
144
+ {
145
+ if( $position == 'top' ) {
146
+ return array_merge($inserted, $arr);
147
+ }
148
+ $key_position = ($key === null)
149
+ ? false
150
+ : array_search($key, array_keys($arr));
151
+ if( $key_position === false OR ($position != 'before' AND $position != 'after') ) {
152
+ return array_merge($arr, $inserted);
153
+ }
154
+ if( $position == 'after' ) {
155
+ $key_position++;
156
+ }
157
+
158
+ return array_merge(array_slice($arr, 0, $key_position, true), $inserted, array_slice($arr, $key_position, null, true));
159
+ }
160
+
161
+ public static function maybeGetPostJson($name)
162
+ {
163
+ if( isset($_POST[$name]) AND is_string($_POST[$name]) ) {
164
+ $result = json_decode(stripslashes($_POST[$name]), true);
165
+ if( !is_array($result) ) {
166
+ $result = array();
167
+ }
168
+
169
+ return $result;
170
+ } else {
171
+ return array();
172
+ }
173
+ }
174
+
175
+ public static function getEscapeJson(array $data)
176
+ {
177
+ return htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');
178
+ }
179
+ }
180
+ }
libs/factory/clearfy/langs/wbcr_factory_clearfy_203-fr-FR.mo ADDED
Binary file
libs/factory/clearfy/langs/wbcr_factory_clearfy_203-fr-FR.po ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: clearfy\n"
4
+ "POT-Creation-Date: 2017-11-09 10:35+0300\n"
5
+ "PO-Revision-Date: 2017-11-09 13:50+0100\n"
6
+ "Last-Translator: alex.kovalevv@gmail.com <alex.kovalevv@gmail.com>\n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: fr\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 2.0.4\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: pages/more-features.php:29
21
+ msgid "More features (<b>free</b>)"
22
+ msgstr "Plus de fonctionnalités (<b>gratuit</b>)"
23
+
24
+ #: pages/more-features.php:36
25
+ msgid "install the ultimate version of the plugin for free!"
26
+ msgstr "installez la version ultime du plugin gratuitement!"
27
+
28
+ #: pages/more-features.php:47
29
+ msgid "Code cleaning"
30
+ msgstr "Nettoyage du code"
31
+
32
+ #: pages/more-features.php:49
33
+ msgid "Clears the source code of the page from unused code."
34
+ msgstr "Efface le code source de la page du code inutilisé."
35
+
36
+ #: pages/more-features.php:56
37
+ msgid "Improve SEO"
38
+ msgstr "Améliorer le référencement"
39
+
40
+ #: pages/more-features.php:58
41
+ msgid ""
42
+ "Removes duplicate pages, closes external links, changes the headers of the "
43
+ "server."
44
+ msgstr ""
45
+ "Supprime les pages en double, ferme les liens externes, modifie les en-têtes "
46
+ "du serveur."
47
+
48
+ #: pages/more-features.php:65
49
+ msgid "Site ptotection"
50
+ msgstr "Protection du site"
51
+
52
+ #: pages/more-features.php:67
53
+ msgid "Enables and disables features that improve the protection of your site."
54
+ msgstr ""
55
+ "Active et désactive les fonctionnalités qui améliorent la protection de "
56
+ "votre site."
57
+
58
+ #: pages/more-features.php:74
59
+ msgid "Disable comments"
60
+ msgstr "Désactiver les commentaires"
61
+
62
+ #: pages/more-features.php:76
63
+ msgid "Disables comments on the entire site or on specific pages."
64
+ msgstr ""
65
+ "Désactive les commentaires sur l'intégralité du site ou sur des pages "
66
+ "spécifiques."
67
+
68
+ #: pages/more-features.php:83
69
+ msgid "Manage updates"
70
+ msgstr "Gérer les mises à jour"
71
+
72
+ #: pages/more-features.php:85
73
+ msgid ""
74
+ "Enables or disables automatically updates for plugins, themes and core. It "
75
+ "is also possible\n"
76
+ "\t\t\t\t\t\t\tto disable all updates."
77
+ msgstr ""
78
+ "Active ou désactive automatiquement les mises à jour pour les plugins, les "
79
+ "thèmes et le core. C'est aussi possible\n"
80
+ "\t\t\t\t\t\t\tdésactiver toutes les mises à jour."
81
+
82
+ #: pages/more-features.php:93
83
+ msgid "Manage widgets"
84
+ msgstr "Gérer les widgets"
85
+
86
+ #: pages/more-features.php:95
87
+ msgid "Allows you to remove unused widgets."
88
+ msgstr "Vous permet de supprimer les widgets inutilisés."
89
+
90
+ #: pages/more-features.php:102
91
+ msgid "Speed Optimization"
92
+ msgstr "Optimisation de la vitesse"
93
+
94
+ #: pages/more-features.php:104
95
+ msgid ""
96
+ "Increases performance by disabling unused functions and reducing the number "
97
+ "of requests."
98
+ msgstr ""
99
+ "Augmente les performances en désactivant les fonctions inutilisées et en "
100
+ "réduisant le nombre de requêtes."
101
+
102
+ #: pages/more-features.php:111
103
+ msgid "Site privacy"
104
+ msgstr "Confidentialité du site"
105
+
106
+ #: pages/more-features.php:113
107
+ msgid ""
108
+ "Allows you to hide the version of the site and plugins. Allows you to hide "
109
+ "your\n"
110
+ "\t\t\t\t\t\t\tWordPress."
111
+ msgstr ""
112
+ "Vous permet de masquer la version du site et des plugins. Vous permet de "
113
+ "cacher votre\n"
114
+ "\t\t\t\t\t\t\tWordPress."
115
+
116
+ #: pages/more-features.php:121
117
+ msgid "Easy setup"
118
+ msgstr "Configuration facile"
119
+
120
+ #: pages/more-features.php:123
121
+ msgid ""
122
+ "In quick mode, you can easily configure the plugin according to your needs."
123
+ msgstr ""
124
+ "En mode rapide, vous pouvez facilement configurer le plugin en fonction de "
125
+ "vos besoins."
126
+
127
+ #: pages/more-features.php:130
128
+ msgid "Get the ultimate plugin 100% FREE"
129
+ msgstr "Obtenez le plugin ultime 100% GRATUIT"
libs/factory/clearfy/langs/wbcr_factory_clearfy_203-ru_RU.mo ADDED
Binary file
libs/factory/clearfy/langs/wbcr_factory_clearfy_203-ru_RU.po ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: clearfy\n"
4
+ "POT-Creation-Date: 2017-10-14 13:50+0300\n"
5
+ "PO-Revision-Date: 2017-10-14 13:50+0300\n"
6
+ "Last-Translator: alex.kovalevv@gmail.com <alex.kovalevv@gmail.com>\n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.8.8\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: pages/more-features.php:27
21
+ msgid "More features (<b>free</b>)"
22
+ msgstr "Дополнительно"
23
+
24
+ #: pages/more-features.php:34
25
+ msgid "install the ultimate version of the plugin for free!"
26
+ msgstr "установите полную версию плагина бесплатно!"
27
+
28
+ #: pages/more-features.php:45
29
+ msgid "Code cleaning"
30
+ msgstr "Очищает код"
31
+
32
+ #: pages/more-features.php:47
33
+ msgid "Clears the source code of the page from unused code."
34
+ msgstr "Очищает исходный код страницы от неиспользуемого кода."
35
+
36
+ #: pages/more-features.php:54
37
+ msgid "Improve SEO"
38
+ msgstr "Улучшает SEO"
39
+
40
+ #: pages/more-features.php:56
41
+ msgid ""
42
+ "Removes duplicate pages, closes external links, changes the headers of the "
43
+ "server."
44
+ msgstr ""
45
+ "Удаляет дубликаты страниц, закрывает внешние ссылки, изменяет заголовки "
46
+ "сервера."
47
+
48
+ #: pages/more-features.php:63
49
+ msgid "Site ptotection"
50
+ msgstr "Защищает ваш сайт"
51
+
52
+ #: pages/more-features.php:65
53
+ msgid "Enables and disables features that improve the protection of your site."
54
+ msgstr "Включает и отключает функции, которые улучшают защиту вашего сайта."
55
+
56
+ #: pages/more-features.php:72
57
+ msgid "Disable comments"
58
+ msgstr "Отключает комментарии"
59
+
60
+ #: pages/more-features.php:74
61
+ msgid "Disables comments on the entire site or on specific pages."
62
+ msgstr "Отключает комментарии на всем сайте или у определенных страниц."
63
+
64
+ #: pages/more-features.php:81
65
+ msgid "Manage updates"
66
+ msgstr "Менеджер обновлений"
67
+
68
+ #: pages/more-features.php:83
69
+ msgid ""
70
+ "Enables or disables automatically updates for plugins, themes and core. It "
71
+ "is also possible\n"
72
+ "\t\t\t\t\t\t\tto disable all updates."
73
+ msgstr ""
74
+ "Включает или отключает автоматические обновление плагинов, тем и ядра. Также "
75
+ "возможно\n"
76
+ "отключение всех обновлений."
77
+
78
+ #: pages/more-features.php:91
79
+ msgid "Manage widgets"
80
+ msgstr "Управление виджетами"
81
+
82
+ #: pages/more-features.php:93
83
+ msgid "Allows you to remove unused widgets."
84
+ msgstr "Позволяет удалить неиспользуемые виджеты."
85
+
86
+ #: pages/more-features.php:100
87
+ msgid "Speed Optimization"
88
+ msgstr "Оптимизация производительности"
89
+
90
+ #: pages/more-features.php:102
91
+ msgid ""
92
+ "Increases performance by disabling unused functions and reducing the number "
93
+ "of requests."
94
+ msgstr ""
95
+ "Повышает производительность, отключая неиспользуемые функции и уменьшая "
96
+ "количество запросов."
97
+
98
+ #: pages/more-features.php:109
99
+ msgid "Site privacy"
100
+ msgstr "Конфиденциальность сайта"
101
+
102
+ #: pages/more-features.php:111
103
+ msgid ""
104
+ "Allows you to hide the version of the site and plugins. Allows you to hide "
105
+ "your\n"
106
+ "\t\t\t\t\t\t\tWordPress."
107
+ msgstr ""
108
+ "Позволяет скрыть версию сайта и плагинов. Позволяет скрыть ваш\n"
109
+ "WordPress."
110
+
111
+ #: pages/more-features.php:119
112
+ msgid "Easy setup"
113
+ msgstr "Простая настройка"
114
+
115
+ #: pages/more-features.php:121
116
+ msgid ""
117
+ "In quick mode, you can easily configure the plugin according to your needs."
118
+ msgstr ""
119
+ "В быстром режиме вы можете легко настроить плагин в соответствии с вашими "
120
+ "потребностями."
121
+
122
+ #: pages/more-features.php:128
123
+ msgid "Get the ultimate plugin 100% FREE"
124
+ msgstr "Получить полную версию бесплатно на 100%"
libs/factory/clearfy/pages/more-features.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The page Settings.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package clearfy
9
+ * @since 1.0.1
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryClearfy203_MoreFeaturesPage') ) {
18
+
19
+ class Wbcr_FactoryClearfy203_MoreFeaturesPage extends Wbcr_FactoryPages407_ImpressiveThemplate {
20
+
21
+ public $id = "more_features";
22
+
23
+ public $page_menu_dashicon = 'dashicons-star-filled wbcr-factory-orange-color';
24
+
25
+ public $page_menu_position = 5;
26
+
27
+ public $type = 'page';
28
+
29
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
30
+ {
31
+ $this->menu_title = __('More features (<b>free</b>)', 'wbcr_factory_clearfy_203');
32
+
33
+ parent::__construct($plugin);
34
+
35
+ $this->plugin = $plugin;
36
+ }
37
+
38
+ public function getPageTitle()
39
+ {
40
+ return __('install the ultimate version of the plugin for free!', 'wbcr_factory_clearfy_203');
41
+ }
42
+
43
+ public function showPageContent()
44
+ {
45
+ ?>
46
+ <div class="row">
47
+ <div class="col-sm-4">
48
+ <div class="wbcr-factory-feature-box">
49
+ <span class="dashicons dashicons-yes"></span>
50
+
51
+ <h3><?php _e('Code cleaning', 'wbcr_factory_clearfy_203')?></h3>
52
+
53
+ <p><?php _e('Clears the source code of the page from unused code.', 'wbcr_factory_clearfy_203')?></p>
54
+ </div>
55
+ </div>
56
+ <div class="col-sm-4">
57
+ <div class="wbcr-factory-feature-box">
58
+ <span class="dashicons dashicons-chart-bar"></span>
59
+
60
+ <h3><?php _e('Improve SEO', 'wbcr_factory_clearfy_203')?></h3>
61
+
62
+ <p><?php _e('Removes duplicate pages, closes external links, changes the headers of the server.', 'wbcr_factory_clearfy_203')?></p>
63
+ </div>
64
+ </div>
65
+ <div class="col-sm-4">
66
+ <div class="wbcr-factory-feature-box">
67
+ <span class="dashicons dashicons-shield-alt"></span>
68
+
69
+ <h3><?php _e('Site protection', 'wbcr_factory_clearfy_203')?></h3>
70
+
71
+ <p><?php _e('Enables and disables features that improve the protection of your site.', 'wbcr_factory_clearfy_203')?></p>
72
+ </div>
73
+ </div>
74
+ <div class="col-sm-4">
75
+ <div class="wbcr-factory-feature-box">
76
+ <span class="dashicons dashicons-welcome-comments"></span>
77
+
78
+ <h3><?php _e('Disable comments', 'wbcr_factory_clearfy_203')?></h3>
79
+
80
+ <p><?php _e('Disables comments on the entire site or on specific pages.', 'wbcr_factory_clearfy_203')?></p>
81
+ </div>
82
+ </div>
83
+ <div class="col-sm-4">
84
+ <div class="wbcr-factory-feature-box">
85
+ <span class="dashicons dashicons-update"></span>
86
+
87
+ <h3><?php _e('Manage updates', 'wbcr_factory_clearfy_203')?></h3>
88
+
89
+ <p><?php _e('Enables or disables automatically updates for plugins, themes and core. It is also possible
90
+ to disable all updates.', 'wbcr_factory_clearfy_203')?></p>
91
+ </div>
92
+ </div>
93
+ <div class="col-sm-4">
94
+ <div class="wbcr-factory-feature-box">
95
+ <span class="dashicons dashicons-admin-plugins"></span>
96
+
97
+ <h3><?php _e('Manage widgets', 'wbcr_factory_clearfy_203')?></h3>
98
+
99
+ <p><?php _e('Allows you to remove unused widgets.', 'wbcr_factory_clearfy_203')?></p>
100
+ </div>
101
+ </div>
102
+ <div class="col-sm-4">
103
+ <div class="wbcr-factory-feature-box">
104
+ <span class="dashicons dashicons-dashboard"></span>
105
+
106
+ <h3><?php _e('Speed Optimization', 'wbcr_factory_clearfy_203')?></h3>
107
+
108
+ <p><?php _e('Increases performance by disabling unused functions and reducing the number of requests.', 'wbcr_factory_clearfy_203')?></p>
109
+ </div>
110
+ </div>
111
+ <div class="col-sm-4">
112
+ <div class="wbcr-factory-feature-box">
113
+ <span class="dashicons dashicons-visibility"></span>
114
+
115
+ <h3><?php _e('Site privacy', 'wbcr_factory_clearfy_203')?></h3>
116
+
117
+ <p><?php _e('Allows you to hide the version of the site and plugins. Allows you to hide your
118
+ WordPress.', 'wbcr_factory_clearfy_203')?></p>
119
+ </div>
120
+ </div>
121
+ <div class="col-sm-4">
122
+ <div class="wbcr-factory-feature-box">
123
+ <span class="dashicons dashicons-admin-settings"></span>
124
+
125
+ <h3><?php _e('Easy setup', 'wbcr_factory_clearfy_203')?></h3>
126
+
127
+ <p><?php _e('In quick mode, you can easily configure the plugin according to your needs.', 'wbcr_factory_clearfy_203')?></p>
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ <div class="wbcr-factory-buttons-wrap">
133
+ <?php
134
+ $url = 'https://clearfy.pro';
135
+
136
+ if( get_locale() == 'ru_RU' ) {
137
+ $url = 'https://ru.clearfy.pro';
138
+ }
139
+ $url .= '?utm_source=wordpress.org&utm_campaign=' . $this->plugin->getPluginName();
140
+ ?>
141
+ <a href="<?= $url ?>" class="wbcr-factory-premium-button" target="_blank">
142
+ <?php _e('Get the ultimate plugin 100% FREE', 'wbcr_factory_clearfy_203')?>
143
+ </a>
144
+ </div>
145
+ <?php
146
+ }
147
+ }
148
+ }
libs/factory/core/boot.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Factory Plugin
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( defined('FACTORY_406_LOADED') ) {
18
+ return;
19
+ }
20
+ define('FACTORY_406_LOADED', true);
21
+
22
+ define('FACTORY_406_VERSION', '000');
23
+
24
+ define('FACTORY_406_DIR', dirname(__FILE__));
25
+ define('FACTORY_406_URL', plugins_url(null, __FILE__));
26
+
27
+ #comp merge
28
+ require_once(FACTORY_406_DIR . '/includes/functions.php');
29
+ require_once(FACTORY_406_DIR . '/includes/request.class.php');
30
+ require_once(FACTORY_406_DIR . '/includes/base.class.php');
31
+
32
+ require_once(FACTORY_406_DIR . '/includes/assets-managment/assets-list.class.php');
33
+ require_once(FACTORY_406_DIR . '/includes/assets-managment/script-list.class.php');
34
+ require_once(FACTORY_406_DIR . '/includes/assets-managment/style-list.class.php');
35
+
36
+ require_once(FACTORY_406_DIR . '/includes/plugin.class.php');
37
+
38
+ require_once(FACTORY_406_DIR . '/includes/activation/activator.class.php');
39
+ require_once(FACTORY_406_DIR . '/includes/activation/update.class.php');
40
+ #endcomp
libs/factory/core/includes/activation/activator.class.php ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains a base class for plugin activators.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+ // Exit if accessed directly
12
+ if( !defined('ABSPATH') ) {
13
+ exit;
14
+ }
15
+
16
+ if( !class_exists('Wbcr_Factory406_Activator') ) {
17
+ /**
18
+ * Plugin Activator
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ abstract class Wbcr_Factory406_Activator {
23
+
24
+ /**
25
+ * Curent plugin.
26
+ * @var Wbcr_Factory406_Plugin
27
+ */
28
+ public $plugin;
29
+
30
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
31
+ {
32
+ $this->plugin = $plugin;
33
+ }
34
+
35
+ public function activate()
36
+ {
37
+ }
38
+
39
+ public function deactivate()
40
+ {
41
+ }
42
+
43
+ public function update()
44
+ {
45
+ }
46
+
47
+ // --------------------------------------------------------------------------------
48
+ // Posts and pages
49
+ // --------------------------------------------------------------------------------
50
+
51
+ /**
52
+ * Adds post on activation.
53
+ * @return array Post info.
54
+ */
55
+ public function addPost()
56
+ {
57
+
58
+ $args_count = func_num_args();
59
+
60
+ $post_info_base = array();
61
+ $meta_info_base = array();
62
+
63
+ if( $args_count == 4 ) {
64
+
65
+ $base = func_get_arg(0);
66
+
67
+ $post_info_base = $base['post'];
68
+ $meta_info_base = $base['meta'];
69
+ }
70
+
71
+ $option_name = ($args_count == 4)
72
+ ? func_get_arg(1)
73
+ : func_get_arg(0);
74
+ $post_info = ($args_count == 4)
75
+ ? func_get_arg(2)
76
+ : func_get_arg(1);
77
+ $meta_info = ($args_count == 4)
78
+ ? func_get_arg(3)
79
+ : func_get_arg(2);
80
+
81
+ if( $post_info == null ) {
82
+ $post_info = array();
83
+ }
84
+ if( $meta_info == null ) {
85
+ $meta_info = array();
86
+ }
87
+
88
+ $post_info = array_merge($post_info_base, $post_info);
89
+ $meta_info = array_merge($meta_info_base, $meta_info);
90
+
91
+ $insert_id = $this->createPost($post_info, $meta_info, $option_name);
92
+
93
+ return array(
94
+ 'post_id' => $insert_id,
95
+ 'post' => $post_info,
96
+ 'meta' => $meta_info
97
+ );
98
+ }
99
+
100
+ /**
101
+ * * Adds a page on activation.
102
+ *
103
+ * @return int|null|string|WP_Error
104
+ */
105
+ public function addPage()
106
+ {
107
+ $option_name = func_get_arg(0);
108
+ $post_info = func_get_arg(1);
109
+ $meta_info = func_get_arg(2);
110
+
111
+ if( $post_info == null ) {
112
+ $post_info = array();
113
+ }
114
+ if( $meta_info == null ) {
115
+ $meta_info = array();
116
+ }
117
+
118
+ $post_info['post_type'] = 'page';
119
+
120
+ return $this->createPost($post_info, $meta_info, $option_name);
121
+ }
122
+
123
+ /**
124
+ * Creates post by using the specified info.
125
+ *
126
+ * @param array $post_info
127
+ * @param array $meta_info
128
+ * @param string $option_name
129
+ * @return int|null|string|WP_Error
130
+ */
131
+ public function createPost($post_info, $meta_info, $option_name)
132
+ {
133
+ global $wpdb;
134
+
135
+ $slug = $post_info['post_name'];
136
+ $post_type = $post_info['post_type'];
137
+
138
+ $postId = $wpdb->get_var($wpdb->prepare("SELECT ID FROM " . $wpdb->posts . " WHERE post_name = '%s' AND
139
+ post_type = '%s' LIMIT 1", $slug, $post_type));
140
+
141
+ $option_value = $this->plugin->getOption($option_name);
142
+
143
+ if( !$postId ) {
144
+ $create = true;
145
+
146
+ if( !empty($option_value) ) {
147
+ $post_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM " . $wpdb->posts . " WHERE ID = '%d' AND
148
+ post_type = '%s' LIMIT 1", $option_value, $post_type));
149
+ if( $post_id ) {
150
+ $create = false;
151
+ }
152
+ };
153
+
154
+ if( $create ) :
155
+ if( !isset($post_info['post_status']) ) {
156
+ $post_info['post_status'] = 'publish';
157
+ }
158
+
159
+ // '@' here is to hide unexpected output while plugin activation
160
+ $option_value = @wp_insert_post($post_info);
161
+ $postId = $option_value;
162
+ $this->plugin->updateOption($option_name, $option_value);
163
+ endif;
164
+ } else {
165
+ if( empty ($option_value) ) {
166
+ $this->plugin->updateOption($option_name, $postId);
167
+ }
168
+ }
169
+
170
+ $this->plugin->updateOption($option_name, $postId);
171
+
172
+ // adds meta
173
+ foreach($meta_info as $key => $value) {
174
+ if( $value === true ) {
175
+ $value = 'true';
176
+ }
177
+ if( $value === false ) {
178
+ $value = 'false';
179
+ }
180
+
181
+ add_post_meta($postId, $key, $value);
182
+ }
183
+
184
+ return $postId;
185
+ }
186
+ }
187
+ }
libs/factory/core/includes/activation/update.class.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains a base class for update items of plugins.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_Factory406_Update') ) {
18
+ /**
19
+ * Plugin Activator
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ abstract class Wbcr_Factory406_Update {
24
+
25
+ /**
26
+ * Current plugin
27
+ * @var Factory406_Plugin
28
+ */
29
+ var $plugin;
30
+
31
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
32
+ {
33
+ $this->plugin = $plugin;
34
+ }
35
+
36
+ abstract function install();
37
+ }
38
+ }
libs/factory/core/includes/assets-managment/assets-list.class.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The class contains a base class for all lists of assets.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+ if( !class_exists('Wbcr_Factory406_AssetsList') ) {
17
+ /**
18
+ * Assets List
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ class Wbcr_Factory406_AssetsList {
23
+
24
+ protected $all = array();
25
+ public $header_place = array();
26
+ public $footer_place = array();
27
+ public $required = array();
28
+
29
+ protected $default_place;
30
+
31
+ /**
32
+ * @var Wbcr_Factory406_Plugin
33
+ */
34
+ protected $plugin;
35
+
36
+ /**
37
+ * @param Wbcr_Factory406_Plugin $plugin
38
+ * @param bool $defaultIsFooter
39
+ */
40
+ public function __construct(Wbcr_Factory406_Plugin $plugin, $defaultIsFooter = true)
41
+ {
42
+ $this->plugin = $plugin;
43
+
44
+ if( $defaultIsFooter ) {
45
+ $this->default_place = &$this->footer_place;
46
+ }
47
+ if( !$defaultIsFooter ) {
48
+ $this->default_place = &$this->header_place;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Adds new items to the collection (default place).
54
+ * @param mixed
55
+ */
56
+ public function add()
57
+ {
58
+ foreach(func_get_args() as $item) {
59
+ $this->all[] = $item;
60
+ $this->default_place[] = $item;
61
+ }
62
+
63
+ return $this;
64
+ }
65
+
66
+ /**
67
+ * Remove items from the collection
68
+ * @return $this
69
+ */
70
+ public function deregister()
71
+ {
72
+ foreach(func_get_args() as $item) {
73
+
74
+ if( !is_string($item) ) {
75
+ return $this;
76
+ }
77
+
78
+ $key_in_all = array_search($item, $this->all);
79
+ $key_in_default_place = array_search($item, $this->default_place);
80
+ $key_in_header_place = array_search($item, $this->header_place);
81
+ $key_inFooterPlace = array_search($item, $this->footer_place);
82
+
83
+ if( $key_in_all ) {
84
+ unset($this->all[$key_in_all]);
85
+ }
86
+ if( $key_in_default_place ) {
87
+ unset($this->default_place[$key_in_default_place]);
88
+ }
89
+ if( $key_in_header_place ) {
90
+ unset($this->header_place[$key_in_header_place]);
91
+ }
92
+ if( $key_inFooterPlace ) {
93
+ unset($this->footer_place[$key_inFooterPlace]);
94
+ }
95
+ }
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * Adds new items to the collection (header).
102
+ * @param mixed
103
+ */
104
+ public function addToHeader()
105
+ {
106
+
107
+ foreach(func_get_args() as $item) {
108
+ $this->all[] = $item;
109
+ $this->header_place[] = $item;
110
+ }
111
+
112
+ return $this;
113
+ }
114
+
115
+ /**
116
+ * Adds new items to the collection (footer).
117
+ * @param mixed
118
+ */
119
+ public function addToFooter()
120
+ {
121
+
122
+ foreach(func_get_args() as $item) {
123
+ $this->all[] = $item;
124
+ $this->footer_place[] = $item;
125
+ }
126
+
127
+ return $this;
128
+ }
129
+
130
+ /**
131
+ * Checks whether the collection is empty.
132
+ *
133
+ * @param string $source if the 'bootstrap' specified, checks only whether the bootstrap assets were required.
134
+ * @return boolean
135
+ */
136
+ public function isEmpty($source = 'wordpress')
137
+ {
138
+ if( 'bootstrap' === $source ) {
139
+ return empty($this->required[$source]);
140
+ }
141
+
142
+ return empty($this->all) && empty($this->required);
143
+ }
144
+
145
+ public function IsHeaderEmpty()
146
+ {
147
+ return empty($this->header_place);
148
+ }
149
+
150
+ public function IsFooterEmpty()
151
+ {
152
+ return empty($this->footer_place);
153
+ }
154
+
155
+ /**
156
+ * Adds new items to the requried collection.
157
+ * @param mixed
158
+ */
159
+ public function request($items, $source = 'wordpress')
160
+ {
161
+
162
+ if( is_array($items) ) {
163
+ foreach($items as $item) {
164
+ $this->required[$source][] = $item;
165
+ }
166
+ } else {
167
+ $this->required[$source][] = $items;
168
+ }
169
+
170
+ return $this;
171
+ }
172
+ }
173
+ }
libs/factory/core/includes/assets-managment/script-list.class.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains a class to manage script assets.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_Factory406_ScriptList') ) {
18
+
19
+ /**
20
+ * Script List
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_Factory406_ScriptList extends Wbcr_Factory406_AssetsList {
25
+
26
+ public $localize_data = array();
27
+ public $use_ajax = false;
28
+
29
+ /**
30
+ * @param string $source
31
+ */
32
+ public function connect($source = 'wordpress')
33
+ {
34
+
35
+ // register all global required scripts
36
+ if( !empty($this->required[$source]) ) {
37
+ foreach($this->required[$source] as $script) {
38
+ if( 'wordpress' === $source ) {
39
+ wp_enqueue_script($script);
40
+ } elseif( 'bootstrap' === $source ) {
41
+ $this->plugin->bootstrap->enqueueScript($script);
42
+ }
43
+ }
44
+ }
45
+
46
+ if( $source == 'bootstrap' ) {
47
+ return;
48
+ }
49
+
50
+ $is_first_script = true;
51
+ $is_footer = false;
52
+
53
+ // register all other scripts
54
+ foreach(array($this->header_place, $this->footer_place) as $scriptPlace) {
55
+ foreach($scriptPlace as $script) {
56
+
57
+ wp_register_script($script, $script, array(), $this->plugin->getPluginVersion(), $is_footer);
58
+
59
+ if( $is_first_script && $this->use_ajax ) {
60
+ wp_localize_script($script, 'factory', array('ajaxurl' => admin_url('admin-ajax.php')));
61
+ }
62
+
63
+ if( !empty($this->localize_data[$script]) ) {
64
+
65
+ wp_localize_script($script, $this->localize_data[$script][0], $this->localize_data[$script][1]);
66
+ }
67
+
68
+ wp_enqueue_script($script);
69
+
70
+ $is_first_script = false;
71
+ }
72
+
73
+ $is_footer = true;
74
+ }
75
+ }
76
+
77
+ public function useAjax()
78
+ {
79
+ $this->use_ajax = true;
80
+ }
81
+
82
+ public function localize($varname, $data)
83
+ {
84
+ $bindTo = count($this->all) == 0
85
+ ? null
86
+ : end($this->all);
87
+
88
+ if( !$bindTo ) {
89
+ return;
90
+ }
91
+
92
+ $this->localize_data[$bindTo] = array($varname, $data);
93
+
94
+ return $this;
95
+ }
96
+ }
97
+ }
libs/factory/core/includes/assets-managment/style-list.class.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains a class to manage style assets.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_Factory406_StyleList') ) {
18
+
19
+ /**
20
+ * Style List
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_Factory406_StyleList extends Wbcr_Factory406_AssetsList {
25
+
26
+ public function connect($source = 'wordpress')
27
+ {
28
+
29
+ // register all global required scripts
30
+ if( !empty($this->required[$source]) ) {
31
+
32
+ foreach($this->required[$source] as $style) {
33
+ if( 'wordpress' === $source ) {
34
+ wp_enqueue_style($style);
35
+ } elseif( 'bootstrap' === $source ) {
36
+ $this->plugin->bootstrap->enqueueStyle($style);
37
+ }
38
+ }
39
+ }
40
+
41
+ if( $source == 'bootstrap' ) {
42
+ return;
43
+ }
44
+
45
+ // register all other styles
46
+ foreach($this->all as $style) {
47
+ wp_enqueue_style(md5($style), $style, array(), $this->plugin->getPluginVersion());
48
+ }
49
+ }
50
+ }
51
+ }
libs/factory/core/includes/base.class.php ADDED
@@ -0,0 +1,378 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if( !defined('ABSPATH') ) {
4
+ exit;
5
+ }
6
+
7
+ if( !class_exists('Wbcr_Factory406_Base') ) {
8
+ class Wbcr_Factory406_Base {
9
+
10
+ /**
11
+ * Буферизуем опции плагинов в этот атрибут, для быстрого доступа
12
+ *
13
+ * @var array
14
+ */
15
+ private static $_opt_buffer = array();
16
+
17
+ /**
18
+ * Префикс для пространства имен среди опций Wordpress
19
+ *
20
+ * @var string
21
+ */
22
+ protected $prefix;
23
+
24
+ /**
25
+ * Экзамеляр класса Wbcr_Factory406_Request, необходим управляет http запросами
26
+ *
27
+ * @var Wbcr_Factory406_Request
28
+ */
29
+ public $request;
30
+
31
+ public function __construct($plugin_path, $data)
32
+ {
33
+ $this->prefix = isset($data['prefix'])
34
+ ? $data['prefix']
35
+ : null;
36
+
37
+ if( empty($this->prefix) || !is_string($this->prefix) ) {
38
+ throw new Exception('Не передан один из обязательных атрибутов (prefix) или атрибует не соотвествует типу данных string.');
39
+ }
40
+
41
+ $this->request = new Wbcr_Factory406_Request();
42
+
43
+ if( !isset(self::$_opt_buffer[$this->prefix]) ) {
44
+ $cache_options = get_option($this->prefix . 'cache_options', array());
45
+
46
+ if( empty($cache_options) || !is_array($cache_options) ) {
47
+ $cache_options = array();
48
+ delete_option($this->prefix . 'cache_options');
49
+ }
50
+
51
+ self::$_opt_buffer[$this->prefix] = $cache_options;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Получает опцию из кеша или из базы данные, если опция не кешируемая,
57
+ * то опция тянется только из базы данных. Не кешируемые опции это массивы,
58
+ * сериализованные массивы, строки больше 150 символов
59
+ *
60
+ * @param string $option_name
61
+ * @param bool $default
62
+ * @return mixed|void
63
+ */
64
+ public function getOption($option_name, $default = false)
65
+ {
66
+ if( $option_name == 'cache_options' ) {
67
+ return $default;
68
+ }
69
+
70
+ $get_cache_option = $this->getOptionFromCache($option_name);
71
+
72
+ if( !is_null($get_cache_option) ) {
73
+ return $get_cache_option === false
74
+ ? $default
75
+ : $get_cache_option;
76
+ }
77
+
78
+ $option_value = get_option($this->prefix . $option_name);
79
+
80
+ if( $this->isCacheable($option_value) ) {
81
+ $this->setCacheOption($option_name, $this->normalizeValue($option_value));
82
+ }
83
+
84
+ return $option_value === false
85
+ ? $default
86
+ : $this->normalizeValue($option_value);
87
+ }
88
+
89
+ /**
90
+ * Обновляет опцию в базе данных и в кеше, кеш обновляется только кешируемых опций.
91
+ * Не кешируемые опции это массивы, сериализованные массивы, строки больше 150 символов
92
+ *
93
+ * @param string $option_name
94
+ * @param string $value
95
+ * @return void
96
+ */
97
+ public function updateOption($option_name, $value)
98
+ {
99
+ if( $this->isCacheable($value) ) {
100
+ $this->setCacheOption($option_name, $this->normalizeValue($value));
101
+ } else {
102
+ if( isset(self::$_opt_buffer[$this->prefix][$option_name]) ) {
103
+ unset(self::$_opt_buffer[$this->prefix][$option_name]);
104
+
105
+ $this->updateOption('cache_options', self::$_opt_buffer[$this->prefix]);
106
+ }
107
+ }
108
+
109
+ update_option($this->prefix . $option_name, $value);
110
+ }
111
+
112
+ /**
113
+ * Пакетное обновление опций, также метод пакетно обновляет кеш в базе данных
114
+ * и в буфере опций, кеш обновляется только кешируемых опций. Не кешируемые опции это массивы,
115
+ * сериализованные массивы, строки больше 150 символов
116
+ *
117
+ * @param array $options
118
+ * @return bool
119
+ */
120
+ public function updateOptions($options)
121
+ {
122
+ if( empty($options) ) {
123
+ return false;
124
+ }
125
+
126
+ foreach((array)$options as $option_name => $option_value) {
127
+ $this->updateOption($option_name, $option_value);
128
+ }
129
+
130
+ $this->updateCacheOptions($options);
131
+
132
+ return true;
133
+ }
134
+
135
+ /**
136
+ * Удаляет опцию из базы данных, если опция есть в кеше,
137
+ * индивидуально удаляет опцию из кеша.
138
+ *
139
+ * @param string $option_name
140
+ * @return void
141
+ */
142
+ public function deleteOption($option_name)
143
+ {
144
+ if( isset(self::$_opt_buffer[$this->prefix][$option_name]) ) {
145
+ unset(self::$_opt_buffer[$this->prefix][$option_name]);
146
+
147
+ $this->updateOption('cache_options', self::$_opt_buffer[$this->prefix]);
148
+ }
149
+
150
+ delete_option($this->prefix . $option_name . '_is_active');
151
+ delete_option($this->prefix . $option_name);
152
+ }
153
+
154
+ /**
155
+ * Пакетное удаление опций, после удаления опции происходит очистка кеша и буфера опций
156
+ *
157
+ * @param array $options
158
+ * @return void
159
+ */
160
+ public function deleteOptions($options)
161
+ {
162
+ if( !empty($options) ) {
163
+ foreach((array)$options as $option_name) {
164
+ if( isset(self::$_opt_buffer[$this->prefix]) ) {
165
+ unset(self::$_opt_buffer[$this->prefix]);
166
+ }
167
+
168
+ delete_option($this->prefix . $option_name . '_is_active');
169
+ delete_option($this->prefix . $option_name);
170
+ }
171
+
172
+ $this->updateOption('cache_options', self::$_opt_buffer[$this->prefix]);
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Сбрасывает кеш опций, удаляет кеш из базы данных и буфер опций
178
+ *
179
+ * @return bool
180
+ */
181
+ public function flushOptionsCache()
182
+ {
183
+ if( isset(self::$_opt_buffer[$this->prefix]) ) {
184
+ unset(self::$_opt_buffer[$this->prefix]);
185
+ self::$_opt_buffer[$this->prefix] = array();
186
+ }
187
+
188
+ $this->deleteOption('cache_options');
189
+ }
190
+
191
+ /**
192
+ * Получает все опций текущего плагина
193
+ *
194
+ * @param bool $is_cacheable - только кешируемые опции, кешируемые опции это массивы,
195
+ * сериализованные массивы, строки больше 150 символов
196
+ * @return array
197
+ */
198
+ protected function getAllPluginOptions($is_cacheable = true)
199
+ {
200
+ global $wpdb;
201
+ $options = array();
202
+
203
+ $request = $wpdb->get_results($wpdb->prepare("
204
+ SELECT option_name, option_value
205
+ FROM {$wpdb->prefix}options
206
+ WHERE option_name
207
+ LIKE '%s'", $this->prefix . "%"));
208
+
209
+ if( !empty($request) ) {
210
+ foreach((array)$request as $option) {
211
+ if( $is_cacheable && !$this->isCacheable($option->option_value) ) {
212
+ continue;
213
+ }
214
+ $options[$option->option_name] = $this->normalizeValue($option->option_value);
215
+ }
216
+ }
217
+
218
+ return $options;
219
+ }
220
+
221
+
222
+ /**
223
+ * Записывает только одну опцию в кеш базы данных и в буфер
224
+ *
225
+ * @param string $option_name
226
+ * @param string $value
227
+ * @return void
228
+ * @throws Exception
229
+ */
230
+ protected function setCacheOption($option_name, $value)
231
+ {
232
+ $this->setBufferOption($option_name, $value);
233
+
234
+ if( !empty(self::$_opt_buffer[$this->prefix]) ) {
235
+ $this->updateOption('cache_options', self::$_opt_buffer[$this->prefix]);
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Пакетное обновление опций в кеше и буфер опций,
241
+ * все записываемые опции приводятся к регламентированному типу данных
242
+ *
243
+ * @param array $options
244
+ * @return bool
245
+ * @throws Exception
246
+ */
247
+ protected function updateCacheOptions($options)
248
+ {
249
+ foreach((array)$options as $option_name => $value) {
250
+ $option_name = str_replace($this->prefix, '', $option_name);
251
+ $this->setBufferOption($option_name, $this->normalizeValue($value));
252
+ }
253
+
254
+ if( !empty(self::$_opt_buffer[$this->prefix]) ) {
255
+ $this->updateOption('cache_options', self::$_opt_buffer[$this->prefix]);
256
+ }
257
+
258
+ return false;
259
+ }
260
+
261
+ /**
262
+ * Получает опцию из кеша или буфера, если опция не найдена и буфер пуст,
263
+ * то заполняет буфер кеширумыми опциями, которые уже записаны в базу данных.
264
+ *
265
+ * @param string $option_name
266
+ * @return null
267
+ * @throws Exception
268
+ */
269
+ protected function getOptionFromCache($option_name)
270
+ {
271
+ if( empty(self::$_opt_buffer[$this->prefix]) ) {
272
+ $all_options = $this->getAllPluginOptions();
273
+
274
+ if( !empty($all_options) ) {
275
+ $this->updateCacheOptions($all_options);
276
+ }
277
+ }
278
+
279
+ $buffer_option = $this->getBufferOption($option_name);
280
+
281
+ if( !is_null($buffer_option) ) {
282
+ return $buffer_option;
283
+ }
284
+
285
+ return null;
286
+ }
287
+
288
+ /**
289
+ * Получает опцию из буфера опций
290
+ *
291
+ * @param string $option_name
292
+ * @return null|mixed
293
+ */
294
+ private function getBufferOption($option_name)
295
+ {
296
+ if( isset(self::$_opt_buffer[$this->prefix][$option_name]) ) {
297
+ return self::$_opt_buffer[$this->prefix][$option_name];
298
+ }
299
+
300
+ return null;
301
+ }
302
+
303
+ /**
304
+ * Записывает опции в буфер опций, если опция уже есть в буфере и их значения не совпадают,
305
+ * то новое значение перезаписывает старое
306
+ *
307
+ * @param string $option_name
308
+ * @param string $option_value
309
+ */
310
+ private function setBufferOption($option_name, $option_value)
311
+ {
312
+ if( !isset(self::$_opt_buffer[$this->prefix][$option_name]) ) {
313
+ self::$_opt_buffer[$this->prefix][$option_name] = $option_value;
314
+ } else {
315
+ if( self::$_opt_buffer[$this->prefix][$option_name] !== $option_value ) {
316
+ self::$_opt_buffer[$this->prefix][$option_name] = $option_value;
317
+ }
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Возвращает название опции в пространстве имен плагина
323
+ *
324
+ * @param string $option_name
325
+ * @return null|string
326
+ */
327
+ public function getOptionName($option_name)
328
+ {
329
+ $option_name = trim(rtrim($option_name));
330
+ if( empty($option_name) || !is_string($option_name) ) {
331
+ return null;
332
+ }
333
+
334
+ return $this->prefix . $option_name;
335
+ }
336
+
337
+ /**
338
+ * Проверяет является ли опция кешируемой. Кешируемые опции это массивы,
339
+ * сериализованные массивы, строки больше 150 символов.
340
+ *
341
+ * @param string $data - переданое значение опции
342
+ * @return bool
343
+ */
344
+ public function isCacheable($data)
345
+ {
346
+ if( (is_string($data) && (is_serialized($data) || strlen($data) > 150)) || is_array($data) ) {
347
+ return false;
348
+ }
349
+
350
+ return true;
351
+ }
352
+
353
+ /**
354
+ * Приведение значений опций к строгому типу данных
355
+ *
356
+ * @param $string
357
+ * @return bool|int
358
+ */
359
+ public function normalizeValue($string)
360
+ {
361
+ if( is_numeric($string) ) {
362
+ $number = intval($string);
363
+
364
+ if( strlen($number) != strlen($string) ) {
365
+ throw new Exception('Error converting data type to a number.');
366
+ }
367
+
368
+ return $number;
369
+ } else if( $string === 'false' ) {
370
+ return false;
371
+ } else if( $string === 'true' ) {
372
+ return true;
373
+ }
374
+
375
+ return $string;
376
+ }
377
+ }
378
+ }
libs/factory/core/includes/functions.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Factory Function Library
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( function_exists('wbcr_factory_406_set_lazy_redirect') ) {
18
+ /**
19
+ * Sets a lazy redirect.
20
+ *
21
+ * @since 3.0.6
22
+ * @return void
23
+ */
24
+ function wbcr_factory_406_set_lazy_redirect($url)
25
+ {
26
+ update_option('wbcr_factory_406_lazy_redirect', $url);
27
+ }
28
+ }
29
+
30
+ if( function_exists('wbcr_factory_406_do_lazy_redirect') ) {
31
+ function wbcr_factory_406_do_lazy_redirect()
32
+ {
33
+ $url = get_option('wbcr_factory_406_lazy_redirect', null);
34
+
35
+ if( empty($url) ) {
36
+ return;
37
+ }
38
+
39
+ delete_option('wbcr_factory_406_lazy_redirect');
40
+ wp_redirect($url);
41
+ }
42
+
43
+ add_action('admin_init', 'wbcr_factory_406_do_lazy_redirect');
44
+ }
45
+
46
+ /**
47
+ * Fires functions attached to a deprecated filter hook.
48
+ *
49
+ * When a filter hook is deprecated, the apply_filters() call is replaced with
50
+ * apply_filters_deprecated(), which triggers a deprecation notice and then fires
51
+ * the original filter hook.
52
+ *
53
+ * This is a copy of `apply_filters_deprecated` introduced in WP 4.6.
54
+ *
55
+ * @since 1.0.0
56
+ *
57
+ * @see wbcr_factory_406_deprecated_hook()
58
+ *
59
+ * @param string $tag The name of the filter hook.
60
+ * @param array $args Array of additional function arguments to be passed to apply_filters().
61
+ * @param string $version The version of BP Block Users that deprecated the hook.
62
+ * @param string $replacement Optional. The hook that should have been used.
63
+ * @param string $message Optional. A message regarding the change.
64
+ *
65
+ * @return mixed
66
+ */
67
+ function wbcr_factory_406_apply_filters_deprecated($tag, $args, $version, $replacement = false, $message = null)
68
+ {
69
+ if( function_exists('apply_filters_deprecated') ) {
70
+ return apply_filters_deprecated($tag, $args, $version, $replacement, $message);
71
+ }
72
+ if( !has_filter($tag) ) {
73
+ return $args[0];
74
+ }
75
+ wbcr_factory_406_deprecated_hook($tag, $version, $replacement, $message);
76
+
77
+ return apply_filters_ref_array($tag, $args);
78
+ }
79
+
80
+ /**
81
+ * Fires functions attached to a deprecated action hook.
82
+ *
83
+ * When an action hook is deprecated, the do_action() call is replaced with
84
+ * do_action_deprecated(), which triggers a deprecation notice and then fires
85
+ * the original hook.
86
+ *
87
+ * This is a copy of `do_action_deprecated` introduced in WP 4.6.
88
+ *
89
+ * @since 1.0.0
90
+ *
91
+ * @see _deprecated_hook()
92
+ *
93
+ * @param string $tag The name of the action hook.
94
+ * @param array $args Array of additional function arguments to be passed to do_action().
95
+ * @param string $version The version of BP Block Users that deprecated the hook.
96
+ * @param string $replacement Optional. The hook that should have been used.
97
+ * @param string $message Optional. A message regarding the change.
98
+ *
99
+ * @return void
100
+ */
101
+ function wbcr_factory_406_do_action_deprecated($tag, $args, $version, $replacement = false, $message = null)
102
+ {
103
+ if( function_exists('do_action_deprecated') ) {
104
+ do_action_deprecated($tag, $args, $version, $replacement, $message);
105
+
106
+ return;
107
+ }
108
+ if( !has_action($tag) ) {
109
+ return;
110
+ }
111
+ wbcr_factory_406_deprecated_hook($tag, $version, $replacement, $message);
112
+ do_action_ref_array($tag, $args);
113
+ }
114
+
115
+ /**
116
+ * Marks a deprecated action or filter hook as deprecated and throws a notice.
117
+ *
118
+ * Use the 'wbcr_factory_406_deprecated_hook_run' action to get the backtrace describing where the
119
+ * deprecated hook was called.
120
+ *
121
+ * Default behavior is to trigger a user error if WP_DEBUG is true.
122
+ *
123
+ * This function is called by the do_action_deprecated() and apply_filters_deprecated()
124
+ * functions, and so generally does not need to be called directly.
125
+ *
126
+ * This is a copy of `_deprecated_hook` introduced in WP 4.6.
127
+ *
128
+ * @since 1.0.0
129
+ * @access private
130
+ *
131
+ * @param string $hook The hook that was used.
132
+ * @param string $version The version of WordPress that deprecated the hook.
133
+ * @param string $replacement Optional. The hook that should have been used.
134
+ * @param string $message Optional. A message regarding the change.
135
+ */
136
+ function wbcr_factory_406_deprecated_hook($hook, $version, $replacement = null, $message = null)
137
+ {
138
+ /**
139
+ * Fires when a deprecated hook is called.
140
+ *
141
+ * @since 1.0.0
142
+ *
143
+ * @param string $hook The hook that was called.
144
+ * @param string $replacement The hook that should be used as a replacement.
145
+ * @param string $version The version of BP Block Users that deprecated the argument used.
146
+ * @param string $message A message regarding the change.
147
+ */
148
+ do_action('deprecated_hook_run', $hook, $replacement, $version, $message);
149
+
150
+ /**
151
+ * Filter whether to trigger deprecated hook errors.
152
+ *
153
+ * @since 1.0.0
154
+ *
155
+ * @param bool $trigger Whether to trigger deprecated hook errors. Requires
156
+ * `WP_DEBUG` to be defined true.
157
+ */
158
+ if( WP_DEBUG && apply_filters('deprecated_hook_trigger_error', true) ) {
159
+ $message = empty($message)
160
+ ? ''
161
+ : ' ' . $message;
162
+ if( !is_null($replacement) ) {
163
+ trigger_error(sprintf(__('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $hook, $version, $replacement) . $message);
164
+ } else {
165
+ trigger_error(sprintf(__('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $hook, $version) . $message);
166
+ }
167
+ }
168
+ }
169
+
libs/factory/core/includes/plugin.class.php ADDED
@@ -0,0 +1,913 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class to register a plugin in the Factory.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018 Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_Factory406_Plugin') ) {
18
+
19
+ abstract class Wbcr_Factory406_Plugin extends Wbcr_Factory406_Base {
20
+
21
+ /**
22
+ * Is a current page one of the admin pages?
23
+ *
24
+ * @since 1.0.0
25
+ * @var bool
26
+ */
27
+ public $is_admin;
28
+
29
+ /**
30
+ * The Bootstrap Manager class.n.
31
+ *
32
+ * @var Wbcr_FactoryBootstrap406_Manager
33
+ */
34
+ public $bootstrap;
35
+
36
+ /**
37
+ * The Bootstrap Manager class.n.
38
+ *
39
+ * @var Wbcr_FactoryForms407_Manager
40
+ */
41
+ public $forms;
42
+
43
+ /**
44
+ * Заголовок плагина
45
+ *
46
+ * @var string
47
+ */
48
+ protected $plugin_title;
49
+
50
+ /**
51
+ * Название плагина
52
+ *
53
+ * @var string
54
+ */
55
+ protected $plugin_name;
56
+
57
+ /**
58
+ * Версия плагина
59
+ *
60
+ * @var string
61
+ */
62
+ protected $plugin_version;
63
+
64
+ /**
65
+ * Тип сборки плагина. Возможнные варианты: free, premium, trial
66
+ *
67
+ * @var string
68
+ */
69
+ protected $plugin_build;
70
+
71
+ /**
72
+ * @var string
73
+ */
74
+ protected $plugin_assembly;
75
+
76
+ /**
77
+ * Абсолютный путь к основному файлу плагина.
78
+ *
79
+ * @var string
80
+ */
81
+ protected $main_file;
82
+
83
+ /**
84
+ * Абсолютный путь к директории плагина
85
+ *
86
+ * @var string
87
+ */
88
+ protected $plugin_root;
89
+
90
+ /**
91
+ * Относительный путь к директории плагина
92
+ *
93
+ * @var string
94
+ */
95
+ protected $relative_path;
96
+
97
+ /**
98
+ * Ссылка на директорию плагина
99
+ *
100
+ * @var string
101
+ */
102
+ protected $plugin_url;
103
+
104
+ /**
105
+ * A class name of an activator to activate the plugin.
106
+ *
107
+ * @var string
108
+ */
109
+ protected $activator_class = array();
110
+
111
+ /**
112
+ * Путь к директории миграций. В этой директории хранятся миграции для разных версий плагина.
113
+ * По умолчанию plugin_dir/updates
114
+ * @var string
115
+ */
116
+ protected $updates;
117
+
118
+ /**
119
+ * Подключенные компоненнты плагина
120
+ *
121
+ * @var array[] Wbcr_Factory406_Plugin
122
+ */
123
+ private $plugin_addons;
124
+
125
+ /**
126
+ * @var array
127
+ */
128
+ private $plugin_data;
129
+
130
+ /**
131
+ * Creates an instance of Factory plugin.
132
+ *
133
+ * @param string $plugin_path A full path to the main plugin file.
134
+ * @param array $data A set of plugin data.
135
+ * @since 1.0.0
136
+ * @throws Exception
137
+ */
138
+ public function __construct($plugin_path, $data)
139
+ {
140
+ $this->plugin_data = $data;
141
+
142
+ parent::__construct($plugin_path, $data);
143
+
144
+ foreach((array)$data as $option_name => $option_value) {
145
+ if( property_exists($this, $option_name) ) {
146
+ $this->$option_name = $option_value;
147
+ }
148
+ }
149
+
150
+ $this->is_admin = is_admin();
151
+
152
+ if( empty($this->prefix) || empty($this->plugin_title) || empty($this->plugin_version) || empty($this->plugin_build) ) {
153
+ throw new Exception('One of the required attributes has not been passed (prefix,plugin_title,plugin_name,plugin_version,plugin_build).');
154
+ }
155
+
156
+ // saves plugin basic paramaters
157
+ $this->main_file = $plugin_path;
158
+ $this->plugin_root = dirname($plugin_path);
159
+ $this->relative_path = plugin_basename($plugin_path);
160
+ $this->plugin_url = plugins_url(null, $plugin_path);
161
+
162
+ // used only in the module 'updates'
163
+ $this->plugin_slug = !empty($this->plugin_name)
164
+ ? $this->plugin_name
165
+ : basename($plugin_path);
166
+
167
+ if( empty($this->updates) && file_exists($this->plugin_root . '/updates') ) {
168
+ $this->updates = $this->plugin_root . '/updates';
169
+ }
170
+
171
+ // init actions
172
+ $this->setupActions();
173
+
174
+ // register activation hooks
175
+ if( is_admin() ) {
176
+ register_activation_hook($this->main_file, array($this, 'forceActivationHook'));
177
+ register_deactivation_hook($this->main_file, array($this, 'deactivationHook'));
178
+ }
179
+ }
180
+
181
+ /**
182
+ * @return string
183
+ */
184
+ public function getPluginTitle()
185
+ {
186
+ return $this->plugin_title;
187
+ }
188
+
189
+ /**
190
+ * @return string
191
+ */
192
+ public function getPrefix()
193
+ {
194
+ return $this->prefix;
195
+ }
196
+
197
+ /**
198
+ * @return string
199
+ */
200
+ public function getPluginName()
201
+ {
202
+ return $this->plugin_name;
203
+ }
204
+
205
+ /**
206
+ * @return string
207
+ */
208
+ public function getPluginVersion()
209
+ {
210
+ return $this->plugin_version;
211
+ }
212
+
213
+ /**
214
+ * @return string
215
+ */
216
+ public function getPluginBuild()
217
+ {
218
+ return $this->plugin_build;
219
+ }
220
+
221
+ /**
222
+ * @return string
223
+ */
224
+ public function getPluginAssembly()
225
+ {
226
+ return $this->plugin_assembly;
227
+ }
228
+
229
+ /**
230
+ * @return stdClass
231
+ */
232
+ public function getPluginPathInfo()
233
+ {
234
+
235
+ $object = new stdClass;
236
+
237
+ $object->main_file = $this->main_file;
238
+ $object->plugin_root = $this->plugin_root;
239
+ $object->relative_path = $this->relative_path;
240
+ $object->plugin_url = $this->plugin_url;
241
+
242
+ return $object;
243
+ }
244
+
245
+ /**
246
+ * @param $attr_name
247
+ * @return null
248
+ */
249
+ public function getPluginInfoAttr($attr_name)
250
+ {
251
+ if( isset($this->plugin_data[$attr_name]) ) {
252
+ return $this->plugin_data[$attr_name];
253
+ }
254
+
255
+ return null;
256
+ }
257
+
258
+ /**
259
+ * @return object
260
+ */
261
+ public function getPluginInfo()
262
+ {
263
+ return (object)$this->plugin_data;
264
+ }
265
+
266
+ /**
267
+ * @param Wbcr_FactoryBootstrap406_Manager $bootstrap
268
+ */
269
+ public function setBootstap(Wbcr_FactoryBootstrap406_Manager $bootstrap)
270
+ {
271
+ $this->bootstrap = $bootstrap;
272
+ }
273
+
274
+ /**
275
+ * @param Wbcr_FactoryForms407_Manager $forms
276
+ */
277
+ public function setForms(Wbcr_FactoryForms407_Manager $forms)
278
+ {
279
+ $this->forms = $forms;
280
+ }
281
+
282
+ /**
283
+ * @param string $class_name
284
+ * @param string $path
285
+ */
286
+ public function registerPage($class_name, $file_path)
287
+ {
288
+
289
+ if( !file_exists($file_path) ) {
290
+ throw new Exception('The page file was not found by the path {' . $file_path . '} you set.');
291
+ }
292
+
293
+ require_once($file_path);
294
+
295
+ if( !class_exists($class_name) ) {
296
+ throw new Exception('A class with this name {' . $class_name . '} does not exist.');
297
+ }
298
+
299
+ if( !class_exists('Wbcr_FactoryPages407') ) {
300
+ throw new Exception('The factory_pages_407 module is not included.');
301
+ }
302
+
303
+ Wbcr_FactoryPages407::register($this, $class_name);
304
+ }
305
+
306
+ /**
307
+ * @param string $class_name
308
+ * @param string $path
309
+ */
310
+ public function registerType($class_name, $file_path)
311
+ {
312
+
313
+ if( !file_exists($file_path) ) {
314
+ throw new Exception('The page file was not found by the path {' . $file_path . '} you set.');
315
+ }
316
+
317
+ require_once($file_path);
318
+
319
+ if( !class_exists($class_name) ) {
320
+ throw new Exception('A class with this name {' . $class_name . '} does not exist.');
321
+ }
322
+
323
+ if( !class_exists('Wbcr_FactoryTypes000') ) {
324
+ throw new Exception('The factory_types_000 module is not included.');
325
+ }
326
+
327
+ Wbcr_FactoryTypes000::register($class_name, $this);
328
+ }
329
+
330
+ /**
331
+ * Loads modules required for a plugin.
332
+ *
333
+ * @since 3.2.0
334
+ * @param mixed[] $modules
335
+ * @return void
336
+ */
337
+ protected function load($modules = array())
338
+ {
339
+ foreach($modules as $module) {
340
+ $this->loadModule($module);
341
+ }
342
+
343
+ do_action('wbcr_factory_406_core_modules_loaded-' . $this->plugin_name);
344
+ }
345
+
346
+ /**
347
+ * Загружает аддоны для плагина, как часть проекта, а не как отдельный плагин
348
+ * @param array $addons - массив со списком загружаемых аддонов.
349
+ * array(
350
+ * 'hide_login_page' => - ключ, идентификатора массива с информацией об аддоне
351
+ * array(
352
+ * 'WHLP_Plugin', - имя основного класса аддона
353
+ * WCL_PLUGIN_DIR . '/components/hide-login-page/hide-login-page.php' - пусть к основному файлу аддона
354
+ * ));
355
+ */
356
+ protected function loadAddons($addons)
357
+ {
358
+ if( empty($addons) ) {
359
+ return;
360
+ }
361
+
362
+ foreach($addons as $addon_name => $addon_path) {
363
+ if( !isset($this->plugin_addons[$addon_name]) ) {
364
+
365
+ // При подключении аддона, мы объявляем константу, что такой аддон уже загружен
366
+ // $addon_name индентификатор аддона в вверхнем регистре
367
+ $const_name = strtoupper('LOADING_' . str_replace('-', '_', $addon_name) . '_AS_ADDON');
368
+
369
+ if( !defined($const_name) ) {
370
+ define($const_name, true);
371
+ }
372
+
373
+ require_once($addon_path[1]);
374
+
375
+ // Передаем аддону информацию о родительском плагине
376
+ $plugin_data = $this->plugin_data;
377
+
378
+ // Устанавливаем метку для аддона, которая указывает на то, что это аддон
379
+ $plugin_data['as_addon'] = true;
380
+
381
+ // Передаем класс родителя в аддон, для того,
382
+ // чтобы аддон использовал экземпляр класса родителя, а не создавал свой собственный.
383
+ $plugin_data['plugin_parent'] = $this;
384
+
385
+ // Создаем экземпляр класса аддона и записываем его в список загруженных аддонов
386
+ if( class_exists($addon_path[0]) ) {
387
+ $this->plugin_addons[$addon_name] = new $addon_path[0]($this->main_file, $plugin_data);
388
+ }
389
+ }
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Загружает специальные модули для расширения фреймворка "Factory"
395
+ *
396
+ * @since 3.2.0
397
+ * @param array $module - массив с информацией о загружаемом модуле,
398
+ * пример array('libs/factory/bootstrap', 'factory_bootstrap_406', 'admin'),
399
+ * $module[0] - относительный путь к директории модуля
400
+ * $module[1] - идентификатор модуля с префиксом 000
401
+ * $module[2] - область применения,
402
+ * admin - модуль будет загружен только в админ панели,
403
+ * public - будет загружен только на фронтенде
404
+ * all - модуль будет загружен везде
405
+ * @return void
406
+ */
407
+ protected function loadModule($module)
408
+ {
409
+ $scope = isset($module[2])
410
+ ? $module[2]
411
+ : 'all';
412
+
413
+ if( $scope == 'all' || (is_admin() && $scope == 'admin') || (!is_admin() && $scope == 'public') ) {
414
+
415
+ if( !file_exists($this->plugin_root . '/' . $module[0] . '/boot.php') ) {
416
+ throw new Exception('Module ' . $module[1] . ' is not included.');
417
+ }
418
+
419
+ require_once $this->plugin_root . '/' . $module[0] . '/boot.php';
420
+ do_action('wbcr_' . $module[1] . '_plugin_created', $this);
421
+ }
422
+ }
423
+
424
+ /**
425
+ * Registers a class to activate the plugin.
426
+ *
427
+ * @since 1.0.0
428
+ * @param string $className class name of the plugin activator.
429
+ * @return void
430
+ */
431
+ public function registerActivation($className)
432
+ {
433
+ $this->activator_class[] = $className;
434
+ }
435
+
436
+ /**
437
+ * Setups actions related with the Factory Plugin.
438
+ *
439
+ * @since 1.0.0
440
+ */
441
+ private function setupActions()
442
+ {
443
+ add_action('init', array($this, 'checkPluginVersioninDatabase'));
444
+
445
+ if( $this->is_admin ) {
446
+ add_action('admin_init', array($this, 'customizePluginRow'), 20);
447
+ /*add_action('wbcr_factory_406_core_modules_loaded-' . $this->plugin_name, array(
448
+ $this,
449
+ 'modulesLoaded'
450
+ ));*/
451
+ }
452
+ }
453
+
454
+ /**
455
+ * Checks the plugin version in database. If it's not the same as the currernt,
456
+ * it means that the plugin was updated and we need to execute the update hook.
457
+ *
458
+ * Calls on the hook "plugins_loaded".
459
+ *
460
+ * @since 1.0.0
461
+ * @return void
462
+ */
463
+ public function checkPluginVersioninDatabase()
464
+ {
465
+
466
+ // checks whether the plugin needs to run updates.
467
+ if( $this->is_admin ) {
468
+ $plugin_version = $this->getPluginVersionFromDatabase();
469
+
470
+ if( $plugin_version != $this->plugin_build . '-' . $this->plugin_version ) {
471
+ $this->activationOrUpdateHook(false);
472
+ }
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Returns the plugin version from database.
478
+ *
479
+ * @since 1.0.0
480
+ * @return string|null The plugin version registered in the database.
481
+ */
482
+ public function getPluginVersionFromDatabase()
483
+ {
484
+ $plugin_versions = get_option('factory_plugin_versions', array());
485
+ $plugin_version = isset ($plugin_versions[$this->plugin_name])
486
+ ? $plugin_versions[$this->plugin_name]
487
+ : null;
488
+
489
+ return $plugin_version;
490
+ }
491
+
492
+ /**
493
+ * Registers in the database a new version of the plugin.
494
+ *
495
+ * @since 1.0.0
496
+ * @return void
497
+ */
498
+ public function updatePluginVersionInDatabase()
499
+ {
500
+ $plugin_versions = get_option('factory_plugin_versions', array());
501
+ $plugin_versions[$this->plugin_name] = $this->plugin_build . '-' . $this->plugin_version;
502
+ update_option('factory_plugin_versions', $plugin_versions);
503
+ }
504
+
505
+ /**
506
+ * Customize the plugin row (on the page plugins.php).
507
+ *
508
+ * Calls on the hook "admin_init".
509
+ *
510
+ * @since 1.0.0
511
+ * @return void
512
+ */
513
+ public function customizePluginRow()
514
+ {
515
+ remove_action("after_plugin_row_" . $this->relative_path, 'wp_plugin_update_row');
516
+ add_action("after_plugin_row_" . $this->relative_path, array($this, 'showCustomPluginRow'), 10, 2);
517
+ }
518
+
519
+ public function activate()
520
+ {
521
+ $this->forceActivationHook();
522
+ }
523
+
524
+ public function deactivate()
525
+ {
526
+ $this->deactivationHook();
527
+ }
528
+
529
+ /**
530
+ * Executes an activation hook for this plugin immediately.
531
+ *
532
+ * @since 1.0.0
533
+ * @return void
534
+ */
535
+ public function forceActivationHook()
536
+ {
537
+ $this->activationOrUpdateHook(true);
538
+ }
539
+
540
+ /**
541
+ * Executes an activation hook or an update hook.
542
+ *
543
+ * @param bool $forceActivation If true, then executes an activation hook.
544
+ * @since 1.0.0
545
+ * @return void
546
+ */
547
+ public function activationOrUpdateHook($force_activation = false)
548
+ {
549
+
550
+ $db_version = $this->getPluginVersionFromDatabase();
551
+ do_action('wbcr_factory_406_plugin_activation_or_update_' . $this->plugin_name, $force_activation, $db_version, $this);
552
+
553
+ // there are not any previous version of the plugin in the past
554
+ if( !$db_version ) {
555
+ $this->activationHook();
556
+
557
+ $this->updatePluginVersionInDatabase();
558
+
559
+ return;
560
+ }
561
+
562
+ $parts = explode('-', $db_version);
563
+ $prevous_build = $parts[0];
564
+ $prevous_version = $parts[1];
565
+
566
+ // if another build was used previously
567
+ if( $prevous_build != $this->plugin_build ) {
568
+ $this->migrationHook($prevous_build, $this->plugin_build);
569
+ $this->activationHook();
570
+
571
+ $this->updatePluginVersionInDatabase();
572
+
573
+ return;
574
+ }
575
+
576
+ // if another less version was used previously
577
+ if( version_compare($prevous_version, $this->plugin_version, '<') ) {
578
+ $this->updateHook($prevous_version, $this->plugin_version);
579
+ }
580
+
581
+ // standart plugin activation
582
+ if( $force_activation ) {
583
+ $this->activationHook();
584
+ }
585
+
586
+ // else nothing to do
587
+ $this->updatePluginVersionInDatabase();
588
+
589
+ return;
590
+ }
591
+
592
+ /**
593
+ * It's invoked on plugin activation. Don't excite it directly.
594
+ *
595
+ * @since 1.0.0
596
+ * @return void
597
+ */
598
+ public function activationHook()
599
+ {
600
+ $cancelled = apply_filters('wbcr_factory_406_cancel_plugin_activation_' . $this->plugin_name, false);
601
+
602
+ if( $cancelled ) {
603
+ return;
604
+ }
605
+
606
+ if( !empty($this->activator_class) ) {
607
+ foreach((array)$this->activator_class as $activator_class) {
608
+ $activator = new $activator_class($this);
609
+ $activator->activate();
610
+ }
611
+ }
612
+
613
+ do_action('wbcr_factory_406_plugin_activation', $this);
614
+ do_action('wbcr_factory_406_plugin_activation_' . $this->plugin_name, $this);
615
+
616
+ // just time to know when the plugin was activated the first time
617
+ $activated = $this->getOption('factory_406_plugin_activated_' . $this->plugin_name, 0);
618
+
619
+ if( !$activated ) {
620
+ $this->updateOption('factory_406_plugin_activated_' . $this->plugin_name, time());
621
+ }
622
+ }
623
+
624
+ /**
625
+ * It's invoked on plugin deactionvation. Don't excite it directly.
626
+ *
627
+ * @since 1.0.0
628
+ * @return void
629
+ */
630
+ public function deactivationHook()
631
+ {
632
+ $cancelled = apply_filters('wbcr_factory_406_cancel_plugin_deactivation_' . $this->plugin_name, false);
633
+
634
+ if( $cancelled ) {
635
+ return;
636
+ }
637
+
638
+ do_action('wbcr_factory_406_plugin_deactivation', $this);
639
+ do_action('wbcr_factory_406_plugin_deactivation_' . $this->plugin_name, $this);
640
+
641
+ if( !empty($this->activator_class) ) {
642
+ foreach((array)$this->activator_class as $activator_class) {
643
+ $activator = new $activator_class($this);
644
+ $activator->deactivate();
645
+ }
646
+ }
647
+ }
648
+
649
+ /**
650
+ * Finds migration items and install ones.
651
+ *
652
+ * @since 1.0.0
653
+ * @return void
654
+ */
655
+ public function migrationHook($previos_build, $current_build)
656
+ {
657
+ $migration_file = $this->updates . $previos_build . '-' . $current_build . '.php';
658
+ if( !file_exists($migration_file) ) {
659
+ return;
660
+ }
661
+
662
+ $classes = $this->getClasses($migration_file);
663
+ if( count($classes) == 0 ) {
664
+ return;
665
+ }
666
+
667
+ include_once($migration_file);
668
+ $migrationClass = $classes[0]['name'];
669
+
670
+ $migrationItem = new $migrationClass($this);
671
+ $migrationItem->install();
672
+ }
673
+
674
+ /**
675
+ * Finds upate items and install the ones.
676
+ *
677
+ * @since 1.0.0
678
+ * @return void
679
+ */
680
+ public function updateHook($old, $new)
681
+ {
682
+
683
+ // converts versions like 0.0.0 to 000000
684
+ $old_number = $this->getVersionNumber($old);
685
+ $new_number = $this->getVersionNumber($new);
686
+
687
+ $update_files = $this->updates;
688
+ $files = $this->findFiles($update_files);
689
+
690
+ if( empty($files) ) {
691
+ return;
692
+ }
693
+
694
+ // finds updates that has intermediate version
695
+ foreach($files as $item) {
696
+ if( !preg_match('/^\d+$/', $item['name']) ) {
697
+ continue;
698
+ }
699
+
700
+ $item_number = intval($item['name']);
701
+ if( $item_number > $old_number && $item_number <= $new_number ) {
702
+
703
+ $classes = $this->getClasses($item['path']);
704
+ if( count($classes) == 0 ) {
705
+ return;
706
+ }
707
+
708
+ foreach($classes as $path => $class_data) {
709
+ include_once($path);
710
+ $update_class = $class_data['name'];
711
+
712
+ $update = new $update_class($this);
713
+ $update->install();
714
+ }
715
+ }
716
+ }
717
+
718
+ // just time to know when the plugin was activated the first time
719
+ $activated = $this->getOption('factory_406_plugin_activated_' . $this->plugin_name, 0);
720
+
721
+ if( !$activated ) {
722
+ $this->updateOption('factory_406_plugin_activated_' . $this->plugin_name, time());
723
+ }
724
+ }
725
+
726
+ /**
727
+ * Converts string representation of the version to the numeric.
728
+ *
729
+ * @since 1.0.0
730
+ * @param string $version A string version to convert.
731
+ * @return integer
732
+ */
733
+ protected function getVersionNumber($version)
734
+ {
735
+ preg_match('/(\d+)\.(\d+)\.(\d+)/', $version, $matches);
736
+ if( count($matches) == 0 ) {
737
+ return false;
738
+ }
739
+
740
+ $number = '';
741
+ $number .= (strlen($matches[1]) == 1)
742
+ ? '0' . $matches[1]
743
+ : $matches[1];
744
+ $number .= (strlen($matches[2]) == 1)
745
+ ? '0' . $matches[2]
746
+ : $matches[2];
747
+ $number .= (strlen($matches[3]) == 1)
748
+ ? '0' . $matches[3]
749
+ : $matches[3];
750
+
751
+ return intval($number);
752
+ }
753
+
754
+ /**
755
+ * Forces modules.
756
+ *
757
+ * @since 1.0.0
758
+ * @return void
759
+ */
760
+ //public function modulesLoaded()
761
+ //{
762
+ // factory_core_000_modules_loaded( $this );
763
+ //}
764
+
765
+ // ----------------------------------------------------------------------
766
+ // Plugin row on plugins.php page
767
+ // ----------------------------------------------------------------------
768
+
769
+ public function showCustomPluginRow($file, $plugin_data)
770
+ {
771
+ if( !is_network_admin() && is_multisite() ) {
772
+ return;
773
+ }
774
+
775
+ $messages = apply_filters('wbcr_factory_406_plugin_row_' . $this->plugin_name, array(), $file, $plugin_data);
776
+
777
+ // if nothign to show then, use default handle
778
+ /*if( count($messages) == 0 ) {
779
+ wp_plugin_update_row($file, $plugin_data);
780
+
781
+ return;
782
+ }*/
783
+
784
+ if( empty($messages) ) {
785
+ return;
786
+ }
787
+
788
+ $wp_list_table = _get_list_table('WP_Plugins_List_Table');
789
+
790
+ foreach($messages as $message) {
791
+ echo '<tr class="plugin-update-tr active">';
792
+ echo '<td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">';
793
+ echo '<div class="update-message notice inline notice-error notice-alt">';
794
+ echo '<p>' . $message . '</p>';
795
+ echo '</div>';
796
+ echo '</td></tr>';
797
+ }
798
+ }
799
+
800
+ // ----------------------------------------------------------------------
801
+ // Finding files
802
+ // ----------------------------------------------------------------------
803
+
804
+ /**
805
+ * Returns a list of files at a given path.
806
+ * @param string $path path for search
807
+ */
808
+ private function findFiles($path)
809
+ {
810
+ return $this->findFileOrFolders($path, true);
811
+ }
812
+
813
+ /**
814
+ * Returns a list of folders at a given path.
815
+ * @param string $path path for search
816
+ */
817
+ private function findFolders($path)
818
+ {
819
+ return $this->findFileOrFolders($path, false);
820
+ }
821
+
822
+ /**
823
+ * Returns a list of files or folders at a given path.
824
+ * @param string $path path for search
825
+ * @param bool $files files or folders?
826
+ */
827
+ private function findFileOrFolders($path, $areFiles = true)
828
+ {
829
+ if( !is_dir($path) ) {
830
+ return array();
831
+ }
832
+
833
+ $entries = scandir($path);
834
+ if( empty($entries) ) {
835
+ return array();
836
+ }
837
+
838
+ $files = array();
839
+ foreach($entries as $entryName) {
840
+ if( $entryName == '.' || $entryName == '..' ) {
841
+ continue;
842
+ }
843
+
844
+ $filename = $path . '/' . $entryName;
845
+ if( ($areFiles && is_file($filename)) || (!$areFiles && is_dir($filename)) ) {
846
+ $files[] = array(
847
+ 'path' => str_replace("\\", "/", $filename),
848
+ 'name' => $areFiles
849
+ ? str_replace('.php', '', $entryName)
850
+ : $entryName
851
+ );
852
+ }
853
+ }
854
+
855
+ return $files;
856
+ }
857
+
858
+ /**
859
+ * Gets php classes defined in a specified file.
860
+ * @param string $path
861
+ */
862
+ private function getClasses($path)
863
+ {
864
+
865
+ $phpCode = file_get_contents($path);
866
+
867
+ $classes = array();
868
+ $tokens = token_get_all($phpCode);
869
+
870
+ $count = count($tokens);
871
+ for($i = 2; $i < $count; $i++) {
872
+ if( is_array($tokens) && $tokens[$i - 2][0] == T_CLASS && $tokens[$i - 1][0] == T_WHITESPACE && $tokens[$i][0] == T_STRING ) {
873
+
874
+ $extends = null;
875
+ if( $tokens[$i + 2][0] == T_EXTENDS && $tokens[$i + 4][0] == T_STRING ) {
876
+ $extends = $tokens[$i + 4][1];
877
+ }
878
+
879
+ $class_name = $tokens[$i][1];
880
+ $classes[$path] = array(
881
+ 'name' => $class_name,
882
+ 'extends' => $extends
883
+ );
884
+ }
885
+ }
886
+
887
+ /**
888
+ * result example:
889
+ *
890
+ * $classes['/plugin/items/filename.php'] = array(
891
+ * 'name' => 'PluginNameItem',
892
+ * 'extendes' => 'PluginNameItemBase'
893
+ * )
894
+ */
895
+
896
+ return $classes;
897
+ }
898
+
899
+ // ----------------------------------------------------------------------
900
+ // Public methods
901
+ // ----------------------------------------------------------------------
902
+
903
+ public function newScriptList()
904
+ {
905
+ return new Wbcr_Factory406_ScriptList($this);
906
+ }
907
+
908
+ public function newStyleList()
909
+ {
910
+ return new Wbcr_Factory406_StyleList($this);
911
+ }
912
+ }
913
+ }
libs/factory/core/includes/request.class.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if accessed directly
3
+ if( !defined('ABSPATH') ) {
4
+ exit;
5
+ }
6
+
7
+ if( !class_exists('Wbcr_Factory406_Request') ) {
8
+ class Wbcr_Factory406_Request {
9
+
10
+ /**
11
+ * @param null $param
12
+ * @param bool|string $sanitize true/false or sanitize function name
13
+ * @param bool $default
14
+ * @param string $method_name
15
+ * @return array|bool|mixed
16
+ */
17
+ private function getBody($param = null, $sanitize = false, $default = false, $method_name = 'REQUEST')
18
+ {
19
+ $sanitize_function_name = 'sanitize_text_field';
20
+ $method = $_REQUEST;
21
+
22
+ switch( strtoupper($method_name) ) {
23
+ case 'GET':
24
+ $method = $_GET;
25
+ break;
26
+ case 'POST':
27
+ $method = $_POST;
28
+ break;
29
+ case 'REQUEST':
30
+ $method = $_REQUEST;
31
+ break;
32
+ }
33
+
34
+ if( !empty($sanitize) && is_string($sanitize) && $sanitize !== $sanitize_function_name ) {
35
+ $sanitize_function_name = $sanitize;
36
+ }
37
+
38
+ if( !function_exists($sanitize_function_name) ) {
39
+ throw new Exception('Function ' . $sanitize_function_name . 'is undefined.');
40
+ }
41
+
42
+ if( !empty($param) ) {
43
+ if( isset($method[$param]) && !empty($method[$param]) ) {
44
+ if( is_array($method[$param]) ) {
45
+ return !empty($sanitize)
46
+ ? array_map($sanitize_function_name, $method[$param])
47
+ : $method[$param];
48
+ } else {
49
+ return !empty($sanitize)
50
+ ? call_user_func($sanitize_function_name, $method[$param])
51
+ : $method[$param];
52
+ }
53
+ }
54
+
55
+ return $default;
56
+ }
57
+
58
+ return !empty($sanitize)
59
+ ? array_map($sanitize_function_name, $method)
60
+ : $method;
61
+ }
62
+
63
+ /**
64
+ * @param bool|string see method getBody
65
+ * @param array $default
66
+ * @return mixed|null
67
+ */
68
+ public function requestAll($sanitize = false, $default = array())
69
+ {
70
+ return $this->getBody(null, $sanitize, $default);
71
+ }
72
+
73
+ /**
74
+ * @param $param
75
+ * @param bool|string see method getBody
76
+ * @param bool $default
77
+ * @return mixed|null
78
+ */
79
+ public function request($param, $default = false, $sanitize = false)
80
+ {
81
+ return $this->getBody($param, $sanitize, $default);
82
+ }
83
+
84
+ /**
85
+ * @param bool|string see method getBody
86
+ * @param array $default
87
+ * @return mixed|null
88
+ */
89
+ public function getAll($sanitize = false, $default = array())
90
+ {
91
+ return $this->getBody(null, $sanitize, $default, 'get');
92
+ }
93
+
94
+ /**
95
+ * @param null $param
96
+ * @param bool|string see method getBody
97
+ * @param bool $default
98
+ * @return mixed|null
99
+ */
100
+ public function get($param, $default = false, $sanitize = false)
101
+ {
102
+ return $this->getBody($param, $sanitize, $default, 'get');
103
+ }
104
+
105
+ /**
106
+ * @param bool|string see method getBody
107
+ * @param array $default
108
+ * @return mixed|null
109
+ */
110
+ public function postAll($sanitize = false, $default = array())
111
+ {
112
+ return $this->getBody(null, $sanitize, $default, 'post');
113
+ }
114
+
115
+ /**
116
+ * @param $param
117
+ * @param bool|string see method getBody
118
+ * @param bool $default
119
+ * @return mixed|null
120
+ */
121
+ public function post($param, $default = false, $sanitize = false)
122
+ {
123
+ return $this->getBody($param, $sanitize, $default, 'post');
124
+ }
125
+ }
126
+ }
libs/factory/forms/assets/css/editor.css ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ font-family: Arial;
3
+ font-size: 14px;
4
+ background-color: #fff;
5
+ }
6
+ p {
7
+ margin: 0px;
8
+ }
9
+
10
+ p + p {
11
+ margin-top: 5px;
12
+ }
libs/factory/forms/assets/standard-controls.js ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($){
2
+
3
+ if ( !$.factory ) $.factory = {}
4
+ if ( $.factory.widget ) return;
5
+
6
+ /**
7
+ * OnePress Widget Factory.
8
+ */
9
+ $.factory.widget = function (pluginName, pluginObject) {
10
+
11
+ var factory = {
12
+
13
+ createWidget: function (element, options) {
14
+ var widget = $.extend(true, {}, pluginObject);
15
+
16
+ widget.element = $(element);
17
+ widget.options = $.extend(true, widget.options, options);
18
+
19
+ if (widget._init) widget._init();
20
+ if (widget._create) widget._create();
21
+
22
+ $.data(element, 'plugin_' + pluginName, widget);
23
+ },
24
+
25
+ callMethod: function (widget, methodName) {
26
+ widget[methodName] && widget[methodName]();
27
+ }
28
+ };
29
+
30
+ $.fn[pluginName] = function () {
31
+ var args = arguments;
32
+ var argsCount = arguments.length;
33
+
34
+ this.each(function () {
35
+
36
+ var widget = $.data(this, 'plugin_' + pluginName);
37
+
38
+ // a widget is not created yet
39
+ if (!widget && argsCount <= 1) {
40
+ factory.createWidget(this, argsCount ? args[0] : false);
41
+
42
+ // a widget is created, the public method with no args is being called
43
+ } else if (argsCount == 1) {
44
+ factory.callMethod(widget, args[0]);
45
+ }
46
+ });
47
+ };
48
+ };
49
+
50
+ /**
51
+ * Radio #1
52
+ */
53
+
54
+ $.fn.onpRadioCircles = function( options ) {
55
+ if ( !options ) options = {};
56
+ options.theme = 'circles';
57
+ $(this).onpRadio(options);
58
+ };
59
+
60
+ $.fn.onpRadioSquares = function( options ) {
61
+ if ( !options ) options = {};
62
+ options.theme = 'squares';
63
+ $(this).onpRadio(options);
64
+ };
65
+
66
+ $.factory.widget('onpRadio', {
67
+ options: {
68
+ theme: 'squares',
69
+ selected: null
70
+ },
71
+ _create: function() {
72
+ var self = this;
73
+ this._createMarkup();
74
+
75
+ this.radio.find('.onp-radio-option').click(function(){
76
+ if ( $(this).is(".disabled") ) return;
77
+ var selected = self.radio.find('.onp-radio-option.selected');
78
+ if ( selected.data('value') == $(this).data('value')) return;
79
+
80
+ selected.removeClass('selected');
81
+ $(this).addClass("selected");
82
+
83
+ var value = $(this).data('value');
84
+ self.element.val(value);
85
+ self.element.trigger( "change", $(this).data('value') );
86
+ });
87
+ },
88
+ _createMarkup: function() {
89
+
90
+ var wrap = $("<ul class='onp-radio-wrap'></ul>").addClass('onp-radio-' + this.options.theme);
91
+ this.element.find("option").each(function(){
92
+ var $this = $(this);
93
+
94
+ var value = $this.attr('value');
95
+ var text = $this.html();
96
+ var icon = $this.data('icon');
97
+ var disabled = $this.attr('disabled');
98
+
99
+ var option = $("<li class='onp-radio-option' data-value='" + value + "'></li>");
100
+ var innerOptionWrap = $("<span class='onp-radio-option-inner-wrap'></span>").appendTo(option);
101
+ option.addClass('onp-radio-option-' + value);
102
+
103
+ if ( icon ) innerOptionWrap.append("<i class='" + icon + "'></i>");
104
+ if ( disabled ) option.addClass('disabled');
105
+
106
+ wrap.append(option);
107
+ });
108
+
109
+ this.options.selected = this.options.selected || this.element.find("option:selected").attr('value');
110
+ wrap.find('.onp-radio-option-' + this.options.selected).addClass("selected");
111
+
112
+ this.element.hide();
113
+ this.element.after(wrap);
114
+ this.radio = wrap;
115
+ }
116
+ });
117
+
118
+ var factoryForms = {
119
+
120
+ collapsedGroups: function( $target ) {
121
+ if ( !$target ) $target = $("body");
122
+
123
+ $target.find(".fy-collapsed-show").click(function(){
124
+ $( $(this).attr('href') ).fadeIn();
125
+ $(this).hide();
126
+ return false;
127
+ });
128
+
129
+ $target.find(".fy-collapsed-hide").click(function(){
130
+ var content = $( $(this).attr('href') );
131
+ content.fadeOut(300, function(){
132
+ content.prev().show();
133
+ });
134
+ return false;
135
+ });
136
+ }
137
+ }
138
+
139
+ $(function(){
140
+ $(".onp-radio-circles.auto").onpRadioCircles();
141
+ $(".onp-radio-squares.auto").onpRadioSquares();
142
+ factoryForms.collapsedGroups();
143
+ });
144
+
145
+ })(jQuery)
146
+
libs/factory/forms/boot.php ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Factory Forms
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.1
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ // the module provides function for the admin area only
18
+
19
+ if( !is_admin() ) {
20
+ return;
21
+ }
22
+
23
+ // checks if the module is already loaded in order to
24
+ // prevent loading the same version of the module twice.
25
+ if( defined('FACTORY_FORMS_407_LOADED') ) {
26
+ return;
27
+ }
28
+
29
+ define('FACTORY_FORMS_407_LOADED', true);
30
+
31
+ // absolute path and URL to the files and resources of the module.
32
+ define('FACTORY_FORMS_407_DIR', dirname(__FILE__));
33
+ define('FACTORY_FORMS_407_URL', plugins_url(null, __FILE__));
34
+
35
+ #comp merge
36
+ require_once(FACTORY_FORMS_407_DIR . '/includes/providers/value-provider.interface.php');
37
+ require_once(FACTORY_FORMS_407_DIR . '/includes/providers/meta-value-provider.class.php');
38
+ require_once(FACTORY_FORMS_407_DIR . '/includes/providers/options-value-provider.class.php');
39
+
40
+ require_once(FACTORY_FORMS_407_DIR . '/includes/form.class.php');
41
+ #endcomp
42
+
43
+ load_plugin_textdomain('wbcr_factory_forms_407', false, dirname(plugin_basename(__FILE__)) . '/langs');
44
+
45
+ /**
46
+ * We add this code into the hook because all these controls quite heavy. So in order to get better perfomance,
47
+ * we load the form controls only on pages where the forms are created.
48
+ *
49
+ * @see the 'wbcr_factory_forms_407_register_controls' hook
50
+ *
51
+ * @since 3.0.7
52
+ */
53
+ if( !function_exists('wbcr_factory_forms_407_register_default_controls') ) {
54
+
55
+ /**
56
+ * @param Wbcr_Factory406_Plugin $plugin
57
+ * @throws Exception
58
+ */
59
+ function wbcr_factory_forms_407_register_default_controls(Wbcr_Factory406_Plugin $plugin)
60
+ {
61
+
62
+ if( $plugin && !isset($plugin->forms) ) {
63
+ throw new Exception("The module Factory Forms is not loaded for the plugin '{$plugin->getPluginName()}'.");
64
+ }
65
+
66
+ require_once(FACTORY_FORMS_407_DIR . '/includes/html-builder.class.php');
67
+ require_once(FACTORY_FORMS_407_DIR . '/includes/form-element.class.php');
68
+ require_once(FACTORY_FORMS_407_DIR . '/includes/control.class.php');
69
+ require_once(FACTORY_FORMS_407_DIR . '/includes/complex-control.class.php');
70
+ require_once(FACTORY_FORMS_407_DIR . '/includes/holder.class.php');
71
+ require_once(FACTORY_FORMS_407_DIR . '/includes/control-holder.class.php');
72
+ require_once(FACTORY_FORMS_407_DIR . '/includes/custom-element.class.php');
73
+ require_once(FACTORY_FORMS_407_DIR . '/includes/form-layout.class.php');
74
+
75
+ // registration of controls
76
+ $plugin->forms->registerControls(array(
77
+ array(
78
+ 'type' => 'checkbox',
79
+ 'class' => 'Wbcr_FactoryForms407_CheckboxControl',
80
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/checkbox.php'
81
+ ),
82
+ array(
83
+ 'type' => 'list',
84
+ 'class' => 'Wbcr_FactoryForms407_ListControl',
85
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/list.php'
86
+ ),
87
+ array(
88
+ 'type' => 'dropdown',
89
+ 'class' => 'Wbcr_FactoryForms407_DropdownControl',
90
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/dropdown.php'
91
+ ),
92
+ array(
93
+ 'type' => 'dropdown-and-colors',
94
+ 'class' => 'Wbcr_FactoryForms407_DropdownAndColorsControl',
95
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/dropdown-and-colors.php'
96
+ ),
97
+ array(
98
+ 'type' => 'hidden',
99
+ 'class' => 'Wbcr_FactoryForms407_HiddenControl',
100
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/hidden.php'
101
+ ),
102
+ array(
103
+ 'type' => 'hidden',
104
+ 'class' => 'Wbcr_FactoryForms407_HiddenControl',
105
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/hidden.php'
106
+ ),
107
+ array(
108
+ 'type' => 'radio',
109
+ 'class' => 'Wbcr_FactoryForms407_RadioControl',
110
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/radio.php'
111
+ ),
112
+ array(
113
+ 'type' => 'radio-colors',
114
+ 'class' => 'Wbcr_FactoryForms407_RadioColorsControl',
115
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/radio-colors.php'
116
+ ),
117
+ array(
118
+ 'type' => 'textarea',
119
+ 'class' => 'Wbcr_FactoryForms407_TextareaControl',
120
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/textarea.php'
121
+ ),
122
+ array(
123
+ 'type' => 'textbox',
124
+ 'class' => 'Wbcr_FactoryForms407_TextboxControl',
125
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/textbox.php'
126
+ ),
127
+ array(
128
+ 'type' => 'multiple-textbox',
129
+ 'class' => 'Wbcr_FactoryForms407_MultipleTextboxControl',
130
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/multiple-textbox.php'
131
+ ),
132
+ array(
133
+ 'type' => 'datetimepicker-range',
134
+ 'class' => 'Wbcr_FactoryForms407_DatepickerRangeControl',
135
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/datepicker-range.php'
136
+ ),
137
+ array(
138
+ 'type' => 'url',
139
+ 'class' => 'Wbcr_FactoryForms407_UrlControl',
140
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/url.php'
141
+ ),
142
+ array(
143
+ 'type' => 'wp-editor',
144
+ 'class' => 'Wbcr_FactoryForms407_WpEditorControl',
145
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/wp-editor.php'
146
+ ),
147
+ array(
148
+ 'type' => 'color',
149
+ 'class' => 'Wbcr_FactoryForms407_ColorControl',
150
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/color.php'
151
+ ),
152
+ array(
153
+ 'type' => 'color-and-opacity',
154
+ 'class' => 'Wbcr_FactoryForms407_ColorAndOpacityControl',
155
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/color-and-opacity.php'
156
+ ),
157
+ array(
158
+ 'type' => 'gradient',
159
+ 'class' => 'Wbcr_FactoryForms407_GradientControl',
160
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/gradient.php'
161
+ ),
162
+ array(
163
+ 'type' => 'font',
164
+ 'class' => 'Wbcr_FactoryForms407_FontControl',
165
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/font.php'
166
+ ),
167
+ array(
168
+ 'type' => 'google-font',
169
+ 'class' => 'Wbcr_FactoryForms407_GoogleFontControl',
170
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/google-font.php'
171
+ ),
172
+ array(
173
+ 'type' => 'pattern',
174
+ 'class' => 'Wbcr_FactoryForms407_PatternControl',
175
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/pattern.php'
176
+ ),
177
+ array(
178
+ 'type' => 'integer',
179
+ 'class' => 'Wbcr_FactoryForms407_IntegerControl',
180
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/integer.php'
181
+ ),
182
+ array(
183
+ 'type' => 'control-group',
184
+ 'class' => 'Wbcr_FactoryForms407_ControlGroupHolder',
185
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/control-group.php'
186
+ ),
187
+ array(
188
+ 'type' => 'paddings-editor',
189
+ 'class' => 'Wbcr_FactoryForms407_PaddingsEditorControl',
190
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/paddings-editor.php'
191
+ ),
192
+ ));
193
+
194
+ // registration of control holders
195
+ $plugin->forms->registerHolders(array(
196
+ array(
197
+ 'type' => 'tab',
198
+ 'class' => 'Wbcr_FactoryForms407_TabHolder',
199
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/tab.php'
200
+ ),
201
+ array(
202
+ 'type' => 'tab-item',
203
+ 'class' => 'Wbcr_FactoryForms407_TabItemHolder',
204
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/tab-item.php'
205
+ ),
206
+ array(
207
+ 'type' => 'accordion',
208
+ 'class' => 'Wbcr_FactoryForms407_AccordionHolder',
209
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/accordion.php'
210
+ ),
211
+ array(
212
+ 'type' => 'accordion-item',
213
+ 'class' => 'Wbcr_FactoryForms407_AccordionItemHolder',
214
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/accordion-item.php'
215
+ ),
216
+ array(
217
+ 'type' => 'control-group',
218
+ 'class' => 'Wbcr_FactoryForms407_ControlGroupHolder',
219
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/control-group.php'
220
+ ),
221
+ array(
222
+ 'type' => 'control-group-item',
223
+ 'class' => 'Wbcr_FactoryForms407_ControlGroupItem',
224
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/control-group-item.php'
225
+ ),
226
+ array(
227
+ 'type' => 'form-group',
228
+ 'class' => 'Wbcr_FactoryForms407_FormGroupHolder',
229
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/form-group.php'
230
+ ),
231
+ array(
232
+ 'type' => 'more-link',
233
+ 'class' => 'Wbcr_FactoryForms407_MoreLinkHolder',
234
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/more-link.php'
235
+ ),
236
+ array(
237
+ 'type' => 'div',
238
+ 'class' => 'Wbcr_FactoryForms407_DivHolder',
239
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/div.php'
240
+ ),
241
+ array(
242
+ 'type' => 'columns',
243
+ 'class' => 'Wbcr_FactoryForms407_ColumnsHolder',
244
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/holders/columns.php'
245
+ )
246
+ ));
247
+
248
+ // registration custom form elements
249
+ $plugin->forms->registerCustomElements(array(
250
+ array(
251
+ 'type' => 'html',
252
+ 'class' => 'Wbcr_FactoryForms407_Html',
253
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/customs/html.php',
254
+ ),
255
+ array(
256
+ 'type' => 'separator',
257
+ 'class' => 'Wbcr_FactoryForms407_Separator',
258
+ 'include' => FACTORY_FORMS_407_DIR . '/controls/customs/separator.php',
259
+ ),
260
+ ));
261
+
262
+ // registration of form layouts
263
+ $plugin->forms->registerFormLayout(array(
264
+ 'name' => 'bootstrap-3',
265
+ 'class' => 'Wbcr_FactoryForms407_Bootstrap3FormLayout',
266
+ 'include' => FACTORY_FORMS_407_DIR . '/layouts/bootstrap-3/bootstrap-3.php'
267
+ ));
268
+ }
269
+
270
+ add_action('wbcr_factory_forms_407_register_controls', 'wbcr_factory_forms_407_register_default_controls');
271
+ }
libs/factory/forms/controls/checkbox.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Checkbox Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic Ltd
13
+ *
14
+ * @package factory-forms
15
+ * @since 1.0.0
16
+ */
17
+
18
+ // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
+ exit;
21
+ }
22
+
23
+ if( !class_exists('Wbcr_FactoryForms407_CheckboxControl') ) {
24
+
25
+ class Wbcr_FactoryForms407_CheckboxControl extends Wbcr_FactoryForms407_Control {
26
+
27
+ public $type = 'checkbox';
28
+
29
+ public function getSubmitValue($name, $sub_name)
30
+ {
31
+ $name_on_form = $this->getNameOnForm($name);
32
+
33
+ return isset($_POST[$name_on_form]) && $_POST[$name_on_form] != 0
34
+ ? 1
35
+ : 0;
36
+ }
37
+
38
+ /**
39
+ * Shows the html markup of the control.
40
+ *
41
+ * @since 1.0.0
42
+ * @return void
43
+ */
44
+ public function html()
45
+ {
46
+
47
+ $events_on_data = $this->getOption('eventsOn', array());
48
+ $events_off_data = $this->getOption('eventsOff', array());
49
+
50
+ if( !empty($events_on_data) || !empty($events_off_data) ) {
51
+
52
+ $events_on_string_data = json_encode($events_on_data);
53
+ $events_off_string_data = json_encode($events_off_data);
54
+
55
+ $name_on_form = $this->getNameOnForm();
56
+ $value = $this->getValue();
57
+
58
+ $print_styles = '';
59
+
60
+ if( $value ) {
61
+ $current_events_data = $events_on_data;
62
+ } else {
63
+ $current_events_data = $events_off_data;
64
+ }
65
+
66
+ foreach($current_events_data as $event_name => $selectors) {
67
+ if( $event_name == 'hide' ) {
68
+ $print_styles .= $selectors . '{display:none;}';
69
+ } else if( $event_name == 'show' ) {
70
+ $print_styles .= $selectors . '{display:block;}';
71
+ }
72
+ }
73
+
74
+ echo '<style>' . $print_styles . '</style>';
75
+ ?>
76
+
77
+ <script>
78
+ // Onepress factory checkbox control events
79
+ if( void 0 === window.__factory_checkbox_control_events_on_data ) {
80
+ window.__factory_checkbox_control_events_on_data = {};
81
+ }
82
+ if( void 0 === window.__factory_checkbox_control_events_off_data ) {
83
+ window.__factory_checkbox_control_events_off_data = {};
84
+ }
85
+ window.__factory_checkbox_control_events_on_data['<?php echo $name_on_form ?>'] = <?= $events_on_string_data ?>;
86
+ window.__factory_checkbox_control_events_off_data['<?php echo $name_on_form ?>'] = <?= $events_off_string_data ?>;
87
+ </script>
88
+ <?php
89
+ }
90
+
91
+ if( 'buttons' == $this->getOption('way') ) {
92
+ $this->buttonsHtml();
93
+ } else {
94
+ $this->defaultHtml();
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Shows the Buttons Checkbox.
100
+ *
101
+ * @since 1.0.0
102
+ * @return void
103
+ */
104
+ protected function buttonsHtml()
105
+ {
106
+ $value = esc_attr($this->getValue());
107
+ $name_on_form = $this->getNameOnForm();
108
+
109
+ $this->addCssClass('factory-buttons-way');
110
+ $this->addCssClass('btn-group');
111
+
112
+ if( $this->getOption('tumbler', false) ) {
113
+ $this->addCssClass('factory-tumbler');
114
+ }
115
+
116
+ $tumbler_function = $this->getOption('tumblerFunction', false);
117
+ if( $tumbler_function ) {
118
+ $this->addHtmlData('tumbler-function', $tumbler_function);
119
+ }
120
+
121
+ if( $this->getOption('tumblerHint', false) ) {
122
+ $this->addCssClass('factory-has-tumbler-hint');
123
+
124
+ $delay = $this->getOption('tumblerDelay', 3000);
125
+ $this->addHtmlData('tumbler-delay', $delay);
126
+ }
127
+
128
+
129
+ ?>
130
+ <div <?php $this->attrs() ?>>
131
+ <button type="button" class="btn btn-default btn-small btn-sm factory-on <?php if( $value ) {
132
+ echo 'active';
133
+ } ?>"><?php _e('On', 'wbcr_factory_forms_407') ?></button>
134
+ <button type="button" class="btn btn-default btn-small btn-sm factory-off <?php if( !$value ) {
135
+ echo 'active';
136
+ } ?>" data-value="0"><?php _e('Off', 'wbcr_factory_forms_407') ?></button>
137
+ <input type="checkbox" style="display: none" id="<?php echo $name_on_form ?>" class="factory-result" name="<?php echo $name_on_form ?>" value="<?= $value ?>" <?php if( $value ) {
138
+ echo 'checked="checked"';
139
+ } ?>" />
140
+ </div>
141
+ <?php if( $this->getOption('tumblerHint', false) ) { ?>
142
+ <div class="factory-checkbox-tumbler-hint factory-tumbler-hint" style="display: none;">
143
+ <div class="factory-tumbler-content">
144
+ <?php echo $this->getOption('tumblerHint') ?>
145
+ </div>
146
+ </div>
147
+ <?php } ?>
148
+ <?php
149
+ }
150
+
151
+ /**
152
+ * Shows the standart checkbox.
153
+ *
154
+ * @since 1.0.0
155
+ * @return void
156
+ */
157
+ protected function defaultHtml()
158
+ {
159
+ $value = esc_attr($this->getValue());
160
+ $name_on_form = $this->getNameOnForm();
161
+
162
+ $this->addHtmlAttr('type', 'checkbox');
163
+ $this->addHtmlAttr('id', $name_on_form);
164
+ $this->addHtmlAttr('name', $name_on_form);
165
+ $this->addHtmlAttr('value', $value);
166
+
167
+ if( $value ) {
168
+ $this->addHtmlAttr('checked', 'checked');
169
+ }
170
+ $this->addCssClass('factory-default-way');
171
+
172
+ ?>
173
+ <input <?php $this->attrs() ?>/>
174
+ <?php
175
+ }
176
+ }
177
+ }
libs/factory/forms/controls/color-and-opacity.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Color and Opacity
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic Ltd
13
+ *
14
+ * @package core
15
+ * @since 1.0.0
16
+ */
17
+
18
+ // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
+ exit;
21
+ }
22
+
23
+ if( !class_exists('Wbcr_FactoryForms407_ColorAndOpacityControl') ) {
24
+ }
25
+
26
+ class Wbcr_FactoryForms407_ColorAndOpacityControl extends Wbcr_FactoryForms407_ComplexControl {
27
+
28
+ public $type = 'color-and-opacity';
29
+
30
+ public function __construct($options, $form, $provider = null)
31
+ {
32
+ parent::__construct($options, $form, $provider);
33
+
34
+ if( !isset($options['color']) ) {
35
+ $options['color'] = array();
36
+ }
37
+
38
+ $options['color'] = array_merge($options['color'], array(
39
+ 'name' => $this->options['name'] . '__color',
40
+ 'default' => isset($this->options['default'])
41
+ ? $this->options['default']['color']
42
+ : '#1e8cbe',
43
+ 'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target'
44
+ ));
45
+
46
+ if( !isset($options['opacity']) ) {
47
+ $options['opacity'] = array();
48
+ }
49
+
50
+ $options['opacity'] = array_merge($options['opacity'], array(
51
+ 'name' => $this->options['name'] . '__opacity',
52
+ 'default' => isset($this->options['default'])
53
+ ? $this->options['default']['opacity']
54
+ : 100,
55
+ 'units' => '%',
56
+ 'range' => array(0, 100),
57
+ 'way' => 'slider'
58
+ ));
59
+
60
+ $this->color = new Wbcr_FactoryForms407_ColorControl($options['color'], $form, $provider);
61
+ $this->opacity = new Wbcr_FactoryForms407_IntegerControl($options['opacity'], $form, $provider);
62
+
63
+ $this->innerControls = array($this->color, $this->opacity);
64
+ }
65
+
66
+ /**
67
+ * Shows the html markup of the control.
68
+ *
69
+ * @since 1.0.0
70
+ * @return void
71
+ */
72
+ public function html()
73
+ {
74
+ ?>
75
+ <div <?php $this->attrs() ?>>
76
+ <div class="factory-control-row">
77
+ <div class="factory-color-wrap">
78
+ <?php $this->color->html() ?>
79
+ </div>
80
+ <div class="factory-opacity-wrap">
81
+ <?php $this->opacity->html() ?>
82
+ </div>
83
+ </div>
84
+ <div class="factory-picker-target"></div>
85
+ </div>
86
+ <?php
87
+ }
88
+ }
libs/factory/forms/controls/color.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Color
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic Ltd
13
+ *
14
+ * @package core
15
+ * @since 1.0.0
16
+ */
17
+
18
+ // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
+ exit;
21
+ }
22
+
23
+ if( !class_exists('Wbcr_FactoryForms407_ColorControl') ) {
24
+
25
+ class Wbcr_FactoryForms407_ColorControl extends Wbcr_FactoryForms407_Control {
26
+
27
+ public $type = 'color';
28
+
29
+ /**
30
+ * Shows the html markup of the control.
31
+ *
32
+ * @since 1.0.0
33
+ * @return void
34
+ */
35
+ public function html()
36
+ {
37
+ $name = $this->getNameOnForm();
38
+ $value = esc_attr($this->getValue());
39
+
40
+ if( !$value ) {
41
+ $value = '#1e8cbe';
42
+ }
43
+
44
+ // the "pickerTarget" options allows to select element where the palette will be shown
45
+ $picker_target = $this->getOption('pickerTarget');
46
+
47
+ if( !empty($picker_target) ) {
48
+ $this->addHtmlData('picker-target', $picker_target);
49
+ }
50
+
51
+ ?>
52
+ <div <?php $this->attrs() ?>>
53
+ <div class="factory-background" <?php echo(!empty($value)
54
+ ? 'style="background:' . $value . ';"'
55
+ : ''); ?>></div>
56
+ <div class="factory-pattern"></div>
57
+ <input type="text" id="<?php echo $name; ?>" name="<?php echo $name; ?>" class="factory-input-text factory-color-hex" value="<?php echo $value; ?>">
58
+ </div>
59
+ <?php
60
+ }
61
+ }
62
+ }
libs/factory/forms/controls/customs/html.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Html Markup
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_Html') ) {
18
+
19
+ class Wbcr_FactoryForms407_Html extends Wbcr_FactoryForms407_CustomElement {
20
+
21
+ public $type = 'html';
22
+
23
+ /**
24
+ * Shows the html markup of the element.
25
+ *
26
+ * @since 1.0.0
27
+ * @return void
28
+ */
29
+ public function html()
30
+ {
31
+ $html = $this->getOption('html', '');
32
+
33
+ // if the data options is a valid callback for an object method
34
+ if( (is_array($html) && count($html) == 2 && gettype($html[0]) == 'object') || function_exists($html) ) {
35
+
36
+ call_user_func($html, $this);
37
+
38
+ return;
39
+ }
40
+
41
+ // if the data options is an array of values
42
+ echo $html;
43
+ }
44
+ }
45
+ }
libs/factory/forms/controls/customs/separator.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Separator Markup
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_Separator') ) {
18
+ class Wbcr_FactoryForms407_Separator extends Wbcr_FactoryForms407_CustomElement {
19
+
20
+ public $type = 'separator';
21
+
22
+ /**
23
+ * Shows the html markup of the element.
24
+ *
25
+ * @since 1.0.0
26
+ * @return void
27
+ */
28
+ public function html()
29
+ {
30
+ ?>
31
+ <div <?php $this->attrs() ?>></div>
32
+ <?php
33
+ }
34
+ }
35
+ }
libs/factory/forms/controls/datepicker-range.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Datepicker range control
5
+ *
6
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
7
+ * @copyright (c) 2018, Webcraftic Ltd
8
+ *
9
+ * Example:
10
+ * 'type' => 'datetimepicker-range',
11
+ * 'name' => 'facebook_start_date_filter',
12
+ * 'range_1' => array(
13
+ * 'format' => 'YYYY/MM/DD HH:mm',
14
+ * 'default' => date('Y/m/d H:i', strtotime('-1 week'))
15
+ * ),
16
+ * 'range_2' => array(
17
+ * 'format' => 'YYYY/MM/DD HH:mm',
18
+ * 'default' => date('Y/m/d H:i')
19
+ * ),
20
+ * 'title' => __('Выберите период', 'wpcr-scrapes'),
21
+ * 'hint' => __('Если Вкл., вы сможете установить настройки выбора записей за установленный период времени.', 'wpcr-scrapes')
22
+ *
23
+ * @package factory-forms
24
+ * @since 1.0.0
25
+ */
26
+
27
+ // Exit if accessed directly
28
+ if( !defined('ABSPATH') ) {
29
+ exit;
30
+ }
31
+
32
+ if( !class_exists('Wbcr_FactoryForms407_DatepickerRangeControl') ) {
33
+
34
+ class Wbcr_FactoryForms407_DatepickerRangeControl extends Wbcr_FactoryForms407_ComplexControl {
35
+
36
+ public $type = 'datetimepicker-range';
37
+
38
+ public function __construct($options, $form, $provider = null)
39
+ {
40
+ parent::__construct($options, $form, $provider);
41
+
42
+ if( !isset($options['range_1']) ) {
43
+ $options['range_1'] = array();
44
+ }
45
+
46
+ $options['range_1'] = array_merge(array(
47
+ 'scope' => isset($options['scope'])
48
+ ? $options['scope']
49
+ : 'factory',
50
+ 'name' => $this->options['name'] . '__range_1',
51
+ 'format' => 'YYYY/MM/DD HH:mm',
52
+ 'default' => date('Y/m/d H:i')
53
+ ), $options['range_1']);
54
+
55
+ if( !isset($options['range_2']) ) {
56
+ $options['range_2'] = array();
57
+ }
58
+
59
+ $options['range_2'] = array_merge(array(
60
+ 'scope' => isset($options['scope'])
61
+ ? $options['scope']
62
+ : 'factory',
63
+ 'name' => $this->options['name'] . '__range_2',
64
+ 'format' => 'YYYY/MM/DD HH:mm',
65
+ 'default' => date('Y/m/d H:i', strtotime("+1 month"))
66
+ ), $options['range_2']);
67
+
68
+ $this->range_1 = new Wbcr_FactoryForms407_TextboxControl($options['range_1'], $form, $provider);
69
+ $this->range_2 = new Wbcr_FactoryForms407_TextboxControl($options['range_2'], $form, $provider);
70
+ $this->inner_controls = array($this->range_1, $this->range_2);
71
+
72
+ foreach($this->inner_controls as $key => $control) {
73
+ $control->addCssClass('factory-datetimepicker-range-' . $key);
74
+ $control->addHtmlAttr('data-date-show-today-button', 'true');
75
+ $control->addHtmlAttr('data-date-show-clear', 'true');
76
+
77
+ $format = $control->getOption('format');
78
+
79
+ if( !empty($format) ) {
80
+ //'YYYY/MM/DD HH:mm'
81
+ $control->addHtmlAttr('data-date-format', $format);
82
+ }
83
+
84
+ $locale_parts = explode('_', get_locale());
85
+
86
+ $locale = isset($locale_parts[0])
87
+ ? $locale_parts[0]
88
+ : 'en';
89
+
90
+ $control->addHtmlAttr('data-date-locale', $locale);
91
+ }
92
+ }
93
+
94
+ public function render()
95
+ {
96
+ ?>
97
+ <div class='input-group date factory-datetimepicker-input-group' style="display:inline-block; width: 200px">
98
+ <?php $this->range_1->render(); ?>
99
+ </div>
100
+ <div class='input-group date factory-datetimepicker-input-group' style="display:inline-block; width: 200px">
101
+ <?php $this->range_2->render(); ?>
102
+ </div>
103
+ <?php
104
+ }
105
+ }
106
+ }
libs/factory/forms/controls/dropdown-and-colors.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Dropdown and Colors List Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * // see FactoryForms407_DropdownControl
9
+ * 'dropdown' => array(
10
+ * // a callback to return items or an array of items to select
11
+ * 'data' => OPanda_ThemeManager::getThemes(OPanda_Items::getCurrentItemName(), 'dropdown'),
12
+ * 'default' => 'default',
13
+ * 'value' => 'value' // a value to show in the control
14
+ * ),
15
+ * // see FactoryForms407_RadioColorsControl
16
+ * 'colors' => array(
17
+ * // a callback to return items or an array of items to select
18
+ * 'data' => array(
19
+ * array('default', '#75649b'),
20
+ * array('black', '#222'),
21
+ * array('light', '#fff3ce'),
22
+ * array('forest', '#c9d4be'),
23
+ * ),
24
+ * 'value' => 'value' // a value to show in the control
25
+ * 'default' => 'default', // a default value of the control if the "value" option is not specified
26
+ * ),
27
+ *
28
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
29
+ * @copyright (c) 2018, Webcraftic Ltd
30
+ *
31
+ * @package factory-forms
32
+ * @since 1.0.0
33
+ */
34
+
35
+ // Exit if accessed directly
36
+ if( !defined('ABSPATH') ) {
37
+ exit;
38
+ }
39
+
40
+ if( !class_exists('Wbcr_FactoryForms407_DropdownAndColorsControl') ) {
41
+
42
+ class Wbcr_FactoryForms407_DropdownAndColorsControl extends Wbcr_FactoryForms407_ComplexControl {
43
+
44
+ public $type = 'dropdown-and-colors';
45
+
46
+ public function __construct($options, $form, $provider = null)
47
+ {
48
+ parent::__construct($options, $form, $provider);
49
+
50
+ if( !isset($options['dropdown']) ) {
51
+ $options['dropdown'] = array();
52
+ }
53
+
54
+ $options['dropdown'] = array_merge($options['dropdown'], array(
55
+ 'scope' => isset($options['scope'])
56
+ ? $options['scope']
57
+ : 'opanda',
58
+ 'name' => $this->options['name'] . '__dropdown',
59
+ ));
60
+
61
+ if( !isset($options['colors']) ) {
62
+ $options['colors'] = array();
63
+ }
64
+
65
+ $options['colors'] = array_merge($options['colors'], array(
66
+ 'scope' => isset($options['scope'])
67
+ ? $options['scope']
68
+ : 'opanda',
69
+ 'name' => $this->options['name'] . '__colors',
70
+ ));
71
+
72
+ $this->dropdown = new Wbcr_FactoryForms407_DropdownControl($options['dropdown'], $form, $provider);
73
+ $this->colors = new Wbcr_FactoryForms407_RadioColorsControl($options['colors'], $form, $provider);
74
+ $this->inner_controls = array($this->dropdown, $this->colors);
75
+
76
+ $colors = $this->colors->getOption('data');
77
+
78
+ if( empty($colors) ) {
79
+ $dropdown_value = $this->dropdown->getValue();
80
+ $dOptions = $this->dropdown->getOption('data', array());
81
+
82
+ foreach($dOptions as $option) {
83
+ if( $option['value'] == $dropdown_value && isset($option['data']['colors']) ) {
84
+ $colors_options = json_decode(htmlspecialchars_decode($option['data']['colors']));
85
+ $this->colors->setOption('data', $colors_options);
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Shows the html markup of the control.
93
+ *
94
+ * @since 1.0.0
95
+ * @return void
96
+ */
97
+ public function html()
98
+ {
99
+ ?>
100
+ <script>
101
+ </script>
102
+ <div <?php $this->attrs() ?>>
103
+ <div class="factory-control-row">
104
+ <div class="factory-dropdown-wrap">
105
+ <?php $this->dropdown->render(); ?>
106
+ </div>
107
+ <div class="factory-colors-wrap">
108
+ <?php $this->colors->render(); ?>
109
+ </div>
110
+ </div>
111
+ <div class="factory-picker-target"></div>
112
+ </div>
113
+ <?php
114
+ }
115
+ }
116
+ }
libs/factory/forms/controls/dropdown.php ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Dropdown List Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * items => a callback to return items or an array of items to select
11
+ *
12
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
13
+ * @copyright (c) 2018, Webcraftic Ltd
14
+ *
15
+ * @package factory-forms
16
+ * @since 1.0.0
17
+ */
18
+
19
+ // Exit if accessed directly
20
+ if( !defined('ABSPATH') ) {
21
+ exit;
22
+ }
23
+
24
+ if( !class_exists('Wbcr_FactoryForms407_DropdownControl') ) {
25
+
26
+ class Wbcr_FactoryForms407_DropdownControl extends Wbcr_FactoryForms407_Control {
27
+
28
+ public $type = 'dropdown';
29
+
30
+ /**
31
+ * Returns a set of available items for the list.
32
+ *
33
+ * @since 1.0.0
34
+ * @return mixed[]
35
+ */
36
+ private function getItems()
37
+ {
38
+ $data = $this->getOption('data', array());
39
+
40
+ // if the data options is a valid callback for an object method
41
+ if( (is_array($data) && count($data) == 2 && is_object($data[0])) || is_string($data) ) {
42
+
43
+ return call_user_func($data);
44
+ }
45
+
46
+ // if the data options is an array of values
47
+ return $data;
48
+ }
49
+
50
+ /**
51
+ * Returns true, if the data should be loaded via ajax.
52
+ *
53
+ * @since 1.0.0
54
+ * @return bool
55
+ */
56
+ protected function isAjax()
57
+ {
58
+
59
+ $data = $this->getOption('data', array());
60
+
61
+ return is_array($data) && isset($data['ajax']);
62
+ }
63
+
64
+ /**
65
+ * Shows the html markup of the control.
66
+ *
67
+ * @since 1.0.0
68
+ * @return void
69
+ */
70
+ public function html()
71
+ {
72
+
73
+ $way = $this->getOption('way', 'default');
74
+ $this->addHtmlData('way', $way);
75
+
76
+ $events_data = $this->getOption('events', array());
77
+
78
+ if( !empty($events_data) ) {
79
+ $events_string_data = json_encode($events_data);
80
+ $name_on_form = $this->getNameOnForm();
81
+
82
+ $value = $this->getValue();
83
+
84
+ if( empty($value) || (is_array($value) && empty($value[0])) ) {
85
+ $value = null;
86
+ }
87
+
88
+ if( !empty($value) && isset($events_data[$value]) && is_array($events_data[$value]) ) {
89
+ $print_styles = '';
90
+ foreach($events_data[$value] as $eventName => $selectors) {
91
+ if( $eventName == 'hide' ) {
92
+ $print_styles .= $selectors . '{display:none;}';
93
+ } else if( $eventName == 'show' ) {
94
+ $print_styles .= $selectors . '{display:block;}';
95
+ }
96
+ }
97
+
98
+ echo '<style>' . $print_styles . '</style>';
99
+ }
100
+ ?>
101
+
102
+ <script>
103
+ // Onepress factory dropdown control events
104
+ if( void 0 === window.factory_dropdown_control_events_data ) {
105
+ window.factory_dropdown_control_events_data = {};
106
+ }
107
+ window.factory_dropdown_control_events_data['<?php echo $name_on_form ?>'] = <?= $events_string_data ?>;
108
+ </script>
109
+ <?php
110
+ }
111
+ if( $this->isAjax() ) {
112
+
113
+ $data = $this->getOption('data', array());
114
+ $ajax_id = 'factory-dropdown-' . rand(1000000, 9999999);
115
+
116
+ $value = $this->getValue();
117
+
118
+ if( empty($value) || (is_array($value) && empty($value[0])) ) {
119
+ $value = null;
120
+ }
121
+
122
+ ?>
123
+ <div class="factory-ajax-loader <?php echo $ajax_id . '-loader'; ?>"></div>
124
+ <script>
125
+ window['<?php echo $ajax_id ?>'] = {
126
+ 'loader': '.<?php echo $ajax_id . '-loader' ?>',
127
+ 'url': '<?php echo $data['url'] ?>',
128
+ 'data': <?php echo json_encode( $data['data'] ) ?>,
129
+ 'selected': '<?php echo $value ?>',
130
+ 'emptyList': '<?php echo $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_407') ) ?>'
131
+ };
132
+ </script>
133
+ <?php
134
+
135
+ $this->addHtmlData('ajax', true);
136
+ $this->addHtmlData('ajax-data-id', $ajax_id);
137
+ $this->addCssClass('factory-hidden');
138
+ }
139
+
140
+ if( 'buttons' == $way ) {
141
+ $this->buttonsHtml();
142
+ } elseif( 'ddslick' == $way ) {
143
+ $this->ddslickHtml();
144
+ } else {
145
+ $this->defaultHtml();
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Shows the Buttons Dropdown.
151
+ *
152
+ * @since 1.0.0
153
+ * @return void
154
+ */
155
+ protected function buttonsHtml()
156
+ {
157
+ $items = $this->getItems();
158
+ $value = $this->getValue();
159
+
160
+ $name_on_form = $this->getNameOnForm();
161
+
162
+ $this->addCssClass('factory-buttons-way');
163
+
164
+ ?>
165
+ <div <?php $this->attrs() ?>>
166
+ <div class="btn-group factory-buttons-group">
167
+ <?php foreach($items as $item) { ?>
168
+ <button type="button" class="btn btn-default btn-small factory-<?php echo $item[0] ?> <?php if( $value == $item[0] ) {
169
+ echo 'active';
170
+ } ?>" data-value="<?php echo $item[0] ?>"><?php echo $item[1] ?></button>
171
+ <?php } ?>
172
+ <input type="hidden" id="<?php echo $name_on_form ?>" class="factory-result" name="<?php echo $name_on_form ?>" value="<?php echo $value ?>"/>
173
+ </div>
174
+ <div class="factory-hints">
175
+ <?php foreach($items as $item) { ?>
176
+ <?php if( isset($item[2]) ) { ?>
177
+ <div class="factory-hint factory-hint-<?php echo $item[0] ?>" <?php if( $value !== $item[0] ) {
178
+ echo 'style="display: none;"';
179
+ } ?>><?php echo $item[2] ?></div>
180
+ <?php } ?>
181
+ <?php } ?>
182
+ </div>
183
+ </div>
184
+ <?php
185
+ }
186
+
187
+ /**
188
+ * Shows the ddSlick dropbox.
189
+ *
190
+ * @since 3.2.8
191
+ * @return void
192
+ */
193
+ protected function ddslickHtml()
194
+ {
195
+ $items = $this->getItems();
196
+ $value = $this->getValue();
197
+
198
+ $name_on_form = $this->getNameOnForm();
199
+
200
+ $this->addCssClass('factory-ddslick-way');
201
+ $this->addHtmlData('name', $name_on_form);
202
+
203
+ $this->addHtmlData('width', $this->getOption('width', 300));
204
+ $this->addHtmlData('align', $this->getOption('imagePosition', 'right'));
205
+
206
+ ?>
207
+ <div <?php $this->attrs() ?>>
208
+ <script>
209
+ //Dropdown plugin data
210
+ var factory_<?php echo $name_on_form ?>_data = [
211
+ <?php foreach ( $items as $item ) { ?>
212
+ {
213
+ text: "<?php echo $item['title'] ?>",
214
+ value: "<?php echo $item['value'] ?>",
215
+ selected: <?php if ( $value == $item['value'] ) { echo 'true'; } else { echo 'false'; } ?>,
216
+ description: "<?php echo ( isset( $item['hint'] ) ? $item['hint'] : '' ); ?>",
217
+ imageSrc: "<?php echo ( isset( $item['image'] ) ? $item['image'] : '' ); ?>",
218
+ imageHoverSrc: "<?php echo ( isset( $item['hover'] ) ? $item['hover'] : '' ); ?>"
219
+ },
220
+ <?php } ?>
221
+ ];
222
+ </script>
223
+ <div class="factory-ddslick"></div>
224
+ <input type="hidden" class="factory-result" id="<?php echo $name_on_form ?>" name="<?php echo $name_on_form ?>" value="<?php echo $value ?>"/>
225
+ </div>
226
+ <?php
227
+ }
228
+
229
+ /**
230
+ * Shows the standart dropdown.
231
+ *
232
+ * @since 1.3.1
233
+ * @return void
234
+ */
235
+ protected function defaultHtml()
236
+ {
237
+
238
+ $items = $this->getItems();
239
+ $value = esc_attr($this->getValue());
240
+
241
+ $name_on_form = $this->getNameOnForm();
242
+
243
+ $this->addHtmlAttr('id', $name_on_form);
244
+ $this->addHtmlAttr('name', $name_on_form);
245
+ $this->addCssClass('form-control');
246
+
247
+ $hasGroups = $this->getOption('hasGroups', true);
248
+ $hasHints = $this->getOption('hasHints', false);
249
+
250
+ foreach($items as $item) {
251
+ if( !isset($item['hint']) ) {
252
+ continue;
253
+ }
254
+ if( empty($item['hint']) ) {
255
+ continue;
256
+ }
257
+ $hasHints = true;
258
+ break;
259
+ }
260
+
261
+ $isEmpty = $this->isAjax() || empty($items);
262
+ $emptyList = $this->getOption('empty', __('- empty -', 'wbcr_factory_forms_407'));
263
+
264
+ ?>
265
+
266
+ <select <?php $this->attrs() ?>>
267
+ <?php if( $isEmpty ) { ?>
268
+
269
+ <option value='' class="factory-empty-option">
270
+ <?php echo $emptyList ?>
271
+ </option>
272
+
273
+ <?php } else { ?>
274
+
275
+ <?php $this->printItems($items, $value) ?>
276
+
277
+ <?php } ?>
278
+ </select>
279
+
280
+ <?php if( $hasHints ) { ?>
281
+ <div class="factory-hints">
282
+ <?php foreach($items as $item) {
283
+
284
+ $hint = isset($item[2])
285
+ ? $item[2]
286
+ : null;
287
+ $hint = isset($item['hint'])
288
+ ? $item['hint']
289
+ : null;
290
+ $value = isset($item[0])
291
+ ? esc_attr($item[0])
292
+ : null;
293
+ $value = isset($item['value'])
294
+ ? esc_attr($item['value'])
295
+ : null;
296
+
297
+ if( !empty($hint) ) { ?>
298
+ <div style="display: none;" class="factory-hint factory-hint-<?php echo $value ?>" <?php if( $value !== $value ) {
299
+ echo 'style="display: none;"';
300
+ } ?>><?php echo $hint ?></div>
301
+ <?php }
302
+ } ?>
303
+ </div>
304
+ <?php } ?>
305
+ <?php
306
+ }
307
+
308
+ /**
309
+ * @param array $items
310
+ * @param null $selected
311
+ */
312
+ protected function printItems($items, $selected = null)
313
+ {
314
+
315
+ foreach((array)$items as $item) {
316
+
317
+ $subitems = array();
318
+ $data = null;
319
+
320
+ // this item is an associative array
321
+ if( isset($item['type']) || isset($item['value']) ) {
322
+
323
+ $type = isset($item['type'])
324
+ ? $item['type']
325
+ : 'option';
326
+ if( 'group' === $type ) {
327
+ $subitems = isset($item['items'])
328
+ ? $item['items']
329
+ : array();
330
+ }
331
+
332
+ $value = isset($item['value'])
333
+ ? $item['value']
334
+ : '';
335
+ $title = isset($item['title'])
336
+ ? $item['title']
337
+ : __('- empty -', 'wbcr_factory_forms_407');
338
+
339
+ $data = isset($item['data'])
340
+ ? $item['data']
341
+ : null;
342
+ } else {
343
+
344
+ $type = (count($item) == 3 && $item[0] === 'group')
345
+ ? 'group'
346
+ : 'option';
347
+ if( 'group' === $type ) {
348
+ $subitems = $item[2];
349
+ }
350
+
351
+ $title = esc_html($item[1]);
352
+ $value = esc_attr($item[0]);
353
+ }
354
+
355
+ if( 'group' === $type ) {
356
+ ?>
357
+
358
+ <optgroup label="<?php echo $item[1] ?>">
359
+ <?php $this->printItems($subitems, $selected); ?>
360
+ </optgroup>
361
+
362
+ <?php
363
+ } else {
364
+
365
+ $attr = ($selected == $value)
366
+ ? 'selected="selected"'
367
+ : '';
368
+
369
+ $strData = '';
370
+ if( !empty($data) ) {
371
+
372
+ foreach($data as $key => $values) {
373
+ $strData = $strData . ' data-' . $key . '="' . (is_array($values)
374
+ ? implode(',', $values)
375
+ : $values) . '"';
376
+ }
377
+ }
378
+
379
+ ?>
380
+ <option value='<?php echo $value ?>' <?php echo $attr ?> <?php echo $strData ?>>
381
+ <?php echo $title ?>
382
+ </option>
383
+ <?php
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
libs/factory/forms/controls/font.php ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Dropdown List Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * items => a callback to return items or an array of items to select
11
+ *
12
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
13
+ * @copyright (c) 2018, Webcraftic Ltd
14
+ *
15
+ * @package core
16
+ * @since 1.0.0
17
+ */
18
+ // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
+ exit;
21
+ }
22
+
23
+ if( !class_exists('Wbcr_FactoryForms407_FontControl') ) {
24
+
25
+ class Wbcr_FactoryForms407_FontControl extends Wbcr_FactoryForms407_ComplexControl {
26
+
27
+ public $type = 'font';
28
+
29
+ public function __construct($options, $form, $provider = null)
30
+ {
31
+ parent::__construct($options, $form, $provider);
32
+
33
+ $option_font_size = array(
34
+ 'name' => $this->options['name'] . '__size',
35
+ 'units' => $this->options['units'],
36
+ 'default' => isset($this->options['default'])
37
+ ? $this->options['default']['size']
38
+ : null
39
+ );
40
+
41
+ $option_font_family = array(
42
+ 'name' => $this->options['name'] . '__family',
43
+ 'data' => $this->getFonts(),
44
+ 'default' => isset($this->options['default'])
45
+ ? $this->options['default']['family']
46
+ : null
47
+ );
48
+
49
+ $optionFontColor = array(
50
+ 'name' => $this->options['name'] . '__color',
51
+ 'default' => isset($this->options['default'])
52
+ ? $this->options['default']['color']
53
+ : null,
54
+ 'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target'
55
+ );
56
+
57
+ $this->size = new Wbcr_FactoryForms407_IntegerControl($option_font_size, $form, $provider);
58
+ $this->family = new Wbcr_FactoryForms407_DropdownControl($option_font_family, $form, $provider);
59
+ $this->color = new Wbcr_FactoryForms407_ColorControl($optionFontColor, $form, $provider);
60
+
61
+ $this->innerControls = array($this->family, $this->size, $this->color);
62
+ }
63
+
64
+ public function getFonts()
65
+ {
66
+
67
+ $fonts = $this->getDefaultFonts();
68
+
69
+ $fonts = apply_filters('wbcr_factory_forms_407_fonts', $fonts);
70
+ $fonts = apply_filters('wbcr_factory_forms_407_fonts-' . $this->options['name'], $fonts);
71
+
72
+ return $fonts;
73
+ }
74
+
75
+ public function getDefaultFonts()
76
+ {
77
+
78
+ $fonts = array(
79
+
80
+ array('inherit', __('(use default website font)', 'wbcr_factory_forms_407')),
81
+ array(
82
+ 'group',
83
+ __('Sans Serif:', 'wbcr_factory_forms_407'),
84
+ array(
85
+ array('Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial'),
86
+ array('"Arial Black", "Arial Bold", Gadget, sans-serif', 'Arial Black'),
87
+ array('"Arial Narrow", Arial, sans-serif', 'Arial Narrow'),
88
+ array(
89
+ '"Arial Rounded MT Bold", "Helvetica Rounded", Arial, sans-serif',
90
+ 'Arial Rounded MT Bold'
91
+ ),
92
+ array(
93
+ '"Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, "AppleGothic", sans-serif',
94
+ 'Avant Garde'
95
+ ),
96
+ array('Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif', 'Calibri'),
97
+ array('Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif', 'Candara'),
98
+ array('"Century Gothic", CenturyGothic, AppleGothic, sans-serif', 'Century Gothic'),
99
+ array(
100
+ '"Franklin Gothic Medium", "Franklin Gothic", "ITC Franklin Gothic", Arial, sans-serif',
101
+ 'Franklin Gothic Medium'
102
+ ),
103
+ array('Futura, "Trebuchet MS", Arial, sans-serif', 'Futura'),
104
+ array('Geneva, Tahoma, Verdana, sans-serif', 'Geneva'),
105
+ array('"Gill Sans", "Gill Sans MT", Calibri, sans-serif', 'Gill Sans'),
106
+ array('"Helvetica Neue", Helvetica, Arial, sans-serif', 'Helvetica'),
107
+ array(
108
+ 'Impact, Haettenschweiler, "Franklin Gothic Bold", Charcoal, "Helvetica Inserat", "Bitstream Vera Sans Bold", "Arial Black", sans serif',
109
+ 'Impact'
110
+ ),
111
+ array(
112
+ '"Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif',
113
+ 'Lucida Grande'
114
+ ),
115
+ array('Optima, Segoe, "Segoe UI", Candara, Calibri, Arial, sans-serif', 'Optima'),
116
+ array(
117
+ '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
118
+ 'Segoe UI'
119
+ ),
120
+ array(
121
+ 'Montserrat, "Segoe UI", "Helvetica Neue", Arial, sans-serif',
122
+ 'Montserrat'
123
+ ),
124
+ array('Tahoma, Verdana, Segoe, sans-serif', 'Tahoma'),
125
+ array(
126
+ '"Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif',
127
+ 'Trebuchet MS'
128
+ ),
129
+ array('Verdana, Geneva, sans-serif', 'Verdana'),
130
+ )
131
+ ),
132
+ array(
133
+ 'group',
134
+ __('Serif:', 'wbcr_factory_forms_407'),
135
+ array(
136
+ array(
137
+ 'Baskerville, "Baskerville Old Face", "Hoefler Text", Garamond, "Times New Roman", serif',
138
+ 'Baskerville'
139
+ ),
140
+ array('"Big Caslon", "Book Antiqua", "Palatino Linotype", Georgia, serif', 'Big Caslon'),
141
+ array(
142
+ '"Bodoni MT", Didot, "Didot LT STD", "Hoefler Text", Garamond, "Times New Roman", serif',
143
+ 'Bodoni MT'
144
+ ),
145
+ array(
146
+ '"Book Antiqua", Palatino, "Palatino Linotype", "Palatino LT STD", Georgia, serif',
147
+ 'Book Antiqua'
148
+ ),
149
+ array(
150
+ '"Calisto MT", "Bookman Old Style", Bookman, "Goudy Old Style", Garamond, "Hoefler Text", "Bitstream Charter", Georgia, serif',
151
+ 'Calisto MT'
152
+ ),
153
+ array('Cambria, Georgia, serif', 'Cambria'),
154
+ array('Didot, "Didot LT STD", "Hoefler Text", Garamond, "Times New Roman", serif', 'Didot'),
155
+ array(
156
+ 'Garamond, Baskerville, "Baskerville Old Face", "Hoefler Text", "Times New Roman", serif',
157
+ 'Garamond'
158
+ ),
159
+ array('Georgia, Times, "Times New Roman", serif', 'Georgia'),
160
+ array(
161
+ '"Goudy Old Style", Garamond, "Big Caslon", "Times New Roman", serif',
162
+ 'Goudy Old Style'
163
+ ),
164
+ array(
165
+ '"Hoefler Text", "Baskerville old face", Garamond, "Times New Roman", serif',
166
+ 'Hoefler Text'
167
+ ),
168
+ array('"Lucida Bright", Georgia, serif', 'Lucida Bright'),
169
+ array(
170
+ 'Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif',
171
+ 'Palatino'
172
+ ),
173
+ array(
174
+ 'Perpetua, Baskerville, "Big Caslon", "Palatino Linotype", Palatino, "URW Palladio L", "Nimbus Roman No9 L", serif',
175
+ 'Perpetua'
176
+ ),
177
+ array(
178
+ 'Rockwell, "Courier Bold", Courier, Georgia, Times, "Times New Roman", serif',
179
+ 'Rockwell'
180
+ ),
181
+ array('"Rockwell Extra Bold", "Rockwell Bold", monospace', 'Rockwell Extra Bold'),
182
+ array(
183
+ 'TimesNewRoman, "Times New Roman", Times, Baskerville, Georgia, serif',
184
+ 'Times New Roman'
185
+ )
186
+ )
187
+ ),
188
+ array(
189
+ 'group',
190
+ __('Monospaced:', 'wbcr_factory_forms_407'),
191
+ array(
192
+ array('"Andale Mono", AndaleMono, monospace', 'Andale Mono'),
193
+ array('Consolas, monaco, monospace', 'Consolas'),
194
+ array(
195
+ '"Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter", monospace',
196
+ 'Courier New'
197
+ ),
198
+ array(
199
+ '"Lucida Console", "Lucida Sans Typewriter", Monaco, "Bitstream Vera Sans Mono", monospace',
200
+ 'Lucida Console'
201
+ ),
202
+ array(
203
+ '"Lucida Sans Typewriter", "Lucida Console", Monaco, "Bitstream Vera Sans Mono", monospace',
204
+ 'Lucida Sans Typewriter'
205
+ ),
206
+ array('Monaco, Consolas, "Lucida Console", monospace', 'Monaco')
207
+ )
208
+ )
209
+
210
+ );
211
+
212
+ return $fonts;
213
+ }
214
+
215
+ /**
216
+ * Removes \" in the font family value.
217
+ *
218
+ * @since 3.1.0
219
+ * @return mixed[]
220
+ */
221
+ public function getValuesToSave()
222
+ {
223
+ $values = parent::getValuesToSave();
224
+
225
+ $family_key = $this->options['name'] . '__family';
226
+ $values[$family_key] = sanitize_text_field($values[$family_key]);
227
+
228
+ return $values;
229
+ }
230
+
231
+ public function beforeControlsHtml()
232
+ {
233
+ }
234
+
235
+ public function afterControlsHtml()
236
+ {
237
+ }
238
+
239
+ /**
240
+ * Shows the html markup of the control.
241
+ *
242
+ * @since 1.0.0
243
+ * @return void
244
+ */
245
+ public function html()
246
+ {
247
+ ?>
248
+ <div <?php $this->attrs() ?>>
249
+ <div class="factory-control-row">
250
+ <?php $this->beforeControlsHtml() ?>
251
+
252
+ <div class="factory-family-wrap">
253
+ <?php $this->family->html() ?>
254
+ </div>
255
+ <div class="factory-size-wrap">
256
+ <?php $this->size->html() ?>
257
+ </div>
258
+ <div class="factory-color-wrap">
259
+ <?php $this->color->html() ?>
260
+ </div>
261
+
262
+ <?php $this->afterControlsHtml() ?>
263
+ </div>
264
+ <div class="factory-picker-target"></div>
265
+ </div>
266
+ <?php
267
+ }
268
+ }
269
+ }
270
+
libs/factory/forms/controls/google-font.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Dropdown List Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * items => a callback to return items or an array of items to select
11
+ *
12
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
13
+ * @copyright (c) 2018, Webcraftic Ltd
14
+ *
15
+ * @package core
16
+ * @since 1.0.0
17
+ */
18
+ class Wbcr_FactoryForms407_GoogleFontControl extends Wbcr_FactoryForms407_FontControl {
19
+
20
+ public $type = 'google-font';
21
+ const APIKEY = 'AIzaSyB-3vazYv7Q-5QZA04bmSKFrWcw_VhC40w';
22
+
23
+ public function __construct($options, $form, $provider = null)
24
+ {
25
+ parent::__construct($options, $form, $provider);
26
+ $this->addCssClass('factory-font');
27
+
28
+ $option_google_font_data = array(
29
+ 'name' => $this->options['name'] . '__google_font_data',
30
+ 'cssClass' => 'factory-google-font-data'
31
+ );
32
+
33
+ $this->google_font_data = new Wbcr_FactoryForms407_HiddenControl($option_google_font_data, $form, $provider);
34
+ $this->inner_controls[] = $this->google_font_data;
35
+ }
36
+
37
+ /**
38
+ * @return array|mixed
39
+ */
40
+ public function getDefaultFonts()
41
+ {
42
+
43
+ $cache_fonts = get_transient('wbcr_factory_google_fonts');
44
+
45
+ if( !empty($cache_fonts) ) {
46
+ return $cache_fonts;
47
+ }
48
+
49
+ $google_fonts = $this->getGoogleFonts();
50
+
51
+ $fonts = array(
52
+ array('inherit', __('(use default website font)', 'wbcr_factory_forms_407'))
53
+ );
54
+
55
+ $fontsCommon = array(
56
+ 'group',
57
+ __('Standard:', 'wbcr_factory_forms_407'),
58
+ array(
59
+
60
+ array('Arial, "Helvetica Neue", Helvetica, sans-serif', 'Arial'),
61
+ array('"Helvetica Neue", Helvetica, Arial, sans-serif', 'Helvetica'),
62
+ array('Tahoma, Verdana, Segoe, sans-serif', 'Tahoma'),
63
+ array('Verdana, Geneva, sans-serif', 'Verdana'),
64
+
65
+ )
66
+ );
67
+
68
+ $fontsGoogleFonts = array('group', __('Google Fonts:', 'wbcr_factory_forms_407'), array());
69
+
70
+ foreach($google_fonts->items as $item) {
71
+
72
+ $alt_font = $item->category;
73
+ if( in_array($alt_font, array('handwriting', 'display')) ) {
74
+ $alt_font = 'serif';
75
+ }
76
+
77
+ $listItem = array(
78
+ 'title' => $item->family,
79
+ 'value' => $item->family . ', ' . $item->category,
80
+ 'hint' => '<em>Google Font</em>',
81
+ 'data' => array(
82
+ 'google-font' => true,
83
+ 'family' => $item->family,
84
+ 'variants' => $item->variants,
85
+ 'subsets' => $item->subsets
86
+ )
87
+ );
88
+
89
+ $fontsGoogleFonts[2][] = $listItem;
90
+ }
91
+
92
+ $fonts[] = $fontsCommon;
93
+ $fonts[] = $fontsGoogleFonts;
94
+
95
+ set_transient('wbcr_factory_google_fonts', $fonts, 60 * 60 * 6);
96
+
97
+ return $fonts;
98
+ }
99
+
100
+ /**
101
+ * @return array|mixed|object
102
+ */
103
+ protected function getGoogleFonts()
104
+ {
105
+
106
+ $body = get_transient('wbcr_factory_google_fonts_raw');
107
+ if( !empty($body) ) {
108
+ return $body;
109
+ }
110
+
111
+ $response = wp_remote_get(sprintf('https://www.googleapis.com/webfonts/v1/webfonts?key=%s', self::APIKEY));
112
+
113
+ $this->error = false;
114
+ $this->defailed_error = false;
115
+
116
+ if( is_wp_error($response) ) {
117
+
118
+ $this->error = __('Unable to retrieve the list of Google Fonts.', 'wbcr_factory_forms_407');
119
+ $this->defailed_error = $response->get_error_message();
120
+
121
+ return $body;
122
+ }
123
+
124
+ if( !isset($response['body']) ) {
125
+
126
+ $this->error = __('Invalide response from the Google Fonts API.', 'wbcr_factory_forms_407');
127
+ $this->defailed_error = $response['body'];
128
+
129
+ return $body;
130
+ }
131
+
132
+ $body = json_decode($response['body']);
133
+
134
+ if( empty($body->items) ) {
135
+
136
+ $this->error = __('Unexpected error. The list of Google Fonts are empty.', 'wbcr_factory_forms_407');
137
+
138
+ return $body;
139
+ }
140
+
141
+ set_transient('wbcr_factory_google_fonts_raw', $body, 60 * 60 * 6);
142
+
143
+ return $body;
144
+ }
145
+
146
+ public function afterControlsHtml()
147
+ {
148
+ ?>
149
+ <?php $this->google_font_data->html() ?>
150
+ <?php
151
+ }
152
+ }
libs/factory/forms/controls/gradient.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Gradient picker Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * title => Заголовок
9
+ * colors => массив цветов для градиента
10
+ * Пример: array("#000 0% 0.5", "#e70303 100% 1")
11
+ * filldirection => Направление градиента(top, left)
12
+ * Пример: 90deg
13
+ * value => a value to show in the control
14
+ * default => a default value of the control if the "value" option is not specified
15
+ *
16
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
17
+ * @copyright (c) 2018, Webcraftic Ltd
18
+ *
19
+ * @package core
20
+ * @since 1.0.0
21
+ */
22
+
23
+ // Exit if accessed directly
24
+ if( !defined('ABSPATH') ) {
25
+ exit;
26
+ }
27
+
28
+ if( !class_exists('Wbcr_FactoryForms407_GradientControl') ) {
29
+ class Wbcr_FactoryForms407_GradientControl extends Wbcr_FactoryForms407_Control {
30
+
31
+ public $type = 'gradient';
32
+
33
+ /**
34
+ * Shows the html markup of the control.
35
+ *
36
+ * @since 1.0.0
37
+ * @return void
38
+ */
39
+ public function html()
40
+ {
41
+ $name = $this->getNameOnForm();
42
+ $value = esc_attr($this->getValue());
43
+
44
+ if( !empty($value) ) {
45
+
46
+ $values = json_decode(stripcslashes(htmlspecialchars_decode($value)));
47
+
48
+ $points = '';
49
+
50
+ foreach($values->color_points as $split_values) {
51
+ $points .= $split_values . ',';
52
+ }
53
+
54
+ $points = rtrim($points, ',');
55
+
56
+ $this->addHtmlData('points', $points);
57
+ $this->addHtmlData('directions', $values->filldirection);
58
+ } else {
59
+ $this->addHtmlData('directions', 'top');
60
+ }
61
+ ?>
62
+ <script>
63
+ if( !window.factory ) {
64
+ window.factory = {};
65
+ }
66
+ if( !window.factory.res ) {
67
+ window.factory.res = {};
68
+ }
69
+ factory.res.resVertical = '<?php _e( 'vertical', 'wbcr_factory_forms_407' ) ?>';
70
+ factory.res.resHorizontal = '<?php _e( 'horizontal', 'wbcr_factory_forms_407' ) ?>';
71
+ </script>
72
+ <div <?php $this->attrs() ?>>
73
+ <div class="factory-gradient-picker">
74
+ <ul class="gradientPicker-pallets">
75
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#1bbc9d" data-secondary="#16a086"></li>
76
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#2fcc71" data-secondary="#27ae61"></li>
77
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#3598dc" data-secondary="#2a80b9"></li>
78
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#9c59b8" data-secondary="#8f44ad"></li>
79
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#34495e" data-secondary="#2d3e50"></li>
80
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#f1c40f" data-secondary="#f49c14"></li>
81
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#e84c3d" data-secondary="#c1392b"></li>
82
+ <li class="factory-preset-gradient factory-primary-gradient" data-primary="#ecf0f1" data-secondary="#bec3c7"></li>
83
+ </ul>
84
+ <canvas class='gradientPicker-preview'></canvas>
85
+ <div class='factory-points'></div>
86
+ <div class='factory-color-picker-container'>
87
+ <div class="factory-slider-container">
88
+ <div class="factory-slider">
89
+ <input type="text" class="factory-input-text factory-color-hex"/>
90
+
91
+ <div class="factory-bar"></div>
92
+ <div class="factory-visible-value">100%</div>
93
+ </div>
94
+ </div>
95
+ <div class="factory-color-picker"></div>
96
+ </div>
97
+ </div>
98
+ <input type="hidden" id="<?php echo $name; ?>" class="factory-result" name="<?php echo $name; ?>" value="<?php echo $value; ?>">
99
+ </div>
100
+ <?php
101
+ }
102
+ }
103
+ }
libs/factory/forms/controls/hidden.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Hidden Input Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic Ltd
13
+ *
14
+ * @package factory-forms
15
+ * @since 1.0.0
16
+ */
17
+
18
+ // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
+ exit;
21
+ }
22
+
23
+ if( !class_exists('Wbcr_FactoryForms407_HiddenControl') ) {
24
+
25
+ class Wbcr_FactoryForms407_HiddenControl extends Wbcr_FactoryForms407_Control {
26
+
27
+ public $type = 'hidden';
28
+
29
+ /**
30
+ * Shows the html markup of the control.
31
+ *
32
+ * @since 1.0.0
33
+ * @return void
34
+ */
35
+ public function html()
36
+ {
37
+ $value = esc_attr($this->getValue());
38
+ $name_on_form = $this->getNameOnForm();
39
+
40
+ $this->addHtmlAttr('id', $name_on_form);
41
+ $this->addHtmlAttr('name', $name_on_form);
42
+ $this->addHtmlAttr('value', $value);
43
+ $this->addHtmlAttr('type', 'hidden');
44
+
45
+ ?>
46
+ <input <?php $this->attrs() ?>/>
47
+ <?php
48
+ }
49
+ }
50
+ }
libs/factory/forms/controls/holders/accordion-item.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Tab Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_AccordionItemHolder') ) {
18
+
19
+ /**
20
+ * Tab Control Holder
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_FactoryForms407_AccordionItemHolder extends Wbcr_FactoryForms407_Holder {
25
+
26
+ /**
27
+ * A holder type.
28
+ *
29
+ * @since 1.0.0
30
+ * @var string
31
+ */
32
+ public $type = 'accordion-item';
33
+
34
+ /**
35
+ * Here we should render a beginning html of the tab.
36
+ *
37
+ * @since 1.0.0
38
+ * @return void
39
+ */
40
+ public function beforeRendering()
41
+ {
42
+ ?>
43
+ <h3><?php echo $this->options['title']; ?></h3>
44
+ <div class="factory-accordion-item">
45
+ <div class="inner-factory-accordion-item">
46
+ <?php
47
+ }
48
+
49
+ /**
50
+ * Here we should render an end html of the tab.
51
+ *
52
+ * @since 1.0.0
53
+ * @return void
54
+ */
55
+ public function afterRendering()
56
+ {
57
+ ?>
58
+ </div>
59
+ </div>
60
+ <?php
61
+ }
62
+ }
63
+ }
libs/factory/forms/controls/holders/accordion.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Tab Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+ if( !class_exists('Wbcr_FactoryForms407_AccordionHolder') ) {
17
+ /**
18
+ * Tab Control Holder
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ class Wbcr_FactoryForms407_AccordionHolder extends Wbcr_FactoryForms407_Holder {
23
+
24
+ /**
25
+ * A holder type.
26
+ *
27
+ * @since 1.0.0
28
+ * @var string
29
+ */
30
+ public $type = 'accordion';
31
+
32
+ /**
33
+ * Here we should render a beginning html of the tab.
34
+ *
35
+ * @since 1.0.0
36
+ * @return void
37
+ */
38
+ public function beforeRendering()
39
+ {
40
+ ?>
41
+ <div <?php $this->attrs() ?>>
42
+ <?php
43
+ }
44
+
45
+ /**
46
+ * Here we should render an end html of the tab.
47
+ *
48
+ * @since 1.0.0
49
+ * @return void
50
+ */
51
+ public function afterRendering()
52
+ {
53
+ ?>
54
+ </div>
55
+ <?php
56
+ }
57
+ }
58
+ }
libs/factory/forms/controls/holders/columns.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Columns Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_ColumnsHolder') ) {
18
+ /**
19
+ * Columns Holder
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ class Wbcr_FactoryForms407_ColumnsHolder extends Wbcr_FactoryForms407_Holder {
24
+
25
+ /**
26
+ * A holder type.
27
+ *
28
+ * @since 1.0.0
29
+ * @var string
30
+ */
31
+ public $type = 'columns';
32
+
33
+ public function __construct($options, $form)
34
+ {
35
+ $columns_items = array();
36
+
37
+ // calculates the number of columns
38
+
39
+ $this->columns_count = 0;
40
+
41
+ foreach($options['items'] as $item) {
42
+ $i = (!isset($item['column'])
43
+ ? 1
44
+ : intval($item['column'])) - 1;
45
+ $columns_items[$i][] = $item;
46
+
47
+ if( $i > $this->columns_count ) {
48
+ $this->columns_count = $i + 1;
49
+ }
50
+ }
51
+ // calculates the number of rows
52
+
53
+ $this->rows_count = 0;
54
+ foreach($columns_items as $items) {
55
+ $count = count($items);
56
+ if( $count > $this->rows_count ) {
57
+ $this->rows_count = $count;
58
+ }
59
+ }
60
+
61
+ // creates elements
62
+
63
+ parent::__construct($options, $form);
64
+
65
+ // groups the created by columns
66
+
67
+ $element_index = 0;
68
+ $this->columns = array();
69
+
70
+ foreach($columns_items as $column_index => $columnItems) {
71
+ $count = count($columnItems);
72
+ for($k = 0; $k < $count; $k++) {
73
+ $this->columns[$column_index][] = $this->elements[$element_index];
74
+ $element_index++;
75
+ }
76
+ }
77
+ }
78
+
79
+
80
+ public function render()
81
+ {
82
+ $this->beforeRendering();
83
+
84
+ for($n = 0; $n < $this->rows_count; $n++) {
85
+
86
+ $this->form->layout->startRow($n, $this->rows_count);
87
+
88
+ for($i = 0; $i < $this->columns_count; $i++) {
89
+ $control = $this->columns[$i][$n];
90
+ $this->form->layout->startColumn($control, $i, $this->columns_count);
91
+ $this->columns[$i][$n]->render();
92
+ $this->form->layout->endColumn($control, $i, $this->columns_count);
93
+ }
94
+
95
+ $this->form->layout->endRow($n, $this->rows_count);
96
+ }
97
+ }
98
+ }
99
+ }
libs/factory/forms/controls/holders/control-group-item.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Tab Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_ControlGroupItem') ) {
18
+
19
+ /**
20
+ * Tab Control Holder
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_FactoryForms407_ControlGroupItem extends Wbcr_FactoryForms407_Holder {
25
+
26
+ /**
27
+ * A holder type.
28
+ *
29
+ * @since 1.0.0
30
+ * @var string
31
+ */
32
+ public $type = 'control-group-item';
33
+
34
+
35
+ /**
36
+ * Here we should render a beginning html of the tab.
37
+ *
38
+ * @since 1.0.0
39
+ * @return void
40
+ */
41
+ public function beforeRendering()
42
+ {
43
+ $this->addCssClass('control-group-item');
44
+ $this->addCssClass('factory-control-group-item-' . $this->options['name']);
45
+
46
+ if( $this->parent->getValue() == $this->options['name'] ) {
47
+ $this->addCssClass('current');
48
+
49
+ foreach($this->elements as $val) {
50
+ $val->setOption('isActive', 1);
51
+ }
52
+ } else {
53
+ foreach($this->elements as $val) {
54
+ $val->setOption('isActive', 0);
55
+ }
56
+ }
57
+
58
+ ?>
59
+ <div <?php $this->attrs() ?>>
60
+ <?php
61
+ }
62
+
63
+ /**
64
+ * Here we should render an end html of the tab.
65
+ *
66
+ * @since 1.0.0
67
+ * @return void
68
+ */
69
+ public function afterRendering()
70
+ {
71
+ ?>
72
+ </div>
73
+ <?php
74
+ }
75
+ }
76
+ }
libs/factory/forms/controls/holders/control-group.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Tab Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_ControlGroupHolder') ) {
18
+
19
+ /**
20
+ * Tab Control Holder
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_FactoryForms407_ControlGroupHolder extends Wbcr_FactoryForms407_ControlHolder {
25
+
26
+ /**
27
+ * A holder type.
28
+ *
29
+ * @since 1.0.0
30
+ * @var string
31
+ */
32
+ public $type = 'control-group';
33
+
34
+
35
+ /**
36
+ * Here we should render a beginning html of the tab.
37
+ *
38
+ * @since 1.0.0
39
+ * @return void
40
+ */
41
+ public function beforeRendering()
42
+ {
43
+ $name = $this->getNameOnForm();
44
+ $value = $this->getValue();
45
+
46
+ $title = $this->getOption('title', null);
47
+
48
+ ?>
49
+ <div <?php $this->attrs() ?>>
50
+ <input type="hidden" name="<?php echo $name ?>" id="<?php echo $name ?>" class="factory-ui-control-group" value="<?php echo $value ?>"/>
51
+
52
+ <?php if( $title ) { ?>
53
+ <strong class="factory-header"><?php echo $title; ?></strong>
54
+ <?php } ?>
55
+
56
+ <ul class="factory-control-group-nav">
57
+ <?php
58
+ foreach($this->elements as $element):
59
+
60
+ if( $element->options['type'] !== 'control-group-item' ) {
61
+ continue;
62
+ }
63
+
64
+ $builder = new Wbcr_FactoryForms407_HtmlAttributeBuilder();
65
+
66
+ $builder->addCssClass('factory-control-group-nav-label');
67
+ $builder->addCssClass('factory-control-group-nav-label-' . $element->getOption('name'));
68
+ $builder->addHtmlData('control-id', 'factory-control-group-item-' . $element->getOption('name'));
69
+ $builder->addHtmlData('control-name', $element->getOption('name'));
70
+
71
+ if( $value == $element->getOption('name') ) {
72
+ $builder->addCssClass('current');
73
+ }
74
+
75
+ ?>
76
+ <li <?php $builder->printAttrs(); ?>><?php $element->title(); ?></li>
77
+ <?php endforeach; ?>
78
+ </ul>
79
+ <div class="factory-control-group-body">
80
+ <?php
81
+ }
82
+
83
+ /**
84
+ * Here we should render an end html of the tab.
85
+ *
86
+ * @since 1.0.0
87
+ * @return void
88
+ */
89
+ public function afterRendering()
90
+ {
91
+ ?>
92
+ </div>
93
+ </div>
94
+ <?php
95
+ }
96
+ }
97
+ }
libs/factory/forms/controls/holders/div.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Div Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_DivHolder') ) {
18
+ /**
19
+ * Div Control Holder
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ class Wbcr_FactoryForms407_DivHolder extends Wbcr_FactoryForms407_Holder {
24
+
25
+ /**
26
+ * A holder type.
27
+ *
28
+ * @since 1.0.0
29
+ * @var string
30
+ */
31
+ public $type = 'div';
32
+
33
+ /**
34
+ * Here we should render a beginning html of the tab.
35
+ *
36
+ * @since 1.0.0
37
+ * @return void
38
+ */
39
+ public function beforeRendering()
40
+ {
41
+
42
+ if( isset($this->options['class']) ) {
43
+ $this->addCssClass($this->options['class']);
44
+ }
45
+ if( isset($this->options['id']) ) {
46
+ $this->addHtmlAttr('id', $this->options['id']);
47
+ }
48
+
49
+ ?>
50
+ <div <?php $this->attrs() ?>>
51
+ <?php
52
+ }
53
+
54
+ /**
55
+ * Here we should render an end html of the tab.
56
+ *
57
+ * @since 1.0.0
58
+ * @return void
59
+ */
60
+ public function afterRendering()
61
+ {
62
+ ?>
63
+ </div>
64
+ <?php
65
+ }
66
+ }
67
+ }
libs/factory/forms/controls/holders/form-group.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Group Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_FormGroupHolder') ) {
18
+ /**
19
+ * Group Holder
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ class Wbcr_FactoryForms407_FormGroupHolder extends Wbcr_FactoryForms407_Holder {
24
+
25
+ /**
26
+ * A holder type.
27
+ *
28
+ * @since 1.0.0
29
+ * @var string
30
+ */
31
+ public $type = 'form-group';
32
+
33
+ /**
34
+ * Here we should render a beginning html of the tab.
35
+ *
36
+ * @since 1.0.0
37
+ * @return void
38
+ */
39
+ public function beforeRendering()
40
+ {
41
+
42
+ $this->addCssClass('factory-form-group-' . $this->getName());
43
+ $this->addHtmlAttr('id', 'factory-form-group-' . $this->getName());
44
+
45
+ ?>
46
+ <fieldset <?php $this->attrs() ?>>
47
+ <?php if( $this->hasTitle() ) { ?>
48
+ <legend class='factory-legend'>
49
+ <p class='factory-title'><?php $this->title() ?></p>
50
+ <?php if( $this->hasHint() ) { ?>
51
+ <p class='factory-hint'><?php echo $this->hint() ?></p>
52
+ <?php } ?>
53
+ </legend>
54
+ <?php } ?>
55
+ <?php
56
+ }
57
+
58
+ /**
59
+ * Here we should render an end html of the tab.
60
+ *
61
+ * @since 1.0.0
62
+ * @return void
63
+ */
64
+ public function afterRendering()
65
+ {
66
+ ?>
67
+ </fieldset>
68
+ <?php
69
+ }
70
+ }
71
+ }
libs/factory/forms/controls/holders/more-link.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of More Link Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_MoreLinkHolder') ) {
18
+
19
+ /**
20
+ * Collapsed Group Holder
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_FactoryForms407_MoreLinkHolder extends Wbcr_FactoryForms407_Holder {
25
+
26
+ /**
27
+ * A holder type.
28
+ *
29
+ * @since 1.0.0
30
+ * @var string
31
+ */
32
+ public $type = 'more-link';
33
+
34
+ /**
35
+ * Here we should render a beginning html of the tab.
36
+ *
37
+ * @since 1.0.0
38
+ * @return void
39
+ */
40
+ public function beforeRendering()
41
+ {
42
+ $count = isset($this->options['count'])
43
+ ? $this->options['count']
44
+ : 0;
45
+
46
+ $id = 'factory-more-link-' . $this->getName();
47
+
48
+ ?>
49
+ <div <?php $this->attrs() ?>>
50
+ <div class="form-group">
51
+ <div class="control-label col-sm-2"></div>
52
+ <div class="control-group col-sm-10">
53
+ <a href="#<?php echo $id ?>" class="factory-more-link-show"><?php $this->title() ?>
54
+ (<?php echo $count ?>)</a>
55
+ </div>
56
+ </div>
57
+ <div class='factory-more-link-content' id="<?php echo $id ?>" style="display: none;">
58
+ <a href="#<?php echo $id ?>" class='factory-more-link-hide'><?php _e('hide extra options', 'factory'); ?></a>
59
+ <?php
60
+ }
61
+
62
+ /**
63
+ * Here we should render an end html of the tab.
64
+ *
65
+ * @since 1.0.0
66
+ * @return void
67
+ */
68
+ public function afterRendering()
69
+ {
70
+ ?>
71
+ </div></div>
72
+ <?php
73
+ }
74
+ }
75
+ }
libs/factory/forms/controls/holders/tab-item.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Tab Item Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+ // Exit if accessed directly
12
+ if( !defined('ABSPATH') ) {
13
+ exit;
14
+ }
15
+
16
+ if( !class_exists('Wbcr_FactoryForms407_TabItemHolder') ) {
17
+ /**
18
+ * Tab Item Control Holder
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ class Wbcr_FactoryForms407_TabItemHolder extends Wbcr_FactoryForms407_Holder {
23
+
24
+ /**
25
+ * A holder type.
26
+ *
27
+ * @since 1.0.0
28
+ * @var string
29
+ */
30
+ public $type = 'tab-item';
31
+
32
+ /**
33
+ * Here we should render a beginning html of the tab.
34
+ *
35
+ * @since 1.0.0
36
+ * @return void
37
+ */
38
+ public function beforeRendering()
39
+ {
40
+
41
+ $this->addCssClass('tab-' . $this->getName());
42
+ $this->addHtmlAttr('id', $this->getName());
43
+
44
+ $this->addCssClass('tab-pane');
45
+
46
+ if( isset($this->options['isFirst']) && $this->options['isFirst'] ) {
47
+ $this->addCssClass('active');
48
+ }
49
+
50
+ ?>
51
+ <div <?php $this->attrs() ?>>
52
+ <?php
53
+ }
54
+
55
+ /**
56
+ * Here we should render an end html of the tab.
57
+ *
58
+ * @since 1.0.0
59
+ * @return void
60
+ */
61
+ public function afterRendering()
62
+ {
63
+ ?>
64
+ </div>
65
+ <?php
66
+ }
67
+ }
68
+ }
libs/factory/forms/controls/holders/tab.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Tab Control Holder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_TabHolder') ) {
18
+
19
+ /**
20
+ * Tab Control Holder
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ class Wbcr_FactoryForms407_TabHolder extends Wbcr_FactoryForms407_Holder {
25
+
26
+ /**
27
+ * A holder type.
28
+ *
29
+ * @since 1.0.0
30
+ * @var string
31
+ */
32
+ public $type = 'tab';
33
+
34
+ /**
35
+ * An align of a tab (horizontal or vertical).
36
+ *
37
+ * @since 1.0.0
38
+ * @var string
39
+ */
40
+ public $align = 'horizontal';
41
+
42
+ /**
43
+ * Creates a new instance of control holder.
44
+ *
45
+ * @since 1.0.0
46
+ * @param mixed[] $options A holder options.
47
+ * @param FactoryForms407_Form $form A parent form.
48
+ */
49
+ public function __construct($options, $form)
50
+ {
51
+ parent::__construct($options, $form);
52
+ $this->align = isset($options['align'])
53
+ ? $options['align']
54
+ : 'horizontal';
55
+ }
56
+
57
+ /**
58
+ * Here we should render a beginning html of the tab.
59
+ *
60
+ * @since 1.0.0
61
+ * @return void
62
+ */
63
+ public function beforeRendering()
64
+ {
65
+
66
+ $is_first_tab = true;
67
+ $tab_class = $this->getOption('class');
68
+
69
+ if( !empty($tab_class) ) {
70
+ $this->addCssClass($tab_class);
71
+ }
72
+
73
+ $this->addCssClass('factory-align-' . $this->align);
74
+
75
+ ?>
76
+ <div <?php $this->attrs() ?>>
77
+ <div class="factory-headers">
78
+ <ul class="nav nav-tabs">
79
+ <?php foreach($this->elements as $element) {
80
+ if( $element->options['type'] !== 'tab-item' ) {
81
+ continue;
82
+ }
83
+
84
+ $tab_icon = '';
85
+ $has_icon = isset($element->options['icon']);
86
+
87
+ if( $has_icon ) {
88
+ $tab_icon = $element->options['icon'];
89
+ }
90
+
91
+ $builder = new Wbcr_FactoryForms407_HtmlAttributeBuilder();
92
+
93
+ $builder->addCssClass('factory-tab-item-header');
94
+ $builder->addCssClass('factory-tab-item-header-' . $element->getName());
95
+
96
+ if( $has_icon ) {
97
+ $builder->addCssClass('factory-tab-item-header-with-icon');
98
+ }
99
+ if( $is_first_tab ) {
100
+ $builder->addCssClass('active');
101
+ }
102
+
103
+ $builder->addHtmlData('tab-id', $element->getName());
104
+ $is_first_tab = false;
105
+
106
+ if( $has_icon ) { ?>
107
+ <style>
108
+ .factory-form-tab-item-header-<?php $element->name() ?> a {
109
+ background-image: url("<?php echo $tab_icon ?>");
110
+ }
111
+ </style>
112
+ <?php } ?>
113
+ <li <?php $builder->printAttrs() ?>>
114
+ <a href="#<?php $element->name() ?>" data-toggle="tab">
115
+ <?php $element->title() ?>
116
+ </a>
117
+ </li>
118
+ <?php } ?>
119
+ </ul>
120
+ </div>
121
+ <div class='tab-content factory-bodies'>
122
+ <?php
123
+ }
124
+
125
+ /**
126
+ * Here we should render an end html of the tab.
127
+ *
128
+ * @since 1.0.0
129
+ * @return void
130
+ */
131
+ public function afterRendering()
132
+ {
133
+ ?>
134
+ </div>
135
+ </div>
136
+ <?php
137
+ }
138
+ }
139
+ }
libs/factory/forms/controls/integer.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Integer Control
5
+ * Main options:
6
+ * name => a name of the control
7
+ * way => Тип значения 'slider' - слайдер, 'checkbox-slider' - чекбокс активирует слайдер, по умолчанию input
8
+ * checkbox => Указывается если, 'way' имеет значение 'checkbox-slider'
9
+ * Пример:
10
+ * array(
11
+ * 'on' => __('Show shadow', 'bizpanda'),
12
+ * 'off' => __('Hide shadow', 'bizpanda'),
13
+ * )
14
+ * title => Заголовок контрола
15
+ * slider-title => Заголовок слайдера( Только если 'way' имеет значение 'checkbox-slider' )
16
+ * range => Диапазон значений, указывается если 'way' имеет значение 'slider' или 'checkbox-slider'
17
+ * Пример: array(0,100)
18
+ * units => Единицы измерения(px,pt,em,%)
19
+ * isActive => Включение, отключение поля
20
+ * value => a value to show in the control
21
+ * default => a default value of the control if the "value" option is not specified
22
+ *
23
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
24
+ * @copyright (c) 2018, Webcraftic Ltd
25
+ *
26
+ * @package factory-forms
27
+ * @since 1.0.0
28
+ */
29
+
30
+ // Exit if accessed directly
31
+ if( !defined('ABSPATH') ) {
32
+ exit;
33
+ }
34
+
35
+ if( !class_exists('Wbcr_FactoryForms407_IntegerControl') ) {
36
+
37
+ class Wbcr_FactoryForms407_IntegerControl extends Wbcr_FactoryForms407_Control {
38
+
39
+ public $type = 'integer';
40
+
41
+ /**
42
+ * Converting string to integer.
43
+ *
44
+ * @since 1.0.0
45
+ * @return integer
46
+ */
47
+ public function html()
48
+ {
49
+
50
+ $name = $this->getNameOnForm();
51
+ $value = esc_attr($this->getValue());
52
+ $step = 1;
53
+ $range = $checkbox = array();
54
+ $is_active = $this->getOption('isActive', 1);
55
+ $unit = esc_attr($this->getOption('units'));
56
+
57
+ $way = $this->getOption('way');
58
+
59
+ if( empty($way) ) {
60
+ $way = 'text';
61
+ }
62
+
63
+ $has_slider = false;
64
+
65
+ if( in_array($way, array('slider', 'checkbox-slider')) ) {
66
+ $range = $this->getOption('range', array(0, 99));
67
+ $slider_title = $this->getOption('slider-title');
68
+ $checkbox = $this->getOption('checkbox');
69
+ $step = $this->getOption('step', 1);
70
+ $has_slider = true;
71
+ }
72
+
73
+ $this->addCssClass('factory-way-' . $way);
74
+
75
+ if( $has_slider ) {
76
+ $this->addCssClass('factory-has-slider');
77
+ }
78
+ ?>
79
+
80
+ <div <?php $this->attrs() ?>>
81
+ <?php if( $has_slider ) { ?>
82
+
83
+ <?php if( 'checkbox-slider' == $way ) { ?>
84
+
85
+ <div>
86
+ <label for="<?php echo $name; ?>_checker"><?php echo $is_active
87
+ ? $checkbox['off']
88
+ : $checkbox['on']; ?></label><br>
89
+ <input type="checkbox" id="<?php echo $name; ?>_checker" class="factory-checkbox" name="<?php echo $name; ?>_checker" <?php echo $is_active
90
+ ? 'checked'
91
+ : '' ?>>
92
+ </div>
93
+
94
+ <?php } ?>
95
+
96
+ <div
97
+ data-units="<?php echo $unit ?>"
98
+ data-range-start="<?php echo $range[0] ?>"
99
+ data-range-end="<?php echo $range[1] ?>"
100
+ data-step="<?php echo $step ?>"
101
+ <?php echo !$is_active
102
+ ? ' style="display:none;"'
103
+ : '' ?>
104
+ class="factory-slider-container factory-slider-container-<?php echo $name; ?>">
105
+ <?php if( !empty($slider_title) ): ?>
106
+ <label class="factory-title">
107
+ <?php echo $this->getOption('slider-title'); ?>
108
+ </label>
109
+ <?php endif; ?>
110
+
111
+ <div class="factory-slider">
112
+ <div class="factory-bar"></div>
113
+ <span class="factory-visible-value">
114
+ <?php echo $value ?><?php echo $unit ?>
115
+ </span>
116
+ </div>
117
+ <input type="hidden" name="<?php echo $name; ?>" class="factory-result" value="<?php echo $value; ?>"/>
118
+ </div>
119
+
120
+ <?php } else { ?>
121
+
122
+ <input type="number" id="<?php echo $name; ?>" name="<?php echo $name; ?>" value="<?php echo $value; ?>" class="factory-input-text"/>
123
+ <span class="factory-units"><?php echo $unit ?></span>
124
+
125
+ <?php } ?>
126
+ </div><!-- .factory-integer -->
127
+ <?php
128
+ }
129
+
130
+ /**
131
+ * Форматирует значение без единиц измерения
132
+ * @param string $values
133
+ * @param string $unit
134
+ * @return string
135
+ */
136
+ public function valueFormatWithoutUnit($values, $unit)
137
+ {
138
+ if( !is_numeric($values) ) {
139
+ return str_replace($unit, '', $values);
140
+ } else {
141
+ return $values;
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Форматирует значение c единицами измерения
147
+ * @param string $values
148
+ * @param string $unit
149
+ * @return string
150
+ */
151
+ public function valueFormatWithUnit($values, $unit)
152
+ {
153
+ if( is_numeric($values) ) {
154
+ return $values . $unit;
155
+ } else {
156
+ return $values;
157
+ }
158
+ }
159
+ }
160
+ }
libs/factory/forms/controls/list.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Multiselect List Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * items => a callback to return items or an array of items to select
11
+ *
12
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
13
+ * @copyright (c) 2018, Webcraftic Ltd
14
+ *
15
+ * @package factory-forms
16
+ * @since 1.0.0
17
+ */
18
+
19
+ // Exit if accessed directly
20
+ if( !defined('ABSPATH') ) {
21
+ exit;
22
+ }
23
+
24
+ if( !class_exists('Wbcr_FactoryForms407_ListControl') ) {
25
+
26
+ class Wbcr_FactoryForms407_ListControl extends Wbcr_FactoryForms407_Control {
27
+
28
+ public $type = 'list';
29
+
30
+ /**
31
+ * Returns a set of available items for the list.
32
+ *
33
+ * @since 1.0.0
34
+ * @return mixed[]
35
+ */
36
+ private function getItems()
37
+ {
38
+
39
+ $data = $this->getOption('data', array());
40
+
41
+ // if the data options is a valid callback for an object method
42
+ if( (is_array($data) && count($data) == 2 && is_object($data[0])) || is_string($data) ) {
43
+
44
+ return call_user_func($data);
45
+ }
46
+
47
+ // if the data options is an array of values
48
+ return $data;
49
+ }
50
+
51
+ /**
52
+ * Returns true, if the data should be loaded via ajax.
53
+ *
54
+ * @since 1.0.0
55
+ * @return bool
56
+ */
57
+ protected function isAjax()
58
+ {
59
+
60
+ $data = $this->getOption('data', array());
61
+
62
+ return is_array($data) && isset($data['ajax']);
63
+ }
64
+
65
+ /**
66
+ * Shows the html markup of the control.
67
+ *
68
+ * @since 1.0.0
69
+ * @return void
70
+ */
71
+ public function html()
72
+ {
73
+
74
+ $way = $this->getOption('way', 'default');
75
+ $this->addHtmlData('way', $way);
76
+
77
+ if( $this->isAjax() ) {
78
+
79
+ $data = $this->getOption('data', array());
80
+ $ajax_id = 'factory-list-' . rand(1000000, 9999999);
81
+
82
+ $value = $this->getValue(null, true);
83
+
84
+ if( empty($value) || empty($value[0]) ) {
85
+ $value = array();
86
+ }
87
+
88
+ ?>
89
+ <div class="factory-ajax-loader <?php echo $ajax_id . '-loader'; ?>"></div>
90
+ <script>
91
+ window['<?php echo $ajax_id ?>'] = {
92
+ 'loader': '.<?php echo $ajax_id . '-loader' ?>',
93
+ 'url': '<?php echo $data['url'] ?>',
94
+ 'data': <?php echo json_encode( $data['data'] ) ?>,
95
+ 'selected': <?php echo json_encode( $value ) ?>,
96
+ 'emptyList': '<?php echo $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_407') ) ?>'
97
+ };
98
+ </script>
99
+ <?php
100
+
101
+ $this->addHtmlData('ajax', true);
102
+ $this->addHtmlData('ajax-data-id', $ajax_id);
103
+ $this->addCssClass('factory-hidden');
104
+ }
105
+
106
+ if( 'checklist' == $way ) {
107
+ $this->checklistHtml();
108
+ } else {
109
+ $this->defaultHtml();
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Shows the Buttons Dropdown.
115
+ *
116
+ * @since 1.0.0
117
+ * @return void
118
+ */
119
+ protected function checklistHtml()
120
+ {
121
+ $items = $this->getItems();
122
+
123
+ $value = explode(',', $this->getValue());
124
+ if( empty($value) || empty($value[0]) ) {
125
+ $value = array();
126
+ }
127
+
128
+ $name_on_form = $this->getNameOnForm();
129
+
130
+ $this->addCssClass('factory-checklist-way');
131
+ $this->addHtmlData('name', $name_on_form);
132
+
133
+ $errors_callback = $this->getOption('errors');
134
+ $errors = !empty($errors_callback)
135
+ ? call_user_func($errors_callback)
136
+ : array();
137
+
138
+ $is_empty = $this->isAjax() || empty($items);
139
+ $emptyList = $this->getOption('empty', __('The list is empty.', 'wbcr_factory_forms_407'));
140
+
141
+ if( $is_empty ) {
142
+ $this->addCssClass('factory-empty');
143
+ }
144
+
145
+ ?>
146
+ <ul <?php $this->attrs() ?>>
147
+ <?php if( $is_empty ) { ?>
148
+ <li><?php echo $emptyList ?></li>
149
+ <?php } else { ?>
150
+ <?php foreach($items as $item) { ?>
151
+ <li>
152
+ <label for="factory-checklist-<?php echo $name_on_form ?>-<?php echo $item[0] ?>" class="<?php if( !empty($errors[$item[0]]) ) {
153
+ echo 'factory-has-error';
154
+ } ?>">
155
+ <?php if( !empty($errors[$item[0]]) ) { ?>
156
+ <span class="factory-error">
157
+ <i class="fa fa-exclamation-triangle"></i>
158
+ <div class='factory-error-text'><?php echo $errors[$item[0]] ?></div>
159
+ </span>
160
+ <?php } else { ?>
161
+ <span>
162
+ <input
163
+ type="checkbox"
164
+ name="<?php echo $name_on_form ?>[]"
165
+ value="<?php echo $item[0] ?>"
166
+ id="factory-checklist-<?php echo $name_on_form ?>-<?php echo $item[0] ?>"
167
+ <?php if( in_array($item[0], $value) ) {
168
+ echo 'checked="checked"';
169
+ } ?> />
170
+ </span>
171
+ <?php } ?>
172
+
173
+ <span><?php echo $item[1] ?></span>
174
+ </label>
175
+ </li>
176
+ <?php } ?>
177
+ <?php } ?>
178
+ </ul>
179
+ <?php
180
+ }
181
+
182
+ /**
183
+ * Shows the standart dropdown.
184
+ *
185
+ * @since 1.3.1
186
+ * @return void
187
+ */
188
+ protected function defaultHtml()
189
+ {
190
+
191
+ $items = $this->getItems();
192
+ $value = $this->getValue();
193
+
194
+ $name_on_form = $this->getNameOnForm();
195
+
196
+ $this->addHtmlAttr('id', $name_on_form);
197
+ $this->addHtmlAttr('name', $name_on_form);
198
+ $this->addCssClass('form-control');
199
+
200
+ ?>
201
+ <select multiple="multiple" <?php $this->attrs() ?>/>
202
+ <?php foreach($items as $item) {
203
+ if( count($item) == 3 ) {
204
+ ?>
205
+ <optgroup label="<?php echo $item[1] ?>">
206
+ <?php foreach($item[2] as $subitem) { ?>
207
+ <?php $selected = ($subitem[0] == $value)
208
+ ? 'selected="selected"'
209
+ : ''; ?>
210
+ <option value='<?php echo $subitem[0] ?>' <?php echo $selected ?>>
211
+ <?php echo $subitem[1] ?>
212
+ </option>
213
+ <?php } ?>
214
+ </optgroup>
215
+ <?php
216
+ } else {
217
+ $selected = ($item[0] == $value)
218
+ ? 'selected="selected"'
219
+ : '';
220
+ ?>
221
+ <option value='<?php echo $item[0] ?>' <?php echo $selected ?>>
222
+ <?php echo $item[1] ?>
223
+ </option>
224
+ <?php } ?>
225
+ <?php } ?>
226
+ </select>
227
+ <?php
228
+ }
229
+ }
230
+ }
libs/factory/forms/controls/multiple-textbox.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Control multiple textbox
5
+ *
6
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
7
+ * @copyright (c) 2018, Webcraftic Ltd
8
+ *
9
+ * @package factory-forms
10
+ * @since 1.0.0
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if( !defined('ABSPATH') ) {
15
+ exit;
16
+ }
17
+
18
+ if( !class_exists('Wbcr_FactoryForms407_MultipleTextboxControl') ) {
19
+
20
+ class Wbcr_FactoryForms407_MultipleTextboxControl extends Wbcr_FactoryForms407_Control {
21
+
22
+ public $type = 'multiple-textbox';
23
+
24
+ /**
25
+ * Preparing html attributes before rendering html of the control.
26
+ *
27
+ * @since 1.0.0
28
+ * @return void
29
+ */
30
+ protected function beforeHtml()
31
+ {
32
+
33
+ $name_on_form = $this->getNameOnForm();
34
+
35
+ if( $this->getOption('maxLength', false) ) {
36
+ $this->addHtmlAttr('maxlength', intval($this->getOption('maxLength')));
37
+ }
38
+
39
+ if( $this->getOption('placeholder', false) ) {
40
+ $this->addHtmlAttr('placeholder', $this->getOption('placeholder'));
41
+ }
42
+
43
+ $this->addCssClass('form-control');
44
+ $this->addHtmlAttr('type', 'text');
45
+ //$this->addHtmlAttr('id', $name_on_form);
46
+ $this->addCssClass(str_replace('_', '-', $name_on_form));
47
+ $this->addHtmlAttr('name', $name_on_form . '[]');
48
+ }
49
+
50
+ /**
51
+ * Shows the html markup of the control.
52
+ *
53
+ * @since 1.0.0
54
+ * @return void
55
+ */
56
+ public function html()
57
+ {
58
+
59
+ $values = $this->getValue();
60
+
61
+ if( !empty($values) ) {
62
+ $values = explode('{%spr%}', $values);
63
+ } else {
64
+ $values = array();
65
+ }
66
+
67
+ ?>
68
+ <div class="factory-multiple-textbox-group">
69
+ <div class="factory-mtextbox-items">
70
+ <?php if( empty($values) ): ?>
71
+ <div class="factory-mtextbox-item">
72
+ <input <?php $this->attrs() ?>/>
73
+ </div>
74
+ <?php else: ?>
75
+ <?php $counter = 0; ?>
76
+ <?php foreach($values as $value): ?>
77
+ <div class="factory-mtextbox-item">
78
+ <input value="<?= esc_attr($value) ?>"<?php $this->attrs() ?>/>
79
+ <?php if( $counter >= 1 ): ?>
80
+ <button class="btn btn-default btn-small factory-mtextbox-remove-item">
81
+ <i class="fa fa-times" aria-hidden="true"></i></button>
82
+ <?php endif; ?>
83
+ </div>
84
+ <?php $counter++; ?>
85
+ <?php endforeach; ?>
86
+ <?php endif; ?>
87
+ </div>
88
+ <button class="btn btn-default btn-small factory-mtextbox-add-item">
89
+ <i class="fa fa-plus" aria-hidden="true"></i> <?php _e('Add new', 'wbcr_factory_forms_407') ?>
90
+ </button>
91
+ </div>
92
+
93
+ <?php
94
+ }
95
+
96
+ /**
97
+ * Returns a submit value of the control by a given name.
98
+ *
99
+ * @since 1.0.0
100
+ * @return mixed
101
+ */
102
+ public function getSubmitValue($name, $subName)
103
+ {
104
+ $name_on_form = $this->getNameOnForm($name);
105
+
106
+ $value = isset($_POST[$name_on_form])
107
+ ? $_POST[$name_on_form]
108
+ : null;
109
+
110
+ if( is_array($value) ) {
111
+ $value = array_map('sanitize_text_field', $value);
112
+ $value = implode('{%spr%}', $value);
113
+ }
114
+
115
+ $value = sanitize_text_field($value);
116
+
117
+ return $value;
118
+ }
119
+ }
120
+ }
libs/factory/forms/controls/paddings-editor.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Paddings Control
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_PaddingsEditorControl') ) {
18
+
19
+ class Wbcr_FactoryForms407_PaddingsEditorControl extends Wbcr_FactoryForms407_Control {
20
+
21
+ public $type = 'paddings-editor';
22
+
23
+ /**
24
+ * Converting string to integer.
25
+ *
26
+ * @since 1.0.0
27
+ * @return integer
28
+ */
29
+ public function html()
30
+ {
31
+
32
+ $name = $this->getNameOnForm();
33
+ $raw_value = esc_attr($this->getValue());
34
+
35
+ $units = $this->getOption('units');
36
+ $values_with_units = explode(' ', $raw_value);
37
+
38
+ $values = array();
39
+ foreach($values_with_units as $value_with_unit) {
40
+ $values[] = intval($value_with_unit);
41
+ }
42
+
43
+ $unit = $this->getOption('units', 'px');
44
+ $range = $this->getOption('range', array(0, 99));
45
+ $step = $this->getOption('step', 1);
46
+
47
+ ?>
48
+ <div <?php $this->attrs() ?>
49
+ data-units="<?php echo $unit ?>"
50
+ data-range-start="<?php echo $range[0] ?>"
51
+ data-range-end="<?php echo $range[1] ?>"
52
+ data-step="<?php echo $step ?>">
53
+ <div class="factory-rectangle">
54
+ <div class="factory-side factory-side-top" data-value="<?php echo $values[0] ?>">
55
+ <span class="factory-visible-value"><?php echo $values[0] ?><?php echo $units ?></span>
56
+ </div>
57
+ <div class="factory-side factory-side-bottom" data-value="<?php echo $values[1] ?>">
58
+ <span class="factory-visible-value"><?php echo $values[1] ?><?php echo $units ?></span>
59
+ </div>
60
+ <div class="factory-side factory-side-left" data-value="<?php echo $values[2] ?>">
61
+ <span class="factory-visible-value"><?php echo $values[2] ?><?php echo $units ?></span>
62
+ </div>
63
+ <div class="factory-side factory-side-right" data-value="<?php echo $values[3] ?>">
64
+ <span class="factory-visible-value"><?php echo $values[3] ?><?php echo $units ?></span>
65
+ </div>
66
+ <div class="factory-side factory-side-center" data-value="<?php echo $values[0] ?>"></div>
67
+ </div>
68
+ <div class="factory-slider-container">
69
+ <label class="factory-title">
70
+ <?php _e('Select a side and move the slider to set up:', 'wbcr_factory_forms_407') ?>
71
+ </label>
72
+
73
+ <div class="factory-slider">
74
+ <div class="factory-bar"></div>
75
+ </div>
76
+ </div>
77
+ <input type="hidden" class="factory-result" name="<?php echo $name ?>" value="<?php echo $raw_value ?>"/>
78
+ </div>
79
+ <?php
80
+ }
81
+ }
82
+ }
libs/factory/forms/controls/pattern.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Pattern Control
5
+ *
6
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
7
+ * @copyright (c) 2018, Webcraftic Ltd
8
+ *
9
+ * @package factory-forms
10
+ * @since 3.1.0
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if( !defined('ABSPATH') ) {
15
+ exit;
16
+ }
17
+
18
+ if( !class_exists('Wbcr_FactoryForms407_PatternControl') ) {
19
+
20
+ class Wbcr_FactoryForms407_PatternControl extends Wbcr_FactoryForms407_Control {
21
+
22
+ public $type = 'pattern';
23
+
24
+ public function getName()
25
+ {
26
+ return array(
27
+ $this->getOption('name') . '__url',
28
+ $this->getOption('name') . '__color'
29
+ );
30
+ }
31
+
32
+ public function __construct($options, $form, $provider = null)
33
+ {
34
+ parent::__construct($options, $form, $provider);
35
+
36
+ if( !isset($options['color']) ) {
37
+ $options['color'] = array();
38
+ }
39
+
40
+ $options['color'] = array_merge($options['color'], array(
41
+ 'name' => $this->options['name'] . '_color_picker',
42
+ 'default' => isset($this->options['default'])
43
+ ? $this->options['default']['color']
44
+ : null,
45
+ 'pickerTarget' => '.factory-control-' . $this->options['name'] . ' .factory-picker-target'
46
+ ));
47
+
48
+ if( !$options['color']['default'] ) {
49
+ $options['color']['default'] = '#1e8cbe';
50
+ }
51
+
52
+ $name = $this->getOption('name');
53
+
54
+ // filters to get available patterns for the given background contols
55
+ $this->patterns = apply_filters('wbcr_factory_forms_407_patterns', array());
56
+ $this->patterns = apply_filters('wbcr_factory_forms_407_patterns-' . $name, $this->patterns);
57
+
58
+ $this->custom_patterns = $this->getOption('patterns', array());
59
+
60
+ $this->color = new Wbcr_FactoryForms407_ColorControl($options['color'], $form, $provider);
61
+ }
62
+
63
+ /**
64
+ * Shows the html markup of the control.
65
+ *
66
+ * @since 1.0.0
67
+ * @return void
68
+ */
69
+ public function html()
70
+ {
71
+ $name = $this->getNameOnForm();
72
+ $values = $this->getValue();
73
+
74
+ // if a pattern is not set by defaut, sets the first available pattern
75
+ if( empty($values['url']) && !empty($this->patterns) ) {
76
+ foreach($this->patterns as $group_key => $groupValue) {
77
+ if( !empty($this->patterns[$group_key]['patterns']) ) {
78
+ $values['url'] = $this->patterns[$group_key]['patterns'][0]['pattern'];
79
+ break;
80
+ }
81
+ }
82
+ }
83
+
84
+ if( !empty($values['color']) ) {
85
+ $this->color->setOption('value', $values['color']);
86
+ }
87
+
88
+ $hasColor = !empty($values['color']);
89
+
90
+ if( $hasColor ) {
91
+ $this->addCssClass('factory-color-panel-active');
92
+ }
93
+
94
+ ?>
95
+ <div <?php $this->attrs() ?>>
96
+ <div class="factory-pattern-controls">
97
+ <div class="factory-preview-wrap">
98
+ <div <?php echo (!empty($values['url']))
99
+ ? 'style="background:url(' . esc_url($values['url']) . ') repeat; border:0; font-size:0;"'
100
+ : ''; ?> class="factory-preview <?php echo $this->getOption('name'); ?>"><span></span>
101
+ </div>
102
+ </div>
103
+ <a href="#" class="button button-default factory-button factory-change-color-btn <?php if( $hasColor ) {
104
+ echo 'button-active';
105
+ } ?>" title="<?php _e('Change color', 'wbcr_factory_forms_407') ?>">
106
+ <i class="fa fa-flask"></i>
107
+ <span><?php _e('re-color', 'wbcr_factory_forms_407') ?></span>
108
+ </a>
109
+ <input type="hidden" id="<?php echo $name[0]; ?>" name="<?php echo $name[0]; ?>" value="<?php echo esc_url($values['url']); ?>" class="factory-pattern-result">
110
+ <input type="hidden" id="<?php echo $name[1]; ?>" name="<?php echo $name[1]; ?>" value="<?php echo esc_attr($values['color']); ?>" class="factory-color-result">
111
+ </div>
112
+ <div class="factory-color-panel">
113
+ <div class="factory-color-wrap">
114
+ <span class="factory-color-label"><?php _e('Select color:', 'wbcr_factory_forms_407') ?></span>
115
+ <?php $this->color->html() ?>
116
+ <div class="factory-hint">
117
+ <i><?php _e('Changing the color may takes a minute or more. Please be patient.', 'wbcr_factory_forms_407') ?></i>
118
+ </div>
119
+ </div>
120
+ <div class="factory-picker-target"></div>
121
+ </div>
122
+ <div class="factory-patterns-panel">
123
+ <div class="factory-patterns-group factory-patterns-group-custom">
124
+ <?php $this->printPatterns($this->custom_patterns, 4, '<div class="factory-patterns-item factory-upload-btn factory-no-preview"><span class="fa fa-upload"></span></div>') ?>
125
+ </div>
126
+ <?php foreach($this->patterns as $key => $group): ?>
127
+ <?php if( !empty($group['patterns']) ): ?>
128
+ <div class="factory-patterns-group factory-patterns-group-<?php echo $key ?>">
129
+ <div class="factory-patterns-group-title"><?php echo $group['title'] ?></div>
130
+ <?php $this->printPatterns($group['patterns'], 4) ?>
131
+ </div>
132
+ <?php endif; ?>
133
+ <?php endforeach; ?>
134
+ </div>
135
+ <div class="clearfix"></div>
136
+ </div>
137
+ <?php
138
+ }
139
+
140
+ /**
141
+ * @param $patterns
142
+ * @param $perRow
143
+ * @param null $first_item
144
+ */
145
+ private function printPatterns($patterns, $perRow, $first_item = null)
146
+ {
147
+ $counter = 0;
148
+ $print_first_item = $first_item;
149
+
150
+ ?>
151
+ <div class="factory-patterns-row">
152
+ <?php
153
+
154
+ if( $print_first_item ) {
155
+ echo $print_first_item;
156
+ $print_first_item = null;
157
+ $counter++;
158
+ }
159
+
160
+ foreach($patterns as $pattern) {
161
+ $counter++;
162
+
163
+ ?>
164
+ <div class="factory-patterns-item" data-pattern="<?php echo $pattern['pattern']; ?>">
165
+ <div class="factory-pattern-holder" style="background:url(<?php echo $pattern['preview']; ?>) repeat;"></div>
166
+ </div>
167
+ <?php
168
+
169
+ if( $counter == 4 ) {
170
+ $counter = 0;
171
+ ?>
172
+ </div><div class="factory-patterns-row">
173
+ <?php
174
+ }
175
+ }
176
+ ?>
177
+ </div>
178
+ <?php
179
+ }
180
+ }
181
+ }
libs/factory/forms/controls/radio-colors.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Radio Colors Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * data => a callback to return items or an array of items to select
11
+ * 'data' => array(
12
+ * array('default', '#75649b'),
13
+ * array('black', '#222'),
14
+ * array('light', '#fff3ce'),
15
+ * array('forest', '#c9d4be'),
16
+ *)
17
+ *
18
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
19
+ * @copyright (c) 2018, Webcraftic Ltd
20
+ *
21
+ * @package factory-forms
22
+ * @since 1.0.0
23
+ */
24
+
25
+ // Exit if accessed directly
26
+ if( !defined('ABSPATH') ) {
27
+ exit;
28
+ }
29
+
30
+ if( !class_exists('Wbcr_FactoryForms407_RadioColorsControl') ) {
31
+
32
+ class Wbcr_FactoryForms407_RadioColorsControl extends Wbcr_FactoryForms407_Control {
33
+
34
+ public $type = 'radio-color';
35
+
36
+ /**
37
+ * Returns a set of available items for the radio.
38
+ *
39
+ * @since 1.0.0
40
+ * @return mixed[]
41
+ */
42
+ private function getItems()
43
+ {
44
+ $data = $this->getOption('data', array());
45
+
46
+ // if the data options is a valid callback for an object method
47
+ if( (is_array($data) && count($data) == 2 && is_object($data[0])) || is_string($data) ) {
48
+
49
+ return call_user_func($data);
50
+ }
51
+
52
+ // if the data options is an array of values
53
+ return $data;
54
+ }
55
+
56
+ /**
57
+ * Preparing html attributes before rendering html of the control.
58
+ *
59
+ * @since 1.0.0
60
+ * @return void
61
+ */
62
+ protected function beforeHtml()
63
+ {
64
+ $name_on_form = $this->getNameOnForm();
65
+ $this->addHtmlAttr('name', $name_on_form);
66
+
67
+ echo '<div class="factory-colors-inner-wrap" data-radio-name="' . $name_on_form . '">';
68
+ }
69
+
70
+ /**
71
+ * Preparing html attributes afterHtml rendering html of the control.
72
+ *
73
+ * @since 1.0.0
74
+ * @return void
75
+ */
76
+ protected function afterHtml()
77
+ {
78
+ echo '</div>';
79
+ }
80
+
81
+ /**
82
+ * Shows the html markup of the control.
83
+ *
84
+ * @since 1.0.0
85
+ * @return void
86
+ */
87
+ public function html()
88
+ {
89
+ $items = $this->getItems();
90
+ $value = $this->getValue();
91
+
92
+ ?>
93
+ <?php foreach($items as $item) {
94
+ $checked = ($item[0] == $value)
95
+ ? 'checked="checked"'
96
+ : '';
97
+
98
+ if( empty($item[1]) || strpos($item[1], '#') === false ) {
99
+ $item[1] = '#fff';
100
+ }
101
+ ?>
102
+ <span class="factory-form-radio-item">
103
+ <lable class="factory-from-radio-label">
104
+ <input type="radio" <?php $this->attrs() ?> value="<?php echo esc_attr($item[0]) ?>" <?php echo $checked ?>/>
105
+ <span style="background-color:<?= esc_attr($item[1]) ?>"></span>
106
+ </lable>
107
+ </span>
108
+ <?php }
109
+ }
110
+ }
111
+ }
libs/factory/forms/controls/radio.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Radio Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * items => a callback to return items or an array of items to select
11
+ *
12
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
13
+ * @copyright (c) 2018, Webcraftic Ltd
14
+ *
15
+ * @package factory-forms
16
+ * @since 1.0.0
17
+ */
18
+
19
+ // Exit if accessed directly
20
+ if( !defined('ABSPATH') ) {
21
+ exit;
22
+ }
23
+
24
+ if( !class_exists('Wbcr_FactoryForms407_RadioControl') ) {
25
+
26
+ class Wbcr_FactoryForms407_RadioControl extends Wbcr_FactoryForms407_Control {
27
+
28
+ public $type = 'radio';
29
+
30
+ /**
31
+ * Returns a set of available items for the radio.
32
+ *
33
+ * @since 1.0.0
34
+ * @return mixed[]
35
+ */
36
+ private function getItems()
37
+ {
38
+ $data = $this->getOption('data', array());
39
+
40
+ // if the data options is a valid callback for an object method
41
+ if( (is_array($data) && count($data) == 2 && is_object($data[0])) || is_string($data) ) {
42
+
43
+ return call_user_func($data);
44
+ }
45
+
46
+ // if the data options is an array of values
47
+ return $data;
48
+ }
49
+
50
+ /**
51
+ * Preparing html attributes before rendering html of the control.
52
+ *
53
+ * @since 1.0.0
54
+ * @return void
55
+ */
56
+ protected function beforeHtml()
57
+ {
58
+ $name_on_form = $this->getNameOnForm();
59
+ $this->addHtmlAttr('name', $name_on_form);
60
+ }
61
+
62
+ /**
63
+ * Shows the html markup of the control.
64
+ *
65
+ * @since 1.0.0
66
+ * @return void
67
+ */
68
+ public function html()
69
+ {
70
+ $items = $this->getItems();
71
+ $value = $this->getValue();
72
+ ?>
73
+ <?php foreach($items as $item) {
74
+ $checked = ($item[0] == $value)
75
+ ? 'checked="checked"'
76
+ : '';
77
+ ?>
78
+ <span class="factory-form-radio-item">
79
+ <lable class="factory-from-radio-label"><?= esc_html($item[1]); ?></lable>
80
+ <input type="radio" <?php $this->attrs() ?> value="<?php echo esc_attr($item[0]) ?>" <?php echo $checked ?>/>
81
+ </span>
82
+ <?php }
83
+ }
84
+ }
85
+ }
libs/factory/forms/controls/textarea.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Textarea Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ *
11
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
12
+ * @copyright (c) 2018, Webcraftic Ltd
13
+ *
14
+ * @package factory-forms
15
+ * @since 1.0.0
16
+ */
17
+
18
+ // Exit if accessed directly
19
+ if( !defined('ABSPATH') ) {
20
+ exit;
21
+ }
22
+
23
+ if( !class_exists('Wbcr_FactoryForms407_TextareaControl') ) {
24
+
25
+ class Wbcr_FactoryForms407_TextareaControl extends Wbcr_FactoryForms407_Control {
26
+
27
+ public $type = 'textarea';
28
+
29
+ /**
30
+ * Returns a submit value of the control by a given name.
31
+ *
32
+ * @since 1.0.0
33
+ * @return mixed
34
+ */
35
+ public function getSubmitValue($name, $subName)
36
+ {
37
+ $name_on_form = $this->getNameOnForm($name);
38
+
39
+ $raw_value = isset($_POST[$name_on_form])
40
+ ? $_POST[$name_on_form]
41
+ : null;
42
+
43
+ $value = $raw_value;
44
+
45
+ if( is_array($value) ) {
46
+ $value = array_map('sanitize_textarea_field', $value);
47
+ $value = implode(',', $value);
48
+ } else {
49
+ $value = sanitize_textarea_field($value);
50
+ }
51
+
52
+ return $this->filterValue($value, $raw_value);
53
+ }
54
+
55
+ /**
56
+ * Preparing html attributes before rendering html of the control.
57
+ *
58
+ * @since 1.0.0
59
+ * @return void
60
+ */
61
+ protected function beforeHtml()
62
+ {
63
+ $name_on_form = $this->getNameOnForm();
64
+ $height = (int)$this->getOption('height', 100);
65
+
66
+ $this->addCssClass('form-control');
67
+ $this->addHtmlAttr('name', $name_on_form);
68
+ $this->addHtmlAttr('id', $name_on_form);
69
+ $this->addHtmlAttr('style', 'min-height:' . $height . 'px');
70
+ }
71
+
72
+ /**
73
+ * Shows the html markup of the control.
74
+ *
75
+ * @since 1.0.0
76
+ * @return void
77
+ */
78
+ public function html()
79
+ {
80
+ ?>
81
+ <textarea <?php $this->attrs(); ?>><?php echo esc_textarea($this->getValue()); ?></textarea>
82
+ <?php
83
+ }
84
+ }
85
+ }
libs/factory/forms/controls/textbox.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Textbox Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * maxLength => set the max length of text in the input control
11
+ * placeholder => a placeholder text for the control when the control value is empty
12
+ *
13
+ * Использование datepicker в текстовом поле (необходимо подключить bootstrap.datepicker)
14
+ * 'htmlAttrs' => array(
15
+ * 'data-provide' => 'datepicker-inline',
16
+ * 'data-date-language' => 'ru',
17
+ * 'data-date-autoclose' => 'true'
18
+ * )
19
+ *
20
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
21
+ * @copyright (c) 2018, Webcraftic Ltd
22
+ *
23
+ * @package factory-forms
24
+ * @since 1.0.0
25
+ */
26
+
27
+ // Exit if accessed directly
28
+ if( !defined('ABSPATH') ) {
29
+ exit;
30
+ }
31
+
32
+ if( !class_exists('Wbcr_FactoryForms407_TextboxControl') ) {
33
+
34
+ class Wbcr_FactoryForms407_TextboxControl extends Wbcr_FactoryForms407_Control {
35
+
36
+ public $type = 'textbox';
37
+
38
+ /**
39
+ * Preparing html attributes before rendering html of the control.
40
+ *
41
+ * @since 1.0.0
42
+ * @return void
43
+ */
44
+ protected function beforeHtml()
45
+ {
46
+ $value = esc_attr($this->getValue());
47
+ $name_on_form = $this->getNameOnForm();
48
+
49
+ if( $this->getOption('maxLength', false) ) {
50
+ $this->addHtmlAttr('maxlength', intval($this->getOption('maxLength')));
51
+ }
52
+
53
+ if( $this->getOption('placeholder', false) ) {
54
+ $this->addHtmlAttr('placeholder', $this->getOption('placeholder'));
55
+ }
56
+
57
+ $this->addCssClass('form-control');
58
+ $this->addHtmlAttr('type', 'text');
59
+ $this->addHtmlAttr('id', $name_on_form);
60
+ $this->addHtmlAttr('name', $name_on_form);
61
+ $this->addHtmlAttr('value', $value);
62
+ }
63
+
64
+ /**
65
+ * Shows the html markup of the control.
66
+ *
67
+ * @since 1.0.0
68
+ * @return void
69
+ */
70
+ public function html()
71
+ {
72
+ $units = $this->getOption('units', false);
73
+ ?>
74
+ <?php if( $units ) { ?><div class="input-group"><?php } ?>
75
+ <input <?php $this->attrs() ?>/>
76
+ <?php if( $units ) { ?>
77
+ <span class="input-group-addon"><?php echo $units; ?></span>
78
+ <?php } ?>
79
+ <?php if( $units ) { ?></div><?php } ?>
80
+ <?php
81
+ }
82
+ }
83
+ }
libs/factory/forms/controls/url.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Url Control
5
+ *
6
+ * Main options:
7
+ * @see FactoryForms407_TextboxControl
8
+ *
9
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
10
+ * @copyright (c) 2018, Webcraftic Ltd
11
+ *
12
+ * @package factory-forms
13
+ * @since 1.0.0
14
+ */
15
+
16
+ // Exit if accessed directly
17
+ if( !defined('ABSPATH') ) {
18
+ exit;
19
+ }
20
+
21
+ if( !class_exists('Wbcr_FactoryForms407_UrlControl') ) {
22
+
23
+ class Wbcr_FactoryForms407_UrlControl extends Wbcr_FactoryForms407_TextboxControl {
24
+
25
+ public $type = 'url';
26
+
27
+ /**
28
+ * Adding 'http://' to the url if it was missed.
29
+ *
30
+ * @since 1.0.0
31
+ * @return string
32
+ */
33
+ public function getSubmitValue($name, $sub_name)
34
+ {
35
+ $value = parent::getSubmitValue($name, $sub_name);
36
+ if( !empty($value) && substr($value, 0, 4) != 'http' ) {
37
+ $value = 'http://' . $value;
38
+ }
39
+
40
+ return $value;
41
+ }
42
+ }
43
+ }
libs/factory/forms/controls/wp-editor.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * WP Editor Control
5
+ *
6
+ * Main options:
7
+ * name => a name of the control
8
+ * value => a value to show in the control
9
+ * default => a default value of the control if the "value" option is not specified
10
+ * tinymce => an array of options for tinymce
11
+ * @link http://codex.wordpress.org/Function_Reference/wp_editor
12
+ *
13
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
14
+ * @copyright (c) 2018, Webcraftic Ltd
15
+ *
16
+ * @package factory-forms
17
+ * @since 1.0.0
18
+ */
19
+
20
+ // Exit if accessed directly
21
+ if( !defined('ABSPATH') ) {
22
+ exit;
23
+ }
24
+
25
+ if( !class_exists('Wbcr_FactoryForms407_WpEditorControl') ) {
26
+
27
+ class Wbcr_FactoryForms407_WpEditorControl extends Wbcr_FactoryForms407_Control {
28
+
29
+ public $type = 'wp-editor';
30
+
31
+ /**
32
+ * Preparing html attributes and options for tinymce.
33
+ *
34
+ * @since 1.0.0
35
+ * @return void
36
+ */
37
+ protected function beforeHtml()
38
+ {
39
+
40
+ if( empty($this->options['tinymce']) ) {
41
+ $this->options['tinymce'] = array();
42
+ }
43
+
44
+ if( !isset($this->options['tinymce']['content_css']) ) {
45
+ $this->options['tinymce']['content_css'] = FACTORY_FORMS_407_URL . '/assets/css/editor.css';
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Shows the html markup of the control.
51
+ *
52
+ * @since 1.0.0
53
+ * @return void
54
+ */
55
+ public function html()
56
+ {
57
+ $name_on_form = $this->getNameOnForm();
58
+
59
+ $value = $this->getValue();
60
+
61
+ ?>
62
+ <div class='factory-form-wp-editor'>
63
+ <?php wp_editor($value, $name_on_form, array(
64
+ 'textarea_name' => $name_on_form,
65
+ 'wpautop' => false,
66
+ 'teeny' => true,
67
+ 'tinymce' => $this->getOption('tinymce', array())
68
+ )); ?>
69
+ </div>
70
+ <?php
71
+ }
72
+
73
+ /**
74
+ * Returns a submit value of the control by a given name.
75
+ *
76
+ * @since 1.0.0
77
+ * @return mixed
78
+ */
79
+ public function getSubmitValue($name, $subName)
80
+ {
81
+ $name_on_form = $this->getNameOnForm($name);
82
+
83
+ $value = isset($_POST[$name_on_form])
84
+ ? $_POST[$name_on_form]
85
+ : null;
86
+
87
+ if( is_array($value) ) {
88
+ $value = implode(',', $value);
89
+ }
90
+
91
+ return wp_kses_post($value);
92
+ }
93
+ }
94
+ }
95
+
libs/factory/forms/includes/complex-control.class.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all complex controls.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+ if( !class_exists('Wbcr_FactoryForms407_ComplexControl') ) {
17
+ /**
18
+ * The base class for all controls.
19
+ *
20
+ * @since 1.0.0
21
+ */
22
+ abstract class Wbcr_FactoryForms407_ComplexControl extends Wbcr_FactoryForms407_Control {
23
+
24
+ /**
25
+ * Is this element a complex control?
26
+ *
27
+ * @since 1.0.0
28
+ * @var bool
29
+ */
30
+ public $is_complex_control = true;
31
+
32
+ /**
33
+ * Contains a set of internal controls.
34
+ *
35
+ * @since 1.0.0
36
+ * @var Wbcr_FactoryForms407_Control[]
37
+ */
38
+ public $inner_controls = array();
39
+
40
+ /**
41
+ * Sets a provider for the control.
42
+ *
43
+ * @since 1.0.0
44
+ * @param Wbcr_IFactoryForms407_ValueProvider $provider
45
+ * @return void
46
+ */
47
+ public function setProvider($provider)
48
+ {
49
+ $this->provider = $provider;
50
+
51
+ foreach($this->inner_controls as $control) {
52
+ $control->setProvider($provider);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Returns a control name used to save data with a provider.
58
+ *
59
+ * The method can return if the control have several elements.
60
+ *
61
+ * @since 1.0.0
62
+ * @return array|string|null A control name.
63
+ */
64
+ public function getName()
65
+ {
66
+ $names = array();
67
+
68
+ foreach($this->inner_controls as $control) {
69
+ $inner_names = $control->getName();
70
+ if( is_array($inner_names) ) {
71
+ $names = array_merge($names, $inner_names);
72
+ } else $names[] = $inner_names;
73
+ }
74
+
75
+ return $names;
76
+ }
77
+
78
+ /**
79
+ * Returns an array of value to save received after submission of a form.
80
+ *
81
+ * @see getSubmitValue
82
+ *
83
+ * The array has the following format:
84
+ * array(
85
+ * 'control-name1' => 'value1',
86
+ * 'control-name2__sub-name1' => 'value2'
87
+ * 'control-name2__sub-name2' => 'value3'
88
+ * )
89
+ *
90
+ * @since 1.0.0
91
+ * @return array
92
+ */
93
+ public function getValuesToSave()
94
+ {
95
+ $values = array();
96
+
97
+ foreach($this->inner_controls as $control) {
98
+ $inner_values = $control->getValuesToSave();
99
+ if( is_array($inner_values) ) {
100
+ $values = array_merge($values, $inner_values);
101
+ } else $values[] = $inner_values;
102
+ }
103
+
104
+ return $values;
105
+ }
106
+
107
+ /**
108
+ * Returns an initial value of control that is used to render the control first time.
109
+ *
110
+ * @since 1.0.0
111
+ * @param null $index
112
+ * @param bool $multiple
113
+ * @return array
114
+ */
115
+ public function getValue($index = null, $multiple = false)
116
+ {
117
+
118
+ $values = array();
119
+ foreach($this->inner_controls as $control) {
120
+ $inner_values = array_merge($values, $control->getValue());
121
+ if( is_array($inner_values) ) {
122
+ $values = array_merge($values, $inner_values);
123
+ } else $values[] = $inner_values;
124
+ }
125
+
126
+ if( $index !== null ) {
127
+ return $values[$index];
128
+ } else {
129
+ return $values;
130
+ }
131
+ }
132
+ }
133
+ }
libs/factory/forms/includes/control-holder.class.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all control holder
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_ControlHolder') ) {
18
+ /**
19
+ * The base class for control holders.
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ abstract class Wbcr_FactoryForms407_ControlHolder extends Wbcr_FactoryForms407_Control {
24
+
25
+ /**
26
+ * Holder Elements.
27
+ *
28
+ * @since 1.0.0
29
+ * @var Wbcr_FactoryForms407_Control[]
30
+ */
31
+ protected $elements = array();
32
+
33
+ /**
34
+ * Is this element a control holder?
35
+ *
36
+ * @since 1.0.0
37
+ * @var bool
38
+ */
39
+ public $is_holder = true;
40
+
41
+ /**
42
+ * Creates a new instance of control holder.
43
+ *
44
+ * @since 1.0.0
45
+ * @param mixed[] $options A holder options.
46
+ * @param Wbcr_FactoryForms407_Form $form A parent form.
47
+ */
48
+ public function __construct($options, $form)
49
+ {
50
+ parent::__construct($options, $form);
51
+
52
+ $this->elements = $form->createElements($options['items']);
53
+
54
+ foreach((array)$this->elements as $val) {
55
+ $val->parent = $this;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Returns holder elements.
61
+ *
62
+ * @since 1.0.0
63
+ * @return Wbcr_FactoryForms407_FormElement[].
64
+ */
65
+ public function getElements()
66
+ {
67
+ return $this->elements;
68
+ }
69
+
70
+ /**
71
+ * Renders the form or a given control holder.
72
+ *
73
+ * @since 1.0.0
74
+ * @return void
75
+ */
76
+ function render()
77
+ {
78
+ $this->beforeRendering();
79
+
80
+ $is_first_item = true;
81
+
82
+ foreach($this->elements as $element) {
83
+ $element->setOption('isFirst', $is_first_item);
84
+
85
+ if( $is_first_item ) {
86
+ $is_first_item = false;
87
+ }
88
+
89
+ do_action('wbcr_factory_form_before_element_' . $element->getName());
90
+
91
+ // if a current item is a control holder
92
+ if( $element->is_holder ) {
93
+
94
+ $this->form->layout->beforeHolder($element);
95
+ $element->render();
96
+ $this->form->layout->afterHolder($element);
97
+ // if a current item is an input control
98
+ } elseif( $element->is_control ) {
99
+
100
+ $this->form->layout->beforeControl($element);
101
+ $element->render();
102
+ $this->form->layout->afterControl($element);
103
+ // if a current item is a custom form element
104
+ } elseif( $element->is_custom ) {
105
+
106
+ $element->render();
107
+ // otherwise, show the error
108
+ } else {
109
+ echo('[ERROR] Invalid item.');
110
+ }
111
+
112
+ do_action('wbcr_factory_form_after_element_' . $element->getName());
113
+ }
114
+
115
+ $this->afterRendering();
116
+ }
117
+
118
+ /**
119
+ * Rendering a beginning of a holder.
120
+ *
121
+ * @since 1.0.0
122
+ * @return void
123
+ */
124
+ public function beforeRendering()
125
+ {
126
+ }
127
+
128
+ /**
129
+ * Rendering an end of a holder.
130
+ *
131
+ * @since 1.0.0
132
+ * @return void
133
+ */
134
+ public function afterRendering()
135
+ {
136
+ }
137
+
138
+ /**
139
+ * Rendering some html before an inner holder.
140
+ *
141
+ * @since 1.0.0
142
+ * @return void
143
+ */
144
+ public function beforeInnerHolder()
145
+ {
146
+ }
147
+
148
+ /**
149
+ * Rendering some html after an inner holder.
150
+ *
151
+ * @since 1.0.0
152
+ * @return void
153
+ */
154
+ public function afterInnerHolder()
155
+ {
156
+ }
157
+
158
+
159
+ public function beforeInnerElement()
160
+ {
161
+ }
162
+
163
+ /**
164
+ * Rendering some html after an inner element.
165
+ *
166
+ * @since 1.0.0
167
+ * @return void
168
+ */
169
+ public function afterInnerElement()
170
+ {
171
+ }
172
+ }
173
+ }
libs/factory/forms/includes/control.class.php ADDED
@@ -0,0 +1,422 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all controls.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_Control') ) {
18
+
19
+ /**
20
+ * The base class for all controls.
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ abstract class Wbcr_FactoryForms407_Control extends Wbcr_FactoryForms407_FormElement {
25
+
26
+ /**
27
+ * Is this element a control?
28
+ *
29
+ * @since 1.0.0
30
+ * @var bool
31
+ */
32
+ public $is_control = true;
33
+
34
+ /**
35
+ * Is this element a complex control?
36
+ *
37
+ * @since 1.0.0
38
+ * @var bool
39
+ */
40
+ public $is_complex_control = false;
41
+
42
+ /**
43
+ * A provider that is used to get values.
44
+ *
45
+ * @since 1.0.0
46
+ * @var Wbcr_IFactoryForms407_ValueProvider
47
+ */
48
+ protected $provider = null;
49
+
50
+ /**
51
+ * Create a new instance of the control.
52
+ *
53
+ * @param mixed[] $options
54
+ * @param FactoryForms407_Form $form
55
+ * @param null $provider
56
+ * @since 1.0.0
57
+ * @return void
58
+ */
59
+ public function __construct($options, $form, $provider = null)
60
+ {
61
+ parent::__construct($options, $form);
62
+ $this->provider = $provider;
63
+ }
64
+
65
+ /**
66
+ * Sets a provider for the control.
67
+ *
68
+ * @since 1.0.0
69
+ * @param IFactoryForms407_ValueProvider $provider
70
+ * @return void
71
+ */
72
+ public function setProvider($provider)
73
+ {
74
+ $this->provider = $provider;
75
+ }
76
+
77
+ /**
78
+ * Returns a control name used to save data with a provider.
79
+ *
80
+ * The method can return if the control have several elements.
81
+ *
82
+ * @since 1.0.0
83
+ * @return string[]|string|null A control name.
84
+ */
85
+ public function getName()
86
+ {
87
+ return isset($this->options['name'])
88
+ ? $this->options['name']
89
+ : null;
90
+ }
91
+
92
+ /**
93
+ * Prints a control name used to save data with a provider.
94
+ *
95
+ * @since 1.0.0
96
+ * @return void
97
+ */
98
+ protected function printName()
99
+ {
100
+ $name = $this->getName();
101
+ if( is_array($name) ) {
102
+ echo $name[0];
103
+ } else echo $name;
104
+ }
105
+
106
+ /**
107
+ * Returns a control scope.
108
+ *
109
+ * @since 1.0.0
110
+ * @return string|null A control scope.
111
+ */
112
+ public function getScope()
113
+ {
114
+ return isset($this->options['scope'])
115
+ ? $this->options['scope']
116
+ : null;
117
+ }
118
+
119
+ /**
120
+ * Prints a control scope.
121
+ *
122
+ * @since 1.0.0
123
+ * @return void
124
+ */
125
+ protected function printScope()
126
+ {
127
+ echo $this->getScope();
128
+ }
129
+
130
+ /**
131
+ * Returns a name of control on a form (scope + _ + name)
132
+ *
133
+ * @since 1.0.0
134
+ * @param null|string $name
135
+ * @return array|null|string|string[]
136
+ */
137
+ public function getNameOnForm($name = null)
138
+ {
139
+ $scope = $this->getScope();
140
+ $name = !$name
141
+ ? $this->getName()
142
+ : $name;
143
+
144
+ if( is_array($name) ) {
145
+ $names = array();
146
+ foreach($name as $item) {
147
+ $names[] = empty($scope)
148
+ ? $item
149
+ : $scope . '_' . $item;
150
+ }
151
+
152
+ return $names;
153
+ }
154
+
155
+ if( empty($scope) ) {
156
+ return $name;
157
+ }
158
+ if( empty($name) ) {
159
+ return null;
160
+ }
161
+
162
+ return $scope . '_' . $name;
163
+ }
164
+
165
+ /**
166
+ * Prints a control name on a form.
167
+ *
168
+ * @since 1.0.0
169
+ * @return void
170
+ */
171
+ public function printNameOnForm()
172
+ {
173
+ $name = $this->getNameOnForm();
174
+
175
+ if( is_array($name) ) {
176
+ echo $name[0];
177
+ } else {
178
+ echo $name;
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Returns a submit value of the control by a given name.
184
+ *
185
+ * @since 1.0.0
186
+ * @param string $name
187
+ * @param string $sub_name
188
+ * @return string
189
+ */
190
+ public function getSubmitValue($name, $sub_name)
191
+ {
192
+ $name_on_form = $this->getNameOnForm($name);
193
+
194
+ $raw_value = isset($_POST[$name_on_form])
195
+ ? $_POST[$name_on_form]
196
+ : null;
197
+
198
+ $value = $raw_value;
199
+
200
+ if( is_array($value) ) {
201
+ $value = array_map('sanitize_text_field', $value);
202
+ $value = implode(',', $value);
203
+ } else {
204
+ $value = sanitize_text_field($value);
205
+ }
206
+
207
+ return $this->filterValue($value, $raw_value);
208
+ }
209
+
210
+ /**
211
+ * @param $value
212
+ * @param $raw_value
213
+ * @return mixed
214
+ */
215
+ protected function filterValue($value, $raw_value)
216
+ {
217
+ $sanitize_func = $this->getOption('filter_value');
218
+
219
+ // if the data options is a valid callback for an object method
220
+ if( !empty($sanitize_func) && ((is_array($sanitize_func) && count($sanitize_func) == 2 && gettype($sanitize_func[0]) == 'object') || function_exists($sanitize_func)) ) {
221
+ return call_user_func_array($sanitize_func, array($value, $raw_value));
222
+ }
223
+
224
+ return $value;
225
+ }
226
+
227
+
228
+ /**
229
+ * Returns an array of value to save received after submission of a form.
230
+ *
231
+ * @see getSubmitValue
232
+ *
233
+ * The array has the following format:
234
+ * array(
235
+ * 'control-name1' => 'value1',
236
+ * 'control-name2__sub-name1' => 'value2'
237
+ * 'control-name2__sub-name2' => 'value3'
238
+ * )
239
+ *
240
+ * @since 3.1.0
241
+ * @return mixed[]
242
+ */
243
+ public function getValuesToSave()
244
+ {
245
+ $values = array();
246
+ $name = $this->getName();
247
+
248
+ if( is_array($name) ) {
249
+ $i = 0;
250
+
251
+ foreach($name as $single_name) {
252
+ $sub_name = $this->getSubName($single_name);
253
+ if( !$sub_name ) {
254
+ $sub_name = $i;
255
+ $i++;
256
+ }
257
+ $values[$single_name] = $this->getSubmitValue($single_name, $sub_name);
258
+ }
259
+
260
+ return $values;
261
+ }
262
+
263
+ $values[$name] = $this->getSubmitValue($name, null);
264
+
265
+ return $values;
266
+ }
267
+
268
+ /**
269
+ * Returns an initial value of control that is used to render the control first time.
270
+ *
271
+ * @since 1.0.0
272
+ * @return mixed;
273
+ */
274
+ public function getValue($index = null, $multiple = false)
275
+ {
276
+ if( isset($this->options['value']) ) {
277
+ if( is_array($this->options['value']) ) {
278
+ if( $index !== null ) {
279
+ return $this->options['value'][$index];
280
+ } else return $this->options['value'];
281
+ } else {
282
+ return $this->options['value'];
283
+ }
284
+ }
285
+
286
+ $default = null;
287
+ if( isset($this->options['default']) ) {
288
+ if( is_array($this->options['default']) ) {
289
+ if( $index !== null ) {
290
+ $default = $this->options['default'][$index];
291
+ } else $default = $this->options['default'];
292
+ } else {
293
+ $default = $this->options['default'];
294
+ }
295
+ }
296
+
297
+ if( $this->provider ) {
298
+ $name = $this->getName();
299
+
300
+ if( is_array($name) ) {
301
+
302
+ $values = array();
303
+ $i = 0;
304
+
305
+ foreach($name as $single_name) {
306
+ $sub_name = $this->getSubName($single_name);
307
+ if( !$sub_name ) {
308
+ $sub_name = $i;
309
+ $i++;
310
+ }
311
+ $values[$sub_name] = $this->provider->getValue($single_name, isset($default[$sub_name])
312
+ ? $default[$sub_name]
313
+ : null);
314
+ }
315
+
316
+ if( $index !== null ) {
317
+ return $values[$index];
318
+ }
319
+
320
+ return $values;
321
+ } else {
322
+ return $this->provider->getValue($this->getName(), $default, $multiple);
323
+ }
324
+ }
325
+
326
+ return $default;
327
+ }
328
+
329
+ /**
330
+ * Shows the control.
331
+ *
332
+ * @since 1.0.0
333
+ * @return void
334
+ */
335
+ public function render()
336
+ {
337
+ $this->addCssClass('factory-from-control-' . $this->type);
338
+
339
+ // if the control is off, then ignore it
340
+ $off = $this->getOption('off', false);
341
+
342
+ if( $off ) {
343
+ return;
344
+ }
345
+
346
+ $this->beforeHtml();
347
+ $this->html();
348
+ $this->afterHtml();
349
+ }
350
+
351
+ /**
352
+ * A virtual method that is executed before rendering html markup of the control.
353
+ *
354
+ * @since 1.0.0
355
+ * @return void
356
+ */
357
+ protected function beforeHtml()
358
+ {
359
+ }
360
+
361
+ /**
362
+ * A virtual method that is executed after rendering html markup of the control.
363
+ *
364
+ * @since 1.0.0
365
+ * @return void
366
+ */
367
+ protected function afterHtml()
368
+ {
369
+ }
370
+
371
+ /**
372
+ * Renders the html markup for the control.
373
+ *
374
+ * @since 1.0.0
375
+ * @return void
376
+ */
377
+ public function html()
378
+ {
379
+ }
380
+
381
+ /**
382
+ * Returns a layout option.
383
+ *
384
+ * @since 1.0.0
385
+ * @param string $option_name A layout option to return.
386
+ * @param mixed $default A default value to return if the option doesn't exist.
387
+ * @return mixed
388
+ */
389
+ public function getLayoutOption($option_name, $default)
390
+ {
391
+ if( !isset($this->options['layout']) ) {
392
+ return $default;
393
+ }
394
+ if( !isset($this->options['layout'][$option_name]) ) {
395
+ return $default;
396
+ }
397
+
398
+ return $this->options['layout'][$option_name];
399
+ }
400
+
401
+ /**
402
+ * Splits the control name by '__' and return the right part.
403
+ *
404
+ * For example, if the $control_name is 'control__color', then returns 'color'.
405
+ * Throws an error if the control name cannot be splitted.
406
+ *
407
+ * @since 3.1.0
408
+ * @param string $control_name
409
+ * @return string
410
+ */
411
+ protected function getSubName($control_name)
412
+ {
413
+
414
+ $parts = explode('__', $control_name, 2);
415
+ if( !isset($parts[1]) ) {
416
+ return null;
417
+ }
418
+
419
+ return $parts[1];
420
+ }
421
+ }
422
+ }
libs/factory/forms/includes/custom-element.class.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all custom elements.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_CustomElement') ) {
18
+ /**
19
+ * The base class for all controls.
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ abstract class Wbcr_FactoryForms407_CustomElement extends Wbcr_FactoryForms407_FormElement {
24
+
25
+ /**
26
+ * Is this element a custom form element?
27
+ *
28
+ * @since 1.0.0
29
+ * @var bool
30
+ */
31
+ public $is_custom = true;
32
+
33
+ public function render()
34
+ {
35
+
36
+ // if the control is off, then ignore it
37
+ $off = $this->getOption('off', false);
38
+
39
+ if( $off ) {
40
+ return;
41
+ }
42
+
43
+ $this->html();
44
+ }
45
+ }
46
+ }
libs/factory/forms/includes/form-element.class.php ADDED
@@ -0,0 +1,423 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all form element (controls, holders).
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_FormElement') ) {
18
+
19
+ /**
20
+ * The base class for all form element (controls, holders).
21
+ *
22
+ * Provides several methods to build html markup of an element.
23
+ *
24
+ * @since 1.0.0
25
+ */
26
+ abstract class Wbcr_FactoryForms407_FormElement {
27
+
28
+ /**
29
+ * A type of an elemnt.
30
+ *
31
+ * @since 1.0.0
32
+ * @var boolean
33
+ */
34
+ protected $type = null;
35
+
36
+ /**
37
+ * An html attribute builder.
38
+ *
39
+ * @since 1.0.0
40
+ * @var Wbcr_FactoryForms407_HtmlAttributeBuilder
41
+ */
42
+ private $html_builder;
43
+
44
+ /**
45
+ * Element options.
46
+ *
47
+ * @since 1.0.0
48
+ * @var array
49
+ */
50
+ public $options = array();
51
+
52
+ /**
53
+ * A parent form.
54
+ *
55
+ * @since 1.0.0
56
+ * @var Wbcr_FactoryForms407_Form
57
+ */
58
+ protected $form;
59
+
60
+ /**
61
+ * A form layout.
62
+ *
63
+ * @since 1.0.0
64
+ * @var Wbcr_FactoryForms407_FormLayout
65
+ */
66
+ protected $layout;
67
+
68
+ /**
69
+ * Is this element a control?
70
+ *
71
+ * @since 1.0.0
72
+ * @var bool
73
+ */
74
+ public $is_control = false;
75
+
76
+ /**
77
+ * Is this element a control holder?
78
+ *
79
+ * @since 1.0.0
80
+ * @var bool
81
+ */
82
+ public $is_holder = false;
83
+
84
+ /**
85
+ * Is this element a custom form element?
86
+ *
87
+ * @since 1.0.0
88
+ * @var bool
89
+ */
90
+ public $is_custom = false;
91
+
92
+ /**
93
+ * Creates a new instance of a form element.
94
+ *
95
+ * @since 1.0.0
96
+ * @param mixed[] $options A holder options.
97
+ * @param Wbcr_FactoryForms407_Form $form A parent form.
98
+ */
99
+ public function __construct($options, $form)
100
+ {
101
+ $this->options = $options;
102
+ $this->form = $form;
103
+ $this->layout = $form->layout;
104
+
105
+ $this->html_builder = new Wbcr_FactoryForms407_HtmlAttributeBuilder();
106
+
107
+ if( isset($this->options['cssClass']) ) {
108
+ $this->html_builder->addCssClass($this->options['cssClass']);
109
+ }
110
+
111
+ if( isset($this->options['htmlData']) ) {
112
+ foreach($this->options['htmlData'] as $data_key => $data_value) {
113
+ $this->html_builder->addHtmlData($data_key, $data_value);
114
+ }
115
+ }
116
+
117
+ if( isset($this->options['htmlAttrs']) ) {
118
+ foreach($this->options['htmlAttrs'] as $attr_key => $attr_value) {
119
+ $this->html_builder->addHtmlAttr($attr_key, $attr_value);
120
+ }
121
+ }
122
+
123
+ $this->addCssClass('factory-' . $this->type);
124
+ }
125
+
126
+
127
+ /**
128
+ * Sets options for the control.
129
+ *
130
+ * @since 1.0.0
131
+ * @param mixed[] $options
132
+ * @return void
133
+ */
134
+ public function setOptions($options)
135
+ {
136
+ $this->options = $options;
137
+ }
138
+
139
+ /**
140
+ * Gets options of the control.
141
+ *
142
+ * @since 1.0.0
143
+ * @return mixed[] $options
144
+ */
145
+ public function getOptions()
146
+ {
147
+ return $this->options;
148
+ }
149
+
150
+ /**
151
+ * Sets a new value for a given option.
152
+ *
153
+ * @since 1.0.0
154
+ * @param string $name An option name to set.
155
+ * @param mixed $value A value to set.
156
+ * @return void
157
+ */
158
+ public function setOption($name, $value)
159
+ {
160
+ $this->options[$name] = $value;
161
+ }
162
+
163
+ /**
164
+ * Gets an option value or default.
165
+ *
166
+ * @since 1.0.0
167
+ * @param string $name An option name to get.
168
+ * @param mixed $default A default value
169
+ * @return mixed|null
170
+ */
171
+ public function getOption($name, $default = null)
172
+ {
173
+ return isset($this->options[$name])
174
+ ? $this->options[$name]
175
+ : $default;
176
+ }
177
+
178
+ /**
179
+ * Prints an option value or default.
180
+ *
181
+ * @since 1.0.0
182
+ * @param string $name An option name to get.
183
+ * @param mixed $default A default value
184
+ * @return void
185
+ */
186
+ public function option($name, $default = null)
187
+ {
188
+ $value = $this->getOption($name, $default);
189
+ echo $value;
190
+ }
191
+
192
+ /**
193
+ * Adds a new CSS class for the element.
194
+ *
195
+ * @since 1.0.0
196
+ * @return void
197
+ */
198
+ public function addCssClass($class)
199
+ {
200
+ $this->html_builder->addCssClass($class);
201
+ }
202
+
203
+ /**
204
+ * Prints CSS classes of the element.
205
+ *
206
+ * @since 1.0.0
207
+ * @return void
208
+ */
209
+ protected function cssClass()
210
+ {
211
+ $this->html_builder->printCssClass();
212
+ }
213
+
214
+ /**
215
+ * Adds a new html attribute.
216
+ *
217
+ * @since 1.0.0
218
+ * @param string $data_key
219
+ * @param string $data_value
220
+ */
221
+ protected function addHtmlData($data_key, $data_value)
222
+ {
223
+ $this->html_builder->addHtmlData($data_key, $data_value);
224
+ }
225
+
226
+ /**
227
+ * Adds a new html attribute.
228
+ *
229
+ * @since 1.0.0
230
+ * @param string $attr_name
231
+ * @param string $attr_value
232
+ * @return void
233
+ */
234
+ protected function addHtmlAttr($attr_name, $attr_value)
235
+ {
236
+ $this->html_builder->addHtmlAttr($attr_name, $attr_value);
237
+ }
238
+
239
+ /**
240
+ * Prints all html attributes, including css classes and data.
241
+ *
242
+ * @since 1.0.0
243
+ * @return void
244
+ */
245
+ protected function attrs()
246
+ {
247
+ $this->html_builder->printAttrs();
248
+ }
249
+
250
+ /**
251
+ * Returns an element title.
252
+ *
253
+ * @since 1.0.0
254
+ * @return string|bool
255
+ */
256
+ public function getTitle()
257
+ {
258
+ if( isset($this->options['title']) ) {
259
+ return $this->options['title'];
260
+ }
261
+
262
+ return false;
263
+ }
264
+
265
+ /**
266
+ * Returns true if an element has title.
267
+ *
268
+ * @since 1.0.0
269
+ * @return bool
270
+ */
271
+ public function hasTitle()
272
+ {
273
+ $title = $this->getTitle();
274
+
275
+ return !empty($title);
276
+ }
277
+
278
+ /**
279
+ * Prints an element title.
280
+ *
281
+ * @since 1.0.0
282
+ * @return void
283
+ */
284
+ public function title()
285
+ {
286
+ echo $this->getTitle();
287
+ }
288
+
289
+ /**
290
+ * Returns an element hint.
291
+ *
292
+ * @since 1.0.0
293
+ * @return string
294
+ */
295
+ public function getHint()
296
+ {
297
+ if( isset($this->options['hint']) ) {
298
+ return $this->options['hint'];
299
+ }
300
+
301
+ return false;
302
+ }
303
+
304
+ /**
305
+ * Returns true if an element has hint.
306
+ *
307
+ * @since 1.0.0
308
+ * @return bool
309
+ */
310
+ public function hasHint()
311
+ {
312
+ $hint = $this->getHint();
313
+
314
+ return !empty($hint);
315
+ }
316
+
317
+ /**
318
+ * Prints an element hint.
319
+ *
320
+ * @since 1.0.0
321
+ * @return void
322
+ */
323
+ public function hint($esc = false)
324
+ {
325
+ echo $esc
326
+ ? esc_html($this->getHint())
327
+ : $this->getHint();
328
+ }
329
+
330
+ /**
331
+ * Returns an element name.
332
+ *
333
+ * @since 1.0.0
334
+ * @return string
335
+ */
336
+ public function getName()
337
+ {
338
+
339
+ if( empty($this->options['name']) && !empty($this->options['title']) ) {
340
+ $this->options['name'] = str_replace(' ', '-', $this->options['title']);
341
+ $this->options['name'] = strtolower($this->options['name']);
342
+ }
343
+
344
+ if( !isset($this->options['name']) ) {
345
+ $this->options['name'] = $this->type . '-' . rand();
346
+ }
347
+
348
+ return $this->options['name'];
349
+ }
350
+
351
+ /**
352
+ * Prints an element name.
353
+ *
354
+ * @since 1.0.0
355
+ * @return void
356
+ */
357
+ public function name()
358
+ {
359
+ echo $this->getName();
360
+ }
361
+
362
+ /**
363
+ * Returns a form name
364
+ *
365
+ * @since 1.0.0
366
+ * @return string
367
+ */
368
+ public function getFormName()
369
+ {
370
+ return $this->form->name;
371
+ }
372
+
373
+ /**
374
+ * Returns an element type.
375
+ *
376
+ * @since 1.0.0
377
+ * @return string
378
+ */
379
+ public function getType()
380
+ {
381
+ return $this->type;
382
+ }
383
+
384
+ /**
385
+ * Returns an element icon.
386
+ *
387
+ * @since 1.0.0
388
+ * @return string
389
+ */
390
+ public function getIcon()
391
+ {
392
+ if( isset($this->options['icon']) ) {
393
+ return $this->options['icon'];
394
+ }
395
+
396
+ return false;
397
+ }
398
+
399
+ /**
400
+ * Returns true if an element has a icon.
401
+ *
402
+ * @since 1.0.0
403
+ * @return bool
404
+ */
405
+ public function hasIcon()
406
+ {
407
+ $icon = $this->getIcon();
408
+
409
+ return !empty($icon);
410
+ }
411
+
412
+ /**
413
+ * Prints an element icon.
414
+ *
415
+ * @since 1.0.0
416
+ * @return void
417
+ */
418
+ public function icon()
419
+ {
420
+ echo $this->getIcon();
421
+ }
422
+ }
423
+ }
libs/factory/forms/includes/form-layout.class.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all form layouts.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_FormLayout') ) {
18
+
19
+ /**
20
+ * The base class for all form layouts.
21
+ */
22
+ abstract class Wbcr_FactoryForms407_FormLayout extends Wbcr_FactoryForms407_Holder {
23
+
24
+ /**
25
+ * A form layout name.
26
+ *
27
+ * @since 1.0.0
28
+ * @var string
29
+ */
30
+ protected $name = 'default';
31
+
32
+ /**
33
+ * A holder type.
34
+ *
35
+ * @since 1.0.0
36
+ * @var string
37
+ */
38
+ protected $type = 'form-layout';
39
+
40
+ /**
41
+ * Creates a new instance of a form layout.
42
+ *
43
+ * @since 1.0.0
44
+ * @param mixed[] $options A holder options.
45
+ * @param Wbcr_FactoryForms407_Form $form A parent form.
46
+ */
47
+ public function __construct($options, $form)
48
+ {
49
+
50
+ $options['name'] = $this->name;
51
+ $options['items'] = $form->getItems();
52
+
53
+ parent::__construct($options, $form);
54
+
55
+ $this->addCssClass('factory-forms-407-' . $this->type);
56
+ $this->addCssClass('factory-forms-407-' . $this->name);
57
+ }
58
+
59
+ /**
60
+ * Renders a beginning of a form.
61
+ *
62
+ * @since 1.0.0
63
+ * @return void
64
+ */
65
+ public function beforeRendering()
66
+ {
67
+ echo '<div ';
68
+ $this->attrs();
69
+ echo '>';
70
+ }
71
+
72
+ /**
73
+ * Renders the end of a form.
74
+ *
75
+ * @since 1.0.0
76
+ * @return void
77
+ */
78
+ public function afterRendering()
79
+ {
80
+ echo '</div>';
81
+ }
82
+
83
+ /**
84
+ * Rendering some html before a holder.
85
+ *
86
+ * @since 1.0.0
87
+ * @return void
88
+ */
89
+ public function beforeHolder($element)
90
+ {
91
+ }
92
+
93
+ /**
94
+ * Rendering some html after a holder.
95
+ *
96
+ * @since 1.0.0
97
+ * @return void
98
+ */
99
+ public function afterHolder($element)
100
+ {
101
+ }
102
+
103
+ /**
104
+ * Rendering some html before a contol.
105
+ *
106
+ * @since 1.0.0
107
+ * @return void
108
+ */
109
+ public function beforeControl($element)
110
+ {
111
+ }
112
+
113
+ /**
114
+ * Rendering some html after a contol.
115
+ *
116
+ * @since 1.0.0
117
+ * @return void
118
+ */
119
+ public function afterControl($element)
120
+ {
121
+ }
122
+ }
123
+ }
libs/factory/forms/includes/form.class.php ADDED
@@ -0,0 +1,694 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains a class that represnets an abstraction for forms.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ // creating a license manager for each plugin created via the factory
18
+ add_action('wbcr_factory_forms_407_plugin_created', 'wbcr_factory_forms_407_plugin_created');
19
+
20
+ function wbcr_factory_forms_407_plugin_created($plugin)
21
+ {
22
+ $plugin->forms = new Wbcr_FactoryForms407_Manager($plugin);
23
+ }
24
+
25
+ if( !class_exists('Wbcr_FactoryForms407_Manager') ) {
26
+
27
+ class Wbcr_FactoryForms407_Manager {
28
+
29
+ // ----------------------------------------------------
30
+ // Static fields and methods
31
+ // ----------------------------------------------------
32
+
33
+ /**
34
+ * This array contains data to use a respective control.
35
+ *
36
+ * @since 1.0.0
37
+ * @var array
38
+ */
39
+ public static $registered_controls = array();
40
+
41
+ /**
42
+ * Registers a new control.
43
+ *
44
+ * @since 1.0.0
45
+ * @param mixed[] $item Control data having the following format:
46
+ * type => a control type
47
+ * class => a control php class
48
+ * include => a path to include control code
49
+ * @return void
50
+ */
51
+ public function registerControl($item)
52
+ {
53
+ self::$registered_controls[$item['type']] = $item;
54
+ require_once $item['include'];
55
+ }
56
+
57
+ /**
58
+ * Registers a set of new controls.
59
+ *
60
+ * @see FactoryForms407_Form::registerControl()
61
+ *
62
+ * @since 1.0.0
63
+ * @return void
64
+ */
65
+ public function registerControls($data)
66
+ {
67
+ foreach($data as $item)
68
+ $this->registerControl($item);
69
+ }
70
+
71
+ /**
72
+ * This array contains holder data to use a respective control holder.
73
+ *
74
+ * @since 1.0.0
75
+ * @var array
76
+ */
77
+ public static $registered_holders = array();
78
+
79
+ /**
80
+ * Registers a new holder.
81
+ *
82
+ * @since 1.0.0
83
+ * @param mixed[] $item Holder data having the follwoin format:
84
+ * type => a control holder type
85
+ * class => a control holder php class
86
+ * include => a path to include control holder code
87
+ * @return void
88
+ */
89
+ public function registerHolder($item)
90
+ {
91
+ self::$registered_holders[$item['type']] = $item;
92
+ require_once $item['include'];
93
+ }
94
+
95
+ /**
96
+ * Registers a set of new holder controls.
97
+ *
98
+ * @see FactoryForms407_Form::registerHolder()
99
+ *
100
+ * @since 1.0.0
101
+ * @return void
102
+ */
103
+ public function registerHolders($data)
104
+ {
105
+ foreach($data as $item)
106
+ $this->registerHolder($item);
107
+ }
108
+
109
+ /**
110
+ * This array contains custom form element data to use a respective elements.
111
+ *
112
+ * @since 1.0.0
113
+ * @var array
114
+ */
115
+ public static $registered_custom_elements = array();
116
+
117
+ /**
118
+ * Registers a new custom form element.
119
+ *
120
+ * @since 1.0.0
121
+ * @return void
122
+ */
123
+ public function registerCustomElement($item)
124
+ {
125
+ self::$registered_custom_elements[$item['type']] = $item;
126
+ require_once $item['include'];
127
+ }
128
+
129
+ /**
130
+ * Registers a set of new custom form elements.
131
+ *
132
+ * @see FactoryForms407_Form::registerCustomElement()
133
+ *
134
+ * @since 1.0.0
135
+ * @return void
136
+ */
137
+ public function registerCustomElements($data)
138
+ {
139
+ foreach($data as $item)
140
+ $this->registerCustomElement($item);
141
+ }
142
+
143
+ /**
144
+ * Contains a set of layouts registered for forms.
145
+ *
146
+ * @since 1.0.0
147
+ * @var mixed[]
148
+ */
149
+ public static $form_layouts = array();
150
+
151
+ /**
152
+ * Registers a new layout for forms.
153
+ *
154
+ * @since 1.0.0
155
+ * @param array $data A layout data. Has the following format:
156
+ * name => a name of the layout
157
+ * class => a layout php class
158
+ * include => a path to include layout code
159
+ * @return void
160
+ */
161
+ public function registerFormLayout($data)
162
+ {
163
+ self::$form_layouts[$data['name']] = $data;
164
+ }
165
+
166
+ /**
167
+ * Extra propery that determines which UI is used in the admin panel.
168
+ *
169
+ * @since 1.0.0
170
+ * @var string
171
+ */
172
+ public static $temper;
173
+
174
+ /**
175
+ * A flat to register control only once.
176
+ *
177
+ * @since 3.0.7
178
+ * @var bool
179
+ */
180
+ public static $controls_registered = false;
181
+ }
182
+ }
183
+ if( !class_exists('Wbcr_FactoryForms407_Form') ) {
184
+ /**
185
+ * An abstraction for forms.
186
+ */
187
+ class Wbcr_FactoryForms407_Form {
188
+
189
+ // ----------------------------------------------------
190
+ // Object fields and methods
191
+ // ----------------------------------------------------
192
+
193
+ /**
194
+ * A value provider of the form that is used to save and load values.
195
+ *
196
+ * @since 1.0.0
197
+ * @var Wbcr_IFactoryForms407_ValueProvider
198
+ */
199
+ private $provider;
200
+
201
+ /**
202
+ * A prefix that will be used for names of input fields in the form.
203
+ *
204
+ * @since 1.0.0
205
+ * @var string
206
+ */
207
+ public $scope;
208
+
209
+ /**
210
+ * A form name that is used to call hooks and filter data.
211
+ *
212
+ * @since 1.0.0
213
+ * @var string
214
+ */
215
+ public $name = 'default';
216
+
217
+ /**
218
+ * It's not yet input controls. The array contains names of input controls and their
219
+ * options that are used to render and process input controls.
220
+ *
221
+ * @since 1.0.0
222
+ * @var mixed[]
223
+ */
224
+ protected $items = array();
225
+
226
+ /**
227
+ * Full set of input controls available after building the form.
228
+ *
229
+ * The array contains objects.
230
+ *
231
+ * @since 1.0.0
232
+ * @var array
233
+ */
234
+ private $controls = array();
235
+
236
+ /**
237
+ * A layout for the form.
238
+ *
239
+ * @since 1.0.0
240
+ * @var string
241
+ */
242
+ public $form_layout;
243
+
244
+ /**
245
+ * A current form layout used to render a form.
246
+ *
247
+ * @since 1.0.0
248
+ * @var FactoryForms407_FormLayout
249
+ */
250
+ public $layout;
251
+
252
+
253
+ /**
254
+ * Creates a new instance of a form.
255
+ *
256
+ * @since 1.0.0
257
+ * @param string $options Contains form options to setup.
258
+ */
259
+
260
+ /**
261
+ * Creates a new instance of a form.
262
+ *
263
+ * @since 1.0.0
264
+ * @param array $options
265
+ * @param Wbcr_Factory406_Plugin $plugin
266
+ */
267
+ public function __construct(array $options = array(), Wbcr_Factory406_Plugin $plugin)
268
+ {
269
+ // register controls once, when the first form is created
270
+ if( !Wbcr_FactoryForms407_Manager::$controls_registered ) {
271
+
272
+ do_action('wbcr_factory_forms_407_register_controls', $plugin);
273
+
274
+ //if( !empty($plugin) ) {
275
+ do_action('wbcr_factory_forms_407_register_controls_' . $plugin->getPluginName(), $plugin);
276
+ //}
277
+
278
+ Wbcr_FactoryForms407_Manager::$controls_registered = true;
279
+ }
280
+
281
+ $this->scope = isset($options['scope'])
282
+ ? $options['scope']
283
+ : null;
284
+ $this->name = isset($options['name'])
285
+ ? $options['name']
286
+ : $this->name;
287
+
288
+ if( isset($options['formLayout']) ) {
289
+ $this->form_layout = $options['formLayout'];
290
+ } else {
291
+ $this->form_layout = 'bootstrap-3';
292
+ }
293
+
294
+ Wbcr_FactoryForms407_Manager::$temper = 'flat';
295
+ }
296
+
297
+ /**
298
+ * Sets a provider for the control.
299
+ *
300
+ * @since 1.0.0
301
+ * @param Wbcr_IFactoryForms407_ValueProvider $provider
302
+ * @return void
303
+ */
304
+ public function setProvider($provider)
305
+ {
306
+ $this->provider = $provider;
307
+ }
308
+
309
+ /**
310
+ * Adds items into the form.
311
+ *
312
+ * It's base method to use during configuration form.
313
+ *
314
+ * @since 1.0.0
315
+ * @param array $array An array of items.
316
+ */
317
+ public function add($array)
318
+ {
319
+ if( (bool)count(array_filter(array_keys($array), 'is_string')) ) {
320
+ $this->items[] = $array;
321
+ } else {
322
+ $this->items = array_merge($this->items, $array);
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Returns items to render.
328
+ *
329
+ * Has the follwoing hooks:
330
+ * 'factory_form_items' ( $formName, $items ) to filter form controls before building.
331
+ *
332
+ * @since 1.0.0
333
+ * @return mixed[] Items to render.
334
+ */
335
+ public function getItems()
336
+ {
337
+ return apply_filters('wbcr_factory_406_form_items', $this->items, $this->name);
338
+ }
339
+
340
+ /**
341
+ * Returns form controls (control objects).
342
+ *
343
+ * @since 1.0.0
344
+ * @return Wbcr_FactoryForms407_Control[]
345
+ */
346
+ public function getControls()
347
+ {
348
+ if( !empty($this->controls) ) {
349
+ return $this->controls;
350
+ }
351
+ $this->createControls();
352
+
353
+ return $this->controls;
354
+ }
355
+
356
+ /**
357
+ * Builds a form items to the control objects ready to use.
358
+ *
359
+ * @param null $holder
360
+ * @return Wbcr_FactoryForms407_Control[]
361
+ */
362
+
363
+ public function createControls($holder = null)
364
+ {
365
+ $items = ($holder == null)
366
+ ? $this->getItems()
367
+ : $holder['items'];
368
+
369
+ foreach($items as $item) {
370
+
371
+ if( $this->isControlHolder($item) && $this->isControl($item) ) {
372
+
373
+ $this->controls[] = $this->createControl($item);
374
+ $this->createControls($item);
375
+ // if a current item is a control holder
376
+ } elseif( $this->isControlHolder($item) ) {
377
+
378
+ $this->createControls($item);
379
+ // if a current item is an input control
380
+ } elseif( $this->isControl($item) ) {
381
+
382
+ $this->controls[] = $this->createControl($item);
383
+ // if a current item is an input control
384
+ } elseif( $this->isCustomElement($item) ) {
385
+
386
+ // nothing
387
+
388
+ // otherwise, show the error
389
+ } else {
390
+ die('[ERROR] Invalid item.');
391
+ }
392
+ }
393
+
394
+ return $this->controls;
395
+ }
396
+
397
+ /**
398
+ * Create an element.
399
+ *
400
+ * @since 1.0.0
401
+ * @param array $item Item data.
402
+ * @return Wbcr_FactoryForms407_FormElement|null A form element.
403
+ */
404
+ public function createElement($item)
405
+ {
406
+
407
+ if( $this->isControl($item) ) {
408
+ return $this->createControl($item);
409
+ } elseif( $this->isControlHolder($item) ) {
410
+ return $this->createHolder($item);
411
+ } elseif( $this->isCustomElement($item) ) {
412
+ return $this->createCustomElement($item);
413
+ } else {
414
+ printf('[ERROR] The element with the type <strong>%s</strong> was not found.', $item['type']);
415
+ exit;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * Creates a set of elements.
421
+ *
422
+ * @since 1.0.0
423
+ * @param mixed[] $item Data of items.
424
+ * @return Wbcr_FactoryForms407_FormElement[] Created elements.
425
+ */
426
+ public function createElements($items = array())
427
+ {
428
+ $objects = array();
429
+ foreach($items as $item)
430
+ $objects[] = $this->createElement($item);
431
+
432
+ return $objects;
433
+ }
434
+
435
+ /**
436
+ * Create a control.
437
+ *
438
+ * @since 1.0.0
439
+ * @param array $item Item data.
440
+ * @return Wbcr_FactoryForms407_Control A control object.
441
+ */
442
+ public function createControl($item)
443
+ {
444
+ $object = null;
445
+
446
+ if( is_array($item) ) {
447
+
448
+ $control_data = Wbcr_FactoryForms407_Manager::$registered_controls[$item['type']];
449
+
450
+ require_once($control_data['include']);
451
+
452
+ $options = $item;
453
+ $options['scope'] = $this->scope;
454
+
455
+ $object = new $control_data['class']($options, $this);
456
+ } elseif( gettype($item) == 'object' ) {
457
+ $object = $item;
458
+ } else {
459
+ die('[ERROR] Invalid input control.');
460
+ }
461
+
462
+ $object->setProvider($this->provider);
463
+
464
+ return $object;
465
+ }
466
+
467
+ /**
468
+ * Create a control holder.
469
+ *
470
+ * @since 1.0.0
471
+ * @param array $item Item data.
472
+ * @return Wbcr_FactoryForms407_Holder A control holder object.
473
+ */
474
+ public function createHolder($item)
475
+ {
476
+ $object = null;
477
+
478
+ if( is_array($item) ) {
479
+
480
+ $holderData = Wbcr_FactoryForms407_Manager::$registered_holders[$item['type']];
481
+ require_once($holderData['include']);
482
+
483
+ $object = new $holderData['class']($item, $this);
484
+ } elseif( gettype($item) == 'object' ) {
485
+ $object = $item;
486
+ } else {
487
+ die('[ERROR] Invalid control holder.');
488
+ }
489
+
490
+ return $object;
491
+ }
492
+
493
+ /**
494
+ * Create a custom form element.
495
+ *
496
+ * @since 1.0.0
497
+ * @param mixed $item Item data.
498
+ * @return FactoryForms407_FormElement A custom form element object.
499
+ */
500
+ public function createCustomElement($item)
501
+ {
502
+ $object = null;
503
+
504
+ if( is_array($item) ) {
505
+
506
+ $data = Wbcr_FactoryForms407_Manager::$registered_custom_elements[$item['type']];
507
+ require_once($data['include']);
508
+
509
+ $options = $item;
510
+ $object = new $data['class']($options, $this);
511
+ } elseif( gettype($item) == 'object' ) {
512
+ $object = $item;
513
+ } else {
514
+ die('[ERROR] Invalid custom form element.');
515
+ }
516
+
517
+ return $object;
518
+ }
519
+
520
+ /**
521
+ * Renders a form.
522
+ *
523
+ * @since 1.0.0
524
+ * @param mixed[] $options Options for a form layout.
525
+ * @return void
526
+ */
527
+ public function html($options = array())
528
+ {
529
+
530
+ if( !isset(Wbcr_FactoryForms407_Manager::$form_layouts[$this->form_layout]) ) {
531
+ die(sprintf('[ERROR] The form layout %s was not found.', $this->form_layout));
532
+ }
533
+
534
+ // include a render code
535
+ $layout_data = Wbcr_FactoryForms407_Manager::$form_layouts[$this->form_layout];
536
+ require_once($layout_data['include']);
537
+
538
+ $this->connectAssets();
539
+
540
+ if( $this->provider ) {
541
+ $this->provider->init();
542
+ }
543
+ $layout = new $layout_data['class']($options, $this);
544
+ $this->layout = $layout;
545
+ $this->layout->render();
546
+ }
547
+
548
+ /**
549
+ * Connects assets (css and js).
550
+ *
551
+ * @since 1.0.0
552
+ * @param mixed[] $options Options for a form layout.
553
+ * @return void
554
+ */
555
+ private function connectAssets()
556
+ {
557
+
558
+ $this->connectAssetsForItems();
559
+ $layout_data = Wbcr_FactoryForms407_Manager::$form_layouts[$this->form_layout];
560
+
561
+ if( $layout_data['name'] == 'default' ) {
562
+ if( isset($layout_data['style']) ) {
563
+ wp_enqueue_style('wbcr-factory-form-000-default-layout', $layout_data['style']);
564
+ }
565
+ if( isset($layout_data['script']) ) {
566
+ wp_enqueue_script('wbcr-factory-form-000-default-layout-', $layout_data['script']);
567
+ }
568
+ } else {
569
+ if( isset($layout_data['style']) ) {
570
+ wp_enqueue_style('wbcr-factory-form-layout-' . $layout_data['name'], $layout_data['style']);
571
+ }
572
+ if( isset($layout_data['script']) ) {
573
+ wp_enqueue_script('wbcr-factory-form-layout-' . $layout_data['name'], $layout_data['script']);
574
+ }
575
+ }
576
+ }
577
+
578
+
579
+ /**
580
+ * Connects scripts and styles of form items.
581
+ *
582
+ * @since 1.0.0
583
+ * @param mixed[] $items Items for which it's nessesary to connect scripts and styles.
584
+ * @return void
585
+ */
586
+ public static function connectAssetsForItems($items = array())
587
+ {
588
+ foreach($items as $item)
589
+ self::connectAssetsForItem($item);
590
+ }
591
+
592
+ /**
593
+ * Connects scripts and styles of form item.
594
+ *
595
+ * @since 1.0.0
596
+ * @param mixed[] $item Item for which it's nessesary to connect scripts and styles.
597
+ * @return void
598
+ */
599
+ public static function connectAssetsForItem($item)
600
+ {
601
+ if( !is_array($item) ) {
602
+ return;
603
+ }
604
+
605
+ $type = $item['type'];
606
+
607
+ $haystack = array();
608
+ if( self::isControl($type) ) {
609
+ $haystack = Wbcr_FactoryForms407_Manager::$registered_controls;
610
+ } elseif( self::isControlHolder($type) ) {
611
+ $haystack = Wbcr_FactoryForms407_Manager::$registered_holders;
612
+ }
613
+
614
+ if( isset($haystack[$type]) ) {
615
+ if( isset($haystack[$type]['style']) ) {
616
+ $style = $haystack[$type]['style'];
617
+ if( !wp_style_is($style) ) {
618
+ wp_enqueue_style('factory-form-control-' . $type, $style);
619
+ }
620
+ }
621
+ if( isset($haystack[$type]['script']) ) {
622
+ $script = $haystack[$type]['script'];
623
+ if( !wp_script_is($script) ) {
624
+ wp_enqueue_script('factory-form-control-' . $type, $script, array('jquery'));
625
+ }
626
+ }
627
+ }
628
+
629
+ if( isset($item['items']) ) {
630
+ self::connectAssetsForItem($item['items']);
631
+ }
632
+ }
633
+
634
+ /**
635
+ * Saves form data by using a specified value provider.
636
+ *
637
+ * @since 1.0.0
638
+ * @return mixed
639
+ */
640
+ public function save()
641
+ {
642
+ if( !$this->provider ) {
643
+ return null;
644
+ }
645
+
646
+ $controls = $this->getControls();
647
+ foreach($controls as $control) {
648
+
649
+ $values = $control->getValuesToSave();
650
+ foreach($values as $keyToSave => $valueToSave) {
651
+ $this->provider->setValue($keyToSave, $valueToSave);
652
+ }
653
+ }
654
+
655
+ $this->provider->saveChanges();
656
+ }
657
+
658
+ /**
659
+ * Returns true if a given item is an input control item.
660
+ *
661
+ * @since 1.0.0
662
+ * @param mixed[] $item
663
+ * @return bool
664
+ */
665
+ public static function isControl($item)
666
+ {
667
+ return isset(Wbcr_FactoryForms407_Manager::$registered_controls[$item['type']]);
668
+ }
669
+
670
+ /**
671
+ * Returns true if a given item is an control holder item.
672
+ *
673
+ * @since 1.0.0
674
+ * @param mixed[] $item
675
+ * @return bool
676
+ */
677
+ public static function isControlHolder($item)
678
+ {
679
+ return isset(Wbcr_FactoryForms407_Manager::$registered_holders[$item['type']]);
680
+ }
681
+
682
+ /**
683
+ * Returns true if a given item is html markup.
684
+ *
685
+ * @since 1.0.0
686
+ * @param mixed[] $item
687
+ * @return bool
688
+ */
689
+ public static function isCustomElement($item)
690
+ {
691
+ return isset(Wbcr_FactoryForms407_Manager::$registered_custom_elements[$item['type']]);
692
+ }
693
+ }
694
+ }
libs/factory/forms/includes/holder.class.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the base class for all control holder
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_Holder') ) {
18
+
19
+ /**
20
+ * The base class for control holders.
21
+ *
22
+ * @since 1.0.0
23
+ */
24
+ abstract class Wbcr_FactoryForms407_Holder extends Wbcr_FactoryForms407_FormElement {
25
+
26
+ /**
27
+ * Holder Elements.
28
+ *
29
+ * @since 1.0.0
30
+ * @var Wbcr_FactoryForms407_Control[]
31
+ */
32
+ protected $elements = array();
33
+
34
+ /**
35
+ * Is this element a control holder?
36
+ *
37
+ * @since 1.0.0
38
+ * @var bool
39
+ */
40
+ public $is_holder = true;
41
+
42
+ /**
43
+ * Creates a new instance of control holder.
44
+ *
45
+ * @since 1.0.0
46
+ * @param mixed[] $options A holder options.
47
+ * @param Wbcr_FactoryForms407_Form $form A parent form.
48
+ */
49
+ public function __construct($options, $form)
50
+ {
51
+ parent::__construct($options, $form);
52
+ $this->elements = $form->createElements($options['items']);
53
+ }
54
+
55
+ /**
56
+ * Returns holder elements.
57
+ *
58
+ * @since 1.0.0
59
+ * @return Wbcr_FactoryForms407_Control[].
60
+ */
61
+ public function getElements()
62
+ {
63
+ return $this->elements;
64
+ }
65
+
66
+ /**
67
+ * Renders the form or a given control holder.
68
+ *
69
+ * @since 1.0.0
70
+ * @return void
71
+ */
72
+ function render()
73
+ {
74
+
75
+ $this->beforeRendering();
76
+
77
+ $is_first_item = true;
78
+
79
+ foreach($this->elements as $element) {
80
+
81
+ $element->setOption('isFirst', $is_first_item);
82
+
83
+ if( $is_first_item ) {
84
+ $is_first_item = false;
85
+ }
86
+
87
+ do_action('wbcr_factory_406_form_before_element_' . $element->getOption('name'));
88
+
89
+ // if a current item is a control holder
90
+ if( $element->is_holder ) {
91
+
92
+ $this->form->layout->beforeHolder($element);
93
+ $element->render();
94
+ $this->form->layout->afterHolder($element);
95
+ // if a current item is an input control
96
+ } elseif( $element->is_control ) {
97
+ $this->form->layout->beforeControl($element);
98
+ $element->render();
99
+ $this->form->layout->afterControl($element);
100
+ // if a current item is a custom form element
101
+ } elseif( $element->is_custom ) {
102
+
103
+ $element->render();
104
+ // otherwise, show the error
105
+ } else {
106
+ echo('[ERROR] Invalid item.');
107
+ }
108
+
109
+ do_action('wbcr_factory_form_after_element_' . $element->getOption('name'));
110
+ }
111
+
112
+ $this->afterRendering();
113
+ }
114
+
115
+ /**
116
+ * Rendering a beginning of a holder.
117
+ *
118
+ * @since 1.0.0
119
+ * @return void
120
+ */
121
+ protected function beforeRendering()
122
+ {
123
+ }
124
+
125
+ /**
126
+ * Rendering an end of a holder.
127
+ *
128
+ * @since 1.0.0
129
+ * @return void
130
+ */
131
+ protected function afterRendering()
132
+ {
133
+ }
134
+
135
+ /**
136
+ * Rendering some html before an inner holder.
137
+ *
138
+ * @since 1.0.0
139
+ * @return void
140
+ */
141
+ protected function beforeInnerHolder()
142
+ {
143
+ }
144
+
145
+ /**
146
+ * Rendering some html after an inner holder.
147
+ *
148
+ * @since 1.0.0
149
+ * @return void
150
+ */
151
+ protected function afterInnerHolder()
152
+ {
153
+ }
154
+
155
+
156
+ protected function beforeInnerElement()
157
+ {
158
+ }
159
+
160
+ /**
161
+ * Rendering some html after an inner element.
162
+ *
163
+ * @since 1.0.0
164
+ * @return void
165
+ */
166
+ protected function afterInnerElement()
167
+ {
168
+ }
169
+ }
170
+ }
libs/factory/forms/includes/html-builder.class.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains Html Attribute Builder.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_HtmlAttributeBuilder') ) {
18
+ /**
19
+ * Html Attribute Builder
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ class Wbcr_FactoryForms407_HtmlAttributeBuilder {
24
+
25
+ /**
26
+ * An array to store css classes.
27
+ *
28
+ * @since 1.0.0
29
+ * @var string[]
30
+ */
31
+ protected $css_classes = array();
32
+
33
+ /**
34
+ * An array to store html attributes.
35
+ *
36
+ * @since 1.0.0
37
+ * @var string[]
38
+ */
39
+ protected $html_attrs = array();
40
+
41
+ /**
42
+ * An array to store html data.
43
+ *
44
+ * @since 1.0.0
45
+ * @var string[]
46
+ */
47
+ protected $html_data = array();
48
+
49
+ /**
50
+ * Adds a new CSS class.
51
+ *
52
+ * @since 1.0.0
53
+ * @return void
54
+ */
55
+ public function addCssClass($class)
56
+ {
57
+ if( !is_array($class) ) {
58
+ $this->css_classes[] = $class;
59
+ } else {
60
+ $this->css_classes = array_merge($this->css_classes, $class);
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Prints CSS classes.
66
+ *
67
+ * @since 1.0.0
68
+ * @return void
69
+ */
70
+ public function printCssClass()
71
+ {
72
+ echo implode(' ', $this->css_classes);
73
+ }
74
+
75
+ /**
76
+ * Adds a new html data item.
77
+ *
78
+ * @since 1.0.0
79
+ * @param string $dataKey
80
+ * @param string $dataValue
81
+ * @return void
82
+ */
83
+ public function addHtmlData($dataKey, $dataValue)
84
+ {
85
+ $this->html_data[$dataKey] = $dataValue;
86
+ }
87
+
88
+ /**
89
+ * Prints html data items.
90
+ *
91
+ * @since 1.0.0
92
+ * @return void
93
+ */
94
+ public function printHtmlData()
95
+ {
96
+ foreach($this->html_data as $key => $value) {
97
+ echo 'data-' . $key . '="' . $value . '" ';
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Adds a new html attribute.
103
+ *
104
+ * @since 1.0.0
105
+ * @param string $attr_name
106
+ * @param string $attr_value
107
+ * @return void
108
+ */
109
+ public function addHtmlAttr($attr_name, $attr_value)
110
+ {
111
+ $this->html_attrs[$attr_name] = $attr_value;
112
+ }
113
+
114
+ /**
115
+ * Prints all html attributes, including css classes and data.
116
+ *
117
+ * @since 1.0.0
118
+ * @return void
119
+ */
120
+ public function printAttrs()
121
+ {
122
+ $attrs = $this->html_attrs;
123
+
124
+ if( !empty($this->css_classes) ) {
125
+ $attrs['class'] = implode(' ', $this->css_classes);
126
+ }
127
+
128
+ foreach($this->html_data as $data_key => $data_value) {
129
+ $attrs['data-' . $data_key] = $data_value;
130
+ }
131
+
132
+ foreach($attrs as $key => $value) {
133
+ echo $key . '="' . $value . '" ';
134
+ }
135
+ }
136
+ }
137
+ }
libs/factory/forms/includes/providers/meta-value-provider.class.php ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Factory Meta Value Provider.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_OptionsValueProvider') ) {
18
+
19
+ /**
20
+ * Factory Meta Value Provider
21
+ *
22
+ * This provide works with meta values like a lazy key-value storage and
23
+ * provides methods to commit changes on demand. It increases perfomance on form saving.
24
+ *
25
+ * @since 1.0.0
26
+ */
27
+ class Wbcr_FactoryForms407_MetaValueProvider implements Wbcr_IFactoryForms407_ValueProvider {
28
+
29
+
30
+ public $scope;
31
+
32
+ protected $post_id;
33
+
34
+ /**
35
+ * Values to save $metaName => $metaValue
36
+ * @var array
37
+ */
38
+ private $values = array();
39
+
40
+ /**
41
+ * Chanched meta keys (indexed array)
42
+ * @var array
43
+ */
44
+ private $keys = array();
45
+
46
+ private $meta = array();
47
+
48
+
49
+ /**
50
+ * Creates a new instance of a meta value provider.
51
+ *
52
+ * @param array $options
53
+ */
54
+ public function __construct($options = array())
55
+ {
56
+ global $post;
57
+
58
+ $this->scope = (isset($options['scope']))
59
+ ? $options['scope']
60
+ : null;
61
+
62
+ $this->scope = preg_replace('/\_meta\_box$/', '', $this->formatCamelCase($this->scope));
63
+
64
+ /*$this->post_id = (isset($options['post_id']))
65
+ ? $options['post_id']
66
+ : $post->ID;
67
+
68
+ // the second parameter for compatibility with wordpress 3.0
69
+ $temp = get_post_meta($this->post_id, '', true);
70
+
71
+ foreach($temp as $key => &$content) {
72
+ if( strpos($key, $this->scope) === 0 ) {
73
+ $this->meta[$key] = $content;
74
+ }
75
+ }*/
76
+
77
+ $this->init();
78
+ }
79
+
80
+ /**
81
+ * Initizalize an instance of the provider.
82
+ * This method should be invoked before the provider usage.
83
+ *
84
+ * @param bool $post_id
85
+ */
86
+ public function init($post_id = false)
87
+ {
88
+ global $post;
89
+
90
+ $this->post_id = $post_id
91
+ ? $post_id
92
+ : $post->ID;
93
+
94
+ // the second parameter for compatibility with wordpress 3.0
95
+ $temp = get_post_meta($this->post_id, '', true);
96
+
97
+ foreach($temp as $key => &$content) {
98
+ if( strpos($key, $this->scope) === 0 ) {
99
+ $this->meta[$key] = $content;
100
+ }
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Saves changes into a database.
106
+ * The method is optimized for bulk updates.
107
+ */
108
+ public function saveChanges()
109
+ {
110
+
111
+ $this->deleteValues();
112
+ $this->insertValues();
113
+ /**
114
+ * foreach ($this->values as $key => $value) {
115
+ * update_post_meta($this->postId, $key, $value);
116
+ * }
117
+ */
118
+ }
119
+
120
+ /**
121
+ * Removes all actual values from a database.
122
+ */
123
+ private function deleteValues()
124
+ {
125
+ if( count($this->keys) == 0 ) {
126
+ return;
127
+ }
128
+
129
+ global $wpdb;
130
+
131
+ $values = array();
132
+ $keys[] = $this->post_id;
133
+
134
+ for($i = 0; $i < count($this->keys); $i++) {
135
+ $values[] = '%s';
136
+ $keys[] = $this->keys[$i];
137
+ }
138
+
139
+ $clause = implode(',', $values);
140
+ $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE post_id='%d' AND meta_key IN ($clause)", $keys));
141
+ }
142
+
143
+ /**
144
+ * /**
145
+ * Inserts new values by using bulk insert directly into a database.
146
+ *
147
+ * @return bool|false|int
148
+ */
149
+ private function insertValues()
150
+ {
151
+ global $wpdb;
152
+
153
+ $sql = "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES ";
154
+ $rows = array();
155
+
156
+ foreach($this->values as $meta_key => $meta_value) {
157
+ if( is_array($meta_value) ) {
158
+ foreach($meta_value as $value) {
159
+ $rows[] = $wpdb->prepare('(%d,%s,%s)', $this->post_id, $meta_key, $value);
160
+ }
161
+ } else {
162
+ $rows[] = $wpdb->prepare('(%d,%s,%s)', $this->post_id, $meta_key, $meta_value);
163
+ }
164
+ }
165
+
166
+ if( empty($rows) ) {
167
+ return false;
168
+ }
169
+
170
+ $sql = $sql . implode(',', $rows);
171
+
172
+ return $wpdb->query($sql);
173
+ }
174
+
175
+ /**
176
+ * @param string $name
177
+ * @param null $default
178
+ * @param bool $multiple
179
+ * @return array|int|null
180
+ */
181
+ public function getValue($name, $default = null, $multiple = false)
182
+ {
183
+ if( is_array($name) ) {
184
+
185
+ $values = array();
186
+ $index = 0;
187
+
188
+ foreach($name as $item) {
189
+ $item_default = ($default && is_array($default) && isset($default[$index]))
190
+ ? $default[$index]
191
+ : null;
192
+
193
+ $values[] = $this->getValueBySingleName($item, $item_default, $multiple);
194
+ $index++;
195
+ }
196
+
197
+ return $values;
198
+ }
199
+
200
+ $value = $this->getValueBySingleName($name, $default, $multiple);
201
+
202
+ return $value;
203
+ }
204
+
205
+ /**
206
+ * @param $single_name
207
+ * @param null $default
208
+ * @param bool $multiple
209
+ * @return int|null
210
+ */
211
+ protected function getValueBySingleName($single_name, $default = null, $multiple = false)
212
+ {
213
+
214
+ $value = isset($this->meta[$this->scope . '_' . $single_name])
215
+ ? ($multiple)
216
+ ? $this->meta[$this->scope . '_' . $single_name]
217
+ : $this->meta[$this->scope . '_' . $single_name][0]
218
+ : $default;
219
+
220
+ if( $value === 'true' ) {
221
+ $value = 1;
222
+ }
223
+ if( $value === 'false' ) {
224
+ $value = 0;
225
+ }
226
+
227
+ return $value;
228
+ }
229
+
230
+ /**
231
+ * @param string $name
232
+ * @param mixed $value
233
+ */
234
+ public function setValue($name, $value)
235
+ {
236
+
237
+ if( is_array($name) ) {
238
+ $index = 0;
239
+
240
+ foreach($name as $item) {
241
+ $itemValue = ($value && is_array($value) && isset($value[$index]))
242
+ ? $value[$index]
243
+ : null;
244
+
245
+ $this->setValueBySingleName($item, $itemValue);
246
+ $index++;
247
+ }
248
+
249
+ return;
250
+ }
251
+
252
+ $this->setValueBySingleName($name, $value);
253
+
254
+ return;
255
+ }
256
+
257
+ /**
258
+ * @param string $single_name
259
+ * @param mixed $singe_value
260
+ */
261
+ protected function setValueBySingleName($single_name, $singe_value)
262
+ {
263
+ $name = $this->scope . '_' . $single_name;
264
+
265
+ if( is_array($singe_value) ) {
266
+
267
+ foreach($singe_value as $index => $value) {
268
+
269
+ $singe_value[$index] = empty($singe_value[$index])
270
+ ? $singe_value[$index]
271
+ : stripslashes($singe_value[$index]);
272
+ }
273
+
274
+ $value = $singe_value;
275
+ } else {
276
+ $value = empty($singe_value)
277
+ ? $singe_value
278
+ : stripslashes($singe_value);
279
+ }
280
+
281
+ $this->values[$name] = $value;
282
+ $this->keys[] = $name;
283
+ }
284
+
285
+ /**
286
+ * @param string $string
287
+ * @return string
288
+ */
289
+ private function formatCamelCase($string)
290
+ {
291
+ $output = "";
292
+ foreach(str_split($string) as $char) {
293
+ if( strtoupper($char) == $char && !in_array($char, array('_', '-')) ) {
294
+ $output .= "_";
295
+ }
296
+ $output .= $char;
297
+ }
298
+ $output = strtolower($output);
299
+
300
+ return $output;
301
+ }
302
+ }
303
+ }
libs/factory/forms/includes/providers/options-value-provider.class.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains the class of Factory Option Value Provider.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+ // Exit if accessed directly
12
+ if( !defined('ABSPATH') ) {
13
+ exit;
14
+ }
15
+
16
+ if( !class_exists('Wbcr_FactoryForms407_OptionsValueProvider') ) {
17
+
18
+ /**
19
+ * Factory Options Value Provider
20
+ *
21
+ * This provide stores form values in the wordpress options.
22
+ *
23
+ * @since 1.0.0
24
+ */
25
+ class Wbcr_FactoryForms407_OptionsValueProvider implements Wbcr_IFactoryForms407_ValueProvider {
26
+
27
+ /**
28
+ * Values to save $optionName => $optionValue
29
+ *
30
+ * @since 1.0.0
31
+ * @var mixed[]
32
+ */
33
+ private $values = array();
34
+
35
+ /**
36
+ * A prefix that will be added to all option names.
37
+ *
38
+ * @since 1.0.0
39
+ * @var string
40
+ */
41
+ public $scope;
42
+
43
+ /**
44
+ * Creates a new instance of an options value provider.
45
+ */
46
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
47
+ {
48
+ $this->plugin = $plugin;
49
+ }
50
+
51
+ /**
52
+ * @since 1.0.0
53
+ */
54
+ public function init()
55
+ {
56
+ // nothing to do
57
+ }
58
+
59
+ /**
60
+ * @since 1.0.0
61
+ */
62
+ public function saveChanges()
63
+ {
64
+ $this->plugin->updateOptions($this->values);
65
+ }
66
+
67
+ public function getValue($name, $default = null, $multiple = false)
68
+ {
69
+ $value = $this->plugin->getOption($name, $default);
70
+
71
+ if( $value === 'true' || $value === true ) {
72
+ $value = 1;
73
+ }
74
+ if( $value === 'false' || $value === false ) {
75
+ $value = 0;
76
+ }
77
+
78
+ return $value;
79
+ }
80
+
81
+ /**
82
+ * @param string $name
83
+ * @param mixed $value
84
+ */
85
+ public function setValue($name, $value)
86
+ {
87
+ $value = empty($value)
88
+ ? $value
89
+ : stripslashes($value);
90
+
91
+ $this->values[$name] = $value;
92
+ }
93
+ }
94
+ }
libs/factory/forms/includes/providers/value-provider.interface.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains an interface for all value provides.
4
+ *
5
+ * A value provider is a provide to get and save values to some stores (database, metadata and so on).
6
+ *
7
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
8
+ * @copyright (c) 2018, Webcraftic Ltd
9
+ *
10
+ * @package factory-forms
11
+ * @since 1.0.0
12
+ */
13
+ // Exit if accessed directly
14
+ if( !defined('ABSPATH') ) {
15
+ exit;
16
+ }
17
+ if( !class_exists('Wbcr_IFactoryForms407_ValueProvider') ) {
18
+ /**
19
+ * The interface for all value provides.
20
+ *
21
+ * @since 1.0.0
22
+ */
23
+ interface Wbcr_IFactoryForms407_ValueProvider {
24
+
25
+ /**
26
+ * Inits a form a provider to get data from a storage.
27
+ *
28
+ * @since 1.0.0
29
+ * @return void
30
+ */
31
+ public function init();
32
+
33
+ /**
34
+ * Commits all changes.
35
+ *
36
+ * @since 1.0.0
37
+ * @return void
38
+ */
39
+ public function saveChanges();
40
+
41
+ /**
42
+ * Gets a value by its name.
43
+ *
44
+ * @since 1.0.0
45
+ * @param string $name A value name to get.
46
+ * @param mixed|null $default A default to return if a given name doesn't exist.
47
+ * @param string $name A value name to get.
48
+ * @return mixed
49
+ */
50
+ public function getValue($name, $default = null, $multiple = false);
51
+
52
+ /**
53
+ * Sets a value by its name.
54
+ *
55
+ * @since 1.0.0
56
+ * @param string $name A value name to set.
57
+ * @param mixed $value A value to set.
58
+ * @return void
59
+ */
60
+ public function setValue($name, $value);
61
+ }
62
+ }
libs/factory/forms/langs/wbcr_factory_forms_407-fr-FR.mo ADDED
Binary file
libs/factory/forms/langs/wbcr_factory_forms_407-fr-FR.po ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: factory_forms\n"
4
+ "POT-Creation-Date: 2017-11-09 10:37+0300\n"
5
+ "PO-Revision-Date: 2017-11-09 18:37+0300\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: fr\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.8.8\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: controls/checkbox.php:125
21
+ msgid "On"
22
+ msgstr "On"
23
+
24
+ #: controls/checkbox.php:128
25
+ msgid "Off"
26
+ msgstr "Off"
27
+
28
+ #: controls/dropdown.php:126 controls/list.php:89 controls/list.php:127
29
+ msgid "The list is empty."
30
+ msgstr "La liste est vide."
31
+
32
+ #: controls/dropdown.php:258 controls/dropdown.php:330
33
+ msgid "- empty -"
34
+ msgstr "- vide -"
35
+
36
+ #: controls/font.php:73 controls/google-font.php:41
37
+ msgid "(use default website font)"
38
+ msgstr "(utiliser la police de site par défaut)"
39
+
40
+ #: controls/font.php:76
41
+ msgid "Sans Serif:"
42
+ msgstr "Sans Serif:"
43
+
44
+ #: controls/font.php:127
45
+ msgid "Serif:"
46
+ msgstr "Serif:"
47
+
48
+ #: controls/font.php:177
49
+ msgid "Monospaced:"
50
+ msgstr "Monospaced:"
51
+
52
+ #: controls/google-font.php:44
53
+ msgid "Standard:"
54
+ msgstr "Standard:"
55
+
56
+ #: controls/google-font.php:53
57
+ msgid "Google Fonts:"
58
+ msgstr "Google Fonts:"
59
+
60
+ #: controls/google-font.php:94
61
+ msgid "Unable to retrieve the list of Google Fonts."
62
+ msgstr "Impossible de récupérer la liste des polices Google."
63
+
64
+ #: controls/google-font.php:101
65
+ msgid "Invalide response from the Google Fonts API."
66
+ msgstr "Réponse invalidée de l'API Google Fonts."
67
+
68
+ #: controls/google-font.php:110
69
+ msgid "Unexpected error. The list of Google Fonts are empty."
70
+ msgstr "Erreur inattendue. La liste des polices Google est vide."
71
+
72
+ #: controls/gradient.php:59
73
+ msgid "vertical"
74
+ msgstr "verticale"
75
+
76
+ #: controls/gradient.php:60
77
+ msgid "horizontal"
78
+ msgstr "horizontale"
79
+
80
+ #: controls/holders/more-link.php:47
81
+ msgid "hide extra options"
82
+ msgstr "masquer les options supplémentaires"
83
+
84
+ #: controls/paddings-editor.php:53
85
+ msgid "Select a side and move the slider to set up:"
86
+ msgstr "Sélectionnez un côté et déplacez le curseur pour configurer:"
87
+
88
+ #: controls/pattern.php:90
89
+ msgid "Change color"
90
+ msgstr "Changer de couleur"
91
+
92
+ #: controls/pattern.php:92
93
+ msgid "re-color"
94
+ msgstr "re-color"
95
+
96
+ #: controls/pattern.php:99
97
+ msgid "Select color:"
98
+ msgstr "Sélectionnez couleur:"
99
+
100
+ #: controls/pattern.php:102
101
+ msgid "Changing the color may takes a minute or more. Please be patient."
102
+ msgstr ""
103
+ "Changer la couleur peut prendre une minute ou plus. S'll vous plaît "
104
+ "soyez patient."
libs/factory/forms/langs/wbcr_factory_forms_407-ru_RU.mo ADDED
Binary file
libs/factory/forms/langs/wbcr_factory_forms_407-ru_RU.po ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: factory_forms\n"
4
+ "POT-Creation-Date: 2014-08-24 17:39+0400\n"
5
+ "PO-Revision-Date: 2014-08-24 17:49+0400\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.6.8\n"
13
+ "X-Poedit-Basepath: .\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: E:\\cloud\\Dropbox\\OnePress\\Products\\Topic\\Plugin "
19
+ "- Opt-In Panda for Wordpress\\wp-content\\plugins\\optinpanda-next\\libs"
20
+ "\\factory\\forms\n"
21
+
22
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
23
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/checkbox.php:55
24
+ msgid "On"
25
+ msgstr "Вкл"
26
+
27
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
28
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/checkbox.php:56
29
+ msgid "Off"
30
+ msgstr "Выкл"
31
+
32
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
33
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/font.php:33
34
+ msgid "(use default website font)"
35
+ msgstr "(шрифт сайта по умолчанию)"
36
+
37
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
38
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/font.php:35
39
+ msgid "Sans Serif:"
40
+ msgstr "Группа Sans Serif:"
41
+
42
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
43
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/font.php:58
44
+ msgid "Serif:"
45
+ msgstr "Группа Serif:"
46
+
47
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
48
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/font.php:78
49
+ msgid "Monospaced:"
50
+ msgstr "Группа Monospaced:"
51
+
52
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
53
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/gradient.php:54
54
+ msgid "vertical"
55
+ msgstr "вертикальный"
56
+
57
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
58
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/gradient.php:55
59
+ msgid "horizontal"
60
+ msgstr "горизонтальный"
61
+
62
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
63
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/holders/more-link.php:47
64
+ msgid "hide extra options"
65
+ msgstr "скрыть дополнительные настроки"
66
+
67
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
68
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/paddings-editor.php:51
69
+ msgid "Select a side and move the slider to set up:"
70
+ msgstr "Выберите сторону и переместите ползунок:"
71
+
72
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
73
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/pattern.php:78
74
+ msgid "Change color"
75
+ msgstr "Выбрать цвет"
76
+
77
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
78
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/pattern.php:80
79
+ msgid "re-color"
80
+ msgstr "Перекрасить"
81
+
82
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
83
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/pattern.php:89
84
+ msgid "Select color:"
85
+ msgstr "Выберите цвет:"
86
+
87
+ #: E:\cloud\Dropbox\OnePress\Products\Topic\Plugin - Opt-In Panda for
88
+ #: Wordpress\wp-content\plugins\optinpanda-next\libs\factory\forms/controls/pattern.php:91
89
+ msgid "Changing the color may takes a minute or more. Please be patient."
90
+ msgstr ""
91
+ "В некоторых случаях изменение цвета может занять около минуты. Пожалуйста, "
92
+ "будьте терпеливы."
93
+
94
+ #~ msgid "Upload Pattern"
95
+ #~ msgstr "Добавить шаблон"
libs/factory/forms/layouts/bootstrap-3/bootstrap-3.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The file contains a form layout based on Twitter Bootstrap 3
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-forms
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryForms407_Bootstrap3FormLayout') ) {
18
+ /**
19
+ * A form layout based on Twitter Bootstrap 3
20
+ */
21
+ class Wbcr_FactoryForms407_Bootstrap3FormLayout extends Wbcr_FactoryForms407_FormLayout {
22
+
23
+ public $name = 'default';
24
+
25
+ /**
26
+ * Creates a new instance of a bootstrap3 form layout.
27
+ *
28
+ * @since 1.0.0
29
+ * @param array $options A holder options.
30
+ * @param Wbcr_FactoryForms407_Form $form A parent form.
31
+ */
32
+ public function __construct($options, $form)
33
+ {
34
+ parent::__construct($options, $form);
35
+
36
+ $this->addCssClass('factory-bootstrap');
37
+ if( isset($options['cssClass']) ) {
38
+ $this->addCssClass($options['cssClass']);
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Renders a beginning of a form.
44
+ *
45
+ * @since 1.0.0
46
+ * @return void
47
+ */
48
+ public function beforeRendering()
49
+ {
50
+ ?>
51
+ <div <?php $this->attrs() ?>>
52
+ <div class="form-horizontal">
53
+ <?php
54
+ }
55
+
56
+ /**
57
+ * Renders the end of a form.
58
+ *
59
+ * @since 1.0.0
60
+ * @return void
61
+ */
62
+ public function afterRendering()
63
+ {
64
+ ?>
65
+ </div>
66
+ </div>
67
+ <?php
68
+ }
69
+
70
+ /**
71
+ * @param Wbcr_FactoryForms407_Control $control
72
+ */
73
+ public function beforeControl($control)
74
+ {
75
+ if( $control->getType() == 'hidden' ) {
76
+ return;
77
+ }
78
+
79
+ $theme_class = '';
80
+ if( isset($control->options['theme']) ) {
81
+ $theme_class = $control->options['theme'];
82
+ }
83
+
84
+ $control_name = $control->getOption('name');
85
+ $control_name_class = $control_name
86
+ ? 'factory-control-' . $control_name
87
+ : '';
88
+
89
+ $col_left = $control->getLayoutOption('column-left', '2');
90
+ $col_right = $control->getLayoutOption('column-right', '10');
91
+ ?>
92
+ <div class="form-group form-group-<?php echo $control->getType() ?> <?php echo $theme_class ?> <?php echo $control_name_class ?>">
93
+ <label for="<?php $control->printNameOnForm() ?>" class="col-sm-<?= $col_left ?> control-label">
94
+ <?php if( $control->hasIcon() ) { ?>
95
+ <img class="control-icon" src="<?php $control->icon() ?>"/>
96
+ <?php } ?>
97
+ <?php
98
+ $hint_type = $control->getLayoutOption('hint-type', 'default');
99
+
100
+ $control->title();
101
+ if( $control->hasHint() ) {
102
+ if( $hint_type == 'icon' ): ?>
103
+ <?php $hint_icon_color = $control->getLayoutOption('hint-icon-color', 'green'); ?>
104
+ <span class="factory-hint-icon factory-hint-icon-<?= $hint_icon_color ?>" data-toggle="factory-tooltip" data-placement="right" title="<?php $control->hint(true) ?>">
105
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
106
+
107
+ </span>
108
+ <?php endif; ?>
109
+ <?php if( $control->getLayoutOption('hint-position', 'bottom') == 'left' ): ?>
110
+ <div class="help-block"><?php $control->hint() ?></div>
111
+ <?php endif; ?>
112
+ <?php } ?>
113
+ </label>
114
+ <div class="control-group col-sm-<?= $col_right ?>">
115
+ <?php
116
+ }
117
+
118
+ /**
119
+ * @param Wbcr_FactoryForms407_Control $control
120
+ */
121
+ public function afterControl($control)
122
+ {
123
+ if( $control->getType() == 'hidden' ) {
124
+ return;
125
+ }
126
+ ?>
127
+ <?php if( $control->getOption('after', false) ) { ?>
128
+ <span class="factory-after">
129
+ <?php $control->option('after') ?>
130
+ </span>
131
+ <?php } ?>
132
+
133
+ <?php
134
+ $hint_type = $control->getLayoutOption('hint-type', 'default');
135
+ if( $control->hasHint() && $hint_type == 'default' && $control->getLayoutOption('hint-position', 'bottom') == 'bottom' ):
136
+ ?>
137
+ <div class="help-block">
138
+ <?php $control->hint() ?>
139
+ </div>
140
+ <?php endif; ?>
141
+ </div>
142
+ </div>
143
+ <?php
144
+ }
145
+
146
+ /**
147
+ * @param int $index
148
+ * @param int $total
149
+ */
150
+ public function startRow($index, $total)
151
+ {
152
+ ?>
153
+ <div class='factory-row factory-row-<?php echo $index ?> factory-row-<?php echo $index ?>-of-<?php echo $total ?>'>
154
+ <div class="form-group form-group">
155
+ <?php
156
+ }
157
+
158
+ /**
159
+ * @param int $index
160
+ * @param int $total
161
+ */
162
+ public function endRow($index, $total)
163
+ {
164
+ ?>
165
+ </div>
166
+ </div>
167
+ <?php
168
+ }
169
+
170
+ /**
171
+ * @param Wbcr_FactoryForms407_Control $control
172
+ * @param int $index
173
+ * @param int $total
174
+ */
175
+ public function startColumn($control, $index, $total)
176
+ {
177
+ $index = $total == 2
178
+ ? 4
179
+ : 3;
180
+ $name = $control->getNameOnForm();
181
+ ?>
182
+ <label for="<?php echo $name ?>" class="col-sm-2 control-label control-label-<?php echo $name ?>">
183
+ <?php if( $control->hasIcon() ) { ?>
184
+ <img class="control-icon" src="<?php $control->icon() ?>"/>
185
+ <?php } ?>
186
+ <?php $control->title() ?>
187
+ <?php if( $control->hasHint() && $control->getLayoutOption('hint-position', 'bottom') == 'left' ) { ?>
188
+ <div class="help-block"><?php $control->hint() ?></div>
189
+ <?php } ?>
190
+ </label>
191
+ <div class="control-group control-group-<?php echo $name ?> col-sm-<?php echo $index ?>">
192
+ <?php
193
+ }
194
+
195
+ /**
196
+ * @param Wbcr_FactoryForms407_Control $control
197
+ * @param int $index
198
+ * @param int $total
199
+ */
200
+ public function endColumn($control, $index, $total)
201
+ {
202
+ ?>
203
+ <?php if( $control->getOption('after', false) ) { ?>
204
+ <span class="factory-after">
205
+ <?php $control->option('after') ?>
206
+ </span>
207
+ <?php } ?>
208
+ <?php if( $control->hasHint() && $control->getLayoutOption('hint-position', 'bottom') == 'bottom' ) { ?>
209
+ <div class="help-block">
210
+ <?php $control->hint() ?>
211
+ </div>
212
+ <?php } ?>
213
+ </div>
214
+ <?php
215
+ }
216
+ }
217
+ }
libs/factory/pages/boot.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Factory Pages
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package core
9
+ * @since 1.0.1
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ // module provides function only for the admin area
18
+ if( !is_admin() ) {
19
+ return;
20
+ }
21
+
22
+ if( defined('FACTORY_PAGES_407_LOADED') ) {
23
+ return;
24
+ }
25
+ define('FACTORY_PAGES_407_LOADED', true);
26
+
27
+ define('FACTORY_PAGES_407_DIR', dirname(__FILE__));
28
+ define('FACTORY_PAGES_407_URL', plugins_url(null, __FILE__));
29
+
30
+ if( !defined('FACTORY_FLAT_ADMIN') ) {
31
+ define('FACTORY_FLAT_ADMIN', true);
32
+ }
33
+
34
+ load_plugin_textdomain('wbcr_factory_pages_407', false, dirname(plugin_basename(__FILE__)) . '/langs');
35
+
36
+ require(FACTORY_PAGES_407_DIR . '/pages.php');
37
+ require(FACTORY_PAGES_407_DIR . '/includes/page.class.php');
38
+ require(FACTORY_PAGES_407_DIR . '/includes/admin-page.class.php');
39
+ require(FACTORY_PAGES_407_DIR . '/templates/impressive-page.class.php');
40
+
libs/factory/pages/includes/admin-page.class.php ADDED
@@ -0,0 +1,459 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin page class
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryPages407_AdminPage') ) {
18
+
19
+ class Wbcr_FactoryPages407_AdminPage extends Wbcr_FactoryPages407_Page {
20
+
21
+ /**
22
+ * Visible page title.
23
+ * For example: 'License Manager'
24
+ * @var string
25
+ */
26
+ public $page_title;
27
+
28
+ /**
29
+ * Visible title in menu.
30
+ * For example: 'License Manager'
31
+ * @var string
32
+ */
33
+ public $menu_title = null;
34
+
35
+ /**
36
+ * If set, an extra sub menu will be created with another title.
37
+ * @var string
38
+ */
39
+ public $menu_sub_title = null;
40
+
41
+ /**
42
+ * Menu icon (only if a page is placed as a main menu).
43
+ * For example: '~/assets/img/menu-icon.png'
44
+ * For example dashicons: '\f321'
45
+ * @var string
46
+ */
47
+ public $menu_icon = null;
48
+
49
+ /**
50
+ * Menu position (only if a page is placed as a main menu).
51
+ * @link http://codex.wordpress.org/Function_Reference/add_menu_page
52
+ * @var string
53
+ */
54
+ public $menu_position = null;
55
+
56
+ /**
57
+ * Menu type. Set it to add the page to the specified type menu.
58
+ * For example: 'post'
59
+ * @var string
60
+ */
61
+ public $menu_post_type = null;
62
+
63
+ /**
64
+ * if specified the page will be added to the given menu target as a submenu.
65
+ * For example: 'edit.php?post_type=custom-post-type'
66
+ * @var string
67
+ */
68
+ public $menu_target = null;
69
+
70
+ /**
71
+ * if true, then admin.php is used as a base url.
72
+ * @var bool
73
+ */
74
+ public $custom_target = false;
75
+
76
+ /**
77
+ * Capabilities for roles that have access to work with this page.
78
+ * Leave it empty to use inherited capabilities for custom post type menu.
79
+ * @link http://codex.wordpress.org/Roles_and_Capabilities
80
+ * @var array An array of the capabilities.
81
+ */
82
+ public $capabilitiy = null;
83
+
84
+ /**
85
+ * If true, the page will not added to the admin menu.
86
+ * @var bool
87
+ */
88
+ public $internal = false;
89
+
90
+ /**
91
+ * If true, the page will not be cretaed.
92
+ *
93
+ * @since 3.0.6
94
+ * @var bool
95
+ */
96
+ public $hidden = false;
97
+
98
+ /**
99
+ * Link title for plugin action menu
100
+ *
101
+ * @var string/null
102
+ */
103
+ public $title_plugin_action_link = null;
104
+
105
+ /**
106
+ * If true, add settings link in plugins list
107
+ * https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
108
+ * @var bool
109
+ */
110
+ public $add_link_to_plugin_actions = false;
111
+
112
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
113
+ {
114
+ parent::__construct($plugin);
115
+ $this->configure();
116
+
117
+ $this->id = empty($this->id)
118
+ ? str_replace('adminpage', '', strtolower(get_class($this)))
119
+ : $this->id;
120
+
121
+ if( $this->add_link_to_plugin_actions ) {
122
+ $plugin_path_info = $this->plugin->getPluginPathInfo();
123
+ // plugin settings link
124
+ add_filter("plugin_action_links_" . $plugin_path_info->relative_path, array(
125
+ $this,
126
+ 'addLinkToPluginActions'
127
+ ));
128
+ }
129
+ }
130
+
131
+ /**
132
+ * May be used to configure the page before uts usage.
133
+ */
134
+ public function configure()
135
+ {
136
+ }
137
+
138
+ /**
139
+ * Includes the Factory Bootstrap assets for a current page.
140
+ *
141
+ * @param string $hook
142
+ * @return void
143
+ */
144
+ public function actionAdminBootstrapScripts($hook)
145
+ {
146
+ $this->scripts->connect('bootstrap');
147
+ $this->styles->connect('bootstrap');
148
+ }
149
+
150
+ /**
151
+ * Includes the assets for a current page (all assets except Factory Bootstrap assets).
152
+ *
153
+ * @param string $hook
154
+ * @return void
155
+ */
156
+ public function actionAdminScripts($hook)
157
+ {
158
+ $this->scripts->connect();
159
+ $this->styles->connect();
160
+ }
161
+
162
+ /**
163
+ * @return string
164
+ */
165
+ public function getMenuScope()
166
+ {
167
+ return $this->plugin->getPluginName();
168
+ }
169
+
170
+ /**
171
+ * @param null $id
172
+ * @return mixed|string
173
+ */
174
+ public function getResultId($id = null)
175
+ {
176
+ $id = !empty($id)
177
+ ? $id
178
+ : $this->id;
179
+
180
+ if( $this->plugin ) {
181
+ return $id . '-' . $this->getMenuScope();
182
+ }
183
+
184
+ return $id;
185
+ }
186
+
187
+ /**
188
+ * Registers admin page for the admin menu.
189
+ */
190
+ public function connect()
191
+ {
192
+ $result_id = $this->getResultId();
193
+
194
+ $this->hidden = apply_filters('wbcr_factory_406_page_is_hidden_' . $result_id, $this->hidden);
195
+
196
+ if( $this->hidden ) {
197
+ return;
198
+ }
199
+
200
+ $this->internal = apply_filters('wbcr_factory_406_page_is_internal_' . $result_id, $this->internal);
201
+
202
+ if( $this->internal ) {
203
+ $this->menu_target = null;
204
+ $this->menu_post_type = null;
205
+ }
206
+
207
+ // makes redirect to the page
208
+ $controller = $this->request->get('fy_page', null, true);
209
+
210
+ if( $controller && $controller == $this->id ) {
211
+ $plugin = $this->request->get('fy_plugin', null, true);
212
+
213
+ if( $this->plugin->getPluginName() == $plugin ) {
214
+
215
+ $action = $this->request->get('fy_action', 'index', true);
216
+ $is_ajax = $this->request->get('fy_ajax', false);
217
+
218
+ if( $is_ajax ) {
219
+ $this->executeByName($action);
220
+ exit;
221
+ } else {
222
+
223
+ $params = (array)$this->request->getAll(true);
224
+
225
+ unset($params['fy_page']);
226
+ unset($params['fy_plugin']);
227
+ unset($params['fy_action']);
228
+
229
+ $this->redirectToAction($action, $params);
230
+ }
231
+ }
232
+ }
233
+
234
+ // calls scripts and styles, adds pages to menu
235
+ if( $this->request->get('page', 'none') == $result_id ) {
236
+ $this->assets($this->scripts, $this->styles);
237
+
238
+ if( !$this->scripts->isEmpty('bootstrap') || !$this->styles->isEmpty('bootstrap') ) {
239
+ add_action('wbcr_factory_406_bootstrap_enqueue_scripts_' . $this->plugin->getPluginName(), array(
240
+ $this,
241
+ 'actionAdminBootstrapScripts'
242
+ ));
243
+ }
244
+
245
+ // includes styles and scripts
246
+ if( !$this->scripts->isEmpty() || !$this->styles->isEmpty() ) {
247
+ add_action('admin_enqueue_scripts', array($this, 'actionAdminScripts'));
248
+ }
249
+ }
250
+
251
+ // if this page for a custom menu page
252
+ if( $this->menu_post_type ) {
253
+ $this->menu_target = 'edit.php?post_type=' . $this->menu_post_type;
254
+
255
+ if( empty($this->capabilitiy) ) {
256
+ $this->capabilitiy = 'edit_' . $this->menu_post_type;
257
+ }
258
+ }
259
+
260
+ // sets default capabilities
261
+ if( empty($this->capabilitiy) ) {
262
+ $this->capabilitiy = 'manage_options';
263
+ }
264
+
265
+ $this->page_title = !$this->page_title
266
+ ? $this->menu_title
267
+ : $this->page_title;
268
+
269
+ $this->menu_title = !$this->menu_title
270
+ ? $this->page_title
271
+ : $this->menu_title;
272
+
273
+ $this->page_title = apply_filters('wbcr_factory_page_title_' . $result_id, $this->page_title);
274
+ $this->menu_title = apply_filters('wbcr_factory_menu_title_' . $result_id, $this->menu_title);
275
+
276
+ // submenu
277
+ if( $this->menu_target ) {
278
+
279
+ add_submenu_page($this->menu_target, $this->page_title, $this->menu_title, $this->capabilitiy, $result_id, array(
280
+ $this,
281
+ 'show'
282
+ ));
283
+ // global menu
284
+ } else {
285
+
286
+ add_menu_page($this->page_title, $this->menu_title, $this->capabilitiy, $result_id, array(
287
+ $this,
288
+ 'show'
289
+ ), null, $this->menu_position);
290
+
291
+ if( !empty($this->menu_sub_title) ) {
292
+
293
+ add_submenu_page($result_id, $this->menu_sub_title, $this->menu_sub_title, $this->capabilitiy, $result_id, array(
294
+ $this,
295
+ 'show'
296
+ ));
297
+ }
298
+
299
+ add_action('admin_head', array($this, 'actionAdminHead'));
300
+ }
301
+
302
+ // executes an action
303
+ if( $this->current() ) {
304
+ ob_start();
305
+ $action = $this->request->get('action', 'index', true);
306
+ $this->executeByName($action);
307
+ $this->result = ob_get_contents();
308
+ ob_end_clean();
309
+ }
310
+ }
311
+
312
+ protected function current()
313
+ {
314
+ $result_id = $this->getResultId();
315
+
316
+ if( $result_id == $this->request->get('page', 'none') ) {
317
+ return true;
318
+ }
319
+
320
+ return false;
321
+ }
322
+
323
+ /**
324
+ * @param string $action
325
+ * @param array $query_args
326
+ */
327
+ public function redirectToAction($action, $query_args = array())
328
+ {
329
+
330
+ wp_safe_redirect($this->getActionUrl($action, $query_args));
331
+ exit;
332
+ }
333
+
334
+ /**
335
+ * @param string $action
336
+ * @param array $query_args
337
+ */
338
+ public function actionUrl($action = null, $query_args = array())
339
+ {
340
+ echo $this->getActionUrl($action, $query_args);
341
+ }
342
+
343
+ /**
344
+ * @param null $action
345
+ * @param array $query_args
346
+ * @return string
347
+ */
348
+ public function getActionUrl($action = null, $query_args = array())
349
+ {
350
+ $baseUrl = $this->getBaseUrl();
351
+
352
+ if( !empty($action) ) {
353
+ $query_args['action'] = $action;
354
+ }
355
+ $url = add_query_arg($query_args, $baseUrl);
356
+
357
+ return $url;
358
+ }
359
+
360
+ /**
361
+ * @return string
362
+ */
363
+ protected function getBaseUrl()
364
+ {
365
+ $result_id = $this->getResultId();
366
+
367
+ if( $this->menu_target ) {
368
+ if( $this->custom_target ) {
369
+ return admin_url('admin.php') . '?page=' . $result_id;
370
+ }
371
+
372
+ return $this->menu_target . '&page=' . $result_id;
373
+ } else {
374
+ return 'admin.php?&page=' . $result_id;
375
+ }
376
+ }
377
+
378
+ public function actionAdminHead()
379
+ {
380
+ $result_id = $this->getResultId();
381
+
382
+ if( !empty($this->menu_icon) ) {
383
+
384
+ if( preg_match('/\\\f\d{3}/', $this->menu_icon) ) {
385
+ $icon_code = $this->menu_icon;
386
+ } else {
387
+ $plugin_path_info = $this->plugin->getPluginPathInfo();
388
+ $icon_url = str_replace('~/', $plugin_path_info->plugin_url . '/', $this->menu_icon);
389
+ }
390
+ }
391
+
392
+ global $wp_version;
393
+
394
+ if( version_compare($wp_version, '3.7.3', '>') ) {
395
+ ?>
396
+ <style type="text/css" media="screen">
397
+ <?php if ( !empty($icon_url) ) { ?>
398
+
399
+ a.toplevel_page_<?php echo $result_id ?> .wp-menu-image {
400
+ background: url('<?php echo $icon_url ?>') no-repeat 10px -30px !important;
401
+ }
402
+
403
+ <?php } ?>
404
+
405
+ a.toplevel_page_<?php echo $result_id ?> .wp-menu-image:before {
406
+ content: "<?php echo !empty($icon_code) ? $icon_code : ''; ?>" !important;
407
+ }
408
+
409
+ a.toplevel_page_<?php echo $result_id ?>:hover .wp-menu-image,
410
+ a.toplevel_page_<?php echo $result_id ?>.wp-has-current-submenu .wp-menu-image,
411
+ a.toplevel_page_<?php echo $result_id ?>.current .wp-menu-image {
412
+ background-position: 10px 2px !important;
413
+ }
414
+ </style>
415
+ <?php } else { ?>
416
+ <style type="text/css" media="screen">
417
+ a.toplevel_page_<?php echo $result_id ?> .wp-menu-image {
418
+ background: url('<?php echo $icon_url ?>') no-repeat 6px -33px !important;
419
+ }
420
+
421
+ a.toplevel_page_<?php echo $result_id ?>:hover .wp-menu-image,
422
+ a.toplevel_page_<?php echo $result_id ?>.current .wp-menu-image {
423
+ background-position: 6px -1px !important;
424
+ }
425
+ </style>
426
+ <?php
427
+ }
428
+
429
+ if( $this->internal ) {
430
+ ?>
431
+ <style type="text/css" media="screen">
432
+ li.toplevel_page_<?php echo $result_id ?> {
433
+ display: none;
434
+ }
435
+ </style>
436
+ <?php
437
+ }
438
+ }
439
+
440
+
441
+ /**
442
+ * Add settings link in plugins list
443
+ *
444
+ * @param $links
445
+ * @return mixed
446
+ */
447
+ function addLinkToPluginActions($links)
448
+ {
449
+ $link_title = !empty($this->title_plugin_action_link)
450
+ ? $this->title_plugin_action_link
451
+ : $this->menu_title;
452
+
453
+ $settings_link = '<a href="' . $this->getBaseUrl() . '">' . $link_title . '</a>';
454
+ array_unshift($links, $settings_link);
455
+
456
+ return $links;
457
+ }
458
+ }
459
+ }
libs/factory/pages/includes/page.class.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin page class
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryPages407_Page') ) {
18
+
19
+ class Wbcr_FactoryPages407_Page {
20
+
21
+ /**
22
+ * Page id used to call.
23
+ * @var string
24
+ */
25
+ public $id;
26
+
27
+ /**
28
+ * Current Factory Plugin.
29
+ * @var Wbcr_Factory406_Plugin
30
+ */
31
+ public $plugin;
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ public $result;
37
+
38
+
39
+ /**
40
+ * @param Wbcr_Factory406_Plugin $plugin
41
+ * @throws Exception
42
+ */
43
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
44
+ {
45
+ $this->plugin = $plugin;
46
+
47
+ if( $plugin ) {
48
+ $this->scripts = $this->plugin->newScriptList();
49
+ $this->styles = $this->plugin->newStyleList();
50
+ $this->request = $plugin->request;
51
+ }
52
+ }
53
+
54
+ public function assets($scripts, $styles)
55
+ {
56
+ }
57
+
58
+ /**
59
+ * Shows page.
60
+ */
61
+ public function show()
62
+ {
63
+
64
+ if( $this->result ) {
65
+ echo $this->result;
66
+ } else {
67
+ $action = isset($_GET['action'])
68
+ ? $_GET['action']
69
+ : 'index';
70
+ $this->executeByName($action);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * @param string $action
76
+ * @throws Exception
77
+ */
78
+ public function executeByName($action)
79
+ {
80
+ if( preg_match('/[-_]+/', $action) ) {
81
+ $action = $this->dashesToCamelCase($action, false);
82
+ }
83
+ $actionFunction = $action . 'Action';
84
+
85
+ $cancel = $this->OnActionExecuting($action);
86
+
87
+ if( $cancel === false ) {
88
+ return;
89
+ }
90
+
91
+ if( !method_exists($this, $actionFunction) ) {
92
+ $actionFunction = 'indexAction';
93
+ }
94
+
95
+ call_user_func_array(array($this, $actionFunction), array());
96
+ $this->OnActionExected($action);
97
+ }
98
+
99
+ /**
100
+ * @param string $string
101
+ * @param bool $capitalizeFirstCharacter
102
+ * @return mixed
103
+ * @throws Exception
104
+ */
105
+ protected function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
106
+ {
107
+ $str = str_replace(' ', '', ucwords(preg_replace('/[-_]/', ' ', $string)));
108
+
109
+ if( !$capitalizeFirstCharacter ) {
110
+ $str[0] = strtolower($str[0]);
111
+ }
112
+
113
+ if( empty($str) ) {
114
+ throw new Exception('Dashed to camelcase parse error.');
115
+ }
116
+
117
+ return $str;
118
+ }
119
+
120
+ /**
121
+ * @param $action
122
+ * @return bool
123
+ */
124
+ protected function OnActionExecuting($action)
125
+ {
126
+ }
127
+
128
+ protected function OnActionExected($action)
129
+ {
130
+ }
131
+
132
+ /**
133
+ * @param $path
134
+ */
135
+ protected function script($path)
136
+ {
137
+ wp_enqueue_script($path, $path, array('jquery'), false, true);
138
+ }
139
+ }
140
+ }
libs/factory/pages/langs/wbcr_factory_pages_407-fr_FR.mo ADDED
Binary file
libs/factory/pages/langs/wbcr_factory_pages_407-fr_FR.po ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: clearfy\n"
4
+ "POT-Creation-Date: 2017-11-09 10:33+0300\n"
5
+ "PO-Revision-Date: 2017-11-09 19:04+0300\n"
6
+ "Last-Translator: alex.kovalevv@gmail.com <alex.kovalevv@gmail.com>\n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: fr\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.8.8\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: templates/impressive-page.class.php:45
21
+ msgid "Settings"
22
+ msgstr "Paramètres"
23
+
24
+ #: templates/impressive-page.class.php:170
25
+ msgid ""
26
+ "It seems that a caching/performance plugin is active on this site. Please "
27
+ "manually invalidate that plugin's cache after making any changes to the "
28
+ "settings below."
29
+ msgstr ""
30
+ "Il semble qu'un plugin cache / performance soit actif sur ce site. Veuillez "
31
+ "invalider manuellement le cache de ce plugin après avoir apporté des "
32
+ "modifications aux paramètres ci-dessous."
33
+
34
+ #: templates/impressive-page.class.php:187
35
+ msgid "The settings have been updated successfully!"
36
+ msgstr "Les paramètres ont été mis à jour avec succès!"
37
+
38
+ #: templates/impressive-page.class.php:251
39
+ msgid "Page"
40
+ msgstr "Page"
41
+
42
+ #: templates/impressive-page.class.php:256
43
+ msgid "Save settings"
44
+ msgstr "Enregistrer les paramètres"
45
+
46
+ #: templates/impressive-page.class.php:328
47
+ msgid "You do not have permission to edit page."
48
+ msgstr "Vous n'êtes pas autorisé à modifier la page."
49
+
50
+ #: templates/impressive-page.class.php:403
51
+ msgid ""
52
+ "A neutral setting that can not harm your site, but you must be sure that you "
53
+ "need to use it."
54
+ msgstr ""
55
+ "Un paramètre neutre qui ne peut pas nuire à votre site, mais vous devez être "
56
+ "sûr que vous devez l'utiliser."
57
+
58
+ #: templates/impressive-page.class.php:407
59
+ msgid ""
60
+ "When set this option, you must be careful. Plugins and themes may depend on "
61
+ "this function. You must be sure that you can disable this feature for the "
62
+ "site."
63
+ msgstr ""
64
+ "Lorsque vous définissez cette option, vous devez faire attention. Les "
65
+ "plugins et les thèmes peuvent dépendre de cette fonction. Vous devez être "
66
+ "sûr que vous pouvez désactiver cette fonctionnalité pour le site."
67
+
68
+ #: templates/impressive-page.class.php:411
69
+ msgid "Absolutely safe setting, We recommend to use."
70
+ msgstr "Réglage absolument sûr, nous recommandons d'utiliser."
71
+
72
+ #: templates/impressive-page.class.php:416
73
+ msgid "Hover to the icon to get help for the feature you selected."
74
+ msgstr "Passez à l'icône pour obtenir de l'aide sur la fonction sélectionnée."
75
+
76
+ #: templates/impressive-page.class.php:432
77
+ msgid "Do you want the plugin to improved and update?"
78
+ msgstr "Voulez-vous que le plugin pour améliorer et mettre à jour?"
79
+
80
+ #: templates/impressive-page.class.php:435
81
+ msgid ""
82
+ "Help the author, leave a review on wordpress.org. Thanks to feedback, I will "
83
+ "know that the plugin is really useful to you and is needed."
84
+ msgstr ""
85
+ "Aidez l'auteur, laissez un commentaire sur wordpress.org. Grâce aux retours, "
86
+ "je saurai que le plugin est vraiment utile et nécessaire."
87
+
88
+ #: templates/impressive-page.class.php:437
89
+ msgid "And also write your ideas on how to extend or improve the plugin."
90
+ msgstr ""
91
+ "Et écrivez aussi vos idées sur la façon d'étendre ou d'améliorer le plugin."
92
+
93
+ #: templates/impressive-page.class.php:442
94
+ msgid "Go rate us and push ideas"
95
+ msgstr "Allez nous évaluer et pousser des idées"
96
+
97
+ #: templates/impressive-page.class.php:454
98
+ msgid "Donation for plug-in development"
99
+ msgstr "Don pour le développement du plug-in"
libs/factory/pages/langs/wbcr_factory_pages_407-ru_RU.mo ADDED
Binary file
libs/factory/pages/langs/wbcr_factory_pages_407-ru_RU.po ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: clearfy\n"
4
+ "POT-Creation-Date: 2017-10-14 13:52+0300\n"
5
+ "PO-Revision-Date: 2017-11-17 07:31+0300\n"
6
+ "Last-Translator: alex.kovalevv@gmail.com <alex.kovalevv@gmail.com>\n"
7
+ "Language-Team: Alex Kovalev <alex.kovalevv@gmail.com>\n"
8
+ "Language: ru_RU\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.8.8\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
+ "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
16
+ "X-Poedit-SourceCharset: UTF-8\n"
17
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c\n"
18
+ "X-Poedit-SearchPath-0: .\n"
19
+
20
+ #: templates/impressive-page.class.php:45
21
+ msgid "Settings"
22
+ msgstr "Настройки"
23
+
24
+ #: templates/impressive-page.class.php:170
25
+ msgid ""
26
+ "It seems that a caching/performance plugin is active on this site. Please "
27
+ "manually invalidate that plugin's cache after making any changes to the "
28
+ "settings below."
29
+ msgstr ""
30
+ "Похоже, что Вы используете плагин кэширования или ускорения блога. Не "
31
+ "забудьте после изменения любых настроек, очистить кэш вручную!"
32
+
33
+ #: templates/impressive-page.class.php:187
34
+ msgid "The settings have been updated successfully!"
35
+ msgstr "Настройки были успешно обновлены!"
36
+
37
+ #: templates/impressive-page.class.php:251
38
+ msgid "Page"
39
+ msgstr "Страница"
40
+
41
+ #: templates/impressive-page.class.php:256
42
+ msgid "Save settings"
43
+ msgstr "Сохранить настройки"
44
+
45
+ #: templates/impressive-page.class.php:328
46
+ msgid "You do not have permission to edit page."
47
+ msgstr "У вас недостаточно прав, для редактирования этой страницы."
48
+
49
+ #: templates/impressive-page.class.php:403
50
+ msgid ""
51
+ "A neutral setting that can not harm your site, but you must be sure that you "
52
+ "need to use it."
53
+ msgstr ""
54
+ "Нейтральная настройка, которая не может нанести вред вашему сайту, но вы "
55
+ "должны быть уверены, что вам нужно ее использовать."
56
+
57
+ #: templates/impressive-page.class.php:407
58
+ msgid ""
59
+ "When set this option, you must be careful. Plugins and themes may depend on "
60
+ "this function. You must be sure that you can disable this feature for the "
61
+ "site."
62
+ msgstr ""
63
+ "При включении этой настройки, вы должны быть осторожны. Некоторые плагины и "
64
+ "темы могут зависеть от этой функции. Вы должны быть уверены, что эту функцию "
65
+ "можно отключить для сайта."
66
+
67
+ #: templates/impressive-page.class.php:411
68
+ msgid "Absolutely safe setting, We recommend to use."
69
+ msgstr "Абсолютно безопасная настройка, рекомендуем использовать."
70
+
71
+ #: templates/impressive-page.class.php:416
72
+ msgid "Hover to the icon to get help for the feature you selected."
73
+ msgstr ""
74
+ "Наведите указатель мыши на значок, чтобы получить справку по выбранной "
75
+ "функции."
76
+
77
+ #: templates/impressive-page.class.php:432
78
+ msgid "Do you want the plugin to improved and update?"
79
+ msgstr "Вы хотите, чтобы плагин улучшался и обновлялся?"
80
+
81
+ #: templates/impressive-page.class.php:435
82
+ msgid ""
83
+ "Help the author, leave a review on wordpress.org. Thanks to feedback, I will "
84
+ "know that the plugin is really useful to you and is needed."
85
+ msgstr ""
86
+ "Помогите автору, оставьте отзыв на wordpress.org. Благодаря отзывам, я буду "
87
+ "знать, что плагин действительно полезен для вас и необходим."
88
+
89
+ #: templates/impressive-page.class.php:437
90
+ msgid "And also write your ideas on how to extend or improve the plugin."
91
+ msgstr "А также напишите свои идеи о том, как расширить или улучшить плагин."
92
+
93
+ #: templates/impressive-page.class.php:442
94
+ msgid "Go rate us and push ideas"
95
+ msgstr "Оставить отзыв или поделиться идеей"
96
+
97
+ #: templates/impressive-page.class.php:454
98
+ msgid "Donation for plug-in development"
99
+ msgstr "Пожертвования на развитие плагина"
libs/factory/pages/pages.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A group of classes and methods to create and manage pages.
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package core
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ add_action('admin_menu', 'Wbcr_FactoryPages407::actionAdminMenu');
18
+
19
+ if( !class_exists('Wbcr_FactoryPages407') ) {
20
+ /**
21
+ * A base class to manage pages.
22
+ *
23
+ * @since 1.0.0
24
+ */
25
+ class Wbcr_FactoryPages407 {
26
+
27
+ /**
28
+ * @var Wbcr_FactoryPages407_Page[]
29
+ */
30
+ private static $pages = array();
31
+
32
+ /**
33
+ * @param Wbcr_Factory406_Plugin $plugin
34
+ * @param $class_name
35
+ */
36
+ public static function register($plugin, $class_name)
37
+ {
38
+ if( !isset(self::$pages[$plugin->getPluginName()]) ) {
39
+ self::$pages[$plugin->getPluginName()] = array();
40
+ }
41
+ self::$pages[$plugin->getPluginName()][] = new $class_name($plugin);
42
+ }
43
+
44
+ public static function actionAdminMenu()
45
+ {
46
+ if( empty(self::$pages) ) {
47
+ return;
48
+ }
49
+
50
+ foreach(self::$pages as $plugin_pages) {
51
+ foreach($plugin_pages as $page) {
52
+ $page->connect();
53
+ }
54
+ }
55
+ }
56
+
57
+ /**
58
+ * @param Wbcr_Factory406_Plugin $plugin
59
+ * @return array
60
+ */
61
+ public static function getIds($plugin)
62
+ {
63
+ if( !isset(self::$pages[$plugin->getPluginName()]) ) {
64
+ return array();
65
+ }
66
+
67
+ $result = array();
68
+ foreach(self::$pages[$plugin->getPluginName()] as $page)
69
+ $result[] = $page->getResultId();
70
+
71
+ return $result;
72
+ }
73
+ }
74
+ }
75
+
76
+ if( !function_exists('wbcr_factory_pages_407_get_page_id') ) {
77
+ /**
78
+ *
79
+ * @param Wbcr_Factory406_Plugin $plugin
80
+ * @param string $page_id
81
+ * @return string
82
+ */
83
+ function wbcr_factory_pages_407_get_page_id($plugin, $page_id)
84
+ {
85
+ return $page_id . '-' . $plugin->getPluginName();
86
+ }
87
+ }
libs/factory/pages/templates/assets/css/impressive.page.template.css ADDED
@@ -0,0 +1,430 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * General styles
3
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
4
+ * @copyright Alex Kovalev 23.08.2017
5
+ */
6
+ #WBCR .updated,
7
+ #WBCR .notice,
8
+ #WBCR .error {
9
+ display: none !important;
10
+ }
11
+ #WBCR .wbcr-factory-pages-407-impressive-page-template {
12
+ position: relative;
13
+ /**
14
+ Content sections
15
+ */
16
+ /**
17
+ Widget in the sidebar of the plugin
18
+ */
19
+ }
20
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-color-grey {
21
+ color: #9a9a9a;
22
+ }
23
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-orange-color {
24
+ color: #ffc107;
25
+ }
26
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-light-orange-color {
27
+ color: #ffeb3b;
28
+ }
29
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .form-group {
30
+ padding: 0 20px;
31
+ }
32
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .form-group label {
33
+ font-weight: normal;
34
+ }
35
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .form-horizontal .control-label {
36
+ max-width: 300px;
37
+ }
38
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .factory-control-buttons {
39
+ text-align: right;
40
+ padding-right: 20px;
41
+ }
42
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .factory-from-control-list label span {
43
+ display: inline-block;
44
+ vertical-align: bottom;
45
+ }
46
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .factory-from-control-list label span input[type="checkbox"],
47
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .factory-from-control-list label span input[type="checkbox"]:focus {
48
+ outline: none;
49
+ }
50
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert {
51
+ font-weight: bold;
52
+ margin: 0 !important;
53
+ border: 0;
54
+ border-radius: 0;
55
+ padding: 15px;
56
+ }
57
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert + .wbcr-factory-page-group-header {
58
+ margin-top: 0 !important;
59
+ }
60
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert.alert-warning {
61
+ background: #fff3d0;
62
+ }
63
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert.alert-warning:nth-child(2n+1) {
64
+ background: #fffde9;
65
+ }
66
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert.alert-danger {
67
+ background: #de716d;
68
+ }
69
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert.alert-danger:nth-child(2n+1) {
70
+ background: #ec8c89;
71
+ }
72
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert.alert-success {
73
+ background: #d0ecc4;
74
+ }
75
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .alert.alert-success:nth-child(2n+1) {
76
+ background: #e0eadb;
77
+ }
78
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-header {
79
+ padding: 20px 20px 40px;
80
+ }
81
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-recomended-text {
82
+ display: block;
83
+ font-size: 11px;
84
+ font-weight: lighter;
85
+ color: #179347;
86
+ }
87
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-options,
88
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page {
89
+ position: relative;
90
+ background: #e6e6e6;
91
+ overflow: hidden;
92
+ }
93
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-options:after,
94
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page:after {
95
+ display: block;
96
+ content: '';
97
+ clear: both;
98
+ }
99
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-group-header {
100
+ background: #efefef;
101
+ padding: 20px 0 10px 20px;
102
+ margin: 30px 0;
103
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
104
+ }
105
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-group-header:first-child {
106
+ margin-top: 0;
107
+ }
108
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-group-header strong {
109
+ font-size: 15px;
110
+ }
111
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-group-header p {
112
+ color: #8c8888;
113
+ font-size: 12px;
114
+ }
115
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap {
116
+ margin-left: 230px;
117
+ padding: 80px 0 0 0;
118
+ vertical-align: top;
119
+ background: #fff;
120
+ }
121
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap .nav-tab-wrapper,
122
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap h2.nav-tab-wrapper,
123
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap h1.nav-tab-wrapper {
124
+ border: 0;
125
+ }
126
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap .nav-tab-active {
127
+ background: #efefef;
128
+ }
129
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap .nav-tab:first-child {
130
+ margin-left: 80px !important;
131
+ }
132
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap .nav-tab:hover {
133
+ background: #f7f7f7;
134
+ }
135
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap .nav-tab:active,
136
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap .nav-tab:focus {
137
+ box-shadow: none;
138
+ outline: none;
139
+ }
140
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header {
141
+ position: absolute;
142
+ z-index: 13;
143
+ top: 0;
144
+ left: 0;
145
+ right: 0;
146
+ overflow: hidden;
147
+ background-color: #32373c;
148
+ color: #fff;
149
+ border-radius: 5px 5px 0 0;
150
+ }
151
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-header-logo {
152
+ float: left;
153
+ padding: 25px 0;
154
+ font-size: 20px;
155
+ line-height: 30px;
156
+ font-weight: 400;
157
+ text-align: center;
158
+ background-color: #464b50;
159
+ color: #ccc;
160
+ padding-left: 25px;
161
+ margin-right: 10px;
162
+ background: none;
163
+ }
164
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-header-title {
165
+ display: inline-block;
166
+ vertical-align: middle;
167
+ }
168
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-header-title h2 {
169
+ font-size: 18px;
170
+ line-height: 30px;
171
+ font-weight: 300;
172
+ margin-top: 26px;
173
+ padding: 0 !important;
174
+ overflow: hidden;
175
+ white-space: nowrap;
176
+ text-overflow: ellipsis;
177
+ color: #fff;
178
+ }
179
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-control {
180
+ position: relative;
181
+ float: right;
182
+ margin: 12px;
183
+ }
184
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-control input[type="submit"] {
185
+ display: inline-block;
186
+ vertical-align: top;
187
+ font-size: 13px;
188
+ font-weight: 600;
189
+ line-height: 20px;
190
+ text-transform: uppercase;
191
+ margin: 10px 0 0;
192
+ padding: 8px 30px;
193
+ cursor: pointer;
194
+ position: relative;
195
+ overflow: hidden;
196
+ border: none;
197
+ border-radius: 50px;
198
+ box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.08) inset;
199
+ background-color: #f1f1f1;
200
+ color: inherit;
201
+ transition: background-color 0.3s, border-color 0.3s, color 0.3s, opacity 0.3s;
202
+ text-align: center;
203
+ outline: none;
204
+ z-index: 3;
205
+ }
206
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-control input[type="submit"].wbcr-factory-type-save {
207
+ box-shadow: none;
208
+ min-width: 200px;
209
+ background-color: #8bc34a;
210
+ color: #fff;
211
+ }
212
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-control input[type="submit"].wbcr-factory-type-save:hover {
213
+ background: #9dbb7b;
214
+ color: #fff;
215
+ }
216
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-header .wbcr-factory-control input[type="submit"].wbcr-factory-type-save:active {
217
+ box-shadow: inset -1px 1px 1px rgba(0, 0, 0, 0.3);
218
+ }
219
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar {
220
+ float: left;
221
+ vertical-align: top;
222
+ width: 230px;
223
+ background: #e6e6e6;
224
+ }
225
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul {
226
+ padding: 0;
227
+ margin-bottom: 0;
228
+ margin-top: 80px;
229
+ }
230
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab {
231
+ display: block;
232
+ background: #efefef;
233
+ margin: 1px 0;
234
+ }
235
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a {
236
+ display: block;
237
+ width: 100%;
238
+ padding: 20px 20px;
239
+ font-size: 12px;
240
+ color: #9a9a9a;
241
+ text-decoration: none;
242
+ text-transform: uppercase;
243
+ }
244
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a:hover {
245
+ background: #f7f6f6;
246
+ }
247
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a,
248
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a:active,
249
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a:hover,
250
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a:active,
251
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a:focus {
252
+ outline: 0 !important;
253
+ box-shadow: none !important;
254
+ }
255
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab.wbcr-factory-active-tab {
256
+ background: #fff;
257
+ }
258
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab.wbcr-factory-active-tab a {
259
+ color: #222;
260
+ }
261
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-content-section,
262
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-right-sidebar-section {
263
+ display: inline-block;
264
+ vertical-align: top;
265
+ }
266
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-content-section {
267
+ width: 59%;
268
+ }
269
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-content-section.wbcr-fullwidth {
270
+ width: 100%;
271
+ }
272
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-content-section .nav-tab-wrapper {
273
+ margin-top: 15px;
274
+ }
275
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-content-section .wbcr-factory-content {
276
+ background: #f7f7f7;
277
+ padding: 0 0 20px 0;
278
+ border: 1px solid #dad8d8;
279
+ box-shadow: -1px 0px 1px rgba(0, 0, 0, 0.1);
280
+ }
281
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-content-section .wbcr-factory-content > form {
282
+ padding-top: 0 !important;
283
+ }
284
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-right-sidebar-section {
285
+ width: 40%;
286
+ padding: 20px;
287
+ margin: -40px 0 -20px;
288
+ background-color: #f9f9f9;
289
+ box-shadow: -1px 1px 5px rgba(0, 0, 0, 0.1);
290
+ }
291
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-right-sidebar-section .wbcr-factory-sidebar-widget {
292
+ margin: 0 0 20px;
293
+ }
294
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget {
295
+ display: inline-block;
296
+ min-height: 230px;
297
+ width: 100%;
298
+ margin-top: 20px;
299
+ background-color: #fff;
300
+ padding: 20px 15px;
301
+ vertical-align: top;
302
+ }
303
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget.wbcr-factory-hide {
304
+ display: none;
305
+ }
306
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget.wbcr-factory-warning {
307
+ background: #fff4d0;
308
+ }
309
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget.wbcr-factory-danger {
310
+ background: #e2ffc0;
311
+ }
312
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget.wbcr-factory-success {
313
+ background: #ffebe9;
314
+ }
315
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget .wbcr-factory-hint-icon-simple {
316
+ display: inline-block;
317
+ width: 16px;
318
+ height: 16px;
319
+ line-height: 13px;
320
+ padding: 0;
321
+ font-size: 11px;
322
+ text-align: center;
323
+ color: #fff;
324
+ background: #E91E63;
325
+ border-radius: 3px;
326
+ }
327
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget .wbcr-factory-simple-grey {
328
+ background: #E91E63;
329
+ }
330
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget .wbcr-factory-simple-red {
331
+ background: #9e9e9e;
332
+ }
333
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget .wbcr-factory-simple-green {
334
+ background: #8bc34a;
335
+ }
336
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget .wbcr-factory-icon-5stars {
337
+ display: block;
338
+ width: 80px;
339
+ height: 17px;
340
+ background: url('../img/5-stars22.png') no-repeat;
341
+ vertical-align: middle;
342
+ margin-bottom: 5px;
343
+ }
344
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget #wbcr-factory-paypal-donation-form input[type="image"] {
345
+ display: block;
346
+ margin: 30px auto 0;
347
+ outline: none;
348
+ }
349
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget #wbcr-factory-paypal-donation-form input[type="image"] :focus,
350
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget #wbcr-factory-paypal-donation-form input[type="image"] :active {
351
+ box-shadow: none;
352
+ }
353
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-sidebar-widget #wbcr-factory-paypal-donation-form .wbcr-factory-donation-price {
354
+ font-size: 50px;
355
+ margin-top: 30px;
356
+ text-align: center;
357
+ font-weight: 600;
358
+ color: #8BC34A;
359
+ }
360
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-feature-box {
361
+ min-height: 240px;
362
+ margin-bottom: 20px;
363
+ text-align: center;
364
+ background: #fdfcf7;
365
+ padding: 30px;
366
+ border: 1px solid #f3f1e7;
367
+ }
368
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-feature-box .dashicons {
369
+ width: 50px;
370
+ height: 50px;
371
+ font-size: 50px;
372
+ color: #FFC107;
373
+ line-height: normal;
374
+ }
375
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-feature-box h3 {
376
+ color: #7b6111;
377
+ }
378
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-feature-box p {
379
+ color: #9e9e9e;
380
+ }
381
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-buttons-wrap {
382
+ margin-top: 20px;
383
+ text-align: center;
384
+ }
385
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-premium-button {
386
+ display: inline-block;
387
+ padding: 20px 60px;
388
+ background-color: #FFC107;
389
+ color: #866605;
390
+ text-decoration: none;
391
+ text-transform: uppercase;
392
+ font-weight: bold;
393
+ transition: background-color 0.3s, border-color 0.3s, color 0.3s, opacity 0.3s;
394
+ }
395
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-more_features .wbcr-factory-premium-button:hover {
396
+ background-color: #ffce3a;
397
+ }
398
+ #WBCR .wbcr-factory-pages-407-impressive-page-template #wbcr-factory-confirm-dialog {
399
+ padding: 20px;
400
+ background: #ffffff;
401
+ }
402
+ #WBCR .wbcr-factory-pages-407-impressive-page-template #wbcr-factory-confirm-dialog .updated,
403
+ #WBCR .wbcr-factory-pages-407-impressive-page-template #wbcr-factory-confirm-dialog .alert {
404
+ display: none;
405
+ }
406
+ #WBCR .wbcr-factory-pages-407-impressive-page-template #wbcr-factory-confirm-dialog h2 {
407
+ font-size: 18px;
408
+ margin-top: 10px;
409
+ }
410
+ #WBCR .wbcr-factory-pages-407-impressive-page-template #wbcr-factory-confirm-dialog .wbcr-factory-confirm-description {
411
+ padding: 10px;
412
+ background: #ffedeb;
413
+ border: 1px solid #ffdfdc;
414
+ margin: 15px 0;
415
+ }
416
+ #WBCR .wbcr-factory-pages-407-impressive-page-template #wbcr-factory-confirm-dialog .wbcr-factory-confirm-hint {
417
+ margin-bottom: 15px;
418
+ color: #7b7b7b;
419
+ }
420
+ @media screen and (max-width: 950px) {
421
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar {
422
+ width: 70px;
423
+ }
424
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-left-navigation-bar ul .wbcr-factory-nav-tab a {
425
+ font-size: 0;
426
+ }
427
+ #WBCR .wbcr-factory-pages-407-impressive-page-template .wbcr-factory-page-inner-wrap {
428
+ margin-left: 70px;
429
+ }
430
+ }
libs/factory/pages/templates/assets/css/impressive.page.template.less ADDED
@@ -0,0 +1,510 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * General styles
3
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
4
+ * @copyright Alex Kovalev 23.08.2017
5
+ */
6
+
7
+ #WBCR {
8
+ .updated, .notice, .error {
9
+ display: none !important;
10
+ }
11
+
12
+ .wbcr-factory-pages-000-impressive-page-template {
13
+ position: relative;
14
+
15
+ .wbcr-factory-color-grey {
16
+ color: #9a9a9a;
17
+ }
18
+
19
+ .wbcr-factory-orange-color {
20
+ color: #ffc107;
21
+ }
22
+
23
+ .wbcr-factory-light-orange-color {
24
+ color: #ffeb3b;
25
+ }
26
+
27
+ .form-group {
28
+ padding: 0 20px;
29
+ label {
30
+ font-weight: normal;
31
+ }
32
+ }
33
+
34
+ .form-horizontal .control-label {
35
+ max-width: 300px;
36
+ }
37
+
38
+ .factory-control-buttons {
39
+ text-align: right;
40
+ padding-right: 20px;
41
+ }
42
+
43
+ .factory-from-control-list {
44
+ label {
45
+ span {
46
+ display: inline-block;
47
+ vertical-align: bottom;
48
+ input[type="checkbox"], input[type="checkbox"]:focus {
49
+ outline: none;
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ .alert {
56
+ font-weight: bold;
57
+ margin: 0 !important;
58
+ border: 0;
59
+ border-radius: 0;
60
+ padding: 15px;
61
+
62
+ & + .wbcr-factory-page-group-header {
63
+ margin-top: 0 !important;
64
+ }
65
+
66
+ &.alert-warning {
67
+ background: #fff3d0;
68
+ }
69
+
70
+ &.alert-warning:nth-child(2n+1) {
71
+ background: #fffde9;
72
+ }
73
+
74
+ &.alert-danger {
75
+ background: #de716d;
76
+ }
77
+
78
+ &.alert-danger:nth-child(2n+1) {
79
+ background: #ec8c89;
80
+ }
81
+
82
+ &.alert-success {
83
+ background: #d0ecc4;
84
+ }
85
+
86
+ &.alert-success:nth-child(2n+1) {
87
+ background: #e0eadb;
88
+ }
89
+ }
90
+
91
+ .wbcr-factory-header {
92
+ padding: 20px 20px 40px;
93
+ }
94
+
95
+ .wbcr-factory-recomended-text {
96
+ display: block;
97
+ font-size: 11px;
98
+ font-weight: lighter;
99
+ color: #179347;
100
+ }
101
+
102
+ .wbcr-factory-options, .wbcr-factory-page {
103
+ position: relative;
104
+ background: #e6e6e6;
105
+ overflow: hidden;
106
+ //padding-left: 230px;
107
+
108
+ form.form-horizontal {
109
+ //min-height: 500px;
110
+ //position: relative;
111
+ //padding: 0 0 50px 100px;
112
+ }
113
+
114
+ &:after {
115
+ display: block;
116
+ content: '';
117
+ clear: both;
118
+ }
119
+ }
120
+
121
+ .wbcr-factory-page-group-header {
122
+ background: #efefef;
123
+ padding: 20px 0 10px 20px;
124
+ margin: 30px 0;
125
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
126
+ &:first-child {
127
+ margin-top: 0;
128
+ }
129
+ strong {
130
+ font-size: 15px;
131
+ }
132
+ p {
133
+ color: #8c8888;
134
+ font-size: 12px;
135
+ }
136
+ }
137
+
138
+ .wbcr-factory-page {
139
+ //min-height: 500px;
140
+ // padding: 80px 20px 50px 230px;
141
+ }
142
+
143
+ .wbcr-factory-page-inner-wrap {
144
+ //float: left;
145
+ //display: inline-block;
146
+ //min-height: 800px;
147
+ margin-left: 230px;
148
+ //padding: 120px 0 20px 20px;
149
+ padding: 80px 0 0 0;
150
+ vertical-align: top;
151
+ background: #fff;
152
+ //min-height: 800px;
153
+ .nav-tab-wrapper, h2.nav-tab-wrapper, h1.nav-tab-wrapper {
154
+ border: 0;
155
+ }
156
+ .nav-tab-active {
157
+ background: #efefef;
158
+ }
159
+ .nav-tab:first-child {
160
+ margin-left: 80px !important;
161
+ }
162
+ .nav-tab:hover {
163
+ background: #f7f7f7;
164
+ }
165
+ .nav-tab {
166
+ &:active, &:focus {
167
+ box-shadow: none;
168
+ outline: none;
169
+ }
170
+ }
171
+ }
172
+
173
+ .wbcr-factory-page-header {
174
+ position: absolute;
175
+ z-index: 13;
176
+ top: 0;
177
+ left: 0;
178
+ right: 0;
179
+ overflow: hidden;
180
+ background-color: #32373c;
181
+ color: #fff;
182
+ border-radius: 5px 5px 0 0;
183
+
184
+ .wbcr-factory-header-logo {
185
+ float: left;
186
+ padding: 25px 0;
187
+ font-size: 20px;
188
+ line-height: 30px;
189
+ font-weight: 400;
190
+ text-align: center;
191
+ //width: 170px;
192
+ background-color: #464b50;
193
+ color: #ccc;
194
+ padding-left: 25px;
195
+ margin-right: 10px;
196
+ background: none;
197
+ }
198
+
199
+ .wbcr-factory-header-title {
200
+ display: inline-block;
201
+ vertical-align: middle;
202
+ h2 {
203
+ font-size: 18px;
204
+ line-height: 30px;
205
+ font-weight: 300;
206
+ margin-top: 26px;
207
+ padding: 0 !important;
208
+ //margin: 0 !important;
209
+ overflow: hidden;
210
+ white-space: nowrap;
211
+ text-overflow: ellipsis;
212
+ color: #fff;
213
+ }
214
+ }
215
+
216
+ .wbcr-factory-control {
217
+ position: relative;
218
+ float: right;
219
+ margin: 12px;
220
+
221
+ input[type="submit"] {
222
+ display: inline-block;
223
+ vertical-align: top;
224
+ font-size: 13px;
225
+ font-weight: 600;
226
+ line-height: 20px;
227
+ text-transform: uppercase;
228
+ margin: 10px 0 0;
229
+ padding: 8px 30px;
230
+ cursor: pointer;
231
+ position: relative;
232
+ overflow: hidden;
233
+ border: none;
234
+ border-radius: 50px;
235
+ box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.08) inset;
236
+ background-color: #f1f1f1;
237
+ color: inherit;
238
+ transition: background-color 0.3s, border-color 0.3s, color 0.3s, opacity 0.3s;
239
+ text-align: center;
240
+ outline: none;
241
+ z-index: 3;
242
+
243
+ &.wbcr-factory-type-save {
244
+ box-shadow: none;
245
+ min-width: 200px;
246
+ background-color: #8bc34a;
247
+ color: #fff;
248
+ &:hover {
249
+ background: #9dbb7b;
250
+ color: #fff;
251
+ }
252
+ &:active {
253
+ box-shadow: inset -1px 1px 1px rgba(0, 0, 0, 0.3);
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ }
260
+
261
+ .wbcr-factory-left-navigation-bar {
262
+ //display: inline-block;
263
+ float: left;
264
+ vertical-align: top;
265
+ width: 230px;
266
+ background: #e6e6e6;
267
+
268
+ ul {
269
+ padding: 0;
270
+ margin-bottom: 0;
271
+ margin-top: 80px;
272
+ .wbcr-factory-nav-tab {
273
+ display: block;
274
+ background: #efefef;
275
+ //padding: 15px 20px;
276
+ margin: 1px 0;
277
+ a {
278
+ display: block;
279
+ width: 100%;
280
+ padding: 20px 20px;
281
+ font-size: 12px;
282
+ color: #9a9a9a;
283
+ text-decoration: none;
284
+ text-transform: uppercase;
285
+ &:hover {
286
+ background: #f7f6f6;
287
+ }
288
+ &, &:active, &:hover, &:active, &:focus {
289
+ outline: 0 !important;
290
+ box-shadow: none !important;
291
+ }
292
+
293
+ }
294
+ &.wbcr-factory-active-tab {
295
+ background: #fff;
296
+ a {
297
+ color: #222;
298
+ }
299
+ }
300
+ }
301
+ }
302
+ }
303
+
304
+ /**
305
+ Content sections
306
+ */
307
+ .wbcr-factory-content-section, .wbcr-factory-right-sidebar-section {
308
+ display: inline-block;
309
+ vertical-align: top;
310
+ }
311
+
312
+ .wbcr-factory-content-section {
313
+ width: 59%;
314
+ &.wbcr-fullwidth {
315
+ width: 100%;
316
+ }
317
+ .nav-tab-wrapper {
318
+ margin-top: 15px;
319
+ }
320
+ .wbcr-factory-content {
321
+ background: #f7f7f7;
322
+ padding: 0 0 20px 0;
323
+ border: 1px solid #dad8d8;
324
+ box-shadow: -1px 0px 1px rgba(0, 0, 0, 0.1);
325
+ & > form {
326
+ padding-top: 0 !important;
327
+ }
328
+ }
329
+ }
330
+
331
+ .wbcr-factory-right-sidebar-section {
332
+ width: 40%;
333
+ padding: 20px;
334
+ margin: -40px 0 -20px;
335
+ background-color: #f9f9f9;
336
+ box-shadow: -1px 1px 5px rgba(0, 0, 0, 0.1);
337
+
338
+ .wbcr-factory-sidebar-widget {
339
+ margin: 0 0 20px;
340
+ }
341
+ }
342
+
343
+ /**
344
+ Widget in the sidebar of the plugin
345
+ */
346
+ .wbcr-factory-sidebar-widget {
347
+ display: inline-block;
348
+ min-height: 230px;
349
+ width: 100%;
350
+ margin-top: 20px;
351
+ background-color: #fff;
352
+ padding: 20px 15px;
353
+ vertical-align: top;
354
+
355
+ &.wbcr-factory-hide {
356
+ display: none;
357
+ }
358
+
359
+ &.wbcr-factory-warning {
360
+ background: #fff4d0;
361
+ }
362
+
363
+ &.wbcr-factory-danger {
364
+ background: #e2ffc0;
365
+ }
366
+
367
+ &.wbcr-factory-success {
368
+ background: #ffebe9;
369
+ }
370
+
371
+ .wbcr-factory-hint-icon-simple {
372
+ display: inline-block;
373
+ width: 16px;
374
+ height: 16px;
375
+ line-height: 13px;
376
+ padding: 0;
377
+ font-size: 11px;
378
+ text-align: center;
379
+ color: #fff;
380
+ background: #E91E63;
381
+ border-radius: 3px;
382
+ }
383
+ .wbcr-factory-simple-grey {
384
+ background: #E91E63;
385
+ }
386
+ .wbcr-factory-simple-red {
387
+ background: #9e9e9e;
388
+ }
389
+ .wbcr-factory-simple-green {
390
+ background: #8bc34a;
391
+ }
392
+
393
+ .wbcr-factory-icon-5stars {
394
+ display: block;
395
+ width: 80px;
396
+ height: 17px;
397
+ background: url('../img/5-stars22.png') no-repeat;
398
+ vertical-align: middle;
399
+ margin-bottom: 5px;
400
+ }
401
+
402
+ #wbcr-factory-paypal-donation-form {
403
+ input[type="image"] {
404
+ display: block;
405
+ margin: 30px auto 0;
406
+ outline: none;
407
+ :focus, :active {
408
+ box-shadow: none;
409
+ }
410
+ }
411
+ .wbcr-factory-donation-price {
412
+ font-size: 50px;
413
+ margin-top: 30px;
414
+ text-align: center;
415
+ font-weight: 600;
416
+ color: #8BC34A;
417
+ }
418
+ }
419
+ }
420
+
421
+ .wbcr-factory-page-more_features {
422
+ .wbcr-factory-feature-box {
423
+ //margin: 20px 0 0 20px;
424
+ min-height: 240px;
425
+ margin-bottom: 20px;
426
+ text-align: center;
427
+ background: #fdfcf7;
428
+ padding: 30px;
429
+ border: 1px solid #f3f1e7;
430
+ .dashicons {
431
+ width: 50px;
432
+ height: 50px;
433
+ font-size: 50px;
434
+ color: #FFC107;
435
+ line-height: normal;
436
+ }
437
+ h3 {
438
+ color: #7b6111;
439
+ }
440
+ p {
441
+ color: #9e9e9e;
442
+ }
443
+ }
444
+
445
+ .wbcr-factory-buttons-wrap {
446
+ margin-top: 20px;
447
+ text-align: center;
448
+ }
449
+
450
+ .wbcr-factory-premium-button {
451
+ display: inline-block;
452
+ padding: 20px 60px;
453
+ background-color: #FFC107;
454
+ color: #866605;
455
+ text-decoration: none;
456
+ text-transform: uppercase;
457
+ font-weight: bold;
458
+ transition: background-color 0.3s, border-color 0.3s, color 0.3s, opacity 0.3s;
459
+ &:hover {
460
+ background-color: #ffce3a
461
+ }
462
+ }
463
+ }
464
+
465
+ #wbcr-factory-confirm-dialog {
466
+ padding: 20px;
467
+ background: #ffffff;
468
+
469
+ .updated, .alert {
470
+ display: none;
471
+ }
472
+ h2 {
473
+ font-size: 18px;
474
+ margin-top: 10px;
475
+ }
476
+ .wbcr-factory-confirm-description {
477
+ padding: 10px;
478
+ background: #ffedeb;
479
+ border: 1px solid #ffdfdc;
480
+ margin: 15px 0;
481
+ }
482
+ .wbcr-factory-confirm-hint {
483
+ margin-bottom: 15px;
484
+ color: #7b7b7b;
485
+ }
486
+ }
487
+ }
488
+ }
489
+
490
+ @media screen and (max-width: 950px) {
491
+ #WBCR {
492
+ .wbcr-factory-pages-000-impressive-page-template {
493
+ .wbcr-factory-left-navigation-bar {
494
+ width: 70px;
495
+
496
+ ul {
497
+ .wbcr-factory-nav-tab {
498
+ a {
499
+ font-size: 0;
500
+ }
501
+ }
502
+ }
503
+ }
504
+ .wbcr-factory-page-inner-wrap {
505
+ margin-left: 70px;
506
+ }
507
+
508
+ }
509
+ }
510
+ }
libs/factory/pages/templates/assets/img/5-stars22.png ADDED
Binary file
libs/factory/pages/templates/assets/img/paypal-donate.png ADDED
Binary file
libs/factory/pages/templates/assets/img/webcraftic-plugin-icon.png ADDED
Binary file
libs/factory/pages/templates/impressive-page.class.php ADDED
@@ -0,0 +1,908 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Impressive page themplate class
4
+ *
5
+ * @author Alex Kovalev <alex.kovalevv@gmail.com>
6
+ * @copyright (c) 2018, Webcraftic Ltd
7
+ *
8
+ * @package factory-pages
9
+ * @since 1.0.0
10
+ */
11
+
12
+ // Exit if accessed directly
13
+ if( !defined('ABSPATH') ) {
14
+ exit;
15
+ }
16
+
17
+ if( !class_exists('Wbcr_FactoryPages407_ImpressiveThemplate') ) {
18
+ /**
19
+ * Class Wbcr_FactoryPages407_ImpressiveThemplate
20
+ *
21
+ * @method string getInfoWidget() - get widget content information
22
+ * @method string getRatingWidget(array $args = array()) - get widget content rating
23
+ * @method string getDonateWidget() - get widget content donate
24
+ */
25
+ abstract class Wbcr_FactoryPages407_ImpressiveThemplate extends Wbcr_FactoryPages407_AdminPage {
26
+
27
+ //public $menu_target = 'options-general.php';
28
+
29
+ /**
30
+ * @var bool
31
+ */
32
+ public $internal = true;
33
+
34
+ /**
35
+ * Тип страницы
36
+ * options - предназначена для создании страниц с набором опций и настроек.
37
+ * page - произвольный контент, любой html код
38
+ *
39
+ * @var string
40
+ */
41
+ public $type = 'options';
42
+
43
+ /**
44
+ * ID родительской страницы, если указан, тогда эта страница будет внутренней странтцей
45
+ *
46
+ * @var string
47
+ */
48
+ public $page_parent_page;
49
+
50
+ /**
51
+ * Иконка страницы
52
+ * Полный список иконок смотреть тут:
53
+ * https://developer.wordpress.org/resource/dashicons/#admin-network
54
+ *
55
+ * @var string
56
+ */
57
+ public $page_menu_dashicon;
58
+
59
+ /**
60
+ * Позиция закладки в меню плагина.
61
+ * 0 - в самом конце, 100 - в самом начале
62
+ *
63
+ * @var int
64
+ */
65
+ public $page_menu_position = 10;
66
+
67
+ /**
68
+ * Заголовок страницы, также использует в меню, как название закладки
69
+ *
70
+ * @var bool
71
+ */
72
+ public $show_page_title = true;
73
+
74
+ /**
75
+ * Показывать правый сайдбар?
76
+ * Сайдбар будет показан на внутренних страницах шаблона.
77
+ *
78
+ * @var bool
79
+ */
80
+ public $show_right_sidebar_in_options = false;
81
+
82
+ /**
83
+ * Показывать нижний сайдбар?
84
+ * Сайдбар будет показан на внутренних страницах шаблона.
85
+ *
86
+ * @var bool
87
+ */
88
+ public $show_bottom_sidebar = true;
89
+
90
+ /**
91
+ * @param Wbcr_Factory406_Plugin $plugin
92
+ */
93
+ public function __construct(Wbcr_Factory406_Plugin $plugin)
94
+ {
95
+ $this->menuIcon = FACTORY_PAGES_407_URL . '/templates/assets/img/webcraftic-plugin-icon.png';
96
+ $this->plugin = $plugin;
97
+
98
+ parent::__construct($plugin);
99
+
100
+ global $factory_impressive_page_menu;
101
+
102
+ $dashicon = (!empty($this->page_menu_dashicon))
103
+ ? ' ' . $this->page_menu_dashicon
104
+ : '';
105
+
106
+ $this->title_plugin_action_link = __('Settings', 'wbcr_factory_pages_407');
107
+
108
+ //if( $this->type == 'options' ) {
109
+ //$this->show_right_sidebar_in_options = true;
110
+ //$this->show_bottom_sidebar = false;
111
+ //}
112
+
113
+ $factory_impressive_page_menu[$this->getMenuScope()][$this->getResultId()] = array(
114
+ 'type' => $this->type, // page, options
115
+ 'url' => $this->getBaseUrl(),
116
+ 'title' => '<span class="dashicons' . $dashicon . '"></span> ' . $this->getMenuTitle(),
117
+ 'position' => $this->page_menu_position,
118
+ 'parent' => $this->page_parent_page
119
+ );
120
+ }
121
+
122
+ public function __call($name, $arguments)
123
+ {
124
+ if( substr($name, 0, 3) == 'get' ) {
125
+ $called_method_name = 'show' . substr($name, 3);
126
+ if( method_exists($this, $called_method_name) ) {
127
+ ob_start();
128
+
129
+ $this->$called_method_name($arguments);
130
+ $content = ob_get_contents();
131
+ ob_end_clean();
132
+
133
+ return $content;
134
+ }
135
+ }
136
+
137
+ return null;
138
+ }
139
+
140
+ /**
141
+ * Requests assets (js and css) for the page.
142
+ *
143
+ * @see FactoryPages407_AdminPage
144
+ *
145
+ * @since 1.0.0
146
+ * @return void
147
+ */
148
+ public function assets($scripts, $styles)
149
+ {
150
+
151
+ $this->scripts->request('jquery');
152
+
153
+ $this->scripts->request(array(
154
+ 'control.checkbox',
155
+ 'control.dropdown',
156
+ 'bootstrap.tooltip'
157
+ ), 'bootstrap');
158
+
159
+ $this->styles->request(array(
160
+ 'bootstrap.core',
161
+ 'bootstrap.form-group',
162
+ 'bootstrap.separator',
163
+ 'control.dropdown',
164
+ 'control.checkbox'
165
+ ), 'bootstrap');
166
+
167
+ $this->styles->add(FACTORY_PAGES_407_URL . '/templates/assets/css/impressive.page.template.css');
168
+ //$this->styles->add('https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css');
169
+ }
170
+
171
+ /**
172
+ * @return string
173
+ */
174
+ public function getMenuTitle()
175
+ {
176
+ return $this->menu_title;
177
+ }
178
+
179
+ /**
180
+ * @return string
181
+ */
182
+ public function getPageTitle()
183
+ {
184
+ return $this->getMenuTitle();
185
+ }
186
+
187
+ /**
188
+ * @return string
189
+ */
190
+ public function getPluginTitle()
191
+ {
192
+ return $this->plugin->getPluginTitle();
193
+ }
194
+
195
+ /**
196
+ * @return string
197
+ */
198
+ public function getPageUrl()
199
+ {
200
+ return $this->getBaseUrl();
201
+ }
202
+
203
+ /**
204
+ * Get options with namespace
205
+ * @param $option_name
206
+ * @param bool $default
207
+ * @return mixed|void
208
+ */
209
+ public function getOption($option_name, $default = false)
210
+ {
211
+ return $this->plugin->getOption($option_name, $default);
212
+ }
213
+
214
+ /**
215
+ * @return string
216
+ */
217
+ protected function getBaseUrl()
218
+ {
219
+ $result_id = $this->getResultId();
220
+
221
+ if( $this->menu_target ) {
222
+ return add_query_arg(array('page' => $result_id), admin_url($this->menu_target));
223
+ } else {
224
+ return add_query_arg(array('page' => $result_id), admin_url('admin.php'));
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Shows a page or options
230
+ *
231
+ * @sinve 1.0.0
232
+ * @return void
233
+ */
234
+ public function indexAction()
235
+ {
236
+ global $factory_impressive_page_menu;
237
+
238
+ if( 'options' === $factory_impressive_page_menu[$this->getMenuScope()][$this->getResultId()]['type'] ) {
239
+ $this->showOptions();
240
+ } else {
241
+ $this->showPage();
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Flush cache and rules
247
+ *
248
+ * @sinve 4.0.0
249
+ * @return void
250
+ */
251
+ public function flushCacheAndRulesAction()
252
+ {
253
+ check_admin_referer('wbcr_factory_' . $this->getResultId() . '_flush_action');
254
+
255
+ // todo: test cache control
256
+ if( function_exists('w3tc_pgcache_flush') ) {
257
+ w3tc_pgcache_flush();
258
+ } elseif( function_exists('wp_cache_clear_cache') ) {
259
+ wp_cache_clear_cache();
260
+ } elseif( function_exists('rocket_clean_files') ) {
261
+ rocket_clean_files(esc_url($_SERVER['HTTP_REFERER']));
262
+ } else if( isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache') ) {
263
+ $GLOBALS['wp_fastest_cache']->deleteCache();
264
+ }
265
+
266
+ wbcr_factory_406_do_action_deprecated('wbcr_factory_406_imppage_flush_cache', array(
267
+ $this->plugin->getPluginName(),
268
+ $this->getResultId()
269
+ ), '4.0.1', 'wbcr_factory_406_imppage_after_form_save');
270
+
271
+ /**
272
+ * @since 4.0.1
273
+ */
274
+ do_action('wbcr_factory_406_imppage_after_form_save', $this->plugin, $this);
275
+
276
+ $this->afterFormSave();
277
+
278
+ $this->redirectToAction('index', apply_filters('wbcr_factory_406_imppage_after_form_save_redirect_args', array(
279
+ $this->plugin->getPluginName() . '_saved' => 1
280
+ )));
281
+ }
282
+
283
+
284
+ /**
285
+ * Вызывается всегда при загрузке страницы, перед опциями формы с типом страницы options
286
+ */
287
+ protected function warningNotice()
288
+ {
289
+ /*if( WP_CACHE ) {
290
+ $this->printWarningNotice(__("It seems that a caching/performance plugin is active on this site. Please manually invalidate that plugin's cache after making any changes to the settings below.", 'wbcr_factory_pages_407'));
291
+ }*/
292
+ // Метод предназначен для вызова в дочернем классе
293
+ }
294
+
295
+ /**
296
+ * Вызывается всегда при загрузке страницы, перед опциями формы с типом страницы options
297
+ *
298
+ * @since 4.0.0
299
+ * @param array $notices
300
+ * @return array
301
+ */
302
+ protected function getActionNotices($notices)
303
+ {
304
+ // Метод предназначен для вызова в дочернем классе
305
+ return $notices;
306
+ }
307
+
308
+ /**
309
+ * Вызывается перед сохранением опций формы
310
+ *
311
+ * @since 4.0.0
312
+ * @return void
313
+ */
314
+ protected function beforeFormSave()
315
+ {
316
+ // Метод предназначен для вызова в дочернем классе
317
+ }
318
+
319
+ /**
320
+ * Вызывается после сохранением опций формы, когда выполнен сброс кеша и совершен редирект
321
+ *
322
+ * @since 4.0.0
323
+ * @return void
324
+ */
325
+ protected function afterFormSave()
326
+ {
327
+ // Метод предназначен для вызова в дочернем классе
328
+ }
329
+
330
+ /**
331
+ * Вызывается в процессе выполнения сохранения, но после сохранения всех опций
332
+ *
333
+ * @since 4.0.0
334
+ * @return void
335
+ */
336
+ protected function formSaved()
337
+ {
338
+ // Метод предназначен для вызова в дочернем классе
339
+ }
340
+
341
+ public function printWarningNotice($message)
342
+ {
343
+ echo '<div class="alert alert-warning wbcr-factory-warning-notice"><p><span class="dashicons dashicons-warning"></span> ' . $message . '</p></div>';
344
+ }
345
+
346
+ public function printErrorNotice($message)
347
+ {
348
+ echo '<div class="alert alert-danger wbcr-factory-warning-notice"><p><span class="dashicons dashicons-dismiss"></span> ' . $message . '</p></div>';
349
+ }
350
+
351
+ public function printSuccessNotice($message)
352
+ {
353
+ echo '<div class="alert alert-success wbcr-factory-warning-notice"><p><span class="dashicons dashicons-plus"></span> ' . $message . '</p></div>';
354
+ }
355
+
356
+ protected function printAllNotices()
357
+ {
358
+ $this->warningNotice();
359
+ $this->showActionsNotice();
360
+
361
+ /**
362
+ * @since 4.0.1
363
+ */
364
+ do_action('wbcr_factory_pages_407_imppage_print_all_notices', $this->plugin, $this);
365
+ }
366
+
367
+ private function showActionsNotice()
368
+ {
369
+ $notices = array(
370
+ array(
371
+ 'conditions' => array(
372
+ $this->plugin->getPluginName() . '_saved' => '1'
373
+ ),
374
+ 'type' => 'success',
375
+ 'message' => __('The settings have been updated successfully!', 'wbcr_factory_pages_407') . (WP_CACHE
376
+ ? '<br>' . __("It seems that a caching/performance plugin is active on this site. Please manually invalidate that plugin's cache after making any changes to the settings below.", 'wbcr_factory_pages_407')
377
+ : '')
378
+ )
379
+ );
380
+
381
+ $notices = apply_filters('wbcr_factory_pages_407_imppage_actions_notice', $notices, $this->plugin, $this->id);
382
+ $notices = $this->getActionNotices($notices);
383
+
384
+ foreach($notices as $key => $notice) {
385
+ $show_message = true;
386
+
387
+ if( isset($notice['conditions']) && !empty($notice['conditions']) ) {
388
+ foreach($notice['conditions'] as $condition_name => $value) {
389
+ if( !isset($_REQUEST[$condition_name]) || $_REQUEST[$condition_name] != $value ) {
390
+ $show_message = false;
391
+ }
392
+ }
393
+ }
394
+ if( !$show_message ) {
395
+ continue;
396
+ }
397
+
398
+ $notice_type = isset($notice['type'])
399
+ ? $notice['type']
400
+ : 'success';
401
+
402
+ switch( $notice_type ) {
403
+ case 'success':
404
+ $this->printSuccessNotice($notice['message']);
405
+ break;
406
+ case 'danger':
407
+ $this->printErrorNotice($notice['message']);
408
+ break;
409
+ default:
410
+ $this->printWarningNotice($notice['message']);
411
+ break;
412
+ }
413
+ }
414
+ }
415
+
416
+ protected function showPageMenu()
417
+ {
418
+ global $factory_impressive_page_menu;
419
+
420
+ $page_menu = $factory_impressive_page_menu[$this->getMenuScope()];
421
+ $self_page_id = $this->getResultId();
422
+ $current_page = isset($page_menu[$self_page_id])
423
+ ? $page_menu[$self_page_id]
424
+ : null;
425
+
426
+ $parent_page_id = !empty($current_page['parent'])
427
+ ? $this->getResultId($current_page['parent'])
428
+ : null;
429
+
430
+ uasort($page_menu, array($this, 'pageMenuSort'));
431
+ ?>
432
+ <ul>
433
+ <?php foreach($page_menu as $page_screen => $page): ?>
434
+ <?php
435
+ if( !empty($page['parent']) ) {
436
+ continue;
437
+ }
438
+ $active_tab = '';
439
+ if( $page_screen == $self_page_id || $page_screen == $parent_page_id ) {
440
+ $active_tab = ' wbcr-factory-active-tab';
441
+ }
442
+ ?>
443
+ <li class="wbcr-factory-nav-tab<?= $active_tab ?>">
444
+ <a href="<?php echo $page['url'] ?>" id="<?= $page_screen ?>-tab">
445
+ <?php echo $page['title'] ?>
446
+ </a>
447
+ </li>
448
+ <?php endforeach; ?>
449
+ </ul>
450
+ <?php
451
+ }
452
+
453
+ /**
454
+ * @param int $a
455
+ * @param int $b
456
+ * @return bool
457
+ */
458
+ protected function pageMenuSort($a, $b)
459
+ {
460
+ return $a['position'] < $b['position'];
461
+ }
462
+
463
+ protected function showPageSubMenu()
464
+ {
465
+ global $factory_impressive_page_menu;
466
+ $self_page_id = $this->getResultId();
467
+ $page_menu = $factory_impressive_page_menu[$this->getMenuScope()];
468
+ $current_page = isset($page_menu[$self_page_id])
469
+ ? $page_menu[$self_page_id]
470
+ : null;
471
+
472
+ $page_submenu = array();
473
+ foreach($page_menu as $page_screen => $page) {
474
+ if( !empty($page['parent']) ) {
475
+ $page_parent_id = $this->getResultId($page['parent']);
476
+
477
+ if( isset($page_menu[$page_parent_id]) ) {
478
+ $page['title'] = strip_tags($page['title']);
479
+ $page_submenu[$page_parent_id][$page_screen] = $page;
480
+ }
481
+ }
482
+ }
483
+
484
+ if( empty($page_submenu) ) {
485
+ return;
486
+ }
487
+
488
+ $get_menu_id = null;
489
+ $has_parent = !empty($current_page) && !empty($current_page['parent']);
490
+ $parent_page_id = $has_parent
491
+ ? $this->getResultId($current_page['parent'])
492
+ : null;
493
+
494
+ if( ($has_parent && isset($page_submenu[$parent_page_id])) ) {
495
+ $get_menu_id = $parent_page_id;
496
+ } else if( !$has_parent && isset($page_submenu[$self_page_id]) ) {
497
+ $get_menu_id = $self_page_id;
498
+ }
499
+
500
+ if( !isset($page_submenu[$get_menu_id]) ) {
501
+ return;
502
+ }
503
+
504
+ $unshift = array();
505
+ if( isset($page_menu[$get_menu_id]) ) {
506
+ $page_menu[$get_menu_id]['title'] = strip_tags($page_menu[$get_menu_id]['title']);
507
+
508
+ $unshift[$get_menu_id][$get_menu_id] = $page_menu[$get_menu_id];
509
+ $page_submenu[$get_menu_id] = $unshift[$get_menu_id] + $page_submenu[$get_menu_id];
510
+ }
511
+
512
+ ?>
513
+ <h2 class="nav-tab-wrapper wp-clearfix">
514
+ <?php foreach((array)$page_submenu[$get_menu_id] as $page_screen => $page): ?>
515
+ <?php
516
+ $active_tab = '';
517
+ if( $page_screen == $this->getResultId() ) {
518
+ $active_tab = ' nav-tab-active';
519
+ }
520
+ ?>
521
+ <a href="<?php echo $page['url'] ?>" id="<?= esc_attr($page_screen) ?>-tab" class="nav-tab<?= esc_attr($active_tab) ?>">
522
+ <?php echo $page['title'] ?>
523
+ </a>
524
+ <?php endforeach; ?>
525
+ </h2>
526
+ <?php
527
+ }
528
+
529
+ protected function showHeader()
530
+ {
531
+ ?>
532
+ <div class="wbcr-factory-page-header">
533
+ <div class="wbcr-factory-header-logo"><?= $this->getPluginTitle(); ?>
534
+ <span class="version"><?= $this->plugin->getPluginVersion() ?> </span>
535
+ <?php if( $this->show_page_title ): ?><span class="dash">—</span><?php endif; ?>
536
+ </div>
537
+ <?php if( $this->show_page_title ): ?>
538
+ <div class="wbcr-factory-header-title">
539
+ <h2><?php _e('Page') ?>: <?= $this->getPageTitle() ?></h2>
540
+ </div>
541
+ <?php endif; ?>
542
+ <?php if( $this->type == 'options' ): ?>
543
+ <div class="wbcr-factory-control">
544
+ <input name="<?= $this->plugin->getPluginName() ?>_save_action" class="wbcr-factory-type-save" type="submit" value="<?php _e('Save settings', 'wbcr_factory_pages_407'); ?>">
545
+ <?php wp_nonce_field('wbcr_factory_' . $this->getResultId() . '_save_action'); ?>
546
+ </div><?php endif; ?>
547
+ </div>
548
+ <?php
549
+ }
550
+
551
+ protected function showRightSidebar()
552
+ {
553
+ $widgets = $this->getPageWidgets('right');
554
+
555
+ if( empty($widgets) ) {
556
+ return;
557
+ }
558
+
559
+ foreach($widgets as $widget_content):
560
+ echo $widget_content;
561
+ endforeach;
562
+ }
563
+
564
+ protected function showBottomSidebar()
565
+ {
566
+ $widgets = $this->getPageWidgets('bottom');
567
+
568
+ if( empty($widgets) ) {
569
+ return;
570
+ }
571
+ ?>
572
+ <div class="row">
573
+ <div class="wbcr-factory-top-sidebar">
574
+ <?php foreach($widgets as $widget_content): ?>
575
+ <div class="col-sm-4">
576
+ <?= $widget_content ?>
577
+ </div>
578
+ <?php endforeach; ?>
579
+ </div>
580
+ <?php
581
+ }
582
+
583
+ protected function getPageWidgets($position = 'bottom')
584
+ {
585
+ wbcr_factory_406_apply_filters_deprecated('wbcr_factory_pages_407_imppage_right_sidebar_widgets', array(
586
+ array(
587
+ 'info_widget' => $this->getInfoWidget(),
588
+ 'rating_widget' => $this->getRatingWidget(),
589
+ 'donate_widget' => $this->getDonateWidget()
590
+ ),
591
+ $this->getResultId()
592
+ ), '4.0.1', 'wbcr_factory_pages_407_imppage_get_widgets');
593
+
594
+ wbcr_factory_406_apply_filters_deprecated('wbcr_factory_pages_407_imppage_bottom_sidebar_widgets', array(
595
+ array(
596
+ 'info_widget' => $this->getInfoWidget(),
597
+ 'rating_widget' => $this->getRatingWidget(),
598
+ 'donate_widget' => $this->getDonateWidget()
599
+ ),
600
+ $this->getResultId()
601
+ ), '4.0.1', 'wbcr_factory_pages_407_imppage_get_widgets');
602
+
603
+ return apply_filters('wbcr_factory_pages_407_imppage_get_widgets', array(
604
+ 'info_widget' => $this->getInfoWidget(),
605
+ 'rating_widget' => $this->getRatingWidget(),
606
+ 'donate_widget' => $this->getDonateWidget()
607
+ ), $position, $this->plugin, $this);
608
+ }
609
+
610
+ /**
611
+ *
612
+ */
613
+ protected function showOptions()
614
+ {
615
+
616
+ global $factory_impressive_page_menu;
617
+
618
+ $form = new Wbcr_FactoryForms407_Form(array(
619
+ 'scope' => rtrim($this->plugin->getPrefix(), '_'),
620
+ 'name' => $this->getResultId() . "-options"
621
+ ), $this->plugin);
622
+
623
+ $form->setProvider(new Wbcr_FactoryForms407_OptionsValueProvider($this->plugin));
624
+
625
+ $options = $this->getOptions();
626
+
627
+ if( isset($options[0]) && isset($options[0]['items']) && is_array($options[0]['items']) ) {
628
+
629
+ /*array_unshift($options[0]['items'], array(
630
+ 'type' => 'html',
631
+ 'html' => array($this, 'printAllNotices')
632
+ ));*/
633
+
634
+ foreach($options[0]['items'] as $key => $value) {
635
+
636
+ if( $value['type'] == 'div' ) {
637
+ if( isset($options[0]['items'][$key]['items']) && !empty($options[0]['items'][$key]['items']) ) {
638
+ foreach($options[0]['items'][$key]['items'] as $group_key => $group_value) {
639
+ $options[0]['items'][$key]['items'][$group_key]['layout']['column-left'] = '6';
640
+ $options[0]['items'][$key]['items'][$group_key]['layout']['column-right'] = '6';
641
+ }
642
+
643
+ continue;
644
+ }
645
+ }
646
+
647
+ if( in_array($value['type'], array(
648
+ 'checkbox',
649
+ 'textarea',
650
+ 'integer',
651
+ 'textbox',
652
+ 'dropdown',
653
+ 'list'
654
+ )) ) {
655
+ $options[0]['items'][$key]['layout']['column-left'] = '6';
656
+ $options[0]['items'][$key]['layout']['column-right'] = '6';
657
+ }
658
+ }
659
+ }
660
+
661
+ $form->add($options);
662
+
663
+ if( isset($_POST[$this->plugin->getPluginName() . '_save_action']) ) {
664
+
665
+ check_admin_referer('wbcr_factory_' . $this->getResultId() . '_save_action');
666
+
667
+ if( !current_user_can('administrator') && !current_user_can($this->capabilitiy) ) {
668
+ wp_die(__('You do not have permission to edit page.', 'wbcr_factory_pages_407'));
669
+ exit;
670
+ }
671
+
672
+ wbcr_factory_406_do_action_deprecated('wbcr_factory_406_imppage_before_save', array(
673
+ $form,
674
+ $this->plugin->getPluginName()
675
+ ), '4.0.1', 'wbcr_factory_406_imppage_before_form_save');
676
+
677
+ do_action('wbcr_factory_406_imppage_before_form_save', $form, $this->plugin, $this);
678
+
679
+ $this->beforeFormSave();
680
+
681
+ $form->save();
682
+
683
+ wbcr_factory_406_do_action_deprecated('wbcr_factory_406_imppage_saved', array(
684
+ $form,
685
+ $this->plugin->getPluginName()
686
+ ), '4.0.1', 'wbcr_factory_406_imppage_form_saved');
687
+
688
+ do_action('wbcr_factory_406_imppage_form_saved', $form, $this->plugin, $this);
689
+
690
+ $this->formSaved();
691
+
692
+ $this->redirectToAction('flush-cache-and-rules', array(
693
+ '_wpnonce' => wp_create_nonce('wbcr_factory_' . $this->getResultId() . '_flush_action')
694
+ ));
695
+ }
696
+
697
+ ?>
698
+ <div id="WBCR" class="wrap">
699
+ <div class="wbcr-factory-pages-407-impressive-page-template factory-bootstrap-406 factory-fontawesome-000">
700
+ <div class="wbcr-factory-options wbcr-factory-options-<?= esc_attr($this->id) ?>">
701
+ <div class="wbcr-factory-left-navigation-bar">
702
+ <?php $this->showPageMenu() ?>
703
+ </div>
704
+ <?php
705
+ $min_height = 0;
706
+ foreach($factory_impressive_page_menu[$this->getMenuScope()] as $page) {
707
+ if( !isset($page['parent']) || empty($page['parent']) ) {
708
+ $min_height += 61;
709
+ }
710
+ }
711
+ ?>
712
+ <div class="wbcr-factory-page-inner-wrap">
713
+ <div class="wbcr-factory-content-section<?php if( !$this->show_right_sidebar_in_options ): echo ' wbcr-fullwidth'; endif ?>">
714
+ <?php $this->showPageSubMenu() ?>
715
+ <div class="wbcr-factory-content" style="min-height:<?= $min_height ?>px">
716
+ <form method="post" class="form-horizontal">
717
+ <?php $this->showHeader(); ?>
718
+ <?php $this->printAllNotices(); ?>
719
+ <?php $form->html(); ?>
720
+ </form>
721
+ </div>
722
+ </div>
723
+ <?php if( $this->show_right_sidebar_in_options ): ?>
724
+ <div class="wbcr-factory-right-sidebar-section">
725
+ <?php $this->showRightSidebar(); ?>
726
+ </div>
727
+ <?php endif; ?>
728
+ </div>
729
+ </div>
730
+
731
+ <?php
732
+ if( $this->show_bottom_sidebar ) {
733
+ $this->showBottomSidebar();
734
+ }
735
+ ?>
736
+
737
+ <div class="clearfix"></div>
738
+ </div>
739
+ </div>
740
+ </div>
741
+ <?php
742
+ }
743
+
744
+ protected function showPage()
745
+ {
746
+ global $factory_impressive_page_menu;
747
+ ?>
748
+ <div id="WBCR" class="wrap">
749
+ <div class="wbcr-factory-pages-407-impressive-page-template factory-bootstrap-406 factory-fontawesome-000">
750
+ <div class="wbcr-factory-page wbcr-factory-page-<?= $this->id ?>">
751
+ <?php $this->showHeader(); ?>
752
+
753
+ <div class="wbcr-factory-left-navigation-bar">
754
+ <?php $this->showPageMenu() ?>
755
+ </div>
756
+ <?php
757
+ $min_height = 0;
758
+ foreach($factory_impressive_page_menu[$this->getMenuScope()] as $page) {
759
+ if( !isset($page['parent']) || empty($page['parent']) ) {
760
+ $min_height += 61;
761
+ }
762
+ }
763
+ ?>
764
+ <div class="wbcr-factory-page-inner-wrap">
765
+ <div class="wbcr-factory-content-section<?php if( !$this->show_right_sidebar_in_options ): echo ' wbcr-fullwidth'; endif ?>">
766
+ <?php $this->showPageSubMenu() ?>
767
+ <div class="wbcr-factory-content" style="min-height:<?= $min_height ?>px">
768
+ <?php $this->printAllNotices(); ?>
769
+ <?php $this->showPageContent() ?>
770
+ </div>
771
+ </div>
772
+ </div>
773
+ </div>
774
+ <div class="clearfix"></div>
775
+ <?php $this->showBottomSidebar(); ?>
776
+ </div>
777
+ </div>
778
+ <?php
779
+ }
780
+
781
+ /**
782
+ * @return void
783
+ */
784
+ public function showPageContent()
785
+ {
786
+ // используется в классе потомке
787
+ }
788
+
789
+
790
+ public function showInfoWidget()
791
+ {
792
+ ?>
793
+ <div class="wbcr-factory-sidebar-widget">
794
+ <ul>
795
+ <li>
796
+ <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-red">
797
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
798
+ </span>
799
+ - <?php _e('A neutral setting that can not harm your site, but you must be sure that you need to use it.', 'wbcr_factory_pages_407'); ?>
800
+ </li>
801
+ <li>
802
+ <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-grey">
803
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
804
+ </span>
805
+ - <?php _e('When set this option, you must be careful. Plugins and themes may depend on this function. You must be sure that you can disable this feature for the site.', 'wbcr_factory_pages_407'); ?>
806
+ </li>
807
+ <li>
808
+ <span class="wbcr-factory-hint-icon-simple wbcr-factory-simple-green">
809
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAUUlEQVQIHU3BsQ1AQABA0X/komIrnQHYwyhqQ1hBo9KZRKL9CBfeAwy2ri42JA4mPQ9rJ6OVt0BisFM3Po7qbEliru7m/FkY+TN64ZVxEzh4ndrMN7+Z+jXCAAAAAElFTkSuQmCC" alt=""/>
810
+ </span>
811
+ - <?php _e('Absolutely safe setting, We recommend to use.', 'wbcr_factory_pages_407'); ?>
812
+ </li>
813
+ </ul>
814
+ ----------<br>
815
+
816
+ <p><?php _e('Hover to the icon to get help for the feature you selected.', 'wbcr_factory_pages_407'); ?></p>
817
+ </div>
818
+ <?php
819
+ }
820
+
821
+ public function showRatingWidget(array $args)
822
+ {
823
+ if( !isset($args[0]) || empty($args[0]) ) {
824
+ $page_url = "https://goo.gl/tETE2X";
825
+ } else {
826
+ $page_url = $args[0];
827
+ }
828
+
829
+ $page_url = apply_filters('wbcr_factory_pages_407_imppage_rating_widget_url', $page_url, $this->plugin->getPluginName(), $this->getResultId());
830
+
831
+ ?>
832
+ <div class="wbcr-factory-sidebar-widget">
833
+ <p>
834
+ <strong><?php _e('Do you want the plugin to improved and update?', 'wbcr_factory_pages_407'); ?></strong>
835
+ </p>
836
+
837
+ <p><?php _e('Help the author, leave a review on wordpress.org. Thanks to feedback, I will know that the plugin is really useful to you and is needed.', 'wbcr_factory_pages_407'); ?></p>
838
+
839
+ <p><?php _e('And also write your ideas on how to extend or improve the plugin.', 'wbcr_factory_pages_407'); ?></p>
840
+
841
+ <p>
842
+ <i class="wbcr-factory-icon-5stars"></i>
843
+ <a href="<?= $page_url ?>" title="Go rate us" target="_blank">
844
+ <strong><?php _e('Go rate us and push ideas', 'wbcr_factory_pages_407'); ?></strong>
845
+ </a>
846
+ </p>
847
+ </div>
848
+ <?php
849
+ }
850
+
851
+ public function showDonateWidget()
852
+ {
853
+ ?>
854
+ <div class="wbcr-factory-sidebar-widget">
855
+ <p>
856
+ <strong><?php _e('Donation for plugin development', 'wbcr_factory_pages_407'); ?></strong>
857
+ </p>
858
+
859
+ <?php if( get_locale() !== 'ru_RU' ): ?>
860
+ <form id="wbcr-factory-paypal-donation-form" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
861
+ <input type="hidden" name="cmd" value="_s-xclick">
862
+ <input type="hidden" name="hosted_button_id" value="VDX7JNTQPNPFW">
863
+
864
+ <div class="wbcr-factory-donation-price">5$</div>
865
+ <input type="image" src="<?= FACTORY_PAGES_407_URL ?>/templates/assets/img/paypal-donate.png" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!">
866
+ </form>
867
+ <?php else: ?>
868
+ <iframe frameborder="0" allowtransparency="true" scrolling="no" src="https://money.yandex.ru/embed/donate.xml?account=410011242846510&quickpay=donate&payment-type-choice=on&mobile-payment-type-choice=on&default-sum=300&targets=%D0%9D%D0%B0+%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D1%83+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0+%D0%B8+%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D1%83+%D0%BD%D0%BE%D0%B2%D1%8B%D1%85+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9.+&target-visibility=on&project-name=Webcraftic&project-site=&button-text=05&comment=on&hint=%D0%9A%D0%B0%D0%BA%D1%83%D1%8E+%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8E+%D0%BD%D1%83%D0%B6%D0%BD%D0%BE+%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C+%D0%B2+%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%3F&mail=on&successURL=" width="508" height="187"></iframe>
869
+ <?php endif; ?>
870
+ </div>
871
+ <?php
872
+ }
873
+
874
+ /**
875
+ * Shows the html block with a confirmation dialog.
876
+ *
877
+ * @sinve 1.0.0
878
+ * @return void
879
+ */
880
+ public function confirmPageTemplate($data)
881
+ {
882
+ ?>
883
+ <div id="WBCR" class="wrap">
884
+ <div class="wbcr-factory-pages-407-impressive-page-template factory-bootstrap-406 factory-fontawesome-000">
885
+ <div id="wbcr-factory-confirm-dialog">
886
+ <h2><?php echo $data['title'] ?></h2>
887
+
888
+ <p class="wbcr-factory-confirm-description"><?php echo $data['description'] ?></p>
889
+
890
+ <?php if( isset($data['hint']) ): ?>
891
+ <p class="wbcr-factory-confirm-hint"><?php echo $data['hint'] ?></p>
892
+ <?php endif; ?>
893
+
894
+ <div class='wbcr-factory-confirm-actions'>
895
+ <?php foreach($data['actions'] as $action) { ?>
896
+ <a href='<?php echo $action['url'] ?>' class='<?php echo $action['class'] ?>'>
897
+ <?php echo $action['title'] ?>
898
+ </a>
899
+ <?php } ?>
900
+ </div>
901
+ </div>
902
+ </div>
903
+ </div>
904
+ <?php
905
+ }
906
+ }
907
+ }
908
+
readme.txt ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Robin image optimizer — save money on image compression. ===
2
+ Tags: image, optimizer, image optimization, resmush.it, smush, jpg, png, gif, optimization, compression, Compress, Images, Pictures, Reduce Image Size, Smush, Smush.it
3
+ Contributors: webcraftic
4
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VDX7JNTQPNPFW
5
+ Requires at least: 4.2
6
+ Tested up to: 4.9
7
+ Requires PHP: 5.3
8
+ Stable tag: trunk
9
+ License: GPLv2
10
+
11
+ Automatic image optimization without any quality loss. No limitations, no paid plans. The best Wordpress image optimization plugin allows optimizing any amount of images for free!
12
+
13
+ == Description ==
14
+
15
+ Make your website faster by reducing the weight of images. Our Wordpress image optimizer plugin can cease image weights on 80% without any loss of quality.
16
+
17
+ Robin image optimizer is a smart and advanced image optimizer that really stands out among other Wordpress plugins. Robin image optimizer is a Wordpress free image optimizer plugin with zero limitations in terms of number of images and optimization quality. The only thing that you may stumble across is the image weight, which shouldn’t exceed 5 MB.
18
+
19
+ ### What’s the purpose of image optimization? ###
20
+
21
+ The lighter the weight of the image – the faster your page loads. With the constant growth of mobile users, increases the necessity in mobile websites optimization. If you don’t want to get many rejections and lose money due to the poor ad performances, we’d recommend you to start with image optimization.
22
+
23
+ ### Why should we use Robin image optimizer for image optimization? ###
24
+
25
+ * The first and the most significant difference from the counterparts: our plugin is absolutely free and has the same features as paid products.
26
+
27
+ * This Wordpress image optimizer doesn't have any limits or restrictions in image optimization.
28
+
29
+ * Automatic optimization using Cron. You don't need to wait til optimization is completed; the plugin will be optimizing couple of images every several minutes in the background.
30
+
31
+ * Manual mass-optimization. Press the button and wait til your images are optimized
32
+
33
+ * Image backup. Before optimization starts, all images are being stored in original quality. Then, when optimization is over, you can restore lost images or re-optimize them in another quality.
34
+
35
+ * You can choose compression mode (normal, regular, high). Compression mode influences image weight and quality. The higher the compression, the worse is the quality and the smaller is the weight.
36
+
37
+ * Image optimization on boot.
38
+
39
+ * Reducing pre-optimization image weight by changing image size.
40
+
41
+ * Detailed statistics on optimized images
42
+
43
+ #### RECOMMENDED SEPARATE MODULES ####
44
+ We invite you to check out a few other related free plugins that our team has also produced that you may find especially useful:
45
+
46
+ * [Clearfy – WordPress optimization plugin](https://wordpress.org/plugins/clearfy/)
47
+ * [Disable updates, Disable automatic updates, Updates manager](https://wordpress.org/plugins/webcraftic-updates-manager/)
48
+ * [Cyrlitera – transliteration of links and file names](https://wordpress.org/plugins/cyrlitera/)
49
+ * [Cyr-to-lat reloaded – transliteration of links and file names](https://wordpress.org/plugins/cyr-and-lat/ "Cyr-to-lat reloaded")
50
+ * [Disable admin notices individually](https://wordpress.org/plugins/disable-admin-notices/ "Disable admin notices individually")
51
+ * [WordPress Assets manager, dequeue scripts, dequeue styles](https://wordpress.org/plugins/gonzales/ "WordPress Assets manager, dequeue scripts, dequeue styles")
52
+ * [Hide login page](https://wordpress.org/plugins/hide-login-page/ "Hide login page")
53
+
54
+ == Translations ==
55
+
56
+ * English - default, always included
57
+ * Russian
58
+
59
+ If you want to help with the translation, please contact me through this site or through the contacts inside the plugin.
60
+
61
+ == Installation ==
62
+
63
+ 1. Upload `robin-image-optimizer` to the `/wp-content/plugins/` directory.
64
+ 2. Activate the plugin through the 'Plugins' menu in WordPress.
65
+ 3. All your new pictures will be automatically optimized !
66
+
67
+ == Frequently Asked Questions ==
68
+
69
+ = Why is this plugin free and how long it will be this way? =
70
+
71
+ Our Wordpress plugin to optimize images uses API of this free service: https://resmush.it, So as long as these guys allow free image optimization, our plugin will remain free. Still, we have several ideas of how to make optimization free and planning to implement them in our plugin.
72
+
73
+ = Are there any limits for image optimization? =
74
+ There are no limits for image optimization in our plugin. The only thing we have is a kind of a restriction of image weight – it should be greater than 5 MB. But our plugin can reduce pre-optimization image weight, so you’ll be able to optimize almost all images you have.
75
+
76
+ = What image formats do you support? =
77
+ Robin image optimizer can optimize jpg, png and gif (both animated or not).
78
+
79
+ = Do you remove EXIF images data? =
80
+ EXIF-data is removed by default. However, you can keep it by disabling the feature.
81
+
82
+ = Do you remove source images? =
83
+ No. Robin image optimizer replaces images with their optimized analogues. The backup option stores source images and allows restoring them in one click.
84
+
85
+ = Can I re-optimize images in another mode? =
86
+ Yes. By enabling the backup feature in the plugin, you can re-optimize any image using another compression mode.
87
+
88
+ == Screenshots ==
89
+
90
+ 1. The simple interface
91
+ 2. The simple interface
92
+
93
+ == Changelog ==
94
+ = 1.0.7 =
95
+ * Fixed: Images are saved in a size 0 bytes
96
+ * Fixed: Trying to backup file with empty filename
97
+ * Fixed: Curl replacement for file_get_contents
98
+ * Fixed: Statistics
99
+ = 1.0.6 =
100
+ * Fixed: fixed bar progress styles
101
+ * Fixed: changed the link to the reviews page
102
+ = 1.0.5 =
103
+ * Fixed: corrected image size calculations for individual optimization
104
+ = 1.0.4 =
105
+ * Fixed: update core framework
106
+ = 1.0.3 =
107
+ * Fixed: small bugs
108
+ = 1.0.0 =
109
+ * Release
robin-image-optimizer.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: Webcraftic Robin image optimizer
4
+ * Plugin URI: https://wordpress.org/plugins/robin-image-optimizer/
5
+ * Description: Optimize images without losing quality, speed up your website load, improve SEO and save money on server and CDN bandwidth.
6
+ * Author: Webcraftic <wordpress.webraftic@gmail.com>
7
+ * Version: 1.0.7
8
+ * Text Domain: image-optimizer
9
+ * Domain Path: /languages/
10
+ * Author URI: https://clearfy.pro
11
+ */
12
+
13
+ // Exit if accessed directly
14
+ if( !defined('ABSPATH') ) {
15
+ exit;
16
+ }
17
+
18
+ /**
19
+ * Уведомление о том, что этот плагин используется уже в составе плагина Clearfy, как его компонент.
20
+ * Мы блокируем работу этого плагина, чтобы не вызывать конфликт.
21
+ */
22
+ if( defined('WIO_PLUGIN_ACTIVE') || (defined('WCL_PLUGIN_ACTIVE') && !defined('LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON')) ) {
23
+ function wbcr_wio_admin_notice_error()
24
+ {
25
+ ?>
26
+ <div class="notice notice-error">
27
+ <p><?php _e('We found that you have the "Clearfy - wordpress optimization plugin" plugin installed, this plugin already has disable comments functions, so you can deactivate plugin "Image optimizer"!', 'robin-image-optimizer'); ?></p>
28
+ </div>
29
+ <?php
30
+ }
31
+
32
+ add_action('admin_notices', 'wbcr_wio_admin_notice_error');
33
+
34
+ return;
35
+ } else {
36
+
37
+ // Устанавливаем контстанту, что плагин уже используется
38
+ define('WIO_PLUGIN_ACTIVE', true);
39
+
40
+ // Директория плагина
41
+ define('WIO_PLUGIN_DIR', dirname(__FILE__));
42
+
43
+ // Относительный путь к плагину
44
+ define('WIO_PLUGIN_BASE', plugin_basename(__FILE__));
45
+
46
+ // Ссылка к директории плагина
47
+ define('WIO_PLUGIN_URL', plugins_url(null, __FILE__));
48
+
49
+
50
+
51
+ // Этот плагин может быть аддоном плагина Clearfy, если он загружен, как аддон, то мы не подключаем фреймворк,
52
+ // а наследуем функции фреймворка от плагина Clearfy. Если плагин скомпилирован, как отдельный плагин, то он использует собственный фреймворк для работы.
53
+ // Константа LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON утсанавливается в классе libs/factory/core/includes/Wbcr_Factory406_Plugin
54
+
55
+ if( !defined('LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON') ) {
56
+ // Фреймворк - отвечает за интерфейс, содержит общие функции для серии плагинов и готовые шаблоны для быстрого развертывания плагина.
57
+ require_once(WIO_PLUGIN_DIR . '/libs/factory/core/boot.php');
58
+ }
59
+
60
+ // Основной класс плагина
61
+ require_once(WIO_PLUGIN_DIR . '/includes/class.plugin.php');
62
+
63
+ // Класс WIO_Plugin создается только, если этот плагин работает, как самостоятельный плагин.
64
+ // Если плагин работает, как аддон, то класс создается родительским плагином.
65
+
66
+ if( !defined('LOADING_ROBIN_IMAGE_OPTIMIZER_AS_ADDON') ) {
67
+ new WIO_Plugin(__FILE__, array(
68
+ 'prefix' => 'wbcr_io_',
69
+ // префикс для базы данных и полей формы
70
+ 'plugin_name' => 'wbcr_image_optimizer',
71
+ // имя плагина, как уникальный идентификатор
72
+ 'plugin_title' => __('Webcraftic Robin image optimizer', 'robin-image-optimizer'),
73
+ // заголовок плагина
74
+ 'plugin_version' => '1.0.7',
75
+ // текущая версия плагина
76
+ 'required_php_version' => '5.2',
77
+ // минимальная версия php для работы плагина
78
+ 'required_wp_version' => '4.2',
79
+ // минимальная версия wp для работы плагина
80
+ 'plugin_build' => 'free',
81
+ // сборка плагина
82
+ //'updates' => WIO_PLUGIN_DIR . '/updates/' в этой папке хранятся миграции для разных версий плагина
83
+ ));
84
+ }
85
+ }
uninstall.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // if uninstall.php is not called by WordPress, die
4
+ if( !defined('WP_UNINSTALL_PLUGIN') ) {
5
+ die;
6
+ }
7
+
8
+ // remove plugin options
9
+ global $wpdb;
10
+
11
+ $wpdb->query("DELETE FROM {$wpdb->prefix}options WHERE option_name LIKE 'wbcr_io_%';");
12
+ $wpdb->query("DELETE FROM {$wpdb->prefix}postmeta WHERE meta_key LIKE 'wio_%';");
13
+
14
+ // remove backup dir
15
+ require_once( dirname( __FILE__ ) . '/includes/classes/class.backup.php' );
16
+ $backup = new WIO_Backup;
17
+ $backup->removeBackupDir();