a3 Lazy Load - Version 1.0.0

Version Description

  • 2014/12/20 =
  • First working release
Download this release

Release Info

Developer a3rev
Plugin Icon 128x128 a3 Lazy Load
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

Files changed (81) hide show
  1. LICENSE.txt +674 -0
  2. a3-lazy-load.php +50 -0
  3. admin/a3-lazy-load-admin.php +45 -0
  4. admin/admin-init.php +321 -0
  5. admin/admin-interface.php +2660 -0
  6. admin/admin-pages/admin-settings-page.php +155 -0
  7. admin/admin-ui.php +180 -0
  8. admin/assets/css/a3_admin_metabox.css +276 -0
  9. admin/assets/css/a3_admin_metabox.rtl.css +78 -0
  10. admin/assets/css/a3_admin_metabox.rtl.less +106 -0
  11. admin/assets/css/a3_admin_metabox.rtl.min.css +1 -0
  12. admin/assets/css/admin-flat-ui-style.css +209 -0
  13. admin/assets/css/admin-flat-ui-style.min.css +27 -0
  14. admin/assets/css/admin-ui-style.css +675 -0
  15. admin/assets/css/admin-ui-style.min.css +137 -0
  16. admin/assets/css/admin-ui-style.rtl.css +170 -0
  17. admin/assets/css/admin-ui-style.rtl.less +215 -0
  18. admin/assets/css/admin-ui-style.rtl.min.css +1 -0
  19. admin/assets/css/mixins.less +205 -0
  20. admin/assets/fonts/a3-metabox-plugin-framework.eot +0 -0
  21. admin/assets/fonts/a3-metabox-plugin-framework.svg +16 -0
  22. admin/assets/fonts/a3-metabox-plugin-framework.ttf +0 -0
  23. admin/assets/fonts/a3-metabox-plugin-framework.woff +0 -0
  24. admin/assets/fonts/a3-plugin-framework.eot +0 -0
  25. admin/assets/fonts/a3-plugin-framework.svg +19 -0
  26. admin/assets/fonts/a3-plugin-framework.ttf +0 -0
  27. admin/assets/fonts/a3-plugin-framework.woff +0 -0
  28. admin/assets/images/a3-plugins.png +0 -0
  29. admin/assets/images/help.png +0 -0
  30. admin/assets/images/ico-delete.png +0 -0
  31. admin/assets/images/ico-preview.png +0 -0
  32. admin/assets/images/ico-refresh.png +0 -0
  33. admin/assets/images/loading-bottom.gif +0 -0
  34. admin/assets/images/slider-bg-disable.png +0 -0
  35. admin/assets/images/slider-bg-range.png +0 -0
  36. admin/assets/images/slider-bg-track1.png +0 -0
  37. admin/assets/images/slider-bg.png +0 -0
  38. admin/assets/images/slider-bg1.jpg +0 -0
  39. admin/assets/images/slider-container-end-disable.png +0 -0
  40. admin/assets/images/slider-container-end.png +0 -0
  41. admin/assets/images/slider-container-start-disable.png +0 -0
  42. admin/assets/images/slider-container-start.png +0 -0
  43. admin/assets/images/slider-handle-disable.png +0 -0
  44. admin/assets/images/slider-handle.png +0 -0
  45. admin/assets/images/slider-handle1.png +0 -0
  46. admin/assets/images/slider-handle2.png +0 -0
  47. admin/assets/js/a3rev-settings-preview.js +188 -0
  48. admin/assets/js/a3rev-typography-preview.js +208 -0
  49. admin/assets/js/admin-ui-script.js +213 -0
  50. admin/assets/js/chosen/chosen-sprite.png +0 -0
  51. admin/assets/js/chosen/chosen-sprite@2x.png +0 -0
  52. admin/assets/js/chosen/chosen.css +435 -0
  53. admin/assets/js/chosen/chosen.jquery.js +1211 -0
  54. admin/assets/js/chosen/chosen.jquery.min.js +2 -0
  55. admin/assets/js/chosen/chosen.min.css +3 -0
  56. admin/assets/js/data-meta-boxes.js +39 -0
  57. admin/assets/js/iphone-style-checkboxes.js +381 -0
  58. admin/assets/js/iphone-style-checkboxes.rtl.js +381 -0
  59. admin/assets/js/tipTip/jquery.tipTip.js +191 -0
  60. admin/assets/js/tipTip/jquery.tipTip.min.js +21 -0
  61. admin/assets/js/tipTip/tipTip.css +113 -0
  62. admin/assets/js/ui-slider/jquery.ui.slider.rtl.js +711 -0
  63. admin/assets/js/ui-slider/jquery.ui.slider.rtl.min.js +15 -0
  64. admin/includes/fonts_face.php +445 -0
  65. admin/includes/uploader/class-uploader.php +220 -0
  66. admin/includes/uploader/delete.png +0 -0
  67. admin/includes/uploader/mixins.less +205 -0
  68. admin/includes/uploader/uploader-script.js +69 -0
  69. admin/includes/uploader/uploader.css +35 -0
  70. admin/includes/uploader/uploader.rtl.css +18 -0
  71. admin/includes/uploader/uploader.rtl.less +23 -0
  72. admin/less/assets/css/mixins.less +201 -0
  73. admin/less/assets/css/style.css +0 -0
  74. admin/less/assets/css/style.less +0 -0
  75. admin/less/assets/css/style.min.css +0 -0
  76. admin/less/compile_less_sass_class.php +54 -0
  77. admin/less/index.html +31 -0
  78. admin/less/index.php +27 -0
  79. admin/less/lib/cssmin.inc.php +5082 -0
  80. admin/less/lib/less.js +7942 -0
  81. admin/less/lib/lessc.inc.php +1327 -0
LICENSE.txt ADDED
@@ -0,0 +1,674 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <http://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
+ <http://www.gnu.org/philosophy/why-not-lgpl.html>.
a3-lazy-load.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: a3 Lazy Load
4
+ Description: Speed up your site and enhance frontend user's visual experience in PC's, Tablets and mobile with a3 Lazy Load.
5
+ Version: 1.0.0
6
+ Author: a3 Revolution
7
+ Author URI: http://www.a3rev.com/
8
+ Requires at least: 3.8
9
+ Tested up to: 4.1
10
+ License: GPLv2 or later
11
+ Copyright © 2011 a3 Revolution Software Development team
12
+ a3 Revolution Software Development team
13
+ admin@a3rev.com
14
+ PO Box 1170
15
+ Gympie 4570
16
+ QLD Australia
17
+ */
18
+ ?>
19
+ <?php
20
+ define('A3_LAZY_VERSION', '1.0.0');
21
+ define('A3_LAZY_LOAD_FILE_PATH', dirname(__FILE__));
22
+ define('A3_LAZY_LOAD_DIR_NAME', basename(A3_LAZY_LOAD_FILE_PATH));
23
+ define('A3_LAZY_LOAD_FOLDER', dirname(plugin_basename(__FILE__)));
24
+ define('A3_LAZY_LOAD_NAME', plugin_basename(__FILE__));
25
+ define('A3_LAZY_LOAD_URL', str_replace(array('http:','https:'), '', untrailingslashit(plugins_url('/', __FILE__))));
26
+ define('A3_LAZY_LOAD_DIR', WP_CONTENT_DIR . '/plugins/' . A3_LAZY_LOAD_FOLDER);
27
+ define('A3_LAZY_LOAD_JS_URL', A3_LAZY_LOAD_URL . '/assets/js');
28
+ define('A3_LAZY_LOAD_CSS_URL', A3_LAZY_LOAD_URL . '/assets/css');
29
+ define('A3_LAZY_LOAD_IMAGES_URL', A3_LAZY_LOAD_URL . '/assets/images');
30
+
31
+ include( 'admin/admin-ui.php' );
32
+ include( 'admin/admin-interface.php' );
33
+
34
+ include( 'admin/admin-pages/admin-settings-page.php' );
35
+
36
+ include( 'admin/admin-init.php' );
37
+ include( 'admin/less/sass.php' );
38
+
39
+ include( 'classes/addons/class-a3-lazy-load-addons-page.php' );
40
+
41
+ include( 'classes/class-a3-lazy-load.php' );
42
+ include( 'classes/class-a3-lazy-load-filter.php' );
43
+
44
+ include( 'admin/a3-lazy-load-admin.php' );
45
+
46
+ /**
47
+ * Call when the plugin is activated
48
+ */
49
+ register_activation_hook(__FILE__, 'a3_lazy_load_activated');
50
+ ?>
admin/a3-lazy-load-admin.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ update_option('a3rev_lazy_load_plugin', 'a3_lazy_load');
3
+
4
+ function a3_lazy_load_activated(){
5
+ update_option('a3_lazy_load_version', '1.0.0');
6
+
7
+ // Set Settings Default from Admin Init
8
+ global $a3_lazy_load_admin_init;
9
+ $a3_lazy_load_admin_init->set_default_settings();
10
+
11
+ update_option('a3_lazy_load_just_installed', true);
12
+ }
13
+
14
+ /**
15
+ * Load languages file
16
+ */
17
+ function a3_lazy_load_init() {
18
+ global $a3_lazy_load_global_settings;
19
+
20
+ if ( get_option( 'a3_lazy_load_just_installed' ) ) {
21
+ delete_option( 'a3_lazy_load_just_installed' );
22
+ wp_redirect( admin_url( 'admin.php?page=a3-lazy-load', 'relative' ) );
23
+ exit;
24
+ }
25
+
26
+ load_plugin_textdomain( 'a3_lazy_load', false, A3_LAZY_LOAD_FOLDER.'/languages' );
27
+
28
+ update_option('a3_lazy_load_version', '1.0.0');
29
+ }
30
+
31
+ global $a3_lazy_load_admin_init;
32
+ $a3_lazy_load_admin_init->init();
33
+
34
+ // Add language
35
+ add_action('init', 'a3_lazy_load_init');
36
+
37
+ // Add custom style to dashboard
38
+ add_action( 'admin_enqueue_scripts', array( 'A3_Lazy_Load_Hook_Filter', 'a3_wp_admin' ) );
39
+
40
+ // Add text on right of Visit the plugin on Plugin manager page
41
+ add_filter( 'plugin_row_meta', array( 'A3_Lazy_Load_Hook_Filter', 'plugin_extra_links'), 10, 2 );
42
+
43
+ // Add admin sidebar menu css
44
+ add_action( 'admin_enqueue_scripts', array( 'A3_Lazy_Load_Hook_Filter', 'admin_sidebar_menu_css' ) );
45
+ ?>
admin/admin-init.php ADDED
@@ -0,0 +1,321 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* "Copyright 2012 a3 Revolution Web Design" This software is distributed under the terms of GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 */
3
+ // File Security Check
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+ ?>
6
+ <?php
7
+ /*-----------------------------------------------------------------------------------
8
+ A3rev Plugin Admin Init
9
+
10
+ TABLE OF CONTENTS
11
+
12
+ - var admin_menu
13
+ - init()
14
+ - set_default_settings()
15
+ - get_all_settings()
16
+ - add_admin_menu()
17
+ - register_admin_menu()
18
+ - add_admin_pages()
19
+ - admin_settings_tab()
20
+
21
+ -----------------------------------------------------------------------------------*/
22
+
23
+ class A3_Lazy_Load_Admin_Init extends A3_Lazy_Load_Admin_UI
24
+ {
25
+
26
+ /**
27
+ * @var array
28
+ */
29
+ public $admin_menu = array();
30
+
31
+ /*-----------------------------------------------------------------------------------*/
32
+ /* init() */
33
+ /* Admin Init */
34
+ /*-----------------------------------------------------------------------------------*/
35
+ public function init() {
36
+
37
+ $this->add_admin_menu();
38
+
39
+ // Filter to add admin pages for Amin UI process
40
+ add_filter( $this->plugin_name . '_admin_pages', array( $this, 'add_admin_pages' ) );
41
+
42
+ add_action( 'admin_menu', array( $this, 'register_admin_menu' ) );
43
+
44
+ add_action( 'plugins_loaded', array( $this, 'get_all_settings' ), 8 );
45
+ }
46
+
47
+ /*-----------------------------------------------------------------------------------*/
48
+ /* set_default_settings() */
49
+ /* Called when plugin just installed */
50
+ /*-----------------------------------------------------------------------------------*/
51
+ public function set_default_settings() {
52
+
53
+ do_action( $this->plugin_name . '_set_default_settings' );
54
+ }
55
+
56
+ /*-----------------------------------------------------------------------------------*/
57
+ /* get_all_settings() */
58
+ /* Get all settings when plugin is loaded */
59
+ /*-----------------------------------------------------------------------------------*/
60
+ public function get_all_settings() {
61
+
62
+ do_action( $this->plugin_name . '_get_all_settings' );
63
+ }
64
+
65
+ /**
66
+ * add_admin_menu()
67
+ * Add the Admin menu
68
+ * =============================================
69
+ * check add_menu_page() function at http://codex.wordpress.org/Function_Reference/add_menu_page to know the parameters need to parse for type is menu
70
+ * check add_submenu_page() function at http://codex.wordpress.org/Function_Reference/add_submenu_page to know the parameters need to parse for type is submenu
71
+ * array (
72
+ * array (
73
+ * 'type' => 'menu' : (required) add it as main menu on left sidebar of Dashboard
74
+ * 'page_title' => 'Quotes & Orders Mode' : (required) The text to be displayed in the title tags of the page when the menu is selected
75
+ * 'menu_title' => 'Quotes & Orders Mode' : (required) The text to be displayed in the title tags of the page when the menu is selected
76
+ * 'capability' => 'manage_options' : (required) The capability required for this menu to be displayed to the user.
77
+ * View instruction at http://codex.wordpress.org/Roles_and_Capabilities
78
+ * 'menu_slug' => 'quotes-orders-mode' : (required) The slug name to refer to this menu by.
79
+ * 'function' => 'my_function_name' : (required) The function that displays the page content for the menu page.
80
+ * 'icon_url' => 'http://my_icon.png' : (optional) The url to the icon to be used for this menu.
81
+ * 'position' => 50 : (optional) The position in the menu order this menu should appear.
82
+ * By default, if this parameter is omitted, the menu will appear at the bottom of the menu structure.
83
+ * 'admin_url' => 'admin.php' : (required) The admin url : admin.php , options-general.php
84
+ * 'callback_function'=> 'my_callback_function': (optional) The callback function is called when this page does not have tab
85
+ * 'script_function' => 'my_script_function' : (optional) The script function that only include for this page.
86
+ * 'view_doc' => '' : (optional) Support html. The text show on the heading
87
+ * ),
88
+ * array (
89
+ * 'type' => 'submenu' : (required) add it as sub menu on left sidebar of Dashboard
90
+ * 'parent_slug' => 'quotes-orders-mode' : (required) The slug name for the parent menu.
91
+ * 'page_title' => 'Quotes & Orders Mode' : (required) The text to be displayed in the title tags of the page when the menu is selected
92
+ * 'menu_title' => 'Quotes & Orders Mode' : (required) The text to be displayed in the title tags of the page when the menu is selected
93
+ * 'capability' => 'manage_options' : (required) The capability required for this menu to be displayed to the user.
94
+ * View instruction at http://codex.wordpress.org/Roles_and_Capabilities
95
+ * 'menu_slug' => 'quotes-orders-mode' : (required) The slug name to refer to this menu by.
96
+ * 'function' => 'my_function_name' : (required) The function that displays the page content for the menu page.
97
+ * 'admin_url' => 'admin.php' : (required) The admin url : admin.php , options-general.php
98
+ * 'callback_function'=> 'my_callback_function': (optional) The callback function is called when this page does not have tab
99
+ * 'script_function' => 'my_script_function' : (optional) The script function that only include for this page.
100
+ * 'view_doc' => '' : (optional) Support html. The text show on the heading
101
+ * )
102
+ * )
103
+ *
104
+ */
105
+ public function add_admin_menu() {
106
+
107
+ $this->admin_menu = apply_filters( $this->plugin_name . '_add_admin_menu', $this->admin_menu );
108
+ }
109
+
110
+ /*-----------------------------------------------------------------------------------*/
111
+ /* register_admin_menu() */
112
+ /* Setup the Admin menu in WordPress
113
+ /*-----------------------------------------------------------------------------------*/
114
+ public function register_admin_menu() {
115
+
116
+ if ( is_array( $this->admin_menu ) && count( $this->admin_menu ) > 0 ) {
117
+ foreach ( $this->admin_menu as $menu_item ) {
118
+ if ( ! isset( $menu_item['type'] ) || trim( $menu_item['type'] ) == '' ) continue;
119
+
120
+ switch( $menu_item['type'] ) {
121
+
122
+ case 'menu':
123
+
124
+ $menu_page = add_menu_page( esc_html( $menu_item['page_title'] ), esc_html( $menu_item['menu_title'] ), $menu_item['capability'], $menu_item['menu_slug'] , $menu_item['function'], $menu_item['icon_url'], $menu_item['position'] );
125
+
126
+ if ( isset( $menu_item['script_function'] ) && trim( $menu_item['script_function'] ) != '' )
127
+ add_action( "admin_print_scripts-" . $menu_page, $menu_item['script_function'] );
128
+
129
+ break;
130
+
131
+ case 'submenu':
132
+
133
+ $submenu_page = add_submenu_page( $menu_item['parent_slug'] , esc_html( $menu_item['page_title'] ), esc_html( $menu_item['menu_title'] ), $menu_item['capability'], $menu_item['menu_slug'] , $menu_item['function'] );
134
+
135
+ if ( isset( $menu_item['script_function'] ) && trim( $menu_item['script_function'] ) != '' )
136
+ add_action( "admin_print_scripts-" . $submenu_page, $menu_item['script_function'] );
137
+
138
+ break;
139
+ }
140
+ }
141
+
142
+ }
143
+
144
+ }
145
+
146
+ /*-----------------------------------------------------------------------------------*/
147
+ /* add_admin_pages() */
148
+ /* Get list page for Admin UI can include scripts and styles at header and footer
149
+ /*-----------------------------------------------------------------------------------*/
150
+ public function add_admin_pages( $admin_pages ) {
151
+
152
+ if ( ! is_array( $admin_pages ) ) $admin_pages = array();
153
+
154
+ if ( is_array( $this->admin_menu ) && count( $this->admin_menu ) > 0 ) {
155
+ foreach ( $this->admin_menu as $menu_item ) {
156
+ if ( ! isset( $menu_item['type'] ) || trim( $menu_item['type'] ) == '' ) continue;
157
+
158
+ switch( $menu_item['type'] ) {
159
+
160
+ case 'menu':
161
+ case 'submenu':
162
+ if ( ! in_array( $menu_item['menu_slug'], $admin_pages ) )
163
+ $admin_pages[] = $menu_item['menu_slug'];
164
+ break;
165
+ }
166
+ }
167
+
168
+ }
169
+
170
+ return $admin_pages;
171
+ }
172
+
173
+ /*-----------------------------------------------------------------------------------*/
174
+ /* admin_settings_page() */
175
+ /* Show Settings Page Layout
176
+ /*-----------------------------------------------------------------------------------*/
177
+ public function admin_settings_page( $page_data = array() ) {
178
+ global $current_tab;
179
+
180
+ if ( ! is_array( $page_data ) || count( $page_data ) < 1 ) return;
181
+
182
+ $current_page = $page_data['menu_slug'];
183
+
184
+ do_action( $this->plugin_name . '_page_start' );
185
+ do_action( $this->plugin_name . '-' . $current_page . '_page_start' );
186
+
187
+ ?>
188
+ <div class="wrap">
189
+ <div class="icon32 icon32-a3rev-ui-settings icon32-a3rev<?php echo $current_page; ?>" id="icon32-a3rev<?php echo $current_page; ?>"><br /></div>
190
+ <?php
191
+ $tabs = apply_filters( $this->plugin_name . '-' . $current_page . '_settings_tabs_array', array() );
192
+
193
+ if ( ! is_array( $tabs ) || count( $tabs ) < 1 ) {
194
+ ?>
195
+ <h2>
196
+ <?php
197
+ if ( $page_data !== false) {
198
+ echo esc_html( $page_data['page_title'] );
199
+ if ( isset( $page_data['view_doc'] ) ) echo $page_data['view_doc'];
200
+ }
201
+ ?>
202
+ </h2>
203
+ <div style="width:100%; float:left;">
204
+ <?php if ( isset( $page_data['callback_function'] ) && ! empty( $page_data['callback_function'] ) ) call_user_func( $page_data['callback_function'] ); ?>
205
+ </div>
206
+ <?php
207
+ } else {
208
+ ?>
209
+ <h2 class="nav-tab-wrapper">
210
+ <?php
211
+ // Get current tab
212
+ $current_tab = ( empty( $_GET['tab'] ) ) ? '' : sanitize_text_field( urldecode( $_GET['tab'] ) );
213
+
214
+ $activated_first_tab = false;
215
+ $tab_data = false;
216
+ foreach ( $tabs as $tab ) {
217
+ echo '<a href="' . add_query_arg( array( 'page' => $current_page, 'tab' => $tab['name'] ), admin_url( $page_data['admin_url'] ) ) . '" class="nav-tab ';
218
+ if ( $current_tab == '' && $activated_first_tab === false ) {
219
+ echo 'nav-tab-active';
220
+ $activated_first_tab = true;
221
+ $current_tab = $tab['name'];
222
+ $tab_data = $tab;
223
+ } elseif ( $current_tab == $tab['name'] ) {
224
+ echo 'nav-tab-active';
225
+ $tab_data = $tab;
226
+ }
227
+ echo '">' . $tab['label'] . '</a>';
228
+ }
229
+
230
+ do_action( $this->plugin_name . '-' . $current_page . '_settings_tabs' );
231
+ ?>
232
+ </h2>
233
+ <div style="width:100%; float:left;">
234
+ <?php
235
+ if ( $tab_data !== false && isset ( $tab_data['callback_function'] ) && !empty( $tab_data['callback_function'] ) ) {
236
+ call_user_func( $tab_data['callback_function'] );
237
+ } else {
238
+ do_action( $this->plugin_name . '-' . $current_page . '_settings_tabs_' . $current_tab );
239
+ }
240
+ ?>
241
+ </div>
242
+ <?php
243
+ }
244
+ ?>
245
+ <div style="clear:both; margin-bottom:20px;"></div>
246
+ </div>
247
+ <?php
248
+
249
+ do_action( $this->plugin_name . '_page_end' );
250
+ do_action( $this->plugin_name . '-' . $current_page . '_page_end' );
251
+ }
252
+
253
+ /*-----------------------------------------------------------------------------------*/
254
+ /* admin_settings_tab() */
255
+ /* Show Settings Tab Layout
256
+ /*-----------------------------------------------------------------------------------*/
257
+ public function admin_settings_tab( $current_page = '', $tab_data = array() ) {
258
+ global $current_subtab;
259
+
260
+ if ( ! is_array( $tab_data ) || count( $tab_data ) < 1 ) return;
261
+
262
+ $current_tab = $tab_data['name'];
263
+
264
+ do_action( $this->plugin_name . '-' . $current_page . '_tab_start' );
265
+ do_action( $this->plugin_name . '-' . $current_tab . '_tab_start' );
266
+
267
+ $subtabs = apply_filters( $this->plugin_name . '-' . $current_tab . '_settings_subtabs_array', array() );
268
+
269
+ if ( is_array( $subtabs ) && count( $subtabs ) > 0 ) {
270
+
271
+ ?>
272
+ <div class="a3_subsubsub_section">
273
+ <ul class="subsubsub">
274
+ <?php
275
+ // Get current subtab
276
+ $current_subtab = ( empty( $_REQUEST['subtab'] ) ) ? '' : sanitize_text_field( urldecode( str_replace('#', '', $_REQUEST['subtab'] ) ) );
277
+ $separate_text = '';
278
+ $activated_first_subtab = false;
279
+ foreach ( $subtabs as $subtab ) {
280
+ echo '<li>' . $separate_text . '<a href="#' . trim( $subtab['name'] ) . '" class="';
281
+ if ( $current_subtab == '' && $activated_first_subtab === false ) {
282
+ echo 'current';
283
+ $activated_first_subtab = true;
284
+ $current_subtab = $subtab['name'];
285
+ } elseif ( $current_subtab == $subtab['name'] ) {
286
+ echo 'current';
287
+ }
288
+ echo '">' . $subtab['label'] . '</a></li>' . "\n";
289
+
290
+ $separate_text = ' | ';
291
+ }
292
+
293
+ do_action( $this->plugin_name . '-' . $current_tab . '_settings_subtabs' );
294
+ ?>
295
+ </ul>
296
+ <br class="clear">
297
+ <?php
298
+ foreach ( $subtabs as $subtab ) {
299
+ ?>
300
+ <div class="section" id="<?php echo trim( $subtab['name'] ); ?>">
301
+ <?php if ( isset( $subtab['callback_function'] ) && !empty( $subtab['callback_function'] ) ) call_user_func( $subtab['callback_function'] ); ?>
302
+ </div>
303
+ <?php
304
+ }
305
+
306
+ do_action( $this->plugin_name . '-' . $current_tab . '_settings_subtabs_content' );
307
+ ?>
308
+
309
+ </div>
310
+ <?php
311
+ }
312
+
313
+ do_action( $this->plugin_name . '-' . $current_page . '_tab_end' );
314
+ do_action( $this->plugin_name . '-' . $current_tab . '_tab_end' );
315
+ }
316
+ }
317
+
318
+ global $a3_lazy_load_admin_init;
319
+ $a3_lazy_load_admin_init = new A3_Lazy_Load_Admin_Init();
320
+
321
+ ?>
admin/admin-interface.php ADDED
@@ -0,0 +1,2660 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* "Copyright 2012 A3 Revolution Web Design" This software is distributed under the terms of GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 */
3
+ // File Security Check
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+ ?>
6
+ <?php
7
+ /*-----------------------------------------------------------------------------------
8
+ A3rev Plugin Admin Interface
9
+
10
+ TABLE OF CONTENTS
11
+
12
+ - __construct()
13
+ - get_success_message()
14
+ - get_error_message()
15
+ - get_reset_message()
16
+ - admin_includes()
17
+ - get_font_weights()
18
+ - get_border_styles()
19
+ - admin_script_load()
20
+ - admin_css_load()
21
+ - get_settings_default()
22
+ - get_settings()
23
+ - save_settings()
24
+ - reset_settings()
25
+ - settings_get_option()
26
+ - admin_forms()
27
+ - admin_stripslashes()
28
+ - generate_border_css()
29
+ - generate_border_style_css()
30
+ - generate_border_corner_css()
31
+ - generate_shadow_css()
32
+
33
+ -----------------------------------------------------------------------------------*/
34
+
35
+ class A3_Lazy_Load_Admin_Interface extends A3_Lazy_Load_Admin_UI
36
+ {
37
+
38
+ /*-----------------------------------------------------------------------------------*/
39
+ /* Admin Interface Constructor */
40
+ /*-----------------------------------------------------------------------------------*/
41
+ public function __construct() {
42
+
43
+ $this->admin_includes();
44
+
45
+ add_action( 'init', array( $this, 'init_scripts' ) );
46
+ add_action( 'init', array( $this, 'init_styles' ) );
47
+
48
+ }
49
+
50
+ /*-----------------------------------------------------------------------------------*/
51
+ /* Init scripts */
52
+ /*-----------------------------------------------------------------------------------*/
53
+ public function init_scripts() {
54
+ $admin_pages = $this->admin_pages();
55
+
56
+ if ( is_admin() && isset( $_REQUEST['page'] ) && in_array( $_REQUEST['page'], $admin_pages ) ) {
57
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_script_load' ) );
58
+ do_action( $this->plugin_name . '_init_scripts' );
59
+ }
60
+ }
61
+
62
+ /*-----------------------------------------------------------------------------------*/
63
+ /* Init styles */
64
+ /*-----------------------------------------------------------------------------------*/
65
+ public function init_styles() {
66
+ $admin_pages = $this->admin_pages();
67
+
68
+ if ( is_admin() && isset( $_REQUEST['page'] ) && in_array( $_REQUEST['page'], $admin_pages ) ) {
69
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_css_load' ) );
70
+ do_action( $this->plugin_name . '_init_styles' );
71
+ }
72
+ }
73
+
74
+ /*-----------------------------------------------------------------------------------*/
75
+ /* admin_script_load */
76
+ /*-----------------------------------------------------------------------------------*/
77
+
78
+ public function admin_script_load() {
79
+
80
+ $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
81
+ $rtl = is_rtl() ? '.rtl' : '';
82
+
83
+ wp_register_script( 'chosen', $this->admin_plugin_url() . '/assets/js/chosen/chosen.jquery' . $suffix . '.js', array( 'jquery' ), true, false );
84
+ wp_register_script( 'a3rev-chosen-new', $this->admin_plugin_url() . '/assets/js/chosen/chosen.jquery' . $suffix . '.js', array( 'jquery' ), true, false );
85
+ wp_register_script( 'a3rev-style-checkboxes', $this->admin_plugin_url() . '/assets/js/iphone-style-checkboxes' . $rtl . '.js', array('jquery'), true, false );
86
+ wp_register_script( 'jquery-ui-slider-rtl', $this->admin_plugin_url() . '/assets/js/ui-slider/jquery.ui.slider.rtl' . $suffix . '.js', array('jquery'), true, true );
87
+
88
+ wp_register_script( 'a3rev-admin-ui-script', $this->admin_plugin_url() . '/assets/js/admin-ui-script.js', array('jquery'), true, true );
89
+ wp_register_script( 'a3rev-typography-preview', $this->admin_plugin_url() . '/assets/js/a3rev-typography-preview.js', array('jquery'), false, true );
90
+ wp_register_script( 'a3rev-settings-preview', $this->admin_plugin_url() . '/assets/js/a3rev-settings-preview.js', array('jquery'), false, true );
91
+ wp_register_script( 'jquery-tiptip', $this->admin_plugin_url() . '/assets/js/tipTip/jquery.tipTip' . $suffix . '.js', array( 'jquery' ), true, true );
92
+ wp_register_script( 'a3rev-metabox-ui', $this->admin_plugin_url() . '/assets/js/data-meta-boxes.js', array( 'jquery' ), true, true );
93
+
94
+ wp_enqueue_script( 'jquery' );
95
+ wp_enqueue_script( 'wp-color-picker' );
96
+ if ( is_rtl() ) {
97
+ wp_enqueue_script( 'jquery-ui-slider-rtl' );
98
+ } else {
99
+ wp_enqueue_script( 'jquery-ui-slider' );
100
+ }
101
+ wp_enqueue_script( 'chosen' );
102
+ wp_enqueue_script( 'a3rev-chosen-new' );
103
+ wp_enqueue_script( 'a3rev-style-checkboxes' );
104
+ wp_enqueue_script( 'a3rev-admin-ui-script' );
105
+ wp_enqueue_script( 'a3rev-typography-preview' );
106
+ wp_enqueue_script( 'a3rev-settings-preview' );
107
+ wp_enqueue_script( 'jquery-tiptip' );
108
+ wp_enqueue_script( 'a3rev-metabox-ui' );
109
+
110
+ } // End admin_script_load()
111
+
112
+
113
+ /*-----------------------------------------------------------------------------------*/
114
+ /* admin_css_load */
115
+ /*-----------------------------------------------------------------------------------*/
116
+
117
+ public function admin_css_load () {
118
+ global $wp_version;
119
+
120
+ $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min';
121
+
122
+ wp_enqueue_style( 'a3rev-admin-ui-style', $this->admin_plugin_url() . '/assets/css/admin-ui-style' . $suffix . '.css' );
123
+
124
+ if ( version_compare( $wp_version, '3.8', '>=' ) ) {
125
+ wp_enqueue_style( 'a3rev-admin-flat-ui-style', $this->admin_plugin_url() . '/assets/css/admin-flat-ui-style' . $suffix . '.css' );
126
+ }
127
+ wp_enqueue_style( 'wp-color-picker' );
128
+ wp_enqueue_style( 'a3rev-chosen-new-style', $this->admin_plugin_url() . '/assets/js/chosen/chosen' . $suffix . '.css' );
129
+ wp_enqueue_style( 'a3rev-tiptip-style', $this->admin_plugin_url() . '/assets/js/tipTip/tipTip.css' );
130
+ wp_enqueue_style( 'a3rev-metabox-ui-style', $this->admin_plugin_url() . '/assets/css/a3_admin_metabox.css' );
131
+
132
+ if ( is_rtl() ) {
133
+ wp_enqueue_style( 'a3rev-admin-ui-style-rtl', $this->admin_plugin_url() . '/assets/css/admin-ui-style.rtl' . $suffix . '.css' );
134
+ wp_enqueue_style( 'a3rev-metabox-ui-style-rtl', $this->admin_plugin_url() . '/assets/css/a3_admin_metabox.rtl' . $suffix . '.css' );
135
+ }
136
+
137
+ } // End admin_css_load()
138
+
139
+ /*-----------------------------------------------------------------------------------*/
140
+ /* get_success_message */
141
+ /*-----------------------------------------------------------------------------------*/
142
+ public function get_success_message( $message = '' ) {
143
+ if ( trim( $message ) == '' ) $message = __( 'Settings successfully saved.' , 'a3_lazy_load' );
144
+ return '<div class="updated" id=""><p>' . $message . '</p></div>';
145
+ }
146
+
147
+ /*-----------------------------------------------------------------------------------*/
148
+ /* get_error_message */
149
+ /*-----------------------------------------------------------------------------------*/
150
+ public function get_error_message( $message = '' ) {
151
+ if ( trim( $message ) == '' ) $message = __( 'Error: Settings can not save.' , 'a3_lazy_load' );
152
+ return '<div class="error" id=""><p>' . $message . '</p></div>';
153
+ }
154
+
155
+ /*-----------------------------------------------------------------------------------*/
156
+ /* get_reset_message */
157
+ /*-----------------------------------------------------------------------------------*/
158
+ public function get_reset_message( $message = '' ) {
159
+ if ( trim( $message ) == '' ) $message = __( 'Settings successfully reseted.' , 'a3_lazy_load' );
160
+ return '<div class="updated" id=""><p>' . $message . '</p></div>';
161
+ }
162
+
163
+ /*-----------------------------------------------------------------------------------*/
164
+ /* admin_includes */
165
+ /* Include required core files used in admin UI.
166
+ /*-----------------------------------------------------------------------------------*/
167
+ public function admin_includes() {
168
+ // Includes Font Face Lib
169
+ include_once( 'includes/fonts_face.php' );
170
+
171
+ // Includes Uploader Lib
172
+ include_once( 'includes/uploader/class-uploader.php' );
173
+ }
174
+
175
+ /*-----------------------------------------------------------------------------------*/
176
+ /* Get Font Weights */
177
+ /*-----------------------------------------------------------------------------------*/
178
+ public function get_font_weights() {
179
+ $font_weights = array (
180
+ '300' => __( 'Thin', 'a3_lazy_load' ),
181
+ '300 italic' => __( 'Thin/Italic', 'a3_lazy_load' ),
182
+ 'normal' => __( 'Normal', 'a3_lazy_load' ),
183
+ 'italic' => __( 'Italic', 'a3_lazy_load' ),
184
+ 'bold' => __( 'Bold', 'a3_lazy_load' ),
185
+ 'bold italic' => __( 'Bold/Italic', 'a3_lazy_load' ),
186
+ );
187
+ return apply_filters( $this->plugin_name . '_font_weights', $font_weights );
188
+ }
189
+
190
+ /*-----------------------------------------------------------------------------------*/
191
+ /* Get Border Styles */
192
+ /*-----------------------------------------------------------------------------------*/
193
+ public function get_border_styles() {
194
+ $border_styles = array (
195
+ 'solid' => __( 'Solid', 'a3_lazy_load' ),
196
+ 'double' => __( 'Double', 'a3_lazy_load' ),
197
+ 'dashed' => __( 'Dashed', 'a3_lazy_load' ),
198
+ 'dotted' => __( 'Dotted', 'a3_lazy_load' ),
199
+ 'groove' => __( 'Groove', 'a3_lazy_load' ),
200
+ 'ridge' => __( 'Ridge', 'a3_lazy_load' ),
201
+ 'inset' => __( 'Inset', 'a3_lazy_load' ),
202
+ 'outset' => __( 'Outset', 'a3_lazy_load' ),
203
+ );
204
+ return apply_filters( $this->plugin_name . '_border_styles', $border_styles );
205
+ }
206
+
207
+ /*-----------------------------------------------------------------------------------*/
208
+ /* Get Settings Default Function - get_settings_default */
209
+ /* Just called for when option values is an array and it's in single option name for all settings
210
+ /*-----------------------------------------------------------------------------------*/
211
+
212
+ public function get_settings_default( $options, $option_name = '' ) {
213
+
214
+ $default_settings = array();
215
+
216
+ if ( !is_array( $options ) || count( $options ) < 1 ) return $default_settings;
217
+
218
+ foreach ( $options as $value ) {
219
+ if ( ! isset( $value['type'] ) ) continue;
220
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
221
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
222
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
223
+
224
+ switch ( $value['type'] ) {
225
+
226
+ // Array textfields
227
+ case 'array_textfields' :
228
+ if ( !isset( $value['ids'] ) || !is_array( $value['ids'] ) || count( $value['ids'] ) < 1 ) break;
229
+
230
+ foreach ( $value['ids'] as $text_field ) {
231
+ if ( ! isset( $text_field['id'] ) || trim( $text_field['id'] ) == '' ) continue;
232
+ if ( ! isset( $text_field['default'] ) ) $text_field['default'] = '';
233
+
234
+ // Do not include when it's separate option
235
+ if ( isset( $text_field['separate_option'] ) && $text_field['separate_option'] != false ) continue;
236
+
237
+ // Remove [, ] characters from id argument
238
+ if ( strstr( $text_field['id'], '[' ) ) {
239
+ parse_str( esc_attr( $text_field['id'] ), $option_array );
240
+
241
+ // Option name is first key
242
+ $option_keys = array_keys( $option_array );
243
+ $first_key = current( $option_keys );
244
+
245
+ $id_attribute = $first_key;
246
+ } else {
247
+ $id_attribute = esc_attr( $text_field['id'] );
248
+ }
249
+
250
+ $default_settings[$id_attribute] = $text_field['default'];
251
+ }
252
+
253
+ break;
254
+
255
+ default :
256
+ // Do not include when it's separate option
257
+ if ( isset( $value['separate_option'] ) && $value['separate_option'] != false ) continue;
258
+
259
+ // Remove [, ] characters from id argument
260
+ if ( strstr( $value['id'], '[' ) ) {
261
+ parse_str( esc_attr( $value['id'] ), $option_array );
262
+
263
+ // Option name is first key
264
+ $option_keys = array_keys( $option_array );
265
+ $first_key = current( $option_keys );
266
+
267
+ $id_attribute = $first_key;
268
+ } else {
269
+ $id_attribute = esc_attr( $value['id'] );
270
+ }
271
+
272
+ $default_settings[$id_attribute] = $value['default'];
273
+
274
+ break;
275
+ }
276
+ }
277
+
278
+ if ( trim( $option_name ) != '' ) $default_settings = apply_filters( $this->plugin_name . '_' . $option_name . '_default_settings' , $default_settings );
279
+ if ( ! is_array( $default_settings ) ) $default_settings = array();
280
+
281
+ return $default_settings;
282
+
283
+ }
284
+
285
+ /*-----------------------------------------------------------------------------------*/
286
+ /* Get Settings Function - get_settings */
287
+ /*-----------------------------------------------------------------------------------*/
288
+
289
+ public function get_settings( $options, $option_name = '' ) {
290
+
291
+ if ( !is_array( $options ) || count( $options ) < 1 ) return;
292
+
293
+ $new_settings = array(); $new_single_setting = ''; // :)
294
+
295
+ // Get settings for option values is an array and it's in single option name for all settings
296
+ if ( trim( $option_name ) != '' ) {
297
+ global $$option_name;
298
+
299
+ $default_settings = $this->get_settings_default( $options, $option_name );
300
+
301
+ $current_settings = get_option( $option_name );
302
+ if ( ! is_array( $current_settings ) ) $current_settings = array();
303
+ $current_settings = array_merge( $default_settings, $current_settings );
304
+
305
+ $current_settings = array_map( array( $this, 'admin_stripslashes' ), $current_settings );
306
+ $current_settings = apply_filters( $this->plugin_name . '_' . $option_name . '_get_settings' , $current_settings );
307
+
308
+ $$option_name = $current_settings;
309
+
310
+ }
311
+
312
+ // Get settings for option value is stored as a record or it's spearate option
313
+ foreach ( $options as $value ) {
314
+ if ( ! isset( $value['type'] ) ) continue;
315
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
316
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
317
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
318
+
319
+ // For way it has an option name
320
+ if ( ! isset( $value['separate_option'] ) ) $value['separate_option'] = false;
321
+
322
+ // Remove [, ] characters from id argument
323
+ if ( strstr( $value['id'], '[' ) ) {
324
+ parse_str( esc_attr( $value['id'] ), $option_array );
325
+
326
+ // Option name is first key
327
+ $option_keys = array_keys( $option_array );
328
+ $first_key = current( $option_keys );
329
+
330
+ $id_attribute = $first_key;
331
+ } else {
332
+ $id_attribute = esc_attr( $value['id'] );
333
+ }
334
+
335
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
336
+ global $$id_attribute;
337
+
338
+ $current_setting = get_option( $id_attribute, $value['default'] );
339
+
340
+ switch ( $value['type'] ) {
341
+
342
+ // Array textfields
343
+ case 'wp_editor' :
344
+ if ( is_array( $current_setting ) )
345
+ $current_setting = array_map( array( $this, 'stripslashes' ), $current_setting );
346
+ elseif ( ! is_null( $current_setting ) )
347
+ $current_setting = stripslashes( $current_setting );
348
+ break;
349
+
350
+ default:
351
+
352
+ if ( is_array( $current_setting ) )
353
+ $current_setting = array_map( array( $this, 'admin_stripslashes' ), $current_setting );
354
+ elseif ( ! is_null( $current_setting ) )
355
+ $current_setting = esc_attr( stripslashes( $current_setting ) );
356
+ break;
357
+ }
358
+
359
+ $current_setting = apply_filters( $this->plugin_name . '_' . $id_attribute . '_get_setting' , $current_setting );
360
+
361
+ $$id_attribute = $current_setting;
362
+ }
363
+ }
364
+
365
+ // :)
366
+ if ( ! isset( $this->is_free_plugin ) || ! $this->is_free_plugin ) {
367
+ $fs = array( 0 => 'c', 1 => 'p', 2 => 'h', 3 => 'i', 4 => 'e', 5 => 'n', 6 => 'k', 7 => '_' );
368
+ $cs = array( 0 => 'U', 1 => 'g', 2 => 'p', 3 => 'r', 4 => 'd', 5 => 'a', 6 => 'e', 7 => '_' );
369
+ $check_settings_save = true;
370
+ if ( isset( $this->class_name ) && ! class_exists( $this->class_name . $cs[7] . $cs[0] . $cs[2] . $cs[1] . $cs[3] . $cs[5] . $cs[4] . $cs[6] ) ) {
371
+ $check_settings_save = false;
372
+ }
373
+ if ( ! function_exists( $this->plugin_name . $fs[7] . $fs[0] . $fs[2] . $fs[4] . $fs[0] . $fs[6] . $fs[7] . $fs[1] . $fs[3] . $fs[5] ) ) {
374
+ $check_settings_save = false;
375
+ }
376
+ if ( ! $check_settings_save ) {
377
+
378
+ if ( trim( $option_name ) != '' ) {
379
+ update_option( $option_name, $new_settings );
380
+ $$option_name = $new_settings;
381
+ }
382
+
383
+ foreach ( $options as $value ) {
384
+ if ( ! isset( $value['type'] ) ) continue;
385
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
386
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
387
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
388
+ if ( ! isset( $value['free_version'] ) ) $value['free_version'] = false;
389
+
390
+ // For way it has an option name
391
+ if ( ! isset( $value['separate_option'] ) ) $value['separate_option'] = false;
392
+
393
+ // Remove [, ] characters from id argument
394
+ if ( strstr( $value['id'], '[' ) ) {
395
+ parse_str( esc_attr( $value['id'] ), $option_array );
396
+
397
+ // Option name is first key
398
+ $option_keys = array_keys( $option_array );
399
+ $first_key = current( $option_keys );
400
+
401
+ $id_attribute = $first_key;
402
+ } else {
403
+ $id_attribute = esc_attr( $value['id'] );
404
+ }
405
+
406
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
407
+ update_option( $id_attribute, $new_single_setting );
408
+ $$id_attribute = $new_single_setting;
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ return true;
415
+
416
+ }
417
+
418
+ /*-----------------------------------------------------------------------------------*/
419
+ /* Save Settings Function - save_settings */
420
+ /*-----------------------------------------------------------------------------------*/
421
+
422
+ public function save_settings( $options, $option_name = '' ) {
423
+
424
+ if ( !is_array( $options ) || count( $options ) < 1 ) return;
425
+
426
+ if ( empty( $_POST ) ) return false;
427
+
428
+ $update_options = array();
429
+ $update_separate_options = array();
430
+ //var_dump($_POST);
431
+
432
+ // Get settings for option value is stored as a record or it's spearate option
433
+ foreach ( $options as $value ) {
434
+ if ( ! isset( $value['type'] ) ) continue;
435
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
436
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
437
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
438
+
439
+ // For way it has an option name
440
+ if ( ! isset( $value['separate_option'] ) ) $value['separate_option'] = false;
441
+
442
+ // Remove [, ] characters from id argument
443
+ $key = false;
444
+ if ( strstr( $value['id'], '[' ) ) {
445
+ parse_str( esc_attr( $value['id'] ), $option_array );
446
+
447
+ // Option name is first key
448
+ $option_keys = array_keys( $option_array );
449
+ $first_key = current( $option_keys );
450
+
451
+ $id_attribute = $first_key;
452
+
453
+ $key = key( $option_array[ $id_attribute ] );
454
+ } else {
455
+ $id_attribute = esc_attr( $value['id'] );
456
+ }
457
+
458
+ // Get the option name
459
+ $option_value = null;
460
+
461
+ switch ( $value['type'] ) {
462
+
463
+ // Checkbox type
464
+ case 'checkbox' :
465
+ case 'onoff_checkbox' :
466
+ case 'switcher_checkbox' :
467
+
468
+ if ( ! isset( $value['checked_value'] ) ) $value['checked_value'] = 1;
469
+ if ( ! isset( $value['unchecked_value'] ) ) $value['unchecked_value'] = 0;
470
+
471
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
472
+ if ( $key != false ) {
473
+ if ( isset( $_POST[ $id_attribute ][ $key ] ) ) {
474
+ $option_value = $value['checked_value'];
475
+ } else {
476
+ $option_value = $value['unchecked_value'];
477
+ }
478
+ } else {
479
+ if ( isset( $_POST[ $id_attribute ] ) ) {
480
+ $option_value = $value['checked_value'];
481
+ } else {
482
+ $option_value = $value['unchecked_value'];
483
+ }
484
+ }
485
+
486
+ } else {
487
+ if ( $key != false ) {
488
+ if ( isset( $_POST[ $option_name ][ $id_attribute ][ $key ] ) ) {
489
+ $option_value = $value['checked_value'];
490
+ } else {
491
+ $option_value = $value['unchecked_value'];
492
+ }
493
+ } else {
494
+ if ( isset( $_POST[ $option_name ][ $id_attribute ] ) ) {
495
+ $option_value = $value['checked_value'];
496
+ } else {
497
+ $option_value = $value['unchecked_value'];
498
+ }
499
+ }
500
+ }
501
+
502
+ break;
503
+
504
+ // Array textfields
505
+ case 'array_textfields' :
506
+ if ( !isset( $value['ids'] ) || !is_array( $value['ids'] ) || count( $value['ids'] ) < 1 ) break;
507
+
508
+ foreach ( $value['ids'] as $text_field ) {
509
+ if ( ! isset( $text_field['id'] ) || trim( $text_field['id'] ) == '' ) continue;
510
+ if ( ! isset( $text_field['default'] ) ) $text_field['default'] = '';
511
+
512
+ // Remove [, ] characters from id argument
513
+ $key = false;
514
+ if ( strstr( $text_field['id'], '[' ) ) {
515
+ parse_str( esc_attr( $text_field['id'] ), $option_array );
516
+
517
+ // Option name is first key
518
+ $option_keys = array_keys( $option_array );
519
+ $first_key = current( $option_keys );
520
+
521
+ $id_attribute = $first_key;
522
+
523
+ $key = key( $option_array[ $id_attribute ] );
524
+ } else {
525
+ $id_attribute = esc_attr( $text_field['id'] );
526
+ }
527
+
528
+ // Get the option name
529
+ $option_value = null;
530
+
531
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
532
+ if ( $key != false ) {
533
+ if ( isset( $_POST[ $id_attribute ][ $key ] ) ) {
534
+ $option_value = $_POST[ $id_attribute ][ $key ];
535
+ } else {
536
+ $option_value = '';
537
+ }
538
+ } else {
539
+ if ( isset( $_POST[ $id_attribute ] ) ) {
540
+ $option_value = $_POST[ $id_attribute ];
541
+ } else {
542
+ $option_value = '';
543
+ }
544
+ }
545
+
546
+ } else {
547
+ if ( $key != false ) {
548
+ if ( isset( $_POST[ $option_name ][ $id_attribute ][ $key ] ) ) {
549
+ $option_value = $_POST[ $option_name ][ $id_attribute ][ $key ];
550
+ } else {
551
+ $option_value = '';
552
+ }
553
+ } else {
554
+ if ( isset( $_POST[ $option_name ][ $id_attribute ] ) ) {
555
+ $option_value = $_POST[ $option_name ][ $id_attribute ];
556
+ } else {
557
+ $option_value = '';
558
+ }
559
+ }
560
+ }
561
+
562
+ if ( strstr( $text_field['id'], '[' ) ) {
563
+ // Set keys and value
564
+ $key = key( $option_array[ $id_attribute ] );
565
+
566
+ $update_options[ $id_attribute ][ $key ] = $option_value;
567
+
568
+ if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
569
+ $update_separate_options[ $id_attribute ][ $key ] = $option_value;
570
+ }
571
+
572
+ } else {
573
+ $update_options[ $id_attribute ] = $option_value;
574
+
575
+ if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
576
+ $update_separate_options[ $id_attribute ] = $option_value;
577
+ }
578
+ }
579
+ }
580
+
581
+ break;
582
+
583
+ // Other types
584
+ default :
585
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
586
+ if ( $key != false ) {
587
+ if ( isset( $_POST[ $id_attribute ][ $key ] ) ) {
588
+ $option_value = $_POST[ $id_attribute ][ $key ];
589
+ } else {
590
+ $option_value = '';
591
+ }
592
+ } else {
593
+ if ( isset( $_POST[ $id_attribute ] ) ) {
594
+ $option_value = $_POST[ $id_attribute ];
595
+ } else {
596
+ $option_value = '';
597
+ }
598
+ }
599
+
600
+ } else {
601
+ if ( $key != false ) {
602
+ if ( isset( $_POST[ $option_name ][ $id_attribute ][ $key ] ) ) {
603
+ $option_value = $_POST[ $option_name ][ $id_attribute ][ $key ];
604
+ } else {
605
+ $option_value = '';
606
+ }
607
+ } else {
608
+ if ( isset( $_POST[ $option_name ][ $id_attribute ] ) ) {
609
+ $option_value = $_POST[ $option_name ][ $id_attribute ];
610
+ } else {
611
+ $option_value = '';
612
+ }
613
+ }
614
+ }
615
+
616
+ break;
617
+
618
+ }
619
+
620
+ if ( !in_array( $value['type'], array( 'array_textfields' ) ) ) {
621
+ if ( strstr( $value['id'], '[' ) ) {
622
+ // Set keys and value
623
+ $key = key( $option_array[ $id_attribute ] );
624
+
625
+ $update_options[ $id_attribute ][ $key ] = $option_value;
626
+
627
+ if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
628
+ $update_separate_options[ $id_attribute ][ $key ] = $option_value;
629
+ }
630
+
631
+ } else {
632
+ $update_options[ $id_attribute ] = $option_value;
633
+
634
+ if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
635
+ $update_separate_options[ $id_attribute ] = $option_value;
636
+ }
637
+ }
638
+ }
639
+
640
+ }
641
+
642
+ // Save settings for option values is an array and it's in single option name for all settings
643
+ if ( trim( $option_name ) != '' ) {
644
+ update_option( $option_name, $update_options );
645
+ }
646
+
647
+ // Save options if each option save in a row
648
+ if ( count( $update_options ) > 0 && trim( $option_name ) == '' ) {
649
+ foreach ( $update_options as $name => $value ) {
650
+ update_option( $name, $value );
651
+ }
652
+ }
653
+
654
+ // Save separate options
655
+ if ( count( $update_separate_options ) > 0 ) {
656
+ foreach ( $update_separate_options as $name => $value ) {
657
+ update_option( $name, $value );
658
+ }
659
+ }
660
+
661
+ return true;
662
+
663
+ }
664
+
665
+ /*-----------------------------------------------------------------------------------*/
666
+ /* Reset Function - reset_settings */
667
+ /*-----------------------------------------------------------------------------------*/
668
+
669
+ public function reset_settings( $options, $option_name = '', $reset = false, $free_version = false ) {
670
+
671
+ if ( !is_array( $options ) || count( $options ) < 1 ) return;
672
+
673
+ // Update settings default for option values is an array and it's in single option name for all settings
674
+ if ( trim( $option_name ) != '' ) {
675
+
676
+ $default_settings = $this->get_settings_default( $options, $option_name );
677
+
678
+ $current_settings = get_option( $option_name );
679
+ if ( ! is_array( $current_settings ) ) $current_settings = array();
680
+ $current_settings = array_merge( $default_settings, $current_settings );
681
+
682
+ if ( $reset && !$free_version ) {
683
+ update_option( $option_name, $default_settings );
684
+ } else {
685
+ if ( $free_version ) {
686
+ foreach ( $options as $value ) {
687
+ if ( ! isset( $value['type'] ) ) continue;
688
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
689
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
690
+
691
+ switch ( $value['type'] ) {
692
+
693
+ // Array textfields
694
+ case 'array_textfields' :
695
+ if ( !isset( $value['ids'] ) || !is_array( $value['ids'] ) || count( $value['ids'] ) < 1 ) break;
696
+
697
+ foreach ( $value['ids'] as $text_field ) {
698
+ if ( ! isset( $text_field['id'] ) || trim( $text_field['id'] ) == '' ) continue;
699
+ if ( ! isset( $text_field['default'] ) ) $text_field['default'] = '';
700
+ if ( ! isset( $text_field['free_version'] ) ) {
701
+ if ( ! isset( $value['free_version'] ) )
702
+ $text_field['free_version'] = false;
703
+ else
704
+ $text_field['free_version'] = $value['free_version'];
705
+ }
706
+ if ( $text_field['free_version'] ) unset( $default_settings[ $text_field['id']] );
707
+ }
708
+
709
+ break;
710
+
711
+ default :
712
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
713
+ if ( ! isset( $value['free_version'] ) ) $value['free_version'] = false;
714
+ if ( $value['free_version'] ) unset( $default_settings[ $value['id']] );
715
+
716
+ break;
717
+ }
718
+ }
719
+
720
+ $current_settings = array_merge( $current_settings, $default_settings );
721
+ update_option( $option_name, $current_settings );
722
+ } else {
723
+ update_option( $option_name, $current_settings );
724
+ }
725
+ }
726
+
727
+ }
728
+
729
+ // Update settings default for option value is stored as a record or it's spearate option
730
+ foreach ( $options as $value ) {
731
+ if ( ! isset( $value['type'] ) ) continue;
732
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
733
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
734
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
735
+ if ( ! isset( $value['free_version'] ) ) $value['free_version'] = false;
736
+
737
+ // For way it has an option name
738
+ if ( ! isset( $value['separate_option'] ) ) $value['separate_option'] = false;
739
+
740
+ switch ( $value['type'] ) {
741
+
742
+ // Array textfields
743
+ case 'array_textfields' :
744
+ if ( !isset( $value['ids'] ) || !is_array( $value['ids'] ) || count( $value['ids'] ) < 1 ) break;
745
+
746
+ foreach ( $value['ids'] as $text_field ) {
747
+ if ( ! isset( $text_field['id'] ) || trim( $text_field['id'] ) == '' ) continue;
748
+ if ( ! isset( $text_field['default'] ) ) $text_field['default'] = '';
749
+ if ( ! isset( $text_field['free_version'] ) ) {
750
+ if ( ! isset( $value['free_version'] ) )
751
+ $text_field['free_version'] = false;
752
+ else
753
+ $text_field['free_version'] = $value['free_version'];
754
+ }
755
+
756
+ // Remove [, ] characters from id argument
757
+ if ( strstr( $text_field['id'], '[' ) ) {
758
+ parse_str( esc_attr( $text_field['id'] ), $option_array );
759
+
760
+ // Option name is first key
761
+ $option_keys = array_keys( $option_array );
762
+ $first_key = current( $option_keys );
763
+
764
+ $id_attribute = $first_key;
765
+ } else {
766
+ $id_attribute = esc_attr( $text_field['id'] );
767
+ }
768
+
769
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
770
+ if ( $reset && $text_field['free_version'] && !$free_version ) {
771
+ update_option( $id_attribute, $text_field['default'] );
772
+ } elseif ( $reset && !$text_field['free_version'] ) {
773
+ update_option( $id_attribute, $text_field['default'] );
774
+ } else {
775
+ add_option( $id_attribute, $text_field['default'] );
776
+ }
777
+ }
778
+ }
779
+
780
+ break;
781
+
782
+ default :
783
+ // Remove [, ] characters from id argument
784
+ if ( strstr( $value['id'], '[' ) ) {
785
+ parse_str( esc_attr( $value['id'] ), $option_array );
786
+
787
+ // Option name is first key
788
+ $option_keys = array_keys( $option_array );
789
+ $first_key = current( $option_keys );
790
+
791
+ $id_attribute = $first_key;
792
+ } else {
793
+ $id_attribute = esc_attr( $value['id'] );
794
+ }
795
+
796
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
797
+ if ( $reset && $value['free_version'] && !$free_version ) {
798
+ update_option( $id_attribute, $value['default'] );
799
+ } elseif ( $reset && !$value['free_version'] ) {
800
+ update_option( $id_attribute, $value['default'] );
801
+ } else {
802
+ add_option( $id_attribute, $value['default'] );
803
+ }
804
+ }
805
+
806
+ break;
807
+ }
808
+
809
+ }
810
+
811
+ }
812
+
813
+ /*-----------------------------------------------------------------------------------*/
814
+ /* Get Option Value Function - settings_get_option */
815
+ /* Just called for when each option has an option value for settings
816
+ /*-----------------------------------------------------------------------------------*/
817
+
818
+ public function settings_get_option( $option_name, $default = '' ) {
819
+ // Array value
820
+ if ( strstr( $option_name, '[' ) ) {
821
+
822
+ parse_str( $option_name, $option_array );
823
+
824
+ // Option name is first key
825
+ $option_keys = array_keys( $option_array );
826
+ $option_name = current( $option_keys );
827
+
828
+ // Get value
829
+ $option_values = get_option( $option_name, '' );
830
+
831
+ $key = key( $option_array[ $option_name ] );
832
+
833
+ if ( isset( $option_values[ $key ] ) )
834
+ $option_value = $option_values[ $key ];
835
+ else
836
+ $option_value = null;
837
+
838
+ // Single value
839
+ } else {
840
+ $option_value = get_option( $option_name, null );
841
+ }
842
+
843
+ if ( is_array( $option_value ) )
844
+ $option_value = array_map( 'stripslashes', $option_value );
845
+ elseif ( ! is_null( $option_value ) )
846
+ $option_value = stripslashes( $option_value );
847
+
848
+ return $option_value === null ? $default : $option_value;
849
+ }
850
+
851
+ /**
852
+ * Output admin fields.
853
+ *
854
+ *
855
+ * @access public
856
+ * @param array $options : Opens array to output
857
+ * @param text $form_key : It's unique key for form to get correct save and reset action for this form
858
+ * @param text $option_name : Save all settings as array into database for a single option name
859
+ * @param array $form_messages : { 'success_message' => '', 'error_message' => '', 'reset_message' => '' }
860
+ * @return void
861
+ * ========================================================================
862
+ * Option Array Structure :
863
+ * type => heading | text | email | number | password | color | textarea | select | multiselect | radio | onoff_radio | checkbox | onoff_checkbox
864
+ * | switcher_checkbox | image_size | single_select_page | typography | border | border_styles | border_corner | box_shadow
865
+ * | slider | upload | wp_editor | array_textfields |
866
+ *
867
+ * id => text
868
+ * name => text
869
+ * free_version => true | false : if Yes then when save settings with $free_version = true, it does reset this option
870
+ * class => text
871
+ * css => text
872
+ * default => text : apply for other types
873
+ * array( 'width' => '125', 'height' => '125', 'crop' => 1 ) : apply image_size only
874
+ * array( 'size' => '9px', 'face' => 'Arial', 'style' => 'normal', 'color' => '#515151' ) : apply for typography only
875
+ * array( 'width' => '1px', 'style' => 'normal', 'color' => '#515151', 'corner' => 'rounded' | 'square' , 'top_left_corner' => 3,
876
+ * 'top_right_corner' => 3, 'bottom_left_corner' => 3, 'bottom_right_corner' => 3 ) : apply for border only
877
+ * array( 'width' => '1px', 'style' => 'normal', 'color' => '#515151' ) : apply for border_styles only
878
+ * array( 'corner' => 'rounded' | 'square' , 'top_left_corner' => 3, 'top_right_corner' => 3, 'bottom_left_corner' => 3,
879
+ * 'bottom_right_corner' => 3 ) : apply for border_corner only
880
+ * array( 'enable' => 1|0, 'h_shadow' => '5px' , 'v_shadow' => '5px', 'blur' => '2px' , 'spread' => '2px', 'color' => '#515151',
881
+ * 'inset' => '' | 'insert' ) : apply for box_shadow only
882
+ *
883
+ * desc => text
884
+ * desc_tip => text
885
+ * separate_option => true | false
886
+ * custom_attributes => array
887
+ * view_doc => allowed html code : apply for heading only
888
+ * placeholder => text : apply for input, email, number, password, textarea, select, multiselect and single_select_page
889
+ * hide_if_checked => true | false : apply for checkbox only
890
+ * show_if_checked => true | false : apply for checkbox only
891
+ * checkboxgroup => start | end : apply for checkbox only
892
+ * checked_value => text : apply for checkbox, onoff_checkbox, switcher_checkbox only ( it's value set to database when checkbox is checked )
893
+ * unchecked_value => text : apply for checkbox, onoff_checkbox, switcher_checkbox only ( it's value set to database when checkbox is unchecked )
894
+ * checked_label => text : apply for onoff_checkbox, switcher_checkbox only ( set it to show the text instead ON word default )
895
+ * unchecked_label => text : apply for onoff_checkbox, switcher_checkbox only ( set it to show the text instead OFF word default )
896
+ * options => array : apply for select, multiselect, radio types
897
+ *
898
+ * onoff_options => array : apply for onoff_radio only
899
+ * ---------------- example ---------------------
900
+ * array(
901
+ * array( 'val' => 1,
902
+ * 'text' => 'Top',
903
+ * 'checked_label' => 'ON',
904
+ * 'unchecked_value' => 'OFF' ),
905
+ *
906
+ * array( 'val' => 2,
907
+ * 'text' => 'Bottom',
908
+ * 'checked_label' => 'ON',
909
+ * 'unchecked_value' => 'OFF' ),
910
+ * )
911
+ * ---------------------------------------------
912
+ *
913
+ * args => array : apply for single_select_page only
914
+ * min => number : apply for slider, border, border_corner types only
915
+ * max => number : apply for slider, border, border_corner types only
916
+ * increment => number : apply for slider, border, border_corner types only
917
+ * textarea_rows => number : apply for wp_editor type only
918
+ *
919
+ * ids => array : apply for array_textfields only
920
+ * ---------------- example ---------------------
921
+ * array(
922
+ * array( 'id' => 'box_margin_top',
923
+ * 'name' => 'Top',
924
+ * 'class' => '',
925
+ * 'css' => 'width:40px;',
926
+ * 'default' => '10px' ),
927
+ *
928
+ * array( 'id' => 'box_margin_top',
929
+ * 'name' => 'Top',
930
+ * 'class' => '',
931
+ * 'css' => 'width:40px;',
932
+ * 'default' => '10px' ),
933
+ * )
934
+ * ---------------------------------------------
935
+ *
936
+ */
937
+
938
+ public function admin_forms( $options, $form_key, $option_name = '', $form_messages = array() ) {
939
+ global $a3_lazy_load_fonts_face, $a3_lazy_load_uploader, $current_subtab;
940
+
941
+ $new_settings = array(); $new_single_setting = ''; // :)
942
+ $admin_message = '';
943
+
944
+ if ( isset( $_POST['form_name_action'] ) && $_POST['form_name_action'] == $form_key ) {
945
+
946
+ do_action( $this->plugin_name . '_before_settings_save_reset' );
947
+ do_action( $this->plugin_name . '-' . trim( $form_key ) . '_before_settings_save' );
948
+
949
+ // Save settings action
950
+ if ( isset( $_POST['bt_save_settings'] ) ) {
951
+ $this->save_settings( $options, $option_name );
952
+ $admin_message = $this->get_success_message( ( isset( $form_messages['success_message'] ) ) ? $form_messages['success_message'] : '' );
953
+ }
954
+ // Reset settings action
955
+ elseif ( isset( $_POST['bt_reset_settings'] ) ) {
956
+ $this->reset_settings( $options, $option_name, true );
957
+ $admin_message = $this->get_success_message( ( isset( $form_messages['reset_message'] ) ) ? $form_messages['reset_message'] : '' );
958
+ }
959
+
960
+ do_action( $this->plugin_name . '-' . trim( $form_key ) . '_after_settings_save' );
961
+ do_action( $this->plugin_name . '_after_settings_save_reset' );
962
+ }
963
+ do_action( $this->plugin_name . '-' . trim( $form_key ) . '_settings_init' );
964
+ do_action( $this->plugin_name . '_settings_init' );
965
+
966
+ $option_values = array();
967
+ if ( trim( $option_name ) != '' ) {
968
+ $option_values = get_option( $option_name, array() );
969
+ if ( is_array( $option_values ) )
970
+ $option_values = array_map( array( $this, 'admin_stripslashes' ), $option_values );
971
+ else
972
+ $option_values = array();
973
+
974
+ $default_settings = $this->get_settings_default( $options, $option_name );
975
+
976
+ $option_values = array_merge($default_settings, $option_values);
977
+ }
978
+
979
+ if ( !is_array( $options ) || count( $options ) < 1 ) return '';
980
+ ?>
981
+
982
+ <?php echo $admin_message; ?>
983
+ <div class="a3rev_panel_container" style="visibility:hidden; height:0; overflow:hidden;" >
984
+ <form action="" method="post">
985
+ <?php do_action( $this->plugin_name . '-' . trim( $form_key ) . '_settings_start' ); ?>
986
+ <?php
987
+ $count_heading = 0;
988
+ $end_heading_id = false;
989
+
990
+ foreach ( $options as $value ) {
991
+ if ( ! isset( $value['type'] ) ) continue;
992
+ if ( ! isset( $value['id'] ) ) $value['id'] = '';
993
+ if ( ! isset( $value['name'] ) ) $value['name'] = '';
994
+ if ( ! isset( $value['class'] ) ) $value['class'] = '';
995
+ if ( ! isset( $value['css'] ) ) $value['css'] = '';
996
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
997
+ if ( ! isset( $value['desc'] ) ) $value['desc'] = '';
998
+ if ( ! isset( $value['desc_tip'] ) ) $value['desc_tip'] = false;
999
+ if ( ! isset( $value['placeholder'] ) ) $value['placeholder'] = '';
1000
+
1001
+ // For way it has an option name
1002
+ if ( ! isset( $value['separate_option'] ) ) $value['separate_option'] = false;
1003
+
1004
+ // Custom attribute handling
1005
+ $custom_attributes = array();
1006
+
1007
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) )
1008
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value )
1009
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
1010
+
1011
+ // Description handling
1012
+ if ( $value['desc_tip'] === true ) {
1013
+ $description = '';
1014
+ $tip = $value['desc'];
1015
+ } elseif ( ! empty( $value['desc_tip'] ) ) {
1016
+ $description = $value['desc'];
1017
+ $tip = $value['desc_tip'];
1018
+ } elseif ( ! empty( $value['desc'] ) ) {
1019
+ $description = $value['desc'];
1020
+ $tip = '';
1021
+ } else {
1022
+ $description = $tip = '';
1023
+ }
1024
+
1025
+ if ( $description && in_array( $value['type'], array( 'textarea', 'radio', 'onoff_radio', 'typography', 'border', 'border_styles', 'border_corner', 'box_shadow', 'array_textfields', 'wp_editor', 'upload' ) ) ) {
1026
+ $description = '<div class="desc" style="margin-bottom:5px;">' . wp_kses_post( $description ) . '</div>';
1027
+ } elseif ( $description ) {
1028
+ $description = '<span class="description" style="margin-left:5px;">' . wp_kses_post( $description ) . '</span>';
1029
+ }
1030
+
1031
+ /**
1032
+ * Add Default value into description and description tip if it has shortcode :
1033
+ * [default_value] : apply for normal types
1034
+ *
1035
+ * [default_value_width] : apply for image_size type
1036
+ * [default_value_height] : apply for image_size type
1037
+ *
1038
+ * [default_value_size] : apply for typography type
1039
+ * [default_value_face] : apply for typography type
1040
+ * [default_value_style] : apply for typography, border, border_styles types
1041
+ * [default_value_color] : apply for typography, border, border_styles types
1042
+ *
1043
+ * [default_value_width] : apply for border, border_styles types
1044
+ * [default_value_rounded_value]: apply for border, border_corner types
1045
+ * [default_value_top_left_corner]: apply for border, border_corner types
1046
+ * [default_value_top_right_corner]: apply for border, border_corner types
1047
+ * [default_value_bottom_left_corner]: apply for border, border_corner types
1048
+ * [default_value_bottom_right_corner]: apply for border, border_corner types
1049
+ */
1050
+ if ( $value['type'] == 'image_size' ) {
1051
+ if ( ! is_array( $value['default'] ) ) $value['default'] = array();
1052
+ if ( ! isset( $value['default']['width'] ) ) $value['default']['width'] = '';
1053
+ if ( ! isset( $value['default']['height'] ) ) $value['default']['height'] = '';
1054
+ if ( ! isset( $value['default']['crop'] ) ) $value['default']['crop'] = 1;
1055
+
1056
+ $description = str_replace( '[default_value_width]', $value['default']['width'], $description );
1057
+ $description = str_replace( '[default_value_height]', $value['default']['height'], $description );
1058
+ } elseif ( $value['type'] == 'typography' ) {
1059
+ if ( ! is_array( $value['default'] ) ) $value['default'] = array();
1060
+ if ( ! isset( $value['default']['size'] ) ) $value['default']['size'] = '';
1061
+ if ( ! isset( $value['default']['face'] ) ) $value['default']['face'] = '';
1062
+ if ( ! isset( $value['default']['style'] ) ) $value['default']['style'] = '';
1063
+ if ( ! isset( $value['default']['color'] ) || trim( $value['default']['color'] ) == '' ) $value['default']['color'] = '#515151';
1064
+
1065
+ $description = str_replace( '[default_value_size]', $value['default']['size'], $description );
1066
+ $description = str_replace( '[default_value_face]', $value['default']['face'], $description );
1067
+ $description = str_replace( '[default_value_style]', $value['default']['style'], $description );
1068
+ $description = str_replace( '[default_value_color]', $value['default']['color'], $description );
1069
+ } elseif ( in_array( $value['type'], array( 'border', 'border_styles', 'border_corner' ) ) ) {
1070
+ if ( ! is_array( $value['default'] ) ) $value['default'] = array();
1071
+
1072
+ if ( ! isset( $value['default']['width'] ) ) $value['default']['width'] = '';
1073
+ if ( ! isset( $value['default']['style'] ) ) $value['default']['style'] = '';
1074
+ if ( ! isset( $value['default']['color'] ) || trim( $value['default']['color'] ) == '' ) $value['default']['color'] = '#515151';
1075
+
1076
+ if ( ! isset( $value['default']['corner'] ) ) $value['default']['corner'] = 'rounded';
1077
+ if ( ! isset( $value['default']['rounded_value'] ) ) $value['default']['rounded_value'] = '';
1078
+ if ( ! isset( $value['default']['top_left_corner'] ) ) $value['default']['top_left_corner'] = $value['default']['rounded_value'];
1079
+ if ( ! isset( $value['default']['top_right_corner'] ) ) $value['default']['top_right_corner'] = $value['default']['rounded_value'];
1080
+ if ( ! isset( $value['default']['bottom_left_corner'] ) ) $value['default']['bottom_left_corner'] = $value['default']['rounded_value'];
1081
+ if ( ! isset( $value['default']['bottom_right_corner'] ) ) $value['default']['bottom_right_corner'] = $value['default']['rounded_value'];
1082
+
1083
+ $description = str_replace( '[default_value_width]', $value['default']['width'], $description );
1084
+ $description = str_replace( '[default_value_style]', $value['default']['style'], $description );
1085
+ $description = str_replace( '[default_value_color]', $value['default']['color'], $description );
1086
+ $description = str_replace( '[default_value_rounded_value]', $value['default']['rounded_value'], $description );
1087
+ $description = str_replace( '[default_value_top_left_corner]', $value['default']['top_left_corner'], $description );
1088
+ $description = str_replace( '[default_value_top_right_corner]', $value['default']['top_right_corner'], $description );
1089
+ $description = str_replace( '[default_value_bottom_left_corner]', $value['default']['bottom_left_corner'], $description );
1090
+ $description = str_replace( '[default_value_bottom_right_corner]', $value['default']['bottom_right_corner'], $description );
1091
+ } elseif ( $value['type'] == 'box_shadow' ) {
1092
+ if ( ! is_array( $value['default'] ) ) $value['default'] = array();
1093
+ if ( ! isset( $value['default']['enable'] ) || trim( $value['default']['enable'] ) == '' ) $value['default']['enable'] = 0;
1094
+ if ( ! isset( $value['default']['color'] ) || trim( $value['default']['color'] ) == '' ) $value['default']['color'] = '#515151';
1095
+ if ( ! isset( $value['default']['h_shadow'] ) || trim( $value['default']['h_shadow'] ) == '' ) $value['default']['h_shadow'] = '0px';
1096
+ if ( ! isset( $value['default']['v_shadow'] ) || trim( $value['default']['v_shadow'] ) == '' ) $value['default']['v_shadow'] = '0px';
1097
+ if ( ! isset( $value['default']['blur'] ) || trim( $value['default']['blur'] ) == '' ) $value['default']['blur'] = '0px';
1098
+ if ( ! isset( $value['default']['spread'] ) || trim( $value['default']['spread'] ) == '' ) $value['default']['spread'] = '0px';
1099
+ if ( ! isset( $value['default']['inset'] ) || trim( $value['default']['inset'] ) == '' ) $value['default']['inset'] = '';
1100
+
1101
+ $description = str_replace( '[default_value_color]', $value['default']['color'], $description );
1102
+ $description = str_replace( '[default_value_h_shadow]', $value['default']['h_shadow'], $description );
1103
+ $description = str_replace( '[default_value_v_shadow]', $value['default']['v_shadow'], $description );
1104
+ $description = str_replace( '[default_value_blur]', $value['default']['blur'], $description );
1105
+ $description = str_replace( '[default_value_spread]', $value['default']['spread'], $description );
1106
+
1107
+ } elseif ( $value['type'] != 'multiselect' ) {
1108
+ $description = str_replace( '[default_value]', $value['default'], $description );
1109
+ }
1110
+
1111
+ if ( $tip && in_array( $value['type'], array( 'checkbox' ) ) ) {
1112
+
1113
+ $tip = '<p class="description">' . $tip . '</p>';
1114
+
1115
+ } elseif ( $tip ) {
1116
+
1117
+ $tip = '<div class="help_tip a3-plugin-ui-icon a3-plugin-ui-help-icon" data-tip="' . esc_attr( $tip ) . '"></div>';
1118
+
1119
+ }
1120
+
1121
+ // Remove [, ] characters from id argument
1122
+ $key = false;
1123
+ if ( strstr( $value['id'], '[' ) ) {
1124
+ parse_str( esc_attr( $value['id'] ), $option_array );
1125
+
1126
+ // Option name is first key
1127
+ $option_keys = array_keys( $option_array );
1128
+ $first_key = current( $option_keys );
1129
+
1130
+ $id_attribute = $first_key;
1131
+
1132
+ $key = key( $option_array[ $id_attribute ] );
1133
+ } else {
1134
+ $id_attribute = esc_attr( $value['id'] );
1135
+ }
1136
+
1137
+ // Get option value when option name is not parse or when it's spearate option
1138
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1139
+ $option_value = $this->settings_get_option( $value['id'], $value['default'] );
1140
+ }
1141
+ // Get option value when it's an element from option array
1142
+ else {
1143
+ if ( $key != false ) {
1144
+ $option_value = ( isset( $option_values[ $id_attribute ][ $key ] ) ) ? $option_values[ $id_attribute ][ $key ] : $value['default'];
1145
+ } else {
1146
+ $option_value = ( isset( $option_values[ $id_attribute ] ) ) ? $option_values[ $id_attribute ] : $value['default'];
1147
+ }
1148
+ }
1149
+
1150
+ // Generate name and id attributes
1151
+ if ( trim( $option_name ) == '' ) {
1152
+ $name_attribute = esc_attr( $value['id'] );
1153
+ } elseif ( $value['separate_option'] != false ) {
1154
+ $name_attribute = esc_attr( $value['id'] );
1155
+ $id_attribute = esc_attr( $option_name ) . '_' . $id_attribute;
1156
+ } else {
1157
+ // Array value
1158
+ if ( strstr( $value['id'], '[' ) ) {
1159
+ $name_attribute = esc_attr( $option_name ) . '[' . $id_attribute . ']' . str_replace( $id_attribute . '[', '[', esc_attr( $value['id'] ) );
1160
+ } else {
1161
+ $name_attribute = esc_attr( $option_name ) . '[' . esc_attr( $value['id'] ) . ']';
1162
+ }
1163
+ $id_attribute = esc_attr( $option_name ) . '_' . $id_attribute;
1164
+ }
1165
+
1166
+ // Switch based on type
1167
+ switch( $value['type'] ) {
1168
+
1169
+ // Heading
1170
+ case 'heading':
1171
+
1172
+ $count_heading++;
1173
+ if ( $count_heading > 1 ) {
1174
+ if ( trim( $end_heading_id ) != '' ) do_action( $this->plugin_name . '_settings_' . sanitize_title( $end_heading_id ) . '_end' );
1175
+ echo '</table>' . "\n\n";
1176
+ echo '</div>' . "\n\n";
1177
+ if ( trim( $end_heading_id ) != '' ) do_action( $this->plugin_name . '_settings_' . sanitize_title( $end_heading_id ) . '_after' );
1178
+ }
1179
+ if ( ! empty( $value['id'] ) )
1180
+ $end_heading_id = $value['id'];
1181
+ else
1182
+ $end_heading_id = '';
1183
+
1184
+ $view_doc = ( isset( $value['view_doc'] ) ) ? $value['view_doc'] : '';
1185
+
1186
+ if ( ! empty( $value['id'] ) ) do_action( $this->plugin_name . '_settings_' . sanitize_title( $value['id'] ) . '_before' );
1187
+
1188
+ echo '<div id="'. esc_attr( $value['id'] ) . '" class="a3rev_panel_inner '. esc_attr( $value['class'] ) .'" style="'. esc_attr( $value['css'] ) .'">' . "\n\n";
1189
+ if ( stristr( $value['class'], 'pro_feature_fields' ) !== false && ! empty( $value['id'] ) ) $this->upgrade_top_message( true, sanitize_title( $value['id'] ) );
1190
+ elseif ( stristr( $value['class'], 'pro_feature_fields' ) !== false ) $this->upgrade_top_message( true );
1191
+
1192
+ echo ( ! empty( $value['name'] ) ) ? '<h3>'. esc_html( $value['name'] ) .' '. $view_doc .'</h3>' : '';
1193
+ if ( ! empty( $value['desc'] ) ) echo wpautop( wptexturize( wp_kses_post( $value['desc'] ) ) );
1194
+ echo '<table class="form-table">' . "\n\n";
1195
+
1196
+ if ( ! empty( $value['id'] ) ) do_action( $this->plugin_name . '_settings_' . sanitize_title( $value['id'] ) . '_start' );
1197
+ break;
1198
+
1199
+ // Standard text inputs and subtypes like 'number'
1200
+ case 'text':
1201
+ case 'email':
1202
+ case 'number':
1203
+ case 'password' :
1204
+
1205
+ $type = $value['type'];
1206
+
1207
+ ?><tr valign="top">
1208
+ <th scope="row" class="titledesc">
1209
+ <?php echo $tip; ?>
1210
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1211
+ </th>
1212
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1213
+ <input
1214
+ name="<?php echo $name_attribute; ?>"
1215
+ id="<?php echo $id_attribute; ?>"
1216
+ type="<?php echo esc_attr( $type ); ?>"
1217
+ style="<?php echo esc_attr( $value['css'] ); ?>"
1218
+ value="<?php echo esc_attr( $option_value ); ?>"
1219
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?> <?php echo esc_attr( $value['class'] ); ?>"
1220
+ placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
1221
+ <?php echo implode( ' ', $custom_attributes ); ?>
1222
+ /> <?php echo $description; ?>
1223
+ </td>
1224
+ </tr><?php
1225
+ break;
1226
+
1227
+ // Color
1228
+ case 'color' :
1229
+
1230
+ if ( trim( $value['default'] ) == '' ) $value['default'] = '#515151';
1231
+ $default_color = ' data-default-color="' . esc_attr( $value['default'] ) . '"';
1232
+
1233
+ ?><tr valign="top">
1234
+ <th scope="row" class="titledesc">
1235
+ <?php echo $tip; ?>
1236
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1237
+ </th>
1238
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1239
+ <input
1240
+ name="<?php echo $name_attribute; ?>"
1241
+ id="<?php echo $id_attribute; ?>"
1242
+ type="text"
1243
+ value="<?php echo esc_attr( $option_value ); ?>"
1244
+ class="a3rev-color-picker"
1245
+ <?php echo $default_color; ?>
1246
+ /> <?php echo $description; ?>
1247
+ </td>
1248
+ </tr><?php
1249
+
1250
+ break;
1251
+
1252
+ // Textarea
1253
+ case 'textarea':
1254
+
1255
+ ?><tr valign="top">
1256
+ <th scope="row" class="titledesc">
1257
+ <?php echo $tip; ?>
1258
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1259
+ </th>
1260
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1261
+ <?php echo $description; ?>
1262
+
1263
+ <textarea
1264
+ name="<?php echo $name_attribute; ?>"
1265
+ id="<?php echo $id_attribute; ?>"
1266
+ style="<?php echo esc_attr( $value['css'] ); ?>"
1267
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?> <?php echo esc_attr( $value['class'] ); ?>"
1268
+ placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
1269
+ <?php echo implode( ' ', $custom_attributes ); ?>
1270
+ ><?php echo esc_textarea( $option_value ); ?></textarea>
1271
+ </td>
1272
+ </tr><?php
1273
+ break;
1274
+
1275
+ // Select boxes
1276
+ case 'select' :
1277
+ case 'multiselect' :
1278
+
1279
+ if ( trim( $value['class'] ) == '' ) $value['class'] = 'chzn-select';
1280
+ if ( is_rtl() ) {
1281
+ $value['class'] .= ' chzn-rtl';
1282
+ }
1283
+ if ( ! isset( $value['options'] ) ) $value['options'] = array();
1284
+
1285
+ ?><tr valign="top">
1286
+ <th scope="row" class="titledesc">
1287
+ <?php echo $tip; ?>
1288
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1289
+ </th>
1290
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1291
+ <select
1292
+ name="<?php echo $name_attribute; ?><?php if ( $value['type'] == 'multiselect' ) echo '[]'; ?>"
1293
+ id="<?php echo $id_attribute; ?>"
1294
+ style="<?php echo esc_attr( $value['css'] ); ?>"
1295
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?> <?php echo esc_attr( $value['class'] ); ?>"
1296
+ data-placeholder="<?php echo esc_html( $value['placeholder'] ); ?>"
1297
+ <?php echo implode( ' ', $custom_attributes ); ?>
1298
+ <?php if ( $value['type'] == 'multiselect' ) echo 'multiple="multiple"'; ?>
1299
+ >
1300
+ <?php
1301
+ if ( is_array( $value['options'] ) && count( $value['options'] ) > 0 ) {
1302
+ foreach ( $value['options'] as $key => $val ) {
1303
+ ?>
1304
+ <option value="<?php echo esc_attr( $key ); ?>" <?php
1305
+
1306
+ if ( is_array( $option_value ) )
1307
+ selected( in_array( $key, $option_value ), true );
1308
+ else
1309
+ selected( $option_value, $key );
1310
+
1311
+ ?>><?php echo $val ?></option>
1312
+ <?php
1313
+ }
1314
+ }
1315
+ ?>
1316
+ </select> <?php echo $description; ?>
1317
+ </td>
1318
+ </tr><?php
1319
+ break;
1320
+
1321
+ // Radio inputs
1322
+ case 'radio' :
1323
+
1324
+ if ( ! isset( $value['options'] ) ) $value['options'] = array();
1325
+
1326
+ ?><tr valign="top">
1327
+ <th scope="row" class="titledesc">
1328
+ <?php echo $tip; ?>
1329
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1330
+ </th>
1331
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1332
+ <fieldset>
1333
+ <?php echo $description; ?>
1334
+ <ul>
1335
+ <?php
1336
+ if ( is_array( $value['options'] ) && count( $value['options'] ) > 0 ) {
1337
+ foreach ( $value['options'] as $val => $text ) {
1338
+ ?>
1339
+ <li>
1340
+ <label><input
1341
+ name="<?php echo $name_attribute; ?>"
1342
+ value="<?php echo $val; ?>"
1343
+ type="radio"
1344
+ style="<?php echo esc_attr( $value['css'] ); ?>"
1345
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?> <?php echo esc_attr( $value['class'] ); ?>"
1346
+ <?php echo implode( ' ', $custom_attributes ); ?>
1347
+ <?php checked( $val, $option_value ); ?>
1348
+ /> <span class="description" style="margin-left:5px;"><?php echo $text ?></span></label>
1349
+ </li>
1350
+ <?php
1351
+ }
1352
+ }
1353
+ ?>
1354
+ </ul>
1355
+ </fieldset>
1356
+ </td>
1357
+ </tr><?php
1358
+ break;
1359
+
1360
+ // OnOff Radio inputs
1361
+ case 'onoff_radio' :
1362
+
1363
+ if ( ! isset( $value['onoff_options'] ) ) $value['onoff_options'] = array();
1364
+
1365
+ ?><tr valign="top">
1366
+ <th scope="row" class="titledesc">
1367
+ <?php echo $tip; ?>
1368
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1369
+ </th>
1370
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1371
+ <fieldset>
1372
+ <?php echo $description; ?>
1373
+ <ul>
1374
+ <?php
1375
+ if ( is_array( $value['onoff_options'] ) && count( $value['onoff_options'] ) > 0 ) {
1376
+ foreach ( $value['onoff_options'] as $i_option ) {
1377
+ if ( ! isset( $i_option['checked_label'] ) ) $i_option['checked_label'] = __( 'ON', 'a3_lazy_load' );
1378
+ if ( ! isset( $i_option['unchecked_label'] ) ) $i_option['unchecked_label'] = __( 'OFF', 'a3_lazy_load' );
1379
+ if ( ! isset( $i_option['val'] ) ) $i_option['val'] = 1;
1380
+ if ( ! isset( $i_option['text'] ) ) $i_option['text'] = '';
1381
+ ?>
1382
+ <li>
1383
+ <input
1384
+ name="<?php echo $name_attribute; ?>"
1385
+ <?php if ( $i_option['val'] == $option_value ) echo ' checkbox-disabled="true" ' ; ?>
1386
+ class="a3rev-ui-onoff_radio <?php echo esc_attr( $value['class'] ); ?>"
1387
+ checked_label="<?php echo esc_html( $i_option['checked_label'] ); ?>"
1388
+ unchecked_label="<?php echo esc_html( $i_option['unchecked_label'] ); ?>"
1389
+ type="radio"
1390
+ value="<?php echo esc_attr( stripslashes( $i_option['val'] ) ); ?>"
1391
+ <?php checked( esc_attr( stripslashes( $i_option['val'] ) ), $option_value ); ?>
1392
+ <?php echo implode( ' ', $custom_attributes ); ?>
1393
+ /> <span class="description" style="margin-left:5px;"><?php echo $i_option['text'] ?></span>
1394
+ </li>
1395
+ <?php
1396
+ }
1397
+ }
1398
+ ?>
1399
+ </ul>
1400
+ </fieldset>
1401
+ </td>
1402
+ </tr><?php
1403
+ break;
1404
+
1405
+ // Checkbox input
1406
+ case 'checkbox' :
1407
+
1408
+ if ( ! isset( $value['checked_value'] ) ) $value['checked_value'] = 1;
1409
+ if ( ! isset( $value['hide_if_checked'] ) ) $value['hide_if_checked'] = false;
1410
+ if ( ! isset( $value['show_if_checked'] ) ) $value['show_if_checked'] = false;
1411
+
1412
+ if ( ! isset( $value['checkboxgroup'] ) || ( isset( $value['checkboxgroup'] ) && $value['checkboxgroup'] == 'start' ) ) {
1413
+ ?>
1414
+ <tr valign="top" class="<?php
1415
+ if ( $value['hide_if_checked'] == 'yes' || $value['show_if_checked']=='yes') echo 'hidden_option';
1416
+ if ( $value['hide_if_checked'] == 'option' ) echo 'hide_options_if_checked';
1417
+ if ( $value['show_if_checked'] == 'option' ) echo 'show_options_if_checked';
1418
+ ?>">
1419
+ <th scope="row" class="titledesc">
1420
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1421
+ </th>
1422
+ <td class="forminp forminp-checkbox">
1423
+ <fieldset>
1424
+ <?php
1425
+ } else {
1426
+ ?>
1427
+ <fieldset class="<?php
1428
+ if ( $value['hide_if_checked'] == 'yes' || $value['show_if_checked'] == 'yes') echo 'hidden_option';
1429
+ if ( $value['hide_if_checked'] == 'option') echo 'hide_options_if_checked';
1430
+ if ( $value['show_if_checked'] == 'option') echo 'show_options_if_checked';
1431
+ ?>">
1432
+ <?php
1433
+ }
1434
+
1435
+ ?>
1436
+ <legend class="screen-reader-text"><span><?php echo esc_html( $value['name'] ) ?></span></legend>
1437
+
1438
+ <label for="<?php echo $id_attribute; ?>">
1439
+ <input
1440
+ name="<?php echo $name_attribute; ?>"
1441
+ id="<?php echo $id_attribute; ?>"
1442
+ type="checkbox"
1443
+ value="<?php echo esc_attr( stripslashes( $value['checked_value'] ) ); ?>"
1444
+ <?php checked( $option_value, esc_attr( stripslashes( $value['checked_value'] ) ) ); ?>
1445
+ <?php echo implode( ' ', $custom_attributes ); ?>
1446
+ /> <?php echo $description; ?></label> <?php echo $tip; ?>
1447
+ <?php
1448
+
1449
+ if ( ! isset( $value['checkboxgroup'] ) || ( isset( $value['checkboxgroup'] ) && $value['checkboxgroup'] == 'end' ) ) {
1450
+ ?>
1451
+ </fieldset>
1452
+ </td>
1453
+ </tr>
1454
+ <?php
1455
+ } else {
1456
+ ?>
1457
+ </fieldset>
1458
+ <?php
1459
+ }
1460
+
1461
+ break;
1462
+
1463
+ // OnOff Checkbox input
1464
+ case 'onoff_checkbox' :
1465
+
1466
+ if ( ! isset( $value['checked_value'] ) ) $value['checked_value'] = 1;
1467
+ if ( ! isset( $value['checked_label'] ) ) $value['checked_label'] = __( 'ON', 'a3_lazy_load' );
1468
+ if ( ! isset( $value['unchecked_label'] ) ) $value['unchecked_label'] = __( 'OFF', 'a3_lazy_load' );
1469
+
1470
+ ?><tr valign="top">
1471
+ <th scope="row" class="titledesc">
1472
+ <?php echo $tip; ?>
1473
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1474
+ </th>
1475
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1476
+ <input
1477
+ name="<?php echo $name_attribute; ?>"
1478
+ id="<?php echo $id_attribute; ?>"
1479
+ class="a3rev-ui-onoff_checkbox <?php echo esc_attr( $value['class'] ); ?>"
1480
+ checked_label="<?php echo esc_html( $value['checked_label'] ); ?>"
1481
+ unchecked_label="<?php echo esc_html( $value['unchecked_label'] ); ?>"
1482
+ type="checkbox"
1483
+ value="<?php echo esc_attr( stripslashes( $value['checked_value'] ) ); ?>"
1484
+ <?php checked( $option_value, esc_attr( stripslashes( $value['checked_value'] ) ) ); ?>
1485
+ <?php echo implode( ' ', $custom_attributes ); ?>
1486
+ /> <?php echo $description; ?>
1487
+ </td>
1488
+ </tr><?php
1489
+
1490
+ break;
1491
+
1492
+ // Switcher Checkbox input
1493
+ case 'switcher_checkbox' :
1494
+
1495
+ if ( ! isset( $value['checked_value'] ) ) $value['checked_value'] = 1;
1496
+ if ( ! isset( $value['checked_label'] ) ) $value['checked_label'] = __( 'ON', 'a3_lazy_load' );
1497
+ if ( ! isset( $value['unchecked_label'] ) ) $value['unchecked_label'] = __( 'OFF', 'a3_lazy_load' );
1498
+
1499
+ ?><tr valign="top">
1500
+ <th scope="row" class="titledesc">
1501
+ <?php echo $tip; ?>
1502
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
1503
+ </th>
1504
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1505
+ <input
1506
+ name="<?php echo $name_attribute; ?>"
1507
+ id="<?php echo $id_attribute; ?>"
1508
+ class="a3rev-ui-onoff_checkbox <?php echo esc_attr( $value['class'] ); ?>"
1509
+ checked_label="<?php echo esc_html( $value['checked_label'] ); ?>"
1510
+ unchecked_label="<?php echo esc_html( $value['unchecked_label'] ); ?>"
1511
+ type="checkbox"
1512
+ value="<?php echo esc_attr( stripslashes( $value['checked_value'] ) ); ?>"
1513
+ <?php checked( $option_value, esc_attr( stripslashes( $value['checked_value'] ) ) ); ?>
1514
+ <?php echo implode( ' ', $custom_attributes ); ?>
1515
+ /> <?php echo $description; ?>
1516
+ </td>
1517
+ </tr><?php
1518
+
1519
+ break;
1520
+
1521
+ // Image size settings
1522
+ case 'image_size' :
1523
+
1524
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1525
+ $width = $this->settings_get_option( $value['id'] . '[width]', $value['default']['width'] );
1526
+ $height = $this->settings_get_option( $value['id'] . '[height]', $value['default']['height'] );
1527
+ $crop = checked( 1, $this->settings_get_option( $value['id'] . '[crop]', $value['default']['crop'] ), false );
1528
+ } else {
1529
+ $width = $option_value['width'];
1530
+ $height = $option_value['height'];
1531
+ $crop = checked( 1, $option_value['crop'], false );
1532
+ }
1533
+
1534
+ ?><tr valign="top">
1535
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
1536
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
1537
+
1538
+ <label><?php _e( 'Width', 'a3_lazy_load' ); ?> <input name="<?php echo $name_attribute; ?>[width]" id="<?php echo $id_attribute; ?>-width" type="text" class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-width" value="<?php echo $width; ?>" /></label>
1539
+
1540
+ <label><?php _e( 'Height', 'a3_lazy_load' ); ?> <input name="<?php echo $name_attribute; ?>[height]" id="<?php echo $id_attribute; ?>-height" type="text" class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-height" value="<?php echo $height; ?>" /></label>
1541
+
1542
+ <label><?php _e( 'Hard Crop', 'a3_lazy_load' ); ?> <input name="<?php echo $name_attribute; ?>[crop]" id="<?php echo $id_attribute; ?>-crop" type="checkbox" class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-crop" <?php echo $crop; ?> /></label>
1543
+
1544
+ </td>
1545
+ </tr><?php
1546
+ break;
1547
+
1548
+ // Single page selects
1549
+ case 'single_select_page' :
1550
+
1551
+ if ( trim( $value['class'] ) == '' ) $value['class'] = 'chzn-select-deselect';
1552
+ if ( is_rtl() ) {
1553
+ $value['class'] .= ' chzn-rtl';
1554
+ }
1555
+
1556
+ $args = array( 'name' => $name_attribute,
1557
+ 'id' => $id_attribute,
1558
+ 'sort_column' => 'menu_order',
1559
+ 'sort_order' => 'ASC',
1560
+ 'show_option_none' => ' ',
1561
+ 'class' => 'a3rev-ui-' . sanitize_title( $value['type'] ) . ' ' . $value['class'],
1562
+ 'echo' => false,
1563
+ 'selected' => absint( $option_value )
1564
+ );
1565
+
1566
+ if( isset( $value['args'] ) )
1567
+ $args = wp_parse_args( $value['args'], $args );
1568
+
1569
+ ?><tr valign="top">
1570
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
1571
+ <td class="forminp">
1572
+ <?php echo str_replace(' id=', " data-placeholder='" . esc_html( $value['placeholder'] ) . "' style='" . $value['css'] . "' class='" . $value['class'] . "' id=", wp_dropdown_pages( $args ) ); ?> <?php echo $description; ?>
1573
+ </td>
1574
+ </tr><?php
1575
+ break;
1576
+
1577
+ // Font Control
1578
+ case 'typography':
1579
+
1580
+ $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
1581
+
1582
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1583
+ $size = $this->settings_get_option( $value['id'] . '[size]', $value['default']['size'] );
1584
+ $face = $this->settings_get_option( $value['id'] . '[face]', $value['default']['face'] );
1585
+ $style = $this->settings_get_option( $value['id'] . '[style]', $value['default']['style'] );
1586
+ $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
1587
+ } else {
1588
+ $size = $option_value['size'];
1589
+ $face = $option_value['face'];
1590
+ $style = $option_value['style'];
1591
+ $color = $option_value['color'];
1592
+ }
1593
+
1594
+ ?><tr valign="top">
1595
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
1596
+ <td class="forminp">
1597
+ <?php echo $description; ?>
1598
+ <div class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-control">
1599
+ <!-- Font Size -->
1600
+ <select
1601
+ name="<?php echo $name_attribute; ?>[size]"
1602
+ id="<?php echo $id_attribute; ?>-size"
1603
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-size chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1604
+ >
1605
+ <?php
1606
+ for ( $i = 6; $i <= 70; $i++ ) {
1607
+ ?>
1608
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
1609
+ selected( $size, $i.'px' );
1610
+ ?>><?php echo esc_attr( $i ); ?>px</option>
1611
+ <?php
1612
+ }
1613
+ ?>
1614
+ </select>
1615
+
1616
+ <!-- Font Face -->
1617
+ <select
1618
+ name="<?php echo $name_attribute; ?>[face]"
1619
+ id="<?php echo $id_attribute; ?>-face"
1620
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-face chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1621
+ >
1622
+ <optgroup label="<?php _e( '-- Default Fonts --', 'a3_lazy_load' ); ?>">
1623
+ <?php
1624
+ foreach ( $a3_lazy_load_fonts_face->get_default_fonts() as $val => $text ) {
1625
+ ?>
1626
+ <option value="<?php echo esc_attr( $val ); ?>" <?php
1627
+ selected( esc_attr( $val ), esc_attr( $face ) );
1628
+ ?>><?php echo esc_attr( $text ); ?></option>
1629
+ <?php
1630
+ }
1631
+ ?>
1632
+ </optgroup>
1633
+ <optgroup label="<?php _e( '-- Google Fonts --', 'a3_lazy_load' ); ?>">
1634
+ <?php
1635
+ foreach ( $a3_lazy_load_fonts_face->get_google_fonts() as $font ) {
1636
+ ?>
1637
+ <option value="<?php echo esc_attr( $font['name'] ); ?>" <?php
1638
+ selected( esc_attr( $font['name'] ), esc_attr( $face ) );
1639
+ ?>><?php echo esc_attr( $font['name'] ); ?></option>
1640
+ <?php
1641
+ }
1642
+ ?>
1643
+ </optgroup>
1644
+ </select>
1645
+
1646
+ <!-- Font Weight -->
1647
+ <select
1648
+ name="<?php echo $name_attribute; ?>[style]"
1649
+ id="<?php echo $id_attribute; ?>-style"
1650
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-style chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1651
+ >
1652
+ <?php
1653
+ foreach ( $this->get_font_weights() as $val => $text ) {
1654
+ ?>
1655
+ <option value="<?php echo esc_attr( $val ); ?>" <?php
1656
+ selected( esc_attr( $val ), esc_attr( $style ) );
1657
+ ?>><?php echo esc_attr( $text ); ?></option>
1658
+ <?php
1659
+ }
1660
+ ?>
1661
+ </select>
1662
+
1663
+ <!-- Font Color -->
1664
+ <input
1665
+ name="<?php echo $name_attribute; ?>[color]"
1666
+ id="<?php echo $id_attribute; ?>-color"
1667
+ type="text"
1668
+ value="<?php echo esc_attr( $color ); ?>"
1669
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?>-color a3rev-color-picker"
1670
+ <?php echo $default_color; ?>
1671
+ />
1672
+
1673
+ <!-- Preview Button -->
1674
+ <div class="a3rev-ui-typography-preview"><a href="#" class="a3rev-ui-typography-preview-button button submit-button" title="<?php _e( 'Preview your customized typography settings', 'a3_lazy_load'); ?>"><span>&nbsp;</span></a></div>
1675
+
1676
+ </div>
1677
+
1678
+ </td>
1679
+ </tr><?php
1680
+
1681
+ break;
1682
+
1683
+ // Border Styles & Corner Control
1684
+ case 'border':
1685
+
1686
+ if ( ! is_array( $value['default'] ) ) $value['default'] = array();
1687
+
1688
+ // For Border Styles
1689
+ $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
1690
+
1691
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1692
+ $width = $this->settings_get_option( $value['id'] . '[width]', $value['default']['width'] );
1693
+ $style = $this->settings_get_option( $value['id'] . '[style]', $value['default']['style'] );
1694
+ $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
1695
+ } else {
1696
+ $width = $option_value['width'];
1697
+ $style = $option_value['style'];
1698
+ $color = $option_value['color'];
1699
+ }
1700
+
1701
+ // For Border Corner
1702
+ if ( ! isset( $value['min'] ) ) $value['min'] = 0;
1703
+ if ( ! isset( $value['max'] ) ) $value['max'] = 100;
1704
+ if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
1705
+
1706
+ if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
1707
+ $corner = $this->settings_get_option( $value['id'] . '[corner]', $value['default']['corner'] );
1708
+
1709
+ if ( ! isset( $value['default']['rounded_value'] ) ) $value['default']['rounded_value'] = 3;
1710
+ $rounded_value = $this->settings_get_option( $value['id'] . '[rounded_value]', $value['default']['rounded_value'] );
1711
+
1712
+ if ( ! isset( $value['default']['top_left_corner'] ) ) $value['default']['top_left_corner'] = 3;
1713
+ $top_left_corner = $this->settings_get_option( $value['id'] . '[top_left_corner]', $value['default']['top_left_corner'] );
1714
+
1715
+ if ( ! isset( $value['default']['top_right_corner'] ) ) $value['default']['top_right_corner'] = 3;
1716
+ $top_right_corner = $this->settings_get_option( $value['id'] . '[top_right_corner]', $value['default']['top_right_corner'] );
1717
+
1718
+ if ( ! isset( $value['default']['bottom_left_corner'] ) ) $value['default']['bottom_left_corner'] = 3;
1719
+ $bottom_left_corner = $this->settings_get_option( $value['id'] . '[bottom_left_corner]', $value['default']['bottom_left_corner'] );
1720
+
1721
+ if ( ! isset( $value['default']['bottom_right_corner'] ) ) $value['default']['bottom_right_corner'] = 3;
1722
+ $bottom_right_corner = $this->settings_get_option( $value['id'] . '[bottom_right_corner]', $value['default']['bottom_right_corner'] );
1723
+ } else {
1724
+ if ( ! isset( $option_value['corner'] ) ) $option_value['corner'] = '';
1725
+ $corner = $option_value['corner'];
1726
+
1727
+ if ( ! isset( $option_value['rounded_value'] ) ) $option_value['rounded_value'] = 3;
1728
+ $rounded_value = $option_value['rounded_value'];
1729
+
1730
+ if ( ! isset( $option_value['top_left_corner'] ) ) $option_value['top_left_corner'] = 3;
1731
+ $top_left_corner = $option_value['top_left_corner'];
1732
+
1733
+ if ( ! isset( $option_value['top_right_corner'] ) ) $option_value['top_right_corner'] = 3;
1734
+ $top_right_corner = $option_value['top_right_corner'];
1735
+
1736
+ if ( ! isset( $option_value['bottom_left_corner'] ) ) $option_value['bottom_left_corner'] = 3;
1737
+ $bottom_left_corner = $option_value['bottom_left_corner'];
1738
+
1739
+ if ( ! isset( $option_value['bottom_right_corner'] ) ) $option_value['bottom_right_corner'] = 3;
1740
+ $bottom_right_corner = $option_value['bottom_right_corner'];
1741
+ }
1742
+
1743
+ if ( trim( $rounded_value ) == '' || trim( $rounded_value ) <= 0 ) $rounded_value = $value['min'];
1744
+ $rounded_value = intval( $rounded_value );
1745
+
1746
+ if ( trim( $top_left_corner ) == '' || trim( $top_left_corner ) <= 0 ) $top_left_corner = $rounded_value;
1747
+ $top_left_corner = intval( $top_left_corner );
1748
+
1749
+ if ( trim( $top_right_corner ) == '' || trim( $top_right_corner ) <= 0 ) $top_right_corner = $rounded_value;
1750
+ $top_right_corner = intval( $top_right_corner );
1751
+
1752
+ if ( trim( $bottom_left_corner ) == '' || trim( $bottom_left_corner ) <= 0 ) $bottom_left_corner = $rounded_value;
1753
+ $bottom_left_corner = intval( $bottom_left_corner );
1754
+
1755
+ if ( trim( $bottom_right_corner ) == '' || trim( $bottom_right_corner ) <= 0 ) $bottom_right_corner = $rounded_value;
1756
+ $bottom_right_corner = intval( $bottom_right_corner );
1757
+
1758
+ ?><tr valign="top">
1759
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
1760
+ <td class="forminp forminp-border_corner">
1761
+ <?php echo $description; ?>
1762
+ <div class="a3rev-ui-settings-control">
1763
+ <!-- Border Width -->
1764
+ <select
1765
+ name="<?php echo $name_attribute; ?>[width]"
1766
+ id="<?php echo $id_attribute; ?>-width"
1767
+ class="a3rev-ui-border_styles-width chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1768
+ >
1769
+ <?php
1770
+ for ( $i = 0; $i <= 20; $i++ ) {
1771
+ ?>
1772
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
1773
+ selected( $width, $i.'px' );
1774
+ ?>><?php echo esc_attr( $i ); ?>px</option>
1775
+ <?php
1776
+ }
1777
+ ?>
1778
+ </select>
1779
+
1780
+ <!-- Border Style -->
1781
+ <select
1782
+ name="<?php echo $name_attribute; ?>[style]"
1783
+ id="<?php echo $id_attribute; ?>-style"
1784
+ class="a3rev-ui-border_styles-style chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1785
+ >
1786
+ <?php
1787
+ foreach ( $this->get_border_styles() as $val => $text ) {
1788
+ ?>
1789
+ <option value="<?php echo esc_attr( $val ); ?>" <?php
1790
+ selected( esc_attr( $val ), esc_attr( $style ) );
1791
+ ?>><?php echo esc_attr( $text ); ?></option>
1792
+ <?php
1793
+ }
1794
+ ?>
1795
+ </select>
1796
+
1797
+ <!-- Border Color -->
1798
+ <input
1799
+ name="<?php echo $name_attribute; ?>[color]"
1800
+ id="<?php echo $id_attribute; ?>-color"
1801
+ type="text"
1802
+ value="<?php echo esc_attr( $color ); ?>"
1803
+ class="a3rev-ui-border_styles-color a3rev-color-picker"
1804
+ <?php echo $default_color; ?>
1805
+ />
1806
+
1807
+ <!-- Preview Button -->
1808
+ <div class="a3rev-ui-settings-preview"><a href="#" class="a3rev-ui-border-preview-button a3rev-ui-settings-preview-button button submit-button" title="<?php _e( 'Preview your customized border settings', 'a3_lazy_load'); ?>"><span>&nbsp;</span></a></div>
1809
+
1810
+ <div style="clear:both; margin-bottom:10px"></div>
1811
+
1812
+ <!-- Border Corner : Rounded or Square -->
1813
+ <input
1814
+ name="<?php echo $name_attribute; ?>[corner]"
1815
+ id="<?php echo $id_attribute; ?>"
1816
+ class="a3rev-ui-border-corner a3rev-ui-onoff_checkbox <?php echo esc_attr( $value['class'] ); ?>"
1817
+ checked_label="<?php _e( 'Rounded', 'a3_lazy_load' ); ?>"
1818
+ unchecked_label="<?php _e( 'Square', 'a3_lazy_load' ); ?>"
1819
+ type="checkbox"
1820
+ value="rounded"
1821
+ <?php checked( 'rounded', $corner ); ?>
1822
+ <?php echo implode( ' ', $custom_attributes ); ?>
1823
+ />
1824
+
1825
+ <!-- Border Rounded Value -->
1826
+ <div class="a3rev-ui-border-corner-value-container">
1827
+ <div class="a3rev-ui-border_corner-top_left">
1828
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Top Left Corner', 'a3_lazy_load' ); ?></span>
1829
+ <div class="a3rev-ui-slide-container">
1830
+ <div class="a3rev-ui-slide-container-start">
1831
+ <div class="a3rev-ui-slide-container-end">
1832
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-top_left_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
1833
+ </div>
1834
+ </div>
1835
+ <div class="a3rev-ui-slide-result-container">
1836
+ <input
1837
+ readonly="readonly"
1838
+ name="<?php echo $name_attribute; ?>[top_left_corner]"
1839
+ id="<?php echo $id_attribute; ?>-top_left_corner"
1840
+ type="text"
1841
+ value="<?php echo esc_attr( $top_left_corner ); ?>"
1842
+ class="a3rev-ui-border_top_left_corner a3rev-ui-slider"
1843
+ /> <span class="a3rev-ui-border_corner-px">px</span>
1844
+ </div>
1845
+ </div>
1846
+ </div>
1847
+ <div class="a3rev-ui-border_corner-top_right">
1848
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Top Right Corner', 'a3_lazy_load' ); ?></span>
1849
+ <div class="a3rev-ui-slide-container">
1850
+ <div class="a3rev-ui-slide-container-start">
1851
+ <div class="a3rev-ui-slide-container-end">
1852
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-top_right_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
1853
+ </div>
1854
+ </div>
1855
+ <div class="a3rev-ui-slide-result-container">
1856
+ <input
1857
+ readonly="readonly"
1858
+ name="<?php echo $name_attribute; ?>[top_right_corner]"
1859
+ id="<?php echo $id_attribute; ?>-top_right_corner"
1860
+ type="text"
1861
+ value="<?php echo esc_attr( $top_right_corner ); ?>"
1862
+ class="a3rev-ui-border_top_right_corner a3rev-ui-slider"
1863
+ /> <span class="a3rev-ui-border_corner-px">px</span>
1864
+ </div>
1865
+ </div>
1866
+ </div>
1867
+ <div class="a3rev-ui-border_corner-bottom_right">
1868
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Bottom Right Corner', 'a3_lazy_load' ); ?></span>
1869
+ <div class="a3rev-ui-slide-container">
1870
+ <div class="a3rev-ui-slide-container-start">
1871
+ <div class="a3rev-ui-slide-container-end">
1872
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-bottom_right_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
1873
+ </div>
1874
+ </div>
1875
+ <div class="a3rev-ui-slide-result-container">
1876
+ <input
1877
+ readonly="readonly"
1878
+ name="<?php echo $name_attribute; ?>[bottom_right_corner]"
1879
+ id="<?php echo $id_attribute; ?>-bottom_right_corner"
1880
+ type="text"
1881
+ value="<?php echo esc_attr( $bottom_right_corner ); ?>"
1882
+ class="a3rev-ui-border_bottom_right_corner a3rev-ui-slider"
1883
+ /> <span class="a3rev-ui-border_corner-px">px</span>
1884
+ </div>
1885
+ </div>
1886
+ </div>
1887
+ <div class="a3rev-ui-border_corner-bottom_left">
1888
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Bottom Left Corner', 'a3_lazy_load' ); ?></span>
1889
+ <div class="a3rev-ui-slide-container">
1890
+ <div class="a3rev-ui-slide-container-start">
1891
+ <div class="a3rev-ui-slide-container-end">
1892
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-bottom_left_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
1893
+ </div>
1894
+ </div>
1895
+ <div class="a3rev-ui-slide-result-container">
1896
+ <input
1897
+ readonly="readonly"
1898
+ name="<?php echo $name_attribute; ?>[bottom_left_corner]"
1899
+ id="<?php echo $id_attribute; ?>-bottom_left_corner"
1900
+ type="text"
1901
+ value="<?php echo esc_attr( $bottom_left_corner ); ?>"
1902
+ class="a3rev-ui-border_bottom_left_corner a3rev-ui-slider"
1903
+ /> <span class="a3rev-ui-border_corner-px">px</span>
1904
+ </div>
1905
+ </div>
1906
+ </div>
1907
+ </div>
1908
+ <div style="clear:both"></div>
1909
+ </div>
1910
+
1911
+ </td>
1912
+ </tr><?php
1913
+
1914
+ break;
1915
+
1916
+ // Border Style Control
1917
+ case 'border_styles':
1918
+
1919
+ $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
1920
+
1921
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
1922
+ $width = $this->settings_get_option( $value['id'] . '[width]', $value['default']['width'] );
1923
+ $style = $this->settings_get_option( $value['id'] . '[style]', $value['default']['style'] );
1924
+ $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
1925
+ } else {
1926
+ $width = $option_value['width'];
1927
+ $style = $option_value['style'];
1928
+ $color = $option_value['color'];
1929
+ }
1930
+
1931
+ ?><tr valign="top">
1932
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
1933
+ <td class="forminp">
1934
+ <?php echo $description; ?>
1935
+ <div class="a3rev-ui-settings-control">
1936
+ <!-- Border Width -->
1937
+ <select
1938
+ name="<?php echo $name_attribute; ?>[width]"
1939
+ id="<?php echo $id_attribute; ?>-width"
1940
+ class="a3rev-ui-border_styles-width chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1941
+ >
1942
+ <?php
1943
+ for ( $i = 0; $i <= 20; $i++ ) {
1944
+ ?>
1945
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
1946
+ selected( $width, $i.'px' );
1947
+ ?>><?php echo esc_attr( $i ); ?>px</option>
1948
+ <?php
1949
+ }
1950
+ ?>
1951
+ </select>
1952
+
1953
+ <!-- Border Style -->
1954
+ <select
1955
+ name="<?php echo $name_attribute; ?>[style]"
1956
+ id="<?php echo $id_attribute; ?>-style"
1957
+ class="a3rev-ui-border_styles-style chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
1958
+ >
1959
+ <?php
1960
+ foreach ( $this->get_border_styles() as $val => $text ) {
1961
+ ?>
1962
+ <option value="<?php echo esc_attr( $val ); ?>" <?php
1963
+ selected( esc_attr( $val ), esc_attr( $style ) );
1964
+ ?>><?php echo esc_attr( $text ); ?></option>
1965
+ <?php
1966
+ }
1967
+ ?>
1968
+ </select>
1969
+
1970
+ <!-- Border Color -->
1971
+ <input
1972
+ name="<?php echo $name_attribute; ?>[color]"
1973
+ id="<?php echo $id_attribute; ?>-color"
1974
+ type="text"
1975
+ value="<?php echo esc_attr( $color ); ?>"
1976
+ class="a3rev-ui-border_styles-color a3rev-color-picker"
1977
+ <?php echo $default_color; ?>
1978
+ />
1979
+
1980
+ <!-- Preview Button -->
1981
+ <div class="a3rev-ui-settings-preview"><a href="#" class="a3rev-ui-border-preview-button a3rev-ui-settings-preview-button button submit-button" title="<?php _e( 'Preview your customized border styles settings', 'a3_lazy_load'); ?>"><span>&nbsp;</span></a></div>
1982
+ </div>
1983
+
1984
+ </td>
1985
+ </tr><?php
1986
+
1987
+ break;
1988
+
1989
+ // Border Rounded Corners Control
1990
+ case 'border_corner':
1991
+
1992
+ if ( ! isset( $value['min'] ) ) $value['min'] = 0;
1993
+ if ( ! isset( $value['max'] ) ) $value['max'] = 100;
1994
+ if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
1995
+
1996
+ if ( trim( $option_name ) != '' && $value['separate_option'] != false ) {
1997
+ $corner = $this->settings_get_option( $value['id'] . '[corner]', $value['default']['corner'] );
1998
+
1999
+ if ( ! isset( $value['default']['rounded_value'] ) ) $value['default']['rounded_value'] = 3;
2000
+ $rounded_value = $this->settings_get_option( $value['id'] . '[rounded_value]', $value['default']['rounded_value'] );
2001
+
2002
+ if ( ! isset( $value['default']['top_left_corner'] ) ) $value['default']['top_left_corner'] = 3;
2003
+ $top_left_corner = $this->settings_get_option( $value['id'] . '[top_left_corner]', $value['default']['top_left_corner'] );
2004
+
2005
+ if ( ! isset( $value['default']['top_right_corner'] ) ) $value['default']['top_right_corner'] = 3;
2006
+ $top_right_corner = $this->settings_get_option( $value['id'] . '[top_right_corner]', $value['default']['top_right_corner'] );
2007
+
2008
+ if ( ! isset( $value['default']['bottom_left_corner'] ) ) $value['default']['bottom_left_corner'] = 3;
2009
+ $bottom_left_corner = $this->settings_get_option( $value['id'] . '[bottom_left_corner]', $value['default']['bottom_left_corner'] );
2010
+
2011
+ if ( ! isset( $value['default']['bottom_right_corner'] ) ) $value['default']['bottom_right_corner'] = 3;
2012
+ $bottom_right_corner = $this->settings_get_option( $value['id'] . '[bottom_right_corner]', $value['default']['bottom_right_corner'] );
2013
+ } else {
2014
+ if ( ! isset( $option_value['corner'] ) ) $option_value['corner'] = '';
2015
+ $corner = $option_value['corner'];
2016
+
2017
+ if ( ! isset( $option_value['rounded_value'] ) ) $option_value['rounded_value'] = 3;
2018
+ $rounded_value = $option_value['rounded_value'];
2019
+
2020
+ if ( ! isset( $option_value['top_left_corner'] ) ) $option_value['top_left_corner'] = 3;
2021
+ $top_left_corner = $option_value['top_left_corner'];
2022
+
2023
+ if ( ! isset( $option_value['top_right_corner'] ) ) $option_value['top_right_corner'] = 3;
2024
+ $top_right_corner = $option_value['top_right_corner'];
2025
+
2026
+ if ( ! isset( $option_value['bottom_left_corner'] ) ) $option_value['bottom_left_corner'] = 3;
2027
+ $bottom_left_corner = $option_value['bottom_left_corner'];
2028
+
2029
+ if ( ! isset( $option_value['bottom_right_corner'] ) ) $option_value['bottom_right_corner'] = 3;
2030
+ $bottom_right_corner = $option_value['bottom_right_corner'];
2031
+ }
2032
+
2033
+ if ( trim( $rounded_value ) == '' || trim( $rounded_value ) <= 0 ) $rounded_value = $value['min'];
2034
+ $rounded_value = intval( $rounded_value );
2035
+
2036
+ if ( trim( $top_left_corner ) == '' || trim( $top_left_corner ) <= 0 ) $top_left_corner = $rounded_value;
2037
+ $top_left_corner = intval( $top_left_corner );
2038
+
2039
+ if ( trim( $top_right_corner ) == '' || trim( $top_right_corner ) <= 0 ) $top_right_corner = $rounded_value;
2040
+ $top_right_corner = intval( $top_right_corner );
2041
+
2042
+ if ( trim( $bottom_left_corner ) == '' || trim( $bottom_left_corner ) <= 0 ) $bottom_left_corner = $rounded_value;
2043
+ $bottom_left_corner = intval( $bottom_left_corner );
2044
+
2045
+ if ( trim( $bottom_right_corner ) == '' || trim( $bottom_right_corner ) <= 0 ) $bottom_right_corner = $rounded_value;
2046
+ $bottom_right_corner = intval( $bottom_right_corner );
2047
+
2048
+ ?><tr valign="top">
2049
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
2050
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
2051
+ <?php echo $description; ?>
2052
+ <div class="a3rev-ui-settings-control">
2053
+ <!-- Border Corner : Rounded or Square -->
2054
+ <input
2055
+ name="<?php echo $name_attribute; ?>[corner]"
2056
+ id="<?php echo $id_attribute; ?>"
2057
+ class="a3rev-ui-border-corner a3rev-ui-onoff_checkbox <?php echo esc_attr( $value['class'] ); ?>"
2058
+ checked_label="<?php _e( 'Rounded', 'a3_lazy_load' ); ?>"
2059
+ unchecked_label="<?php _e( 'Square', 'a3_lazy_load' ); ?>"
2060
+ type="checkbox"
2061
+ value="rounded"
2062
+ <?php checked( 'rounded', $corner ); ?>
2063
+ <?php echo implode( ' ', $custom_attributes ); ?>
2064
+ />
2065
+
2066
+ <!-- Preview Button -->
2067
+ <div class="a3rev-ui-settings-preview"><a href="#" class="a3rev-ui-border-preview-button a3rev-ui-settings-preview-button button submit-button" title="<?php _e( 'Preview your customized border settings', 'a3_lazy_load'); ?>"><span>&nbsp;</span></a></div>
2068
+
2069
+ <!-- Border Rounded Value -->
2070
+ <div class="a3rev-ui-border-corner-value-container">
2071
+ <div class="a3rev-ui-border_corner-top_left">
2072
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Top Left Corner', 'a3_lazy_load' ); ?></span>
2073
+ <div class="a3rev-ui-slide-container">
2074
+ <div class="a3rev-ui-slide-container-start">
2075
+ <div class="a3rev-ui-slide-container-end">
2076
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-top_left_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
2077
+ </div>
2078
+ </div>
2079
+ <div class="a3rev-ui-slide-result-container">
2080
+ <input
2081
+ readonly="readonly"
2082
+ name="<?php echo $name_attribute; ?>[top_left_corner]"
2083
+ id="<?php echo $id_attribute; ?>-top_left_corner"
2084
+ type="text"
2085
+ value="<?php echo esc_attr( $top_left_corner ); ?>"
2086
+ class="a3rev-ui-border_top_left_corner a3rev-ui-slider"
2087
+ /> <span class="a3rev-ui-border_corner-px">px</span>
2088
+ </div>
2089
+ </div>
2090
+ </div>
2091
+ <div class="a3rev-ui-border_corner-top_right">
2092
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Top Right Corner', 'a3_lazy_load' ); ?></span>
2093
+ <div class="a3rev-ui-slide-container">
2094
+ <div class="a3rev-ui-slide-container-start">
2095
+ <div class="a3rev-ui-slide-container-end">
2096
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-top_right_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
2097
+ </div>
2098
+ </div>
2099
+ <div class="a3rev-ui-slide-result-container">
2100
+ <input
2101
+ readonly="readonly"
2102
+ name="<?php echo $name_attribute; ?>[top_right_corner]"
2103
+ id="<?php echo $id_attribute; ?>-top_right_corner"
2104
+ type="text"
2105
+ value="<?php echo esc_attr( $top_right_corner ); ?>"
2106
+ class="a3rev-ui-border_top_right_corner a3rev-ui-slider"
2107
+ /> <span class="a3rev-ui-border_corner-px">px</span>
2108
+ </div>
2109
+ </div>
2110
+ </div>
2111
+ <div class="a3rev-ui-border_corner-bottom_right">
2112
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Bottom Right Corner', 'a3_lazy_load' ); ?></span>
2113
+ <div class="a3rev-ui-slide-container">
2114
+ <div class="a3rev-ui-slide-container-start">
2115
+ <div class="a3rev-ui-slide-container-end">
2116
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-bottom_right_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
2117
+ </div>
2118
+ </div>
2119
+ <div class="a3rev-ui-slide-result-container">
2120
+ <input
2121
+ readonly="readonly"
2122
+ name="<?php echo $name_attribute; ?>[bottom_right_corner]"
2123
+ id="<?php echo $id_attribute; ?>-bottom_right_corner"
2124
+ type="text"
2125
+ value="<?php echo esc_attr( $bottom_right_corner ); ?>"
2126
+ class="a3rev-ui-border_bottom_right_corner a3rev-ui-slider"
2127
+ /> <span class="a3rev-ui-border_corner-px">px</span>
2128
+ </div>
2129
+ </div>
2130
+ </div>
2131
+ <div class="a3rev-ui-border_corner-bottom_left">
2132
+ <span class="a3rev-ui-border_corner-span"><?php _e( 'Bottom Left Corner', 'a3_lazy_load' ); ?></span>
2133
+ <div class="a3rev-ui-slide-container">
2134
+ <div class="a3rev-ui-slide-container-start">
2135
+ <div class="a3rev-ui-slide-container-end">
2136
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>-bottom_left_corner_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
2137
+ </div>
2138
+ </div>
2139
+ <div class="a3rev-ui-slide-result-container">
2140
+ <input
2141
+ readonly="readonly"
2142
+ name="<?php echo $name_attribute; ?>[bottom_left_corner]"
2143
+ id="<?php echo $id_attribute; ?>-bottom_left_corner"
2144
+ type="text"
2145
+ value="<?php echo esc_attr( $bottom_left_corner ); ?>"
2146
+ class="a3rev-ui-border_bottom_left_corner a3rev-ui-slider"
2147
+ /> <span class="a3rev-ui-border_corner-px">px</span>
2148
+ </div>
2149
+ </div>
2150
+ </div>
2151
+ </div>
2152
+ <div style="clear:both"></div>
2153
+ </div>
2154
+ <div style="clear:both"></div>
2155
+ </td>
2156
+ </tr><?php
2157
+
2158
+ break;
2159
+
2160
+ // Box Shadow Control
2161
+ case 'box_shadow':
2162
+
2163
+ $default_color = ' data-default-color="' . esc_attr( $value['default']['color'] ) . '"';
2164
+
2165
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
2166
+ $enable = $this->settings_get_option( $value['id'] . '[enable]', $value['default']['enable'] );
2167
+ $h_shadow = $this->settings_get_option( $value['id'] . '[h_shadow]', $value['default']['h_shadow'] );
2168
+ $v_shadow = $this->settings_get_option( $value['id'] . '[v_shadow]', $value['default']['v_shadow'] );
2169
+ $blur = $this->settings_get_option( $value['id'] . '[blur]', $value['default']['blur'] );
2170
+ $spread = $this->settings_get_option( $value['id'] . '[spread]', $value['default']['spread'] );
2171
+ $color = $this->settings_get_option( $value['id'] . '[color]', $value['default']['color'] );
2172
+ $inset = $this->settings_get_option( $value['id'] . '[inset]', $value['default']['inset'] );
2173
+ } else {
2174
+ if ( ! isset( $option_value['enable'] ) ) $option_value['enable'] = 0;
2175
+ $enable = $option_value['enable'];
2176
+ if ( ! isset( $option_value['inset'] ) ) $option_value['inset'] = '';
2177
+ $h_shadow = $option_value['h_shadow'];
2178
+ $v_shadow = $option_value['v_shadow'];
2179
+ $blur = $option_value['blur'];
2180
+ $spread = $option_value['spread'];
2181
+ $color = $option_value['color'];
2182
+ $inset = $option_value['inset'];
2183
+ }
2184
+
2185
+ ?><tr valign="top">
2186
+ <th scope="row" class="titledesc"><?php echo $tip; ?><?php echo esc_html( $value['name'] ) ?></th>
2187
+ <td class="forminp forminp-box_shadow">
2188
+ <?php echo $description; ?>
2189
+ <input
2190
+ name="<?php echo $name_attribute; ?>[enable]"
2191
+ id="<?php echo $id_attribute; ?>"
2192
+ class="a3rev-ui-box_shadow-enable a3rev-ui-onoff_checkbox <?php echo esc_attr( $value['class'] ); ?>"
2193
+ checked_label="<?php _e( 'YES', 'a3_lazy_load' ); ?>"
2194
+ unchecked_label="<?php _e( 'NO', 'a3_lazy_load' ); ?>"
2195
+ type="checkbox"
2196
+ value="1"
2197
+ <?php checked( 1, $enable ); ?>
2198
+ <?php echo implode( ' ', $custom_attributes ); ?>
2199
+ />
2200
+ <div style="clear:both;"></div>
2201
+ <div class="a3rev-ui-box_shadow-enable-container">
2202
+ <div class="a3rev-ui-settings-control">
2203
+ <!-- Box Horizontal Shadow Size -->
2204
+ <select
2205
+ name="<?php echo $name_attribute; ?>[h_shadow]"
2206
+ id="<?php echo $id_attribute; ?>-h_shadow"
2207
+ class="a3rev-ui-box_shadow-h_shadow chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
2208
+ data-placeholder="<?php _e( 'Horizontal Shadow', 'a3_lazy_load' ); ?>"
2209
+ >
2210
+ <?php
2211
+ for ( $i = -20; $i <= 20; $i++ ) {
2212
+ ?>
2213
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
2214
+ selected( $h_shadow, $i.'px' );
2215
+ ?>><?php echo esc_attr( $i ); ?>px</option>
2216
+ <?php
2217
+ }
2218
+ ?>
2219
+ </select>
2220
+
2221
+ <!-- Box Vertical Shadow Size -->
2222
+ <select
2223
+ name="<?php echo $name_attribute; ?>[v_shadow]"
2224
+ id="<?php echo $id_attribute; ?>-v_shadow"
2225
+ class="a3rev-ui-box_shadow-v_shadow chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
2226
+ data-placeholder="<?php _e( 'Vertical Shadow', 'a3_lazy_load' ); ?>"
2227
+ >
2228
+ <?php
2229
+ for ( $i = -20; $i <= 20; $i++ ) {
2230
+ ?>
2231
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
2232
+ selected( $v_shadow, $i.'px' );
2233
+ ?>><?php echo esc_attr( $i ); ?>px</option>
2234
+ <?php
2235
+ }
2236
+ ?>
2237
+ </select>
2238
+
2239
+ <!-- Box Blur Distance -->
2240
+ <select
2241
+ name="<?php echo $name_attribute; ?>[blur]"
2242
+ id="<?php echo $id_attribute; ?>-blur"
2243
+ class="a3rev-ui-box_shadow-blur chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
2244
+ data-placeholder="<?php _e( 'Blur Distance', 'a3_lazy_load' ); ?>"
2245
+ >
2246
+ <?php
2247
+ for ( $i = 0; $i <= 20; $i++ ) {
2248
+ ?>
2249
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
2250
+ selected( $blur, $i.'px' );
2251
+ ?>><?php echo esc_attr( $i ); ?>px</option>
2252
+ <?php
2253
+ }
2254
+ ?>
2255
+ </select>
2256
+
2257
+ <!-- Box Spread -->
2258
+ <select
2259
+ name="<?php echo $name_attribute; ?>[spread]"
2260
+ id="<?php echo $id_attribute; ?>-spread"
2261
+ class="a3rev-ui-box_shadow-spread chzn-select <?php if ( is_rtl() ) { echo 'chzn-rtl'; } ?>"
2262
+ data-placeholder="<?php _e( 'Spread Size', 'a3_lazy_load' ); ?>"
2263
+ >
2264
+ <?php
2265
+ for ( $i = 0; $i <= 20; $i++ ) {
2266
+ ?>
2267
+ <option value="<?php echo esc_attr( $i ); ?>px" <?php
2268
+ selected( $spread, $i.'px' );
2269
+ ?>><?php echo esc_attr( $i ); ?>px</option>
2270
+ <?php
2271
+ }
2272
+ ?>
2273
+ </select>
2274
+
2275
+ <!-- Box Shadow Inset -->
2276
+ <input
2277
+ name="<?php echo $name_attribute; ?>[inset]"
2278
+ id="<?php echo $id_attribute; ?>"
2279
+ class="a3rev-ui-box_shadow-inset a3rev-ui-onoff_checkbox"
2280
+ checked_label="<?php _e( 'INNER', 'a3_lazy_load' ); ?>"
2281
+ unchecked_label="<?php _e( 'OUTER', 'a3_lazy_load' ); ?>"
2282
+ type="checkbox"
2283
+ value="inset"
2284
+ <?php checked( 'inset', $inset ); ?>
2285
+ <?php echo implode( ' ', $custom_attributes ); ?>
2286
+ />
2287
+
2288
+ <!-- Box Shadow Color -->
2289
+ <input
2290
+ name="<?php echo $name_attribute; ?>[color]"
2291
+ id="<?php echo $id_attribute; ?>-color"
2292
+ type="text"
2293
+ value="<?php echo esc_attr( $color ); ?>"
2294
+ class="a3rev-ui-box_shadow-color a3rev-color-picker"
2295
+ <?php echo $default_color; ?>
2296
+ />
2297
+
2298
+ <!-- Preview Button -->
2299
+ <div class="a3rev-ui-settings-preview"><a href="#" class="a3rev-ui-box_shadow-preview-button a3rev-ui-settings-preview-button button submit-button" title="<?php _e( 'Preview your customized box shadow settings', 'a3_lazy_load'); ?>"><span>&nbsp;</span></a></div>
2300
+ </div>
2301
+ <div style="clear:both;"></div>
2302
+ </div>
2303
+ </td>
2304
+ </tr><?php
2305
+
2306
+ break;
2307
+
2308
+ // Slider Control
2309
+ case 'slider':
2310
+
2311
+ if ( ! isset( $value['min'] ) ) $value['min'] = 0;
2312
+ if ( ! isset( $value['max'] ) ) $value['max'] = 100;
2313
+ if ( ! isset( $value['increment'] ) ) $value['increment'] = 1;
2314
+ if ( trim( $option_value ) == '' || trim( $option_value ) <= 0 ) $option_value = $value['min'];
2315
+ $option_value = intval( $option_value );
2316
+
2317
+ ?><tr valign="top">
2318
+ <th scope="row" class="titledesc">
2319
+ <?php echo $tip; ?>
2320
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
2321
+ </th>
2322
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
2323
+ <div class="a3rev-ui-slide-container">
2324
+ <div class="a3rev-ui-slide-container-start"><div class="a3rev-ui-slide-container-end">
2325
+ <div class="a3rev-ui-slide" id="<?php echo $id_attribute; ?>_div" min="<?php echo esc_attr( $value['min'] ); ?>" max="<?php echo esc_attr( $value['max'] ); ?>" inc="<?php echo esc_attr( $value['increment'] ); ?>"></div>
2326
+ </div></div>
2327
+ <div class="a3rev-ui-slide-result-container">
2328
+ <input
2329
+ readonly="readonly"
2330
+ name="<?php echo $name_attribute; ?>"
2331
+ id="<?php echo $id_attribute; ?>"
2332
+ type="text"
2333
+ value="<?php echo esc_attr( $option_value ); ?>"
2334
+ class="a3rev-ui-slider"
2335
+ <?php echo implode( ' ', $custom_attributes ); ?>
2336
+ /> <?php echo $description; ?>
2337
+ </div>
2338
+ </div>
2339
+ </td>
2340
+ </tr><?php
2341
+
2342
+ break;
2343
+
2344
+ // Upload Control
2345
+ case 'upload':
2346
+
2347
+ $class = 'a3rev-ui-' . sanitize_title( $value['type'] ) . ' ' . esc_attr( $value['class'] );
2348
+
2349
+ ?><tr valign="top">
2350
+ <th scope="row" class="titledesc">
2351
+ <?php echo $tip; ?>
2352
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
2353
+ </th>
2354
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
2355
+ <?php echo $description; ?>
2356
+ <?php echo $a3_lazy_load_uploader->upload_input( $name_attribute, $id_attribute, $option_value, $value['default'], esc_html( $value['name'] ), $class, esc_attr( $value['css'] ) , '' );?>
2357
+ </td>
2358
+ </tr><?php
2359
+
2360
+ break;
2361
+
2362
+ // WP Editor Control
2363
+ case 'wp_editor':
2364
+
2365
+ if ( ! isset( $value['textarea_rows'] ) ) $value['textarea_rows'] = 15;
2366
+
2367
+ ?><tr valign="top">
2368
+ <th scope="row" class="titledesc">
2369
+ <?php echo $tip; ?>
2370
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
2371
+ </th>
2372
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
2373
+ <?php echo $description; ?>
2374
+ <?php remove_all_filters('mce_external_plugins'); ?>
2375
+ <?php wp_editor( $option_value,
2376
+ $id_attribute,
2377
+ array( 'textarea_name' => $name_attribute,
2378
+ 'wpautop' => true,
2379
+ 'editor_class' => 'a3rev-ui-' . sanitize_title( $value['type'] ) . ' ' . esc_attr( $value['class'] ),
2380
+ 'textarea_rows' => $value['textarea_rows'] ) ); ?>
2381
+ </td>
2382
+ </tr><?php
2383
+
2384
+ break;
2385
+
2386
+ // Array Text Field Control
2387
+ case 'array_textfields':
2388
+
2389
+ if ( !isset( $value['ids'] ) || !is_array( $value['ids'] ) || count( $value['ids'] ) < 1 ) break;
2390
+
2391
+ ?><tr valign="top">
2392
+ <th scope="row" class="titledesc">
2393
+ <?php echo $tip; ?>
2394
+ <label for="<?php echo $id_attribute; ?>"><?php echo esc_html( $value['name'] ); ?></label>
2395
+ </th>
2396
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
2397
+ <?php echo $description; ?>
2398
+ <div class="a3rev-ui-array_textfields-container">
2399
+ <?php
2400
+ foreach ( $value['ids'] as $text_field ) {
2401
+
2402
+ if ( ! isset( $text_field['id'] ) ) $text_field['id'] = '';
2403
+ if ( ! isset( $text_field['name'] ) ) $text_field['name'] = '';
2404
+ if ( ! isset( $text_field['class'] ) ) $text_field['class'] = '';
2405
+ if ( ! isset( $text_field['css'] ) ) $text_field['css'] = '';
2406
+ if ( ! isset( $text_field['default'] ) ) $text_field['default'] = '';
2407
+
2408
+ // Remove [, ] characters from id argument
2409
+ $key = false;
2410
+ if ( strstr( $text_field['id'], '[' ) ) {
2411
+ parse_str( esc_attr( $text_field['id'] ), $option_array );
2412
+
2413
+ // Option name is first key
2414
+ $option_keys = array_keys( $option_array );
2415
+ $first_key = current( $option_keys );
2416
+
2417
+ $id_attribute = $first_key;
2418
+
2419
+ $key = key( $option_array[ $id_attribute ] );
2420
+ } else {
2421
+ $id_attribute = esc_attr( $text_field['id'] );
2422
+ }
2423
+
2424
+ // Get option value when option name is not parse or when it's spearate option
2425
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
2426
+ $option_value = $this->settings_get_option( $text_field['id'], $text_field['default'] );
2427
+ }
2428
+ // Get option value when it's an element from option array
2429
+ else {
2430
+ if ( $key != false ) {
2431
+ $option_value = ( isset( $option_values[ $id_attribute ][ $key ] ) ) ? $option_values[ $id_attribute ][ $key ] : $text_field['default'];
2432
+ } else {
2433
+ $option_value = ( isset( $option_values[ $id_attribute ] ) ) ? $option_values[ $id_attribute ] : $text_field['default'];
2434
+ }
2435
+ }
2436
+
2437
+ // Generate name and id attributes
2438
+ if ( trim( $option_name ) == '' ) {
2439
+ $name_attribute = esc_attr( $text_field['id'] );
2440
+ } elseif ( $value['separate_option'] != false ) {
2441
+ $name_attribute = esc_attr( $text_field['id'] );
2442
+ $id_attribute = esc_attr( $option_name ) . '_' . $id_attribute;
2443
+ } else {
2444
+ // Array value
2445
+ if ( strstr( $text_field['id'], '[' ) ) {
2446
+ $name_attribute = esc_attr( $option_name ) . '[' . $id_attribute . ']' . str_replace( $id_attribute . '[', '[', esc_attr( $text_field['id'] ) );
2447
+ } else {
2448
+ $name_attribute = esc_attr( $option_name ) . '[' . esc_attr( $text_field['id'] ) . ']';
2449
+ }
2450
+ $id_attribute = esc_attr( $option_name ) . '_' . $id_attribute;
2451
+ }
2452
+ ?>
2453
+ <label><input
2454
+ name="<?php echo $name_attribute; ?>"
2455
+ id="<?php echo $id_attribute; ?>"
2456
+ type="text"
2457
+ style="<?php echo esc_attr( $text_field['css'] ); ?>"
2458
+ value="<?php echo esc_attr( $option_value ); ?>"
2459
+ class="a3rev-ui-<?php echo sanitize_title( $value['type'] ) ?> <?php echo esc_attr( $text_field['class'] ); ?>"
2460
+ /> <span><?php echo esc_html( $text_field['name'] ); ?></span></label>
2461
+ <?php
2462
+ }
2463
+ ?>
2464
+ </div>
2465
+
2466
+ </td>
2467
+ </tr><?php
2468
+
2469
+ break;
2470
+
2471
+ // Default: run an action
2472
+ default:
2473
+ do_action( $this->plugin_name . '_admin_field_' . $value['type'], $value );
2474
+ break;
2475
+ }
2476
+ }
2477
+
2478
+ // :)
2479
+ if ( ! isset( $this->is_free_plugin ) || ! $this->is_free_plugin ) {
2480
+ $fs = array( 0 => 'c', 1 => 'p', 2 => 'h', 3 => 'i', 4 => 'e', 5 => 'n', 6 => 'k', 7 => '_' );
2481
+ $cs = array( 0 => 'U', 1 => 'g', 2 => 'p', 3 => 'r', 4 => 'd', 5 => 'a', 6 => 'e', 7 => '_' );
2482
+ $check_settings_save = true;
2483
+ if ( isset( $this->class_name ) && ! class_exists( $this->class_name . $cs[7] . $cs[0] . $cs[2] . $cs[1] . $cs[3] . $cs[5] . $cs[4] . $cs[6] ) ) {
2484
+ $check_settings_save = false;
2485
+ }
2486
+ if ( ! function_exists( $this->plugin_name . $fs[7] . $fs[0] . $fs[2] . $fs[4] . $fs[0] . $fs[6] . $fs[7] . $fs[1] . $fs[3] . $fs[5] ) ) {
2487
+ $check_settings_save = false;
2488
+ }
2489
+ if ( ! $check_settings_save ) {
2490
+
2491
+ if ( trim( $option_name ) != '' ) {
2492
+ update_option( $option_name, $new_settings );
2493
+ }
2494
+
2495
+ foreach ( $options as $value ) {
2496
+ if ( ! isset( $value['type'] ) ) continue;
2497
+ if ( in_array( $value['type'], array( 'heading' ) ) ) continue;
2498
+ if ( ! isset( $value['id'] ) || trim( $value['id'] ) == '' ) continue;
2499
+ if ( ! isset( $value['default'] ) ) $value['default'] = '';
2500
+ if ( ! isset( $value['free_version'] ) ) $value['free_version'] = false;
2501
+
2502
+ // For way it has an option name
2503
+ if ( ! isset( $value['separate_option'] ) ) $value['separate_option'] = false;
2504
+
2505
+ // Remove [, ] characters from id argument
2506
+ if ( strstr( $value['id'], '[' ) ) {
2507
+ parse_str( esc_attr( $value['id'] ), $option_array );
2508
+
2509
+ // Option name is first key
2510
+ $option_keys = array_keys( $option_array );
2511
+ $first_key = current( $option_keys );
2512
+
2513
+ $id_attribute = $first_key;
2514
+ } else {
2515
+ $id_attribute = esc_attr( $value['id'] );
2516
+ }
2517
+
2518
+ if ( trim( $option_name ) == '' || $value['separate_option'] != false ) {
2519
+ update_option( $id_attribute, $new_single_setting );
2520
+ }
2521
+ }
2522
+ }
2523
+ }
2524
+
2525
+ if ( $end_heading_id !== false ) {
2526
+ if ( trim( $end_heading_id ) != '' ) do_action( $this->plugin_name . '_settings_' . sanitize_title( $end_heading_id ) . '_end' );
2527
+ echo '</table>' . "\n\n";
2528
+ echo '</div>' . "\n\n";
2529
+ if ( trim( $end_heading_id ) != '' ) do_action( $this->plugin_name . '_settings_' . sanitize_title( $end_heading_id ) . '_after' );
2530
+ }
2531
+
2532
+ ?>
2533
+ <?php do_action( $this->plugin_name . '-' . trim( $form_key ) . '_settings_end' ); ?>
2534
+ <p class="submit">
2535
+ <input type="submit" value="<?php _e('Save changes', 'a3_lazy_load'); ?>" class="button button-primary" name="bt_save_settings" />
2536
+ <input type="submit" name="bt_reset_settings" class="button" value="<?php _e('Reset Settings', 'a3_lazy_load'); ?>" />
2537
+ <input type="hidden" name="form_name_action" value="<?php echo $form_key; ?>" />
2538
+ <input type="hidden" class="last_tab" name="subtab" value="#<?php echo $current_subtab; ?>" />
2539
+ </p>
2540
+
2541
+ </form>
2542
+ </div>
2543
+
2544
+ <?php
2545
+ }
2546
+
2547
+ /*-----------------------------------------------------------------------------------*/
2548
+ /* Custom Stripslashed for array in array - admin_stripslashes() */
2549
+ /*-----------------------------------------------------------------------------------*/
2550
+ public function admin_stripslashes( $values ) {
2551
+ if ( is_array( $values ) ) {
2552
+ $values = array_map( array( $this, 'admin_stripslashes' ), $values );
2553
+ } else {
2554
+ $values = esc_attr( stripslashes( $values ) );
2555
+ }
2556
+
2557
+ return $values;
2558
+ }
2559
+
2560
+ /*-----------------------------------------------------------------------------------*/
2561
+ /* generate_border_css() */
2562
+ /* Generate Border CSS on frontend */
2563
+ /*-----------------------------------------------------------------------------------*/
2564
+ public function generate_border_css( $option ) {
2565
+
2566
+ $border_css = '';
2567
+
2568
+ $border_css .= 'border: ' . esc_attr( $option['width'] ) . ' ' . esc_attr( $option['style'] ) . ' ' . esc_attr( $option['color'] ) .' !important;';
2569
+
2570
+ if ( isset( $option['corner'] ) && esc_attr( $option['corner'] ) == 'rounded' ) {
2571
+ if ( ! isset( $option['rounded_value'] ) ) $option['rounded_value'] = 0;
2572
+ if ( ! isset( $option['top_left_corner'] ) ) $option['top_left_corner'] = $option['rounded_value'];
2573
+ if ( ! isset( $option['top_right_corner'] ) ) $option['top_right_corner'] = $option['rounded_value'];
2574
+ if ( ! isset( $option['bottom_left_corner'] ) ) $option['bottom_left_corner'] = $option['rounded_value'];
2575
+ if ( ! isset( $option['bottom_right_corner'] ) ) $option['bottom_right_corner'] = $option['rounded_value'];
2576
+
2577
+ $border_css .= 'border-radius: ' . $option['top_left_corner'] . 'px ' . $option['top_right_corner'] . 'px ' . $option['bottom_right_corner'] . 'px ' . $option['bottom_left_corner'] . 'px !important;';
2578
+ $border_css .= '-moz-border-radius: ' . $option['top_left_corner'] . 'px ' . $option['top_right_corner'] . 'px ' . $option['bottom_right_corner'] . 'px ' . $option['bottom_left_corner'] . 'px !important;';
2579
+ $border_css .= '-webkit-border-radius: ' . $option['top_left_corner'] . 'px ' . $option['top_right_corner'] . 'px ' . $option['bottom_right_corner'] . 'px ' . $option['bottom_left_corner'] . 'px !important;';
2580
+ } else {
2581
+ $border_css .= 'border-radius: 0px !important;';
2582
+ $border_css .= '-moz-border-radius: 0px !important;';
2583
+ $border_css .= '-webkit-border-radius: 0px !important;';
2584
+ }
2585
+
2586
+ return $border_css;
2587
+
2588
+ }
2589
+
2590
+ /*-----------------------------------------------------------------------------------*/
2591
+ /* generate_border_style_css() */
2592
+ /* Generate Border Style CSS on frontend */
2593
+ /*-----------------------------------------------------------------------------------*/
2594
+ public function generate_border_style_css( $option ) {
2595
+
2596
+ $border_style_css = '';
2597
+
2598
+ $border_style_css .= 'border: ' . esc_attr( $option['width'] ) . ' ' . esc_attr( $option['style'] ) . ' ' . esc_attr( $option['color'] ) .' !important;';
2599
+
2600
+ return $border_style_css;
2601
+
2602
+ }
2603
+
2604
+ /*-----------------------------------------------------------------------------------*/
2605
+ /* generate_border_corner_css() */
2606
+ /* Generate Border Corner CSS on frontend */
2607
+ /*-----------------------------------------------------------------------------------*/
2608
+ public function generate_border_corner_css( $option ) {
2609
+
2610
+ $border_corner_css = '';
2611
+
2612
+ if ( isset( $option['corner'] ) && esc_attr( $option['corner'] ) == 'rounded' ) {
2613
+ if ( ! isset( $option['rounded_value'] ) ) $option['rounded_value'] = 0;
2614
+ if ( ! isset( $option['top_left_corner'] ) ) $option['top_left_corner'] = $option['rounded_value'];
2615
+ if ( ! isset( $option['top_right_corner'] ) ) $option['top_right_corner'] = $option['rounded_value'];
2616
+ if ( ! isset( $option['bottom_left_corner'] ) ) $option['bottom_left_corner'] = $option['rounded_value'];
2617
+ if ( ! isset( $option['bottom_right_corner'] ) ) $option['bottom_right_corner'] = $option['rounded_value'];
2618
+
2619
+ $border_corner_css .= 'border-radius: ' . $option['top_left_corner'] . 'px ' . $option['top_right_corner'] . 'px ' . $option['bottom_right_corner'] . 'px ' . $option['bottom_left_corner'] . 'px !important;';
2620
+ $border_corner_css .= '-moz-border-radius: ' . $option['top_left_corner'] . 'px ' . $option['top_right_corner'] . 'px ' . $option['bottom_right_corner'] . 'px ' . $option['bottom_left_corner'] . 'px !important;';
2621
+ $border_corner_css .= '-webkit-border-radius: ' . $option['top_left_corner'] . 'px ' . $option['top_right_corner'] . 'px ' . $option['bottom_right_corner'] . 'px ' . $option['bottom_left_corner'] . 'px !important;';
2622
+ } else {
2623
+ $border_corner_css .= 'border-radius: 0px !important;';
2624
+ $border_corner_css .= '-moz-border-radius: 0px !important;';
2625
+ $border_corner_css .= '-webkit-border-radius: 0px !important;';
2626
+ }
2627
+
2628
+ return $border_corner_css;
2629
+
2630
+ }
2631
+
2632
+ /*-----------------------------------------------------------------------------------*/
2633
+ /* generate_shadow_css() */
2634
+ /* Generate Shadow CSS on frontend */
2635
+ /*-----------------------------------------------------------------------------------*/
2636
+ public function generate_shadow_css( $option ) {
2637
+
2638
+ $shadow_css = '';
2639
+ if ( ! isset( $option['inset'] ) ) $option['inset'] = '';
2640
+
2641
+ if ( isset( $option['enable'] ) && $option['enable'] == 1 ) {
2642
+ $shadow_css .= 'box-shadow: ' . $option['h_shadow'] . ' ' . $option['v_shadow'] . ' ' . $option['blur'] . ' ' . $option['spread'] . ' ' . $option['color'] . ' ' . $option['inset'] . ' !important;';
2643
+ $shadow_css .= '-moz-box-shadow: ' . $option['h_shadow'] . ' ' . $option['v_shadow'] . ' ' . $option['blur'] . ' ' . $option['spread'] . ' ' . $option['color'] . ' ' . $option['inset'] . ' !important;';
2644
+ $shadow_css .= '-webkit-box-shadow: ' . $option['h_shadow'] . ' ' . $option['v_shadow'] . ' ' . $option['blur'] . ' ' . $option['spread'] . ' ' . $option['color'] . ' ' . $option['inset'] . ' !important;';
2645
+ } else {
2646
+ $shadow_css .= 'box-shadow: none !important ;';
2647
+ $shadow_css .= '-moz-box-shadow: none !important ;';
2648
+ $shadow_css .= '-webkit-box-shadow: none !important ;';
2649
+ }
2650
+
2651
+ return $shadow_css;
2652
+
2653
+ }
2654
+
2655
+ }
2656
+
2657
+ global $a3_lazy_load_admin_interface;
2658
+ $a3_lazy_load_admin_interface = new A3_Lazy_Load_Admin_Interface();
2659
+
2660
+ ?>
admin/admin-pages/admin-settings-page.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* "Copyright 2012 a3 Revolution Web Design" This software is distributed under the terms of GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 */
3
+ // File Security Check
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+ ?>
6
+ <?php
7
+ /*-----------------------------------------------------------------------------------
8
+ a3 LazyLoad Settings Page
9
+
10
+ TABLE OF CONTENTS
11
+
12
+ - var menu_slug
13
+ - var page_data
14
+
15
+ - __construct()
16
+ - page_init()
17
+ - page_data()
18
+ - add_admin_menu()
19
+ - tabs_include()
20
+ - admin_settings_page()
21
+
22
+ -----------------------------------------------------------------------------------*/
23
+
24
+ class A3_Lazy_Load_Settings_Page extends A3_Lazy_Load_Admin_UI
25
+ {
26
+ /**
27
+ * @var string
28
+ */
29
+ private $menu_slug = 'a3-lazy-load';
30
+
31
+ /**
32
+ * @var array
33
+ */
34
+ private $page_data;
35
+
36
+ /*-----------------------------------------------------------------------------------*/
37
+ /* __construct() */
38
+ /* Settings Constructor */
39
+ /*-----------------------------------------------------------------------------------*/
40
+ public function __construct() {
41
+ $this->page_init();
42
+ $this->tabs_include();
43
+ }
44
+
45
+ /*-----------------------------------------------------------------------------------*/
46
+ /* page_init() */
47
+ /* Page Init */
48
+ /*-----------------------------------------------------------------------------------*/
49
+ public function page_init() {
50
+ add_filter( $this->plugin_name . '_add_admin_menu', array( $this, 'add_admin_menu' ) );
51
+ }
52
+
53
+ /*-----------------------------------------------------------------------------------*/
54
+ /* page_data() */
55
+ /* Get Page Data */
56
+ /*-----------------------------------------------------------------------------------*/
57
+ public function page_data() {
58
+
59
+ $page_data = array(
60
+ array(
61
+ 'type' => 'menu',
62
+ 'page_title' => __('a3 Lazy Load','a3_lazy_load'),
63
+ 'menu_title' => __('Lazy Load','a3_lazy_load'),
64
+ 'icon_url' => '',
65
+ 'position' => '25.564',
66
+ 'capability' => 'manage_options',
67
+ 'menu_slug' => $this->menu_slug,
68
+ 'function' => 'a3_lazy_load_settings_page_show',
69
+ 'admin_url' => 'admin.php',
70
+ 'callback_function' => 'callback_a3_lazy_load_settings_page_show',
71
+ 'script_function' => '',
72
+ 'view_doc' => '',
73
+ ),
74
+ array(
75
+ 'type' => 'submenu',
76
+ 'parent_slug' => $this->menu_slug,
77
+ 'page_title' => __( 'a3 Lazy Load', 'a3_lazy_load' ),
78
+ 'menu_title' => __( 'Settings', 'a3_lazy_load' ),
79
+ 'capability' => 'manage_options',
80
+ 'menu_slug' => $this->menu_slug,
81
+ 'function' => 'a3_lazy_load_settings_page_show',
82
+ 'admin_url' => 'admin.php',
83
+ 'callback_function' => 'a3_lazy_load_global_settings_tab_manager',
84
+ 'script_function' => '',
85
+ 'view_doc' => '',
86
+ ),
87
+ );
88
+
89
+ if ( $this->page_data ) return $this->page_data;
90
+ return $this->page_data = $page_data;
91
+
92
+ }
93
+
94
+ /*-----------------------------------------------------------------------------------*/
95
+ /* add_admin_menu() */
96
+ /* Add This page to menu on left sidebar */
97
+ /*-----------------------------------------------------------------------------------*/
98
+ public function add_admin_menu( $admin_menu ) {
99
+
100
+ if ( ! is_array( $admin_menu ) ) $admin_menu = array();
101
+ $admin_menu = array_merge( $this->page_data(), $admin_menu );
102
+
103
+ return $admin_menu;
104
+ }
105
+
106
+ /*-----------------------------------------------------------------------------------*/
107
+ /* tabs_include() */
108
+ /* Include all tabs into this page
109
+ /*-----------------------------------------------------------------------------------*/
110
+ public function tabs_include() {
111
+ include_once( $this->admin_plugin_dir() . '/tabs/template-settings/global-settings-tab.php' );
112
+ }
113
+
114
+ /*-----------------------------------------------------------------------------------*/
115
+ /* admin_settings_page() */
116
+ /* Show Settings Page */
117
+ /*-----------------------------------------------------------------------------------*/
118
+ public function admin_settings_page() {
119
+ global $a3_lazy_load_admin_init;
120
+
121
+ $my_page_data = $this->page_data();
122
+ $my_page_data = array_values( $my_page_data );
123
+ $a3_lazy_load_admin_init->admin_settings_page( $my_page_data[1] );
124
+ }
125
+
126
+ /*-----------------------------------------------------------------------------------*/
127
+ /* admin_settings_page() */
128
+ /* Show Settings Page */
129
+ /*-----------------------------------------------------------------------------------*/
130
+ public function callback_admin_settings_page() {
131
+ global $a3_lazy_load_global_settings_panel;
132
+
133
+ $a3_lazy_load_global_settings_panel->settings_form();
134
+ }
135
+
136
+ }
137
+
138
+ global $a3_lazy_load_settings_page;
139
+ $a3_lazy_load_settings_page = new A3_Lazy_Load_Settings_Page();
140
+
141
+ /**
142
+ * a3_lazy_load_settings_page_show()
143
+ * Define the callback function to show page content
144
+ */
145
+ function a3_lazy_load_settings_page_show() {
146
+ global $a3_lazy_load_settings_page;
147
+ $a3_lazy_load_settings_page->admin_settings_page();
148
+ }
149
+
150
+ function callback_a3_lazy_load_settings_page_show() {
151
+ global $a3_lazy_load_settings_page;
152
+ $a3_lazy_load_settings_page->callback_admin_settings_page();
153
+ }
154
+
155
+ ?>
admin/admin-ui.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* "Copyright 2012 a3 Revolution Web Design" This software is distributed under the terms of GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 */
3
+ // File Security Check
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+ ?>
6
+ <?php
7
+ /*-----------------------------------------------------------------------------------
8
+ A3rev Plugin Admin UI
9
+
10
+ TABLE OF CONTENTS
11
+
12
+ - var plugin_name
13
+ - var admin_plugin_url
14
+ - var admin_plugin_dir
15
+ - var admin_pages
16
+ - admin_plugin_url()
17
+ - admin_plugin_dir()
18
+ - admin_pages()
19
+ - plugin_extension_start()
20
+ - plugin_extension_end()
21
+ - pro_fields_before()
22
+ - pro_fields_after()
23
+ - blue_message_box()
24
+
25
+ -----------------------------------------------------------------------------------*/
26
+
27
+ class A3_Lazy_Load_Admin_UI
28
+ {
29
+ /**
30
+ * @var string
31
+ * You must change to correct plugin name that you are working
32
+ */
33
+ public $plugin_name = 'a3_lazy_load';
34
+
35
+ public $is_free_plugin = true;
36
+
37
+ /**
38
+ * @var string
39
+ * You must change to correct class name that you are working
40
+ */
41
+ public $class_name = 'A3_Lazy_Load';
42
+
43
+ /**
44
+ * @var string
45
+ * You must change to correct pro plugin page url on a3rev site
46
+ */
47
+ public $pro_plugin_page_url = 'http://a3rev.com/shop/a3-lazy-load/';
48
+
49
+ /**
50
+ * @var string
51
+ */
52
+ public $admin_plugin_url;
53
+
54
+ /**
55
+ * @var string
56
+ */
57
+ public $admin_plugin_dir;
58
+
59
+ /**
60
+ * @var array
61
+ * You must change to correct page you want to include scripts & styles, if you have many pages then use array() : array( 'quotes-orders-mode', 'quotes-orders-rule' )
62
+ */
63
+ public $admin_pages = array( 'a3-lazy-load', 'a3-lazy-load-add' );
64
+
65
+
66
+ /*-----------------------------------------------------------------------------------*/
67
+ /* admin_plugin_url() */
68
+ /*-----------------------------------------------------------------------------------*/
69
+ public function admin_plugin_url() {
70
+ if ( $this->admin_plugin_url ) return $this->admin_plugin_url;
71
+ return $this->admin_plugin_url = untrailingslashit( plugins_url( '/', __FILE__ ) );
72
+ }
73
+
74
+ /*-----------------------------------------------------------------------------------*/
75
+ /* admin_plugin_dir() */
76
+ /*-----------------------------------------------------------------------------------*/
77
+ public function admin_plugin_dir() {
78
+ if ( $this->admin_plugin_dir ) return $this->admin_plugin_dir;
79
+ return $this->admin_plugin_dir = untrailingslashit( plugin_dir_path( __FILE__ ) );
80
+ }
81
+
82
+ /*-----------------------------------------------------------------------------------*/
83
+ /* admin_pages() */
84
+ /*-----------------------------------------------------------------------------------*/
85
+ public function admin_pages() {
86
+ $admin_pages = apply_filters( $this->plugin_name . '_admin_pages', $this->admin_pages );
87
+
88
+ return (array)$admin_pages;
89
+ }
90
+
91
+ /*-----------------------------------------------------------------------------------*/
92
+ /* plugin_extension_start() */
93
+ /* Start of yellow box on right for pro fields
94
+ /*-----------------------------------------------------------------------------------*/
95
+ public function plugin_extension_start( $echo = true ) {
96
+ $output = '<div id="a3_plugin_panel_container">';
97
+ $output .= '<div id="a3_plugin_panel_fields">';
98
+
99
+ $output = apply_filters( $this->plugin_name . '_plugin_extension_start', $output );
100
+
101
+ if ( $echo )
102
+ echo $output;
103
+ else
104
+ return $output;
105
+ }
106
+
107
+ /*-----------------------------------------------------------------------------------*/
108
+ /* plugin_extension_start() */
109
+ /* End of yellow box on right for pro fields
110
+ /*-----------------------------------------------------------------------------------*/
111
+ public function plugin_extension_end( $echo = true ) {
112
+ $output = '</div>';
113
+ $output .= '<div id="a3_plugin_panel_upgrade_area">';
114
+ $output .= '<div id="a3_plugin_panel_extensions">';
115
+ $output .= apply_filters( $this->plugin_name . '_plugin_extension', '' );
116
+ $output .= '</div>';
117
+ $output .= '</div>';
118
+ $output .= '</div>';
119
+
120
+ $output = apply_filters( $this->plugin_name . '_plugin_extension_end', $output );
121
+
122
+ if ( $echo )
123
+ echo $output;
124
+ else
125
+ return $output;
126
+
127
+ }
128
+
129
+ /*-----------------------------------------------------------------------------------*/
130
+ /* upgrade_top_message() */
131
+ /* Show upgrade top message for pro fields
132
+ /*-----------------------------------------------------------------------------------*/
133
+ public function upgrade_top_message( $echo = false, $setting_id = '' ) {
134
+ $upgrade_top_message = sprintf( '<div class="pro_feature_top_message">'
135
+ . __( 'Settings inside this yellow border are %s Features.', 'a3_lazy_load' )
136
+ . '<br />'
137
+ . __( 'Upgrade to the <a href="%s" target="_blank">%s</a> to activate these settings.', 'a3_lazy_load' )
138
+ . '</div>'
139
+ , apply_filters( $this->plugin_name . '_' . $setting_id . '_pro_version_name', apply_filters( $this->plugin_name . '_pro_version_name', __( 'Pro Version', 'a3_lazy_load' ) ) )
140
+ , apply_filters( $this->plugin_name . '_' . $setting_id . '_pro_plugin_page_url', apply_filters( $this->plugin_name . '_pro_plugin_page_url', $this->pro_plugin_page_url ) )
141
+ , apply_filters( $this->plugin_name . '_' . $setting_id . '_pro_version_name', apply_filters( $this->plugin_name . '_pro_version_name', __( 'Pro Version', 'a3_lazy_load' ) ) )
142
+ );
143
+
144
+ $upgrade_top_message = apply_filters( $this->plugin_name . '_upgrade_top_message', $upgrade_top_message );
145
+
146
+ if ( $echo ) echo $upgrade_top_message;
147
+ else return $upgrade_top_message;
148
+
149
+ }
150
+
151
+ /*-----------------------------------------------------------------------------------*/
152
+ /* pro_fields_before() */
153
+ /* Start of yellow box on right for pro fields
154
+ /*-----------------------------------------------------------------------------------*/
155
+ public function pro_fields_before( $echo = true ) {
156
+ echo apply_filters( $this->plugin_name . '_pro_fields_before', '<div class="pro_feature_fields">'. $this->upgrade_top_message() );
157
+ }
158
+
159
+ /*-----------------------------------------------------------------------------------*/
160
+ /* pro_fields_after() */
161
+ /* End of yellow border for pro fields
162
+ /*-----------------------------------------------------------------------------------*/
163
+ public function pro_fields_after( $echo = true ) {
164
+ echo apply_filters( $this->plugin_name . '_pro_fields_after', '</div>' );
165
+ }
166
+
167
+ /*-----------------------------------------------------------------------------------*/
168
+ /* blue_message_box() */
169
+ /* Blue Message Box
170
+ /*-----------------------------------------------------------------------------------*/
171
+ public function blue_message_box( $message = '', $width = '600px' ) {
172
+ $message = '<div class="a3rev_blue_message_box_container" style="width:'.$width.'"><div class="a3rev_blue_message_box">' . $message . '</div></div>';
173
+ $message = apply_filters( $this->plugin_name . '_blue_message_box', $message );
174
+
175
+ return $message;
176
+ }
177
+
178
+ }
179
+
180
+ ?>
admin/assets/css/a3_admin_metabox.css ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @font-face {
2
+ font-family: "a3-metabox-plugin-framework";
3
+ src:url("../fonts/a3-metabox-plugin-framework.eot");
4
+ src:url("../fonts/a3-metabox-plugin-framework.eot?#iefix") format("embedded-opentype"),
5
+ url("../fonts/a3-metabox-plugin-framework.woff") format("woff"),
6
+ url("../fonts/a3-metabox-plugin-framework.ttf") format("truetype"),
7
+ url("../fonts/a3-metabox-plugin-framework.svg#a3-metabox-plugin-framework") format("svg");
8
+ font-weight: normal;
9
+ font-style: normal;
10
+
11
+ }
12
+
13
+ .a3-metabox-panel-wrap .a3-metabox-icon:before {
14
+ font-family: "a3-metabox-plugin-framework" !important;
15
+ font-style: normal !important;
16
+ font-weight: normal !important;
17
+ font-variant: normal !important;
18
+ text-transform: none !important;
19
+ speak: none;
20
+ line-height: 1;
21
+ -webkit-font-smoothing: antialiased;
22
+ -moz-osx-font-smoothing: grayscale;
23
+ content: attr(data-icon);
24
+ }
25
+ .a3-metabox-wrapper .expand_all:before, .a3-metabox-wrapper .close_all:before {
26
+ font-size: 12px;
27
+ color: #aaa;
28
+ font-weight: bold !important;
29
+ margin-right: 5px;
30
+ }
31
+ .a3-metabox-wrapper .expand_all:before {
32
+ content: "\e000";
33
+ }
34
+ .a3-metabox-wrapper .close_all:before {
35
+ content: "\e002";
36
+ }
37
+ .a3-metabox-wrapper .a3-metabox-item .handlediv:before {
38
+ font-size: 16px !important;
39
+ }
40
+ .a3-metabox-wrapper .a3-metabox-item.closed .handlediv:before {
41
+ content: "\e005"!important;
42
+ }
43
+ .a3-metabox-wrapper .a3-metabox-item.open .handlediv:before {
44
+ content: "\e004"!important;
45
+ }
46
+
47
+ .a3-metabox-panel-wrap {
48
+ background: #fff;
49
+ padding-left: 153px;
50
+ }
51
+ .a3-metabox-wrapper, .a3-metabox-options-panel {
52
+ float: right;
53
+ width: 100%;
54
+ }
55
+ .a3-metabox-wrapper .a3-metabox-items, .a3-metabox-wrapper p.toolbar, .a3-metabox-options-panel .a3-metabox-items, .a3-metabox-options-panel p.toolbar {
56
+ padding-left: 12px!important;
57
+ padding-right: 20px!important;
58
+ }
59
+ .a3-metabox-tabs-back {
60
+ position: absolute;
61
+ top: 0;
62
+ left: 0;
63
+ bottom: 0;
64
+ background: #f5f5f5;
65
+ width: 145px;
66
+ border-right: 1px solid #DFDFDF;
67
+ }
68
+ ul.a3-metabox-data-tabs {
69
+ background: #f5f5f5;
70
+ line-height: 1em;
71
+ float: left;
72
+ width: 145px;
73
+ margin: 0 0 0 -153px;
74
+ position: relative;
75
+ padding: 0 0 10px;
76
+ }
77
+ ul.a3-metabox-data-tabs li {
78
+ display: block;
79
+ padding: 0;
80
+ margin: 0;
81
+ }
82
+ ul.a3-metabox-data-tabs li a {
83
+ padding: 10px;
84
+ line-height: 18px!important;
85
+ margin: 0;
86
+ display: block;
87
+ background: #f5f5f5;
88
+ text-decoration: none;
89
+ border-bottom: 1px solid #f5f5f5;
90
+ border-top: 1px solid #eaeaea;
91
+ }
92
+ ul.a3-metabox-data-tabs li:first-child a {
93
+ border-top: 0 !important;
94
+ }
95
+ ul.a3-metabox-data-tabs li.active a {
96
+ border-color: #DFDFDF;
97
+ position: relative;
98
+ background-color: #fff;
99
+ color: #555;
100
+ margin: 0 -1px 0 0;
101
+ }
102
+ .a3-metabox-panel, .a3-metabox-options-panel {
103
+ padding: 0;
104
+ color: #555
105
+ }
106
+ .a3-metabox-panel table.form-table td label,
107
+ .a3-metabox-panel table.form-table td span,
108
+ .a3-metabox-panel table.form-table td a,
109
+ .a3-metabox-panel table.form-table td input,
110
+ .a3-metabox-panel table.form-table td select,
111
+ .a3-metabox-panel table.form-table td *,
112
+ .a3-metabox-panel table.form-table td,
113
+ .a3-metabox-panel * {
114
+ font-size: 12px;
115
+ }
116
+
117
+ .a3-metabox-wrapper .toolbar {
118
+ margin: 0!important;
119
+ border-top: 1px solid #fff;
120
+ border-bottom: 1px solid #DFDFDF;
121
+ padding: 9px 12px!important;
122
+ }
123
+ .a3-metabox-wrapper .toolbar:first-child {
124
+ border-top: 0
125
+ }
126
+ .a3-metabox-wrapper .toolbar: last-child {
127
+ border-bottom: 0
128
+ }
129
+ .a3-metabox-wrapper p.toolbar {
130
+ overflow: hidden;
131
+ zoom: 1;
132
+ }
133
+ .a3-metabox-wrapper .a3-metabox-items {
134
+ border-bottom: 1px solid #DFDFDF;
135
+ padding: 0 12px;
136
+ }
137
+ .a3-metabox-wrapper .a3-metabox-item-sortable-placeholder {
138
+ border-color: #bbb;
139
+ background-color: #f5f5f5;
140
+ margin-bottom: 9px;
141
+ border-width: 1px;
142
+ border-style: dashed
143
+ }
144
+ .a3-metabox-wrapper .a3-metabox-item {
145
+ background: #fff;
146
+ border: 1px solid #dfdfdf;
147
+ margin: 9px 0!important;
148
+ -moz-border-radius-topleft: 3px;
149
+ -moz-border-radius-topright: 3px;
150
+ -webkit-border-top-left-radius: 3px;
151
+ -webkit-border-top-right-radius: 3px;
152
+ border-top-left-radius: 3px;
153
+ border-top-right-radius: 3px
154
+ }
155
+ .a3-metabox-wrapper .a3-metabox-item .handlediv:before {
156
+ line-height: .5!important;
157
+ }
158
+ .a3-metabox-wrapper .a3-metabox-item.closed {
159
+ -moz-border-radius: 3px;
160
+ -webkit-border-radius: 3px;
161
+ border-radius: 3px;
162
+ }
163
+ .a3-metabox-wrapper .a3-metabox-item.closed h3 {
164
+ border: 0;
165
+ }
166
+ .a3-metabox-wrapper .a3-metabox-item h3 {
167
+ margin: 0!important;
168
+ padding: 6px 6px 6px 0 !important;
169
+ font-size: 1em!important;
170
+ overflow: hidden;
171
+ zoom: 1;
172
+ cursor: pointer;
173
+ position: relative;
174
+ }
175
+ .a3-metabox-wrapper .a3-metabox-item.open h3 {
176
+ cursor: ne-resize;
177
+ }
178
+ .a3-metabox-wrapper .a3-metabox-item.closed h3 {
179
+ cursor: sw-resize;
180
+ }
181
+ .a3-metabox-wrapper .a3-metabox-item h3 button {
182
+ float: right;
183
+ }
184
+ .a3-metabox-wrapper .a3-metabox-item h3 strong {
185
+ font-weight: 400;
186
+ line-height: 24px;
187
+ }
188
+ .a3-metabox-wrapper .a3-metabox-item h3 .handlediv {
189
+ background-position: 6px 5px!important;
190
+ height: 24px;
191
+ position: absolute;
192
+ z-index: 1000;
193
+ right: 0;
194
+ }
195
+ .a3-metabox-wrapper .a3-metabox-item h3.fixed {
196
+ cursor: pointer!important;
197
+ }
198
+ .a3-metabox-wrapper .a3-metabox-item h3:hover .handlediv {
199
+ display: block;
200
+ }
201
+ .a3-metabox-wrapper .a3-metabox-item table {
202
+ width: 100%;
203
+ position: relative;
204
+ background: #fff;
205
+ padding: 3px
206
+ }
207
+ .a3-metabox-wrapper .a3-metabox-item h3 table {
208
+ margin: 0;
209
+ }
210
+ .a3-metabox-wrapper .a3-metabox-item h3 table td:first-child {
211
+ width: 25%;
212
+ }
213
+ .a3-metabox-panel table tr td:first-child {
214
+ width: 25%;
215
+ }
216
+ .a3-metabox-wrapper .a3-metabox-item table td {
217
+ text-align: left;
218
+ padding: 6px;
219
+ vertical-align: top;
220
+ border: 0
221
+ }
222
+ .a3-metabox-wrapper .a3-metabox-item table td label {
223
+ text-align: left;
224
+ display: block;
225
+ line-height: 21px;
226
+ }
227
+ .a3-metabox-wrapper .close_all, .a3-metabox-wrapper .expand_all {
228
+ float: right;
229
+ margin-left: 14px;
230
+ line-height: 22px;
231
+ text-decoration: none
232
+ }
233
+ @media only screen and (max-width: 900px) {
234
+ .a3-metabox-panel-wrap {
235
+ padding-left: 35px;
236
+ }
237
+ .a3-metabox-tabs-back {
238
+ position: absolute;
239
+ top: 0;
240
+ left: 0;
241
+ bottom: 0;
242
+ width: 28px;
243
+ border-right: 1px solid #DFDFDF;
244
+ }
245
+ ul.a3-metabox-data-tabs {
246
+ width: 28px;
247
+ margin-left: -35px;
248
+ }
249
+ ul.a3-metabox-data-tabs li a {
250
+ overflow: hidden;
251
+ white-space: nowrap;
252
+ }
253
+ .a3-metabox-tabs-back, ul.a3-metabox-data-tabs {
254
+ width: 40px;
255
+ }
256
+ ul.a3-metabox-data-tabs li a {
257
+ position: relative;
258
+ text-indent: -999px;
259
+ padding: 10px;
260
+ }
261
+ ul.a3-metabox-data-tabs li a:before {
262
+ position: absolute;
263
+ top: 0;
264
+ right: 0;
265
+ bottom: 0;
266
+ left: 0;
267
+ text-indent: 0;
268
+ text-align: center;
269
+ line-height: 40px;
270
+ width: 40px;
271
+ height: 40px;
272
+ }
273
+ .a3-metabox-wrapper, .a3-metabox-options-panel {
274
+ width: 98%;
275
+ }
276
+ }
admin/assets/css/a3_admin_metabox.rtl.css ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .clear {
2
+ clear: both;
3
+ }
4
+ .nobr {
5
+ white-space: nowrap;
6
+ }
7
+ .a3-metabox-panel-wrap {
8
+ padding-left: 0px;
9
+ padding-right: 153px;
10
+ }
11
+ .a3-metabox-panel-wrap .a3-metabox-tabs-back {
12
+ left: auto;
13
+ right: 0;
14
+ border-left: 1px solid #DFDFDF;
15
+ border-right: none;
16
+ }
17
+ .a3-metabox-panel-wrap ul.a3-metabox-data-tabs {
18
+ float: right;
19
+ margin: 0 -153px 0 0;
20
+ }
21
+ .a3-metabox-panel-wrap ul.a3-metabox-data-tabs li.active a {
22
+ margin: 0 0 0 -1px;
23
+ }
24
+ .a3-metabox-wrapper,
25
+ .a3-metabox-options-panel {
26
+ float: left;
27
+ }
28
+ .a3-metabox-wrapper .a3-metabox-items,
29
+ .a3-metabox-wrapper p.toolbar,
30
+ .a3-metabox-options-panel .a3-metabox-items,
31
+ .a3-metabox-options-panel p.toolbar {
32
+ padding-left: 20px !important;
33
+ padding-right: 12px !important;
34
+ }
35
+ .a3-metabox-wrapper .close_all,
36
+ .a3-metabox-wrapper .expand_all {
37
+ float: left;
38
+ margin-left: 0px;
39
+ margin-right: 14px;
40
+ }
41
+ .a3-metabox-wrapper .a3-metabox-item table td {
42
+ text-align: right;
43
+ }
44
+ .a3-metabox-wrapper .a3-metabox-item table td label {
45
+ text-align: right;
46
+ }
47
+ .a3-metabox-wrapper .a3-metabox-item h3 .handlediv {
48
+ left: 0;
49
+ right: auto;
50
+ }
51
+ @media only screen and (max-width: 900px) {
52
+ .a3-metabox-panel-wrap {
53
+ padding-left: 0px;
54
+ padding-right: 35px;
55
+ }
56
+ .a3-metabox-panel-wrap .a3-metabox-tabs-back {
57
+ left: auto;
58
+ left: 0;
59
+ border-left: 1px solid #DFDFDF;
60
+ border-right: none;
61
+ }
62
+ .a3-metabox-panel-wrap ul.a3-metabox-data-tabs {
63
+ margin-left: 0px;
64
+ margin-right: -35px;
65
+ }
66
+ .a3-metabox-panel-wrap ul.a3-metabox-data-tabs li a:after {
67
+ position: absolute;
68
+ top: 0;
69
+ right: 0;
70
+ bottom: 0;
71
+ left: 0;
72
+ text-indent: 0;
73
+ text-align: center;
74
+ line-height: 40px;
75
+ width: 40px;
76
+ height: 40px;
77
+ }
78
+ }
admin/assets/css/a3_admin_metabox.rtl.less ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "mixins.less";
2
+
3
+ /*-------------------------------------------------------------------------------------------*/
4
+ /* A3rev Admin Metabox RTL UI */
5
+ /*-------------------------------------------------------------------------------------------*/
6
+
7
+ .a3-metabox-panel-wrap {
8
+ padding-left: 0px;
9
+ padding-right: 153px;
10
+
11
+ .a3-metabox-tabs-back {
12
+ left: auto;
13
+ right: 0;
14
+ border-left: 1px solid #DFDFDF;
15
+ border-right: none;
16
+ }
17
+
18
+ ul {
19
+ &.a3-metabox-data-tabs {
20
+ float: right;
21
+ margin: 0 -153px 0 0;
22
+
23
+ li {
24
+ &.active {
25
+ a {
26
+ margin: 0 0 0 -1px;
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ .a3-metabox-wrapper, .a3-metabox-options-panel {
35
+ float: left;
36
+
37
+ .a3-metabox-items, p.toolbar {
38
+ padding-left: 20px !important;
39
+ padding-right: 12px !important;
40
+ }
41
+ }
42
+
43
+ .a3-metabox-wrapper {
44
+ .close_all, .expand_all {
45
+ float: left;
46
+ margin-left: 0px;
47
+ margin-right: 14px;
48
+ }
49
+
50
+ .a3-metabox-item {
51
+ table {
52
+ td {
53
+ text-align: right;
54
+
55
+ label {
56
+ text-align: right;
57
+ }
58
+ }
59
+ }
60
+ h3 {
61
+ .handlediv {
62
+ left: 0;
63
+ right: auto;
64
+
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ @media only screen and (max-width: 900px) {
71
+ .a3-metabox-panel-wrap {
72
+ padding-left: 0px;
73
+ padding-right: 35px;
74
+
75
+ .a3-metabox-tabs-back {
76
+ left: auto;
77
+ left: 0;
78
+ border-left: 1px solid #DFDFDF;
79
+ border-right: none;
80
+ }
81
+
82
+ ul {
83
+ &.a3-metabox-data-tabs {
84
+ margin-left: 0px;
85
+ margin-right: -35px;
86
+
87
+ li {
88
+ a {
89
+ &:after {
90
+ position: absolute;
91
+ top: 0;
92
+ right: 0;
93
+ bottom: 0;
94
+ left: 0;
95
+ text-indent: 0;
96
+ text-align: center;
97
+ line-height: 40px;
98
+ width: 40px;
99
+ height: 40px;
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
admin/assets/css/a3_admin_metabox.rtl.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .clear{clear:both}.nobr{white-space:nowrap}.a3-metabox-panel-wrap{padding-left:0px;padding-right:153px}.a3-metabox-panel-wrap .a3-metabox-tabs-back{left:auto;right:0;border-left:1px solid #DFDFDF;border-right:none}.a3-metabox-panel-wrap ul.a3-metabox-data-tabs{float:right;margin:0 -153px 0 0}.a3-metabox-panel-wrap ul.a3-metabox-data-tabs li.active a{margin:0 0 0 -1px}.a3-metabox-wrapper,.a3-metabox-options-panel{float:left}.a3-metabox-wrapper .a3-metabox-items,.a3-metabox-wrapper p.toolbar,.a3-metabox-options-panel .a3-metabox-items,.a3-metabox-options-panel p.toolbar{padding-left:20px !important;padding-right:12px !important}.a3-metabox-wrapper .close_all,.a3-metabox-wrapper .expand_all{float:left;margin-left:0px;margin-right:14px}.a3-metabox-wrapper .a3-metabox-item table td{text-align:right}.a3-metabox-wrapper .a3-metabox-item table td label{text-align:right}.a3-metabox-wrapper .a3-metabox-item h3 .handlediv{left:0;right:auto}@media only screen and (max-width: 900px){.a3-metabox-panel-wrap{padding-left:0px;padding-right:35px}.a3-metabox-panel-wrap .a3-metabox-tabs-back{left:auto;left:0;border-left:1px solid #DFDFDF;border-right:none}.a3-metabox-panel-wrap ul.a3-metabox-data-tabs{margin-left:0px;margin-right:-35px}.a3-metabox-panel-wrap ul.a3-metabox-data-tabs li a:after{position:absolute;top:0;right:0;bottom:0;left:0;text-indent:0;text-align:center;line-height:40px;width:40px;height:40px}}
admin/assets/css/admin-flat-ui-style.css ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*-------------------------------------------------------------------------------------------*/
2
+ /* A3rev Panel UI FLAT */
3
+ /*-------------------------------------------------------------------------------------------*/
4
+ @charset "UTF-8";
5
+
6
+ .a3rev_panel_container input[type="text"], .a3rev_panel_container input[type="email"] , .a3rev_panel_container input[type="number"], .a3rev_panel_container input[type="password"] { height:auto !important; }
7
+
8
+ /* Font Control */
9
+ .a3rev_panel_container .a3rev-ui-typography-preview { height:24px; margin-top: 1px; vertical-align: top; }
10
+
11
+ /* Color Control */
12
+ .a3rev_panel_container .wp-picker-container, .a3rev_panel_container .wp-picker-container:active { vertical-align:bottom; }
13
+ .a3rev_panel_container .wp-color-result { top:1px !important; vertical-align: top !important; }
14
+ .a3rev_panel_container input.a3rev-color-picker { font-family: open sans !important; margin-top: 1px !important;}
15
+ .a3rev_panel_container input.wp-picker-default { margin-top: 1px !important; vertical-align:top; }
16
+
17
+ /* Settings Preview */
18
+ .a3rev_panel_container .a3rev-ui-settings-preview { height:24px; margin-top: 1px; vertical-align: top; }
19
+
20
+ /* Border Rounded Corner Control */
21
+ .a3rev_panel_container .a3rev-ui-border_corner-span { float:left; width:150px; }
22
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer .iPhoneCheckLabelOff, .a3rev_panel_container .forminp-border_corner .iOSCheckContainer .iOSCheckLabelOff {
23
+ background: #569aef !important;
24
+ box-shadow: none !important;
25
+ -webkit-box-shadow: none !important;
26
+ border: 1px solid #666666;
27
+ border-radius: 5px;
28
+ -webkit-border-radius: 5px 5px 5px 5px;
29
+ -moz-border-radius: 5px 5px 5px 5px;
30
+
31
+ color: #FFFFFF !important;
32
+ text-shadow: none !important;
33
+ }
34
+
35
+ /* Box Shadow Control */
36
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer, .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer { top:0px; vertical-align:top; }
37
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer .iPhoneCheckLabelOff, .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer .iOSCheckLabelOff {
38
+ background: #569aef !important;
39
+ box-shadow: none !important;
40
+ -webkit-box-shadow: none !important;
41
+ border: 1px solid #666666;
42
+ border-radius: 5px;
43
+ -webkit-border-radius: 5px 5px 5px 5px;
44
+ -moz-border-radius: 5px 5px 5px 5px;
45
+
46
+ color: #FFFFFF !important;
47
+ text-shadow: none !important;
48
+ }
49
+
50
+ /* SLIDER Control */
51
+ .a3rev_panel_container .a3rev-ui-slide {
52
+ background: #ededed !important;
53
+ border: 1px solid #666 !important;
54
+ border-radius: 3px;
55
+ -webkit-border-radius: 3px 3px 3px 3px;
56
+ -moz-border-radius: 3px 3px 3px 3px;
57
+
58
+ height: 10px;
59
+ width: 220px;
60
+ position:relative;
61
+ float:left;
62
+ margin-top:4px;
63
+ }
64
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-handle {
65
+ background: #666 !important;
66
+ box-shadow: none !important;
67
+ -webkit-box-shadow: none !important;
68
+ border: 1px solid #666 !important;
69
+ border-radius: 3px;
70
+ -webkit-border-radius: 3px 3px 3px 3px;
71
+ -moz-border-radius: 3px 3px 3px 3px;
72
+
73
+ position: absolute;
74
+ z-index: 2;
75
+ width: 22px;
76
+ height: 23px;
77
+ cursor: pointer;
78
+ font-weight: bold;
79
+ color: #1C94C4;
80
+ outline: none;
81
+ top: -8px;
82
+ margin-left: -11px;
83
+ }
84
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-range {
85
+ background: #569aef !important;
86
+ box-shadow: none !important;
87
+ -webkit-box-shadow: none !important;
88
+ border: 1px solid #666 !important;
89
+ border-left:none !important;
90
+ border-radius: 3px;
91
+ -webkit-border-radius: 3px 3px 3px 3px;
92
+ -moz-border-radius: 3px 3px 3px 3px;
93
+
94
+ position: absolute;
95
+ top: -1px;
96
+ height: 100%;
97
+ }
98
+
99
+ /* OnOff Radio Control */
100
+ .a3rev_panel_container .forminp-onoff_radio li .iPhoneCheckContainer label {
101
+ margin:0 !important;
102
+ }
103
+
104
+ /* OnOff Checkbox & Radio Control */
105
+ .a3rev_panel_container .iPhoneCheckContainer label, .a3rev_panel_container .iOSCheckContainer label {
106
+ white-space: nowrap;
107
+ font-size: 14px;
108
+ line-height: 23px;
109
+ font-weight: bold;
110
+ font-family: inherit !important;
111
+ cursor: pointer;
112
+ display: block;
113
+ position: absolute;
114
+ width: auto;
115
+ top: 0;
116
+ overflow: hidden;
117
+ user-select: none;
118
+ -moz-user-select: none;
119
+ -khtml-user-select: none;
120
+ }
121
+ .a3rev_panel_container label.iPhoneCheckLabelOff, .a3rev_panel_container label.iOSCheckLabelOff {
122
+ background: #ededed !important;
123
+ box-shadow: none !important;
124
+ -webkit-box-shadow: none !important;
125
+ border: 1px solid #666;
126
+ border-radius: 5px;
127
+ -webkit-border-radius: 5px 5px 5px 5px;
128
+ -moz-border-radius: 5px 5px 5px 5px;
129
+
130
+ height: 23px;
131
+ color: #000 !important;
132
+ text-shadow: none !important;
133
+ text-align: right;
134
+ right: 0;
135
+ }
136
+ .a3rev_panel_container label.iPhoneCheckLabelOn, .a3rev_panel_container label.iOSCheckLabelOn {
137
+ background: #569aef !important;
138
+ box-shadow: none !important;
139
+ -webkit-box-shadow: none !important;
140
+ border: 1px solid #666;
141
+ border-radius: 5px;
142
+ -webkit-border-radius: 5px 5px 5px 5px;
143
+ -moz-border-radius: 5px 5px 5px 5px;
144
+
145
+ height: 23px;
146
+ text-align:left;
147
+ color: #FFFFFF;
148
+ text-shadow: none !important;
149
+ left: 0;
150
+ }
151
+ .a3rev_panel_container .iPhoneCheckHandle, .a3rev_panel_container .iOSCheckHandle {
152
+ background: #666 !important;
153
+ box-shadow: none !important;
154
+ -webkit-box-shadow: none !important;
155
+ border: 1px solid #666;
156
+ border-radius: 5px;
157
+ -webkit-border-radius: 5px 5px 5px 5px;
158
+ -moz-border-radius: 5px 5px 5px 5px;
159
+
160
+ display: block;
161
+ cursor: pointer;
162
+ position: absolute;
163
+ top: 0px;
164
+ left: -1px;
165
+ width: 35px;
166
+ height:23px;
167
+ }
168
+
169
+ /* Switcher Checkbox Control */
170
+ .a3rev_panel_container .forminp-switcher_checkbox .iPhoneCheckContainer .iPhoneCheckLabelOff, .a3rev_panel_container .forminp-switcher_checkbox .iOSCheckContainer .iOSCheckLabelOff {
171
+ background: #569aef !important;
172
+ box-shadow: none !important;
173
+ -webkit-box-shadow: none !important;
174
+ border: 1px solid #666666;
175
+ border-radius: 5px;
176
+ -webkit-border-radius: 5px 5px 5px 5px;
177
+ -moz-border-radius: 5px 5px 5px 5px;
178
+
179
+ color: #FFFFFF !important;
180
+ text-shadow: none !important;
181
+ }
182
+
183
+ /* Style for Chosen lib */
184
+ .chosen-container-single .chosen-single {
185
+ background: #FFF !important;
186
+ }
187
+ .chosen-container-active .chosen-single-with-drop {
188
+ background: #FFF !important;
189
+ }
190
+ .chosen-container-multi .chosen-choices .search-choice {
191
+ background: #e4e4e4 !important;
192
+ -webkit-box-shadow: none !important;
193
+ -moz-box-shadow : none !important;
194
+ box-shadow : none !important;
195
+ }
196
+
197
+ /* Thickbox of Uploader */
198
+ #media-upload .ui-sortable .media-item {
199
+ clear:both;
200
+ }
201
+
202
+ @media screen and ( max-width: 782px ) {
203
+ #media-items {
204
+ width:100%;
205
+ }
206
+ .media-item .describe input[type="text"], .media-item .describe textarea {
207
+ width:100%;
208
+ }
209
+ }
admin/assets/css/admin-flat-ui-style.min.css ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .a3rev_panel_container input[type="text"],.a3rev_panel_container input[type="email"],.a3rev_panel_container input[type="number"],.a3rev_panel_container input[type="password"]{height:auto !important}
2
+ .a3rev_panel_container .a3rev-ui-typography-preview{height:24px;margin-top:1px;vertical-align:top}
3
+ .a3rev_panel_container .wp-picker-container,.a3rev_panel_container .wp-picker-container:active{vertical-align:bottom}
4
+ .a3rev_panel_container .wp-color-result{top:1px !important;vertical-align:top !important}
5
+ .a3rev_panel_container input.a3rev-color-picker{font-family:open sans !important;margin-top:1px !important}
6
+ .a3rev_panel_container input.wp-picker-default{margin-top:1px !important;vertical-align:top}
7
+ .a3rev_panel_container .a3rev-ui-settings-preview{height:24px;margin-top:1px;vertical-align:top}
8
+ .a3rev_panel_container .a3rev-ui-border_corner-span{float:left;width:150px}
9
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer .iPhoneCheckLabelOff,.a3rev_panel_container .forminp-border_corner .iOSCheckContainer .iOSCheckLabelOff{background:#569aef !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;color:#fff !important;text-shadow:none !important}
10
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer,.a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer{top:0;vertical-align:top}
11
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer .iPhoneCheckLabelOff,.a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer .iOSCheckLabelOff{background:#569aef !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;color:#fff !important;text-shadow:none !important}
12
+ .a3rev_panel_container .a3rev-ui-slide{background:#ededed !important;border:1px solid #666 !important;border-radius:3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;height:10px;width:220px;position:relative;float:left;margin-top:4px}
13
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-handle{background:#666 !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666 !important;border-radius:3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;position:absolute;z-index:2;width:22px;height:23px;cursor:pointer;font-weight:bold;color:#1c94c4;outline:0;top:-8px;margin-left:-11px}
14
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-range{background:#569aef !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666 !important;border-left:none !important;border-radius:3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;position:absolute;top:-1px;height:100%}
15
+ .a3rev_panel_container .forminp-onoff_radio li .iPhoneCheckContainer label{margin:0 !important}
16
+ .a3rev_panel_container .iPhoneCheckContainer label,.a3rev_panel_container .iOSCheckContainer label{white-space:nowrap;font-size:14px;line-height:23px;font-weight:bold;font-family:inherit !important;cursor:pointer;display:block;position:absolute;width:auto;top:0;overflow:hidden;user-select:none;-moz-user-select:none;-khtml-user-select:none}
17
+ .a3rev_panel_container label.iPhoneCheckLabelOff,.a3rev_panel_container label.iOSCheckLabelOff{background:#ededed !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;height:23px;color:#000 !important;text-shadow:none !important;text-align:right;right:0}
18
+ .a3rev_panel_container label.iPhoneCheckLabelOn,.a3rev_panel_container label.iOSCheckLabelOn{background:#569aef !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;height:23px;text-align:left;color:#fff;text-shadow:none !important;left:0}
19
+ .a3rev_panel_container .iPhoneCheckHandle,.a3rev_panel_container .iOSCheckHandle{background:#666 !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;display:block;cursor:pointer;position:absolute;top:0;left:-1px;width:35px;height:23px}
20
+ .a3rev_panel_container .forminp-switcher_checkbox .iPhoneCheckContainer .iPhoneCheckLabelOff,.a3rev_panel_container .forminp-switcher_checkbox .iOSCheckContainer .iOSCheckLabelOff{background:#569aef !important;box-shadow:none !important;-webkit-box-shadow:none !important;border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;color:#fff !important;text-shadow:none !important}
21
+ .chosen-container-single .chosen-single{background:#FFF !important}
22
+ .chosen-container-active .chosen-single-with-drop{background:#FFF !important}
23
+ .chosen-container-multi .chosen-choices .search-choice{background:#e4e4e4 !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important;box-shadow:none !important}
24
+ #media-upload .ui-sortable .media-item{clear:both}
25
+ @media screen and (max-width:782px){#media-items{width:100%}
26
+ .media-item .describe input[type="text"],.media-item .describe textarea{width:100%}
27
+ }
admin/assets/css/admin-ui-style.css ADDED
@@ -0,0 +1,675 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*-------------------------------------------------------------------------------------------*/
2
+ /* A3rev Panel UI */
3
+ /*-------------------------------------------------------------------------------------------*/
4
+ @charset "UTF-8";
5
+
6
+ .a3rev_panel_container {
7
+ visibility:hidden;
8
+ height:0;
9
+ overflow:hidden;
10
+ margin-top:10px;
11
+ }
12
+ .a3rev_panel_container .a3rev_panel_inner {
13
+ clear:both;
14
+ display:block;
15
+ padding-bottom:10px;
16
+ }
17
+ .a3rev_panel_container .a3rev_panel_inner h3 {
18
+ margin-bottom:0;
19
+ }
20
+ .a3rev_panel_container .a3rev_panel_inner .form-table {
21
+ margin-bottom:0;
22
+ }
23
+ .icon32-a3rev-ui-settings {
24
+ background:url("../images/a3-plugins.png") no-repeat left top;
25
+ }
26
+
27
+ .a3rev_panel_container input[type="text"], .a3rev_panel_container input[type="email"] , .a3rev_panel_container input[type="number"], .a3rev_panel_container input[type="password"] { height:24px; }
28
+
29
+ /* Font Control */
30
+ .a3rev_panel_container .a3rev-ui-typography-size { width:80px; }
31
+ .a3rev_panel_container .a3rev-ui-typography-face { width:160px; }
32
+ .a3rev_panel_container .a3rev-ui-typography-style { width:100px; }
33
+ .a3rev_panel_container .a3rev-ui-typography-preview { display:inline-block; }
34
+
35
+ .a3rev_panel_container .typography-preview-container .preview_remove {
36
+ background:#EEEEEE;
37
+ border: 1px solid #DDDDDD;
38
+ border-radius: 2px 2px 2px 2px;
39
+ -webkit-border-radius: 2px 2px 2px 2px;
40
+ -moz-border-radius: 2px 2px 2px 2px;
41
+ cursor: pointer;
42
+ height: 10px;
43
+ padding: 2px;
44
+ position: absolute;
45
+ right: -10px;
46
+ top: -10px;
47
+ width: 10px;
48
+ z-index: 99;
49
+ text-decoration:none !important;
50
+ }
51
+ .a3rev_panel_container .a3rev-ui-typography-preview-button { float: left; margin: 0px; padding-top: 0px; height:24px; line-height:24px; }
52
+ .a3rev_panel_container .typography-preview-container { clear: both; position:relative; width:50%; margin-top:10px; }
53
+ .a3rev_panel_container .typography-preview { word-wrap: break-word; clear: both; padding: 20px; border: 1px solid #CCCCCC; background: #FDFDFD; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
54
+ /* Class is dynamically added to the "html" tag. */
55
+
56
+ /* Color Control */
57
+ .a3rev_panel_container .wp-picker-holder { position:absolute; z-index: 10000; }
58
+ .a3rev_panel_container input.wp-picker-default { height:24px !important; }
59
+ .a3rev_panel_container .wp-color-result { top:0px; }
60
+
61
+ /* Text Input Control */
62
+ .a3rev_panel_container .a3rev-ui-text { width:300px; max-width:70%; }
63
+
64
+ /* Email Input Control */
65
+ .a3rev_panel_container .a3rev-ui-email { width:300px; max-width:70%; }
66
+
67
+ /* Number Input Control */
68
+ .a3rev_panel_container .a3rev-ui-number { width:40px; max-width:70%; }
69
+
70
+ /* Password Input Control */
71
+ .a3rev_panel_container .a3rev-ui-password { width:300px; max-width:70%; }
72
+
73
+ /* Textarea Control */
74
+ .a3rev_panel_container .a3rev-ui-textarea { width:600px; max-width:70%; }
75
+
76
+ /* Select Control */
77
+ .a3rev_panel_container .a3rev-ui-select { width:160px; max-width:70%; }
78
+
79
+ /* Multiselect Control */
80
+ .a3rev_panel_container .a3rev-ui-multiselect { width:300px; max-width:70%; }
81
+
82
+ /* Radio Control */
83
+ .a3rev_panel_container .forminp-radio ul { margin:0; }
84
+
85
+ /* Image Size Control */
86
+ .a3rev_panel_container .a3rev-ui-image_size-width { width:40px; }
87
+ .a3rev_panel_container .a3rev-ui-image_size-height { width:40px; }
88
+ .a3rev_panel_container .a3rev-ui-image_size-crop { }
89
+
90
+ /* Single Select Page Control */
91
+ .a3rev_panel_container .a3rev-ui-single_select_page { width:300px; max-width:70%; }
92
+
93
+ /* Settings Preview */
94
+ .a3rev_panel_container .a3rev-ui-settings-preview { display:inline-block; }
95
+ .a3rev_panel_container .settings-apply-preview { padding:10px; background:#FF0; }
96
+ .a3rev_panel_container .settings-preview-container .preview_remove {
97
+ background:#EEEEEE;
98
+ border: 1px solid #DDDDDD;
99
+ border-radius: 2px 2px 2px 2px;
100
+ -webkit-border-radius: 2px 2px 2px 2px;
101
+ -moz-border-radius: 2px 2px 2px 2px;
102
+ cursor: pointer;
103
+ height: 10px;
104
+ padding: 2px;
105
+ position: absolute;
106
+ right: -10px;
107
+ top: -10px;
108
+ width: 10px;
109
+ z-index: 99;
110
+ text-decoration:none !important;
111
+ }
112
+ .a3rev_panel_container .a3rev-ui-settings-preview-button { float: left; margin: 0px; padding-top: 0px; height:24px; line-height:24px; }
113
+ .a3rev_panel_container .settings-preview-container { clear: both; position:relative; margin-top:12px; width:50%; }
114
+ .a3rev_panel_container .settings-preview { word-wrap: break-word; clear: both; padding: 30px; border: 1px solid #CCCCCC; background: #FDFDFD; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
115
+
116
+ /* Border Styles Control */
117
+ .a3rev_panel_container .a3rev-ui-border_styles-width { width:80px; }
118
+ .a3rev_panel_container .a3rev-ui-border_styles-style { width:80px; }
119
+
120
+ /* Border Rounded Corner Control */
121
+ .a3rev_panel_container .forminp-border_corner .desc { margin-bottom:10px !important; }
122
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer { margin-right:30px; }
123
+ .a3rev_panel_container .a3rev-ui-border-corner-value-container { float:left; width:100%; }
124
+ .a3rev_panel_container .a3rev-ui-border_corner-top_left, .a3rev_panel_container .a3rev-ui-border_corner-top_right, .a3rev_panel_container .a3rev-ui-border_corner-bottom_left, .a3rev_panel_container .a3rev-ui-border_corner-bottom_right { float:left; width:100%; clear:both; padding-top:5px; }
125
+ .a3rev_panel_container .a3rev-ui-border_corner-span { float:left; width:140px; margin-bottom:8px; }
126
+ .a3rev_panel_container .a3rev-ui-border_corner-px { float:left; margin-right:10px; }
127
+ .a3rev_panel_container .forminp-border_corner .settings-apply-preview { border:1px solid #515151; }
128
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer .iPhoneCheckLabelOff, .a3rev_panel_container .forminp-border_corner .iOSCheckContainer .iOSCheckLabelOff {
129
+ background: #569aef;
130
+ background: -moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
131
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));
132
+ background: -webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
133
+ background: -o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
134
+ background: -ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
135
+ background: linear-gradient(#468be0 20%, #569aef 50%, #6aa7f6 52%, #82b3f5 100%);
136
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);
137
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
138
+ -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
139
+ border: 1px solid #666666;
140
+ border-radius: 5px;
141
+ -webkit-border-radius: 5px 5px 5px 5px;
142
+ -moz-border-radius: 5px 5px 5px 5px;
143
+
144
+ color: #FFFFFF;
145
+ text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.6);
146
+ }
147
+
148
+ /* Box Shadow Control */
149
+ .a3rev_panel_container .a3rev-ui-box_shadow-h_shadow { width:80px; }
150
+ .a3rev_panel_container .a3rev-ui-box_shadow-v_shadow { width:80px; }
151
+ .a3rev_panel_container .a3rev-ui-box_shadow-blur { width:80px; }
152
+ .a3rev_panel_container .a3rev-ui-box_shadow-spread { width:80px; }
153
+ .a3rev_panel_container .a3rev-ui-box_shadow-enable-container { margin-top:10px; }
154
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer, .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer { float:none; display:inline-block; margin-top:0; top:-12px; margin-right:0px; }
155
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer .iPhoneCheckLabelOff, .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer .iOSCheckLabelOff {
156
+ background: #569aef;
157
+ background: -moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
158
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));
159
+ background: -webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
160
+ background: -o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
161
+ background: -ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
162
+ background: linear-gradient(#468be0 20%, #569aef 50%, #6aa7f6 52%, #82b3f5 100%);
163
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);
164
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
165
+ -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
166
+ border: 1px solid #666666;
167
+ border-radius: 5px;
168
+ -webkit-border-radius: 5px 5px 5px 5px;
169
+ -moz-border-radius: 5px 5px 5px 5px;
170
+
171
+ color: #FFFFFF;
172
+ text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.6);
173
+ }
174
+
175
+ /* Uploader Control */
176
+ .a3rev_panel_container .a3rev-ui-upload { width:300px; height:24px; }
177
+
178
+ /* SLIDER Control */
179
+ .a3rev_panel_container .a3rev-ui-slide-container {
180
+ white-space:nowrap;
181
+ float:left;
182
+ }
183
+ .a3rev_panel_container .a3rev-ui-slide-container-start {
184
+ padding-left:12px;
185
+ margin-bottom:15px;
186
+ margin-right:20px;
187
+ float:left;
188
+ }
189
+ .a3rev_panel_container .a3rev-ui-slide-result-container {
190
+ float:left;
191
+ white-space:nowrap;
192
+ }
193
+ .a3rev_panel_container .a3rev-ui-slide {
194
+ background: #ededed;
195
+ background: -moz-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
196
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#ededed),color-stop(50%,#ededed),color-stop(52%,#f7f6f6),color-stop(100%,#ffffff));
197
+ background: -webkit-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
198
+ background: -o-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
199
+ background: -ms-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
200
+ background: linear-gradient(#dcdcdc 20%, #ededed 50%, #f7f6f6 52%, #ffffff 100%);
201
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dcdcdc',endColorstr='#ffffff',GradientType=0);
202
+ border: 1px solid #d0d0d9;
203
+ border-radius: 3px;
204
+ -webkit-border-radius: 3px 3px 3px 3px;
205
+ -moz-border-radius: 3px 3px 3px 3px;
206
+
207
+ height: 10px;
208
+ width: 220px;
209
+ position:relative;
210
+ float:left;
211
+ margin-top:4px;
212
+ }
213
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-handle {
214
+ background: #569aef;
215
+ background: -moz-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
216
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#bcbcbc),color-stop(50%,#d5d5d5),color-stop(52%,#d8d8d8),color-stop(100%,#efefef));
217
+ background: -webkit-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
218
+ background: -o-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
219
+ background: -ms-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
220
+ background: linear-gradient(#bcbcbc 20%, #d5d5d5 50%, #d8d8d8 52%, #efefef 100%);
221
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#bcbcbc',endColorstr='#efefef',GradientType=0);
222
+ box-shadow: 0 1px 0px 0px #FFFFFF inset;
223
+ -webkit-box-shadow: 0 1px 0px 0px #FFFFFF inset;
224
+ border: 1px solid #999999;
225
+ border-radius: 3px;
226
+ -webkit-border-radius: 3px 3px 3px 3px;
227
+ -moz-border-radius: 3px 3px 3px 3px;
228
+
229
+ position: absolute;
230
+ z-index: 2;
231
+ width: 22px;
232
+ height: 23px;
233
+ cursor: pointer;
234
+ font-weight: bold;
235
+ color: #1C94C4;
236
+ outline: none;
237
+ top: -8px;
238
+ margin-left: -11px;
239
+ }
240
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-range {
241
+ background: #569aef;
242
+ background: -moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
243
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));
244
+ background: -webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
245
+ background: -o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
246
+ background: -ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
247
+ background: linear-gradient(#468be0 20%, #569aef 50%, #6aa7f6 52%, #82b3f5 100%);
248
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);
249
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
250
+ -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
251
+ border: 1px solid #255399;
252
+ border-radius: 3px;
253
+ -webkit-border-radius: 3px 3px 3px 3px;
254
+ -moz-border-radius: 3px 3px 3px 3px;
255
+
256
+ position: absolute;
257
+ top: -1px;
258
+ height: 100%;
259
+ }
260
+ .a3rev_panel_container .a3rev-ui-slider { float:left; width: 50px; padding:3px; margin-top:-1px;}
261
+
262
+ /* Array TextFields Control */
263
+ .a3rev_panel_container .a3rev-ui-array_textfields { width:40px; }
264
+
265
+ /* OnOff Radio Control */
266
+ .a3rev_panel_container .forminp-onoff_radio ul {
267
+ float:left;
268
+ width:100%;
269
+ margin:0;
270
+ }
271
+ .a3rev_panel_container .forminp-onoff_radio li {
272
+ float:left;
273
+ width:100%;
274
+ padding-top:10px;
275
+ }
276
+ .a3rev_panel_container .forminp-onoff_radio .iPhoneCheckDisabled , .a3rev_panel_container .forminp-onoff_radio .iOSCheckDisabled {
277
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
278
+ opacity: 1;
279
+ }
280
+
281
+ /* OnOff Checkbox & Radio Control */
282
+ .a3rev_panel_container .iPhoneCheckContainer, .a3rev_panel_container .iOSCheckContainer {
283
+ position: relative;
284
+ height: 25px;
285
+ cursor: pointer;
286
+ margin-right:10px;
287
+ float:left;
288
+ margin-top:-3px;
289
+ }
290
+ .a3rev_panel_container .iPhoneCheckContainer input, .a3rev_panel_container .iOSCheckContainer input {
291
+ display: none;
292
+ }
293
+ .a3rev_panel_container .iPhoneCheckContainer label, .a3rev_panel_container .iOSCheckContainer label {
294
+ white-space: nowrap;
295
+ font-size: 14px;
296
+ line-height: 24px;
297
+ font-weight: bold;
298
+ font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
299
+ cursor: pointer;
300
+ display: block;
301
+ position: absolute;
302
+ width: auto;
303
+ top: 0;
304
+ overflow: hidden;
305
+ user-select: none;
306
+ -moz-user-select: none;
307
+ -khtml-user-select: none;
308
+ }
309
+ .a3rev_panel_container label.iPhoneCheckLabelOff, .a3rev_panel_container label.iOSCheckLabelOff {
310
+ background: #ededed;
311
+ background: -moz-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
312
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#ededed),color-stop(50%,#ededed),color-stop(52%,#f7f6f6),color-stop(100%,#ffffff));
313
+ background: -webkit-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
314
+ background: -o-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
315
+ background: -ms-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#ffffff 100%);
316
+ background: linear-gradient(#dcdcdc 20%, #ededed 50%, #f7f6f6 52%, #ffffff 100%);
317
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dcdcdc',endColorstr='#ffffff',GradientType=0);
318
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
319
+ -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
320
+ border: 1px solid #999999;
321
+ border-radius: 5px;
322
+ -webkit-border-radius: 5px 5px 5px 5px;
323
+ -moz-border-radius: 5px 5px 5px 5px;
324
+
325
+ height: 23px;
326
+ color: #8b8b8b;
327
+ text-shadow: 0px 0px 2px rgba(255, 255, 255, 0.6);
328
+ text-align: right;
329
+ right: 0;
330
+ }
331
+ .a3rev_panel_container label.iPhoneCheckLabelOff span, .a3rev_panel_container label.iOSCheckLabelOff span {
332
+ padding-right: 10px;
333
+ padding-left: 0px;
334
+ display: inline-block;
335
+ text-transform:uppercase;
336
+ }
337
+ .a3rev_panel_container label.iPhoneCheckLabelOn, .a3rev_panel_container label.iOSCheckLabelOn {
338
+ background: #569aef;
339
+ background: -moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
340
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));
341
+ background: -webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
342
+ background: -o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
343
+ background: -ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
344
+ background: linear-gradient(#468be0 20%, #569aef 50%, #6aa7f6 52%, #82b3f5 100%);
345
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);
346
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
347
+ -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
348
+ border: 1px solid #999999;
349
+ border-radius: 5px;
350
+ -webkit-border-radius: 5px 5px 5px 5px;
351
+ -moz-border-radius: 5px 5px 5px 5px;
352
+
353
+ height: 23px;
354
+ text-align:left;
355
+ color: #FFFFFF;
356
+ text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.6);
357
+ left: 0;
358
+ }
359
+ .a3rev_panel_container label.iPhoneCheckLabelOn span, .a3rev_panel_container label.iOSCheckLabelOn span {
360
+ padding-left:10px;
361
+ display: inline-block;
362
+ text-transform:uppercase;
363
+ }
364
+ .a3rev_panel_container .iPhoneCheckHandle, .a3rev_panel_container .iOSCheckHandle {
365
+ background: #569aef;
366
+ background: -moz-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
367
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#bcbcbc),color-stop(50%,#d5d5d5),color-stop(52%,#d8d8d8),color-stop(100%,#efefef));
368
+ background: -webkit-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
369
+ background: -o-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
370
+ background: -ms-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);
371
+ background: linear-gradient(#bcbcbc 20%, #d5d5d5 50%, #d8d8d8 52%, #efefef 100%);
372
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#bcbcbc',endColorstr='#efefef',GradientType=0);
373
+ box-shadow: 0 1px 0px 0px #FFFFFF inset;
374
+ -webkit-box-shadow: 0 1px 0px 0px #FFFFFF inset;
375
+ border: 1px solid #999999;
376
+ border-radius: 5px;
377
+ -webkit-border-radius: 5px 5px 5px 5px;
378
+ -moz-border-radius: 5px 5px 5px 5px;
379
+
380
+ display: block;
381
+ cursor: pointer;
382
+ position: absolute;
383
+ top: 0px;
384
+ left: -1px;
385
+ width: 35px;
386
+ height:23px;
387
+ }
388
+
389
+ .a3rev_panel_container .iPhoneCheckDisabled , .a3rev_panel_container .iOSCheckDisabled {
390
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
391
+ opacity: 0.5;
392
+ }
393
+ /* Switcher Checkbox Control */
394
+ .a3rev_panel_container .forminp-switcher_checkbox .iPhoneCheckContainer .iPhoneCheckLabelOff, .a3rev_panel_container .forminp-switcher_checkbox .iOSCheckContainer .iOSCheckLabelOff {
395
+ background: #569aef;
396
+ background: -moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
397
+ background: -webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));
398
+ background: -webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
399
+ background: -o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
400
+ background: -ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);
401
+ background: linear-gradient(#468be0 20%, #569aef 50%, #6aa7f6 52%, #82b3f5 100%);
402
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);
403
+ box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
404
+ -webkit-box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.5) inset, 0 1px 0 0 rgba(250, 250, 250, 0.5);
405
+ border: 1px solid #666666;
406
+ border-radius: 5px;
407
+ -webkit-border-radius: 5px 5px 5px 5px;
408
+ -moz-border-radius: 5px 5px 5px 5px;
409
+
410
+ color: #FFFFFF;
411
+ text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.6);
412
+ }
413
+
414
+ /* Help Tip */
415
+ .a3rev_panel_container table.form-table th img.help_tip {
416
+ float: right;
417
+ margin: 0 -12px 0 0;
418
+ }
419
+ .a3rev_panel_container table.form-table img.help_tip {
420
+ cursor: help;
421
+ line-height: 1;
422
+ margin: -4px 0 0 5px;
423
+ padding: 0;
424
+ vertical-align: middle;
425
+ }
426
+
427
+ /* Sub tab ui */
428
+ .subsubsub { white-space:normal; }
429
+ .subsubsub li { white-space:nowrap ;}
430
+
431
+ /* View Doc button */
432
+ .a3-view-docs-button { background-color: #FFFFE0 !important; border: 1px solid #E6DB55 !important; display: inline-block !important; font-weight: normal !important; margin: 5px 10px 0 !important; text-shadow: none !important; }
433
+
434
+
435
+ /* Style for yellow box about Pro or Ultimate version */
436
+ #a3_plugin_panel_container { position:relative; margin-top:10px; float:left; width:100%;}
437
+ #a3_plugin_panel_fields { width:65%; float:left;}
438
+ #a3_plugin_panel_upgrade_area { margin-left: 65%; padding-left:10px;}
439
+ #a3_plugin_panel_extensions { border:2px solid #E6DB55;-webkit-border-radius:10px;-moz-border-radius:10px;-o-border-radius:10px; border-radius: 10px; color: #555555; margin: 0px; padding: 5px 10px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); background:#FFFBCC; }
440
+ #a3_plugin_panel_extensions img { width:100%; max-width:100%; }
441
+ .pro_feature_top_message { font-size:11px; text-align:center; margin:10px 0; }
442
+ .pro_feature_fields { margin-right: -12px; position: relative; z-index: 10; border:2px solid #E6DB55;-webkit-border-radius:10px 0 0 10px;-moz-border-radius:10px 0 0 10px;-o-border-radius:10px 0 0 10px; border-radius: 10px 0 0 10px; border-right: 2px solid #FFFFFF; }
443
+ .pro_feature_fields h3 { margin:8px 5px; }
444
+ .pro_feature_fields p { margin-left:5px; }
445
+ .pro_feature_fields .form-table td, .pro_feature_fields .form-table th { padding:4px 10px; }
446
+
447
+ /* Style for Blue message box */
448
+ .a3rev_blue_message_box {
449
+ margin:0 !important;
450
+ background-color: #F0F8FF;
451
+ border-color: #CEE1EF;
452
+ padding:5px 10px;
453
+ border-radius: 3px 3px 3px 3px;
454
+ -webkit-border-radius: 3px 3px 3px 3px;
455
+ -moz-border-radius: 3px 3px 3px 3px;
456
+ border-style: solid;
457
+ border-width: 1px;
458
+ }
459
+ .a3rev_blue_message_box a {
460
+ color:#F00;
461
+ }
462
+
463
+ /* Chosen Style */
464
+ .a3rev_panel_container .chosen-container {
465
+ margin-bottom:5px;
466
+ margin-right:2px;
467
+ }
468
+
469
+ /* A3 Plugin Framework Font Icons */
470
+
471
+ /* GENERATE by Fontastic http://fontastic.me */
472
+ @font-face {
473
+ font-family: "a3-plugin-framework";
474
+ src:url("../fonts/a3-plugin-framework.eot");
475
+ src:url("../fonts/a3-plugin-framework.eot?#iefix") format("embedded-opentype"),
476
+ url("../fonts/a3-plugin-framework.woff") format("woff"),
477
+ url("../fonts/a3-plugin-framework.ttf") format("truetype"),
478
+ url("../fonts/a3-plugin-framework.svg#a3-plugin-framework") format("svg");
479
+ font-weight: normal;
480
+ font-style: normal;
481
+
482
+ }
483
+
484
+ [data-icon]:before {
485
+ font-family: "a3-plugin-framework" !important;
486
+ content: attr(data-icon);
487
+ font-style: normal !important;
488
+ font-weight: normal !important;
489
+ font-variant: normal !important;
490
+ text-transform: none !important;
491
+ speak: none;
492
+ line-height: 1;
493
+ -webkit-font-smoothing: antialiased;
494
+ -moz-osx-font-smoothing: grayscale;
495
+ }
496
+
497
+ [class^="a3-plugin-ui-"]:before,
498
+ [class*=" a3-plugin-ui-"]:before {
499
+ font-family: "a3-plugin-framework" !important;
500
+ font-style: normal !important;
501
+ font-weight: normal !important;
502
+ font-variant: normal !important;
503
+ text-transform: none !important;
504
+ speak: none;
505
+ line-height: 1;
506
+ -webkit-font-smoothing: antialiased;
507
+ -moz-osx-font-smoothing: grayscale;
508
+ }
509
+
510
+ .a3-plugin-ui-a3-plugins-icon:before {
511
+ content: "a";
512
+ }
513
+ .a3-plugin-ui-a3-rev-logo:before {
514
+ content: "b";
515
+ }
516
+ .a3-plugin-ui-a3-thumb-icon:before {
517
+ content: "c";
518
+ }
519
+ .a3-plugin-ui-delete-icon:before {
520
+ content: "d";
521
+ }
522
+ .a3-plugin-ui-help-icon:before {
523
+ content: "e";
524
+ }
525
+ .a3-plugin-ui-key-icon:before {
526
+ content: "f";
527
+ }
528
+ .a3-plugin-ui-preview-icon:before {
529
+ content: "g";
530
+ }
531
+ .a3-plugin-ui-refresh-icon:before {
532
+ content: "h";
533
+ }
534
+ .a3-plugin-ui-loading-icon:before {
535
+ content: "k";
536
+ }
537
+ .a3-plugin-ui-a3-plugins-icon-1:before {
538
+ content: "i";
539
+ }
540
+ .a3-plugin-ui-a3-rev-logo-1:before {
541
+ content: "j";
542
+ }
543
+
544
+ /* Custom for each element web icons font */
545
+ .a3-plugin-ui-delete-icon:before {
546
+ vertical-align:top;
547
+ }
548
+ .a3-plugin-ui-icon {
549
+ color:#46719d;
550
+ overflow:hidden;
551
+ }
552
+ .a3-plugin-ui-a3-rev-logo {
553
+ font-size: 170px;
554
+ height: 125px;
555
+ margin-top: -30px;
556
+ }
557
+ .a3-plugin-ui-help-icon {
558
+ color:#777;
559
+ float:right;
560
+ margin-right:-15px;
561
+ width:14px;
562
+ height:14px;
563
+ cursor:pointer;
564
+ font-size:12px;
565
+ margin-top:5px;
566
+ }
567
+ .a3-plugin-ui-preview-icon {
568
+ color: #000;
569
+ display: block;
570
+ width: 14px;
571
+ height: 16px;
572
+ }
573
+ .a3rev_panel_container .a3rev-ui-typography-preview-button span:before, .a3rev_panel_container .a3rev-ui-settings-preview-button span:before {
574
+ font-family: "a3-plugin-framework" !important;
575
+ font-style: normal !important;
576
+ font-weight: normal !important;
577
+ font-variant: normal !important;
578
+ text-transform: none !important;
579
+ speak: none;
580
+ line-height: 1;
581
+ -webkit-font-smoothing: antialiased;
582
+ -moz-osx-font-smoothing: grayscale;
583
+
584
+ content: "g";
585
+ width: 14px;
586
+ height: 16px;
587
+ font-size:12px;
588
+ }
589
+ .a3rev_panel_container .a3rev-ui-typography-preview-button span.refresh:before, .a3rev_panel_container .a3rev-ui-settings-preview-button span.refresh:before {
590
+ content: "h" !important;
591
+ }
592
+ .wf-loading .a3rev_panel_container .typography-preview.current:before, .wf-loading .a3rev_panel_container .settings-preview.current:before {
593
+ content: "k" !important;
594
+ }
595
+ .a3-plugin-ui-delete-icon {
596
+ font-size:10px;
597
+ color:#C00;
598
+ }
599
+
600
+ /* END A3 Plugin Framework Font Icons */
601
+
602
+ @media screen and ( min-width: 783px ) {
603
+ .a3rev_panel_container .chosen-container-multi {
604
+ min-width:300px;
605
+ }
606
+ }
607
+
608
+ @media screen and ( max-width: 782px ) {
609
+ #a3_plugin_panel_fields {
610
+ width: 100%;
611
+ }
612
+ #a3_plugin_panel_upgrade_area {
613
+ display:none;
614
+ }
615
+ .a3rev_panel_container .pro_feature_fields {
616
+ border-color: #E6DB55;
617
+ margin-right: 0px;
618
+ border-radius:10px;
619
+ -webkit-border-radius:10px;
620
+ -moz-border-radius:10px;
621
+ -o-border-radius:10px;
622
+ }
623
+ .a3rev_panel_container input[type="text"], .a3rev_panel_container input[type="email"], .a3rev_panel_container input[type="number"], .a3rev_panel_container input[type="password"] {
624
+ min-width:50px;
625
+ width:100%;
626
+ }
627
+ .a3rev_panel_container .a3rev-ui-text {
628
+ max-width:none;
629
+ width:100%;
630
+ }
631
+ .a3rev_panel_container .a3rev-ui-textarea {
632
+ max-width:none !important;
633
+ width:100% !important;
634
+ }
635
+ .a3rev_panel_container .a3rev-ui-slider {
636
+ width:50px !important;
637
+ }
638
+ .a3rev_panel_container .typography-preview-container, .a3rev_panel_container .settings-preview-container {
639
+ width:90%;
640
+ }
641
+ .a3rev_panel_container .a3rev-ui-typography-preview-button:active, .a3rev_panel_container .a3rev-ui-settings-preview-button:active {
642
+ padding-top:inherit !important;
643
+ }
644
+ .a3rev_panel_container .wp-picker-container input.wp-color-picker[type="text"] {
645
+ width:75px !important;
646
+ padding:3px 10px !important;
647
+ }
648
+ .wp-core-ui .button.wp-picker-default {
649
+ padding:0 8px 1px;
650
+ }
651
+ .a3rev_panel_container input.a3rev-color-picker { margin-top: 1px !important;}
652
+ .a3rev_panel_container input.wp-picker-default { margin-top: 1px !important; padding:2px 8px !important; }
653
+
654
+ .a3rev_panel_container .chosen-container-multi {
655
+ width: 100% !important;
656
+ }
657
+ .a3rev_blue_message_box_container {
658
+ width:100% !important;
659
+ }
660
+ .a3-plugin-ui-help-icon {
661
+ margin-right:0px;
662
+ }
663
+ }
664
+
665
+ @media screen and ( max-width: 480px ) {
666
+ .a3rev_panel_container .a3rev-ui-slide-container-start {
667
+ margin-top:5px;
668
+ }
669
+ .a3_subsubsub_section .subsubsub {
670
+ text-align:left;
671
+ }
672
+ .a3rev_panel_container .chosen-container-single {
673
+ max-width: 300px !important;
674
+ }
675
+ }
admin/assets/css/admin-ui-style.min.css ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .a3rev_panel_container{visibility:hidden;height:0;overflow:hidden;margin-top:10px}
2
+ .a3rev_panel_container .a3rev_panel_inner{clear:both;display:block;padding-bottom:10px}
3
+ .a3rev_panel_container .a3rev_panel_inner h3{margin-bottom:0}
4
+ .a3rev_panel_container .a3rev_panel_inner .form-table{margin-bottom:0}
5
+ .icon32-a3rev-ui-settings{background:url("../images/a3-plugins.png") no-repeat left top}
6
+ .a3rev_panel_container input[type="text"],.a3rev_panel_container input[type="email"],.a3rev_panel_container input[type="number"],.a3rev_panel_container input[type="password"]{height:24px}
7
+ .a3rev_panel_container .a3rev-ui-typography-size{width:80px}
8
+ .a3rev_panel_container .a3rev-ui-typography-face{width:160px}
9
+ .a3rev_panel_container .a3rev-ui-typography-style{width:100px}
10
+ .a3rev_panel_container .a3rev-ui-typography-preview{display:inline-block}
11
+ .a3rev_panel_container .typography-preview-container .preview_remove{background:#eee;border:1px solid #ddd;border-radius:2px 2px 2px 2px;-webkit-border-radius:2px 2px 2px 2px;-moz-border-radius:2px 2px 2px 2px;cursor:pointer;height:10px;padding:2px;position:absolute;right:-10px;top:-10px;width:10px;z-index:99;text-decoration:none !important}
12
+ .a3rev_panel_container .a3rev-ui-typography-preview-button{float:left;margin:0;padding-top:0;height:24px;line-height:24px}
13
+ .a3rev_panel_container .typography-preview-container{clear:both;position:relative;width:50%;margin-top:10px}
14
+ .a3rev_panel_container .typography-preview{word-wrap:break-word;clear:both;padding:20px;border:1px solid #ccc;background:#fdfdfd;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}
15
+ .a3rev_panel_container .wp-picker-holder{position:absolute;z-index:10000}
16
+ .a3rev_panel_container input.wp-picker-default{height:24px !important}
17
+ .a3rev_panel_container .wp-color-result{top:0}
18
+ .a3rev_panel_container .a3rev-ui-text{width:300px;max-width:70%}
19
+ .a3rev_panel_container .a3rev-ui-email{width:300px;max-width:70%}
20
+ .a3rev_panel_container .a3rev-ui-number{width:40px;max-width:70%}
21
+ .a3rev_panel_container .a3rev-ui-password{width:300px;max-width:70%}
22
+ .a3rev_panel_container .a3rev-ui-textarea{width:600px;max-width:70%}
23
+ .a3rev_panel_container .a3rev-ui-select{width:160px;max-width:70%}
24
+ .a3rev_panel_container .a3rev-ui-multiselect{width:300px;max-width:70%}
25
+ .a3rev_panel_container .forminp-radio ul{margin:0}
26
+ .a3rev_panel_container .a3rev-ui-image_size-width{width:40px}
27
+ .a3rev_panel_container .a3rev-ui-image_size-height{width:40px}
28
+ .a3rev_panel_container .a3rev-ui-single_select_page{width:300px;max-width:70%}
29
+ .a3rev_panel_container .a3rev-ui-settings-preview{display:inline-block}
30
+ .a3rev_panel_container .settings-apply-preview{padding:10px;background:#FF0}
31
+ .a3rev_panel_container .settings-preview-container .preview_remove{background:#eee;border:1px solid #ddd;border-radius:2px 2px 2px 2px;-webkit-border-radius:2px 2px 2px 2px;-moz-border-radius:2px 2px 2px 2px;cursor:pointer;height:10px;padding:2px;position:absolute;right:-10px;top:-10px;width:10px;z-index:99;text-decoration:none !important}
32
+ .a3rev_panel_container .a3rev-ui-settings-preview-button{float:left;margin:0;padding-top:0;height:24px;line-height:24px}
33
+ .a3rev_panel_container .settings-preview-container{clear:both;position:relative;margin-top:12px;width:50%}
34
+ .a3rev_panel_container .settings-preview{word-wrap:break-word;clear:both;padding:30px;border:1px solid #ccc;background:#fdfdfd;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}
35
+ .a3rev_panel_container .a3rev-ui-border_styles-width{width:80px}
36
+ .a3rev_panel_container .a3rev-ui-border_styles-style{width:80px}
37
+ .a3rev_panel_container .forminp-border_corner .desc{margin-bottom:10px !important}
38
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer{margin-right:30px}
39
+ .a3rev_panel_container .a3rev-ui-border-corner-value-container{float:left;width:100%}
40
+ .a3rev_panel_container .a3rev-ui-border_corner-top_left,.a3rev_panel_container .a3rev-ui-border_corner-top_right,.a3rev_panel_container .a3rev-ui-border_corner-bottom_left,.a3rev_panel_container .a3rev-ui-border_corner-bottom_right{float:left;width:100%;clear:both;padding-top:5px}
41
+ .a3rev_panel_container .a3rev-ui-border_corner-span{float:left;width:140px;margin-bottom:8px}
42
+ .a3rev_panel_container .a3rev-ui-border_corner-px{float:left;margin-right:10px}
43
+ .a3rev_panel_container .forminp-border_corner .settings-apply-preview{border:1px solid #515151}
44
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer .iPhoneCheckLabelOff,.a3rev_panel_container .forminp-border_corner .iOSCheckContainer .iOSCheckLabelOff{background:#569aef;background:-moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));background:-webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:linear-gradient(#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;color:#fff;text-shadow:0 0 2px rgba(0,0,0,0.6)}
45
+ .a3rev_panel_container .a3rev-ui-box_shadow-h_shadow{width:80px}
46
+ .a3rev_panel_container .a3rev-ui-box_shadow-v_shadow{width:80px}
47
+ .a3rev_panel_container .a3rev-ui-box_shadow-blur{width:80px}
48
+ .a3rev_panel_container .a3rev-ui-box_shadow-spread{width:80px}
49
+ .a3rev_panel_container .a3rev-ui-box_shadow-enable-container{margin-top:10px}
50
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer,.a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer{float:none;display:inline-block;margin-top:0;top:-12px;margin-right:0}
51
+ .a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iPhoneCheckContainer .iPhoneCheckLabelOff,.a3rev_panel_container .forminp-box_shadow .a3rev-ui-settings-control .iOSCheckContainer .iOSCheckLabelOff{background:#569aef;background:-moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));background:-webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:linear-gradient(#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;color:#fff;text-shadow:0 0 2px rgba(0,0,0,0.6)}
52
+ .a3rev_panel_container .a3rev-ui-upload{width:300px;height:24px}
53
+ .a3rev_panel_container .a3rev-ui-slide-container{white-space:nowrap;float:left}
54
+ .a3rev_panel_container .a3rev-ui-slide-container-start{padding-left:12px;margin-bottom:15px;margin-right:20px;float:left}
55
+ .a3rev_panel_container .a3rev-ui-slide-result-container{float:left;white-space:nowrap}
56
+ .a3rev_panel_container .a3rev-ui-slide{background:#ededed;background:-moz-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#ededed),color-stop(50%,#ededed),color-stop(52%,#f7f6f6),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:-o-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:-ms-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:linear-gradient(#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dcdcdc',endColorstr='#ffffff',GradientType=0);border:1px solid #d0d0d9;border-radius:3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;height:10px;width:220px;position:relative;float:left;margin-top:4px}
57
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-handle{background:#569aef;background:-moz-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#bcbcbc),color-stop(50%,#d5d5d5),color-stop(52%,#d8d8d8),color-stop(100%,#efefef));background:-webkit-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:-o-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:-ms-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:linear-gradient(#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#bcbcbc',endColorstr='#efefef',GradientType=0);box-shadow:0 1px 0 0 #fff inset;-webkit-box-shadow:0 1px 0 0 #fff inset;border:1px solid #999;border-radius:3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;position:absolute;z-index:2;width:22px;height:23px;cursor:pointer;font-weight:bold;color:#1c94c4;outline:0;top:-8px;margin-left:-11px}
58
+ .a3rev_panel_container .a3rev-ui-slide .ui-slider-range{background:#569aef;background:-moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));background:-webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:linear-gradient(#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);border:1px solid #255399;border-radius:3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;position:absolute;top:-1px;height:100%}
59
+ .a3rev_panel_container .a3rev-ui-slider{float:left;width:50px;padding:3px;margin-top:-1px}
60
+ .a3rev_panel_container .a3rev-ui-array_textfields{width:40px}
61
+ .a3rev_panel_container .forminp-onoff_radio ul{float:left;width:100%;margin:0}
62
+ .a3rev_panel_container .forminp-onoff_radio li{float:left;width:100%;padding-top:10px}
63
+ .a3rev_panel_container .forminp-onoff_radio .iPhoneCheckDisabled,.a3rev_panel_container .forminp-onoff_radio .iOSCheckDisabled{filter:alpha(opacity=100);opacity:1}
64
+ .a3rev_panel_container .iPhoneCheckContainer,.a3rev_panel_container .iOSCheckContainer{position:relative;height:25px;cursor:pointer;margin-right:10px;float:left;margin-top:-3px}
65
+ .a3rev_panel_container .iPhoneCheckContainer input,.a3rev_panel_container .iOSCheckContainer input{display:none}
66
+ .a3rev_panel_container .iPhoneCheckContainer label,.a3rev_panel_container .iOSCheckContainer label{white-space:nowrap;font-size:14px;line-height:24px;font-weight:bold;font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;cursor:pointer;display:block;position:absolute;width:auto;top:0;overflow:hidden;user-select:none;-moz-user-select:none;-khtml-user-select:none}
67
+ .a3rev_panel_container label.iPhoneCheckLabelOff,.a3rev_panel_container label.iOSCheckLabelOff{background:#ededed;background:-moz-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#ededed),color-stop(50%,#ededed),color-stop(52%,#f7f6f6),color-stop(100%,#fff));background:-webkit-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:-o-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:-ms-linear-gradient(top,#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);background:linear-gradient(#dcdcdc 20%,#ededed 50%,#f7f6f6 52%,#fff 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dcdcdc',endColorstr='#ffffff',GradientType=0);box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);border:1px solid #999;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;height:23px;color:#8b8b8b;text-shadow:0 0 2px rgba(255,255,255,0.6);text-align:right;right:0}
68
+ .a3rev_panel_container label.iPhoneCheckLabelOff span,.a3rev_panel_container label.iOSCheckLabelOff span{padding-right:10px;padding-left:0;display:inline-block;text-transform:uppercase}
69
+ .a3rev_panel_container label.iPhoneCheckLabelOn,.a3rev_panel_container label.iOSCheckLabelOn{background:#569aef;background:-moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));background:-webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:linear-gradient(#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);border:1px solid #999;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;height:23px;text-align:left;color:#fff;text-shadow:0 0 2px rgba(0,0,0,0.6);left:0}
70
+ .a3rev_panel_container label.iPhoneCheckLabelOn span,.a3rev_panel_container label.iOSCheckLabelOn span{padding-left:10px;display:inline-block;text-transform:uppercase}
71
+ .a3rev_panel_container .iPhoneCheckHandle,.a3rev_panel_container .iOSCheckHandle{background:#569aef;background:-moz-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#bcbcbc),color-stop(50%,#d5d5d5),color-stop(52%,#d8d8d8),color-stop(100%,#efefef));background:-webkit-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:-o-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:-ms-linear-gradient(top,#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);background:linear-gradient(#bcbcbc 20%,#d5d5d5 50%,#d8d8d8 52%,#efefef 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#bcbcbc',endColorstr='#efefef',GradientType=0);box-shadow:0 1px 0 0 #fff inset;-webkit-box-shadow:0 1px 0 0 #fff inset;border:1px solid #999;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;display:block;cursor:pointer;position:absolute;top:0;left:-1px;width:35px;height:23px}
72
+ .a3rev_panel_container .iPhoneCheckDisabled,.a3rev_panel_container .iOSCheckDisabled{filter:alpha(opacity=50);opacity:.5}
73
+ .a3rev_panel_container .forminp-switcher_checkbox .iPhoneCheckContainer .iPhoneCheckLabelOff,.a3rev_panel_container .forminp-switcher_checkbox .iOSCheckContainer .iOSCheckLabelOff{background:#569aef;background:-moz-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-webkit-gradient(linear,0 0,0 100%,color-stop(20%,#468be0),color-stop(50%,#569aef),color-stop(52%,#6aa7f6),color-stop(100%,#82b3f5));background:-webkit-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-o-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:-ms-linear-gradient(top,#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);background:linear-gradient(#468be0 20%,#569aef 50%,#6aa7f6 52%,#82b3f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#468be0',endColorstr='#82b3f5',GradientType=0);box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,0.5) inset,0 1px 0 0 rgba(250,250,250,0.5);border:1px solid #666;border-radius:5px;-webkit-border-radius:5px 5px 5px 5px;-moz-border-radius:5px 5px 5px 5px;color:#fff;text-shadow:0 0 2px rgba(0,0,0,0.6)}
74
+ .a3rev_panel_container table.form-table th img.help_tip{float:right;margin:0 -12px 0 0}
75
+ .a3rev_panel_container table.form-table img.help_tip{cursor:help;line-height:1;margin:-4px 0 0 5px;padding:0;vertical-align:middle}
76
+ .subsubsub{white-space:normal}
77
+ .subsubsub li{white-space:nowrap}
78
+ .a3-view-docs-button{background-color:#ffffe0 !important;border:1px solid #e6db55 !important;display:inline-block !important;font-weight:normal !important;margin:5px 10px 0 !important;text-shadow:none !important}
79
+ #a3_plugin_panel_container{position:relative;margin-top:10px;float:left;width:100%}
80
+ #a3_plugin_panel_fields{width:65%;float:left}
81
+ #a3_plugin_panel_upgrade_area{margin-left:65%;padding-left:10px}
82
+ #a3_plugin_panel_extensions{border:2px solid #e6db55;-webkit-border-radius:10px;-moz-border-radius:10px;-o-border-radius:10px;border-radius:10px;color:#555;margin:0;padding:5px 10px;text-shadow:0 1px 0 rgba(255,255,255,0.8);background:#fffbcc}
83
+ #a3_plugin_panel_extensions img{width:100%;max-width:100%}
84
+ .pro_feature_top_message{font-size:11px;text-align:center;margin:10px 0}
85
+ .pro_feature_fields{margin-right:-12px;position:relative;z-index:10;border:2px solid #e6db55;-webkit-border-radius:10px 0 0 10px;-moz-border-radius:10px 0 0 10px;-o-border-radius:10px 0 0 10px;border-radius:10px 0 0 10px;border-right:2px solid #fff}
86
+ .pro_feature_fields h3{margin:8px 5px}
87
+ .pro_feature_fields p{margin-left:5px}
88
+ .pro_feature_fields .form-table td,.pro_feature_fields .form-table th{padding:4px 10px}
89
+ .a3rev_blue_message_box{margin:0 !important;background-color:#f0f8ff;border-color:#cee1ef;padding:5px 10px;border-radius:3px 3px 3px 3px;-webkit-border-radius:3px 3px 3px 3px;-moz-border-radius:3px 3px 3px 3px;border-style:solid;border-width:1px}
90
+ .a3rev_blue_message_box a{color:#F00}
91
+ .a3rev_panel_container .chosen-container{margin-bottom:5px;margin-right:2px}
92
+ @font-face{font-family:"a3-plugin-framework";src:url("../fonts/a3-plugin-framework.eot");src:url("../fonts/a3-plugin-framework.eot?#iefix") format("embedded-opentype"),url("../fonts/a3-plugin-framework.woff") format("woff"),url("../fonts/a3-plugin-framework.ttf") format("truetype"),url("../fonts/a3-plugin-framework.svg#a3-plugin-framework") format("svg");font-weight:normal;font-style:normal}
93
+ [data-icon]:before{font-family:"a3-plugin-framework" !important;content:attr(data-icon);font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
94
+ [class^="a3-plugin-ui-"]:before,[class*=" a3-plugin-ui-"]:before{font-family:"a3-plugin-framework" !important;font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
95
+ .a3-plugin-ui-a3-plugins-icon:before{content:"a"}
96
+ .a3-plugin-ui-a3-rev-logo:before{content:"b"}
97
+ .a3-plugin-ui-a3-thumb-icon:before{content:"c"}
98
+ .a3-plugin-ui-delete-icon:before{content:"d"}
99
+ .a3-plugin-ui-help-icon:before{content:"e"}
100
+ .a3-plugin-ui-key-icon:before{content:"f"}
101
+ .a3-plugin-ui-preview-icon:before{content:"g"}
102
+ .a3-plugin-ui-refresh-icon:before{content:"h"}
103
+ .a3-plugin-ui-loading-icon:before{content:"k"}
104
+ .a3-plugin-ui-a3-plugins-icon-1:before{content:"i"}
105
+ .a3-plugin-ui-a3-rev-logo-1:before{content:"j"}
106
+ .a3-plugin-ui-delete-icon:before{vertical-align:top}
107
+ .a3-plugin-ui-icon{color:#46719d;overflow:hidden}
108
+ .a3-plugin-ui-a3-rev-logo{font-size:170px;height:125px;margin-top:-30px}
109
+ .a3-plugin-ui-help-icon{color:#777;float:right;margin-right:-15px;width:14px;height:14px;cursor:pointer;font-size:12px;margin-top:5px}
110
+ .a3-plugin-ui-preview-icon{color:#000;display:block;width:14px;height:16px}
111
+ .a3rev_panel_container .a3rev-ui-typography-preview-button span:before,.a3rev_panel_container .a3rev-ui-settings-preview-button span:before{font-family:"a3-plugin-framework" !important;font-style:normal !important;font-weight:normal !important;font-variant:normal !important;text-transform:none !important;speak:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"g";width:14px;height:16px;font-size:12px}
112
+ .a3rev_panel_container .a3rev-ui-typography-preview-button span.refresh:before,.a3rev_panel_container .a3rev-ui-settings-preview-button span.refresh:before{content:"h" !important}
113
+ .wf-loading .a3rev_panel_container .typography-preview.current:before,.wf-loading .a3rev_panel_container .settings-preview.current:before{content:"k" !important}
114
+ .a3-plugin-ui-delete-icon{font-size:10px;color:#C00}
115
+ @media screen and (min-width:783px){.a3rev_panel_container .chosen-container-multi{min-width:300px}
116
+ }
117
+ @media screen and (max-width:782px){#a3_plugin_panel_fields{width:100%}
118
+ #a3_plugin_panel_upgrade_area{display:none}
119
+ .a3rev_panel_container .pro_feature_fields{border-color:#e6db55;margin-right:0;border-radius:10px;-webkit-border-radius:10px;-moz-border-radius:10px;-o-border-radius:10px}
120
+ .a3rev_panel_container input[type="text"],.a3rev_panel_container input[type="email"],.a3rev_panel_container input[type="number"],.a3rev_panel_container input[type="password"]{min-width:50px;width:100%}
121
+ .a3rev_panel_container .a3rev-ui-text{max-width:none;width:100%}
122
+ .a3rev_panel_container .a3rev-ui-textarea{max-width:none !important;width:100% !important}
123
+ .a3rev_panel_container .a3rev-ui-slider{width:50px !important}
124
+ .a3rev_panel_container .typography-preview-container,.a3rev_panel_container .settings-preview-container{width:90%}
125
+ .a3rev_panel_container .a3rev-ui-typography-preview-button:active,.a3rev_panel_container .a3rev-ui-settings-preview-button:active{padding-top:inherit !important}
126
+ .a3rev_panel_container .wp-picker-container input.wp-color-picker[type="text"]{width:75px !important;padding:3px 10px !important}
127
+ .wp-core-ui .button.wp-picker-default{padding:0 8px 1px}
128
+ .a3rev_panel_container input.a3rev-color-picker{margin-top:1px !important}
129
+ .a3rev_panel_container input.wp-picker-default{margin-top:1px !important;padding:2px 8px !important}
130
+ .a3rev_panel_container .chosen-container-multi{width:100% !important}
131
+ .a3rev_blue_message_box_container{width:100% !important}
132
+ .a3-plugin-ui-help-icon{margin-right:0}
133
+ }
134
+ @media screen and (max-width:480px){.a3rev_panel_container .a3rev-ui-slide-container-start{margin-top:5px}
135
+ .a3_subsubsub_section .subsubsub{text-align:left}
136
+ .a3rev_panel_container .chosen-container-single{max-width:300px !important}
137
+ }
admin/assets/css/admin-ui-style.rtl.css ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .clear {
2
+ clear: both;
3
+ }
4
+ .nobr {
5
+ white-space: nowrap;
6
+ }
7
+ body.rtl .a3rev_panel_container {
8
+ font-family: "Open Sans", sans-serif;
9
+ }
10
+ .a3rev_panel_container code {
11
+ float: right;
12
+ }
13
+ .a3rev_panel_container .chosen-container {
14
+ margin-right: 0px;
15
+ margin-left: 2px;
16
+ }
17
+ .a3rev_panel_container .chosen-container .chosen-drop {
18
+ left: auto;
19
+ right: -9999px;
20
+ }
21
+ .a3rev_panel_container .chosen-container.chosen-with-drop .chosen-drop {
22
+ left: auto;
23
+ right: 0;
24
+ }
25
+ .a3rev_panel_container .chosen-container.chosen-container-multi .chosen-choices li.search-choice {
26
+ margin-left: 0px;
27
+ margin-right: 5px;
28
+ float: left;
29
+ padding-left: 20px;
30
+ padding-right: 5px;
31
+ }
32
+ .a3rev_panel_container .chosen-container.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
33
+ left: 3px;
34
+ right: auto;
35
+ }
36
+ .a3rev_panel_container span.description {
37
+ margin-right: 5px;
38
+ }
39
+ .a3rev_panel_container .typography-preview-container .preview_remove,
40
+ .a3rev_panel_container .settings-preview-container .preview_remove {
41
+ left: -10px;
42
+ right: auto;
43
+ }
44
+ .a3rev_panel_container .a3rev-ui-settings-preview-button {
45
+ float: right;
46
+ }
47
+ .a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer {
48
+ margin-left: 30px;
49
+ margin-right: 0px;
50
+ }
51
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border-corner-value-container {
52
+ float: right;
53
+ }
54
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-top_left,
55
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-top_right,
56
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-bottom_left,
57
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-bottom_right {
58
+ float: right;
59
+ }
60
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-span {
61
+ float: right;
62
+ }
63
+ .a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-px {
64
+ float: right;
65
+ margin-left: 10px;
66
+ margin-right: 0px;
67
+ }
68
+ .a3rev_panel_container .a3rev-ui-slide-container {
69
+ float: right;
70
+ }
71
+ .a3rev_panel_container .a3rev-ui-slide-container-start {
72
+ padding-left: 20px;
73
+ margin-right: 12px;
74
+ float: right;
75
+ }
76
+ .a3rev_panel_container .a3rev-ui-slide-result-container {
77
+ float: right;
78
+ }
79
+ .a3rev_panel_container .a3rev-ui-slider {
80
+ float: right;
81
+ }
82
+ .a3rev_panel_container .a3rev-ui-slide {
83
+ float: right;
84
+ }
85
+ .a3rev_panel_container .forminp-onoff_radio ul,
86
+ .a3rev_panel_container .forminp-onoff_radio li {
87
+ float: right;
88
+ }
89
+ .a3rev_panel_container .iPhoneCheckContainer,
90
+ .a3rev_panel_container .iOSCheckContainer {
91
+ margin-left: 10px;
92
+ margin-right: 0px;
93
+ float: right;
94
+ }
95
+ .a3rev_panel_container label.iPhoneCheckLabelOff,
96
+ .a3rev_panel_container label.iOSCheckLabelOff {
97
+ text-align: left;
98
+ left: 0;
99
+ right: auto;
100
+ }
101
+ .a3rev_panel_container label.iPhoneCheckLabelOff span,
102
+ .a3rev_panel_container label.iOSCheckLabelOff span {
103
+ padding-right: 0px;
104
+ padding-left: 10px;
105
+ }
106
+ .a3rev_panel_container label.iPhoneCheckLabelOn,
107
+ .a3rev_panel_container label.iOSCheckLabelOn {
108
+ text-align: right;
109
+ left: auto;
110
+ right: 0;
111
+ }
112
+ .a3rev_panel_container label.iPhoneCheckLabelOn span,
113
+ .a3rev_panel_container label.iOSCheckLabelOn span {
114
+ padding-left: 0px;
115
+ padding-right: 10px;
116
+ }
117
+ .a3rev_panel_container .iPhoneCheckHandle,
118
+ .a3rev_panel_container .iOSCheckHandle {
119
+ left: auto;
120
+ right: -1px;
121
+ }
122
+ .a3rev_panel_container .a3rev-ui-array_textfields-container label {
123
+ float: right;
124
+ margin-left: 5px;
125
+ }
126
+ .a3rev_panel_container table.form-table th img.help_tip {
127
+ float: left;
128
+ margin: 0 0 0 -12px;
129
+ }
130
+ .a3rev_panel_container table.form-table img.help_tip {
131
+ margin: -4px 5px 0 0;
132
+ }
133
+ #a3_plugin_panel_fields {
134
+ float: right;
135
+ }
136
+ #a3_plugin_panel_fields .pro_feature_fields {
137
+ margin-left: -12px;
138
+ margin-right: 0px;
139
+ -webkit-border-top-left-radius: 0px;
140
+ border-top-left-radius: 0px;
141
+ -webkit-border-top-right-radius: 10px;
142
+ border-top-right-radius: 10px;
143
+ -webkit-border-bottom-left-radius: 0px;
144
+ border-bottom-left-radius: 0px;
145
+ -webkit-border-bottom-right-radius: 10px;
146
+ border-bottom-right-radius: 10px;
147
+ border-left: 2px solid #FFFFFF;
148
+ border-right: 2px solid #E6DB55;
149
+ }
150
+ #a3_plugin_panel_fields .pro_feature_fields p {
151
+ margin-left: 0px;
152
+ margin-right: 5px;
153
+ }
154
+ #a3_plugin_panel_upgrade_area {
155
+ margin-left: 0px;
156
+ margin-right: 65%;
157
+ padding-left: 0px;
158
+ padding-right: 10px;
159
+ }
160
+ #a3_plugin_panel_upgrade_area #a3_plugin_panel_extensions a:first-child {
161
+ float: left !important;
162
+ clear: left !important;
163
+ margin-left: 0px !important;
164
+ margin-right: 10px;
165
+ }
166
+ .a3-plugin-ui-help-icon {
167
+ float: left;
168
+ margin-left: -15px;
169
+ margin-right: 0px;
170
+ }
admin/assets/css/admin-ui-style.rtl.less ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "mixins.less";
2
+
3
+ /*-------------------------------------------------------------------------------------------*/
4
+ /* A3rev Panel RTL UI */
5
+ /*-------------------------------------------------------------------------------------------*/
6
+
7
+ body.rtl {
8
+ .a3rev_panel_container {
9
+ font-family: "Open Sans",sans-serif;
10
+ }
11
+ }
12
+ .a3rev_panel_container {
13
+
14
+ code {
15
+ float: right;
16
+ }
17
+
18
+ /* Chosen RTL */
19
+ .chosen-container {
20
+ margin-right: 0px;
21
+ margin-left: 2px;
22
+
23
+ .chosen-drop {
24
+ left: auto;
25
+ right: -9999px;
26
+ }
27
+ &.chosen-with-drop {
28
+ .chosen-drop {
29
+ left: auto;
30
+ right: 0;
31
+ }
32
+ }
33
+ &.chosen-container-multi {
34
+ .chosen-choices {
35
+ li.search-choice {
36
+ margin-left: 0px;
37
+ margin-right: 5px;
38
+ float: left;
39
+ padding-left: 20px;
40
+ padding-right: 5px;
41
+
42
+ .search-choice-close {
43
+ left: 3px;
44
+ right: auto;
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+
51
+ /* Description */
52
+ span.description {
53
+ margin-right: 5px;
54
+ }
55
+
56
+ /* Preview Remove Button */
57
+ .typography-preview-container, .settings-preview-container {
58
+ .preview_remove {
59
+ left: -10px;
60
+ right: auto;
61
+ }
62
+
63
+ }
64
+ .a3rev-ui-settings-preview-button {
65
+ float: right;
66
+ }
67
+
68
+ /* Border Rounded Corner Control */
69
+ .forminp-border_corner {
70
+ .iPhoneCheckContainer {
71
+ margin-left: 30px;
72
+ margin-right: 0px;
73
+ }
74
+
75
+ .a3rev-ui-border-corner-value-container {
76
+ float: right;
77
+ }
78
+
79
+ .a3rev-ui-border_corner-top_left, .a3rev-ui-border_corner-top_right, .a3rev-ui-border_corner-bottom_left, .a3rev-ui-border_corner-bottom_right {
80
+ float: right;
81
+ }
82
+
83
+ .a3rev-ui-border_corner-span {
84
+ float: right;
85
+ }
86
+
87
+ .a3rev-ui-border_corner-px {
88
+ float: right;
89
+ margin-left: 10px;
90
+ margin-right: 0px;
91
+ }
92
+ }
93
+
94
+ /* SLIDER Control */
95
+ .a3rev-ui-slide-container {
96
+ float: right;
97
+ }
98
+ .a3rev-ui-slide-container-start {
99
+ padding-left: 20px;
100
+ margin-right: 12px;
101
+ float: right;
102
+ }
103
+ .a3rev-ui-slide-result-container {
104
+ float: right;
105
+ }
106
+ .a3rev-ui-slider {
107
+ float: right;
108
+ }
109
+ .a3rev-ui-slide {
110
+ float: right;
111
+ }
112
+
113
+ /* OnOff Radio Control */
114
+ .forminp-onoff_radio {
115
+ ul, li {
116
+ float: right;
117
+ }
118
+ }
119
+
120
+ /* OnOff Checkbox & Radio Control */
121
+ .iPhoneCheckContainer, .iOSCheckContainer {
122
+ margin-left: 10px;
123
+ margin-right: 0px;
124
+ float: right;
125
+ }
126
+ label.iPhoneCheckLabelOff, label.iOSCheckLabelOff {
127
+ text-align: left;
128
+ left: 0;
129
+ right: auto;
130
+
131
+ span {
132
+ padding-right: 0px;
133
+ padding-left: 10px;
134
+ }
135
+ }
136
+ label.iPhoneCheckLabelOn, label.iOSCheckLabelOn {
137
+ text-align: right;
138
+ left: auto;
139
+ right: 0;
140
+
141
+ span {
142
+ padding-left: 0px;
143
+ padding-right: 10px;
144
+ }
145
+ }
146
+
147
+ .iPhoneCheckHandle, .iOSCheckHandle {
148
+ left: auto;
149
+ right: -1px;
150
+ }
151
+
152
+ /* TextFields */
153
+ .a3rev-ui-array_textfields-container {
154
+ label {
155
+ float: right;
156
+ margin-left: 5px;
157
+ }
158
+ }
159
+
160
+ /* Help Tip */
161
+ table {
162
+ &.form-table {
163
+ th {
164
+ img.help_tip {
165
+ float: left;
166
+ margin: 0 0 0 -12px;
167
+ }
168
+ }
169
+
170
+ img.help_tip {
171
+ margin: -4px 5px 0 0;
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ /* Style for yellow box about Pro or Ultimate version */
178
+ #a3_plugin_panel_fields {
179
+ float: right;
180
+
181
+ .pro_feature_fields {
182
+ margin-left: -12px;
183
+ margin-right: 0px;
184
+ .border_radius_corner(@topleft:0px, @topright:10px, @bottomleft:0px, @bottomright:10px);
185
+ border-left: 2px solid #FFFFFF;
186
+ border-right: 2px solid #E6DB55;
187
+
188
+ p {
189
+ margin-left:0px;
190
+ margin-right:5px;
191
+ }
192
+ }
193
+ }
194
+ #a3_plugin_panel_upgrade_area {
195
+ margin-left: 0px;
196
+ margin-right: 65%;
197
+ padding-left: 0px;
198
+ padding-right:10px;
199
+
200
+ #a3_plugin_panel_extensions {
201
+ a:first-child {
202
+ float: left !important;
203
+ clear: left !important;
204
+ margin-left: 0px !important;
205
+ margin-right: 10px;
206
+ }
207
+ }
208
+ }
209
+
210
+ /* Custom for each element web icons font */
211
+ .a3-plugin-ui-help-icon {
212
+ float: left;
213
+ margin-left: -15px;
214
+ margin-right: 0px;
215
+ }
admin/assets/css/admin-ui-style.rtl.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .clear{clear:both}.nobr{white-space:nowrap}body.rtl .a3rev_panel_container{font-family:"Open Sans", sans-serif}.a3rev_panel_container code{float:right}.a3rev_panel_container .chosen-container{margin-right:0px;margin-left:2px}.a3rev_panel_container .chosen-container .chosen-drop{left:auto;right:-9999px}.a3rev_panel_container .chosen-container.chosen-with-drop .chosen-drop{left:auto;right:0}.a3rev_panel_container .chosen-container.chosen-container-multi .chosen-choices li.search-choice{margin-left:0px;margin-right:5px;float:left;padding-left:20px;padding-right:5px}.a3rev_panel_container .chosen-container.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{left:3px;right:auto}.a3rev_panel_container span.description{margin-right:5px}.a3rev_panel_container .typography-preview-container .preview_remove,.a3rev_panel_container .settings-preview-container .preview_remove{left:-10px;right:auto}.a3rev_panel_container .a3rev-ui-settings-preview-button{float:right}.a3rev_panel_container .forminp-border_corner .iPhoneCheckContainer{margin-left:30px;margin-right:0px}.a3rev_panel_container .forminp-border_corner .a3rev-ui-border-corner-value-container{float:right}.a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-top_left,.a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-top_right,.a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-bottom_left,.a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-bottom_right{float:right}.a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-span{float:right}.a3rev_panel_container .forminp-border_corner .a3rev-ui-border_corner-px{float:right;margin-left:10px;margin-right:0px}.a3rev_panel_container .a3rev-ui-slide-container{float:right}.a3rev_panel_container .a3rev-ui-slide-container-start{padding-left:20px;margin-right:12px;float:right}.a3rev_panel_container .a3rev-ui-slide-result-container{float:right}.a3rev_panel_container .a3rev-ui-slider{float:right}.a3rev_panel_container .a3rev-ui-slide{float:right}.a3rev_panel_container .forminp-onoff_radio ul,.a3rev_panel_container .forminp-onoff_radio li{float:right}.a3rev_panel_container .iPhoneCheckContainer,.a3rev_panel_container .iOSCheckContainer{margin-left:10px;margin-right:0px;float:right}.a3rev_panel_container label.iPhoneCheckLabelOff,.a3rev_panel_container label.iOSCheckLabelOff{text-align:left;left:0;right:auto}.a3rev_panel_container label.iPhoneCheckLabelOff span,.a3rev_panel_container label.iOSCheckLabelOff span{padding-right:0px;padding-left:10px}.a3rev_panel_container label.iPhoneCheckLabelOn,.a3rev_panel_container label.iOSCheckLabelOn{text-align:right;left:auto;right:0}.a3rev_panel_container label.iPhoneCheckLabelOn span,.a3rev_panel_container label.iOSCheckLabelOn span{padding-left:0px;padding-right:10px}.a3rev_panel_container .iPhoneCheckHandle,.a3rev_panel_container .iOSCheckHandle{left:auto;right:-1px}.a3rev_panel_container .a3rev-ui-array_textfields-container label{float:right;margin-left:5px}.a3rev_panel_container table.form-table th img.help_tip{float:left;margin:0 0 0 -12px}.a3rev_panel_container table.form-table img.help_tip{margin:-4px 5px 0 0}#a3_plugin_panel_fields{float:right}#a3_plugin_panel_fields .pro_feature_fields{margin-left:-12px;margin-right:0px;-webkit-border-top-left-radius:0px;border-top-left-radius:0px;-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-webkit-border-bottom-left-radius:0px;border-bottom-left-radius:0px;-webkit-border-bottom-right-radius:10px;border-bottom-right-radius:10px;border-left:2px solid #FFFFFF;border-right:2px solid #E6DB55}#a3_plugin_panel_fields .pro_feature_fields p{margin-left:0px;margin-right:5px}#a3_plugin_panel_upgrade_area{margin-left:0px;margin-right:65%;padding-left:0px;padding-right:10px}#a3_plugin_panel_upgrade_area #a3_plugin_panel_extensions a:first-child{float:left !important;clear:left !important;margin-left:0px !important;margin-right:10px}.a3-plugin-ui-help-icon{float:left;margin-left:-15px;margin-right:0px}
admin/assets/css/mixins.less ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @green: green;
2
+ @red: red;
3
+ @orange: orange;
4
+ @blue: blue;
5
+ @yellow: yellow;
6
+ @white: white;
7
+ @black: black;
8
+
9
+ .clearfix() {
10
+ *zoom:1;
11
+ &:before,
12
+ &:after {
13
+ content: " ";
14
+ display: table;
15
+ }
16
+ &:after {
17
+ clear: both;
18
+ }
19
+ }
20
+ .border_radius(@radius:4px) {
21
+ -webkit-border-radius:@radius;
22
+ border-radius:@radius;
23
+ }
24
+ .border_radius_corner(@topleft:4px, @topright:4px, @bottomleft:4px, @bottomright:4px) {
25
+ -webkit-border-top-left-radius: @topleft;
26
+ border-top-left-radius: @topleft;
27
+ -webkit-border-top-right-radius: @topright;
28
+ border-top-right-radius: @topright;
29
+ -webkit-border-bottom-left-radius: @bottomleft;
30
+ border-bottom-left-radius: @bottomleft;
31
+ -webkit-border-bottom-right-radius: @bottomright;
32
+ border-bottom-right-radius: @bottomright;
33
+ }
34
+
35
+ .border_radius_top_left(@radius:4px) {
36
+ -webkit-border-top-left-radius: @radius;
37
+ border-top-left-radius: @radius;
38
+ }
39
+ .border_radius_top_right(@radius:4px) {
40
+ -webkit-border-top-right-radius: @radius;
41
+ border-top-right-radius: @radius;
42
+ }
43
+ .border_radius_bottom_left(@radius:4px) {
44
+ -webkit-border-bottom-left-radius: @radius;
45
+ border-bottom-left-radius: @radius;
46
+ }
47
+ .border_radius_bottom_right(@radius:4px) {
48
+ -webkit-border-bottom-right-radius: @radius;
49
+ border-bottom-right-radius: @radius;
50
+ }
51
+
52
+ .border_radius_right(@radius:4px) {
53
+ -webkit-border-top-right-radius: @radius;
54
+ -webkit-border-bottom-right-radius: @radius;
55
+ border-top-right-radius: @radius;
56
+ border-bottom-right-radius: @radius;
57
+ }
58
+ .border_radius_left(@radius:4px) {
59
+ -webkit-border-top-left-radius: @radius;
60
+ -webkit-border-bottom-left-radius: @radius;
61
+ border-top-left-radius: @radius;
62
+ border-bottom-left-radius: @radius;
63
+ }
64
+ .border_radius_bottom(@radius:4px) {
65
+ -webkit-border-bottom-left-radius: @radius;
66
+ -webkit-border-bottom-right-radius: @radius;
67
+ border-bottom-left-radius: @radius;
68
+ border-bottom-right-radius: @radius;
69
+ }
70
+ .border_radius_top(@radius:4px) {
71
+ -webkit-border-top-left-radius: @radius;
72
+ -webkit-border-top-right-radius: @radius;
73
+ border-top-left-radius: @radius;
74
+ border-top-right-radius: @radius;
75
+ }
76
+ .opacity(@opacity:0.75) {
77
+ filter:~"alpha(opacity=@opacity * 100)";
78
+ -moz-opacity:@opacity;
79
+ -khtml-opacity: @opacity;
80
+ opacity: @opacity;
81
+ }
82
+ .box_shadow_none() {
83
+ box-shadow: none;
84
+ -moz-box-shadow: none;
85
+ -webkit-box-shadow: none;
86
+ }
87
+ .box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
88
+ box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
89
+ -webkit-box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
90
+ }
91
+ .inset_box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
92
+ box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
93
+ -webkit-box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
94
+ }
95
+ .text_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_color:#fff) {
96
+ text-shadow:@shadow_x @shadow_y @shadow_rad @shadow_color;
97
+ }
98
+ .vertical_gradient(@from: #000, @to: #FFF) {
99
+ background: @from;
100
+ background: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to));
101
+ background: -webkit-linear-gradient(@from, @to);
102
+ background: -moz-linear-gradient(center top, @from 0%, @to 100%);
103
+ background: -moz-gradient(center top, @from 0%, @to 100%);
104
+ }
105
+ .transition(@selector:all, @animation:ease-in-out, @duration:.2s) {
106
+ -webkit-transition:@selector @animation @duration;
107
+ -moz-transition:@selector @animation @duration;
108
+ -o-transition:@selector @animation @duration;
109
+ transition:@selector @animation @duration;
110
+ }
111
+
112
+ .scale(@ratio:1.5){
113
+ -webkit-transform:scale(@ratio);
114
+ -moz-transform:scale(@ratio);
115
+ -ms-transform:scale(@ratio);
116
+ -o-transform:scale(@ratio);
117
+ transform:scale(@ratio);
118
+ }
119
+
120
+ .borderbox () {
121
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
122
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
123
+ box-sizing: border-box; /* Opera/IE 8+ */
124
+ }
125
+
126
+ .clear { clear: both; }
127
+ .nobr { white-space: nowrap; }
128
+
129
+ .darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) >= 65%) { .text_shadow( 0, -1px, 0, rgba(0,0,0,@opacity) ); }
130
+ .darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) < 65%) { .text_shadow( 0, 1px, 0, rgba(255,255,255,@opacity) ); }
131
+
132
+ /**
133
+ * Objects
134
+ */
135
+ .menu() {
136
+ .clearfix;
137
+ li {
138
+ display: inline-block;
139
+ }
140
+ }
141
+ .mediaright() {
142
+ .clearfix;
143
+ img {
144
+ float:right;
145
+ height:auto;
146
+ }
147
+ }
148
+ .medialeft() {
149
+ .clearfix;
150
+ img {
151
+ float:right;
152
+ height:auto;
153
+ }
154
+ }
155
+ .ir() {
156
+ display: block;
157
+ text-indent: -9999px;
158
+ position: relative;
159
+ height:1em;
160
+ width:1em;
161
+ }
162
+
163
+ .margin( @top:0, @right:0px, @bottom:0px , @left:0 ){
164
+ margin-top: @top;
165
+ margin-right: @right;
166
+ margin-bottom: @bottom;
167
+ margin-left: @left;
168
+ }
169
+
170
+ .margin_left( @left:0 ){
171
+ margin-left: @left;
172
+ }
173
+ .margin_right( @right:0 ){
174
+ margin-right: @right;
175
+ }
176
+ .margin_top( @top:0 ){
177
+ margin-top: @top;
178
+ }
179
+ .margin_bottom( @bottom:0 ){
180
+ margin-bottom: @bottom;
181
+ }
182
+
183
+ .padding( @top:0, @right:0px, @bottom:0px , @left:0 ){
184
+ padding-top: @top;
185
+ padding-right: @right;
186
+ padding-bottom: @bottom;
187
+ padding-left: @left;
188
+ }
189
+
190
+ .padding_left( @left:0 ){
191
+ padding-left: @left;
192
+ }
193
+ .padding_right( @right:0 ){
194
+ padding-right: @right;
195
+ }
196
+ .padding_top( @top:0 ){
197
+ padding-top: @top;
198
+ }
199
+ .padding_bottom( @bottom:0 ){
200
+ padding-bottom: @bottom;
201
+ }
202
+
203
+ .background( @url, @repeat:no-repeat, @hoz:0, @ver:0, @color ){
204
+ background: url(@url) @repeat @hoz @ver @color;
205
+ }
admin/assets/fonts/a3-metabox-plugin-framework.eot ADDED
Binary file
admin/assets/fonts/a3-metabox-plugin-framework.svg ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by Fontastic.me</metadata>
5
+ <defs>
6
+ <font id="a3-metabox-plugin-framework" horiz-adv-x="512">
7
+ <font-face font-family="a3-metabox-plugin-framework" units-per-em="512" ascent="480" descent="-32"/>
8
+ <missing-glyph horiz-adv-x="512" />
9
+
10
+ <glyph unicode="&#57344;" d="M26 168l-26-158c0-2 1-5 3-7 0 0 0 0 0 0 2-2 5-3 7-3l158 27c3 0 6 3 7 6 1 3 0 7-3 9l-30 31 82 82c4 4 4 9 0 13l-57 57c-3 3-9 3-12 0l-83-83-31 31c-2 2-5 3-9 2-3-1-5-4-6-7z m460 176l26 158c0 2-1 5-3 7 0 0 0 0 0 0-2 2-5 3-7 3l-158-27c-3 0-6-3-7-6-1-3 0-7 3-9l30-31-82-82c-4-4-4-9 0-13l57-57c3-3 9-3 12 0l83 83 31-31c2-2 5-3 9-2 3 1 5 4 6 7z"/>
11
+ <glyph unicode="&#57345;" d="M252 210c0-2-1-4-3-6l-94-95 41-41c3-4 5-8 5-13 0-5-2-9-5-13-4-4-8-5-13-5l-128 0c-5 0-9 1-13 5-4 4-5 8-5 13l0 128c0 5 1 9 5 13 4 3 8 5 13 5 5 0 9-2 13-5l41-41 95 94c2 2 4 3 6 3 3 0 5-1 7-3l32-32c2-2 3-4 3-7z m223 247l0-128c0-5-1-9-5-13-4-3-8-5-13-5-5 0-9 2-13 5l-41 41-95-94c-2-2-4-3-6-3-3 0-5 1-7 3l-32 32c-2 2-3 4-3 7 0 2 1 4 3 6l94 95-41 41c-3 4-5 8-5 13 0 5 2 9 5 13 4 4 8 5 13 5l128 0c5 0 9-1 13-5 4-4 5-8 5-13z"/>
12
+ <glyph unicode="&#57346;" d="M201 59l26 158c0 3-1 6-3 8 0 0 0 0 0 0-2 2-5 3-8 2l-157-26c-3-1-6-3-7-7-1-3 0-6 2-9l31-30-82-83c-4-3-4-9 0-13l56-56c4-4 10-4 13 0l83 82 30-31c3-2 6-3 9-2 4 1 6 4 7 7z m110 394l-26-158c0-3 1-6 3-8 0 0 0 0 0 0 2-2 5-3 8-2l157 26c3 1 6 3 7 7 1 3 0 6-2 9l-31 30 82 83c4 3 4 9 0 13l-56 56c-4 4-10 4-13 0l-83-82-30 31c-3 2-6 3-9 2-4-1-6-4-7-7z"/>
13
+ <glyph unicode="&#57347;" d="M256 238l0-128c0-5-2-10-5-13-4-4-8-6-13-6-5 0-10 2-13 6l-41 41-95-95c-2-2-4-3-7-3-2 0-4 1-6 3l-33 33c-2 2-3 4-3 6 0 3 1 5 3 7l95 95-41 41c-4 3-6 8-6 13 0 5 2 9 6 13 3 3 8 5 13 5l128 0c5 0 9-2 13-5 3-4 5-8 5-13z m216 192c0-3-1-5-3-7l-95-95 41-41c4-3 6-8 6-13 0-5-2-9-6-13-3-3-8-5-13-5l-128 0c-5 0-9 2-13 5-3 4-5 8-5 13l0 128c0 5 2 10 5 13 4 4 8 6 13 6 5 0 10-2 13-6l41-41 95 95c2 2 4 3 7 3 2 0 4-1 6-3l33-33c2-2 3-4 3-6z"/>
14
+ <glyph unicode="&#57348;" d="M184 54l24 145c1 3 0 5-2 7 0 0 0 0 0 0-2 2-5 3-7 3l-145-25c-3 0-5-2-6-5-1-3 0-7 2-9l28-28-76-76c-3-3-3-8 0-11l53-53c3-3 8-3 11 0l76 76 28-28c3-2 6-3 9-2 3 1 5 3 5 6z m144 404l-24-145c-1-3 0-5 2-7 0 0 0 0 0 0 2-2 5-3 7-3l145 25c3 0 5 2 6 5 1 3 0 7-2 9l-28 28 76 76c3 3 3 8 0 11l-53 53c-3 3-8 3-11 0l-76-76-28 28c-3 2-6 3-9 2-3-1-5-3-5-6z m130-274l-145 24c-3 1-5 0-7-2 0 0 0 0 0 0-2-2-3-5-3-7l25-145c0-3 2-5 5-6 3-1 7 0 9 2l28 28 76-76c3-3 8-3 11 0l53 53c3 3 3 8 0 11l-76 76 28 28c2 3 3 6 2 9-1 3-3 5-6 5z m-404 144l145-24c3-1 5 0 7 2 0 0 0 0 0 0 2 2 3 5 3 7l-25 145c0 3-2 5-5 6-3 1-6 0-9-2l-28-28-76 76c-3 3-8 3-11 0l-53-53c-3-3-3-8 0-11l76-76-28-28c-2-3-3-6-2-9 1-3 3-5 6-5z"/>
15
+ <glyph unicode="&#57349;" d="M24 154l-24-144c0-3 1-6 2-8 0 0 0 0 0 0 2-1 5-2 8-2l144 25c3 0 6 2 6 5 1 3 1 6-2 8l-28 29 76 75c3 4 3 9 0 12l-52 52c-3 4-9 4-12 0l-76-75-28 28c-2 2-5 3-8 2-3-1-5-4-6-7z m464 204l24 144c0 3-1 6-2 8 0 0 0 0 0 0-2 1-5 2-8 2l-144-25c-3 0-6-2-6-5-1-3-1-6 2-8l28-29-76-75c-3-4-3-9 0-12l52-52c3-4 9-4 12 0l76 75 28-28c2-2 5-3 8-2 3 1 5 4 6 7z m-130-334l144-24c3 0 6 1 8 2 0 0 0 0 0 0 1 2 2 5 2 8l-25 144c0 3-2 6-5 6-3 1-6 1-8-2l-29-28-75 76c-4 3-9 3-12 0l-52-52c-4-3-4-9 0-12l75-76-28-28c-2-2-3-5-2-8 1-3 4-5 7-6z m-204 464l-144 24c-3 0-6-1-8-2 0 0 0 0 0 0-1-2-2-5-2-8l25-144c0-3 2-6 5-6 3-1 6-1 8 2l29 28 75-76c4-3 9-3 12 0l52 52c4 3 4 9 0 12l-75 76 28 28c2 2 3 5 2 8-1 3-4 5-7 6z"/>
16
+ </font></defs></svg>
admin/assets/fonts/a3-metabox-plugin-framework.ttf ADDED
Binary file
admin/assets/fonts/a3-metabox-plugin-framework.woff ADDED
Binary file
admin/assets/fonts/a3-plugin-framework.eot ADDED
Binary file
admin/assets/fonts/a3-plugin-framework.svg ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by Fontastic.me</metadata>
5
+ <defs>
6
+ <font id="a3-plugin-framework" horiz-adv-x="512">
7
+ <font-face font-family="a3-plugin-framework" units-per-em="512" ascent="480" descent="-32"/>
8
+ <missing-glyph horiz-adv-x="512" />
9
+
10
+ <glyph unicode="&#100;" d="m484 395l-89 89l-139-139l-139 139l-89-89l139-139l-139-139l89-89l139 139l139-139l89 89l-139 139z"/>
11
+ <glyph unicode="&#101;" d="m150 320c0 13 5 26 13 39c8 13 20 24 36 33c16 9 34 13 55 13c20 0 37-4 52-11c15-7 27-17 35-30c8-12 12-26 12-40c0-12-2-22-7-30c-4-9-10-16-16-23c-7-6-18-17-35-31c-4-5-8-8-11-12c-3-3-5-6-6-8c-1-3-3-6-3-8c-1-3-2-7-4-14c-2-14-10-21-24-21c-7 0-13 2-18 7c-4 4-7 11-7 20c0 12 2 21 6 30c3 8 8 15 14 22c5 6 13 13 23 22c9 8 15 13 19 17c4 4 7 8 10 13c2 5 4 10 4 15c0 11-4 20-13 28c-8 7-18 11-31 11c-15 0-26-4-33-11c-7-8-13-19-17-33c-5-16-14-23-27-23c-7 0-14 2-19 8c-5 5-8 11-8 17z m99-222c-8 0-15 2-21 8c-6 5-9 12-9 22c0 9 3 16 9 22c6 5 13 8 21 8c9 0 16-3 22-8c6-6 9-13 9-22c0-9-3-17-9-22c-7-6-14-8-22-8z m3 362c114 0 207-93 207-207c0-114-93-207-207-207c-114 0-207 93-207 207c0 114 93 207 207 207m0 30c-131 0-238-106-238-237c0-132 107-238 238-238c131 0 238 106 238 238c0 131-107 237-238 237z"/>
12
+ <glyph unicode="&#102;" d="m72 11l31 0l0 61l61 0l0 62l61 0l0 30l62 0l0 44c18-9 39-13 61-13c84 0 153 68 153 153c0 84-69 153-153 153c-85 0-153-69-153-153c0-22 5-43 13-61l-44 0l0-62l-153-122l0-92z m306 429c34 0 62-28 62-62c0-33-28-61-62-61c-33 0-61 28-61 61c0 34 28 62 61 62z"/>
13
+ <glyph unicode="&#107;" d="m48 252c0 7-6 12-13 12c-6 0-12-5-12-12c0-6 6-12 12-12c7 0 13 6 13 12z m19-90c0 8-7 15-16 15c-9 0-16-7-16-15c0-9 7-16 16-16c9 0 16 7 16 16z m71-86c0 10-9 19-20 19c-11 0-19-9-19-19c0-11 8-20 19-20c11 0 20 9 20 20z m105-43c0 13-10 23-23 23c-12 0-23-10-23-23c0-12 11-22 23-22c13 0 23 10 23 22z m117 16c0 15-12 26-27 26c-15 0-27-11-27-26c0-14 12-26 27-26c15 0 27 12 27 26z m89 68c0 16-14 29-31 29c-16 0-30-13-30-29c0-17 14-30 30-30c17 0 31 13 31 30z m45 102c0 18-15 33-34 33c-19 0-34-15-34-33c0-18 15-33 34-33c19 0 34 15 34 33z m-13 112c0 21-17 37-37 37c-21 0-38-16-38-37c0-20 17-36 38-36c20 0 37 16 37 36z m-64 86c0-23-19-41-41-41c-23 0-41 18-41 41c0 22 18 40 41 40c22 0 41-18 41-40z m-99 41c0 24-20 43-45 43c-25 0-45-19-45-43c0-25 20-44 45-44c25 0 45 19 45 44z m-112-21c0 26-22 48-48 48c-27 0-49-22-49-48c0-26 22-47 49-47c26 0 48 21 48 47z m-84-85c0 28-23 50-52 50c-29 0-52-22-52-50c0-28 23-51 52-51c29 0 52 23 52 51z"/>
14
+ <glyph unicode="&#103;" d="m27 41l14-14c14-14 37-14 51 0l88 88c32-19 69-31 109-31c114 0 206 92 206 206c0 113-92 205-206 205c-113 0-205-92-205-205c0-41 11-78 31-110l-88-88c-14-14-14-37 0-51z m262 397c83 0 149-66 149-148c0-82-66-149-149-149c-82 0-148 67-148 149c0 82 66 148 148 148z"/>
15
+ <glyph unicode="&#104;" d="m299 319l47 43c-25 20-64 40-98 40c-66 0-122-46-137-107l-95 24c26 104 120 180 231 180c63 0 128-32 170-71l45 40l35-202z m-133-169c25-20 64-40 98-40c66 0 122 46 137 107l95-24c-26-104-120-180-231-180c-63 0-127 32-170 71l-45-40l-35 202l198-53z"/>
16
+ <glyph unicode="&#97;" d="m451 354c7 11 12 24 12 41c0 61-47 102-117 102c-38 0-75-22-94-42c-11-12-11-31-1-43l32-38c2-3 5-5 8-7c0-1 0-37 0-37c-5-2-9-4-12-8l-6-6l0 22c0 60-47 100-121 100c-28 0-58-10-88-28c-14-8-20-25-14-40l11-32c-13-16-20-35-20-57c0-58 49-88 97-88c7 0 23 1 39 9c4-2 9-3 13-3l70 0c10 0 18 5 24 11c19-9 41-15 61-15c62 0 124 36 124 105c0 15-4 35-18 54z m-191-122l-70 0l-8 15c-12-17-32-21-44-21c-31 0-64 17-64 55c0 36 31 60 68 60c19 0 30-10 32-12l0 12c0 14-13 18-31 18c-19 0-36-8-49-15l-13 38c13 7 41 23 71 23c39 0 88-15 88-67l0-64l20 0z m85-4c-31 0-63 18-76 37l34 34c12-12 24-21 43-21c18 0 29 9 29 25c0 18-11 24-27 24l-24 0l0 39l23 0c16 0 28 8 28 22c0 18-15 26-29 26c-12 0-26-7-38-19l-31 38c11 13 40 31 69 31c54 0 84-28 84-69c0-23-16-35-25-42c11-7 31-24 31-53c0-49-47-72-91-72z m-190 73c-13 0-19-7-19-17c0-9 7-16 17-16c10 0 18 6 21 11l0 13c-1 1-6 9-19 9z m-114-126c0 2 1 3 3 3l17 0c11 0 20-3 25-8c5-5 7-14 7-26c0-8 0-14-2-18c-2-5-4-9-7-12c-3-3-6-5-10-7c-4-1-8-1-13-1l-6 0l0-47c0-1 0-1 0-2c0 0-1-1-2-1c0 0-2 0-4 0c-2 0-4 0-8 0z m37-30c0 6-1 11-3 15c-2 4-6 6-11 6l-9 0l0-47l8 0c5 0 8 2 11 6c2 4 4 11 4 20z m49-86c0-1 0-1 0-2c0 0-1-1-2-1c0 0-2 0-4 0c-2 0-4 0-8 0l0 122c0 1 0 3 1 4c0 0 1 1 2 1c1 1 2 1 4 1c2 0 4 0 7 0z m77 2c-3-2-7-4-12-5c-5-1-9-2-14-2c-5 0-10 1-13 2c-3 1-6 3-8 5c-2 3-3 6-4 9c-1 4-1 8-1 13l0 57c0 1 0 2 0 2c0 0 1 1 2 1c0 0 2 0 4 0c2 0 5 0 8 0l0-61c0-6 1-10 3-12c1-2 4-3 9-3c2 0 4 0 6 0c2 1 4 2 6 3l0 70c0 1 0 2 0 2c0 0 1 1 2 1c0 0 2 0 4 0c2 0 4 0 8 0l0-82z m53 84c1 0 2 0 4 0c1-1 3-1 4-1l21 0c1-1 1-2 1-3c1-1 1-3 1-4c0-4-2-6-5-6c-2 0-4 1-6 1c1-2 3-4 4-7c2-4 2-7 2-12c0-9-2-16-6-22c-5-5-12-8-22-8c-3 0-6 0-8 1c-1-2-2-3-3-4c-1-2-2-3-2-4c0-1 1-2 2-2c1-1 3-1 4-1c2-1 4-1 7-1c2-1 5-1 8-2c4 0 7-1 9-2c3-1 6-2 8-3c2-2 3-4 4-6c2-3 2-5 2-9c0-4-1-7-2-11c-1-3-3-6-6-9c-3-2-6-4-10-6c-5-2-10-2-15-2c-6 0-11 0-15 1c-3 1-6 3-8 5c-2 2-4 4-4 6c-1 2-1 4-1 7c0 4 1 8 4 11c2 4 5 7 9 10c-3 1-6 2-8 3c-2 2-3 4-3 6c0 2 1 5 3 8c2 3 5 5 8 8c-4 3-6 6-8 11c-2 4-2 9-2 15c0 6 0 11 2 15c1 4 3 7 6 10c2 2 5 4 9 5c3 1 7 2 12 2z m-5-86c-1 0-1 0-2 0c0 0-1 1-1 1c-3-2-5-5-7-7c-2-3-3-6-3-9c0-1 1-3 1-4c0-1 1-2 2-3c1 0 3-1 5-2c1 0 4 0 7 0c3 0 6 0 8 1c2 1 4 2 6 3c1 2 2 3 3 5c0 1 1 3 1 4c0 2-1 4-1 5c-1 1-2 2-3 3c-2 1-4 2-7 2c-2 1-5 1-9 1z m4 76c-4 0-7-2-9-5c-3-3-4-9-4-17c0-3 0-6 0-8c1-2 1-4 2-6c1-2 2-3 4-4c2-1 4-1 7-1c4 0 8 2 10 5c2 4 3 10 3 18c0 6-1 11-3 13c-3 3-6 5-10 5z m65-76c0-1 0-1-1-2c0 0 0-1-1-1c-1 0-3 0-5 0c-1 0-4 0-8 0l0 81c0 1 0 3 1 4c0 0 1 1 2 1c1 1 3 1 4 1c2 0 5 0 8 0z m-15 112c0 3 1 6 2 8c2 2 4 2 7 2c2 0 4 0 5-2c1-1 2-4 2-8c0-3-1-6-2-8c-2-2-4-3-7-3c-2 0-4 1-5 2c-1 2-2 5-2 9z m39-32c2 1 4 2 6 2c2 1 5 2 7 2c3 1 5 1 8 1c2 1 4 1 7 1c9 0 15-2 19-5c4-4 5-10 5-18l0-63c0-1 0-1 0-2c0 0-1-1-1-1c-1 0-3 0-5 0c-2 0-5 0-8 0l0 61c0 6-1 10-2 12c-1 2-4 4-9 4c-2 0-4-1-6-1c-2-1-5-1-7-3l0-70c0-1 0-1 0-2c0 0-1-1-2-1c0 0-2 0-4 0c-2 0-4 0-8 0l0 83z m102 6c4 0 8 0 11-1c3-1 5-2 6-3c2-1 3-2 4-3c0-1 1-2 1-3c0-2-1-5-4-7c-5 3-10 5-17 5c-4 0-7-1-10-3c-2-1-3-3-3-6c0-1 0-3 1-5c1-1 3-3 6-6l16-13c4-3 6-7 8-10c1-3 2-7 2-11c0-8-2-14-8-18c-5-5-12-7-21-7c-6 0-11 1-15 2c-4 2-6 4-6 7c0 1 0 2 1 4c0 1 1 3 1 4c5-3 11-4 18-4c4 0 8 1 10 3c3 2 4 4 4 8c0 2 0 4-1 7c-1 2-3 4-6 6l-17 15c-4 3-6 6-8 9c-1 3-2 6-2 9c0 6 2 11 7 15c5 4 12 6 22 6z"/>
17
+ <glyph unicode="&#98;" d="m70 260c-6 0-9-3-9-9c0-4 3-7 8-7c5 0 10 3 11 5l0 6c0 1-3 5-10 5z m263 28c-10 0-13-9-13-13l25 0c0 6-1 13-12 13z m146 41l-43 0c-1 0-3 0-4 0c-2 0-3 0-4 0l-51 0c-5 0-10-2-13-5c-10 5-20 7-32 7c-12 0-22-2-31-7c-4 6-10 9-17 9c-11 0-19-2-25-5c-2 1-4 1-6 1l-25 0c-8 22-30 35-59 35c-24 0-44-14-51-22c-5-6-7-14-5-21c-11 8-26 13-44 13c-15 0-31-5-47-15c-9-5-12-15-9-24l5-15c-6-8-10-19-10-30c0-28 23-49 54-49c3 0 11 1 20 4c2 0 4-1 6-1l36 0c5 0 10 2 13 6c10-5 21-8 31-8c13 0 27 3 38 10c3-5 9-8 15-8l47 0c9 0 16 6 19 14c13-11 28-17 44-17c23 0 41 7 57 20c1 2 3 3 4 6l5-11c4-7 11-12 19-12l26 0c8 0 15 5 18 12l24 51c9 2 16 11 16 20l0 22c0 11-9 20-21 20z m-355-104l-36 0l-4 7c-6-8-16-10-22-10c-16 0-33 8-33 28c0 19 16 30 35 30c9 0 15-4 16-5l0 5c0 8-7 10-16 10c-10 0-18-4-25-8l-7 20c7 4 21 11 37 11c20 0 45-7 45-34l0-33l10 0l0-21z m44-2c-16 0-32 9-39 19l17 17c6-6 13-10 22-10c10 0 15 4 15 12c0 9-5 13-14 13l-12 0l0 20l12 0c8 0 14 4 14 11c0 9-7 13-14 13c-7 0-14-4-20-10l-16 20c6 6 20 16 36 16c27 0 42-14 42-36c0-11-8-18-12-21c5-4 15-12 15-27c0-25-23-37-46-37z m116 60c-15 0-24-4-24-19l0-17l8 0l0-22l-47 0l0 22l7 0l0 40l-7 0l0 22l32 0l5-11c4 8 8 15 26 15z m47-61c-21 0-44 13-44 45c0 28 20 44 45 44c20 0 35-10 40-24c2-6 4-19 0-29l-52 0c1-4 3-13 17-13c5 0 14 0 23 8l14-17c-12-10-26-14-43-14z m148 65l-8 0l-29-62l-26 0l-31 62l-8 0l0 22l51 0l0-22l-9 0l8-17c2-7 4-14 4-18l1 0c0 4 2 12 5 18l8 17l-9 0l0 22l43 0z m-471-93c0 0 0 1 0 1c0 0 1 0 1 0l3 0l4-19c0-2 1-4 1-6c0-2 0-3 0-5l1 0c0 2 0 4 0 6c0 2 1 4 1 5l3 16c0 1 0 1 0 1c0 1 1 1 1 1l3 0l3-18c1-2 1-4 1-6c0-1 1-3 1-5l0 0c0 2 0 4 1 6c0 2 0 3 0 5l3 18c1 0 1 1 1 1c0 0 0 0 1 0l3 0l-7-34c0 0 0 0 0 0c-1 0-1 0-1 0c0 0-1 0-1 0c0 0 0 0-1 0c0 0-1 0-1 0c-1 1-1 1-1 2l-3 11c0 1 0 2 0 3c0 1 0 2 0 3c0 1-1 2-1 3c0 1 0 2 0 2c0 0 0-1 0-2c-1-1-1-2-1-3c0-1 0-2 0-3c0-1 0-2 0-3l-3-13c-1 0-1 0-2 0c0 0-1 0-2 0c0 0-1 0-1 0c0 1-1 2-1 3c0 1 0 2-1 3c0 2 0 3 0 5c-1 1-1 3-1 5c-1 2-1 3-1 5c-1 4-2 8-3 12z m33-21c0 5 0 8 2 10c1 2 3 3 6 3c1 0 2 0 3-1c1 0 2-1 3-2c0-1 1-2 1-4c0-1 0-3 0-6c0-4 0-8-2-10c-1-2-3-3-6-3c-1 0-2 1-3 1c-1 0-2 1-2 2c-1 1-2 2-2 4c0 1 0 3 0 6z m4 0c0-2 0-4 0-5c0-1 1-2 1-3c0 0 1-1 1-1c0 0 1 0 1 0c1 0 1 0 2 0c0 0 1 1 1 2c0 0 1 1 1 3c0 1 0 2 0 4c0 2 0 4 0 5c0 1-1 2-1 3c0 0 0 1-1 1c0 0-1 0-1 0c-1 0-1 0-2 0c0 0-1-1-1-1c0-1-1-2-1-3c0-1 0-3 0-5z m16 11c1 0 2 1 3 1c1 1 2 1 3 1c2 0 3 0 3-1c1 0 1 0 1-1c0 0 0-1 0-1c0-1 0-1-1-1c0 0-1 0-2 0c0 0-1 0-2 0c0 0-1-1-1-1l0-19c0 0 0-1 0-1c0 0 0 0-1 0c0 0 0 0-1 0c0 0-1 0-2 0z m23 11c0 1 0 1 0 1c0 0 1 1 1 1c0 0 1 0 1 0c1 0 1 0 2 0l0-35c-1 0-2-1-3-1c-1 0-2-1-4-1c-1 0-2 1-3 1c-1 0-2 1-3 1c0 1-1 2-1 4c-1 2-1 4-1 6c0 3 0 5 1 7c0 1 1 3 1 4c1 1 2 2 3 2c1 1 2 1 3 1c1 0 2 0 3-1z m0-13c0 0-1 0-1 0c0 0-1 0-1 0c-1 0-1 0-2 0c0 0-1-1-1-1c0-1-1-2-1-3c0-2 0-3 0-5c0-2 0-4 0-5c0-1 0-2 1-2c0-1 0-1 1-2c0 0 1 0 1 0c1 0 1 0 2 0c0 0 1 0 1 1z m10 12c0 1 0 1 0 1l5 0c3 0 6 0 7-2c2-2 2-4 2-7c0-2 0-4 0-6c-1-1-1-2-2-3c-1-1-2-1-3-2c-1 0-2 0-4 0l-1 0l0-13c0 0 0-1 0-1c0 0-1 0-1 0c0 0-1 0-1 0c-1 0-1 0-2 0z m10-8c0 2 0 3-1 4c0 1-1 2-3 2l-2 0l0-13l2 0c1 0 2 0 3 1c1 1 1 3 1 6z m9-2c0 0 2 1 3 1c1 1 2 1 3 1c1 0 2 0 3-1c0 0 1 0 1-1c0 0 0-1 0-1c-1-1-1-1-1-1c-1 0-1 0-2 0c-1 0-1 0-2 0c0 0-1-1-1-1l0-19c0 0 0-1-1-1c0 0 0 0 0 0c0 0-1 0-1 0c-1 0-2 0-2 0z m20 2c5 0 7-3 7-8c0-1 0-2 0-3c-1-1-1-2-1-3c-1 0-2-1-3-1c0 0-1 0-2 0c-1 0-2 0-3 0c-1 0-2 0-2 0c0-1 0-3 0-3c0-1 1-2 1-2c0-1 1-1 2-1c0-1 1-1 1-1c1 0 2 0 3 1c1 0 2 0 3 1c0-1 0-1 0-2c0 0 0 0 0-1c0 0 0-1 0-1c0 0-1-1-2-1c0 0-1 0-2 0c-1-1-1-1-2-1c-2 0-3 1-4 1c-1 0-1 1-2 2c-1 0-1 2-2 3c0 2 0 4 0 6c0 3 0 5 1 7c0 2 1 4 2 5c0 1 1 1 2 1c1 1 2 1 3 1z m0-4c0 0-1 0-1 0c-1 0-1-1-2-1c0-1 0-2-1-3c0-1 0-2 0-4c0 0 1 0 2 0c0 0 1 0 1 0c1 0 2 0 2 0c1 0 1 1 2 1c0 0 0 1 0 1c0 1 0 1 0 2c0 1 0 3-1 3c0 1-1 1-2 1z m19 4c1 0 2 0 3 0c0-1 1-1 2-1c0 0 0-1 1-1c0 0 0-1 0-1c0 0-1-1-1-2c-2 1-3 1-5 1c-1 0-2 0-3 0c0-1-1-1-1-2c0 0 0-1 1-1c0-1 0-1 1-2l5-4c1-1 2-2 2-3c0 0 1-2 1-3c0-2-1-4-3-5c-1-1-3-2-5-2c-2 0-4 1-5 1c-1 0-1 1-1 2c0 0 0 1 0 1c0 0 0 1 0 1c2-1 3-1 5-1c1 0 2 0 3 1c1 0 1 1 1 2c0 1 0 1 0 2c-1 1-1 1-2 2l-5 4c-1 1-1 2-2 3c0 0 0 1 0 2c0 2 0 3 1 4c2 1 4 2 7 2z m18 0c1 0 2 0 3 0c1-1 1-1 2-1c0 0 0-1 1-1c0 0 0-1 0-1c0 0-1-1-1-2c-2 1-3 1-5 1c-1 0-2 0-3 0c0-1-1-1-1-2c0 0 0-1 1-1c0-1 0-1 1-2l5-4c1-1 2-2 2-3c0 0 1-2 1-3c0-2-1-4-3-5c-1-1-3-2-5-2c-2 0-4 1-5 1c-1 0-1 1-1 2c0 0 0 1 0 1c0 0 0 1 0 1c2-1 3-1 5-1c1 0 2 0 3 1c1 0 1 1 1 2c0 1 0 1 0 2c-1 1-1 1-2 2l-5 4c-1 1-1 2-2 3c0 0 0 1 0 2c0 2 0 3 2 4c1 1 3 2 6 2z m19 8c0 1 0 1 1 1l5 0c3 0 5 0 7-2c1-2 2-4 2-7c0-2-1-4-1-6c0-1-1-2-2-3c-1-1-2-1-3-2c-1 0-2 0-3 0l-2 0l0-13c0 0 0-1 0-1c0 0 0 0-1 0c0 0 0 0-1 0c0 0-1 0-2 0l0 33z m10-8c0 2 0 3-1 4c0 1-1 2-3 2l-2 0l0-13l2 0c1 0 3 0 3 1c1 1 1 3 1 6z m13-24c0 0 0-1 0-1c0 0 0 0-1 0c0 0 0 0-1 0c0 0-1 0-2 0l0 34c0 1 0 1 0 1c0 0 0 1 1 1c0 0 0 0 1 0c0 0 1 0 2 0l0-35z m20 0c-1 0-2-1-3-1c-2 0-3-1-4-1c-2 0-3 1-4 1c-1 0-2 1-2 1c-1 1-1 2-1 3c-1 1-1 2-1 4l0 16c0 0 0 0 0 0c0 0 1 0 1 0c0 0 1 0 1 0c1 0 1 0 2 0l0-17c0-1 1-2 1-3c1-1 1-1 3-1c0 0 1 0 1 0c1 0 2 0 2 1l0 20c0 0 0 0 0 0c0 0 0 0 1 0c0 0 0 0 1 0c0 0 1 0 2 0l0-23z m13 24c1 0 1 0 2 0c0 0 1 0 1 0l6 0c0-1 0-1 0-1c0-1 0-1 0-1c0-1 0-2-1-2c-1 0-1 0-2 0c1 0 1-1 1-2c1-1 1-2 1-3c0-3-1-5-2-6c-1-2-3-3-6-3c-1 0-2 1-2 1c-1-1-1-1-1-1c0-1-1-1-1-1c0-1 1-1 1-1c0 0 1 0 1 0c1-1 1-1 2-1c1 0 1 0 2 0c1 0 2 0 3-1c1 0 1 0 2-1c1 0 1-1 1-1c1-1 1-2 1-3c0-1 0-2-1-3c0-1-1-2-1-2c-1-1-2-2-3-2c-2-1-3-1-5-1c-1 0-3 0-4 1c-1 0-1 0-2 1c-1 0-1 1-1 2c0 0-1 1-1 2c0 1 1 2 2 3c0 1 1 2 2 2c-1 1-1 1-2 2c-1 0-1 1-1 1c0 1 1 2 1 2c1 1 1 2 2 3c-1 0-2 1-2 3c0 1-1 2-1 4c0 2 1 3 1 4c0 1 1 2 2 3c0 1 1 1 2 1c1 1 2 1 3 1z m-1-24c0 0 0 0 0 0c0 0-1 0-1 0c0-1-1-1-2-2c0-1 0-2 0-2c0-1 0-1 0-2c0 0 0 0 0 0c1-1 1-1 2-1c0 0 1 0 2 0c1 0 1 0 2 0c1 1 1 1 2 1c0 1 0 1 0 1c1 1 1 1 1 2c0 0 0 1-1 1c0 0 0 1 0 1c-1 0-1 0-2 1c-1 0-2 0-3 0z m1 21c-1 0-2 0-2-1c-1-1-1-3-1-5c0-1 0-2 0-2c0-1 0-2 0-2c1-1 1-1 1-1c1 0 1 0 2 0c1 0 2 0 3 1c1 1 1 3 1 5c0 2 0 3-1 4c-1 1-1 1-3 1z m17-21c0 0 0-1 0-1c0 0 0 0 0 0c-1 0-1 0-2 0c0 0-1 0-2 0l0 23c0 0 0 0 0 1c0 0 1 0 1 0c0 0 1 0 1 0c1 0 1 0 2 0z m-4 31c0 1 0 2 1 2c0 1 1 1 1 1c1 0 2 0 2 0c0-1 0-2 0-3c0-1 0-1 0-2c-1-1-1-1-2-1c-1 0-1 0-1 1c-1 0-1 1-1 2z m10-9c0 0 1 1 1 1c1 0 2 0 2 0c1 1 2 1 2 1c1 0 2 0 2 0c3 0 5-1 6-2c1-1 1-2 1-5l0-17c0 0 0-1 0-1c0 0 0 0 0 0c0 0-1 0-1 0c-1 0-2 0-3 0l0 17c0 2 0 3 0 4c-1 0-1 0-3 0c0 0-1 0-2 0c0 0-1 0-1 0l0-20c0-1 0-1 0-1c0 0-1 0-1 0c0 0-1 0-1 0c-1 0-1 0-2 0z m27 2c1 0 2 0 3 0c1-1 1-1 2-1c0 0 1-1 1-1c0 0 0-1 0-1c0 0 0-1-1-2c-1 1-3 1-5 1c-1 0-2 0-2 0c-1-1-2-1-2-2c0 0 1-1 1-1c0-1 1-1 1-2l5-4c1-1 2-2 2-3c1 0 1-2 1-3c0-2-1-4-2-5c-2-1-4-2-6-2c-2 0-3 1-5 1c-1 0-1 1-1 2c0 0 0 1 0 1c0 0 0 1 0 1c2-1 3-1 5-1c2 0 3 0 3 1c1 0 1 1 1 2c0 1 0 1 0 2c0 1-1 1-2 2l-4 4c-2 1-2 2-3 3c0 0 0 1 0 2c0 2 0 3 2 4c1 1 3 2 6 2z m19-3c0 1 0 1 0 1c0 0 0 0 0 1c1 0 1 0 3 0c1 1 3 1 5 1c2 0 3 0 4-1c1-1 2-3 2-5l0-3c0-1 0-2 0-4c0-1 0-3 0-4c0-1 0-3-1-4c0-1 0-2 0-3c0 0-1-1-2-1c-2 0-3-1-4-1c-1 0-2 0-3 1c-1 0-2 0-2 1c-1 0-2 1-2 2c0 1-1 2-1 4c0 2 1 3 1 4c0 1 1 2 2 2c0 1 1 1 2 2c0 0 1 0 2 0c1 0 1 0 2 0c1 0 1 0 2-1l0 4c0 1-1 2-1 2c-1 1-1 1-2 1c-2 0-3 0-4 0c-1 0-2-1-3-1c0 0 0 1 0 1c0 1 0 1 0 1z m10-11c-1 1-1 1-2 1c0 0 0 0-1 0c0 0-1 0-1 0c-1 0-1-1-1-1c-1 0-1-1-1-1c0-1 0-2 0-3c0-1 0-2 0-2c0-1 0-1 1-1c0-1 0-1 1-1c0 0 0 0 1 0c0 0 1 0 1 0c1 0 1 0 1 1c1 0 1 1 1 1c0 1 0 1 0 2c0 1 0 2 0 2c0 1 0 2 0 2z m9 12c0 0 1 1 1 1c1 0 2 0 2 0c1 1 2 1 2 1c1 0 2 0 3 0c2 0 4-1 5-2c1-1 1-2 1-5l0-17c0 0 0-1 0-1c0 0 0 0 0 0c0 0-1 0-1 0c-1 0-2 0-3 0l0 17c0 2 0 3 0 4c-1 0-1 0-3 0c0 0-1 0-1 0c-1 0-2 0-2 0l0-20c0-1 0-1 0-1c0 0-1 0-1 0c0 0 0 0-1 0c-1 0-1 0-2 0z m30 11c0 1 0 1 0 1c0 0 0 1 1 1c0 0 0 0 1 0c0 0 1 0 2 0l0-35c-1 0-2-1-3-1c-1 0-3-1-4-1c-1 0-2 1-3 1c-1 0-2 1-3 1c0 1-1 2-1 4c-1 2-1 4-1 6c0 3 0 5 1 7c0 1 0 3 1 4c1 1 2 2 3 2c0 1 1 1 2 1c2 0 3 0 4-1l0 10z m0-13c0 0-1 0-1 0c0 0-1 0-1 0c-1 0-1 0-2 0c0 0-1-1-1-1c-1-1-1-2-1-3c0-2-1-3-1-5c0-2 0-4 1-5c0-1 0-2 0-2c1-1 1-1 2-2c0 0 1 0 1 0c1 0 1 0 2 0c0 0 1 0 1 1l0 17z m27 10l0-30c0 0 0-1 0-1c0 0 0 0 0 0c-1 0-1 0-1 0c-1 0-2 0-3 0l0 31l-6 0l0 2c0 1 0 1 0 1l17 0l0-3c0 0 0 0-1 0l-6 0z m10 3c0 1 0 1 0 1c0 0 0 1 0 1c1 0 1 0 2 0c0 0 1 0 2 0l0-13c0 1 1 1 2 1c1 1 2 1 3 1c1 0 2 0 3 0c0-1 1-1 1-2c1 0 1-1 1-2c0-1 0-2 0-3l0-17c0 0 0-1 0-1c0 0 0 0 0 0c-1 0-1 0-2 0c0 0-1 0-2 0l0 17c0 1 0 1 0 2c0 0 0 1 0 1c-1 0-1 1-1 1c-1 0-1 0-2 0c0 0-1 0-2 0c0 0-1-1-1-1l0-19c0 0 0-1-1-1c0 0 0 0 0 0c0 0-1 0-1 0c-1 0-1 0-2 0l0 34z m27-9c5 0 7-3 7-8c0-1 0-2-1-3c0-1 0-2 0-3c-1 0-2-1-3-1c-1 0-2 0-2 0c-1 0-2 0-3 0c-1 0-2 0-2 0c0-1 0-3 0-3c0-1 1-2 1-2c0-1 1-1 1-1c1-1 2-1 2-1c1 0 2 0 3 1c1 0 2 0 3 1c0-1 0-1 0-2c0 0 0 0 0-1c0 0 0-1 0-1c-1 0-1-1-2-1c0 0-1 0-2 0c-1-1-2-1-2-1c-2 0-3 1-4 1c-1 0-1 1-2 2c-1 0-1 2-2 3c0 2 0 4 0 6c0 3 0 5 0 7c1 2 2 4 2 5c1 1 2 1 3 1c1 1 2 1 3 1z m0-4c-1 0-1 0-2 0c0 0 0-1-1-1c0-1 0-2-1-3c0-1 0-2 0-4c0 0 1 0 1 0c1 0 2 0 2 0c1 0 1 0 2 0c1 0 1 1 1 1c1 0 1 1 1 1c0 1 0 1 0 2c0 1-1 3-1 3c0 1-1 1-2 1z m21-2c0 1 0 2-1 2c0 0-1 0-2 0c-1 0-2 0-3 0l0-20c0 0 0-1 0-1c0 0 0 0 0 0c-1 0-1 0-2 0c0 0-1 0-2 0l0 23c1 1 2 1 4 1c1 1 2 1 4 1c1 0 2 0 2 0c1-1 2-1 2-2c1 1 2 1 3 2c1 0 2 0 3 0c1 0 2 0 3-1c1 0 1 0 2-1c0 0 0-1 0-2c0-1 1-2 1-3l0-17c0-1 0-1-1-1c0 0 0 0 0 0c0 0-1 0-1 0c-1 0-1 0-2 0l0 18c0 1-1 2-1 3c0 0-1 0-2 0c0 0-1 0-1 0c-1 0-2 0-2-1l0-19c0-1 0-1 0-1c0 0 0 0-1 0c0 0 0 0-1 0c0 0-1 0-2 0z m27 6c4 0 6-3 6-8c0-1 0-2 0-3c0-1 0-2 0-3c-1 0-2-1-3-1c-1 0-2 0-3 0c-1 0-2 0-3 0c0 0-1 0-2 0c0-1 0-3 1-3c0-1 0-2 1-2c0-1 0-1 1-1c0-1 1-1 2-1c1 0 2 0 3 1c1 0 2 0 2 1c1-1 1-1 1-2c0 0 0 0 0-1c0 0 0-1-1-1c0 0-1-1-1-1c-1 0-2 0-2 0c-1-1-2-1-3-1c-1 0-2 1-3 1c-1 0-2 1-3 2c0 0-1 2-1 3c-1 2-1 4-1 6c0 3 0 5 1 7c0 2 1 4 2 5c1 1 2 1 3 1c1 1 2 1 3 1z m-1-4c0 0-1 0-1 0c0 0-1-1-1-1c-1-1-1-2-1-3c0-1-1-2-1-4c1 0 1 0 2 0c0 0 1 0 2 0c0 0 1 0 1 0c1 0 2 1 2 1c0 0 0 1 0 1c0 1 0 1 0 2c0 1 0 3 0 3c-1 1-2 1-3 1z m19 4c1 0 2 0 3 0c1-1 2-1 2-1c0 0 1-1 1-1c0 0 0-1 0-1c0 0 0-1-1-2c-1 1-3 1-5 1c-1 0-2 0-2 0c-1-1-1-1-1-2c0 0 0-1 0-1c0-1 1-1 2-2l4-4c1-1 2-2 2-3c1 0 1-2 1-3c0-2-1-4-2-5c-2-1-4-2-6-2c-2 0-3 1-4 1c-2 0-2 1-2 2c0 0 0 1 0 1c0 0 0 1 1 1c1-1 3-1 5-1c1 0 2 0 2 1c1 0 1 1 1 2c0 1 0 1 0 2c0 1-1 1-1 2l-5 4c-1 1-2 2-2 3c-1 0-1 1-1 2c0 2 1 3 2 4c1 1 3 2 6 2z"/>
18
+ <glyph unicode="&#99;" d="m447 512l-382 0c-37 0-67-30-67-66l0-380c0-36 30-66 67-66l382 0c37 0 67 30 67 66l0 380c0 36-30 66-67 66z m-210-280l0-111l-114 0c-20 0-34 1-42 2c-8 1-15 4-21 8c-16 11-24 27-24 49c0 13 3 25 10 35c6 10 15 17 25 21c9 3 24 5 46 5l66 0c0 14-3 23-8 28c-6 5-17 7-33 7l-92 0l0 42l92 0c16 0 28 0 34-1c6 0 12-2 19-4c30-11 44-38 42-81z m210-96c-9-6-18-10-28-12c-11-2-26-3-46-3l-91 0l0 48l88 0c16 0 27 2 32 7c7 5 11 14 11 25c0 13-5 23-14 28c-5 3-15 5-29 5l-47 0l0 48l47 0c17 0 28 2 33 6c6 5 9 13 9 24c0 11-4 20-12 26c-3 2-6 3-10 4c-4 1-11 1-20 1l-88 0l0 48l98 0c18 0 29-1 34-1c5-1 11-2 17-4c13-6 24-15 33-28c8-13 12-27 12-42c0-25-12-44-36-58c24-16 36-37 36-65c0-26-10-45-29-57z m-335 63c-7 0-12-2-15-5c-4-3-6-8-6-13c0-7 3-11 7-14c4-2 12-4 23-4l62 0l0 36l-62 0z"/>
19
+ </font></defs></svg>
admin/assets/fonts/a3-plugin-framework.ttf ADDED
Binary file
admin/assets/fonts/a3-plugin-framework.woff ADDED
Binary file
admin/assets/images/a3-plugins.png ADDED
Binary file
admin/assets/images/help.png ADDED
Binary file
admin/assets/images/ico-delete.png ADDED
Binary file
admin/assets/images/ico-preview.png ADDED
Binary file
admin/assets/images/ico-refresh.png ADDED
Binary file
admin/assets/images/loading-bottom.gif ADDED
Binary file
admin/assets/images/slider-bg-disable.png ADDED
Binary file
admin/assets/images/slider-bg-range.png ADDED
Binary file
admin/assets/images/slider-bg-track1.png ADDED
Binary file
admin/assets/images/slider-bg.png ADDED
Binary file
admin/assets/images/slider-bg1.jpg ADDED
Binary file
admin/assets/images/slider-container-end-disable.png ADDED
Binary file
admin/assets/images/slider-container-end.png ADDED
Binary file
admin/assets/images/slider-container-start-disable.png ADDED
Binary file
admin/assets/images/slider-container-start.png ADDED
Binary file
admin/assets/images/slider-handle-disable.png ADDED
Binary file
admin/assets/images/slider-handle.png ADDED
Binary file
admin/assets/images/slider-handle1.png ADDED
Binary file
admin/assets/images/slider-handle2.png ADDED
Binary file
admin/assets/js/a3rev-settings-preview.js ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * A3revThemes Settings Live Preview
3
+ * 2011-10-07.
4
+ *
5
+ * @description The code below is designed to generate a live preview using the
6
+ * setting specified in a "custom settings" field in the ResponsiFramework.
7
+ *
8
+ * @since 4.7.0
9
+ */
10
+
11
+ (function ($) {
12
+
13
+ a3revButtonPreview = {
14
+
15
+ /**
16
+ * loadPreviewButtons()
17
+ *
18
+ * @description Setup a "preview" button next to each type field.
19
+ * @since 4.7.0
20
+ */
21
+
22
+ loadPreviewButtons: function () {
23
+
24
+ // Register event handlers.
25
+ a3revButtonPreview.handleEvents();
26
+
27
+ }, // End loadPreviewButtons()
28
+
29
+ /**
30
+ * handleEvents()
31
+ *
32
+ * @description Handle the events.
33
+ * @since 4.7.0
34
+ */
35
+
36
+ handleEvents: function () {
37
+ $(document).on( 'click', 'a.a3rev-ui-border-preview-button', function () {
38
+ a3revButtonPreview.generateBorderPreview( $( this ) );
39
+ return false;
40
+ });
41
+
42
+ $(document).on( 'click', 'a.a3rev-ui-box_shadow-preview-button', function () {
43
+ a3revButtonPreview.generateBoxShadowPreview( $( this ) );
44
+ return false;
45
+ });
46
+
47
+ $(document).on( 'click', 'a.preview_remove', function () {
48
+ a3revButtonPreview.closePreview( $( this ) );
49
+ return false;
50
+ });
51
+ },
52
+
53
+ /**
54
+ * closePreview()
55
+ *
56
+ * @description Close the preview.
57
+ * @since 4.7.0
58
+ */
59
+
60
+ closePreview: function ( target ) {
61
+ target.parents( '.section' ).find( '.a3rev-ui-settings-preview-button .refresh' ).removeClass( 'refresh' );
62
+ target.parents( '.settings-preview-container' ).remove();
63
+ },
64
+
65
+
66
+ /**
67
+ * generateBorderPreview()
68
+ *
69
+ * @description Generate the border preview.
70
+ * @since 4.7.0
71
+ */
72
+
73
+ generateBorderPreview: function ( target ) {
74
+ var previewText = '<div class="settings-apply-preview">Grumpy wizards make toxic brew for the evil Queen and Jack.</div>';
75
+ var previewHTML = '';
76
+ var previewStyles = '';
77
+
78
+ // Get the control parent element.
79
+ var controls = target.parents( '.a3rev-ui-settings-control' );
80
+
81
+ var borderSize = controls.find( '.a3rev-ui-border_styles-width' ).val();
82
+ var borderStyle = controls.find( '.a3rev-ui-border_styles-style' ).val();
83
+ var borderColor = controls.find( '.a3rev-ui-border_styles-color' ).val();
84
+ var borderRoundedCorner = 0;
85
+ if ( controls.find( '.a3rev-ui-border-corner' ).is(":checked") ) {
86
+ borderRoundedCorner = 1;
87
+ }
88
+ var borderTopLeft = controls.find( '.a3rev-ui-border_top_left_corner' ).val();
89
+ var borderTopRight = controls.find( '.a3rev-ui-border_top_right_corner' ).val();
90
+ var borderBottomLeft = controls.find( '.a3rev-ui-border_bottom_left_corner' ).val();
91
+ var borderBottomRight = controls.find( '.a3rev-ui-border_bottom_right_corner' ).val();
92
+
93
+ // Remove "current" class from previously modified border field.
94
+ $( '.settings-preview' ).removeClass( 'current' );
95
+
96
+ // Construct styles.
97
+ previewStyles += 'border: ' + borderSize + ' ' + borderStyle + ' ' + borderColor + ';';
98
+ if ( borderRoundedCorner == 1 ) {
99
+ previewStyles += ' border-radius: ' + borderTopLeft + 'px ' + borderTopRight + 'px ' + borderBottomRight + 'px ' + borderBottomLeft + 'px ;';
100
+ previewStyles += ' -webkit-border-radius: ' + borderTopLeft + 'px ' + borderTopRight + 'px ' + borderBottomRight + 'px ' + borderBottomLeft + 'px ;';
101
+ previewStyles += ' -moz-border-radius: ' + borderTopLeft + 'px ' + borderTopRight + 'px ' + borderBottomRight + 'px ' + borderBottomLeft + 'px ;';
102
+ }
103
+
104
+ // Construct preview HTML.
105
+ var previewHTMLInner = $( '<div />' ).addClass( 'current' ).addClass( 'settings-preview' ).html( previewText );
106
+
107
+ previewHTML = $( '<div />' ).addClass( 'settings-preview-container' ).html( previewHTMLInner ).append( '<a href="#" class="preview_remove a3-plugin-ui-delete-icon">&nbsp;</a>' );
108
+
109
+ // If no preview display is present, add one.
110
+ if ( ! controls.next( '.settings-preview-container' ).length ) {
111
+ previewHTML.find( '.settings-apply-preview' ).attr( 'style', previewStyles );
112
+ controls.after( previewHTML );
113
+ } else {
114
+ // Otherwise, just update the styles of the existing preview.
115
+ controls.next( '.settings-preview-container' ).find( '.settings-apply-preview' ).attr( 'style', previewStyles );
116
+ }
117
+
118
+ // Set the button to "refresh" mode.
119
+ controls.find( '.a3rev-ui-settings-preview-button span' ).addClass( 'refresh' );
120
+ },
121
+
122
+ /**
123
+ * generateBoxShadowPreview()
124
+ *
125
+ * @description Generate the border preview.
126
+ * @since 4.7.0
127
+ */
128
+
129
+ generateBoxShadowPreview: function ( target ) {
130
+ var previewText = '<div class="settings-apply-preview">Grumpy wizards make toxic brew for the evil Queen and Jack.</div>';
131
+ var previewHTML = '';
132
+ var previewStyles = '';
133
+ var customStyles = '';
134
+
135
+ // Get the control parent element.
136
+ var controls = target.parents( '.a3rev-ui-settings-control' );
137
+
138
+ var hShadow = controls.find( '.a3rev-ui-box_shadow-h_shadow' ).val();
139
+ var vShadow = controls.find( '.a3rev-ui-box_shadow-v_shadow' ).val();
140
+ var blurSize = controls.find( '.a3rev-ui-box_shadow-blur' ).val();
141
+ var spreadSize = controls.find( '.a3rev-ui-box_shadow-spread' ).val();
142
+ var shadowColor = controls.find( '.a3rev-ui-box_shadow-color' ).val();
143
+ var insetShadow = '';
144
+ if ( controls.find( '.a3rev-ui-box_shadow-inset' ).is(":checked") ) {
145
+ insetShadow = 'inset';
146
+ }
147
+
148
+ // Remove "current" class from previously modified border field.
149
+ $( '.settings-preview' ).removeClass( 'current' );
150
+
151
+ // Construct styles.
152
+ customStyles += hShadow + ' ' + vShadow + ' ' + blurSize + ' ' + spreadSize + ' ' + shadowColor + ' ' + insetShadow ;
153
+ previewStyles += ' box-shadow: ' + customStyles + ';';
154
+ previewStyles += ' -moz-box-shadow: ' + customStyles + ';';
155
+ previewStyles += ' -webkit-box-shadow: ' + customStyles + ';';
156
+
157
+ // Construct preview HTML.
158
+ var previewHTMLInner = $( '<div />' ).addClass( 'current' ).addClass( 'settings-preview' ).html( previewText );
159
+
160
+ previewHTML = $( '<div />' ).addClass( 'settings-preview-container' ).html( previewHTMLInner ).append( '<a href="#" class="preview_remove a3-plugin-ui-delete-icon">&nbsp;</a>' );
161
+
162
+ // If no preview display is present, add one.
163
+ if ( ! controls.next( '.settings-preview-container' ).length ) {
164
+ previewHTML.find( '.settings-apply-preview' ).attr( 'style', previewStyles );
165
+ controls.after( previewHTML );
166
+ } else {
167
+ // Otherwise, just update the styles of the existing preview.
168
+ controls.next( '.settings-preview-container' ).find( '.settings-apply-preview' ).attr( 'style', previewStyles );
169
+ }
170
+
171
+ // Set the button to "refresh" mode.
172
+ controls.find( '.a3rev-ui-settings-preview-button span' ).addClass( 'refresh' );
173
+ }
174
+
175
+
176
+ }; // End a3revButtonPreview Object // Don't remove this, or the sky will fall on your head.
177
+
178
+ /*-----------------------------------------------------------------------------------*/
179
+ /* Execute the above methods in the a3revButtonPreview object.
180
+ /*-----------------------------------------------------------------------------------*/
181
+
182
+ $(document).ready(function () {
183
+
184
+ a3revButtonPreview.loadPreviewButtons();
185
+
186
+ });
187
+
188
+ })(jQuery);
admin/assets/js/a3rev-typography-preview.js ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * A3revThemes Typography Live Preview
3
+ * 2011-10-07.
4
+ *
5
+ * @description The code below is designed to generate a live preview using the
6
+ * setting specified in a "custom typography" field in the ResponsiFramework.
7
+ *
8
+ * @since 4.7.0
9
+ */
10
+
11
+ (function ($) {
12
+
13
+ a3revTypographyPreview = {
14
+
15
+ /**
16
+ * loadPreviewButtons()
17
+ *
18
+ * @description Setup a "preview" button next to each typography field.
19
+ * @since 4.7.0
20
+ */
21
+
22
+ loadPreviewButtons: function () {
23
+
24
+ // Register event handlers.
25
+ a3revTypographyPreview.handleEvents();
26
+
27
+ }, // End loadPreviewButtons()
28
+
29
+ /**
30
+ * handleEvents()
31
+ *
32
+ * @description Handle the events.
33
+ * @since 4.7.0
34
+ */
35
+
36
+ handleEvents: function () {
37
+ $(document).on( 'click', 'a.a3rev-ui-typography-preview-button', function () {
38
+ a3revTypographyPreview.generatePreview( $( this ) );
39
+ return false;
40
+ });
41
+
42
+ $(document).on( 'click', 'a.preview_remove', function () {
43
+ a3revTypographyPreview.closePreview( $( this ) );
44
+ return false;
45
+ });
46
+ },
47
+
48
+ /**
49
+ * closePreview()
50
+ *
51
+ * @description Close the preview.
52
+ * @since 4.7.0
53
+ */
54
+
55
+ closePreview: function ( target ) {
56
+ target.parents( '.section' ).find( '.a3rev-ui-typography-preview-button .refresh' ).removeClass( 'refresh' );
57
+ target.parents( '.typography-preview-container' ).remove();
58
+ },
59
+
60
+ /**
61
+ * generatePreview()
62
+ *
63
+ * @description Generate the typography preview.
64
+ * @since 4.7.0
65
+ */
66
+
67
+ generatePreview: function ( target ) {
68
+ var previewText = 'Grumpy wizards make toxic brew for the evil Queen and Jack.';
69
+ var previewHTML = '';
70
+ var previewStyles = '';
71
+
72
+ // Get the control parent element.
73
+ var controls = target.parents( '.a3rev-ui-typography-control' );
74
+
75
+ var sizeSelector = '.a3rev-ui-typography-size';
76
+
77
+ var fontSize = controls.find( sizeSelector ).val();
78
+
79
+ var fontFace = controls.find( '.a3rev-ui-typography-face' ).val();
80
+ var fontStyle = controls.find( '.a3rev-ui-typography-style' ).val();
81
+ var fontColor = controls.find( '.a3rev-ui-typography-color' ).val();
82
+ var lineHeight = ( parseInt( fontSize ) / 2 ) + parseInt( fontSize ); // Calculate pleasant line-height for the selected font size.
83
+
84
+ // Generate array of non-Google fonts.
85
+ var nonGoogleFonts = new Array(
86
+ 'Arial, sans-serif',
87
+ 'Verdana, Geneva, sans-serif',
88
+ 'Trebuchet MS, Tahoma, sans-serif',
89
+ 'Georgia, serif',
90
+ 'Times New Roman, serif',
91
+ 'Tahoma, Geneva, Verdana, sans-serif',
92
+ 'Palatino, Palatino Linotype, serif',
93
+ 'Helvetica Neue, Helvetica, sans-serif',
94
+ 'Calibri, Candara, Segoe, Optima, sans-serif',
95
+ 'Myriad Pro, Myriad, sans-serif',
96
+ 'Lucida Grande, Lucida Sans Unicode, Lucida Sans, sans-serif',
97
+ 'Arial Black, sans-serif',
98
+ 'Gill Sans, Gill Sans MT, Calibri, sans-serif',
99
+ 'Geneva, Tahoma, Verdana, sans-serif',
100
+ 'Impact, Charcoal, sans-serif',
101
+ 'Courier, Courier New, monospace',
102
+ 'Century Gothic, sans-serif'
103
+ );
104
+
105
+ // Remove "current" class from previously modified typography field.
106
+ $( '.typography-preview' ).removeClass( 'current' );
107
+
108
+ // Prepare selected fontFace for testing.
109
+ var fontFaceTest = fontFace.replace( /"/g, '&quot;' );
110
+
111
+ // Load Google WebFonts, if we need to.
112
+ if ( jQuery.inArray( fontFaceTest, nonGoogleFonts ) == -1 ) { // -1 is returned if the item is not found in the array.
113
+
114
+ // Prepare fontFace for use in the WebFont loader.
115
+ var fontFaceString = fontFace;
116
+
117
+ // Handle fonts that require specific weights when being included.
118
+ switch ( fontFaceString ) {
119
+ case 'Allan':
120
+ case 'Cabin Sketch':
121
+ case 'Corben':
122
+ case 'UnifrakturCook':
123
+ fontFaceString += ':700';
124
+ break;
125
+
126
+ case 'Buda':
127
+ case 'Open Sans Condensed':
128
+ fontFaceString += ':300';
129
+ break;
130
+
131
+ case 'Coda':
132
+ case 'Sniglet':
133
+ fontFaceString += ':800';
134
+ break;
135
+
136
+ case 'Raleway':
137
+ fontFaceString += ':100';
138
+ break;
139
+ }
140
+
141
+
142
+ fontFaceString += '::latin';
143
+ fontFaceString = fontFaceString.replace( / /g, '+' );
144
+
145
+ // Add the fontFace in quotes for use in the style declaration, if the selected font has a number in it.
146
+ var specificFonts = new Array( 'Goudy Bookletter 1911' );
147
+
148
+ if ( jQuery.inArray( fontFace, specificFonts ) > -1 ) {
149
+ var fontFace = "'" + fontFace + "'";
150
+ }
151
+
152
+ WebFontConfig = {
153
+ google: { families: [ fontFaceString ] }
154
+ };
155
+
156
+ if ( $( 'script.google-webfonts-script' ).length ) { $( 'script.google-webfonts-script' ).remove(); WebFont.load({ google: {families: [ fontFaceString ]} }); }
157
+
158
+ (function() {
159
+ var wf = document.createElement( 'script' );
160
+ wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
161
+ '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
162
+ wf.type = 'text/javascript';
163
+ wf.async = 'true';
164
+ var s = document.getElementsByTagName( 'script' )[0];
165
+ s.parentNode.insertBefore( wf, s );
166
+
167
+ $( wf ).addClass( 'google-webfonts-script' );
168
+
169
+ })();
170
+
171
+ }
172
+
173
+ // Construct styles.
174
+ previewStyles += 'font: ' + fontStyle + ' ' + fontSize + '/' + lineHeight + 'px ' + fontFace + ';';
175
+ if ( fontColor ) { previewStyles += ' color: ' + fontColor + ';'; }
176
+
177
+ // Construct preview HTML.
178
+ var previewHTMLInner = $( '<div />' ).addClass( 'current' ).addClass( 'typography-preview' ).text( previewText );
179
+
180
+ previewHTML = $( '<div />' ).addClass( 'typography-preview-container' ).html( previewHTMLInner ).append( '<a href="#" class="preview_remove a3-plugin-ui-delete-icon">&nbsp;</a>' );
181
+
182
+ // If no preview display is present, add one.
183
+ if ( ! controls.next( '.typography-preview-container' ).length ) {
184
+ previewHTML.find( '.typography-preview' ).attr( 'style', previewStyles );
185
+ controls.after( previewHTML );
186
+ } else {
187
+ // Otherwise, just update the styles of the existing preview.
188
+ controls.next( '.typography-preview-container' ).find( '.typography-preview' ).attr( 'style', previewStyles );
189
+ }
190
+
191
+ // Set the button to "refresh" mode.
192
+ controls.find( '.a3rev-ui-typography-preview-button span' ).addClass( 'refresh' );
193
+ }
194
+
195
+
196
+ }; // End a3revTypographyPreview Object // Don't remove this, or the sky will fall on your head.
197
+
198
+ /*-----------------------------------------------------------------------------------*/
199
+ /* Execute the above methods in the a3revTypographyPreview object.
200
+ /*-----------------------------------------------------------------------------------*/
201
+
202
+ $(document).ready(function () {
203
+
204
+ a3revTypographyPreview.loadPreviewButtons();
205
+
206
+ });
207
+
208
+ })(jQuery);
admin/assets/js/admin-ui-script.js ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ $(document).ready(function() {
3
+
4
+ /* Apply wp color picker */
5
+ $('.a3rev_panel_container .a3rev-color-picker').each(function(i){
6
+ $(this).wpColorPicker({
7
+ change: function( event, ui ) {
8
+ //bgImage.css('background-color', ui.color.toString());
9
+ },
10
+ clear: function() {
11
+ //bgImage.css('background-color', '');
12
+ }
13
+ });
14
+ });
15
+
16
+ /* Apply UI slider */
17
+ $('.a3rev_panel_container div.a3rev-ui-slide').each(function(i){
18
+
19
+ if( $(this).attr('min') != undefined && $(this).attr('max') != undefined ) {
20
+
21
+ $(this).slider( {
22
+ isRTL: true,
23
+ range: "min",
24
+ min: parseInt($(this).attr('min')),
25
+ max: parseInt($(this).attr('max')),
26
+ value: parseInt($(this).parent('.a3rev-ui-slide-container-end').parent('.a3rev-ui-slide-container-start').next(".a3rev-ui-slide-result-container").children("input").val()),
27
+ step: parseInt($(this).attr('inc')) ,
28
+ slide: function( event, ui ) {
29
+ $( this ).parent('.a3rev-ui-slide-container-end').parent('.a3rev-ui-slide-container-start').next(".a3rev-ui-slide-result-container").children("input").val(ui.value);
30
+ }
31
+ });
32
+
33
+ $(this).removeAttr('min').removeAttr('max').removeAttr('inc');
34
+
35
+ }
36
+
37
+ });
38
+
39
+ /* Apply Box Shadow */
40
+ $('.a3rev_panel_container input.a3rev-ui-box_shadow-enable').each(function(i){
41
+ if ( $(this).is(':checked') ) {
42
+ $(this).parent('.forminp-box_shadow').find('.a3rev-ui-box_shadow-enable-container').css( {'visibility': 'visible', 'height' : 'auto', 'overflow' : 'inherit'} );
43
+ } else {
44
+ $(this).parent('.forminp-box_shadow').find('.a3rev-ui-box_shadow-enable-container').css( {'visibility': 'hidden', 'height' : '0px', 'overflow' : 'hidden'} );
45
+ }
46
+ $(this).on( "a3rev-ui-onoff_checkbox-switch", function( event, value, status ) {
47
+ if ( status == 'true') {
48
+ $(this).parents('.forminp-box_shadow').find('.a3rev-ui-box_shadow-enable-container').hide().css( {'visibility': 'visible', 'height' : 'auto', 'overflow' : 'inherit'} ).slideDown();
49
+ } else {
50
+ $(this).parents('.forminp-box_shadow').find('.a3rev-ui-box_shadow-enable-container').show().css( {'visibility': 'hidden', 'height' : '0px', 'overflow' : 'hidden'} ).slideUp();
51
+ }
52
+ });
53
+ });
54
+
55
+ /* Apply OnOff Checbox */
56
+ $('.a3rev_panel_container input.a3rev-ui-onoff_checkbox').each(function(i){
57
+ var checked_label = 'ON';
58
+ var unchecked_label = 'OFF';
59
+ var callback = "maincheck";
60
+
61
+ if( $(this).attr('checked_label') != undefined ) checked_label = $(this).attr('checked_label');
62
+ if( $(this).attr('unchecked_label') != undefined ) unchecked_label = $(this).attr('unchecked_label');
63
+ if( $(this).attr('callback') != undefined ) callback = $(this).attr('callback');
64
+ var input_name = $(this).attr('name');
65
+
66
+ /* Apply for Border Corner */
67
+ if ( $(this).prop('checked') ) {
68
+ $(this).parents('.a3rev-ui-settings-control').find('.a3rev-ui-border-corner-value-container').css( {'display': 'block'} );
69
+ } else {
70
+ $(this).parents('.a3rev-ui-settings-control').find('.a3rev-ui-border-corner-value-container').css( {'display': 'none'} );
71
+ }
72
+
73
+ $(this).iphoneStyle({
74
+ /*resizeContainer: false,*/
75
+ resizeHandle: false,
76
+ handleMargin: 10,
77
+ handleRadius: 5,
78
+ containerRadius: 0,
79
+ checkedLabel: checked_label,
80
+ uncheckedLabel: unchecked_label,
81
+ onChange: function(elem, value) {
82
+ var status = value.toString();
83
+ /* Apply for Border Corner */
84
+ if ( status == 'true' ) {
85
+ elem.parents('.a3rev-ui-settings-control').find('.a3rev-ui-border-corner-value-container').slideDown();
86
+ } else {
87
+ elem.parents('.a3rev-ui-settings-control').find('.a3rev-ui-border-corner-value-container').slideUp();
88
+ }
89
+
90
+ $('input[name="' + input_name + '"]').trigger("a3rev-ui-onoff_checkbox-switch", [elem.val(), status]);
91
+ },
92
+ onEnd: function(elem, value) {
93
+ var status = value.toString();
94
+
95
+ $('input[name="' + input_name + '"]').trigger("a3rev-ui-onoff_checkbox-switch-end", [elem.val(), status]);
96
+ }
97
+ });
98
+ });
99
+
100
+ /* Apply OnOff Radio */
101
+ $('.a3rev_panel_container input.a3rev-ui-onoff_radio').each(function(i){
102
+ var checked_label = 'ON';
103
+ var unchecked_label = 'OFF';
104
+
105
+ if( $(this).attr('checked_label') != undefined ) checked_label = $(this).attr('checked_label');
106
+ if( $(this).attr('unchecked_label') != undefined ) unchecked_label = $(this).attr('unchecked_label');
107
+ var input_name = $(this).attr('name');
108
+ var current_item = $(this);
109
+
110
+ $(this).iphoneStyle({
111
+ /*resizeContainer: false,*/
112
+ resizeHandle: false,
113
+ handleMargin: 10,
114
+ handleRadius: 5,
115
+ containerRadius: 0,
116
+ checkedLabel: checked_label,
117
+ uncheckedLabel: unchecked_label,
118
+ onChange: function(elem, value) {
119
+ var status = value.toString();
120
+ if ( status == 'true') {
121
+ $('input[name="' + input_name + '"]').not(current_item).removeAttr('checked').removeAttr('checkbox-disabled').iphoneStyle("refresh");
122
+ }
123
+ $('input[name="' + input_name + '"]').trigger("a3rev-ui-onoff_radio-switch", [elem.val(), status]);
124
+ },
125
+ onEnd: function(elem, value) {
126
+ var status = value.toString();
127
+ if ( status == 'true') {
128
+ $('input[name="' + input_name + '"]').not(current_item).removeAttr('checkbox-disabled');
129
+ $(current_item).attr('checkbox-disabled', 'true');
130
+ }
131
+ $('input[name="' + input_name + '"]').trigger("a3rev-ui-onoff_radio-switch-end", [elem.val(), status]);
132
+ }
133
+ });
134
+ });
135
+
136
+ /* Apply for normal checkbox */
137
+ $('.a3rev_panel_container .hide_options_if_checked').each(function(){
138
+
139
+ $(this).find('input:eq(0)').change(function() {
140
+
141
+ if ($(this).is(':checked')) {
142
+ $(this).closest('fieldset, tr').nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option').hide();
143
+ } else {
144
+ $(this).closest('fieldset, tr').nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option').show();
145
+ }
146
+
147
+ }).change();
148
+
149
+ });
150
+ $('.a3rev_panel_container .show_options_if_checked').each(function(){
151
+
152
+ $(this).find('input:eq(0)').change(function() {
153
+
154
+ if ($(this).is(':checked')) {
155
+ $(this).closest('fieldset, tr').nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option').show();
156
+ } else {
157
+ $(this).closest('fieldset, tr').nextUntil( '.hide_options_if_checked, .show_options_if_checked', '.hidden_option').hide();
158
+ }
159
+
160
+ }).change();
161
+
162
+ });
163
+
164
+ /* Apply chosen script for dropdown */
165
+ $(".a3rev_panel_container .chzn-select").chosen();
166
+ $(".a3rev_panel_container .chzn-select-deselect").chosen({ allow_single_deselect:true });
167
+
168
+ /* Apply help tip script */
169
+ $(".a3rev_panel_container .help_tip").tipTip({
170
+ "attribute" : "data-tip",
171
+ "fadeIn" : 50,
172
+ "fadeOut" : 50
173
+ });
174
+
175
+ /* Apply Sub tab selected script */
176
+ $('div.a3_subsubsub_section ul.subsubsub li a:eq(0)').addClass('current');
177
+ $('div.a3_subsubsub_section .section:gt(0)').hide();
178
+ $('div.a3_subsubsub_section ul.subsubsub li a:gt(0)').each(function(){
179
+ if( $(this).attr('class') == 'current') {
180
+ $('div.a3_subsubsub_section ul.subsubsub li a').removeClass('current');
181
+ $(this).addClass('current');
182
+ $('div.a3_subsubsub_section .section').hide();
183
+ $('div.a3_subsubsub_section ' + $(this).attr('href') ).show();
184
+ }
185
+ });
186
+ $('div.a3_subsubsub_section ul.subsubsub li a').click(function(){
187
+ var clicked = $(this);
188
+ var section = clicked.closest('.a3_subsubsub_section');
189
+ var target = clicked.attr('href');
190
+
191
+ section.find('a').removeClass('current');
192
+
193
+ if ( section.find('.section:visible').size() > 0 ) {
194
+ section.find('.section:visible').fadeOut( 100, function() {
195
+ section.find( target ).fadeIn('fast');
196
+ });
197
+ } else {
198
+ section.find( target ).fadeIn('fast');
199
+ }
200
+
201
+ clicked.addClass('current');
202
+ $('.last_tab').val( target );
203
+
204
+ return false;
205
+ });
206
+
207
+ $('.a3rev_panel_container').each( function(i){
208
+ $(this).css( {'visibility': 'visible', 'height' : 'auto', 'overflow' : 'inherit'} );
209
+ })
210
+
211
+ $(document).trigger("a3rev-ui-script-loaded");
212
+ });
213
+ })(jQuery);
admin/assets/js/chosen/chosen-sprite.png ADDED
Binary file
admin/assets/js/chosen/chosen-sprite@2x.png ADDED
Binary file
admin/assets/js/chosen/chosen.css ADDED
@@ -0,0 +1,435 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.1.0
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ /* @group Base */
14
+ .chosen-container {
15
+ position: relative;
16
+ display: inline-block;
17
+ vertical-align: middle;
18
+ font-size: 13px;
19
+ zoom: 1;
20
+ *display: inline;
21
+ -webkit-user-select: none;
22
+ -moz-user-select: none;
23
+ user-select: none;
24
+ }
25
+ .chosen-container .chosen-drop {
26
+ position: absolute;
27
+ top: 100%;
28
+ left: -9999px;
29
+ z-index: 1010;
30
+ -webkit-box-sizing: border-box;
31
+ -moz-box-sizing: border-box;
32
+ box-sizing: border-box;
33
+ width: 100%;
34
+ border: 1px solid #aaa;
35
+ border-top: 0;
36
+ background: #fff;
37
+ box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
38
+ }
39
+ .chosen-container.chosen-with-drop .chosen-drop {
40
+ left: 0;
41
+ }
42
+ .chosen-container a {
43
+ cursor: pointer;
44
+ }
45
+
46
+ /* @end */
47
+ /* @group Single Chosen */
48
+ .chosen-container-single .chosen-single {
49
+ position: relative;
50
+ display: block;
51
+ overflow: hidden;
52
+ padding: 0 0 0 8px;
53
+ height: 23px;
54
+ border: 1px solid #aaa;
55
+ border-radius: 5px;
56
+ background-color: #fff;
57
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
58
+ background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
59
+ background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
60
+ background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
61
+ background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
62
+ background-clip: padding-box;
63
+ box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
64
+ color: #444;
65
+ text-decoration: none;
66
+ white-space: nowrap;
67
+ line-height: 24px;
68
+ }
69
+ .chosen-container-single .chosen-default {
70
+ color: #999;
71
+ }
72
+ .chosen-container-single .chosen-single span {
73
+ display: block;
74
+ overflow: hidden;
75
+ margin-right: 26px;
76
+ text-overflow: ellipsis;
77
+ white-space: nowrap;
78
+ }
79
+ .chosen-container-single .chosen-single-with-deselect span {
80
+ margin-right: 38px;
81
+ }
82
+ .chosen-container-single .chosen-single abbr {
83
+ position: absolute;
84
+ top: 6px;
85
+ right: 26px;
86
+ display: block;
87
+ width: 12px;
88
+ height: 12px;
89
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
90
+ font-size: 1px;
91
+ }
92
+ .chosen-container-single .chosen-single abbr:hover {
93
+ background-position: -42px -10px;
94
+ }
95
+ .chosen-container-single.chosen-disabled .chosen-single abbr:hover {
96
+ background-position: -42px -10px;
97
+ }
98
+ .chosen-container-single .chosen-single div {
99
+ position: absolute;
100
+ top: 0;
101
+ right: 0;
102
+ display: block;
103
+ width: 18px;
104
+ height: 100%;
105
+ }
106
+ .chosen-container-single .chosen-single div b {
107
+ display: block;
108
+ width: 100%;
109
+ height: 100%;
110
+ background: url('chosen-sprite.png') no-repeat 0px 2px;
111
+ }
112
+ .chosen-container-single .chosen-search {
113
+ position: relative;
114
+ z-index: 1010;
115
+ margin: 0;
116
+ padding: 3px 4px;
117
+ white-space: nowrap;
118
+ }
119
+ .chosen-container-single .chosen-search input[type="text"] {
120
+ -webkit-box-sizing: border-box;
121
+ -moz-box-sizing: border-box;
122
+ box-sizing: border-box;
123
+ margin: 1px 0;
124
+ padding: 4px 20px 4px 5px;
125
+ width: 100%;
126
+ height: auto;
127
+ outline: 0;
128
+ border: 1px solid #aaa;
129
+ background: white url('chosen-sprite.png') no-repeat 100% -20px;
130
+ background: url('chosen-sprite.png') no-repeat 100% -20px;
131
+ font-size: 1em;
132
+ font-family: sans-serif;
133
+ line-height: normal;
134
+ border-radius: 0;
135
+ }
136
+ .chosen-container-single .chosen-drop {
137
+ margin-top: -1px;
138
+ border-radius: 0 0 4px 4px;
139
+ background-clip: padding-box;
140
+ }
141
+ .chosen-container-single.chosen-container-single-nosearch .chosen-search {
142
+ position: absolute;
143
+ left: -9999px;
144
+ }
145
+
146
+ /* @end */
147
+ /* @group Results */
148
+ .chosen-container .chosen-results {
149
+ position: relative;
150
+ overflow-x: hidden;
151
+ overflow-y: auto;
152
+ margin: 0 4px 4px 0;
153
+ padding: 0 0 0 4px;
154
+ max-height: 240px;
155
+ -webkit-overflow-scrolling: touch;
156
+ }
157
+ .chosen-container .chosen-results li {
158
+ display: none;
159
+ margin: 0;
160
+ padding: 5px 6px;
161
+ list-style: none;
162
+ line-height: 15px;
163
+ -webkit-touch-callout: none;
164
+ }
165
+ .chosen-container .chosen-results li.active-result {
166
+ display: list-item;
167
+ cursor: pointer;
168
+ }
169
+ .chosen-container .chosen-results li.disabled-result {
170
+ display: list-item;
171
+ color: #ccc;
172
+ cursor: default;
173
+ }
174
+ .chosen-container .chosen-results li.highlighted {
175
+ background-color: #3875d7;
176
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
177
+ background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
178
+ background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
179
+ background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
180
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
181
+ color: #fff;
182
+ }
183
+ .chosen-container .chosen-results li.no-results {
184
+ display: list-item;
185
+ background: #f4f4f4;
186
+ }
187
+ .chosen-container .chosen-results li.group-result {
188
+ display: list-item;
189
+ font-weight: bold;
190
+ cursor: default;
191
+ }
192
+ .chosen-container .chosen-results li.group-option {
193
+ padding-left: 15px;
194
+ }
195
+ .chosen-container .chosen-results li em {
196
+ font-style: normal;
197
+ text-decoration: underline;
198
+ }
199
+
200
+ /* @end */
201
+ /* @group Multi Chosen */
202
+ .chosen-container-multi .chosen-choices {
203
+ position: relative;
204
+ overflow: hidden;
205
+ -webkit-box-sizing: border-box;
206
+ -moz-box-sizing: border-box;
207
+ box-sizing: border-box;
208
+ margin: 0;
209
+ padding: 0;
210
+ width: 100%;
211
+ height: auto !important;
212
+ height: 1%;
213
+ border: 1px solid #aaa;
214
+ background-color: #fff;
215
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
216
+ background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
217
+ background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
218
+ background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
219
+ background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
220
+ cursor: text;
221
+ }
222
+ .chosen-container-multi .chosen-choices li {
223
+ float: left;
224
+ list-style: none;
225
+ }
226
+ .chosen-container-multi .chosen-choices li.search-field {
227
+ margin: 0;
228
+ padding: 0;
229
+ white-space: nowrap;
230
+ }
231
+ .chosen-container-multi .chosen-choices li.search-field input[type="text"] {
232
+ margin: 1px 0;
233
+ padding: 5px;
234
+ height: 15px;
235
+ outline: 0;
236
+ border: 0 !important;
237
+ background: transparent !important;
238
+ box-shadow: none;
239
+ color: #666;
240
+ font-size: 100%;
241
+ font-family: sans-serif;
242
+ line-height: normal;
243
+ border-radius: 0;
244
+ }
245
+ .chosen-container-multi .chosen-choices li.search-field .default {
246
+ color: #999;
247
+ }
248
+ .chosen-container-multi .chosen-choices li.search-choice {
249
+ position: relative;
250
+ margin: 3px 0 3px 5px;
251
+ padding: 3px 20px 3px 5px;
252
+ border: 1px solid #aaa;
253
+ border-radius: 3px;
254
+ background-color: #e4e4e4;
255
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
256
+ background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
257
+ background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
258
+ background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
259
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
260
+ background-clip: padding-box;
261
+ box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
262
+ color: #333;
263
+ line-height: 13px;
264
+ cursor: default;
265
+ }
266
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
267
+ position: absolute;
268
+ top: 4px;
269
+ right: 3px;
270
+ display: block;
271
+ width: 12px;
272
+ height: 12px;
273
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
274
+ font-size: 1px;
275
+ }
276
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
277
+ background-position: -42px -10px;
278
+ }
279
+ .chosen-container-multi .chosen-choices li.search-choice-disabled {
280
+ padding-right: 5px;
281
+ border: 1px solid #ccc;
282
+ background-color: #e4e4e4;
283
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
284
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
285
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
286
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
287
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
288
+ color: #666;
289
+ }
290
+ .chosen-container-multi .chosen-choices li.search-choice-focus {
291
+ background: #d4d4d4;
292
+ }
293
+ .chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
294
+ background-position: -42px -10px;
295
+ }
296
+ .chosen-container-multi .chosen-results {
297
+ margin: 0;
298
+ padding: 0;
299
+ }
300
+ .chosen-container-multi .chosen-drop .result-selected {
301
+ display: list-item;
302
+ color: #ccc;
303
+ cursor: default;
304
+ }
305
+
306
+ /* @end */
307
+ /* @group Active */
308
+ .chosen-container-active .chosen-single {
309
+ border: 1px solid #5897fb;
310
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
311
+ }
312
+ .chosen-container-active.chosen-with-drop .chosen-single {
313
+ border: 1px solid #aaa;
314
+ -moz-border-radius-bottomright: 0;
315
+ border-bottom-right-radius: 0;
316
+ -moz-border-radius-bottomleft: 0;
317
+ border-bottom-left-radius: 0;
318
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
319
+ background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
320
+ background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
321
+ background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
322
+ background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
323
+ box-shadow: 0 1px 0 #fff inset;
324
+ }
325
+ .chosen-container-active.chosen-with-drop .chosen-single div {
326
+ border-left: none;
327
+ background: transparent;
328
+ }
329
+ .chosen-container-active.chosen-with-drop .chosen-single div b {
330
+ background-position: -18px 2px;
331
+ }
332
+ .chosen-container-active .chosen-choices {
333
+ border: 1px solid #5897fb;
334
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
335
+ }
336
+ .chosen-container-active .chosen-choices li.search-field input[type="text"] {
337
+ color: #111 !important;
338
+ }
339
+
340
+ /* @end */
341
+ /* @group Disabled Support */
342
+ .chosen-disabled {
343
+ opacity: 0.5 !important;
344
+ cursor: default;
345
+ }
346
+ .chosen-disabled .chosen-single {
347
+ cursor: default;
348
+ }
349
+ .chosen-disabled .chosen-choices .search-choice .search-choice-close {
350
+ cursor: default;
351
+ }
352
+
353
+ /* @end */
354
+ /* @group Right to Left */
355
+ .chosen-rtl {
356
+ text-align: right;
357
+ }
358
+ .chosen-rtl .chosen-single {
359
+ overflow: visible;
360
+ padding: 0 8px 0 0;
361
+ }
362
+ .chosen-rtl .chosen-single span {
363
+ margin-right: 0;
364
+ margin-left: 26px;
365
+ direction: rtl;
366
+ }
367
+ .chosen-rtl .chosen-single-with-deselect span {
368
+ margin-left: 38px;
369
+ }
370
+ .chosen-rtl .chosen-single div {
371
+ right: auto;
372
+ left: 3px;
373
+ }
374
+ .chosen-rtl .chosen-single abbr {
375
+ right: auto;
376
+ left: 26px;
377
+ }
378
+ .chosen-rtl .chosen-choices li {
379
+ float: right;
380
+ }
381
+ .chosen-rtl .chosen-choices li.search-field input[type="text"] {
382
+ direction: rtl;
383
+ }
384
+ .chosen-rtl .chosen-choices li.search-choice {
385
+ margin: 3px 5px 3px 0;
386
+ padding: 3px 5px 3px 19px;
387
+ }
388
+ .chosen-rtl .chosen-choices li.search-choice .search-choice-close {
389
+ right: auto;
390
+ left: 4px;
391
+ }
392
+ .chosen-rtl.chosen-container-single-nosearch .chosen-search,
393
+ .chosen-rtl .chosen-drop {
394
+ left: 9999px;
395
+ }
396
+ .chosen-rtl.chosen-container-single .chosen-results {
397
+ margin: 0 0 4px 4px;
398
+ padding: 0 4px 0 0;
399
+ }
400
+ .chosen-rtl .chosen-results li.group-option {
401
+ padding-right: 15px;
402
+ padding-left: 0;
403
+ }
404
+ .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
405
+ border-right: none;
406
+ }
407
+ .chosen-rtl .chosen-search input[type="text"] {
408
+ padding: 4px 5px 4px 20px;
409
+ background: white url('chosen-sprite.png') no-repeat -30px -20px;
410
+ background: url('chosen-sprite.png') no-repeat -30px -20px;
411
+ direction: rtl;
412
+ }
413
+ .chosen-rtl.chosen-container-single .chosen-single div b {
414
+ background-position: 6px 2px;
415
+ }
416
+ .chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
417
+ background-position: -12px 2px;
418
+ }
419
+
420
+ /* @end */
421
+ /* @group Retina compatibility */
422
+ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
423
+ .chosen-rtl .chosen-search input[type="text"],
424
+ .chosen-container-single .chosen-single abbr,
425
+ .chosen-container-single .chosen-single div b,
426
+ .chosen-container-single .chosen-search input[type="text"],
427
+ .chosen-container-multi .chosen-choices .search-choice .search-choice-close,
428
+ .chosen-container .chosen-results-scroll-down span,
429
+ .chosen-container .chosen-results-scroll-up span {
430
+ background-image: url('chosen-sprite@2x.png') !important;
431
+ background-size: 52px 37px !important;
432
+ background-repeat: no-repeat !important;
433
+ }
434
+ }
435
+ /* @end */
admin/assets/js/chosen/chosen.jquery.js ADDED
@@ -0,0 +1,1211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ Chosen, a Select Box Enhancer for jQuery and Prototype
3
+ by Patrick Filler for Harvest, http://getharvest.com
4
+
5
+ Version 1.1.0
6
+ Full source at https://github.com/harvesthq/chosen
7
+ Copyright (c) 2011 Harvest http://getharvest.com
8
+
9
+ MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10
+ This file is generated by `grunt build`, do not edit it by hand.
11
+ */
12
+
13
+ (function() {
14
+ var $, AbstractChosen, Chosen, SelectParser, _ref,
15
+ __hasProp = {}.hasOwnProperty,
16
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
17
+
18
+ SelectParser = (function() {
19
+ function SelectParser() {
20
+ this.options_index = 0;
21
+ this.parsed = [];
22
+ }
23
+
24
+ SelectParser.prototype.add_node = function(child) {
25
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
26
+ return this.add_group(child);
27
+ } else {
28
+ return this.add_option(child);
29
+ }
30
+ };
31
+
32
+ SelectParser.prototype.add_group = function(group) {
33
+ var group_position, option, _i, _len, _ref, _results;
34
+ group_position = this.parsed.length;
35
+ this.parsed.push({
36
+ array_index: group_position,
37
+ group: true,
38
+ label: this.escapeExpression(group.label),
39
+ children: 0,
40
+ disabled: group.disabled
41
+ });
42
+ _ref = group.childNodes;
43
+ _results = [];
44
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
45
+ option = _ref[_i];
46
+ _results.push(this.add_option(option, group_position, group.disabled));
47
+ }
48
+ return _results;
49
+ };
50
+
51
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
52
+ if (option.nodeName.toUpperCase() === "OPTION") {
53
+ if (option.text !== "") {
54
+ if (group_position != null) {
55
+ this.parsed[group_position].children += 1;
56
+ }
57
+ this.parsed.push({
58
+ array_index: this.parsed.length,
59
+ options_index: this.options_index,
60
+ value: option.value,
61
+ text: option.text,
62
+ html: option.innerHTML,
63
+ selected: option.selected,
64
+ disabled: group_disabled === true ? group_disabled : option.disabled,
65
+ group_array_index: group_position,
66
+ classes: option.className,
67
+ style: option.style.cssText
68
+ });
69
+ } else {
70
+ this.parsed.push({
71
+ array_index: this.parsed.length,
72
+ options_index: this.options_index,
73
+ empty: true
74
+ });
75
+ }
76
+ return this.options_index += 1;
77
+ }
78
+ };
79
+
80
+ SelectParser.prototype.escapeExpression = function(text) {
81
+ var map, unsafe_chars;
82
+ if ((text == null) || text === false) {
83
+ return "";
84
+ }
85
+ if (!/[\&\<\>\"\'\`]/.test(text)) {
86
+ return text;
87
+ }
88
+ map = {
89
+ "<": "&lt;",
90
+ ">": "&gt;",
91
+ '"': "&quot;",
92
+ "'": "&#x27;",
93
+ "`": "&#x60;"
94
+ };
95
+ unsafe_chars = /&(?!\w+;)|[\<\>\"\'\`]/g;
96
+ return text.replace(unsafe_chars, function(chr) {
97
+ return map[chr] || "&amp;";
98
+ });
99
+ };
100
+
101
+ return SelectParser;
102
+
103
+ })();
104
+
105
+ SelectParser.select_to_array = function(select) {
106
+ var child, parser, _i, _len, _ref;
107
+ parser = new SelectParser();
108
+ _ref = select.childNodes;
109
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
110
+ child = _ref[_i];
111
+ parser.add_node(child);
112
+ }
113
+ return parser.parsed;
114
+ };
115
+
116
+ AbstractChosen = (function() {
117
+ function AbstractChosen(form_field, options) {
118
+ this.form_field = form_field;
119
+ this.options = options != null ? options : {};
120
+ if (!AbstractChosen.browser_is_supported()) {
121
+ return;
122
+ }
123
+ this.is_multiple = this.form_field.multiple;
124
+ this.set_default_text();
125
+ this.set_default_values();
126
+ this.setup();
127
+ this.set_up_html();
128
+ this.register_observers();
129
+ }
130
+
131
+ AbstractChosen.prototype.set_default_values = function() {
132
+ var _this = this;
133
+ this.click_test_action = function(evt) {
134
+ return _this.test_active_click(evt);
135
+ };
136
+ this.activate_action = function(evt) {
137
+ return _this.activate_field(evt);
138
+ };
139
+ this.active_field = false;
140
+ this.mouse_on_container = false;
141
+ this.results_showing = false;
142
+ this.result_highlighted = null;
143
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
144
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
145
+ this.disable_search = this.options.disable_search || false;
146
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
147
+ this.group_search = this.options.group_search != null ? this.options.group_search : true;
148
+ this.search_contains = this.options.search_contains || false;
149
+ this.single_backstroke_delete = this.options.single_backstroke_delete != null ? this.options.single_backstroke_delete : true;
150
+ this.max_selected_options = this.options.max_selected_options || Infinity;
151
+ this.inherit_select_classes = this.options.inherit_select_classes || false;
152
+ this.display_selected_options = this.options.display_selected_options != null ? this.options.display_selected_options : true;
153
+ return this.display_disabled_options = this.options.display_disabled_options != null ? this.options.display_disabled_options : true;
154
+ };
155
+
156
+ AbstractChosen.prototype.set_default_text = function() {
157
+ if (this.form_field.getAttribute("data-placeholder")) {
158
+ this.default_text = this.form_field.getAttribute("data-placeholder");
159
+ } else if (this.is_multiple) {
160
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
161
+ } else {
162
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
163
+ }
164
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
165
+ };
166
+
167
+ AbstractChosen.prototype.mouse_enter = function() {
168
+ return this.mouse_on_container = true;
169
+ };
170
+
171
+ AbstractChosen.prototype.mouse_leave = function() {
172
+ return this.mouse_on_container = false;
173
+ };
174
+
175
+ AbstractChosen.prototype.input_focus = function(evt) {
176
+ var _this = this;
177
+ if (this.is_multiple) {
178
+ if (!this.active_field) {
179
+ return setTimeout((function() {
180
+ return _this.container_mousedown();
181
+ }), 50);
182
+ }
183
+ } else {
184
+ if (!this.active_field) {
185
+ return this.activate_field();
186
+ }
187
+ }
188
+ };
189
+
190
+ AbstractChosen.prototype.input_blur = function(evt) {
191
+ var _this = this;
192
+ if (!this.mouse_on_container) {
193
+ this.active_field = false;
194
+ return setTimeout((function() {
195
+ return _this.blur_test();
196
+ }), 100);
197
+ }
198
+ };
199
+
200
+ AbstractChosen.prototype.results_option_build = function(options) {
201
+ var content, data, _i, _len, _ref;
202
+ content = '';
203
+ _ref = this.results_data;
204
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
205
+ data = _ref[_i];
206
+ if (data.group) {
207
+ content += this.result_add_group(data);
208
+ } else {
209
+ content += this.result_add_option(data);
210
+ }
211
+ if (options != null ? options.first : void 0) {
212
+ if (data.selected && this.is_multiple) {
213
+ this.choice_build(data);
214
+ } else if (data.selected && !this.is_multiple) {
215
+ this.single_set_selected_text(data.text);
216
+ }
217
+ }
218
+ }
219
+ return content;
220
+ };
221
+
222
+ AbstractChosen.prototype.result_add_option = function(option) {
223
+ var classes, option_el;
224
+ if (!option.search_match) {
225
+ return '';
226
+ }
227
+ if (!this.include_option_in_results(option)) {
228
+ return '';
229
+ }
230
+ classes = [];
231
+ if (!option.disabled && !(option.selected && this.is_multiple)) {
232
+ classes.push("active-result");
233
+ }
234
+ if (option.disabled && !(option.selected && this.is_multiple)) {
235
+ classes.push("disabled-result");
236
+ }
237
+ if (option.selected) {
238
+ classes.push("result-selected");
239
+ }
240
+ if (option.group_array_index != null) {
241
+ classes.push("group-option");
242
+ }
243
+ if (option.classes !== "") {
244
+ classes.push(option.classes);
245
+ }
246
+ option_el = document.createElement("li");
247
+ option_el.className = classes.join(" ");
248
+ option_el.style.cssText = option.style;
249
+ option_el.setAttribute("data-option-array-index", option.array_index);
250
+ option_el.innerHTML = option.search_text;
251
+ return this.outerHTML(option_el);
252
+ };
253
+
254
+ AbstractChosen.prototype.result_add_group = function(group) {
255
+ var group_el;
256
+ if (!(group.search_match || group.group_match)) {
257
+ return '';
258
+ }
259
+ if (!(group.active_options > 0)) {
260
+ return '';
261
+ }
262
+ group_el = document.createElement("li");
263
+ group_el.className = "group-result";
264
+ group_el.innerHTML = group.search_text;
265
+ return this.outerHTML(group_el);
266
+ };
267
+
268
+ AbstractChosen.prototype.results_update_field = function() {
269
+ this.set_default_text();
270
+ if (!this.is_multiple) {
271
+ this.results_reset_cleanup();
272
+ }
273
+ this.result_clear_highlight();
274
+ this.results_build();
275
+ if (this.results_showing) {
276
+ return this.winnow_results();
277
+ }
278
+ };
279
+
280
+ AbstractChosen.prototype.reset_single_select_options = function() {
281
+ var result, _i, _len, _ref, _results;
282
+ _ref = this.results_data;
283
+ _results = [];
284
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
285
+ result = _ref[_i];
286
+ if (result.selected) {
287
+ _results.push(result.selected = false);
288
+ } else {
289
+ _results.push(void 0);
290
+ }
291
+ }
292
+ return _results;
293
+ };
294
+
295
+ AbstractChosen.prototype.results_toggle = function() {
296
+ if (this.results_showing) {
297
+ return this.results_hide();
298
+ } else {
299
+ return this.results_show();
300
+ }
301
+ };
302
+
303
+ AbstractChosen.prototype.results_search = function(evt) {
304
+ if (this.results_showing) {
305
+ return this.winnow_results();
306
+ } else {
307
+ return this.results_show();
308
+ }
309
+ };
310
+
311
+ AbstractChosen.prototype.winnow_results = function() {
312
+ var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
313
+ this.no_results_clear();
314
+ results = 0;
315
+ searchText = this.get_search_text();
316
+ escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
317
+ regexAnchor = this.search_contains ? "" : "^";
318
+ regex = new RegExp(regexAnchor + escapedSearchText, 'i');
319
+ zregex = new RegExp(escapedSearchText, 'i');
320
+ _ref = this.results_data;
321
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
322
+ option = _ref[_i];
323
+ option.search_match = false;
324
+ results_group = null;
325
+ if (this.include_option_in_results(option)) {
326
+ if (option.group) {
327
+ option.group_match = false;
328
+ option.active_options = 0;
329
+ }
330
+ if ((option.group_array_index != null) && this.results_data[option.group_array_index]) {
331
+ results_group = this.results_data[option.group_array_index];
332
+ if (results_group.active_options === 0 && results_group.search_match) {
333
+ results += 1;
334
+ }
335
+ results_group.active_options += 1;
336
+ }
337
+ if (!(option.group && !this.group_search)) {
338
+ option.search_text = option.group ? option.label : option.html;
339
+ option.search_match = this.search_string_match(option.search_text, regex);
340
+ if (option.search_match && !option.group) {
341
+ results += 1;
342
+ }
343
+ if (option.search_match) {
344
+ if (searchText.length) {
345
+ startpos = option.search_text.search(zregex);
346
+ text = option.search_text.substr(0, startpos + searchText.length) + '</em>' + option.search_text.substr(startpos + searchText.length);
347
+ option.search_text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
348
+ }
349
+ if (results_group != null) {
350
+ results_group.group_match = true;
351
+ }
352
+ } else if ((option.group_array_index != null) && this.results_data[option.group_array_index].search_match) {
353
+ option.search_match = true;
354
+ }
355
+ }
356
+ }
357
+ }
358
+ this.result_clear_highlight();
359
+ if (results < 1 && searchText.length) {
360
+ this.update_results_content("");
361
+ return this.no_results(searchText);
362
+ } else {
363
+ this.update_results_content(this.results_option_build());
364
+ return this.winnow_results_set_highlight();
365
+ }
366
+ };
367
+
368
+ AbstractChosen.prototype.search_string_match = function(search_string, regex) {
369
+ var part, parts, _i, _len;
370
+ if (regex.test(search_string)) {
371
+ return true;
372
+ } else if (this.enable_split_word_search && (search_string.indexOf(" ") >= 0 || search_string.indexOf("[") === 0)) {
373
+ parts = search_string.replace(/\[|\]/g, "").split(" ");
374
+ if (parts.length) {
375
+ for (_i = 0, _len = parts.length; _i < _len; _i++) {
376
+ part = parts[_i];
377
+ if (regex.test(part)) {
378
+ return true;
379
+ }
380
+ }
381
+ }
382
+ }
383
+ };
384
+
385
+ AbstractChosen.prototype.choices_count = function() {
386
+ var option, _i, _len, _ref;
387
+ if (this.selected_option_count != null) {
388
+ return this.selected_option_count;
389
+ }
390
+ this.selected_option_count = 0;
391
+ _ref = this.form_field.options;
392
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
393
+ option = _ref[_i];
394
+ if (option.selected) {
395
+ this.selected_option_count += 1;
396
+ }
397
+ }
398
+ return this.selected_option_count;
399
+ };
400
+
401
+ AbstractChosen.prototype.choices_click = function(evt) {
402
+ evt.preventDefault();
403
+ if (!(this.results_showing || this.is_disabled)) {
404
+ return this.results_show();
405
+ }
406
+ };
407
+
408
+ AbstractChosen.prototype.keyup_checker = function(evt) {
409
+ var stroke, _ref;
410
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
411
+ this.search_field_scale();
412
+ switch (stroke) {
413
+ case 8:
414
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
415
+ return this.keydown_backstroke();
416
+ } else if (!this.pending_backstroke) {
417
+ this.result_clear_highlight();
418
+ return this.results_search();
419
+ }
420
+ break;
421
+ case 13:
422
+ evt.preventDefault();
423
+ if (this.results_showing) {
424
+ return this.result_select(evt);
425
+ }
426
+ break;
427
+ case 27:
428
+ if (this.results_showing) {
429
+ this.results_hide();
430
+ }
431
+ return true;
432
+ case 9:
433
+ case 38:
434
+ case 40:
435
+ case 16:
436
+ case 91:
437
+ case 17:
438
+ break;
439
+ default:
440
+ return this.results_search();
441
+ }
442
+ };
443
+
444
+ AbstractChosen.prototype.clipboard_event_checker = function(evt) {
445
+ var _this = this;
446
+ return setTimeout((function() {
447
+ return _this.results_search();
448
+ }), 50);
449
+ };
450
+
451
+ AbstractChosen.prototype.container_width = function() {
452
+ if (this.options.width != null) {
453
+ return this.options.width;
454
+ } else {
455
+ return "" + this.form_field.offsetWidth + "px";
456
+ }
457
+ };
458
+
459
+ AbstractChosen.prototype.include_option_in_results = function(option) {
460
+ if (this.is_multiple && (!this.display_selected_options && option.selected)) {
461
+ return false;
462
+ }
463
+ if (!this.display_disabled_options && option.disabled) {
464
+ return false;
465
+ }
466
+ if (option.empty) {
467
+ return false;
468
+ }
469
+ return true;
470
+ };
471
+
472
+ AbstractChosen.prototype.search_results_touchstart = function(evt) {
473
+ this.touch_started = true;
474
+ return this.search_results_mouseover(evt);
475
+ };
476
+
477
+ AbstractChosen.prototype.search_results_touchmove = function(evt) {
478
+ this.touch_started = false;
479
+ return this.search_results_mouseout(evt);
480
+ };
481
+
482
+ AbstractChosen.prototype.search_results_touchend = function(evt) {
483
+ if (this.touch_started) {
484
+ return this.search_results_mouseup(evt);
485
+ }
486
+ };
487
+
488
+ AbstractChosen.prototype.outerHTML = function(element) {
489
+ var tmp;
490
+ if (element.outerHTML) {
491
+ return element.outerHTML;
492
+ }
493
+ tmp = document.createElement("div");
494
+ tmp.appendChild(element);
495
+ return tmp.innerHTML;
496
+ };
497
+
498
+ AbstractChosen.browser_is_supported = function() {
499
+ if (window.navigator.appName === "Microsoft Internet Explorer") {
500
+ return document.documentMode >= 8;
501
+ }
502
+ if (/iP(od|hone)/i.test(window.navigator.userAgent)) {
503
+ return false;
504
+ }
505
+ if (/Android/i.test(window.navigator.userAgent)) {
506
+ if (/Mobile/i.test(window.navigator.userAgent)) {
507
+ return false;
508
+ }
509
+ }
510
+ return true;
511
+ };
512
+
513
+ AbstractChosen.default_multiple_text = "Select Some Options";
514
+
515
+ AbstractChosen.default_single_text = "Select an Option";
516
+
517
+ AbstractChosen.default_no_result_text = "No results match";
518
+
519
+ return AbstractChosen;
520
+
521
+ })();
522
+
523
+ $ = jQuery;
524
+
525
+ $.fn.extend({
526
+ chosen: function(options) {
527
+ if (!AbstractChosen.browser_is_supported()) {
528
+ return this;
529
+ }
530
+ return this.each(function(input_field) {
531
+ var $this, chosen;
532
+ $this = $(this);
533
+ chosen = $this.data('chosen');
534
+ if (options === 'destroy' && chosen) {
535
+ chosen.destroy();
536
+ } else if (!chosen) {
537
+ $this.data('chosen', new Chosen(this, options));
538
+ }
539
+ });
540
+ }
541
+ });
542
+
543
+ Chosen = (function(_super) {
544
+ __extends(Chosen, _super);
545
+
546
+ function Chosen() {
547
+ _ref = Chosen.__super__.constructor.apply(this, arguments);
548
+ return _ref;
549
+ }
550
+
551
+ Chosen.prototype.setup = function() {
552
+ this.form_field_jq = $(this.form_field);
553
+ this.current_selectedIndex = this.form_field.selectedIndex;
554
+ return this.is_rtl = this.form_field_jq.hasClass("chosen-rtl");
555
+ };
556
+
557
+ Chosen.prototype.set_up_html = function() {
558
+ var container_classes, container_props;
559
+ container_classes = ["chosen-container"];
560
+ container_classes.push("chosen-container-" + (this.is_multiple ? "multi" : "single"));
561
+ if (this.inherit_select_classes && this.form_field.className) {
562
+ container_classes.push(this.form_field.className);
563
+ }
564
+ if (this.is_rtl) {
565
+ container_classes.push("chosen-rtl");
566
+ }
567
+ container_props = {
568
+ 'class': container_classes.join(' '),
569
+ 'style': "width: " + (this.container_width()) + ";",
570
+ 'title': this.form_field.title
571
+ };
572
+ if (this.form_field.id.length) {
573
+ container_props.id = this.form_field.id.replace(/[^\w]/g, '_') + "_chosen";
574
+ }
575
+ this.container = $("<div />", container_props);
576
+ if (this.is_multiple) {
577
+ this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
578
+ } else {
579
+ this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
580
+ }
581
+ this.form_field_jq.hide().after(this.container);
582
+ this.dropdown = this.container.find('div.chosen-drop').first();
583
+ this.search_field = this.container.find('input').first();
584
+ this.search_results = this.container.find('ul.chosen-results').first();
585
+ this.search_field_scale();
586
+ this.search_no_results = this.container.find('li.no-results').first();
587
+ if (this.is_multiple) {
588
+ this.search_choices = this.container.find('ul.chosen-choices').first();
589
+ this.search_container = this.container.find('li.search-field').first();
590
+ } else {
591
+ this.search_container = this.container.find('div.chosen-search').first();
592
+ this.selected_item = this.container.find('.chosen-single').first();
593
+ }
594
+ this.results_build();
595
+ this.set_tab_index();
596
+ this.set_label_behavior();
597
+ return this.form_field_jq.trigger("chosen:ready", {
598
+ chosen: this
599
+ });
600
+ };
601
+
602
+ Chosen.prototype.register_observers = function() {
603
+ var _this = this;
604
+ this.container.bind('mousedown.chosen', function(evt) {
605
+ _this.container_mousedown(evt);
606
+ });
607
+ this.container.bind('mouseup.chosen', function(evt) {
608
+ _this.container_mouseup(evt);
609
+ });
610
+ this.container.bind('mouseenter.chosen', function(evt) {
611
+ _this.mouse_enter(evt);
612
+ });
613
+ this.container.bind('mouseleave.chosen', function(evt) {
614
+ _this.mouse_leave(evt);
615
+ });
616
+ this.search_results.bind('mouseup.chosen', function(evt) {
617
+ _this.search_results_mouseup(evt);
618
+ });
619
+ this.search_results.bind('mouseover.chosen', function(evt) {
620
+ _this.search_results_mouseover(evt);
621
+ });
622
+ this.search_results.bind('mouseout.chosen', function(evt) {
623
+ _this.search_results_mouseout(evt);
624
+ });
625
+ this.search_results.bind('mousewheel.chosen DOMMouseScroll.chosen', function(evt) {
626
+ _this.search_results_mousewheel(evt);
627
+ });
628
+ this.search_results.bind('touchstart.chosen', function(evt) {
629
+ _this.search_results_touchstart(evt);
630
+ });
631
+ this.search_results.bind('touchmove.chosen', function(evt) {
632
+ _this.search_results_touchmove(evt);
633
+ });
634
+ this.search_results.bind('touchend.chosen', function(evt) {
635
+ _this.search_results_touchend(evt);
636
+ });
637
+ this.form_field_jq.bind("chosen:updated.chosen", function(evt) {
638
+ _this.results_update_field(evt);
639
+ });
640
+ this.form_field_jq.bind("chosen:activate.chosen", function(evt) {
641
+ _this.activate_field(evt);
642
+ });
643
+ this.form_field_jq.bind("chosen:open.chosen", function(evt) {
644
+ _this.container_mousedown(evt);
645
+ });
646
+ this.form_field_jq.bind("chosen:close.chosen", function(evt) {
647
+ _this.input_blur(evt);
648
+ });
649
+ this.search_field.bind('blur.chosen', function(evt) {
650
+ _this.input_blur(evt);
651
+ });
652
+ this.search_field.bind('keyup.chosen', function(evt) {
653
+ _this.keyup_checker(evt);
654
+ });
655
+ this.search_field.bind('keydown.chosen', function(evt) {
656
+ _this.keydown_checker(evt);
657
+ });
658
+ this.search_field.bind('focus.chosen', function(evt) {
659
+ _this.input_focus(evt);
660
+ });
661
+ this.search_field.bind('cut.chosen', function(evt) {
662
+ _this.clipboard_event_checker(evt);
663
+ });
664
+ this.search_field.bind('paste.chosen', function(evt) {
665
+ _this.clipboard_event_checker(evt);
666
+ });
667
+ if (this.is_multiple) {
668
+ return this.search_choices.bind('click.chosen', function(evt) {
669
+ _this.choices_click(evt);
670
+ });
671
+ } else {
672
+ return this.container.bind('click.chosen', function(evt) {
673
+ evt.preventDefault();
674
+ });
675
+ }
676
+ };
677
+
678
+ Chosen.prototype.destroy = function() {
679
+ $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
680
+ if (this.search_field[0].tabIndex) {
681
+ this.form_field_jq[0].tabIndex = this.search_field[0].tabIndex;
682
+ }
683
+ this.container.remove();
684
+ this.form_field_jq.removeData('chosen');
685
+ return this.form_field_jq.show();
686
+ };
687
+
688
+ Chosen.prototype.search_field_disabled = function() {
689
+ this.is_disabled = this.form_field_jq[0].disabled;
690
+ if (this.is_disabled) {
691
+ this.container.addClass('chosen-disabled');
692
+ this.search_field[0].disabled = true;
693
+ if (!this.is_multiple) {
694
+ this.selected_item.unbind("focus.chosen", this.activate_action);
695
+ }
696
+ return this.close_field();
697
+ } else {
698
+ this.container.removeClass('chosen-disabled');
699
+ this.search_field[0].disabled = false;
700
+ if (!this.is_multiple) {
701
+ return this.selected_item.bind("focus.chosen", this.activate_action);
702
+ }
703
+ }
704
+ };
705
+
706
+ Chosen.prototype.container_mousedown = function(evt) {
707
+ if (!this.is_disabled) {
708
+ if (evt && evt.type === "mousedown" && !this.results_showing) {
709
+ evt.preventDefault();
710
+ }
711
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
712
+ if (!this.active_field) {
713
+ if (this.is_multiple) {
714
+ this.search_field.val("");
715
+ }
716
+ $(this.container[0].ownerDocument).bind('click.chosen', this.click_test_action);
717
+ this.results_show();
718
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chosen-single").length)) {
719
+ evt.preventDefault();
720
+ this.results_toggle();
721
+ }
722
+ return this.activate_field();
723
+ }
724
+ }
725
+ };
726
+
727
+ Chosen.prototype.container_mouseup = function(evt) {
728
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
729
+ return this.results_reset(evt);
730
+ }
731
+ };
732
+
733
+ Chosen.prototype.search_results_mousewheel = function(evt) {
734
+ var delta;
735
+ if (evt.originalEvent) {
736
+ delta = -evt.originalEvent.wheelDelta || evt.originalEvent.detail;
737
+ }
738
+ if (delta != null) {
739
+ evt.preventDefault();
740
+ if (evt.type === 'DOMMouseScroll') {
741
+ delta = delta * 40;
742
+ }
743
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
744
+ }
745
+ };
746
+
747
+ Chosen.prototype.blur_test = function(evt) {
748
+ if (!this.active_field && this.container.hasClass("chosen-container-active")) {
749
+ return this.close_field();
750
+ }
751
+ };
752
+
753
+ Chosen.prototype.close_field = function() {
754
+ $(this.container[0].ownerDocument).unbind("click.chosen", this.click_test_action);
755
+ this.active_field = false;
756
+ this.results_hide();
757
+ this.container.removeClass("chosen-container-active");
758
+ this.clear_backstroke();
759
+ this.show_search_field_default();
760
+ return this.search_field_scale();
761
+ };
762
+
763
+ Chosen.prototype.activate_field = function() {
764
+ this.container.addClass("chosen-container-active");
765
+ this.active_field = true;
766
+ this.search_field.val(this.search_field.val());
767
+ return this.search_field.focus();
768
+ };
769
+
770
+ Chosen.prototype.test_active_click = function(evt) {
771
+ var active_container;
772
+ active_container = $(evt.target).closest('.chosen-container');
773
+ if (active_container.length && this.container[0] === active_container[0]) {
774
+ return this.active_field = true;
775
+ } else {
776
+ return this.close_field();
777
+ }
778
+ };
779
+
780
+ Chosen.prototype.results_build = function() {
781
+ this.parsing = true;
782
+ this.selected_option_count = null;
783
+ this.results_data = SelectParser.select_to_array(this.form_field);
784
+ if (this.is_multiple) {
785
+ this.search_choices.find("li.search-choice").remove();
786
+ } else if (!this.is_multiple) {
787
+ this.single_set_selected_text();
788
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
789
+ this.search_field[0].readOnly = true;
790
+ this.container.addClass("chosen-container-single-nosearch");
791
+ } else {
792
+ this.search_field[0].readOnly = false;
793
+ this.container.removeClass("chosen-container-single-nosearch");
794
+ }
795
+ }
796
+ this.update_results_content(this.results_option_build({
797
+ first: true
798
+ }));
799
+ this.search_field_disabled();
800
+ this.show_search_field_default();
801
+ this.search_field_scale();
802
+ return this.parsing = false;
803
+ };
804
+
805
+ Chosen.prototype.result_do_highlight = function(el) {
806
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
807
+ if (el.length) {
808
+ this.result_clear_highlight();
809
+ this.result_highlight = el;
810
+ this.result_highlight.addClass("highlighted");
811
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
812
+ visible_top = this.search_results.scrollTop();
813
+ visible_bottom = maxHeight + visible_top;
814
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
815
+ high_bottom = high_top + this.result_highlight.outerHeight();
816
+ if (high_bottom >= visible_bottom) {
817
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
818
+ } else if (high_top < visible_top) {
819
+ return this.search_results.scrollTop(high_top);
820
+ }
821
+ }
822
+ };
823
+
824
+ Chosen.prototype.result_clear_highlight = function() {
825
+ if (this.result_highlight) {
826
+ this.result_highlight.removeClass("highlighted");
827
+ }
828
+ return this.result_highlight = null;
829
+ };
830
+
831
+ Chosen.prototype.results_show = function() {
832
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
833
+ this.form_field_jq.trigger("chosen:maxselected", {
834
+ chosen: this
835
+ });
836
+ return false;
837
+ }
838
+ this.container.addClass("chosen-with-drop");
839
+ this.results_showing = true;
840
+ this.search_field.focus();
841
+ this.search_field.val(this.search_field.val());
842
+ this.winnow_results();
843
+ return this.form_field_jq.trigger("chosen:showing_dropdown", {
844
+ chosen: this
845
+ });
846
+ };
847
+
848
+ Chosen.prototype.update_results_content = function(content) {
849
+ return this.search_results.html(content);
850
+ };
851
+
852
+ Chosen.prototype.results_hide = function() {
853
+ if (this.results_showing) {
854
+ this.result_clear_highlight();
855
+ this.container.removeClass("chosen-with-drop");
856
+ this.form_field_jq.trigger("chosen:hiding_dropdown", {
857
+ chosen: this
858
+ });
859
+ }
860
+ return this.results_showing = false;
861
+ };
862
+
863
+ Chosen.prototype.set_tab_index = function(el) {
864
+ var ti;
865
+ if (this.form_field.tabIndex) {
866
+ ti = this.form_field.tabIndex;
867
+ this.form_field.tabIndex = -1;
868
+ return this.search_field[0].tabIndex = ti;
869
+ }
870
+ };
871
+
872
+ Chosen.prototype.set_label_behavior = function() {
873
+ var _this = this;
874
+ this.form_field_label = this.form_field_jq.parents("label");
875
+ if (!this.form_field_label.length && this.form_field.id.length) {
876
+ this.form_field_label = $("label[for='" + this.form_field.id + "']");
877
+ }
878
+ if (this.form_field_label.length > 0) {
879
+ return this.form_field_label.bind('click.chosen', function(evt) {
880
+ if (_this.is_multiple) {
881
+ return _this.container_mousedown(evt);
882
+ } else {
883
+ return _this.activate_field();
884
+ }
885
+ });
886
+ }
887
+ };
888
+
889
+ Chosen.prototype.show_search_field_default = function() {
890
+ if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
891
+ this.search_field.val(this.default_text);
892
+ return this.search_field.addClass("default");
893
+ } else {
894
+ this.search_field.val("");
895
+ return this.search_field.removeClass("default");
896
+ }
897
+ };
898
+
899
+ Chosen.prototype.search_results_mouseup = function(evt) {
900
+ var target;
901
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
902
+ if (target.length) {
903
+ this.result_highlight = target;
904
+ this.result_select(evt);
905
+ return this.search_field.focus();
906
+ }
907
+ };
908
+
909
+ Chosen.prototype.search_results_mouseover = function(evt) {
910
+ var target;
911
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
912
+ if (target) {
913
+ return this.result_do_highlight(target);
914
+ }
915
+ };
916
+
917
+ Chosen.prototype.search_results_mouseout = function(evt) {
918
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
919
+ return this.result_clear_highlight();
920
+ }
921
+ };
922
+
923
+ Chosen.prototype.choice_build = function(item) {
924
+ var choice, close_link,
925
+ _this = this;
926
+ choice = $('<li />', {
927
+ "class": "search-choice"
928
+ }).html("<span>" + item.html + "</span>");
929
+ if (item.disabled) {
930
+ choice.addClass('search-choice-disabled');
931
+ } else {
932
+ close_link = $('<a />', {
933
+ "class": 'search-choice-close',
934
+ 'data-option-array-index': item.array_index
935
+ });
936
+ close_link.bind('click.chosen', function(evt) {
937
+ return _this.choice_destroy_link_click(evt);
938
+ });
939
+ choice.append(close_link);
940
+ }
941
+ return this.search_container.before(choice);
942
+ };
943
+
944
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
945
+ evt.preventDefault();
946
+ evt.stopPropagation();
947
+ if (!this.is_disabled) {
948
+ return this.choice_destroy($(evt.target));
949
+ }
950
+ };
951
+
952
+ Chosen.prototype.choice_destroy = function(link) {
953
+ if (this.result_deselect(link[0].getAttribute("data-option-array-index"))) {
954
+ this.show_search_field_default();
955
+ if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
956
+ this.results_hide();
957
+ }
958
+ link.parents('li').first().remove();
959
+ return this.search_field_scale();
960
+ }
961
+ };
962
+
963
+ Chosen.prototype.results_reset = function() {
964
+ this.reset_single_select_options();
965
+ this.form_field.options[0].selected = true;
966
+ this.single_set_selected_text();
967
+ this.show_search_field_default();
968
+ this.results_reset_cleanup();
969
+ this.form_field_jq.trigger("change");
970
+ if (this.active_field) {
971
+ return this.results_hide();
972
+ }
973
+ };
974
+
975
+ Chosen.prototype.results_reset_cleanup = function() {
976
+ this.current_selectedIndex = this.form_field.selectedIndex;
977
+ return this.selected_item.find("abbr").remove();
978
+ };
979
+
980
+ Chosen.prototype.result_select = function(evt) {
981
+ var high, item;
982
+ if (this.result_highlight) {
983
+ high = this.result_highlight;
984
+ this.result_clear_highlight();
985
+ if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
986
+ this.form_field_jq.trigger("chosen:maxselected", {
987
+ chosen: this
988
+ });
989
+ return false;
990
+ }
991
+ if (this.is_multiple) {
992
+ high.removeClass("active-result");
993
+ } else {
994
+ this.reset_single_select_options();
995
+ }
996
+ item = this.results_data[high[0].getAttribute("data-option-array-index")];
997
+ item.selected = true;
998
+ this.form_field.options[item.options_index].selected = true;
999
+ this.selected_option_count = null;
1000
+ if (this.is_multiple) {
1001
+ this.choice_build(item);
1002
+ } else {
1003
+ this.single_set_selected_text(item.text);
1004
+ }
1005
+ if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
1006
+ this.results_hide();
1007
+ }
1008
+ this.search_field.val("");
1009
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
1010
+ this.form_field_jq.trigger("change", {
1011
+ 'selected': this.form_field.options[item.options_index].value
1012
+ });
1013
+ }
1014
+ this.current_selectedIndex = this.form_field.selectedIndex;
1015
+ return this.search_field_scale();
1016
+ }
1017
+ };
1018
+
1019
+ Chosen.prototype.single_set_selected_text = function(text) {
1020
+ if (text == null) {
1021
+ text = this.default_text;
1022
+ }
1023
+ if (text === this.default_text) {
1024
+ this.selected_item.addClass("chosen-default");
1025
+ } else {
1026
+ this.single_deselect_control_build();
1027
+ this.selected_item.removeClass("chosen-default");
1028
+ }
1029
+ return this.selected_item.find("span").text(text);
1030
+ };
1031
+
1032
+ Chosen.prototype.result_deselect = function(pos) {
1033
+ var result_data;
1034
+ result_data = this.results_data[pos];
1035
+ if (!this.form_field.options[result_data.options_index].disabled) {
1036
+ result_data.selected = false;
1037
+ this.form_field.options[result_data.options_index].selected = false;
1038
+ this.selected_option_count = null;
1039
+ this.result_clear_highlight();
1040
+ if (this.results_showing) {
1041
+ this.winnow_results();
1042
+ }
1043
+ this.form_field_jq.trigger("change", {
1044
+ deselected: this.form_field.options[result_data.options_index].value
1045
+ });
1046
+ this.search_field_scale();
1047
+ return true;
1048
+ } else {
1049
+ return false;
1050
+ }
1051
+ };
1052
+
1053
+ Chosen.prototype.single_deselect_control_build = function() {
1054
+ if (!this.allow_single_deselect) {
1055
+ return;
1056
+ }
1057
+ if (!this.selected_item.find("abbr").length) {
1058
+ this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
1059
+ }
1060
+ return this.selected_item.addClass("chosen-single-with-deselect");
1061
+ };
1062
+
1063
+ Chosen.prototype.get_search_text = function() {
1064
+ if (this.search_field.val() === this.default_text) {
1065
+ return "";
1066
+ } else {
1067
+ return $('<div/>').text($.trim(this.search_field.val())).html();
1068
+ }
1069
+ };
1070
+
1071
+ Chosen.prototype.winnow_results_set_highlight = function() {
1072
+ var do_high, selected_results;
1073
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
1074
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
1075
+ if (do_high != null) {
1076
+ return this.result_do_highlight(do_high);
1077
+ }
1078
+ };
1079
+
1080
+ Chosen.prototype.no_results = function(terms) {
1081
+ var no_results_html;
1082
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
1083
+ no_results_html.find("span").first().html(terms);
1084
+ this.search_results.append(no_results_html);
1085
+ return this.form_field_jq.trigger("chosen:no_results", {
1086
+ chosen: this
1087
+ });
1088
+ };
1089
+
1090
+ Chosen.prototype.no_results_clear = function() {
1091
+ return this.search_results.find(".no-results").remove();
1092
+ };
1093
+
1094
+ Chosen.prototype.keydown_arrow = function() {
1095
+ var next_sib;
1096
+ if (this.results_showing && this.result_highlight) {
1097
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
1098
+ if (next_sib) {
1099
+ return this.result_do_highlight(next_sib);
1100
+ }
1101
+ } else {
1102
+ return this.results_show();
1103
+ }
1104
+ };
1105
+
1106
+ Chosen.prototype.keyup_arrow = function() {
1107
+ var prev_sibs;
1108
+ if (!this.results_showing && !this.is_multiple) {
1109
+ return this.results_show();
1110
+ } else if (this.result_highlight) {
1111
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
1112
+ if (prev_sibs.length) {
1113
+ return this.result_do_highlight(prev_sibs.first());
1114
+ } else {
1115
+ if (this.choices_count() > 0) {
1116
+ this.results_hide();
1117
+ }
1118
+ return this.result_clear_highlight();
1119
+ }
1120
+ }
1121
+ };
1122
+
1123
+ Chosen.prototype.keydown_backstroke = function() {
1124
+ var next_available_destroy;
1125
+ if (this.pending_backstroke) {
1126
+ this.choice_destroy(this.pending_backstroke.find("a").first());
1127
+ return this.clear_backstroke();
1128
+ } else {
1129
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
1130
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
1131
+ this.pending_backstroke = next_available_destroy;
1132
+ if (this.single_backstroke_delete) {
1133
+ return this.keydown_backstroke();
1134
+ } else {
1135
+ return this.pending_backstroke.addClass("search-choice-focus");
1136
+ }
1137
+ }
1138
+ }
1139
+ };
1140
+
1141
+ Chosen.prototype.clear_backstroke = function() {
1142
+ if (this.pending_backstroke) {
1143
+ this.pending_backstroke.removeClass("search-choice-focus");
1144
+ }
1145
+ return this.pending_backstroke = null;
1146
+ };
1147
+
1148
+ Chosen.prototype.keydown_checker = function(evt) {
1149
+ var stroke, _ref1;
1150
+ stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
1151
+ this.search_field_scale();
1152
+ if (stroke !== 8 && this.pending_backstroke) {
1153
+ this.clear_backstroke();
1154
+ }
1155
+ switch (stroke) {
1156
+ case 8:
1157
+ this.backstroke_length = this.search_field.val().length;
1158
+ break;
1159
+ case 9:
1160
+ if (this.results_showing && !this.is_multiple) {
1161
+ this.result_select(evt);
1162
+ }
1163
+ this.mouse_on_container = false;
1164
+ break;
1165
+ case 13:
1166
+ evt.preventDefault();
1167
+ break;
1168
+ case 38:
1169
+ evt.preventDefault();
1170
+ this.keyup_arrow();
1171
+ break;
1172
+ case 40:
1173
+ evt.preventDefault();
1174
+ this.keydown_arrow();
1175
+ break;
1176
+ }
1177
+ };
1178
+
1179
+ Chosen.prototype.search_field_scale = function() {
1180
+ var div, f_width, h, style, style_block, styles, w, _i, _len;
1181
+ if (this.is_multiple) {
1182
+ h = 0;
1183
+ w = 0;
1184
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
1185
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
1186
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
1187
+ style = styles[_i];
1188
+ style_block += style + ":" + this.search_field.css(style) + ";";
1189
+ }
1190
+ div = $('<div />', {
1191
+ 'style': style_block
1192
+ });
1193
+ div.text(this.search_field.val());
1194
+ $('body').append(div);
1195
+ w = div.width() + 25;
1196
+ div.remove();
1197
+ f_width = this.container.outerWidth();
1198
+ if (w > f_width - 10) {
1199
+ w = f_width - 10;
1200
+ }
1201
+ return this.search_field.css({
1202
+ 'width': w + 'px'
1203
+ });
1204
+ }
1205
+ };
1206
+
1207
+ return Chosen;
1208
+
1209
+ })(AbstractChosen);
1210
+
1211
+ }).call(this);
admin/assets/js/chosen/chosen.jquery.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /* Chosen v1.1.0 | (c) 2011-2013 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
2
+ !function(){var a,AbstractChosen,Chosen,SelectParser,b,c={}.hasOwnProperty,d=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),children:0,disabled:a.disabled}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&amp;"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(c.text));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,this.outerHTML(c)):"":""},AbstractChosen.prototype.result_add_group=function(a){var b;return a.search_match||a.group_match?a.active_options>0?(b=document.createElement("li"),b.className="group-result",b.innerHTML=a.search_text,this.outerHTML(b)):"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l,m;for(this.no_results_clear(),e=0,g=this.get_search_text(),a=g.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),d=this.search_contains?"":"^",c=new RegExp(d+a,"i"),j=new RegExp(a,"i"),m=this.results_data,k=0,l=m.length;l>k;k++)b=m[k],b.search_match=!1,f=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(f=this.results_data[b.group_array_index],0===f.active_options&&f.search_match&&(e+=1),f.active_options+=1),(!b.group||this.group_search)&&(b.search_text=b.group?b.label:b.html,b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(e+=1),b.search_match?(g.length&&(h=b.search_text.search(j),i=b.search_text.substr(0,h+g.length)+"</em>"+b.search_text.substr(h+g.length),b.search_text=i.substr(0,h)+"<em>"+i.substr(h)),null!=f&&(f.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>e&&g.length?(this.update_results_content(""),this.no_results(g)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(){var a=this;return setTimeout(function(){return a.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),a=jQuery,a.fn.extend({chosen:function(b){return AbstractChosen.browser_is_supported()?this.each(function(){var c,d;c=a(this),d=c.data("chosen"),"destroy"===b&&d?d.destroy():d||c.data("chosen",new Chosen(this,b))}):this}}),Chosen=function(c){function Chosen(){return b=Chosen.__super__.constructor.apply(this,arguments)}return d(Chosen,c),Chosen.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},Chosen.prototype.set_up_html=function(){var b,c;return b=["chosen-container"],b.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&b.push(this.form_field.className),this.is_rtl&&b.push("chosen-rtl"),c={"class":b.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(c.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=a("<div />",c),this.is_multiple?this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="'+this.default_text+'" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'):this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>'+this.default_text+'</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field_jq.trigger("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.bind("mousedown.chosen",function(b){a.container_mousedown(b)}),this.container.bind("mouseup.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mouseenter.chosen",function(b){a.mouse_enter(b)}),this.container.bind("mouseleave.chosen",function(b){a.mouse_leave(b)}),this.search_results.bind("mouseup.chosen",function(b){a.search_results_mouseup(b)}),this.search_results.bind("mouseover.chosen",function(b){a.search_results_mouseover(b)}),this.search_results.bind("mouseout.chosen",function(b){a.search_results_mouseout(b)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(b){a.search_results_mousewheel(b)}),this.search_results.bind("touchstart.chosen",function(b){a.search_results_touchstart(b)}),this.search_results.bind("touchmove.chosen",function(b){a.search_results_touchmove(b)}),this.search_results.bind("touchend.chosen",function(b){a.search_results_touchend(b)}),this.form_field_jq.bind("chosen:updated.chosen",function(b){a.results_update_field(b)}),this.form_field_jq.bind("chosen:activate.chosen",function(b){a.activate_field(b)}),this.form_field_jq.bind("chosen:open.chosen",function(b){a.container_mousedown(b)}),this.form_field_jq.bind("chosen:close.chosen",function(b){a.input_blur(b)}),this.search_field.bind("blur.chosen",function(b){a.input_blur(b)}),this.search_field.bind("keyup.chosen",function(b){a.keyup_checker(b)}),this.search_field.bind("keydown.chosen",function(b){a.keydown_checker(b)}),this.search_field.bind("focus.chosen",function(b){a.input_focus(b)}),this.search_field.bind("cut.chosen",function(b){a.clipboard_event_checker(b)}),this.search_field.bind("paste.chosen",function(b){a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.bind("click.chosen",function(b){a.choices_click(b)}):this.container.bind("click.chosen",function(a){a.preventDefault()})},Chosen.prototype.destroy=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},Chosen.prototype.container_mousedown=function(b){return this.is_disabled||(b&&"mousedown"===b.type&&!this.results_showing&&b.preventDefault(),null!=b&&a(b.target).hasClass("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!b||a(b.target)[0]!==this.selected_item[0]&&!a(b.target).parents("a.chosen-single").length||(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return a.originalEvent&&(b=-a.originalEvent.wheelDelta||a.originalEvent.detail),null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop(b+this.search_results.scrollTop())):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClass("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},Chosen.prototype.test_active_click=function(b){var c;return c=a(b.target).closest(".chosen-container"),c.length&&this.container[0]===c[0]?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){if(this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight(),b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(f>c)return this.search_results.scrollTop(c)}},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results(),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.html(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var b=this;return this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=a("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0?this.form_field_label.bind("click.chosen",function(a){return b.is_multiple?b.container_mousedown(a):b.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},Chosen.prototype.search_results_mouseup=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c.length?(this.result_highlight=c,this.result_select(b),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c?this.result_do_highlight(c):void 0},Chosen.prototype.search_results_mouseout=function(b){return a(b.target).hasClass("active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(b){var c,d,e=this;return c=a("<li />",{"class":"search-choice"}).html("<span>"+b.html+"</span>"),b.disabled?c.addClass("search-choice-disabled"):(d=a("<a />",{"class":"search-choice-close","data-option-array-index":b.array_index}),d.bind("click.chosen",function(a){return e.choice_destroy_link_click(a)}),c.append(d)),this.search_container.before(c)},Chosen.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),b.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a(b.target))},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a[0].getAttribute("data-option-array-index"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),a.parents("li").first().remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClass("active-result"):this.reset_single_select_options(),c=this.results_data[b[0].getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(c.text),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[c.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").text(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[b.options_index].value}),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.find("abbr").length||this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>'),this.selected_item.addClass("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return this.search_field.val()===this.default_text?"":a("<div/>").text(a.trim(this.search_field.val())).html()},Chosen.prototype.winnow_results_set_highlight=function(){var a,b;return b=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),a=b.length?b.first():this.search_results.find(".active-result").first(),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(b){var c;return c=a('<li class="no-results">'+this.results_none_found+' "<span></span>"</li>'),c.find("span").first().html(b),this.search_results.append(c),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a;return this.results_showing||this.is_multiple?this.result_highlight?(a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(a=this.search_container.siblings("li.search-choice").last(),a.length&&!a.hasClass("search-choice-disabled")?(this.pending_backstroke=a,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){for(d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],i=0,j=g.length;j>i;i++)e=g[i],f+=e+":"+this.search_field.css(e)+";";return b=a("<div />",{style:f}),b.text(this.search_field.val()),a("body").append(b),h=b.width()+25,b.remove(),c=this.container.outerWidth(),h>c-10&&(h=c-10),this.search_field.css({width:h+"px"})}},Chosen}(AbstractChosen)}.call(this);
admin/assets/js/chosen/chosen.min.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* Chosen v1.1.0 | (c) 2011-2013 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
2
+
3
+ .chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;*display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:23px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(chosen-sprite.png) no-repeat 100% -20px;background:url(chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:5px;height:15px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#666;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;border:1px solid #aaa;border-radius:3px;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:transparent}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single-nosearch .chosen-search,.chosen-rtl .chosen-drop{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(chosen-sprite.png) no-repeat -30px -20px;background:url(chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-rtl .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-container-single .chosen-search input[type=text],.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background-image:url(chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}}
admin/assets/js/data-meta-boxes.js ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function ( $ ) {
2
+
3
+ // TABS
4
+ $('ul.a3-metabox-data-tabs').show();
5
+ $('div.a3-metabox-panel-wrap').each(function(){
6
+ $(this).find('div.a3-metabox-panel:not(:first)').hide();
7
+ });
8
+ $('ul.a3-metabox-data-tabs a').click(function(){
9
+ var panel_wrap = $(this).closest('div.a3-metabox-panel-wrap');
10
+ $('ul.a3-metabox-data-tabs li', panel_wrap).removeClass('active');
11
+ $(this).parent().addClass('active');
12
+ $('div.a3-metabox-panel', panel_wrap).hide();
13
+ $( $(this).attr('href') ).show();
14
+ return false;
15
+ });
16
+ $('ul.a3-metabox-data-tabs li:visible').eq(0).find('a').click();
17
+
18
+ // META BOXES - Open/close
19
+ $('.a3-metabox-wrapper').on('click', '.a3-metabox-item h3', function(event){
20
+ // If the user clicks on some form input inside the h3, like a select list (for variations), the box should not be toggled
21
+ if ($(event.target).filter(':input, option').length) return;
22
+ $( this ).parent( '.a3-metabox-item' ).toggleClass( 'closed' ).toggleClass( 'open' );
23
+ $(this).next('.a3-metabox-item-content').toggle();
24
+ })
25
+ .on('click', '.expand_all', function(event){
26
+ $(this).closest('.a3-metabox-wrapper').find('.a3-metabox-item').removeClass( 'closed' ).addClass( 'open' );
27
+ $(this).closest('.a3-metabox-wrapper').find('.a3-metabox-item > table').show();
28
+ return false;
29
+ })
30
+ .on('click', '.close_all', function(event){
31
+ $(this).closest('.a3-metabox-wrapper').find('.a3-metabox-item').removeClass( 'open' ).addClass( 'closed' );
32
+ $(this).closest('.a3-metabox-wrapper').find('.a3-metabox-item > table').hide();
33
+ return false;
34
+ });
35
+ $('.a3-metabox-item.closed').each(function(){
36
+ $(this).find('.a3-metabox-item-content').hide();
37
+ });
38
+
39
+ });
admin/assets/js/iphone-style-checkboxes.js ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Generated by CoffeeScript 1.6.2
2
+ (function($) {
3
+ (function() {
4
+ var iOSCheckbox, matched, userAgent,
5
+ __slice = [].slice;
6
+
7
+ if ($.browser == null) {
8
+ userAgent = navigator.userAgent || "";
9
+ jQuery.uaMatch = function(ua) {
10
+ var match;
11
+
12
+ ua = ua.toLowerCase();
13
+ match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+))?/.exec(ua) || [];
14
+ return {
15
+ browser: match[1] || "",
16
+ version: match[2] || "0"
17
+ };
18
+ };
19
+ matched = jQuery.uaMatch(userAgent);
20
+ jQuery.browser = {};
21
+ if (matched.browser) {
22
+ jQuery.browser[matched.browser] = true;
23
+ jQuery.browser.version = matched.version;
24
+ }
25
+ if (jQuery.browser.webkit) {
26
+ jQuery.browser.safari = true;
27
+ }
28
+ }
29
+
30
+ iOSCheckbox = (function() {
31
+ function iOSCheckbox(elem, options) {
32
+ var key, opts, value;
33
+
34
+ this.elem = $(elem);
35
+ opts = $.extend({}, iOSCheckbox.defaults, options);
36
+ for (key in opts) {
37
+ value = opts[key];
38
+ this[key] = value;
39
+ }
40
+ this.elem.data(this.dataName, this);
41
+ this.wrapCheckboxWithDivs();
42
+ this.attachEvents();
43
+ this.disableTextSelection();
44
+ this.calculateDimensions();
45
+ }
46
+
47
+ iOSCheckbox.prototype.calculateDimensions = function() {
48
+ if (this.resizeHandle) {
49
+ this.optionallyResize('handle');
50
+ }
51
+ if (this.resizeContainer) {
52
+ this.optionallyResize('container');
53
+ }
54
+ return this.initialPosition();
55
+ };
56
+
57
+ iOSCheckbox.prototype.isDisabled = function() {
58
+ if ( this.elem.is(':disabled') )
59
+ return true;
60
+ else if ( this.elem.attr('checkbox-disabled') == 'true' )
61
+ return true;
62
+ else
63
+ return false;
64
+ };
65
+
66
+ iOSCheckbox.prototype.wrapCheckboxWithDivs = function() {
67
+ this.elem.wrap("<div class='" + this.containerClass + "' />");
68
+ this.container = this.elem.parent();
69
+ this.offLabel = $("<label class='" + this.labelOffClass + "'>\n <span>" + this.uncheckedLabel + "</span>\n</label>").appendTo(this.container);
70
+ this.offSpan = this.offLabel.children('span');
71
+ this.onLabel = $("<label class='" + this.labelOnClass + "'>\n <span>" + this.checkedLabel + "</span>\n</label>").appendTo(this.container);
72
+ this.onSpan = this.onLabel.children('span');
73
+ return this.handle = $("<div class='" + this.handleClass + "'>\n <div class='" + this.handleRightClass + "'>\n <div class='" + this.handleCenterClass + "' />\n </div>\n</div>").appendTo(this.container).before("<span class='iPhoneCheckBeforeContainer'>&nbsp;</span><span class='iPhoneCheckAfterContainer'>&nbsp;</span>");
74
+ };
75
+
76
+ iOSCheckbox.prototype.disableTextSelection = function() {
77
+ if ($.browser.msie) {
78
+ return $([this.handle, this.offLabel, this.onLabel, this.container]).attr("unselectable", "on");
79
+ }
80
+ };
81
+
82
+ iOSCheckbox.prototype._getDimension = function(elem, dimension) {
83
+ if ($.fn.actual != null) {
84
+ return elem.actual(dimension);
85
+ } else {
86
+ return elem[dimension]();
87
+ }
88
+ };
89
+
90
+ iOSCheckbox.prototype.optionallyResize = function(mode) {
91
+ var newWidth, offLabelWidth, offSpan, onLabelWidth, onSpan;
92
+
93
+ onSpan = this.onLabel.find('span');
94
+ onLabelWidth = this._getDimension(onSpan, "width");
95
+ onLabelWidth += parseInt(onSpan.css('padding-left'), 10);
96
+ offSpan = this.offLabel.find('span');
97
+ offLabelWidth = this._getDimension(offSpan, "width");
98
+ offLabelWidth += parseInt(offSpan.css('padding-right'), 10);
99
+ if (mode === "container") {
100
+ newWidth = onLabelWidth > offLabelWidth ? onLabelWidth : offLabelWidth;
101
+ newWidth += this._getDimension(this.handle, "width") + this.handleMargin;
102
+ return this.container.css({
103
+ width: newWidth
104
+ });
105
+ } else {
106
+ newWidth = onLabelWidth > offLabelWidth ? onLabelWidth : offLabelWidth;
107
+ return this.handle.css({
108
+ width: newWidth
109
+ });
110
+ }
111
+ };
112
+
113
+ iOSCheckbox.prototype.onMouseDown = function(event) {
114
+ var x;
115
+
116
+ event.preventDefault();
117
+ if (this.isDisabled()) {
118
+ return;
119
+ }
120
+ x = event.pageX || event.originalEvent.changedTouches[0].pageX;
121
+ iOSCheckbox.currentlyClicking = this.handle;
122
+ iOSCheckbox.dragStartPosition = x;
123
+ return iOSCheckbox.handleLeftOffset = parseInt(this.handle.css('left'), 10) || 0;
124
+ };
125
+
126
+ iOSCheckbox.prototype.onDragMove = function(event, x) {
127
+ var newWidth, p, leftHandle;
128
+
129
+ if (iOSCheckbox.currentlyClicking !== this.handle) {
130
+ return;
131
+ }
132
+ p = (x + iOSCheckbox.handleLeftOffset - iOSCheckbox.dragStartPosition) / this.rightSide;
133
+ if (p < 0) {
134
+ p = 0;
135
+ }
136
+ if (p > 1) {
137
+ p = 1;
138
+ }
139
+ newWidth = p * this.rightSide;
140
+ leftHandle = newWidth;
141
+ if ( leftHandle == 0 ) leftHandle = -1;
142
+ this.handle.css({
143
+ left: leftHandle
144
+ });
145
+ this.onLabel.css({
146
+ width: newWidth + this.handleRadius
147
+ });
148
+ this.offSpan.css({
149
+ marginRight: -newWidth
150
+ });
151
+ return this.onSpan.css({
152
+ marginLeft: -(1 - p) * this.rightSide
153
+ });
154
+ };
155
+
156
+ iOSCheckbox.prototype.onDragEnd = function(event, x) {
157
+ var p;
158
+
159
+ if (iOSCheckbox.currentlyClicking !== this.handle) {
160
+ return;
161
+ }
162
+ if (this.isDisabled()) {
163
+ return;
164
+ }
165
+ if (iOSCheckbox.dragging) {
166
+ p = (x - iOSCheckbox.dragStartPosition) / this.rightSide;
167
+ this.elem.prop('checked', p >= 0.5);
168
+ } else {
169
+ this.elem.prop('checked', !this.elem.prop('checked'));
170
+ }
171
+ iOSCheckbox.currentlyClicking = null;
172
+ iOSCheckbox.dragging = null;
173
+ return this.didChange();
174
+ };
175
+
176
+ iOSCheckbox.prototype.refresh = function() {
177
+ return this.didChange();
178
+ };
179
+
180
+ iOSCheckbox.prototype.didChange = function() {
181
+ var new_left, leftHandle;
182
+
183
+ if (typeof this.onChange === "function") {
184
+ this.onChange(this.elem, this.elem.prop('checked'));
185
+ }
186
+ if (this.isDisabled()) {
187
+ this.container.addClass(this.disabledClass);
188
+ return false;
189
+ } else {
190
+ this.container.removeClass(this.disabledClass);
191
+ }
192
+ new_left = this.elem.prop('checked') ? this.rightSide : 0;
193
+ leftHandle = new_left;
194
+ if ( leftHandle == 0 ) leftHandle = -1;
195
+ this.handle.animate({
196
+ left: leftHandle
197
+ }, this.duration);
198
+ this.onLabel.animate({
199
+ width: new_left + this.handleRadius
200
+ }, this.duration);
201
+ this.offSpan.animate({
202
+ marginRight: -new_left
203
+ }, this.duration);
204
+ this.onSpan.animate({
205
+ marginLeft: new_left - this.rightSide
206
+ }, this.duration);
207
+ if (typeof this.onEnd === "function") {
208
+ this.onEnd(this.elem, this.elem.prop('checked'));
209
+ }
210
+ return true;
211
+ };
212
+
213
+ iOSCheckbox.prototype.attachEvents = function() {
214
+ var localMouseMove, localMouseUp, self;
215
+
216
+ self = this;
217
+ localMouseMove = function(event) {
218
+ return self.onGlobalMove.apply(self, arguments);
219
+ };
220
+ localMouseUp = function(event) {
221
+ self.onGlobalUp.apply(self, arguments);
222
+ $(document).unbind('mousemove touchmove', localMouseMove);
223
+ return $(document).unbind('mouseup touchend', localMouseUp);
224
+ };
225
+ this.elem.change(function() {
226
+ return self.refresh();
227
+ });
228
+ return this.container.bind('mousedown touchstart', function(event) {
229
+ self.onMouseDown.apply(self, arguments);
230
+ $(document).bind('mousemove touchmove', localMouseMove);
231
+ return $(document).bind('mouseup touchend', localMouseUp);
232
+ });
233
+ };
234
+
235
+ iOSCheckbox.prototype.initialPosition = function() {
236
+ var containerWidth, offset, leftHandle;
237
+
238
+ containerWidth = this._getDimension(this.container, "width");
239
+ this.offLabel.css({
240
+ width: containerWidth - this.containerRadius - 16
241
+ });
242
+ offset = this.containerRadius + 1;
243
+ if ($.browser.msie && $.browser.version < 7) {
244
+ offset -= 3;
245
+ }
246
+ this.rightSide = containerWidth - this._getDimension(this.handle, "width") - offset;
247
+ leftHandle = this.rightSide;
248
+ if ( leftHandle == 0 ) leftHandle = -1;
249
+ if (this.elem.is(':checked')) {
250
+ this.handle.css({
251
+ left: leftHandle
252
+ });
253
+ this.onLabel.css({
254
+ width: this.rightSide + this.handleRadius
255
+ });
256
+ this.offSpan.css({
257
+ marginRight: -this.rightSide
258
+ });
259
+ } else {
260
+ this.onLabel.css({
261
+ width: this.handleRadius
262
+ });
263
+ this.onSpan.css({
264
+ marginLeft: -this.rightSide
265
+ });
266
+ }
267
+ if (this.isDisabled()) {
268
+ return this.container.addClass(this.disabledClass);
269
+ }
270
+ };
271
+
272
+ iOSCheckbox.prototype.onGlobalMove = function(event) {
273
+ var x;
274
+
275
+ if (!(!this.isDisabled() && iOSCheckbox.currentlyClicking)) {
276
+ return;
277
+ }
278
+ event.preventDefault();
279
+ x = event.pageX || event.originalEvent.changedTouches[0].pageX;
280
+ if (!iOSCheckbox.dragging && (Math.abs(iOSCheckbox.dragStartPosition - x) > this.dragThreshold)) {
281
+ iOSCheckbox.dragging = true;
282
+ }
283
+ return this.onDragMove(event, x);
284
+ };
285
+
286
+ iOSCheckbox.prototype.onGlobalUp = function(event) {
287
+ var x;
288
+
289
+ if (!iOSCheckbox.currentlyClicking) {
290
+ return;
291
+ }
292
+ event.preventDefault();
293
+ x = event.pageX || event.originalEvent.changedTouches[0].pageX;
294
+ this.onDragEnd(event, x);
295
+ return false;
296
+ };
297
+
298
+ iOSCheckbox.defaults = {
299
+ duration: 200,
300
+ checkedLabel: 'ON',
301
+ uncheckedLabel: 'OFF',
302
+ resizeHandle: true,
303
+ resizeContainer: true,
304
+ disabledClass: 'iPhoneCheckDisabled',
305
+ containerClass: 'iPhoneCheckContainer',
306
+ labelOnClass: 'iPhoneCheckLabelOn',
307
+ labelOffClass: 'iPhoneCheckLabelOff',
308
+ handleClass: 'iPhoneCheckHandle',
309
+ handleCenterClass: 'iPhoneCheckHandleCenter',
310
+ handleRightClass: 'iPhoneCheckHandleRight',
311
+ dragThreshold: 5,
312
+ handleMargin: 15,
313
+ handleRadius: 4,
314
+ containerRadius: 5,
315
+ dataName: "iphoneStyle",
316
+ onChange: function() {},
317
+ onEnd: function() {}
318
+ };
319
+
320
+ return iOSCheckbox;
321
+
322
+ })();
323
+
324
+ $.iphoneStyle = this.iOSCheckbox = iOSCheckbox;
325
+
326
+ $.fn.iphoneStyle = function() {
327
+ var args, checkbox, dataName, existingControl, method, params, _i, _len, _ref, _ref1, _ref2, _ref3, _refradio;
328
+
329
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
330
+ dataName = (_ref = (_ref1 = args[0]) != null ? _ref1.dataName : void 0) != null ? _ref : iOSCheckbox.defaults.dataName;
331
+ _ref2 = this.filter(':checkbox');
332
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
333
+ checkbox = _ref2[_i];
334
+ existingControl = $(checkbox).data(dataName);
335
+ if (existingControl != null) {
336
+ method = args[0], params = 2 <= args.length ? __slice.call(args, 1) : [];
337
+ if ((_ref3 = existingControl[method]) != null) {
338
+ _ref3.apply(existingControl, params);
339
+ }
340
+ } else {
341
+ new iOSCheckbox(checkbox, args[0]);
342
+ }
343
+ }
344
+ _refradio = this.filter(':radio');
345
+ for (_i = 0, _len = _refradio.length; _i < _len; _i++) {
346
+ checkbox = _refradio[_i];
347
+ existingControl = $(checkbox).data(dataName);
348
+ if (existingControl != null) {
349
+ method = args[0], params = 2 <= args.length ? __slice.call(args, 1) : [];
350
+ if ((_ref3 = existingControl[method]) != null) {
351
+ _ref3.apply(existingControl, params);
352
+ }
353
+ } else {
354
+ new iOSCheckbox(checkbox, args[0]);
355
+ }
356
+ }
357
+ return this;
358
+ };
359
+
360
+ $.fn.iOSCheckbox = function(options) {
361
+ var opts;
362
+
363
+ if (options == null) {
364
+ options = {};
365
+ }
366
+ opts = $.extend({}, options, {
367
+ resizeHandle: false,
368
+ disabledClass: 'iOSCheckDisabled',
369
+ containerClass: 'iOSCheckContainer',
370
+ labelOnClass: 'iOSCheckLabelOn',
371
+ labelOffClass: 'iOSCheckLabelOff',
372
+ handleClass: 'iOSCheckHandle',
373
+ handleCenterClass: 'iOSCheckHandleCenter',
374
+ handleRightClass: 'iOSCheckHandleRight',
375
+ dataName: 'iOSCheckbox'
376
+ });
377
+ return this.iphoneStyle(opts);
378
+ };
379
+
380
+ }).call(this);
381
+ })(jQuery);
admin/assets/js/iphone-style-checkboxes.rtl.js ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Generated by CoffeeScript 1.6.2
2
+ (function($) {
3
+ (function() {
4
+ var iOSCheckbox, matched, userAgent,
5
+ __slice = [].slice;
6
+
7
+ if ($.browser == null) {
8
+ userAgent = navigator.userAgent || "";
9
+ jQuery.uaMatch = function(ua) {
10
+ var match;
11
+
12
+ ua = ua.toLowerCase();
13
+ match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+))?/.exec(ua) || [];
14
+ return {
15
+ browser: match[1] || "",
16
+ version: match[2] || "0"
17
+ };
18
+ };
19
+ matched = jQuery.uaMatch(userAgent);
20
+ jQuery.browser = {};
21
+ if (matched.browser) {
22
+ jQuery.browser[matched.browser] = true;
23
+ jQuery.browser.version = matched.version;
24
+ }
25
+ if (jQuery.browser.webkit) {
26
+ jQuery.browser.safari = true;
27
+ }
28
+ }
29
+
30
+ iOSCheckbox = (function() {
31
+ function iOSCheckbox(elem, options) {
32
+ var key, opts, value;
33
+
34
+ this.elem = $(elem);
35
+ opts = $.extend({}, iOSCheckbox.defaults, options);
36
+ for (key in opts) {
37
+ value = opts[key];
38
+ this[key] = value;
39
+ }
40
+ this.elem.data(this.dataName, this);
41
+ this.wrapCheckboxWithDivs();
42
+ this.attachEvents();
43
+ this.disableTextSelection();
44
+ this.calculateDimensions();
45
+ }
46
+
47
+ iOSCheckbox.prototype.calculateDimensions = function() {
48
+ if (this.resizeHandle) {
49
+ this.optionallyResize('handle');
50
+ }
51
+ if (this.resizeContainer) {
52
+ this.optionallyResize('container');
53
+ }
54
+ return this.initialPosition();
55
+ };
56
+
57
+ iOSCheckbox.prototype.isDisabled = function() {
58
+ if ( this.elem.is(':disabled') )
59
+ return true;
60
+ else if ( this.elem.attr('checkbox-disabled') == 'true' )
61
+ return true;
62
+ else
63
+ return false;
64
+ };
65
+
66
+ iOSCheckbox.prototype.wrapCheckboxWithDivs = function() {
67
+ this.elem.wrap("<div class='" + this.containerClass + "' />");
68
+ this.container = this.elem.parent();
69
+ this.offLabel = $("<label class='" + this.labelOffClass + "'>\n <span>" + this.uncheckedLabel + "</span>\n</label>").appendTo(this.container);
70
+ this.offSpan = this.offLabel.children('span');
71
+ this.onLabel = $("<label class='" + this.labelOnClass + "'>\n <span>" + this.checkedLabel + "</span>\n</label>").appendTo(this.container);
72
+ this.onSpan = this.onLabel.children('span');
73
+ return this.handle = $("<div class='" + this.handleClass + "'>\n <div class='" + this.handleRightClass + "'>\n <div class='" + this.handleCenterClass + "' />\n </div>\n</div>").appendTo(this.container).before("<span class='iPhoneCheckBeforeContainer'>&nbsp;</span><span class='iPhoneCheckAfterContainer'>&nbsp;</span>");
74
+ };
75
+
76
+ iOSCheckbox.prototype.disableTextSelection = function() {
77
+ if ($.browser.msie) {
78
+ return $([this.handle, this.offLabel, this.onLabel, this.container]).attr("unselectable", "on");
79
+ }
80
+ };
81
+
82
+ iOSCheckbox.prototype._getDimension = function(elem, dimension) {
83
+ if ($.fn.actual != null) {
84
+ return elem.actual(dimension);
85
+ } else {
86
+ return elem[dimension]();
87
+ }
88
+ };
89
+
90
+ iOSCheckbox.prototype.optionallyResize = function(mode) {
91
+ var newWidth, offLabelWidth, offSpan, onLabelWidth, onSpan;
92
+
93
+ onSpan = this.onLabel.find('span');
94
+ onLabelWidth = this._getDimension(onSpan, "width");
95
+ onLabelWidth += parseInt(onSpan.css('padding-right'), 10);
96
+ offSpan = this.offLabel.find('span');
97
+ offLabelWidth = this._getDimension(offSpan, "width");
98
+ offLabelWidth += parseInt(offSpan.css('padding-left'), 10);
99
+ if (mode === "container") {
100
+ newWidth = onLabelWidth > offLabelWidth ? onLabelWidth : offLabelWidth;
101
+ newWidth += this._getDimension(this.handle, "width") + this.handleMargin;
102
+ return this.container.css({
103
+ width: newWidth
104
+ });
105
+ } else {
106
+ newWidth = onLabelWidth > offLabelWidth ? onLabelWidth : offLabelWidth;
107
+ return this.handle.css({
108
+ width: newWidth
109
+ });
110
+ }
111
+ };
112
+
113
+ iOSCheckbox.prototype.onMouseDown = function(event) {
114
+ var x;
115
+
116
+ event.preventDefault();
117
+ if (this.isDisabled()) {
118
+ return;
119
+ }
120
+ x = event.pageX || event.originalEvent.changedTouches[0].pageX;
121
+ iOSCheckbox.currentlyClicking = this.handle;
122
+ iOSCheckbox.dragStartPosition = x;
123
+ return iOSCheckbox.handleLeftOffset = parseInt(this.handle.css('right'), 10) || 0;
124
+ };
125
+
126
+ iOSCheckbox.prototype.onDragMove = function(event, x) {
127
+ var newWidth, p, leftHandle;
128
+
129
+ if (iOSCheckbox.currentlyClicking !== this.handle) {
130
+ return;
131
+ }
132
+ p = (x + iOSCheckbox.handleLeftOffset - iOSCheckbox.dragStartPosition) / this.rightSide;
133
+ if (p < 0) {
134
+ p = 0;
135
+ }
136
+ if (p > 1) {
137
+ p = 1;
138
+ }
139
+ newWidth = p * this.rightSide;
140
+ leftHandle = newWidth;
141
+ if ( leftHandle == 0 ) leftHandle = -1;
142
+ this.handle.css({
143
+ right: leftHandle
144
+ });
145
+ this.onLabel.css({
146
+ width: newWidth + this.handleRadius
147
+ });
148
+ this.offSpan.css({
149
+ marginLeft: -newWidth
150
+ });
151
+ return this.onSpan.css({
152
+ marginRight: -(1 - p) * this.rightSide
153
+ });
154
+ };
155
+
156
+ iOSCheckbox.prototype.onDragEnd = function(event, x) {
157
+ var p;
158
+
159
+ if (iOSCheckbox.currentlyClicking !== this.handle) {
160
+ return;
161
+ }
162
+ if (this.isDisabled()) {
163
+ return;
164
+ }
165
+ if (iOSCheckbox.dragging) {
166
+ p = (x - iOSCheckbox.dragStartPosition) / this.rightSide;
167
+ this.elem.prop('checked', p >= 0.5);
168
+ } else {
169
+ this.elem.prop('checked', !this.elem.prop('checked'));
170
+ }
171
+ iOSCheckbox.currentlyClicking = null;
172
+ iOSCheckbox.dragging = null;
173
+ return this.didChange();
174
+ };
175
+
176
+ iOSCheckbox.prototype.refresh = function() {
177
+ return this.didChange();
178
+ };
179
+
180
+ iOSCheckbox.prototype.didChange = function() {
181
+ var new_left, leftHandle;
182
+
183
+ if (typeof this.onChange === "function") {
184
+ this.onChange(this.elem, this.elem.prop('checked'));
185
+ }
186
+ if (this.isDisabled()) {
187
+ this.container.addClass(this.disabledClass);
188
+ return false;
189
+ } else {
190
+ this.container.removeClass(this.disabledClass);
191
+ }
192
+ new_left = this.elem.prop('checked') ? this.rightSide : 0;
193
+ leftHandle = new_left;
194
+ if ( leftHandle == 0 ) leftHandle = -1;
195
+ this.handle.animate({
196
+ right: leftHandle
197
+ }, this.duration);
198
+ this.onLabel.animate({
199
+ width: new_left + this.handleRadius
200
+ }, this.duration);
201
+ this.offSpan.animate({
202
+ marginLeft: -new_left
203
+ }, this.duration);
204
+ this.onSpan.animate({
205
+ marginRight: new_left - this.rightSide
206
+ }, this.duration);
207
+ if (typeof this.onEnd === "function") {
208
+ this.onEnd(this.elem, this.elem.prop('checked'));
209
+ }
210
+ return true;
211
+ };
212
+
213
+ iOSCheckbox.prototype.attachEvents = function() {
214
+ var localMouseMove, localMouseUp, self;
215
+
216
+ self = this;
217
+ localMouseMove = function(event) {
218
+ return self.onGlobalMove.apply(self, arguments);
219
+ };
220
+ localMouseUp = function(event) {
221
+ self.onGlobalUp.apply(self, arguments);
222
+ $(document).unbind('mousemove touchmove', localMouseMove);
223
+ return $(document).unbind('mouseup touchend', localMouseUp);
224
+ };
225
+ this.elem.change(function() {
226
+ return self.refresh();
227
+ });
228
+ return this.container.bind('mousedown touchstart', function(event) {
229
+ self.onMouseDown.apply(self, arguments);
230
+ $(document).bind('mousemove touchmove', localMouseMove);
231
+ return $(document).bind('mouseup touchend', localMouseUp);
232
+ });
233
+ };
234
+
235
+ iOSCheckbox.prototype.initialPosition = function() {
236
+ var containerWidth, offset, leftHandle;
237
+
238
+ containerWidth = this._getDimension(this.container, "width");
239
+ this.offLabel.css({
240
+ width: containerWidth - this.containerRadius - 16
241
+ });
242
+ offset = this.containerRadius + 1;
243
+ if ($.browser.msie && $.browser.version < 7) {
244
+ offset -= 3;
245
+ }
246
+ this.rightSide = containerWidth - this._getDimension(this.handle, "width") - offset;
247
+ leftHandle = this.rightSide;
248
+ if ( leftHandle == 0 ) leftHandle = -1;
249
+ if (this.elem.is(':checked')) {
250
+ this.handle.css({
251
+ right: leftHandle
252
+ });
253
+ this.onLabel.css({
254
+ width: this.rightSide + this.handleRadius
255
+ });
256
+ this.offSpan.css({
257
+ marginLeft: -this.rightSide
258
+ });
259
+ } else {
260
+ this.onLabel.css({
261
+ width: this.handleRadius
262
+ });
263
+ this.onSpan.css({
264
+ marginRight: -this.rightSide
265
+ });
266
+ }
267
+ if (this.isDisabled()) {
268
+ return this.container.addClass(this.disabledClass);
269
+ }
270
+ };
271
+
272
+ iOSCheckbox.prototype.onGlobalMove = function(event) {
273
+ var x;
274
+
275
+ if (!(!this.isDisabled() && iOSCheckbox.currentlyClicking)) {
276
+ return;
277
+ }
278
+ event.preventDefault();
279
+ x = event.pageX || event.originalEvent.changedTouches[0].pageX;
280
+ if (!iOSCheckbox.dragging && (Math.abs(iOSCheckbox.dragStartPosition - x) > this.dragThreshold)) {
281
+ iOSCheckbox.dragging = true;
282
+ }
283
+ return this.onDragMove(event, x);
284
+ };
285
+
286
+ iOSCheckbox.prototype.onGlobalUp = function(event) {
287
+ var x;
288
+
289
+ if (!iOSCheckbox.currentlyClicking) {
290
+ return;
291
+ }
292
+ event.preventDefault();
293
+ x = event.pageX || event.originalEvent.changedTouches[0].pageX;
294
+ this.onDragEnd(event, x);
295
+ return false;
296
+ };
297
+
298
+ iOSCheckbox.defaults = {
299
+ duration: 200,
300
+ checkedLabel: 'ON',
301
+ uncheckedLabel: 'OFF',
302
+ resizeHandle: true,
303
+ resizeContainer: true,
304
+ disabledClass: 'iPhoneCheckDisabled',
305
+ containerClass: 'iPhoneCheckContainer',
306
+ labelOnClass: 'iPhoneCheckLabelOn',
307
+ labelOffClass: 'iPhoneCheckLabelOff',
308
+ handleClass: 'iPhoneCheckHandle',
309
+ handleCenterClass: 'iPhoneCheckHandleCenter',
310
+ handleRightClass: 'iPhoneCheckHandleRight',
311
+ dragThreshold: 5,
312
+ handleMargin: 15,
313
+ handleRadius: 4,
314
+ containerRadius: 5,
315
+ dataName: "iphoneStyle",
316
+ onChange: function() {},
317
+ onEnd: function() {}
318
+ };
319
+
320
+ return iOSCheckbox;
321
+
322
+ })();
323
+
324
+ $.iphoneStyle = this.iOSCheckbox = iOSCheckbox;
325
+
326
+ $.fn.iphoneStyle = function() {
327
+ var args, checkbox, dataName, existingControl, method, params, _i, _len, _ref, _ref1, _ref2, _ref3, _refradio;
328
+
329
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
330
+ dataName = (_ref = (_ref1 = args[0]) != null ? _ref1.dataName : void 0) != null ? _ref : iOSCheckbox.defaults.dataName;
331
+ _ref2 = this.filter(':checkbox');
332
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
333
+ checkbox = _ref2[_i];
334
+ existingControl = $(checkbox).data(dataName);
335
+ if (existingControl != null) {
336
+ method = args[0], params = 2 <= args.length ? __slice.call(args, 1) : [];
337
+ if ((_ref3 = existingControl[method]) != null) {
338
+ _ref3.apply(existingControl, params);
339
+ }
340
+ } else {
341
+ new iOSCheckbox(checkbox, args[0]);
342
+ }
343
+ }
344
+ _refradio = this.filter(':radio');
345
+ for (_i = 0, _len = _refradio.length; _i < _len; _i++) {
346
+ checkbox = _refradio[_i];
347
+ existingControl = $(checkbox).data(dataName);
348
+ if (existingControl != null) {
349
+ method = args[0], params = 2 <= args.length ? __slice.call(args, 1) : [];
350
+ if ((_ref3 = existingControl[method]) != null) {
351
+ _ref3.apply(existingControl, params);
352
+ }
353
+ } else {
354
+ new iOSCheckbox(checkbox, args[0]);
355
+ }
356
+ }
357
+ return this;
358
+ };
359
+
360
+ $.fn.iOSCheckbox = function(options) {
361
+ var opts;
362
+
363
+ if (options == null) {
364
+ options = {};
365
+ }
366
+ opts = $.extend({}, options, {
367
+ resizeHandle: false,
368
+ disabledClass: 'iOSCheckDisabled',
369
+ containerClass: 'iOSCheckContainer',
370
+ labelOnClass: 'iOSCheckLabelOn',
371
+ labelOffClass: 'iOSCheckLabelOff',
372
+ handleClass: 'iOSCheckHandle',
373
+ handleCenterClass: 'iOSCheckHandleCenter',
374
+ handleRightClass: 'iOSCheckHandleRight',
375
+ dataName: 'iOSCheckbox'
376
+ });
377
+ return this.iphoneStyle(opts);
378
+ };
379
+
380
+ }).call(this);
381
+ })(jQuery);
admin/assets/js/tipTip/jquery.tipTip.js ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TipTip
3
+ * Copyright 2010 Drew Wilson
4
+ * www.drewwilson.com
5
+ * code.drewwilson.com/entry/tiptip-jquery-plugin
6
+ *
7
+ * Version 1.3 - Updated: Mar. 23, 2010
8
+ *
9
+ * This Plug-In will create a custom tooltip to replace the default
10
+ * browser tooltip. It is extremely lightweight and very smart in
11
+ * that it detects the edges of the browser window and will make sure
12
+ * the tooltip stays within the current window size. As a result the
13
+ * tooltip will adjust itself to be displayed above, below, to the left
14
+ * or to the right depending on what is necessary to stay within the
15
+ * browser window. It is completely customizable as well via CSS.
16
+ *
17
+ * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
18
+ * http://www.opensource.org/licenses/mit-license.php
19
+ * http://www.gnu.org/licenses/gpl.html
20
+ */
21
+
22
+ (function($){
23
+ $.fn.tipTip = function(options) {
24
+ var defaults = {
25
+ activation: "hover",
26
+ keepAlive: false,
27
+ maxWidth: "200px",
28
+ edgeOffset: 3,
29
+ defaultPosition: "bottom",
30
+ delay: 400,
31
+ fadeIn: 200,
32
+ fadeOut: 200,
33
+ attribute: "title",
34
+ content: false, // HTML or String to fill TipTIp with
35
+ enter: function(){},
36
+ exit: function(){}
37
+ };
38
+ var opts = $.extend(defaults, options);
39
+
40
+ // Setup tip tip elements and render them to the DOM
41
+ if($("#tiptip_holder").length <= 0){
42
+ var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
43
+ var tiptip_content = $('<div id="tiptip_content"></div>');
44
+ var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
45
+ $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
46
+ } else {
47
+ var tiptip_holder = $("#tiptip_holder");
48
+ var tiptip_content = $("#tiptip_content");
49
+ var tiptip_arrow = $("#tiptip_arrow");
50
+ }
51
+
52
+ return this.each(function(){
53
+ var org_elem = $(this);
54
+ if(opts.content){
55
+ var org_title = opts.content;
56
+ } else {
57
+ var org_title = org_elem.attr(opts.attribute);
58
+ }
59
+ if(org_title != ""){
60
+ if(!opts.content){
61
+ org_elem.removeAttr(opts.attribute); //remove original Attribute
62
+ }
63
+ var timeout = false;
64
+
65
+ if(opts.activation == "hover"){
66
+ org_elem.hover(function(){
67
+ active_tiptip();
68
+ }, function(){
69
+ if(!opts.keepAlive){
70
+ deactive_tiptip();
71
+ }
72
+ });
73
+ if(opts.keepAlive){
74
+ tiptip_holder.hover(function(){}, function(){
75
+ deactive_tiptip();
76
+ });
77
+ }
78
+ } else if(opts.activation == "focus"){
79
+ org_elem.focus(function(){
80
+ active_tiptip();
81
+ }).blur(function(){
82
+ deactive_tiptip();
83
+ });
84
+ } else if(opts.activation == "click"){
85
+ org_elem.click(function(){
86
+ active_tiptip();
87
+ return false;
88
+ }).hover(function(){},function(){
89
+ if(!opts.keepAlive){
90
+ deactive_tiptip();
91
+ }
92
+ });
93
+ if(opts.keepAlive){
94
+ tiptip_holder.hover(function(){}, function(){
95
+ deactive_tiptip();
96
+ });
97
+ }
98
+ }
99
+
100
+ function active_tiptip(){
101
+ opts.enter.call(this);
102
+ tiptip_content.html(org_title);
103
+ tiptip_holder.hide().removeAttr("class").css("margin","0");
104
+ tiptip_arrow.removeAttr("style");
105
+
106
+ var top = parseInt(org_elem.offset()['top']);
107
+ var left = parseInt(org_elem.offset()['left']);
108
+ var org_width = parseInt(org_elem.outerWidth());
109
+ var org_height = parseInt(org_elem.outerHeight());
110
+ var tip_w = tiptip_holder.outerWidth();
111
+ var tip_h = tiptip_holder.outerHeight();
112
+ var w_compare = Math.round((org_width - tip_w) / 2);
113
+ var h_compare = Math.round((org_height - tip_h) / 2);
114
+ var marg_left = Math.round(left + w_compare);
115
+ var marg_top = Math.round(top + org_height + opts.edgeOffset);
116
+ var t_class = "";
117
+ var arrow_top = "";
118
+ var arrow_left = Math.round(tip_w - 12) / 2;
119
+
120
+ if(opts.defaultPosition == "bottom"){
121
+ t_class = "_bottom";
122
+ } else if(opts.defaultPosition == "top"){
123
+ t_class = "_top";
124
+ } else if(opts.defaultPosition == "left"){
125
+ t_class = "_left";
126
+ } else if(opts.defaultPosition == "right"){
127
+ t_class = "_right";
128
+ }
129
+
130
+ var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
131
+ var left_compare = (tip_w + left) > parseInt($(window).width());
132
+
133
+ if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
134
+ t_class = "_right";
135
+ arrow_top = Math.round(tip_h - 13) / 2;
136
+ arrow_left = -12;
137
+ marg_left = Math.round(left + org_width + opts.edgeOffset);
138
+ marg_top = Math.round(top + h_compare);
139
+ } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
140
+ t_class = "_left";
141
+ arrow_top = Math.round(tip_h - 13) / 2;
142
+ arrow_left = Math.round(tip_w);
143
+ marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
144
+ marg_top = Math.round(top + h_compare);
145
+ }
146
+
147
+ var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
148
+ var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
149
+
150
+ if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
151
+ if(t_class == "_top" || t_class == "_bottom"){
152
+ t_class = "_top";
153
+ } else {
154
+ t_class = t_class+"_top";
155
+ }
156
+ arrow_top = tip_h;
157
+ marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
158
+ } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
159
+ if(t_class == "_top" || t_class == "_bottom"){
160
+ t_class = "_bottom";
161
+ } else {
162
+ t_class = t_class+"_bottom";
163
+ }
164
+ arrow_top = -12;
165
+ marg_top = Math.round(top + org_height + opts.edgeOffset);
166
+ }
167
+
168
+ if(t_class == "_right_top" || t_class == "_left_top"){
169
+ marg_top = marg_top + 5;
170
+ } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
171
+ marg_top = marg_top - 5;
172
+ }
173
+ if(t_class == "_left_top" || t_class == "_left_bottom"){
174
+ marg_left = marg_left + 5;
175
+ }
176
+ tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
177
+ tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
178
+
179
+ if (timeout){ clearTimeout(timeout); }
180
+ timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
181
+ }
182
+
183
+ function deactive_tiptip(){
184
+ opts.exit.call(this);
185
+ if (timeout){ clearTimeout(timeout); }
186
+ tiptip_holder.fadeOut(opts.fadeOut);
187
+ }
188
+ }
189
+ });
190
+ }
191
+ })(jQuery);
admin/assets/js/tipTip/jquery.tipTip.min.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TipTip
3
+ * Copyright 2010 Drew Wilson
4
+ * www.drewwilson.com
5
+ * code.drewwilson.com/entry/tiptip-jquery-plugin
6
+ *
7
+ * Version 1.3 - Updated: Mar. 23, 2010
8
+ *
9
+ * This Plug-In will create a custom tooltip to replace the default
10
+ * browser tooltip. It is extremely lightweight and very smart in
11
+ * that it detects the edges of the browser window and will make sure
12
+ * the tooltip stays within the current window size. As a result the
13
+ * tooltip will adjust itself to be displayed above, below, to the left
14
+ * or to the right depending on what is necessary to stay within the
15
+ * browser window. It is completely customizable as well via CSS.
16
+ *
17
+ * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
18
+ * http://www.opensource.org/licenses/mit-license.php
19
+ * http://www.gnu.org/licenses/gpl.html
20
+ */
21
+ (function($){$.fn.tipTip=function(options){var defaults={activation:"hover",keepAlive:false,maxWidth:"200px",edgeOffset:3,defaultPosition:"bottom",delay:400,fadeIn:200,fadeOut:200,attribute:"title",content:false,enter:function(){},exit:function(){}};var opts=$.extend(defaults,options);if($("#tiptip_holder").length<=0){var tiptip_holder=$('<div id="tiptip_holder" style="max-width:'+opts.maxWidth+';"></div>');var tiptip_content=$('<div id="tiptip_content"></div>');var tiptip_arrow=$('<div id="tiptip_arrow"></div>');$("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')))}else{var tiptip_holder=$("#tiptip_holder");var tiptip_content=$("#tiptip_content");var tiptip_arrow=$("#tiptip_arrow")}return this.each(function(){var org_elem=$(this);if(opts.content){var org_title=opts.content}else{var org_title=org_elem.attr(opts.attribute)}if(org_title!=""){if(!opts.content){org_elem.removeAttr(opts.attribute)}var timeout=false;if(opts.activation=="hover"){org_elem.hover(function(){active_tiptip()},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}else if(opts.activation=="focus"){org_elem.focus(function(){active_tiptip()}).blur(function(){deactive_tiptip()})}else if(opts.activation=="click"){org_elem.click(function(){active_tiptip();return false}).hover(function(){},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}function active_tiptip(){opts.enter.call(this);tiptip_content.html(org_title);tiptip_holder.hide().removeAttr("class").css("margin","0");tiptip_arrow.removeAttr("style");var top=parseInt(org_elem.offset()['top']);var left=parseInt(org_elem.offset()['left']);var org_width=parseInt(org_elem.outerWidth());var org_height=parseInt(org_elem.outerHeight());var tip_w=tiptip_holder.outerWidth();var tip_h=tiptip_holder.outerHeight();var w_compare=Math.round((org_width-tip_w)/2);var h_compare=Math.round((org_height-tip_h)/2);var marg_left=Math.round(left+w_compare);var marg_top=Math.round(top+org_height+opts.edgeOffset);var t_class="";var arrow_top="";var arrow_left=Math.round(tip_w-12)/2;if(opts.defaultPosition=="bottom"){t_class="_bottom"}else if(opts.defaultPosition=="top"){t_class="_top"}else if(opts.defaultPosition=="left"){t_class="_left"}else if(opts.defaultPosition=="right"){t_class="_right"}var right_compare=(w_compare+left)<parseInt($(window).scrollLeft());var left_compare=(tip_w+left)>parseInt($(window).width());if((right_compare&&w_compare<0)||(t_class=="_right"&&!left_compare)||(t_class=="_left"&&left<(tip_w+opts.edgeOffset+5))){t_class="_right";arrow_top=Math.round(tip_h-13)/2;arrow_left=-12;marg_left=Math.round(left+org_width+opts.edgeOffset);marg_top=Math.round(top+h_compare)}else if((left_compare&&w_compare<0)||(t_class=="_left"&&!right_compare)){t_class="_left";arrow_top=Math.round(tip_h-13)/2;arrow_left=Math.round(tip_w);marg_left=Math.round(left-(tip_w+opts.edgeOffset+5));marg_top=Math.round(top+h_compare)}var top_compare=(top+org_height+opts.edgeOffset+tip_h+8)>parseInt($(window).height()+$(window).scrollTop());var bottom_compare=((top+org_height)-(opts.edgeOffset+tip_h+8))<0;if(top_compare||(t_class=="_bottom"&&top_compare)||(t_class=="_top"&&!bottom_compare)){if(t_class=="_top"||t_class=="_bottom"){t_class="_top"}else{t_class=t_class+"_top"}arrow_top=tip_h;marg_top=Math.round(top-(tip_h+5+opts.edgeOffset))}else if(bottom_compare|(t_class=="_top"&&bottom_compare)||(t_class=="_bottom"&&!top_compare)){if(t_class=="_top"||t_class=="_bottom"){t_class="_bottom"}else{t_class=t_class+"_bottom"}arrow_top=-12;marg_top=Math.round(top+org_height+opts.edgeOffset)}if(t_class=="_right_top"||t_class=="_left_top"){marg_top=marg_top+5}else if(t_class=="_right_bottom"||t_class=="_left_bottom"){marg_top=marg_top-5}if(t_class=="_left_top"||t_class=="_left_bottom"){marg_left=marg_left+5}tiptip_arrow.css({"margin-left":arrow_left+"px","margin-top":arrow_top+"px"});tiptip_holder.css({"margin-left":marg_left+"px","margin-top":marg_top+"px"}).attr("class","tip"+t_class);if(timeout){clearTimeout(timeout)}timeout=setTimeout(function(){tiptip_holder.stop(true,true).fadeIn(opts.fadeIn)},opts.delay)}function deactive_tiptip(){opts.exit.call(this);if(timeout){clearTimeout(timeout)}tiptip_holder.fadeOut(opts.fadeOut)}}})}})(jQuery);
admin/assets/js/tipTip/tipTip.css ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* TipTip CSS - Version 1.2 */
2
+
3
+ #tiptip_holder {
4
+ display: none;
5
+ position: absolute;
6
+ top: 0;
7
+ left: 0;
8
+ z-index: 99999;
9
+ }
10
+
11
+ #tiptip_holder.tip_top {
12
+ padding-bottom: 5px;
13
+ }
14
+
15
+ #tiptip_holder.tip_bottom {
16
+ padding-top: 5px;
17
+ }
18
+
19
+ #tiptip_holder.tip_right {
20
+ padding-left: 5px;
21
+ }
22
+
23
+ #tiptip_holder.tip_left {
24
+ padding-right: 5px;
25
+ }
26
+
27
+ #tiptip_content {
28
+ font-size: 11px;
29
+ color: #fff;
30
+ text-shadow: 0 0 2px #000;
31
+ padding: 4px 8px;
32
+ border: 1px solid rgba(255,255,255,0.25);
33
+ background-color: rgb(25,25,25);
34
+ background-color: rgba(25,25,25,0.92);
35
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(transparent), to(#000));
36
+ border-radius: 3px;
37
+ -webkit-border-radius: 3px;
38
+ -moz-border-radius: 3px;
39
+ box-shadow: 0 0 3px #555;
40
+ -webkit-box-shadow: 0 0 3px #555;
41
+ -moz-box-shadow: 0 0 3px #555;
42
+ }
43
+
44
+ #tiptip_arrow, #tiptip_arrow_inner {
45
+ position: absolute;
46
+ border-color: transparent;
47
+ border-style: solid;
48
+ border-width: 6px;
49
+ height: 0;
50
+ width: 0;
51
+ }
52
+
53
+ #tiptip_holder.tip_top #tiptip_arrow {
54
+ border-top-color: #fff;
55
+ border-top-color: rgba(255,255,255,0.35);
56
+ }
57
+
58
+ #tiptip_holder.tip_bottom #tiptip_arrow {
59
+ border-bottom-color: #fff;
60
+ border-bottom-color: rgba(255,255,255,0.35);
61
+ }
62
+
63
+ #tiptip_holder.tip_right #tiptip_arrow {
64
+ border-right-color: #fff;
65
+ border-right-color: rgba(255,255,255,0.35);
66
+ }
67
+
68
+ #tiptip_holder.tip_left #tiptip_arrow {
69
+ border-left-color: #fff;
70
+ border-left-color: rgba(255,255,255,0.35);
71
+ }
72
+
73
+ #tiptip_holder.tip_top #tiptip_arrow_inner {
74
+ margin-top: -7px;
75
+ margin-left: -6px;
76
+ border-top-color: rgb(25,25,25);
77
+ border-top-color: rgba(25,25,25,0.92);
78
+ }
79
+
80
+ #tiptip_holder.tip_bottom #tiptip_arrow_inner {
81
+ margin-top: -5px;
82
+ margin-left: -6px;
83
+ border-bottom-color: rgb(25,25,25);
84
+ border-bottom-color: rgba(25,25,25,0.92);
85
+ }
86
+
87
+ #tiptip_holder.tip_right #tiptip_arrow_inner {
88
+ margin-top: -6px;
89
+ margin-left: -5px;
90
+ border-right-color: rgb(25,25,25);
91
+ border-right-color: rgba(25,25,25,0.92);
92
+ }
93
+
94
+ #tiptip_holder.tip_left #tiptip_arrow_inner {
95
+ margin-top: -6px;
96
+ margin-left: -7px;
97
+ border-left-color: rgb(25,25,25);
98
+ border-left-color: rgba(25,25,25,0.92);
99
+ }
100
+
101
+ /* Webkit Hacks */
102
+ @media screen and (-webkit-min-device-pixel-ratio:0) {
103
+ #tiptip_content {
104
+ padding: 4px 8px 5px 8px;
105
+ background-color: rgba(45,45,45,0.88);
106
+ }
107
+ #tiptip_holder.tip_bottom #tiptip_arrow_inner {
108
+ border-bottom-color: rgba(45,45,45,0.88);
109
+ }
110
+ #tiptip_holder.tip_top #tiptip_arrow_inner {
111
+ border-top-color: rgba(20,20,20,0.92);
112
+ }
113
+ }
admin/assets/js/ui-slider/jquery.ui.slider.rtl.js ADDED
@@ -0,0 +1,711 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery UI Slider 1.8.9.rtl.1
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI/Slider
9
+ *
10
+ * Depends:
11
+ * jquery.ui.core.js
12
+ * jquery.ui.mouse.js
13
+ * jquery.ui.widget.js
14
+ */
15
+ (function( $, undefined ) {
16
+
17
+ // number of pages in a slider
18
+ // (how many times can you page up/down to go through the whole range)
19
+ var numPages = 5;
20
+
21
+ $.widget( "ui.slider", $.ui.mouse, {
22
+
23
+ widgetEventPrefix: "slide",
24
+
25
+ options: {
26
+ animate: false,
27
+ distance: 0,
28
+ max: 100,
29
+ min: 0,
30
+ orientation: "horizontal",
31
+ isRTL: false, // RTL
32
+ range: false,
33
+ step: 1,
34
+ value: 0,
35
+ values: null
36
+ },
37
+
38
+ _create: function() {
39
+ var self = this,
40
+ o = this.options;
41
+
42
+ this._keySliding = false;
43
+ this._mouseSliding = false;
44
+ this._animateOff = true;
45
+ this._handleIndex = null;
46
+ this._detectOrientation();
47
+ this._mouseInit();
48
+
49
+ this.element
50
+ .addClass( "ui-slider" +
51
+ " ui-slider-" + this.orientation +
52
+ ( o.isRTL ? " ui-slider-rtl" : "" ) + // RTL
53
+ " ui-widget" +
54
+ " ui-widget-content" +
55
+ " ui-corner-all" );
56
+
57
+ if ( o.disabled ) {
58
+ this.element.addClass( "ui-slider-disabled ui-disabled" );
59
+ }
60
+
61
+ this.range = $([]);
62
+
63
+ if ( o.range ) {
64
+ if ( o.range === true ) {
65
+ this.range = $( "<div></div>" );
66
+ if ( !o.values ) {
67
+ o.values = [ this._valueMin(), this._valueMin() ];
68
+ }
69
+ if ( o.values.length && o.values.length !== 2 ) {
70
+ o.values = [ o.values[0], o.values[0] ];
71
+ }
72
+ } else {
73
+ this.range = $( "<div></div>" );
74
+ }
75
+
76
+ this.range
77
+ .appendTo( this.element )
78
+ .addClass( "ui-slider-range" );
79
+
80
+ if ( o.range === "min" || o.range === "max" ) {
81
+ this.range.addClass( "ui-slider-range-" + o.range );
82
+ }
83
+
84
+ // note: this isn't the most fittingly semantic framework class for this element,
85
+ // but worked best visually with a variety of themes
86
+ this.range.addClass( "ui-widget-header" );
87
+ }
88
+
89
+ if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
90
+ $( "<a href='#'></a>" )
91
+ .appendTo( this.element )
92
+ .addClass( "ui-slider-handle" );
93
+ }
94
+
95
+ if ( o.values && o.values.length ) {
96
+ while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
97
+ $( "<a href='#'></a>" )
98
+ .appendTo( this.element )
99
+ .addClass( "ui-slider-handle" );
100
+ }
101
+ }
102
+
103
+ this.handles = $( ".ui-slider-handle", this.element )
104
+ .addClass( "ui-state-default" +
105
+ " ui-corner-all" );
106
+
107
+ this.handle = this.handles.eq( 0 );
108
+
109
+ this.handles.add( this.range ).filter( "a" )
110
+ .click(function( event ) {
111
+ event.preventDefault();
112
+ })
113
+ .hover(function() {
114
+ if ( !o.disabled ) {
115
+ $( this ).addClass( "ui-state-hover" );
116
+ }
117
+ }, function() {
118
+ $( this ).removeClass( "ui-state-hover" );
119
+ })
120
+ .focus(function() {
121
+ if ( !o.disabled ) {
122
+ $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
123
+ $( this ).addClass( "ui-state-focus" );
124
+ } else {
125
+ $( this ).blur();
126
+ }
127
+ })
128
+ .blur(function() {
129
+ $( this ).removeClass( "ui-state-focus" );
130
+ });
131
+
132
+ this.handles.each(function( i ) {
133
+ $( this ).data( "index.ui-slider-handle", i );
134
+ });
135
+
136
+ this.handles
137
+ .keydown(function( event ) {
138
+ var ret = true,
139
+ index = $( this ).data( "index.ui-slider-handle" ),
140
+ allowed,
141
+ curVal,
142
+ newVal,
143
+ step;
144
+
145
+ if ( self.options.disabled ) {
146
+ return;
147
+ }
148
+
149
+ switch ( event.keyCode ) {
150
+ case $.ui.keyCode.HOME:
151
+ case $.ui.keyCode.END:
152
+ case $.ui.keyCode.PAGE_UP:
153
+ case $.ui.keyCode.PAGE_DOWN:
154
+ case $.ui.keyCode.UP:
155
+ case $.ui.keyCode.RIGHT:
156
+ case $.ui.keyCode.DOWN:
157
+ case $.ui.keyCode.LEFT:
158
+ ret = false;
159
+ if ( !self._keySliding ) {
160
+ self._keySliding = true;
161
+ $( this ).addClass( "ui-state-active" );
162
+ allowed = self._start( event, index );
163
+ if ( allowed === false ) {
164
+ return;
165
+ }
166
+ }
167
+ break;
168
+ }
169
+
170
+ step = self.options.step;
171
+ if ( self.options.values && self.options.values.length ) {
172
+ curVal = newVal = self.values( index );
173
+ } else {
174
+ curVal = newVal = self.value();
175
+ }
176
+
177
+ var adjust = function( minMax, offset ) { // RTL
178
+ if ( curVal === minMax ) {
179
+ return;
180
+ }
181
+ newVal = self._trimAlignValue( curVal + offset );
182
+ };
183
+ switch ( event.keyCode ) {
184
+ case $.ui.keyCode.HOME:
185
+ newVal = self._valueMin();
186
+ break;
187
+ case $.ui.keyCode.END:
188
+ newVal = self._valueMax();
189
+ break;
190
+ case $.ui.keyCode.PAGE_UP:
191
+ newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
192
+ break;
193
+ case $.ui.keyCode.PAGE_DOWN:
194
+ newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
195
+ break;
196
+ case $.ui.keyCode.UP:
197
+ adjust( self._valueMax(), step ); // RTL
198
+ break;
199
+ case $.ui.keyCode.RIGHT:
200
+ adjust( self._valueMax(), self.options.isRTL ? -step : step ); // RTL
201
+ break;
202
+ case $.ui.keyCode.DOWN:
203
+ adjust( self._valueMin(), -step ); // RTL
204
+ break;
205
+ case $.ui.keyCode.LEFT:
206
+ adjust( self._valueMin(), self.options.isRTL ? step : -step ); // RTL
207
+ break;
208
+ }
209
+
210
+ self._slide( event, index, newVal );
211
+
212
+ return ret;
213
+
214
+ })
215
+ .keyup(function( event ) {
216
+ var index = $( this ).data( "index.ui-slider-handle" );
217
+
218
+ if ( self._keySliding ) {
219
+ self._keySliding = false;
220
+ self._stop( event, index );
221
+ self._change( event, index );
222
+ $( this ).removeClass( "ui-state-active" );
223
+ }
224
+
225
+ });
226
+
227
+ this._refreshValue();
228
+
229
+ this._animateOff = false;
230
+ },
231
+
232
+ destroy: function() {
233
+ this.handles.remove();
234
+ this.range.remove();
235
+
236
+ this.element
237
+ .removeClass( "ui-slider" +
238
+ " ui-slider-horizontal" +
239
+ " ui-slider-vertical" +
240
+ " ui-slider-disabled" +
241
+ " ui-widget" +
242
+ " ui-widget-content" +
243
+ " ui-corner-all" )
244
+ .removeData( "slider" )
245
+ .unbind( ".slider" );
246
+
247
+ this._mouseDestroy();
248
+
249
+ return this;
250
+ },
251
+
252
+ _mouseCapture: function( event ) {
253
+ var o = this.options,
254
+ position,
255
+ normValue,
256
+ distance,
257
+ closestHandle,
258
+ self,
259
+ index,
260
+ allowed,
261
+ offset,
262
+ mouseOverHandle;
263
+
264
+ if ( o.disabled ) {
265
+ return false;
266
+ }
267
+
268
+ this.elementSize = {
269
+ width: this.element.outerWidth(),
270
+ height: this.element.outerHeight()
271
+ };
272
+ this.elementOffset = this.element.offset();
273
+
274
+ position = { x: event.pageX, y: event.pageY };
275
+ normValue = this._normValueFromMouse( position );
276
+ distance = this._valueMax() - this._valueMin() + 1;
277
+ self = this;
278
+ this.handles.each(function( i ) {
279
+ var thisDistance = Math.abs( normValue - self.values(i) );
280
+ if ( distance > thisDistance ) {
281
+ distance = thisDistance;
282
+ closestHandle = $( this );
283
+ index = i;
284
+ }
285
+ });
286
+
287
+ // workaround for bug #3736 (if both handles of a range are at 0,
288
+ // the first is always used as the one with least distance,
289
+ // and moving it is obviously prevented by preventing negative ranges)
290
+ if( o.range === true && this.values(1) === o.min ) {
291
+ index += 1;
292
+ closestHandle = $( this.handles[index] );
293
+ }
294
+
295
+ allowed = this._start( event, index );
296
+ if ( allowed === false ) {
297
+ return false;
298
+ }
299
+ this._mouseSliding = true;
300
+
301
+ self._handleIndex = index;
302
+
303
+ closestHandle
304
+ .addClass( "ui-state-active" )
305
+ .focus();
306
+
307
+ offset = closestHandle.offset();
308
+ mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
309
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
310
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
311
+ top: event.pageY - offset.top -
312
+ ( closestHandle.height() / 2 ) -
313
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
314
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
315
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
316
+ };
317
+
318
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
319
+ this._slide( event, index, normValue );
320
+ }
321
+ this._animateOff = true;
322
+ return true;
323
+ },
324
+
325
+ _mouseStart: function( event ) {
326
+ return true;
327
+ },
328
+
329
+ _mouseDrag: function( event ) {
330
+ var position = { x: event.pageX, y: event.pageY },
331
+ normValue = this._normValueFromMouse( position );
332
+
333
+ this._slide( event, this._handleIndex, normValue );
334
+
335
+ return false;
336
+ },
337
+
338
+ _mouseStop: function( event ) {
339
+ this.handles.removeClass( "ui-state-active" );
340
+ this._mouseSliding = false;
341
+
342
+ this._stop( event, this._handleIndex );
343
+ this._change( event, this._handleIndex );
344
+
345
+ this._handleIndex = null;
346
+ this._clickOffset = null;
347
+ this._animateOff = false;
348
+
349
+ return false;
350
+ },
351
+
352
+ _detectOrientation: function() {
353
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
354
+ },
355
+
356
+ _normValueFromMouse: function( position ) {
357
+ var pixelTotal,
358
+ pixelMouse,
359
+ percentMouse,
360
+ valueTotal,
361
+ valueMouse;
362
+
363
+ if ( this.orientation === "horizontal" ) {
364
+ pixelTotal = this.elementSize.width;
365
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
366
+ } else {
367
+ pixelTotal = this.elementSize.height;
368
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
369
+ }
370
+
371
+ percentMouse = ( pixelMouse / pixelTotal );
372
+ if ( percentMouse > 1 ) {
373
+ percentMouse = 1;
374
+ }
375
+ if ( percentMouse < 0 ) {
376
+ percentMouse = 0;
377
+ }
378
+ if ( this.orientation === "vertical" ) {
379
+ percentMouse = 1 - percentMouse;
380
+ }
381
+ if ( this.options.isRTL ) { // RTL
382
+ percentMouse = 1 - percentMouse;
383
+ }
384
+
385
+ valueTotal = this._valueMax() - this._valueMin();
386
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
387
+
388
+ return this._trimAlignValue( valueMouse );
389
+ },
390
+
391
+ _start: function( event, index ) {
392
+ var uiHash = {
393
+ handle: this.handles[ index ],
394
+ value: this.value()
395
+ };
396
+ if ( this.options.values && this.options.values.length ) {
397
+ uiHash.value = this.values( index );
398
+ uiHash.values = this.values();
399
+ }
400
+ return this._trigger( "start", event, uiHash );
401
+ },
402
+
403
+ _slide: function( event, index, newVal ) {
404
+ var otherVal,
405
+ newValues,
406
+ allowed;
407
+
408
+ if ( this.options.values && this.options.values.length ) {
409
+ otherVal = this.values( index ? 0 : 1 );
410
+
411
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
412
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
413
+ ) {
414
+ newVal = otherVal;
415
+ }
416
+
417
+ if ( newVal !== this.values( index ) ) {
418
+ newValues = this.values();
419
+ newValues[ index ] = newVal;
420
+ // A slide can be canceled by returning false from the slide callback
421
+ allowed = this._trigger( "slide", event, {
422
+ handle: this.handles[ index ],
423
+ value: newVal,
424
+ values: newValues
425
+ } );
426
+ otherVal = this.values( index ? 0 : 1 );
427
+ if ( allowed !== false ) {
428
+ this.values( index, newVal, true );
429
+ }
430
+ }
431
+ } else {
432
+ if ( newVal !== this.value() ) {
433
+ // A slide can be canceled by returning false from the slide callback
434
+ allowed = this._trigger( "slide", event, {
435
+ handle: this.handles[ index ],
436
+ value: newVal
437
+ } );
438
+ if ( allowed !== false ) {
439
+ this.value( newVal );
440
+ }
441
+ }
442
+ }
443
+ },
444
+
445
+ _stop: function( event, index ) {
446
+ var uiHash = {
447
+ handle: this.handles[ index ],
448
+ value: this.value()
449
+ };
450
+ if ( this.options.values && this.options.values.length ) {
451
+ uiHash.value = this.values( index );
452
+ uiHash.values = this.values();
453
+ }
454
+
455
+ this._trigger( "stop", event, uiHash );
456
+ },
457
+
458
+ _change: function( event, index ) {
459
+ if ( !this._keySliding && !this._mouseSliding ) {
460
+ var uiHash = {
461
+ handle: this.handles[ index ],
462
+ value: this.value()
463
+ };
464
+ if ( this.options.values && this.options.values.length ) {
465
+ uiHash.value = this.values( index );
466
+ uiHash.values = this.values();
467
+ }
468
+
469
+ this._trigger( "change", event, uiHash );
470
+ }
471
+ },
472
+
473
+ value: function( newValue ) {
474
+ if ( arguments.length ) {
475
+ this.options.value = this._trimAlignValue( newValue );
476
+ this._refreshValue();
477
+ this._change( null, 0 );
478
+ }
479
+
480
+ return this._value();
481
+ },
482
+
483
+ values: function( index, newValue ) {
484
+ var vals,
485
+ newValues,
486
+ i;
487
+
488
+ if ( arguments.length > 1 ) {
489
+ this.options.values[ index ] = this._trimAlignValue( newValue );
490
+ this._refreshValue();
491
+ this._change( null, index );
492
+ }
493
+
494
+ if ( arguments.length ) {
495
+ if ( $.isArray( arguments[ 0 ] ) ) {
496
+ vals = this.options.values;
497
+ newValues = arguments[ 0 ];
498
+ for ( i = 0; i < vals.length; i += 1 ) {
499
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
500
+ this._change( null, i );
501
+ }
502
+ this._refreshValue();
503
+ } else {
504
+ if ( this.options.values && this.options.values.length ) {
505
+ return this._values( index );
506
+ } else {
507
+ return this.value();
508
+ }
509
+ }
510
+ } else {
511
+ return this._values();
512
+ }
513
+ },
514
+
515
+ _setOption: function( key, value ) {
516
+ var i,
517
+ valsLength = 0;
518
+
519
+ if ( $.isArray( this.options.values ) ) {
520
+ valsLength = this.options.values.length;
521
+ }
522
+
523
+ $.Widget.prototype._setOption.apply( this, arguments );
524
+
525
+ switch ( key ) {
526
+ case "disabled":
527
+ if ( value ) {
528
+ this.handles.filter( ".ui-state-focus" ).blur();
529
+ this.handles.removeClass( "ui-state-hover" );
530
+ this.handles.attr( "disabled", "disabled" );
531
+ this.element.addClass( "ui-disabled" );
532
+ } else {
533
+ this.handles.removeAttr( "disabled" );
534
+ this.element.removeClass( "ui-disabled" );
535
+ }
536
+ break;
537
+ case "orientation":
538
+ this._detectOrientation();
539
+ this.element
540
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
541
+ .addClass( "ui-slider-" + this.orientation );
542
+ this._refreshValue();
543
+ break;
544
+ case "isRTL": // RTL
545
+ this.element.toggleClass( "ui-slider-rtl", value );
546
+ this._refreshValue();
547
+ break;
548
+ case "value":
549
+ this._animateOff = true;
550
+ this._refreshValue();
551
+ this._change( null, 0 );
552
+ this._animateOff = false;
553
+ break;
554
+ case "values":
555
+ this._animateOff = true;
556
+ this._refreshValue();
557
+ for ( i = 0; i < valsLength; i += 1 ) {
558
+ this._change( null, i );
559
+ }
560
+ this._animateOff = false;
561
+ break;
562
+ }
563
+ },
564
+
565
+ //internal value getter
566
+ // _value() returns value trimmed by min and max, aligned by step
567
+ _value: function() {
568
+ var val = this.options.value;
569
+ val = this._trimAlignValue( val );
570
+
571
+ return val;
572
+ },
573
+
574
+ //internal values getter
575
+ // _values() returns array of values trimmed by min and max, aligned by step
576
+ // _values( index ) returns single value trimmed by min and max, aligned by step
577
+ _values: function( index ) {
578
+ var val,
579
+ vals,
580
+ i;
581
+
582
+ if ( arguments.length ) {
583
+ val = this.options.values[ index ];
584
+ val = this._trimAlignValue( val );
585
+
586
+ return val;
587
+ } else {
588
+ // .slice() creates a copy of the array
589
+ // this copy gets trimmed by min and max and then returned
590
+ vals = this.options.values.slice();
591
+ for ( i = 0; i < vals.length; i+= 1) {
592
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
593
+ }
594
+
595
+ return vals;
596
+ }
597
+ },
598
+
599
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
600
+ _trimAlignValue: function( val ) {
601
+ if ( val <= this._valueMin() ) {
602
+ return this._valueMin();
603
+ }
604
+ if ( val >= this._valueMax() ) {
605
+ return this._valueMax();
606
+ }
607
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
608
+ valModStep = (val - this._valueMin()) % step;
609
+ alignValue = val - valModStep;
610
+
611
+ if ( Math.abs(valModStep) * 2 >= step ) {
612
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
613
+ }
614
+
615
+ // Since JavaScript has problems with large floats, round
616
+ // the final value to 5 digits after the decimal point (see #4124)
617
+ return parseFloat( alignValue.toFixed(5) );
618
+ },
619
+
620
+ _valueMin: function() {
621
+ return this.options.min;
622
+ },
623
+
624
+ _valueMax: function() {
625
+ return this.options.max;
626
+ },
627
+
628
+ _refreshValue: function() {
629
+ var oRange = this.options.range,
630
+ o = this.options,
631
+ self = this,
632
+ animate = ( !this._animateOff ) ? o.animate : false,
633
+ valPercent,
634
+ _set = {},
635
+ lastValPercent,
636
+ value,
637
+ valueMin,
638
+ valueMax;
639
+
640
+ if ( this.options.values && this.options.values.length ) {
641
+ this.handles.each(function( i, j ) {
642
+ valPercent = ( self.values( i ) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
643
+ valPercent = ( self.options.isRTL ? 100 - valPercent : valPercent ); // RTL
644
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
645
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
646
+ if ( self.options.range === true ) {
647
+ if ( self.orientation === "horizontal" ) {
648
+ if ( i === 0 ) {
649
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ](
650
+ self.options.isRTL ? { right: ( 100 - valPercent ) + "%"} : // RTL
651
+ { left: valPercent + "%" }, o.animate );
652
+ }
653
+ if ( i === 1 ) {
654
+ self.range[ animate ? "animate" : "css" ]( {
655
+ width: ( ( self.options.isRTL ? -1 : +1 ) * ( valPercent - lastValPercent ) ) + "%" }, // RTL
656
+ { queue: false, duration: o.animate } );
657
+ }
658
+ } else {
659
+ if ( i === 0 ) {
660
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ](
661
+ self.options.isRTL ? { top: ( 100 - valPercent ) + "%" } : // RTL
662
+ { bottom: ( valPercent ) + "%" }, o.animate );
663
+ }
664
+ if ( i === 1 ) {
665
+ self.range[ animate ? "animate" : "css" ]( {
666
+ height: ( ( self.options.isRTL ? -1 : +1 ) * ( valPercent - lastValPercent ) ) + "%" }, // RTL
667
+ { queue: false, duration: o.animate } );
668
+ }
669
+ }
670
+ }
671
+ lastValPercent = valPercent;
672
+ });
673
+ } else {
674
+ value = this.value();
675
+ valueMin = this._valueMin();
676
+ valueMax = this._valueMax();
677
+ valPercent = ( valueMax !== valueMin ) ?
678
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
679
+ 0;
680
+ valPercent = ( self.options.isRTL ? 100 - valPercent : valPercent ); // RTL
681
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
682
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
683
+
684
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
685
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ](
686
+ { width: ( self.options.isRTL ? 100 - valPercent : valPercent ) + "%" }, o.animate ); // RTL
687
+ }
688
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
689
+ this.range[ animate ? "animate" : "css" ]( {
690
+ width: ( self.options.isRTL ? valPercent : 100 - valPercent ) + "%" }, // RTL
691
+ { queue: false, duration: o.animate } );
692
+ }
693
+ if ( oRange === "min" && this.orientation === "vertical" ) {
694
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ](
695
+ { height: ( self.options.isRTL ? 100 - valPercent : valPercent ) + "%" }, o.animate ); // RTL
696
+ }
697
+ if ( oRange === "max" && this.orientation === "vertical" ) {
698
+ this.range[ animate ? "animate" : "css" ](
699
+ { height: ( self.options.isRTL ? valPercent : 100 - valPercent ) + "%" }, // RTL
700
+ { queue: false, duration: o.animate } );
701
+ }
702
+ }
703
+ }
704
+
705
+ });
706
+
707
+ $.extend( $.ui.slider, {
708
+ version: "1.8.9"
709
+ });
710
+
711
+ }(jQuery));
admin/assets/js/ui-slider/jquery.ui.slider.rtl.min.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery UI Slider 1.8.9.rtl.1
3
+ *
4
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ * http://jquery.org/license
7
+ *
8
+ * http://docs.jquery.com/UI/Slider
9
+ *
10
+ * Depends:
11
+ * jquery.ui.core.js
12
+ * jquery.ui.mouse.js
13
+ * jquery.ui.widget.js
14
+ */
15
+ (function($,g){var h=5;$.widget("ui.slider",$.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",isRTL:false,range:false,step:1,value:0,values:null},_create:function(){var f=this,o=this.options;this._keySliding=false;this._mouseSliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider"+" ui-slider-"+this.orientation+(o.isRTL?" ui-slider-rtl":"")+" ui-widget"+" ui-widget-content"+" ui-corner-all");if(o.disabled){this.element.addClass("ui-slider-disabled ui-disabled")}this.range=$([]);if(o.range){if(o.range===true){this.range=$("<div></div>");if(!o.values){o.values=[this._valueMin(),this._valueMin()]}if(o.values.length&&o.values.length!==2){o.values=[o.values[0],o.values[0]]}}else{this.range=$("<div></div>")}this.range.appendTo(this.element).addClass("ui-slider-range");if(o.range==="min"||o.range==="max"){this.range.addClass("ui-slider-range-"+o.range)}this.range.addClass("ui-widget-header")}if($(".ui-slider-handle",this.element).length===0){$("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle")}if(o.values&&o.values.length){while($(".ui-slider-handle",this.element).length<o.values.length){$("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle")}}this.handles=$(".ui-slider-handle",this.element).addClass("ui-state-default"+" ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(a){a.preventDefault()}).hover(function(){if(!o.disabled){$(this).addClass("ui-state-hover")}},function(){$(this).removeClass("ui-state-hover")}).focus(function(){if(!o.disabled){$(".ui-slider .ui-state-focus").removeClass("ui-state-focus");$(this).addClass("ui-state-focus")}else{$(this).blur()}}).blur(function(){$(this).removeClass("ui-state-focus")});this.handles.each(function(i){$(this).data("index.ui-slider-handle",i)});this.handles.keydown(function(c){var d=true,index=$(this).data("index.ui-slider-handle"),allowed,curVal,newVal,step;if(f.options.disabled){return}switch(c.keyCode){case $.ui.keyCode.HOME:case $.ui.keyCode.END:case $.ui.keyCode.PAGE_UP:case $.ui.keyCode.PAGE_DOWN:case $.ui.keyCode.UP:case $.ui.keyCode.RIGHT:case $.ui.keyCode.DOWN:case $.ui.keyCode.LEFT:d=false;if(!f._keySliding){f._keySliding=true;$(this).addClass("ui-state-active");allowed=f._start(c,index);if(allowed===false){return}}break}step=f.options.step;if(f.options.values&&f.options.values.length){curVal=newVal=f.values(index)}else{curVal=newVal=f.value()}var e=function(a,b){if(curVal===a){return}newVal=f._trimAlignValue(curVal+b)};switch(c.keyCode){case $.ui.keyCode.HOME:newVal=f._valueMin();break;case $.ui.keyCode.END:newVal=f._valueMax();break;case $.ui.keyCode.PAGE_UP:newVal=f._trimAlignValue(curVal+((f._valueMax()-f._valueMin())/h));break;case $.ui.keyCode.PAGE_DOWN:newVal=f._trimAlignValue(curVal-((f._valueMax()-f._valueMin())/h));break;case $.ui.keyCode.UP:e(f._valueMax(),step);break;case $.ui.keyCode.RIGHT:e(f._valueMax(),f.options.isRTL?-step:step);break;case $.ui.keyCode.DOWN:e(f._valueMin(),-step);break;case $.ui.keyCode.LEFT:e(f._valueMin(),f.options.isRTL?step:-step);break}f._slide(c,index,newVal);return d}).keyup(function(a){var b=$(this).data("index.ui-slider-handle");if(f._keySliding){f._keySliding=false;f._stop(a,b);f._change(a,b);$(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider"+" ui-slider-horizontal"+" ui-slider-vertical"+" ui-slider-disabled"+" ui-widget"+" ui-widget-content"+" ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy();return this},_mouseCapture:function(b){var o=this.options,position,normValue,distance,closestHandle,self,index,allowed,offset,mouseOverHandle;if(o.disabled){return false}this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();position={x:b.pageX,y:b.pageY};normValue=this._normValueFromMouse(position);distance=this._valueMax()-this._valueMin()+1;self=this;this.handles.each(function(i){var a=Math.abs(normValue-self.values(i));if(distance>a){distance=a;closestHandle=$(this);index=i}});if(o.range===true&&this.values(1)===o.min){index+=1;closestHandle=$(this.handles[index])}allowed=this._start(b,index);if(allowed===false){return false}this._mouseSliding=true;self._handleIndex=index;closestHandle.addClass("ui-state-active").focus();offset=closestHandle.offset();mouseOverHandle=!$(b.target).parents().andSelf().is(".ui-slider-handle");this._clickOffset=mouseOverHandle?{left:0,top:0}:{left:b.pageX-offset.left-(closestHandle.width()/2),top:b.pageY-offset.top-(closestHandle.height()/2)-(parseInt(closestHandle.css("borderTopWidth"),10)||0)-(parseInt(closestHandle.css("borderBottomWidth"),10)||0)+(parseInt(closestHandle.css("marginTop"),10)||0)};if(!this.handles.hasClass("ui-state-hover")){this._slide(b,index,normValue)}this._animateOff=true;return true},_mouseStart:function(a){return true},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},normValue=this._normValueFromMouse(b);this._slide(a,this._handleIndex,normValue);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._handleIndex=null;this._clickOffset=null;this._animateOff=false;return false},_detectOrientation:function(){this.orientation=(this.options.orientation==="vertical")?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,pixelMouse,percentMouse,valueTotal,valueMouse;if(this.orientation==="horizontal"){b=this.elementSize.width;pixelMouse=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;pixelMouse=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}percentMouse=(pixelMouse/b);if(percentMouse>1){percentMouse=1}if(percentMouse<0){percentMouse=0}if(this.orientation==="vertical"){percentMouse=1-percentMouse}if(this.options.isRTL){percentMouse=1-percentMouse}valueTotal=this._valueMax()-this._valueMin();valueMouse=this._valueMin()+percentMouse*valueTotal;return this._trimAlignValue(valueMouse)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var d,newValues,allowed;if(this.options.values&&this.options.values.length){d=this.values(b?0:1);if((this.options.values.length===2&&this.options.range===true)&&((b===0&&c>d)||(b===1&&c<d))){c=d}if(c!==this.values(b)){newValues=this.values();newValues[b]=c;allowed=this._trigger("slide",a,{handle:this.handles[b],value:c,values:newValues});d=this.values(b?0:1);if(allowed!==false){this.values(b,c,true)}}}else{if(c!==this.value()){allowed=this._trigger("slide",a,{handle:this.handles[b],value:c});if(allowed!==false){this.value(c)}}}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,newValues,i;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length){if($.isArray(arguments[0])){c=this.options.values;newValues=arguments[0];for(i=0;i<c.length;i+=1){c[i]=this._trimAlignValue(newValues[i]);this._change(null,i)}this._refreshValue()}else{if(this.options.values&&this.options.values.length){return this._values(a)}else{return this.value()}}}else{return this._values()}},_setOption:function(a,b){var i,valsLength=0;if($.isArray(this.options.values)){valsLength=this.options.values.length}$.Widget.prototype._setOption.apply(this,arguments);switch(a){case"disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case"orientation":this._detectOrientation();this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case"isRTL":this.element.toggleClass("ui-slider-rtl",b);this._refreshValue();break;case"value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case"values":this._animateOff=true;this._refreshValue();for(i=0;i<valsLength;i+=1){this._change(null,i)}this._animateOff=false;break}},_value:function(){var a=this.options.value;a=this._trimAlignValue(a);return a},_values:function(a){var b,vals,i;if(arguments.length){b=this.options.values[a];b=this._trimAlignValue(b);return b}else{vals=this.options.values.slice();for(i=0;i<vals.length;i+=1){vals[i]=this._trimAlignValue(vals[i])}return vals}},_trimAlignValue:function(a){if(a<=this._valueMin()){return this._valueMin()}if(a>=this._valueMax()){return this._valueMax()}var b=(this.options.step>0)?this.options.step:1,valModStep=(a-this._valueMin())%b;alignValue=a-valModStep;if(Math.abs(valModStep)*2>=b){alignValue+=(valModStep>0)?b:(-b)}return parseFloat(alignValue.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=this.options.range,o=this.options,self=this,animate=(!this._animateOff)?o.animate:false,valPercent,_set={},lastValPercent,value,valueMin,valueMax;if(this.options.values&&this.options.values.length){this.handles.each(function(i,j){valPercent=(self.values(i)-self._valueMin())/(self._valueMax()-self._valueMin())*100;valPercent=(self.options.isRTL?100-valPercent:valPercent);_set[self.orientation==="horizontal"?"left":"bottom"]=valPercent+"%";$(this).stop(1,1)[animate?"animate":"css"](_set,o.animate);if(self.options.range===true){if(self.orientation==="horizontal"){if(i===0){self.range.stop(1,1)[animate?"animate":"css"](self.options.isRTL?{right:(100-valPercent)+"%"}:{left:valPercent+"%"},o.animate)}if(i===1){self.range[animate?"animate":"css"]({width:((self.options.isRTL?-1:+1)*(valPercent-lastValPercent))+"%"},{queue:false,duration:o.animate})}}else{if(i===0){self.range.stop(1,1)[animate?"animate":"css"](self.options.isRTL?{top:(100-valPercent)+"%"}:{bottom:(valPercent)+"%"},o.animate)}if(i===1){self.range[animate?"animate":"css"]({height:((self.options.isRTL?-1:+1)*(valPercent-lastValPercent))+"%"},{queue:false,duration:o.animate})}}}lastValPercent=valPercent})}else{value=this.value();valueMin=this._valueMin();valueMax=this._valueMax();valPercent=(valueMax!==valueMin)?(value-valueMin)/(valueMax-valueMin)*100:0;valPercent=(self.options.isRTL?100-valPercent:valPercent);_set[self.orientation==="horizontal"?"left":"bottom"]=valPercent+"%";this.handle.stop(1,1)[animate?"animate":"css"](_set,o.animate);if(a==="min"&&this.orientation==="horizontal"){this.range.stop(1,1)[animate?"animate":"css"]({width:(self.options.isRTL?100-valPercent:valPercent)+"%"},o.animate)}if(a==="max"&&this.orientation==="horizontal"){this.range[animate?"animate":"css"]({width:(self.options.isRTL?valPercent:100-valPercent)+"%"},{queue:false,duration:o.animate})}if(a==="min"&&this.orientation==="vertical"){this.range.stop(1,1)[animate?"animate":"css"]({height:(self.options.isRTL?100-valPercent:valPercent)+"%"},o.animate)}if(a==="max"&&this.orientation==="vertical"){this.range[animate?"animate":"css"]({height:(self.options.isRTL?valPercent:100-valPercent)+"%"},{queue:false,duration:o.animate})}}}});$.extend($.ui.slider,{version:"1.8.9"})}(jQuery));
admin/includes/fonts_face.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* "Copyright 2012 A3 Revolution Web Design" This software is distributed under the terms of GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 */
3
+ // File Security Check
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+ ?>
6
+ <?php
7
+ /*-----------------------------------------------------------------------------------
8
+ A3rev Plugin Fonts Face
9
+
10
+ TABLE OF CONTENTS
11
+
12
+ - var default_fonts
13
+ - var google_fonts
14
+ - __construct()
15
+ - get_default_fonts()
16
+ - get_google_fonts()
17
+ - generate_font_css()
18
+ - generate_google_webfonts()
19
+
20
+ -----------------------------------------------------------------------------------*/
21
+
22
+ class A3_Lazy_Load_Fonts_Face extends A3_Lazy_Load_Admin_UI
23
+ {
24
+
25
+ /**
26
+ * Window Default Fonts
27
+ */
28
+ public $default_fonts = array(
29
+ 'Arial, sans-serif' => 'Arial',
30
+ 'Verdana, Geneva, sans-serif' => 'Verdana',
31
+ 'Trebuchet MS, Tahoma, sans-serif' => 'Trebuchet',
32
+ 'Georgia, serif' => 'Georgia',
33
+ 'Times New Roman, serif' => 'Times New Roman',
34
+ 'Tahoma, Geneva, Verdana, sans-serif' => 'Tahoma',
35
+ 'Palatino, Palatino Linotype, serif' => 'Palatino',
36
+ 'Helvetica Neue, Helvetica, sans-serif' => 'Helvetica*',
37
+ 'Calibri, Candara, Segoe, Optima, sans-serif' => 'Calibri*',
38
+ 'Myriad Pro, Myriad, sans-serif' => 'Myriad Pro*',
39
+ 'Lucida Grande, Lucida Sans Unicode, Lucida Sans, sans-serif' => 'Lucida',
40
+ 'Arial Black, sans-serif' => 'Arial Black',
41
+ 'Gill Sans, Gill Sans MT, Calibri, sans-serif' => 'Gill Sans*',
42
+ 'Geneva, Tahoma, Verdana, sans-serif' => 'Geneva*',
43
+ 'Impact, Charcoal, sans-serif' => 'Impact',
44
+ 'Courier, Courier New, monospace' => 'Courier',
45
+ 'Century Gothic, sans-serif' => 'Century Gothic',
46
+ );
47
+
48
+ /*-----------------------------------------------------------------------------------*/
49
+ /* Google Webfonts Array */
50
+ /* Documentation:
51
+ /*
52
+ /* name: The name of the Google Font.
53
+ /* variant: The Google Font API variants available for the font.
54
+ /*-----------------------------------------------------------------------------------*/
55
+
56
+ // Available Google webfont names
57
+ public $google_fonts = array( array( 'name' => "Cantarell", 'variant' => ':r,b,i,bi'),
58
+ array( 'name' => "Cardo", 'variant' => ''),
59
+ array( 'name' => "Crimson Text", 'variant' => ''),
60
+ array( 'name' => "Droid Sans", 'variant' => ':r,b'),
61
+ array( 'name' => "Droid Sans Mono", 'variant' => ''),
62
+ array( 'name' => "Droid Serif", 'variant' => ':r,b,i,bi'),
63
+ array( 'name' => "IM Fell DW Pica", 'variant' => ':r,i'),
64
+ array( 'name' => "Inconsolata", 'variant' => ''),
65
+ array( 'name' => "Josefin Sans", 'variant' => ':400,400italic,700,700italic'),
66
+ array( 'name' => "Josefin Slab", 'variant' => ':r,b,i,bi'),
67
+ array( 'name' => "Lobster", 'variant' => ''),
68
+ array( 'name' => "Molengo", 'variant' => ''),
69
+ array( 'name' => "Nobile", 'variant' => ':r,b,i,bi'),
70
+ array( 'name' => "OFL Sorts Mill Goudy TT", 'variant' => ':r,i'),
71
+ array( 'name' => "Old Standard TT", 'variant' => ':r,b,i'),
72
+ array( 'name' => "Reenie Beanie", 'variant' => ''),
73
+ array( 'name' => "Tangerine", 'variant' => ':r,b'),
74
+ array( 'name' => "Vollkorn", 'variant' => ':r,b'),
75
+ array( 'name' => "Yanone Kaffeesatz", 'variant' => ':r,b'),
76
+ array( 'name' => "Cuprum", 'variant' => ''),
77
+ array( 'name' => "Neucha", 'variant' => ''),
78
+ array( 'name' => "Neuton", 'variant' => ''),
79
+ array( 'name' => "PT Sans", 'variant' => ':r,b,i,bi'),
80
+ array( 'name' => "PT Sans Caption", 'variant' => ':r,b'),
81
+ array( 'name' => "PT Sans Narrow", 'variant' => ':r,b'),
82
+ array( 'name' => "Philosopher", 'variant' => ''),
83
+ array( 'name' => "Allerta", 'variant' => ''),
84
+ array( 'name' => "Allerta Stencil", 'variant' => ''),
85
+ array( 'name' => "Arimo", 'variant' => ':r,b,i,bi'),
86
+ array( 'name' => "Arvo", 'variant' => ':r,b,i,bi'),
87
+ array( 'name' => "Bentham", 'variant' => ''),
88
+ array( 'name' => "Coda", 'variant' => ':800'),
89
+ array( 'name' => "Cousine", 'variant' => ''),
90
+ array( 'name' => "Covered By Your Grace", 'variant' => ''),
91
+ array( 'name' => "Geo", 'variant' => ''),
92
+ array( 'name' => "Just Me Again Down Here", 'variant' => ''),
93
+ array( 'name' => "Puritan", 'variant' => ':r,b,i,bi'),
94
+ array( 'name' => "Raleway", 'variant' => ':100'),
95
+ array( 'name' => "Tinos", 'variant' => ':r,b,i,bi'),
96
+ array( 'name' => "UnifrakturCook", 'variant' => ':bold'),
97
+ array( 'name' => "UnifrakturMaguntia", 'variant' => ''),
98
+ array( 'name' => "Mountains of Christmas", 'variant' => ''),
99
+ array( 'name' => "Lato", 'variant' => ':400,700,400italic'),
100
+ array( 'name' => "Orbitron", 'variant' => ':r,b,i,bi'),
101
+ array( 'name' => "Allan", 'variant' => ':bold'),
102
+ array( 'name' => "Anonymous Pro", 'variant' => ':r,b,i,bi'),
103
+ array( 'name' => "Copse", 'variant' => ''),
104
+ array( 'name' => "Kenia", 'variant' => ''),
105
+ array( 'name' => "Ubuntu", 'variant' => ':r,b,i,bi'),
106
+ array( 'name' => "Vibur", 'variant' => ''),
107
+ array( 'name' => "Sniglet", 'variant' => ':800'),
108
+ array( 'name' => "Syncopate", 'variant' => ''),
109
+ array( 'name' => "Cabin", 'variant' => ':400,400italic,700,700italic,'),
110
+ array( 'name' => "Merriweather", 'variant' => ''),
111
+ array( 'name' => "Maiden Orange", 'variant' => ''),
112
+ array( 'name' => "Just Another Hand", 'variant' => ''),
113
+ array( 'name' => "Kristi", 'variant' => ''),
114
+ array( 'name' => "Corben", 'variant' => ':b'),
115
+ array( 'name' => "Gruppo", 'variant' => ''),
116
+ array( 'name' => "Buda", 'variant' => ':light'),
117
+ array( 'name' => "Lekton", 'variant' => ''),
118
+ array( 'name' => "Luckiest Guy", 'variant' => ''),
119
+ array( 'name' => "Crushed", 'variant' => ''),
120
+ array( 'name' => "Chewy", 'variant' => ''),
121
+ array( 'name' => "Coming Soon", 'variant' => ''),
122
+ array( 'name' => "Crafty Girls", 'variant' => ''),
123
+ array( 'name' => "Fontdiner Swanky", 'variant' => ''),
124
+ array( 'name' => "Permanent Marker", 'variant' => ''),
125
+ array( 'name' => "Rock Salt", 'variant' => ''),
126
+ array( 'name' => "Sunshiney", 'variant' => ''),
127
+ array( 'name' => "Unkempt", 'variant' => ''),
128
+ array( 'name' => "Calligraffitti", 'variant' => ''),
129
+ array( 'name' => "Cherry Cream Soda", 'variant' => ''),
130
+ array( 'name' => "Homemade Apple", 'variant' => ''),
131
+ array( 'name' => "Irish Growler", 'variant' => ''),
132
+ array( 'name' => "Kranky", 'variant' => ''),
133
+ array( 'name' => "Schoolbell", 'variant' => ''),
134
+ array( 'name' => "Slackey", 'variant' => ''),
135
+ array( 'name' => "Walter Turncoat", 'variant' => ''),
136
+ array( 'name' => "Radley", 'variant' => ''),
137
+ array( 'name' => "Meddon", 'variant' => ''),
138
+ array( 'name' => "Kreon", 'variant' => ':r,b'),
139
+ array( 'name' => "Dancing Script", 'variant' => ''),
140
+ array( 'name' => "Goudy Bookletter 1911", 'variant' => ''),
141
+ array( 'name' => "PT Serif Caption", 'variant' => ':r,i'),
142
+ array( 'name' => "PT Serif", 'variant' => ':r,b,i,bi'),
143
+ array( 'name' => "Astloch", 'variant' => ':b'),
144
+ array( 'name' => "Bevan", 'variant' => ''),
145
+ array( 'name' => "Anton", 'variant' => ''),
146
+ array( 'name' => "Expletus Sans", 'variant' => ':b'),
147
+ array( 'name' => "VT323", 'variant' => ''),
148
+ array( 'name' => "Pacifico", 'variant' => ''),
149
+ array( 'name' => "Candal", 'variant' => ''),
150
+ array( 'name' => "Architects Daughter", 'variant' => ''),
151
+ array( 'name' => "Indie Flower", 'variant' => ''),
152
+ array( 'name' => "League Script", 'variant' => ''),
153
+ array( 'name' => "Quattrocento", 'variant' => ''),
154
+ array( 'name' => "Amaranth", 'variant' => ''),
155
+ array( 'name' => "Irish Grover", 'variant' => ''),
156
+ array( 'name' => "Oswald", 'variant' => ':400,300,700'),
157
+ array( 'name' => "EB Garamond", 'variant' => ''),
158
+ array( 'name' => "Nova Round", 'variant' => ''),
159
+ array( 'name' => "Nova Slim", 'variant' => ''),
160
+ array( 'name' => "Nova Script", 'variant' => ''),
161
+ array( 'name' => "Nova Cut", 'variant' => ''),
162
+ array( 'name' => "Nova Mono", 'variant' => ''),
163
+ array( 'name' => "Nova Oval", 'variant' => ''),
164
+ array( 'name' => "Nova Flat", 'variant' => ''),
165
+ array( 'name' => "Terminal Dosis Light", 'variant' => ''),
166
+ array( 'name' => "Michroma", 'variant' => ''),
167
+ array( 'name' => "Miltonian", 'variant' => ''),
168
+ array( 'name' => "Miltonian Tattoo", 'variant' => ''),
169
+ array( 'name' => "Annie Use Your Telescope", 'variant' => ''),
170
+ array( 'name' => "Dawning of a New Day", 'variant' => ''),
171
+ array( 'name' => "Sue Ellen Francisco", 'variant' => ''),
172
+ array( 'name' => "Waiting for the Sunrise", 'variant' => ''),
173
+ array( 'name' => "Special Elite", 'variant' => ''),
174
+ array( 'name' => "Quattrocento Sans", 'variant' => ''),
175
+ array( 'name' => "Smythe", 'variant' => ''),
176
+ array( 'name' => "The Girl Next Door", 'variant' => ''),
177
+ array( 'name' => "Aclonica", 'variant' => ''),
178
+ array( 'name' => "News Cycle", 'variant' => ''),
179
+ array( 'name' => "Damion", 'variant' => ''),
180
+ array( 'name' => "Wallpoet", 'variant' => ''),
181
+ array( 'name' => "Over the Rainbow", 'variant' => ''),
182
+ array( 'name' => "MedievalSharp", 'variant' => ''),
183
+ array( 'name' => "Six Caps", 'variant' => ''),
184
+ array( 'name' => "Swanky and Moo Moo", 'variant' => ''),
185
+ array( 'name' => "Bigshot One", 'variant' => ''),
186
+ array( 'name' => "Francois One", 'variant' => ''),
187
+ array( 'name' => "Sigmar One", 'variant' => ''),
188
+ array( 'name' => "Carter One", 'variant' => ''),
189
+ array( 'name' => "Holta3revd One SC", 'variant' => ''),
190
+ array( 'name' => "Paytone One", 'variant' => ''),
191
+ array( 'name' => "Monofett", 'variant' => ''),
192
+ array( 'name' => "Rokkitt", 'variant' => ':400,700'),
193
+ array( 'name' => "Megrim", 'variant' => ''),
194
+ array( 'name' => "Judson", 'variant' => ':r,ri,b'),
195
+ array( 'name' => "Didact Gothic", 'variant' => ''),
196
+ array( 'name' => "Play", 'variant' => ':r,b'),
197
+ array( 'name' => "Ultra", 'variant' => ''),
198
+ array( 'name' => "Metrophobic", 'variant' => ''),
199
+ array( 'name' => "Mako", 'variant' => ''),
200
+ array( 'name' => "Shanti", 'variant' => ''),
201
+ array( 'name' => "Caudex", 'variant' => ':r,b,i,bi'),
202
+ array( 'name' => "Jura", 'variant' => ''),
203
+ array( 'name' => "Ruslan Display", 'variant' => ''),
204
+ array( 'name' => "Brawler", 'variant' => ''),
205
+ array( 'name' => "Nunito", 'variant' => ''),
206
+ array( 'name' => "Wire One", 'variant' => ''),
207
+ array( 'name' => "Podkova", 'variant' => ''),
208
+ array( 'name' => "Muli", 'variant' => ''),
209
+ array( 'name' => "Maven Pro", 'variant' => ':400,500,700'),
210
+ array( 'name' => "Tenor Sans", 'variant' => ''),
211
+ array( 'name' => "Limelight", 'variant' => ''),
212
+ array( 'name' => "Playfair Display", 'variant' => ''),
213
+ array( 'name' => "Artifika", 'variant' => ''),
214
+ array( 'name' => "Lora", 'variant' => ''),
215
+ array( 'name' => "Kameron", 'variant' => ':r,b'),
216
+ array( 'name' => "Cedarville Cursive", 'variant' => ''),
217
+ array( 'name' => "Zeyada", 'variant' => ''),
218
+ array( 'name' => "La Belle Aurore", 'variant' => ''),
219
+ array( 'name' => "Shadows Into Light", 'variant' => ''),
220
+ array( 'name' => "Lobster Two", 'variant' => ':r,b,i,bi'),
221
+ array( 'name' => "Nixie One", 'variant' => ''),
222
+ array( 'name' => "Redressed", 'variant' => ''),
223
+ array( 'name' => "Bangers", 'variant' => ''),
224
+ array( 'name' => "Open Sans Condensed", 'variant' => ':300italic,400italic,700italic,400,300,700'),
225
+ array( 'name' => "Open Sans", 'variant' => ':r,i,b,bi'),
226
+ array( 'name' => "Varela", 'variant' => ''),
227
+ array( 'name' => "Goblin One", 'variant' => ''),
228
+ array( 'name' => "Asset", 'variant' => ''),
229
+ array( 'name' => "Gravitas One", 'variant' => ''),
230
+ array( 'name' => "Hammersmith One", 'variant' => ''),
231
+ array( 'name' => "Stardos Stencil", 'variant' => ''),
232
+ array( 'name' => "Love Ya Like A Sister", 'variant' => ''),
233
+ array( 'name' => "Loved by the King", 'variant' => ''),
234
+ array( 'name' => "Bowlby One SC", 'variant' => ''),
235
+ array( 'name' => "Forum", 'variant' => ''),
236
+ array( 'name' => "Patrick Hand", 'variant' => ''),
237
+ array( 'name' => "Varela Round", 'variant' => ''),
238
+ array( 'name' => "Yeseva One", 'variant' => ''),
239
+ array( 'name' => "Give You Glory", 'variant' => ''),
240
+ array( 'name' => "Modern Antiqua", 'variant' => ''),
241
+ array( 'name' => "Bowlby One", 'variant' => ''),
242
+ array( 'name' => "Tienne", 'variant' => ''),
243
+ array( 'name' => "Istok Web", 'variant' => ':r,b,i,bi'),
244
+ array( 'name' => "Yellowtail", 'variant' => ''),
245
+ array( 'name' => "Pompiere", 'variant' => ''),
246
+ array( 'name' => "Unna", 'variant' => ''),
247
+ array( 'name' => "Rosario", 'variant' => ''),
248
+ array( 'name' => "Leckerli One", 'variant' => ''),
249
+ array( 'name' => "Snippet", 'variant' => ''),
250
+ array( 'name' => "Ovo", 'variant' => ''),
251
+ array( 'name' => "IM Fell English", 'variant' => ':r,i'),
252
+ array( 'name' => "IM Fell English SC", 'variant' => ''),
253
+ array( 'name' => "Gloria Hallelujah", 'variant' => ''),
254
+ array( 'name' => "Kelly Slab", 'variant' => ''),
255
+ array( 'name' => "Black Ops One", 'variant' => ''),
256
+ array( 'name' => "Carme", 'variant' => ''),
257
+ array( 'name' => "Aubrey", 'variant' => ''),
258
+ array( 'name' => "Federo", 'variant' => ''),
259
+ array( 'name' => "Delius", 'variant' => ''),
260
+ array( 'name' => "Rochester", 'variant' => ''),
261
+ array( 'name' => "Rationale", 'variant' => ''),
262
+ array( 'name' => "Abel", 'variant' => ''),
263
+ array( 'name' => "Marvel", 'variant' => ':r,b,i,bi'),
264
+ array( 'name' => "Actor", 'variant' => ''),
265
+ array( 'name' => "Delius Swash Caps", 'variant' => ''),
266
+ array( 'name' => "Smokum", 'variant' => ''),
267
+ array( 'name' => "Tulpen One", 'variant' => ''),
268
+ array( 'name' => "Coustard", 'variant' => ':r,b'),
269
+ array( 'name' => "Andika", 'variant' => ''),
270
+ array( 'name' => "Alice", 'variant' => ''),
271
+ array( 'name' => "Questrial", 'variant' => ''),
272
+ array( 'name' => "Comfortaa", 'variant' => ':r,b'),
273
+ array( 'name' => "Geostar", 'variant' => ''),
274
+ array( 'name' => "Geostar Fill", 'variant' => ''),
275
+ array( 'name' => "Volkhov", 'variant' => ''),
276
+ array( 'name' => "Voltaire", 'variant' => ''),
277
+ array( 'name' => "Montez", 'variant' => ''),
278
+ array( 'name' => "Short Stack", 'variant' => ''),
279
+ array( 'name' => "Vidaloka", 'variant' => ''),
280
+ array( 'name' => "Aldrich", 'variant' => ''),
281
+ array( 'name' => "Numans", 'variant' => ''),
282
+ array( 'name' => "Days One", 'variant' => ''),
283
+ array( 'name' => "Gentium Book Basic", 'variant' => ''),
284
+ array( 'name' => "Monoton", 'variant' => ''),
285
+ array( 'name' => "Alike", 'variant' => ''),
286
+ array( 'name' => "Delius Unicase", 'variant' => ''),
287
+ array( 'name' => "Abril Fatface", 'variant' => ''),
288
+ array( 'name' => "Dorsa", 'variant' => ''),
289
+ array( 'name' => "Antic", 'variant' => ''),
290
+ array( 'name' => "Passero One", 'variant' => ''),
291
+ array( 'name' => "Fana3revd Text", 'variant' => ''),
292
+ array( 'name' => "Prociono", 'variant' => ''),
293
+ array( 'name' => "Merienda One", 'variant' => ''),
294
+ array( 'name' => "Changa One", 'variant' => ''),
295
+ array( 'name' => "Julee", 'variant' => ''),
296
+ array( 'name' => "Prata", 'variant' => ''),
297
+ array( 'name' => "Adamina", 'variant' => ''),
298
+ array( 'name' => "Sorts Mill Goudy", 'variant' => ''),
299
+ array( 'name' => "Terminal Dosis", 'variant' => ''),
300
+ array( 'name' => "Sansita One", 'variant' => ''),
301
+ array( 'name' => "Chivo", 'variant' => ''),
302
+ array( 'name' => "Spinnaker", 'variant' => ''),
303
+ array( 'name' => "Poller One", 'variant' => ''),
304
+ array( 'name' => "Alike Angular", 'variant' => ''),
305
+ array( 'name' => "Gochi Hand", 'variant' => ''),
306
+ array( 'name' => "Poly", 'variant' => ''),
307
+ array( 'name' => "Andada", 'variant' => ''),
308
+ array( 'name' => "Federant", 'variant' => ''),
309
+ array( 'name' => "Ubuntu Condensed", 'variant' => ''),
310
+ array( 'name' => "Ubuntu Mono", 'variant' => ''),
311
+ array( 'name' => "Sancreek", 'variant' => ''),
312
+ array( 'name' => "Coda", 'variant' => ''),
313
+ array( 'name' => "Rancho", 'variant' => ''),
314
+ array( 'name' => "Satisfy", 'variant' => ''),
315
+ array( 'name' => "Pinyon Script", 'variant' => ''),
316
+ array( 'name' => "Vast Shadow", 'variant' => ''),
317
+ array( 'name' => "Marck Script", 'variant' => ''),
318
+ array( 'name' => "Salsa", 'variant' => ''),
319
+ array( 'name' => "Amatic SC", 'variant' => ''),
320
+ array( 'name' => "Quicksand", 'variant' => ''),
321
+ array( 'name' => "Linden Hill", 'variant' => ''),
322
+ array( 'name' => "Corben", 'variant' => ''),
323
+ array( 'name' => "Creepster Caps", 'variant' => ''),
324
+ array( 'name' => "Butcherman Caps", 'variant' => ''),
325
+ array( 'name' => "Eater Caps", 'variant' => ''),
326
+ array( 'name' => "Nosifer Caps", 'variant' => ''),
327
+ array( 'name' => "Atomic Age", 'variant' => ''),
328
+ array( 'name' => "Contrail One", 'variant' => ''),
329
+ array( 'name' => "Jockey One", 'variant' => ''),
330
+ array( 'name' => "Cabin Sketch", 'variant' => ':r,b'),
331
+ array( 'name' => "Cabin Condensed", 'variant' => ':r,b'),
332
+ array( 'name' => "Fjord One", 'variant' => ''),
333
+ array( 'name' => "Rametto One", 'variant' => ''),
334
+ array( 'name' => "Mate", 'variant' => ':r,i'),
335
+ array( 'name' => "Mate SC", 'variant' => ''),
336
+ array( 'name' => "Arapey", 'variant' => ':r,i'),
337
+ array( 'name' => "Supermercado One", 'variant' => ''),
338
+ array( 'name' => "Petrona", 'variant' => ''),
339
+ array( 'name' => "Lancelot", 'variant' => ''),
340
+ array( 'name' => "Convergence", 'variant' => ''),
341
+ array( 'name' => "Cutive", 'variant' => ''),
342
+ array( 'name' => "Karla", 'variant' => ':400,400italic,700,700italic'),
343
+ array( 'name' => "Bitter", 'variant' => ':r,i,b'),
344
+ array( 'name' => "Asap", 'variant' => ':400,700,400italic,700italic'),
345
+ array( 'name' => "Bree Serif", 'variant' => '')
346
+
347
+ );
348
+
349
+ /*-----------------------------------------------------------------------------------*/
350
+ /* Fonts Face Constructor */
351
+ /*-----------------------------------------------------------------------------------*/
352
+ public function __construct() {
353
+ $google_fonts = apply_filters( $this->plugin_name . '_google_fonts', $this->google_fonts );
354
+
355
+ sort( $google_fonts );
356
+
357
+ $new_google_fonts = array();
358
+ foreach ( $google_fonts as $row ) {
359
+ $new_google_fonts[$row['name']] = $row;
360
+ }
361
+
362
+ $this->google_fonts = $new_google_fonts;
363
+
364
+ }
365
+
366
+ /*-----------------------------------------------------------------------------------*/
367
+ /* Get Window Default Fonts */
368
+ /*-----------------------------------------------------------------------------------*/
369
+ public function get_default_fonts() {
370
+ $default_fonts = apply_filters( $this->plugin_name . '_default_fonts', $this->default_fonts );
371
+
372
+ asort( $default_fonts );
373
+
374
+ return $default_fonts;
375
+ }
376
+
377
+ /*-----------------------------------------------------------------------------------*/
378
+ /* Get Google Fonts */
379
+ /*-----------------------------------------------------------------------------------*/
380
+ public function get_google_fonts() {
381
+
382
+ return $this->google_fonts;
383
+ }
384
+
385
+ /*-----------------------------------------------------------------------------------*/
386
+ /* generate_font_css() */
387
+ /* Generate font CSS for frontend */
388
+ /*-----------------------------------------------------------------------------------*/
389
+ public function generate_font_css( $option, $em = '1.2' ) {
390
+ $google_fonts = $this->get_google_fonts();
391
+
392
+ if ( array_key_exists( $option['face'], $google_fonts ) ) {
393
+ $option['face'] = "'" . $option['face'] . "', arial, sans-serif";
394
+ }
395
+
396
+ if ( !@$option['style'] && !@$option['size'] && !@$option['color'] )
397
+ return 'font-family: '.stripslashes($option["face"]).' !important;';
398
+ else
399
+ return 'font:'.$option['style'].' '.$option['size'].' '.stripslashes($option['face']).' !important; color:'.$option['color'].' !important;';
400
+ }
401
+
402
+
403
+ /*-----------------------------------------------------------------------------------*/
404
+ /* Google Webfonts Stylesheet Generator */
405
+ /*-----------------------------------------------------------------------------------*/
406
+ /*
407
+ INSTRUCTIONS: Needs to be loaded for the Google Fonts options to work for font options.
408
+
409
+ add_action( 'wp_head', array( $this, 'generate_google_webfonts' ) );
410
+ */
411
+ public function generate_google_webfonts( $my_google_fonts = array(), $echo = true ) {
412
+ $google_fonts = $this->get_google_fonts();
413
+
414
+ $fonts = '';
415
+ $output = '';
416
+
417
+ // Go through the options
418
+ if ( is_array( $my_google_fonts ) ) {
419
+ foreach ( $my_google_fonts as $font_face ) {
420
+ // Check if the google font name exists in the current "face" option
421
+ if ( array_key_exists( $font_face, $google_fonts ) && !strstr( $fonts, $font_face ) ) {
422
+ $fonts .= $google_fonts[$font_face]['name'].$google_fonts[$font_face]['variant']."|";
423
+ }
424
+ } // End Foreach Loop
425
+
426
+ // Output google font css in header
427
+ if ( trim( $fonts ) != '' ) {
428
+ $fonts = str_replace( " ","+",$fonts);
429
+ $output .= "\n<!-- Google Webfonts -->\n";
430
+ $output .= '<link href="http'. ( is_ssl() ? 's' : '' ) .'://fonts.googleapis.com/css?family=' . $fonts .'" rel="stylesheet" type="text/css" />'."\n";
431
+ $output = str_replace( '|"','"',$output);
432
+ }
433
+ }
434
+
435
+ if ( $echo )
436
+ echo $output;
437
+ else
438
+ return $output;
439
+
440
+ } // End generate_google_webfonts()
441
+
442
+ }
443
+
444
+ global $a3_lazy_load_fonts_face;
445
+ $a3_lazy_load_fonts_face = new A3_Lazy_Load_Fonts_Face();
admin/includes/uploader/class-uploader.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /* "Copyright 2012 a3 Revolution Web Design" This software is distributed under the terms of GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 */
3
+ // File Security Check
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
5
+ ?>
6
+ <?php
7
+ /*-----------------------------------------------------------------------------------
8
+ A3rev Plugin Uploader
9
+
10
+ TABLE OF CONTENTS
11
+
12
+ - var admin_uploader_url
13
+ - __construct()
14
+ - admin_uploader_url()
15
+ - uploader_js()
16
+ - uploader_style()
17
+ - uploader_init()
18
+ - get_silentpost()
19
+ - upload_input()
20
+ - change_button_text()
21
+ - modify_tabs()
22
+ - inside_popup()
23
+
24
+ -----------------------------------------------------------------------------------*/
25
+ class A3_Lazy_Load_Uploader extends A3_Lazy_Load_Admin_UI
26
+ {
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ private $admin_uploader_url;
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ private $custom_post_type_image = 'wp_email_images';
37
+
38
+ /**
39
+ * @var string
40
+ */
41
+ private $custom_post_type_name = 'Custom Image Type For Uploader';
42
+
43
+ /*-----------------------------------------------------------------------------------*/
44
+ /* Admin Uploader Constructor */
45
+ /*-----------------------------------------------------------------------------------*/
46
+ public function __construct() {
47
+ if ( is_admin() ) {
48
+ add_action( 'init', array( $this, 'uploader_init' ) );
49
+ add_action( 'admin_print_scripts', array( $this, 'inside_popup' ) );
50
+ add_filter( 'gettext', array( $this, 'change_button_text' ), null, 3 );
51
+
52
+ // include scripts to Admin UI Interface
53
+ add_action( $this->plugin_name . '_init_scripts', array( $this, 'uploader_js' ) );
54
+
55
+ // include styles to Admin UI Interface
56
+ add_action( $this->plugin_name . '_init_styles', array( $this, 'uploader_style' ) );
57
+ }
58
+
59
+ }
60
+
61
+ /*-----------------------------------------------------------------------------------*/
62
+ /* admin_uploader_url */
63
+ /*-----------------------------------------------------------------------------------*/
64
+ public function admin_uploader_url() {
65
+ if ( $this->admin_uploader_url ) return $this->admin_uploader_url;
66
+ return $this->admin_uploader_url = untrailingslashit( plugins_url( '/', __FILE__ ) );
67
+ }
68
+
69
+ /*-----------------------------------------------------------------------------------*/
70
+ /* Include Uploader Script */
71
+ /*-----------------------------------------------------------------------------------*/
72
+ public function uploader_js () {
73
+ wp_enqueue_script( 'jquery' );
74
+ wp_enqueue_script( 'thickbox' );
75
+ wp_enqueue_script( 'a3-uploader-script', $this->admin_uploader_url() . '/uploader-script.js' );
76
+ wp_enqueue_script( 'media-upload' );
77
+ }
78
+
79
+ /*-----------------------------------------------------------------------------------*/
80
+ /* Include Uploader Style */
81
+ /*-----------------------------------------------------------------------------------*/
82
+ public function uploader_style () {
83
+ wp_enqueue_style( 'thickbox' );
84
+ wp_enqueue_style( 'a3-uploader-style', $this->admin_uploader_url() . '/uploader.css' );
85
+ if ( is_rtl() ) {
86
+ wp_enqueue_style( 'a3-uploader-style-rtl', $this->admin_uploader_url() . '/uploader.rtl.css' );
87
+ }
88
+ }
89
+
90
+ /*-----------------------------------------------------------------------------------*/
91
+ /* Uploader Init : Create Custom Post for Image */
92
+ /*-----------------------------------------------------------------------------------*/
93
+ public function uploader_init () {
94
+ register_post_type( $this->custom_post_type_image, array(
95
+ 'labels' => array(
96
+ 'name' => $this->custom_post_type_name,
97
+ ),
98
+ 'public' => true,
99
+ 'show_ui' => false,
100
+ 'capability_type' => 'post',
101
+ 'hierarchical' => false,
102
+ 'rewrite' => false,
103
+ 'supports' => array( 'title', 'editor' ),
104
+ 'query_var' => false,
105
+ 'can_export' => true,
106
+ 'show_in_nav_menus' => false
107
+ ) );
108
+ }
109
+
110
+ /*-----------------------------------------------------------------------------------*/
111
+ /* Get Post Id of Custom Post for Image */
112
+ /*-----------------------------------------------------------------------------------*/
113
+ public function get_silentpost ( $option_key = '' ) {
114
+ global $wpdb;
115
+ $post_id = 1;
116
+ if ( $option_key != '' ) {
117
+ $args = array(
118
+ 'post_parent' => '0',
119
+ 'post_type' => $this->custom_post_type_image,
120
+ 'post_name' => $option_key,
121
+ 'post_status' => 'draft',
122
+ 'comment_status' => 'closed',
123
+ 'ping_status' => 'closed'
124
+ );
125
+ $my_posts = get_posts( $args );
126
+ if ( $my_posts ) {
127
+ foreach ($my_posts as $my_post) {
128
+ $post_id = $my_post->ID;
129
+ break;
130
+ }
131
+ } else {
132
+ $args['post_title'] = str_replace('_', ' ', $option_key);
133
+ $post_id = wp_insert_post( $args );
134
+ }
135
+ }
136
+ return $post_id;
137
+ }
138
+
139
+ /*-----------------------------------------------------------------------------------*/
140
+ /* Get Upload Input Field */
141
+ /*-----------------------------------------------------------------------------------*/
142
+ public function upload_input ( $name_attribute, $id_attribute = '', $value = '', $default_value = '', $field_name = '', $class = '', $css = '', $description = '', $post_id = 0 ) {
143
+ $output = '';
144
+
145
+ if ( $post_id == 0 ) {
146
+ $post_id = $this->get_silentpost( $id_attribute );
147
+ }
148
+
149
+ if ( trim( $value ) == '' ) $value = trim( $default_value );
150
+
151
+ $output .= '<input type="text" name="'.$name_attribute.'" id="'.$id_attribute.'" value="'.esc_attr( $value ).'" class="'.$id_attribute. ' ' .$class.' a3_upload" style="'.$css.'" rel="'.$field_name.'" /> ';
152
+ $output .= '<input id="upload_'.$id_attribute.'" class="a3rev-ui-upload-button a3_upload_button button" type="button" value="'.__( 'Upload', 'a3_lazy_load' ).'" rel="'.$post_id.'" /> '.$description;
153
+
154
+ $output .= '<div style="clear:both;"></div><div class="a3_screenshot" id="'.$id_attribute.'_image" style="'.( ( $value == '' ) ? 'display:none;' : 'display:block;' ).'">';
155
+
156
+ if ( $value != '' ) {
157
+ $remove = '<a href="javascript:(void);" class="a3_uploader_remove a3-plugin-ui-delete-icon">&nbsp;</a>';
158
+
159
+ $image = preg_match( '/(^.*\.jpg|jpeg|png|gif|ico*)/i', $value );
160
+
161
+ if ( $image ) {
162
+ $output .= '<img class="a3_uploader_image" src="' . esc_url( $value ) . '" alt="" />'.$remove.'';
163
+ } else {
164
+ $parts = explode( "/", $value );
165
+
166
+ for( $i = 0; $i < sizeof( $parts ); ++$i ) {
167
+ $title = $parts[$i];
168
+ }
169
+
170
+ $output .= '';
171
+
172
+ $title = __( 'View File', 'a3_lazy_load' );
173
+
174
+ $output .= '<div class="a3_no_image"><span class="a3_file_link"><a href="'.esc_url( $value ).'" target="_blank" rel="a3_external">'.$title.'</a></span>'.$remove.'</div>';
175
+
176
+ }
177
+ }
178
+
179
+ $output .= '</div>';
180
+
181
+ return $output;
182
+ }
183
+
184
+ /*-----------------------------------------------------------------------------------*/
185
+ /* Change the Button text on image popup */
186
+ /*-----------------------------------------------------------------------------------*/
187
+ public function change_button_text( $translation, $original, $domain ) {
188
+ if ( isset( $_REQUEST['type'] ) ) { return $translation; }
189
+
190
+ if ( is_admin() && $original === 'Insert into Post' ) {
191
+ $translation = __( 'Use this Image', 'a3_lazy_load' );
192
+ if ( isset( $_REQUEST['title'] ) && $_REQUEST['title'] != '' ) { $translation =__( 'Use as', 'a3_lazy_load' ).' '.esc_attr( $_REQUEST['title'] ); }
193
+ }
194
+
195
+ return $translation;
196
+ }
197
+
198
+ /*-----------------------------------------------------------------------------------*/
199
+ /* modify_tabs */
200
+ /*-----------------------------------------------------------------------------------*/
201
+ public function modify_tabs ( $tabs ) {
202
+ if ( isset( $tabs['gallery'] ) ) { $tabs['gallery'] = str_replace( 'Gallery', __( 'Previously Uploaded', 'a3_lazy_load' ), $tabs['gallery'] ); }
203
+ return $tabs;
204
+ }
205
+
206
+ /*-----------------------------------------------------------------------------------*/
207
+ /* inside_popup */
208
+ /*-----------------------------------------------------------------------------------*/
209
+ public function inside_popup () {
210
+ if ( isset( $_REQUEST['a3_uploader'] ) && $_REQUEST['a3_uploader'] == 'yes' ) {
211
+ add_filter( 'media_upload_tabs', array( $this, 'modify_tabs' ) );
212
+ }
213
+ }
214
+
215
+ }
216
+
217
+ global $a3_lazy_load_uploader;
218
+ $a3_lazy_load_uploader = new A3_Lazy_Load_Uploader();
219
+
220
+ ?>
admin/includes/uploader/delete.png ADDED
Binary file
admin/includes/uploader/mixins.less ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @green: green;
2
+ @red: red;
3
+ @orange: orange;
4
+ @blue: blue;
5
+ @yellow: yellow;
6
+ @white: white;
7
+ @black: black;
8
+
9
+ .clearfix() {
10
+ *zoom:1;
11
+ &:before,
12
+ &:after {
13
+ content: " ";
14
+ display: table;
15
+ }
16
+ &:after {
17
+ clear: both;
18
+ }
19
+ }
20
+ .border_radius(@radius:4px) {
21
+ -webkit-border-radius:@radius;
22
+ border-radius:@radius;
23
+ }
24
+ .border_radius_corner(@topleft:4px, @topright:4px, @bottomleft:4px, @bottomright:4px) {
25
+ -webkit-border-top-left-radius: @topleft;
26
+ border-top-left-radius: @topleft;
27
+ -webkit-border-top-right-radius: @topright;
28
+ border-top-right-radius: @topright;
29
+ -webkit-border-bottom-left-radius: @bottomleft;
30
+ border-bottom-left-radius: @bottomleft;
31
+ -webkit-border-bottom-right-radius: @bottomright;
32
+ border-bottom-right-radius: @bottomright;
33
+ }
34
+
35
+ .border_radius_top_left(@radius:4px) {
36
+ -webkit-border-top-left-radius: @radius;
37
+ border-top-left-radius: @radius;
38
+ }
39
+ .border_radius_top_right(@radius:4px) {
40
+ -webkit-border-top-right-radius: @radius;
41
+ border-top-right-radius: @radius;
42
+ }
43
+ .border_radius_bottom_left(@radius:4px) {
44
+ -webkit-border-bottom-left-radius: @radius;
45
+ border-bottom-left-radius: @radius;
46
+ }
47
+ .border_radius_bottom_right(@radius:4px) {
48
+ -webkit-border-bottom-right-radius: @radius;
49
+ border-bottom-right-radius: @radius;
50
+ }
51
+
52
+ .border_radius_right(@radius:4px) {
53
+ -webkit-border-top-right-radius: @radius;
54
+ -webkit-border-bottom-right-radius: @radius;
55
+ border-top-right-radius: @radius;
56
+ border-bottom-right-radius: @radius;
57
+ }
58
+ .border_radius_left(@radius:4px) {
59
+ -webkit-border-top-left-radius: @radius;
60
+ -webkit-border-bottom-left-radius: @radius;
61
+ border-top-left-radius: @radius;
62
+ border-bottom-left-radius: @radius;
63
+ }
64
+ .border_radius_bottom(@radius:4px) {
65
+ -webkit-border-bottom-left-radius: @radius;
66
+ -webkit-border-bottom-right-radius: @radius;
67
+ border-bottom-left-radius: @radius;
68
+ border-bottom-right-radius: @radius;
69
+ }
70
+ .border_radius_top(@radius:4px) {
71
+ -webkit-border-top-left-radius: @radius;
72
+ -webkit-border-top-right-radius: @radius;
73
+ border-top-left-radius: @radius;
74
+ border-top-right-radius: @radius;
75
+ }
76
+ .opacity(@opacity:0.75) {
77
+ filter:~"alpha(opacity=@opacity * 100)";
78
+ -moz-opacity:@opacity;
79
+ -khtml-opacity: @opacity;
80
+ opacity: @opacity;
81
+ }
82
+ .box_shadow_none() {
83
+ box-shadow: none;
84
+ -moz-box-shadow: none;
85
+ -webkit-box-shadow: none;
86
+ }
87
+ .box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
88
+ box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
89
+ -webkit-box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
90
+ }
91
+ .inset_box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
92
+ box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
93
+ -webkit-box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
94
+ }
95
+ .text_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_color:#fff) {
96
+ text-shadow:@shadow_x @shadow_y @shadow_rad @shadow_color;
97
+ }
98
+ .vertical_gradient(@from: #000, @to: #FFF) {
99
+ background: @from;
100
+ background: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to));
101
+ background: -webkit-linear-gradient(@from, @to);
102
+ background: -moz-linear-gradient(center top, @from 0%, @to 100%);
103
+ background: -moz-gradient(center top, @from 0%, @to 100%);
104
+ }
105
+ .transition(@selector:all, @animation:ease-in-out, @duration:.2s) {
106
+ -webkit-transition:@selector @animation @duration;
107
+ -moz-transition:@selector @animation @duration;
108
+ -o-transition:@selector @animation @duration;
109
+ transition:@selector @animation @duration;
110
+ }
111
+
112
+ .scale(@ratio:1.5){
113
+ -webkit-transform:scale(@ratio);
114
+ -moz-transform:scale(@ratio);
115
+ -ms-transform:scale(@ratio);
116
+ -o-transform:scale(@ratio);
117
+ transform:scale(@ratio);
118
+ }
119
+
120
+ .borderbox () {
121
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
122
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
123
+ box-sizing: border-box; /* Opera/IE 8+ */
124
+ }
125
+
126
+ .clear { clear: both; }
127
+ .nobr { white-space: nowrap; }
128
+
129
+ .darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) >= 65%) { .text_shadow( 0, -1px, 0, rgba(0,0,0,@opacity) ); }
130
+ .darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) < 65%) { .text_shadow( 0, 1px, 0, rgba(255,255,255,@opacity) ); }
131
+
132
+ /**
133
+ * Objects
134
+ */
135
+ .menu() {
136
+ .clearfix;
137
+ li {
138
+ display: inline-block;
139
+ }
140
+ }
141
+ .mediaright() {
142
+ .clearfix;
143
+ img {
144
+ float:right;
145
+ height:auto;
146
+ }
147
+ }
148
+ .medialeft() {
149
+ .clearfix;
150
+ img {
151
+ float:right;
152
+ height:auto;
153
+ }
154
+ }
155
+ .ir() {
156
+ display: block;
157
+ text-indent: -9999px;
158
+ position: relative;
159
+ height:1em;
160
+ width:1em;
161
+ }
162
+
163
+ .margin( @top:0, @right:0px, @bottom:0px , @left:0 ){
164
+ margin-top: @top;
165
+ margin-right: @right;
166
+ margin-bottom: @bottom;
167
+ margin-left: @left;
168
+ }
169
+
170
+ .margin_left( @left:0 ){
171
+ margin-left: @left;
172
+ }
173
+ .margin_right( @right:0 ){
174
+ margin-right: @right;
175
+ }
176
+ .margin_top( @top:0 ){
177
+ margin-top: @top;
178
+ }
179
+ .margin_bottom( @bottom:0 ){
180
+ margin-bottom: @bottom;
181
+ }
182
+
183
+ .padding( @top:0, @right:0px, @bottom:0px , @left:0 ){
184
+ padding-top: @top;
185
+ padding-right: @right;
186
+ padding-bottom: @bottom;
187
+ padding-left: @left;
188
+ }
189
+
190
+ .padding_left( @left:0 ){
191
+ padding-left: @left;
192
+ }
193
+ .padding_right( @right:0 ){
194
+ padding-right: @right;
195
+ }
196
+ .padding_top( @top:0 ){
197
+ padding-top: @top;
198
+ }
199
+ .padding_bottom( @bottom:0 ){
200
+ padding-bottom: @bottom;
201
+ }
202
+
203
+ .background( @url, @repeat:no-repeat, @hoz:0, @ver:0, @color ){
204
+ background: url(@url) @repeat @hoz @ver @color;
205
+ }
admin/includes/uploader/uploader-script.js ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ($) {
2
+
3
+ a3Uploader = {
4
+ removeFile: function () {
5
+ $(document).on( 'click', '.a3_uploader_remove', function(event) {
6
+ $(this).hide();
7
+ $(this).parents().parents().children( '.a3_upload').attr( 'value', '' );
8
+ $(this).parents( '.a3_screenshot').slideUp();
9
+
10
+ return false;
11
+ });
12
+ },
13
+
14
+ mediaUpload: function () {
15
+ jQuery.noConflict();
16
+
17
+ var formfield, formID, upload_title, btnContent = true;
18
+
19
+ $(document).on( 'click', 'input.a3_upload_button', function () {
20
+ formfield = $(this).prev( 'input').attr( 'id' );
21
+ formID = $(this).attr( 'rel' );
22
+ upload_title = $(this).prev( 'input').attr( 'rel' );
23
+
24
+ tb_show( upload_title, 'media-upload.php?post_id='+formID+'&amp;title=' + upload_title + '&amp;a3_uploader=yes&amp;TB_iframe=1' );
25
+ return false;
26
+ });
27
+
28
+ window.original_send_to_editor = window.send_to_editor;
29
+ window.send_to_editor = function(html) {
30
+ if (formfield) {
31
+ if ( $(html).html(html).find( 'img').length > 0 ) {
32
+ itemurl = $(html).html(html).find( 'img').attr( 'src' );
33
+ } else {
34
+ var htmlBits = html.split( "'" );
35
+ itemurl = htmlBits[1];
36
+ var itemtitle = htmlBits[2];
37
+ itemtitle = itemtitle.replace( '>', '' );
38
+ itemtitle = itemtitle.replace( '</a>', '' );
39
+ }
40
+ var image = /(^.*\.jpg|jpeg|png|gif|ico*)/gi;
41
+ var document = /(^.*\.pdf|doc|docx|ppt|pptx|odt*)/gi;
42
+ var audio = /(^.*\.mp3|m4a|ogg|wav*)/gi;
43
+ var video = /(^.*\.mp4|m4v|mov|wmv|avi|mpg|ogv|3gp|3g2*)/gi;
44
+
45
+ if (itemurl.match(image)) {
46
+ btnContent = '<img class="a3_uploader_image" src="'+itemurl+'" alt="" /><a href="#" class="a3_uploader_remove a3-plugin-ui-delete-icon">&nbsp;</a>';
47
+ } else {
48
+ html = '<a href="'+itemurl+'" target="_blank" rel="a3_external">View File</a>';
49
+ btnContent = '<div class="a3_no_image"><span class="a3_file_link">'+html+'</span><a href="#" class="a3_uploader_remove a3-plugin-ui-delete-icon">&nbsp;</a></div>';
50
+ }
51
+ $( '#' + formfield).val(itemurl);
52
+ $( '#' + formfield).siblings( '.a3_screenshot').slideDown().html(btnContent);
53
+ tb_remove();
54
+ } else {
55
+ window.original_send_to_editor(html);
56
+ }
57
+ formfield = '';
58
+ }
59
+ }
60
+ };
61
+
62
+ $(document).ready(function () {
63
+
64
+ a3Uploader.removeFile();
65
+ a3Uploader.mediaUpload();
66
+
67
+ });
68
+
69
+ })(jQuery);
admin/includes/uploader/uploader.css ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .a3_screenshot {
2
+ float:left;
3
+ position:relative;
4
+ border-color: #CCCCCC #EEEEEE #EEEEEE #CCCCCC;
5
+ border-style: solid;
6
+ border-width: 1px;
7
+ background:#FAFAFA;
8
+ padding:5px;
9
+ margin-top:15px;
10
+ margin-right:15px;
11
+ }
12
+ .a3_uploader_remove {
13
+ background:#EEEEEE;
14
+ border: 1px solid #DDDDDD;
15
+ border-radius: 2px 2px 2px 2px;
16
+ -webkit-border-radius: 2px 2px 2px 2px;
17
+ -moz-border-radius: 2px 2px 2px 2px;
18
+ cursor: pointer;
19
+ height: 10px;
20
+ padding: 2px;
21
+ position: absolute;
22
+ right: -10px;
23
+ top: -10px;
24
+ width: 10px;
25
+ text-decoration:none !important;
26
+ }
27
+ .a3_uploader_image {
28
+ border:none;
29
+ background:none;
30
+ padding:0;
31
+ margin:0;
32
+ float:left;
33
+ max-width:225px;
34
+ width:100%;
35
+ }
admin/includes/uploader/uploader.rtl.css ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .clear {
2
+ clear: both;
3
+ }
4
+ .nobr {
5
+ white-space: nowrap;
6
+ }
7
+ .a3rev_panel_container .a3_screenshot {
8
+ float: right;
9
+ margin-left: 15px;
10
+ margin-right: 0px;
11
+ }
12
+ .a3rev_panel_container .a3_uploader_remove {
13
+ left: -10px;
14
+ right: auto;
15
+ }
16
+ .a3rev_panel_container .a3_uploader_image {
17
+ float: right;
18
+ }
admin/includes/uploader/uploader.rtl.less ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "mixins.less";
2
+
3
+ /*-------------------------------------------------------------------------------------------*/
4
+ /* A3rev Uploader RTL UI */
5
+ /*-------------------------------------------------------------------------------------------*/
6
+
7
+ .a3rev_panel_container {
8
+
9
+ .a3_screenshot {
10
+ float: right;
11
+ margin-left:15px;
12
+ margin-right:0px;
13
+ }
14
+
15
+ .a3_uploader_remove {
16
+ left: -10px;
17
+ right: auto;
18
+ }
19
+
20
+ .a3_uploader_image {
21
+ float:right;
22
+ }
23
+ }
admin/less/assets/css/mixins.less ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @green: green;
2
+ @red: red;
3
+ @orange: orange;
4
+ @blue: blue;
5
+ @yellow: yellow;
6
+ @white: white;
7
+ @black: black;
8
+
9
+ .clearfix() {
10
+ *zoom:1;
11
+ &:before,
12
+ &:after {
13
+ content: " ";
14
+ display: table;
15
+ }
16
+ &:after {
17
+ clear: both;
18
+ }
19
+ }
20
+ .border_radius(@radius:4px) {
21
+ -webkit-border-radius:@radius;
22
+ border-radius:@radius;
23
+ }
24
+ .border_radius_corner(@topleft:4px, @topright:4px, @bottomleft:4px, @bottomright:4px) {
25
+ -webkit-border-top-left-radius: @topleft;
26
+ border-top-left-radius: @topleft;
27
+ -webkit-border-top-right-radius: @topright;
28
+ border-top-right-radius: @topright;
29
+ -webkit-border-bottom-left-radius: @bottomleft;
30
+ border-bottom-left-radius: @bottomleft;
31
+ -webkit-border-bottom-right-radius: @bottomright;
32
+ border-bottom-right-radius: @bottomright;
33
+
34
+ }
35
+
36
+ .border_radius_top_left(@radius:4px) {
37
+ -webkit-border-top-left-radius: @radius;
38
+ border-top-left-radius: @radius;
39
+ }
40
+ .border_radius_top_right(@radius:4px) {
41
+ -webkit-border-top-right-radius: @radius;
42
+ border-top-right-radius: @radius;
43
+ }
44
+ .border_radius_bottom_left(@radius:4px) {
45
+ -webkit-border-bottom-left-radius: @radius;
46
+ border-bottom-left-radius: @radius;
47
+ }
48
+ .border_radius_bottom_right(@radius:4px) {
49
+ -webkit-border-bottom-right-radius: @radius;
50
+ border-bottom-right-radius: @radius;
51
+ }
52
+
53
+ .border_radius_right(@radius:4px) {
54
+ -webkit-border-top-right-radius: @radius;
55
+ -webkit-border-bottom-right-radius: @radius;
56
+ border-top-right-radius: @radius;
57
+ border-bottom-right-radius: @radius;
58
+ }
59
+ .border_radius_left(@radius:4px) {
60
+ -webkit-border-top-left-radius: @radius;
61
+ -webkit-border-bottom-left-radius: @radius;
62
+ border-top-left-radius: @radius;
63
+ border-bottom-left-radius: @radius;
64
+ }
65
+ .border_radius_bottom(@radius:4px) {
66
+ -webkit-border-bottom-left-radius: @radius;
67
+ -webkit-border-bottom-right-radius: @radius;
68
+ border-bottom-left-radius: @radius;
69
+ border-bottom-right-radius: @radius;
70
+ }
71
+ .border_radius_top(@radius:4px) {
72
+ -webkit-border-top-left-radius: @radius;
73
+ -webkit-border-top-right-radius: @radius;
74
+ border-top-left-radius: @radius;
75
+ border-top-right-radius: @radius;
76
+ }
77
+ .opacity(@opacity:0.75) {
78
+ filter:~"alpha(opacity=@opacity * 100)";
79
+ -moz-opacity:@opacity;
80
+ -khtml-opacity: @opacity;
81
+ opacity: @opacity;
82
+ }
83
+ .box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
84
+ box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color @inset;
85
+ -webkit-box-shadow:@shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
86
+ }
87
+ .inset_box_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_in:3px, @shadow_color:#888) {
88
+ box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
89
+ -webkit-box-shadow:inset @shadow_x @shadow_y @shadow_rad @shadow_in @shadow_color;
90
+ }
91
+ .text_shadow(@shadow_x:3px, @shadow_y:3px, @shadow_rad:3px, @shadow_color:#fff) {
92
+ text-shadow:@shadow_x @shadow_y @shadow_rad @shadow_color;
93
+ }
94
+ .vertical_gradient(@from: #000, @to: #FFF) {
95
+ background: @from;
96
+ background: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to));
97
+ background: -webkit-linear-gradient(@from, @to);
98
+ background: -moz-linear-gradient(center top, @from 0%, @to 100%);
99
+ background: -moz-gradient(center top, @from 0%, @to 100%);
100
+ }
101
+ .transition(@selector:all, @animation:ease-in-out, @duration:.2s) {
102
+ -webkit-transition:@selector @animation @duration;
103
+ -moz-transition:@selector @animation @duration;
104
+ -o-transition:@selector @animation @duration;
105
+ transition:@selector @animation @duration;
106
+ }
107
+
108
+ .scale(@ratio:1.5){
109
+ -webkit-transform:scale(@ratio);
110
+ -moz-transform:scale(@ratio);
111
+ -ms-transform:scale(@ratio);
112
+ -o-transform:scale(@ratio);
113
+ transform:scale(@ratio);
114
+ }
115
+
116
+ .borderbox () {
117
+ -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
118
+ -moz-box-sizing: border-box; /* Firefox, other Gecko */
119
+ box-sizing: border-box; /* Opera/IE 8+ */
120
+ }
121
+
122
+ .clear { clear: both; }
123
+ .nobr { white-space: nowrap; }
124
+
125
+ .darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) >= 65%) { .text_shadow( 0, -1px, 0, rgba(0,0,0,@opacity) ); }
126
+ .darkorlighttextshadow ( @a, @opacity: 0.8 ) when (lightness(@a) < 65%) { .text_shadow( 0, 1px, 0, rgba(255,255,255,@opacity) ); }
127
+
128
+ /**
129
+ * Objects
130
+ */
131
+ .menu() {
132
+ .clearfix;
133
+ li {
134
+ display: inline-block;
135
+ }
136
+ }
137
+ .mediaright() {
138
+ .clearfix;
139
+ img {
140
+ float:right;
141
+ height:auto;
142
+ }
143
+ }
144
+ .medialeft() {
145
+ .clearfix;
146
+ img {
147
+ float:right;
148
+ height:auto;
149
+ }
150
+ }
151
+ .ir() {
152
+ display: block;
153
+ text-indent: -9999px;
154
+ position: relative;
155
+ height:1em;
156
+ width:1em;
157
+ }
158
+
159
+ .margin( @top:0, @right:0px, @bottom:0px , @left:0 ){
160
+ margin-top: @top;
161
+ margin-right: @right;
162
+ margin-bottom: @bottom;
163
+ margin-left: @left;
164
+ }
165
+
166
+ .margin_left( @left:0 ){
167
+ margin-left: @left;
168
+ }
169
+ .margin_right( @right:0 ){
170
+ margin-right: @right;
171
+ }
172
+ .margin_top( @top:0 ){
173
+ margin-top: @top;
174
+ }
175
+ .margin_bottom( @bottom:0 ){
176
+ margin-bottom: @bottom;
177
+ }
178
+
179
+ .padding( @top:0, @right:0px, @bottom:0px , @left:0 ){
180
+ padding-top: @top;
181
+ padding-right: @right;
182
+ padding-bottom: @bottom;
183
+ padding-left: @left;
184
+ }
185
+
186
+ .padding_left( @left:0 ){
187
+ padding-left: @left;
188
+ }
189
+ .padding_right( @right:0 ){
190
+ padding-right: @right;
191
+ }
192
+ .padding_top( @top:0 ){
193
+ padding-top: @top;
194
+ }
195
+ .padding_bottom( @bottom:0 ){
196
+ padding-bottom: @bottom;
197
+ }
198
+
199
+ .background( @url, @repeat:no-repeat, @hoz:0, @ver:0, @color ){
200
+ background: url(@url) @repeat @hoz @ver @color;
201
+ }
admin/less/assets/css/style.css ADDED
File without changes
admin/less/assets/css/style.less ADDED
File without changes
admin/less/assets/css/style.min.css ADDED
File without changes
admin/less/compile_less_sass_class.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Compile_Less_Sass {
3
+
4
+ public function Compile_Less_Sass(){
5
+ $this->init();
6
+ }
7
+ public function init(){
8
+ }
9
+
10
+ public function compileLessFile( $less_file = '', $css_file = '', $css_min_file = '' ){
11
+
12
+ if( empty( $less_file ) )
13
+ $less_file = dirname( __FILE__ ) . '/assets/css/style.less';
14
+ if( empty( $css_file ) )
15
+ $css_file = dirname( __FILE__ ) . '/assets/css/style.css';
16
+ if( empty( $css_min_file ) )
17
+ $css_min_file = dirname( __FILE__ ) . '/assets/css/style.min.css';
18
+
19
+ //@chmod( $css_file, 0777 );
20
+ //@chmod( $css_min_file, 0777 );
21
+
22
+ // Write less file
23
+ if ( is_writable( $css_file ) && is_writable( $css_min_file ) ) {
24
+
25
+ if ( ! class_exists( 'lessc' ) ){
26
+ include( dirname( __FILE__ ) . '/lib/lessc.inc.php' );
27
+ }
28
+ if ( ! class_exists( 'cssmin' ) ){
29
+ include( dirname( __FILE__ ) . '/lib/cssmin.inc.php' );
30
+ }
31
+
32
+ try {
33
+
34
+ $less = new lessc;
35
+
36
+ $compiled_css = $less->compileFile( $less_file );
37
+
38
+ if ( $compiled_css != '' ){
39
+ file_put_contents( $css_file, $compiled_css );
40
+
41
+ $compiled_css_min = CssMin::minify( $compiled_css );
42
+ if ( $compiled_css_min != '' )
43
+ file_put_contents( $css_min_file, $compiled_css_min );
44
+ }
45
+
46
+ } catch ( exception $ex ) {
47
+
48
+ //echo ( __( 'Could not compile .less:', 'sass' ) . ' ' . $ex->getMessage() );
49
+ }
50
+ }
51
+
52
+ }
53
+ }
54
+ ?>
admin/less/index.html ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <title>SASS JS</title>
6
+ <link media="screen" rel="stylesheet/less" type="text/css" href="./assets/css/style.less" type="text/css">
7
+ <script type="text/javascript">
8
+ less = {
9
+ env: "development",
10
+ logLevel: 2,
11
+ async: true,
12
+ fileAsync: true,
13
+ poll: 1000,
14
+ functions: {},
15
+ dumpLineNumbers: "comments",
16
+ relativeUrls: true,
17
+ globalVars: {
18
+ var1: '"string value"',
19
+ var2: 'regular value'
20
+ },
21
+ rootpath: false
22
+ };
23
+ </script>
24
+ <script type="text/javascript" src="./lib/less.js" type="text/javascript"></script>
25
+
26
+ </head>
27
+
28
+ <body>
29
+ <p element-id="3466" class="pvc_stats pvc_load_by_ajax_update" id="pvc_stats_3466">3,894&nbsp;total views, 1&nbsp;views today</p>
30
+ </body>
31
+ </html>
admin/less/index.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <?php
5
+ function sass_compile_less_mincss(){
6
+
7
+ include( dirname( __FILE__ ) . '/compile_less_sass_class.php' );
8
+
9
+ $less_file = dirname( __FILE__ ) . '/assets/css/style.less';
10
+ $css_file = dirname( __FILE__ ) . '/assets/css/style.css';
11
+ $css_min_file = dirname( __FILE__ ) . '/assets/css/style.min.css';
12
+
13
+ $compile = new Compile_Less_Sass;
14
+
15
+ $compile->compileLessFile( $less_file, $css_file, $css_min_file );
16
+ }
17
+ sass_compile_less_mincss();
18
+ ?>
19
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
20
+ <title>SASS PHP</title>
21
+ <link media="screen" href="./assets/css/style.min.css" type="text/css" rel="stylesheet">
22
+ </head>
23
+
24
+ <body>
25
+ <p element-id="3466" class="pvc_stats pvc_load_by_ajax_update" id="pvc_stats_3466">3,894&nbsp;total views, 1&nbsp;views today</p>
26
+ </body>
27
+ </html>
admin/less/lib/cssmin.inc.php ADDED
@@ -0,0 +1,5082 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * CssMin - A (simple) css minifier with benefits
4
+ *
5
+ * --
6
+ * Copyright (c) 2011 Joe Scylla <joe.scylla@gmail.com>
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ * --
26
+ *
27
+ * @package CssMin
28
+ * @link http://code.google.com/p/cssmin/
29
+ * @author Joe Scylla <joe.scylla@gmail.com>
30
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
31
+ * @license http://opensource.org/licenses/mit-license.php MIT License
32
+ * @version 3.0.1
33
+ */
34
+ /**
35
+ * Abstract definition of a CSS token class.
36
+ *
37
+ * Every token has to extend this class.
38
+ *
39
+ * @package CssMin/Tokens
40
+ * @link http://code.google.com/p/cssmin/
41
+ * @author Joe Scylla <joe.scylla@gmail.com>
42
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
43
+ * @license http://opensource.org/licenses/mit-license.php MIT License
44
+ * @version 3.0.1
45
+ */
46
+ abstract class aCssToken
47
+ {
48
+ /**
49
+ * Returns the token as string.
50
+ *
51
+ * @return string
52
+ */
53
+ abstract public function __toString();
54
+ }
55
+
56
+ /**
57
+ * Abstract definition of a for a ruleset start token.
58
+ *
59
+ * @package CssMin/Tokens
60
+ * @link http://code.google.com/p/cssmin/
61
+ * @author Joe Scylla <joe.scylla@gmail.com>
62
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
63
+ * @license http://opensource.org/licenses/mit-license.php MIT License
64
+ * @version 3.0.1
65
+ */
66
+ abstract class aCssRulesetStartToken extends aCssToken
67
+ {
68
+
69
+ }
70
+
71
+ /**
72
+ * Abstract definition of a for ruleset end token.
73
+ *
74
+ * @package CssMin/Tokens
75
+ * @link http://code.google.com/p/cssmin/
76
+ * @author Joe Scylla <joe.scylla@gmail.com>
77
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
78
+ * @license http://opensource.org/licenses/mit-license.php MIT License
79
+ * @version 3.0.1
80
+ */
81
+ abstract class aCssRulesetEndToken extends aCssToken
82
+ {
83
+ /**
84
+ * Implements {@link aCssToken::__toString()}.
85
+ *
86
+ * @return string
87
+ */
88
+ public function __toString()
89
+ {
90
+ return "}";
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Abstract definition of a parser plugin.
96
+ *
97
+ * Every parser plugin have to extend this class. A parser plugin contains the logic to parse one or aspects of a
98
+ * stylesheet.
99
+ *
100
+ * @package CssMin/Parser/Plugins
101
+ * @link http://code.google.com/p/cssmin/
102
+ * @author Joe Scylla <joe.scylla@gmail.com>
103
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
104
+ * @license http://opensource.org/licenses/mit-license.php MIT License
105
+ * @version 3.0.1
106
+ */
107
+ abstract class aCssParserPlugin
108
+ {
109
+ /**
110
+ * Plugin configuration.
111
+ *
112
+ * @var array
113
+ */
114
+ protected $configuration = array();
115
+ /**
116
+ * The CssParser of the plugin.
117
+ *
118
+ * @var CssParser
119
+ */
120
+ protected $parser = null;
121
+ /**
122
+ * Plugin buffer.
123
+ *
124
+ * @var string
125
+ */
126
+ protected $buffer = "";
127
+ /**
128
+ * Constructor.
129
+ *
130
+ * @param CssParser $parser The CssParser object of this plugin.
131
+ * @param array $configuration Plugin configuration [optional]
132
+ * @return void
133
+ */
134
+ public function __construct(CssParser $parser, array $configuration = null)
135
+ {
136
+ $this->configuration = $configuration;
137
+ $this->parser = $parser;
138
+ }
139
+ /**
140
+ * Returns the array of chars triggering the parser plugin.
141
+ *
142
+ * @return array
143
+ */
144
+ abstract public function getTriggerChars();
145
+ /**
146
+ * Returns the array of states triggering the parser plugin or FALSE if every state will trigger the parser plugin.
147
+ *
148
+ * @return array
149
+ */
150
+ abstract public function getTriggerStates();
151
+ /**
152
+ * Parser routine of the plugin.
153
+ *
154
+ * @param integer $index Current index
155
+ * @param string $char Current char
156
+ * @param string $previousChar Previous char
157
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
158
+ */
159
+ abstract public function parse($index, $char, $previousChar, $state);
160
+ }
161
+
162
+ /**
163
+ * Abstract definition of a minifier plugin class.
164
+ *
165
+ * Minifier plugin process the parsed tokens one by one to apply changes to the token. Every minifier plugin has to
166
+ * extend this class.
167
+ *
168
+ * @package CssMin/Minifier/Plugins
169
+ * @link http://code.google.com/p/cssmin/
170
+ * @author Joe Scylla <joe.scylla@gmail.com>
171
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
172
+ * @license http://opensource.org/licenses/mit-license.php MIT License
173
+ * @version 3.0.1
174
+ */
175
+ abstract class aCssMinifierPlugin
176
+ {
177
+ /**
178
+ * Plugin configuration.
179
+ *
180
+ * @var array
181
+ */
182
+ protected $configuration = array();
183
+ /**
184
+ * The CssMinifier of the plugin.
185
+ *
186
+ * @var CssMinifier
187
+ */
188
+ protected $minifier = null;
189
+ /**
190
+ * Constructor.
191
+ *
192
+ * @param CssMinifier $minifier The CssMinifier object of this plugin.
193
+ * @param array $configuration Plugin configuration [optional]
194
+ * @return void
195
+ */
196
+ public function __construct(CssMinifier $minifier, array $configuration = array())
197
+ {
198
+ $this->configuration = $configuration;
199
+ $this->minifier = $minifier;
200
+ }
201
+ /**
202
+ * Apply the plugin to the token.
203
+ *
204
+ * @param aCssToken $token Token to process
205
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
206
+ */
207
+ abstract public function apply(aCssToken &$token);
208
+ /**
209
+ * --
210
+ *
211
+ * @return array
212
+ */
213
+ abstract public function getTriggerTokens();
214
+ }
215
+
216
+ /**
217
+ * Abstract definition of a minifier filter class.
218
+ *
219
+ * Minifier filters allows a pre-processing of the parsed token to add, edit or delete tokens. Every minifier filter
220
+ * has to extend this class.
221
+ *
222
+ * @package CssMin/Minifier/Filters
223
+ * @link http://code.google.com/p/cssmin/
224
+ * @author Joe Scylla <joe.scylla@gmail.com>
225
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
226
+ * @license http://opensource.org/licenses/mit-license.php MIT License
227
+ * @version 3.0.1
228
+ */
229
+ abstract class aCssMinifierFilter
230
+ {
231
+ /**
232
+ * Filter configuration.
233
+ *
234
+ * @var array
235
+ */
236
+ protected $configuration = array();
237
+ /**
238
+ * The CssMinifier of the filter.
239
+ *
240
+ * @var CssMinifier
241
+ */
242
+ protected $minifier = null;
243
+ /**
244
+ * Constructor.
245
+ *
246
+ * @param CssMinifier $minifier The CssMinifier object of this plugin.
247
+ * @param array $configuration Filter configuration [optional]
248
+ * @return void
249
+ */
250
+ public function __construct(CssMinifier $minifier, array $configuration = array())
251
+ {
252
+ $this->configuration = $configuration;
253
+ $this->minifier = $minifier;
254
+ }
255
+ /**
256
+ * Filter the tokens.
257
+ *
258
+ * @param array $tokens Array of objects of type aCssToken
259
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
260
+ */
261
+ abstract public function apply(array &$tokens);
262
+ }
263
+
264
+ /**
265
+ * Abstract formatter definition.
266
+ *
267
+ * Every formatter have to extend this class.
268
+ *
269
+ * @package CssMin/Formatter
270
+ * @link http://code.google.com/p/cssmin/
271
+ * @author Joe Scylla <joe.scylla@gmail.com>
272
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
273
+ * @license http://opensource.org/licenses/mit-license.php MIT License
274
+ * @version 3.0.1
275
+ */
276
+ abstract class aCssFormatter
277
+ {
278
+ /**
279
+ * Indent string.
280
+ *
281
+ * @var string
282
+ */
283
+ protected $indent = " ";
284
+ /**
285
+ * Declaration padding.
286
+ *
287
+ * @var integer
288
+ */
289
+ protected $padding = 0;
290
+ /**
291
+ * Tokens.
292
+ *
293
+ * @var array
294
+ */
295
+ protected $tokens = array();
296
+ /**
297
+ * Constructor.
298
+ *
299
+ * @param array $tokens Array of CssToken
300
+ * @param string $indent Indent string [optional]
301
+ * @param integer $padding Declaration value padding [optional]
302
+ */
303
+ public function __construct(array $tokens, $indent = null, $padding = null)
304
+ {
305
+ $this->tokens = $tokens;
306
+ $this->indent = !is_null($indent) ? $indent : $this->indent;
307
+ $this->padding = !is_null($padding) ? $padding : $this->padding;
308
+ }
309
+ /**
310
+ * Returns the array of aCssToken as formatted string.
311
+ *
312
+ * @return string
313
+ */
314
+ abstract public function __toString();
315
+ }
316
+
317
+ /**
318
+ * Abstract definition of a ruleset declaration token.
319
+ *
320
+ * @package CssMin/Tokens
321
+ * @link http://code.google.com/p/cssmin/
322
+ * @author Joe Scylla <joe.scylla@gmail.com>
323
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
324
+ * @license http://opensource.org/licenses/mit-license.php MIT License
325
+ * @version 3.0.1
326
+ */
327
+ abstract class aCssDeclarationToken extends aCssToken
328
+ {
329
+ /**
330
+ * Is the declaration flagged as important?
331
+ *
332
+ * @var boolean
333
+ */
334
+ public $IsImportant = false;
335
+ /**
336
+ * Is the declaration flagged as last one of the ruleset?
337
+ *
338
+ * @var boolean
339
+ */
340
+ public $IsLast = false;
341
+ /**
342
+ * Property name of the declaration.
343
+ *
344
+ * @var string
345
+ */
346
+ public $Property = "";
347
+ /**
348
+ * Value of the declaration.
349
+ *
350
+ * @var string
351
+ */
352
+ public $Value = "";
353
+ /**
354
+ * Set the properties of the @font-face declaration.
355
+ *
356
+ * @param string $property Property of the declaration
357
+ * @param string $value Value of the declaration
358
+ * @param boolean $isImportant Is the !important flag is set?
359
+ * @param boolean $IsLast Is the declaration the last one of the block?
360
+ * @return void
361
+ */
362
+ public function __construct($property, $value, $isImportant = false, $isLast = false)
363
+ {
364
+ $this->Property = $property;
365
+ $this->Value = $value;
366
+ $this->IsImportant = $isImportant;
367
+ $this->IsLast = $isLast;
368
+ }
369
+ /**
370
+ * Implements {@link aCssToken::__toString()}.
371
+ *
372
+ * @return string
373
+ */
374
+ public function __toString()
375
+ {
376
+ return $this->Property . ":" . $this->Value . ($this->IsImportant ? " !important" : "") . ($this->IsLast ? "" : ";");
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Abstract definition of a for at-rule block start token.
382
+ *
383
+ * @package CssMin/Tokens
384
+ * @link http://code.google.com/p/cssmin/
385
+ * @author Joe Scylla <joe.scylla@gmail.com>
386
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
387
+ * @license http://opensource.org/licenses/mit-license.php MIT License
388
+ * @version 3.0.1
389
+ */
390
+ abstract class aCssAtBlockStartToken extends aCssToken
391
+ {
392
+
393
+ }
394
+
395
+ /**
396
+ * Abstract definition of a for at-rule block end token.
397
+ *
398
+ * @package CssMin/Tokens
399
+ * @link http://code.google.com/p/cssmin/
400
+ * @author Joe Scylla <joe.scylla@gmail.com>
401
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
402
+ * @license http://opensource.org/licenses/mit-license.php MIT License
403
+ * @version 3.0.1
404
+ */
405
+ abstract class aCssAtBlockEndToken extends aCssToken
406
+ {
407
+ /**
408
+ * Implements {@link aCssToken::__toString()}.
409
+ *
410
+ * @return string
411
+ */
412
+ public function __toString()
413
+ {
414
+ return "}";
415
+ }
416
+ }
417
+
418
+ /**
419
+ * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/etzLs Whitesmiths indent style}.
420
+ *
421
+ * @package CssMin/Formatter
422
+ * @link http://code.google.com/p/cssmin/
423
+ * @author Joe Scylla <joe.scylla@gmail.com>
424
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
425
+ * @license http://opensource.org/licenses/mit-license.php MIT License
426
+ * @version 3.0.1
427
+ */
428
+ class CssWhitesmithsFormatter extends aCssFormatter
429
+ {
430
+ /**
431
+ * Implements {@link aCssFormatter::__toString()}.
432
+ *
433
+ * @return string
434
+ */
435
+ public function __toString()
436
+ {
437
+ $r = array();
438
+ $level = 0;
439
+ for ($i = 0, $l = count($this->tokens); $i < $l; $i++)
440
+ {
441
+ $token = $this->tokens[$i];
442
+ $class = get_class($token);
443
+ $indent = str_repeat($this->indent, $level);
444
+ if ($class === "CssCommentToken")
445
+ {
446
+ $lines = array_map("trim", explode("\n", $token->Comment));
447
+ for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++)
448
+ {
449
+ $r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii];
450
+ }
451
+ }
452
+ elseif ($class === "CssAtCharsetToken")
453
+ {
454
+ $r[] = $indent . "@charset " . $token->Charset . ";";
455
+ }
456
+ elseif ($class === "CssAtFontFaceStartToken")
457
+ {
458
+ $r[] = $indent . "@font-face";
459
+ $r[] = $this->indent . $indent . "{";
460
+ $level++;
461
+ }
462
+ elseif ($class === "CssAtImportToken")
463
+ {
464
+ $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";
465
+ }
466
+ elseif ($class === "CssAtKeyframesStartToken")
467
+ {
468
+ $r[] = $indent . "@keyframes \"" . $token->Name . "\"";
469
+ $r[] = $this->indent . $indent . "{";
470
+ $level++;
471
+ }
472
+ elseif ($class === "CssAtMediaStartToken")
473
+ {
474
+ $r[] = $indent . "@media " . implode(", ", $token->MediaTypes);
475
+ $r[] = $this->indent . $indent . "{";
476
+ $level++;
477
+ }
478
+ elseif ($class === "CssAtPageStartToken")
479
+ {
480
+ $r[] = $indent . "@page";
481
+ $r[] = $this->indent . $indent . "{";
482
+ $level++;
483
+ }
484
+ elseif ($class === "CssAtVariablesStartToken")
485
+ {
486
+ $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes);
487
+ $r[] = $this->indent . $indent . "{";
488
+ $level++;
489
+ }
490
+ elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")
491
+ {
492
+ $r[] = $indent . implode(", ", $token->Selectors);
493
+ $r[] = $this->indent . $indent . "{";
494
+ $level++;
495
+ }
496
+ elseif ($class == "CssAtFontFaceDeclarationToken"
497
+ || $class === "CssAtKeyframesRulesetDeclarationToken"
498
+ || $class === "CssAtPageDeclarationToken"
499
+ || $class == "CssAtVariablesDeclarationToken"
500
+ || $class === "CssRulesetDeclarationToken"
501
+ )
502
+ {
503
+ $declaration = $indent . $token->Property . ": ";
504
+ if ($this->padding)
505
+ {
506
+ $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);
507
+ }
508
+ $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";
509
+ }
510
+ elseif ($class === "CssAtFontFaceEndToken"
511
+ || $class === "CssAtMediaEndToken"
512
+ || $class === "CssAtKeyframesEndToken"
513
+ || $class === "CssAtKeyframesRulesetEndToken"
514
+ || $class === "CssAtPageEndToken"
515
+ || $class === "CssAtVariablesEndToken"
516
+ || $class === "CssRulesetEndToken"
517
+ )
518
+ {
519
+ $r[] = $indent . "}";
520
+ $level--;
521
+ }
522
+ }
523
+ return implode("\n", $r);
524
+ }
525
+ }
526
+
527
+ /**
528
+ * This {@link aCssMinifierPlugin} will process var-statement and sets the declaration value to the variable value.
529
+ *
530
+ * This plugin only apply the variable values. The variable values itself will get parsed by the
531
+ * {@link CssVariablesMinifierFilter}.
532
+ *
533
+ * Example:
534
+ * <code>
535
+ * @variables
536
+ * {
537
+ * defaultColor: black;
538
+ * }
539
+ * color: var(defaultColor);
540
+ * </code>
541
+ *
542
+ * Will get converted to:
543
+ * <code>
544
+ * color:black;
545
+ * </code>
546
+ *
547
+ * @package CssMin/Minifier/Plugins
548
+ * @link http://code.google.com/p/cssmin/
549
+ * @author Joe Scylla <joe.scylla@gmail.com>
550
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
551
+ * @license http://opensource.org/licenses/mit-license.php MIT License
552
+ * @version 3.0.1
553
+ */
554
+ class CssVariablesMinifierPlugin extends aCssMinifierPlugin
555
+ {
556
+ /**
557
+ * Regular expression matching a value.
558
+ *
559
+ * @var string
560
+ */
561
+ private $reMatch = "/var\((.+)\)/iSU";
562
+ /**
563
+ * Parsed variables.
564
+ *
565
+ * @var array
566
+ */
567
+ private $variables = null;
568
+ /**
569
+ * Returns the variables.
570
+ *
571
+ * @return array
572
+ */
573
+ public function getVariables()
574
+ {
575
+ return $this->variables;
576
+ }
577
+ /**
578
+ * Implements {@link aCssMinifierPlugin::minify()}.
579
+ *
580
+ * @param aCssToken $token Token to process
581
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
582
+ */
583
+ public function apply(aCssToken &$token)
584
+ {
585
+ if (stripos($token->Value, "var") !== false && preg_match_all($this->reMatch, $token->Value, $m))
586
+ {
587
+ $mediaTypes = $token->MediaTypes;
588
+ if (!in_array("all", $mediaTypes))
589
+ {
590
+ $mediaTypes[] = "all";
591
+ }
592
+ for ($i = 0, $l = count($m[0]); $i < $l; $i++)
593
+ {
594
+ $variable = trim($m[1][$i]);
595
+ foreach ($mediaTypes as $mediaType)
596
+ {
597
+ if (isset($this->variables[$mediaType], $this->variables[$mediaType][$variable]))
598
+ {
599
+ // Variable value found => set the declaration value to the variable value and return
600
+ $token->Value = str_replace($m[0][$i], $this->variables[$mediaType][$variable], $token->Value);
601
+ continue 2;
602
+ }
603
+ }
604
+ // If no value was found trigger an error and replace the token with a CssNullToken
605
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": No value found for variable <code>" . $variable . "</code> in media types <code>" . implode(", ", $mediaTypes) . "</code>", (string) $token));
606
+ $token = new CssNullToken();
607
+ return true;
608
+ }
609
+ }
610
+ return false;
611
+ }
612
+ /**
613
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
614
+ *
615
+ * @return array
616
+ */
617
+ public function getTriggerTokens()
618
+ {
619
+ return array
620
+ (
621
+ "CssAtFontFaceDeclarationToken",
622
+ "CssAtPageDeclarationToken",
623
+ "CssRulesetDeclarationToken"
624
+ );
625
+ }
626
+ /**
627
+ * Sets the variables.
628
+ *
629
+ * @param array $variables Variables to set
630
+ * @return void
631
+ */
632
+ public function setVariables(array $variables)
633
+ {
634
+ $this->variables = $variables;
635
+ }
636
+ }
637
+
638
+ /**
639
+ * This {@link aCssMinifierFilter minifier filter} will parse the variable declarations out of @variables at-rule
640
+ * blocks. The variables will get store in the {@link CssVariablesMinifierPlugin} that will apply the variables to
641
+ * declaration.
642
+ *
643
+ * @package CssMin/Minifier/Filters
644
+ * @link http://code.google.com/p/cssmin/
645
+ * @author Joe Scylla <joe.scylla@gmail.com>
646
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
647
+ * @license http://opensource.org/licenses/mit-license.php MIT License
648
+ * @version 3.0.1
649
+ */
650
+ class CssVariablesMinifierFilter extends aCssMinifierFilter
651
+ {
652
+ /**
653
+ * Implements {@link aCssMinifierFilter::filter()}.
654
+ *
655
+ * @param array $tokens Array of objects of type aCssToken
656
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
657
+ */
658
+ public function apply(array &$tokens)
659
+ {
660
+ $variables = array();
661
+ $defaultMediaTypes = array("all");
662
+ $mediaTypes = array();
663
+ $remove = array();
664
+ for($i = 0, $l = count($tokens); $i < $l; $i++)
665
+ {
666
+ // @variables at-rule block found
667
+ if (get_class($tokens[$i]) === "CssAtVariablesStartToken")
668
+ {
669
+ $remove[] = $i;
670
+ $mediaTypes = (count($tokens[$i]->MediaTypes) == 0 ? $defaultMediaTypes : $tokens[$i]->MediaTypes);
671
+ foreach ($mediaTypes as $mediaType)
672
+ {
673
+ if (!isset($variables[$mediaType]))
674
+ {
675
+ $variables[$mediaType] = array();
676
+ }
677
+ }
678
+ // Read the variable declaration tokens
679
+ for($i = $i; $i < $l; $i++)
680
+ {
681
+ // Found a variable declaration => read the variable values
682
+ if (get_class($tokens[$i]) === "CssAtVariablesDeclarationToken")
683
+ {
684
+ foreach ($mediaTypes as $mediaType)
685
+ {
686
+ $variables[$mediaType][$tokens[$i]->Property] = $tokens[$i]->Value;
687
+ }
688
+ $remove[] = $i;
689
+ }
690
+ // Found the variables end token => break;
691
+ elseif (get_class($tokens[$i]) === "CssAtVariablesEndToken")
692
+ {
693
+ $remove[] = $i;
694
+ break;
695
+ }
696
+ }
697
+ }
698
+ }
699
+ // Variables in @variables at-rule blocks
700
+ foreach($variables as $mediaType => $null)
701
+ {
702
+ foreach($variables[$mediaType] as $variable => $value)
703
+ {
704
+ // If a var() statement in a variable value found...
705
+ if (stripos($value, "var") !== false && preg_match_all("/var\((.+)\)/iSU", $value, $m))
706
+ {
707
+ // ... then replace the var() statement with the variable values.
708
+ for ($i = 0, $l = count($m[0]); $i < $l; $i++)
709
+ {
710
+ $variables[$mediaType][$variable] = str_replace($m[0][$i], (isset($variables[$mediaType][$m[1][$i]]) ? $variables[$mediaType][$m[1][$i]] : ""), $variables[$mediaType][$variable]);
711
+ }
712
+ }
713
+ }
714
+ }
715
+ // Remove the complete @variables at-rule block
716
+ foreach ($remove as $i)
717
+ {
718
+ $tokens[$i] = null;
719
+ }
720
+ if (!($plugin = $this->minifier->getPlugin("CssVariablesMinifierPlugin")))
721
+ {
722
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>CssVariablesMinifierPlugin</code> was not found but is required for <code>" . __CLASS__ . "</code>"));
723
+ }
724
+ else
725
+ {
726
+ $plugin->setVariables($variables);
727
+ }
728
+ return count($remove);
729
+ }
730
+ }
731
+
732
+ /**
733
+ * {@link aCssParserPlugin Parser plugin} for preserve parsing url() values.
734
+ *
735
+ * This plugin return no {@link aCssToken CssToken} but ensures that url() values will get parsed properly.
736
+ *
737
+ * @package CssMin/Parser/Plugins
738
+ * @link http://code.google.com/p/cssmin/
739
+ * @author Joe Scylla <joe.scylla@gmail.com>
740
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
741
+ * @license http://opensource.org/licenses/mit-license.php MIT License
742
+ * @version 3.0.1
743
+ */
744
+ class CssUrlParserPlugin extends aCssParserPlugin
745
+ {
746
+ /**
747
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
748
+ *
749
+ * @return array
750
+ */
751
+ public function getTriggerChars()
752
+ {
753
+ return array("(", ")");
754
+ }
755
+ /**
756
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
757
+ *
758
+ * @return array
759
+ */
760
+ public function getTriggerStates()
761
+ {
762
+ return false;
763
+ }
764
+ /**
765
+ * Implements {@link aCssParserPlugin::parse()}.
766
+ *
767
+ * @param integer $index Current index
768
+ * @param string $char Current char
769
+ * @param string $previousChar Previous char
770
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
771
+ */
772
+ public function parse($index, $char, $previousChar, $state)
773
+ {
774
+ // Start of string
775
+ if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 3, 4)) === "url(" && $state !== "T_URL")
776
+ {
777
+ $this->parser->pushState("T_URL");
778
+ $this->parser->setExclusive(__CLASS__);
779
+ }
780
+ // Escaped LF in url => remove escape backslash and LF
781
+ elseif ($char === "\n" && $previousChar === "\\" && $state === "T_URL")
782
+ {
783
+ $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));
784
+ }
785
+ // Parse error: Unescaped LF in string literal
786
+ elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_URL")
787
+ {
788
+ $line = $this->parser->getBuffer();
789
+ $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . ")"); // Replace the LF with the url string delimiter
790
+ $this->parser->popState();
791
+ $this->parser->unsetExclusive();
792
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));
793
+ }
794
+ // End of string
795
+ elseif ($char === ")" && $state === "T_URL")
796
+ {
797
+ $this->parser->popState();
798
+ $this->parser->unsetExclusive();
799
+ }
800
+ else
801
+ {
802
+ return false;
803
+ }
804
+ return true;
805
+ }
806
+ }
807
+
808
+ /**
809
+ * {@link aCssParserPlugin Parser plugin} for preserve parsing string values.
810
+ *
811
+ * This plugin return no {@link aCssToken CssToken} but ensures that string values will get parsed properly.
812
+ *
813
+ * @package CssMin/Parser/Plugins
814
+ * @link http://code.google.com/p/cssmin/
815
+ * @author Joe Scylla <joe.scylla@gmail.com>
816
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
817
+ * @license http://opensource.org/licenses/mit-license.php MIT License
818
+ * @version 3.0.1
819
+ */
820
+ class CssStringParserPlugin extends aCssParserPlugin
821
+ {
822
+ /**
823
+ * Current string delimiter char.
824
+ *
825
+ * @var string
826
+ */
827
+ private $delimiterChar = null;
828
+ /**
829
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
830
+ *
831
+ * @return array
832
+ */
833
+ public function getTriggerChars()
834
+ {
835
+ return array("\"", "'", "\n");
836
+ }
837
+ /**
838
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
839
+ *
840
+ * @return array
841
+ */
842
+ public function getTriggerStates()
843
+ {
844
+ return false;
845
+ }
846
+ /**
847
+ * Implements {@link aCssParserPlugin::parse()}.
848
+ *
849
+ * @param integer $index Current index
850
+ * @param string $char Current char
851
+ * @param string $previousChar Previous char
852
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
853
+ */
854
+ public function parse($index, $char, $previousChar, $state)
855
+ {
856
+ // Start of string
857
+ if (($char === "\"" || $char === "'") && $state !== "T_STRING")
858
+ {
859
+ $this->delimiterChar = $char;
860
+ $this->parser->pushState("T_STRING");
861
+ $this->parser->setExclusive(__CLASS__);
862
+ }
863
+ // Escaped LF in string => remove escape backslash and LF
864
+ elseif ($char === "\n" && $previousChar === "\\" && $state === "T_STRING")
865
+ {
866
+ $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2));
867
+ }
868
+ // Parse error: Unescaped LF in string literal
869
+ elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_STRING")
870
+ {
871
+ $line = $this->parser->getBuffer();
872
+ $this->parser->popState();
873
+ $this->parser->unsetExclusive();
874
+ $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . $this->delimiterChar); // Replace the LF with the current string char
875
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_"));
876
+ $this->delimiterChar = null;
877
+ }
878
+ // End of string
879
+ elseif ($char === $this->delimiterChar && $state === "T_STRING")
880
+ {
881
+ // If the Previous char is a escape char count the amount of the previous escape chars. If the amount of
882
+ // escape chars is uneven do not end the string
883
+ if ($previousChar == "\\")
884
+ {
885
+ $source = $this->parser->getSource();
886
+ $c = 1;
887
+ $i = $index - 2;
888
+ while (substr($source, $i, 1) === "\\")
889
+ {
890
+ $c++; $i--;
891
+ }
892
+ if ($c % 2)
893
+ {
894
+ return false;
895
+ }
896
+ }
897
+ $this->parser->popState();
898
+ $this->parser->unsetExclusive();
899
+ $this->delimiterChar = null;
900
+ }
901
+ else
902
+ {
903
+ return false;
904
+ }
905
+ return true;
906
+ }
907
+ }
908
+
909
+ /**
910
+ * This {@link aCssMinifierFilter minifier filter} sorts the ruleset declarations of a ruleset by name.
911
+ *
912
+ * @package CssMin/Minifier/Filters
913
+ * @link http://code.google.com/p/cssmin/
914
+ * @author Rowan Beentje <http://assanka.net>
915
+ * @copyright Rowan Beentje <http://assanka.net>
916
+ * @license http://opensource.org/licenses/mit-license.php MIT License
917
+ * @version 3.0.1
918
+ */
919
+ class CssSortRulesetPropertiesMinifierFilter extends aCssMinifierFilter
920
+ {
921
+ /**
922
+ * Implements {@link aCssMinifierFilter::filter()}.
923
+ *
924
+ * @param array $tokens Array of objects of type aCssToken
925
+ * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array
926
+ */
927
+ public function apply(array &$tokens)
928
+ {
929
+ $r = 0;
930
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
931
+ {
932
+ // Only look for ruleset start rules
933
+ if (get_class($tokens[$i]) !== "CssRulesetStartToken") { continue; }
934
+ // Look for the corresponding ruleset end
935
+ $endIndex = false;
936
+ for ($ii = $i + 1; $ii < $l; $ii++)
937
+ {
938
+ if (get_class($tokens[$ii]) !== "CssRulesetEndToken") { continue; }
939
+ $endIndex = $ii;
940
+ break;
941
+ }
942
+ if (!$endIndex) { break; }
943
+ $startIndex = $i;
944
+ $i = $endIndex;
945
+ // Skip if there's only one token in this ruleset
946
+ if ($endIndex - $startIndex <= 2) { continue; }
947
+ // Ensure that everything between the start and end is a declaration token, for safety
948
+ for ($ii = $startIndex + 1; $ii < $endIndex; $ii++)
949
+ {
950
+ if (get_class($tokens[$ii]) !== "CssRulesetDeclarationToken") { continue(2); }
951
+ }
952
+ $declarations = array_slice($tokens, $startIndex + 1, $endIndex - $startIndex - 1);
953
+ // Check whether a sort is required
954
+ $sortRequired = $lastPropertyName = false;
955
+ foreach ($declarations as $declaration)
956
+ {
957
+ if ($lastPropertyName)
958
+ {
959
+ if (strcmp($lastPropertyName, $declaration->Property) > 0)
960
+ {
961
+ $sortRequired = true;
962
+ break;
963
+ }
964
+ }
965
+ $lastPropertyName = $declaration->Property;
966
+ }
967
+ if (!$sortRequired) { continue; }
968
+ // Arrange the declarations alphabetically by name
969
+ usort($declarations, array(__CLASS__, "userDefinedSort1"));
970
+ // Update "IsLast" property
971
+ for ($ii = 0, $ll = count($declarations) - 1; $ii <= $ll; $ii++)
972
+ {
973
+ if ($ii == $ll)
974
+ {
975
+ $declarations[$ii]->IsLast = true;
976
+ }
977
+ else
978
+ {
979
+ $declarations[$ii]->IsLast = false;
980
+ }
981
+ }
982
+ // Splice back into the array.
983
+ array_splice($tokens, $startIndex + 1, $endIndex - $startIndex - 1, $declarations);
984
+ $r += $endIndex - $startIndex - 1;
985
+ }
986
+ return $r;
987
+ }
988
+ /**
989
+ * User defined sort function.
990
+ *
991
+ * @return integer
992
+ */
993
+ public static function userDefinedSort1($a, $b)
994
+ {
995
+ return strcmp($a->Property, $b->Property);
996
+ }
997
+ }
998
+
999
+ /**
1000
+ * This {@link aCssToken CSS token} represents the start of a ruleset.
1001
+ *
1002
+ * @package CssMin/Tokens
1003
+ * @link http://code.google.com/p/cssmin/
1004
+ * @author Joe Scylla <joe.scylla@gmail.com>
1005
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1006
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1007
+ * @version 3.0.1
1008
+ */
1009
+ class CssRulesetStartToken extends aCssRulesetStartToken
1010
+ {
1011
+ /**
1012
+ * Array of selectors.
1013
+ *
1014
+ * @var array
1015
+ */
1016
+ public $Selectors = array();
1017
+ /**
1018
+ * Set the properties of a ruleset token.
1019
+ *
1020
+ * @param array $selectors Selectors of the ruleset
1021
+ * @return void
1022
+ */
1023
+ public function __construct(array $selectors = array())
1024
+ {
1025
+ $this->Selectors = $selectors;
1026
+ }
1027
+ /**
1028
+ * Implements {@link aCssToken::__toString()}.
1029
+ *
1030
+ * @return string
1031
+ */
1032
+ public function __toString()
1033
+ {
1034
+ return implode(",", $this->Selectors) . "{";
1035
+ }
1036
+ }
1037
+
1038
+ /**
1039
+ * {@link aCssParserPlugin Parser plugin} for parsing ruleset block with including declarations.
1040
+ *
1041
+ * Found rulesets will add a {@link CssRulesetStartToken} and {@link CssRulesetEndToken} to the
1042
+ * parser; including declarations as {@link CssRulesetDeclarationToken}.
1043
+ *
1044
+ * @package CssMin/Parser/Plugins
1045
+ * @link http://code.google.com/p/cssmin/
1046
+ * @author Joe Scylla <joe.scylla@gmail.com>
1047
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1048
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1049
+ * @version 3.0.1
1050
+ */
1051
+ class CssRulesetParserPlugin extends aCssParserPlugin
1052
+ {
1053
+ /**
1054
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
1055
+ *
1056
+ * @return array
1057
+ */
1058
+ public function getTriggerChars()
1059
+ {
1060
+ return array(",", "{", "}", ":", ";");
1061
+ }
1062
+ /**
1063
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
1064
+ *
1065
+ * @return array
1066
+ */
1067
+ public function getTriggerStates()
1068
+ {
1069
+ return array("T_DOCUMENT", "T_AT_MEDIA", "T_RULESET::SELECTORS", "T_RULESET", "T_RULESET_DECLARATION");
1070
+ }
1071
+ /**
1072
+ * Selectors.
1073
+ *
1074
+ * @var array
1075
+ */
1076
+ private $selectors = array();
1077
+ /**
1078
+ * Implements {@link aCssParserPlugin::parse()}.
1079
+ *
1080
+ * @param integer $index Current index
1081
+ * @param string $char Current char
1082
+ * @param string $previousChar Previous char
1083
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
1084
+ */
1085
+ public function parse($index, $char, $previousChar, $state)
1086
+ {
1087
+ // Start of Ruleset and selectors
1088
+ if ($char === "," && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))
1089
+ {
1090
+ if ($state !== "T_RULESET::SELECTORS")
1091
+ {
1092
+ $this->parser->pushState("T_RULESET::SELECTORS");
1093
+ }
1094
+ $this->selectors[] = $this->parser->getAndClearBuffer(",{");
1095
+ }
1096
+ // End of selectors and start of declarations
1097
+ elseif ($char === "{" && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS"))
1098
+ {
1099
+ if ($this->parser->getBuffer() !== "")
1100
+ {
1101
+ $this->selectors[] = $this->parser->getAndClearBuffer(",{");
1102
+ if ($state == "T_RULESET::SELECTORS")
1103
+ {
1104
+ $this->parser->popState();
1105
+ }
1106
+ $this->parser->pushState("T_RULESET");
1107
+ $this->parser->appendToken(new CssRulesetStartToken($this->selectors));
1108
+ $this->selectors = array();
1109
+ }
1110
+ }
1111
+ // Start of declaration
1112
+ elseif ($char === ":" && $state === "T_RULESET")
1113
+ {
1114
+ $this->parser->pushState("T_RULESET_DECLARATION");
1115
+ $this->buffer = $this->parser->getAndClearBuffer(":;", true);
1116
+ }
1117
+ // Unterminated ruleset declaration
1118
+ elseif ($char === ":" && $state === "T_RULESET_DECLARATION")
1119
+ {
1120
+ // Ignore Internet Explorer filter declarations
1121
+ if ($this->buffer === "filter")
1122
+ {
1123
+ return false;
1124
+ }
1125
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
1126
+ }
1127
+ // End of declaration
1128
+ elseif (($char === ";" || $char === "}") && $state === "T_RULESET_DECLARATION")
1129
+ {
1130
+ $value = $this->parser->getAndClearBuffer(";}");
1131
+ if (strtolower(substr($value, -10, 10)) === "!important")
1132
+ {
1133
+ $value = trim(substr($value, 0, -10));
1134
+ $isImportant = true;
1135
+ }
1136
+ else
1137
+ {
1138
+ $isImportant = false;
1139
+ }
1140
+ $this->parser->popState();
1141
+ $this->parser->appendToken(new CssRulesetDeclarationToken($this->buffer, $value, $this->parser->getMediaTypes(), $isImportant));
1142
+ // Declaration ends with a right curly brace; so we have to end the ruleset
1143
+ if ($char === "}")
1144
+ {
1145
+ $this->parser->appendToken(new CssRulesetEndToken());
1146
+ $this->parser->popState();
1147
+ }
1148
+ $this->buffer = "";
1149
+ }
1150
+ // End of ruleset
1151
+ elseif ($char === "}" && $state === "T_RULESET")
1152
+ {
1153
+ $this->parser->popState();
1154
+ $this->parser->clearBuffer();
1155
+ $this->parser->appendToken(new CssRulesetEndToken());
1156
+ $this->buffer = "";
1157
+ $this->selectors = array();
1158
+ }
1159
+ else
1160
+ {
1161
+ return false;
1162
+ }
1163
+ return true;
1164
+ }
1165
+ }
1166
+
1167
+ /**
1168
+ * This {@link aCssToken CSS token} represents the end of a ruleset.
1169
+ *
1170
+ * @package CssMin/Tokens
1171
+ * @link http://code.google.com/p/cssmin/
1172
+ * @author Joe Scylla <joe.scylla@gmail.com>
1173
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1174
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1175
+ * @version 3.0.1
1176
+ */
1177
+ class CssRulesetEndToken extends aCssRulesetEndToken
1178
+ {
1179
+
1180
+ }
1181
+
1182
+ /**
1183
+ * This {@link aCssToken CSS token} represents a ruleset declaration.
1184
+ *
1185
+ * @package CssMin/Tokens
1186
+ * @link http://code.google.com/p/cssmin/
1187
+ * @author Joe Scylla <joe.scylla@gmail.com>
1188
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1189
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1190
+ * @version 3.0.1
1191
+ */
1192
+ class CssRulesetDeclarationToken extends aCssDeclarationToken
1193
+ {
1194
+ /**
1195
+ * Media types of the declaration.
1196
+ *
1197
+ * @var array
1198
+ */
1199
+ public $MediaTypes = array("all");
1200
+ /**
1201
+ * Set the properties of a ddocument- or at-rule @media level declaration.
1202
+ *
1203
+ * @param string $property Property of the declaration
1204
+ * @param string $value Value of the declaration
1205
+ * @param mixed $mediaTypes Media types of the declaration
1206
+ * @param boolean $isImportant Is the !important flag is set
1207
+ * @param boolean $isLast Is the declaration the last one of the ruleset
1208
+ * @return void
1209
+ */
1210
+ public function __construct($property, $value, $mediaTypes = null, $isImportant = false, $isLast = false)
1211
+ {
1212
+ parent::__construct($property, $value, $isImportant, $isLast);
1213
+ $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all");
1214
+ }
1215
+ }
1216
+
1217
+ /**
1218
+ * This {@link aCssMinifierFilter minifier filter} sets the IsLast property of any last declaration in a ruleset,
1219
+ * @font-face at-rule or @page at-rule block. If the property IsLast is TRUE the decrations will get stringified
1220
+ * without tailing semicolon.
1221
+ *
1222
+ * @package CssMin/Minifier/Filters
1223
+ * @link http://code.google.com/p/cssmin/
1224
+ * @author Joe Scylla <joe.scylla@gmail.com>
1225
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1226
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1227
+ * @version 3.0.1
1228
+ */
1229
+ class CssRemoveLastDelarationSemiColonMinifierFilter extends aCssMinifierFilter
1230
+ {
1231
+ /**
1232
+ * Implements {@link aCssMinifierFilter::filter()}.
1233
+ *
1234
+ * @param array $tokens Array of objects of type aCssToken
1235
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1236
+ */
1237
+ public function apply(array &$tokens)
1238
+ {
1239
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
1240
+ {
1241
+ $current = get_class($tokens[$i]);
1242
+ $next = isset($tokens[$i+1]) ? get_class($tokens[$i+1]) : false;
1243
+ if (($current === "CssRulesetDeclarationToken" && $next === "CssRulesetEndToken") ||
1244
+ ($current === "CssAtFontFaceDeclarationToken" && $next === "CssAtFontFaceEndToken") ||
1245
+ ($current === "CssAtPageDeclarationToken" && $next === "CssAtPageEndToken"))
1246
+ {
1247
+ $tokens[$i]->IsLast = true;
1248
+ }
1249
+ }
1250
+ return 0;
1251
+ }
1252
+ }
1253
+
1254
+ /**
1255
+ * This {@link aCssMinifierFilter minifier filter} will remove any empty rulesets (including @keyframes at-rule block
1256
+ * rulesets).
1257
+ *
1258
+ * @package CssMin/Minifier/Filters
1259
+ * @link http://code.google.com/p/cssmin/
1260
+ * @author Joe Scylla <joe.scylla@gmail.com>
1261
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1262
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1263
+ * @version 3.0.1
1264
+ */
1265
+ class CssRemoveEmptyRulesetsMinifierFilter extends aCssMinifierFilter
1266
+ {
1267
+ /**
1268
+ * Implements {@link aCssMinifierFilter::filter()}.
1269
+ *
1270
+ * @param array $tokens Array of objects of type aCssToken
1271
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1272
+ */
1273
+ public function apply(array &$tokens)
1274
+ {
1275
+ $r = 0;
1276
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
1277
+ {
1278
+ $current = get_class($tokens[$i]);
1279
+ $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;
1280
+ if (($current === "CssRulesetStartToken" && $next === "CssRulesetEndToken") ||
1281
+ ($current === "CssAtKeyframesRulesetStartToken" && $next === "CssAtKeyframesRulesetEndToken" && !array_intersect(array("from", "0%", "to", "100%"), array_map("strtolower", $tokens[$i]->Selectors)))
1282
+ )
1283
+ {
1284
+ $tokens[$i] = null;
1285
+ $tokens[$i + 1] = null;
1286
+ $i++;
1287
+ $r = $r + 2;
1288
+ }
1289
+ }
1290
+ return $r;
1291
+ }
1292
+ }
1293
+
1294
+ /**
1295
+ * This {@link aCssMinifierFilter minifier filter} will remove any empty @font-face, @keyframes, @media and @page
1296
+ * at-rule blocks.
1297
+ *
1298
+ * @package CssMin/Minifier/Filters
1299
+ * @link http://code.google.com/p/cssmin/
1300
+ * @author Joe Scylla <joe.scylla@gmail.com>
1301
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1302
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1303
+ * @version 3.0.1
1304
+ */
1305
+ class CssRemoveEmptyAtBlocksMinifierFilter extends aCssMinifierFilter
1306
+ {
1307
+ /**
1308
+ * Implements {@link aCssMinifierFilter::filter()}.
1309
+ *
1310
+ * @param array $tokens Array of objects of type aCssToken
1311
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1312
+ */
1313
+ public function apply(array &$tokens)
1314
+ {
1315
+ $r = 0;
1316
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
1317
+ {
1318
+ $current = get_class($tokens[$i]);
1319
+ $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false;
1320
+ if (($current === "CssAtFontFaceStartToken" && $next === "CssAtFontFaceEndToken") ||
1321
+ ($current === "CssAtKeyframesStartToken" && $next === "CssAtKeyframesEndToken") ||
1322
+ ($current === "CssAtPageStartToken" && $next === "CssAtPageEndToken") ||
1323
+ ($current === "CssAtMediaStartToken" && $next === "CssAtMediaEndToken"))
1324
+ {
1325
+ $tokens[$i] = null;
1326
+ $tokens[$i + 1] = null;
1327
+ $i++;
1328
+ $r = $r + 2;
1329
+ }
1330
+ }
1331
+ return $r;
1332
+ }
1333
+ }
1334
+
1335
+ /**
1336
+ * This {@link aCssMinifierFilter minifier filter} will remove any comments from the array of parsed tokens.
1337
+ *
1338
+ * @package CssMin/Minifier/Filters
1339
+ * @link http://code.google.com/p/cssmin/
1340
+ * @author Joe Scylla <joe.scylla@gmail.com>
1341
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1342
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1343
+ * @version 3.0.1
1344
+ */
1345
+ class CssRemoveCommentsMinifierFilter extends aCssMinifierFilter
1346
+ {
1347
+ /**
1348
+ * Implements {@link aCssMinifierFilter::filter()}.
1349
+ *
1350
+ * @param array $tokens Array of objects of type aCssToken
1351
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
1352
+ */
1353
+ public function apply(array &$tokens)
1354
+ {
1355
+ $r = 0;
1356
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
1357
+ {
1358
+ if (get_class($tokens[$i]) === "CssCommentToken")
1359
+ {
1360
+ $tokens[$i] = null;
1361
+ $r++;
1362
+ }
1363
+ }
1364
+ return $r;
1365
+ }
1366
+ }
1367
+
1368
+ /**
1369
+ * CSS Parser.
1370
+ *
1371
+ * @package CssMin/Parser
1372
+ * @link http://code.google.com/p/cssmin/
1373
+ * @author Joe Scylla <joe.scylla@gmail.com>
1374
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1375
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1376
+ * @version 3.0.1
1377
+ */
1378
+ class CssParser
1379
+ {
1380
+ /**
1381
+ * Parse buffer.
1382
+ *
1383
+ * @var string
1384
+ */
1385
+ private $buffer = "";
1386
+ /**
1387
+ * {@link aCssParserPlugin Plugins}.
1388
+ *
1389
+ * @var array
1390
+ */
1391
+ private $plugins = array();
1392
+ /**
1393
+ * Source to parse.
1394
+ *
1395
+ * @var string
1396
+ */
1397
+ private $source = "";
1398
+ /**
1399
+ * Current state.
1400
+ *
1401
+ * @var integer
1402
+ */
1403
+ private $state = "T_DOCUMENT";
1404
+ /**
1405
+ * Exclusive state.
1406
+ *
1407
+ * @var string
1408
+ */
1409
+ private $stateExclusive = false;
1410
+ /**
1411
+ * Media types state.
1412
+ *
1413
+ * @var mixed
1414
+ */
1415
+ private $stateMediaTypes = false;
1416
+ /**
1417
+ * State stack.
1418
+ *
1419
+ * @var array
1420
+ */
1421
+ private $states = array("T_DOCUMENT");
1422
+ /**
1423
+ * Parsed tokens.
1424
+ *
1425
+ * @var array
1426
+ */
1427
+ private $tokens = array();
1428
+ /**
1429
+ * Constructer.
1430
+ *
1431
+ * Create instances of the used {@link aCssParserPlugin plugins}.
1432
+ *
1433
+ * @param string $source CSS source [optional]
1434
+ * @param array $plugins Plugin configuration [optional]
1435
+ * @return void
1436
+ */
1437
+ public function __construct($source = null, array $plugins = null)
1438
+ {
1439
+ $plugins = array_merge(array
1440
+ (
1441
+ "Comment" => true,
1442
+ "String" => true,
1443
+ "Url" => true,
1444
+ "Expression" => true,
1445
+ "Ruleset" => true,
1446
+ "AtCharset" => true,
1447
+ "AtFontFace" => true,
1448
+ "AtImport" => true,
1449
+ "AtKeyframes" => true,
1450
+ "AtMedia" => true,
1451
+ "AtPage" => true,
1452
+ "AtVariables" => true
1453
+ ), is_array($plugins) ? $plugins : array());
1454
+ // Create plugin instances
1455
+ foreach ($plugins as $name => $config)
1456
+ {
1457
+ if ($config !== false)
1458
+ {
1459
+ $class = "Css" . $name . "ParserPlugin";
1460
+ $config = is_array($config) ? $config : array();
1461
+ if (class_exists($class))
1462
+ {
1463
+ $this->plugins[] = new $class($this, $config);
1464
+ }
1465
+ else
1466
+ {
1467
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
1468
+ }
1469
+ }
1470
+ }
1471
+ if (!is_null($source))
1472
+ {
1473
+ $this->parse($source);
1474
+ }
1475
+ }
1476
+ /**
1477
+ * Append a token to the array of tokens.
1478
+ *
1479
+ * @param aCssToken $token Token to append
1480
+ * @return void
1481
+ */
1482
+ public function appendToken(aCssToken $token)
1483
+ {
1484
+ $this->tokens[] = $token;
1485
+ }
1486
+ /**
1487
+ * Clears the current buffer.
1488
+ *
1489
+ * @return void
1490
+ */
1491
+ public function clearBuffer()
1492
+ {
1493
+ $this->buffer = "";
1494
+ }
1495
+ /**
1496
+ * Returns and clear the current buffer.
1497
+ *
1498
+ * @param string $trim Chars to use to trim the returned buffer
1499
+ * @param boolean $tolower if TRUE the returned buffer will get converted to lower case
1500
+ * @return string
1501
+ */
1502
+ public function getAndClearBuffer($trim = "", $tolower = false)
1503
+ {
1504
+ $r = $this->getBuffer($trim, $tolower);
1505
+ $this->buffer = "";
1506
+ return $r;
1507
+ }
1508
+ /**
1509
+ * Returns the current buffer.
1510
+ *
1511
+ * @param string $trim Chars to use to trim the returned buffer
1512
+ * @param boolean $tolower if TRUE the returned buffer will get converted to lower case
1513
+ * @return string
1514
+ */
1515
+ public function getBuffer($trim = "", $tolower = false)
1516
+ {
1517
+ $r = $this->buffer;
1518
+ if ($trim)
1519
+ {
1520
+ $r = trim($r, " \t\n\r\0\x0B" . $trim);
1521
+ }
1522
+ if ($tolower)
1523
+ {
1524
+ $r = strtolower($r);
1525
+ }
1526
+ return $r;
1527
+ }
1528
+ /**
1529
+ * Returns the current media types state.
1530
+ *
1531
+ * @return array
1532
+ */
1533
+ public function getMediaTypes()
1534
+ {
1535
+ return $this->stateMediaTypes;
1536
+ }
1537
+ /**
1538
+ * Returns the CSS source.
1539
+ *
1540
+ * @return string
1541
+ */
1542
+ public function getSource()
1543
+ {
1544
+ return $this->source;
1545
+ }
1546
+ /**
1547
+ * Returns the current state.
1548
+ *
1549
+ * @return integer The current state
1550
+ */
1551
+ public function getState()
1552
+ {
1553
+ return $this->state;
1554
+ }
1555
+ /**
1556
+ * Returns a plugin by class name.
1557
+ *
1558
+ * @param string $name Class name of the plugin
1559
+ * @return aCssParserPlugin
1560
+ */
1561
+ public function getPlugin($class)
1562
+ {
1563
+ static $index = null;
1564
+ if (is_null($index))
1565
+ {
1566
+ $index = array();
1567
+ for ($i = 0, $l = count($this->plugins); $i < $l; $i++)
1568
+ {
1569
+ $index[get_class($this->plugins[$i])] = $i;
1570
+ }
1571
+ }
1572
+ return isset($index[$class]) ? $this->plugins[$index[$class]] : false;
1573
+ }
1574
+ /**
1575
+ * Returns the parsed tokens.
1576
+ *
1577
+ * @return array
1578
+ */
1579
+ public function getTokens()
1580
+ {
1581
+ return $this->tokens;
1582
+ }
1583
+ /**
1584
+ * Returns if the current state equals the passed state.
1585
+ *
1586
+ * @param integer $state State to compare with the current state
1587
+ * @return boolean TRUE is the state equals to the passed state; FALSE if not
1588
+ */
1589
+ public function isState($state)
1590
+ {
1591
+ return ($this->state == $state);
1592
+ }
1593
+ /**
1594
+ * Parse the CSS source and return a array with parsed tokens.
1595
+ *
1596
+ * @param string $source CSS source
1597
+ * @return array Array with tokens
1598
+ */
1599
+ public function parse($source)
1600
+ {
1601
+ // Reset
1602
+ $this->source = "";
1603
+ $this->tokens = array();
1604
+ // Create a global and plugin lookup table for trigger chars; set array of plugins as local variable and create
1605
+ // several helper variables for plugin handling
1606
+ $globalTriggerChars = "";
1607
+ $plugins = $this->plugins;
1608
+ $pluginCount = count($plugins);
1609
+ $pluginIndex = array();
1610
+ $pluginTriggerStates = array();
1611
+ $pluginTriggerChars = array();
1612
+ for ($i = 0, $l = count($plugins); $i < $l; $i++)
1613
+ {
1614
+ $tPluginClassName = get_class($plugins[$i]);
1615
+ $pluginTriggerChars[$i] = implode("", $plugins[$i]->getTriggerChars());
1616
+ $tPluginTriggerStates = $plugins[$i]->getTriggerStates();
1617
+ $pluginTriggerStates[$i] = $tPluginTriggerStates === false ? false : "|" . implode("|", $tPluginTriggerStates) . "|";
1618
+ $pluginIndex[$tPluginClassName] = $i;
1619
+ for ($ii = 0, $ll = strlen($pluginTriggerChars[$i]); $ii < $ll; $ii++)
1620
+ {
1621
+ $c = substr($pluginTriggerChars[$i], $ii, 1);
1622
+ if (strpos($globalTriggerChars, $c) === false)
1623
+ {
1624
+ $globalTriggerChars .= $c;
1625
+ }
1626
+ }
1627
+ }
1628
+ // Normalise line endings
1629
+ $source = str_replace("\r\n", "\n", $source); // Windows to Unix line endings
1630
+ $source = str_replace("\r", "\n", $source); // Mac to Unix line endings
1631
+ $this->source = $source;
1632
+ // Variables
1633
+ $buffer = &$this->buffer;
1634
+ $exclusive = &$this->stateExclusive;
1635
+ $state = &$this->state;
1636
+ $c = $p = null;
1637
+ // --
1638
+ for ($i = 0, $l = strlen($source); $i < $l; $i++)
1639
+ {
1640
+ // Set the current Char
1641
+ $c = $source[$i]; // Is faster than: $c = substr($source, $i, 1);
1642
+ // Normalize and filter double whitespace characters
1643
+ if ($exclusive === false)
1644
+ {
1645
+ if ($c === "\n" || $c === "\t")
1646
+ {
1647
+ $c = " ";
1648
+ }
1649
+ if ($c === " " && $p === " ")
1650
+ {
1651
+ continue;
1652
+ }
1653
+ }
1654
+ $buffer .= $c;
1655
+ // Extended processing only if the current char is a global trigger char
1656
+ if (strpos($globalTriggerChars, $c) !== false)
1657
+ {
1658
+ // Exclusive state is set; process with the exclusive plugin
1659
+ if ($exclusive)
1660
+ {
1661
+ $tPluginIndex = $pluginIndex[$exclusive];
1662
+ if (strpos($pluginTriggerChars[$tPluginIndex], $c) !== false && ($pluginTriggerStates[$tPluginIndex] === false || strpos($pluginTriggerStates[$tPluginIndex], $state) !== false))
1663
+ {
1664
+ $r = $plugins[$tPluginIndex]->parse($i, $c, $p, $state);
1665
+ // Return value is TRUE => continue with next char
1666
+ if ($r === true)
1667
+ {
1668
+ continue;
1669
+ }
1670
+ // Return value is numeric => set new index and continue with next char
1671
+ elseif ($r !== false && $r != $i)
1672
+ {
1673
+ $i = $r;
1674
+ continue;
1675
+ }
1676
+ }
1677
+ }
1678
+ // Else iterate through the plugins
1679
+ else
1680
+ {
1681
+ $triggerState = "|" . $state . "|";
1682
+ for ($ii = 0, $ll = $pluginCount; $ii < $ll; $ii++)
1683
+ {
1684
+ // Only process if the current char is one of the plugin trigger chars
1685
+ if (strpos($pluginTriggerChars[$ii], $c) !== false && ($pluginTriggerStates[$ii] === false || strpos($pluginTriggerStates[$ii], $triggerState) !== false))
1686
+ {
1687
+ // Process with the plugin
1688
+ $r = $plugins[$ii]->parse($i, $c, $p, $state);
1689
+ // Return value is TRUE => break the plugin loop and and continue with next char
1690
+ if ($r === true)
1691
+ {
1692
+ break;
1693
+ }
1694
+ // Return value is numeric => set new index, break the plugin loop and and continue with next char
1695
+ elseif ($r !== false && $r != $i)
1696
+ {
1697
+ $i = $r;
1698
+ break;
1699
+ }
1700
+ }
1701
+ }
1702
+ }
1703
+ }
1704
+ $p = $c; // Set the parent char
1705
+ }
1706
+ return $this->tokens;
1707
+ }
1708
+ /**
1709
+ * Remove the last state of the state stack and return the removed stack value.
1710
+ *
1711
+ * @return integer Removed state value
1712
+ */
1713
+ public function popState()
1714
+ {
1715
+ $r = array_pop($this->states);
1716
+ $this->state = $this->states[count($this->states) - 1];
1717
+ return $r;
1718
+ }
1719
+ /**
1720
+ * Adds a new state onto the state stack.
1721
+ *
1722
+ * @param integer $state State to add onto the state stack.
1723
+ * @return integer The index of the added state in the state stacks
1724
+ */
1725
+ public function pushState($state)
1726
+ {
1727
+ $r = array_push($this->states, $state);
1728
+ $this->state = $this->states[count($this->states) - 1];
1729
+ return $r;
1730
+ }
1731
+ /**
1732
+ * Sets/restores the buffer.
1733
+ *
1734
+ * @param string $buffer Buffer to set
1735
+ * @return void
1736
+ */
1737
+ public function setBuffer($buffer)
1738
+ {
1739
+ $this->buffer = $buffer;
1740
+ }
1741
+ /**
1742
+ * Set the exclusive state.
1743
+ *
1744
+ * @param string $exclusive Exclusive state
1745
+ * @return void
1746
+ */
1747
+ public function setExclusive($exclusive)
1748
+ {
1749
+ $this->stateExclusive = $exclusive;
1750
+ }
1751
+ /**
1752
+ * Set the media types state.
1753
+ *
1754
+ * @param array $mediaTypes Media types state
1755
+ * @return void
1756
+ */
1757
+ public function setMediaTypes(array $mediaTypes)
1758
+ {
1759
+ $this->stateMediaTypes = $mediaTypes;
1760
+ }
1761
+ /**
1762
+ * Sets the current state in the state stack; equals to {@link CssParser::popState()} + {@link CssParser::pushState()}.
1763
+ *
1764
+ * @param integer $state State to set
1765
+ * @return integer
1766
+ */
1767
+ public function setState($state)
1768
+ {
1769
+ $r = array_pop($this->states);
1770
+ array_push($this->states, $state);
1771
+ $this->state = $this->states[count($this->states) - 1];
1772
+ return $r;
1773
+ }
1774
+ /**
1775
+ * Removes the exclusive state.
1776
+ *
1777
+ * @return void
1778
+ */
1779
+ public function unsetExclusive()
1780
+ {
1781
+ $this->stateExclusive = false;
1782
+ }
1783
+ /**
1784
+ * Removes the media types state.
1785
+ *
1786
+ * @return void
1787
+ */
1788
+ public function unsetMediaTypes()
1789
+ {
1790
+ $this->stateMediaTypes = false;
1791
+ }
1792
+ }
1793
+
1794
+ /**
1795
+ * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/j4XdU OTBS indent style} (The One True Brace Style).
1796
+ *
1797
+ * @package CssMin/Formatter
1798
+ * @link http://code.google.com/p/cssmin/
1799
+ * @author Joe Scylla <joe.scylla@gmail.com>
1800
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1801
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1802
+ * @version 3.0.1
1803
+ */
1804
+ class CssOtbsFormatter extends aCssFormatter
1805
+ {
1806
+ /**
1807
+ * Implements {@link aCssFormatter::__toString()}.
1808
+ *
1809
+ * @return string
1810
+ */
1811
+ public function __toString()
1812
+ {
1813
+ $r = array();
1814
+ $level = 0;
1815
+ for ($i = 0, $l = count($this->tokens); $i < $l; $i++)
1816
+ {
1817
+ $token = $this->tokens[$i];
1818
+ $class = get_class($token);
1819
+ $indent = str_repeat($this->indent, $level);
1820
+ if ($class === "CssCommentToken")
1821
+ {
1822
+ $lines = array_map("trim", explode("\n", $token->Comment));
1823
+ for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++)
1824
+ {
1825
+ $r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii];
1826
+ }
1827
+ }
1828
+ elseif ($class === "CssAtCharsetToken")
1829
+ {
1830
+ $r[] = $indent . "@charset " . $token->Charset . ";";
1831
+ }
1832
+ elseif ($class === "CssAtFontFaceStartToken")
1833
+ {
1834
+ $r[] = $indent . "@font-face {";
1835
+ $level++;
1836
+ }
1837
+ elseif ($class === "CssAtImportToken")
1838
+ {
1839
+ $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";";
1840
+ }
1841
+ elseif ($class === "CssAtKeyframesStartToken")
1842
+ {
1843
+ $r[] = $indent . "@keyframes \"" . $token->Name . "\" {";
1844
+ $level++;
1845
+ }
1846
+ elseif ($class === "CssAtMediaStartToken")
1847
+ {
1848
+ $r[] = $indent . "@media " . implode(", ", $token->MediaTypes) . " {";
1849
+ $level++;
1850
+ }
1851
+ elseif ($class === "CssAtPageStartToken")
1852
+ {
1853
+ $r[] = $indent . "@page {";
1854
+ $level++;
1855
+ }
1856
+ elseif ($class === "CssAtVariablesStartToken")
1857
+ {
1858
+ $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes) . " {";
1859
+ $level++;
1860
+ }
1861
+ elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken")
1862
+ {
1863
+ $r[] = $indent . implode(", ", $token->Selectors) . " {";
1864
+ $level++;
1865
+ }
1866
+ elseif ($class == "CssAtFontFaceDeclarationToken"
1867
+ || $class === "CssAtKeyframesRulesetDeclarationToken"
1868
+ || $class === "CssAtPageDeclarationToken"
1869
+ || $class == "CssAtVariablesDeclarationToken"
1870
+ || $class === "CssRulesetDeclarationToken"
1871
+ )
1872
+ {
1873
+ $declaration = $indent . $token->Property . ": ";
1874
+ if ($this->padding)
1875
+ {
1876
+ $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT);
1877
+ }
1878
+ $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";";
1879
+ }
1880
+ elseif ($class === "CssAtFontFaceEndToken"
1881
+ || $class === "CssAtMediaEndToken"
1882
+ || $class === "CssAtKeyframesEndToken"
1883
+ || $class === "CssAtKeyframesRulesetEndToken"
1884
+ || $class === "CssAtPageEndToken"
1885
+ || $class === "CssAtVariablesEndToken"
1886
+ || $class === "CssRulesetEndToken"
1887
+ )
1888
+ {
1889
+ $level--;
1890
+ $r[] = str_repeat($indent, $level) . "}";
1891
+ }
1892
+ }
1893
+ return implode("\n", $r);
1894
+ }
1895
+ }
1896
+
1897
+ /**
1898
+ * This {@link aCssToken CSS token} is a utility token that extends {@link aNullToken} and returns only a empty string.
1899
+ *
1900
+ * @package CssMin/Tokens
1901
+ * @link http://code.google.com/p/cssmin/
1902
+ * @author Joe Scylla <joe.scylla@gmail.com>
1903
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1904
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1905
+ * @version 3.0.1
1906
+ */
1907
+ class CssNullToken extends aCssToken
1908
+ {
1909
+ /**
1910
+ * Implements {@link aCssToken::__toString()}.
1911
+ *
1912
+ * @return string
1913
+ */
1914
+ public function __toString()
1915
+ {
1916
+ return "";
1917
+ }
1918
+ }
1919
+
1920
+ /**
1921
+ * CSS Minifier.
1922
+ *
1923
+ * @package CssMin/Minifier
1924
+ * @link http://code.google.com/p/cssmin/
1925
+ * @author Joe Scylla <joe.scylla@gmail.com>
1926
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
1927
+ * @license http://opensource.org/licenses/mit-license.php MIT License
1928
+ * @version 3.0.1
1929
+ */
1930
+ class CssMinifier
1931
+ {
1932
+ /**
1933
+ * {@link aCssMinifierFilter Filters}.
1934
+ *
1935
+ * @var array
1936
+ */
1937
+ private $filters = array();
1938
+ /**
1939
+ * {@link aCssMinifierPlugin Plugins}.
1940
+ *
1941
+ * @var array
1942
+ */
1943
+ private $plugins = array();
1944
+ /**
1945
+ * Minified source.
1946
+ *
1947
+ * @var string
1948
+ */
1949
+ private $minified = "";
1950
+ /**
1951
+ * Constructer.
1952
+ *
1953
+ * Creates instances of {@link aCssMinifierFilter filters} and {@link aCssMinifierPlugin plugins}.
1954
+ *
1955
+ * @param string $source CSS source [optional]
1956
+ * @param array $filters Filter configuration [optional]
1957
+ * @param array $plugins Plugin configuration [optional]
1958
+ * @return void
1959
+ */
1960
+ public function __construct($source = null, array $filters = null, array $plugins = null)
1961
+ {
1962
+ $filters = array_merge(array
1963
+ (
1964
+ "ImportImports" => false,
1965
+ "RemoveComments" => true,
1966
+ "RemoveEmptyRulesets" => true,
1967
+ "RemoveEmptyAtBlocks" => true,
1968
+ "ConvertLevel3Properties" => false,
1969
+ "ConvertLevel3AtKeyframes" => false,
1970
+ "Variables" => true,
1971
+ "RemoveLastDelarationSemiColon" => true
1972
+ ), is_array($filters) ? $filters : array());
1973
+ $plugins = array_merge(array
1974
+ (
1975
+ "Variables" => true,
1976
+ "ConvertFontWeight" => false,
1977
+ "ConvertHslColors" => false,
1978
+ "ConvertRgbColors" => false,
1979
+ "ConvertNamedColors" => false,
1980
+ "CompressColorValues" => false,
1981
+ "CompressUnitValues" => false,
1982
+ "CompressExpressionValues" => false
1983
+ ), is_array($plugins) ? $plugins : array());
1984
+ // Filters
1985
+ foreach ($filters as $name => $config)
1986
+ {
1987
+ if ($config !== false)
1988
+ {
1989
+ $class = "Css" . $name . "MinifierFilter";
1990
+ $config = is_array($config) ? $config : array();
1991
+ if (class_exists($class))
1992
+ {
1993
+ $this->filters[] = new $class($this, $config);
1994
+ }
1995
+ else
1996
+ {
1997
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The filter <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
1998
+ }
1999
+ }
2000
+ }
2001
+ // Plugins
2002
+ foreach ($plugins as $name => $config)
2003
+ {
2004
+ if ($config !== false)
2005
+ {
2006
+ $class = "Css" . $name . "MinifierPlugin";
2007
+ $config = is_array($config) ? $config : array();
2008
+ if (class_exists($class))
2009
+ {
2010
+ $this->plugins[] = new $class($this, $config);
2011
+ }
2012
+ else
2013
+ {
2014
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin <code>" . $name . "</code> with the class name <code>" . $class . "</code> was not found"));
2015
+ }
2016
+ }
2017
+ }
2018
+ // --
2019
+ if (!is_null($source))
2020
+ {
2021
+ $this->minify($source);
2022
+ }
2023
+ }
2024
+ /**
2025
+ * Returns the minified Source.
2026
+ *
2027
+ * @return string
2028
+ */
2029
+ public function getMinified()
2030
+ {
2031
+ return $this->minified;
2032
+ }
2033
+ /**
2034
+ * Returns a plugin by class name.
2035
+ *
2036
+ * @param string $name Class name of the plugin
2037
+ * @return aCssMinifierPlugin
2038
+ */
2039
+ public function getPlugin($class)
2040
+ {
2041
+ static $index = null;
2042
+ if (is_null($index))
2043
+ {
2044
+ $index = array();
2045
+ for ($i = 0, $l = count($this->plugins); $i < $l; $i++)
2046
+ {
2047
+ $index[get_class($this->plugins[$i])] = $i;
2048
+ }
2049
+ }
2050
+ return isset($index[$class]) ? $this->plugins[$index[$class]] : false;
2051
+ }
2052
+ /**
2053
+ * Minifies the CSS source.
2054
+ *
2055
+ * @param string $source CSS source
2056
+ * @return string
2057
+ */
2058
+ public function minify($source)
2059
+ {
2060
+ // Variables
2061
+ $r = "";
2062
+ $parser = new CssParser($source);
2063
+ $tokens = $parser->getTokens();
2064
+ $filters = $this->filters;
2065
+ $filterCount = count($this->filters);
2066
+ $plugins = $this->plugins;
2067
+ $pluginCount = count($plugins);
2068
+ $pluginIndex = array();
2069
+ $pluginTriggerTokens = array();
2070
+ $globalTriggerTokens = array();
2071
+ for ($i = 0, $l = count($plugins); $i < $l; $i++)
2072
+ {
2073
+ $tPluginClassName = get_class($plugins[$i]);
2074
+ $pluginTriggerTokens[$i] = $plugins[$i]->getTriggerTokens();
2075
+ foreach ($pluginTriggerTokens[$i] as $v)
2076
+ {
2077
+ if (!in_array($v, $globalTriggerTokens))
2078
+ {
2079
+ $globalTriggerTokens[] = $v;
2080
+ }
2081
+ }
2082
+ $pluginTriggerTokens[$i] = "|" . implode("|", $pluginTriggerTokens[$i]) . "|";
2083
+ $pluginIndex[$tPluginClassName] = $i;
2084
+ }
2085
+ $globalTriggerTokens = "|" . implode("|", $globalTriggerTokens) . "|";
2086
+ /*
2087
+ * Apply filters
2088
+ */
2089
+ for($i = 0; $i < $filterCount; $i++)
2090
+ {
2091
+ // Apply the filter; if the return value is larger than 0...
2092
+ if ($filters[$i]->apply($tokens) > 0)
2093
+ {
2094
+ // ...then filter null values and rebuild the token array
2095
+ $tokens = array_values(array_filter($tokens));
2096
+ }
2097
+ }
2098
+ $tokenCount = count($tokens);
2099
+ /*
2100
+ * Apply plugins
2101
+ */
2102
+ for($i = 0; $i < $tokenCount; $i++)
2103
+ {
2104
+ $triggerToken = "|" . get_class($tokens[$i]) . "|";
2105
+ if (strpos($globalTriggerTokens, $triggerToken) !== false)
2106
+ {
2107
+ for($ii = 0; $ii < $pluginCount; $ii++)
2108
+ {
2109
+ if (strpos($pluginTriggerTokens[$ii], $triggerToken) !== false || $pluginTriggerTokens[$ii] === false)
2110
+ {
2111
+ // Apply the plugin; if the return value is TRUE continue to the next token
2112
+ if ($plugins[$ii]->apply($tokens[$i]) === true)
2113
+ {
2114
+ continue 2;
2115
+ }
2116
+ }
2117
+ }
2118
+ }
2119
+ }
2120
+ // Stringify the tokens
2121
+ for($i = 0; $i < $tokenCount; $i++)
2122
+ {
2123
+ $r .= (string) $tokens[$i];
2124
+ }
2125
+ $this->minified = $r;
2126
+ return $r;
2127
+ }
2128
+ }
2129
+
2130
+ /**
2131
+ * CssMin - A (simple) css minifier with benefits
2132
+ *
2133
+ * --
2134
+ * Copyright (c) 2011 Joe Scylla <joe.scylla@gmail.com>
2135
+ *
2136
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
2137
+ * of this software and associated documentation files (the "Software"), to deal
2138
+ * in the Software without restriction, including without limitation the rights
2139
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2140
+ * copies of the Software, and to permit persons to whom the Software is
2141
+ * furnished to do so, subject to the following conditions:
2142
+ *
2143
+ * The above copyright notice and this permission notice shall be included in
2144
+ * all copies or substantial portions of the Software.
2145
+ *
2146
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2147
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2148
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2149
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2150
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2151
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2152
+ * THE SOFTWARE.
2153
+ * --
2154
+ *
2155
+ * @package CssMin
2156
+ * @link http://code.google.com/p/cssmin/
2157
+ * @author Joe Scylla <joe.scylla@gmail.com>
2158
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2159
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2160
+ * @version 3.0.1
2161
+ */
2162
+ class CssMin
2163
+ {
2164
+ /**
2165
+ * Index of classes
2166
+ *
2167
+ * @var array
2168
+ */
2169
+ private static $classIndex = array();
2170
+ /**
2171
+ * Parse/minify errors
2172
+ *
2173
+ * @var array
2174
+ */
2175
+ private static $errors = array();
2176
+ /**
2177
+ * Verbose output.
2178
+ *
2179
+ * @var boolean
2180
+ */
2181
+ private static $isVerbose = false;
2182
+ /**
2183
+ * {@link http://goo.gl/JrW54 Autoload} function of CssMin.
2184
+ *
2185
+ * @param string $class Name of the class
2186
+ * @return void
2187
+ */
2188
+ public static function autoload($class)
2189
+ {
2190
+ if (isset(self::$classIndex[$class]))
2191
+ {
2192
+ require(self::$classIndex[$class]);
2193
+ }
2194
+ }
2195
+ /**
2196
+ * Return errors
2197
+ *
2198
+ * @return array of {CssError}.
2199
+ */
2200
+ public static function getErrors()
2201
+ {
2202
+ return self::$errors;
2203
+ }
2204
+ /**
2205
+ * Returns if there were errors.
2206
+ *
2207
+ * @return boolean
2208
+ */
2209
+ public static function hasErrors()
2210
+ {
2211
+ return count(self::$errors) > 0;
2212
+ }
2213
+ /**
2214
+ * Initialises CssMin.
2215
+ *
2216
+ * @return void
2217
+ */
2218
+ public static function initialise()
2219
+ {
2220
+ // Create the class index for autoloading or including
2221
+ $paths = array(dirname(__FILE__));
2222
+ while (list($i, $path) = each($paths))
2223
+ {
2224
+ $subDirectorys = glob($path . "*", GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);
2225
+ if (is_array($subDirectorys))
2226
+ {
2227
+ foreach ($subDirectorys as $subDirectory)
2228
+ {
2229
+ $paths[] = $subDirectory;
2230
+ }
2231
+ }
2232
+ $files = glob($path . "*.php", 0);
2233
+ if (is_array($files))
2234
+ {
2235
+ foreach ($files as $file)
2236
+ {
2237
+ $class = substr(basename($file), 0, -4);
2238
+ self::$classIndex[$class] = $file;
2239
+ }
2240
+ }
2241
+ }
2242
+ krsort(self::$classIndex);
2243
+ // Only use autoloading if spl_autoload_register() is available and no __autoload() is defined (because
2244
+ // __autoload() breaks if spl_autoload_register() is used.
2245
+ if (function_exists("spl_autoload_register") && !is_callable("__autoload"))
2246
+ {
2247
+ spl_autoload_register(array(__CLASS__, "autoload"));
2248
+ }
2249
+ // Otherwise include all class files
2250
+ else
2251
+ {
2252
+ foreach (self::$classIndex as $class => $file)
2253
+ {
2254
+ if (!class_exists($class))
2255
+ {
2256
+ require_once($file);
2257
+ }
2258
+ }
2259
+ }
2260
+ }
2261
+ /**
2262
+ * Minifies CSS source.
2263
+ *
2264
+ * @param string $source CSS source
2265
+ * @param array $filters Filter configuration [optional]
2266
+ * @param array $plugins Plugin configuration [optional]
2267
+ * @return string Minified CSS
2268
+ */
2269
+ public static function minify($source, array $filters = null, array $plugins = null)
2270
+ {
2271
+ self::$errors = array();
2272
+ $minifier = new CssMinifier($source, $filters, $plugins);
2273
+ return $minifier->getMinified();
2274
+ }
2275
+ /**
2276
+ * Parse the CSS source.
2277
+ *
2278
+ * @param string $source CSS source
2279
+ * @param array $plugins Plugin configuration [optional]
2280
+ * @return array Array of aCssToken
2281
+ */
2282
+ public static function parse($source, array $plugins = null)
2283
+ {
2284
+ self::$errors = array();
2285
+ $parser = new CssParser($source, $plugins);
2286
+ return $parser->getTokens();
2287
+ }
2288
+ /**
2289
+ * --
2290
+ *
2291
+ * @param boolean $to
2292
+ * @return boolean
2293
+ */
2294
+ public static function setVerbose($to)
2295
+ {
2296
+ self::$isVerbose = (boolean) $to;
2297
+ return self::$isVerbose;
2298
+ }
2299
+ /**
2300
+ * --
2301
+ *
2302
+ * @param CssError $error
2303
+ * @return void
2304
+ */
2305
+ public static function triggerError(CssError $error)
2306
+ {
2307
+ self::$errors[] = $error;
2308
+ if (self::$isVerbose)
2309
+ {
2310
+ trigger_error((string) $error, E_USER_WARNING);
2311
+ }
2312
+ }
2313
+ }
2314
+ // Initialises CssMin
2315
+ CssMin::initialise();
2316
+
2317
+ /**
2318
+ * This {@link aCssMinifierFilter minifier filter} import external css files defined with the @import at-rule into the
2319
+ * current stylesheet.
2320
+ *
2321
+ * @package CssMin/Minifier/Filters
2322
+ * @link http://code.google.com/p/cssmin/
2323
+ * @author Joe Scylla <joe.scylla@gmail.com>
2324
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2325
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2326
+ * @version 3.0.1
2327
+ */
2328
+ class CssImportImportsMinifierFilter extends aCssMinifierFilter
2329
+ {
2330
+ /**
2331
+ * Array with already imported external stylesheets.
2332
+ *
2333
+ * @var array
2334
+ */
2335
+ private $imported = array();
2336
+ /**
2337
+ * Implements {@link aCssMinifierFilter::filter()}.
2338
+ *
2339
+ * @param array $tokens Array of objects of type aCssToken
2340
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
2341
+ */
2342
+ public function apply(array &$tokens)
2343
+ {
2344
+ if (!isset($this->configuration["BasePath"]) || !is_dir($this->configuration["BasePath"]))
2345
+ {
2346
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Base path <code>" . ($this->configuration["BasePath"] ? $this->configuration["BasePath"] : "null"). "</code> is not a directory"));
2347
+ return 0;
2348
+ }
2349
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
2350
+ {
2351
+ if (get_class($tokens[$i]) === "CssAtImportToken")
2352
+ {
2353
+ $import = $this->configuration["BasePath"] . "/" . $tokens[$i]->Import;
2354
+ // Import file was not found/is not a file
2355
+ if (!is_file($import))
2356
+ {
2357
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file <code>" . $import. "</code> was not found.", (string) $tokens[$i]));
2358
+ }
2359
+ // Import file already imported; remove this @import at-rule to prevent recursions
2360
+ elseif (in_array($import, $this->imported))
2361
+ {
2362
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file <code>" . $import. "</code> was already imported.", (string) $tokens[$i]));
2363
+ $tokens[$i] = null;
2364
+ }
2365
+ else
2366
+ {
2367
+ $this->imported[] = $import;
2368
+ $parser = new CssParser(file_get_contents($import));
2369
+ $import = $parser->getTokens();
2370
+ // The @import at-rule has media types defined requiring special handling
2371
+ if (count($tokens[$i]->MediaTypes) > 0 && !(count($tokens[$i]->MediaTypes) == 1 && $tokens[$i]->MediaTypes[0] == "all"))
2372
+ {
2373
+ $blocks = array();
2374
+ /*
2375
+ * Filter or set media types of @import at-rule or remove the @import at-rule if no media type is matching the parent @import at-rule
2376
+ */
2377
+ for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2378
+ {
2379
+ if (get_class($import[$ii]) === "CssAtImportToken")
2380
+ {
2381
+ // @import at-rule defines no media type or only the "all" media type; set the media types to the one defined in the parent @import at-rule
2382
+ if (count($import[$ii]->MediaTypes) == 0 || (count($import[$ii]->MediaTypes) == 1 && $import[$ii]->MediaTypes[0] == "all"))
2383
+ {
2384
+ $import[$ii]->MediaTypes = $tokens[$i]->MediaTypes;
2385
+ }
2386
+ // @import at-rule defineds one or more media types; filter out media types not matching with the parent @import at-rule
2387
+ elseif (count($import[$ii]->MediaTypes > 0))
2388
+ {
2389
+ foreach ($import[$ii]->MediaTypes as $index => $mediaType)
2390
+ {
2391
+ if (!in_array($mediaType, $tokens[$i]->MediaTypes))
2392
+ {
2393
+ unset($import[$ii]->MediaTypes[$index]);
2394
+ }
2395
+ }
2396
+ $import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes);
2397
+ // If there are no media types left in the @import at-rule remove the @import at-rule
2398
+ if (count($import[$ii]->MediaTypes) == 0)
2399
+ {
2400
+ $import[$ii] = null;
2401
+ }
2402
+ }
2403
+ }
2404
+ }
2405
+ /*
2406
+ * Remove media types of @media at-rule block not defined in the @import at-rule
2407
+ */
2408
+ for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2409
+ {
2410
+ if (get_class($import[$ii]) === "CssAtMediaStartToken")
2411
+ {
2412
+ foreach ($import[$ii]->MediaTypes as $index => $mediaType)
2413
+ {
2414
+ if (!in_array($mediaType, $tokens[$i]->MediaTypes))
2415
+ {
2416
+ unset($import[$ii]->MediaTypes[$index]);
2417
+ }
2418
+ $import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes);
2419
+ }
2420
+ }
2421
+ }
2422
+ /*
2423
+ * If no media types left of the @media at-rule block remove the complete block
2424
+ */
2425
+ for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2426
+ {
2427
+ if (get_class($import[$ii]) === "CssAtMediaStartToken")
2428
+ {
2429
+ if (count($import[$ii]->MediaTypes) === 0)
2430
+ {
2431
+ for ($iii = $ii; $iii < $ll; $iii++)
2432
+ {
2433
+ if (get_class($import[$iii]) === "CssAtMediaEndToken")
2434
+ {
2435
+ break;
2436
+ }
2437
+ }
2438
+ if (get_class($import[$iii]) === "CssAtMediaEndToken")
2439
+ {
2440
+ array_splice($import, $ii, $iii - $ii + 1, array());
2441
+ $ll = count($import);
2442
+ }
2443
+ }
2444
+ }
2445
+ }
2446
+ /*
2447
+ * If the media types of the @media at-rule equals the media types defined in the @import
2448
+ * at-rule remove the CssAtMediaStartToken and CssAtMediaEndToken token
2449
+ */
2450
+ for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2451
+ {
2452
+ if (get_class($import[$ii]) === "CssAtMediaStartToken" && count(array_diff($tokens[$i]->MediaTypes, $import[$ii]->MediaTypes)) === 0)
2453
+ {
2454
+ for ($iii = $ii; $iii < $ll; $iii++)
2455
+ {
2456
+ if (get_class($import[$iii]) == "CssAtMediaEndToken")
2457
+ {
2458
+ break;
2459
+ }
2460
+ }
2461
+ if (get_class($import[$iii]) == "CssAtMediaEndToken")
2462
+ {
2463
+ unset($import[$ii]);
2464
+ unset($import[$iii]);
2465
+ $import = array_values($import);
2466
+ $ll = count($import);
2467
+ }
2468
+ }
2469
+ }
2470
+ /**
2471
+ * Extract CssAtImportToken and CssAtCharsetToken tokens
2472
+ */
2473
+ for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2474
+ {
2475
+ $class = get_class($import[$ii]);
2476
+ if ($class === "CssAtImportToken" || $class === "CssAtCharsetToken")
2477
+ {
2478
+ $blocks = array_merge($blocks, array_splice($import, $ii, 1, array()));
2479
+ $ll = count($import);
2480
+ }
2481
+ }
2482
+ /*
2483
+ * Extract the @font-face, @media and @page at-rule block
2484
+ */
2485
+ for($ii = 0, $ll = count($import); $ii < $ll; $ii++)
2486
+ {
2487
+ $class = get_class($import[$ii]);
2488
+ if ($class === "CssAtFontFaceStartToken" || $class === "CssAtMediaStartToken" || $class === "CssAtPageStartToken" || $class === "CssAtVariablesStartToken")
2489
+ {
2490
+ for ($iii = $ii; $iii < $ll; $iii++)
2491
+ {
2492
+ $class = get_class($import[$iii]);
2493
+ if ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken")
2494
+ {
2495
+ break;
2496
+ }
2497
+ }
2498
+ $class = get_class($import[$iii]);
2499
+ if (isset($import[$iii]) && ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken"))
2500
+ {
2501
+ $blocks = array_merge($blocks, array_splice($import, $ii, $iii - $ii + 1, array()));
2502
+ $ll = count($import);
2503
+ }
2504
+ }
2505
+ }
2506
+ // Create the import array with extracted tokens and the rulesets wrapped into a @media at-rule block
2507
+ $import = array_merge($blocks, array(new CssAtMediaStartToken($tokens[$i]->MediaTypes)), $import, array(new CssAtMediaEndToken()));
2508
+ }
2509
+ // Insert the imported tokens
2510
+ array_splice($tokens, $i, 1, $import);
2511
+ // Modify parameters of the for-loop
2512
+ $i--;
2513
+ $l = count($tokens);
2514
+ }
2515
+ }
2516
+ }
2517
+ }
2518
+ }
2519
+
2520
+ /**
2521
+ * {@link aCssParserPlugin Parser plugin} for preserve parsing expression() declaration values.
2522
+ *
2523
+ * This plugin return no {@link aCssToken CssToken} but ensures that expression() declaration values will get parsed
2524
+ * properly.
2525
+ *
2526
+ * @package CssMin/Parser/Plugins
2527
+ * @link http://code.google.com/p/cssmin/
2528
+ * @author Joe Scylla <joe.scylla@gmail.com>
2529
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2530
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2531
+ * @version 3.0.1
2532
+ */
2533
+ class CssExpressionParserPlugin extends aCssParserPlugin
2534
+ {
2535
+ /**
2536
+ * Count of left braces.
2537
+ *
2538
+ * @var integer
2539
+ */
2540
+ private $leftBraces = 0;
2541
+ /**
2542
+ * Count of right braces.
2543
+ *
2544
+ * @var integer
2545
+ */
2546
+ private $rightBraces = 0;
2547
+ /**
2548
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
2549
+ *
2550
+ * @return array
2551
+ */
2552
+ public function getTriggerChars()
2553
+ {
2554
+ return array("(", ")", ";", "}");
2555
+ }
2556
+ /**
2557
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
2558
+ *
2559
+ * @return array
2560
+ */
2561
+ public function getTriggerStates()
2562
+ {
2563
+ return false;
2564
+ }
2565
+ /**
2566
+ * Implements {@link aCssParserPlugin::parse()}.
2567
+ *
2568
+ * @param integer $index Current index
2569
+ * @param string $char Current char
2570
+ * @param string $previousChar Previous char
2571
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
2572
+ */
2573
+ public function parse($index, $char, $previousChar, $state)
2574
+ {
2575
+ // Start of expression
2576
+ if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 10, 11)) === "expression(" && $state !== "T_EXPRESSION")
2577
+ {
2578
+ $this->parser->pushState("T_EXPRESSION");
2579
+ $this->leftBraces++;
2580
+ }
2581
+ // Count left braces
2582
+ elseif ($char === "(" && $state === "T_EXPRESSION")
2583
+ {
2584
+ $this->leftBraces++;
2585
+ }
2586
+ // Count right braces
2587
+ elseif ($char === ")" && $state === "T_EXPRESSION")
2588
+ {
2589
+ $this->rightBraces++;
2590
+ }
2591
+ // Possible end of expression; if left and right braces are equal the expressen ends
2592
+ elseif (($char === ";" || $char === "}") && $state === "T_EXPRESSION" && $this->leftBraces === $this->rightBraces)
2593
+ {
2594
+ $this->leftBraces = $this->rightBraces = 0;
2595
+ $this->parser->popState();
2596
+ return $index - 1;
2597
+ }
2598
+ else
2599
+ {
2600
+ return false;
2601
+ }
2602
+ return true;
2603
+ }
2604
+ }
2605
+
2606
+ /**
2607
+ * CSS Error.
2608
+ *
2609
+ * @package CssMin
2610
+ * @link http://code.google.com/p/cssmin/
2611
+ * @author Joe Scylla <joe.scylla@gmail.com>
2612
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2613
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2614
+ * @version 3.0.1
2615
+ */
2616
+ class CssError
2617
+ {
2618
+ /**
2619
+ * File.
2620
+ *
2621
+ * @var string
2622
+ */
2623
+ public $File = "";
2624
+ /**
2625
+ * Line.
2626
+ *
2627
+ * @var integer
2628
+ */
2629
+ public $Line = 0;
2630
+ /**
2631
+ * Error message.
2632
+ *
2633
+ * @var string
2634
+ */
2635
+ public $Message = "";
2636
+ /**
2637
+ * Source.
2638
+ *
2639
+ * @var string
2640
+ */
2641
+ public $Source = "";
2642
+ /**
2643
+ * Constructor triggering the error.
2644
+ *
2645
+ * @param string $message Error message
2646
+ * @param string $source Corresponding line [optional]
2647
+ * @return void
2648
+ */
2649
+ public function __construct($file, $line, $message, $source = "")
2650
+ {
2651
+ $this->File = $file;
2652
+ $this->Line = $line;
2653
+ $this->Message = $message;
2654
+ $this->Source = $source;
2655
+ }
2656
+ /**
2657
+ * Returns the error as formatted string.
2658
+ *
2659
+ * @return string
2660
+ */
2661
+ public function __toString()
2662
+ {
2663
+ return $this->Message . ($this->Source ? ": <br /><code>" . $this->Source . "</code>": "") . "<br />in file " . $this->File . " at line " . $this->Line;
2664
+ }
2665
+ }
2666
+
2667
+ /**
2668
+ * This {@link aCssMinifierPlugin} will convert a color value in rgb notation to hexadecimal notation.
2669
+ *
2670
+ * Example:
2671
+ * <code>
2672
+ * color: rgb(200,60%,5);
2673
+ * </code>
2674
+ *
2675
+ * Will get converted to:
2676
+ * <code>
2677
+ * color:#c89905;
2678
+ * </code>
2679
+ *
2680
+ * @package CssMin/Minifier/Plugins
2681
+ * @link http://code.google.com/p/cssmin/
2682
+ * @author Joe Scylla <joe.scylla@gmail.com>
2683
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2684
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2685
+ * @version 3.0.1
2686
+ */
2687
+ class CssConvertRgbColorsMinifierPlugin extends aCssMinifierPlugin
2688
+ {
2689
+ /**
2690
+ * Regular expression matching the value.
2691
+ *
2692
+ * @var string
2693
+ */
2694
+ private $reMatch = "/rgb\s*\(\s*([0-9%]+)\s*,\s*([0-9%]+)\s*,\s*([0-9%]+)\s*\)/iS";
2695
+ /**
2696
+ * Implements {@link aCssMinifierPlugin::minify()}.
2697
+ *
2698
+ * @param aCssToken $token Token to process
2699
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
2700
+ */
2701
+ public function apply(aCssToken &$token)
2702
+ {
2703
+ if (stripos($token->Value, "rgb") !== false && preg_match($this->reMatch, $token->Value, $m))
2704
+ {
2705
+ for ($i = 1, $l = count($m); $i < $l; $i++)
2706
+ {
2707
+ if (strpos("%", $m[$i]) !== false)
2708
+ {
2709
+ $m[$i] = substr($m[$i], 0, -1);
2710
+ $m[$i] = (int) (256 * ($m[$i] / 100));
2711
+ }
2712
+ $m[$i] = str_pad(dechex($m[$i]), 2, "0", STR_PAD_LEFT);
2713
+ }
2714
+ $token->Value = str_replace($m[0], "#" . $m[1] . $m[2] . $m[3], $token->Value);
2715
+ }
2716
+ return false;
2717
+ }
2718
+ /**
2719
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
2720
+ *
2721
+ * @return array
2722
+ */
2723
+ public function getTriggerTokens()
2724
+ {
2725
+ return array
2726
+ (
2727
+ "CssAtFontFaceDeclarationToken",
2728
+ "CssAtPageDeclarationToken",
2729
+ "CssRulesetDeclarationToken"
2730
+ );
2731
+ }
2732
+ }
2733
+
2734
+ /**
2735
+ * This {@link aCssMinifierPlugin} will convert named color values to hexadecimal notation.
2736
+ *
2737
+ * Example:
2738
+ * <code>
2739
+ * color: black;
2740
+ * border: 1px solid indigo;
2741
+ * </code>
2742
+ *
2743
+ * Will get converted to:
2744
+ * <code>
2745
+ * color:#000;
2746
+ * border:1px solid #4b0082;
2747
+ * </code>
2748
+ *
2749
+ * @package CssMin/Minifier/Plugins
2750
+ * @link http://code.google.com/p/cssmin/
2751
+ * @author Joe Scylla <joe.scylla@gmail.com>
2752
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2753
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2754
+ * @version 3.0.1
2755
+ */
2756
+ class CssConvertNamedColorsMinifierPlugin extends aCssMinifierPlugin
2757
+ {
2758
+
2759
+ /**
2760
+ * Regular expression matching the value.
2761
+ *
2762
+ * @var string
2763
+ */
2764
+ private $reMatch = null;
2765
+ /**
2766
+ * Regular expression replacing the value.
2767
+ *
2768
+ * @var string
2769
+ */
2770
+ private $reReplace = "\"\${1}\" . \$this->transformation[strtolower(\"\${2}\")] . \"\${3}\"";
2771
+ /**
2772
+ * Transformation table used by the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}.
2773
+ *
2774
+ * @var array
2775
+ */
2776
+ private $transformation = array
2777
+ (
2778
+ "aliceblue" => "#f0f8ff",
2779
+ "antiquewhite" => "#faebd7",
2780
+ "aqua" => "#0ff",
2781
+ "aquamarine" => "#7fffd4",
2782
+ "azure" => "#f0ffff",
2783
+ "beige" => "#f5f5dc",
2784
+ "black" => "#000",
2785
+ "blue" => "#00f",
2786
+ "blueviolet" => "#8a2be2",
2787
+ "brown" => "#a52a2a",
2788
+ "burlywood" => "#deb887",
2789
+ "cadetblue" => "#5f9ea0",
2790
+ "chartreuse" => "#7fff00",
2791
+ "chocolate" => "#d2691e",
2792
+ "coral" => "#ff7f50",
2793
+ "cornflowerblue" => "#6495ed",
2794
+ "cornsilk" => "#fff8dc",
2795
+ "crimson" => "#dc143c",
2796
+ "darkblue" => "#00008b",
2797
+ "darkcyan" => "#008b8b",
2798
+ "darkgoldenrod" => "#b8860b",
2799
+ "darkgray" => "#a9a9a9",
2800
+ "darkgreen" => "#006400",
2801
+ "darkkhaki" => "#bdb76b",
2802
+ "darkmagenta" => "#8b008b",
2803
+ "darkolivegreen" => "#556b2f",
2804
+ "darkorange" => "#ff8c00",
2805
+ "darkorchid" => "#9932cc",
2806
+ "darkred" => "#8b0000",
2807
+ "darksalmon" => "#e9967a",
2808
+ "darkseagreen" => "#8fbc8f",
2809
+ "darkslateblue" => "#483d8b",
2810
+ "darkslategray" => "#2f4f4f",
2811
+ "darkturquoise" => "#00ced1",
2812
+ "darkviolet" => "#9400d3",
2813
+ "deeppink" => "#ff1493",
2814
+ "deepskyblue" => "#00bfff",
2815
+ "dimgray" => "#696969",
2816
+ "dodgerblue" => "#1e90ff",
2817
+ "firebrick" => "#b22222",
2818
+ "floralwhite" => "#fffaf0",
2819
+ "forestgreen" => "#228b22",
2820
+ "fuchsia" => "#f0f",
2821
+ "gainsboro" => "#dcdcdc",
2822
+ "ghostwhite" => "#f8f8ff",
2823
+ "gold" => "#ffd700",
2824
+ "goldenrod" => "#daa520",
2825
+ "gray" => "#808080",
2826
+ "green" => "#008000",
2827
+ "greenyellow" => "#adff2f",
2828
+ "honeydew" => "#f0fff0",
2829
+ "hotpink" => "#ff69b4",
2830
+ "indianred" => "#cd5c5c",
2831
+ "indigo" => "#4b0082",
2832
+ "ivory" => "#fffff0",
2833
+ "khaki" => "#f0e68c",
2834
+ "lavender" => "#e6e6fa",
2835
+ "lavenderblush" => "#fff0f5",
2836
+ "lawngreen" => "#7cfc00",
2837
+ "lemonchiffon" => "#fffacd",
2838
+ "lightblue" => "#add8e6",
2839
+ "lightcoral" => "#f08080",
2840
+ "lightcyan" => "#e0ffff",
2841
+ "lightgoldenrodyellow" => "#fafad2",
2842
+ "lightgreen" => "#90ee90",
2843
+ "lightgrey" => "#d3d3d3",
2844
+ "lightpink" => "#ffb6c1",
2845
+ "lightsalmon" => "#ffa07a",
2846
+ "lightseagreen" => "#20b2aa",
2847
+ "lightskyblue" => "#87cefa",
2848
+ "lightslategray" => "#789",
2849
+ "lightsteelblue" => "#b0c4de",
2850
+ "lightyellow" => "#ffffe0",
2851
+ "lime" => "#0f0",
2852
+ "limegreen" => "#32cd32",
2853
+ "linen" => "#faf0e6",
2854
+ "maroon" => "#800000",
2855
+ "mediumaquamarine" => "#66cdaa",
2856
+ "mediumblue" => "#0000cd",
2857
+ "mediumorchid" => "#ba55d3",
2858
+ "mediumpurple" => "#9370db",
2859
+ "mediumseagreen" => "#3cb371",
2860
+ "mediumslateblue" => "#7b68ee",
2861
+ "mediumspringgreen" => "#00fa9a",
2862
+ "mediumturquoise" => "#48d1cc",
2863
+ "mediumvioletred" => "#c71585",
2864
+ "midnightblue" => "#191970",
2865
+ "mintcream" => "#f5fffa",
2866
+ "mistyrose" => "#ffe4e1",
2867
+ "moccasin" => "#ffe4b5",
2868
+ "navajowhite" => "#ffdead",
2869
+ "navy" => "#000080",
2870
+ "oldlace" => "#fdf5e6",
2871
+ "olive" => "#808000",
2872
+ "olivedrab" => "#6b8e23",
2873
+ "orange" => "#ffa500",
2874
+ "orangered" => "#ff4500",
2875
+ "orchid" => "#da70d6",
2876
+ "palegoldenrod" => "#eee8aa",
2877
+ "palegreen" => "#98fb98",
2878
+ "paleturquoise" => "#afeeee",
2879
+ "palevioletred" => "#db7093",
2880
+ "papayawhip" => "#ffefd5",
2881
+ "peachpuff" => "#ffdab9",
2882
+ "peru" => "#cd853f",
2883
+ "pink" => "#ffc0cb",
2884
+ "plum" => "#dda0dd",
2885
+ "powderblue" => "#b0e0e6",
2886
+ "purple" => "#800080",
2887
+ "red" => "#f00",
2888
+ "rosybrown" => "#bc8f8f",
2889
+ "royalblue" => "#4169e1",
2890
+ "saddlebrown" => "#8b4513",
2891
+ "salmon" => "#fa8072",
2892
+ "sandybrown" => "#f4a460",
2893
+ "seagreen" => "#2e8b57",
2894
+ "seashell" => "#fff5ee",
2895
+ "sienna" => "#a0522d",
2896
+ "silver" => "#c0c0c0",
2897
+ "skyblue" => "#87ceeb",
2898
+ "slateblue" => "#6a5acd",
2899
+ "slategray" => "#708090",
2900
+ "snow" => "#fffafa",
2901
+ "springgreen" => "#00ff7f",
2902
+ "steelblue" => "#4682b4",
2903
+ "tan" => "#d2b48c",
2904
+ "teal" => "#008080",
2905
+ "thistle" => "#d8bfd8",
2906
+ "tomato" => "#ff6347",
2907
+ "turquoise" => "#40e0d0",
2908
+ "violet" => "#ee82ee",
2909
+ "wheat" => "#f5deb3",
2910
+ "white" => "#fff",
2911
+ "whitesmoke" => "#f5f5f5",
2912
+ "yellow" => "#ff0",
2913
+ "yellowgreen" => "#9acd32"
2914
+ );
2915
+ /**
2916
+ * Overwrites {@link aCssMinifierPlugin::__construct()}.
2917
+ *
2918
+ * The constructor will create the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}
2919
+ * based on the {@link CssConvertNamedColorsMinifierPlugin::$transformation transformation table}.
2920
+ *
2921
+ * @param CssMinifier $minifier The CssMinifier object of this plugin.
2922
+ * @param array $configuration Plugin configuration [optional]
2923
+ * @return void
2924
+ */
2925
+ public function __construct(CssMinifier $minifier, array $configuration = array())
2926
+ {
2927
+ $this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)) . ")(\s|$)+/eiS";
2928
+ parent::__construct($minifier, $configuration);
2929
+ }
2930
+ /**
2931
+ * Implements {@link aCssMinifierPlugin::minify()}.
2932
+ *
2933
+ * @param aCssToken $token Token to process
2934
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
2935
+ */
2936
+ public function apply(aCssToken &$token)
2937
+ {
2938
+ $lcValue = strtolower($token->Value);
2939
+ // Declaration value equals a value in the transformation table => simple replace
2940
+ if (isset($this->transformation[$lcValue]))
2941
+ {
2942
+ $token->Value = $this->transformation[$lcValue];
2943
+ }
2944
+ // Declaration value contains a value in the transformation table => regular expression replace
2945
+ elseif (preg_match($this->reMatch, $token->Value))
2946
+ {
2947
+ $token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value);
2948
+ }
2949
+ return false;
2950
+ }
2951
+ /**
2952
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
2953
+ *
2954
+ * @return array
2955
+ */
2956
+ public function getTriggerTokens()
2957
+ {
2958
+ return array
2959
+ (
2960
+ "CssAtFontFaceDeclarationToken",
2961
+ "CssAtPageDeclarationToken",
2962
+ "CssRulesetDeclarationToken"
2963
+ );
2964
+ }
2965
+ }
2966
+
2967
+ /**
2968
+ * This {@link aCssMinifierFilter minifier filter} triggers on CSS Level 3 properties and will add declaration tokens
2969
+ * with browser-specific properties.
2970
+ *
2971
+ * @package CssMin/Minifier/Filters
2972
+ * @link http://code.google.com/p/cssmin/
2973
+ * @author Joe Scylla <joe.scylla@gmail.com>
2974
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
2975
+ * @license http://opensource.org/licenses/mit-license.php MIT License
2976
+ * @version 3.0.1
2977
+ */
2978
+ class CssConvertLevel3PropertiesMinifierFilter extends aCssMinifierFilter
2979
+ {
2980
+ /**
2981
+ * Css property transformations table. Used to convert CSS3 and proprietary properties to the browser-specific
2982
+ * counterparts.
2983
+ *
2984
+ * @var array
2985
+ */
2986
+ private $transformations = array
2987
+ (
2988
+ // Property Array(Mozilla, Webkit, Opera, Internet Explorer); NULL values are placeholders and will get ignored
2989
+ "animation" => array(null, "-webkit-animation", null, null),
2990
+ "animation-delay" => array(null, "-webkit-animation-delay", null, null),
2991
+ "animation-direction" => array(null, "-webkit-animation-direction", null, null),
2992
+ "animation-duration" => array(null, "-webkit-animation-duration", null, null),
2993
+ "animation-fill-mode" => array(null, "-webkit-animation-fill-mode", null, null),
2994
+ "animation-iteration-count" => array(null, "-webkit-animation-iteration-count", null, null),
2995
+ "animation-name" => array(null, "-webkit-animation-name", null, null),
2996
+ "animation-play-state" => array(null, "-webkit-animation-play-state", null, null),
2997
+ "animation-timing-function" => array(null, "-webkit-animation-timing-function", null, null),
2998
+ "appearance" => array("-moz-appearance", "-webkit-appearance", null, null),
2999
+ "backface-visibility" => array(null, "-webkit-backface-visibility", null, null),
3000
+ "background-clip" => array(null, "-webkit-background-clip", null, null),
3001
+ "background-composite" => array(null, "-webkit-background-composite", null, null),
3002
+ "background-inline-policy" => array("-moz-background-inline-policy", null, null, null),
3003
+ "background-origin" => array(null, "-webkit-background-origin", null, null),
3004
+ "background-position-x" => array(null, null, null, "-ms-background-position-x"),
3005
+ "background-position-y" => array(null, null, null, "-ms-background-position-y"),
3006
+ "background-size" => array(null, "-webkit-background-size", null, null),
3007
+ "behavior" => array(null, null, null, "-ms-behavior"),
3008
+ "binding" => array("-moz-binding", null, null, null),
3009
+ "border-after" => array(null, "-webkit-border-after", null, null),
3010
+ "border-after-color" => array(null, "-webkit-border-after-color", null, null),
3011
+ "border-after-style" => array(null, "-webkit-border-after-style", null, null),
3012
+ "border-after-width" => array(null, "-webkit-border-after-width", null, null),
3013
+ "border-before" => array(null, "-webkit-border-before", null, null),
3014
+ "border-before-color" => array(null, "-webkit-border-before-color", null, null),
3015
+ "border-before-style" => array(null, "-webkit-border-before-style", null, null),
3016
+ "border-before-width" => array(null, "-webkit-border-before-width", null, null),
3017
+ "border-border-bottom-colors" => array("-moz-border-bottom-colors", null, null, null),
3018
+ "border-bottom-left-radius" => array("-moz-border-radius-bottomleft", "-webkit-border-bottom-left-radius", null, null),
3019
+ "border-bottom-right-radius" => array("-moz-border-radius-bottomright", "-webkit-border-bottom-right-radius", null, null),
3020
+ "border-end" => array("-moz-border-end", "-webkit-border-end", null, null),
3021
+ "border-end-color" => array("-moz-border-end-color", "-webkit-border-end-color", null, null),
3022
+ "border-end-style" => array("-moz-border-end-style", "-webkit-border-end-style", null, null),
3023
+ "border-end-width" => array("-moz-border-end-width", "-webkit-border-end-width", null, null),
3024
+ "border-fit" => array(null, "-webkit-border-fit", null, null),
3025
+ "border-horizontal-spacing" => array(null, "-webkit-border-horizontal-spacing", null, null),
3026
+ "border-image" => array("-moz-border-image", "-webkit-border-image", null, null),
3027
+ "border-left-colors" => array("-moz-border-left-colors", null, null, null),
3028
+ "border-radius" => array("-moz-border-radius", "-webkit-border-radius", null, null),
3029
+ "border-border-right-colors" => array("-moz-border-right-colors", null, null, null),
3030
+ "border-start" => array("-moz-border-start", "-webkit-border-start", null, null),
3031
+ "border-start-color" => array("-moz-border-start-color", "-webkit-border-start-color", null, null),
3032
+ "border-start-style" => array("-moz-border-start-style", "-webkit-border-start-style", null, null),
3033
+ "border-start-width" => array("-moz-border-start-width", "-webkit-border-start-width", null, null),
3034
+ "border-top-colors" => array("-moz-border-top-colors", null, null, null),
3035
+ "border-top-left-radius" => array("-moz-border-radius-topleft", "-webkit-border-top-left-radius", null, null),
3036
+ "border-top-right-radius" => array("-moz-border-radius-topright", "-webkit-border-top-right-radius", null, null),
3037
+ "border-vertical-spacing" => array(null, "-webkit-border-vertical-spacing", null, null),
3038
+ "box-align" => array("-moz-box-align", "-webkit-box-align", null, null),
3039
+ "box-direction" => array("-moz-box-direction", "-webkit-box-direction", null, null),
3040
+ "box-flex" => array("-moz-box-flex", "-webkit-box-flex", null, null),
3041
+ "box-flex-group" => array(null, "-webkit-box-flex-group", null, null),
3042
+ "box-flex-lines" => array(null, "-webkit-box-flex-lines", null, null),
3043
+ "box-ordinal-group" => array("-moz-box-ordinal-group", "-webkit-box-ordinal-group", null, null),
3044
+ "box-orient" => array("-moz-box-orient", "-webkit-box-orient", null, null),
3045
+ "box-pack" => array("-moz-box-pack", "-webkit-box-pack", null, null),
3046
+ "box-reflect" => array(null, "-webkit-box-reflect", null, null),
3047
+ "box-shadow" => array("-moz-box-shadow", "-webkit-box-shadow", null, null),
3048
+ "box-sizing" => array("-moz-box-sizing", null, null, null),
3049
+ "color-correction" => array(null, "-webkit-color-correction", null, null),
3050
+ "column-break-after" => array(null, "-webkit-column-break-after", null, null),
3051
+ "column-break-before" => array(null, "-webkit-column-break-before", null, null),
3052
+ "column-break-inside" => array(null, "-webkit-column-break-inside", null, null),
3053
+ "column-count" => array("-moz-column-count", "-webkit-column-count", null, null),
3054
+ "column-gap" => array("-moz-column-gap", "-webkit-column-gap", null, null),
3055
+ "column-rule" => array("-moz-column-rule", "-webkit-column-rule", null, null),
3056
+ "column-rule-color" => array("-moz-column-rule-color", "-webkit-column-rule-color", null, null),
3057
+ "column-rule-style" => array("-moz-column-rule-style", "-webkit-column-rule-style", null, null),
3058
+ "column-rule-width" => array("-moz-column-rule-width", "-webkit-column-rule-width", null, null),
3059
+ "column-span" => array(null, "-webkit-column-span", null, null),
3060
+ "column-width" => array("-moz-column-width", "-webkit-column-width", null, null),
3061
+ "columns" => array(null, "-webkit-columns", null, null),
3062
+ "filter" => array(__CLASS__, "filter"),
3063
+ "float-edge" => array("-moz-float-edge", null, null, null),
3064
+ "font-feature-settings" => array("-moz-font-feature-settings", null, null, null),
3065
+ "font-language-override" => array("-moz-font-language-override", null, null, null),
3066
+ "font-size-delta" => array(null, "-webkit-font-size-delta", null, null),
3067
+ "font-smoothing" => array(null, "-webkit-font-smoothing", null, null),
3068
+ "force-broken-image-icon" => array("-moz-force-broken-image-icon", null, null, null),
3069
+ "highlight" => array(null, "-webkit-highlight", null, null),
3070
+ "hyphenate-character" => array(null, "-webkit-hyphenate-character", null, null),
3071
+ "hyphenate-locale" => array(null, "-webkit-hyphenate-locale", null, null),
3072
+ "hyphens" => array(null, "-webkit-hyphens", null, null),
3073
+ "force-broken-image-icon" => array("-moz-image-region", null, null, null),
3074
+ "ime-mode" => array(null, null, null, "-ms-ime-mode"),
3075
+ "interpolation-mode" => array(null, null, null, "-ms-interpolation-mode"),
3076
+ "layout-flow" => array(null, null, null, "-ms-layout-flow"),
3077
+ "layout-grid" => array(null, null, null, "-ms-layout-grid"),
3078
+ "layout-grid-char" => array(null, null, null, "-ms-layout-grid-char"),
3079
+ "layout-grid-line" => array(null, null, null, "-ms-layout-grid-line"),
3080
+ "layout-grid-mode" => array(null, null, null, "-ms-layout-grid-mode"),
3081
+ "layout-grid-type" => array(null, null, null, "-ms-layout-grid-type"),
3082
+ "line-break" => array(null, "-webkit-line-break", null, "-ms-line-break"),
3083
+ "line-clamp" => array(null, "-webkit-line-clamp", null, null),
3084
+ "line-grid-mode" => array(null, null, null, "-ms-line-grid-mode"),
3085
+ "logical-height" => array(null, "-webkit-logical-height", null, null),
3086
+ "logical-width" => array(null, "-webkit-logical-width", null, null),
3087
+ "margin-after" => array(null, "-webkit-margin-after", null, null),
3088
+ "margin-after-collapse" => array(null, "-webkit-margin-after-collapse", null, null),
3089
+ "margin-before" => array(null, "-webkit-margin-before", null, null),
3090
+ "margin-before-collapse" => array(null, "-webkit-margin-before-collapse", null, null),
3091
+ "margin-bottom-collapse" => array(null, "-webkit-margin-bottom-collapse", null, null),
3092
+ "margin-collapse" => array(null, "-webkit-margin-collapse", null, null),
3093
+ "margin-end" => array("-moz-margin-end", "-webkit-margin-end", null, null),
3094
+ "margin-start" => array("-moz-margin-start", "-webkit-margin-start", null, null),
3095
+ "margin-top-collapse" => array(null, "-webkit-margin-top-collapse", null, null),
3096
+ "marquee " => array(null, "-webkit-marquee", null, null),
3097
+ "marquee-direction" => array(null, "-webkit-marquee-direction", null, null),
3098
+ "marquee-increment" => array(null, "-webkit-marquee-increment", null, null),
3099
+ "marquee-repetition" => array(null, "-webkit-marquee-repetition", null, null),
3100
+ "marquee-speed" => array(null, "-webkit-marquee-speed", null, null),
3101
+ "marquee-style" => array(null, "-webkit-marquee-style", null, null),
3102
+ "mask" => array(null, "-webkit-mask", null, null),
3103
+ "mask-attachment" => array(null, "-webkit-mask-attachment", null, null),
3104
+ "mask-box-image" => array(null, "-webkit-mask-box-image", null, null),
3105
+ "mask-clip" => array(null, "-webkit-mask-clip", null, null),
3106
+ "mask-composite" => array(null, "-webkit-mask-composite", null, null),
3107
+ "mask-image" => array(null, "-webkit-mask-image", null, null),
3108
+ "mask-origin" => array(null, "-webkit-mask-origin", null, null),
3109
+ "mask-position" => array(null, "-webkit-mask-position", null, null),
3110
+ "mask-position-x" => array(null, "-webkit-mask-position-x", null, null),
3111
+ "mask-position-y" => array(null, "-webkit-mask-position-y", null, null),
3112
+ "mask-repeat" => array(null, "-webkit-mask-repeat", null, null),
3113
+ "mask-repeat-x" => array(null, "-webkit-mask-repeat-x", null, null),
3114
+ "mask-repeat-y" => array(null, "-webkit-mask-repeat-y", null, null),
3115
+ "mask-size" => array(null, "-webkit-mask-size", null, null),
3116
+ "match-nearest-mail-blockquote-color" => array(null, "-webkit-match-nearest-mail-blockquote-color", null, null),
3117
+ "max-logical-height" => array(null, "-webkit-max-logical-height", null, null),
3118
+ "max-logical-width" => array(null, "-webkit-max-logical-width", null, null),
3119
+ "min-logical-height" => array(null, "-webkit-min-logical-height", null, null),
3120
+ "min-logical-width" => array(null, "-webkit-min-logical-width", null, null),
3121
+ "object-fit" => array(null, null, "-o-object-fit", null),
3122
+ "object-position" => array(null, null, "-o-object-position", null),
3123
+ "opacity" => array(__CLASS__, "opacity"),
3124
+ "outline-radius" => array("-moz-outline-radius", null, null, null),
3125
+ "outline-bottom-left-radius" => array("-moz-outline-radius-bottomleft", null, null, null),
3126
+ "outline-bottom-right-radius" => array("-moz-outline-radius-bottomright", null, null, null),
3127
+ "outline-top-left-radius" => array("-moz-outline-radius-topleft", null, null, null),
3128
+ "outline-top-right-radius" => array("-moz-outline-radius-topright", null, null, null),
3129
+ "padding-after" => array(null, "-webkit-padding-after", null, null),
3130
+ "padding-before" => array(null, "-webkit-padding-before", null, null),
3131
+ "padding-end" => array("-moz-padding-end", "-webkit-padding-end", null, null),
3132
+ "padding-start" => array("-moz-padding-start", "-webkit-padding-start", null, null),
3133
+ "perspective" => array(null, "-webkit-perspective", null, null),
3134
+ "perspective-origin" => array(null, "-webkit-perspective-origin", null, null),
3135
+ "perspective-origin-x" => array(null, "-webkit-perspective-origin-x", null, null),
3136
+ "perspective-origin-y" => array(null, "-webkit-perspective-origin-y", null, null),
3137
+ "rtl-ordering" => array(null, "-webkit-rtl-ordering", null, null),
3138
+ "scrollbar-3dlight-color" => array(null, null, null, "-ms-scrollbar-3dlight-color"),
3139
+ "scrollbar-arrow-color" => array(null, null, null, "-ms-scrollbar-arrow-color"),
3140
+ "scrollbar-base-color" => array(null, null, null, "-ms-scrollbar-base-color"),
3141
+ "scrollbar-darkshadow-color" => array(null, null, null, "-ms-scrollbar-darkshadow-color"),
3142
+ "scrollbar-face-color" => array(null, null, null, "-ms-scrollbar-face-color"),
3143
+ "scrollbar-highlight-color" => array(null, null, null, "-ms-scrollbar-highlight-color"),
3144
+ "scrollbar-shadow-color" => array(null, null, null, "-ms-scrollbar-shadow-color"),
3145
+ "scrollbar-track-color" => array(null, null, null, "-ms-scrollbar-track-color"),
3146
+ "stack-sizing" => array("-moz-stack-sizing", null, null, null),
3147
+ "svg-shadow" => array(null, "-webkit-svg-shadow", null, null),
3148
+ "tab-size" => array("-moz-tab-size", null, "-o-tab-size", null),
3149
+ "table-baseline" => array(null, null, "-o-table-baseline", null),
3150
+ "text-align-last" => array(null, null, null, "-ms-text-align-last"),
3151
+ "text-autospace" => array(null, null, null, "-ms-text-autospace"),
3152
+ "text-combine" => array(null, "-webkit-text-combine", null, null),
3153
+ "text-decorations-in-effect" => array(null, "-webkit-text-decorations-in-effect", null, null),
3154
+ "text-emphasis" => array(null, "-webkit-text-emphasis", null, null),
3155
+ "text-emphasis-color" => array(null, "-webkit-text-emphasis-color", null, null),
3156
+ "text-emphasis-position" => array(null, "-webkit-text-emphasis-position", null, null),
3157
+ "text-emphasis-style" => array(null, "-webkit-text-emphasis-style", null, null),
3158
+ "text-fill-color" => array(null, "-webkit-text-fill-color", null, null),
3159
+ "text-justify" => array(null, null, null, "-ms-text-justify"),
3160
+ "text-kashida-space" => array(null, null, null, "-ms-text-kashida-space"),
3161
+ "text-overflow" => array(null, null, "-o-text-overflow", "-ms-text-overflow"),
3162
+ "text-security" => array(null, "-webkit-text-security", null, null),
3163
+ "text-size-adjust" => array(null, "-webkit-text-size-adjust", null, "-ms-text-size-adjust"),
3164
+ "text-stroke" => array(null, "-webkit-text-stroke", null, null),
3165
+ "text-stroke-color" => array(null, "-webkit-text-stroke-color", null, null),
3166
+ "text-stroke-width" => array(null, "-webkit-text-stroke-width", null, null),
3167
+ "text-underline-position" => array(null, null, null, "-ms-text-underline-position"),
3168
+ "transform" => array("-moz-transform", "-webkit-transform", "-o-transform", null),
3169
+ "transform-origin" => array("-moz-transform-origin", "-webkit-transform-origin", "-o-transform-origin", null),
3170
+ "transform-origin-x" => array(null, "-webkit-transform-origin-x", null, null),
3171
+ "transform-origin-y" => array(null, "-webkit-transform-origin-y", null, null),
3172
+ "transform-origin-z" => array(null, "-webkit-transform-origin-z", null, null),
3173
+ "transform-style" => array(null, "-webkit-transform-style", null, null),
3174
+ "transition" => array("-moz-transition", "-webkit-transition", "-o-transition", null),
3175
+ "transition-delay" => array("-moz-transition-delay", "-webkit-transition-delay", "-o-transition-delay", null),
3176
+ "transition-duration" => array("-moz-transition-duration", "-webkit-transition-duration", "-o-transition-duration", null),
3177
+ "transition-property" => array("-moz-transition-property", "-webkit-transition-property", "-o-transition-property", null),
3178
+ "transition-timing-function" => array("-moz-transition-timing-function", "-webkit-transition-timing-function", "-o-transition-timing-function", null),
3179
+ "user-drag" => array(null, "-webkit-user-drag", null, null),
3180
+ "user-focus" => array("-moz-user-focus", null, null, null),
3181
+ "user-input" => array("-moz-user-input", null, null, null),
3182
+ "user-modify" => array("-moz-user-modify", "-webkit-user-modify", null, null),
3183
+ "user-select" => array("-moz-user-select", "-webkit-user-select", null, null),
3184
+ "white-space" => array(__CLASS__, "whiteSpace"),
3185
+ "window-shadow" => array("-moz-window-shadow", null, null, null),
3186
+ "word-break" => array(null, null, null, "-ms-word-break"),
3187
+ "word-wrap" => array(null, null, null, "-ms-word-wrap"),
3188
+ "writing-mode" => array(null, "-webkit-writing-mode", null, "-ms-writing-mode"),
3189
+ "zoom" => array(null, null, null, "-ms-zoom")
3190
+ );
3191
+ /**
3192
+ * Implements {@link aCssMinifierFilter::filter()}.
3193
+ *
3194
+ * @param array $tokens Array of objects of type aCssToken
3195
+ * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array
3196
+ */
3197
+ public function apply(array &$tokens)
3198
+ {
3199
+ $r = 0;
3200
+ $transformations = &$this->transformations;
3201
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
3202
+ {
3203
+ if (get_class($tokens[$i]) === "CssRulesetDeclarationToken")
3204
+ {
3205
+ $tProperty = $tokens[$i]->Property;
3206
+ if (isset($transformations[$tProperty]))
3207
+ {
3208
+ $result = array();
3209
+ if (is_callable($transformations[$tProperty]))
3210
+ {
3211
+ $result = call_user_func_array($transformations[$tProperty], array($tokens[$i]));
3212
+ if (!is_array($result) && is_object($result))
3213
+ {
3214
+ $result = array($result);
3215
+ }
3216
+ }
3217
+ else
3218
+ {
3219
+ $tValue = $tokens[$i]->Value;
3220
+ $tMediaTypes = $tokens[$i]->MediaTypes;
3221
+ foreach ($transformations[$tProperty] as $property)
3222
+ {
3223
+ if ($property !== null)
3224
+ {
3225
+ $result[] = new CssRulesetDeclarationToken($property, $tValue, $tMediaTypes);
3226
+ }
3227
+ }
3228
+ }
3229
+ if (count($result) > 0)
3230
+ {
3231
+ array_splice($tokens, $i + 1, 0, $result);
3232
+ $i += count($result);
3233
+ $l += count($result);
3234
+ }
3235
+ }
3236
+ }
3237
+ }
3238
+ return $r;
3239
+ }
3240
+ /**
3241
+ * Transforms the Internet Explorer specific declaration property "filter" to Internet Explorer 8+ compatible
3242
+ * declaratiopn property "-ms-filter".
3243
+ *
3244
+ * @param aCssToken $token
3245
+ * @return array
3246
+ */
3247
+ private static function filter($token)
3248
+ {
3249
+ $r = array
3250
+ (
3251
+ new CssRulesetDeclarationToken("-ms-filter", "\"" . $token->Value . "\"", $token->MediaTypes),
3252
+ );
3253
+ return $r;
3254
+ }
3255
+ /**
3256
+ * Transforms "opacity: {value}" into browser specific counterparts.
3257
+ *
3258
+ * @param aCssToken $token
3259
+ * @return array
3260
+ */
3261
+ private static function opacity($token)
3262
+ {
3263
+ // Calculate the value for Internet Explorer filter statement
3264
+ $ieValue = (int) ((float) $token->Value * 100);
3265
+ $r = array
3266
+ (
3267
+ // Internet Explorer >= 8
3268
+ new CssRulesetDeclarationToken("-ms-filter", "\"alpha(opacity=" . $ieValue . ")\"", $token->MediaTypes),
3269
+ // Internet Explorer >= 4 <= 7
3270
+ new CssRulesetDeclarationToken("filter", "alpha(opacity=" . $ieValue . ")", $token->MediaTypes),
3271
+ new CssRulesetDeclarationToken("zoom", "1", $token->MediaTypes)
3272
+ );
3273
+ return $r;
3274
+ }
3275
+ /**
3276
+ * Transforms "white-space: pre-wrap" into browser specific counterparts.
3277
+ *
3278
+ * @param aCssToken $token
3279
+ * @return array
3280
+ */
3281
+ private static function whiteSpace($token)
3282
+ {
3283
+ if (strtolower($token->Value) === "pre-wrap")
3284
+ {
3285
+ $r = array
3286
+ (
3287
+ // Firefox < 3
3288
+ new CssRulesetDeclarationToken("white-space", "-moz-pre-wrap", $token->MediaTypes),
3289
+ // Webkit
3290
+ new CssRulesetDeclarationToken("white-space", "-webkit-pre-wrap", $token->MediaTypes),
3291
+ // Opera >= 4 <= 6
3292
+ new CssRulesetDeclarationToken("white-space", "-pre-wrap", $token->MediaTypes),
3293
+ // Opera >= 7
3294
+ new CssRulesetDeclarationToken("white-space", "-o-pre-wrap", $token->MediaTypes),
3295
+ // Internet Explorer >= 5.5
3296
+ new CssRulesetDeclarationToken("word-wrap", "break-word", $token->MediaTypes)
3297
+ );
3298
+ return $r;
3299
+ }
3300
+ else
3301
+ {
3302
+ return array();
3303
+ }
3304
+ }
3305
+ }
3306
+
3307
+ /**
3308
+ * This {@link aCssMinifierFilter minifier filter} will convert @keyframes at-rule block to browser specific counterparts.
3309
+ *
3310
+ * @package CssMin/Minifier/Filters
3311
+ * @link http://code.google.com/p/cssmin/
3312
+ * @author Joe Scylla <joe.scylla@gmail.com>
3313
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3314
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3315
+ * @version 3.0.1
3316
+ */
3317
+ class CssConvertLevel3AtKeyframesMinifierFilter extends aCssMinifierFilter
3318
+ {
3319
+ /**
3320
+ * Implements {@link aCssMinifierFilter::filter()}.
3321
+ *
3322
+ * @param array $tokens Array of objects of type aCssToken
3323
+ * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array
3324
+ */
3325
+ public function apply(array &$tokens)
3326
+ {
3327
+ $r = 0;
3328
+ $transformations = array("-moz-keyframes", "-webkit-keyframes");
3329
+ for ($i = 0, $l = count($tokens); $i < $l; $i++)
3330
+ {
3331
+ if (get_class($tokens[$i]) === "CssAtKeyframesStartToken")
3332
+ {
3333
+ for ($ii = $i; $ii < $l; $ii++)
3334
+ {
3335
+ if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken")
3336
+ {
3337
+ break;
3338
+ }
3339
+ }
3340
+ if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken")
3341
+ {
3342
+ $add = array();
3343
+ $source = array();
3344
+ for ($iii = $i; $iii <= $ii; $iii++)
3345
+ {
3346
+ $source[] = clone($tokens[$iii]);
3347
+ }
3348
+ foreach ($transformations as $transformation)
3349
+ {
3350
+ $t = array();
3351
+ foreach ($source as $token)
3352
+ {
3353
+ $t[] = clone($token);
3354
+ }
3355
+ $t[0]->AtRuleName = $transformation;
3356
+ $add = array_merge($add, $t);
3357
+ }
3358
+ if (isset($this->configuration["RemoveSource"]) && $this->configuration["RemoveSource"] === true)
3359
+ {
3360
+ array_splice($tokens, $i, $ii - $i + 1, $add);
3361
+ }
3362
+ else
3363
+ {
3364
+ array_splice($tokens, $ii + 1, 0, $add);
3365
+ }
3366
+ $l = count($tokens);
3367
+ $i = $ii + count($add);
3368
+ $r += count($add);
3369
+ }
3370
+ }
3371
+ }
3372
+ return $r;
3373
+ }
3374
+ }
3375
+
3376
+ /**
3377
+ * This {@link aCssMinifierPlugin} will convert a color value in hsl notation to hexadecimal notation.
3378
+ *
3379
+ * Example:
3380
+ * <code>
3381
+ * color: hsl(232,36%,48%);
3382
+ * </code>
3383
+ *
3384
+ * Will get converted to:
3385
+ * <code>
3386
+ * color:#4e5aa7;
3387
+ * </code>
3388
+ *
3389
+ * @package CssMin/Minifier/Plugins
3390
+ * @link http://code.google.com/p/cssmin/
3391
+ * @author Joe Scylla <joe.scylla@gmail.com>
3392
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3393
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3394
+ * @version 3.0.1
3395
+ */
3396
+ class CssConvertHslColorsMinifierPlugin extends aCssMinifierPlugin
3397
+ {
3398
+ /**
3399
+ * Regular expression matching the value.
3400
+ *
3401
+ * @var string
3402
+ */
3403
+ private $reMatch = "/^hsl\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*%\s*,\s*([0-9]+)\s*%\s*\)/iS";
3404
+ /**
3405
+ * Implements {@link aCssMinifierPlugin::minify()}.
3406
+ *
3407
+ * @param aCssToken $token Token to process
3408
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3409
+ */
3410
+ public function apply(aCssToken &$token)
3411
+ {
3412
+ if (stripos($token->Value, "hsl") !== false && preg_match($this->reMatch, $token->Value, $m))
3413
+ {
3414
+ $token->Value = str_replace($m[0], $this->hsl2hex($m[1], $m[2], $m[3]), $token->Value);
3415
+ }
3416
+ return false;
3417
+ }
3418
+ /**
3419
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
3420
+ *
3421
+ * @return array
3422
+ */
3423
+ public function getTriggerTokens()
3424
+ {
3425
+ return array
3426
+ (
3427
+ "CssAtFontFaceDeclarationToken",
3428
+ "CssAtPageDeclarationToken",
3429
+ "CssRulesetDeclarationToken"
3430
+ );
3431
+ }
3432
+ /**
3433
+ * Convert a HSL value to hexadecimal notation.
3434
+ *
3435
+ * Based on: {@link http://www.easyrgb.com/index.php?X=MATH&H=19#text19}.
3436
+ *
3437
+ * @param integer $hue Hue
3438
+ * @param integer $saturation Saturation
3439
+ * @param integer $lightness Lightnesss
3440
+ * @return string
3441
+ */
3442
+ private function hsl2hex($hue, $saturation, $lightness)
3443
+ {
3444
+ $hue = $hue / 360;
3445
+ $saturation = $saturation / 100;
3446
+ $lightness = $lightness / 100;
3447
+ if ($saturation == 0)
3448
+ {
3449
+ $red = $lightness * 255;
3450
+ $green = $lightness * 255;
3451
+ $blue = $lightness * 255;
3452
+ }
3453
+ else
3454
+ {
3455
+ if ($lightness < 0.5 )
3456
+ {
3457
+ $v2 = $lightness * (1 + $saturation);
3458
+ }
3459
+ else
3460
+ {
3461
+ $v2 = ($lightness + $saturation) - ($saturation * $lightness);
3462
+ }
3463
+ $v1 = 2 * $lightness - $v2;
3464
+ $red = 255 * self::hue2rgb($v1, $v2, $hue + (1 / 3));
3465
+ $green = 255 * self::hue2rgb($v1, $v2, $hue);
3466
+ $blue = 255 * self::hue2rgb($v1, $v2, $hue - (1 / 3));
3467
+ }
3468
+ return "#" . str_pad(dechex(round($red)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($green)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($blue)), 2, "0", STR_PAD_LEFT);
3469
+ }
3470
+ /**
3471
+ * Apply hue to a rgb color value.
3472
+ *
3473
+ * @param integer $v1 Value 1
3474
+ * @param integer $v2 Value 2
3475
+ * @param integer $hue Hue
3476
+ * @return integer
3477
+ */
3478
+ private function hue2rgb($v1, $v2, $hue)
3479
+ {
3480
+ if ($hue < 0)
3481
+ {
3482
+ $hue += 1;
3483
+ }
3484
+ if ($hue > 1)
3485
+ {
3486
+ $hue -= 1;
3487
+ }
3488
+ if ((6 * $hue) < 1)
3489
+ {
3490
+ return ($v1 + ($v2 - $v1) * 6 * $hue);
3491
+ }
3492
+ if ((2 * $hue) < 1)
3493
+ {
3494
+ return ($v2);
3495
+ }
3496
+ if ((3 * $hue) < 2)
3497
+ {
3498
+ return ($v1 + ($v2 - $v1) * (( 2 / 3) - $hue) * 6);
3499
+ }
3500
+ return $v1;
3501
+ }
3502
+ }
3503
+
3504
+ /**
3505
+ * This {@link aCssMinifierPlugin} will convert the font-weight values normal and bold to their numeric notation.
3506
+ *
3507
+ * Example:
3508
+ * <code>
3509
+ * font-weight: normal;
3510
+ * font: bold 11px monospace;
3511
+ * </code>
3512
+ *
3513
+ * Will get converted to:
3514
+ * <code>
3515
+ * font-weight:400;
3516
+ * font:700 11px monospace;
3517
+ * </code>
3518
+ *
3519
+ * @package CssMin/Minifier/Pluginsn
3520
+ * @link http://code.google.com/p/cssmin/
3521
+ * @author Joe Scylla <joe.scylla@gmail.com>
3522
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3523
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3524
+ * @version 3.0.1
3525
+ */
3526
+ class CssConvertFontWeightMinifierPlugin extends aCssMinifierPlugin
3527
+ {
3528
+ /**
3529
+ * Array of included declaration properties this plugin will process; others declaration properties will get
3530
+ * ignored.
3531
+ *
3532
+ * @var array
3533
+ */
3534
+ private $include = array
3535
+ (
3536
+ "font",
3537
+ "font-weight"
3538
+ );
3539
+ /**
3540
+ * Regular expression matching the value.
3541
+ *
3542
+ * @var string
3543
+ */
3544
+ private $reMatch = null;
3545
+ /**
3546
+ * Regular expression replace the value.
3547
+ *
3548
+ * @var string
3549
+ */
3550
+ private $reReplace = "\"\${1}\" . \$this->transformation[\"\${2}\"] . \"\${3}\"";
3551
+ /**
3552
+ * Transformation table used by the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}.
3553
+ *
3554
+ * @var array
3555
+ */
3556
+ private $transformation = array
3557
+ (
3558
+ "normal" => "400",
3559
+ "bold" => "700"
3560
+ );
3561
+ /**
3562
+ * Overwrites {@link aCssMinifierPlugin::__construct()}.
3563
+ *
3564
+ * The constructor will create the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}
3565
+ * based on the {@link CssConvertFontWeightMinifierPlugin::$transformation transformation table}.
3566
+ *
3567
+ * @param CssMinifier $minifier The CssMinifier object of this plugin.
3568
+ * @return void
3569
+ */
3570
+ public function __construct(CssMinifier $minifier)
3571
+ {
3572
+ $this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)). ")(\s|$)+/eiS";
3573
+ parent::__construct($minifier);
3574
+ }
3575
+ /**
3576
+ * Implements {@link aCssMinifierPlugin::minify()}.
3577
+ *
3578
+ * @param aCssToken $token Token to process
3579
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3580
+ */
3581
+ public function apply(aCssToken &$token)
3582
+ {
3583
+ if (in_array($token->Property, $this->include) && preg_match($this->reMatch, $token->Value, $m))
3584
+ {
3585
+ $token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value);
3586
+ }
3587
+ return false;
3588
+ }
3589
+ /**
3590
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
3591
+ *
3592
+ * @return array
3593
+ */
3594
+ public function getTriggerTokens()
3595
+ {
3596
+ return array
3597
+ (
3598
+ "CssAtFontFaceDeclarationToken",
3599
+ "CssAtPageDeclarationToken",
3600
+ "CssRulesetDeclarationToken"
3601
+ );
3602
+ }
3603
+ }
3604
+
3605
+ /**
3606
+ * This {@link aCssMinifierPlugin} will compress several unit values to their short notations. Examples:
3607
+ *
3608
+ * <code>
3609
+ * padding: 0.5em;
3610
+ * border: 0px;
3611
+ * margin: 0 0 0 0;
3612
+ * </code>
3613
+ *
3614
+ * Will get compressed to:
3615
+ *
3616
+ * <code>
3617
+ * padding:.5px;
3618
+ * border:0;
3619
+ * margin:0;
3620
+ * </code>
3621
+ *
3622
+ * --
3623
+ *
3624
+ * @package CssMin/Minifier/Plugins
3625
+ * @link http://code.google.com/p/cssmin/
3626
+ * @author Joe Scylla <joe.scylla@gmail.com>
3627
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3628
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3629
+ * @version 3.0.1
3630
+ */
3631
+ class CssCompressUnitValuesMinifierPlugin extends aCssMinifierPlugin
3632
+ {
3633
+ /**
3634
+ * Regular expression used for matching and replacing unit values.
3635
+ *
3636
+ * @var array
3637
+ */
3638
+ private $re = array
3639
+ (
3640
+ "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}.\${2}\${4}",
3641
+ "/(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}0",
3642
+ "/(^0\s0\s0\s0)|(^0\s0\s0$)|(^0\s0$)/iS" => "0"
3643
+ );
3644
+ /**
3645
+ * Regular expression matching the value.
3646
+ *
3647
+ * @var string
3648
+ */
3649
+ private $reMatch = "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)|(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)|(^0\s0\s0\s0$)|(^0\s0\s0$)|(^0\s0$)/iS";
3650
+ /**
3651
+ * Implements {@link aCssMinifierPlugin::minify()}.
3652
+ *
3653
+ * @param aCssToken $token Token to process
3654
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3655
+ */
3656
+ public function apply(aCssToken &$token)
3657
+ {
3658
+ if (preg_match($this->reMatch, $token->Value))
3659
+ {
3660
+ foreach ($this->re as $reMatch => $reReplace)
3661
+ {
3662
+ $token->Value = preg_replace($reMatch, $reReplace, $token->Value);
3663
+ }
3664
+ }
3665
+ return false;
3666
+ }
3667
+ /**
3668
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
3669
+ *
3670
+ * @return array
3671
+ */
3672
+ public function getTriggerTokens()
3673
+ {
3674
+ return array
3675
+ (
3676
+ "CssAtFontFaceDeclarationToken",
3677
+ "CssAtPageDeclarationToken",
3678
+ "CssRulesetDeclarationToken"
3679
+ );
3680
+ }
3681
+ }
3682
+
3683
+ /**
3684
+ * This {@link aCssMinifierPlugin} compress the content of expresssion() declaration values.
3685
+ *
3686
+ * For compression of expressions {@link https://github.com/rgrove/jsmin-php/ JSMin} will get used. JSMin have to be
3687
+ * already included or loadable via {@link http://goo.gl/JrW54 PHP autoloading}.
3688
+ *
3689
+ * @package CssMin/Minifier/Plugins
3690
+ * @link http://code.google.com/p/cssmin/
3691
+ * @author Joe Scylla <joe.scylla@gmail.com>
3692
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3693
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3694
+ * @version 3.0.1
3695
+ */
3696
+ class CssCompressExpressionValuesMinifierPlugin extends aCssMinifierPlugin
3697
+ {
3698
+ /**
3699
+ * Implements {@link aCssMinifierPlugin::minify()}.
3700
+ *
3701
+ * @param aCssToken $token Token to process
3702
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3703
+ */
3704
+ public function apply(aCssToken &$token)
3705
+ {
3706
+ if (class_exists("JSMin") && stripos($token->Value, "expression(") !== false)
3707
+ {
3708
+ $value = $token->Value;
3709
+ $value = substr($token->Value, stripos($token->Value, "expression(") + 10);
3710
+ $value = trim(JSMin::minify($value));
3711
+ $token->Value = "expression(" . $value . ")";
3712
+ }
3713
+ return false;
3714
+ }
3715
+ /**
3716
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
3717
+ *
3718
+ * @return array
3719
+ */
3720
+ public function getTriggerTokens()
3721
+ {
3722
+ return array
3723
+ (
3724
+ "CssAtFontFaceDeclarationToken",
3725
+ "CssAtPageDeclarationToken",
3726
+ "CssRulesetDeclarationToken"
3727
+ );
3728
+ }
3729
+ }
3730
+
3731
+ /**
3732
+ * This {@link aCssMinifierPlugin} will convert hexadecimal color value with 6 chars to their 3 char hexadecimal
3733
+ * notation (if possible).
3734
+ *
3735
+ * Example:
3736
+ * <code>
3737
+ * color: #aabbcc;
3738
+ * </code>
3739
+ *
3740
+ * Will get converted to:
3741
+ * <code>
3742
+ * color:#abc;
3743
+ * </code>
3744
+ *
3745
+ * @package CssMin/Minifier/Plugins
3746
+ * @link http://code.google.com/p/cssmin/
3747
+ * @author Joe Scylla <joe.scylla@gmail.com>
3748
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3749
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3750
+ * @version 3.0.1
3751
+ */
3752
+ class CssCompressColorValuesMinifierPlugin extends aCssMinifierPlugin
3753
+ {
3754
+ /**
3755
+ * Regular expression matching 6 char hexadecimal color values.
3756
+ *
3757
+ * @var string
3758
+ */
3759
+ private $reMatch = "/\#([0-9a-f]{6})/iS";
3760
+ /**
3761
+ * Implements {@link aCssMinifierPlugin::minify()}.
3762
+ *
3763
+ * @param aCssToken $token Token to process
3764
+ * @return boolean Return TRUE to break the processing of this token; FALSE to continue
3765
+ */
3766
+ public function apply(aCssToken &$token)
3767
+ {
3768
+ if (strpos($token->Value, "#") !== false && preg_match($this->reMatch, $token->Value, $m))
3769
+ {
3770
+ $value = strtolower($m[1]);
3771
+ if ($value[0] == $value[1] && $value[2] == $value[3] && $value[4] == $value[5])
3772
+ {
3773
+ $token->Value = str_replace($m[0], "#" . $value[0] . $value[2] . $value[4], $token->Value);
3774
+ }
3775
+ }
3776
+ return false;
3777
+ }
3778
+ /**
3779
+ * Implements {@link aMinifierPlugin::getTriggerTokens()}
3780
+ *
3781
+ * @return array
3782
+ */
3783
+ public function getTriggerTokens()
3784
+ {
3785
+ return array
3786
+ (
3787
+ "CssAtFontFaceDeclarationToken",
3788
+ "CssAtPageDeclarationToken",
3789
+ "CssRulesetDeclarationToken"
3790
+ );
3791
+ }
3792
+ }
3793
+
3794
+ /**
3795
+ * This {@link aCssToken CSS token} represents a CSS comment.
3796
+ *
3797
+ * @package CssMin/Tokens
3798
+ * @link http://code.google.com/p/cssmin/
3799
+ * @author Joe Scylla <joe.scylla@gmail.com>
3800
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3801
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3802
+ * @version 3.0.1
3803
+ */
3804
+ class CssCommentToken extends aCssToken
3805
+ {
3806
+ /**
3807
+ * Comment as Text.
3808
+ *
3809
+ * @var string
3810
+ */
3811
+ public $Comment = "";
3812
+ /**
3813
+ * Set the properties of a comment token.
3814
+ *
3815
+ * @param string $comment Comment including comment delimiters
3816
+ * @return void
3817
+ */
3818
+ public function __construct($comment)
3819
+ {
3820
+ $this->Comment = $comment;
3821
+ }
3822
+ /**
3823
+ * Implements {@link aCssToken::__toString()}.
3824
+ *
3825
+ * @return string
3826
+ */
3827
+ public function __toString()
3828
+ {
3829
+ return $this->Comment;
3830
+ }
3831
+ }
3832
+
3833
+ /**
3834
+ * {@link aCssParserPlugin Parser plugin} for parsing comments.
3835
+ *
3836
+ * Adds a {@link CssCommentToken} to the parser if a comment was found.
3837
+ *
3838
+ * @package CssMin/Parser/Plugins
3839
+ * @link http://code.google.com/p/cssmin/
3840
+ * @author Joe Scylla <joe.scylla@gmail.com>
3841
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3842
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3843
+ * @version 3.0.1
3844
+ */
3845
+ class CssCommentParserPlugin extends aCssParserPlugin
3846
+ {
3847
+ /**
3848
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
3849
+ *
3850
+ * @return array
3851
+ */
3852
+ public function getTriggerChars()
3853
+ {
3854
+ return array("*", "/");
3855
+ }
3856
+ /**
3857
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
3858
+ *
3859
+ * @return array
3860
+ */
3861
+ public function getTriggerStates()
3862
+ {
3863
+ return false;
3864
+ }
3865
+ /**
3866
+ * Stored buffer for restore.
3867
+ *
3868
+ * @var string
3869
+ */
3870
+ private $restoreBuffer = "";
3871
+ /**
3872
+ * Implements {@link aCssParserPlugin::parse()}.
3873
+ *
3874
+ * @param integer $index Current index
3875
+ * @param string $char Current char
3876
+ * @param string $previousChar Previous char
3877
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
3878
+ */
3879
+ public function parse($index, $char, $previousChar, $state)
3880
+ {
3881
+ if ($char === "*" && $previousChar === "/" && $state !== "T_COMMENT")
3882
+ {
3883
+ $this->parser->pushState("T_COMMENT");
3884
+ $this->parser->setExclusive(__CLASS__);
3885
+ $this->restoreBuffer = substr($this->parser->getAndClearBuffer(), 0, -2);
3886
+ }
3887
+ elseif ($char === "/" && $previousChar === "*" && $state === "T_COMMENT")
3888
+ {
3889
+ $this->parser->popState();
3890
+ $this->parser->unsetExclusive();
3891
+ $this->parser->appendToken(new CssCommentToken("/*" . $this->parser->getAndClearBuffer()));
3892
+ $this->parser->setBuffer($this->restoreBuffer);
3893
+ }
3894
+ else
3895
+ {
3896
+ return false;
3897
+ }
3898
+ return true;
3899
+ }
3900
+ }
3901
+
3902
+ /**
3903
+ * This {@link aCssToken CSS token} represents the start of a @variables at-rule block.
3904
+ *
3905
+ * @package CssMin/Tokens
3906
+ * @link http://code.google.com/p/cssmin/
3907
+ * @author Joe Scylla <joe.scylla@gmail.com>
3908
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3909
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3910
+ * @version 3.0.1
3911
+ */
3912
+ class CssAtVariablesStartToken extends aCssAtBlockStartToken
3913
+ {
3914
+ /**
3915
+ * Media types of the @variables at-rule block.
3916
+ *
3917
+ * @var array
3918
+ */
3919
+ public $MediaTypes = array();
3920
+ /**
3921
+ * Set the properties of a @variables at-rule token.
3922
+ *
3923
+ * @param array $mediaTypes Media types
3924
+ * @return void
3925
+ */
3926
+ public function __construct($mediaTypes = null)
3927
+ {
3928
+ $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all");
3929
+ }
3930
+ /**
3931
+ * Implements {@link aCssToken::__toString()}.
3932
+ *
3933
+ * @return string
3934
+ */
3935
+ public function __toString()
3936
+ {
3937
+ return "";
3938
+ }
3939
+ }
3940
+
3941
+ /**
3942
+ * {@link aCssParserPlugin Parser plugin} for parsing @variables at-rule block with including declarations.
3943
+ *
3944
+ * Found @variables at-rule blocks will add a {@link CssAtVariablesStartToken} and {@link CssAtVariablesEndToken} to the
3945
+ * parser; including declarations as {@link CssAtVariablesDeclarationToken}.
3946
+ *
3947
+ * @package CssMin/Parser/Plugins
3948
+ * @link http://code.google.com/p/cssmin/
3949
+ * @author Joe Scylla <joe.scylla@gmail.com>
3950
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
3951
+ * @license http://opensource.org/licenses/mit-license.php MIT License
3952
+ * @version 3.0.1
3953
+ */
3954
+ class CssAtVariablesParserPlugin extends aCssParserPlugin
3955
+ {
3956
+ /**
3957
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
3958
+ *
3959
+ * @return array
3960
+ */
3961
+ public function getTriggerChars()
3962
+ {
3963
+ return array("@", "{", "}", ":", ";");
3964
+ }
3965
+ /**
3966
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
3967
+ *
3968
+ * @return array
3969
+ */
3970
+ public function getTriggerStates()
3971
+ {
3972
+ return array("T_DOCUMENT", "T_AT_VARIABLES::PREPARE", "T_AT_VARIABLES", "T_AT_VARIABLES_DECLARATION");
3973
+ }
3974
+ /**
3975
+ * Implements {@link aCssParserPlugin::parse()}.
3976
+ *
3977
+ * @param integer $index Current index
3978
+ * @param string $char Current char
3979
+ * @param string $previousChar Previous char
3980
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
3981
+ */
3982
+ public function parse($index, $char, $previousChar, $state)
3983
+ {
3984
+ // Start of @variables at-rule block
3985
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@variables")
3986
+ {
3987
+ $this->parser->pushState("T_AT_VARIABLES::PREPARE");
3988
+ $this->parser->clearBuffer();
3989
+ return $index + 10;
3990
+ }
3991
+ // Start of @variables declarations
3992
+ elseif ($char === "{" && $state === "T_AT_VARIABLES::PREPARE")
3993
+ {
3994
+ $this->parser->setState("T_AT_VARIABLES");
3995
+ $mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{"))));
3996
+ $this->parser->appendToken(new CssAtVariablesStartToken($mediaTypes));
3997
+ }
3998
+ // Start of @variables declaration
3999
+ if ($char === ":" && $state === "T_AT_VARIABLES")
4000
+ {
4001
+ $this->buffer = $this->parser->getAndClearBuffer(":");
4002
+ $this->parser->pushState("T_AT_VARIABLES_DECLARATION");
4003
+ }
4004
+ // Unterminated @variables declaration
4005
+ elseif ($char === ":" && $state === "T_AT_VARIABLES_DECLARATION")
4006
+ {
4007
+ // Ignore Internet Explorer filter declarations
4008
+ if ($this->buffer === "filter")
4009
+ {
4010
+ return false;
4011
+ }
4012
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @variables declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4013
+ }
4014
+ // End of @variables declaration
4015
+ elseif (($char === ";" || $char === "}") && $state === "T_AT_VARIABLES_DECLARATION")
4016
+ {
4017
+ $value = $this->parser->getAndClearBuffer(";}");
4018
+ if (strtolower(substr($value, -10, 10)) === "!important")
4019
+ {
4020
+ $value = trim(substr($value, 0, -10));
4021
+ $isImportant = true;
4022
+ }
4023
+ else
4024
+ {
4025
+ $isImportant = false;
4026
+ }
4027
+ $this->parser->popState();
4028
+ $this->parser->appendToken(new CssAtVariablesDeclarationToken($this->buffer, $value, $isImportant));
4029
+ $this->buffer = "";
4030
+ }
4031
+ // End of @variables at-rule block
4032
+ elseif ($char === "}" && $state === "T_AT_VARIABLES")
4033
+ {
4034
+ $this->parser->popState();
4035
+ $this->parser->clearBuffer();
4036
+ $this->parser->appendToken(new CssAtVariablesEndToken());
4037
+ }
4038
+ else
4039
+ {
4040
+ return false;
4041
+ }
4042
+ return true;
4043
+ }
4044
+ }
4045
+
4046
+ /**
4047
+ * This {@link aCssToken CSS token} represents the end of a @variables at-rule block.
4048
+ *
4049
+ * @package CssMin/Tokens
4050
+ * @link http://code.google.com/p/cssmin/
4051
+ * @author Joe Scylla <joe.scylla@gmail.com>
4052
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4053
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4054
+ * @version 3.0.1
4055
+ */
4056
+ class CssAtVariablesEndToken extends aCssAtBlockEndToken
4057
+ {
4058
+ /**
4059
+ * Implements {@link aCssToken::__toString()}.
4060
+ *
4061
+ * @return string
4062
+ */
4063
+ public function __toString()
4064
+ {
4065
+ return "";
4066
+ }
4067
+ }
4068
+
4069
+ /**
4070
+ * This {@link aCssToken CSS token} represents a declaration of a @variables at-rule block.
4071
+ *
4072
+ * @package CssMin/Tokens
4073
+ * @link http://code.google.com/p/cssmin/
4074
+ * @author Joe Scylla <joe.scylla@gmail.com>
4075
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4076
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4077
+ * @version 3.0.1
4078
+ */
4079
+ class CssAtVariablesDeclarationToken extends aCssDeclarationToken
4080
+ {
4081
+ /**
4082
+ * Implements {@link aCssToken::__toString()}.
4083
+ *
4084
+ * @return string
4085
+ */
4086
+ public function __toString()
4087
+ {
4088
+ return "";
4089
+ }
4090
+ }
4091
+
4092
+ /**
4093
+ * This {@link aCssToken CSS token} represents the start of a @page at-rule block.
4094
+ *
4095
+ * @package CssMin/Tokens
4096
+ * @link http://code.google.com/p/cssmin/
4097
+ * @author Joe Scylla <joe.scylla@gmail.com>
4098
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4099
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4100
+ * @version 3.0.1
4101
+ */
4102
+ class CssAtPageStartToken extends aCssAtBlockStartToken
4103
+ {
4104
+ /**
4105
+ * Selector.
4106
+ *
4107
+ * @var string
4108
+ */
4109
+ public $Selector = "";
4110
+ /**
4111
+ * Sets the properties of the @page at-rule.
4112
+ *
4113
+ * @param string $selector Selector
4114
+ * @return void
4115
+ */
4116
+ public function __construct($selector = "")
4117
+ {
4118
+ $this->Selector = $selector;
4119
+ }
4120
+ /**
4121
+ * Implements {@link aCssToken::__toString()}.
4122
+ *
4123
+ * @return string
4124
+ */
4125
+ public function __toString()
4126
+ {
4127
+ return "@page" . ($this->Selector ? " " . $this->Selector : "") . "{";
4128
+ }
4129
+ }
4130
+
4131
+ /**
4132
+ * {@link aCssParserPlugin Parser plugin} for parsing @page at-rule block with including declarations.
4133
+ *
4134
+ * Found @page at-rule blocks will add a {@link CssAtPageStartToken} and {@link CssAtPageEndToken} to the
4135
+ * parser; including declarations as {@link CssAtPageDeclarationToken}.
4136
+ *
4137
+ * @package CssMin/Parser/Plugins
4138
+ * @link http://code.google.com/p/cssmin/
4139
+ * @author Joe Scylla <joe.scylla@gmail.com>
4140
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4141
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4142
+ * @version 3.0.1
4143
+ */
4144
+ class CssAtPageParserPlugin extends aCssParserPlugin
4145
+ {
4146
+ /**
4147
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
4148
+ *
4149
+ * @return array
4150
+ */
4151
+ public function getTriggerChars()
4152
+ {
4153
+ return array("@", "{", "}", ":", ";");
4154
+ }
4155
+ /**
4156
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
4157
+ *
4158
+ * @return array
4159
+ */
4160
+ public function getTriggerStates()
4161
+ {
4162
+ return array("T_DOCUMENT", "T_AT_PAGE::SELECTOR", "T_AT_PAGE", "T_AT_PAGE_DECLARATION");
4163
+ }
4164
+ /**
4165
+ * Implements {@link aCssParserPlugin::parse()}.
4166
+ *
4167
+ * @param integer $index Current index
4168
+ * @param string $char Current char
4169
+ * @param string $previousChar Previous char
4170
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4171
+ */
4172
+ public function parse($index, $char, $previousChar, $state)
4173
+ {
4174
+ // Start of @page at-rule block
4175
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 5)) === "@page")
4176
+ {
4177
+ $this->parser->pushState("T_AT_PAGE::SELECTOR");
4178
+ $this->parser->clearBuffer();
4179
+ return $index + 5;
4180
+ }
4181
+ // Start of @page declarations
4182
+ elseif ($char === "{" && $state === "T_AT_PAGE::SELECTOR")
4183
+ {
4184
+ $selector = $this->parser->getAndClearBuffer("{");
4185
+ $this->parser->setState("T_AT_PAGE");
4186
+ $this->parser->clearBuffer();
4187
+ $this->parser->appendToken(new CssAtPageStartToken($selector));
4188
+ }
4189
+ // Start of @page declaration
4190
+ elseif ($char === ":" && $state === "T_AT_PAGE")
4191
+ {
4192
+ $this->parser->pushState("T_AT_PAGE_DECLARATION");
4193
+ $this->buffer = $this->parser->getAndClearBuffer(":", true);
4194
+ }
4195
+ // Unterminated @font-face declaration
4196
+ elseif ($char === ":" && $state === "T_AT_PAGE_DECLARATION")
4197
+ {
4198
+ // Ignore Internet Explorer filter declarations
4199
+ if ($this->buffer === "filter")
4200
+ {
4201
+ return false;
4202
+ }
4203
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @page declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4204
+ }
4205
+ // End of @page declaration
4206
+ elseif (($char === ";" || $char === "}") && $state == "T_AT_PAGE_DECLARATION")
4207
+ {
4208
+ $value = $this->parser->getAndClearBuffer(";}");
4209
+ if (strtolower(substr($value, -10, 10)) == "!important")
4210
+ {
4211
+ $value = trim(substr($value, 0, -10));
4212
+ $isImportant = true;
4213
+ }
4214
+ else
4215
+ {
4216
+ $isImportant = false;
4217
+ }
4218
+ $this->parser->popState();
4219
+ $this->parser->appendToken(new CssAtPageDeclarationToken($this->buffer, $value, $isImportant));
4220
+ // --
4221
+ if ($char === "}")
4222
+ {
4223
+ $this->parser->popState();
4224
+ $this->parser->appendToken(new CssAtPageEndToken());
4225
+ }
4226
+ $this->buffer = "";
4227
+ }
4228
+ // End of @page at-rule block
4229
+ elseif ($char === "}" && $state === "T_AT_PAGE")
4230
+ {
4231
+ $this->parser->popState();
4232
+ $this->parser->clearBuffer();
4233
+ $this->parser->appendToken(new CssAtPageEndToken());
4234
+ }
4235
+ else
4236
+ {
4237
+ return false;
4238
+ }
4239
+ return true;
4240
+ }
4241
+ }
4242
+
4243
+ /**
4244
+ * This {@link aCssToken CSS token} represents the end of a @page at-rule block.
4245
+ *
4246
+ * @package CssMin/Tokens
4247
+ * @link http://code.google.com/p/cssmin/
4248
+ * @author Joe Scylla <joe.scylla@gmail.com>
4249
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4250
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4251
+ * @version 3.0.1
4252
+ */
4253
+ class CssAtPageEndToken extends aCssAtBlockEndToken
4254
+ {
4255
+
4256
+ }
4257
+
4258
+ /**
4259
+ * This {@link aCssToken CSS token} represents a declaration of a @page at-rule block.
4260
+ *
4261
+ * @package CssMin/Tokens
4262
+ * @link http://code.google.com/p/cssmin/
4263
+ * @author Joe Scylla <joe.scylla@gmail.com>
4264
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4265
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4266
+ * @version 3.0.1
4267
+ */
4268
+ class CssAtPageDeclarationToken extends aCssDeclarationToken
4269
+ {
4270
+
4271
+ }
4272
+
4273
+ /**
4274
+ * This {@link aCssToken CSS token} represents the start of a @media at-rule block.
4275
+ *
4276
+ * @package CssMin/Tokens
4277
+ * @link http://code.google.com/p/cssmin/
4278
+ * @author Joe Scylla <joe.scylla@gmail.com>
4279
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4280
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4281
+ * @version 3.0.1
4282
+ */
4283
+ class CssAtMediaStartToken extends aCssAtBlockStartToken
4284
+ {
4285
+ /**
4286
+ * Sets the properties of the @media at-rule.
4287
+ *
4288
+ * @param array $mediaTypes Media types
4289
+ * @return void
4290
+ */
4291
+ public function __construct(array $mediaTypes = array())
4292
+ {
4293
+ $this->MediaTypes = $mediaTypes;
4294
+ }
4295
+ /**
4296
+ * Implements {@link aCssToken::__toString()}.
4297
+ *
4298
+ * @return string
4299
+ */
4300
+ public function __toString()
4301
+ {
4302
+ return "@media " . implode(",", $this->MediaTypes) . "{";
4303
+ }
4304
+ }
4305
+
4306
+ /**
4307
+ * {@link aCssParserPlugin Parser plugin} for parsing @media at-rule block.
4308
+ *
4309
+ * Found @media at-rule blocks will add a {@link CssAtMediaStartToken} and {@link CssAtMediaEndToken} to the parser.
4310
+ * This plugin will also set the the current media types using {@link CssParser::setMediaTypes()} and
4311
+ * {@link CssParser::unsetMediaTypes()}.
4312
+ *
4313
+ * @package CssMin/Parser/Plugins
4314
+ * @link http://code.google.com/p/cssmin/
4315
+ * @author Joe Scylla <joe.scylla@gmail.com>
4316
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4317
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4318
+ * @version 3.0.1
4319
+ */
4320
+ class CssAtMediaParserPlugin extends aCssParserPlugin
4321
+ {
4322
+ /**
4323
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
4324
+ *
4325
+ * @return array
4326
+ */
4327
+ public function getTriggerChars()
4328
+ {
4329
+ return array("@", "{", "}");
4330
+ }
4331
+ /**
4332
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
4333
+ *
4334
+ * @return array
4335
+ */
4336
+ public function getTriggerStates()
4337
+ {
4338
+ return array("T_DOCUMENT", "T_AT_MEDIA::PREPARE", "T_AT_MEDIA");
4339
+ }
4340
+ /**
4341
+ * Implements {@link aCssParserPlugin::parse()}.
4342
+ *
4343
+ * @param integer $index Current index
4344
+ * @param string $char Current char
4345
+ * @param string $previousChar Previous char
4346
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4347
+ */
4348
+ public function parse($index, $char, $previousChar, $state)
4349
+ {
4350
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 6)) === "@media")
4351
+ {
4352
+ $this->parser->pushState("T_AT_MEDIA::PREPARE");
4353
+ $this->parser->clearBuffer();
4354
+ return $index + 6;
4355
+ }
4356
+ elseif ($char === "{" && $state === "T_AT_MEDIA::PREPARE")
4357
+ {
4358
+ $mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{"))));
4359
+ $this->parser->setMediaTypes($mediaTypes);
4360
+ $this->parser->setState("T_AT_MEDIA");
4361
+ $this->parser->appendToken(new CssAtMediaStartToken($mediaTypes));
4362
+ }
4363
+ elseif ($char === "}" && $state === "T_AT_MEDIA")
4364
+ {
4365
+ $this->parser->appendToken(new CssAtMediaEndToken());
4366
+ $this->parser->clearBuffer();
4367
+ $this->parser->unsetMediaTypes();
4368
+ $this->parser->popState();
4369
+ }
4370
+ else
4371
+ {
4372
+ return false;
4373
+ }
4374
+ return true;
4375
+ }
4376
+ }
4377
+
4378
+ /**
4379
+ * This {@link aCssToken CSS token} represents the end of a @media at-rule block.
4380
+ *
4381
+ * @package CssMin/Tokens
4382
+ * @link http://code.google.com/p/cssmin/
4383
+ * @author Joe Scylla <joe.scylla@gmail.com>
4384
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4385
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4386
+ * @version 3.0.1
4387
+ */
4388
+ class CssAtMediaEndToken extends aCssAtBlockEndToken
4389
+ {
4390
+
4391
+ }
4392
+
4393
+ /**
4394
+ * This {@link aCssToken CSS token} represents the start of a @keyframes at-rule block.
4395
+ *
4396
+ * @package CssMin/Tokens
4397
+ * @link http://code.google.com/p/cssmin/
4398
+ * @author Joe Scylla <joe.scylla@gmail.com>
4399
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4400
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4401
+ * @version 3.0.1
4402
+ */
4403
+ class CssAtKeyframesStartToken extends aCssAtBlockStartToken
4404
+ {
4405
+ /**
4406
+ * Name of the at-rule.
4407
+ *
4408
+ * @var string
4409
+ */
4410
+ public $AtRuleName = "keyframes";
4411
+ /**
4412
+ * Name
4413
+ *
4414
+ * @var string
4415
+ */
4416
+ public $Name = "";
4417
+ /**
4418
+ * Sets the properties of the @page at-rule.
4419
+ *
4420
+ * @param string $selector Selector
4421
+ * @return void
4422
+ */
4423
+ public function __construct($name, $atRuleName = null)
4424
+ {
4425
+ $this->Name = $name;
4426
+ if (!is_null($atRuleName))
4427
+ {
4428
+ $this->AtRuleName = $atRuleName;
4429
+ }
4430
+ }
4431
+ /**
4432
+ * Implements {@link aCssToken::__toString()}.
4433
+ *
4434
+ * @return string
4435
+ */
4436
+ public function __toString()
4437
+ {
4438
+ return "@" . $this->AtRuleName . " \"" . $this->Name . "\"{";
4439
+ }
4440
+ }
4441
+
4442
+ /**
4443
+ * This {@link aCssToken CSS token} represents the start of a ruleset of a @keyframes at-rule block.
4444
+ *
4445
+ * @package CssMin/Tokens
4446
+ * @link http://code.google.com/p/cssmin/
4447
+ * @author Joe Scylla <joe.scylla@gmail.com>
4448
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4449
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4450
+ * @version 3.0.1
4451
+ */
4452
+ class CssAtKeyframesRulesetStartToken extends aCssRulesetStartToken
4453
+ {
4454
+ /**
4455
+ * Array of selectors.
4456
+ *
4457
+ * @var array
4458
+ */
4459
+ public $Selectors = array();
4460
+ /**
4461
+ * Set the properties of a ruleset token.
4462
+ *
4463
+ * @param array $selectors Selectors of the ruleset
4464
+ * @return void
4465
+ */
4466
+ public function __construct(array $selectors = array())
4467
+ {
4468
+ $this->Selectors = $selectors;
4469
+ }
4470
+ /**
4471
+ * Implements {@link aCssToken::__toString()}.
4472
+ *
4473
+ * @return string
4474
+ */
4475
+ public function __toString()
4476
+ {
4477
+ return implode(",", $this->Selectors) . "{";
4478
+ }
4479
+ }
4480
+
4481
+ /**
4482
+ * This {@link aCssToken CSS token} represents the end of a ruleset of a @keyframes at-rule block.
4483
+ *
4484
+ * @package CssMin/Tokens
4485
+ * @link http://code.google.com/p/cssmin/
4486
+ * @author Joe Scylla <joe.scylla@gmail.com>
4487
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4488
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4489
+ * @version 3.0.1
4490
+ */
4491
+ class CssAtKeyframesRulesetEndToken extends aCssRulesetEndToken
4492
+ {
4493
+
4494
+ }
4495
+
4496
+ /**
4497
+ * This {@link aCssToken CSS token} represents a ruleset declaration of a @keyframes at-rule block.
4498
+ *
4499
+ * @package CssMin/Tokens
4500
+ * @link http://code.google.com/p/cssmin/
4501
+ * @author Joe Scylla <joe.scylla@gmail.com>
4502
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4503
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4504
+ * @version 3.0.1
4505
+ */
4506
+ class CssAtKeyframesRulesetDeclarationToken extends aCssDeclarationToken
4507
+ {
4508
+
4509
+ }
4510
+
4511
+ /**
4512
+ * {@link aCssParserPlugin Parser plugin} for parsing @keyframes at-rule blocks, rulesets and declarations.
4513
+ *
4514
+ * @package CssMin/Parser/Plugins
4515
+ * @link http://code.google.com/p/cssmin/
4516
+ * @author Joe Scylla <joe.scylla@gmail.com>
4517
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4518
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4519
+ * @version 3.0.1
4520
+ */
4521
+ class CssAtKeyframesParserPlugin extends aCssParserPlugin
4522
+ {
4523
+ /**
4524
+ * @var string Keyword
4525
+ */
4526
+ private $atRuleName = "";
4527
+ /**
4528
+ * Selectors.
4529
+ *
4530
+ * @var array
4531
+ */
4532
+ private $selectors = array();
4533
+ /**
4534
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
4535
+ *
4536
+ * @return array
4537
+ */
4538
+ public function getTriggerChars()
4539
+ {
4540
+ return array("@", "{", "}", ":", ",", ";");
4541
+ }
4542
+ /**
4543
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
4544
+ *
4545
+ * @return array
4546
+ */
4547
+ public function getTriggerStates()
4548
+ {
4549
+ return array("T_DOCUMENT", "T_AT_KEYFRAMES::NAME", "T_AT_KEYFRAMES", "T_AT_KEYFRAMES_RULESETS", "T_AT_KEYFRAMES_RULESET", "T_AT_KEYFRAMES_RULESET_DECLARATION");
4550
+ }
4551
+ /**
4552
+ * Implements {@link aCssParserPlugin::parse()}.
4553
+ *
4554
+ * @param integer $index Current index
4555
+ * @param string $char Current char
4556
+ * @param string $previousChar Previous char
4557
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4558
+ */
4559
+ public function parse($index, $char, $previousChar, $state)
4560
+ {
4561
+ // Start of @keyframes at-rule block
4562
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@keyframes")
4563
+ {
4564
+ $this->atRuleName = "keyframes";
4565
+ $this->parser->pushState("T_AT_KEYFRAMES::NAME");
4566
+ $this->parser->clearBuffer();
4567
+ return $index + 10;
4568
+ }
4569
+ // Start of @keyframes at-rule block (@-moz-keyframes)
4570
+ elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 15)) === "@-moz-keyframes")
4571
+ {
4572
+ $this->atRuleName = "-moz-keyframes";
4573
+ $this->parser->pushState("T_AT_KEYFRAMES::NAME");
4574
+ $this->parser->clearBuffer();
4575
+ return $index + 15;
4576
+ }
4577
+ // Start of @keyframes at-rule block (@-webkit-keyframes)
4578
+ elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 18)) === "@-webkit-keyframes")
4579
+ {
4580
+ $this->atRuleName = "-webkit-keyframes";
4581
+ $this->parser->pushState("T_AT_KEYFRAMES::NAME");
4582
+ $this->parser->clearBuffer();
4583
+ return $index + 18;
4584
+ }
4585
+ // Start of @keyframes rulesets
4586
+ elseif ($char === "{" && $state === "T_AT_KEYFRAMES::NAME")
4587
+ {
4588
+ $name = $this->parser->getAndClearBuffer("{\"'");
4589
+ $this->parser->setState("T_AT_KEYFRAMES_RULESETS");
4590
+ $this->parser->clearBuffer();
4591
+ $this->parser->appendToken(new CssAtKeyframesStartToken($name, $this->atRuleName));
4592
+ }
4593
+ // Start of @keyframe ruleset and selectors
4594
+ if ($char === "," && $state === "T_AT_KEYFRAMES_RULESETS")
4595
+ {
4596
+ $this->selectors[] = $this->parser->getAndClearBuffer(",{");
4597
+ }
4598
+ // Start of a @keyframes ruleset
4599
+ elseif ($char === "{" && $state === "T_AT_KEYFRAMES_RULESETS")
4600
+ {
4601
+ if ($this->parser->getBuffer() !== "")
4602
+ {
4603
+ $this->selectors[] = $this->parser->getAndClearBuffer(",{");
4604
+ $this->parser->pushState("T_AT_KEYFRAMES_RULESET");
4605
+ $this->parser->appendToken(new CssAtKeyframesRulesetStartToken($this->selectors));
4606
+ $this->selectors = array();
4607
+ }
4608
+ }
4609
+ // Start of @keyframes ruleset declaration
4610
+ elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET")
4611
+ {
4612
+ $this->parser->pushState("T_AT_KEYFRAMES_RULESET_DECLARATION");
4613
+ $this->buffer = $this->parser->getAndClearBuffer(":;", true);
4614
+ }
4615
+ // Unterminated @keyframes ruleset declaration
4616
+ elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION")
4617
+ {
4618
+ // Ignore Internet Explorer filter declarations
4619
+ if ($this->buffer === "filter")
4620
+ {
4621
+ return false;
4622
+ }
4623
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @keyframes ruleset declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4624
+ }
4625
+ // End of declaration
4626
+ elseif (($char === ";" || $char === "}") && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION")
4627
+ {
4628
+ $value = $this->parser->getAndClearBuffer(";}");
4629
+ if (strtolower(substr($value, -10, 10)) === "!important")
4630
+ {
4631
+ $value = trim(substr($value, 0, -10));
4632
+ $isImportant = true;
4633
+ }
4634
+ else
4635
+ {
4636
+ $isImportant = false;
4637
+ }
4638
+ $this->parser->popState();
4639
+ $this->parser->appendToken(new CssAtKeyframesRulesetDeclarationToken($this->buffer, $value, $isImportant));
4640
+ // Declaration ends with a right curly brace; so we have to end the ruleset
4641
+ if ($char === "}")
4642
+ {
4643
+ $this->parser->appendToken(new CssAtKeyframesRulesetEndToken());
4644
+ $this->parser->popState();
4645
+ }
4646
+ $this->buffer = "";
4647
+ }
4648
+ // End of @keyframes ruleset
4649
+ elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESET")
4650
+ {
4651
+ $this->parser->clearBuffer();
4652
+
4653
+ $this->parser->popState();
4654
+ $this->parser->appendToken(new CssAtKeyframesRulesetEndToken());
4655
+ }
4656
+ // End of @keyframes rulesets
4657
+ elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESETS")
4658
+ {
4659
+ $this->parser->clearBuffer();
4660
+ $this->parser->popState();
4661
+ $this->parser->appendToken(new CssAtKeyframesEndToken());
4662
+ }
4663
+ else
4664
+ {
4665
+ return false;
4666
+ }
4667
+ return true;
4668
+ }
4669
+ }
4670
+
4671
+ /**
4672
+ * This {@link aCssToken CSS token} represents the end of a @keyframes at-rule block.
4673
+ *
4674
+ * @package CssMin/Tokens
4675
+ * @link http://code.google.com/p/cssmin/
4676
+ * @author Joe Scylla <joe.scylla@gmail.com>
4677
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4678
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4679
+ * @version 3.0.1
4680
+ */
4681
+ class CssAtKeyframesEndToken extends aCssAtBlockEndToken
4682
+ {
4683
+
4684
+ }
4685
+
4686
+ /**
4687
+ * This {@link aCssToken CSS token} represents a @import at-rule.
4688
+ *
4689
+ * @package CssMin/Tokens
4690
+ * @link http://code.google.com/p/cssmin/
4691
+ * @author Joe Scylla <joe.scylla@gmail.com>
4692
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4693
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4694
+ * @version 3.0.1.b1 (2001-02-22)
4695
+ */
4696
+ class CssAtImportToken extends aCssToken
4697
+ {
4698
+ /**
4699
+ * Import path of the @import at-rule.
4700
+ *
4701
+ * @var string
4702
+ */
4703
+ public $Import = "";
4704
+ /**
4705
+ * Media types of the @import at-rule.
4706
+ *
4707
+ * @var array
4708
+ */
4709
+ public $MediaTypes = array();
4710
+ /**
4711
+ * Set the properties of a @import at-rule token.
4712
+ *
4713
+ * @param string $import Import path
4714
+ * @param array $mediaTypes Media types
4715
+ * @return void
4716
+ */
4717
+ public function __construct($import, $mediaTypes)
4718
+ {
4719
+ $this->Import = $import;
4720
+ $this->MediaTypes = $mediaTypes ? $mediaTypes : array();
4721
+ }
4722
+ /**
4723
+ * Implements {@link aCssToken::__toString()}.
4724
+ *
4725
+ * @return string
4726
+ */
4727
+ public function __toString()
4728
+ {
4729
+ return "@import \"" . $this->Import . "\"" . (count($this->MediaTypes) > 0 ? " " . implode(",", $this->MediaTypes) : ""). ";";
4730
+ }
4731
+ }
4732
+
4733
+ /**
4734
+ * {@link aCssParserPlugin Parser plugin} for parsing @import at-rule.
4735
+ *
4736
+ * If a @import at-rule was found this plugin will add a {@link CssAtImportToken} to the parser.
4737
+ *
4738
+ * @package CssMin/Parser/Plugins
4739
+ * @link http://code.google.com/p/cssmin/
4740
+ * @author Joe Scylla <joe.scylla@gmail.com>
4741
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4742
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4743
+ * @version 3.0.1
4744
+ */
4745
+ class CssAtImportParserPlugin extends aCssParserPlugin
4746
+ {
4747
+ /**
4748
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
4749
+ *
4750
+ * @return array
4751
+ */
4752
+ public function getTriggerChars()
4753
+ {
4754
+ return array("@", ";", ",", "\n");
4755
+ }
4756
+ /**
4757
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
4758
+ *
4759
+ * @return array
4760
+ */
4761
+ public function getTriggerStates()
4762
+ {
4763
+ return array("T_DOCUMENT", "T_AT_IMPORT");
4764
+ }
4765
+ /**
4766
+ * Implements {@link aCssParserPlugin::parse()}.
4767
+ *
4768
+ * @param integer $index Current index
4769
+ * @param string $char Current char
4770
+ * @param string $previousChar Previous char
4771
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4772
+ */
4773
+ public function parse($index, $char, $previousChar, $state)
4774
+ {
4775
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 7)) === "@import")
4776
+ {
4777
+ $this->parser->pushState("T_AT_IMPORT");
4778
+ $this->parser->clearBuffer();
4779
+ return $index + 7;
4780
+ }
4781
+ elseif (($char === ";" || $char === "\n") && $state === "T_AT_IMPORT")
4782
+ {
4783
+ $this->buffer = $this->parser->getAndClearBuffer(";");
4784
+ $pos = false;
4785
+ foreach (array(")", "\"", "'") as $needle)
4786
+ {
4787
+ if (($pos = strrpos($this->buffer, $needle)) !== false)
4788
+ {
4789
+ break;
4790
+ }
4791
+ }
4792
+ $import = substr($this->buffer, 0, $pos + 1);
4793
+ if (stripos($import, "url(") === 0)
4794
+ {
4795
+ $import = substr($import, 4, -1);
4796
+ }
4797
+ $import = trim($import, " \t\n\r\0\x0B'\"");
4798
+ $mediaTypes = array_filter(array_map("trim", explode(",", trim(substr($this->buffer, $pos + 1), " \t\n\r\0\x0B{"))));
4799
+ if ($pos)
4800
+ {
4801
+ $this->parser->appendToken(new CssAtImportToken($import, $mediaTypes));
4802
+ }
4803
+ else
4804
+ {
4805
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Invalid @import at-rule syntax", $this->parser->buffer));
4806
+ }
4807
+ $this->parser->popState();
4808
+ }
4809
+ else
4810
+ {
4811
+ return false;
4812
+ }
4813
+ return true;
4814
+ }
4815
+ }
4816
+
4817
+ /**
4818
+ * This {@link aCssToken CSS token} represents the start of a @font-face at-rule block.
4819
+ *
4820
+ * @package CssMin/Tokens
4821
+ * @link http://code.google.com/p/cssmin/
4822
+ * @author Joe Scylla <joe.scylla@gmail.com>
4823
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4824
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4825
+ * @version 3.0.1
4826
+ */
4827
+ class CssAtFontFaceStartToken extends aCssAtBlockStartToken
4828
+ {
4829
+ /**
4830
+ * Implements {@link aCssToken::__toString()}.
4831
+ *
4832
+ * @return string
4833
+ */
4834
+ public function __toString()
4835
+ {
4836
+ return "@font-face{";
4837
+ }
4838
+ }
4839
+
4840
+ /**
4841
+ * {@link aCssParserPlugin Parser plugin} for parsing @font-face at-rule block with including declarations.
4842
+ *
4843
+ * Found @font-face at-rule blocks will add a {@link CssAtFontFaceStartToken} and {@link CssAtFontFaceEndToken} to the
4844
+ * parser; including declarations as {@link CssAtFontFaceDeclarationToken}.
4845
+ *
4846
+ * @package CssMin/Parser/Plugins
4847
+ * @link http://code.google.com/p/cssmin/
4848
+ * @author Joe Scylla <joe.scylla@gmail.com>
4849
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4850
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4851
+ * @version 3.0.1
4852
+ */
4853
+ class CssAtFontFaceParserPlugin extends aCssParserPlugin
4854
+ {
4855
+ /**
4856
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
4857
+ *
4858
+ * @return array
4859
+ */
4860
+ public function getTriggerChars()
4861
+ {
4862
+ return array("@", "{", "}", ":", ";");
4863
+ }
4864
+ /**
4865
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
4866
+ *
4867
+ * @return array
4868
+ */
4869
+ public function getTriggerStates()
4870
+ {
4871
+ return array("T_DOCUMENT", "T_AT_FONT_FACE::PREPARE", "T_AT_FONT_FACE", "T_AT_FONT_FACE_DECLARATION");
4872
+ }
4873
+ /**
4874
+ * Implements {@link aCssParserPlugin::parse()}.
4875
+ *
4876
+ * @param integer $index Current index
4877
+ * @param string $char Current char
4878
+ * @param string $previousChar Previous char
4879
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
4880
+ */
4881
+ public function parse($index, $char, $previousChar, $state)
4882
+ {
4883
+ // Start of @font-face at-rule block
4884
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@font-face")
4885
+ {
4886
+ $this->parser->pushState("T_AT_FONT_FACE::PREPARE");
4887
+ $this->parser->clearBuffer();
4888
+ return $index + 10;
4889
+ }
4890
+ // Start of @font-face declarations
4891
+ elseif ($char === "{" && $state === "T_AT_FONT_FACE::PREPARE")
4892
+ {
4893
+ $this->parser->setState("T_AT_FONT_FACE");
4894
+ $this->parser->clearBuffer();
4895
+ $this->parser->appendToken(new CssAtFontFaceStartToken());
4896
+ }
4897
+ // Start of @font-face declaration
4898
+ elseif ($char === ":" && $state === "T_AT_FONT_FACE")
4899
+ {
4900
+ $this->parser->pushState("T_AT_FONT_FACE_DECLARATION");
4901
+ $this->buffer = $this->parser->getAndClearBuffer(":", true);
4902
+ }
4903
+ // Unterminated @font-face declaration
4904
+ elseif ($char === ":" && $state === "T_AT_FONT_FACE_DECLARATION")
4905
+ {
4906
+ // Ignore Internet Explorer filter declarations
4907
+ if ($this->buffer === "filter")
4908
+ {
4909
+ return false;
4910
+ }
4911
+ CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @font-face declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_"));
4912
+ }
4913
+ // End of @font-face declaration
4914
+ elseif (($char === ";" || $char === "}") && $state === "T_AT_FONT_FACE_DECLARATION")
4915
+ {
4916
+ $value = $this->parser->getAndClearBuffer(";}");
4917
+ if (strtolower(substr($value, -10, 10)) === "!important")
4918
+ {
4919
+ $value = trim(substr($value, 0, -10));
4920
+ $isImportant = true;
4921
+ }
4922
+ else
4923
+ {
4924
+ $isImportant = false;
4925
+ }
4926
+ $this->parser->popState();
4927
+ $this->parser->appendToken(new CssAtFontFaceDeclarationToken($this->buffer, $value, $isImportant));
4928
+ $this->buffer = "";
4929
+ // --
4930
+ if ($char === "}")
4931
+ {
4932
+ $this->parser->appendToken(new CssAtFontFaceEndToken());
4933
+ $this->parser->popState();
4934
+ }
4935
+ }
4936
+ // End of @font-face at-rule block
4937
+ elseif ($char === "}" && $state === "T_AT_FONT_FACE")
4938
+ {
4939
+ $this->parser->appendToken(new CssAtFontFaceEndToken());
4940
+ $this->parser->clearBuffer();
4941
+ $this->parser->popState();
4942
+ }
4943
+ else
4944
+ {
4945
+ return false;
4946
+ }
4947
+ return true;
4948
+ }
4949
+ }
4950
+
4951
+ /**
4952
+ * This {@link aCssToken CSS token} represents the end of a @font-face at-rule block.
4953
+ *
4954
+ * @package CssMin/Tokens
4955
+ * @link http://code.google.com/p/cssmin/
4956
+ * @author Joe Scylla <joe.scylla@gmail.com>
4957
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4958
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4959
+ * @version 3.0.1
4960
+ */
4961
+ class CssAtFontFaceEndToken extends aCssAtBlockEndToken
4962
+ {
4963
+
4964
+ }
4965
+
4966
+ /**
4967
+ * This {@link aCssToken CSS token} represents a declaration of a @font-face at-rule block.
4968
+ *
4969
+ * @package CssMin/Tokens
4970
+ * @link http://code.google.com/p/cssmin/
4971
+ * @author Joe Scylla <joe.scylla@gmail.com>
4972
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4973
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4974
+ * @version 3.0.1
4975
+ */
4976
+ class CssAtFontFaceDeclarationToken extends aCssDeclarationToken
4977
+ {
4978
+
4979
+ }
4980
+
4981
+ /**
4982
+ * This {@link aCssToken CSS token} represents a @charset at-rule.
4983
+ *
4984
+ * @package CssMin/Tokens
4985
+ * @link http://code.google.com/p/cssmin/
4986
+ * @author Joe Scylla <joe.scylla@gmail.com>
4987
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
4988
+ * @license http://opensource.org/licenses/mit-license.php MIT License
4989
+ * @version 3.0.1
4990
+ */
4991
+ class CssAtCharsetToken extends aCssToken
4992
+ {
4993
+ /**
4994
+ * Charset of the @charset at-rule.
4995
+ *
4996
+ * @var string
4997
+ */
4998
+ public $Charset = "";
4999
+ /**
5000
+ * Set the properties of @charset at-rule token.
5001
+ *
5002
+ * @param string $charset Charset of the @charset at-rule token
5003
+ * @return void
5004
+ */
5005
+ public function __construct($charset)
5006
+ {
5007
+ $this->Charset = $charset;
5008
+ }
5009
+ /**
5010
+ * Implements {@link aCssToken::__toString()}.
5011
+ *
5012
+ * @return string
5013
+ */
5014
+ public function __toString()
5015
+ {
5016
+ return "@charset " . $this->Charset . ";";
5017
+ }
5018
+ }
5019
+
5020
+ /**
5021
+ * {@link aCssParserPlugin Parser plugin} for parsing @charset at-rule.
5022
+ *
5023
+ * If a @charset at-rule was found this plugin will add a {@link CssAtCharsetToken} to the parser.
5024
+ *
5025
+ * @package CssMin/Parser/Plugins
5026
+ * @link http://code.google.com/p/cssmin/
5027
+ * @author Joe Scylla <joe.scylla@gmail.com>
5028
+ * @copyright 2008 - 2011 Joe Scylla <joe.scylla@gmail.com>
5029
+ * @license http://opensource.org/licenses/mit-license.php MIT License
5030
+ * @version 3.0.1
5031
+ */
5032
+ class CssAtCharsetParserPlugin extends aCssParserPlugin
5033
+ {
5034
+ /**
5035
+ * Implements {@link aCssParserPlugin::getTriggerChars()}.
5036
+ *
5037
+ * @return array
5038
+ */
5039
+ public function getTriggerChars()
5040
+ {
5041
+ return array("@", ";", "\n");
5042
+ }
5043
+ /**
5044
+ * Implements {@link aCssParserPlugin::getTriggerStates()}.
5045
+ *
5046
+ * @return array
5047
+ */
5048
+ public function getTriggerStates()
5049
+ {
5050
+ return array("T_DOCUMENT", "T_AT_CHARSET");
5051
+ }
5052
+ /**
5053
+ * Implements {@link aCssParserPlugin::parse()}.
5054
+ *
5055
+ * @param integer $index Current index
5056
+ * @param string $char Current char
5057
+ * @param string $previousChar Previous char
5058
+ * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing
5059
+ */
5060
+ public function parse($index, $char, $previousChar, $state)
5061
+ {
5062
+ if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 8)) === "@charset")
5063
+ {
5064
+ $this->parser->pushState("T_AT_CHARSET");
5065
+ $this->parser->clearBuffer();
5066
+ return $index + 8;
5067
+ }
5068
+ elseif (($char === ";" || $char === "\n") && $state === "T_AT_CHARSET")
5069
+ {
5070
+ $charset = $this->parser->getAndClearBuffer(";");
5071
+ $this->parser->popState();
5072
+ $this->parser->appendToken(new CssAtCharsetToken($charset));
5073
+ }
5074
+ else
5075
+ {
5076
+ return false;
5077
+ }
5078
+ return true;
5079
+ }
5080
+ }
5081
+
5082
+ ?>
admin/less/lib/less.js ADDED
@@ -0,0 +1,7942 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Less - Leaner CSS v1.7.3
3
+ * http://lesscss.org
4
+ *
5
+ * Copyright (c) 2009-2014, Alexis Sellier <self@cloudhead.net>
6
+ * Licensed under the Apache v2 License.
7
+ *
8
+ */
9
+
10
+ /** * @license Apache v2
11
+ */
12
+
13
+
14
+
15
+ (function (window, undefined) {//
16
+ // Stub out `require` in the browser
17
+ //
18
+ function require(arg) {
19
+ return window.less[arg.split('/')[1]];
20
+ };
21
+
22
+
23
+ if (typeof(window.less) === 'undefined' || typeof(window.less.nodeType) !== 'undefined') { window.less = {}; }
24
+ less = window.less;
25
+ tree = window.less.tree = {};
26
+ less.mode = 'browser';
27
+
28
+ var less, tree;
29
+
30
+ // Node.js does not have a header file added which defines less
31
+ if (less === undefined) {
32
+ less = exports;
33
+ tree = require('./tree');
34
+ less.mode = 'node';
35
+ }
36
+ //
37
+ // less.js - parser
38
+ //
39
+ // A relatively straight-forward predictive parser.
40
+ // There is no tokenization/lexing stage, the input is parsed
41
+ // in one sweep.
42
+ //
43
+ // To make the parser fast enough to run in the browser, several
44
+ // optimization had to be made:
45
+ //
46
+ // - Matching and slicing on a huge input is often cause of slowdowns.
47
+ // The solution is to chunkify the input into smaller strings.
48
+ // The chunks are stored in the `chunks` var,
49
+ // `j` holds the current chunk index, and `currentPos` holds
50
+ // the index of the current chunk in relation to `input`.
51
+ // This gives us an almost 4x speed-up.
52
+ //
53
+ // - In many cases, we don't need to match individual tokens;
54
+ // for example, if a value doesn't hold any variables, operations
55
+ // or dynamic references, the parser can effectively 'skip' it,
56
+ // treating it as a literal.
57
+ // An example would be '1px solid #000' - which evaluates to itself,
58
+ // we don't need to know what the individual components are.
59
+ // The drawback, of course is that you don't get the benefits of
60
+ // syntax-checking on the CSS. This gives us a 50% speed-up in the parser,
61
+ // and a smaller speed-up in the code-gen.
62
+ //
63
+ //
64
+ // Token matching is done with the `$` function, which either takes
65
+ // a terminal string or regexp, or a non-terminal function to call.
66
+ // It also takes care of moving all the indices forwards.
67
+ //
68
+ //
69
+ less.Parser = function Parser(env) {
70
+ var input, // LeSS input string
71
+ i, // current index in `input`
72
+ j, // current chunk
73
+ saveStack = [], // holds state for backtracking
74
+ furthest, // furthest index the parser has gone to
75
+ chunks, // chunkified input
76
+ current, // current chunk
77
+ currentPos, // index of current chunk, in `input`
78
+ parser,
79
+ parsers,
80
+ rootFilename = env && env.filename;
81
+
82
+ // Top parser on an import tree must be sure there is one "env"
83
+ // which will then be passed around by reference.
84
+ if (!(env instanceof tree.parseEnv)) {
85
+ env = new tree.parseEnv(env);
86
+ }
87
+
88
+ var imports = this.imports = {
89
+ paths: env.paths || [], // Search paths, when importing
90
+ queue: [], // Files which haven't been imported yet
91
+ files: env.files, // Holds the imported parse trees
92
+ contents: env.contents, // Holds the imported file contents
93
+ contentsIgnoredChars: env.contentsIgnoredChars, // lines inserted, not in the original less
94
+ mime: env.mime, // MIME type of .less files
95
+ error: null, // Error in parsing/evaluating an import
96
+ push: function (path, currentFileInfo, importOptions, callback) {
97
+ var parserImports = this;
98
+ this.queue.push(path);
99
+
100
+ var fileParsedFunc = function (e, root, fullPath) {
101
+ parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue
102
+
103
+ var importedPreviously = fullPath === rootFilename;
104
+
105
+ parserImports.files[fullPath] = root; // Store the root
106
+
107
+ if (e && !parserImports.error) { parserImports.error = e; }
108
+
109
+ callback(e, root, importedPreviously, fullPath);
110
+ };
111
+
112
+ if (less.Parser.importer) {
113
+ less.Parser.importer(path, currentFileInfo, fileParsedFunc, env);
114
+ } else {
115
+ less.Parser.fileLoader(path, currentFileInfo, function(e, contents, fullPath, newFileInfo) {
116
+ if (e) {fileParsedFunc(e); return;}
117
+
118
+ var newEnv = new tree.parseEnv(env);
119
+
120
+ newEnv.currentFileInfo = newFileInfo;
121
+ newEnv.processImports = false;
122
+ newEnv.contents[fullPath] = contents;
123
+
124
+ if (currentFileInfo.reference || importOptions.reference) {
125
+ newFileInfo.reference = true;
126
+ }
127
+
128
+ if (importOptions.inline) {
129
+ fileParsedFunc(null, contents, fullPath);
130
+ } else {
131
+ new(less.Parser)(newEnv).parse(contents, function (e, root) {
132
+ fileParsedFunc(e, root, fullPath);
133
+ });
134
+ }
135
+ }, env);
136
+ }
137
+ }
138
+ };
139
+
140
+ function save() { currentPos = i; saveStack.push( { current: current, i: i, j: j }); }
141
+ function restore() { var state = saveStack.pop(); current = state.current; currentPos = i = state.i; j = state.j; }
142
+ function forget() { saveStack.pop(); }
143
+
144
+ function sync() {
145
+ if (i > currentPos) {
146
+ current = current.slice(i - currentPos);
147
+ currentPos = i;
148
+ }
149
+ }
150
+ function isWhitespace(str, pos) {
151
+ var code = str.charCodeAt(pos | 0);
152
+ return (code <= 32) && (code === 32 || code === 10 || code === 9);
153
+ }
154
+ //
155
+ // Parse from a token, regexp or string, and move forward if match
156
+ //
157
+ function $(tok) {
158
+ var tokType = typeof tok,
159
+ match, length;
160
+
161
+ // Either match a single character in the input,
162
+ // or match a regexp in the current chunk (`current`).
163
+ //
164
+ if (tokType === "string") {
165
+ if (input.charAt(i) !== tok) {
166
+ return null;
167
+ }
168
+ skipWhitespace(1);
169
+ return tok;
170
+ }
171
+
172
+ // regexp
173
+ sync ();
174
+ if (! (match = tok.exec(current))) {
175
+ return null;
176
+ }
177
+
178
+ length = match[0].length;
179
+
180
+ // The match is confirmed, add the match length to `i`,
181
+ // and consume any extra white-space characters (' ' || '\n')
182
+ // which come after that. The reason for this is that LeSS's
183
+ // grammar is mostly white-space insensitive.
184
+ //
185
+ skipWhitespace(length);
186
+
187
+ if(typeof(match) === 'string') {
188
+ return match;
189
+ } else {
190
+ return match.length === 1 ? match[0] : match;
191
+ }
192
+ }
193
+
194
+ // Specialization of $(tok)
195
+ function $re(tok) {
196
+ if (i > currentPos) {
197
+ current = current.slice(i - currentPos);
198
+ currentPos = i;
199
+ }
200
+ var m = tok.exec(current);
201
+ if (!m) {
202
+ return null;
203
+ }
204
+
205
+ skipWhitespace(m[0].length);
206
+ if(typeof m === "string") {
207
+ return m;
208
+ }
209
+
210
+ return m.length === 1 ? m[0] : m;
211
+ }
212
+
213
+ var _$re = $re;
214
+
215
+ // Specialization of $(tok)
216
+ function $char(tok) {
217
+ if (input.charAt(i) !== tok) {
218
+ return null;
219
+ }
220
+ skipWhitespace(1);
221
+ return tok;
222
+ }
223
+
224
+ function skipWhitespace(length) {
225
+ var oldi = i, oldj = j,
226
+ curr = i - currentPos,
227
+ endIndex = i + current.length - curr,
228
+ mem = (i += length),
229
+ inp = input,
230
+ c;
231
+
232
+ for (; i < endIndex; i++) {
233
+ c = inp.charCodeAt(i);
234
+ if (c > 32) {
235
+ break;
236
+ }
237
+
238
+ if ((c !== 32) && (c !== 10) && (c !== 9) && (c !== 13)) {
239
+ break;
240
+ }
241
+ }
242
+
243
+ current = current.slice(length + i - mem + curr);
244
+ currentPos = i;
245
+
246
+ if (!current.length && (j < chunks.length - 1)) {
247
+ current = chunks[++j];
248
+ skipWhitespace(0); // skip space at the beginning of a chunk
249
+ return true; // things changed
250
+ }
251
+
252
+ return oldi !== i || oldj !== j;
253
+ }
254
+
255
+ function expect(arg, msg) {
256
+ // some older browsers return typeof 'function' for RegExp
257
+ var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : $(arg);
258
+ if (result) {
259
+ return result;
260
+ }
261
+ error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'"
262
+ : "unexpected token"));
263
+ }
264
+
265
+ // Specialization of expect()
266
+ function expectChar(arg, msg) {
267
+ if (input.charAt(i) === arg) {
268
+ skipWhitespace(1);
269
+ return arg;
270
+ }
271
+ error(msg || "expected '" + arg + "' got '" + input.charAt(i) + "'");
272
+ }
273
+
274
+ function error(msg, type) {
275
+ var e = new Error(msg);
276
+ e.index = i;
277
+ e.type = type || 'Syntax';
278
+ throw e;
279
+ }
280
+
281
+ // Same as $(), but don't change the state of the parser,
282
+ // just return the match.
283
+ function peek(tok) {
284
+ if (typeof(tok) === 'string') {
285
+ return input.charAt(i) === tok;
286
+ } else {
287
+ return tok.test(current);
288
+ }
289
+ }
290
+
291
+ // Specialization of peek()
292
+ function peekChar(tok) {
293
+ return input.charAt(i) === tok;
294
+ }
295
+
296
+
297
+ function getInput(e, env) {
298
+ if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) {
299
+ return parser.imports.contents[e.filename];
300
+ } else {
301
+ return input;
302
+ }
303
+ }
304
+
305
+ function getLocation(index, inputStream) {
306
+ var n = index + 1,
307
+ line = null,
308
+ column = -1;
309
+
310
+ while (--n >= 0 && inputStream.charAt(n) !== '\n') {
311
+ column++;
312
+ }
313
+
314
+ if (typeof index === 'number') {
315
+ line = (inputStream.slice(0, index).match(/\n/g) || "").length;
316
+ }
317
+
318
+ return {
319
+ line: line,
320
+ column: column
321
+ };
322
+ }
323
+
324
+ function getDebugInfo(index, inputStream, env) {
325
+ var filename = env.currentFileInfo.filename;
326
+ if(less.mode !== 'browser' && less.mode !== 'rhino') {
327
+ filename = require('path').resolve(filename);
328
+ }
329
+
330
+ return {
331
+ lineNumber: getLocation(index, inputStream).line + 1,
332
+ fileName: filename
333
+ };
334
+ }
335
+
336
+ function LessError(e, env) {
337
+ var input = getInput(e, env),
338
+ loc = getLocation(e.index, input),
339
+ line = loc.line,
340
+ col = loc.column,
341
+ callLine = e.call && getLocation(e.call, input).line,
342
+ lines = input.split('\n');
343
+
344
+ this.type = e.type || 'Syntax';
345
+ this.message = e.message;
346
+ this.filename = e.filename || env.currentFileInfo.filename;
347
+ this.index = e.index;
348
+ this.line = typeof(line) === 'number' ? line + 1 : null;
349
+ this.callLine = callLine + 1;
350
+ this.callExtract = lines[callLine];
351
+ this.stack = e.stack;
352
+ this.column = col;
353
+ this.extract = [
354
+ lines[line - 1],
355
+ lines[line],
356
+ lines[line + 1]
357
+ ];
358
+ }
359
+
360
+ LessError.prototype = new Error();
361
+ LessError.prototype.constructor = LessError;
362
+
363
+ this.env = env = env || {};
364
+
365
+ // The optimization level dictates the thoroughness of the parser,
366
+ // the lower the number, the less nodes it will create in the tree.
367
+ // This could matter for debugging, or if you want to access
368
+ // the individual nodes in the tree.
369
+ this.optimization = ('optimization' in this.env) ? this.env.optimization : 1;
370
+
371
+ //
372
+ // The Parser
373
+ //
374
+ parser = {
375
+
376
+ imports: imports,
377
+ //
378
+ // Parse an input string into an abstract syntax tree,
379
+ // @param str A string containing 'less' markup
380
+ // @param callback call `callback` when done.
381
+ // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
382
+ //
383
+ parse: function (str, callback, additionalData) {
384
+ var root, line, lines, error = null, globalVars, modifyVars, preText = "";
385
+
386
+ i = j = currentPos = furthest = 0;
387
+
388
+ globalVars = (additionalData && additionalData.globalVars) ? less.Parser.serializeVars(additionalData.globalVars) + '\n' : '';
389
+ modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + less.Parser.serializeVars(additionalData.modifyVars) : '';
390
+
391
+ if (globalVars || (additionalData && additionalData.banner)) {
392
+ preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars;
393
+ parser.imports.contentsIgnoredChars[env.currentFileInfo.filename] = preText.length;
394
+ }
395
+
396
+ str = str.replace(/\r\n/g, '\n');
397
+ // Remove potential UTF Byte Order Mark
398
+ input = str = preText + str.replace(/^\uFEFF/, '') + modifyVars;
399
+ parser.imports.contents[env.currentFileInfo.filename] = str;
400
+
401
+ // Split the input into chunks.
402
+ chunks = (function (input) {
403
+ var len = input.length, level = 0, parenLevel = 0,
404
+ lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace,
405
+ chunks = [], emitFrom = 0,
406
+ parserCurrentIndex, currentChunkStartIndex, cc, cc2, matched;
407
+
408
+ function fail(msg, index) {
409
+ error = new(LessError)({
410
+ index: index || parserCurrentIndex,
411
+ type: 'Parse',
412
+ message: msg,
413
+ filename: env.currentFileInfo.filename
414
+ }, env);
415
+ }
416
+
417
+ function emitChunk(force) {
418
+ var len = parserCurrentIndex - emitFrom;
419
+ if (((len < 512) && !force) || !len) {
420
+ return;
421
+ }
422
+ chunks.push(input.slice(emitFrom, parserCurrentIndex + 1));
423
+ emitFrom = parserCurrentIndex + 1;
424
+ }
425
+
426
+ for (parserCurrentIndex = 0; parserCurrentIndex < len; parserCurrentIndex++) {
427
+ cc = input.charCodeAt(parserCurrentIndex);
428
+ if (((cc >= 97) && (cc <= 122)) || (cc < 34)) {
429
+ // a-z or whitespace
430
+ continue;
431
+ }
432
+
433
+ switch (cc) {
434
+ case 40: // (
435
+ parenLevel++;
436
+ lastOpeningParen = parserCurrentIndex;
437
+ continue;
438
+ case 41: // )
439
+ if (--parenLevel < 0) {
440
+ return fail("missing opening `(`");
441
+ }
442
+ continue;
443
+ case 59: // ;
444
+ if (!parenLevel) { emitChunk(); }
445
+ continue;
446
+ case 123: // {
447
+ level++;
448
+ lastOpening = parserCurrentIndex;
449
+ continue;
450
+ case 125: // }
451
+ if (--level < 0) {
452
+ return fail("missing opening `{`");
453
+ }
454
+ if (!level && !parenLevel) { emitChunk(); }
455
+ continue;
456
+ case 92: // \
457
+ if (parserCurrentIndex < len - 1) { parserCurrentIndex++; continue; }
458
+ return fail("unescaped `\\`");
459
+ case 34:
460
+ case 39:
461
+ case 96: // ", ' and `
462
+ matched = 0;
463
+ currentChunkStartIndex = parserCurrentIndex;
464
+ for (parserCurrentIndex = parserCurrentIndex + 1; parserCurrentIndex < len; parserCurrentIndex++) {
465
+ cc2 = input.charCodeAt(parserCurrentIndex);
466
+ if (cc2 > 96) { continue; }
467
+ if (cc2 == cc) { matched = 1; break; }
468
+ if (cc2 == 92) { // \
469
+ if (parserCurrentIndex == len - 1) {
470
+ return fail("unescaped `\\`");
471
+ }
472
+ parserCurrentIndex++;
473
+ }
474
+ }
475
+ if (matched) { continue; }
476
+ return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex);
477
+ case 47: // /, check for comment
478
+ if (parenLevel || (parserCurrentIndex == len - 1)) { continue; }
479
+ cc2 = input.charCodeAt(parserCurrentIndex + 1);
480
+ if (cc2 == 47) {
481
+ // //, find lnfeed
482
+ for (parserCurrentIndex = parserCurrentIndex + 2; parserCurrentIndex < len; parserCurrentIndex++) {
483
+ cc2 = input.charCodeAt(parserCurrentIndex);
484
+ if ((cc2 <= 13) && ((cc2 == 10) || (cc2 == 13))) { break; }
485
+ }
486
+ } else if (cc2 == 42) {
487
+ // /*, find */
488
+ lastMultiComment = currentChunkStartIndex = parserCurrentIndex;
489
+ for (parserCurrentIndex = parserCurrentIndex + 2; parserCurrentIndex < len - 1; parserCurrentIndex++) {
490
+ cc2 = input.charCodeAt(parserCurrentIndex);
491
+ if (cc2 == 125) { lastMultiCommentEndBrace = parserCurrentIndex; }
492
+ if (cc2 != 42) { continue; }
493
+ if (input.charCodeAt(parserCurrentIndex + 1) == 47) { break; }
494
+ }
495
+ if (parserCurrentIndex == len - 1) {
496
+ return fail("missing closing `*/`", currentChunkStartIndex);
497
+ }
498
+ parserCurrentIndex++;
499
+ }
500
+ continue;
501
+ case 42: // *, check for unmatched */
502
+ if ((parserCurrentIndex < len - 1) && (input.charCodeAt(parserCurrentIndex + 1) == 47)) {
503
+ return fail("unmatched `/*`");
504
+ }
505
+ continue;
506
+ }
507
+ }
508
+
509
+ if (level !== 0) {
510
+ if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) {
511
+ return fail("missing closing `}` or `*/`", lastOpening);
512
+ } else {
513
+ return fail("missing closing `}`", lastOpening);
514
+ }
515
+ } else if (parenLevel !== 0) {
516
+ return fail("missing closing `)`", lastOpeningParen);
517
+ }
518
+
519
+ emitChunk(true);
520
+ return chunks;
521
+ })(str);
522
+
523
+ if (error) {
524
+ return callback(new(LessError)(error, env));
525
+ }
526
+
527
+ current = chunks[0];
528
+
529
+ // Start with the primary rule.
530
+ // The whole syntax tree is held under a Ruleset node,
531
+ // with the `root` property set to true, so no `{}` are
532
+ // output. The callback is called when the input is parsed.
533
+ try {
534
+ root = new(tree.Ruleset)(null, this.parsers.primary());
535
+ root.root = true;
536
+ root.firstRoot = true;
537
+ } catch (e) {
538
+ return callback(new(LessError)(e, env));
539
+ }
540
+
541
+ root.toCSS = (function (evaluate) {
542
+ return function (options, variables) {
543
+ options = options || {};
544
+ var evaldRoot,
545
+ css,
546
+ evalEnv = new tree.evalEnv(options);
547
+
548
+ //
549
+ // Allows setting variables with a hash, so:
550
+ //
551
+ // `{ color: new(tree.Color)('#f01') }` will become:
552
+ //
553
+ // new(tree.Rule)('@color',
554
+ // new(tree.Value)([
555
+ // new(tree.Expression)([
556
+ // new(tree.Color)('#f01')
557
+ // ])
558
+ // ])
559
+ // )
560
+ //
561
+ if (typeof(variables) === 'object' && !Array.isArray(variables)) {
562
+ variables = Object.keys(variables).map(function (k) {
563
+ var value = variables[k];
564
+
565
+ if (! (value instanceof tree.Value)) {
566
+ if (! (value instanceof tree.Expression)) {
567
+ value = new(tree.Expression)([value]);
568
+ }
569
+ value = new(tree.Value)([value]);
570
+ }
571
+ return new(tree.Rule)('@' + k, value, false, null, 0);
572
+ });
573
+ evalEnv.frames = [new(tree.Ruleset)(null, variables)];
574
+ }
575
+
576
+ try {
577
+ var preEvalVisitors = [],
578
+ visitors = [
579
+ new(tree.joinSelectorVisitor)(),
580
+ new(tree.processExtendsVisitor)(),
581
+ new(tree.toCSSVisitor)({compress: Boolean(options.compress)})
582
+ ], i, root = this;
583
+
584
+ if (options.plugins) {
585
+ for(i =0; i < options.plugins.length; i++) {
586
+ if (options.plugins[i].isPreEvalVisitor) {
587
+ preEvalVisitors.push(options.plugins[i]);
588
+ } else {
589
+ if (options.plugins[i].isPreVisitor) {
590
+ visitors.splice(0, 0, options.plugins[i]);
591
+ } else {
592
+ visitors.push(options.plugins[i]);
593
+ }
594
+ }
595
+ }
596
+ }
597
+
598
+ for(i = 0; i < preEvalVisitors.length; i++) {
599
+ preEvalVisitors[i].run(root);
600
+ }
601
+
602
+ evaldRoot = evaluate.call(root, evalEnv);
603
+
604
+ for(i = 0; i < visitors.length; i++) {
605
+ visitors[i].run(evaldRoot);
606
+ }
607
+
608
+ if (options.sourceMap) {
609
+ evaldRoot = new tree.sourceMapOutput(
610
+ {
611
+ contentsIgnoredCharsMap: parser.imports.contentsIgnoredChars,
612
+ writeSourceMap: options.writeSourceMap,
613
+ rootNode: evaldRoot,
614
+ contentsMap: parser.imports.contents,
615
+ sourceMapFilename: options.sourceMapFilename,
616
+ sourceMapURL: options.sourceMapURL,
617
+ outputFilename: options.sourceMapOutputFilename,
618
+ sourceMapBasepath: options.sourceMapBasepath,
619
+ sourceMapRootpath: options.sourceMapRootpath,
620
+ outputSourceFiles: options.outputSourceFiles,
621
+ sourceMapGenerator: options.sourceMapGenerator
622
+ });
623
+ }
624
+
625
+ css = evaldRoot.toCSS({
626
+ compress: Boolean(options.compress),
627
+ dumpLineNumbers: env.dumpLineNumbers,
628
+ strictUnits: Boolean(options.strictUnits),
629
+ numPrecision: 8});
630
+ } catch (e) {
631
+ throw new(LessError)(e, env);
632
+ }
633
+
634
+ if (options.cleancss && less.mode === 'node') {
635
+ var CleanCSS = require('clean-css'),
636
+ cleancssOptions = options.cleancssOptions || {};
637
+
638
+ if (cleancssOptions.keepSpecialComments === undefined) {
639
+ cleancssOptions.keepSpecialComments = "*";
640
+ }
641
+ cleancssOptions.processImport = false;
642
+ cleancssOptions.noRebase = true;
643
+ if (cleancssOptions.noAdvanced === undefined) {
644
+ cleancssOptions.noAdvanced = true;
645
+ }
646
+
647
+ return new CleanCSS(cleancssOptions).minify(css);
648
+ } else if (options.compress) {
649
+ return css.replace(/(^(\s)+)|((\s)+$)/g, "");
650
+ } else {
651
+ return css;
652
+ }
653
+ };
654
+ })(root.eval);
655
+
656
+ // If `i` is smaller than the `input.length - 1`,
657
+ // it means the parser wasn't able to parse the whole
658
+ // string, so we've got a parsing error.
659
+ //
660
+ // We try to extract a \n delimited string,
661
+ // showing the line where the parse error occured.
662
+ // We split it up into two parts (the part which parsed,
663
+ // and the part which didn't), so we can color them differently.
664
+ if (i < input.length - 1) {
665
+ i = furthest;
666
+ var loc = getLocation(i, input);
667
+ lines = input.split('\n');
668
+ line = loc.line + 1;
669
+
670
+ error = {
671
+ type: "Parse",
672
+ message: "Unrecognised input",
673
+ index: i,
674
+ filename: env.currentFileInfo.filename,
675
+ line: line,
676
+ column: loc.column,
677
+ extract: [
678
+ lines[line - 2],
679
+ lines[line - 1],
680
+ lines[line]
681
+ ]
682
+ };
683
+ }
684
+
685
+ var finish = function (e) {
686
+ e = error || e || parser.imports.error;
687
+
688
+ if (e) {
689
+ if (!(e instanceof LessError)) {
690
+ e = new(LessError)(e, env);
691
+ }
692
+
693
+ return callback(e);
694
+ }
695
+ else {
696
+ return callback(null, root);
697
+ }
698
+ };
699
+
700
+ if (env.processImports !== false) {
701
+ new tree.importVisitor(this.imports, finish)
702
+ .run(root);
703
+ } else {
704
+ return finish();
705
+ }
706
+ },
707
+
708
+ //
709
+ // Here in, the parsing rules/functions
710
+ //
711
+ // The basic structure of the syntax tree generated is as follows:
712
+ //
713
+ // Ruleset -> Rule -> Value -> Expression -> Entity
714
+ //
715
+ // Here's some Less code:
716
+ //
717
+ // .class {
718
+ // color: #fff;
719
+ // border: 1px solid #000;
720
+ // width: @w + 4px;
721
+ // > .child {...}
722
+ // }
723
+ //
724
+ // And here's what the parse tree might look like:
725
+ //
726
+ // Ruleset (Selector '.class', [
727
+ // Rule ("color", Value ([Expression [Color #fff]]))
728
+ // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
729
+ // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]]))
730
+ // Ruleset (Selector [Element '>', '.child'], [...])
731
+ // ])
732
+ //
733
+ // In general, most rules will try to parse a token with the `$()` function, and if the return
734
+ // value is truly, will return a new node, of the relevant type. Sometimes, we need to check
735
+ // first, before parsing, that's when we use `peek()`.
736
+ //
737
+ parsers: parsers = {
738
+ //
739
+ // The `primary` rule is the *entry* and *exit* point of the parser.
740
+ // The rules here can appear at any level of the parse tree.
741
+ //
742
+ // The recursive nature of the grammar is an interplay between the `block`
743
+ // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule,
744
+ // as represented by this simplified grammar:
745
+ //
746
+ // primary → (ruleset | rule)+
747
+ // ruleset → selector+ block
748
+ // block → '{' primary '}'
749
+ //
750
+ // Only at one point is the primary rule not called from the
751
+ // block rule: at the root level.
752
+ //
753
+ primary: function () {
754
+ var mixin = this.mixin, $re = _$re, root = [], node;
755
+
756
+ while (current)
757
+ {
758
+ node = this.extendRule() || mixin.definition() || this.rule() || this.ruleset() ||
759
+ mixin.call() || this.comment() || this.rulesetCall() || this.directive();
760
+ if (node) {
761
+ root.push(node);
762
+ } else {
763
+ if (!($re(/^[\s\n]+/) || $re(/^;+/))) {
764
+ break;
765
+ }
766
+ }
767
+ if (peekChar('}')) {
768
+ break;
769
+ }
770
+ }
771
+
772
+ return root;
773
+ },
774
+
775
+ // We create a Comment node for CSS comments `/* */`,
776
+ // but keep the LeSS comments `//` silent, by just skipping
777
+ // over them.
778
+ comment: function () {
779
+ var comment;
780
+
781
+ if (input.charAt(i) !== '/') { return; }
782
+
783
+ if (input.charAt(i + 1) === '/') {
784
+ return new(tree.Comment)($re(/^\/\/.*/), true, i, env.currentFileInfo);
785
+ }
786
+ comment = $re(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/);
787
+ if (comment) {
788
+ return new(tree.Comment)(comment, false, i, env.currentFileInfo);
789
+ }
790
+ },
791
+
792
+ comments: function () {
793
+ var comment, comments = [];
794
+
795
+ while(true) {
796
+ comment = this.comment();
797
+ if (!comment) {
798
+ break;
799
+ }
800
+ comments.push(comment);
801
+ }
802
+
803
+ return comments;
804
+ },
805
+
806
+ //
807
+ // Entities are tokens which can be found inside an Expression
808
+ //
809
+ entities: {
810
+ //
811
+ // A string, which supports escaping " and '
812
+ //
813
+ // "milky way" 'he\'s the one!'
814
+ //
815
+ quoted: function () {
816
+ var str, j = i, e, index = i;
817
+
818
+ if (input.charAt(j) === '~') { j++; e = true; } // Escaped strings
819
+ if (input.charAt(j) !== '"' && input.charAt(j) !== "'") { return; }
820
+
821
+ if (e) { $char('~'); }
822
+
823
+ str = $re(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/);
824
+ if (str) {
825
+ return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo);
826
+ }
827
+ },
828
+
829
+ //
830
+ // A catch-all word, such as:
831
+ //
832
+ // black border-collapse
833
+ //
834
+ keyword: function () {
835
+ var k;
836
+
837
+ k = $re(/^%|^[_A-Za-z-][_A-Za-z0-9-]*/);
838
+ if (k) {
839
+ var color = tree.Color.fromKeyword(k);
840
+ if (color) {
841
+ return color;
842
+ }
843
+ return new(tree.Keyword)(k);
844
+ }
845
+ },
846
+
847
+ //
848
+ // A function call
849
+ //
850
+ // rgb(255, 0, 255)
851
+ //
852
+ // We also try to catch IE's `alpha()`, but let the `alpha` parser
853
+ // deal with the details.
854
+ //
855
+ // The arguments are parsed with the `entities.arguments` parser.
856
+ //
857
+ call: function () {
858
+ var name, nameLC, args, alpha_ret, index = i;
859
+
860
+ name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(current);
861
+ if (!name) { return; }
862
+
863
+ name = name[1];
864
+ nameLC = name.toLowerCase();
865
+ if (nameLC === 'url') {
866
+ return null;
867
+ }
868
+
869
+ i += name.length;
870
+
871
+ if (nameLC === 'alpha') {
872
+ alpha_ret = parsers.alpha();
873
+ if(typeof alpha_ret !== 'undefined') {
874
+ return alpha_ret;
875
+ }
876
+ }
877
+
878
+ $char('('); // Parse the '(' and consume whitespace.
879
+
880
+ args = this.arguments();
881
+
882
+ if (! $char(')')) {
883
+ return;
884
+ }
885
+
886
+ if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); }
887
+ },
888
+ arguments: function () {
889
+ var args = [], arg;
890
+
891
+ while (true) {
892
+ arg = this.assignment() || parsers.expression();
893
+ if (!arg) {
894
+ break;
895
+ }
896
+ args.push(arg);
897
+ if (! $char(',')) {
898
+ break;
899
+ }
900
+ }
901
+ return args;
902
+ },
903
+ literal: function () {
904
+ return this.dimension() ||
905
+ this.color() ||
906
+ this.quoted() ||
907
+ this.unicodeDescriptor();
908
+ },
909
+
910
+ // Assignments are argument entities for calls.
911
+ // They are present in ie filter properties as shown below.
912
+ //
913
+ // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* )
914
+ //
915
+
916
+ assignment: function () {
917
+ var key, value;
918
+ key = $re(/^\w+(?=\s?=)/i);
919
+ if (!key) {
920
+ return;
921
+ }
922
+ if (!$char('=')) {
923
+ return;
924
+ }
925
+ value = parsers.entity();
926
+ if (value) {
927
+ return new(tree.Assignment)(key, value);
928
+ }
929
+ },
930
+
931
+ //
932
+ // Parse url() tokens
933
+ //
934
+ // We use a specific rule for urls, because they don't really behave like
935
+ // standard function calls. The difference is that the argument doesn't have
936
+ // to be enclosed within a string, so it can't be parsed as an Expression.
937
+ //
938
+ url: function () {
939
+ var value;
940
+
941
+ if (input.charAt(i) !== 'u' || !$re(/^url\(/)) {
942
+ return;
943
+ }
944
+
945
+ value = this.quoted() || this.variable() ||
946
+ $re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || "";
947
+
948
+ expectChar(')');
949
+
950
+ return new(tree.URL)((value.value != null || value instanceof tree.Variable)
951
+ ? value : new(tree.Anonymous)(value), env.currentFileInfo);
952
+ },
953
+
954
+ //
955
+ // A Variable entity, such as `@fink`, in
956
+ //
957
+ // width: @fink + 2px
958
+ //
959
+ // We use a different parser for variable definitions,
960
+ // see `parsers.variable`.
961
+ //
962
+ variable: function () {
963
+ var name, index = i;
964
+
965
+ if (input.charAt(i) === '@' && (name = $re(/^@@?[\w-]+/))) {
966
+ return new(tree.Variable)(name, index, env.currentFileInfo);
967
+ }
968
+ },
969
+
970
+ // A variable entity useing the protective {} e.g. @{var}
971
+ variableCurly: function () {
972
+ var curly, index = i;
973
+
974
+ if (input.charAt(i) === '@' && (curly = $re(/^@\{([\w-]+)\}/))) {
975
+ return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo);
976
+ }
977
+ },
978
+
979
+ //
980
+ // A Hexadecimal color
981
+ //
982
+ // #4F3C2F
983
+ //
984
+ // `rgb` and `hsl` colors are parsed through the `entities.call` parser.
985
+ //
986
+ color: function () {
987
+ var rgb;
988
+
989
+ if (input.charAt(i) === '#' && (rgb = $re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
990
+ var colorCandidateString = rgb.input.match(/^#([\w]+).*/); // strip colons, brackets, whitespaces and other characters that should not definitely be part of color string
991
+ colorCandidateString = colorCandidateString[1];
992
+ if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
993
+ error("Invalid HEX color code");
994
+ }
995
+ return new(tree.Color)(rgb[1]);
996
+ }
997
+ },
998
+
999
+ //
1000
+ // A Dimension, that is, a number and a unit
1001
+ //
1002
+ // 0.5em 95%
1003
+ //
1004
+ dimension: function () {
1005
+ var value, c = input.charCodeAt(i);
1006
+ //Is the first char of the dimension 0-9, '.', '+' or '-'
1007
+ if ((c > 57 || c < 43) || c === 47 || c == 44) {
1008
+ return;
1009
+ }
1010
+
1011
+ value = $re(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/);
1012
+ if (value) {
1013
+ return new(tree.Dimension)(value[1], value[2]);
1014
+ }
1015
+ },
1016
+
1017
+ //
1018
+ // A unicode descriptor, as is used in unicode-range
1019
+ //
1020
+ // U+0?? or U+00A1-00A9
1021
+ //
1022
+ unicodeDescriptor: function () {
1023
+ var ud;
1024
+
1025
+ ud = $re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/);
1026
+ if (ud) {
1027
+ return new(tree.UnicodeDescriptor)(ud[0]);
1028
+ }
1029
+ },
1030
+
1031
+ //
1032
+ // JavaScript code to be evaluated
1033
+ //
1034
+ // `window.location.href`
1035
+ //
1036
+ javascript: function () {
1037
+ var str, j = i, e;
1038
+
1039
+ if (input.charAt(j) === '~') { j++; e = true; } // Escaped strings
1040
+ if (input.charAt(j) !== '`') { return; }
1041
+ if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) {
1042
+ error("You are using JavaScript, which has been disabled.");
1043
+ }
1044
+
1045
+ if (e) { $char('~'); }
1046
+
1047
+ str = $re(/^`([^`]*)`/);
1048
+ if (str) {
1049
+ return new(tree.JavaScript)(str[1], i, e);
1050
+ }
1051
+ }
1052
+ },
1053
+
1054
+ //
1055
+ // The variable part of a variable definition. Used in the `rule` parser
1056
+ //
1057
+ // @fink:
1058
+ //
1059
+ variable: function () {
1060
+ var name;
1061
+
1062
+ if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*:/))) { return name[1]; }
1063
+ },
1064
+
1065
+ //
1066
+ // The variable part of a variable definition. Used in the `rule` parser
1067
+ //
1068
+ // @fink();
1069
+ //
1070
+ rulesetCall: function () {
1071
+ var name;
1072
+
1073
+ if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) {
1074
+ return new tree.RulesetCall(name[1]);
1075
+ }
1076
+ },
1077
+
1078
+ //
1079
+ // extend syntax - used to extend selectors
1080
+ //
1081
+ extend: function(isRule) {
1082
+ var elements, e, index = i, option, extendList, extend;
1083
+
1084
+ if (!(isRule ? $re(/^&:extend\(/) : $re(/^:extend\(/))) { return; }
1085
+
1086
+ do {
1087
+ option = null;
1088
+ elements = null;
1089
+ while (! (option = $re(/^(all)(?=\s*(\)|,))/))) {
1090
+ e = this.element();
1091
+ if (!e) { break; }
1092
+ if (elements) { elements.push(e); } else { elements = [ e ]; }
1093
+ }
1094
+
1095
+ option = option && option[1];
1096
+
1097
+ extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
1098
+ if (extendList) { extendList.push(extend); } else { extendList = [ extend ]; }
1099
+
1100
+ } while($char(","));
1101
+
1102
+ expect(/^\)/);
1103
+
1104
+ if (isRule) {
1105
+ expect(/^;/);
1106
+ }
1107
+
1108
+ return extendList;
1109
+ },
1110
+
1111
+ //
1112
+ // extendRule - used in a rule to extend all the parent selectors
1113
+ //
1114
+ extendRule: function() {
1115
+ return this.extend(true);
1116
+ },
1117
+
1118
+ //
1119
+ // Mixins
1120
+ //
1121
+ mixin: {
1122
+ //
1123
+ // A Mixin call, with an optional argument list
1124
+ //
1125
+ // #mixins > .square(#fff);
1126
+ // .rounded(4px, black);
1127
+ // .button;
1128
+ //
1129
+ // The `while` loop is there because mixins can be
1130
+ // namespaced, but we only support the child and descendant
1131
+ // selector for now.
1132
+ //
1133
+ call: function () {
1134
+ var s = input.charAt(i), important = false, index = i, elemIndex,
1135
+ elements, elem, e, c, args;
1136
+
1137
+ if (s !== '.' && s !== '#') { return; }
1138
+
1139
+ save(); // stop us absorbing part of an invalid selector
1140
+
1141
+ while (true) {
1142
+ elemIndex = i;
1143
+ e = $re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/);
1144
+ if (!e) {
1145
+ break;
1146
+ }
1147
+ elem = new(tree.Element)(c, e, elemIndex, env.currentFileInfo);
1148
+ if (elements) { elements.push(elem); } else { elements = [ elem ]; }
1149
+ c = $char('>');
1150
+ }
1151
+
1152
+ if (elements) {
1153
+ if ($char('(')) {
1154
+ args = this.args(true).args;
1155
+ expectChar(')');
1156
+ }
1157
+
1158
+ if (parsers.important()) {
1159
+ important = true;
1160
+ }
1161
+
1162
+ if (parsers.end()) {
1163
+ forget();
1164
+ return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important);
1165
+ }
1166
+ }
1167
+
1168
+ restore();
1169
+ },
1170
+ args: function (isCall) {
1171
+ var parsers = parser.parsers, entities = parsers.entities,
1172
+ returner = { args:null, variadic: false },
1173
+ expressions = [], argsSemiColon = [], argsComma = [],
1174
+ isSemiColonSeperated, expressionContainsNamed, name, nameLoop, value, arg;
1175
+
1176
+ save();
1177
+
1178
+ while (true) {
1179
+ if (isCall) {
1180
+ arg = parsers.detachedRuleset() || parsers.expression();
1181
+ } else {
1182
+ parsers.comments();
1183
+ if (input.charAt(i) === '.' && $re(/^\.{3}/)) {
1184
+ returner.variadic = true;
1185
+ if ($char(";") && !isSemiColonSeperated) {
1186
+ isSemiColonSeperated = true;
1187
+ }
1188
+ (isSemiColonSeperated ? argsSemiColon : argsComma)
1189
+ .push({ variadic: true });
1190
+ break;
1191
+ }
1192
+ arg = entities.variable() || entities.literal() || entities.keyword();
1193
+ }
1194
+
1195
+ if (!arg) {
1196
+ break;
1197
+ }
1198
+
1199
+ nameLoop = null;
1200
+ if (arg.throwAwayComments) {
1201
+ arg.throwAwayComments();
1202
+ }
1203
+ value = arg;
1204
+ var val = null;
1205
+
1206
+ if (isCall) {
1207
+ // Variable
1208
+ if (arg.value && arg.value.length == 1) {
1209
+ val = arg.value[0];
1210
+ }
1211
+ } else {
1212
+ val = arg;
1213
+ }
1214
+
1215
+ if (val && val instanceof tree.Variable) {
1216
+ if ($char(':')) {
1217
+ if (expressions.length > 0) {
1218
+ if (isSemiColonSeperated) {
1219
+ error("Cannot mix ; and , as delimiter types");
1220
+ }
1221
+ expressionContainsNamed = true;
1222
+ }
1223
+
1224
+ // we do not support setting a ruleset as a default variable - it doesn't make sense
1225
+ // However if we do want to add it, there is nothing blocking it, just don't error
1226
+ // and remove isCall dependency below
1227
+ value = (isCall && parsers.detachedRuleset()) || parsers.expression();
1228
+
1229
+ if (!value) {
1230
+ if (isCall) {
1231
+ error("could not understand value for named argument");
1232
+ } else {
1233
+ restore();
1234
+ returner.args = [];
1235
+ return returner;
1236
+ }
1237
+ }
1238
+ nameLoop = (name = val.name);
1239
+ } else if (!isCall && $re(/^\.{3}/)) {
1240
+ returner.variadic = true;
1241
+ if ($char(";") && !isSemiColonSeperated) {
1242
+ isSemiColonSeperated = true;
1243
+ }
1244
+ (isSemiColonSeperated ? argsSemiColon : argsComma)
1245
+ .push({ name: arg.name, variadic: true });
1246
+ break;
1247
+ } else if (!isCall) {
1248
+ name = nameLoop = val.name;
1249
+ value = null;
1250
+ }
1251
+ }
1252
+
1253
+ if (value) {
1254
+ expressions.push(value);
1255
+ }
1256
+
1257
+ argsComma.push({ name:nameLoop, value:value });
1258
+
1259
+ if ($char(',')) {
1260
+ continue;
1261
+ }
1262
+
1263
+ if ($char(';') || isSemiColonSeperated) {
1264
+
1265
+ if (expressionContainsNamed) {
1266
+ error("Cannot mix ; and , as delimiter types");
1267
+ }
1268
+
1269
+ isSemiColonSeperated = true;
1270
+
1271
+ if (expressions.length > 1) {
1272
+ value = new(tree.Value)(expressions);
1273
+ }
1274
+ argsSemiColon.push({ name:name, value:value });
1275
+
1276
+ name = null;
1277
+ expressions = [];
1278
+ expressionContainsNamed = false;
1279
+ }
1280
+ }
1281
+
1282
+ forget();
1283
+ returner.args = isSemiColonSeperated ? argsSemiColon : argsComma;
1284
+ return returner;
1285
+ },
1286
+ //
1287
+ // A Mixin definition, with a list of parameters
1288
+ //
1289
+ // .rounded (@radius: 2px, @color) {
1290
+ // ...
1291
+ // }
1292
+ //
1293
+ // Until we have a finer grained state-machine, we have to
1294
+ // do a look-ahead, to make sure we don't have a mixin call.
1295
+ // See the `rule` function for more information.
1296
+ //
1297
+ // We start by matching `.rounded (`, and then proceed on to
1298
+ // the argument list, which has optional default values.
1299
+ // We store the parameters in `params`, with a `value` key,
1300
+ // if there is a value, such as in the case of `@radius`.
1301
+ //
1302
+ // Once we've got our params list, and a closing `)`, we parse
1303
+ // the `{...}` block.
1304
+ //
1305
+ definition: function () {
1306
+ var name, params = [], match, ruleset, cond, variadic = false;
1307
+ if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') ||
1308
+ peek(/^[^{]*\}/)) {
1309
+ return;
1310
+ }
1311
+
1312
+ save();
1313
+
1314
+ match = $re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
1315
+ if (match) {
1316
+ name = match[1];
1317
+
1318
+ var argInfo = this.args(false);
1319
+ params = argInfo.args;
1320
+ variadic = argInfo.variadic;
1321
+
1322
+ // .mixincall("@{a}");
1323
+ // looks a bit like a mixin definition..
1324
+ // also
1325
+ // .mixincall(@a: {rule: set;});
1326
+ // so we have to be nice and restore
1327
+ if (!$char(')')) {
1328
+ furthest = i;
1329
+ restore();
1330
+ return;
1331
+ }
1332
+
1333
+ parsers.comments();
1334
+
1335
+ if ($re(/^when/)) { // Guard
1336
+ cond = expect(parsers.conditions, 'expected condition');
1337
+ }
1338
+
1339
+ ruleset = parsers.block();
1340
+
1341
+ if (ruleset) {
1342
+ forget();
1343
+ return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
1344
+ } else {
1345
+ restore();
1346
+ }
1347
+ } else {
1348
+ forget();
1349
+ }
1350
+ }
1351
+ },
1352
+
1353
+ //
1354
+ // Entities are the smallest recognized token,
1355
+ // and can be found inside a rule's value.
1356
+ //
1357
+ entity: function () {
1358
+ var entities = this.entities;
1359
+
1360
+ return entities.literal() || entities.variable() || entities.url() ||
1361
+ entities.call() || entities.keyword() || entities.javascript() ||
1362
+ this.comment();
1363
+ },
1364
+
1365
+ //
1366
+ // A Rule terminator. Note that we use `peek()` to check for '}',
1367
+ // because the `block` rule will be expecting it, but we still need to make sure
1368
+ // it's there, if ';' was ommitted.
1369
+ //
1370
+ end: function () {
1371
+ return $char(';') || peekChar('}');
1372
+ },
1373
+
1374
+ //
1375
+ // IE's alpha function
1376
+ //
1377
+ // alpha(opacity=88)
1378
+ //
1379
+ alpha: function () {
1380
+ var value;
1381
+
1382
+ if (! $re(/^\(opacity=/i)) { return; }
1383
+ value = $re(/^\d+/) || this.entities.variable();
1384
+ if (value) {
1385
+ expectChar(')');
1386
+ return new(tree.Alpha)(value);
1387
+ }
1388
+ },
1389
+
1390
+ //
1391
+ // A Selector Element
1392
+ //
1393
+ // div
1394
+ // + h1
1395
+ // #socks
1396
+ // input[type="text"]
1397
+ //
1398
+ // Elements are the building blocks for Selectors,
1399
+ // they are made out of a `Combinator` (see combinator rule),
1400
+ // and an element name, such as a tag a class, or `*`.
1401
+ //
1402
+ element: function () {
1403
+ var e, c, v, index = i;
1404
+
1405
+ c = this.combinator();
1406
+
1407
+ e = $re(/^(?:\d+\.\d+|\d+)%/) || $re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
1408
+ $char('*') || $char('&') || this.attribute() || $re(/^\([^()@]+\)/) || $re(/^[\.#](?=@)/) ||
1409
+ this.entities.variableCurly();
1410
+
1411
+ if (! e) {
1412
+ save();
1413
+ if ($char('(')) {
1414
+ if ((v = this.selector()) && $char(')')) {
1415
+ e = new(tree.Paren)(v);
1416
+ forget();
1417
+ } else {
1418
+ restore();
1419
+ }
1420
+ } else {
1421
+ forget();
1422
+ }
1423
+ }
1424
+
1425
+ if (e) { return new(tree.Element)(c, e, index, env.currentFileInfo); }
1426
+ },
1427
+
1428
+ //
1429
+ // Combinators combine elements together, in a Selector.
1430
+ //
1431
+ // Because our parser isn't white-space sensitive, special care
1432
+ // has to be taken, when parsing the descendant combinator, ` `,
1433
+ // as it's an empty space. We have to check the previous character
1434
+ // in the input, to see if it's a ` ` character. More info on how
1435
+ // we deal with this in *combinator.js*.
1436
+ //
1437
+ combinator: function () {
1438
+ var c = input.charAt(i);
1439
+
1440
+ if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') {
1441
+ i++;
1442
+ if (input.charAt(i) === '^') {
1443
+ c = '^^';
1444
+ i++;
1445
+ }
1446
+ while (isWhitespace(input, i)) { i++; }
1447
+ return new(tree.Combinator)(c);
1448
+ } else if (isWhitespace(input, i - 1)) {
1449
+ return new(tree.Combinator)(" ");
1450
+ } else {
1451
+ return new(tree.Combinator)(null);
1452
+ }
1453
+ },
1454
+ //
1455
+ // A CSS selector (see selector below)
1456
+ // with less extensions e.g. the ability to extend and guard
1457
+ //
1458
+ lessSelector: function () {
1459
+ return this.selector(true);
1460
+ },
1461
+ //
1462
+ // A CSS Selector
1463
+ //
1464
+ // .class > div + h1
1465
+ // li a:hover
1466
+ //
1467
+ // Selectors are made out of one or more Elements, see above.
1468
+ //
1469
+ selector: function (isLess) {
1470
+ var index = i, $re = _$re, elements, extendList, c, e, extend, when, condition;
1471
+
1472
+ while ((isLess && (extend = this.extend())) || (isLess && (when = $re(/^when/))) || (e = this.element())) {
1473
+ if (when) {
1474
+ condition = expect(this.conditions, 'expected condition');
1475
+ } else if (condition) {
1476
+ error("CSS guard can only be used at the end of selector");
1477
+ } else if (extend) {
1478
+ if (extendList) { extendList.push(extend); } else { extendList = [ extend ]; }
1479
+ } else {
1480
+ if (extendList) { error("Extend can only be used at the end of selector"); }
1481
+ c = input.charAt(i);
1482
+ if (elements) { elements.push(e); } else { elements = [ e ]; }
1483
+ e = null;
1484
+ }
1485
+ if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') {
1486
+ break;
1487
+ }
1488
+ }
1489
+
1490
+ if (elements) { return new(tree.Selector)(elements, extendList, condition, index, env.currentFileInfo); }
1491
+ if (extendList) { error("Extend must be used to extend a selector, it cannot be used on its own"); }
1492
+ },
1493
+ attribute: function () {
1494
+ if (! $char('[')) { return; }
1495
+
1496
+ var entities = this.entities,
1497
+ key, val, op;
1498
+
1499
+ if (!(key = entities.variableCurly())) {
1500
+ key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/);
1501
+ }
1502
+
1503
+ op = $re(/^[|~*$^]?=/);
1504
+ if (op) {
1505
+ val = entities.quoted() || $re(/^[0-9]+%/) || $re(/^[\w-]+/) || entities.variableCurly();
1506
+ }
1507
+
1508
+ expectChar(']');
1509
+
1510
+ return new(tree.Attribute)(key, op, val);
1511
+ },
1512
+
1513
+ //
1514
+ // The `block` rule is used by `ruleset` and `mixin.definition`.
1515
+ // It's a wrapper around the `primary` rule, with added `{}`.
1516
+ //
1517
+ block: function () {
1518
+ var content;
1519
+ if ($char('{') && (content = this.primary()) && $char('}')) {
1520
+ return content;
1521
+ }
1522
+ },
1523
+
1524
+ blockRuleset: function() {
1525
+ var block = this.block();
1526
+
1527
+ if (block) {
1528
+ block = new tree.Ruleset(null, block);
1529
+ }
1530
+ return block;
1531
+ },
1532
+
1533
+ detachedRuleset: function() {
1534
+ var blockRuleset = this.blockRuleset();
1535
+ if (blockRuleset) {
1536
+ return new tree.DetachedRuleset(blockRuleset);
1537
+ }
1538
+ },
1539
+
1540
+ //
1541
+ // div, .class, body > p {...}
1542
+ //
1543
+ ruleset: function () {
1544
+ var selectors, s, rules, debugInfo;
1545
+
1546
+ save();
1547
+
1548
+ if (env.dumpLineNumbers) {
1549
+ debugInfo = getDebugInfo(i, input, env);
1550
+ }
1551
+
1552
+ while (true) {
1553
+ s = this.lessSelector();
1554
+ if (!s) {
1555
+ break;
1556
+ }
1557
+ if (selectors) { selectors.push(s); } else { selectors = [ s ]; }
1558
+ this.comments();
1559
+ if (s.condition && selectors.length > 1) {
1560
+ error("Guards are only currently allowed on a single selector.");
1561
+ }
1562
+ if (! $char(',')) { break; }
1563
+ if (s.condition) {
1564
+ error("Guards are only currently allowed on a single selector.");
1565
+ }
1566
+ this.comments();
1567
+ }
1568
+
1569
+ if (selectors && (rules = this.block())) {
1570
+ forget();
1571
+ var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports);
1572
+ if (env.dumpLineNumbers) {
1573
+ ruleset.debugInfo = debugInfo;
1574
+ }
1575
+ return ruleset;
1576
+ } else {
1577
+ // Backtrack
1578
+ furthest = i;
1579
+ restore();
1580
+ }
1581
+ },
1582
+ rule: function (tryAnonymous) {
1583
+ var name, value, startOfRule = i, c = input.charAt(startOfRule), important, merge, isVariable;
1584
+
1585
+ if (c === '.' || c === '#' || c === '&') { return; }
1586
+
1587
+ save();
1588
+
1589
+ name = this.variable() || this.ruleProperty();
1590
+ if (name) {
1591
+ isVariable = typeof name === "string";
1592
+
1593
+ if (isVariable) {
1594
+ value = this.detachedRuleset();
1595
+ }
1596
+
1597
+ if (!value) {
1598
+ // prefer to try to parse first if its a variable or we are compressing
1599
+ // but always fallback on the other one
1600
+ value = !tryAnonymous && (env.compress || isVariable) ?
1601
+ (this.value() || this.anonymousValue()) :
1602
+ (this.anonymousValue() || this.value());
1603
+
1604
+ important = this.important();
1605
+
1606
+ // a name returned by this.ruleProperty() is always an array of the form:
1607
+ // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
1608
+ // where each item is a tree.Keyword or tree.Variable
1609
+ merge = !isVariable && name.pop().value;
1610
+ }
1611
+
1612
+ if (value && this.end()) {
1613
+ forget();
1614
+ return new (tree.Rule)(name, value, important, merge, startOfRule, env.currentFileInfo);
1615
+ } else {
1616
+ furthest = i;
1617
+ restore();
1618
+ if (value && !tryAnonymous) {
1619
+ return this.rule(true);
1620
+ }
1621
+ }
1622
+ } else {
1623
+ forget();
1624
+ }
1625
+ },
1626
+ anonymousValue: function () {
1627
+ var match;
1628
+ match = /^([^@+\/'"*`(;{}-]*);/.exec(current);
1629
+ if (match) {
1630
+ i += match[0].length - 1;
1631
+ return new(tree.Anonymous)(match[1]);
1632
+ }
1633
+ },
1634
+
1635
+ //
1636
+ // An @import directive
1637
+ //
1638
+ // @import "lib";
1639
+ //
1640
+ // Depending on our environemnt, importing is done differently:
1641
+ // In the browser, it's an XHR request, in Node, it would be a
1642
+ // file-system operation. The function used for importing is
1643
+ // stored in `import`, which we pass to the Import constructor.
1644
+ //
1645
+ "import": function () {
1646
+ var path, features, index = i;
1647
+
1648
+ save();
1649
+
1650
+ var dir = $re(/^@import?\s+/);
1651
+
1652
+ var options = (dir ? this.importOptions() : null) || {};
1653
+
1654
+ if (dir && (path = this.entities.quoted() || this.entities.url())) {
1655
+ features = this.mediaFeatures();
1656
+ if ($char(';')) {
1657
+ forget();
1658
+ features = features && new(tree.Value)(features);
1659
+ return new(tree.Import)(path, features, options, index, env.currentFileInfo);
1660
+ }
1661
+ }
1662
+
1663
+ restore();
1664
+ },
1665
+
1666
+ importOptions: function() {
1667
+ var o, options = {}, optionName, value;
1668
+
1669
+ // list of options, surrounded by parens
1670
+ if (! $char('(')) { return null; }
1671
+ do {
1672
+ o = this.importOption();
1673
+ if (o) {
1674
+ optionName = o;
1675
+ value = true;
1676
+ switch(optionName) {
1677
+ case "css":
1678
+ optionName = "less";
1679
+ value = false;
1680
+ break;
1681
+ case "once":
1682
+ optionName = "multiple";
1683
+ value = false;
1684
+ break;
1685
+ }
1686
+ options[optionName] = value;
1687
+ if (! $char(',')) { break; }
1688
+ }
1689
+ } while (o);
1690
+ expectChar(')');
1691
+ return options;
1692
+ },
1693
+
1694
+ importOption: function() {
1695
+ var opt = $re(/^(less|css|multiple|once|inline|reference)/);
1696
+ if (opt) {
1697
+ return opt[1];
1698
+ }
1699
+ },
1700
+
1701
+ mediaFeature: function () {
1702
+ var entities = this.entities, nodes = [], e, p;
1703
+ do {
1704
+ e = entities.keyword() || entities.variable();
1705
+ if (e) {
1706
+ nodes.push(e);
1707
+ } else if ($char('(')) {
1708
+ p = this.property();
1709
+ e = this.value();
1710
+ if ($char(')')) {
1711
+ if (p && e) {
1712
+ nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, i, env.currentFileInfo, true)));
1713
+ } else if (e) {
1714
+ nodes.push(new(tree.Paren)(e));
1715
+ } else {
1716
+ return null;
1717
+ }
1718
+ } else { return null; }
1719
+ }
1720
+ } while (e);
1721
+
1722
+ if (nodes.length > 0) {
1723
+ return new(tree.Expression)(nodes);
1724
+ }
1725
+ },
1726
+
1727
+ mediaFeatures: function () {
1728
+ var entities = this.entities, features = [], e;
1729
+ do {
1730
+ e = this.mediaFeature();
1731
+ if (e) {
1732
+ features.push(e);
1733
+ if (! $char(',')) { break; }
1734
+ } else {
1735
+ e = entities.variable();
1736
+ if (e) {
1737
+ features.push(e);
1738
+ if (! $char(',')) { break; }
1739
+ }
1740
+ }
1741
+ } while (e);
1742
+
1743
+ return features.length > 0 ? features : null;
1744
+ },
1745
+
1746
+ media: function () {
1747
+ var features, rules, media, debugInfo;
1748
+
1749
+ if (env.dumpLineNumbers) {
1750
+ debugInfo = getDebugInfo(i, input, env);
1751
+ }
1752
+
1753
+ if ($re(/^@media/)) {
1754
+ features = this.mediaFeatures();
1755
+
1756
+ rules = this.block();
1757
+ if (rules) {
1758
+ media = new(tree.Media)(rules, features, i, env.currentFileInfo);
1759
+ if (env.dumpLineNumbers) {
1760
+ media.debugInfo = debugInfo;
1761
+ }
1762
+ return media;
1763
+ }
1764
+ }
1765
+ },
1766
+
1767
+ //
1768
+ // A CSS Directive
1769
+ //
1770
+ // @charset "utf-8";
1771
+ //
1772
+ directive: function () {
1773
+ var index = i, name, value, rules, nonVendorSpecificName,
1774
+ hasIdentifier, hasExpression, hasUnknown, hasBlock = true;
1775
+
1776
+ if (input.charAt(i) !== '@') { return; }
1777
+
1778
+ value = this['import']() || this.media();
1779
+ if (value) {
1780
+ return value;
1781
+ }
1782
+
1783
+ save();
1784
+
1785
+ name = $re(/^@[a-z-]+/);
1786
+
1787
+ if (!name) { return; }
1788
+
1789
+ nonVendorSpecificName = name;
1790
+ if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
1791
+ nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1);
1792
+ }
1793
+
1794
+ switch(nonVendorSpecificName) {
1795
+ /*
1796
+ case "@font-face":
1797
+ case "@viewport":
1798
+ case "@top-left":
1799
+ case "@top-left-corner":
1800
+ case "@top-center":
1801
+ case "@top-right":
1802
+ case "@top-right-corner":
1803
+ case "@bottom-left":
1804
+ case "@bottom-left-corner":
1805
+ case "@bottom-center":
1806
+ case "@bottom-right":
1807
+ case "@bottom-right-corner":
1808
+ case "@left-top":
1809
+ case "@left-middle":
1810
+ case "@left-bottom":
1811
+ case "@right-top":
1812
+ case "@right-middle":
1813
+ case "@right-bottom":
1814
+ hasBlock = true;
1815
+ break;
1816
+ */
1817
+ case "@charset":
1818
+ hasIdentifier = true;
1819
+ hasBlock = false;
1820
+ break;
1821
+ case "@namespace":
1822
+ hasExpression = true;
1823
+ hasBlock = false;
1824
+ break;
1825
+ case "@keyframes":
1826
+ hasIdentifier = true;
1827
+ break;
1828
+ case "@host":
1829
+ case "@page":
1830
+ case "@document":
1831
+ case "@supports":
1832
+ hasUnknown = true;
1833
+ break;
1834
+ }
1835
+
1836
+ if (hasIdentifier) {
1837
+ value = this.entity();
1838
+ if (!value) {
1839
+ error("expected " + name + " identifier");
1840
+ }
1841
+ } else if (hasExpression) {
1842
+ value = this.expression();
1843
+ if (!value) {
1844
+ error("expected " + name + " expression");
1845
+ }
1846
+ } else if (hasUnknown) {
1847
+ value = ($re(/^[^{;]+/) || '').trim();
1848
+ if (value) {
1849
+ value = new(tree.Anonymous)(value);
1850
+ }
1851
+ }
1852
+
1853
+ if (hasBlock) {
1854
+ rules = this.blockRuleset();
1855
+ }
1856
+
1857
+ if (rules || (!hasBlock && value && $char(';'))) {
1858
+ forget();
1859
+ return new(tree.Directive)(name, value, rules, index, env.currentFileInfo,
1860
+ env.dumpLineNumbers ? getDebugInfo(index, input, env) : null);
1861
+ }
1862
+
1863
+ restore();
1864
+ },
1865
+
1866
+ //
1867
+ // A Value is a comma-delimited list of Expressions
1868
+ //
1869
+ // font-family: Baskerville, Georgia, serif;
1870
+ //
1871
+ // In a Rule, a Value represents everything after the `:`,
1872
+ // and before the `;`.
1873
+ //
1874
+ value: function () {
1875
+ var e, expressions = [];
1876
+
1877
+ do {
1878
+ e = this.expression();
1879
+ if (e) {
1880
+ expressions.push(e);
1881
+ if (! $char(',')) { break; }
1882
+ }
1883
+ } while(e);
1884
+
1885
+ if (expressions.length > 0) {
1886
+ return new(tree.Value)(expressions);
1887
+ }
1888
+ },
1889
+ important: function () {
1890
+ if (input.charAt(i) === '!') {
1891
+ return $re(/^! *important/);
1892
+ }
1893
+ },
1894
+ sub: function () {
1895
+ var a, e;
1896
+
1897
+ if ($char('(')) {
1898
+ a = this.addition();
1899
+ if (a) {
1900
+ e = new(tree.Expression)([a]);
1901
+ expectChar(')');
1902
+ e.parens = true;
1903
+ return e;
1904
+ }
1905
+ }
1906
+ },
1907
+ multiplication: function () {
1908
+ var m, a, op, operation, isSpaced;
1909
+ m = this.operand();
1910
+ if (m) {
1911
+ isSpaced = isWhitespace(input, i - 1);
1912
+ while (true) {
1913
+ if (peek(/^\/[*\/]/)) {
1914
+ break;
1915
+ }
1916
+
1917
+ save();
1918
+
1919
+ op = $char('/') || $char('*');
1920
+
1921
+ if (!op) { forget(); break; }
1922
+
1923
+ a = this.operand();
1924
+
1925
+ if (!a) { restore(); break; }
1926
+ forget();
1927
+
1928
+ m.parensInOp = true;
1929
+ a.parensInOp = true;
1930
+ operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
1931
+ isSpaced = isWhitespace(input, i - 1);
1932
+ }
1933
+ return operation || m;
1934
+ }
1935
+ },
1936
+ addition: function () {
1937
+ var m, a, op, operation, isSpaced;
1938
+ m = this.multiplication();
1939
+ if (m) {
1940
+ isSpaced = isWhitespace(input, i - 1);
1941
+ while (true) {
1942
+ op = $re(/^[-+]\s+/) || (!isSpaced && ($char('+') || $char('-')));
1943
+ if (!op) {
1944
+ break;
1945
+ }
1946
+ a = this.multiplication();
1947
+ if (!a) {
1948
+ break;
1949
+ }
1950
+
1951
+ m.parensInOp = true;
1952
+ a.parensInOp = true;
1953
+ operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
1954
+ isSpaced = isWhitespace(input, i - 1);
1955
+ }
1956
+ return operation || m;
1957
+ }
1958
+ },
1959
+ conditions: function () {
1960
+ var a, b, index = i, condition;
1961
+
1962
+ a = this.condition();
1963
+ if (a) {
1964
+ while (true) {
1965
+ if (!peek(/^,\s*(not\s*)?\(/) || !$char(',')) {
1966
+ break;
1967
+ }
1968
+ b = this.condition();
1969
+ if (!b) {
1970
+ break;
1971
+ }
1972
+ condition = new(tree.Condition)('or', condition || a, b, index);
1973
+ }
1974
+ return condition || a;
1975
+ }
1976
+ },
1977
+ condition: function () {
1978
+ var entities = this.entities, index = i, negate = false,
1979
+ a, b, c, op;
1980
+
1981
+ if ($re(/^not/)) { negate = true; }
1982
+ expectChar('(');
1983
+ a = this.addition() || entities.keyword() || entities.quoted();
1984
+ if (a) {
1985
+ op = $re(/^(?:>=|<=|=<|[<=>])/);
1986
+ if (op) {
1987
+ b = this.addition() || entities.keyword() || entities.quoted();
1988
+ if (b) {
1989
+ c = new(tree.Condition)(op, a, b, index, negate);
1990
+ } else {
1991
+ error('expected expression');
1992
+ }
1993
+ } else {
1994
+ c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate);
1995
+ }
1996
+ expectChar(')');
1997
+ return $re(/^and/) ? new(tree.Condition)('and', c, this.condition()) : c;
1998
+ }
1999
+ },
2000
+
2001
+ //
2002
+ // An operand is anything that can be part of an operation,
2003
+ // such as a Color, or a Variable
2004
+ //
2005
+ operand: function () {
2006
+ var entities = this.entities,
2007
+ p = input.charAt(i + 1), negate;
2008
+
2009
+ if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $char('-'); }
2010
+ var o = this.sub() || entities.dimension() ||
2011
+ entities.color() || entities.variable() ||
2012
+ entities.call();
2013
+
2014
+ if (negate) {
2015
+ o.parensInOp = true;
2016
+ o = new(tree.Negative)(o);
2017
+ }
2018
+
2019
+ return o;
2020
+ },
2021
+
2022
+ //
2023
+ // Expressions either represent mathematical operations,
2024
+ // or white-space delimited Entities.
2025
+ //
2026
+ // 1px solid black
2027
+ // @var * 2
2028
+ //
2029
+ expression: function () {
2030
+ var entities = [], e, delim;
2031
+
2032
+ do {
2033
+ e = this.addition() || this.entity();
2034
+ if (e) {
2035
+ entities.push(e);
2036
+ // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here
2037
+ if (!peek(/^\/[\/*]/)) {
2038
+ delim = $char('/');
2039
+ if (delim) {
2040
+ entities.push(new(tree.Anonymous)(delim));
2041
+ }
2042
+ }
2043
+ }
2044
+ } while (e);
2045
+ if (entities.length > 0) {
2046
+ return new(tree.Expression)(entities);
2047
+ }
2048
+ },
2049
+ property: function () {
2050
+ var name = $re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);
2051
+ if (name) {
2052
+ return name[1];
2053
+ }
2054
+ },
2055
+ ruleProperty: function () {
2056
+ var c = current, name = [], index = [], length = 0, s, k;
2057
+
2058
+ function match(re) {
2059
+ var a = re.exec(c);
2060
+ if (a) {
2061
+ index.push(i + length);
2062
+ length += a[0].length;
2063
+ c = c.slice(a[1].length);
2064
+ return name.push(a[1]);
2065
+ }
2066
+ }
2067
+
2068
+ match(/^(\*?)/);
2069
+ while (match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)); // !
2070
+ if ((name.length > 1) && match(/^\s*((?:\+_|\+)?)\s*:/)) {
2071
+ // at last, we have the complete match now. move forward,
2072
+ // convert name particles to tree objects and return:
2073
+ skipWhitespace(length);
2074
+ if (name[0] === '') {
2075
+ name.shift();
2076
+ index.shift();
2077
+ }
2078
+ for (k = 0; k < name.length; k++) {
2079
+ s = name[k];
2080
+ name[k] = (s.charAt(0) !== '@')
2081
+ ? new(tree.Keyword)(s)
2082
+ : new(tree.Variable)('@' + s.slice(2, -1),
2083
+ index[k], env.currentFileInfo);
2084
+ }
2085
+ return name;
2086
+ }
2087
+ }
2088
+ }
2089
+ };
2090
+ return parser;
2091
+ };
2092
+ less.Parser.serializeVars = function(vars) {
2093
+ var s = '';
2094
+
2095
+ for (var name in vars) {
2096
+ if (Object.hasOwnProperty.call(vars, name)) {
2097
+ var value = vars[name];
2098
+ s += ((name[0] === '@') ? '' : '@') + name +': '+ value +
2099
+ ((('' + value).slice(-1) === ';') ? '' : ';');
2100
+ }
2101
+ }
2102
+
2103
+ return s;
2104
+ };
2105
+
2106
+ (function (tree) {
2107
+
2108
+ tree.functions = {
2109
+ rgb: function (r, g, b) {
2110
+ return this.rgba(r, g, b, 1.0);
2111
+ },
2112
+ rgba: function (r, g, b, a) {
2113
+ var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
2114
+ a = number(a);
2115
+ return new(tree.Color)(rgb, a);
2116
+ },
2117
+ hsl: function (h, s, l) {
2118
+ return this.hsla(h, s, l, 1.0);
2119
+ },
2120
+ hsla: function (h, s, l, a) {
2121
+ function hue(h) {
2122
+ h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
2123
+ if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
2124
+ else if (h * 2 < 1) { return m2; }
2125
+ else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
2126
+ else { return m1; }
2127
+ }
2128
+
2129
+ h = (number(h) % 360) / 360;
2130
+ s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
2131
+
2132
+ var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
2133
+ var m1 = l * 2 - m2;
2134
+
2135
+ return this.rgba(hue(h + 1/3) * 255,
2136
+ hue(h) * 255,
2137
+ hue(h - 1/3) * 255,
2138
+ a);
2139
+ },
2140
+
2141
+ hsv: function(h, s, v) {
2142
+ return this.hsva(h, s, v, 1.0);
2143
+ },
2144
+
2145
+ hsva: function(h, s, v, a) {
2146
+ h = ((number(h) % 360) / 360) * 360;
2147
+ s = number(s); v = number(v); a = number(a);
2148
+
2149
+ var i, f;
2150
+ i = Math.floor((h / 60) % 6);
2151
+ f = (h / 60) - i;
2152
+
2153
+ var vs = [v,
2154
+ v * (1 - s),
2155
+ v * (1 - f * s),
2156
+ v * (1 - (1 - f) * s)];
2157
+ var perm = [[0, 3, 1],
2158
+ [2, 0, 1],
2159
+ [1, 0, 3],
2160
+ [1, 2, 0],
2161
+ [3, 1, 0],
2162
+ [0, 1, 2]];
2163
+
2164
+ return this.rgba(vs[perm[i][0]] * 255,
2165
+ vs[perm[i][1]] * 255,
2166
+ vs[perm[i][2]] * 255,
2167
+ a);
2168
+ },
2169
+
2170
+ hue: function (color) {
2171
+ return new(tree.Dimension)(color.toHSL().h);
2172
+ },
2173
+ saturation: function (color) {
2174
+ return new(tree.Dimension)(color.toHSL().s * 100, '%');
2175
+ },
2176
+ lightness: function (color) {
2177
+ return new(tree.Dimension)(color.toHSL().l * 100, '%');
2178
+ },
2179
+ hsvhue: function(color) {
2180
+ return new(tree.Dimension)(color.toHSV().h);
2181
+ },
2182
+ hsvsaturation: function (color) {
2183
+ return new(tree.Dimension)(color.toHSV().s * 100, '%');
2184
+ },
2185
+ hsvvalue: function (color) {
2186
+ return new(tree.Dimension)(color.toHSV().v * 100, '%');
2187
+ },
2188
+ red: function (color) {
2189
+ return new(tree.Dimension)(color.rgb[0]);
2190
+ },
2191
+ green: function (color) {
2192
+ return new(tree.Dimension)(color.rgb[1]);
2193
+ },
2194
+ blue: function (color) {
2195
+ return new(tree.Dimension)(color.rgb[2]);
2196
+ },
2197
+ alpha: function (color) {
2198
+ return new(tree.Dimension)(color.toHSL().a);
2199
+ },
2200
+ luma: function (color) {
2201
+ return new(tree.Dimension)(color.luma() * color.alpha * 100, '%');
2202
+ },
2203
+ luminance: function (color) {
2204
+ var luminance =
2205
+ (0.2126 * color.rgb[0] / 255)
2206
+ + (0.7152 * color.rgb[1] / 255)
2207
+ + (0.0722 * color.rgb[2] / 255);
2208
+
2209
+ return new(tree.Dimension)(luminance * color.alpha * 100, '%');
2210
+ },
2211
+ saturate: function (color, amount) {
2212
+ // filter: saturate(3.2);
2213
+ // should be kept as is, so check for color
2214
+ if (!color.rgb) {
2215
+ return null;
2216
+ }
2217
+ var hsl = color.toHSL();
2218
+
2219
+ hsl.s += amount.value / 100;
2220
+ hsl.s = clamp(hsl.s);
2221
+ return hsla(hsl);
2222
+ },
2223
+ desaturate: function (color, amount) {
2224
+ var hsl = color.toHSL();
2225
+
2226
+ hsl.s -= amount.value / 100;
2227
+ hsl.s = clamp(hsl.s);
2228
+ return hsla(hsl);
2229
+ },
2230
+ lighten: function (color, amount) {
2231
+ var hsl = color.toHSL();
2232
+
2233
+ hsl.l += amount.value / 100;
2234
+ hsl.l = clamp(hsl.l);
2235
+ return hsla(hsl);
2236
+ },
2237
+ darken: function (color, amount) {
2238
+ var hsl = color.toHSL();
2239
+
2240
+ hsl.l -= amount.value / 100;
2241
+ hsl.l = clamp(hsl.l);
2242
+ return hsla(hsl);
2243
+ },
2244
+ fadein: function (color, amount) {
2245
+ var hsl = color.toHSL();
2246
+
2247
+ hsl.a += amount.value / 100;
2248
+ hsl.a = clamp(hsl.a);
2249
+ return hsla(hsl);
2250
+ },
2251
+ fadeout: function (color, amount) {
2252
+ var hsl = color.toHSL();
2253
+
2254
+ hsl.a -= amount.value / 100;
2255
+ hsl.a = clamp(hsl.a);
2256
+ return hsla(hsl);
2257
+ },
2258
+ fade: function (color, amount) {
2259
+ var hsl = color.toHSL();
2260
+
2261
+ hsl.a = amount.value / 100;
2262
+ hsl.a = clamp(hsl.a);
2263
+ return hsla(hsl);
2264
+ },
2265
+ spin: function (color, amount) {
2266
+ var hsl = color.toHSL();
2267
+ var hue = (hsl.h + amount.value) % 360;
2268
+
2269
+ hsl.h = hue < 0 ? 360 + hue : hue;
2270
+
2271
+ return hsla(hsl);
2272
+ },
2273
+ //
2274
+ // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
2275
+ // http://sass-lang.com
2276
+ //
2277
+ mix: function (color1, color2, weight) {
2278
+ if (!weight) {
2279
+ weight = new(tree.Dimension)(50);
2280
+ }
2281
+ var p = weight.value / 100.0;
2282
+ var w = p * 2 - 1;
2283
+ var a = color1.toHSL().a - color2.toHSL().a;
2284
+
2285
+ var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
2286
+ var w2 = 1 - w1;
2287
+
2288
+ var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2,
2289
+ color1.rgb[1] * w1 + color2.rgb[1] * w2,
2290
+ color1.rgb[2] * w1 + color2.rgb[2] * w2];
2291
+
2292
+ var alpha = color1.alpha * p + color2.alpha * (1 - p);
2293
+
2294
+ return new(tree.Color)(rgb, alpha);
2295
+ },
2296
+ greyscale: function (color) {
2297
+ return this.desaturate(color, new(tree.Dimension)(100));
2298
+ },
2299
+ contrast: function (color, dark, light, threshold) {
2300
+ // filter: contrast(3.2);
2301
+ // should be kept as is, so check for color
2302
+ if (!color.rgb) {
2303
+ return null;
2304
+ }
2305
+ if (typeof light === 'undefined') {
2306
+ light = this.rgba(255, 255, 255, 1.0);
2307
+ }
2308
+ if (typeof dark === 'undefined') {
2309
+ dark = this.rgba(0, 0, 0, 1.0);
2310
+ }
2311
+ //Figure out which is actually light and dark!
2312
+ if (dark.luma() > light.luma()) {
2313
+ var t = light;
2314
+ light = dark;
2315
+ dark = t;
2316
+ }
2317
+ if (typeof threshold === 'undefined') {
2318
+ threshold = 0.43;
2319
+ } else {
2320
+ threshold = number(threshold);
2321
+ }
2322
+ if (color.luma() < threshold) {
2323
+ return light;
2324
+ } else {
2325
+ return dark;
2326
+ }
2327
+ },
2328
+ e: function (str) {
2329
+ return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str.value);
2330
+ },
2331
+ escape: function (str) {
2332
+ return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29"));
2333
+ },
2334
+ replace: function (string, pattern, replacement, flags) {
2335
+ var result = string.value;
2336
+
2337
+ result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement.value);
2338
+ return new(tree.Quoted)(string.quote || '', result, string.escaped);
2339
+ },
2340
+ '%': function (string /* arg, arg, ...*/) {
2341
+ var args = Array.prototype.slice.call(arguments, 1),
2342
+ result = string.value;
2343
+
2344
+ for (var i = 0; i < args.length; i++) {
2345
+ /*jshint loopfunc:true */
2346
+ result = result.replace(/%[sda]/i, function(token) {
2347
+ var value = token.match(/s/i) ? args[i].value : args[i].toCSS();
2348
+ return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value;
2349
+ });
2350
+ }
2351
+ result = result.replace(/%%/g, '%');
2352
+ return new(tree.Quoted)(string.quote || '', result, string.escaped);
2353
+ },
2354
+ unit: function (val, unit) {
2355
+ if(!(val instanceof tree.Dimension)) {
2356
+ throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") };
2357
+ }
2358
+ if (unit) {
2359
+ if (unit instanceof tree.Keyword) {
2360
+ unit = unit.value;
2361
+ } else {
2362
+ unit = unit.toCSS();
2363
+ }
2364
+ } else {
2365
+ unit = "";
2366
+ }
2367
+ return new(tree.Dimension)(val.value, unit);
2368
+ },
2369
+ convert: function (val, unit) {
2370
+ return val.convertTo(unit.value);
2371
+ },
2372
+ round: function (n, f) {
2373
+ var fraction = typeof(f) === "undefined" ? 0 : f.value;
2374
+ return _math(function(num) { return num.toFixed(fraction); }, null, n);
2375
+ },
2376
+ pi: function () {
2377
+ return new(tree.Dimension)(Math.PI);
2378
+ },
2379
+ mod: function(a, b) {
2380
+ return new(tree.Dimension)(a.value % b.value, a.unit);
2381
+ },
2382
+ pow: function(x, y) {
2383
+ if (typeof x === "number" && typeof y === "number") {
2384
+ x = new(tree.Dimension)(x);
2385
+ y = new(tree.Dimension)(y);
2386
+ } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) {
2387
+ throw { type: "Argument", message: "arguments must be numbers" };
2388
+ }
2389
+
2390
+ return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit);
2391
+ },
2392
+ _minmax: function (isMin, args) {
2393
+ args = Array.prototype.slice.call(args);
2394
+ switch(args.length) {
2395
+ case 0: throw { type: "Argument", message: "one or more arguments required" };
2396
+ }
2397
+ var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone,
2398
+ order = [], // elems only contains original argument values.
2399
+ values = {}; // key is the unit.toString() for unified tree.Dimension values,
2400
+ // value is the index into the order array.
2401
+ for (i = 0; i < args.length; i++) {
2402
+ current = args[i];
2403
+ if (!(current instanceof tree.Dimension)) {
2404
+ if(Array.isArray(args[i].value)) {
2405
+ Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value));
2406
+ }
2407
+ continue;
2408
+ }
2409
+ currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new(tree.Dimension)(current.value, unitClone).unify() : current.unify();
2410
+ unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString();
2411
+ unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic;
2412
+ unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone;
2413
+ j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit];
2414
+ if (j === undefined) {
2415
+ if(unitStatic !== undefined && unit !== unitStatic) {
2416
+ throw{ type: "Argument", message: "incompatible types" };
2417
+ }
2418
+ values[unit] = order.length;
2419
+ order.push(current);
2420
+ continue;
2421
+ }
2422
+ referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new(tree.Dimension)(order[j].value, unitClone).unify() : order[j].unify();
2423
+ if ( isMin && currentUnified.value < referenceUnified.value ||
2424
+ !isMin && currentUnified.value > referenceUnified.value) {
2425
+ order[j] = current;
2426
+ }
2427
+ }
2428
+ if (order.length == 1) {
2429
+ return order[0];
2430
+ }
2431
+ args = order.map(function (a) { return a.toCSS(this.env); }).join(this.env.compress ? "," : ", ");
2432
+ return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")");
2433
+ },
2434
+ min: function () {
2435
+ return this._minmax(true, arguments);
2436
+ },
2437
+ max: function () {
2438
+ return this._minmax(false, arguments);
2439
+ },
2440
+ "get-unit": function (n) {
2441
+ return new(tree.Anonymous)(n.unit);
2442
+ },
2443
+ argb: function (color) {
2444
+ return new(tree.Anonymous)(color.toARGB());
2445
+ },
2446
+ percentage: function (n) {
2447
+ return new(tree.Dimension)(n.value * 100, '%');
2448
+ },
2449
+ color: function (n) {
2450
+ if (n instanceof tree.Quoted) {
2451
+ var colorCandidate = n.value,
2452
+ returnColor;
2453
+ returnColor = tree.Color.fromKeyword(colorCandidate);
2454
+ if (returnColor) {
2455
+ return returnColor;
2456
+ }
2457
+ if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) {
2458
+ return new(tree.Color)(colorCandidate.slice(1));
2459
+ }
2460
+ throw { type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" };
2461
+ } else {
2462
+ throw { type: "Argument", message: "argument must be a string" };
2463
+ }
2464
+ },
2465
+ iscolor: function (n) {
2466
+ return this._isa(n, tree.Color);
2467
+ },
2468
+ isnumber: function (n) {
2469
+ return this._isa(n, tree.Dimension);
2470
+ },
2471
+ isstring: function (n) {
2472
+ return this._isa(n, tree.Quoted);
2473
+ },
2474
+ iskeyword: function (n) {
2475
+ return this._isa(n, tree.Keyword);
2476
+ },
2477
+ isurl: function (n) {
2478
+ return this._isa(n, tree.URL);
2479
+ },
2480
+ ispixel: function (n) {
2481
+ return this.isunit(n, 'px');
2482
+ },
2483
+ ispercentage: function (n) {
2484
+ return this.isunit(n, '%');
2485
+ },
2486
+ isem: function (n) {
2487
+ return this.isunit(n, 'em');
2488
+ },
2489
+ isunit: function (n, unit) {
2490
+ return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False;
2491
+ },
2492
+ _isa: function (n, Type) {
2493
+ return (n instanceof Type) ? tree.True : tree.False;
2494
+ },
2495
+ tint: function(color, amount) {
2496
+ return this.mix(this.rgb(255,255,255), color, amount);
2497
+ },
2498
+ shade: function(color, amount) {
2499
+ return this.mix(this.rgb(0, 0, 0), color, amount);
2500
+ },
2501
+ extract: function(values, index) {
2502
+ index = index.value - 1; // (1-based index)
2503
+ // handle non-array values as an array of length 1
2504
+ // return 'undefined' if index is invalid
2505
+ return Array.isArray(values.value)
2506
+ ? values.value[index] : Array(values)[index];
2507
+ },
2508
+ length: function(values) {
2509
+ var n = Array.isArray(values.value) ? values.value.length : 1;
2510
+ return new tree.Dimension(n);
2511
+ },
2512
+
2513
+ "data-uri": function(mimetypeNode, filePathNode) {
2514
+
2515
+ if (typeof window !== 'undefined') {
2516
+ return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env);
2517
+ }
2518
+
2519
+ var mimetype = mimetypeNode.value;
2520
+ var filePath = (filePathNode && filePathNode.value);
2521
+
2522
+ var fs = require('./fs'),
2523
+ path = require('path'),
2524
+ useBase64 = false;
2525
+
2526
+ if (arguments.length < 2) {
2527
+ filePath = mimetype;
2528
+ }
2529
+
2530
+ if (this.env.isPathRelative(filePath)) {
2531
+ if (this.currentFileInfo.relativeUrls) {
2532
+ filePath = path.join(this.currentFileInfo.currentDirectory, filePath);
2533
+ } else {
2534
+ filePath = path.join(this.currentFileInfo.entryPath, filePath);
2535
+ }
2536
+ }
2537
+
2538
+ // detect the mimetype if not given
2539
+ if (arguments.length < 2) {
2540
+ var mime;
2541
+ try {
2542
+ mime = require('mime');
2543
+ } catch (ex) {
2544
+ mime = tree._mime;
2545
+ }
2546
+
2547
+ mimetype = mime.lookup(filePath);
2548
+
2549
+ // use base 64 unless it's an ASCII or UTF-8 format
2550
+ var charset = mime.charsets.lookup(mimetype);
2551
+ useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
2552
+ if (useBase64) { mimetype += ';base64'; }
2553
+ }
2554
+ else {
2555
+ useBase64 = /;base64$/.test(mimetype);
2556
+ }
2557
+
2558
+ var buf = fs.readFileSync(filePath);
2559
+
2560
+ // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
2561
+ // and the --ieCompat flag is enabled, return a normal url() instead.
2562
+ var DATA_URI_MAX_KB = 32,
2563
+ fileSizeInKB = parseInt((buf.length / 1024), 10);
2564
+ if (fileSizeInKB >= DATA_URI_MAX_KB) {
2565
+
2566
+ if (this.env.ieCompat !== false) {
2567
+ if (!this.env.silent) {
2568
+ console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB);
2569
+ }
2570
+
2571
+ return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env);
2572
+ }
2573
+ }
2574
+
2575
+ buf = useBase64 ? buf.toString('base64')
2576
+ : encodeURIComponent(buf);
2577
+
2578
+ var uri = "\"data:" + mimetype + ',' + buf + "\"";
2579
+ return new(tree.URL)(new(tree.Anonymous)(uri));
2580
+ },
2581
+
2582
+ "svg-gradient": function(direction) {
2583
+
2584
+ function throwArgumentDescriptor() {
2585
+ throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" };
2586
+ }
2587
+
2588
+ if (arguments.length < 3) {
2589
+ throwArgumentDescriptor();
2590
+ }
2591
+ var stops = Array.prototype.slice.call(arguments, 1),
2592
+ gradientDirectionSvg,
2593
+ gradientType = "linear",
2594
+ rectangleDimension = 'x="0" y="0" width="1" height="1"',
2595
+ useBase64 = true,
2596
+ renderEnv = {compress: false},
2597
+ returner,
2598
+ directionValue = direction.toCSS(renderEnv),
2599
+ i, color, position, positionValue, alpha;
2600
+
2601
+ switch (directionValue) {
2602
+ case "to bottom":
2603
+ gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"';
2604
+ break;
2605
+ case "to right":
2606
+ gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"';
2607
+ break;
2608
+ case "to bottom right":
2609
+ gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"';
2610
+ break;
2611
+ case "to top right":
2612
+ gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"';
2613
+ break;
2614
+ case "ellipse":
2615
+ case "ellipse at center":
2616
+ gradientType = "radial";
2617
+ gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"';
2618
+ rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
2619
+ break;
2620
+ default:
2621
+ throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" };
2622
+ }
2623
+ returner = '<?xml version="1.0" ?>' +
2624
+ '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
2625
+ '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
2626
+
2627
+ for (i = 0; i < stops.length; i+= 1) {
2628
+ if (stops[i].value) {
2629
+ color = stops[i].value[0];
2630
+ position = stops[i].value[1];
2631
+ } else {
2632
+ color = stops[i];
2633
+ position = undefined;
2634
+ }
2635
+
2636
+ if (!(color instanceof tree.Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) {
2637
+ throwArgumentDescriptor();
2638
+ }
2639
+ positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
2640
+ alpha = color.alpha;
2641
+ returner += '<stop offset="' + positionValue + '" stop-color="' + color.toRGB() + '"' + (alpha < 1 ? ' stop-opacity="' + alpha + '"' : '') + '/>';
2642
+ }
2643
+ returner += '</' + gradientType + 'Gradient>' +
2644
+ '<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
2645
+
2646
+ if (useBase64) {
2647
+ try {
2648
+ returner = require('./encoder').encodeBase64(returner); // TODO browser implementation
2649
+ } catch(e) {
2650
+ useBase64 = false;
2651
+ }
2652
+ }
2653
+
2654
+ returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'";
2655
+ return new(tree.URL)(new(tree.Anonymous)(returner));
2656
+ }
2657
+ };
2658
+
2659
+ // these static methods are used as a fallback when the optional 'mime' dependency is missing
2660
+ tree._mime = {
2661
+ // this map is intentionally incomplete
2662
+ // if you want more, install 'mime' dep
2663
+ _types: {
2664
+ '.htm' : 'text/html',
2665
+ '.html': 'text/html',
2666
+ '.gif' : 'image/gif',
2667
+ '.jpg' : 'image/jpeg',
2668
+ '.jpeg': 'image/jpeg',
2669
+ '.png' : 'image/png'
2670
+ },
2671
+ lookup: function (filepath) {
2672
+ var ext = require('path').extname(filepath),
2673
+ type = tree._mime._types[ext];
2674
+ if (type === undefined) {
2675
+ throw new Error('Optional dependency "mime" is required for ' + ext);
2676
+ }
2677
+ return type;
2678
+ },
2679
+ charsets: {
2680
+ lookup: function (type) {
2681
+ // assumes all text types are UTF-8
2682
+ return type && (/^text\//).test(type) ? 'UTF-8' : '';
2683
+ }
2684
+ }
2685
+ };
2686
+
2687
+ // Math
2688
+
2689
+ var mathFunctions = {
2690
+ // name, unit
2691
+ ceil: null,
2692
+ floor: null,
2693
+ sqrt: null,
2694
+ abs: null,
2695
+ tan: "",
2696
+ sin: "",
2697
+ cos: "",
2698
+ atan: "rad",
2699
+ asin: "rad",
2700
+ acos: "rad"
2701
+ };
2702
+
2703
+ function _math(fn, unit, n) {
2704
+ if (!(n instanceof tree.Dimension)) {
2705
+ throw { type: "Argument", message: "argument must be a number" };
2706
+ }
2707
+ if (unit == null) {
2708
+ unit = n.unit;
2709
+ } else {
2710
+ n = n.unify();
2711
+ }
2712
+ return new(tree.Dimension)(fn(parseFloat(n.value)), unit);
2713
+ }
2714
+
2715
+ // ~ End of Math
2716
+
2717
+ // Color Blending
2718
+ // ref: http://www.w3.org/TR/compositing-1
2719
+
2720
+ function colorBlend(mode, color1, color2) {
2721
+ var ab = color1.alpha, cb, // backdrop
2722
+ as = color2.alpha, cs, // source
2723
+ ar, cr, r = []; // result
2724
+
2725
+ ar = as + ab * (1 - as);
2726
+ for (var i = 0; i < 3; i++) {
2727
+ cb = color1.rgb[i] / 255;
2728
+ cs = color2.rgb[i] / 255;
2729
+ cr = mode(cb, cs);
2730
+ if (ar) {
2731
+ cr = (as * cs + ab * (cb
2732
+ - as * (cb + cs - cr))) / ar;
2733
+ }
2734
+ r[i] = cr * 255;
2735
+ }
2736
+
2737
+ return new(tree.Color)(r, ar);
2738
+ }
2739
+
2740
+ var colorBlendMode = {
2741
+ multiply: function(cb, cs) {
2742
+ return cb * cs;
2743
+ },
2744
+ screen: function(cb, cs) {
2745
+ return cb + cs - cb * cs;
2746
+ },
2747
+ overlay: function(cb, cs) {
2748
+ cb *= 2;
2749
+ return (cb <= 1)
2750
+ ? colorBlendMode.multiply(cb, cs)
2751
+ : colorBlendMode.screen(cb - 1, cs);
2752
+ },
2753
+ softlight: function(cb, cs) {
2754
+ var d = 1, e = cb;
2755
+ if (cs > 0.5) {
2756
+ e = 1;
2757
+ d = (cb > 0.25) ? Math.sqrt(cb)
2758
+ : ((16 * cb - 12) * cb + 4) * cb;
2759
+ }
2760
+ return cb - (1 - 2 * cs) * e * (d - cb);
2761
+ },
2762
+ hardlight: function(cb, cs) {
2763
+ return colorBlendMode.overlay(cs, cb);
2764
+ },
2765
+ difference: function(cb, cs) {
2766
+ return Math.abs(cb - cs);
2767
+ },
2768
+ exclusion: function(cb, cs) {
2769
+ return cb + cs - 2 * cb * cs;
2770
+ },
2771
+
2772
+ // non-w3c functions:
2773
+ average: function(cb, cs) {
2774
+ return (cb + cs) / 2;
2775
+ },
2776
+ negation: function(cb, cs) {
2777
+ return 1 - Math.abs(cb + cs - 1);
2778
+ }
2779
+ };
2780
+
2781
+ // ~ End of Color Blending
2782
+
2783
+ tree.defaultFunc = {
2784
+ eval: function () {
2785
+ var v = this.value_, e = this.error_;
2786
+ if (e) {
2787
+ throw e;
2788
+ }
2789
+ if (v != null) {
2790
+ return v ? tree.True : tree.False;
2791
+ }
2792
+ },
2793
+ value: function (v) {
2794
+ this.value_ = v;
2795
+ },
2796
+ error: function (e) {
2797
+ this.error_ = e;
2798
+ },
2799
+ reset: function () {
2800
+ this.value_ = this.error_ = null;
2801
+ }
2802
+ };
2803
+
2804
+ function initFunctions() {
2805
+ var f, tf = tree.functions;
2806
+
2807
+ // math
2808
+ for (f in mathFunctions) {
2809
+ if (mathFunctions.hasOwnProperty(f)) {
2810
+ tf[f] = _math.bind(null, Math[f], mathFunctions[f]);
2811
+ }
2812
+ }
2813
+
2814
+ // color blending
2815
+ for (f in colorBlendMode) {
2816
+ if (colorBlendMode.hasOwnProperty(f)) {
2817
+ tf[f] = colorBlend.bind(null, colorBlendMode[f]);
2818
+ }
2819
+ }
2820
+
2821
+ // default
2822
+ f = tree.defaultFunc;
2823
+ tf["default"] = f.eval.bind(f);
2824
+
2825
+ } initFunctions();
2826
+
2827
+ function hsla(color) {
2828
+ return tree.functions.hsla(color.h, color.s, color.l, color.a);
2829
+ }
2830
+
2831
+ function scaled(n, size) {
2832
+ if (n instanceof tree.Dimension && n.unit.is('%')) {
2833
+ return parseFloat(n.value * size / 100);
2834
+ } else {
2835
+ return number(n);
2836
+ }
2837
+ }
2838
+
2839
+ function number(n) {
2840
+ if (n instanceof tree.Dimension) {
2841
+ return parseFloat(n.unit.is('%') ? n.value / 100 : n.value);
2842
+ } else if (typeof(n) === 'number') {
2843
+ return n;
2844
+ } else {
2845
+ throw {
2846
+ error: "RuntimeError",
2847
+ message: "color functions take numbers as parameters"
2848
+ };
2849
+ }
2850
+ }
2851
+
2852
+ function clamp(val) {
2853
+ return Math.min(1, Math.max(0, val));
2854
+ }
2855
+
2856
+ tree.fround = function(env, value) {
2857
+ var p = env && env.numPrecision;
2858
+ //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
2859
+ return (p == null) ? value : Number((value + 2e-16).toFixed(p));
2860
+ };
2861
+
2862
+ tree.functionCall = function(env, currentFileInfo) {
2863
+ this.env = env;
2864
+ this.currentFileInfo = currentFileInfo;
2865
+ };
2866
+
2867
+ tree.functionCall.prototype = tree.functions;
2868
+
2869
+ })(require('./tree'));
2870
+
2871
+ (function (tree) {
2872
+ tree.colors = {
2873
+ 'aliceblue':'#f0f8ff',
2874
+ 'antiquewhite':'#faebd7',
2875
+ 'aqua':'#00ffff',
2876
+ 'aquamarine':'#7fffd4',
2877
+ 'azure':'#f0ffff',
2878
+ 'beige':'#f5f5dc',
2879
+ 'bisque':'#ffe4c4',
2880
+ 'black':'#000000',
2881
+ 'blanchedalmond':'#ffebcd',
2882
+ 'blue':'#0000ff',
2883
+ 'blueviolet':'#8a2be2',
2884
+ 'brown':'#a52a2a',
2885
+ 'burlywood':'#deb887',
2886
+ 'cadetblue':'#5f9ea0',
2887
+ 'chartreuse':'#7fff00',
2888
+ 'chocolate':'#d2691e',
2889
+ 'coral':'#ff7f50',
2890
+ 'cornflowerblue':'#6495ed',
2891
+ 'cornsilk':'#fff8dc',
2892
+ 'crimson':'#dc143c',
2893
+ 'cyan':'#00ffff',
2894
+ 'darkblue':'#00008b',
2895
+ 'darkcyan':'#008b8b',
2896
+ 'darkgoldenrod':'#b8860b',
2897
+ 'darkgray':'#a9a9a9',
2898
+ 'darkgrey':'#a9a9a9',
2899
+ 'darkgreen':'#006400',
2900
+ 'darkkhaki':'#bdb76b',
2901
+ 'darkmagenta':'#8b008b',
2902
+ 'darkolivegreen':'#556b2f',
2903
+ 'darkorange':'#ff8c00',
2904
+ 'darkorchid':'#9932cc',
2905
+ 'darkred':'#8b0000',
2906
+ 'darksalmon':'#e9967a',
2907
+ 'darkseagreen':'#8fbc8f',
2908
+ 'darkslateblue':'#483d8b',
2909
+ 'darkslategray':'#2f4f4f',
2910
+ 'darkslategrey':'#2f4f4f',
2911
+ 'darkturquoise':'#00ced1',
2912
+ 'darkviolet':'#9400d3',
2913
+ 'deeppink':'#ff1493',
2914
+ 'deepskyblue':'#00bfff',
2915
+ 'dimgray':'#696969',
2916
+ 'dimgrey':'#696969',
2917
+ 'dodgerblue':'#1e90ff',
2918
+ 'firebrick':'#b22222',
2919
+ 'floralwhite':'#fffaf0',
2920
+ 'forestgreen':'#228b22',
2921
+ 'fuchsia':'#ff00ff',
2922
+ 'gainsboro':'#dcdcdc',
2923
+ 'ghostwhite':'#f8f8ff',
2924
+ 'gold':'#ffd700',
2925
+ 'goldenrod':'#daa520',
2926
+ 'gray':'#808080',
2927
+ 'grey':'#808080',
2928
+ 'green':'#008000',
2929
+ 'greenyellow':'#adff2f',
2930
+ 'honeydew':'#f0fff0',
2931
+ 'hotpink':'#ff69b4',
2932
+ 'indianred':'#cd5c5c',
2933
+ 'indigo':'#4b0082',
2934
+ 'ivory':'#fffff0',
2935
+ 'khaki':'#f0e68c',
2936
+ 'lavender':'#e6e6fa',
2937
+ 'lavenderblush':'#fff0f5',
2938
+ 'lawngreen':'#7cfc00',
2939
+ 'lemonchiffon':'#fffacd',
2940
+ 'lightblue':'#add8e6',
2941
+ 'lightcoral':'#f08080',
2942
+ 'lightcyan':'#e0ffff',
2943
+ 'lightgoldenrodyellow':'#fafad2',
2944
+ 'lightgray':'#d3d3d3',
2945
+ 'lightgrey':'#d3d3d3',
2946
+ 'lightgreen':'#90ee90',
2947
+ 'lightpink':'#ffb6c1',
2948
+ 'lightsalmon':'#ffa07a',
2949
+ 'lightseagreen':'#20b2aa',
2950
+ 'lightskyblue':'#87cefa',
2951
+ 'lightslategray':'#778899',
2952
+ 'lightslategrey':'#778899',
2953
+ 'lightsteelblue':'#b0c4de',
2954
+ 'lightyellow':'#ffffe0',
2955
+ 'lime':'#00ff00',
2956
+ 'limegreen':'#32cd32',
2957
+ 'linen':'#faf0e6',
2958
+ 'magenta':'#ff00ff',
2959
+ 'maroon':'#800000',
2960
+ 'mediumaquamarine':'#66cdaa',
2961
+ 'mediumblue':'#0000cd',
2962
+ 'mediumorchid':'#ba55d3',
2963
+ 'mediumpurple':'#9370d8',
2964
+ 'mediumseagreen':'#3cb371',
2965
+ 'mediumslateblue':'#7b68ee',
2966
+ 'mediumspringgreen':'#00fa9a',
2967
+ 'mediumturquoise':'#48d1cc',
2968
+ 'mediumvioletred':'#c71585',
2969
+ 'midnightblue':'#191970',
2970
+ 'mintcream':'#f5fffa',
2971
+ 'mistyrose':'#ffe4e1',
2972
+ 'moccasin':'#ffe4b5',
2973
+ 'navajowhite':'#ffdead',
2974
+ 'navy':'#000080',
2975
+ 'oldlace':'#fdf5e6',
2976
+ 'olive':'#808000',
2977
+ 'olivedrab':'#6b8e23',
2978
+ 'orange':'#ffa500',
2979
+ 'orangered':'#ff4500',
2980
+ 'orchid':'#da70d6',
2981
+ 'palegoldenrod':'#eee8aa',
2982
+ 'palegreen':'#98fb98',
2983
+ 'paleturquoise':'#afeeee',
2984
+ 'palevioletred':'#d87093',
2985
+ 'papayawhip':'#ffefd5',
2986
+ 'peachpuff':'#ffdab9',
2987
+ 'peru':'#cd853f',
2988
+ 'pink':'#ffc0cb',
2989
+ 'plum':'#dda0dd',
2990
+ 'powderblue':'#b0e0e6',
2991
+ 'purple':'#800080',
2992
+ 'red':'#ff0000',
2993
+ 'rosybrown':'#bc8f8f',
2994
+ 'royalblue':'#4169e1',
2995
+ 'saddlebrown':'#8b4513',
2996
+ 'salmon':'#fa8072',
2997
+ 'sandybrown':'#f4a460',
2998
+ 'seagreen':'#2e8b57',
2999
+ 'seashell':'#fff5ee',
3000
+ 'sienna':'#a0522d',
3001
+ 'silver':'#c0c0c0',
3002
+ 'skyblue':'#87ceeb',
3003
+ 'slateblue':'#6a5acd',
3004
+ 'slategray':'#708090',
3005
+ 'slategrey':'#708090',
3006
+ 'snow':'#fffafa',
3007
+ 'springgreen':'#00ff7f',
3008
+ 'steelblue':'#4682b4',
3009
+ 'tan':'#d2b48c',
3010
+ 'teal':'#008080',
3011
+ 'thistle':'#d8bfd8',
3012
+ 'tomato':'#ff6347',
3013
+ 'turquoise':'#40e0d0',
3014
+ 'violet':'#ee82ee',
3015
+ 'wheat':'#f5deb3',
3016
+ 'white':'#ffffff',
3017
+ 'whitesmoke':'#f5f5f5',
3018
+ 'yellow':'#ffff00',
3019
+ 'yellowgreen':'#9acd32'
3020
+ };
3021
+ })(require('./tree'));
3022
+
3023
+ (function (tree) {
3024
+
3025
+ tree.debugInfo = function(env, ctx, lineSeperator) {
3026
+ var result="";
3027
+ if (env.dumpLineNumbers && !env.compress) {
3028
+ switch(env.dumpLineNumbers) {
3029
+ case 'comments':
3030
+ result = tree.debugInfo.asComment(ctx);
3031
+ break;
3032
+ case 'mediaquery':
3033
+ result = tree.debugInfo.asMediaQuery(ctx);
3034
+ break;
3035
+ case 'all':
3036
+ result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx);
3037
+ break;
3038
+ }
3039
+ }
3040
+ return result;
3041
+ };
3042
+
3043
+ tree.debugInfo.asComment = function(ctx) {
3044
+ return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n';
3045
+ };
3046
+
3047
+ tree.debugInfo.asMediaQuery = function(ctx) {
3048
+ return '@media -sass-debug-info{filename{font-family:' +
3049
+ ('file://' + ctx.debugInfo.fileName).replace(/([.:\/\\])/g, function (a) {
3050
+ if (a == '\\') {
3051
+ a = '\/';
3052
+ }
3053
+ return '\\' + a;
3054
+ }) +
3055
+ '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n';
3056
+ };
3057
+
3058
+ tree.find = function (obj, fun) {
3059
+ for (var i = 0, r; i < obj.length; i++) {
3060
+ r = fun.call(obj, obj[i]);
3061
+ if (r) { return r; }
3062
+ }
3063
+ return null;
3064
+ };
3065
+
3066
+ tree.jsify = function (obj) {
3067
+ if (Array.isArray(obj.value) && (obj.value.length > 1)) {
3068
+ return '[' + obj.value.map(function (v) { return v.toCSS(); }).join(', ') + ']';
3069
+ } else {
3070
+ return obj.toCSS();
3071
+ }
3072
+ };
3073
+
3074
+ tree.toCSS = function (env) {
3075
+ var strs = [];
3076
+ this.genCSS(env, {
3077
+ add: function(chunk, fileInfo, index) {
3078
+ strs.push(chunk);
3079
+ },
3080
+ isEmpty: function () {
3081
+ return strs.length === 0;
3082
+ }
3083
+ });
3084
+ return strs.join('');
3085
+ };
3086
+
3087
+ tree.outputRuleset = function (env, output, rules) {
3088
+ var ruleCnt = rules.length, i;
3089
+ env.tabLevel = (env.tabLevel | 0) + 1;
3090
+
3091
+ // Compressed
3092
+ if (env.compress) {
3093
+ output.add('{');
3094
+ for (i = 0; i < ruleCnt; i++) {
3095
+ rules[i].genCSS(env, output);
3096
+ }
3097
+ output.add('}');
3098
+ env.tabLevel--;
3099
+ return;
3100
+ }
3101
+
3102
+ // Non-compressed
3103
+ var tabSetStr = '\n' + Array(env.tabLevel).join(" "), tabRuleStr = tabSetStr + " ";
3104
+ if (!ruleCnt) {
3105
+ output.add(" {" + tabSetStr + '}');
3106
+ } else {
3107
+ output.add(" {" + tabRuleStr);
3108
+ rules[0].genCSS(env, output);
3109
+ for (i = 1; i < ruleCnt; i++) {
3110
+ output.add(tabRuleStr);
3111
+ rules[i].genCSS(env, output);
3112
+ }
3113
+ output.add(tabSetStr + '}');
3114
+ }
3115
+
3116
+ env.tabLevel--;
3117
+ };
3118
+
3119
+ })(require('./tree'));
3120
+
3121
+ (function (tree) {
3122
+
3123
+ tree.Alpha = function (val) {
3124
+ this.value = val;
3125
+ };
3126
+ tree.Alpha.prototype = {
3127
+ type: "Alpha",
3128
+ accept: function (visitor) {
3129
+ this.value = visitor.visit(this.value);
3130
+ },
3131
+ eval: function (env) {
3132
+ if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); }
3133
+ return this;
3134
+ },
3135
+ genCSS: function (env, output) {
3136
+ output.add("alpha(opacity=");
3137
+
3138
+ if (this.value.genCSS) {
3139
+ this.value.genCSS(env, output);
3140
+ } else {
3141
+ output.add(this.value);
3142
+ }
3143
+
3144
+ output.add(")");
3145
+ },
3146
+ toCSS: tree.toCSS
3147
+ };
3148
+
3149
+ })(require('../tree'));
3150
+
3151
+ (function (tree) {
3152
+
3153
+ tree.Anonymous = function (value, index, currentFileInfo, mapLines) {
3154
+ this.value = value;
3155
+ this.index = index;
3156
+ this.mapLines = mapLines;
3157
+ this.currentFileInfo = currentFileInfo;
3158
+ };
3159
+ tree.Anonymous.prototype = {
3160
+ type: "Anonymous",
3161
+ eval: function () {
3162
+ return new tree.Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines);
3163
+ },
3164
+ compare: function (x) {
3165
+ if (!x.toCSS) {
3166
+ return -1;
3167
+ }
3168
+
3169
+ var left = this.toCSS(),
3170
+ right = x.toCSS();
3171
+
3172
+ if (left === right) {
3173
+ return 0;
3174
+ }
3175
+
3176
+ return left < right ? -1 : 1;
3177
+ },
3178
+ genCSS: function (env, output) {
3179
+ output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
3180
+ },
3181
+ toCSS: tree.toCSS
3182
+ };
3183
+
3184
+ })(require('../tree'));
3185
+
3186
+ (function (tree) {
3187
+
3188
+ tree.Assignment = function (key, val) {
3189
+ this.key = key;
3190
+ this.value = val;
3191
+ };
3192
+ tree.Assignment.prototype = {
3193
+ type: "Assignment",
3194
+ accept: function (visitor) {
3195
+ this.value = visitor.visit(this.value);
3196
+ },
3197
+ eval: function (env) {
3198
+ if (this.value.eval) {
3199
+ return new(tree.Assignment)(this.key, this.value.eval(env));
3200
+ }
3201
+ return this;
3202
+ },
3203
+ genCSS: function (env, output) {
3204
+ output.add(this.key + '=');
3205
+ if (this.value.genCSS) {
3206
+ this.value.genCSS(env, output);
3207
+ } else {
3208
+ output.add(this.value);
3209
+ }
3210
+ },
3211
+ toCSS: tree.toCSS
3212
+ };
3213
+
3214
+ })(require('../tree'));
3215
+
3216
+ (function (tree) {
3217
+
3218
+ //
3219
+ // A function call node.
3220
+ //
3221
+ tree.Call = function (name, args, index, currentFileInfo) {
3222
+ this.name = name;
3223
+ this.args = args;
3224
+ this.index = index;
3225
+ this.currentFileInfo = currentFileInfo;
3226
+ };
3227
+ tree.Call.prototype = {
3228
+ type: "Call",
3229
+ accept: function (visitor) {
3230
+ if (this.args) {
3231
+ this.args = visitor.visitArray(this.args);
3232
+ }
3233
+ },
3234
+ //
3235
+ // When evaluating a function call,
3236
+ // we either find the function in `tree.functions` [1],
3237
+ // in which case we call it, passing the evaluated arguments,
3238
+ // if this returns null or we cannot find the function, we
3239
+ // simply print it out as it appeared originally [2].
3240
+ //
3241
+ // The *functions.js* file contains the built-in functions.
3242
+ //
3243
+ // The reason why we evaluate the arguments, is in the case where
3244
+ // we try to pass a variable to a function, like: `saturate(@color)`.
3245
+ // The function should receive the value, not the variable.
3246
+ //
3247
+ eval: function (env) {
3248
+ var args = this.args.map(function (a) { return a.eval(env); }),
3249
+ nameLC = this.name.toLowerCase(),
3250
+ result, func;
3251
+
3252
+ if (nameLC in tree.functions) { // 1.
3253
+ try {
3254
+ func = new tree.functionCall(env, this.currentFileInfo);
3255
+ result = func[nameLC].apply(func, args);
3256
+ if (result != null) {
3257
+ return result;
3258
+ }
3259
+ } catch (e) {
3260
+ throw { type: e.type || "Runtime",
3261
+ message: "error evaluating function `" + this.name + "`" +
3262
+ (e.message ? ': ' + e.message : ''),
3263
+ index: this.index, filename: this.currentFileInfo.filename };
3264
+ }
3265
+ }
3266
+
3267
+ return new tree.Call(this.name, args, this.index, this.currentFileInfo);
3268
+ },
3269
+
3270
+ genCSS: function (env, output) {
3271
+ output.add(this.name + "(", this.currentFileInfo, this.index);
3272
+
3273
+ for(var i = 0; i < this.args.length; i++) {
3274
+ this.args[i].genCSS(env, output);
3275
+ if (i + 1 < this.args.length) {
3276
+ output.add(", ");
3277
+ }
3278
+ }
3279
+
3280
+ output.add(")");
3281
+ },
3282
+
3283
+ toCSS: tree.toCSS
3284
+ };
3285
+
3286
+ })(require('../tree'));
3287
+
3288
+ (function (tree) {
3289
+ //
3290
+ // RGB Colors - #ff0014, #eee
3291
+ //
3292
+ tree.Color = function (rgb, a) {
3293
+ //
3294
+ // The end goal here, is to parse the arguments
3295
+ // into an integer triplet, such as `128, 255, 0`
3296
+ //
3297
+ // This facilitates operations and conversions.
3298
+ //
3299
+ if (Array.isArray(rgb)) {
3300
+ this.rgb = rgb;
3301
+ } else if (rgb.length == 6) {
3302
+ this.rgb = rgb.match(/.{2}/g).map(function (c) {
3303
+ return parseInt(c, 16);
3304
+ });
3305
+ } else {
3306
+ this.rgb = rgb.split('').map(function (c) {
3307
+ return parseInt(c + c, 16);
3308
+ });
3309
+ }
3310
+ this.alpha = typeof(a) === 'number' ? a : 1;
3311
+ };
3312
+
3313
+ var transparentKeyword = "transparent";
3314
+
3315
+ tree.Color.prototype = {
3316
+ type: "Color",
3317
+ eval: function () { return this; },
3318
+ luma: function () {
3319
+ var r = this.rgb[0] / 255,
3320
+ g = this.rgb[1] / 255,
3321
+ b = this.rgb[2] / 255;
3322
+
3323
+ r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
3324
+ g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
3325
+ b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
3326
+
3327
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
3328
+ },
3329
+
3330
+ genCSS: function (env, output) {
3331
+ output.add(this.toCSS(env));
3332
+ },
3333
+ toCSS: function (env, doNotCompress) {
3334
+ var compress = env && env.compress && !doNotCompress,
3335
+ alpha = tree.fround(env, this.alpha);
3336
+
3337
+ // If we have some transparency, the only way to represent it
3338
+ // is via `rgba`. Otherwise, we use the hex representation,
3339
+ // which has better compatibility with older browsers.
3340
+ // Values are capped between `0` and `255`, rounded and zero-padded.
3341
+ if (alpha < 1) {
3342
+ if (alpha === 0 && this.isTransparentKeyword) {
3343
+ return transparentKeyword;
3344
+ }
3345
+ return "rgba(" + this.rgb.map(function (c) {
3346
+ return clamp(Math.round(c), 255);
3347
+ }).concat(clamp(alpha, 1))
3348
+ .join(',' + (compress ? '' : ' ')) + ")";
3349
+ } else {
3350
+ var color = this.toRGB();
3351
+
3352
+ if (compress) {
3353
+ var splitcolor = color.split('');
3354
+
3355
+ // Convert color to short format
3356
+ if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
3357
+ color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5];
3358
+ }
3359
+ }
3360
+
3361
+ return color;
3362
+ }
3363
+ },
3364
+
3365
+ //
3366
+ // Operations have to be done per-channel, if not,
3367
+ // channels will spill onto each other. Once we have
3368
+ // our result, in the form of an integer triplet,
3369
+ // we create a new Color node to hold the result.
3370
+ //
3371
+ operate: function (env, op, other) {
3372
+ var rgb = [];
3373
+ var alpha = this.alpha * (1 - other.alpha) + other.alpha;
3374
+ for (var c = 0; c < 3; c++) {
3375
+ rgb[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]);
3376
+ }
3377
+ return new(tree.Color)(rgb, alpha);
3378
+ },
3379
+
3380
+ toRGB: function () {
3381
+ return toHex(this.rgb);
3382
+ },
3383
+
3384
+ toHSL: function () {
3385
+ var r = this.rgb[0] / 255,
3386
+ g = this.rgb[1] / 255,
3387
+ b = this.rgb[2] / 255,
3388
+ a = this.alpha;
3389
+
3390
+ var max = Math.max(r, g, b), min = Math.min(r, g, b);
3391
+ var h, s, l = (max + min) / 2, d = max - min;
3392
+
3393
+ if (max === min) {
3394
+ h = s = 0;
3395
+ } else {
3396
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
3397
+
3398
+ switch (max) {
3399
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
3400
+ case g: h = (b - r) / d + 2; break;
3401
+ case b: h = (r - g) / d + 4; break;
3402
+ }
3403
+ h /= 6;
3404
+ }
3405
+ return { h: h * 360, s: s, l: l, a: a };
3406
+ },
3407
+ //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
3408
+ toHSV: function () {
3409
+ var r = this.rgb[0] / 255,
3410
+ g = this.rgb[1] / 255,
3411
+ b = this.rgb[2] / 255,
3412
+ a = this.alpha;
3413
+
3414
+ var max = Math.max(r, g, b), min = Math.min(r, g, b);
3415
+ var h, s, v = max;
3416
+
3417
+ var d = max - min;
3418
+ if (max === 0) {
3419
+ s = 0;
3420
+ } else {
3421
+ s = d / max;
3422
+ }
3423
+
3424
+ if (max === min) {
3425
+ h = 0;
3426
+ } else {
3427
+ switch(max){
3428
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
3429
+ case g: h = (b - r) / d + 2; break;
3430
+ case b: h = (r - g) / d + 4; break;
3431
+ }
3432
+ h /= 6;
3433
+ }
3434
+ return { h: h * 360, s: s, v: v, a: a };
3435
+ },
3436
+ toARGB: function () {
3437
+ return toHex([this.alpha * 255].concat(this.rgb));
3438
+ },
3439
+ compare: function (x) {
3440
+ if (!x.rgb) {
3441
+ return -1;
3442
+ }
3443
+
3444
+ return (x.rgb[0] === this.rgb[0] &&
3445
+ x.rgb[1] === this.rgb[1] &&
3446
+ x.rgb[2] === this.rgb[2] &&
3447
+ x.alpha === this.alpha) ? 0 : -1;
3448
+ }
3449
+ };
3450
+
3451
+ tree.Color.fromKeyword = function(keyword) {
3452
+ keyword = keyword.toLowerCase();
3453
+
3454
+ if (tree.colors.hasOwnProperty(keyword)) {
3455
+ // detect named color
3456
+ return new(tree.Color)(tree.colors[keyword].slice(1));
3457
+ }
3458
+ if (keyword === transparentKeyword) {
3459
+ var transparent = new(tree.Color)([0, 0, 0], 0);
3460
+ transparent.isTransparentKeyword = true;
3461
+ return transparent;
3462
+ }
3463
+ };
3464
+
3465
+ function toHex(v) {
3466
+ return '#' + v.map(function (c) {
3467
+ c = clamp(Math.round(c), 255);
3468
+ return (c < 16 ? '0' : '') + c.toString(16);
3469
+ }).join('');
3470
+ }
3471
+
3472
+ function clamp(v, max) {
3473
+ return Math.min(Math.max(v, 0), max);
3474
+ }
3475
+
3476
+ })(require('../tree'));
3477
+
3478
+ (function (tree) {
3479
+
3480
+ tree.Comment = function (value, silent, index, currentFileInfo) {
3481
+ this.value = value;
3482
+ this.silent = !!silent;
3483
+ this.currentFileInfo = currentFileInfo;
3484
+ };
3485
+ tree.Comment.prototype = {
3486
+ type: "Comment",
3487
+ genCSS: function (env, output) {
3488
+ if (this.debugInfo) {
3489
+ output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index);
3490
+ }
3491
+ output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n
3492
+ },
3493
+ toCSS: tree.toCSS,
3494
+ isSilent: function(env) {
3495
+ var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced),
3496
+ isCompressed = env.compress && !this.value.match(/^\/\*!/);
3497
+ return this.silent || isReference || isCompressed;
3498
+ },
3499
+ eval: function () { return this; },
3500
+ markReferenced: function () {
3501
+ this.isReferenced = true;
3502
+ }
3503
+ };
3504
+
3505
+ })(require('../tree'));
3506
+
3507
+ (function (tree) {
3508
+
3509
+ tree.Condition = function (op, l, r, i, negate) {
3510
+ this.op = op.trim();
3511
+ this.lvalue = l;
3512
+ this.rvalue = r;
3513
+ this.index = i;
3514
+ this.negate = negate;
3515
+ };
3516
+ tree.Condition.prototype = {
3517
+ type: "Condition",
3518
+ accept: function (visitor) {
3519
+ this.lvalue = visitor.visit(this.lvalue);
3520
+ this.rvalue = visitor.visit(this.rvalue);
3521
+ },
3522
+ eval: function (env) {
3523
+ var a = this.lvalue.eval(env),
3524
+ b = this.rvalue.eval(env);
3525
+
3526
+ var i = this.index, result;
3527
+
3528
+ result = (function (op) {
3529
+ switch (op) {
3530
+ case 'and':
3531
+ return a && b;
3532
+ case 'or':
3533
+ return a || b;
3534
+ default:
3535
+ if (a.compare) {
3536
+ result = a.compare(b);
3537
+ } else if (b.compare) {
3538
+ result = b.compare(a);
3539
+ } else {
3540
+ throw { type: "Type",
3541
+ message: "Unable to perform comparison",
3542
+ index: i };
3543
+ }
3544
+ switch (result) {
3545
+ case -1: return op === '<' || op === '=<' || op === '<=';
3546
+ case 0: return op === '=' || op === '>=' || op === '=<' || op === '<=';
3547
+ case 1: return op === '>' || op === '>=';
3548
+ }
3549
+ }
3550
+ })(this.op);
3551
+ return this.negate ? !result : result;
3552
+ }
3553
+ };
3554
+
3555
+ })(require('../tree'));
3556
+
3557
+ (function (tree) {
3558
+
3559
+ tree.DetachedRuleset = function (ruleset, frames) {
3560
+ this.ruleset = ruleset;
3561
+ this.frames = frames;
3562
+ };
3563
+ tree.DetachedRuleset.prototype = {
3564
+ type: "DetachedRuleset",
3565
+ accept: function (visitor) {
3566
+ this.ruleset = visitor.visit(this.ruleset);
3567
+ },
3568
+ eval: function (env) {
3569
+ var frames = this.frames || env.frames.slice(0);
3570
+ return new tree.DetachedRuleset(this.ruleset, frames);
3571
+ },
3572
+ callEval: function (env) {
3573
+ return this.ruleset.eval(this.frames ? new(tree.evalEnv)(env, this.frames.concat(env.frames)) : env);
3574
+ }
3575
+ };
3576
+ })(require('../tree'));
3577
+
3578
+ (function (tree) {
3579
+
3580
+ //
3581
+ // A number with a unit
3582
+ //
3583
+ tree.Dimension = function (value, unit) {
3584
+ this.value = parseFloat(value);
3585
+ this.unit = (unit && unit instanceof tree.Unit) ? unit :
3586
+ new(tree.Unit)(unit ? [unit] : undefined);
3587
+ };
3588
+
3589
+ tree.Dimension.prototype = {
3590
+ type: "Dimension",
3591
+ accept: function (visitor) {
3592
+ this.unit = visitor.visit(this.unit);
3593
+ },
3594
+ eval: function (env) {
3595
+ return this;
3596
+ },
3597
+ toColor: function () {
3598
+ return new(tree.Color)([this.value, this.value, this.value]);
3599
+ },
3600
+ genCSS: function (env, output) {
3601
+ if ((env && env.strictUnits) && !this.unit.isSingular()) {
3602
+ throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
3603
+ }
3604
+
3605
+ var value = tree.fround(env, this.value),
3606
+ strValue = String(value);
3607
+
3608
+ if (value !== 0 && value < 0.000001 && value > -0.000001) {
3609
+ // would be output 1e-6 etc.
3610
+ strValue = value.toFixed(20).replace(/0+$/, "");
3611
+ }
3612
+
3613
+ if (env && env.compress) {
3614
+ // Zero values doesn't need a unit
3615
+ if (value === 0 && this.unit.isLength()) {
3616
+ output.add(strValue);
3617
+ return;
3618
+ }
3619
+
3620
+ // Float values doesn't need a leading zero
3621
+ if (value > 0 && value < 1) {
3622
+ strValue = (strValue).substr(1);
3623
+ }
3624
+ }
3625
+
3626
+ output.add(strValue);
3627
+ this.unit.genCSS(env, output);
3628
+ },
3629
+ toCSS: tree.toCSS,
3630
+
3631
+ // In an operation between two Dimensions,
3632
+ // we default to the first Dimension's unit,
3633
+ // so `1px + 2` will yield `3px`.
3634
+ operate: function (env, op, other) {
3635
+ /*jshint noempty:false */
3636
+ var value = tree.operate(env, op, this.value, other.value),
3637
+ unit = this.unit.clone();
3638
+
3639
+ if (op === '+' || op === '-') {
3640
+ if (unit.numerator.length === 0 && unit.denominator.length === 0) {
3641
+ unit.numerator = other.unit.numerator.slice(0);
3642
+ unit.denominator = other.unit.denominator.slice(0);
3643
+ } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
3644
+ // do nothing
3645
+ } else {
3646
+ other = other.convertTo(this.unit.usedUnits());
3647
+
3648
+ if(env.strictUnits && other.unit.toString() !== unit.toString()) {
3649
+ throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
3650
+ "' and '" + other.unit.toString() + "'.");
3651
+ }
3652
+
3653
+ value = tree.operate(env, op, this.value, other.value);
3654
+ }
3655
+ } else if (op === '*') {
3656
+ unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
3657
+ unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
3658
+ unit.cancel();
3659
+ } else if (op === '/') {
3660
+ unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
3661
+ unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
3662
+ unit.cancel();
3663
+ }
3664
+ return new(tree.Dimension)(value, unit);
3665
+ },
3666
+
3667
+ compare: function (other) {
3668
+ if (other instanceof tree.Dimension) {
3669
+ var a, b,
3670
+ aValue, bValue;
3671
+
3672
+ if (this.unit.isEmpty() || other.unit.isEmpty()) {
3673
+ a = this;
3674
+ b = other;
3675
+ } else {
3676
+ a = this.unify();
3677
+ b = other.unify();
3678
+ if (a.unit.compare(b.unit) !== 0) {
3679
+ return -1;
3680
+ }
3681
+ }
3682
+ aValue = a.value;
3683
+ bValue = b.value;
3684
+
3685
+ if (bValue > aValue) {
3686
+ return -1;
3687
+ } else if (bValue < aValue) {
3688
+ return 1;
3689
+ } else {
3690
+ return 0;
3691
+ }
3692
+ } else {
3693
+ return -1;
3694
+ }
3695
+ },
3696
+
3697
+ unify: function () {
3698
+ return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
3699
+ },
3700
+
3701
+ convertTo: function (conversions) {
3702
+ var value = this.value, unit = this.unit.clone(),
3703
+ i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
3704
+
3705
+ if (typeof conversions === 'string') {
3706
+ for(i in tree.UnitConversions) {
3707
+ if (tree.UnitConversions[i].hasOwnProperty(conversions)) {
3708
+ derivedConversions = {};
3709
+ derivedConversions[i] = conversions;
3710
+ }
3711
+ }
3712
+ conversions = derivedConversions;
3713
+ }
3714
+ applyUnit = function (atomicUnit, denominator) {
3715
+ /*jshint loopfunc:true */
3716
+ if (group.hasOwnProperty(atomicUnit)) {
3717
+ if (denominator) {
3718
+ value = value / (group[atomicUnit] / group[targetUnit]);
3719
+ } else {
3720
+ value = value * (group[atomicUnit] / group[targetUnit]);
3721
+ }
3722
+
3723
+ return targetUnit;
3724
+ }
3725
+
3726
+ return atomicUnit;
3727
+ };
3728
+
3729
+ for (groupName in conversions) {
3730
+ if (conversions.hasOwnProperty(groupName)) {
3731
+ targetUnit = conversions[groupName];
3732
+ group = tree.UnitConversions[groupName];
3733
+
3734
+ unit.map(applyUnit);
3735
+ }
3736
+ }
3737
+
3738
+ unit.cancel();
3739
+
3740
+ return new(tree.Dimension)(value, unit);
3741
+ }
3742
+ };
3743
+
3744
+ // http://www.w3.org/TR/css3-values/#absolute-lengths
3745
+ tree.UnitConversions = {
3746
+ length: {
3747
+ 'm': 1,
3748
+ 'cm': 0.01,
3749
+ 'mm': 0.001,
3750
+ 'in': 0.0254,
3751
+ 'px': 0.0254 / 96,
3752
+ 'pt': 0.0254 / 72,
3753
+ 'pc': 0.0254 / 72 * 12
3754
+ },
3755
+ duration: {
3756
+ 's': 1,
3757
+ 'ms': 0.001
3758
+ },
3759
+ angle: {
3760
+ 'rad': 1/(2*Math.PI),
3761
+ 'deg': 1/360,
3762
+ 'grad': 1/400,
3763
+ 'turn': 1
3764
+ }
3765
+ };
3766
+
3767
+ tree.Unit = function (numerator, denominator, backupUnit) {
3768
+ this.numerator = numerator ? numerator.slice(0).sort() : [];
3769
+ this.denominator = denominator ? denominator.slice(0).sort() : [];
3770
+ this.backupUnit = backupUnit;
3771
+ };
3772
+
3773
+ tree.Unit.prototype = {
3774
+ type: "Unit",
3775
+ clone: function () {
3776
+ return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
3777
+ },
3778
+ genCSS: function (env, output) {
3779
+ if (this.numerator.length >= 1) {
3780
+ output.add(this.numerator[0]);
3781
+ } else
3782
+ if (this.denominator.length >= 1) {
3783
+ output.add(this.denominator[0]);
3784
+ } else
3785
+ if ((!env || !env.strictUnits) && this.backupUnit) {
3786
+ output.add(this.backupUnit);
3787
+ }
3788
+ },
3789
+ toCSS: tree.toCSS,
3790
+
3791
+ toString: function () {
3792
+ var i, returnStr = this.numerator.join("*");
3793
+ for (i = 0; i < this.denominator.length; i++) {
3794
+ returnStr += "/" + this.denominator[i];
3795
+ }
3796
+ return returnStr;
3797
+ },
3798
+
3799
+ compare: function (other) {
3800
+ return this.is(other.toString()) ? 0 : -1;
3801
+ },
3802
+
3803
+ is: function (unitString) {
3804
+ return this.toString() === unitString;
3805
+ },
3806
+
3807
+ isLength: function () {
3808
+ return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
3809
+ },
3810
+
3811
+ isEmpty: function () {
3812
+ return this.numerator.length === 0 && this.denominator.length === 0;
3813
+ },
3814
+
3815
+ isSingular: function() {
3816
+ return this.numerator.length <= 1 && this.denominator.length === 0;
3817
+ },
3818
+
3819
+ map: function(callback) {
3820
+ var i;
3821
+
3822
+ for (i = 0; i < this.numerator.length; i++) {
3823
+ this.numerator[i] = callback(this.numerator[i], false);
3824
+ }
3825
+
3826
+ for (i = 0; i < this.denominator.length; i++) {
3827
+ this.denominator[i] = callback(this.denominator[i], true);
3828
+ }
3829
+ },
3830
+
3831
+ usedUnits: function() {
3832
+ var group, result = {}, mapUnit;
3833
+
3834
+ mapUnit = function (atomicUnit) {
3835
+ /*jshint loopfunc:true */
3836
+ if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
3837
+ result[groupName] = atomicUnit;
3838
+ }
3839
+
3840
+ return atomicUnit;
3841
+ };
3842
+
3843
+ for (var groupName in tree.UnitConversions) {
3844
+ if (tree.UnitConversions.hasOwnProperty(groupName)) {
3845
+ group = tree.UnitConversions[groupName];
3846
+
3847
+ this.map(mapUnit);
3848
+ }
3849
+ }
3850
+
3851
+ return result;
3852
+ },
3853
+
3854
+ cancel: function () {
3855
+ var counter = {}, atomicUnit, i, backup;
3856
+
3857
+ for (i = 0; i < this.numerator.length; i++) {
3858
+ atomicUnit = this.numerator[i];
3859
+ if (!backup) {
3860
+ backup = atomicUnit;
3861
+ }
3862
+ counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
3863
+ }
3864
+
3865
+ for (i = 0; i < this.denominator.length; i++) {
3866
+ atomicUnit = this.denominator[i];
3867
+ if (!backup) {
3868
+ backup = atomicUnit;
3869
+ }
3870
+ counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
3871
+ }
3872
+
3873
+ this.numerator = [];
3874
+ this.denominator = [];
3875
+
3876
+ for (atomicUnit in counter) {
3877
+ if (counter.hasOwnProperty(atomicUnit)) {
3878
+ var count = counter[atomicUnit];
3879
+
3880
+ if (count > 0) {
3881
+ for (i = 0; i < count; i++) {
3882
+ this.numerator.push(atomicUnit);
3883
+ }
3884
+ } else if (count < 0) {
3885
+ for (i = 0; i < -count; i++) {
3886
+ this.denominator.push(atomicUnit);
3887
+ }
3888
+ }
3889
+ }
3890
+ }
3891
+
3892
+ if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
3893
+ this.backupUnit = backup;
3894
+ }
3895
+
3896
+ this.numerator.sort();
3897
+ this.denominator.sort();
3898
+ }
3899
+ };
3900
+
3901
+ })(require('../tree'));
3902
+
3903
+ (function (tree) {
3904
+
3905
+ tree.Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
3906
+ this.name = name;
3907
+ this.value = value;
3908
+ if (rules) {
3909
+ this.rules = rules;
3910
+ this.rules.allowImports = true;
3911
+ }
3912
+ this.index = index;
3913
+ this.currentFileInfo = currentFileInfo;
3914
+ this.debugInfo = debugInfo;
3915
+ };
3916
+
3917
+ tree.Directive.prototype = {
3918
+ type: "Directive",
3919
+ accept: function (visitor) {
3920
+ var value = this.value, rules = this.rules;
3921
+ if (rules) {
3922
+ rules = visitor.visit(rules);
3923
+ }
3924
+ if (value) {
3925
+ value = visitor.visit(value);
3926
+ }
3927
+ },
3928
+ genCSS: function (env, output) {
3929
+ var value = this.value, rules = this.rules;
3930
+ output.add(this.name, this.currentFileInfo, this.index);
3931
+ if (value) {
3932
+ output.add(' ');
3933
+ value.genCSS(env, output);
3934
+ }
3935
+ if (rules) {
3936
+ tree.outputRuleset(env, output, [rules]);
3937
+ } else {
3938
+ output.add(';');
3939
+ }
3940
+ },
3941
+ toCSS: tree.toCSS,
3942
+ eval: function (env) {
3943
+ var value = this.value, rules = this.rules;
3944
+ if (value) {
3945
+ value = value.eval(env);
3946
+ }
3947
+ if (rules) {
3948
+ rules = rules.eval(env);
3949
+ rules.root = true;
3950
+ }
3951
+ return new(tree.Directive)(this.name, value, rules,
3952
+ this.index, this.currentFileInfo, this.debugInfo);
3953
+ },
3954
+ variable: function (name) { if (this.rules) return tree.Ruleset.prototype.variable.call(this.rules, name); },
3955
+ find: function () { if (this.rules) return tree.Ruleset.prototype.find.apply(this.rules, arguments); },
3956
+ rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
3957
+ markReferenced: function () {
3958
+ var i, rules;
3959
+ this.isReferenced = true;
3960
+ if (this.rules) {
3961
+ rules = this.rules.rules;
3962
+ for (i = 0; i < rules.length; i++) {
3963
+ if (rules[i].markReferenced) {
3964
+ rules[i].markReferenced();
3965
+ }
3966
+ }
3967
+ }
3968
+ }
3969
+ };
3970
+
3971
+ })(require('../tree'));
3972
+
3973
+ (function (tree) {
3974
+
3975
+ tree.Element = function (combinator, value, index, currentFileInfo) {
3976
+ this.combinator = combinator instanceof tree.Combinator ?
3977
+ combinator : new(tree.Combinator)(combinator);
3978
+
3979
+ if (typeof(value) === 'string') {
3980
+ this.value = value.trim();
3981
+ } else if (value) {
3982
+ this.value = value;
3983
+ } else {
3984
+ this.value = "";
3985
+ }
3986
+ this.index = index;
3987
+ this.currentFileInfo = currentFileInfo;
3988
+ };
3989
+ tree.Element.prototype = {
3990
+ type: "Element",
3991
+ accept: function (visitor) {
3992
+ var value = this.value;
3993
+ this.combinator = visitor.visit(this.combinator);
3994
+ if (typeof value === "object") {
3995
+ this.value = visitor.visit(value);
3996
+ }
3997
+ },
3998
+ eval: function (env) {
3999
+ return new(tree.Element)(this.combinator,
4000
+ this.value.eval ? this.value.eval(env) : this.value,
4001
+ this.index,
4002
+ this.currentFileInfo);
4003
+ },
4004
+ genCSS: function (env, output) {
4005
+ output.add(this.toCSS(env), this.currentFileInfo, this.index);
4006
+ },
4007
+ toCSS: function (env) {
4008
+ var value = (this.value.toCSS ? this.value.toCSS(env) : this.value);
4009
+ if (value === '' && this.combinator.value.charAt(0) === '&') {
4010
+ return '';
4011
+ } else {
4012
+ return this.combinator.toCSS(env || {}) + value;
4013
+ }
4014
+ }
4015
+ };
4016
+
4017
+ tree.Attribute = function (key, op, value) {
4018
+ this.key = key;
4019
+ this.op = op;
4020
+ this.value = value;
4021
+ };
4022
+ tree.Attribute.prototype = {
4023
+ type: "Attribute",
4024
+ eval: function (env) {
4025
+ return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key,
4026
+ this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value);
4027
+ },
4028
+ genCSS: function (env, output) {
4029
+ output.add(this.toCSS(env));
4030
+ },
4031
+ toCSS: function (env) {
4032
+ var value = this.key.toCSS ? this.key.toCSS(env) : this.key;
4033
+
4034
+ if (this.op) {
4035
+ value += this.op;
4036
+ value += (this.value.toCSS ? this.value.toCSS(env) : this.value);
4037
+ }
4038
+
4039
+ return '[' + value + ']';
4040
+ }
4041
+ };
4042
+
4043
+ tree.Combinator = function (value) {
4044
+ if (value === ' ') {
4045
+ this.value = ' ';
4046
+ } else {
4047
+ this.value = value ? value.trim() : "";
4048
+ }
4049
+ };
4050
+ tree.Combinator.prototype = {
4051
+ type: "Combinator",
4052
+ _outputMap: {
4053
+ '' : '',
4054
+ ' ' : ' ',
4055
+ ':' : ' :',
4056
+ '+' : ' + ',
4057
+ '~' : ' ~ ',
4058
+ '>' : ' > ',
4059
+ '|' : '|',
4060
+ '^' : ' ^ ',
4061
+ '^^' : ' ^^ '
4062
+ },
4063
+ _outputMapCompressed: {
4064
+ '' : '',
4065
+ ' ' : ' ',
4066
+ ':' : ' :',
4067
+ '+' : '+',
4068
+ '~' : '~',
4069
+ '>' : '>',
4070
+ '|' : '|',
4071
+ '^' : '^',
4072
+ '^^' : '^^'
4073
+ },
4074
+ genCSS: function (env, output) {
4075
+ output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]);
4076
+ },
4077
+ toCSS: tree.toCSS
4078
+ };
4079
+
4080
+ })(require('../tree'));
4081
+
4082
+ (function (tree) {
4083
+
4084
+ tree.Expression = function (value) { this.value = value; };
4085
+ tree.Expression.prototype = {
4086
+ type: "Expression",
4087
+ accept: function (visitor) {
4088
+ if (this.value) {
4089
+ this.value = visitor.visitArray(this.value);
4090
+ }
4091
+ },
4092
+ eval: function (env) {
4093
+ var returnValue,
4094
+ inParenthesis = this.parens && !this.parensInOp,
4095
+ doubleParen = false;
4096
+ if (inParenthesis) {
4097
+ env.inParenthesis();
4098
+ }
4099
+ if (this.value.length > 1) {
4100
+ returnValue = new(tree.Expression)(this.value.map(function (e) {
4101
+ return e.eval(env);
4102
+ }));
4103
+ } else if (this.value.length === 1) {
4104
+ if (this.value[0].parens && !this.value[0].parensInOp) {
4105
+ doubleParen = true;
4106
+ }
4107
+ returnValue = this.value[0].eval(env);
4108
+ } else {
4109
+ returnValue = this;
4110
+ }
4111
+ if (inParenthesis) {
4112
+ env.outOfParenthesis();
4113
+ }
4114
+ if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) {
4115
+ returnValue = new(tree.Paren)(returnValue);
4116
+ }
4117
+ return returnValue;
4118
+ },
4119
+ genCSS: function (env, output) {
4120
+ for(var i = 0; i < this.value.length; i++) {
4121
+ this.value[i].genCSS(env, output);
4122
+ if (i + 1 < this.value.length) {
4123
+ output.add(" ");
4124
+ }
4125
+ }
4126
+ },
4127
+ toCSS: tree.toCSS,
4128
+ throwAwayComments: function () {
4129
+ this.value = this.value.filter(function(v) {
4130
+ return !(v instanceof tree.Comment);
4131
+ });
4132
+ }
4133
+ };
4134
+
4135
+ })(require('../tree'));
4136
+
4137
+ (function (tree) {
4138
+
4139
+ tree.Extend = function Extend(selector, option, index) {
4140
+ this.selector = selector;
4141
+ this.option = option;
4142
+ this.index = index;
4143
+ this.object_id = tree.Extend.next_id++;
4144
+ this.parent_ids = [this.object_id];
4145
+
4146
+ switch(option) {
4147
+ case "all":
4148
+ this.allowBefore = true;
4149
+ this.allowAfter = true;
4150
+ break;
4151
+ default:
4152
+ this.allowBefore = false;
4153
+ this.allowAfter = false;
4154
+ break;
4155
+ }
4156
+ };
4157
+ tree.Extend.next_id = 0;
4158
+
4159
+ tree.Extend.prototype = {
4160
+ type: "Extend",
4161
+ accept: function (visitor) {
4162
+ this.selector = visitor.visit(this.selector);
4163
+ },
4164
+ eval: function (env) {
4165
+ return new(tree.Extend)(this.selector.eval(env), this.option, this.index);
4166
+ },
4167
+ clone: function (env) {
4168
+ return new(tree.Extend)(this.selector, this.option, this.index);
4169
+ },
4170
+ findSelfSelectors: function (selectors) {
4171
+ var selfElements = [],
4172
+ i,
4173
+ selectorElements;
4174
+
4175
+ for(i = 0; i < selectors.length; i++) {
4176
+ selectorElements = selectors[i].elements;
4177
+ // duplicate the logic in genCSS function inside the selector node.
4178
+ // future TODO - move both logics into the selector joiner visitor
4179
+ if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") {
4180
+ selectorElements[0].combinator.value = ' ';
4181
+ }
4182
+ selfElements = selfElements.concat(selectors[i].elements);
4183
+ }
4184
+
4185
+ this.selfSelectors = [{ elements: selfElements }];
4186
+ }
4187
+ };
4188
+
4189
+ })(require('../tree'));
4190
+
4191
+ (function (tree) {
4192
+ //
4193
+ // CSS @import node
4194
+ //
4195
+ // The general strategy here is that we don't want to wait
4196
+ // for the parsing to be completed, before we start importing
4197
+ // the file. That's because in the context of a browser,
4198
+ // most of the time will be spent waiting for the server to respond.
4199
+ //
4200
+ // On creation, we push the import path to our import queue, though
4201
+ // `import,push`, we also pass it a callback, which it'll call once
4202
+ // the file has been fetched, and parsed.
4203
+ //
4204
+ tree.Import = function (path, features, options, index, currentFileInfo) {
4205
+ this.options = options;
4206
+ this.index = index;
4207
+ this.path = path;
4208
+ this.features = features;
4209
+ this.currentFileInfo = currentFileInfo;
4210
+
4211
+ if (this.options.less !== undefined || this.options.inline) {
4212
+ this.css = !this.options.less || this.options.inline;
4213
+ } else {
4214
+ var pathValue = this.getPath();
4215
+ if (pathValue && /css([\?;].*)?$/.test(pathValue)) {
4216
+ this.css = true;
4217
+ }
4218
+ }
4219
+ };
4220
+
4221
+ //
4222
+ // The actual import node doesn't return anything, when converted to CSS.
4223
+ // The reason is that it's used at the evaluation stage, so that the rules
4224
+ // it imports can be treated like any other rules.
4225
+ //
4226
+ // In `eval`, we make sure all Import nodes get evaluated, recursively, so
4227
+ // we end up with a flat structure, which can easily be imported in the parent
4228
+ // ruleset.
4229
+ //
4230
+ tree.Import.prototype = {
4231
+ type: "Import",
4232
+ accept: function (visitor) {
4233
+ if (this.features) {
4234
+ this.features = visitor.visit(this.features);
4235
+ }
4236
+ this.path = visitor.visit(this.path);
4237
+ if (!this.options.inline && this.root) {
4238
+ this.root = visitor.visit(this.root);
4239
+ }
4240
+ },
4241
+ genCSS: function (env, output) {
4242
+ if (this.css) {
4243
+ output.add("@import ", this.currentFileInfo, this.index);
4244
+ this.path.genCSS(env, output);
4245
+ if (this.features) {
4246
+ output.add(" ");
4247
+ this.features.genCSS(env, output);
4248
+ }
4249
+ output.add(';');
4250
+ }
4251
+ },
4252
+ toCSS: tree.toCSS,
4253
+ getPath: function () {
4254
+ if (this.path instanceof tree.Quoted) {
4255
+ var path = this.path.value;
4256
+ return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less';
4257
+ } else if (this.path instanceof tree.URL) {
4258
+ return this.path.value.value;
4259
+ }
4260
+ return null;
4261
+ },
4262
+ evalForImport: function (env) {
4263
+ return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo);
4264
+ },
4265
+ evalPath: function (env) {
4266
+ var path = this.path.eval(env);
4267
+ var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
4268
+
4269
+ if (!(path instanceof tree.URL)) {
4270
+ if (rootpath) {
4271
+ var pathValue = path.value;
4272
+ // Add the base path if the import is relative
4273
+ if (pathValue && env.isPathRelative(pathValue)) {
4274
+ path.value = rootpath +pathValue;
4275
+ }
4276
+ }
4277
+ path.value = env.normalizePath(path.value);
4278
+ }
4279
+
4280
+ return path;
4281
+ },
4282
+ eval: function (env) {
4283
+ var ruleset, features = this.features && this.features.eval(env);
4284
+
4285
+ if (this.skip) {
4286
+ if (typeof this.skip === "function") {
4287
+ this.skip = this.skip();
4288
+ }
4289
+ if (this.skip) {
4290
+ return [];
4291
+ }
4292
+ }
4293
+
4294
+ if (this.options.inline) {
4295
+ //todo needs to reference css file not import
4296
+ var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true);
4297
+ return this.features ? new(tree.Media)([contents], this.features.value) : [contents];
4298
+ } else if (this.css) {
4299
+ var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index);
4300
+ if (!newImport.css && this.error) {
4301
+ throw this.error;
4302
+ }
4303
+ return newImport;
4304
+ } else {
4305
+ ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0));
4306
+
4307
+ ruleset.evalImports(env);
4308
+
4309
+ return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules;
4310
+ }
4311
+ }
4312
+ };
4313
+
4314
+ })(require('../tree'));
4315
+
4316
+ (function (tree) {
4317
+
4318
+ tree.JavaScript = function (string, index, escaped) {
4319
+ this.escaped = escaped;
4320
+ this.expression = string;
4321
+ this.index = index;
4322
+ };
4323
+ tree.JavaScript.prototype = {
4324
+ type: "JavaScript",
4325
+ eval: function (env) {
4326
+ var result,
4327
+ that = this,
4328
+ context = {};
4329
+
4330
+ var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
4331
+ return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env));
4332
+ });
4333
+
4334
+ try {
4335
+ expression = new(Function)('return (' + expression + ')');
4336
+ } catch (e) {
4337
+ throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" ,
4338
+ index: this.index };
4339
+ }
4340
+
4341
+ var variables = env.frames[0].variables();
4342
+ for (var k in variables) {
4343
+ if (variables.hasOwnProperty(k)) {
4344
+ /*jshint loopfunc:true */
4345
+ context[k.slice(1)] = {
4346
+ value: variables[k].value,
4347
+ toJS: function () {
4348
+ return this.value.eval(env).toCSS();
4349
+ }
4350
+ };
4351
+ }
4352
+ }
4353
+
4354
+ try {
4355
+ result = expression.call(context);
4356
+ } catch (e) {
4357
+ throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
4358
+ index: this.index };
4359
+ }
4360
+ if (typeof(result) === 'number') {
4361
+ return new(tree.Dimension)(result);
4362
+ } else if (typeof(result) === 'string') {
4363
+ return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index);
4364
+ } else if (Array.isArray(result)) {
4365
+ return new(tree.Anonymous)(result.join(', '));
4366
+ } else {
4367
+ return new(tree.Anonymous)(result);
4368
+ }
4369
+ }
4370
+ };
4371
+
4372
+ })(require('../tree'));
4373
+
4374
+
4375
+ (function (tree) {
4376
+
4377
+ tree.Keyword = function (value) { this.value = value; };
4378
+ tree.Keyword.prototype = {
4379
+ type: "Keyword",
4380
+ eval: function () { return this; },
4381
+ genCSS: function (env, output) {
4382
+ if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
4383
+ output.add(this.value);
4384
+ },
4385
+ toCSS: tree.toCSS,
4386
+ compare: function (other) {
4387
+ if (other instanceof tree.Keyword) {
4388
+ return other.value === this.value ? 0 : 1;
4389
+ } else {
4390
+ return -1;
4391
+ }
4392
+ }
4393
+ };
4394
+
4395
+ tree.True = new(tree.Keyword)('true');
4396
+ tree.False = new(tree.Keyword)('false');
4397
+
4398
+ })(require('../tree'));
4399
+
4400
+ (function (tree) {
4401
+
4402
+ tree.Media = function (value, features, index, currentFileInfo) {
4403
+ this.index = index;
4404
+ this.currentFileInfo = currentFileInfo;
4405
+
4406
+ var selectors = this.emptySelectors();
4407
+
4408
+ this.features = new(tree.Value)(features);
4409
+ this.rules = [new(tree.Ruleset)(selectors, value)];
4410
+ this.rules[0].allowImports = true;
4411
+ };
4412
+ tree.Media.prototype = {
4413
+ type: "Media",
4414
+ accept: function (visitor) {
4415
+ if (this.features) {
4416
+ this.features = visitor.visit(this.features);
4417
+ }
4418
+ if (this.rules) {
4419
+ this.rules = visitor.visitArray(this.rules);
4420
+ }
4421
+ },
4422
+ genCSS: function (env, output) {
4423
+ output.add('@media ', this.currentFileInfo, this.index);
4424
+ this.features.genCSS(env, output);
4425
+ tree.outputRuleset(env, output, this.rules);
4426
+ },
4427
+ toCSS: tree.toCSS,
4428
+ eval: function (env) {
4429
+ if (!env.mediaBlocks) {
4430
+ env.mediaBlocks = [];
4431
+ env.mediaPath = [];
4432
+ }
4433
+
4434
+ var media = new(tree.Media)(null, [], this.index, this.currentFileInfo);
4435
+ if(this.debugInfo) {
4436
+ this.rules[0].debugInfo = this.debugInfo;
4437
+ media.debugInfo = this.debugInfo;
4438
+ }
4439
+ var strictMathBypass = false;
4440
+ if (!env.strictMath) {
4441
+ strictMathBypass = true;
4442
+ env.strictMath = true;
4443
+ }
4444
+ try {
4445
+ media.features = this.features.eval(env);
4446
+ }
4447
+ finally {
4448
+ if (strictMathBypass) {
4449
+ env.strictMath = false;
4450
+ }
4451
+ }
4452
+
4453
+ env.mediaPath.push(media);
4454
+ env.mediaBlocks.push(media);
4455
+
4456
+ env.frames.unshift(this.rules[0]);
4457
+ media.rules = [this.rules[0].eval(env)];
4458
+ env.frames.shift();
4459
+
4460
+ env.mediaPath.pop();
4461
+
4462
+ return env.mediaPath.length === 0 ? media.evalTop(env) :
4463
+ media.evalNested(env);
4464
+ },
4465
+ variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); },
4466
+ find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); },
4467
+ rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); },
4468
+ emptySelectors: function() {
4469
+ var el = new(tree.Element)('', '&', this.index, this.currentFileInfo),
4470
+ sels = [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)];
4471
+ sels[0].mediaEmpty = true;
4472
+ return sels;
4473
+ },
4474
+ markReferenced: function () {
4475
+ var i, rules = this.rules[0].rules;
4476
+ this.rules[0].markReferenced();
4477
+ this.isReferenced = true;
4478
+ for (i = 0; i < rules.length; i++) {
4479
+ if (rules[i].markReferenced) {
4480
+ rules[i].markReferenced();
4481
+ }
4482
+ }
4483
+ },
4484
+
4485
+ evalTop: function (env) {
4486
+ var result = this;
4487
+
4488
+ // Render all dependent Media blocks.
4489
+ if (env.mediaBlocks.length > 1) {
4490
+ var selectors = this.emptySelectors();
4491
+ result = new(tree.Ruleset)(selectors, env.mediaBlocks);
4492
+ result.multiMedia = true;
4493
+ }
4494
+
4495
+ delete env.mediaBlocks;
4496
+ delete env.mediaPath;
4497
+
4498
+ return result;
4499
+ },
4500
+ evalNested: function (env) {
4501
+ var i, value,
4502
+ path = env.mediaPath.concat([this]);
4503
+
4504
+ // Extract the media-query conditions separated with `,` (OR).
4505
+ for (i = 0; i < path.length; i++) {
4506
+ value = path[i].features instanceof tree.Value ?
4507
+ path[i].features.value : path[i].features;
4508
+ path[i] = Array.isArray(value) ? value : [value];
4509
+ }
4510
+
4511
+ // Trace all permutations to generate the resulting media-query.
4512
+ //
4513
+ // (a, b and c) with nested (d, e) ->
4514
+ // a and d
4515
+ // a and e
4516
+ // b and c and d
4517
+ // b and c and e
4518
+ this.features = new(tree.Value)(this.permute(path).map(function (path) {
4519
+ path = path.map(function (fragment) {
4520
+ return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment);
4521
+ });
4522
+
4523
+ for(i = path.length - 1; i > 0; i--) {
4524
+ path.splice(i, 0, new(tree.Anonymous)("and"));
4525
+ }
4526
+
4527
+ return new(tree.Expression)(path);
4528
+ }));
4529
+
4530
+ // Fake a tree-node that doesn't output anything.
4531
+ return new(tree.Ruleset)([], []);
4532
+ },
4533
+ permute: function (arr) {
4534
+ if (arr.length === 0) {
4535
+ return [];
4536
+ } else if (arr.length === 1) {
4537
+ return arr[0];
4538
+ } else {
4539
+ var result = [];
4540
+ var rest = this.permute(arr.slice(1));
4541
+ for (var i = 0; i < rest.length; i++) {
4542
+ for (var j = 0; j < arr[0].length; j++) {
4543
+ result.push([arr[0][j]].concat(rest[i]));
4544
+ }
4545
+ }
4546
+ return result;
4547
+ }
4548
+ },
4549
+ bubbleSelectors: function (selectors) {
4550
+ if (!selectors)
4551
+ return;
4552
+ this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])];
4553
+ }
4554
+ };
4555
+
4556
+ })(require('../tree'));
4557
+
4558
+ (function (tree) {
4559
+
4560
+ tree.mixin = {};
4561
+ tree.mixin.Call = function (elements, args, index, currentFileInfo, important) {
4562
+ this.selector = new(tree.Selector)(elements);
4563
+ this.arguments = (args && args.length) ? args : null;
4564
+ this.index = index;
4565
+ this.currentFileInfo = currentFileInfo;
4566
+ this.important = important;
4567
+ };
4568
+ tree.mixin.Call.prototype = {
4569
+ type: "MixinCall",
4570
+ accept: function (visitor) {
4571
+ if (this.selector) {
4572
+ this.selector = visitor.visit(this.selector);
4573
+ }
4574
+ if (this.arguments) {
4575
+ this.arguments = visitor.visitArray(this.arguments);
4576
+ }
4577
+ },
4578
+ eval: function (env) {
4579
+ var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
4580
+ candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc,
4581
+ defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset;
4582
+
4583
+ args = this.arguments && this.arguments.map(function (a) {
4584
+ return { name: a.name, value: a.value.eval(env) };
4585
+ });
4586
+
4587
+ for (i = 0; i < env.frames.length; i++) {
4588
+ if ((mixins = env.frames[i].find(this.selector)).length > 0) {
4589
+ isOneFound = true;
4590
+
4591
+ // To make `default()` function independent of definition order we have two "subpasses" here.
4592
+ // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
4593
+ // and build candidate list with corresponding flags. Then, when we know all possible matches,
4594
+ // we make a final decision.
4595
+
4596
+ for (m = 0; m < mixins.length; m++) {
4597
+ mixin = mixins[m];
4598
+ isRecursive = false;
4599
+ for(f = 0; f < env.frames.length; f++) {
4600
+ if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) {
4601
+ isRecursive = true;
4602
+ break;
4603
+ }
4604
+ }
4605
+ if (isRecursive) {
4606
+ continue;
4607
+ }
4608
+
4609
+ if (mixin.matchArgs(args, env)) {
4610
+ candidate = {mixin: mixin, group: defNone};
4611
+
4612
+ if (mixin.matchCondition) {
4613
+ for (f = 0; f < 2; f++) {
4614
+ defaultFunc.value(f);
4615
+ conditionResult[f] = mixin.matchCondition(args, env);
4616
+ }
4617
+ if (conditionResult[0] || conditionResult[1]) {
4618
+ if (conditionResult[0] != conditionResult[1]) {
4619
+ candidate.group = conditionResult[1] ?
4620
+ defTrue : defFalse;
4621
+ }
4622
+
4623
+ candidates.push(candidate);
4624
+ }
4625
+ }
4626
+ else {
4627
+ candidates.push(candidate);
4628
+ }
4629
+
4630
+ match = true;
4631
+ }
4632
+ }
4633
+
4634
+ defaultFunc.reset();
4635
+
4636
+ count = [0, 0, 0];
4637
+ for (m = 0; m < candidates.length; m++) {
4638
+ count[candidates[m].group]++;
4639
+ }
4640
+
4641
+ if (count[defNone] > 0) {
4642
+ defaultResult = defFalse;
4643
+ } else {
4644
+ defaultResult = defTrue;
4645
+ if ((count[defTrue] + count[defFalse]) > 1) {
4646
+ throw { type: 'Runtime',
4647
+ message: 'Ambiguous use of `default()` found when matching for `'
4648
+ + this.format(args) + '`',
4649
+ index: this.index, filename: this.currentFileInfo.filename };
4650
+ }
4651
+ }
4652
+
4653
+ for (m = 0; m < candidates.length; m++) {
4654
+ candidate = candidates[m].group;
4655
+ if ((candidate === defNone) || (candidate === defaultResult)) {
4656
+ try {
4657
+ mixin = candidates[m].mixin;
4658
+ if (!(mixin instanceof tree.mixin.Definition)) {
4659
+ originalRuleset = mixin.originalRuleset || mixin;
4660
+ mixin = new tree.mixin.Definition("", [], mixin.rules, null, false);
4661
+ mixin.originalRuleset = originalRuleset;
4662
+ }
4663
+ Array.prototype.push.apply(
4664
+ rules, mixin.evalCall(env, args, this.important).rules);
4665
+ } catch (e) {
4666
+ throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
4667
+ }
4668
+ }
4669
+ }
4670
+
4671
+ if (match) {
4672
+ if (!this.currentFileInfo || !this.currentFileInfo.reference) {
4673
+ for (i = 0; i < rules.length; i++) {
4674
+ rule = rules[i];
4675
+ if (rule.markReferenced) {
4676
+ rule.markReferenced();
4677
+ }
4678
+ }
4679
+ }
4680
+ return rules;
4681
+ }
4682
+ }
4683
+ }
4684
+ if (isOneFound) {
4685
+ throw { type: 'Runtime',
4686
+ message: 'No matching definition was found for `' + this.format(args) + '`',
4687
+ index: this.index, filename: this.currentFileInfo.filename };
4688
+ } else {
4689
+ throw { type: 'Name',
4690
+ message: this.selector.toCSS().trim() + " is undefined",
4691
+ index: this.index, filename: this.currentFileInfo.filename };
4692
+ }
4693
+ },
4694
+ format: function (args) {
4695
+ return this.selector.toCSS().trim() + '(' +
4696
+ (args ? args.map(function (a) {
4697
+ var argValue = "";
4698
+ if (a.name) {
4699
+ argValue += a.name + ":";
4700
+ }
4701
+ if (a.value.toCSS) {
4702
+ argValue += a.value.toCSS();
4703
+ } else {
4704
+ argValue += "???";
4705
+ }
4706
+ return argValue;
4707
+ }).join(', ') : "") + ")";
4708
+ }
4709
+ };
4710
+
4711
+ tree.mixin.Definition = function (name, params, rules, condition, variadic, frames) {
4712
+ this.name = name;
4713
+ this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])];
4714
+ this.params = params;
4715
+ this.condition = condition;
4716
+ this.variadic = variadic;
4717
+ this.arity = params.length;
4718
+ this.rules = rules;
4719
+ this._lookups = {};
4720
+ this.required = params.reduce(function (count, p) {
4721
+ if (!p.name || (p.name && !p.value)) { return count + 1; }
4722
+ else { return count; }
4723
+ }, 0);
4724
+ this.parent = tree.Ruleset.prototype;
4725
+ this.frames = frames;
4726
+ };
4727
+ tree.mixin.Definition.prototype = {
4728
+ type: "MixinDefinition",
4729
+ accept: function (visitor) {
4730
+ if (this.params && this.params.length) {
4731
+ this.params = visitor.visitArray(this.params);
4732
+ }
4733
+ this.rules = visitor.visitArray(this.rules);
4734
+ if (this.condition) {
4735
+ this.condition = visitor.visit(this.condition);
4736
+ }
4737
+ },
4738
+ variable: function (name) { return this.parent.variable.call(this, name); },
4739
+ variables: function () { return this.parent.variables.call(this); },
4740
+ find: function () { return this.parent.find.apply(this, arguments); },
4741
+ rulesets: function () { return this.parent.rulesets.apply(this); },
4742
+
4743
+ evalParams: function (env, mixinEnv, args, evaldArguments) {
4744
+ /*jshint boss:true */
4745
+ var frame = new(tree.Ruleset)(null, null),
4746
+ varargs, arg,
4747
+ params = this.params.slice(0),
4748
+ i, j, val, name, isNamedFound, argIndex, argsLength = 0;
4749
+
4750
+ mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames));
4751
+
4752
+ if (args) {
4753
+ args = args.slice(0);
4754
+ argsLength = args.length;
4755
+
4756
+ for(i = 0; i < argsLength; i++) {
4757
+ arg = args[i];
4758
+ if (name = (arg && arg.name)) {
4759
+ isNamedFound = false;
4760
+ for(j = 0; j < params.length; j++) {
4761
+ if (!evaldArguments[j] && name === params[j].name) {
4762
+ evaldArguments[j] = arg.value.eval(env);
4763
+ frame.prependRule(new(tree.Rule)(name, arg.value.eval(env)));
4764
+ isNamedFound = true;
4765
+ break;
4766
+ }
4767
+ }
4768
+ if (isNamedFound) {
4769
+ args.splice(i, 1);
4770
+ i--;
4771
+ continue;
4772
+ } else {
4773
+ throw { type: 'Runtime', message: "Named argument for " + this.name +
4774
+ ' ' + args[i].name + ' not found' };
4775
+ }
4776
+ }
4777
+ }
4778
+ }
4779
+ argIndex = 0;
4780
+ for (i = 0; i < params.length; i++) {
4781
+ if (evaldArguments[i]) { continue; }
4782
+
4783
+ arg = args && args[argIndex];
4784
+
4785
+ if (name = params[i].name) {
4786
+ if (params[i].variadic) {
4787
+ varargs = [];
4788
+ for (j = argIndex; j < argsLength; j++) {
4789
+ varargs.push(args[j].value.eval(env));
4790
+ }
4791
+ frame.prependRule(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env)));
4792
+ } else {
4793
+ val = arg && arg.value;
4794
+ if (val) {
4795
+ val = val.eval(env);
4796
+ } else if (params[i].value) {
4797
+ val = params[i].value.eval(mixinEnv);
4798
+ frame.resetCache();
4799
+ } else {
4800
+ throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
4801
+ ' (' + argsLength + ' for ' + this.arity + ')' };
4802
+ }
4803
+
4804
+ frame.prependRule(new(tree.Rule)(name, val));
4805
+ evaldArguments[i] = val;
4806
+ }
4807
+ }
4808
+
4809
+ if (params[i].variadic && args) {
4810
+ for (j = argIndex; j < argsLength; j++) {
4811
+ evaldArguments[j] = args[j].value.eval(env);
4812
+ }
4813
+ }
4814
+ argIndex++;
4815
+ }
4816
+
4817
+ return frame;
4818
+ },
4819
+ eval: function (env) {
4820
+ return new tree.mixin.Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || env.frames.slice(0));
4821
+ },
4822
+ evalCall: function (env, args, important) {
4823
+ var _arguments = [],
4824
+ mixinFrames = this.frames ? this.frames.concat(env.frames) : env.frames,
4825
+ frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments),
4826
+ rules, ruleset;
4827
+
4828
+ frame.prependRule(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env)));
4829
+
4830
+ rules = this.rules.slice(0);
4831
+
4832
+ ruleset = new(tree.Ruleset)(null, rules);
4833
+ ruleset.originalRuleset = this;
4834
+ ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames)));
4835
+ if (important) {
4836
+ ruleset = this.parent.makeImportant.apply(ruleset);
4837
+ }
4838
+ return ruleset;
4839
+ },
4840
+ matchCondition: function (args, env) {
4841
+ if (this.condition && !this.condition.eval(
4842
+ new(tree.evalEnv)(env,
4843
+ [this.evalParams(env, new(tree.evalEnv)(env, this.frames ? this.frames.concat(env.frames) : env.frames), args, [])] // the parameter variables
4844
+ .concat(this.frames) // the parent namespace/mixin frames
4845
+ .concat(env.frames)))) { // the current environment frames
4846
+ return false;
4847
+ }
4848
+ return true;
4849
+ },
4850
+ matchArgs: function (args, env) {
4851
+ var argsLength = (args && args.length) || 0, len;
4852
+
4853
+ if (! this.variadic) {
4854
+ if (argsLength < this.required) { return false; }
4855
+ if (argsLength > this.params.length) { return false; }
4856
+ } else {
4857
+ if (argsLength < (this.required - 1)) { return false; }
4858
+ }
4859
+
4860
+ len = Math.min(argsLength, this.arity);
4861
+
4862
+ for (var i = 0; i < len; i++) {
4863
+ if (!this.params[i].name && !this.params[i].variadic) {
4864
+ if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) {
4865
+ return false;
4866
+ }
4867
+ }
4868
+ }
4869
+ return true;
4870
+ }
4871
+ };
4872
+
4873
+ })(require('../tree'));
4874
+
4875
+ (function (tree) {
4876
+
4877
+ tree.Negative = function (node) {
4878
+ this.value = node;
4879
+ };
4880
+ tree.Negative.prototype = {
4881
+ type: "Negative",
4882
+ accept: function (visitor) {
4883
+ this.value = visitor.visit(this.value);
4884
+ },
4885
+ genCSS: function (env, output) {
4886
+ output.add('-');
4887
+ this.value.genCSS(env, output);
4888
+ },
4889
+ toCSS: tree.toCSS,
4890
+ eval: function (env) {
4891
+ if (env.isMathOn()) {
4892
+ return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env);
4893
+ }
4894
+ return new(tree.Negative)(this.value.eval(env));
4895
+ }
4896
+ };
4897
+
4898
+ })(require('../tree'));
4899
+
4900
+ (function (tree) {
4901
+
4902
+ tree.Operation = function (op, operands, isSpaced) {
4903
+ this.op = op.trim();
4904
+ this.operands = operands;
4905
+ this.isSpaced = isSpaced;
4906
+ };
4907
+ tree.Operation.prototype = {
4908
+ type: "Operation",
4909
+ accept: function (visitor) {
4910
+ this.operands = visitor.visit(this.operands);
4911
+ },
4912
+ eval: function (env) {
4913
+ var a = this.operands[0].eval(env),
4914
+ b = this.operands[1].eval(env);
4915
+
4916
+ if (env.isMathOn()) {
4917
+ if (a instanceof tree.Dimension && b instanceof tree.Color) {
4918
+ a = a.toColor();
4919
+ }
4920
+ if (b instanceof tree.Dimension && a instanceof tree.Color) {
4921
+ b = b.toColor();
4922
+ }
4923
+ if (!a.operate) {
4924
+ throw { type: "Operation",
4925
+ message: "Operation on an invalid type" };
4926
+ }
4927
+
4928
+ return a.operate(env, this.op, b);
4929
+ } else {
4930
+ return new(tree.Operation)(this.op, [a, b], this.isSpaced);
4931
+ }
4932
+ },
4933
+ genCSS: function (env, output) {
4934
+ this.operands[0].genCSS(env, output);
4935
+ if (this.isSpaced) {
4936
+ output.add(" ");
4937
+ }
4938
+ output.add(this.op);
4939
+ if (this.isSpaced) {
4940
+ output.add(" ");
4941
+ }
4942
+ this.operands[1].genCSS(env, output);
4943
+ },
4944
+ toCSS: tree.toCSS
4945
+ };
4946
+
4947
+ tree.operate = function (env, op, a, b) {
4948
+ switch (op) {
4949
+ case '+': return a + b;
4950
+ case '-': return a - b;
4951
+ case '*': return a * b;
4952
+ case '/': return a / b;
4953
+ }
4954
+ };
4955
+
4956
+ })(require('../tree'));
4957
+
4958
+
4959
+ (function (tree) {
4960
+
4961
+ tree.Paren = function (node) {
4962
+ this.value = node;
4963
+ };
4964
+ tree.Paren.prototype = {
4965
+ type: "Paren",
4966
+ accept: function (visitor) {
4967
+ this.value = visitor.visit(this.value);
4968
+ },
4969
+ genCSS: function (env, output) {
4970
+ output.add('(');
4971
+ this.value.genCSS(env, output);
4972
+ output.add(')');
4973
+ },
4974
+ toCSS: tree.toCSS,
4975
+ eval: function (env) {
4976
+ return new(tree.Paren)(this.value.eval(env));
4977
+ }
4978
+ };
4979
+
4980
+ })(require('../tree'));
4981
+
4982
+ (function (tree) {
4983
+
4984
+ tree.Quoted = function (str, content, escaped, index, currentFileInfo) {
4985
+ this.escaped = escaped;
4986
+ this.value = content || '';
4987
+ this.quote = str.charAt(0);
4988
+ this.index = index;
4989
+ this.currentFileInfo = currentFileInfo;
4990
+ };
4991
+ tree.Quoted.prototype = {
4992
+ type: "Quoted",
4993
+ genCSS: function (env, output) {
4994
+ if (!this.escaped) {
4995
+ output.add(this.quote, this.currentFileInfo, this.index);
4996
+ }
4997
+ output.add(this.value);
4998
+ if (!this.escaped) {
4999
+ output.add(this.quote);
5000
+ }
5001
+ },
5002
+ toCSS: tree.toCSS,
5003
+ eval: function (env) {
5004
+ var that = this;
5005
+ var value = this.value.replace(/`([^`]+)`/g, function (_, exp) {
5006
+ return new(tree.JavaScript)(exp, that.index, true).eval(env).value;
5007
+ }).replace(/@\{([\w-]+)\}/g, function (_, name) {
5008
+ var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true);
5009
+ return (v instanceof tree.Quoted) ? v.value : v.toCSS();
5010
+ });
5011
+ return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
5012
+ },
5013
+ compare: function (x) {
5014
+ if (!x.toCSS) {
5015
+ return -1;
5016
+ }
5017
+
5018
+ var left, right;
5019
+
5020
+ // when comparing quoted strings allow the quote to differ
5021
+ if (x.type === "Quoted" && !this.escaped && !x.escaped) {
5022
+ left = x.value;
5023
+ right = this.value;
5024
+ } else {
5025
+ left = this.toCSS();
5026
+ right = x.toCSS();
5027
+ }
5028
+
5029
+ if (left === right) {
5030
+ return 0;
5031
+ }
5032
+
5033
+ return left < right ? -1 : 1;
5034
+ }
5035
+ };
5036
+
5037
+ })(require('../tree'));
5038
+
5039
+ (function (tree) {
5040
+
5041
+ tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) {
5042
+ this.name = name;
5043
+ this.value = (value instanceof tree.Value || value instanceof tree.Ruleset) ? value : new(tree.Value)([value]);
5044
+ this.important = important ? ' ' + important.trim() : '';
5045
+ this.merge = merge;
5046
+ this.index = index;
5047
+ this.currentFileInfo = currentFileInfo;
5048
+ this.inline = inline || false;
5049
+ this.variable = name.charAt && (name.charAt(0) === '@');
5050
+ };
5051
+
5052
+ tree.Rule.prototype = {
5053
+ type: "Rule",
5054
+ accept: function (visitor) {
5055
+ this.value = visitor.visit(this.value);
5056
+ },
5057
+ genCSS: function (env, output) {
5058
+ output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index);
5059
+ try {
5060
+ this.value.genCSS(env, output);
5061
+ }
5062
+ catch(e) {
5063
+ e.index = this.index;
5064
+ e.filename = this.currentFileInfo.filename;
5065
+ throw e;
5066
+ }
5067
+ output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index);
5068
+ },
5069
+ toCSS: tree.toCSS,
5070
+ eval: function (env) {
5071
+ var strictMathBypass = false, name = this.name, evaldValue;
5072
+ if (typeof name !== "string") {
5073
+ // expand 'primitive' name directly to get
5074
+ // things faster (~10% for benchmark.less):
5075
+ name = (name.length === 1)
5076
+ && (name[0] instanceof tree.Keyword)
5077
+ ? name[0].value : evalName(env, name);
5078
+ }
5079
+ if (name === "font" && !env.strictMath) {
5080
+ strictMathBypass = true;
5081
+ env.strictMath = true;
5082
+ }
5083
+ try {
5084
+ evaldValue = this.value.eval(env);
5085
+
5086
+ if (!this.variable && evaldValue.type === "DetachedRuleset") {
5087
+ throw { message: "Rulesets cannot be evaluated on a property.",
5088
+ index: this.index, filename: this.currentFileInfo.filename };
5089
+ }
5090
+
5091
+ return new(tree.Rule)(name,
5092
+ evaldValue,
5093
+ this.important,
5094
+ this.merge,
5095
+ this.index, this.currentFileInfo, this.inline);
5096
+ }
5097
+ catch(e) {
5098
+ if (typeof e.index !== 'number') {
5099
+ e.index = this.index;
5100
+ e.filename = this.currentFileInfo.filename;
5101
+ }
5102
+ throw e;
5103
+ }
5104
+ finally {
5105
+ if (strictMathBypass) {
5106
+ env.strictMath = false;
5107
+ }
5108
+ }
5109
+ },
5110
+ makeImportant: function () {
5111
+ return new(tree.Rule)(this.name,
5112
+ this.value,
5113
+ "!important",
5114
+ this.merge,
5115
+ this.index, this.currentFileInfo, this.inline);
5116
+ }
5117
+ };
5118
+
5119
+ function evalName(env, name) {
5120
+ var value = "", i, n = name.length,
5121
+ output = {add: function (s) {value += s;}};
5122
+ for (i = 0; i < n; i++) {
5123
+ name[i].eval(env).genCSS(env, output);
5124
+ }
5125
+ return value;
5126
+ }
5127
+
5128
+ })(require('../tree'));
5129
+
5130
+ (function (tree) {
5131
+
5132
+ tree.RulesetCall = function (variable) {
5133
+ this.variable = variable;
5134
+ };
5135
+ tree.RulesetCall.prototype = {
5136
+ type: "RulesetCall",
5137
+ accept: function (visitor) {
5138
+ },
5139
+ eval: function (env) {
5140
+ var detachedRuleset = new(tree.Variable)(this.variable).eval(env);
5141
+ return detachedRuleset.callEval(env);
5142
+ }
5143
+ };
5144
+
5145
+ })(require('../tree'));
5146
+
5147
+ (function (tree) {
5148
+
5149
+ tree.Ruleset = function (selectors, rules, strictImports) {
5150
+ this.selectors = selectors;
5151
+ this.rules = rules;
5152
+ this._lookups = {};
5153
+ this.strictImports = strictImports;
5154
+ };
5155
+ tree.Ruleset.prototype = {
5156
+ type: "Ruleset",
5157
+ accept: function (visitor) {
5158
+ if (this.paths) {
5159
+ visitor.visitArray(this.paths, true);
5160
+ } else if (this.selectors) {
5161
+ this.selectors = visitor.visitArray(this.selectors);
5162
+ }
5163
+ if (this.rules && this.rules.length) {
5164
+ this.rules = visitor.visitArray(this.rules);
5165
+ }
5166
+ },
5167
+ eval: function (env) {
5168
+ var thisSelectors = this.selectors, selectors,
5169
+ selCnt, selector, i, defaultFunc = tree.defaultFunc, hasOnePassingSelector = false;
5170
+
5171
+ if (thisSelectors && (selCnt = thisSelectors.length)) {
5172
+ selectors = [];
5173
+ defaultFunc.error({
5174
+ type: "Syntax",
5175
+ message: "it is currently only allowed in parametric mixin guards,"
5176
+ });
5177
+ for (i = 0; i < selCnt; i++) {
5178
+ selector = thisSelectors[i].eval(env);
5179
+ selectors.push(selector);
5180
+ if (selector.evaldCondition) {
5181
+ hasOnePassingSelector = true;
5182
+ }
5183
+ }
5184
+ defaultFunc.reset();
5185
+ } else {
5186
+ hasOnePassingSelector = true;
5187
+ }
5188
+
5189
+ var rules = this.rules ? this.rules.slice(0) : null,
5190
+ ruleset = new(tree.Ruleset)(selectors, rules, this.strictImports),
5191
+ rule, subRule;
5192
+
5193
+ ruleset.originalRuleset = this;
5194
+ ruleset.root = this.root;
5195
+ ruleset.firstRoot = this.firstRoot;
5196
+ ruleset.allowImports = this.allowImports;
5197
+
5198
+ if(this.debugInfo) {
5199
+ ruleset.debugInfo = this.debugInfo;
5200
+ }
5201
+
5202
+ if (!hasOnePassingSelector) {
5203
+ rules.length = 0;
5204
+ }
5205
+
5206
+ // push the current ruleset to the frames stack
5207
+ var envFrames = env.frames;
5208
+ envFrames.unshift(ruleset);
5209
+
5210
+ // currrent selectors
5211
+ var envSelectors = env.selectors;
5212
+ if (!envSelectors) {
5213
+ env.selectors = envSelectors = [];
5214
+ }
5215
+ envSelectors.unshift(this.selectors);
5216
+
5217
+ // Evaluate imports
5218
+ if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
5219
+ ruleset.evalImports(env);
5220
+ }
5221
+
5222
+ // Store the frames around mixin definitions,
5223
+ // so they can be evaluated like closures when the time comes.
5224
+ var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0;
5225
+ for (i = 0; i < rsRuleCnt; i++) {
5226
+ if (rsRules[i] instanceof tree.mixin.Definition || rsRules[i] instanceof tree.DetachedRuleset) {
5227
+ rsRules[i] = rsRules[i].eval(env);
5228
+ }
5229
+ }
5230
+
5231
+ var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0;
5232
+
5233
+ // Evaluate mixin calls.
5234
+ for (i = 0; i < rsRuleCnt; i++) {
5235
+ if (rsRules[i] instanceof tree.mixin.Call) {
5236
+ /*jshint loopfunc:true */
5237
+ rules = rsRules[i].eval(env).filter(function(r) {
5238
+ if ((r instanceof tree.Rule) && r.variable) {
5239
+ // do not pollute the scope if the variable is
5240
+ // already there. consider returning false here
5241
+ // but we need a way to "return" variable from mixins
5242
+ return !(ruleset.variable(r.name));
5243
+ }
5244
+ return true;
5245
+ });
5246
+ rsRules.splice.apply(rsRules, [i, 1].concat(rules));
5247
+ rsRuleCnt += rules.length - 1;
5248
+ i += rules.length-1;
5249
+ ruleset.resetCache();
5250
+ } else if (rsRules[i] instanceof tree.RulesetCall) {
5251
+ /*jshint loopfunc:true */
5252
+ rules = rsRules[i].eval(env).rules.filter(function(r) {
5253
+ if ((r instanceof tree.Rule) && r.variable) {
5254
+ // do not pollute the scope at all
5255
+ return false;
5256
+ }
5257
+ return true;
5258
+ });
5259
+ rsRules.splice.apply(rsRules, [i, 1].concat(rules));
5260
+ rsRuleCnt += rules.length - 1;
5261
+ i += rules.length-1;
5262
+ ruleset.resetCache();
5263
+ }
5264
+ }
5265
+
5266
+ // Evaluate everything else
5267
+ for (i = 0; i < rsRules.length; i++) {
5268
+ rule = rsRules[i];
5269
+ if (! (rule instanceof tree.mixin.Definition || rule instanceof tree.DetachedRuleset)) {
5270
+ rsRules[i] = rule = rule.eval ? rule.eval(env) : rule;
5271
+ }
5272
+ }
5273
+
5274
+ // Evaluate everything else
5275
+ for (i = 0; i < rsRules.length; i++) {
5276
+ rule = rsRules[i];
5277
+ // for rulesets, check if it is a css guard and can be removed
5278
+ if (rule instanceof tree.Ruleset && rule.selectors && rule.selectors.length === 1) {
5279
+ // check if it can be folded in (e.g. & where)
5280
+ if (rule.selectors[0].isJustParentSelector()) {
5281
+ rsRules.splice(i--, 1);
5282
+
5283
+ for(var j = 0; j < rule.rules.length; j++) {
5284
+ subRule = rule.rules[j];
5285
+ if (!(subRule instanceof tree.Rule) || !subRule.variable) {
5286
+ rsRules.splice(++i, 0, subRule);
5287
+ }
5288
+ }
5289
+ }
5290
+ }
5291
+ }
5292
+
5293
+ // Pop the stack
5294
+ envFrames.shift();
5295
+ envSelectors.shift();
5296
+
5297
+ if (env.mediaBlocks) {
5298
+ for (i = mediaBlockCount; i < env.mediaBlocks.length; i++) {
5299
+ env.mediaBlocks[i].bubbleSelectors(selectors);
5300
+ }
5301
+ }
5302
+
5303
+ return ruleset;
5304
+ },
5305
+ evalImports: function(env) {
5306
+ var rules = this.rules, i, importRules;
5307
+ if (!rules) { return; }
5308
+
5309
+ for (i = 0; i < rules.length; i++) {
5310
+ if (rules[i] instanceof tree.Import) {
5311
+ importRules = rules[i].eval(env);
5312
+ if (importRules && importRules.length) {
5313
+ rules.splice.apply(rules, [i, 1].concat(importRules));
5314
+ i+= importRules.length-1;
5315
+ } else {
5316
+ rules.splice(i, 1, importRules);
5317
+ }
5318
+ this.resetCache();
5319
+ }
5320
+ }
5321
+ },
5322
+ makeImportant: function() {
5323
+ return new tree.Ruleset(this.selectors, this.rules.map(function (r) {
5324
+ if (r.makeImportant) {
5325
+ return r.makeImportant();
5326
+ } else {
5327
+ return r;
5328
+ }
5329
+ }), this.strictImports);
5330
+ },
5331
+ matchArgs: function (args) {
5332
+ return !args || args.length === 0;
5333
+ },
5334
+ // lets you call a css selector with a guard
5335
+ matchCondition: function (args, env) {
5336
+ var lastSelector = this.selectors[this.selectors.length-1];
5337
+ if (!lastSelector.evaldCondition) {
5338
+ return false;
5339
+ }
5340
+ if (lastSelector.condition &&
5341
+ !lastSelector.condition.eval(
5342
+ new(tree.evalEnv)(env,
5343
+ env.frames))) {
5344
+ return false;
5345
+ }
5346
+ return true;
5347
+ },
5348
+ resetCache: function () {
5349
+ this._rulesets = null;
5350
+ this._variables = null;
5351
+ this._lookups = {};
5352
+ },
5353
+ variables: function () {
5354
+ if (!this._variables) {
5355
+ this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
5356
+ if (r instanceof tree.Rule && r.variable === true) {
5357
+ hash[r.name] = r;
5358
+ }
5359
+ return hash;
5360
+ }, {});
5361
+ }
5362
+ return this._variables;
5363
+ },
5364
+ variable: function (name) {
5365
+ return this.variables()[name];
5366
+ },
5367
+ rulesets: function () {
5368
+ if (!this.rules) { return null; }
5369
+
5370
+ var _Ruleset = tree.Ruleset, _MixinDefinition = tree.mixin.Definition,
5371
+ filtRules = [], rules = this.rules, cnt = rules.length,
5372
+ i, rule;
5373
+
5374
+ for (i = 0; i < cnt; i++) {
5375
+ rule = rules[i];
5376
+ if ((rule instanceof _Ruleset) || (rule instanceof _MixinDefinition)) {
5377
+ filtRules.push(rule);
5378
+ }
5379
+ }
5380
+
5381
+ return filtRules;
5382
+ },
5383
+ prependRule: function (rule) {
5384
+ var rules = this.rules;
5385
+ if (rules) { rules.unshift(rule); } else { this.rules = [ rule ]; }
5386
+ },
5387
+ find: function (selector, self) {
5388
+ self = self || this;
5389
+ var rules = [], match,
5390
+ key = selector.toCSS();
5391
+
5392
+ if (key in this._lookups) { return this._lookups[key]; }
5393
+
5394
+ this.rulesets().forEach(function (rule) {
5395
+ if (rule !== self) {
5396
+ for (var j = 0; j < rule.selectors.length; j++) {
5397
+ match = selector.match(rule.selectors[j]);
5398
+ if (match) {
5399
+ if (selector.elements.length > match) {
5400
+ Array.prototype.push.apply(rules, rule.find(
5401
+ new(tree.Selector)(selector.elements.slice(match)), self));
5402
+ } else {
5403
+ rules.push(rule);
5404
+ }
5405
+ break;
5406
+ }
5407
+ }
5408
+ }
5409
+ });
5410
+ this._lookups[key] = rules;
5411
+ return rules;
5412
+ },
5413
+ genCSS: function (env, output) {
5414
+ var i, j,
5415
+ ruleNodes = [],
5416
+ rulesetNodes = [],
5417
+ rulesetNodeCnt,
5418
+ debugInfo, // Line number debugging
5419
+ rule,
5420
+ path;
5421
+
5422
+ env.tabLevel = (env.tabLevel || 0);
5423
+
5424
+ if (!this.root) {
5425
+ env.tabLevel++;
5426
+ }
5427
+
5428
+ var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "),
5429
+ tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" "),
5430
+ sep;
5431
+
5432
+ for (i = 0; i < this.rules.length; i++) {
5433
+ rule = this.rules[i];
5434
+ if (rule.rules || (rule instanceof tree.Media) || rule instanceof tree.Directive || (this.root && rule instanceof tree.Comment)) {
5435
+ rulesetNodes.push(rule);
5436
+ } else {
5437
+ ruleNodes.push(rule);
5438
+ }
5439
+ }
5440
+
5441
+ // If this is the root node, we don't render
5442
+ // a selector, or {}.
5443
+ if (!this.root) {
5444
+ debugInfo = tree.debugInfo(env, this, tabSetStr);
5445
+
5446
+ if (debugInfo) {
5447
+ output.add(debugInfo);
5448
+ output.add(tabSetStr);
5449
+ }
5450
+
5451
+ var paths = this.paths, pathCnt = paths.length,
5452
+ pathSubCnt;
5453
+
5454
+ sep = env.compress ? ',' : (',\n' + tabSetStr);
5455
+
5456
+ for (i = 0; i < pathCnt; i++) {
5457
+ path = paths[i];
5458
+ if (!(pathSubCnt = path.length)) { continue; }
5459
+ if (i > 0) { output.add(sep); }
5460
+
5461
+ env.firstSelector = true;
5462
+ path[0].genCSS(env, output);
5463
+
5464
+ env.firstSelector = false;
5465
+ for (j = 1; j < pathSubCnt; j++) {
5466
+ path[j].genCSS(env, output);
5467
+ }
5468
+ }
5469
+
5470
+ output.add((env.compress ? '{' : ' {\n') + tabRuleStr);
5471
+ }
5472
+
5473
+ // Compile rules and rulesets
5474
+ for (i = 0; i < ruleNodes.length; i++) {
5475
+ rule = ruleNodes[i];
5476
+
5477
+ // @page{ directive ends up with root elements inside it, a mix of rules and rulesets
5478
+ // In this instance we do not know whether it is the last property
5479
+ if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) {
5480
+ env.lastRule = true;
5481
+ }
5482
+
5483
+ if (rule.genCSS) {
5484
+ rule.genCSS(env, output);
5485
+ } else if (rule.value) {
5486
+ output.add(rule.value.toString());
5487
+ }
5488
+
5489
+ if (!env.lastRule) {
5490
+ output.add(env.compress ? '' : ('\n' + tabRuleStr));
5491
+ } else {
5492
+ env.lastRule = false;
5493
+ }
5494
+ }
5495
+
5496
+ if (!this.root) {
5497
+ output.add((env.compress ? '}' : '\n' + tabSetStr + '}'));
5498
+ env.tabLevel--;
5499
+ }
5500
+
5501
+ sep = (env.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr);
5502
+ rulesetNodeCnt = rulesetNodes.length;
5503
+ if (rulesetNodeCnt) {
5504
+ if (ruleNodes.length && sep) { output.add(sep); }
5505
+ rulesetNodes[0].genCSS(env, output);
5506
+ for (i = 1; i < rulesetNodeCnt; i++) {
5507
+ if (sep) { output.add(sep); }
5508
+ rulesetNodes[i].genCSS(env, output);
5509
+ }
5510
+ }
5511
+
5512
+ if (!output.isEmpty() && !env.compress && this.firstRoot) {
5513
+ output.add('\n');
5514
+ }
5515
+ },
5516
+
5517
+ toCSS: tree.toCSS,
5518
+
5519
+ markReferenced: function () {
5520
+ if (!this.selectors) {
5521
+ return;
5522
+ }
5523
+ for (var s = 0; s < this.selectors.length; s++) {
5524
+ this.selectors[s].markReferenced();
5525
+ }
5526
+ },
5527
+
5528
+ joinSelectors: function (paths, context, selectors) {
5529
+ for (var s = 0; s < selectors.length; s++) {
5530
+ this.joinSelector(paths, context, selectors[s]);
5531
+ }
5532
+ },
5533
+
5534
+ joinSelector: function (paths, context, selector) {
5535
+
5536
+ var i, j, k,
5537
+ hasParentSelector, newSelectors, el, sel, parentSel,
5538
+ newSelectorPath, afterParentJoin, newJoinedSelector,
5539
+ newJoinedSelectorEmpty, lastSelector, currentElements,
5540
+ selectorsMultiplied;
5541
+
5542
+ for (i = 0; i < selector.elements.length; i++) {
5543
+ el = selector.elements[i];
5544
+ if (el.value === '&') {
5545
+ hasParentSelector = true;
5546
+ }
5547
+ }
5548
+
5549
+ if (!hasParentSelector) {
5550
+ if (context.length > 0) {
5551
+ for (i = 0; i < context.length; i++) {
5552
+ paths.push(context[i].concat(selector));
5553
+ }
5554
+ }
5555
+ else {
5556
+ paths.push([selector]);
5557
+ }
5558
+ return;
5559
+ }
5560
+
5561
+ // The paths are [[Selector]]
5562
+ // The first list is a list of comma seperated selectors
5563
+ // The inner list is a list of inheritance seperated selectors
5564
+ // e.g.
5565
+ // .a, .b {
5566
+ // .c {
5567
+ // }
5568
+ // }
5569
+ // == [[.a] [.c]] [[.b] [.c]]
5570
+ //
5571
+
5572
+ // the elements from the current selector so far
5573
+ currentElements = [];
5574
+ // the current list of new selectors to add to the path.
5575
+ // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
5576
+ // by the parents
5577
+ newSelectors = [[]];
5578
+
5579
+ for (i = 0; i < selector.elements.length; i++) {
5580
+ el = selector.elements[i];
5581
+ // non parent reference elements just get added
5582
+ if (el.value !== "&") {
5583
+ currentElements.push(el);
5584
+ } else {
5585
+ // the new list of selectors to add
5586
+ selectorsMultiplied = [];
5587
+
5588
+ // merge the current list of non parent selector elements
5589
+ // on to the current list of selectors to add
5590
+ if (currentElements.length > 0) {
5591
+ this.mergeElementsOnToSelectors(currentElements, newSelectors);
5592
+ }
5593
+
5594
+ // loop through our current selectors
5595
+ for (j = 0; j < newSelectors.length; j++) {
5596
+ sel = newSelectors[j];
5597
+ // if we don't have any parent paths, the & might be in a mixin so that it can be used
5598
+ // whether there are parents or not
5599
+ if (context.length === 0) {
5600
+ // the combinator used on el should now be applied to the next element instead so that
5601
+ // it is not lost
5602
+ if (sel.length > 0) {
5603
+ sel[0].elements = sel[0].elements.slice(0);
5604
+ sel[0].elements.push(new(tree.Element)(el.combinator, '', el.index, el.currentFileInfo));
5605
+ }
5606
+ selectorsMultiplied.push(sel);
5607
+ }
5608
+ else {
5609
+ // and the parent selectors
5610
+ for (k = 0; k < context.length; k++) {
5611
+ parentSel = context[k];
5612
+ // We need to put the current selectors
5613
+ // then join the last selector's elements on to the parents selectors
5614
+
5615
+ // our new selector path
5616
+ newSelectorPath = [];
5617
+ // selectors from the parent after the join
5618
+ afterParentJoin = [];
5619
+ newJoinedSelectorEmpty = true;
5620
+
5621
+ //construct the joined selector - if & is the first thing this will be empty,
5622
+ // if not newJoinedSelector will be the last set of elements in the selector
5623
+ if (sel.length > 0) {
5624
+ newSelectorPath = sel.slice(0);
5625
+ lastSelector = newSelectorPath.pop();
5626
+ newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
5627
+ newJoinedSelectorEmpty = false;
5628
+ }
5629
+ else {
5630
+ newJoinedSelector = selector.createDerived([]);
5631
+ }
5632
+
5633
+ //put together the parent selectors after the join
5634
+ if (parentSel.length > 1) {
5635
+ afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
5636
+ }
5637
+
5638
+ if (parentSel.length > 0) {
5639
+ newJoinedSelectorEmpty = false;
5640
+
5641
+ // join the elements so far with the first part of the parent
5642
+ newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, el.index, el.currentFileInfo));
5643
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
5644
+ }
5645
+
5646
+ if (!newJoinedSelectorEmpty) {
5647
+ // now add the joined selector
5648
+ newSelectorPath.push(newJoinedSelector);
5649
+ }
5650
+
5651
+ // and the rest of the parent
5652
+ newSelectorPath = newSelectorPath.concat(afterParentJoin);
5653
+
5654
+ // add that to our new set of selectors
5655
+ selectorsMultiplied.push(newSelectorPath);
5656
+ }
5657
+ }
5658
+ }
5659
+
5660
+ // our new selectors has been multiplied, so reset the state
5661
+ newSelectors = selectorsMultiplied;
5662
+ currentElements = [];
5663
+ }
5664
+ }
5665
+
5666
+ // if we have any elements left over (e.g. .a& .b == .b)
5667
+ // add them on to all the current selectors
5668
+ if (currentElements.length > 0) {
5669
+ this.mergeElementsOnToSelectors(currentElements, newSelectors);
5670
+ }
5671
+
5672
+ for (i = 0; i < newSelectors.length; i++) {
5673
+ if (newSelectors[i].length > 0) {
5674
+ paths.push(newSelectors[i]);
5675
+ }
5676
+ }
5677
+ },
5678
+
5679
+ mergeElementsOnToSelectors: function(elements, selectors) {
5680
+ var i, sel;
5681
+
5682
+ if (selectors.length === 0) {
5683
+ selectors.push([ new(tree.Selector)(elements) ]);
5684
+ return;
5685
+ }
5686
+
5687
+ for (i = 0; i < selectors.length; i++) {
5688
+ sel = selectors[i];
5689
+
5690
+ // if the previous thing in sel is a parent this needs to join on to it
5691
+ if (sel.length > 0) {
5692
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
5693
+ }
5694
+ else {
5695
+ sel.push(new(tree.Selector)(elements));
5696
+ }
5697
+ }
5698
+ }
5699
+ };
5700
+ })(require('../tree'));
5701
+
5702
+ (function (tree) {
5703
+
5704
+ tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
5705
+ this.elements = elements;
5706
+ this.extendList = extendList;
5707
+ this.condition = condition;
5708
+ this.currentFileInfo = currentFileInfo || {};
5709
+ this.isReferenced = isReferenced;
5710
+ if (!condition) {
5711
+ this.evaldCondition = true;
5712
+ }
5713
+ };
5714
+ tree.Selector.prototype = {
5715
+ type: "Selector",
5716
+ accept: function (visitor) {
5717
+ if (this.elements) {
5718
+ this.elements = visitor.visitArray(this.elements);
5719
+ }
5720
+ if (this.extendList) {
5721
+ this.extendList = visitor.visitArray(this.extendList);
5722
+ }
5723
+ if (this.condition) {
5724
+ this.condition = visitor.visit(this.condition);
5725
+ }
5726
+ },
5727
+ createDerived: function(elements, extendList, evaldCondition) {
5728
+ evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
5729
+ var newSelector = new(tree.Selector)(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced);
5730
+ newSelector.evaldCondition = evaldCondition;
5731
+ newSelector.mediaEmpty = this.mediaEmpty;
5732
+ return newSelector;
5733
+ },
5734
+ match: function (other) {
5735
+ var elements = this.elements,
5736
+ len = elements.length,
5737
+ olen, i;
5738
+
5739
+ other.CacheElements();
5740
+
5741
+ olen = other._elements.length;
5742
+ if (olen === 0 || len < olen) {
5743
+ return 0;
5744
+ } else {
5745
+ for (i = 0; i < olen; i++) {
5746
+ if (elements[i].value !== other._elements[i]) {
5747
+ return 0;
5748
+ }
5749
+ }
5750
+ }
5751
+
5752
+ return olen; // return number of matched elements
5753
+ },
5754
+ CacheElements: function(){
5755
+ var css = '', len, v, i;
5756
+
5757
+ if( !this._elements ){
5758
+
5759
+ len = this.elements.length;
5760
+ for(i = 0; i < len; i++){
5761
+
5762
+ v = this.elements[i];
5763
+ css += v.combinator.value;
5764
+
5765
+ if( !v.value.value ){
5766
+ css += v.value;
5767
+ continue;
5768
+ }
5769
+
5770
+ if( typeof v.value.value !== "string" ){
5771
+ css = '';
5772
+ break;
5773
+ }
5774
+ css += v.value.value;
5775
+ }
5776
+
5777
+ this._elements = css.match(/[,&#\.\w-]([\w-]|(\\.))*/g);
5778
+
5779
+ if (this._elements) {
5780
+ if (this._elements[0] === "&") {
5781
+ this._elements.shift();
5782
+ }
5783
+
5784
+ } else {
5785
+ this._elements = [];
5786
+ }
5787
+
5788
+ }
5789
+ },
5790
+ isJustParentSelector: function() {
5791
+ return !this.mediaEmpty &&
5792
+ this.elements.length === 1 &&
5793
+ this.elements[0].value === '&' &&
5794
+ (this.elements[0].combinator.value === ' ' || this.elements[0].combinator.value === '');
5795
+ },
5796
+ eval: function (env) {
5797
+ var evaldCondition = this.condition && this.condition.eval(env),
5798
+ elements = this.elements, extendList = this.extendList;
5799
+
5800
+ elements = elements && elements.map(function (e) { return e.eval(env); });
5801
+ extendList = extendList && extendList.map(function(extend) { return extend.eval(env); });
5802
+
5803
+ return this.createDerived(elements, extendList, evaldCondition);
5804
+ },
5805
+ genCSS: function (env, output) {
5806
+ var i, element;
5807
+ if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") {
5808
+ output.add(' ', this.currentFileInfo, this.index);
5809
+ }
5810
+ if (!this._css) {
5811
+ //TODO caching? speed comparison?
5812
+ for(i = 0; i < this.elements.length; i++) {
5813
+ element = this.elements[i];
5814
+ element.genCSS(env, output);
5815
+ }
5816
+ }
5817
+ },
5818
+ toCSS: tree.toCSS,
5819
+ markReferenced: function () {
5820
+ this.isReferenced = true;
5821
+ },
5822
+ getIsReferenced: function() {
5823
+ return !this.currentFileInfo.reference || this.isReferenced;
5824
+ },
5825
+ getIsOutput: function() {
5826
+ return this.evaldCondition;
5827
+ }
5828
+ };
5829
+
5830
+ })(require('../tree'));
5831
+
5832
+ (function (tree) {
5833
+
5834
+ tree.UnicodeDescriptor = function (value) {
5835
+ this.value = value;
5836
+ };
5837
+ tree.UnicodeDescriptor.prototype = {
5838
+ type: "UnicodeDescriptor",
5839
+ genCSS: function (env, output) {
5840
+ output.add(this.value);
5841
+ },
5842
+ toCSS: tree.toCSS,
5843
+ eval: function () { return this; }
5844
+ };
5845
+
5846
+ })(require('../tree'));
5847
+
5848
+ (function (tree) {
5849
+
5850
+ tree.URL = function (val, currentFileInfo, isEvald) {
5851
+ this.value = val;
5852
+ this.currentFileInfo = currentFileInfo;
5853
+ this.isEvald = isEvald;
5854
+ };
5855
+ tree.URL.prototype = {
5856
+ type: "Url",
5857
+ accept: function (visitor) {
5858
+ this.value = visitor.visit(this.value);
5859
+ },
5860
+ genCSS: function (env, output) {
5861
+ output.add("url(");
5862
+ this.value.genCSS(env, output);
5863
+ output.add(")");
5864
+ },
5865
+ toCSS: tree.toCSS,
5866
+ eval: function (ctx) {
5867
+ var val = this.value.eval(ctx),
5868
+ rootpath;
5869
+
5870
+ if (!this.isEvald) {
5871
+ // Add the base path if the URL is relative
5872
+ rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
5873
+ if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) {
5874
+ if (!val.quote) {
5875
+ rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
5876
+ }
5877
+ val.value = rootpath + val.value;
5878
+ }
5879
+
5880
+ val.value = ctx.normalizePath(val.value);
5881
+
5882
+ // Add url args if enabled
5883
+ if (ctx.urlArgs) {
5884
+ if (!val.value.match(/^\s*data:/)) {
5885
+ var delimiter = val.value.indexOf('?') === -1 ? '?' : '&';
5886
+ var urlArgs = delimiter + ctx.urlArgs;
5887
+ if (val.value.indexOf('#') !== -1) {
5888
+ val.value = val.value.replace('#', urlArgs + '#');
5889
+ } else {
5890
+ val.value += urlArgs;
5891
+ }
5892
+ }
5893
+ }
5894
+ }
5895
+
5896
+ return new(tree.URL)(val, this.currentFileInfo, true);
5897
+ }
5898
+ };
5899
+
5900
+ })(require('../tree'));
5901
+
5902
+ (function (tree) {
5903
+
5904
+ tree.Value = function (value) {
5905
+ this.value = value;
5906
+ };
5907
+ tree.Value.prototype = {
5908
+ type: "Value",
5909
+ accept: function (visitor) {
5910
+ if (this.value) {
5911
+ this.value = visitor.visitArray(this.value);
5912
+ }
5913
+ },
5914
+ eval: function (env) {
5915
+ if (this.value.length === 1) {
5916
+ return this.value[0].eval(env);
5917
+ } else {
5918
+ return new(tree.Value)(this.value.map(function (v) {
5919
+ return v.eval(env);
5920
+ }));
5921
+ }
5922
+ },
5923
+ genCSS: function (env, output) {
5924
+ var i;
5925
+ for(i = 0; i < this.value.length; i++) {
5926
+ this.value[i].genCSS(env, output);
5927
+ if (i+1 < this.value.length) {
5928
+ output.add((env && env.compress) ? ',' : ', ');
5929
+ }
5930
+ }
5931
+ },
5932
+ toCSS: tree.toCSS
5933
+ };
5934
+
5935
+ })(require('../tree'));
5936
+
5937
+ (function (tree) {
5938
+
5939
+ tree.Variable = function (name, index, currentFileInfo) {
5940
+ this.name = name;
5941
+ this.index = index;
5942
+ this.currentFileInfo = currentFileInfo || {};
5943
+ };
5944
+ tree.Variable.prototype = {
5945
+ type: "Variable",
5946
+ eval: function (env) {
5947
+ var variable, name = this.name;
5948
+
5949
+ if (name.indexOf('@@') === 0) {
5950
+ name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value;
5951
+ }
5952
+
5953
+ if (this.evaluating) {
5954
+ throw { type: 'Name',
5955
+ message: "Recursive variable definition for " + name,
5956
+ filename: this.currentFileInfo.file,
5957
+ index: this.index };
5958
+ }
5959
+
5960
+ this.evaluating = true;
5961
+
5962
+ variable = tree.find(env.frames, function (frame) {
5963
+ var v = frame.variable(name);
5964
+ if (v) {
5965
+ return v.value.eval(env);
5966
+ }
5967
+ });
5968
+ if (variable) {
5969
+ this.evaluating = false;
5970
+ return variable;
5971
+ } else {
5972
+ throw { type: 'Name',
5973
+ message: "variable " + name + " is undefined",
5974
+ filename: this.currentFileInfo.filename,
5975
+ index: this.index };
5976
+ }
5977
+ }
5978
+ };
5979
+
5980
+ })(require('../tree'));
5981
+
5982
+ (function (tree) {
5983
+
5984
+ var parseCopyProperties = [
5985
+ 'paths', // option - unmodified - paths to search for imports on
5986
+ 'optimization', // option - optimization level (for the chunker)
5987
+ 'files', // list of files that have been imported, used for import-once
5988
+ 'contents', // map - filename to contents of all the files
5989
+ 'contentsIgnoredChars', // map - filename to lines at the begining of each file to ignore
5990
+ 'relativeUrls', // option - whether to adjust URL's to be relative
5991
+ 'rootpath', // option - rootpath to append to URL's
5992
+ 'strictImports', // option -
5993
+ 'insecure', // option - whether to allow imports from insecure ssl hosts
5994
+ 'dumpLineNumbers', // option - whether to dump line numbers
5995
+ 'compress', // option - whether to compress
5996
+ 'processImports', // option - whether to process imports. if false then imports will not be imported
5997
+ 'syncImport', // option - whether to import synchronously
5998
+ 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
5999
+ 'mime', // browser only - mime type for sheet import
6000
+ 'useFileCache', // browser only - whether to use the per file session cache
6001
+ 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc.
6002
+ ];
6003
+
6004
+ //currentFileInfo = {
6005
+ // 'relativeUrls' - option - whether to adjust URL's to be relative
6006
+ // 'filename' - full resolved filename of current file
6007
+ // 'rootpath' - path to append to normal URLs for this node
6008
+ // 'currentDirectory' - path to the current file, absolute
6009
+ // 'rootFilename' - filename of the base file
6010
+ // 'entryPath' - absolute path to the entry file
6011
+ // 'reference' - whether the file should not be output and only output parts that are referenced
6012
+
6013
+ tree.parseEnv = function(options) {
6014
+ copyFromOriginal(options, this, parseCopyProperties);
6015
+
6016
+ if (!this.contents) { this.contents = {}; }
6017
+ if (!this.contentsIgnoredChars) { this.contentsIgnoredChars = {}; }
6018
+ if (!this.files) { this.files = {}; }
6019
+
6020
+ if (typeof this.paths === "string") { this.paths = [this.paths]; }
6021
+
6022
+ if (!this.currentFileInfo) {
6023
+ var filename = (options && options.filename) || "input";
6024
+ var entryPath = filename.replace(/[^\/\\]*$/, "");
6025
+ if (options) {
6026
+ options.filename = null;
6027
+ }
6028
+ this.currentFileInfo = {
6029
+ filename: filename,
6030
+ relativeUrls: this.relativeUrls,
6031
+ rootpath: (options && options.rootpath) || "",
6032
+ currentDirectory: entryPath,
6033
+ entryPath: entryPath,
6034
+ rootFilename: filename
6035
+ };
6036
+ }
6037
+ };
6038
+
6039
+ var evalCopyProperties = [
6040
+ 'silent', // whether to swallow errors and warnings
6041
+ 'verbose', // whether to log more activity
6042
+ 'compress', // whether to compress
6043
+ 'yuicompress', // whether to compress with the outside tool yui compressor
6044
+ 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
6045
+ 'strictMath', // whether math has to be within parenthesis
6046
+ 'strictUnits', // whether units need to evaluate correctly
6047
+ 'cleancss', // whether to compress with clean-css
6048
+ 'sourceMap', // whether to output a source map
6049
+ 'importMultiple', // whether we are currently importing multiple copies
6050
+ 'urlArgs' // whether to add args into url tokens
6051
+ ];
6052
+
6053
+ tree.evalEnv = function(options, frames) {
6054
+ copyFromOriginal(options, this, evalCopyProperties);
6055
+
6056
+ this.frames = frames || [];
6057
+ };
6058
+
6059
+ tree.evalEnv.prototype.inParenthesis = function () {
6060
+ if (!this.parensStack) {
6061
+ this.parensStack = [];
6062
+ }
6063
+ this.parensStack.push(true);
6064
+ };
6065
+
6066
+ tree.evalEnv.prototype.outOfParenthesis = function () {
6067
+ this.parensStack.pop();
6068
+ };
6069
+
6070
+ tree.evalEnv.prototype.isMathOn = function () {
6071
+ return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
6072
+ };
6073
+
6074
+ tree.evalEnv.prototype.isPathRelative = function (path) {
6075
+ return !/^(?:[a-z-]+:|\/)/.test(path);
6076
+ };
6077
+
6078
+ tree.evalEnv.prototype.normalizePath = function( path ) {
6079
+ var
6080
+ segments = path.split("/").reverse(),
6081
+ segment;
6082
+
6083
+ path = [];
6084
+ while (segments.length !== 0 ) {
6085
+ segment = segments.pop();
6086
+ switch( segment ) {
6087
+ case ".":
6088
+ break;
6089
+ case "..":
6090
+ if ((path.length === 0) || (path[path.length - 1] === "..")) {
6091
+ path.push( segment );
6092
+ } else {
6093
+ path.pop();
6094
+ }
6095
+ break;
6096
+ default:
6097
+ path.push( segment );
6098
+ break;
6099
+ }
6100
+ }
6101
+
6102
+ return path.join("/");
6103
+ };
6104
+
6105
+ //todo - do the same for the toCSS env
6106
+ //tree.toCSSEnv = function (options) {
6107
+ //};
6108
+
6109
+ var copyFromOriginal = function(original, destination, propertiesToCopy) {
6110
+ if (!original) { return; }
6111
+
6112
+ for(var i = 0; i < propertiesToCopy.length; i++) {
6113
+ if (original.hasOwnProperty(propertiesToCopy[i])) {
6114
+ destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
6115
+ }
6116
+ }
6117
+ };
6118
+
6119
+ })(require('./tree'));
6120
+
6121
+ (function (tree) {
6122
+
6123
+ var _visitArgs = { visitDeeper: true },
6124
+ _hasIndexed = false;
6125
+
6126
+ function _noop(node) {
6127
+ return node;
6128
+ }
6129
+
6130
+ function indexNodeTypes(parent, ticker) {
6131
+ // add .typeIndex to tree node types for lookup table
6132
+ var key, child;
6133
+ for (key in parent) {
6134
+ if (parent.hasOwnProperty(key)) {
6135
+ child = parent[key];
6136
+ switch (typeof child) {
6137
+ case "function":
6138
+ // ignore bound functions directly on tree which do not have a prototype
6139
+ // or aren't nodes
6140
+ if (child.prototype && child.prototype.type) {
6141
+ child.prototype.typeIndex = ticker++;
6142
+ }
6143
+ break;
6144
+ case "object":
6145
+ ticker = indexNodeTypes(child, ticker);
6146
+ break;
6147
+ }
6148
+ }
6149
+ }
6150
+ return ticker;
6151
+ }
6152
+
6153
+ tree.visitor = function(implementation) {
6154
+ this._implementation = implementation;
6155
+ this._visitFnCache = [];
6156
+
6157
+ if (!_hasIndexed) {
6158
+ indexNodeTypes(tree, 1);
6159
+ _hasIndexed = true;
6160
+ }
6161
+ };
6162
+
6163
+ tree.visitor.prototype = {
6164
+ visit: function(node) {
6165
+ if (!node) {
6166
+ return node;
6167
+ }
6168
+
6169
+ var nodeTypeIndex = node.typeIndex;
6170
+ if (!nodeTypeIndex) {
6171
+ return node;
6172
+ }
6173
+
6174
+ var visitFnCache = this._visitFnCache,
6175
+ impl = this._implementation,
6176
+ aryIndx = nodeTypeIndex << 1,
6177
+ outAryIndex = aryIndx | 1,
6178
+ func = visitFnCache[aryIndx],
6179
+ funcOut = visitFnCache[outAryIndex],
6180
+ visitArgs = _visitArgs,
6181
+ fnName;
6182
+
6183
+ visitArgs.visitDeeper = true;
6184
+
6185
+ if (!func) {
6186
+ fnName = "visit" + node.type;
6187
+ func = impl[fnName] || _noop;
6188
+ funcOut = impl[fnName + "Out"] || _noop;
6189
+ visitFnCache[aryIndx] = func;
6190
+ visitFnCache[outAryIndex] = funcOut;
6191
+ }
6192
+
6193
+ if (func !== _noop) {
6194
+ var newNode = func.call(impl, node, visitArgs);
6195
+ if (impl.isReplacing) {
6196
+ node = newNode;
6197
+ }
6198
+ }
6199
+
6200
+ if (visitArgs.visitDeeper && node && node.accept) {
6201
+ node.accept(this);
6202
+ }
6203
+
6204
+ if (funcOut != _noop) {
6205
+ funcOut.call(impl, node);
6206
+ }
6207
+
6208
+ return node;
6209
+ },
6210
+ visitArray: function(nodes, nonReplacing) {
6211
+ if (!nodes) {
6212
+ return nodes;
6213
+ }
6214
+
6215
+ var cnt = nodes.length, i;
6216
+
6217
+ // Non-replacing
6218
+ if (nonReplacing || !this._implementation.isReplacing) {
6219
+ for (i = 0; i < cnt; i++) {
6220
+ this.visit(nodes[i]);
6221
+ }
6222
+ return nodes;
6223
+ }
6224
+
6225
+ // Replacing
6226
+ var out = [];
6227
+ for (i = 0; i < cnt; i++) {
6228
+ var evald = this.visit(nodes[i]);
6229
+ if (!evald.splice) {
6230
+ out.push(evald);
6231
+ } else if (evald.length) {
6232
+ this.flatten(evald, out);
6233
+ }
6234
+ }
6235
+ return out;
6236
+ },
6237
+ flatten: function(arr, out) {
6238
+ if (!out) {
6239
+ out = [];
6240
+ }
6241
+
6242
+ var cnt, i, item,
6243
+ nestedCnt, j, nestedItem;
6244
+
6245
+ for (i = 0, cnt = arr.length; i < cnt; i++) {
6246
+ item = arr[i];
6247
+ if (!item.splice) {
6248
+ out.push(item);
6249
+ continue;
6250
+ }
6251
+
6252
+ for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
6253
+ nestedItem = item[j];
6254
+ if (!nestedItem.splice) {
6255
+ out.push(nestedItem);
6256
+ } else if (nestedItem.length) {
6257
+ this.flatten(nestedItem, out);
6258
+ }
6259
+ }
6260
+ }
6261
+
6262
+ return out;
6263
+ }
6264
+ };
6265
+
6266
+ })(require('./tree'));
6267
+ (function (tree) {
6268
+ tree.importVisitor = function(importer, finish, evalEnv, onceFileDetectionMap, recursionDetector) {
6269
+ this._visitor = new tree.visitor(this);
6270
+ this._importer = importer;
6271
+ this._finish = finish;
6272
+ this.env = evalEnv || new tree.evalEnv();
6273
+ this.importCount = 0;
6274
+ this.onceFileDetectionMap = onceFileDetectionMap || {};
6275
+ this.recursionDetector = {};
6276
+ if (recursionDetector) {
6277
+ for(var fullFilename in recursionDetector) {
6278
+ if (recursionDetector.hasOwnProperty(fullFilename)) {
6279
+ this.recursionDetector[fullFilename] = true;
6280
+ }
6281
+ }
6282
+ }
6283
+ };
6284
+
6285
+ tree.importVisitor.prototype = {
6286
+ isReplacing: true,
6287
+ run: function (root) {
6288
+ var error;
6289
+ try {
6290
+ // process the contents
6291
+ this._visitor.visit(root);
6292
+ }
6293
+ catch(e) {
6294
+ error = e;
6295
+ }
6296
+
6297
+ this.isFinished = true;
6298
+
6299
+ if (this.importCount === 0) {
6300
+ this._finish(error);
6301
+ }
6302
+ },
6303
+ visitImport: function (importNode, visitArgs) {
6304
+ var importVisitor = this,
6305
+ evaldImportNode,
6306
+ inlineCSS = importNode.options.inline;
6307
+
6308
+ if (!importNode.css || inlineCSS) {
6309
+
6310
+ try {
6311
+ evaldImportNode = importNode.evalForImport(this.env);
6312
+ } catch(e){
6313
+ if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
6314
+ // attempt to eval properly and treat as css
6315
+ importNode.css = true;
6316
+ // if that fails, this error will be thrown
6317
+ importNode.error = e;
6318
+ }
6319
+
6320
+ if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
6321
+ importNode = evaldImportNode;
6322
+ this.importCount++;
6323
+ var env = new tree.evalEnv(this.env, this.env.frames.slice(0));
6324
+
6325
+ if (importNode.options.multiple) {
6326
+ env.importMultiple = true;
6327
+ }
6328
+
6329
+ this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, importedAtRoot, fullPath) {
6330
+ if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
6331
+
6332
+ if (!env.importMultiple) {
6333
+ if (importedAtRoot) {
6334
+ importNode.skip = true;
6335
+ } else {
6336
+ importNode.skip = function() {
6337
+ if (fullPath in importVisitor.onceFileDetectionMap) {
6338
+ return true;
6339
+ }
6340
+ importVisitor.onceFileDetectionMap[fullPath] = true;
6341
+ return false;
6342
+ };
6343
+ }
6344
+ }
6345
+
6346
+ var subFinish = function(e) {
6347
+ importVisitor.importCount--;
6348
+
6349
+ if (importVisitor.importCount === 0 && importVisitor.isFinished) {
6350
+ importVisitor._finish(e);
6351
+ }
6352
+ };
6353
+
6354
+ if (root) {
6355
+ importNode.root = root;
6356
+ importNode.importedFilename = fullPath;
6357
+ var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
6358
+
6359
+ if (!inlineCSS && (env.importMultiple || !duplicateImport)) {
6360
+ importVisitor.recursionDetector[fullPath] = true;
6361
+ new(tree.importVisitor)(importVisitor._importer, subFinish, env, importVisitor.onceFileDetectionMap, importVisitor.recursionDetector)
6362
+ .run(root);
6363
+ return;
6364
+ }
6365
+ }
6366
+
6367
+ subFinish();
6368
+ });
6369
+ }
6370
+ }
6371
+ visitArgs.visitDeeper = false;
6372
+ return importNode;
6373
+ },
6374
+ visitRule: function (ruleNode, visitArgs) {
6375
+ visitArgs.visitDeeper = false;
6376
+ return ruleNode;
6377
+ },
6378
+ visitDirective: function (directiveNode, visitArgs) {
6379
+ this.env.frames.unshift(directiveNode);
6380
+ return directiveNode;
6381
+ },
6382
+ visitDirectiveOut: function (directiveNode) {
6383
+ this.env.frames.shift();
6384
+ },
6385
+ visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
6386
+ this.env.frames.unshift(mixinDefinitionNode);
6387
+ return mixinDefinitionNode;
6388
+ },
6389
+ visitMixinDefinitionOut: function (mixinDefinitionNode) {
6390
+ this.env.frames.shift();
6391
+ },
6392
+ visitRuleset: function (rulesetNode, visitArgs) {
6393
+ this.env.frames.unshift(rulesetNode);
6394
+ return rulesetNode;
6395
+ },
6396
+ visitRulesetOut: function (rulesetNode) {
6397
+ this.env.frames.shift();
6398
+ },
6399
+ visitMedia: function (mediaNode, visitArgs) {
6400
+ this.env.frames.unshift(mediaNode.ruleset);
6401
+ return mediaNode;
6402
+ },
6403
+ visitMediaOut: function (mediaNode) {
6404
+ this.env.frames.shift();
6405
+ }
6406
+ };
6407
+
6408
+ })(require('./tree'));
6409
+ (function (tree) {
6410
+ tree.joinSelectorVisitor = function() {
6411
+ this.contexts = [[]];
6412
+ this._visitor = new tree.visitor(this);
6413
+ };
6414
+
6415
+ tree.joinSelectorVisitor.prototype = {
6416
+ run: function (root) {
6417
+ return this._visitor.visit(root);
6418
+ },
6419
+ visitRule: function (ruleNode, visitArgs) {
6420
+ visitArgs.visitDeeper = false;
6421
+ },
6422
+ visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
6423
+ visitArgs.visitDeeper = false;
6424
+ },
6425
+
6426
+ visitRuleset: function (rulesetNode, visitArgs) {
6427
+ var context = this.contexts[this.contexts.length - 1],
6428
+ paths = [], selectors;
6429
+
6430
+ this.contexts.push(paths);
6431
+
6432
+ if (! rulesetNode.root) {
6433
+ selectors = rulesetNode.selectors;
6434
+ if (selectors) {
6435
+ selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
6436
+ rulesetNode.selectors = selectors.length ? selectors : (selectors = null);
6437
+ if (selectors) { rulesetNode.joinSelectors(paths, context, selectors); }
6438
+ }
6439
+ if (!selectors) { rulesetNode.rules = null; }
6440
+ rulesetNode.paths = paths;
6441
+ }
6442
+ },
6443
+ visitRulesetOut: function (rulesetNode) {
6444
+ this.contexts.length = this.contexts.length - 1;
6445
+ },
6446
+ visitMedia: function (mediaNode, visitArgs) {
6447
+ var context = this.contexts[this.contexts.length - 1];
6448
+ mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
6449
+ }
6450
+ };
6451
+
6452
+ })(require('./tree'));
6453
+ (function (tree) {
6454
+ tree.toCSSVisitor = function(env) {
6455
+ this._visitor = new tree.visitor(this);
6456
+ this._env = env;
6457
+ };
6458
+
6459
+ tree.toCSSVisitor.prototype = {
6460
+ isReplacing: true,
6461
+ run: function (root) {
6462
+ return this._visitor.visit(root);
6463
+ },
6464
+
6465
+ visitRule: function (ruleNode, visitArgs) {
6466
+ if (ruleNode.variable) {
6467
+ return [];
6468
+ }
6469
+ return ruleNode;
6470
+ },
6471
+
6472
+ visitMixinDefinition: function (mixinNode, visitArgs) {
6473
+ // mixin definitions do not get eval'd - this means they keep state
6474
+ // so we have to clear that state here so it isn't used if toCSS is called twice
6475
+ mixinNode.frames = [];
6476
+ return [];
6477
+ },
6478
+
6479
+ visitExtend: function (extendNode, visitArgs) {
6480
+ return [];
6481
+ },
6482
+
6483
+ visitComment: function (commentNode, visitArgs) {
6484
+ if (commentNode.isSilent(this._env)) {
6485
+ return [];
6486
+ }
6487
+ return commentNode;
6488
+ },
6489
+
6490
+ visitMedia: function(mediaNode, visitArgs) {
6491
+ mediaNode.accept(this._visitor);
6492
+ visitArgs.visitDeeper = false;
6493
+
6494
+ if (!mediaNode.rules.length) {
6495
+ return [];
6496
+ }
6497
+ return mediaNode;
6498
+ },
6499
+
6500
+ visitDirective: function(directiveNode, visitArgs) {
6501
+ if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
6502
+ return [];
6503
+ }
6504
+ if (directiveNode.name === "@charset") {
6505
+ // Only output the debug info together with subsequent @charset definitions
6506
+ // a comment (or @media statement) before the actual @charset directive would
6507
+ // be considered illegal css as it has to be on the first line
6508
+ if (this.charset) {
6509
+ if (directiveNode.debugInfo) {
6510
+ var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n");
6511
+ comment.debugInfo = directiveNode.debugInfo;
6512
+ return this._visitor.visit(comment);
6513
+ }
6514
+ return [];
6515
+ }
6516
+ this.charset = true;
6517
+ }
6518
+ return directiveNode;
6519
+ },
6520
+
6521
+ checkPropertiesInRoot: function(rules) {
6522
+ var ruleNode;
6523
+ for(var i = 0; i < rules.length; i++) {
6524
+ ruleNode = rules[i];
6525
+ if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
6526
+ throw { message: "properties must be inside selector blocks, they cannot be in the root.",
6527
+ index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
6528
+ }
6529
+ }
6530
+ },
6531
+
6532
+ visitRuleset: function (rulesetNode, visitArgs) {
6533
+ var rule, rulesets = [];
6534
+ if (rulesetNode.firstRoot) {
6535
+ this.checkPropertiesInRoot(rulesetNode.rules);
6536
+ }
6537
+ if (! rulesetNode.root) {
6538
+ if (rulesetNode.paths) {
6539
+ rulesetNode.paths = rulesetNode.paths
6540
+ .filter(function(p) {
6541
+ var i;
6542
+ if (p[0].elements[0].combinator.value === ' ') {
6543
+ p[0].elements[0].combinator = new(tree.Combinator)('');
6544
+ }
6545
+ for(i = 0; i < p.length; i++) {
6546
+ if (p[i].getIsReferenced() && p[i].getIsOutput()) {
6547
+ return true;
6548
+ }
6549
+ }
6550
+ return false;
6551
+ });
6552
+ }
6553
+
6554
+ // Compile rules and rulesets
6555
+ var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0;
6556
+ for (var i = 0; i < nodeRuleCnt; ) {
6557
+ rule = nodeRules[i];
6558
+ if (rule && rule.rules) {
6559
+ // visit because we are moving them out from being a child
6560
+ rulesets.push(this._visitor.visit(rule));
6561
+ nodeRules.splice(i, 1);
6562
+ nodeRuleCnt--;
6563
+ continue;
6564
+ }
6565
+ i++;
6566
+ }
6567
+ // accept the visitor to remove rules and refactor itself
6568
+ // then we can decide now whether we want it or not
6569
+ if (nodeRuleCnt > 0) {
6570
+ rulesetNode.accept(this._visitor);
6571
+ } else {
6572
+ rulesetNode.rules = null;
6573
+ }
6574
+ visitArgs.visitDeeper = false;
6575
+
6576
+ nodeRules = rulesetNode.rules;
6577
+ if (nodeRules) {
6578
+ this._mergeRules(nodeRules);
6579
+ nodeRules = rulesetNode.rules;
6580
+ }
6581
+ if (nodeRules) {
6582
+ this._removeDuplicateRules(nodeRules);
6583
+ nodeRules = rulesetNode.rules;
6584
+ }
6585
+
6586
+ // now decide whether we keep the ruleset
6587
+ if (nodeRules && nodeRules.length > 0 && rulesetNode.paths.length > 0) {
6588
+ rulesets.splice(0, 0, rulesetNode);
6589
+ }
6590
+ } else {
6591
+ rulesetNode.accept(this._visitor);
6592
+ visitArgs.visitDeeper = false;
6593
+ if (rulesetNode.firstRoot || (rulesetNode.rules && rulesetNode.rules.length > 0)) {
6594
+ rulesets.splice(0, 0, rulesetNode);
6595
+ }
6596
+ }
6597
+ if (rulesets.length === 1) {
6598
+ return rulesets[0];
6599
+ }
6600
+ return rulesets;
6601
+ },
6602
+
6603
+ _removeDuplicateRules: function(rules) {
6604
+ if (!rules) { return; }
6605
+
6606
+ // remove duplicates
6607
+ var ruleCache = {},
6608
+ ruleList, rule, i;
6609
+
6610
+ for(i = rules.length - 1; i >= 0 ; i--) {
6611
+ rule = rules[i];
6612
+ if (rule instanceof tree.Rule) {
6613
+ if (!ruleCache[rule.name]) {
6614
+ ruleCache[rule.name] = rule;
6615
+ } else {
6616
+ ruleList = ruleCache[rule.name];
6617
+ if (ruleList instanceof tree.Rule) {
6618
+ ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)];
6619
+ }
6620
+ var ruleCSS = rule.toCSS(this._env);
6621
+ if (ruleList.indexOf(ruleCSS) !== -1) {
6622
+ rules.splice(i, 1);
6623
+ } else {
6624
+ ruleList.push(ruleCSS);
6625
+ }
6626
+ }
6627
+ }
6628
+ }
6629
+ },
6630
+
6631
+ _mergeRules: function (rules) {
6632
+ if (!rules) { return; }
6633
+
6634
+ var groups = {},
6635
+ parts,
6636
+ rule,
6637
+ key;
6638
+
6639
+ for (var i = 0; i < rules.length; i++) {
6640
+ rule = rules[i];
6641
+
6642
+ if ((rule instanceof tree.Rule) && rule.merge) {
6643
+ key = [rule.name,
6644
+ rule.important ? "!" : ""].join(",");
6645
+
6646
+ if (!groups[key]) {
6647
+ groups[key] = [];
6648
+ } else {
6649
+ rules.splice(i--, 1);
6650
+ }
6651
+
6652
+ groups[key].push(rule);
6653
+ }
6654
+ }
6655
+
6656
+ Object.keys(groups).map(function (k) {
6657
+
6658
+ function toExpression(values) {
6659
+ return new (tree.Expression)(values.map(function (p) {
6660
+ return p.value;
6661
+ }));
6662
+ }
6663
+
6664
+ function toValue(values) {
6665
+ return new (tree.Value)(values.map(function (p) {
6666
+ return p;
6667
+ }));
6668
+ }
6669
+
6670
+ parts = groups[k];
6671
+
6672
+ if (parts.length > 1) {
6673
+ rule = parts[0];
6674
+ var spacedGroups = [];
6675
+ var lastSpacedGroup = [];
6676
+ parts.map(function (p) {
6677
+ if (p.merge==="+") {
6678
+ if (lastSpacedGroup.length > 0) {
6679
+ spacedGroups.push(toExpression(lastSpacedGroup));
6680
+ }
6681
+ lastSpacedGroup = [];
6682
+ }
6683
+ lastSpacedGroup.push(p);
6684
+ });
6685
+ spacedGroups.push(toExpression(lastSpacedGroup));
6686
+ rule.value = toValue(spacedGroups);
6687
+ }
6688
+ });
6689
+ }
6690
+ };
6691
+
6692
+ })(require('./tree'));
6693
+ (function (tree) {
6694
+ /*jshint loopfunc:true */
6695
+
6696
+ tree.extendFinderVisitor = function() {
6697
+ this._visitor = new tree.visitor(this);
6698
+ this.contexts = [];
6699
+ this.allExtendsStack = [[]];
6700
+ };
6701
+
6702
+ tree.extendFinderVisitor.prototype = {
6703
+ run: function (root) {
6704
+ root = this._visitor.visit(root);
6705
+ root.allExtends = this.allExtendsStack[0];
6706
+ return root;
6707
+ },
6708
+ visitRule: function (ruleNode, visitArgs) {
6709
+ visitArgs.visitDeeper = false;
6710
+ },
6711
+ visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
6712
+ visitArgs.visitDeeper = false;
6713
+ },
6714
+ visitRuleset: function (rulesetNode, visitArgs) {
6715
+ if (rulesetNode.root) {
6716
+ return;
6717
+ }
6718
+
6719
+ var i, j, extend, allSelectorsExtendList = [], extendList;
6720
+
6721
+ // get &:extend(.a); rules which apply to all selectors in this ruleset
6722
+ var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
6723
+ for(i = 0; i < ruleCnt; i++) {
6724
+ if (rulesetNode.rules[i] instanceof tree.Extend) {
6725
+ allSelectorsExtendList.push(rules[i]);
6726
+ rulesetNode.extendOnEveryPath = true;
6727
+ }
6728
+ }
6729
+
6730
+ // now find every selector and apply the extends that apply to all extends
6731
+ // and the ones which apply to an individual extend
6732
+ var paths = rulesetNode.paths;
6733
+ for(i = 0; i < paths.length; i++) {
6734
+ var selectorPath = paths[i],
6735
+ selector = selectorPath[selectorPath.length - 1],
6736
+ selExtendList = selector.extendList;
6737
+
6738
+ extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
6739
+ : allSelectorsExtendList;
6740
+
6741
+ if (extendList) {
6742
+ extendList = extendList.map(function(allSelectorsExtend) {
6743
+ return allSelectorsExtend.clone();
6744
+ });
6745
+ }
6746
+
6747
+ for(j = 0; j < extendList.length; j++) {
6748
+ this.foundExtends = true;
6749
+ extend = extendList[j];
6750
+ extend.findSelfSelectors(selectorPath);
6751
+ extend.ruleset = rulesetNode;
6752
+ if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
6753
+ this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
6754
+ }
6755
+ }
6756
+
6757
+ this.contexts.push(rulesetNode.selectors);
6758
+ },
6759
+ visitRulesetOut: function (rulesetNode) {
6760
+ if (!rulesetNode.root) {
6761
+ this.contexts.length = this.contexts.length - 1;
6762
+ }
6763
+ },
6764
+ visitMedia: function (mediaNode, visitArgs) {
6765
+ mediaNode.allExtends = [];
6766
+ this.allExtendsStack.push(mediaNode.allExtends);
6767
+ },
6768
+ visitMediaOut: function (mediaNode) {
6769
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
6770
+ },
6771
+ visitDirective: function (directiveNode, visitArgs) {
6772
+ directiveNode.allExtends = [];
6773
+ this.allExtendsStack.push(directiveNode.allExtends);
6774
+ },
6775
+ visitDirectiveOut: function (directiveNode) {
6776
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
6777
+ }
6778
+ };
6779
+
6780
+ tree.processExtendsVisitor = function() {
6781
+ this._visitor = new tree.visitor(this);
6782
+ };
6783
+
6784
+ tree.processExtendsVisitor.prototype = {
6785
+ run: function(root) {
6786
+ var extendFinder = new tree.extendFinderVisitor();
6787
+ extendFinder.run(root);
6788
+ if (!extendFinder.foundExtends) { return root; }
6789
+ root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
6790
+ this.allExtendsStack = [root.allExtends];
6791
+ return this._visitor.visit(root);
6792
+ },
6793
+ doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
6794
+ //
6795
+ // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
6796
+ // the selector we would do normally, but we are also adding an extend with the same target selector
6797
+ // this means this new extend can then go and alter other extends
6798
+ //
6799
+ // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
6800
+ // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
6801
+ // we look at each selector at a time, as is done in visitRuleset
6802
+
6803
+ var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
6804
+
6805
+ iterationCount = iterationCount || 0;
6806
+
6807
+ //loop through comparing every extend with every target extend.
6808
+ // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
6809
+ // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
6810
+ // and the second is the target.
6811
+ // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
6812
+ // case when processing media queries
6813
+ for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){
6814
+ for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){
6815
+
6816
+ extend = extendsList[extendIndex];
6817
+ targetExtend = extendsListTarget[targetExtendIndex];
6818
+
6819
+ // look for circular references
6820
+ if( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ){ continue; }
6821
+
6822
+ // find a match in the target extends self selector (the bit before :extend)
6823
+ selectorPath = [targetExtend.selfSelectors[0]];
6824
+ matches = extendVisitor.findMatch(extend, selectorPath);
6825
+
6826
+ if (matches.length) {
6827
+
6828
+ // we found a match, so for each self selector..
6829
+ extend.selfSelectors.forEach(function(selfSelector) {
6830
+
6831
+ // process the extend as usual
6832
+ newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector);
6833
+
6834
+ // but now we create a new extend from it
6835
+ newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0);
6836
+ newExtend.selfSelectors = newSelector;
6837
+
6838
+ // add the extend onto the list of extends for that selector
6839
+ newSelector[newSelector.length-1].extendList = [newExtend];
6840
+
6841
+ // record that we need to add it.
6842
+ extendsToAdd.push(newExtend);
6843
+ newExtend.ruleset = targetExtend.ruleset;
6844
+
6845
+ //remember its parents for circular references
6846
+ newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
6847
+
6848
+ // only process the selector once.. if we have :extend(.a,.b) then multiple
6849
+ // extends will look at the same selector path, so when extending
6850
+ // we know that any others will be duplicates in terms of what is added to the css
6851
+ if (targetExtend.firstExtendOnThisSelectorPath) {
6852
+ newExtend.firstExtendOnThisSelectorPath = true;
6853
+ targetExtend.ruleset.paths.push(newSelector);
6854
+ }
6855
+ });
6856
+ }
6857
+ }
6858
+ }
6859
+
6860
+ if (extendsToAdd.length) {
6861
+ // try to detect circular references to stop a stack overflow.
6862
+ // may no longer be needed.
6863
+ this.extendChainCount++;
6864
+ if (iterationCount > 100) {
6865
+ var selectorOne = "{unable to calculate}";
6866
+ var selectorTwo = "{unable to calculate}";
6867
+ try
6868
+ {
6869
+ selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
6870
+ selectorTwo = extendsToAdd[0].selector.toCSS();
6871
+ }
6872
+ catch(e) {}
6873
+ throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
6874
+ }
6875
+
6876
+ // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
6877
+ return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
6878
+ } else {
6879
+ return extendsToAdd;
6880
+ }
6881
+ },
6882
+ visitRule: function (ruleNode, visitArgs) {
6883
+ visitArgs.visitDeeper = false;
6884
+ },
6885
+ visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
6886
+ visitArgs.visitDeeper = false;
6887
+ },
6888
+ visitSelector: function (selectorNode, visitArgs) {
6889
+ visitArgs.visitDeeper = false;
6890
+ },
6891
+ visitRuleset: function (rulesetNode, visitArgs) {
6892
+ if (rulesetNode.root) {
6893
+ return;
6894
+ }
6895
+ var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
6896
+
6897
+ // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
6898
+
6899
+ for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
6900
+ for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
6901
+ selectorPath = rulesetNode.paths[pathIndex];
6902
+
6903
+ // extending extends happens initially, before the main pass
6904
+ if (rulesetNode.extendOnEveryPath) { continue; }
6905
+ var extendList = selectorPath[selectorPath.length-1].extendList;
6906
+ if (extendList && extendList.length) { continue; }
6907
+
6908
+ matches = this.findMatch(allExtends[extendIndex], selectorPath);
6909
+
6910
+ if (matches.length) {
6911
+
6912
+ allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
6913
+ selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
6914
+ });
6915
+ }
6916
+ }
6917
+ }
6918
+ rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
6919
+ },
6920
+ findMatch: function (extend, haystackSelectorPath) {
6921
+ //
6922
+ // look through the haystack selector path to try and find the needle - extend.selector
6923
+ // returns an array of selector matches that can then be replaced
6924
+ //
6925
+ var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement,
6926
+ targetCombinator, i,
6927
+ extendVisitor = this,
6928
+ needleElements = extend.selector.elements,
6929
+ potentialMatches = [], potentialMatch, matches = [];
6930
+
6931
+ // loop through the haystack elements
6932
+ for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
6933
+ hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
6934
+
6935
+ for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
6936
+
6937
+ haystackElement = hackstackSelector.elements[hackstackElementIndex];
6938
+
6939
+ // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
6940
+ if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
6941
+ potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
6942
+ }
6943
+
6944
+ for(i = 0; i < potentialMatches.length; i++) {
6945
+ potentialMatch = potentialMatches[i];
6946
+
6947
+ // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
6948
+ // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
6949
+ // what the resulting combinator will be
6950
+ targetCombinator = haystackElement.combinator.value;
6951
+ if (targetCombinator === '' && hackstackElementIndex === 0) {
6952
+ targetCombinator = ' ';
6953
+ }
6954
+
6955
+ // if we don't match, null our match to indicate failure
6956
+ if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
6957
+ (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
6958
+ potentialMatch = null;
6959
+ } else {
6960
+ potentialMatch.matched++;
6961
+ }
6962
+
6963
+ // if we are still valid and have finished, test whether we have elements after and whether these are allowed
6964
+ if (potentialMatch) {
6965
+ potentialMatch.finished = potentialMatch.matched === needleElements.length;
6966
+ if (potentialMatch.finished &&
6967
+ (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
6968
+ potentialMatch = null;
6969
+ }
6970
+ }
6971
+ // if null we remove, if not, we are still valid, so either push as a valid match or continue
6972
+ if (potentialMatch) {
6973
+ if (potentialMatch.finished) {
6974
+ potentialMatch.length = needleElements.length;
6975
+ potentialMatch.endPathIndex = haystackSelectorIndex;
6976
+ potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
6977
+ potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
6978
+ matches.push(potentialMatch);
6979
+ }
6980
+ } else {
6981
+ potentialMatches.splice(i, 1);
6982
+ i--;
6983
+ }
6984
+ }
6985
+ }
6986
+ }
6987
+ return matches;
6988
+ },
6989
+ isElementValuesEqual: function(elementValue1, elementValue2) {
6990
+ if (typeof elementValue1 === "string" || typeof elementValue2 === "string") {
6991
+ return elementValue1 === elementValue2;
6992
+ }
6993
+ if (elementValue1 instanceof tree.Attribute) {
6994
+ if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
6995
+ return false;
6996
+ }
6997
+ if (!elementValue1.value || !elementValue2.value) {
6998
+ if (elementValue1.value || elementValue2.value) {
6999
+ return false;
7000
+ }
7001
+ return true;
7002
+ }
7003
+ elementValue1 = elementValue1.value.value || elementValue1.value;
7004
+ elementValue2 = elementValue2.value.value || elementValue2.value;
7005
+ return elementValue1 === elementValue2;
7006
+ }
7007
+ elementValue1 = elementValue1.value;
7008
+ elementValue2 = elementValue2.value;
7009
+ if (elementValue1 instanceof tree.Selector) {
7010
+ if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
7011
+ return false;
7012
+ }
7013
+ for(var i = 0; i <elementValue1.elements.length; i++) {
7014
+ if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
7015
+ if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
7016
+ return false;
7017
+ }
7018
+ }
7019
+ if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
7020
+ return false;
7021
+ }
7022
+ }
7023
+ return true;
7024
+ }
7025
+ return false;
7026
+ },
7027
+ extendSelector:function (matches, selectorPath, replacementSelector) {
7028
+
7029
+ //for a set of matches, replace each match with the replacement selector
7030
+
7031
+ var currentSelectorPathIndex = 0,
7032
+ currentSelectorPathElementIndex = 0,
7033
+ path = [],
7034
+ matchIndex,
7035
+ selector,
7036
+ firstElement,
7037
+ match,
7038
+ newElements;
7039
+
7040
+ for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
7041
+ match = matches[matchIndex];
7042
+ selector = selectorPath[match.pathIndex];
7043
+ firstElement = new tree.Element(
7044
+ match.initialCombinator,
7045
+ replacementSelector.elements[0].value,
7046
+ replacementSelector.elements[0].index,
7047
+ replacementSelector.elements[0].currentFileInfo
7048
+ );
7049
+
7050
+ if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
7051
+ path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
7052
+ currentSelectorPathElementIndex = 0;
7053
+ currentSelectorPathIndex++;
7054
+ }
7055
+
7056
+ newElements = selector.elements
7057
+ .slice(currentSelectorPathElementIndex, match.index)
7058
+ .concat([firstElement])
7059
+ .concat(replacementSelector.elements.slice(1));
7060
+
7061
+ if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
7062
+ path[path.length - 1].elements =
7063
+ path[path.length - 1].elements.concat(newElements);
7064
+ } else {
7065
+ path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
7066
+
7067
+ path.push(new tree.Selector(
7068
+ newElements
7069
+ ));
7070
+ }
7071
+ currentSelectorPathIndex = match.endPathIndex;
7072
+ currentSelectorPathElementIndex = match.endPathElementIndex;
7073
+ if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
7074
+ currentSelectorPathElementIndex = 0;
7075
+ currentSelectorPathIndex++;
7076
+ }
7077
+ }
7078
+
7079
+ if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
7080
+ path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
7081
+ currentSelectorPathIndex++;
7082
+ }
7083
+
7084
+ path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
7085
+
7086
+ return path;
7087
+ },
7088
+ visitRulesetOut: function (rulesetNode) {
7089
+ },
7090
+ visitMedia: function (mediaNode, visitArgs) {
7091
+ var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
7092
+ newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
7093
+ this.allExtendsStack.push(newAllExtends);
7094
+ },
7095
+ visitMediaOut: function (mediaNode) {
7096
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
7097
+ },
7098
+ visitDirective: function (directiveNode, visitArgs) {
7099
+ var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
7100
+ newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
7101
+ this.allExtendsStack.push(newAllExtends);
7102
+ },
7103
+ visitDirectiveOut: function (directiveNode) {
7104
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
7105
+ }
7106
+ };
7107
+
7108
+ })(require('./tree'));
7109
+
7110
+ (function (tree) {
7111
+
7112
+ tree.sourceMapOutput = function (options) {
7113
+ this._css = [];
7114
+ this._rootNode = options.rootNode;
7115
+ this._writeSourceMap = options.writeSourceMap;
7116
+ this._contentsMap = options.contentsMap;
7117
+ this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap;
7118
+ this._sourceMapFilename = options.sourceMapFilename;
7119
+ this._outputFilename = options.outputFilename;
7120
+ this._sourceMapURL = options.sourceMapURL;
7121
+ if (options.sourceMapBasepath) {
7122
+ this._sourceMapBasepath = options.sourceMapBasepath.replace(/\\/g, '/');
7123
+ }
7124
+ this._sourceMapRootpath = options.sourceMapRootpath;
7125
+ this._outputSourceFiles = options.outputSourceFiles;
7126
+ this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator;
7127
+
7128
+ if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') {
7129
+ this._sourceMapRootpath += '/';
7130
+ }
7131
+
7132
+ this._lineNumber = 0;
7133
+ this._column = 0;
7134
+ };
7135
+
7136
+ tree.sourceMapOutput.prototype.normalizeFilename = function(filename) {
7137
+ filename = filename.replace(/\\/g, '/');
7138
+
7139
+ if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
7140
+ filename = filename.substring(this._sourceMapBasepath.length);
7141
+ if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
7142
+ filename = filename.substring(1);
7143
+ }
7144
+ }
7145
+ return (this._sourceMapRootpath || "") + filename;
7146
+ };
7147
+
7148
+ tree.sourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) {
7149
+
7150
+ //ignore adding empty strings
7151
+ if (!chunk) {
7152
+ return;
7153
+ }
7154
+
7155
+ var lines,
7156
+ sourceLines,
7157
+ columns,
7158
+ sourceColumns,
7159
+ i;
7160
+
7161
+ if (fileInfo) {
7162
+ var inputSource = this._contentsMap[fileInfo.filename];
7163
+
7164
+ // remove vars/banner added to the top of the file
7165
+ if (this._contentsIgnoredCharsMap[fileInfo.filename]) {
7166
+ // adjust the index
7167
+ index -= this._contentsIgnoredCharsMap[fileInfo.filename];
7168
+ if (index < 0) { index = 0; }
7169
+ // adjust the source
7170
+ inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]);
7171
+ }
7172
+ inputSource = inputSource.substring(0, index);
7173
+ sourceLines = inputSource.split("\n");
7174
+ sourceColumns = sourceLines[sourceLines.length-1];
7175
+ }
7176
+
7177
+ lines = chunk.split("\n");
7178
+ columns = lines[lines.length-1];
7179
+
7180
+ if (fileInfo) {
7181
+ if (!mapLines) {
7182
+ this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
7183
+ original: { line: sourceLines.length, column: sourceColumns.length},
7184
+ source: this.normalizeFilename(fileInfo.filename)});
7185
+ } else {
7186
+ for(i = 0; i < lines.length; i++) {
7187
+ this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
7188
+ original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
7189
+ source: this.normalizeFilename(fileInfo.filename)});
7190
+ }
7191
+ }
7192
+ }
7193
+
7194
+ if (lines.length === 1) {
7195
+ this._column += columns.length;
7196
+ } else {
7197
+ this._lineNumber += lines.length - 1;
7198
+ this._column = columns.length;
7199
+ }
7200
+
7201
+ this._css.push(chunk);
7202
+ };
7203
+
7204
+ tree.sourceMapOutput.prototype.isEmpty = function() {
7205
+ return this._css.length === 0;
7206
+ };
7207
+
7208
+ tree.sourceMapOutput.prototype.toCSS = function(env) {
7209
+ this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
7210
+
7211
+ if (this._outputSourceFiles) {
7212
+ for(var filename in this._contentsMap) {
7213
+ if (this._contentsMap.hasOwnProperty(filename))
7214
+ {
7215
+ var source = this._contentsMap[filename];
7216
+ if (this._contentsIgnoredCharsMap[filename]) {
7217
+ source = source.slice(this._contentsIgnoredCharsMap[filename]);
7218
+ }
7219
+ this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source);
7220
+ }
7221
+ }
7222
+ }
7223
+
7224
+ this._rootNode.genCSS(env, this);
7225
+
7226
+ if (this._css.length > 0) {
7227
+ var sourceMapURL,
7228
+ sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON());
7229
+
7230
+ if (this._sourceMapURL) {
7231
+ sourceMapURL = this._sourceMapURL;
7232
+ } else if (this._sourceMapFilename) {
7233
+ sourceMapURL = this.normalizeFilename(this._sourceMapFilename);
7234
+ }
7235
+
7236
+ if (this._writeSourceMap) {
7237
+ this._writeSourceMap(sourceMapContent);
7238
+ } else {
7239
+ sourceMapURL = "data:application/json;base64," + require('./encoder.js').encodeBase64(sourceMapContent);
7240
+ }
7241
+
7242
+ if (sourceMapURL) {
7243
+ this._css.push("/*# sourceMappingURL=" + sourceMapURL + " */");
7244
+ }
7245
+ }
7246
+
7247
+ return this._css.join('');
7248
+ };
7249
+
7250
+ })(require('./tree'));
7251
+
7252
+ //
7253
+ // browser.js - client-side engine
7254
+ //
7255
+ /*global less, window, document, XMLHttpRequest, location */
7256
+
7257
+ var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);
7258
+
7259
+ less.env = less.env || (location.hostname == '127.0.0.1' ||
7260
+ location.hostname == '0.0.0.0' ||
7261
+ location.hostname == 'localhost' ||
7262
+ (location.port &&
7263
+ location.port.length > 0) ||
7264
+ isFileProtocol ? 'development'
7265
+ : 'production');
7266
+
7267
+ var logLevel = {
7268
+ debug: 3,
7269
+ info: 2,
7270
+ errors: 1,
7271
+ none: 0
7272
+ };
7273
+
7274
+ // The amount of logging in the javascript console.
7275
+ // 3 - Debug, information and errors
7276
+ // 2 - Information and errors
7277
+ // 1 - Errors
7278
+ // 0 - None
7279
+ // Defaults to 2
7280
+ less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : (less.env === 'development' ? logLevel.debug : logLevel.errors);
7281
+
7282
+ // Load styles asynchronously (default: false)
7283
+ //
7284
+ // This is set to `false` by default, so that the body
7285
+ // doesn't start loading before the stylesheets are parsed.
7286
+ // Setting this to `true` can result in flickering.
7287
+ //
7288
+ less.async = less.async || false;
7289
+ less.fileAsync = less.fileAsync || false;
7290
+
7291
+ // Interval between watch polls
7292
+ less.poll = less.poll || (isFileProtocol ? 1000 : 1500);
7293
+
7294
+ //Setup user functions
7295
+ if (less.functions) {
7296
+ for(var func in less.functions) {
7297
+ if (less.functions.hasOwnProperty(func)) {
7298
+ less.tree.functions[func] = less.functions[func];
7299
+ }
7300
+ }
7301
+ }
7302
+
7303
+ var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);
7304
+ if (dumpLineNumbers) {
7305
+ less.dumpLineNumbers = dumpLineNumbers[1];
7306
+ }
7307
+
7308
+ var typePattern = /^text\/(x-)?less$/;
7309
+ var cache = null;
7310
+ var fileCache = {};
7311
+
7312
+ function log(str, level) {
7313
+ if (typeof(console) !== 'undefined' && less.logLevel >= level) {
7314
+ console.log('less: ' + str);
7315
+ }
7316
+ }
7317
+
7318
+ function extractId(href) {
7319
+ return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain
7320
+ .replace(/^\//, '' ) // Remove root /
7321
+ .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension
7322
+ .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
7323
+ .replace(/\./g, ':'); // Replace dots with colons(for valid id)
7324
+ }
7325
+
7326
+ function errorConsole(e, rootHref) {
7327
+ var template = '{line} {content}';
7328
+ var filename = e.filename || rootHref;
7329
+ var errors = [];
7330
+ var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
7331
+ " in " + filename + " ";
7332
+
7333
+ var errorline = function (e, i, classname) {
7334
+ if (e.extract[i] !== undefined) {
7335
+ errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
7336
+ .replace(/\{class\}/, classname)
7337
+ .replace(/\{content\}/, e.extract[i]));
7338
+ }
7339
+ };
7340
+
7341
+ if (e.extract) {
7342
+ errorline(e, 0, '');
7343
+ errorline(e, 1, 'line');
7344
+ errorline(e, 2, '');
7345
+ content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
7346
+ errors.join('\n');
7347
+ } else if (e.stack) {
7348
+ content += e.stack;
7349
+ }
7350
+ log(content, logLevel.errors);
7351
+ }
7352
+
7353
+ function createCSS(styles, sheet, lastModified) {
7354
+ // Strip the query-string
7355
+ var href = sheet.href || '';
7356
+
7357
+ // If there is no title set, use the filename, minus the extension
7358
+ var id = 'less:' + (sheet.title || extractId(href));
7359
+
7360
+ // If this has already been inserted into the DOM, we may need to replace it
7361
+ var oldCss = document.getElementById(id);
7362
+ var keepOldCss = false;
7363
+
7364
+ // Create a new stylesheet node for insertion or (if necessary) replacement
7365
+ var css = document.createElement('style');
7366
+ css.setAttribute('type', 'text/css');
7367
+ if (sheet.media) {
7368
+ css.setAttribute('media', sheet.media);
7369
+ }
7370
+ css.id = id;
7371
+
7372
+ if (!css.styleSheet) {
7373
+ css.appendChild(document.createTextNode(styles));
7374
+
7375
+ // If new contents match contents of oldCss, don't replace oldCss
7376
+ keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 &&
7377
+ oldCss.firstChild.nodeValue === css.firstChild.nodeValue);
7378
+ }
7379
+
7380
+ var head = document.getElementsByTagName('head')[0];
7381
+
7382
+ // If there is no oldCss, just append; otherwise, only append if we need
7383
+ // to replace oldCss with an updated stylesheet
7384
+ if (oldCss === null || keepOldCss === false) {
7385
+ var nextEl = sheet && sheet.nextSibling || null;
7386
+ if (nextEl) {
7387
+ nextEl.parentNode.insertBefore(css, nextEl);
7388
+ } else {
7389
+ head.appendChild(css);
7390
+ }
7391
+ }
7392
+ if (oldCss && keepOldCss === false) {
7393
+ oldCss.parentNode.removeChild(oldCss);
7394
+ }
7395
+
7396
+ // For IE.
7397
+ // This needs to happen *after* the style element is added to the DOM, otherwise IE 7 and 8 may crash.
7398
+ // See http://social.msdn.microsoft.com/Forums/en-US/7e081b65-878a-4c22-8e68-c10d39c2ed32/internet-explorer-crashes-appending-style-element-to-head
7399
+ if (css.styleSheet) {
7400
+ try {
7401
+ css.styleSheet.cssText = styles;
7402
+ } catch (e) {
7403
+ throw new(Error)("Couldn't reassign styleSheet.cssText.");
7404
+ }
7405
+ }
7406
+
7407
+ // Don't update the local store if the file wasn't modified
7408
+ if (lastModified && cache) {
7409
+ log('saving ' + href + ' to cache.', logLevel.info);
7410
+ try {
7411
+ cache.setItem(href, styles);
7412
+ cache.setItem(href + ':timestamp', lastModified);
7413
+ } catch(e) {
7414
+ //TODO - could do with adding more robust error handling
7415
+ log('failed to save', logLevel.errors);
7416
+ }
7417
+ }
7418
+ }
7419
+
7420
+ function postProcessCSS(styles) {
7421
+ if (less.postProcessor && typeof less.postProcessor === 'function') {
7422
+ styles = less.postProcessor.call(styles, styles) || styles;
7423
+ }
7424
+ return styles;
7425
+ }
7426
+
7427
+ function errorHTML(e, rootHref) {
7428
+ var id = 'less-error-message:' + extractId(rootHref || "");
7429
+ var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
7430
+ var elem = document.createElement('div'), timer, content, errors = [];
7431
+ var filename = e.filename || rootHref;
7432
+ var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1];
7433
+
7434
+ elem.id = id;
7435
+ elem.className = "less-error-message";
7436
+
7437
+ content = '<h3>' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
7438
+ '</h3>' + '<p>in <a href="' + filename + '">' + filenameNoPath + "</a> ";
7439
+
7440
+ var errorline = function (e, i, classname) {
7441
+ if (e.extract[i] !== undefined) {
7442
+ errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
7443
+ .replace(/\{class\}/, classname)
7444
+ .replace(/\{content\}/, e.extract[i]));
7445
+ }
7446
+ };
7447
+
7448
+ if (e.extract) {
7449
+ errorline(e, 0, '');
7450
+ errorline(e, 1, 'line');
7451
+ errorline(e, 2, '');
7452
+ content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':</p>' +
7453
+ '<ul>' + errors.join('') + '</ul>';
7454
+ } else if (e.stack) {
7455
+ content += '<br/>' + e.stack.split('\n').slice(1).join('<br/>');
7456
+ }
7457
+ elem.innerHTML = content;
7458
+
7459
+ // CSS for error messages
7460
+ createCSS([
7461
+ '.less-error-message ul, .less-error-message li {',
7462
+ 'list-style-type: none;',
7463
+ 'margin-right: 15px;',
7464
+ 'padding: 4px 0;',
7465
+ 'margin: 0;',
7466
+ '}',
7467
+ '.less-error-message label {',
7468
+ 'font-size: 12px;',
7469
+ 'margin-right: 15px;',
7470
+ 'padding: 4px 0;',
7471
+ 'color: #cc7777;',
7472
+ '}',
7473
+ '.less-error-message pre {',
7474
+ 'color: #dd6666;',
7475
+ 'padding: 4px 0;',
7476
+ 'margin: 0;',
7477
+ 'display: inline-block;',
7478
+ '}',
7479
+ '.less-error-message pre.line {',
7480
+ 'color: #ff0000;',
7481
+ '}',
7482
+ '.less-error-message h3 {',
7483
+ 'font-size: 20px;',
7484
+ 'font-weight: bold;',
7485
+ 'padding: 15px 0 5px 0;',
7486
+ 'margin: 0;',
7487
+ '}',
7488
+ '.less-error-message a {',
7489
+ 'color: #10a',
7490
+ '}',
7491
+ '.less-error-message .error {',
7492
+ 'color: red;',
7493
+ 'font-weight: bold;',
7494
+ 'padding-bottom: 2px;',
7495
+ 'border-bottom: 1px dashed red;',
7496
+ '}'
7497
+ ].join('\n'), { title: 'error-message' });
7498
+
7499
+ elem.style.cssText = [
7500
+ "font-family: Arial, sans-serif",
7501
+ "border: 1px solid #e00",
7502
+ "background-color: #eee",
7503
+ "border-radius: 5px",
7504
+ "-webkit-border-radius: 5px",
7505
+ "-moz-border-radius: 5px",
7506
+ "color: #e00",
7507
+ "padding: 15px",
7508
+ "margin-bottom: 15px"
7509
+ ].join(';');
7510
+
7511
+ if (less.env == 'development') {
7512
+ timer = setInterval(function () {
7513
+ if (document.body) {
7514
+ if (document.getElementById(id)) {
7515
+ document.body.replaceChild(elem, document.getElementById(id));
7516
+ } else {
7517
+ document.body.insertBefore(elem, document.body.firstChild);
7518
+ }
7519
+ clearInterval(timer);
7520
+ }
7521
+ }, 10);
7522
+ }
7523
+ }
7524
+
7525
+ function error(e, rootHref) {
7526
+ if (!less.errorReporting || less.errorReporting === "html") {
7527
+ errorHTML(e, rootHref);
7528
+ } else if (less.errorReporting === "console") {
7529
+ errorConsole(e, rootHref);
7530
+ } else if (typeof less.errorReporting === 'function') {
7531
+ less.errorReporting("add", e, rootHref);
7532
+ }
7533
+ }
7534
+
7535
+ function removeErrorHTML(path) {
7536
+ var node = document.getElementById('less-error-message:' + extractId(path));
7537
+ if (node) {
7538
+ node.parentNode.removeChild(node);
7539
+ }
7540
+ }
7541
+
7542
+ function removeErrorConsole(path) {
7543
+ //no action
7544
+ }
7545
+
7546
+ function removeError(path) {
7547
+ if (!less.errorReporting || less.errorReporting === "html") {
7548
+ removeErrorHTML(path);
7549
+ } else if (less.errorReporting === "console") {
7550
+ removeErrorConsole(path);
7551
+ } else if (typeof less.errorReporting === 'function') {
7552
+ less.errorReporting("remove", path);
7553
+ }
7554
+ }
7555
+
7556
+ function loadStyles(modifyVars) {
7557
+ var styles = document.getElementsByTagName('style'),
7558
+ style;
7559
+ for (var i = 0; i < styles.length; i++) {
7560
+ style = styles[i];
7561
+ if (style.type.match(typePattern)) {
7562
+ var env = new less.tree.parseEnv(less),
7563
+ lessText = style.innerHTML || '';
7564
+ env.filename = document.location.href.replace(/#.*$/, '');
7565
+
7566
+ if (modifyVars || less.globalVars) {
7567
+ env.useFileCache = true;
7568
+ }
7569
+
7570
+ /*jshint loopfunc:true */
7571
+ // use closure to store current value of i
7572
+ var callback = (function(style) {
7573
+ return function (e, cssAST) {
7574
+ if (e) {
7575
+ return error(e, "inline");
7576
+ }
7577
+ var css = cssAST.toCSS(less);
7578
+ style.type = 'text/css';
7579
+ if (style.styleSheet) {
7580
+ style.styleSheet.cssText = css;
7581
+ } else {
7582
+ style.innerHTML = css;
7583
+ }
7584
+ };
7585
+ })(style);
7586
+ new(less.Parser)(env).parse(lessText, callback, {globalVars: less.globalVars, modifyVars: modifyVars});
7587
+ }
7588
+ }
7589
+ }
7590
+
7591
+ function extractUrlParts(url, baseUrl) {
7592
+ // urlParts[1] = protocol&hostname || /
7593
+ // urlParts[2] = / if path relative to host base
7594
+ // urlParts[3] = directories
7595
+ // urlParts[4] = filename
7596
+ // urlParts[5] = parameters
7597
+
7598
+ var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
7599
+ urlParts = url.match(urlPartsRegex),
7600
+ returner = {}, directories = [], i, baseUrlParts;
7601
+
7602
+ if (!urlParts) {
7603
+ throw new Error("Could not parse sheet href - '"+url+"'");
7604
+ }
7605
+
7606
+ // Stylesheets in IE don't always return the full path
7607
+ if (!urlParts[1] || urlParts[2]) {
7608
+ baseUrlParts = baseUrl.match(urlPartsRegex);
7609
+ if (!baseUrlParts) {
7610
+ throw new Error("Could not parse page url - '"+baseUrl+"'");
7611
+ }
7612
+ urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
7613
+ if (!urlParts[2]) {
7614
+ urlParts[3] = baseUrlParts[3] + urlParts[3];
7615
+ }
7616
+ }
7617
+
7618
+ if (urlParts[3]) {
7619
+ directories = urlParts[3].replace(/\\/g, "/").split("/");
7620
+
7621
+ // extract out . before .. so .. doesn't absorb a non-directory
7622
+ for(i = 0; i < directories.length; i++) {
7623
+ if (directories[i] === ".") {
7624
+ directories.splice(i, 1);
7625
+ i -= 1;
7626
+ }
7627
+ }
7628
+
7629
+ for(i = 0; i < directories.length; i++) {
7630
+ if (directories[i] === ".." && i > 0) {
7631
+ directories.splice(i-1, 2);
7632
+ i -= 2;
7633
+ }
7634
+ }
7635
+ }
7636
+
7637
+ returner.hostPart = urlParts[1];
7638
+ returner.directories = directories;
7639
+ returner.path = urlParts[1] + directories.join("/");
7640
+ returner.fileUrl = returner.path + (urlParts[4] || "");
7641
+ returner.url = returner.fileUrl + (urlParts[5] || "");
7642
+ return returner;
7643
+ }
7644
+
7645
+ function pathDiff(url, baseUrl) {
7646
+ // diff between two paths to create a relative path
7647
+
7648
+ var urlParts = extractUrlParts(url),
7649
+ baseUrlParts = extractUrlParts(baseUrl),
7650
+ i, max, urlDirectories, baseUrlDirectories, diff = "";
7651
+ if (urlParts.hostPart !== baseUrlParts.hostPart) {
7652
+ return "";
7653
+ }
7654
+ max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
7655
+ for(i = 0; i < max; i++) {
7656
+ if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; }
7657
+ }
7658
+ baseUrlDirectories = baseUrlParts.directories.slice(i);
7659
+ urlDirectories = urlParts.directories.slice(i);
7660
+ for(i = 0; i < baseUrlDirectories.length-1; i++) {
7661
+ diff += "../";
7662
+ }
7663
+ for(i = 0; i < urlDirectories.length-1; i++) {
7664
+ diff += urlDirectories[i] + "/";
7665
+ }
7666
+ return diff;
7667
+ }
7668
+
7669
+ function getXMLHttpRequest() {
7670
+ if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
7671
+ return new XMLHttpRequest();
7672
+ } else {
7673
+ try {
7674
+ /*global ActiveXObject */
7675
+ return new ActiveXObject("Microsoft.XMLHTTP");
7676
+ } catch (e) {
7677
+ log("browser doesn't support AJAX.", logLevel.errors);
7678
+ return null;
7679
+ }
7680
+ }
7681
+ }
7682
+
7683
+ function doXHR(url, type, callback, errback) {
7684
+ var xhr = getXMLHttpRequest();
7685
+ var async = isFileProtocol ? less.fileAsync : less.async;
7686
+
7687
+ if (typeof(xhr.overrideMimeType) === 'function') {
7688
+ xhr.overrideMimeType('text/css');
7689
+ }
7690
+ log("XHR: Getting '" + url + "'", logLevel.debug);
7691
+ xhr.open('GET', url, async);
7692
+ xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
7693
+ xhr.send(null);
7694
+
7695
+ function handleResponse(xhr, callback, errback) {
7696
+ if (xhr.status >= 200 && xhr.status < 300) {
7697
+ callback(xhr.responseText,
7698
+ xhr.getResponseHeader("Last-Modified"));
7699
+ } else if (typeof(errback) === 'function') {
7700
+ errback(xhr.status, url);
7701
+ }
7702
+ }
7703
+
7704
+ if (isFileProtocol && !less.fileAsync) {
7705
+ if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
7706
+ callback(xhr.responseText);
7707
+ } else {
7708
+ errback(xhr.status, url);
7709
+ }
7710
+ } else if (async) {
7711
+ xhr.onreadystatechange = function () {
7712
+ if (xhr.readyState == 4) {
7713
+ handleResponse(xhr, callback, errback);
7714
+ }
7715
+ };
7716
+ } else {
7717
+ handleResponse(xhr, callback, errback);
7718
+ }
7719
+ }
7720
+
7721
+ function loadFile(originalHref, currentFileInfo, callback, env, modifyVars) {
7722
+
7723
+ if (currentFileInfo && currentFileInfo.currentDirectory && !/^([a-z-]+:)?\//.test(originalHref)) {
7724
+ originalHref = currentFileInfo.currentDirectory + originalHref;
7725
+ }
7726
+
7727
+ // sheet may be set to the stylesheet for the initial load or a collection of properties including
7728
+ // some env variables for imports
7729
+ var hrefParts = extractUrlParts(originalHref, window.location.href);
7730
+ var href = hrefParts.url;
7731
+ var newFileInfo = {
7732
+ currentDirectory: hrefParts.path,
7733
+ filename: href
7734
+ };
7735
+
7736
+ if (currentFileInfo) {
7737
+ newFileInfo.entryPath = currentFileInfo.entryPath;
7738
+ newFileInfo.rootpath = currentFileInfo.rootpath;
7739
+ newFileInfo.rootFilename = currentFileInfo.rootFilename;
7740
+ newFileInfo.relativeUrls = currentFileInfo.relativeUrls;
7741
+ } else {
7742
+ newFileInfo.entryPath = hrefParts.path;
7743
+ newFileInfo.rootpath = less.rootpath || hrefParts.path;
7744
+ newFileInfo.rootFilename = href;
7745
+ newFileInfo.relativeUrls = env.relativeUrls;
7746
+ }
7747
+
7748
+ if (newFileInfo.relativeUrls) {
7749
+ if (env.rootpath) {
7750
+ newFileInfo.rootpath = extractUrlParts(env.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path;
7751
+ } else {
7752
+ newFileInfo.rootpath = hrefParts.path;
7753
+ }
7754
+ }
7755
+
7756
+ if (env.useFileCache && fileCache[href]) {
7757
+ try {
7758
+ var lessText = fileCache[href];
7759
+ callback(null, lessText, href, newFileInfo, { lastModified: new Date() });
7760
+ } catch (e) {
7761
+ callback(e, null, href);
7762
+ }
7763
+ return;
7764
+ }
7765
+
7766
+ doXHR(href, env.mime, function (data, lastModified) {
7767
+ // per file cache
7768
+ fileCache[href] = data;
7769
+
7770
+ // Use remote copy (re-parse)
7771
+ try {
7772
+ callback(null, data, href, newFileInfo, { lastModified: lastModified });
7773
+ } catch (e) {
7774
+ callback(e, null, href);
7775
+ }
7776
+ }, function (status, url) {
7777
+ callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, href);
7778
+ });
7779
+ }
7780
+
7781
+ function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
7782
+
7783
+ var env = new less.tree.parseEnv(less);
7784
+ env.mime = sheet.type;
7785
+
7786
+ if (modifyVars || less.globalVars) {
7787
+ env.useFileCache = true;
7788
+ }
7789
+
7790
+ loadFile(sheet.href, null, function(e, data, path, newFileInfo, webInfo) {
7791
+
7792
+ if (webInfo) {
7793
+ webInfo.remaining = remaining;
7794
+
7795
+ var css = cache && cache.getItem(path),
7796
+ timestamp = cache && cache.getItem(path + ':timestamp');
7797
+
7798
+ if (!reload && timestamp && webInfo.lastModified &&
7799
+ (new(Date)(webInfo.lastModified).valueOf() ===
7800
+ new(Date)(timestamp).valueOf())) {
7801
+ // Use local copy
7802
+ createCSS(css, sheet);
7803
+ webInfo.local = true;
7804
+ callback(null, null, data, sheet, webInfo, path);
7805
+ return;
7806
+ }
7807
+ }
7808
+
7809
+ //TODO add tests around how this behaves when reloading
7810
+ removeError(path);
7811
+
7812
+ if (data) {
7813
+ env.currentFileInfo = newFileInfo;
7814
+ new(less.Parser)(env).parse(data, function (e, root) {
7815
+ if (e) { return callback(e, null, null, sheet); }
7816
+ try {
7817
+ callback(e, root, data, sheet, webInfo, path);
7818
+ } catch (e) {
7819
+ callback(e, null, null, sheet);
7820
+ }
7821
+ }, {modifyVars: modifyVars, globalVars: less.globalVars});
7822
+ } else {
7823
+ callback(e, null, null, sheet, webInfo, path);
7824
+ }
7825
+ }, env, modifyVars);
7826
+ }
7827
+
7828
+ function loadStyleSheets(callback, reload, modifyVars) {
7829
+ for (var i = 0; i < less.sheets.length; i++) {
7830
+ loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
7831
+ }
7832
+ }
7833
+
7834
+ function initRunningMode(){
7835
+ if (less.env === 'development') {
7836
+ less.optimization = 0;
7837
+ less.watchTimer = setInterval(function () {
7838
+ if (less.watchMode) {
7839
+ loadStyleSheets(function (e, root, _, sheet, env) {
7840
+ if (e) {
7841
+ error(e, sheet.href);
7842
+ } else if (root) {
7843
+ var styles = root.toCSS(less);
7844
+ styles = postProcessCSS(styles);
7845
+ createCSS(styles, sheet, env.lastModified);
7846
+ }
7847
+ });
7848
+ }
7849
+ }, less.poll);
7850
+ } else {
7851
+ less.optimization = 3;
7852
+ }
7853
+ }
7854
+
7855
+
7856
+
7857
+ //
7858
+ // Watch mode
7859
+ //
7860
+ less.watch = function () {
7861
+ if (!less.watchMode ){
7862
+ less.env = 'development';
7863
+ initRunningMode();
7864
+ }
7865
+ this.watchMode = true;
7866
+ return true;
7867
+ };
7868
+
7869
+ less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };
7870
+
7871
+ if (/!watch/.test(location.hash)) {
7872
+ less.watch();
7873
+ }
7874
+
7875
+ if (less.env != 'development') {
7876
+ try {
7877
+ cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage;
7878
+ } catch (_) {}
7879
+ }
7880
+
7881
+ //
7882
+ // Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
7883
+ //
7884
+ var links = document.getElementsByTagName('link');
7885
+
7886
+ less.sheets = [];
7887
+
7888
+ for (var i = 0; i < links.length; i++) {
7889
+ if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
7890
+ (links[i].type.match(typePattern)))) {
7891
+ less.sheets.push(links[i]);
7892
+ }
7893
+ }
7894
+
7895
+ //
7896
+ // With this function, it's possible to alter variables and re-render
7897
+ // CSS without reloading less-files
7898
+ //
7899
+ less.modifyVars = function(record) {
7900
+ less.refresh(false, record);
7901
+ };
7902
+
7903
+ less.refresh = function (reload, modifyVars) {
7904
+ var startTime, endTime;
7905
+ startTime = endTime = new Date();
7906
+
7907
+ loadStyleSheets(function (e, root, _, sheet, env) {
7908
+ if (e) {
7909
+ return error(e, sheet.href);
7910
+ }
7911
+ if (env.local) {
7912
+ log("loading " + sheet.href + " from cache.", logLevel.info);
7913
+ } else {
7914
+ log("parsed " + sheet.href + " successfully.", logLevel.debug);
7915
+ var styles = root.toCSS(less);
7916
+ styles = postProcessCSS(styles);
7917
+ createCSS(styles, sheet, env.lastModified);
7918
+ }
7919
+ log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info);
7920
+ if (env.remaining === 0) {
7921
+ log("less has finished. css generated in " + (new Date() - startTime) + 'ms', logLevel.info);
7922
+ }
7923
+ endTime = new Date();
7924
+ }, reload, modifyVars);
7925
+
7926
+ loadStyles(modifyVars);
7927
+ };
7928
+
7929
+ less.refreshStyles = loadStyles;
7930
+
7931
+ less.Parser.fileLoader = loadFile;
7932
+
7933
+ less.refresh(less.env === 'development');
7934
+
7935
+ // amd.js
7936
+ //
7937
+ // Define Less as an AMD module.
7938
+ if (typeof define === "function" && define.amd) {
7939
+ define(function () { return less; } );
7940
+ }
7941
+
7942
+ })(window);
admin/less/lib/lessc.inc.php ADDED
@@ -0,0 +1,3675 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * lessphp v0.4.0
5
+ * http://leafo.net/lessphp
6
+ *
7
+ * LESS css compiler, adapted from http://lesscss.org
8
+ *
9
+ * Copyright 2012, Leaf Corcoran <leafot@gmail.com>
10
+ * Licensed under MIT or GPLv3, see LICENSE
11
+ */
12
+
13
+
14
+ /**
15
+ * The less compiler and parser.
16
+ *
17
+ * Converting LESS to CSS is a three stage process. The incoming file is parsed
18
+ * by `lessc_parser` into a syntax tree, then it is compiled into another tree
19
+ * representing the CSS structure by `lessc`. The CSS tree is fed into a
20
+ * formatter, like `lessc_formatter` which then outputs CSS as a string.
21
+ *
22
+ * During the first compile, all values are *reduced*, which means that their
23
+ * types are brought to the lowest form before being dump as strings. This
24
+ * handles math equations, variable dereferences, and the like.
25
+ *
26
+ * The `parse` function of `lessc` is the entry point.
27
+ *
28
+ * In summary:
29
+ *
30
+ * The `lessc` class creates an intstance of the parser, feeds it LESS code,
31
+ * then transforms the resulting tree to a CSS tree. This class also holds the
32
+ * evaluation context, such as all available mixins and variables at any given
33
+ * time.
34
+ *
35
+ * The `lessc_parser` class is only concerned with parsing its input.
36
+ *
37
+ * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
38
+ * handling things like indentation.
39
+ */
40
+ class lessc {
41
+ static public $VERSION = "v0.4.0";
42
+ static protected $TRUE = array("keyword", "true");
43
+ static protected $FALSE = array("keyword", "false");
44
+
45
+ protected $libFunctions = array();
46
+ protected $registeredVars = array();
47
+ protected $preserveComments = false;
48
+
49
+ public $vPrefix = '@'; // prefix of abstract properties
50
+ public $mPrefix = '$'; // prefix of abstract blocks
51
+ public $parentSelector = '&';
52
+
53
+ public $importDisabled = false;
54
+ public $importDir = '';
55
+
56
+ protected $numberPrecision = null;
57
+
58
+ protected $allParsedFiles = array();
59
+
60
+ // set to the parser that generated the current line when compiling
61
+ // so we know how to create error messages
62
+ protected $sourceParser = null;
63
+ protected $sourceLoc = null;
64
+
65
+ static public $defaultValue = array("keyword", "");
66
+
67
+ static protected $nextImportId = 0; // uniquely identify imports
68
+
69
+ // attempts to find the path of an import url, returns null for css files
70
+ protected function findImport($url) {
71
+ foreach ((array)$this->importDir as $dir) {
72
+ $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
73
+ if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
74
+ return $file;
75
+ }
76
+ }
77
+
78
+ return null;
79
+ }
80
+
81
+ protected function fileExists($name) {
82
+ return is_file($name);
83
+ }
84
+
85
+ static public function compressList($items, $delim) {
86
+ if (!isset($items[1]) && isset($items[0])) return $items[0];
87
+ else return array('list', $delim, $items);
88
+ }
89
+
90
+ static public function preg_quote($what) {
91
+ return preg_quote($what, '/');
92
+ }
93
+
94
+ protected function tryImport($importPath, $parentBlock, $out) {
95
+ if ($importPath[0] == "function" && $importPath[1] == "url") {
96
+ $importPath = $this->flattenList($importPath[2]);
97
+ }
98
+
99
+ $str = $this->coerceString($importPath);
100
+ if ($str === null) return false;
101
+
102
+ $url = $this->compileValue($this->lib_e($str));
103
+
104
+ // don't import if it ends in css
105
+ if (substr_compare($url, '.css', -4, 4) === 0) return false;
106
+
107
+ $realPath = $this->findImport($url);
108
+
109
+ if ($realPath === null) return false;
110
+
111
+ if ($this->importDisabled) {
112
+ return array(false, "/* import disabled */");
113
+ }
114
+
115
+ if (isset($this->allParsedFiles[realpath($realPath)])) {
116
+ return array(false, null);
117
+ }
118
+
119
+ $this->addParsedFile($realPath);
120
+ $parser = $this->makeParser($realPath);
121
+ $root = $parser->parse(file_get_contents($realPath));
122
+
123
+ // set the parents of all the block props
124
+ foreach ($root->props as $prop) {
125
+ if ($prop[0] == "block") {
126
+ $prop[1]->parent = $parentBlock;
127
+ }
128
+ }
129
+
130
+ // copy mixins into scope, set their parents
131
+ // bring blocks from import into current block
132
+ // TODO: need to mark the source parser these came from this file
133
+ foreach ($root->children as $childName => $child) {
134
+ if (isset($parentBlock->children[$childName])) {
135
+ $parentBlock->children[$childName] = array_merge(
136
+ $parentBlock->children[$childName],
137
+ $child);
138
+ } else {
139
+ $parentBlock->children[$childName] = $child;
140
+ }
141
+ }
142
+
143
+ $pi = pathinfo($realPath);
144
+ $dir = $pi["dirname"];
145
+
146
+ list($top, $bottom) = $this->sortProps($root->props, true);
147
+ $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);
148
+
149
+ return array(true, $bottom, $parser, $dir);
150
+ }
151
+
152
+ protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
153
+ $oldSourceParser = $this->sourceParser;
154
+
155
+ $oldImport = $this->importDir;
156
+
157
+ // TODO: this is because the importDir api is stupid
158
+ $this->importDir = (array)$this->importDir;
159
+ array_unshift($this->importDir, $importDir);
160
+
161
+ foreach ($props as $prop) {
162
+ $this->compileProp($prop, $block, $out);
163
+ }
164
+
165
+ $this->importDir = $oldImport;
166
+ $this->sourceParser = $oldSourceParser;
167
+ }
168
+
169
+ /**
170
+ * Recursively compiles a block.
171
+ *
172
+ * A block is analogous to a CSS block in most cases. A single LESS document
173
+ * is encapsulated in a block when parsed, but it does not have parent tags
174
+ * so all of it's children appear on the root level when compiled.
175
+ *
176
+ * Blocks are made up of props and children.
177
+ *
178
+ * Props are property instructions, array tuples which describe an action
179
+ * to be taken, eg. write a property, set a variable, mixin a block.
180
+ *
181
+ * The children of a block are just all the blocks that are defined within.
182
+ * This is used to look up mixins when performing a mixin.
183
+ *
184
+ * Compiling the block involves pushing a fresh environment on the stack,
185
+ * and iterating through the props, compiling each one.
186
+ *
187
+ * See lessc::compileProp()
188
+ *
189
+ */
190
+ protected function compileBlock($block) {
191
+ switch ($block->type) {
192
+ case "root":
193
+ $this->compileRoot($block);
194
+ break;
195
+ case null:
196
+ $this->compileCSSBlock($block);
197
+ break;
198
+ case "media":
199
+ $this->compileMedia($block);
200
+ break;
201
+ case "directive":
202
+ $name = "@" . $block->name;
203
+ if (!empty($block->value)) {
204
+ $name .= " " . $this->compileValue($this->reduce($block->value));
205
+ }
206
+
207
+ $this->compileNestedBlock($block, array($name));
208
+ break;
209
+ default:
210
+ $this->throwError("unknown block type: $block->type\n");
211
+ }
212
+ }
213
+
214
+ protected function compileCSSBlock($block) {
215
+ $env = $this->pushEnv();
216
+
217
+ $selectors = $this->compileSelectors($block->tags);
218
+ $env->selectors = $this->multiplySelectors($selectors);
219
+ $out = $this->makeOutputBlock(null, $env->selectors);
220
+
221
+ $this->scope->children[] = $out;
222
+ $this->compileProps($block, $out);
223
+
224
+ $block->scope = $env; // mixins carry scope with them!
225
+ $this->popEnv();
226
+ }
227
+
228
+ protected function compileMedia($media) {
229
+ $env = $this->pushEnv($media);
230
+ $parentScope = $this->mediaParent($this->scope);
231
+
232
+ $query = $this->compileMediaQuery($this->multiplyMedia($env));
233
+
234
+ $this->scope = $this->makeOutputBlock($media->type, array($query));
235
+ $parentScope->children[] = $this->scope;
236
+
237
+ $this->compileProps($media, $this->scope);
238
+
239
+ if (count($this->scope->lines) > 0) {
240
+ $orphanSelelectors = $this->findClosestSelectors();
241
+ if (!is_null($orphanSelelectors)) {
242
+ $orphan = $this->makeOutputBlock(null, $orphanSelelectors);
243
+ $orphan->lines = $this->scope->lines;
244
+ array_unshift($this->scope->children, $orphan);
245
+ $this->scope->lines = array();
246
+ }
247
+ }
248
+
249
+ $this->scope = $this->scope->parent;
250
+ $this->popEnv();
251
+ }
252
+
253
+ protected function mediaParent($scope) {
254
+ while (!empty($scope->parent)) {
255
+ if (!empty($scope->type) && $scope->type != "media") {
256
+ break;
257
+ }
258
+ $scope = $scope->parent;
259
+ }
260
+
261
+ return $scope;
262
+ }
263
+
264
+ protected function compileNestedBlock($block, $selectors) {
265
+ $this->pushEnv($block);
266
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
267
+ $this->scope->parent->children[] = $this->scope;
268
+
269
+ $this->compileProps($block, $this->scope);
270
+
271
+ $this->scope = $this->scope->parent;
272
+ $this->popEnv();
273
+ }
274
+
275
+ protected function compileRoot($root) {
276
+ $this->pushEnv();
277
+ $this->scope = $this->makeOutputBlock($root->type);
278
+ $this->compileProps($root, $this->scope);
279
+ $this->popEnv();
280
+ }
281
+
282
+ protected function compileProps($block, $out) {
283
+ foreach ($this->sortProps($block->props) as $prop) {
284
+ $this->compileProp($prop, $block, $out);
285
+ }
286
+
287
+ $out->lines = array_values(array_unique($out->lines));
288
+ }
289
+
290
+ protected function sortProps($props, $split = false) {
291
+ $vars = array();
292
+ $imports = array();
293
+ $other = array();
294
+
295
+ foreach ($props as $prop) {
296
+ switch ($prop[0]) {
297
+ case "assign":
298
+ if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
299
+ $vars[] = $prop;
300
+ } else {
301
+ $other[] = $prop;
302
+ }
303
+ break;
304
+ case "import":
305
+ $id = self::$nextImportId++;
306
+ $prop[] = $id;
307
+ $imports[] = $prop;
308
+ $other[] = array("import_mixin", $id);
309
+ break;
310
+ default:
311
+ $other[] = $prop;
312
+ }
313
+ }
314
+
315
+ if ($split) {
316
+ return array(array_merge($vars, $imports), $other);
317
+ } else {
318
+ return array_merge($vars, $imports, $other);
319
+ }
320
+ }
321
+
322
+ protected function compileMediaQuery($queries) {
323
+ $compiledQueries = array();
324
+ foreach ($queries as $query) {
325
+ $parts = array();
326
+ foreach ($query as $q) {
327
+ switch ($q[0]) {
328
+ case "mediaType":
329
+ $parts[] = implode(" ", array_slice($q, 1));
330
+ break;
331
+ case "mediaExp":
332
+ if (isset($q[2])) {
333
+ $parts[] = "($q[1]: " .
334
+ $this->compileValue($this->reduce($q[2])) . ")";
335
+ } else {
336
+ $parts[] = "($q[1])";
337
+ }
338
+ break;
339
+ case "variable":
340
+ $parts[] = $this->compileValue($this->reduce($q));
341
+ break;
342
+ }
343
+ }
344
+
345
+ if (count($parts) > 0) {
346
+ $compiledQueries[] = implode(" and ", $parts);
347
+ }
348
+ }
349
+
350
+ $out = "@media";
351
+ if (!empty($parts)) {
352
+ $out .= " " .
353
+ implode($this->formatter->selectorSeparator, $compiledQueries);
354
+ }
355
+ return $out;
356
+ }
357
+
358
+ protected function multiplyMedia($env, $childQueries = null) {
359
+ if (is_null($env) ||
360
+ !empty($env->block->type) && $env->block->type != "media")
361
+ {
362
+ return $childQueries;
363
+ }
364
+
365
+ // plain old block, skip
366
+ if (empty($env->block->type)) {
367
+ return $this->multiplyMedia($env->parent, $childQueries);
368
+ }
369
+
370
+ $out = array();
371
+ $queries = $env->block->queries;
372
+ if (is_null($childQueries)) {
373
+ $out = $queries;
374
+ } else {
375
+ foreach ($queries as $parent) {
376
+ foreach ($childQueries as $child) {
377
+ $out[] = array_merge($parent, $child);
378
+ }
379
+ }
380
+ }
381
+
382
+ return $this->multiplyMedia($env->parent, $out);
383
+ }
384
+
385
+ protected function expandParentSelectors(&$tag, $replace) {
386
+ $parts = explode("$&$", $tag);
387
+ $count = 0;
388
+ foreach ($parts as &$part) {
389
+ $part = str_replace($this->parentSelector, $replace, $part, $c);
390
+ $count += $c;
391
+ }
392
+ $tag = implode($this->parentSelector, $parts);
393
+ return $count;
394
+ }
395
+
396
+ protected function findClosestSelectors() {
397
+ $env = $this->env;
398
+ $selectors = null;
399
+ while ($env !== null) {
400
+ if (isset($env->selectors)) {
401
+ $selectors = $env->selectors;
402
+ break;
403
+ }
404
+ $env = $env->parent;
405
+ }
406
+
407
+ return $selectors;
408
+ }
409
+
410
+
411
+ // multiply $selectors against the nearest selectors in env
412
+ protected function multiplySelectors($selectors) {
413
+ // find parent selectors
414
+
415
+ $parentSelectors = $this->findClosestSelectors();
416
+ if (is_null($parentSelectors)) {
417
+ // kill parent reference in top level selector
418
+ foreach ($selectors as &$s) {
419
+ $this->expandParentSelectors($s, "");
420
+ }
421
+
422
+ return $selectors;
423
+ }
424
+
425
+ $out = array();
426
+ foreach ($parentSelectors as $parent) {
427
+ foreach ($selectors as $child) {
428
+ $count = $this->expandParentSelectors($child, $parent);
429
+
430
+ // don't prepend the parent tag if & was used
431
+ if ($count > 0) {
432
+ $out[] = trim($child);
433
+ } else {
434
+ $out[] = trim($parent . ' ' . $child);
435
+ }
436
+ }
437
+ }
438
+
439
+ return $out;
440
+ }
441
+
442
+ // reduces selector expressions
443
+ protected function compileSelectors($selectors) {
444
+ $out = array();
445
+
446
+ foreach ($selectors as $s) {
447
+ if (is_array($s)) {
448
+ list(, $value) = $s;
449
+ $out[] = trim($this->compileValue($this->reduce($value)));
450
+ } else {
451
+ $out[] = $s;
452
+ }
453
+ }
454
+
455
+ return $out;
456
+ }
457
+
458
+ protected function eq($left, $right) {
459
+ return $left == $right;
460
+ }
461
+
462
+ protected function patternMatch($block, $orderedArgs, $keywordArgs) {
463
+ // match the guards if it has them
464
+ // any one of the groups must have all its guards pass for a match
465
+ if (!empty($block->guards)) {
466
+ $groupPassed = false;
467
+ foreach ($block->guards as $guardGroup) {
468
+ foreach ($guardGroup as $guard) {
469
+ $this->pushEnv();
470
+ $this->zipSetArgs($block->args, $orderedArgs, $keywordArgs);
471
+
472
+ $negate = false;
473
+ if ($guard[0] == "negate") {
474
+ $guard = $guard[1];
475
+ $negate = true;
476
+ }
477
+
478
+ $passed = $this->reduce($guard) == self::$TRUE;
479
+ if ($negate) $passed = !$passed;
480
+
481
+ $this->popEnv();
482
+
483
+ if ($passed) {
484
+ $groupPassed = true;
485
+ } else {
486
+ $groupPassed = false;
487
+ break;
488
+ }
489
+ }
490
+
491
+ if ($groupPassed) break;
492
+ }
493
+
494
+ if (!$groupPassed) {
495
+ return false;
496
+ }
497
+ }
498
+
499
+ if (empty($block->args)) {
500
+ return $block->isVararg || empty($orderedArgs) && empty($keywordArgs);
501
+ }
502
+
503
+ $remainingArgs = $block->args;
504
+ if ($keywordArgs) {
505
+ $remainingArgs = array();
506
+ foreach ($block->args as $arg) {
507
+ if ($arg[0] == "arg" && isset($keywordArgs[$arg[1]])) {
508
+ continue;
509
+ }
510
+
511
+ $remainingArgs[] = $arg;
512
+ }
513
+ }
514
+
515
+ $i = -1; // no args
516
+ // try to match by arity or by argument literal
517
+ foreach ($remainingArgs as $i => $arg) {
518
+ switch ($arg[0]) {
519
+ case "lit":
520
+ if (empty($orderedArgs[$i]) || !$this->eq($arg[1], $orderedArgs[$i])) {
521
+ return false;
522
+ }
523
+ break;
524
+ case "arg":
525
+ // no arg and no default value
526
+ if (!isset($orderedArgs[$i]) && !isset($arg[2])) {
527
+ return false;
528
+ }
529
+ break;
530
+ case "rest":
531
+ $i--; // rest can be empty
532
+ break 2;
533
+ }
534
+ }
535
+
536
+ if ($block->isVararg) {
537
+ return true; // not having enough is handled above
538
+ } else {
539
+ $numMatched = $i + 1;
540
+ // greater than becuase default values always match
541
+ return $numMatched >= count($orderedArgs);
542
+ }
543
+ }
544
+
545
+ protected function patternMatchAll($blocks, $orderedArgs, $keywordArgs, $skip=array()) {
546
+ $matches = null;
547
+ foreach ($blocks as $block) {
548
+ // skip seen blocks that don't have arguments
549
+ if (isset($skip[$block->id]) && !isset($block->args)) {
550
+ continue;
551
+ }
552
+
553
+ if ($this->patternMatch($block, $orderedArgs, $keywordArgs)) {
554
+ $matches[] = $block;
555
+ }
556
+ }
557
+
558
+ return $matches;
559
+ }
560
+
561
+ // attempt to find blocks matched by path and args
562
+ protected function findBlocks($searchIn, $path, $orderedArgs, $keywordArgs, $seen=array()) {
563
+ if ($searchIn == null) return null;
564
+ if (isset($seen[$searchIn->id])) return null;
565
+ $seen[$searchIn->id] = true;
566
+
567
+ $name = $path[0];
568
+
569
+ if (isset($searchIn->children[$name])) {
570
+ $blocks = $searchIn->children[$name];
571
+ if (count($path) == 1) {
572
+ $matches = $this->patternMatchAll($blocks, $orderedArgs, $keywordArgs, $seen);
573
+ if (!empty($matches)) {
574
+ // This will return all blocks that match in the closest
575
+ // scope that has any matching block, like lessjs
576
+ return $matches;
577
+ }
578
+ } else {
579
+ $matches = array();
580
+ foreach ($blocks as $subBlock) {
581
+ $subMatches = $this->findBlocks($subBlock,
582
+ array_slice($path, 1), $orderedArgs, $keywordArgs, $seen);
583
+
584
+ if (!is_null($subMatches)) {
585
+ foreach ($subMatches as $sm) {
586
+ $matches[] = $sm;
587
+ }
588
+ }
589
+ }
590
+
591
+ return count($matches) > 0 ? $matches : null;
592
+ }
593
+ }
594
+ if ($searchIn->parent === $searchIn) return null;
595
+ return $this->findBlocks($searchIn->parent, $path, $orderedArgs, $keywordArgs, $seen);
596
+ }
597
+
598
+ // sets all argument names in $args to either the default value
599
+ // or the one passed in through $values
600
+ protected function zipSetArgs($args, $orderedValues, $keywordValues) {
601
+ $assignedValues = array();
602
+
603
+ $i = 0;
604
+ foreach ($args as $a) {
605
+ if ($a[0] == "arg") {
606
+ if (isset($keywordValues[$a[1]])) {
607
+ // has keyword arg
608
+ $value = $keywordValues[$a[1]];
609
+ } elseif (isset($orderedValues[$i])) {
610
+ // has ordered arg
611
+ $value = $orderedValues[$i];
612
+ $i++;
613
+ } elseif (isset($a[2])) {
614
+ // has default value
615
+ $value = $a[2];
616
+ } else {
617
+ $this->throwError("Failed to assign arg " . $a[1]);
618
+ $value = null; // :(
619
+ }
620
+
621
+ $value = $this->reduce($value);
622
+ $this->set($a[1], $value);
623
+ $assignedValues[] = $value;
624
+ } else {
625
+ // a lit
626
+ $i++;
627
+ }
628
+ }
629
+
630
+ // check for a rest
631
+ $last = end($args);
632
+ if ($last[0] == "rest") {
633
+ $rest = array_slice($orderedValues, count($args) - 1);
634
+ $this->set($last[1], $this->reduce(array("list", " ", $rest)));
635
+ }
636
+
637
+ // wow is this the only true use of PHP's + operator for arrays?
638
+ $this->env->arguments = $assignedValues + $orderedValues;
639
+ }
640
+
641
+ // compile a prop and update $lines or $blocks appropriately
642
+ protected function compileProp($prop, $block, $out) {
643
+ // set error position context
644
+ $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;
645
+
646
+ switch ($prop[0]) {
647
+ case 'assign':
648
+ list(, $name, $value) = $prop;
649
+ if ($name[0] == $this->vPrefix) {
650
+ $this->set($name, $value);
651
+ } else {
652
+ $out->lines[] = $this->formatter->property($name,
653
+ $this->compileValue($this->reduce($value)));
654
+ }
655
+ break;
656
+ case 'block':
657
+ list(, $child) = $prop;
658
+ $this->compileBlock($child);
659
+ break;
660
+ case 'mixin':
661
+ list(, $path, $args, $suffix) = $prop;
662
+
663
+ $orderedArgs = array();
664
+ $keywordArgs = array();
665
+ foreach ((array)$args as $arg) {
666
+ $argval = null;
667
+ switch ($arg[0]) {
668
+ case "arg":
669
+ if (!isset($arg[2])) {
670
+ $orderedArgs[] = $this->reduce(array("variable", $arg[1]));
671
+ } else {
672
+ $keywordArgs[$arg[1]] = $this->reduce($arg[2]);
673
+ }
674
+ break;
675
+
676
+ case "lit":
677
+ $orderedArgs[] = $this->reduce($arg[1]);
678
+ break;
679
+ default:
680
+ $this->throwError("Unknown arg type: " . $arg[0]);
681
+ }
682
+ }
683
+
684
+ $mixins = $this->findBlocks($block, $path, $orderedArgs, $keywordArgs);
685
+
686
+ if ($mixins === null) {
687
+ // fwrite(STDERR,"failed to find block: ".implode(" > ", $path)."\n");
688
+ break; // throw error here??
689
+ }
690
+
691
+ foreach ($mixins as $mixin) {
692
+ if ($mixin === $block && !$orderedArgs) {
693
+ continue;
694
+ }
695
+
696
+ $haveScope = false;
697
+ if (isset($mixin->parent->scope)) {
698
+ $haveScope = true;
699
+ $mixinParentEnv = $this->pushEnv();
700
+ $mixinParentEnv->storeParent = $mixin->parent->scope;
701
+ }
702
+
703
+ $haveArgs = false;
704
+ if (isset($mixin->args)) {
705
+ $haveArgs = true;
706
+ $this->pushEnv();
707
+ $this->zipSetArgs($mixin->args, $orderedArgs, $keywordArgs);
708
+ }
709
+
710
+ $oldParent = $mixin->parent;
711
+ if ($mixin != $block) $mixin->parent = $block;
712
+
713
+ foreach ($this->sortProps($mixin->props) as $subProp) {
714
+ if ($suffix !== null &&
715
+ $subProp[0] == "assign" &&
716
+ is_string($subProp[1]) &&
717
+ $subProp[1]{0} != $this->vPrefix)
718
+ {
719
+ $subProp[2] = array(
720
+ 'list', ' ',
721
+ array($subProp[2], array('keyword', $suffix))
722
+ );
723
+ }
724
+
725
+ $this->compileProp($subProp, $mixin, $out);
726
+ }
727
+
728
+ $mixin->parent = $oldParent;
729
+
730
+ if ($haveArgs) $this->popEnv();
731
+ if ($haveScope) $this->popEnv();
732
+ }
733
+
734
+ break;
735
+ case 'raw':
736
+ $out->lines[] = $prop[1];
737
+ break;
738
+ case "directive":
739
+ list(, $name, $value) = $prop;
740
+ $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
741
+ break;
742
+ case "comment":
743
+ $out->lines[] = $prop[1];
744
+ break;
745
+ case "import";
746
+ list(, $importPath, $importId) = $prop;
747
+ $importPath = $this->reduce($importPath);
748
+
749
+ if (!isset($this->env->imports)) {
750
+ $this->env->imports = array();
751
+ }
752
+
753
+ $result = $this->tryImport($importPath, $block, $out);
754
+
755
+ $this->env->imports[$importId] = $result === false ?
756
+ array(false, "@import " . $this->compileValue($importPath).";") :
757
+ $result;
758
+
759
+ break;
760
+ case "import_mixin":
761
+ list(,$importId) = $prop;
762
+ $import = $this->env->imports[$importId];
763
+ if ($import[0] === false) {
764
+ if (isset($import[1])) {
765
+ $out->lines[] = $import[1];
766
+ }
767
+ } else {
768
+ list(, $bottom, $parser, $importDir) = $import;
769
+ $this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
770
+ }
771
+
772
+ break;
773
+ default:
774
+ $this->throwError("unknown op: {$prop[0]}\n");
775
+ }
776
+ }
777
+
778
+
779
+ /**
780
+ * Compiles a primitive value into a CSS property value.
781
+ *
782
+ * Values in lessphp are typed by being wrapped in arrays, their format is
783
+ * typically:
784
+ *
785
+ * array(type, contents [, additional_contents]*)
786
+ *
787
+ * The input is expected to be reduced. This function will not work on
788
+ * things like expressions and variables.
789
+ */
790
+ protected function compileValue($value) {
791
+ switch ($value[0]) {
792
+ case 'list':
793
+ // [1] - delimiter
794
+ // [2] - array of values
795
+ return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
796
+ case 'raw_color':
797
+ if (!empty($this->formatter->compressColors)) {
798
+ return $this->compileValue($this->coerceColor($value));
799
+ }
800
+ return $value[1];
801
+ case 'keyword':
802
+ // [1] - the keyword
803
+ return $value[1];
804
+ case 'number':
805
+ list(, $num, $unit) = $value;
806
+ // [1] - the number
807
+ // [2] - the unit
808
+ if ($this->numberPrecision !== null) {
809
+ $num = round($num, $this->numberPrecision);
810
+ }
811
+ return $num . $unit;
812
+ case 'string':
813
+ // [1] - contents of string (includes quotes)
814
+ list(, $delim, $content) = $value;
815
+ foreach ($content as &$part) {
816
+ if (is_array($part)) {
817
+ $part = $this->compileValue($part);
818
+ }
819
+ }
820
+ return $delim . implode($content) . $delim;
821
+ case 'color':
822
+ // [1] - red component (either number or a %)
823
+ // [2] - green component
824
+ // [3] - blue component
825
+ // [4] - optional alpha component
826
+ list(, $r, $g, $b) = $value;
827
+ $r = round($r);
828
+ $g = round($g);
829
+ $b = round($b);
830
+
831
+ if (count($value) == 5 && $value[4] != 1) { // rgba
832
+ return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
833
+ }
834
+
835
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
836
+
837
+ if (!empty($this->formatter->compressColors)) {
838
+ // Converting hex color to short notation (e.g. #003399 to #039)
839
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
840
+ $h = '#' . $h[1] . $h[3] . $h[5];
841
+ }
842
+ }
843
+
844
+ return $h;
845
+
846
+ case 'function':
847
+ list(, $name, $args) = $value;
848
+ return $name.'('.$this->compileValue($args).')';
849
+ default: // assumed to be unit
850
+ $this->throwError("unknown value type: $value[0]");
851
+ }
852
+ }
853
+
854
+ protected function lib_pow($args) {
855
+ list($base, $exp) = $this->assertArgs($args, 2, "pow");
856
+ return pow($this->assertNumber($base), $this->assertNumber($exp));
857
+ }
858
+
859
+ protected function lib_pi() {
860
+ return pi();
861
+ }
862
+
863
+ protected function lib_mod($args) {
864
+ list($a, $b) = $this->assertArgs($args, 2, "mod");
865
+ return $this->assertNumber($a) % $this->assertNumber($b);
866
+ }
867
+
868
+ protected function lib_tan($num) {
869
+ return tan($this->assertNumber($num));
870
+ }
871
+
872
+ protected function lib_sin($num) {
873
+ return sin($this->assertNumber($num));
874
+ }
875
+
876
+ protected function lib_cos($num) {
877
+ return cos($this->assertNumber($num));
878
+ }
879
+
880
+ protected function lib_atan($num) {
881
+ $num = atan($this->assertNumber($num));
882
+ return array("number", $num, "rad");
883
+ }
884
+
885
+ protected function lib_asin($num) {
886
+ $num = asin($this->assertNumber($num));
887
+ return array("number", $num, "rad");
888
+ }
889
+
890
+ protected function lib_acos($num) {
891
+ $num = acos($this->assertNumber($num));
892
+ return array("number", $num, "rad");
893
+ }
894
+
895
+ protected function lib_sqrt($num) {
896
+ return sqrt($this->assertNumber($num));
897
+ }
898
+
899
+ protected function lib_extract($value) {
900
+ list($list, $idx) = $this->assertArgs($value, 2, "extract");
901
+ $idx = $this->assertNumber($idx);
902
+ // 1 indexed
903
+ if ($list[0] == "list" && isset($list[2][$idx - 1])) {
904
+ return $list[2][$idx - 1];
905
+ }
906
+ }
907
+
908
+ protected function lib_isnumber($value) {
909
+ return $this->toBool($value[0] == "number");
910
+ }
911
+
912
+ protected function lib_isstring($value) {
913
+ return $this->toBool($value[0] == "string");
914
+ }
915
+
916
+ protected function lib_iscolor($value) {
917
+ return $this->toBool($this->coerceColor($value));
918
+ }
919
+
920
+ protected function lib_iskeyword($value) {
921
+ return $this->toBool($value[0] == "keyword");
922
+ }
923
+
924
+ protected function lib_ispixel($value) {
925
+ return $this->toBool($value[0] == "number" && $value[2] == "px");
926
+ }
927
+
928
+ protected function lib_ispercentage($value) {
929
+ return $this->toBool($value[0] == "number" && $value[2] == "%");
930
+ }
931
+
932
+ protected function lib_isem($value) {
933
+ return $this->toBool($value[0] == "number" && $value[2] == "em");
934
+ }
935
+
936
+ protected function lib_isrem($value) {
937
+ return $this->toBool($value[0] == "number" && $value[2] == "rem");
938
+ }
939
+
940
+ protected function lib_rgbahex($color) {
941
+ $color = $this->coerceColor($color);
942
+ if (is_null($color))
943
+ $this->throwError("color expected for rgbahex");
944
+
945
+ return sprintf("#%02x%02x%02x%02x",
946
+ isset($color[4]) ? $color[4]*255 : 255,
947
+ $color[1],$color[2], $color[3]);
948
+ }
949
+
950
+ protected function lib_argb($color){
951
+ return $this->lib_rgbahex($color);
952
+ }
953
+
954
+ // utility func to unquote a string
955
+ protected function lib_e($arg) {
956
+ switch ($arg[0]) {
957
+ case "list":
958
+ $items = $arg[2];
959
+ if (isset($items[0])) {
960
+ return $this->lib_e($items[0]);
961
+ }
962
+ return self::$defaultValue;
963
+ case "string":
964
+ $arg[1] = "";
965
+ return $arg;
966
+ case "keyword":
967
+ return $arg;
968
+ default:
969
+ return array("keyword", $this->compileValue($arg));
970
+ }
971
+ }
972
+
973
+ protected function lib__sprintf($args) {
974
+ if ($args[0] != "list") return $args;
975
+ $values = $args[2];
976
+ $string = array_shift($values);
977
+ $template = $this->compileValue($this->lib_e($string));
978
+
979
+ $i = 0;
980
+ if (preg_match_all('/%[dsa]/', $template, $m)) {
981
+ foreach ($m[0] as $match) {
982
+ $val = isset($values[$i]) ?
983
+ $this->reduce($values[$i]) : array('keyword', '');
984
+
985
+ // lessjs compat, renders fully expanded color, not raw color
986
+ if ($color = $this->coerceColor($val)) {
987
+ $val = $color;
988
+ }
989
+
990
+ $i++;
991
+ $rep = $this->compileValue($this->lib_e($val));
992
+ $template = preg_replace('/'.self::preg_quote($match).'/',
993
+ $rep, $template, 1);
994
+ }
995
+ }
996
+
997
+ $d = $string[0] == "string" ? $string[1] : '"';
998
+ return array("string", $d, array($template));
999
+ }
1000
+
1001
+ protected function lib_floor($arg) {
1002
+ $value = $this->assertNumber($arg);
1003
+ return array("number", floor($value), $arg[2]);
1004
+ }
1005
+
1006
+ protected function lib_ceil($arg) {
1007
+ $value = $this->assertNumber($arg);
1008
+ return array("number", ceil($value), $arg[2]);
1009
+ }
1010
+
1011
+ protected function lib_round($arg) {
1012
+ $value = $this->assertNumber($arg);
1013
+ return array("number", round($value), $arg[2]);
1014
+ }
1015
+
1016
+ protected function lib_unit($arg) {
1017
+ if ($arg[0] == "list") {
1018
+ list($number, $newUnit) = $arg[2];
1019
+ return array("number", $this->assertNumber($number),
1020
+ $this->compileValue($this->lib_e($newUnit)));
1021
+ } else {
1022
+ return array("number", $this->assertNumber($arg), "");
1023
+ }
1024
+ }
1025
+
1026
+ /**
1027
+ * Helper function to get arguments for color manipulation functions.
1028
+ * takes a list that contains a color like thing and a percentage
1029
+ */
1030
+ protected function colorArgs($args) {
1031
+ if ($args[0] != 'list' || count($args[2]) < 2) {
1032
+ return array(array('color', 0, 0, 0), 0);
1033
+ }
1034
+ list($color, $delta) = $args[2];
1035
+ $color = $this->assertColor($color);
1036
+ $delta = floatval($delta[1]);
1037
+
1038
+ return array($color, $delta);
1039
+ }
1040
+
1041
+ protected function lib_darken($args) {
1042
+ list($color, $delta) = $this->colorArgs($args);
1043
+
1044
+ $hsl = $this->toHSL($color);
1045
+ $hsl[3] = $this->clamp($hsl[3] - $delta, 100);
1046
+ return $this->toRGB($hsl);
1047
+ }
1048
+
1049
+ protected function lib_lighten($args) {
1050
+ list($color, $delta) = $this->colorArgs($args);
1051
+
1052
+ $hsl = $this->toHSL($color);
1053
+ $hsl[3] = $this->clamp($hsl[3] + $delta, 100);
1054
+ return $this->toRGB($hsl);
1055
+ }
1056
+
1057
+ protected function lib_saturate($args) {
1058
+ list($color, $delta) = $this->colorArgs($args);
1059
+
1060
+ $hsl = $this->toHSL($color);
1061
+ $hsl[2] = $this->clamp($hsl[2] + $delta, 100);
1062
+ return $this->toRGB($hsl);
1063
+ }
1064
+
1065
+ protected function lib_desaturate($args) {
1066
+ list($color, $delta) = $this->colorArgs($args);
1067
+
1068
+ $hsl = $this->toHSL($color);
1069
+ $hsl[2] = $this->clamp($hsl[2] - $delta, 100);
1070
+ return $this->toRGB($hsl);
1071
+ }
1072
+
1073
+ protected function lib_spin($args) {
1074
+ list($color, $delta) = $this->colorArgs($args);
1075
+
1076
+ $hsl = $this->toHSL($color);
1077
+
1078
+ $hsl[1] = $hsl[1] + $delta % 360;
1079
+ if ($hsl[1] < 0) $hsl[1] += 360;
1080
+
1081
+ return $this->toRGB($hsl);
1082
+ }
1083
+
1084
+ protected function lib_fadeout($args) {
1085
+ list($color, $delta) = $this->colorArgs($args);
1086
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
1087
+ return $color;
1088
+ }
1089
+
1090
+ protected function lib_fadein($args) {
1091
+ list($color, $delta) = $this->colorArgs($args);
1092
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
1093
+ return $color;
1094
+ }
1095
+
1096
+ protected function lib_hue($color) {
1097
+ $hsl = $this->toHSL($this->assertColor($color));
1098
+ return round($hsl[1]);
1099
+ }
1100
+
1101
+ protected function lib_saturation($color) {
1102
+ $hsl = $this->toHSL($this->assertColor($color));
1103
+ return round($hsl[2]);
1104
+ }
1105
+
1106
+ protected function lib_lightness($color) {
1107
+ $hsl = $this->toHSL($this->assertColor($color));
1108
+ return round($hsl[3]);
1109
+ }
1110
+
1111
+ // get the alpha of a color
1112
+ // defaults to 1 for non-colors or colors without an alpha
1113
+ protected function lib_alpha($value) {
1114
+ if (!is_null($color = $this->coerceColor($value))) {
1115
+ return isset($color[4]) ? $color[4] : 1;
1116
+ }
1117
+ }
1118
+
1119
+ // set the alpha of the color
1120
+ protected function lib_fade($args) {
1121
+ list($color, $alpha) = $this->colorArgs($args);
1122
+ $color[4] = $this->clamp($alpha / 100.0);
1123
+ return $color;
1124
+ }
1125
+
1126
+ protected function lib_percentage($arg) {
1127
+ $num = $this->assertNumber($arg);
1128
+ return array("number", $num*100, "%");
1129
+ }
1130
+
1131
+ // mixes two colors by weight
1132
+ // mix(@color1, @color2, [@weight: 50%]);
1133
+ // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
1134
+ protected function lib_mix($args) {
1135
+ if ($args[0] != "list" || count($args[2]) < 2)
1136
+ $this->throwError("mix expects (color1, color2, weight)");
1137
+
1138
+ list($first, $second) = $args[2];
1139
+ $first = $this->assertColor($first);
1140
+ $second = $this->assertColor($second);
1141
+
1142
+ $first_a = $this->lib_alpha($first);
1143
+ $second_a = $this->lib_alpha($second);
1144
+
1145
+ if (isset($args[2][2])) {
1146
+ $weight = $args[2][2][1] / 100.0;
1147
+ } else {
1148
+ $weight = 0.5;
1149
+ }
1150
+
1151
+ $w = $weight * 2 - 1;
1152
+ $a = $first_a - $second_a;
1153
+
1154
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
1155
+ $w2 = 1.0 - $w1;
1156
+
1157
+ $new = array('color',
1158
+ $w1 * $first[1] + $w2 * $second[1],
1159
+ $w1 * $first[2] + $w2 * $second[2],
1160
+ $w1 * $first[3] + $w2 * $second[3],
1161
+ );
1162
+
1163
+ if ($first_a != 1.0 || $second_a != 1.0) {
1164
+ $new[] = $first_a * $weight + $second_a * ($weight - 1);
1165
+ }
1166
+
1167
+ return $this->fixColor($new);
1168
+ }
1169
+
1170
+ protected function lib_contrast($args) {
1171
+ if ($args[0] != 'list' || count($args[2]) < 3) {
1172
+ return array(array('color', 0, 0, 0), 0);
1173
+ }
1174
+
1175
+ list($inputColor, $darkColor, $lightColor) = $args[2];
1176
+
1177
+ $inputColor = $this->assertColor($inputColor);
1178
+ $darkColor = $this->assertColor($darkColor);
1179
+ $lightColor = $this->assertColor($lightColor);
1180
+ $hsl = $this->toHSL($inputColor);
1181
+
1182
+ if ($hsl[3] > 50) {
1183
+ return $darkColor;
1184
+ }
1185
+
1186
+ return $lightColor;
1187
+ }
1188
+
1189
+ protected function assertColor($value, $error = "expected color value") {
1190
+ $color = $this->coerceColor($value);
1191
+ if (is_null($color)) $this->throwError($error);
1192
+ return $color;
1193
+ }
1194
+
1195
+ protected function assertNumber($value, $error = "expecting number") {
1196
+ if ($value[0] == "number") return $value[1];
1197
+ $this->throwError($error);
1198
+ }
1199
+
1200
+ protected function assertArgs($value, $expectedArgs, $name="") {
1201
+ if ($expectedArgs == 1) {
1202
+ return $value;
1203
+ } else {
1204
+ if ($value[0] !== "list" || $value[1] != ",") $this->throwError("expecting list");
1205
+ $values = $value[2];
1206
+ $numValues = count($values);
1207
+ if ($expectedArgs != $numValues) {
1208
+ if ($name) {
1209
+ $name = $name . ": ";
1210
+ }
1211
+
1212
+ $this->throwError("${name}expecting $expectedArgs arguments, got $numValues");
1213
+ }
1214
+
1215
+ return $values;
1216
+ }
1217
+ }
1218
+
1219
+ protected function toHSL($color) {
1220
+ if ($color[0] == 'hsl') return $color;
1221
+
1222
+ $r = $color[1] / 255;
1223
+ $g = $color[2] / 255;
1224
+ $b = $color[3] / 255;
1225
+
1226
+ $min = min($r, $g, $b);
1227
+ $max = max($r, $g, $b);
1228
+
1229
+ $L = ($min + $max) / 2;
1230
+ if ($min == $max) {
1231
+ $S = $H = 0;
1232
+ } else {
1233
+ if ($L < 0.5)
1234
+ $S = ($max - $min)/($max + $min);
1235
+ else
1236
+ $S = ($max - $min)/(2.0 - $max - $min);
1237
+
1238
+ if ($r == $max) $H = ($g - $b)/($max - $min);
1239
+ elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min);
1240
+ elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min);
1241
+
1242
+ }
1243
+
1244
+ $out = array('hsl',
1245
+ ($H < 0 ? $H + 6 : $H)*60,
1246
+ $S*100,
1247
+ $L*100,
1248
+ );
1249
+
1250
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
1251
+ return $out;
1252
+ }
1253
+
1254
+ protected function toRGB_helper($comp, $temp1, $temp2) {
1255
+ if ($comp < 0) $comp += 1.0;
1256
+ elseif ($comp > 1) $comp -= 1.0;
1257
+
1258
+ if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
1259
+ if (2 * $comp < 1) return $temp2;
1260
+ if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
1261
+
1262
+ return $temp1;
1263
+ }
1264
+
1265
+ /**
1266
+ * Converts a hsl array into a color value in rgb.
1267
+ * Expects H to be in range of 0 to 360, S and L in 0 to 100
1268
+ */
1269
+ protected function toRGB($color) {
1270
+ if ($color[0] == 'color') return $color;
1271
+
1272
+ $H = $color[1] / 360;
1273
+ $S = $color[2] / 100;
1274
+ $L = $color[3] / 100;
1275
+
1276
+ if ($S == 0) {
1277
+ $r = $g = $b = $L;
1278
+ } else {
1279
+ $temp2 = $L < 0.5 ?
1280
+ $L*(1.0 + $S) :
1281
+ $L + $S - $L * $S;
1282
+
1283
+ $temp1 = 2.0 * $L - $temp2;
1284
+
1285
+ $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
1286
+ $g = $this->toRGB_helper($H, $temp1, $temp2);
1287
+ $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
1288
+ }
1289
+
1290
+ // $out = array('color', round($r*255), round($g*255), round($b*255));
1291
+ $out = array('color', $r*255, $g*255, $b*255);
1292
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
1293
+ return $out;
1294
+ }
1295
+
1296
+ protected function clamp($v, $max = 1, $min = 0) {
1297
+ return min($max, max($min, $v));
1298
+ }
1299
+
1300
+ /**
1301
+ * Convert the rgb, rgba, hsl color literals of function type
1302
+ * as returned by the parser into values of color type.
1303
+ */
1304
+ protected function funcToColor($func) {
1305
+ $fname = $func[1];
1306
+ if ($func[2][0] != 'list') return false; // need a list of arguments
1307
+ $rawComponents = $func[2][2];
1308
+
1309
+ if ($fname == 'hsl' || $fname == 'hsla') {
1310
+ $hsl = array('hsl');
1311
+ $i = 0;
1312
+ foreach ($rawComponents as $c) {
1313
+ $val = $this->reduce($c);
1314
+ $val = isset($val[1]) ? floatval($val[1]) : 0;
1315
+
1316
+ if ($i == 0) $clamp = 360;
1317
+ elseif ($i < 3) $clamp = 100;
1318
+ else $clamp = 1;
1319
+
1320
+ $hsl[] = $this->clamp($val, $clamp);
1321
+ $i++;
1322
+ }
1323
+
1324
+ while (count($hsl) < 4) $hsl[] = 0;
1325
+ return $this->toRGB($hsl);
1326
+
1327
+ } elseif ($fname == 'rgb