Version Description
- Completely rewritten lightbox code
- Add: Automatically resize lightbox to fit window
- Add: APIs for third-party add-ons
- Add: Flexible theme support
- Add: Flexible content handler support
- Add: Mobile-optimized responsive themes (2)
- Optimize: PHP class autoloading
- Optimize: Improved performance and compatibility
- Optimize: Full internationalization support
Download this release
Release Info
Developer | Archetyped |
Plugin | Simple Lightbox |
Version | 2.0 |
Comparing to | |
See all releases |
Code changes from version 1.4 to 2.0
- CONTRIBUTING.md +28 -0
- COPYING +339 -339
- README.md +11 -0
- assets/screenshot-1.png +0 -0
- assets/screenshot-2.jpg +0 -0
- assets/screenshot-3.jpg +0 -0
- client/config.rb +24 -0
- client/css/admin.css +1 -0
- client/js/lib.admin.js +31 -0
- client/js/lib.core.js +591 -0
- client/js/lib.view.js +4649 -0
- client/sass/admin.scss +31 -0
- content-handlers/image/handler.image.js +29 -0
- css/admin.css +0 -3
- css/lightbox.css +0 -135
- images/blank.gif +0 -0
- images/closelabel.gif +0 -0
- images/nextlabel.gif +0 -0
- images/prevlabel.gif +0 -0
- includes/class.admin.php +1576 -0
- includes/class.base.php +438 -88
- includes/class.base_collection.php +369 -0
- includes/class.base_object.php +277 -0
- includes/class.collection_controller.php +57 -0
- includes/class.component.php +89 -0
- includes/class.content_handler.php +57 -0
- includes/class.content_handlers.php +228 -0
- includes/class.fields.php +2590 -0
- includes/class.options.php +673 -0
- includes/class.template_tag.php +9 -0
- includes/class.template_tags.php +101 -0
- includes/class.theme.php +103 -0
- includes/class.themes.php +225 -0
- includes/class.utilities.php +1346 -84
- js/dev/lightbox.js +0 -736
- js/lib.js +0 -22
- l10n/simple-lightbox-tr_TR.mo +0 -0
- l10n/simple-lightbox-tr_TR.po +163 -0
- l10n/simple-lightbox.pot +218 -0
- main.php +31 -11
- model.php +964 -364
- readme.txt +202 -80
- screenshot-1.gif +0 -0
- screenshot-2.gif +0 -0
- template-tags/item/tag.item.js +17 -0
- template-tags/ui/tag.ui.js +108 -0
- themes/black/config.rb +23 -0
- themes/black/css/style.css +1 -0
- themes/black/images/loading.gif +0 -0
- themes/black/images/nav_next.png +0 -0
- themes/black/images/nav_prev.png +0 -0
- themes/black/sass/style.scss +37 -0
- themes/default/client.js +202 -0
- themes/default/config.rb +23 -0
- themes/default/css/style.css +1 -0
- {images → themes/default/images}/loading.gif +0 -0
- themes/default/images/nav_next.png +0 -0
- themes/default/images/nav_prev.png +0 -0
- themes/default/images/ui_close.png +0 -0
- themes/default/images/ui_slideshow_pause.png +0 -0
- themes/default/images/ui_slideshow_play.png +0 -0
- themes/default/layout.html +41 -0
- themes/default/sass/style.scss +294 -0
CONTRIBUTING.md
ADDED
@@ -0,0 +1,28 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# How to contribute
|
2 |
+
|
3 |
+
User feedback is huge. You're experiencing an issue, want a new feature, or just want to shout to the mountains about how much you love Simple Lightbox? Here's how to do it and get the best outcome.
|
4 |
+
|
5 |
+
## Getting Started
|
6 |
+
|
7 |
+
* Install the [latest version of SLB][latest]
|
8 |
+
* Get a [GitHub account][gh] if you don't already have one.
|
9 |
+
|
10 |
+
Now you're ready to contribute!
|
11 |
+
|
12 |
+
## Reporting Issues
|
13 |
+
|
14 |
+
Because of the vast number and variety of sites WordPress powers, your reports are essential to making sure that SLB works everywhere. Sometimes an issue may be particular to your site's setup and sometimes it might be universal to all users. Either way, you can report your issue here.
|
15 |
+
|
16 |
+
Before reporting an issue, please read [Reporting Issues][report-issue] to ensure that you've provided the necessary information for your issue to be properly investigated.
|
17 |
+
|
18 |
+
|
19 |
+
## Additional Resources
|
20 |
+
|
21 |
+
* [Simple Lightbox's Official Page][slb]
|
22 |
+
* [Simple Lightbox on WordPress.org][slb-wp]
|
23 |
+
|
24 |
+
[slb]: http://archetyped.com/tools/simple-lightbox/ "Simple Lightbox"
|
25 |
+
[slb-wp]: http://wordpress.org/plugins/simple-lightbox
|
26 |
+
[latest]: https://github.com/archetyped/simple-lightbox "Simple Lightbox"
|
27 |
+
[gh]: https://github.com/signup/free "GitHub Signup"
|
28 |
+
[report-issue]: https://github.com/archetyped/simple-lightbox/wiki/Reporting-Issues "Reporting Issues"
|
COPYING
CHANGED
@@ -1,339 +1,339 @@
|
|
1 |
-
GNU GENERAL PUBLIC LICENSE
|
2 |
-
Version 2, June 1991
|
3 |
-
|
4 |
-
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
5 |
-
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
6 |
-
Everyone is permitted to copy and distribute verbatim copies
|
7 |
-
of this license document, but changing it is not allowed.
|
8 |
-
|
9 |
-
Preamble
|
10 |
-
|
11 |
-
The licenses for most software are designed to take away your
|
12 |
-
freedom to share and change it. By contrast, the GNU General Public
|
13 |
-
License is intended to guarantee your freedom to share and change free
|
14 |
-
software--to make sure the software is free for all its users. This
|
15 |
-
General Public License applies to most of the Free Software
|
16 |
-
Foundation's software and to any other program whose authors commit to
|
17 |
-
using it. (Some other Free Software Foundation software is covered by
|
18 |
-
the GNU Lesser General Public License instead.) You can apply it to
|
19 |
-
your programs, too.
|
20 |
-
|
21 |
-
When we speak of free software, we are referring to freedom, not
|
22 |
-
price. Our General Public Licenses are designed to make sure that you
|
23 |
-
have the freedom to distribute copies of free software (and charge for
|
24 |
-
this service if you wish), that you receive source code or can get it
|
25 |
-
if you want it, that you can change the software or use pieces of it
|
26 |
-
in new free programs; and that you know you can do these things.
|
27 |
-
|
28 |
-
To protect your rights, we need to make restrictions that forbid
|
29 |
-
anyone to deny you these rights or to ask you to surrender the rights.
|
30 |
-
These restrictions translate to certain responsibilities for you if you
|
31 |
-
distribute copies of the software, or if you modify it.
|
32 |
-
|
33 |
-
For example, if you distribute copies of such a program, whether
|
34 |
-
gratis or for a fee, you must give the recipients all the rights that
|
35 |
-
you have. You must make sure that they, too, receive or can get the
|
36 |
-
source code. And you must show them these terms so they know their
|
37 |
-
rights.
|
38 |
-
|
39 |
-
We protect your rights with two steps: (1) copyright the software, and
|
40 |
-
(2) offer you this license which gives you legal permission to copy,
|
41 |
-
distribute and/or modify the software.
|
42 |
-
|
43 |
-
Also, for each author's protection and ours, we want to make certain
|
44 |
-
that everyone understands that there is no warranty for this free
|
45 |
-
software. If the software is modified by someone else and passed on, we
|
46 |
-
want its recipients to know that what they have is not the original, so
|
47 |
-
that any problems introduced by others will not reflect on the original
|
48 |
-
authors' reputations.
|
49 |
-
|
50 |
-
Finally, any free program is threatened constantly by software
|
51 |
-
patents. We wish to avoid the danger that redistributors of a free
|
52 |
-
program will individually obtain patent licenses, in effect making the
|
53 |
-
program proprietary. To prevent this, we have made it clear that any
|
54 |
-
patent must be licensed for everyone's free use or not licensed at all.
|
55 |
-
|
56 |
-
The precise terms and conditions for copying, distribution and
|
57 |
-
modification follow.
|
58 |
-
|
59 |
-
GNU GENERAL PUBLIC LICENSE
|
60 |
-
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
61 |
-
|
62 |
-
0. This License applies to any program or other work which contains
|
63 |
-
a notice placed by the copyright holder saying it may be distributed
|
64 |
-
under the terms of this General Public License. The "Program", below,
|
65 |
-
refers to any such program or work, and a "work based on the Program"
|
66 |
-
means either the Program or any derivative work under copyright law:
|
67 |
-
that is to say, a work containing the Program or a portion of it,
|
68 |
-
either verbatim or with modifications and/or translated into another
|
69 |
-
language. (Hereinafter, translation is included without limitation in
|
70 |
-
the term "modification".) Each licensee is addressed as "you".
|
71 |
-
|
72 |
-
Activities other than copying, distribution and modification are not
|
73 |
-
covered by this License; they are outside its scope. The act of
|
74 |
-
running the Program is not restricted, and the output from the Program
|
75 |
-
is covered only if its contents constitute a work based on the
|
76 |
-
Program (independent of having been made by running the Program).
|
77 |
-
Whether that is true depends on what the Program does.
|
78 |
-
|
79 |
-
1. You may copy and distribute verbatim copies of the Program's
|
80 |
-
source code as you receive it, in any medium, provided that you
|
81 |
-
conspicuously and appropriately publish on each copy an appropriate
|
82 |
-
copyright notice and disclaimer of warranty; keep intact all the
|
83 |
-
notices that refer to this License and to the absence of any warranty;
|
84 |
-
and give any other recipients of the Program a copy of this License
|
85 |
-
along with the Program.
|
86 |
-
|
87 |
-
You may charge a fee for the physical act of transferring a copy, and
|
88 |
-
you may at your option offer warranty protection in exchange for a fee.
|
89 |
-
|
90 |
-
2. You may modify your copy or copies of the Program or any portion
|
91 |
-
of it, thus forming a work based on the Program, and copy and
|
92 |
-
distribute such modifications or work under the terms of Section 1
|
93 |
-
above, provided that you also meet all of these conditions:
|
94 |
-
|
95 |
-
a) You must cause the modified files to carry prominent notices
|
96 |
-
stating that you changed the files and the date of any change.
|
97 |
-
|
98 |
-
b) You must cause any work that you distribute or publish, that in
|
99 |
-
whole or in part contains or is derived from the Program or any
|
100 |
-
part thereof, to be licensed as a whole at no charge to all third
|
101 |
-
parties under the terms of this License.
|
102 |
-
|
103 |
-
c) If the modified program normally reads commands interactively
|
104 |
-
when run, you must cause it, when started running for such
|
105 |
-
interactive use in the most ordinary way, to print or display an
|
106 |
-
announcement including an appropriate copyright notice and a
|
107 |
-
notice that there is no warranty (or else, saying that you provide
|
108 |
-
a warranty) and that users may redistribute the program under
|
109 |
-
these conditions, and telling the user how to view a copy of this
|
110 |
-
License. (Exception: if the Program itself is interactive but
|
111 |
-
does not normally print such an announcement, your work based on
|
112 |
-
the Program is not required to print an announcement.)
|
113 |
-
|
114 |
-
These requirements apply to the modified work as a whole. If
|
115 |
-
identifiable sections of that work are not derived from the Program,
|
116 |
-
and can be reasonably considered independent and separate works in
|
117 |
-
themselves, then this License, and its terms, do not apply to those
|
118 |
-
sections when you distribute them as separate works. But when you
|
119 |
-
distribute the same sections as part of a whole which is a work based
|
120 |
-
on the Program, the distribution of the whole must be on the terms of
|
121 |
-
this License, whose permissions for other licensees extend to the
|
122 |
-
entire whole, and thus to each and every part regardless of who wrote it.
|
123 |
-
|
124 |
-
Thus, it is not the intent of this section to claim rights or contest
|
125 |
-
your rights to work written entirely by you; rather, the intent is to
|
126 |
-
exercise the right to control the distribution of derivative or
|
127 |
-
collective works based on the Program.
|
128 |
-
|
129 |
-
In addition, mere aggregation of another work not based on the Program
|
130 |
-
with the Program (or with a work based on the Program) on a volume of
|
131 |
-
a storage or distribution medium does not bring the other work under
|
132 |
-
the scope of this License.
|
133 |
-
|
134 |
-
3. You may copy and distribute the Program (or a work based on it,
|
135 |
-
under Section 2) in object code or executable form under the terms of
|
136 |
-
Sections 1 and 2 above provided that you also do one of the following:
|
137 |
-
|
138 |
-
a) Accompany it with the complete corresponding machine-readable
|
139 |
-
source code, which must be distributed under the terms of Sections
|
140 |
-
1 and 2 above on a medium customarily used for software interchange; or,
|
141 |
-
|
142 |
-
b) Accompany it with a written offer, valid for at least three
|
143 |
-
years, to give any third party, for a charge no more than your
|
144 |
-
cost of physically performing source distribution, a complete
|
145 |
-
machine-readable copy of the corresponding source code, to be
|
146 |
-
distributed under the terms of Sections 1 and 2 above on a medium
|
147 |
-
customarily used for software interchange; or,
|
148 |
-
|
149 |
-
c) Accompany it with the information you received as to the offer
|
150 |
-
to distribute corresponding source code. (This alternative is
|
151 |
-
allowed only for noncommercial distribution and only if you
|
152 |
-
received the program in object code or executable form with such
|
153 |
-
an offer, in accord with Subsection b above.)
|
154 |
-
|
155 |
-
The source code for a work means the preferred form of the work for
|
156 |
-
making modifications to it. For an executable work, complete source
|
157 |
-
code means all the source code for all modules it contains, plus any
|
158 |
-
associated interface definition files, plus the scripts used to
|
159 |
-
control compilation and installation of the executable. However, as a
|
160 |
-
special exception, the source code distributed need not include
|
161 |
-
anything that is normally distributed (in either source or binary
|
162 |
-
form) with the major components (compiler, kernel, and so on) of the
|
163 |
-
operating system on which the executable runs, unless that component
|
164 |
-
itself accompanies the executable.
|
165 |
-
|
166 |
-
If distribution of executable or object code is made by offering
|
167 |
-
access to copy from a designated place, then offering equivalent
|
168 |
-
access to copy the source code from the same place counts as
|
169 |
-
distribution of the source code, even though third parties are not
|
170 |
-
compelled to copy the source along with the object code.
|
171 |
-
|
172 |
-
4. You may not copy, modify, sublicense, or distribute the Program
|
173 |
-
except as expressly provided under this License. Any attempt
|
174 |
-
otherwise to copy, modify, sublicense or distribute the Program is
|
175 |
-
void, and will automatically terminate your rights under this License.
|
176 |
-
However, parties who have received copies, or rights, from you under
|
177 |
-
this License will not have their licenses terminated so long as such
|
178 |
-
parties remain in full compliance.
|
179 |
-
|
180 |
-
5. You are not required to accept this License, since you have not
|
181 |
-
signed it. However, nothing else grants you permission to modify or
|
182 |
-
distribute the Program or its derivative works. These actions are
|
183 |
-
prohibited by law if you do not accept this License. Therefore, by
|
184 |
-
modifying or distributing the Program (or any work based on the
|
185 |
-
Program), you indicate your acceptance of this License to do so, and
|
186 |
-
all its terms and conditions for copying, distributing or modifying
|
187 |
-
the Program or works based on it.
|
188 |
-
|
189 |
-
6. Each time you redistribute the Program (or any work based on the
|
190 |
-
Program), the recipient automatically receives a license from the
|
191 |
-
original licensor to copy, distribute or modify the Program subject to
|
192 |
-
these terms and conditions. You may not impose any further
|
193 |
-
restrictions on the recipients' exercise of the rights granted herein.
|
194 |
-
You are not responsible for enforcing compliance by third parties to
|
195 |
-
this License.
|
196 |
-
|
197 |
-
7. If, as a consequence of a court judgment or allegation of patent
|
198 |
-
infringement or for any other reason (not limited to patent issues),
|
199 |
-
conditions are imposed on you (whether by court order, agreement or
|
200 |
-
otherwise) that contradict the conditions of this License, they do not
|
201 |
-
excuse you from the conditions of this License. If you cannot
|
202 |
-
distribute so as to satisfy simultaneously your obligations under this
|
203 |
-
License and any other pertinent obligations, then as a consequence you
|
204 |
-
may not distribute the Program at all. For example, if a patent
|
205 |
-
license would not permit royalty-free redistribution of the Program by
|
206 |
-
all those who receive copies directly or indirectly through you, then
|
207 |
-
the only way you could satisfy both it and this License would be to
|
208 |
-
refrain entirely from distribution of the Program.
|
209 |
-
|
210 |
-
If any portion of this section is held invalid or unenforceable under
|
211 |
-
any particular circumstance, the balance of the section is intended to
|
212 |
-
apply and the section as a whole is intended to apply in other
|
213 |
-
circumstances.
|
214 |
-
|
215 |
-
It is not the purpose of this section to induce you to infringe any
|
216 |
-
patents or other property right claims or to contest validity of any
|
217 |
-
such claims; this section has the sole purpose of protecting the
|
218 |
-
integrity of the free software distribution system, which is
|
219 |
-
implemented by public license practices. Many people have made
|
220 |
-
generous contributions to the wide range of software distributed
|
221 |
-
through that system in reliance on consistent application of that
|
222 |
-
system; it is up to the author/donor to decide if he or she is willing
|
223 |
-
to distribute software through any other system and a licensee cannot
|
224 |
-
impose that choice.
|
225 |
-
|
226 |
-
This section is intended to make thoroughly clear what is believed to
|
227 |
-
be a consequence of the rest of this License.
|
228 |
-
|
229 |
-
8. If the distribution and/or use of the Program is restricted in
|
230 |
-
certain countries either by patents or by copyrighted interfaces, the
|
231 |
-
original copyright holder who places the Program under this License
|
232 |
-
may add an explicit geographical distribution limitation excluding
|
233 |
-
those countries, so that distribution is permitted only in or among
|
234 |
-
countries not thus excluded. In such case, this License incorporates
|
235 |
-
the limitation as if written in the body of this License.
|
236 |
-
|
237 |
-
9. The Free Software Foundation may publish revised and/or new versions
|
238 |
-
of the General Public License from time to time. Such new versions will
|
239 |
-
be similar in spirit to the present version, but may differ in detail to
|
240 |
-
address new problems or concerns.
|
241 |
-
|
242 |
-
Each version is given a distinguishing version number. If the Program
|
243 |
-
specifies a version number of this License which applies to it and "any
|
244 |
-
later version", you have the option of following the terms and conditions
|
245 |
-
either of that version or of any later version published by the Free
|
246 |
-
Software Foundation. If the Program does not specify a version number of
|
247 |
-
this License, you may choose any version ever published by the Free Software
|
248 |
-
Foundation.
|
249 |
-
|
250 |
-
10. If you wish to incorporate parts of the Program into other free
|
251 |
-
programs whose distribution conditions are different, write to the author
|
252 |
-
to ask for permission. For software which is copyrighted by the Free
|
253 |
-
Software Foundation, write to the Free Software Foundation; we sometimes
|
254 |
-
make exceptions for this. Our decision will be guided by the two goals
|
255 |
-
of preserving the free status of all derivatives of our free software and
|
256 |
-
of promoting the sharing and reuse of software generally.
|
257 |
-
|
258 |
-
NO WARRANTY
|
259 |
-
|
260 |
-
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
261 |
-
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
262 |
-
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
263 |
-
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
264 |
-
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
265 |
-
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
266 |
-
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
267 |
-
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
268 |
-
REPAIR OR CORRECTION.
|
269 |
-
|
270 |
-
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
271 |
-
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
272 |
-
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
273 |
-
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
274 |
-
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
275 |
-
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
276 |
-
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
277 |
-
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
278 |
-
POSSIBILITY OF SUCH DAMAGES.
|
279 |
-
|
280 |
-
END OF TERMS AND CONDITIONS
|
281 |
-
|
282 |
-
How to Apply These Terms to Your New Programs
|
283 |
-
|
284 |
-
If you develop a new program, and you want it to be of the greatest
|
285 |
-
possible use to the public, the best way to achieve this is to make it
|
286 |
-
free software which everyone can redistribute and change under these terms.
|
287 |
-
|
288 |
-
To do so, attach the following notices to the program. It is safest
|
289 |
-
to attach them to the start of each source file to most effectively
|
290 |
-
convey the exclusion of warranty; and each file should have at least
|
291 |
-
the "copyright" line and a pointer to where the full notice is found.
|
292 |
-
|
293 |
-
<one line to give the program's name and a brief idea of what it does.>
|
294 |
-
Copyright (C) <year> <name of author>
|
295 |
-
|
296 |
-
This program is free software; you can redistribute it and/or modify
|
297 |
-
it under the terms of the GNU General Public License as published by
|
298 |
-
the Free Software Foundation; either version 2 of the License, or
|
299 |
-
(at your option) any later version.
|
300 |
-
|
301 |
-
This program is distributed in the hope that it will be useful,
|
302 |
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
303 |
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
304 |
-
GNU General Public License for more details.
|
305 |
-
|
306 |
-
You should have received a copy of the GNU General Public License along
|
307 |
-
with this program; if not, write to the Free Software Foundation, Inc.,
|
308 |
-
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
309 |
-
|
310 |
-
Also add information on how to contact you by electronic and paper mail.
|
311 |
-
|
312 |
-
If the program is interactive, make it output a short notice like this
|
313 |
-
when it starts in an interactive mode:
|
314 |
-
|
315 |
-
Gnomovision version 69, Copyright (C) year name of author
|
316 |
-
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
317 |
-
This is free software, and you are welcome to redistribute it
|
318 |
-
under certain conditions; type `show c' for details.
|
319 |
-
|
320 |
-
The hypothetical commands `show w' and `show c' should show the appropriate
|
321 |
-
parts of the General Public License. Of course, the commands you use may
|
322 |
-
be called something other than `show w' and `show c'; they could even be
|
323 |
-
mouse-clicks or menu items--whatever suits your program.
|
324 |
-
|
325 |
-
You should also get your employer (if you work as a programmer) or your
|
326 |
-
school, if any, to sign a "copyright disclaimer" for the program, if
|
327 |
-
necessary. Here is a sample; alter the names:
|
328 |
-
|
329 |
-
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
330 |
-
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
331 |
-
|
332 |
-
<signature of Ty Coon>, 1 April 1989
|
333 |
-
Ty Coon, President of Vice
|
334 |
-
|
335 |
-
This General Public License does not permit incorporating your program into
|
336 |
-
proprietary programs. If your program is a subroutine library, you may
|
337 |
-
consider it more useful to permit linking proprietary applications with the
|
338 |
-
library. If this is what you want to do, use the GNU Lesser General
|
339 |
-
Public License instead of this License.
|
1 |
+
GNU GENERAL PUBLIC LICENSE
|
2 |
+
Version 2, June 1991
|
3 |
+
|
4 |
+
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
5 |
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
6 |
+
Everyone is permitted to copy and distribute verbatim copies
|
7 |
+
of this license document, but changing it is not allowed.
|
8 |
+
|
9 |
+
Preamble
|
10 |
+
|
11 |
+
The licenses for most software are designed to take away your
|
12 |
+
freedom to share and change it. By contrast, the GNU General Public
|
13 |
+
License is intended to guarantee your freedom to share and change free
|
14 |
+
software--to make sure the software is free for all its users. This
|
15 |
+
General Public License applies to most of the Free Software
|
16 |
+
Foundation's software and to any other program whose authors commit to
|
17 |
+
using it. (Some other Free Software Foundation software is covered by
|
18 |
+
the GNU Lesser General Public License instead.) You can apply it to
|
19 |
+
your programs, too.
|
20 |
+
|
21 |
+
When we speak of free software, we are referring to freedom, not
|
22 |
+
price. Our General Public Licenses are designed to make sure that you
|
23 |
+
have the freedom to distribute copies of free software (and charge for
|
24 |
+
this service if you wish), that you receive source code or can get it
|
25 |
+
if you want it, that you can change the software or use pieces of it
|
26 |
+
in new free programs; and that you know you can do these things.
|
27 |
+
|
28 |
+
To protect your rights, we need to make restrictions that forbid
|
29 |
+
anyone to deny you these rights or to ask you to surrender the rights.
|
30 |
+
These restrictions translate to certain responsibilities for you if you
|
31 |
+
distribute copies of the software, or if you modify it.
|
32 |
+
|
33 |
+
For example, if you distribute copies of such a program, whether
|
34 |
+
gratis or for a fee, you must give the recipients all the rights that
|
35 |
+
you have. You must make sure that they, too, receive or can get the
|
36 |
+
source code. And you must show them these terms so they know their
|
37 |
+
rights.
|
38 |
+
|
39 |
+
We protect your rights with two steps: (1) copyright the software, and
|
40 |
+
(2) offer you this license which gives you legal permission to copy,
|
41 |
+
distribute and/or modify the software.
|
42 |
+
|
43 |
+
Also, for each author's protection and ours, we want to make certain
|
44 |
+
that everyone understands that there is no warranty for this free
|
45 |
+
software. If the software is modified by someone else and passed on, we
|
46 |
+
want its recipients to know that what they have is not the original, so
|
47 |
+
that any problems introduced by others will not reflect on the original
|
48 |
+
authors' reputations.
|
49 |
+
|
50 |
+
Finally, any free program is threatened constantly by software
|
51 |
+
patents. We wish to avoid the danger that redistributors of a free
|
52 |
+
program will individually obtain patent licenses, in effect making the
|
53 |
+
program proprietary. To prevent this, we have made it clear that any
|
54 |
+
patent must be licensed for everyone's free use or not licensed at all.
|
55 |
+
|
56 |
+
The precise terms and conditions for copying, distribution and
|
57 |
+
modification follow.
|
58 |
+
|
59 |
+
GNU GENERAL PUBLIC LICENSE
|
60 |
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
61 |
+
|
62 |
+
0. This License applies to any program or other work which contains
|
63 |
+
a notice placed by the copyright holder saying it may be distributed
|
64 |
+
under the terms of this General Public License. The "Program", below,
|
65 |
+
refers to any such program or work, and a "work based on the Program"
|
66 |
+
means either the Program or any derivative work under copyright law:
|
67 |
+
that is to say, a work containing the Program or a portion of it,
|
68 |
+
either verbatim or with modifications and/or translated into another
|
69 |
+
language. (Hereinafter, translation is included without limitation in
|
70 |
+
the term "modification".) Each licensee is addressed as "you".
|
71 |
+
|
72 |
+
Activities other than copying, distribution and modification are not
|
73 |
+
covered by this License; they are outside its scope. The act of
|
74 |
+
running the Program is not restricted, and the output from the Program
|
75 |
+
is covered only if its contents constitute a work based on the
|
76 |
+
Program (independent of having been made by running the Program).
|
77 |
+
Whether that is true depends on what the Program does.
|
78 |
+
|
79 |
+
1. You may copy and distribute verbatim copies of the Program's
|
80 |
+
source code as you receive it, in any medium, provided that you
|
81 |
+
conspicuously and appropriately publish on each copy an appropriate
|
82 |
+
copyright notice and disclaimer of warranty; keep intact all the
|
83 |
+
notices that refer to this License and to the absence of any warranty;
|
84 |
+
and give any other recipients of the Program a copy of this License
|
85 |
+
along with the Program.
|
86 |
+
|
87 |
+
You may charge a fee for the physical act of transferring a copy, and
|
88 |
+
you may at your option offer warranty protection in exchange for a fee.
|
89 |
+
|
90 |
+
2. You may modify your copy or copies of the Program or any portion
|
91 |
+
of it, thus forming a work based on the Program, and copy and
|
92 |
+
distribute such modifications or work under the terms of Section 1
|
93 |
+
above, provided that you also meet all of these conditions:
|
94 |
+
|
95 |
+
a) You must cause the modified files to carry prominent notices
|
96 |
+
stating that you changed the files and the date of any change.
|
97 |
+
|
98 |
+
b) You must cause any work that you distribute or publish, that in
|
99 |
+
whole or in part contains or is derived from the Program or any
|
100 |
+
part thereof, to be licensed as a whole at no charge to all third
|
101 |
+
parties under the terms of this License.
|
102 |
+
|
103 |
+
c) If the modified program normally reads commands interactively
|
104 |
+
when run, you must cause it, when started running for such
|
105 |
+
interactive use in the most ordinary way, to print or display an
|
106 |
+
announcement including an appropriate copyright notice and a
|
107 |
+
notice that there is no warranty (or else, saying that you provide
|
108 |
+
a warranty) and that users may redistribute the program under
|
109 |
+
these conditions, and telling the user how to view a copy of this
|
110 |
+
License. (Exception: if the Program itself is interactive but
|
111 |
+
does not normally print such an announcement, your work based on
|
112 |
+
the Program is not required to print an announcement.)
|
113 |
+
|
114 |
+
These requirements apply to the modified work as a whole. If
|
115 |
+
identifiable sections of that work are not derived from the Program,
|
116 |
+
and can be reasonably considered independent and separate works in
|
117 |
+
themselves, then this License, and its terms, do not apply to those
|
118 |
+
sections when you distribute them as separate works. But when you
|
119 |
+
distribute the same sections as part of a whole which is a work based
|
120 |
+
on the Program, the distribution of the whole must be on the terms of
|
121 |
+
this License, whose permissions for other licensees extend to the
|
122 |
+
entire whole, and thus to each and every part regardless of who wrote it.
|
123 |
+
|
124 |
+
Thus, it is not the intent of this section to claim rights or contest
|
125 |
+
your rights to work written entirely by you; rather, the intent is to
|
126 |
+
exercise the right to control the distribution of derivative or
|
127 |
+
collective works based on the Program.
|
128 |
+
|
129 |
+
In addition, mere aggregation of another work not based on the Program
|
130 |
+
with the Program (or with a work based on the Program) on a volume of
|
131 |
+
a storage or distribution medium does not bring the other work under
|
132 |
+
the scope of this License.
|
133 |
+
|
134 |
+
3. You may copy and distribute the Program (or a work based on it,
|
135 |
+
under Section 2) in object code or executable form under the terms of
|
136 |
+
Sections 1 and 2 above provided that you also do one of the following:
|
137 |
+
|
138 |
+
a) Accompany it with the complete corresponding machine-readable
|
139 |
+
source code, which must be distributed under the terms of Sections
|
140 |
+
1 and 2 above on a medium customarily used for software interchange; or,
|
141 |
+
|
142 |
+
b) Accompany it with a written offer, valid for at least three
|
143 |
+
years, to give any third party, for a charge no more than your
|
144 |
+
cost of physically performing source distribution, a complete
|
145 |
+
machine-readable copy of the corresponding source code, to be
|
146 |
+
distributed under the terms of Sections 1 and 2 above on a medium
|
147 |
+
customarily used for software interchange; or,
|
148 |
+
|
149 |
+
c) Accompany it with the information you received as to the offer
|
150 |
+
to distribute corresponding source code. (This alternative is
|
151 |
+
allowed only for noncommercial distribution and only if you
|
152 |
+
received the program in object code or executable form with such
|
153 |
+
an offer, in accord with Subsection b above.)
|
154 |
+
|
155 |
+
The source code for a work means the preferred form of the work for
|
156 |
+
making modifications to it. For an executable work, complete source
|
157 |
+
code means all the source code for all modules it contains, plus any
|
158 |
+
associated interface definition files, plus the scripts used to
|
159 |
+
control compilation and installation of the executable. However, as a
|
160 |
+
special exception, the source code distributed need not include
|
161 |
+
anything that is normally distributed (in either source or binary
|
162 |
+
form) with the major components (compiler, kernel, and so on) of the
|
163 |
+
operating system on which the executable runs, unless that component
|
164 |
+
itself accompanies the executable.
|
165 |
+
|
166 |
+
If distribution of executable or object code is made by offering
|
167 |
+
access to copy from a designated place, then offering equivalent
|
168 |
+
access to copy the source code from the same place counts as
|
169 |
+
distribution of the source code, even though third parties are not
|
170 |
+
compelled to copy the source along with the object code.
|
171 |
+
|
172 |
+
4. You may not copy, modify, sublicense, or distribute the Program
|
173 |
+
except as expressly provided under this License. Any attempt
|
174 |
+
otherwise to copy, modify, sublicense or distribute the Program is
|
175 |
+
void, and will automatically terminate your rights under this License.
|
176 |
+
However, parties who have received copies, or rights, from you under
|
177 |
+
this License will not have their licenses terminated so long as such
|
178 |
+
parties remain in full compliance.
|
179 |
+
|
180 |
+
5. You are not required to accept this License, since you have not
|
181 |
+
signed it. However, nothing else grants you permission to modify or
|
182 |
+
distribute the Program or its derivative works. These actions are
|
183 |
+
prohibited by law if you do not accept this License. Therefore, by
|
184 |
+
modifying or distributing the Program (or any work based on the
|
185 |
+
Program), you indicate your acceptance of this License to do so, and
|
186 |
+
all its terms and conditions for copying, distributing or modifying
|
187 |
+
the Program or works based on it.
|
188 |
+
|
189 |
+
6. Each time you redistribute the Program (or any work based on the
|
190 |
+
Program), the recipient automatically receives a license from the
|
191 |
+
original licensor to copy, distribute or modify the Program subject to
|
192 |
+
these terms and conditions. You may not impose any further
|
193 |
+
restrictions on the recipients' exercise of the rights granted herein.
|
194 |
+
You are not responsible for enforcing compliance by third parties to
|
195 |
+
this License.
|
196 |
+
|
197 |
+
7. If, as a consequence of a court judgment or allegation of patent
|
198 |
+
infringement or for any other reason (not limited to patent issues),
|
199 |
+
conditions are imposed on you (whether by court order, agreement or
|
200 |
+
otherwise) that contradict the conditions of this License, they do not
|
201 |
+
excuse you from the conditions of this License. If you cannot
|
202 |
+
distribute so as to satisfy simultaneously your obligations under this
|
203 |
+
License and any other pertinent obligations, then as a consequence you
|
204 |
+
may not distribute the Program at all. For example, if a patent
|
205 |
+
license would not permit royalty-free redistribution of the Program by
|
206 |
+
all those who receive copies directly or indirectly through you, then
|
207 |
+
the only way you could satisfy both it and this License would be to
|
208 |
+
refrain entirely from distribution of the Program.
|
209 |
+
|
210 |
+
If any portion of this section is held invalid or unenforceable under
|
211 |
+
any particular circumstance, the balance of the section is intended to
|
212 |
+
apply and the section as a whole is intended to apply in other
|
213 |
+
circumstances.
|
214 |
+
|
215 |
+
It is not the purpose of this section to induce you to infringe any
|
216 |
+
patents or other property right claims or to contest validity of any
|
217 |
+
such claims; this section has the sole purpose of protecting the
|
218 |
+
integrity of the free software distribution system, which is
|
219 |
+
implemented by public license practices. Many people have made
|
220 |
+
generous contributions to the wide range of software distributed
|
221 |
+
through that system in reliance on consistent application of that
|
222 |
+
system; it is up to the author/donor to decide if he or she is willing
|
223 |
+
to distribute software through any other system and a licensee cannot
|
224 |
+
impose that choice.
|
225 |
+
|
226 |
+
This section is intended to make thoroughly clear what is believed to
|
227 |
+
be a consequence of the rest of this License.
|
228 |
+
|
229 |
+
8. If the distribution and/or use of the Program is restricted in
|
230 |
+
certain countries either by patents or by copyrighted interfaces, the
|
231 |
+
original copyright holder who places the Program under this License
|
232 |
+
may add an explicit geographical distribution limitation excluding
|
233 |
+
those countries, so that distribution is permitted only in or among
|
234 |
+
countries not thus excluded. In such case, this License incorporates
|
235 |
+
the limitation as if written in the body of this License.
|
236 |
+
|
237 |
+
9. The Free Software Foundation may publish revised and/or new versions
|
238 |
+
of the General Public License from time to time. Such new versions will
|
239 |
+
be similar in spirit to the present version, but may differ in detail to
|
240 |
+
address new problems or concerns.
|
241 |
+
|
242 |
+
Each version is given a distinguishing version number. If the Program
|
243 |
+
specifies a version number of this License which applies to it and "any
|
244 |
+
later version", you have the option of following the terms and conditions
|
245 |
+
either of that version or of any later version published by the Free
|
246 |
+
Software Foundation. If the Program does not specify a version number of
|
247 |
+
this License, you may choose any version ever published by the Free Software
|
248 |
+
Foundation.
|
249 |
+
|
250 |
+
10. If you wish to incorporate parts of the Program into other free
|
251 |
+
programs whose distribution conditions are different, write to the author
|
252 |
+
to ask for permission. For software which is copyrighted by the Free
|
253 |
+
Software Foundation, write to the Free Software Foundation; we sometimes
|
254 |
+
make exceptions for this. Our decision will be guided by the two goals
|
255 |
+
of preserving the free status of all derivatives of our free software and
|
256 |
+
of promoting the sharing and reuse of software generally.
|
257 |
+
|
258 |
+
NO WARRANTY
|
259 |
+
|
260 |
+
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
261 |
+
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
262 |
+
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
263 |
+
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
264 |
+
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
265 |
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
266 |
+
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
267 |
+
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
268 |
+
REPAIR OR CORRECTION.
|
269 |
+
|
270 |
+
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
271 |
+
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
272 |
+
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
273 |
+
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
274 |
+
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
275 |
+
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
276 |
+
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
277 |
+
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
278 |
+
POSSIBILITY OF SUCH DAMAGES.
|
279 |
+
|
280 |
+
END OF TERMS AND CONDITIONS
|
281 |
+
|
282 |
+
How to Apply These Terms to Your New Programs
|
283 |
+
|
284 |
+
If you develop a new program, and you want it to be of the greatest
|
285 |
+
possible use to the public, the best way to achieve this is to make it
|
286 |
+
free software which everyone can redistribute and change under these terms.
|
287 |
+
|
288 |
+
To do so, attach the following notices to the program. It is safest
|
289 |
+
to attach them to the start of each source file to most effectively
|
290 |
+
convey the exclusion of warranty; and each file should have at least
|
291 |
+
the "copyright" line and a pointer to where the full notice is found.
|
292 |
+
|
293 |
+
<one line to give the program's name and a brief idea of what it does.>
|
294 |
+
Copyright (C) <year> <name of author>
|
295 |
+
|
296 |
+
This program is free software; you can redistribute it and/or modify
|
297 |
+
it under the terms of the GNU General Public License as published by
|
298 |
+
the Free Software Foundation; either version 2 of the License, or
|
299 |
+
(at your option) any later version.
|
300 |
+
|
301 |
+
This program is distributed in the hope that it will be useful,
|
302 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
303 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
304 |
+
GNU General Public License for more details.
|
305 |
+
|
306 |
+
You should have received a copy of the GNU General Public License along
|
307 |
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
308 |
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
309 |
+
|
310 |
+
Also add information on how to contact you by electronic and paper mail.
|
311 |
+
|
312 |
+
If the program is interactive, make it output a short notice like this
|
313 |
+
when it starts in an interactive mode:
|
314 |
+
|
315 |
+
Gnomovision version 69, Copyright (C) year name of author
|
316 |
+
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
317 |
+
This is free software, and you are welcome to redistribute it
|
318 |
+
under certain conditions; type `show c' for details.
|
319 |
+
|
320 |
+
The hypothetical commands `show w' and `show c' should show the appropriate
|
321 |
+
parts of the General Public License. Of course, the commands you use may
|
322 |
+
be called something other than `show w' and `show c'; they could even be
|
323 |
+
mouse-clicks or menu items--whatever suits your program.
|
324 |
+
|
325 |
+
You should also get your employer (if you work as a programmer) or your
|
326 |
+
school, if any, to sign a "copyright disclaimer" for the program, if
|
327 |
+
necessary. Here is a sample; alter the names:
|
328 |
+
|
329 |
+
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
330 |
+
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
331 |
+
|
332 |
+
<signature of Ty Coon>, 1 April 1989
|
333 |
+
Ty Coon, President of Vice
|
334 |
+
|
335 |
+
This General Public License does not permit incorporating your program into
|
336 |
+
proprietary programs. If your program is a subroutine library, you may
|
337 |
+
consider it more useful to permit linking proprietary applications with the
|
338 |
+
library. If this is what you want to do, use the GNU Lesser General
|
339 |
+
Public License instead of this License.
|
README.md
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
Simple Lightbox
|
2 |
+
===============
|
3 |
+
|
4 |
+
The highly customizable lightbox for WordPress
|
5 |
+
|
6 |
+
http://archetyped.com/tools/simple-lightbox/
|
7 |
+
|
8 |
+
## Support
|
9 |
+
Found a bug or otherwise experiencing an issue with Simple Lightbox? [Report the issue here][issue-report]
|
10 |
+
|
11 |
+
[issue-report]: https://github.com/archetyped/simple-lightbox/wiki/Reporting-Issues "Report an issue"
|
assets/screenshot-1.png
ADDED
Binary file
|
assets/screenshot-2.jpg
ADDED
Binary file
|
assets/screenshot-3.jpg
ADDED
Binary file
|
client/config.rb
ADDED
@@ -0,0 +1,24 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# Require any additional compass plugins here.
|
2 |
+
|
3 |
+
# Set this to the root of your project when deployed:
|
4 |
+
http_path = "/"
|
5 |
+
css_dir = "css"
|
6 |
+
sass_dir = "sass"
|
7 |
+
images_dir = "images"
|
8 |
+
javascripts_dir = "js"
|
9 |
+
|
10 |
+
# You can select your preferred output style here (can be overridden via the command line):
|
11 |
+
output_style = :compressed
|
12 |
+
|
13 |
+
# To enable relative paths to assets via compass helper functions. Uncomment:
|
14 |
+
# relative_assets = true
|
15 |
+
|
16 |
+
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
17 |
+
# line_comments = false
|
18 |
+
|
19 |
+
|
20 |
+
# If you prefer the indented syntax, you might want to regenerate this
|
21 |
+
# project again passing --syntax sass, or you can uncomment this:
|
22 |
+
# preferred_syntax = :sass
|
23 |
+
# and then run:
|
24 |
+
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
client/css/admin.css
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
.slb_section_head{display:block;padding:2em 0 0}.slb_option_item .block{display:inline-block}.slb_option_item label.title{width:200px;padding:10px}.slb_option_item .input{font-size:11px;line-height:20px;margin-bottom:9px;padding:8px 10px}.slb_option_item .input select{min-width:12em}.slb_notice{color:#f00;font-weight:bold}
|
client/js/lib.admin.js
ADDED
@@ -0,0 +1,31 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Admin
|
3 |
+
* @package Simple Lightbox
|
4 |
+
* @subpackage Admin
|
5 |
+
* @author Archetyped
|
6 |
+
*/
|
7 |
+
|
8 |
+
(function ($) {
|
9 |
+
|
10 |
+
if ( !SLB || !SLB.attach ) {
|
11 |
+
return false;
|
12 |
+
}
|
13 |
+
|
14 |
+
var Admin = {
|
15 |
+
/**
|
16 |
+
* Initialization routines
|
17 |
+
*/
|
18 |
+
init: function() {
|
19 |
+
if ( postboxes ) {
|
20 |
+
postboxes.add_postbox_toggles(pagenow);
|
21 |
+
}
|
22 |
+
},
|
23 |
+
}
|
24 |
+
|
25 |
+
SLB.attach('Admin', Admin);
|
26 |
+
|
27 |
+
$(document).ready(function() {
|
28 |
+
SLB.Admin.init();
|
29 |
+
});
|
30 |
+
|
31 |
+
})(jQuery);
|
client/js/lib.core.js
ADDED
@@ -0,0 +1,591 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Core
|
3 |
+
* @package SLB
|
4 |
+
* @author Archetyped
|
5 |
+
*/
|
6 |
+
|
7 |
+
(function($) {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Extendible class
|
11 |
+
* Adapted from John Resig
|
12 |
+
* @link http://ejohn.org/blog/simple-javascript-inheritance/
|
13 |
+
*/
|
14 |
+
var c_init = false;
|
15 |
+
var Class = function() {};
|
16 |
+
|
17 |
+
Class.extend = function(members) {
|
18 |
+
var _super = this.prototype;
|
19 |
+
|
20 |
+
//Copy instance to prototype
|
21 |
+
c_init = true;
|
22 |
+
var proto = new this();
|
23 |
+
c_init = false;
|
24 |
+
|
25 |
+
var val;
|
26 |
+
//Scrub prototype objects (Decouple from super class)
|
27 |
+
for ( var name in proto ) {
|
28 |
+
if ( $.isPlainObject(proto[name]) ) {
|
29 |
+
val = $.extend({}, proto[name]);
|
30 |
+
proto[name] = val;
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
//Copy members
|
35 |
+
for ( var name in members ) {
|
36 |
+
//Evaluate function members (if overwriting super class method)
|
37 |
+
if ( 'function' == typeof members[name] && 'function' == typeof _super[name] ) {
|
38 |
+
proto[name] = (function(name, fn) {
|
39 |
+
return function() {
|
40 |
+
//Cache super variable
|
41 |
+
var tmp = this._super;
|
42 |
+
//Set variable to super class method
|
43 |
+
this._super = _super[name];
|
44 |
+
//Call method
|
45 |
+
var ret = fn.apply(this, arguments);
|
46 |
+
//Restore super variable
|
47 |
+
this._super = tmp;
|
48 |
+
//Return value
|
49 |
+
return ret;
|
50 |
+
}
|
51 |
+
})(name, members[name]);
|
52 |
+
} else {
|
53 |
+
val = members[name];
|
54 |
+
if ( $.isPlainObject(members[name]) ) {
|
55 |
+
val = $.extend({}, members[name]);
|
56 |
+
}
|
57 |
+
proto[name] = val;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
//Constructor
|
62 |
+
function Class() {
|
63 |
+
if ( !c_init ) {
|
64 |
+
//Private init
|
65 |
+
if ( this._init ) {
|
66 |
+
this._init.apply(this, arguments);
|
67 |
+
}
|
68 |
+
//Main Constructor
|
69 |
+
if ( this._c ) {
|
70 |
+
this._c.apply(this, arguments);
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
|
76 |
+
//Populate new prototype
|
77 |
+
Class.prototype = proto;
|
78 |
+
|
79 |
+
//Set constructor
|
80 |
+
Class.prototype.constructor = Class;
|
81 |
+
|
82 |
+
Class.extend = arguments.callee;
|
83 |
+
|
84 |
+
//Return function
|
85 |
+
return Class;
|
86 |
+
};
|
87 |
+
|
88 |
+
/* Base */
|
89 |
+
var Base = {
|
90 |
+
/* Properties */
|
91 |
+
|
92 |
+
base: false,
|
93 |
+
_parent: null,
|
94 |
+
prefix: 'slb',
|
95 |
+
|
96 |
+
/* Methods */
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Constructor
|
100 |
+
*/
|
101 |
+
_init: function() {
|
102 |
+
this._set_parent();
|
103 |
+
},
|
104 |
+
|
105 |
+
_set_parent: function(p) {
|
106 |
+
if ( typeof p != 'undefined' )
|
107 |
+
this._parent = p;
|
108 |
+
this.util._parent = this;
|
109 |
+
},
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Attach member to object
|
113 |
+
* @param string name Member name
|
114 |
+
* @param mixed Member data
|
115 |
+
* > obj: Member inherits from base object
|
116 |
+
* > other: Simple data object
|
117 |
+
*/
|
118 |
+
attach: function(member, data, simple) {
|
119 |
+
simple = ( typeof simple == undefined ) ? false : !!simple;
|
120 |
+
if ( $.type(member) == 'string' && $.isPlainObject(data) ) {
|
121 |
+
//Add initial member
|
122 |
+
var obj = {};
|
123 |
+
if ( simple ) {
|
124 |
+
//Simple object
|
125 |
+
obj[member] = $.extend({}, data);
|
126 |
+
$.extend(this, obj);
|
127 |
+
} else {
|
128 |
+
//Add new instance object
|
129 |
+
data['_parent'] = this;
|
130 |
+
var c = this.Class.extend(data);
|
131 |
+
this[member] = new c();
|
132 |
+
}
|
133 |
+
}
|
134 |
+
},
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Get parent object
|
138 |
+
* @return obj Parent object
|
139 |
+
*/
|
140 |
+
get_parent: function() {
|
141 |
+
return this._parent;
|
142 |
+
},
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Utility methods
|
146 |
+
*/
|
147 |
+
util: {
|
148 |
+
/* Properties */
|
149 |
+
|
150 |
+
_base: null,
|
151 |
+
_parent: null,
|
152 |
+
|
153 |
+
/* Constants */
|
154 |
+
|
155 |
+
string: 'string',
|
156 |
+
bool: 'boolean',
|
157 |
+
array: 'array',
|
158 |
+
obj: 'object',
|
159 |
+
func: 'function',
|
160 |
+
num: 'number',
|
161 |
+
|
162 |
+
/* Methods */
|
163 |
+
|
164 |
+
get_base: function() {
|
165 |
+
if ( !this._base ) {
|
166 |
+
var p = this.get_parent();
|
167 |
+
var p_last = null;
|
168 |
+
//Iterate through parents
|
169 |
+
while ( !p.base && p_last != p && p._parent ) {
|
170 |
+
p_last = p;
|
171 |
+
p = p._parent;
|
172 |
+
}
|
173 |
+
//Set base
|
174 |
+
this._base = p;
|
175 |
+
}
|
176 |
+
return this._base;
|
177 |
+
},
|
178 |
+
|
179 |
+
get_parent: function() {
|
180 |
+
return this._parent;
|
181 |
+
},
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Retrieve valid separator
|
185 |
+
* If supplied argument is not a valid separator, use default separator
|
186 |
+
* @param string (optional) sep Separator text
|
187 |
+
* @return string Separator text
|
188 |
+
*/
|
189 |
+
get_sep: function(sep) {
|
190 |
+
return ( this.is_string(sep, false) ) ? sep : '_';
|
191 |
+
},
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Retrieve prefix
|
195 |
+
* @return string Prefix
|
196 |
+
*/
|
197 |
+
get_prefix: function() {
|
198 |
+
return ( this.is_string(this.get_parent().prefix) ) ? this.get_parent().prefix : '';
|
199 |
+
},
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Check if string is prefixed
|
203 |
+
*/
|
204 |
+
has_prefix: function(val, sep) {
|
205 |
+
return ( this.is_string(val) && val.indexOf(this.get_prefix() + this.get_sep(sep)) === 0 );
|
206 |
+
},
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Add Prefix to a string
|
210 |
+
* @param string val Value to add prefix to
|
211 |
+
* @param string sep (optional) Separator (Default: `_`)
|
212 |
+
* @param bool (optional) once If text should only be prefixed once (Default: TRUE)
|
213 |
+
*/
|
214 |
+
add_prefix: function(val, sep, once) {
|
215 |
+
//Validate
|
216 |
+
if ( !this.is_string(val) ) {
|
217 |
+
//Return prefix if value to add prefix to is empty
|
218 |
+
return this.get_prefix();
|
219 |
+
}
|
220 |
+
sep = this.get_sep(sep);
|
221 |
+
if ( !this.is_bool(once) ) {
|
222 |
+
once = true;
|
223 |
+
}
|
224 |
+
|
225 |
+
return ( once && this.has_prefix(val, sep) ) ? val : [this.get_prefix(), val].join(sep);
|
226 |
+
},
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Remove Prefix from a string
|
230 |
+
* @param string val Value to add prefix to
|
231 |
+
* @param string sep (optional) Separator (Default: `_`)
|
232 |
+
* @param bool (optional) once If text should only be prefixed once (Default: true)
|
233 |
+
*/
|
234 |
+
remove_prefix: function(val, sep, once) {
|
235 |
+
//Validate parameters
|
236 |
+
if ( !this.is_string(val, true) ) {
|
237 |
+
return val;
|
238 |
+
}
|
239 |
+
//Default values
|
240 |
+
sep = this.get_sep(sep);
|
241 |
+
if ( !this.is_bool(once) ) {
|
242 |
+
once = true;
|
243 |
+
}
|
244 |
+
//Check if string is prefixed
|
245 |
+
if ( this.has_prefix(val, sep) ) {
|
246 |
+
//Remove prefix
|
247 |
+
var prfx = this.get_prefix() + sep;
|
248 |
+
do {
|
249 |
+
val = val.substr(prfx.length);
|
250 |
+
} while ( !once && this.has_prefix(val, sep) );
|
251 |
+
}
|
252 |
+
return val;
|
253 |
+
},
|
254 |
+
|
255 |
+
/*
|
256 |
+
* Get attribute name
|
257 |
+
* @param string val Attribute's base name
|
258 |
+
*/
|
259 |
+
get_attribute: function(val) {
|
260 |
+
//Setup
|
261 |
+
var sep = '-';
|
262 |
+
var top = 'data';
|
263 |
+
//Validate
|
264 |
+
var pre = [top, this.get_prefix()].join(sep);
|
265 |
+
if ( !this.is_string(val, false) ) {
|
266 |
+
return pre;
|
267 |
+
}
|
268 |
+
//Process
|
269 |
+
if ( val.indexOf(pre + sep) == -1 ) {
|
270 |
+
val = [pre, val].join(sep);
|
271 |
+
}
|
272 |
+
return val;
|
273 |
+
},
|
274 |
+
|
275 |
+
/* Request */
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Retrieve valid context
|
279 |
+
* @return array Context
|
280 |
+
*/
|
281 |
+
get_context: function() {
|
282 |
+
//Valid context
|
283 |
+
var b = this.get_base();
|
284 |
+
if ( !$.isArray(b.context) )
|
285 |
+
b.context = [];
|
286 |
+
//Return context
|
287 |
+
return b.context;
|
288 |
+
},
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Check if a context exists in current request
|
292 |
+
* If multiple contexts are supplied, result will be TRUE if at least ONE context exists
|
293 |
+
*
|
294 |
+
* @param string|array ctx Context to check for
|
295 |
+
* @return bool TRUE if context exists, FALSE otherwise
|
296 |
+
*/
|
297 |
+
is_context: function(ctx) {
|
298 |
+
var ret = false;
|
299 |
+
//Validate context
|
300 |
+
if ( typeof ctx == 'string' )
|
301 |
+
ctx = [ctx];
|
302 |
+
if ( $.isArray(ctx) && this.arr_intersect(this.get_context(), ctx).length ) {
|
303 |
+
ret = true;
|
304 |
+
}
|
305 |
+
return ret;
|
306 |
+
},
|
307 |
+
|
308 |
+
/* Helpers */
|
309 |
+
|
310 |
+
is_set: function(value) {
|
311 |
+
return ( $.type(value) != 'undefined' ) ? true : false;
|
312 |
+
},
|
313 |
+
|
314 |
+
is_type: function(value, type, nonempty) {
|
315 |
+
var ret = false;
|
316 |
+
if ( this.is_set(value) && null != value && this.is_set(type) ) {
|
317 |
+
switch ( $.type(type) ) {
|
318 |
+
case this.func:
|
319 |
+
ret = ( value instanceof type ) ? true : false;
|
320 |
+
break;
|
321 |
+
case this.string:
|
322 |
+
ret = ( $.type(value) == type ) ? true : false;
|
323 |
+
break;
|
324 |
+
default:
|
325 |
+
ret = false;
|
326 |
+
break;
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
//Validate empty values
|
331 |
+
if ( ret && ( $.type(nonempty) != this.bool || nonempty ) ) {
|
332 |
+
ret = !this.is_empty(value);
|
333 |
+
}
|
334 |
+
return ret;
|
335 |
+
},
|
336 |
+
|
337 |
+
is_string: function(value, nonempty) {
|
338 |
+
return this.is_type(value, this.string, nonempty);
|
339 |
+
},
|
340 |
+
|
341 |
+
is_array: function(value, nonempty) {
|
342 |
+
return ( this.is_type(value, this.array, nonempty) );
|
343 |
+
},
|
344 |
+
|
345 |
+
is_bool: function(value) {
|
346 |
+
return this.is_type(value, this.bool, false);
|
347 |
+
},
|
348 |
+
|
349 |
+
is_obj: function(value, nonempty) {
|
350 |
+
return this.is_type(value, this.obj, nonempty);
|
351 |
+
},
|
352 |
+
|
353 |
+
is_func: function(value) {
|
354 |
+
return this.is_type(value, this.func, false);
|
355 |
+
},
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Checks if an object has a method
|
359 |
+
* @param obj Object to check
|
360 |
+
* @param string|array Names of methods to check for
|
361 |
+
* @return bool TRUE if method(s) exist, FALSE otherwise
|
362 |
+
*/
|
363 |
+
is_method: function(obj, value) {
|
364 |
+
var ret = false;
|
365 |
+
if ( this.is_string(value) ) {
|
366 |
+
value = [value];
|
367 |
+
}
|
368 |
+
if ( this.in_obj(obj, value) ) {
|
369 |
+
var t = this;
|
370 |
+
$.each(value, function(idx, val) {
|
371 |
+
ret = ( t.is_func(obj[val]) ) ? true : false;
|
372 |
+
return ret;
|
373 |
+
});
|
374 |
+
}
|
375 |
+
return ret;
|
376 |
+
},
|
377 |
+
|
378 |
+
is_num: function(value, nonempty) {
|
379 |
+
return ( this.is_type(value, this.num, nonempty) && !isNaN(value) );
|
380 |
+
},
|
381 |
+
|
382 |
+
is_int: function(value, nonempty) {
|
383 |
+
return ( this.is_num(value, nonempty) && Math.floor(value) === value );
|
384 |
+
},
|
385 |
+
|
386 |
+
is_scalar: function(value, nonempty) {
|
387 |
+
return ( this.is_num(value, nonempty) || this.is_string(value, nonempty) || this.is_bool(value, nonempty) );
|
388 |
+
},
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Checks if value is empty
|
392 |
+
* @param mixed value Value to check
|
393 |
+
* @param string type (optional) Data type
|
394 |
+
* @return bool TRUE if value is empty, FALSE if not empty
|
395 |
+
*/
|
396 |
+
is_empty: function(value, type) {
|
397 |
+
var ret = false;
|
398 |
+
//Initial check for empty value
|
399 |
+
if ( !this.is_set(value) || null === value || false === value ) {
|
400 |
+
ret = true;
|
401 |
+
} else {
|
402 |
+
//Validate type
|
403 |
+
if ( !this.is_set(type) ) {
|
404 |
+
type = $.type(value);
|
405 |
+
}
|
406 |
+
//Type-based check
|
407 |
+
if ( this.is_type(value, type, false) ) {
|
408 |
+
switch ( type ) {
|
409 |
+
case this.string:
|
410 |
+
case this.array:
|
411 |
+
if ( value.length == 0 ) {
|
412 |
+
ret = true;
|
413 |
+
}
|
414 |
+
break;
|
415 |
+
case this.obj:
|
416 |
+
//Only evaluate literal objects
|
417 |
+
ret = ( $.isPlainObject(value) && !$.map(value, function(v, key) { return key; }).length );
|
418 |
+
break;
|
419 |
+
case this.num:
|
420 |
+
ret = ( value === 0 );
|
421 |
+
break;
|
422 |
+
}
|
423 |
+
} else {
|
424 |
+
ret = true;
|
425 |
+
}
|
426 |
+
}
|
427 |
+
return ret;
|
428 |
+
},
|
429 |
+
|
430 |
+
/**
|
431 |
+
* Check if object is a jQuery.Promise instance
|
432 |
+
* Will also match (but not guarantee) jQuery.Deferred instances
|
433 |
+
* @return bool TRUE if object is Promise/Deferred, FALSE otherwise
|
434 |
+
*/
|
435 |
+
is_promise: function(obj) {
|
436 |
+
return ( this.is_obj(obj) && this.is_method(obj, ['then', 'done', 'always', 'fail', 'pipe']) )
|
437 |
+
},
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Check if object is a jQuery.Deferred instance
|
441 |
+
*/
|
442 |
+
is_deferred: function(obj) {
|
443 |
+
return ( this.is_promise(obj) && this.is_method(obj, ['resolve', 'reject', 'promise']));
|
444 |
+
},
|
445 |
+
|
446 |
+
/**
|
447 |
+
* Validate specified value's data type and return default value if necessary
|
448 |
+
* Data type of default value is used to determine data type
|
449 |
+
* @param mixed val Value to check
|
450 |
+
* @param mixed def Default value
|
451 |
+
* @return mixed Valid value
|
452 |
+
*/
|
453 |
+
validate: function(val, def) {
|
454 |
+
return ( this.is_type(val, def, true) ) ? val : def;
|
455 |
+
},
|
456 |
+
|
457 |
+
/**
|
458 |
+
* Return formatted string
|
459 |
+
*/
|
460 |
+
format: function(fmt, val) {
|
461 |
+
if ( !this.is_string(fmt) ) {
|
462 |
+
return '';
|
463 |
+
}
|
464 |
+
var params = [],
|
465 |
+
ph = '%s';
|
466 |
+
//Stop processing if no replacement values specified or format string contains no placeholders
|
467 |
+
if ( arguments.length < 2 || fmt.indexOf(ph) == -1 ) {
|
468 |
+
return fmt;
|
469 |
+
}
|
470 |
+
//Get replacement values
|
471 |
+
params = Array.prototype.slice.call(arguments, 1);
|
472 |
+
|
473 |
+
//Replace placeholders in string with parameters
|
474 |
+
|
475 |
+
//Replace all placeholders at once if single parameter set
|
476 |
+
if ( params.length == 1 ) {
|
477 |
+
fmt = fmt.replace(ph, params[0].toString());
|
478 |
+
} else {
|
479 |
+
var idx = 0,
|
480 |
+
len = params.length,
|
481 |
+
pos = 0;
|
482 |
+
while ( ( pos = fmt.indexOf(ph) ) && idx < len ) {
|
483 |
+
fmt = fmt.substr(0, pos) + params[idx].toString() + fmt.substr(pos + ph.length);
|
484 |
+
idx++;
|
485 |
+
}
|
486 |
+
//Remove any remaining placeholders
|
487 |
+
fmt = fmt.replace(ph, '');
|
488 |
+
}
|
489 |
+
return fmt;
|
490 |
+
},
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Checks if key(s) exist in an object
|
494 |
+
* @param object obj Object to check
|
495 |
+
* @param string|array key Key(s) to check for in object
|
496 |
+
* @return bool TRUE if key(s) exist in object, FALSE otherwise
|
497 |
+
*/
|
498 |
+
in_obj: function(obj, key, all) {
|
499 |
+
//Validate
|
500 |
+
if ( !this.is_bool(all) ) {
|
501 |
+
all = true;
|
502 |
+
}
|
503 |
+
if ( this.is_string(key) ) {
|
504 |
+
key = [key];
|
505 |
+
}
|
506 |
+
var ret = false;
|
507 |
+
if ( this.is_obj(obj) && this.is_array(key) ) {
|
508 |
+
var val;
|
509 |
+
for ( var x = 0; x < key.length; x++ ) {
|
510 |
+
val = key[x];
|
511 |
+
ret = ( this.is_string(val) && ( val in obj ) ) ? true : false;
|
512 |
+
//Stop processing if conditions have been met
|
513 |
+
if ( ( !all && ret ) || ( all && !ret ) ) {
|
514 |
+
break;
|
515 |
+
}
|
516 |
+
}
|
517 |
+
}
|
518 |
+
return ret;
|
519 |
+
},
|
520 |
+
|
521 |
+
/**
|
522 |
+
* Find common elements of 2 arrays
|
523 |
+
* @param array arr1 First array
|
524 |
+
* @param array arr2 Second array
|
525 |
+
* @return array Elements common to both arrays
|
526 |
+
*/
|
527 |
+
arr_intersect: function(arr1, arr2) {
|
528 |
+
var ret = [];
|
529 |
+
if ( arr1 == arr2 ) {
|
530 |
+
return arr2;
|
531 |
+
}
|
532 |
+
if ( !$.isArray(arr2) || !arr2.length || !arr1.length ) {
|
533 |
+
return ret;
|
534 |
+
}
|
535 |
+
//Compare elements in arrays
|
536 |
+
var a1;
|
537 |
+
var a2;
|
538 |
+
var val;
|
539 |
+
if ( arr1.length < arr2.length ) {
|
540 |
+
a1 = arr1;
|
541 |
+
a2 = arr2;
|
542 |
+
} else {
|
543 |
+
a1 = arr2;
|
544 |
+
a2 = arr1;
|
545 |
+
}
|
546 |
+
|
547 |
+
for ( var x = 0; x < a1.length; x++ ) {
|
548 |
+
//Add mutual elements into intersection array
|
549 |
+
val = a1[x];
|
550 |
+
if ( a2.indexOf(val) != -1 && ret.indexOf(val) == -1 )
|
551 |
+
ret.push(val);
|
552 |
+
}
|
553 |
+
|
554 |
+
//Return intersection results
|
555 |
+
return ret;
|
556 |
+
}
|
557 |
+
}
|
558 |
+
};
|
559 |
+
var SLB_Base = Class.extend(Base);
|
560 |
+
|
561 |
+
//Init global object
|
562 |
+
var Core = {
|
563 |
+
/* Properties */
|
564 |
+
|
565 |
+
base: true,
|
566 |
+
context: [],
|
567 |
+
|
568 |
+
/**
|
569 |
+
* New object initializer
|
570 |
+
* @var obj
|
571 |
+
*/
|
572 |
+
Class: SLB_Base,
|
573 |
+
|
574 |
+
/* Methods */
|
575 |
+
|
576 |
+
/**
|
577 |
+
* Setup client
|
578 |
+
* Set variables, DOM, etc.
|
579 |
+
*/
|
580 |
+
setup_client: function() {
|
581 |
+
/* Quick Hide */
|
582 |
+
$('html').addClass(this.util.get_prefix());
|
583 |
+
}
|
584 |
+
};
|
585 |
+
var SLB_Core = SLB_Base.extend(Core);
|
586 |
+
|
587 |
+
this.SLB = new SLB_Core();
|
588 |
+
|
589 |
+
SLB.setup_client();
|
590 |
+
|
591 |
+
})(jQuery);
|
client/js/lib.view.js
ADDED
@@ -0,0 +1,4649 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* View (Lightbox) functionality
|
3 |
+
* @package Simple Lightbox
|
4 |
+
* @subpackage View
|
5 |
+
* @author Archetyped
|
6 |
+
*/
|
7 |
+
|
8 |
+
(function ($) {
|
9 |
+
|
10 |
+
if ( typeof SLB == 'undefined' || !SLB.attach ) {
|
11 |
+
return false;
|
12 |
+
}
|
13 |
+
|
14 |
+
/*-** Controller **-*/
|
15 |
+
|
16 |
+
var View = {
|
17 |
+
|
18 |
+
/* Properties */
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Media item properties
|
22 |
+
* > Item key: Link URI
|
23 |
+
* > Base properties
|
24 |
+
* > id: WP Attachment ID
|
25 |
+
* > source: Source URI
|
26 |
+
* > title: Media title (generally WP attachment title)
|
27 |
+
* > desc: Media description (generally WP Attachment content)
|
28 |
+
* > type: Asset type (attachment, image, etc.)
|
29 |
+
*/
|
30 |
+
assets: {},
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Component types that can have default instances
|
34 |
+
* @var array
|
35 |
+
*/
|
36 |
+
component_defaults: [],
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Collection of jQuery.Deferred instances added during loading routine
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
loading: [],
|
43 |
+
|
44 |
+
/* Component Collections */
|
45 |
+
|
46 |
+
viewers: {},
|
47 |
+
items: [],
|
48 |
+
content_handlers: {},
|
49 |
+
groups: {},
|
50 |
+
template_tags: {},
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Collection/Data type mapping
|
54 |
+
* > Key: Collection name
|
55 |
+
* > Value: Data type
|
56 |
+
* @var object
|
57 |
+
*/
|
58 |
+
collections: {},
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Temporary component instances
|
62 |
+
* For use by controller when no component instance is available
|
63 |
+
* > Key: Component slug
|
64 |
+
* > Value: Component instance
|
65 |
+
*/
|
66 |
+
component_temps: {},
|
67 |
+
|
68 |
+
/* Options */
|
69 |
+
options: {
|
70 |
+
ui_animate: true,
|
71 |
+
slideshow_enabled: true,
|
72 |
+
slideshow_autostart: false,
|
73 |
+
slideshow_duration: '6'
|
74 |
+
},
|
75 |
+
|
76 |
+
/* Methods */
|
77 |
+
|
78 |
+
/* Init */
|
79 |
+
|
80 |
+
update_refs: function() {
|
81 |
+
var c;
|
82 |
+
var r;
|
83 |
+
var ref;
|
84 |
+
for ( var p in this ) {
|
85 |
+
if ( !this.util.is_func(this[p]) || !( '_refs' in this[p].prototype ) ) {
|
86 |
+
continue;
|
87 |
+
}
|
88 |
+
//Set component
|
89 |
+
c = this[p];
|
90 |
+
if ( !this.util.is_empty(c.prototype._refs) ) {
|
91 |
+
for ( r in c.prototype._refs ) {
|
92 |
+
ref = c.prototype._refs[r];
|
93 |
+
if ( this.util.is_func(ref) ) {
|
94 |
+
continue;
|
95 |
+
}
|
96 |
+
if ( this.util.is_string(ref) && ref in this ) {
|
97 |
+
ref = c.prototype._refs[r] = this[ref];
|
98 |
+
}
|
99 |
+
if ( !this.util.is_func(ref) ) {
|
100 |
+
delete c.prototype_refs[r];
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
/* Initialize components */
|
107 |
+
this.init_components();
|
108 |
+
},
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Initialization
|
112 |
+
*/
|
113 |
+
init: function(options) {
|
114 |
+
var t = this;
|
115 |
+
$.when.apply($, this.loading).always(function() {
|
116 |
+
//Set options
|
117 |
+
$.extend(true, t.options, options);
|
118 |
+
//History
|
119 |
+
$(window).on('popstate', function(e) {
|
120 |
+
var state = e.originalEvent.state;
|
121 |
+
if ( t.util.in_obj(state, ['item', 'viewer']) ) {
|
122 |
+
var v = t.get_viewer(state.viewer);
|
123 |
+
v.history_handle(e);
|
124 |
+
return e.preventDefault();
|
125 |
+
}
|
126 |
+
});
|
127 |
+
|
128 |
+
/* Set defaults */
|
129 |
+
|
130 |
+
//Items
|
131 |
+
t.init_items();
|
132 |
+
});
|
133 |
+
},
|
134 |
+
|
135 |
+
init_components: function() {
|
136 |
+
this.collections = {
|
137 |
+
'viewers': this.Viewer,
|
138 |
+
'items': this.Content_Item,
|
139 |
+
'content_handlers': this.Content_Handler,
|
140 |
+
'groups': this.Group,
|
141 |
+
'themes': this.Theme,
|
142 |
+
'template_tags': this.Template_Tag
|
143 |
+
};
|
144 |
+
|
145 |
+
this.component_defaults = [
|
146 |
+
this.Viewer,
|
147 |
+
];
|
148 |
+
|
149 |
+
},
|
150 |
+
|
151 |
+
/* Components */
|
152 |
+
|
153 |
+
component_make_default: function(type) {
|
154 |
+
var ret = false;
|
155 |
+
for ( var x = 0; x < this.component_defaults.length; x++ ) {
|
156 |
+
if ( type == this.component_defaults[x] ) {
|
157 |
+
ret = true;
|
158 |
+
break;
|
159 |
+
}
|
160 |
+
}
|
161 |
+
return ret;
|
162 |
+
},
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Validates component type
|
166 |
+
* @param function comp Component type to check
|
167 |
+
* @return bool TRUE if param is valid component, FALSE otherwise
|
168 |
+
*/
|
169 |
+
check_component: function(comp) {
|
170 |
+
//Validate component type
|
171 |
+
return ( this.util.is_func(comp) && ('_slug' in comp.prototype ) && ( comp.prototype instanceof (this.Component) ) ) ? true : false;
|
172 |
+
},
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Retrieve collection of components of specified type
|
176 |
+
* @param function type Component type
|
177 |
+
* @return object|array|null Component collection (NULL if invalid)
|
178 |
+
*/
|
179 |
+
get_components: function(type) {
|
180 |
+
var ret = null;
|
181 |
+
if ( this.util.is_func(type) ) {
|
182 |
+
//Determine collection
|
183 |
+
for ( var coll in this.collections ) {
|
184 |
+
if ( type == this.collections[coll] && coll in this ) {
|
185 |
+
ret = this[coll];
|
186 |
+
break;
|
187 |
+
}
|
188 |
+
}
|
189 |
+
}
|
190 |
+
return ret;
|
191 |
+
},
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Retrieve component from specific collection
|
195 |
+
* @param function type Component type
|
196 |
+
* @param string id Component ID
|
197 |
+
* @return object|null Component reference (NULL if invalid)
|
198 |
+
*/
|
199 |
+
get_component: function(type, id) {
|
200 |
+
var ret = null;
|
201 |
+
//Validate parameters
|
202 |
+
if ( !this.util.is_func(type) ) {
|
203 |
+
return ret;
|
204 |
+
}
|
205 |
+
//Sanitize id
|
206 |
+
if ( !this.util.is_string(id) ) {
|
207 |
+
id = null;
|
208 |
+
}
|
209 |
+
|
210 |
+
//Get component from collection
|
211 |
+
var coll = this.get_components(type);
|
212 |
+
if ( this.util.is_obj(coll) ) {
|
213 |
+
var tid = ( this.util.is_string(id) ) ? id : this.util.add_prefix('default');
|
214 |
+
if ( tid in coll ) {
|
215 |
+
ret = coll[tid];
|
216 |
+
}
|
217 |
+
}
|
218 |
+
|
219 |
+
//Default: Create default component
|
220 |
+
if ( this.util.is_empty(ret) ) {
|
221 |
+
if ( this.util.is_string(id) || this.component_make_default(type) ) {
|
222 |
+
ret = this.add_component(type, id);
|
223 |
+
}
|
224 |
+
}
|
225 |
+
//Return component
|
226 |
+
return ret;
|
227 |
+
},
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Create new component instance and save to appropriate collection
|
231 |
+
* @param function type Component type to create
|
232 |
+
* @param string id ID of component
|
233 |
+
* @param object options Component initialization options (Default options used if default component is allowed)
|
234 |
+
* @return object|null New component (NULL if invalid)
|
235 |
+
*/
|
236 |
+
add_component: function(type, id, options) {
|
237 |
+
//Validate type
|
238 |
+
if ( !this.util.is_func(type) ) {
|
239 |
+
return false;
|
240 |
+
}
|
241 |
+
//Validate request
|
242 |
+
if ( this.util.is_empty(id) && !this.component_make_default(type) ) {
|
243 |
+
return false;
|
244 |
+
}
|
245 |
+
//Defaults
|
246 |
+
var ret = null;
|
247 |
+
if ( this.util.is_empty(id) ) {
|
248 |
+
id = this.util.add_prefix('default');
|
249 |
+
}
|
250 |
+
if ( !this.util.is_obj(options) ) {
|
251 |
+
options = {};
|
252 |
+
}
|
253 |
+
//Check if specialized method exists for component type
|
254 |
+
var m = ( 'component' != type.prototype._slug ) ? 'add_' + type.prototype._slug : null;
|
255 |
+
if ( !this.util.is_empty(m) && ( m in this ) && this.util.is_func(this[m]) ) {
|
256 |
+
ret = this[m](id, options);
|
257 |
+
}
|
258 |
+
//Default process
|
259 |
+
else {
|
260 |
+
ret = new type(id, options);
|
261 |
+
}
|
262 |
+
|
263 |
+
//Add new component to collection
|
264 |
+
if ( this.util.is_type(ret, type) ) {
|
265 |
+
//Get collection
|
266 |
+
var coll = this.get_components(type);
|
267 |
+
//Add to collection
|
268 |
+
switch ( $.type(coll) ) {
|
269 |
+
case 'object' :
|
270 |
+
coll[id] = ret;
|
271 |
+
break;
|
272 |
+
case 'array' :
|
273 |
+
coll.push(ret);
|
274 |
+
break;
|
275 |
+
}
|
276 |
+
} else {
|
277 |
+
ret = null;
|
278 |
+
}
|
279 |
+
//Return new component
|
280 |
+
return ret;
|
281 |
+
},
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Create new temporary component instance
|
285 |
+
* @param function type Component type
|
286 |
+
* @return New temporary instance
|
287 |
+
*/
|
288 |
+
add_component_temp: function(type) {
|
289 |
+
var ret = null;
|
290 |
+
if ( this.check_component(type) ) {
|
291 |
+
//Create new instance
|
292 |
+
ret = new type('');
|
293 |
+
//Save to collection
|
294 |
+
this.component_temps[ret._slug] = ret;
|
295 |
+
}
|
296 |
+
return ret;
|
297 |
+
},
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Retrieve temporary component instance
|
301 |
+
* Creates new temp component instance for type if not previously created
|
302 |
+
* @param function type Component type to retrieve temp instance for
|
303 |
+
* @return obj Temporary component instance
|
304 |
+
*/
|
305 |
+
get_component_temp: function(type) {
|
306 |
+
return ( this.has_component_temp(type) ) ? this.component_temps[type.prototype._slug] : this.add_component_temp(type);
|
307 |
+
},
|
308 |
+
|
309 |
+
/**
|
310 |
+
* Check if temporary component instance exists
|
311 |
+
* @param function type Component type to check for
|
312 |
+
* @return bool TRUE if temp instance exists, FALSE otherwise
|
313 |
+
*/
|
314 |
+
has_component_temp: function(type) {
|
315 |
+
return ( this.check_component(type) && ( type.prototype._slug in this.component_temps ) ) ? true : false;
|
316 |
+
},
|
317 |
+
|
318 |
+
/* Properties */
|
319 |
+
|
320 |
+
/**
|
321 |
+
* Retrieve specified options
|
322 |
+
* @param array opts Array of option names
|
323 |
+
* @return object Specified options (Default: empty object)
|
324 |
+
*/
|
325 |
+
get_options: function(opts) {
|
326 |
+
var ret = {};
|
327 |
+
//Validate
|
328 |
+
if ( this.util.is_string(opts) ) {
|
329 |
+
opts = [opts];
|
330 |
+
}
|
331 |
+
if ( !this.util.is_array(opts) ) {
|
332 |
+
return ret;
|
333 |
+
}
|
334 |
+
//Get specified options
|
335 |
+
for ( var x = 0; x < opts.length; x++ ) {
|
336 |
+
//Skip if option not set
|
337 |
+
if ( !( opts[x] in this.options ) ) {
|
338 |
+
continue;
|
339 |
+
}
|
340 |
+
ret[ opts[x] ] = this.options[ opts[x] ];
|
341 |
+
}
|
342 |
+
return ret;
|
343 |
+
},
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Retrieve option
|
347 |
+
* @uses View.options
|
348 |
+
* @param string opt Option to retrieve
|
349 |
+
* @param mixed def (optional) Default value if option does not exist (Default: NULL)
|
350 |
+
* @return mixed Option value
|
351 |
+
*/
|
352 |
+
get_option: function(opt, def) {
|
353 |
+
var ret = this.get_options(opt);
|
354 |
+
if ( this.util.is_obj(ret) && ( opt in ret ) ) {
|
355 |
+
ret = ret[opt];
|
356 |
+
} else {
|
357 |
+
ret = ( this.util.is_set(def) ) ? def : null;
|
358 |
+
}
|
359 |
+
return ret;
|
360 |
+
},
|
361 |
+
|
362 |
+
/* Viewers */
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Add viewer instance to collection
|
366 |
+
* @param string id Viewer ID
|
367 |
+
* @param obj options Viewer options
|
368 |
+
*/
|
369 |
+
add_viewer: function(id, options) {
|
370 |
+
//Validate
|
371 |
+
if ( !this.util.is_string(id) ) {
|
372 |
+
return false;
|
373 |
+
}
|
374 |
+
if ( !this.util.is_obj(options, false) ) {
|
375 |
+
options = {};
|
376 |
+
}
|
377 |
+
//Create viewer
|
378 |
+
var v = new this.Viewer(id, options);
|
379 |
+
//Add to collection
|
380 |
+
this.viewers[v.get_id()] = v;
|
381 |
+
//Return viewer
|
382 |
+
return v;
|
383 |
+
},
|
384 |
+
|
385 |
+
/**
|
386 |
+
* Retrieve all viewer instances
|
387 |
+
* @return obj Viewer instances
|
388 |
+
*/
|
389 |
+
get_viewers: function() {
|
390 |
+
return this.viewers;
|
391 |
+
},
|
392 |
+
|
393 |
+
/**
|
394 |
+
* Check if viewer exists
|
395 |
+
* @param string v Viewer ID
|
396 |
+
* @return bool TRUE if viewer exists, FALSE otherwise
|
397 |
+
*/
|
398 |
+
has_viewer: function(v) {
|
399 |
+
return ( this.util.is_string(v) && v in this.get_viewers() ) ? true : false;
|
400 |
+
},
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Retrieve Viewer instance
|
404 |
+
* Default viewer retrieved if specified viewer does not exist
|
405 |
+
* > Default viewer created if necessary
|
406 |
+
* @param string v Viewer ID to retrieve
|
407 |
+
* @return Viewer Viewer instance
|
408 |
+
*/
|
409 |
+
get_viewer: function(v) {
|
410 |
+
//Retrieve default viewer if specified viewer not set
|
411 |
+
if ( !this.has_viewer(v) ) {
|
412 |
+
v = this.util.add_prefix('default');
|
413 |
+
//Create default viewer if necessary
|
414 |
+
if ( !this.has_viewer(v) ) {
|
415 |
+
this.add_viewer(v);
|
416 |
+
}
|
417 |
+
}
|
418 |
+
return this.get_viewers()[v];
|
419 |
+
},
|
420 |
+
|
421 |
+
/* Items */
|
422 |
+
|
423 |
+
/**
|
424 |
+
* Set event handlers
|
425 |
+
*/
|
426 |
+
init_items: function() {
|
427 |
+
//Define handler
|
428 |
+
var t = this;
|
429 |
+
var handler = function() {
|
430 |
+
var ret = t.show_item(this);
|
431 |
+
if ( !t.util.is_bool(ret) ) {
|
432 |
+
ret = true;
|
433 |
+
}
|
434 |
+
return !ret;
|
435 |
+
};
|
436 |
+
|
437 |
+
//Get activated links
|
438 |
+
var sel = this.util.format('a[href][%s="%s"]', this.util.get_attribute('active'), 1);
|
439 |
+
//Add event handler
|
440 |
+
$(document).on('click', sel, handler);
|
441 |
+
},
|
442 |
+
|
443 |
+
get_items: function() {
|
444 |
+
return this.get_components(this.Content_Item);
|
445 |
+
},
|
446 |
+
|
447 |
+
/**
|
448 |
+
* Retrieve specific Content_Item instance
|
449 |
+
* @param mixed Item reference
|
450 |
+
* > Content_Item: Item instance (returned immediately)
|
451 |
+
* > DOM element: DOM element to get item for
|
452 |
+
* > int: Index of cached item
|
453 |
+
* @return Content_Item Item instance for DOM node
|
454 |
+
*/
|
455 |
+
get_item: function(ref) {
|
456 |
+
//Evaluate reference type
|
457 |
+
|
458 |
+
//Content Item instance
|
459 |
+
if ( this.util.is_type(ref, this.Content_Item) ) {
|
460 |
+
return ref;
|
461 |
+
}
|
462 |
+
//Retrieve item instance
|
463 |
+
var item = null;
|
464 |
+
|
465 |
+
//DOM element
|
466 |
+
if ( this.util.in_obj(ref, 'nodeType') ) {
|
467 |
+
//Check if item instance attached to element
|
468 |
+
var key = this.get_component_temp(this.Content_Item).get_data_key();
|
469 |
+
item = $(ref).data(key);
|
470 |
+
}
|
471 |
+
//Cached item (index)
|
472 |
+
else if ( this.util.is_int(ref, false) ) {
|
473 |
+
var items = this.get_items();
|
474 |
+
if ( items.length > ref ) {
|
475 |
+
item = items[ref];
|
476 |
+
}
|
477 |
+
}
|
478 |
+
//Create default item instance
|
479 |
+
if ( !this.util.is_type(item, this.Content_Item) ) {
|
480 |
+
item = this.add_item(ref);
|
481 |
+
}
|
482 |
+
return item;
|
483 |
+
},
|
484 |
+
|
485 |
+
/**
|
486 |
+
* Create new item instance
|
487 |
+
* @param obj el DOM element representing item
|
488 |
+
* @return Content_Item New item instance
|
489 |
+
*/
|
490 |
+
add_item: function(el) {
|
491 |
+
var item = new this.Content_Item(el);
|
492 |
+
return item;
|
493 |
+
},
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Display item in viewer
|
497 |
+
* @param obj el DOM element representing item
|
498 |
+
*/
|
499 |
+
show_item: function(el) {
|
500 |
+
var ret = this.get_item(el).show();
|
501 |
+
return ret;
|
502 |
+
},
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Cache item instance
|
506 |
+
* @uses this.items to store cached items
|
507 |
+
* @param Content_Item item Item to cache
|
508 |
+
* @return int Index of item in cache
|
509 |
+
*/
|
510 |
+
save_item: function(item) {
|
511 |
+
var ret = -1;
|
512 |
+
if ( !this.util.is_type(item, this.Content_Item) ) {
|
513 |
+
return ret;
|
514 |
+
}
|
515 |
+
var prop = 'items';
|
516 |
+
var items = this.get_items();
|
517 |
+
//Check if item exists in collection
|
518 |
+
ret = $.inArray(item, items);
|
519 |
+
//Cache item
|
520 |
+
if ( -1 == ret ) {
|
521 |
+
ret = items.push(item) - 1;
|
522 |
+
}
|
523 |
+
//Return item index in cache
|
524 |
+
return ret;
|
525 |
+
},
|
526 |
+
|
527 |
+
/* Content Handler */
|
528 |
+
|
529 |
+
get_content_handlers: function() {
|
530 |
+
return this.get_components(this.Content_Handler);
|
531 |
+
},
|
532 |
+
|
533 |
+
/**
|
534 |
+
* Find matching content handler for item
|
535 |
+
* @param Content_Item|string item Item to find handler for (or ID of Handler)
|
536 |
+
* @return Content_Handler|null Matching content handler (NULL if no matching handler found)
|
537 |
+
*/
|
538 |
+
get_content_handler: function(item) {
|
539 |
+
//Determine handler to retrieve
|
540 |
+
var type = ( this.util.is_type(item, this.Content_Item) ) ? item.get_attribute('type', '') : item.toString();
|
541 |
+
//Retrieve handler
|
542 |
+
var types = this.get_content_handlers();
|
543 |
+
return ( type in types ) ? types[type] : null;
|
544 |
+
},
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Add Content Handler
|
548 |
+
* @param string id Handler ID
|
549 |
+
* @param obj attributes (optional) Handler properties/methods
|
550 |
+
*/
|
551 |
+
add_content_handler: function(id, attributes) {
|
552 |
+
//Validate
|
553 |
+
if ( !this.util.is_string(id) ) {
|
554 |
+
return false;
|
555 |
+
}
|
556 |
+
var dfr = $.Deferred();
|
557 |
+
var t = this;
|
558 |
+
|
559 |
+
if ( !this.util.is_obj(attributes, false) ) {
|
560 |
+
//Check for URI (external loading)
|
561 |
+
if ( this.util.is_string(attributes) ) {
|
562 |
+
$.get(attributes).always(function(data, textStatus) {
|
563 |
+
var r = null;
|
564 |
+
try {
|
565 |
+
eval('r = ' + data);
|
566 |
+
} catch (e) {}
|
567 |
+
if ( !t.util.is_obj(r) ) {
|
568 |
+
r = {};
|
569 |
+
}
|
570 |
+
dfr.resolve(r);
|
571 |
+
});
|
572 |
+
} else {
|
573 |
+
dfr.resolve({});
|
574 |
+
}
|
575 |
+
} else {
|
576 |
+
dfr.resolve(attributes);
|
577 |
+
}
|
578 |
+
|
579 |
+
dfr.done(function(o) {
|
580 |
+
//Save
|
581 |
+
var types = t.get_components(t.Content_Handler);
|
582 |
+
if ( !t.util.is_obj(types, false) ) {
|
583 |
+
types = {};
|
584 |
+
}
|
585 |
+
types[id] = new t.Content_Handler(id, o);
|
586 |
+
});
|
587 |
+
},
|
588 |
+
|
589 |
+
/**
|
590 |
+
* Update content handler
|
591 |
+
* @param string id Handler to update
|
592 |
+
* @param obj attr Variable number of attribute objects to add handlera
|
593 |
+
*/
|
594 |
+
update_content_handler: function(id, attr) {
|
595 |
+
if ( !this.util.is_string(id) || !this.util.is_obj(attr) ) {
|
596 |
+
return false;
|
597 |
+
}
|
598 |
+
//Get existing handler
|
599 |
+
var h = this.get_content_handler(id);
|
600 |
+
if ( null == h ) {
|
601 |
+
return false;
|
602 |
+
}
|
603 |
+
//Add additional attributes
|
604 |
+
h.set_attributes(attr);
|
605 |
+
},
|
606 |
+
|
607 |
+
/* Group */
|
608 |
+
|
609 |
+
/**
|
610 |
+
* Add new group
|
611 |
+
* @param string g Group ID
|
612 |
+
* > If group with same ID already set, new group replaces existing one
|
613 |
+
* @param object attrs (optional) Group attributes
|
614 |
+
*/
|
615 |
+
add_group: function(g, attrs) {
|
616 |
+
//Create new group
|
617 |
+
g = new this.Group(g, attrs);
|
618 |
+
//Add group to collection
|
619 |
+
if ( this.util.is_string(g.get_id()) ) {
|
620 |
+
this.groups[g.get_id()] = g;
|
621 |
+
}
|
622 |
+
},
|
623 |
+
|
624 |
+
/**
|
625 |
+
* Retrieve groups
|
626 |
+
* @uses groups property
|
627 |
+
* @return object Registered groups
|
628 |
+
*/
|
629 |
+
get_groups: function() {
|
630 |
+
return this.groups;
|
631 |
+
},
|
632 |
+
|
633 |
+
/**
|
634 |
+
* Retrieve specified group
|
635 |
+
* @param string g Group ID
|
636 |
+
* @return object|null Group instance (NULL if group does not exist)
|
637 |
+
*/
|
638 |
+
get_group: function(g) {
|
639 |
+
if ( this.util.is_string(g) ) {
|
640 |
+
if ( !this.has_group(g) ) {
|
641 |
+
//Add new group (if necessary)
|
642 |
+
this.add_group(g);
|
643 |
+
}
|
644 |
+
//Retrieve group
|
645 |
+
g = this.get_groups()[g];
|
646 |
+
}
|
647 |
+
return ( this.util.is_type(g, this.Group) ) ? g : null;
|
648 |
+
},
|
649 |
+
|
650 |
+
/**
|
651 |
+
* Checks if group is registered
|
652 |
+
* @uses get_groups() to retrieve registered groups
|
653 |
+
* @return bool TRUE if group exists, FALSE otherwise
|
654 |
+
*/
|
655 |
+
has_group: function(g) {
|
656 |
+
return ( this.util.is_string(g) && ( g in this.get_groups() ) ) ? true : false;
|
657 |
+
},
|
658 |
+
|
659 |
+
/* Theme */
|
660 |
+
|
661 |
+
/**
|
662 |
+
* Add theme
|
663 |
+
* @param string name Theme name
|
664 |
+
* @param obj attr Theme options
|
665 |
+
* > Multiple attribute parameters are merged
|
666 |
+
* @return obj Theme model
|
667 |
+
*/
|
668 |
+
add_theme: function(id, attr) {
|
669 |
+
var t = this;
|
670 |
+
//Validate
|
671 |
+
if ( !this.util.is_string(id) ) {
|
672 |
+
return false;
|
673 |
+
}
|
674 |
+
var dfr = $.Deferred();
|
675 |
+
this.loading.push(dfr);
|
676 |
+
|
677 |
+
//Build attributes
|
678 |
+
var attrs = [{'parent': null}];
|
679 |
+
if ( arguments.length >= 2 ) {
|
680 |
+
var args = Array.prototype.slice.call(arguments, 1);
|
681 |
+
var t = this;
|
682 |
+
$.each(args, function(idx, arg) {
|
683 |
+
if ( t.util.is_obj(arg) ) {
|
684 |
+
attrs.push(arg)
|
685 |
+
}
|
686 |
+
});
|
687 |
+
}
|
688 |
+
|
689 |
+
//Set ID
|
690 |
+
attrs.push({'id': id});
|
691 |
+
|
692 |
+
//Create theme model
|
693 |
+
var model = $.extend.apply(null, attrs);
|
694 |
+
|
695 |
+
//Connect to parent model
|
696 |
+
if ( this.util.is_string(model.parent) ) {
|
697 |
+
model.parent = this.get_theme_model(model.parent);
|
698 |
+
}
|
699 |
+
|
700 |
+
/* Process attributes */
|
701 |
+
|
702 |
+
//Layout
|
703 |
+
var prop_layout = 'layout_uri';
|
704 |
+
var dfr_layout = $.Deferred();
|
705 |
+
if ( prop_layout in model && this.util.is_string(model[prop_layout]) ) {
|
706 |
+
$.get(model[prop_layout]).always(function(data) {
|
707 |
+
//Set layout (raw) attribute
|
708 |
+
if ( t.util.is_string(data) ) {
|
709 |
+
model['layout_raw'] = data;
|
710 |
+
}
|
711 |
+
dfr_layout.resolve();
|
712 |
+
});
|
713 |
+
} else {
|
714 |
+
dfr_layout.resolve();
|
715 |
+
}
|
716 |
+
|
717 |
+
//Attributes (external)
|
718 |
+
var prop_script = 'client_script';
|
719 |
+
var dfr_script = $.Deferred();
|
720 |
+
if ( prop_script in model && this.util.is_string(model[prop_script]) ) {
|
721 |
+
//Retrieve client script
|
722 |
+
$.get(model[prop_script]).always(function(data) {
|
723 |
+
var r = null;
|
724 |
+
try {
|
725 |
+
eval('r = ' + data);
|
726 |
+
} catch (e) {}
|
727 |
+
if ( t.util.is_obj(r) ) {
|
728 |
+
//Add attributes to model
|
729 |
+
$.extend(model, r);
|
730 |
+
}
|
731 |
+
dfr_script.resolve();
|
732 |
+
});
|
733 |
+
} else {
|
734 |
+
dfr_script.resolve();
|
735 |
+
}
|
736 |
+
|
737 |
+
//Styles
|
738 |
+
var prop_style = 'client_style';
|
739 |
+
if ( prop_style in model && this.util.is_string(model[prop_style]) ) {
|
740 |
+
//Add stylesheet to document
|
741 |
+
$('<link />', {
|
742 |
+
'id': 'theme_style_' + model.id,
|
743 |
+
'href': model[prop_style],
|
744 |
+
'type': 'text/css',
|
745 |
+
'rel': 'stylesheet'
|
746 |
+
}).appendTo('body');
|
747 |
+
}
|
748 |
+
|
749 |
+
//Complete loading when all components loaded
|
750 |
+
$.when(dfr_layout, dfr_script).always(function() {
|
751 |
+
dfr.resolve();
|
752 |
+
});
|
753 |
+
//Add theme model
|
754 |
+
this.Theme.prototype._models[id] = model;
|
755 |
+
return model;
|
756 |
+
},
|
757 |
+
|
758 |
+
/**
|
759 |
+
* Update theme model
|
760 |
+
* @param string id Theme to update
|
761 |
+
* @param obj attr Variable number of attribute objects to add to model
|
762 |
+
*/
|
763 |
+
update_theme: function(id, attr) {
|
764 |
+
var model = this.get_theme_model(id);
|
765 |
+
var args = Array.prototype.slice.call(arguments);
|
766 |
+
if ( this.util.is_empty(model) ) {
|
767 |
+
model = this.add_model.apply(this, args);
|
768 |
+
} else {
|
769 |
+
//Process attributes
|
770 |
+
args.shift();
|
771 |
+
var attrs = [];
|
772 |
+
var t = this;
|
773 |
+
$.each(args, function(idx, arg) {
|
774 |
+
if ( t.util.is_obj(arg) ) {
|
775 |
+
attrs.push(arg);
|
776 |
+
}
|
777 |
+
});
|
778 |
+
//Merge attributes into model
|
779 |
+
attrs.unshift(model);
|
780 |
+
$.extend.apply($, attrs);
|
781 |
+
}
|
782 |
+
return model;
|
783 |
+
},
|
784 |
+
|
785 |
+
/**
|
786 |
+
* Retrieve theme models
|
787 |
+
* @return obj Theme models
|
788 |
+
*/
|
789 |
+
get_theme_models: function() {
|
790 |
+
//Retrieve matching theme model
|
791 |
+
return this.Theme.prototype._models;
|
792 |
+
},
|
793 |
+
|
794 |
+
/**
|
795 |
+
* Retrieve theme model
|
796 |
+
* @param string id Theme to retrieve
|
797 |
+
* @return obj Theme model (Default: empty object)
|
798 |
+
*/
|
799 |
+
get_theme_model: function(id) {
|
800 |
+
var ms = this.get_theme_models();
|
801 |
+
return ( this.util.in_obj(ms, id) ) ? ms[id] : {};
|
802 |
+
},
|
803 |
+
|
804 |
+
/**
|
805 |
+
* Add Theme Tag Handler to Theme prototype
|
806 |
+
* @param string id Unique ID
|
807 |
+
* @param obj attrs (optional) Default tag attributes/values (or URI to attributes definition)
|
808 |
+
*/
|
809 |
+
add_template_tag_handler: function(id, attributes) {
|
810 |
+
//Validate
|
811 |
+
if ( !this.util.is_string(id) ) {
|
812 |
+
return false;
|
813 |
+
}
|
814 |
+
var dfr = $.Deferred();
|
815 |
+
var t = this;
|
816 |
+
|
817 |
+
if ( !this.util.is_obj(attributes, false) ) {
|
818 |
+
//Check for URI (external loading)
|
819 |
+
if ( this.util.is_string(attributes) ) {
|
820 |
+
$.get(attributes).always(function(data) {
|
821 |
+
var r = null;
|
822 |
+
try {
|
823 |
+
eval('r = ' + data);
|
824 |
+
} catch (e) {}
|
825 |
+
if ( !t.util.is_obj(r) ) {
|
826 |
+
r = {};
|
827 |
+
}
|
828 |
+
dfr.resolve(r);
|
829 |
+
});
|
830 |
+
} else {
|
831 |
+
dfr.resolve({});
|
832 |
+
}
|
833 |
+
} else {
|
834 |
+
dfr.resolve(attributes);
|
835 |
+
}
|
836 |
+
|
837 |
+
dfr.done(function(o) {
|
838 |
+
//Add handler
|
839 |
+
t.get_template_tag_handlers()[id] = new t.Template_Tag_Handler(id, o);
|
840 |
+
});
|
841 |
+
},
|
842 |
+
|
843 |
+
/**
|
844 |
+
* Retrieve Template Tag Handler collection
|
845 |
+
* @return obj Template_Tag_Handler objects
|
846 |
+
*/
|
847 |
+
get_template_tag_handlers: function() {
|
848 |
+
return this.Template_Tag.prototype.handlers;
|
849 |
+
},
|
850 |
+
|
851 |
+
/**
|
852 |
+
* Retrieve template tag handler
|
853 |
+
* @param string id ID of tag handler to retrieve
|
854 |
+
* @return Template_Tag_Handler Tag Handler instance (new instance for invalid ID)
|
855 |
+
*/
|
856 |
+
get_template_tag_handler: function(id) {
|
857 |
+
var handlers = this.get_template_tag_handlers();
|
858 |
+
//Retrieve existing handler
|
859 |
+
if ( this.util.is_string(id) && ( id in handlers ) ) {
|
860 |
+
return handlers[id];
|
861 |
+
}
|
862 |
+
//Default: Return empty handler
|
863 |
+
return new this.Template_Tag_Handler(id, {});
|
864 |
+
}
|
865 |
+
};
|
866 |
+
|
867 |
+
/* Components */
|
868 |
+
var Component = {
|
869 |
+
/*-** Properties **-*/
|
870 |
+
|
871 |
+
/* Internal/Configuration */
|
872 |
+
|
873 |
+
/**
|
874 |
+
* Base name of component type
|
875 |
+
* @var string
|
876 |
+
*/
|
877 |
+
_slug: 'component',
|
878 |
+
|
879 |
+
/**
|
880 |
+
* Valid component references for current component
|
881 |
+
* > Key (string): Property name that stores reference
|
882 |
+
* > Value (function): Data type of component
|
883 |
+
* @var object
|
884 |
+
*/
|
885 |
+
_refs: {},
|
886 |
+
|
887 |
+
/**
|
888 |
+
* Components that may contain current object
|
889 |
+
* Used for retrieving data from a parent object
|
890 |
+
* Example: An Item may be contained by a Group
|
891 |
+
* > Value (strong): Property name of container component
|
892 |
+
* @var array
|
893 |
+
*/
|
894 |
+
_containers: [],
|
895 |
+
|
896 |
+
/**
|
897 |
+
* Whether DOM element and component are connected in 1:1 relationship
|
898 |
+
* Some components will be assigned to different DOM elements depending on usage
|
899 |
+
* @var bool
|
900 |
+
*/
|
901 |
+
_reciprocal: false,
|
902 |
+
|
903 |
+
/**
|
904 |
+
* DOM Element tied to component
|
905 |
+
* @var DOM Element
|
906 |
+
*/
|
907 |
+
_dom: null,
|
908 |
+
|
909 |
+
/**
|
910 |
+
* Default attributes
|
911 |
+
* @var object
|
912 |
+
*/
|
913 |
+
_attr_default: {},
|
914 |
+
|
915 |
+
/**
|
916 |
+
* Attributes passed to constructor
|
917 |
+
* @var obj
|
918 |
+
*/
|
919 |
+
_attr_init: null,
|
920 |
+
|
921 |
+
/**
|
922 |
+
* Attributes to retrieve from parent (controller)
|
923 |
+
* @var array
|
924 |
+
*/
|
925 |
+
_attr_parent: [],
|
926 |
+
|
927 |
+
/**
|
928 |
+
* Defines how parent properties should be remapped to component properties
|
929 |
+
* @var object
|
930 |
+
*/
|
931 |
+
_attr_map: {},
|
932 |
+
|
933 |
+
/**
|
934 |
+
* Event handlers
|
935 |
+
* @var object
|
936 |
+
* > Key: string Event type
|
937 |
+
* > Value: array Handlers
|
938 |
+
*/
|
939 |
+
_events: null,
|
940 |
+
|
941 |
+
/**
|
942 |
+
* Status management
|
943 |
+
* @var object
|
944 |
+
* > Key: Status ID
|
945 |
+
* > Value: Status value
|
946 |
+
*/
|
947 |
+
_status: null,
|
948 |
+
|
949 |
+
/* Public */
|
950 |
+
|
951 |
+
attributes: false,
|
952 |
+
|
953 |
+
/**
|
954 |
+
* Component ID
|
955 |
+
* @var string
|
956 |
+
*/
|
957 |
+
id: '',
|
958 |
+
|
959 |
+
/* Init */
|
960 |
+
|
961 |
+
_c: function(id, attributes) {
|
962 |
+
//Set ID
|
963 |
+
this.set_id(id);
|
964 |
+
//Save init attributes
|
965 |
+
this._attr_init = attributes;
|
966 |
+
this.register_hooks();
|
967 |
+
},
|
968 |
+
|
969 |
+
_set_parent: function() {
|
970 |
+
this._parent = View;
|
971 |
+
this.util._parent = this;
|
972 |
+
},
|
973 |
+
|
974 |
+
/**
|
975 |
+
* Register hooks on init
|
976 |
+
* Placeholder method to be overridden by child classes
|
977 |
+
*/
|
978 |
+
register_hooks: function() {},
|
979 |
+
|
980 |
+
/* Methods */
|
981 |
+
|
982 |
+
/* Properties */
|
983 |
+
|
984 |
+
/**
|
985 |
+
* Retrieve status
|
986 |
+
* @param string id Status to retrieve
|
987 |
+
* @param bool raw (optional) Retrieve raw value (Default: FALSE)
|
988 |
+
* @return mixed Status value (Default: bool)
|
989 |
+
*/
|
990 |
+
get_status: function(id, raw) {
|
991 |
+
var ret = false;
|
992 |
+
if ( this.util.in_obj(this._status, id) ) {
|
993 |
+
ret = ( !!raw ) ? this._status[id] : !!this._status[id];
|
994 |
+
}
|
995 |
+
return ret;
|
996 |
+
},
|
997 |
+
|
998 |
+
/**
|
999 |
+
* Set status
|
1000 |
+
* @param string id Status to retrieve
|
1001 |
+
* @param mixed val Status value (Default: TRUE)
|
1002 |
+
* @return mixed Status value (Default: bool)
|
1003 |
+
*/
|
1004 |
+
set_status: function(id, val) {
|
1005 |
+
//Validate
|
1006 |
+
if ( this.util.is_string(id) ) {
|
1007 |
+
if ( !this.util.is_set(val) ) {
|
1008 |
+
val = true;
|
1009 |
+
}
|
1010 |
+
//Initialize property
|
1011 |
+
if ( !this.util.is_obj(this._status, false) ) {
|
1012 |
+
this._status = {};
|
1013 |
+
}
|
1014 |
+
//Set status
|
1015 |
+
this._status[id] = val;
|
1016 |
+
} else if ( !this.util.is_set(val) ) {
|
1017 |
+
val = false;
|
1018 |
+
}
|
1019 |
+
return val;
|
1020 |
+
},
|
1021 |
+
|
1022 |
+
/**
|
1023 |
+
* Retrieve instance ID
|
1024 |
+
* @uses id as ID base
|
1025 |
+
* @uses _slug to add namespace (if necessary)
|
1026 |
+
* @param bool ns (optional) Whether or not to namespace ID (Default: FALSE)
|
1027 |
+
* @return string Instance ID
|
1028 |
+
*/
|
1029 |
+
get_id: function(ns) {
|
1030 |
+
//Validate
|
1031 |
+
if ( !this.check_id() ) {
|
1032 |
+
this.id = '';
|
1033 |
+
}
|
1034 |
+
var id = this.id;
|
1035 |
+
//Namespace ID
|
1036 |
+
if ( this.util.is_bool(ns) && ns ) {
|
1037 |
+
id = this.add_ns(id);
|
1038 |
+
}
|
1039 |
+
|
1040 |
+
return id;
|
1041 |
+
},
|
1042 |
+
|
1043 |
+
/**
|
1044 |
+
* Set instance ID
|
1045 |
+
* @param string id Unique ID
|
1046 |
+
*/
|
1047 |
+
set_id: function(id) {
|
1048 |
+
this.id = ( this.check_id(id) ) ? id : '';
|
1049 |
+
},
|
1050 |
+
|
1051 |
+
/**
|
1052 |
+
* Validate ID value
|
1053 |
+
* @param string id (optional) ID value (Default: Component ID)
|
1054 |
+
* @param bool nonempty (optional) TRUE if it should also check for empty strings, FALSE otherwise (Default: FALSE)
|
1055 |
+
* @return bool TRUE if ID is valid, FALSE otherwise
|
1056 |
+
*/
|
1057 |
+
check_id: function(id, nonempty) {
|
1058 |
+
//Validate
|
1059 |
+
if ( arguments.length == 1 && this.util.is_bool(arguments[0]) ) {
|
1060 |
+
nonempty = arguments[0];
|
1061 |
+
id = null;
|
1062 |
+
}
|
1063 |
+
if ( this.util.is_empty(id) ) {
|
1064 |
+
id = this.id;
|
1065 |
+
}
|
1066 |
+
if ( !this.util.is_bool(nonempty) ) {
|
1067 |
+
nonempty = false;
|
1068 |
+
}
|
1069 |
+
return ( this.util.is_string(id, nonempty) ) ? true : false;
|
1070 |
+
},
|
1071 |
+
|
1072 |
+
/**
|
1073 |
+
* Get namespace
|
1074 |
+
* @uses _slug for namespace segment
|
1075 |
+
* @uses Util.add_prefix() to prefix slug
|
1076 |
+
* @return string Component namespace
|
1077 |
+
*/
|
1078 |
+
get_ns: function() {
|
1079 |
+
return this.util.add_prefix(this._slug);
|
1080 |
+
},
|
1081 |
+
|
1082 |
+
/**
|
1083 |
+
* Add namespace to value
|
1084 |
+
* @param string val Value to namespace
|
1085 |
+
* @return string Namespaced value (Empty string if invalid value provided)
|
1086 |
+
*/
|
1087 |
+
add_ns: function(val) {
|
1088 |
+
return ( this.util.is_string(val) ) ? this.get_ns() + '_' + val : '';
|
1089 |
+
},
|
1090 |
+
|
1091 |
+
/* Components */
|
1092 |
+
|
1093 |
+
/**
|
1094 |
+
* Retrieve component containers
|
1095 |
+
* @uses _container property
|
1096 |
+
* @return array Component containers
|
1097 |
+
*/
|
1098 |
+
get_containers: function() {
|
1099 |
+
//Sanitize property
|
1100 |
+
if ( !this.util.is_array(this._containers) ) {
|
1101 |
+
this._containers = [];
|
1102 |
+
}
|
1103 |
+
//Return value
|
1104 |
+
return this._containers;
|
1105 |
+
},
|
1106 |
+
|
1107 |
+
/**
|
1108 |
+
* Check if current object has potential container objects
|
1109 |
+
* @return bool TRUE if containers exist, FALSE otherwise
|
1110 |
+
*/
|
1111 |
+
has_containers: function() {
|
1112 |
+
return ( this.get_containers().length > 0 );
|
1113 |
+
},
|
1114 |
+
|
1115 |
+
/**
|
1116 |
+
* Check if reference exists in object
|
1117 |
+
* @param string ref Reference ID
|
1118 |
+
* @return bool TRUE if reference exists, FALSE otherwise
|
1119 |
+
*/
|
1120 |
+
has_reference: function(ref) {
|
1121 |
+
return ( this.util.is_string(ref) && ( ref in this ) && ( ref in this.get_references() ) ) ? true : false;
|
1122 |
+
},
|
1123 |
+
|
1124 |
+
/**
|
1125 |
+
* Retrieve object references
|
1126 |
+
* @uses _refs
|
1127 |
+
* @return obj References object
|
1128 |
+
|
1129 |
+
*/
|
1130 |
+
get_references: function() {
|
1131 |
+
return this._refs;
|
1132 |
+
},
|
1133 |
+
|
1134 |
+
/**
|
1135 |
+
* Retrieve reference data type
|
1136 |
+
* @param string ref Reference ID
|
1137 |
+
* @return function Reference data type (NULL if invalid)
|
1138 |
+
*/
|
1139 |
+
get_reference: function(ref) {
|
1140 |
+
return ( this.has_reference(ref) ) ? this._refs[ref] : null;
|
1141 |
+
},
|
1142 |
+
|
1143 |
+
/**
|
1144 |
+
* Checks if component is valid
|
1145 |
+
* @param obj|string Component instance or ID
|
1146 |
+
* > If ID is specified then it will check for component on current instance
|
1147 |
+
* @param function|string ctype Component type
|
1148 |
+
* > If component is an object, then ctype is required
|
1149 |
+
* > If component is string ID, then ctype is optional (Default: reference type)
|
1150 |
+
* > If ctype is a function, then it is compared to component directly
|
1151 |
+
* > If ctype is a string, then the component reference type is retrieved
|
1152 |
+
* @uses get_reference()
|
1153 |
+
* @return bool TRUE if component is valid, FALSE otherwise
|
1154 |
+
*/
|
1155 |
+
check_component: function(comp, ctype) {
|
1156 |
+
//Validate
|
1157 |
+
if ( this.util.is_empty(comp)
|
1158 |
+
|| ( this.util.is_obj(comp) && !this.util.is_func(ctype) )
|
1159 |
+
|| ( this.util.is_string(comp) && !this.has_reference(comp) )
|
1160 |
+
|| ( this.util.is_empty(ctype) && !this.util.is_string(comp) )
|
1161 |
+
|| ( !this.util.is_obj(comp) && !this.util.is_string(comp) )
|
1162 |
+
) {
|
1163 |
+
return false;
|
1164 |
+
}
|
1165 |
+
//Get component type
|
1166 |
+
if ( !this.util.is_func(ctype) ) {
|
1167 |
+
//Component is a string ID
|
1168 |
+
ctype = this.get_reference(comp);
|
1169 |
+
}
|
1170 |
+
//Get component instance
|
1171 |
+
if ( this.util.is_string(comp) ) {
|
1172 |
+
comp = this.get_component(comp, false);
|
1173 |
+
}
|
1174 |
+
return this.util.is_type(comp, ctype);
|
1175 |
+
},
|
1176 |
+
|
1177 |
+
/**
|
1178 |
+
* Retrieve component reference from current object
|
1179 |
+
* > Procedure:
|
1180 |
+
* > Check if property already set
|
1181 |
+
* > Check attributes
|
1182 |
+
* > Check container object(s)
|
1183 |
+
* > Check parent object (controller)
|
1184 |
+
* @uses _containers to check potential container components for references
|
1185 |
+
* @param string cname Component name
|
1186 |
+
* @param bool check_attr (optional) Whether or not to check instance attributes for component (Default: TRUE)
|
1187 |
+
* @param bool get_default (optional) Whether or not to retrieve default object from controller if none exists in current instance (Default: TRUE)
|
1188 |
+
* @param bool recursive (optional) Whether or not to check containers for specified component reference (Default: TRUE)
|
1189 |
+
* @return object|null Component reference (NULL if no component found)
|
1190 |
+
*/
|
1191 |
+
get_component: function(cname, check_attr, get_default, recursive) {
|
1192 |
+
var c = null;
|
1193 |
+
//Validate request
|
1194 |
+
if ( !this.util.is_string(cname) || !( cname in this ) || !this.has_reference(cname) ) {
|
1195 |
+
return c;
|
1196 |
+
}
|
1197 |
+
|
1198 |
+
//Normalize parameters
|
1199 |
+
if ( !this.util.is_bool(check_attr) ) {
|
1200 |
+
check_attr = true;
|
1201 |
+
}
|
1202 |
+
if ( !this.util.is_bool(get_default) ) {
|
1203 |
+
get_default = true;
|
1204 |
+
}
|
1205 |
+
if ( !this.util.is_bool(recursive) ) {
|
1206 |
+
recursive = true;
|
1207 |
+
}
|
1208 |
+
var ctype = this._refs[cname];
|
1209 |
+
//Phase 1: Check if component reference previously set
|
1210 |
+
if ( this.util.is_type(this[cname], ctype) ) {
|
1211 |
+
return this[cname];
|
1212 |
+
}
|
1213 |
+
//If reference not set, iterate through component hierarchy until reference is found
|
1214 |
+
c = this[cname] = null;
|
1215 |
+
|
1216 |
+
//Phase 2: Check attributes
|
1217 |
+
if ( check_attr ) {
|
1218 |
+
c = this.get_attribute(cname);
|
1219 |
+
//Save object-specific component reference
|
1220 |
+
if ( !this.util.is_empty(c) ) {
|
1221 |
+
c = this.set_component(cname, c);
|
1222 |
+
}
|
1223 |
+
}
|
1224 |
+
|
1225 |
+
//Phase 3: Check Container(s)
|
1226 |
+
if ( recursive && this.util.is_empty(c) && this.has_containers() ) {
|
1227 |
+
var containers = this.get_containers();
|
1228 |
+
var con = null;
|
1229 |
+
for ( var i = 0; i < containers.length; i++ ) {
|
1230 |
+
con = containers[i];
|
1231 |
+
//Validate container
|
1232 |
+
if ( con == cname ) {
|
1233 |
+
continue;
|
1234 |
+
}
|
1235 |
+
//Retrieve container
|
1236 |
+
con = this.get_component(con, true, false);
|
1237 |
+
if ( this.util.is_empty(con) ) {
|
1238 |
+
continue;
|
1239 |
+
}
|
1240 |
+
//Attempt to retrieve component from container
|
1241 |
+
c = con.get_component(cname);
|
1242 |
+
//Stop iterating if valid component found
|
1243 |
+
if ( !this.util.is_empty(c) ) {
|
1244 |
+
break;
|
1245 |
+
}
|
1246 |
+
}
|
1247 |
+
}
|
1248 |
+
|
1249 |
+
//Phase 4: From controller (optional)
|
1250 |
+
if ( get_default && this.util.is_empty(c) ) {
|
1251 |
+
c = this.get_parent().get_component(ctype);
|
1252 |
+
}
|
1253 |
+
return c;
|
1254 |
+
},
|
1255 |
+
|
1256 |
+
/**
|
1257 |
+
* Sets component reference on current object
|
1258 |
+
* > Component property reset (set to NULL) if invalid component supplied
|
1259 |
+
* @param string name Name of property to set component on object
|
1260 |
+
* @param string|object ref Component or Component ID (to be retrieved from controller)
|
1261 |
+
* @param function validate (optional) Additional validation to be performed (Must return bool: TRUE (Valid)/FALSE (Invalid))
|
1262 |
+
* @return object Component (NULL if invalid)
|
1263 |
+
*/
|
1264 |
+
set_component: function(name, ref, validate) {
|
1265 |
+
var clear = null;
|
1266 |
+
//Make sure component property exists
|
1267 |
+
if ( !this.has_reference(name) ) {
|
1268 |
+
return clear;
|
1269 |
+
}
|
1270 |
+
//Normalize reference
|
1271 |
+
if ( this.util.is_empty(ref) ) {
|
1272 |
+
ref = clear;
|
1273 |
+
}
|
1274 |
+
var ctype = this.get_reference(name);
|
1275 |
+
|
1276 |
+
//Get component from controller if ID supplied
|
1277 |
+
if ( this.util.is_string(ref) ) {
|
1278 |
+
ref = this.get_parent().get_component(ctype, ref);
|
1279 |
+
}
|
1280 |
+
|
1281 |
+
if ( !this.util.is_type(ref, ctype) ) {
|
1282 |
+
ref = clear;
|
1283 |
+
}
|
1284 |
+
|
1285 |
+
//Additional validation
|
1286 |
+
if ( !this.util.is_empty(ref) && this.util.is_func(validate) && !validate.call(this, ref) ) {
|
1287 |
+
ref = clear;
|
1288 |
+
}
|
1289 |
+
//Set (or clear) component reference
|
1290 |
+
this[name] = ref;
|
1291 |
+
//Return value for confirmation
|
1292 |
+
return this[name];
|
1293 |
+
},
|
1294 |
+
|
1295 |
+
/* Attributes */
|
1296 |
+
|
1297 |
+
/**
|
1298 |
+
* Initializes attributes
|
1299 |
+
*/
|
1300 |
+
init_attributes: function(force) {
|
1301 |
+
if ( !this.util.is_bool(force) ) {
|
1302 |
+
force = false;
|
1303 |
+
}
|
1304 |
+
if ( force || !this.util.is_obj(this.attributes) ) {
|
1305 |
+
this.attributes = {};
|
1306 |
+
//Build attribute groups
|
1307 |
+
var attrs = [{}];
|
1308 |
+
attrs.push(this.init_default_attributes());
|
1309 |
+
if ( this.dom_has() ) {
|
1310 |
+
attrs.push(this.get_dom_attributes());
|
1311 |
+
}
|
1312 |
+
if ( this.util.is_obj(this._attr_init) ) {
|
1313 |
+
attrs.push(this._attr_init);
|
1314 |
+
}
|
1315 |
+
//Merge attributes
|
1316 |
+
this.attributes = $.extend.apply(null, attrs);
|
1317 |
+
}
|
1318 |
+
},
|
1319 |
+
|
1320 |
+
/**
|
1321 |
+
* Generate default attributes for component
|
1322 |
+
* @uses _attr_parent to determine options to retrieve from controller
|
1323 |
+
* @uses View.get_options() to get values from controller
|
1324 |
+
* @uses _attr_map to Remap controller attributes to instance attributes
|
1325 |
+
* @uses _attr_default to Store default attributes
|
1326 |
+
*/
|
1327 |
+
init_default_attributes: function() {
|
1328 |
+
//Get parent options
|
1329 |
+
var opts = this.get_parent().get_options(this._attr_parent);
|
1330 |
+
if ( this.util.is_obj(opts) ) {
|
1331 |
+
//Remap
|
1332 |
+
for ( var opt in this._attr_map ) {
|
1333 |
+
if ( opt in opts ) {
|
1334 |
+
//Move value to new property
|
1335 |
+
opts[this._attr_map[opt]] = opts[opt];
|
1336 |
+
//Delete old property
|
1337 |
+
delete opts[opt];
|
1338 |
+
}
|
1339 |
+
}
|
1340 |
+
//Merge with default attributes
|
1341 |
+
$.extend(true, this._attr_default, opts);
|
1342 |
+
}
|
1343 |
+
return this._attr_default;
|
1344 |
+
},
|
1345 |
+
|
1346 |
+
/**
|
1347 |
+
* Retrieve DOM attributes
|
1348 |
+
*/
|
1349 |
+
get_dom_attributes: function() {
|
1350 |
+
var attrs = {};
|
1351 |
+
var el = this.dom_get();
|
1352 |
+
if ( el.length ) {
|
1353 |
+
//Get attributes from element
|
1354 |
+
var opts = $(el).get(0).attributes;
|
1355 |
+
if ( this.util.is_obj(opts) ) {
|
1356 |
+
var attr_prefix = this.util.get_attribute();
|
1357 |
+
$.each(opts, function(idx, opt) {
|
1358 |
+
if ( opt.name.indexOf( attr_prefix ) == -1 ) {
|
1359 |
+
return true;
|
1360 |
+
}
|
1361 |
+
//Process custom attributes
|
1362 |
+
//Strip prefix
|
1363 |
+
var key = opt.name.substr(attr_prefix.length + 1);
|
1364 |
+
attrs[key] = opt.value;
|
1365 |
+
});
|
1366 |
+
}
|
1367 |
+
}
|
1368 |
+
return attrs;
|
1369 |
+
},
|
1370 |
+
|
1371 |
+
/**
|
1372 |
+
* Retrieve all instance attributes
|
1373 |
+
* @uses parse_attributes() to initialize attributes (if necessary)
|
1374 |
+
* @uses attributes
|
1375 |
+
* @return obj Attributes
|
1376 |
+
*/
|
1377 |
+
get_attributes: function() {
|
1378 |
+
//Initilize attributes
|
1379 |
+
this.init_attributes();
|
1380 |
+
//Return attributes
|
1381 |
+
return this.attributes;
|
1382 |
+
},
|
1383 |
+
|
1384 |
+
/**
|
1385 |
+
* Retrieve value of specified attribute for value
|
1386 |
+
* @param string key Attribute to retrieve
|
1387 |
+
* @param mixed def (optional) Default value if attribute is not set
|
1388 |
+
* @param bool enforce_type (optional) Whether data type should match default value (Default: TRUE)
|
1389 |
+
* > If possible, attribute value will be converted to match default data type
|
1390 |
+
* > If attribute value cannot match default data type, default value will be used
|
1391 |
+
* @return mixed Attribute value (NULL if attribute is not set)
|
1392 |
+
*/
|
1393 |
+
get_attribute: function(key, def, enforce_type) {
|
1394 |
+
//Validate
|
1395 |
+
if ( !this.util.is_set(def) ) {
|
1396 |
+
def = null;
|
1397 |
+
}
|
1398 |
+
if ( !this.util.is_string(key) ) {
|
1399 |
+
return def;
|
1400 |
+
}
|
1401 |
+
if ( !this.util.is_bool(enforce_type) ) {
|
1402 |
+
enforce_type = true;
|
1403 |
+
}
|
1404 |
+
//Get attribute value
|
1405 |
+
var ret = ( this.has_attribute(key) ) ? this.get_attributes()[key] : def;
|
1406 |
+
//Validate type
|
1407 |
+
if ( enforce_type && ret !== def && null !== def && !this.util.is_type(ret, $.type(def), false) ) {
|
1408 |
+
//Convert type
|
1409 |
+
//Scalar default
|
1410 |
+
if ( this.util.is_scalar(def, false) ) {
|
1411 |
+
//Non-scalar attribute
|
1412 |
+
if ( !this.util.is_scalar(ret, false) ) {
|
1413 |
+
ret = def;
|
1414 |
+
} else if ( this.util.is_string(def, false) ) {
|
1415 |
+
ret = ret.toString();
|
1416 |
+
} else if ( this.util.is_num(def, false) && !this.util.is_num(ret, false) ) {
|
1417 |
+
ret = ( this.util.is_int(def, false) ) ? parseInt(ret) : parseFloat(ret);
|
1418 |
+
if ( !this.util.is_num(ret, false) ) {
|
1419 |
+
ret = def;
|
1420 |
+
}
|
1421 |
+
} else if ( this.util.is_bool(def, false) ) {
|
1422 |
+
ret = ( this.util.is_string(ret) || ( this.util.is_num(ret) ) );
|
1423 |
+
} else {
|
1424 |
+
ret = def;
|
1425 |
+
}
|
1426 |
+
}
|
1427 |
+
//Non-scalar default
|
1428 |
+
else {
|
1429 |
+
ret = def;
|
1430 |
+
}
|
1431 |
+
}
|
1432 |
+
return ret;
|
1433 |
+
},
|
1434 |
+
|
1435 |
+
/**
|
1436 |
+
* Call attribute as method
|
1437 |
+
* @param string attr Attribute to call
|
1438 |
+
* @param arguments (optional) Additional arguments to pass to method
|
1439 |
+
*/
|
1440 |
+
call_attribute: function(attr, args) {
|
1441 |
+
attr = this.get_attribute(attr);
|
1442 |
+
if ( this.util.is_func(attr) ) {
|
1443 |
+
//Get arguments
|
1444 |
+
var args = Array.prototype.slice.call(arguments, 1);
|
1445 |
+
//Pass arguments to user-defined method
|
1446 |
+
attr = attr.apply(this, args);
|
1447 |
+
}
|
1448 |
+
return attr;
|
1449 |
+
},
|
1450 |
+
|
1451 |
+
/**
|
1452 |
+
* Check if attribute exists
|
1453 |
+
* @param string key Attribute name
|
1454 |
+
* @return bool TRUE if exists, FALSE otherwise
|
1455 |
+
*/
|
1456 |
+
has_attribute: function(key) {
|
1457 |
+
return ( key in this.get_attributes() );
|
1458 |
+
},
|
1459 |
+
|
1460 |
+
/**
|
1461 |
+
* Set component attributes
|
1462 |
+
* @param obj attributes Attributes to set
|
1463 |
+
* @param bool full (optional) Whether to fully replace or merge component's attributes with new values (Default: Merge)
|
1464 |
+
*/
|
1465 |
+
set_attributes: function(attributes, full) {
|
1466 |
+
if ( !this.util.is_bool(full) ) {
|
1467 |
+
full = false;
|
1468 |
+
}
|
1469 |
+
|
1470 |
+
//Initialize attributes
|
1471 |
+
this.init_attributes(full);
|
1472 |
+
|
1473 |
+
//Merge new/existing attributes
|
1474 |
+
if ( this.util.is_obj(attributes) ) {
|
1475 |
+
$.extend(this.attributes, attributes);
|
1476 |
+
}
|
1477 |
+
},
|
1478 |
+
|
1479 |
+
/**
|
1480 |
+
* Set value for a component attribute
|
1481 |
+
* @uses get_attributes() to retrieve attributes
|
1482 |
+
* @param string key Attribute to set
|
1483 |
+
* @param mixed val Attribute value
|
1484 |
+
*/
|
1485 |
+
set_attribute: function(key, val) {
|
1486 |
+
if ( this.util.is_string(key) && this.util.is_set(val) ) {
|
1487 |
+
this.get_attributes()[key] = val;
|
1488 |
+
}
|
1489 |
+
return val;
|
1490 |
+
},
|
1491 |
+
|
1492 |
+
/* DOM */
|
1493 |
+
|
1494 |
+
/**
|
1495 |
+
* Generate selector for retrieving child element
|
1496 |
+
* @param string element Class name of child element
|
1497 |
+
* @return string Element selector
|
1498 |
+
*/
|
1499 |
+
dom_get_selector: function(element) {
|
1500 |
+
return ( this.util.is_string(element) ) ? '.' + this.add_ns(element) : '';
|
1501 |
+
},
|
1502 |
+
|
1503 |
+
dom_get_attribute: function() {
|
1504 |
+
return this.util.get_attribute(this._slug);
|
1505 |
+
},
|
1506 |
+
|
1507 |
+
/**
|
1508 |
+
* Set reference of instance on DOM element
|
1509 |
+
* @uses _reciprocal to determine if DOM element should also be attached to instance
|
1510 |
+
* @param string|obj (jQuery) el DOM element to attach instance to
|
1511 |
+
* @return jQuery DOM element set
|
1512 |
+
*/
|
1513 |
+
dom_set: function(el) {
|
1514 |
+
el = $(el);
|
1515 |
+
//Save instance to DOM object
|
1516 |
+
el.data(this.get_data_key(), this);
|
1517 |
+
//Save DOM object to instance
|
1518 |
+
if ( this._reciprocal ) {
|
1519 |
+
this._dom = el;
|
1520 |
+
}
|
1521 |
+
return el;
|
1522 |
+
},
|
1523 |
+
|
1524 |
+
/**
|
1525 |
+
* Retrieve attached DOM element
|
1526 |
+
* @uses _dom to retrieve attached DOM element
|
1527 |
+
* @uses dom_put() to insert child element
|
1528 |
+
* @param string element Child element to retrieve
|
1529 |
+
* @param bool put (optional) Whether to insert element if it does not exist (Default: FALSE)
|
1530 |
+
* @param obj options (optional) Options for creating new object
|
1531 |
+
* @return obj jQuery DOM element
|
1532 |
+
*/
|
1533 |
+
dom_get: function(element, put, options) {
|
1534 |
+
//Init Component DOM
|
1535 |
+
if ( !this.get_status('dom_init') ) {
|
1536 |
+
this.set_status('dom_init');
|
1537 |
+
this.dom_init();
|
1538 |
+
}
|
1539 |
+
//Check for main DOM element
|
1540 |
+
var ret = this._dom;
|
1541 |
+
if ( !!ret && this.util.is_string(element) ) {
|
1542 |
+
var ch = $(ret).find( this.dom_get_selector(element) );
|
1543 |
+
//Check for child element
|
1544 |
+
if ( ch.length ) {
|
1545 |
+
ret = ch;
|
1546 |
+
} else if ( this.util.is_bool(put) && put ) {
|
1547 |
+
//Insert child element
|
1548 |
+
ret = this.dom_put(element, options);
|
1549 |
+
}
|
1550 |
+
}
|
1551 |
+
return $(ret);
|
1552 |
+
},
|
1553 |
+
|
1554 |
+
/**
|
1555 |
+
* Initialize DOM element
|
1556 |
+
* To be overridden by child classes
|
1557 |
+
*/
|
1558 |
+
dom_init: function() {},
|
1559 |
+
|
1560 |
+
/**
|
1561 |
+
* Wrap output in DOM element
|
1562 |
+
* Wrapper element created and added to main DOM element if not yet created
|
1563 |
+
* @param string element ID for DOM element (Used as class name for wrapper)
|
1564 |
+
* @param string|jQuery|obj content Content to add to DOM (Object contains element properties)
|
1565 |
+
* > tag : Element tag name
|
1566 |
+
* > content : Element content
|
1567 |
+
* @return jQuery Inserted element(s)
|
1568 |
+
*/
|
1569 |
+
dom_put: function(element, content) {
|
1570 |
+
var r = null;
|
1571 |
+
//Stop processing if main DOM element not set or element is not valid
|
1572 |
+
if ( !this.dom_has() || !this.util.is_string(element) ) {
|
1573 |
+
return $(r);
|
1574 |
+
}
|
1575 |
+
//Setup options
|
1576 |
+
var strip = ['tag', 'content', 'put_success'];
|
1577 |
+
var options = {
|
1578 |
+
'tag': 'div',
|
1579 |
+
'content': '',
|
1580 |
+
'class': this.add_ns(element)
|
1581 |
+
}
|
1582 |
+
//Setup content
|
1583 |
+
if ( !this.util.is_empty(content) ) {
|
1584 |
+
if ( this.util.is_type(content, jQuery, false) || this.util.is_string(content, false) ) {
|
1585 |
+
options.content = content;
|
1586 |
+
}
|
1587 |
+
else if ( this.util.is_obj(content, false) ) {
|
1588 |
+
$.extend(options, content);
|
1589 |
+
}
|
1590 |
+
}
|
1591 |
+
var attrs = $.extend({}, options);
|
1592 |
+
for ( var x = 0; x < strip.length; x++ ) {
|
1593 |
+
delete attrs[strip[x]];
|
1594 |
+
}
|
1595 |
+
//Retrieve existing element
|
1596 |
+
var d = this.dom_get();
|
1597 |
+
r = $(this.dom_get_selector(element), d);
|
1598 |
+
//Create element (if necessary)
|
1599 |
+
if ( !r.length ) {
|
1600 |
+
r = $(this.util.format('<%s />', options.tag), attrs).appendTo(d);
|
1601 |
+
if ( r.length && this.util.is_method(options, 'put_success') ) {
|
1602 |
+
options['put_success'].call(r, r);
|
1603 |
+
}
|
1604 |
+
}
|
1605 |
+
//Set content
|
1606 |
+
$(r).append(options.content);
|
1607 |
+
return $(r);
|
1608 |
+
},
|
1609 |
+
|
1610 |
+
/**
|
1611 |
+
* Check if DOM element is set for instance
|
1612 |
+
* DOM is initialized before evaluation
|
1613 |
+
* @return bool TRUE if DOM element set, FALSE otherwise
|
1614 |
+
*/
|
1615 |
+
dom_has: function() {
|
1616 |
+
return ( !!this.dom_get().length );
|
1617 |
+
},
|
1618 |
+
|
1619 |
+
/* Data */
|
1620 |
+
|
1621 |
+
/**
|
1622 |
+
* Retrieve key used to store data in DOM element
|
1623 |
+
* @return string Data key
|
1624 |
+
*/
|
1625 |
+
get_data_key: function() {
|
1626 |
+
return this.get_ns();
|
1627 |
+
},
|
1628 |
+
|
1629 |
+
/* Events */
|
1630 |
+
|
1631 |
+
/**
|
1632 |
+
* Register event handler for custom event
|
1633 |
+
* Structure
|
1634 |
+
* > Events (obj)
|
1635 |
+
* > Event-Name (array)
|
1636 |
+
* > Handlers (functions)
|
1637 |
+
* @param mixed event Custom event to register handler for
|
1638 |
+
* > string: Standard event handler
|
1639 |
+
* > array: Multiple events to register single handler on
|
1640 |
+
* > object: Map of events/handlers
|
1641 |
+
* @param function fn Event handler
|
1642 |
+
* @param obj options Handler registration options
|
1643 |
+
* > clear (bool) Clear existing event handlers before setting current handler (Default: FALSE)
|
1644 |
+
* @return obj Component instance (allows chaining)
|
1645 |
+
*/
|
1646 |
+
on: function(event, fn, options) {
|
1647 |
+
//Handle request types
|
1648 |
+
if ( !this.util.is_string(event) || !this.util.is_func(fn) ) {
|
1649 |
+
var t = this;
|
1650 |
+
var args = Array.prototype.slice.call(arguments, 1);
|
1651 |
+
if ( this.util.is_array(event) ) {
|
1652 |
+
//Events array
|
1653 |
+
$.each(event, function(idx, val) {
|
1654 |
+
t.on.apply(t, [val].concat(args));
|
1655 |
+
});
|
1656 |
+
} else if ( this.util.is_obj(event) ) {
|
1657 |
+
//Events map
|
1658 |
+
$.each(event, function(ev, hdl) {
|
1659 |
+
t.on.apply(t, [ev, hdl].concat(args));
|
1660 |
+
});
|
1661 |
+
}
|
1662 |
+
return this;
|
1663 |
+
}
|
1664 |
+
|
1665 |
+
//Options
|
1666 |
+
|
1667 |
+
//Default options
|
1668 |
+
var options_std = {
|
1669 |
+
clear: false
|
1670 |
+
};
|
1671 |
+
if ( !this.util.is_obj(options, false) ) {
|
1672 |
+
//Reset options
|
1673 |
+
options = {};
|
1674 |
+
}
|
1675 |
+
//Build options
|
1676 |
+
options = $.extend({}, options_std, options);
|
1677 |
+
//Initialize events bucket
|
1678 |
+
if ( !this.util.is_obj(this._events, false) ) {
|
1679 |
+
this._events = {};
|
1680 |
+
}
|
1681 |
+
//Setup event
|
1682 |
+
var es = this._events;
|
1683 |
+
if ( !( event in es ) || !this.util.is_obj(es[event], false) || !!options.clear ) {
|
1684 |
+
es[event] = [];
|
1685 |
+
}
|
1686 |
+
//Add event handler
|
1687 |
+
es[event].push(fn);
|
1688 |
+
return this;
|
1689 |
+
},
|
1690 |
+
|
1691 |
+
/**
|
1692 |
+
* Trigger custom event
|
1693 |
+
* Event handlers are executed in the context of the current component instance
|
1694 |
+
* Event handlers are passed parameters
|
1695 |
+
* > ev (obj) Event object
|
1696 |
+
* > type (string) Event name
|
1697 |
+
* > data (mixed) Data to pass to handlers (if supplied)
|
1698 |
+
* > component (obj) Current component instance
|
1699 |
+
* @param string event Custom event to trigger
|
1700 |
+
* @param mixed data (optional) Data to pass to event handlers
|
1701 |
+
* @return jQuery.Promise Promise that is resolved once event handlers are resolved
|
1702 |
+
*/
|
1703 |
+
trigger: function(event, data) {
|
1704 |
+
var dfr = $.Deferred();
|
1705 |
+
var dfrs = [];
|
1706 |
+
var t = this;
|
1707 |
+
//Handle array of events
|
1708 |
+
if ( this.util.is_array(event) ) {
|
1709 |
+
$.each(event, function(idx, val) {
|
1710 |
+
//Collect promises from triggered events
|
1711 |
+
dfrs.push( t.trigger(val, data) );
|
1712 |
+
});
|
1713 |
+
//Resolve trigger when all events have been resolved
|
1714 |
+
$.when.apply(t, dfrs).done(function() {
|
1715 |
+
dfr.resolve();
|
1716 |
+
});
|
1717 |
+
return dfr.promise();
|
1718 |
+
}
|
1719 |
+
//Validate
|
1720 |
+
if ( !this.util.is_string(event) || !( event in this._events ) ) {
|
1721 |
+
dfr.resolve();
|
1722 |
+
return dfr.promise();
|
1723 |
+
}
|
1724 |
+
//Create event object
|
1725 |
+
var ev = { 'type': event, 'data': null };
|
1726 |
+
//Add data to event object
|
1727 |
+
if ( this.util.is_set(data) ) {
|
1728 |
+
ev.data = data;
|
1729 |
+
}
|
1730 |
+
//Fire handlers for event
|
1731 |
+
$.each(this._events[event], function(idx, fn) {
|
1732 |
+
//Call handler (`this` set to current instance)
|
1733 |
+
//Collect promises from event handlers
|
1734 |
+
dfrs.push( fn.call(t, ev, t) );
|
1735 |
+
});
|
1736 |
+
//Resolve trigger when all handlers have been resolved
|
1737 |
+
$.when.apply(this, dfrs).done(function() {
|
1738 |
+
dfr.resolve();
|
1739 |
+
});
|
1740 |
+
return dfr.promise();
|
1741 |
+
}
|
1742 |
+
};
|
1743 |
+
|
1744 |
+
View.Component = Component = SLB.Class.extend(Component);
|
1745 |
+
|
1746 |
+
/**
|
1747 |
+
* Content viewer
|
1748 |
+
* @param obj options Init options
|
1749 |
+
*/
|
1750 |
+
var Viewer = {
|
1751 |
+
|
1752 |
+
/* Configuration */
|
1753 |
+
|
1754 |
+
_slug: 'viewer',
|
1755 |
+
|
1756 |
+
_refs: {
|
1757 |
+
item: 'Content_Item',
|
1758 |
+
theme: 'Theme'
|
1759 |
+
},
|
1760 |
+
|
1761 |
+
_reciprocal: true,
|
1762 |
+
|
1763 |
+
_attr_default: {
|
1764 |
+
loop: true,
|
1765 |
+
animate: true,
|
1766 |
+
autofit: true,
|
1767 |
+
overlay_enabled: true,
|
1768 |
+
overlay_opacity: '0.8',
|
1769 |
+
container: null,
|
1770 |
+
slideshow_enabled: true,
|
1771 |
+
slideshow_autostart: true,
|
1772 |
+
slideshow_duration: 2,
|
1773 |
+
slideshow_active: false,
|
1774 |
+
slideshow_timer: null,
|
1775 |
+
labels: {
|
1776 |
+
close: 'close',
|
1777 |
+
nav_prev: '« prev',
|
1778 |
+
nav_next: 'next »',
|
1779 |
+
slideshow_start: 'start slideshow',
|
1780 |
+
slideshow_stop: 'stop slideshow',
|
1781 |
+
group_status: 'Image %current% of %total%',
|
1782 |
+
loading: 'loading'
|
1783 |
+
}
|
1784 |
+
},
|
1785 |
+
|
1786 |
+
_attr_parent: [
|
1787 |
+
'theme',
|
1788 |
+
'group_loop',
|
1789 |
+
'ui_autofit', 'ui_animate', 'ui_overlay_opacity', 'ui_labels',
|
1790 |
+
'slideshow_enabled', 'slideshow_autostart', 'slideshow_duration'],
|
1791 |
+
|
1792 |
+
_attr_map: {
|
1793 |
+
'group_loop': 'loop',
|
1794 |
+
'ui_autofit': 'autofit',
|
1795 |
+
'ui_animate': 'animate',
|
1796 |
+
'ui_overlay_opacity': 'overlay_opacity',
|
1797 |
+
'ui_labels': 'labels'
|
1798 |
+
},
|
1799 |
+
|
1800 |
+
/* References */
|
1801 |
+
|
1802 |
+
/**
|
1803 |
+
* Item currently loaded in viewer
|
1804 |
+
* @var object Content_Item
|
1805 |
+
*/
|
1806 |
+
item: null,
|
1807 |
+
|
1808 |
+
/**
|
1809 |
+
* Queued item to be loaded once viewer is available
|
1810 |
+
* @var object Content_Item
|
1811 |
+
*/
|
1812 |
+
item_queued: null,
|
1813 |
+
|
1814 |
+
/**
|
1815 |
+
* Theme used by viewer
|
1816 |
+
* @var object Theme
|
1817 |
+
*/
|
1818 |
+
theme: null,
|
1819 |
+
|
1820 |
+
/* Properties */
|
1821 |
+
|
1822 |
+
item_working: null,
|
1823 |
+
|
1824 |
+
active: false,
|
1825 |
+
init: false,
|
1826 |
+
open: false,
|
1827 |
+
loading: false,
|
1828 |
+
|
1829 |
+
/* Methods */
|
1830 |
+
|
1831 |
+
/* Init */
|
1832 |
+
|
1833 |
+
register_hooks: function() {
|
1834 |
+
var t = this;
|
1835 |
+
this
|
1836 |
+
.on(['item-prev', 'item-next'], function() {
|
1837 |
+
t.trigger('item-change');
|
1838 |
+
})
|
1839 |
+
.on(['close', 'item-change'], function() {
|
1840 |
+
t.unlock();
|
1841 |
+
});
|
1842 |
+
},
|
1843 |
+
|
1844 |
+
/* References */
|
1845 |
+
|
1846 |
+
/**
|
1847 |
+
* Set item reference
|
1848 |
+
* Validates item before setting
|
1849 |
+
* @param obj item Content_Item instance
|
1850 |
+
* @return bool TRUE if valid item set, FALSE otherwise
|
1851 |
+
*/
|
1852 |
+
set_item: function(item) {
|
1853 |
+
//Clear existing item
|
1854 |
+
this.clear_item(false);
|
1855 |
+
var i = this.set_component('item', item, function(item) {
|
1856 |
+
return ( item.has_type() );
|
1857 |
+
});
|
1858 |
+
return ( !this.util.is_empty(i) );
|
1859 |
+
},
|
1860 |
+
|
1861 |
+
clear_item: function(full) {
|
1862 |
+
//Validate
|
1863 |
+
if ( !this.util.is_bool(full) ) {
|
1864 |
+
full = true;
|
1865 |
+
}
|
1866 |
+
var item = this.get_item();
|
1867 |
+
if ( !!item ) {
|
1868 |
+
item.reset();
|
1869 |
+
}
|
1870 |
+
if ( full ) {
|
1871 |
+
this.set_item(false);
|
1872 |
+
}
|
1873 |
+
},
|
1874 |
+
|
1875 |
+
/**
|
1876 |
+
* Retrieve item instance current attached to viewer
|
1877 |
+
* @return Content_Item|NULL Current item instance
|
1878 |
+
*/
|
1879 |
+
get_item: function() {
|
1880 |
+
return this.get_component('item', true, false);
|
1881 |
+
},
|
1882 |
+
|
1883 |
+
/**
|
1884 |
+
* Retrieve theme reference
|
1885 |
+
* @return object Theme reference
|
1886 |
+
*/
|
1887 |
+
get_theme: function() {
|
1888 |
+
//Get saved theme
|
1889 |
+
var ret = this.get_component('theme', false, false, false);
|
1890 |
+
if ( this.util.is_empty(ret) ) {
|
1891 |
+
//Theme needs to be initialized
|
1892 |
+
ret = this.set_component('theme', new View.Theme(this));
|
1893 |
+
}
|
1894 |
+
return ret;
|
1895 |
+
},
|
1896 |
+
|
1897 |
+
/**
|
1898 |
+
* Set viewer's theme
|
1899 |
+
* @param object theme Theme object
|
1900 |
+
*/
|
1901 |
+
set_theme: function(theme) {
|
1902 |
+
this.set_component('theme', theme);
|
1903 |
+
},
|
1904 |
+
|
1905 |
+
/* Properties */
|
1906 |
+
|
1907 |
+
/**
|
1908 |
+
* Lock the viewer
|
1909 |
+
* Indicates that item is currently being processed
|
1910 |
+
* @return jQuery.Deferred Resolved when item processing is complete
|
1911 |
+
*/
|
1912 |
+
lock: function() {
|
1913 |
+
return this.set_status('item_working', $.Deferred());
|
1914 |
+
},
|
1915 |
+
|
1916 |
+
/**
|
1917 |
+
* Retrieve lock
|
1918 |
+
* @param bool simple (optional) Whether to return a simple status of the locked status (Default: FALSE)
|
1919 |
+
* @param bool full (optional) Whether to return Deferred (TRUE) or Promise (FALSE) object (Default: FALSE)
|
1920 |
+
* @return jQuery.Promise Resolved when item processing is complete
|
1921 |
+
*/
|
1922 |
+
get_lock: function(simple, full) {
|
1923 |
+
//Validate
|
1924 |
+
if ( !this.util.is_bool(simple) ) {
|
1925 |
+
simple = false;
|
1926 |
+
}
|
1927 |
+
if ( !this.util.is_bool(full) ) {
|
1928 |
+
full = false;
|
1929 |
+
}
|
1930 |
+
var s = 'item_working';
|
1931 |
+
//Simple status
|
1932 |
+
if ( simple ) {
|
1933 |
+
return this.get_status(s);
|
1934 |
+
}
|
1935 |
+
//Full value
|
1936 |
+
var r = this.get_status(s, true);
|
1937 |
+
if ( !this.util.is_promise(r) ) {
|
1938 |
+
//Create default
|
1939 |
+
r = this.lock();
|
1940 |
+
}
|
1941 |
+
return ( full ) ? r : r.promise();
|
1942 |
+
},
|
1943 |
+
|
1944 |
+
is_locked: function() {
|
1945 |
+
return this.get_lock(true);
|
1946 |
+
},
|
1947 |
+
|
1948 |
+
/**
|
1949 |
+
* Unlock the viewer
|
1950 |
+
* Any callbacks registered for this action will be executed
|
1951 |
+
* @return jQuery.Deferred Resolved instance
|
1952 |
+
*/
|
1953 |
+
unlock: function() {
|
1954 |
+
return this.get_lock(false, true).resolve();
|
1955 |
+
},
|
1956 |
+
|
1957 |
+
/**
|
1958 |
+
* Set Viewer active status
|
1959 |
+
* @param bool mode (optional) Activate or deactivate status (Default: TRUE)
|
1960 |
+
* @return bool Active status
|
1961 |
+
*/
|
1962 |
+
set_active: function(mode) {
|
1963 |
+
if ( !this.util.is_bool(mode) ) {
|
1964 |
+
mode = true;
|
1965 |
+
}
|
1966 |
+
return this.set_status('active', mode);
|
1967 |
+
},
|
1968 |
+
|
1969 |
+
/**
|
1970 |
+
* Check Viewer active status
|
1971 |
+
* @return bool Active status
|
1972 |
+
*/
|
1973 |
+
is_active: function() {
|
1974 |
+
return this.get_status('active');
|
1975 |
+
},
|
1976 |
+
|
1977 |
+
/**
|
1978 |
+
* Set loading mode
|
1979 |
+
* @param bool mode (optional) Set (TRUE) or unset (FALSE) loading mode (Default: TRUE)
|
1980 |
+
* @return jQuery.Promise Promise that resolves when loading mode is set
|
1981 |
+
*/
|
1982 |
+
set_loading: function(mode) {
|
1983 |
+
var dfr = $.Deferred();
|
1984 |
+
if ( !this.util.is_bool(mode) ) {
|
1985 |
+
mode = true;
|
1986 |
+
}
|
1987 |
+
this.loading = mode;
|
1988 |
+
//Pause/Resume slideshow
|
1989 |
+
if ( this.slideshow_active() ) {
|
1990 |
+
this.slideshow_pause(mode);
|
1991 |
+
}
|
1992 |
+
//Set CSS class on DOM element
|
1993 |
+
var m = ( mode ) ? 'addClass' : 'removeClass';
|
1994 |
+
$(this.dom_get())[m]('loading');
|
1995 |
+
if ( mode ) {
|
1996 |
+
//Loading transition
|
1997 |
+
this.get_theme().transition('load').always(function() {
|
1998 |
+
dfr.resolve();
|
1999 |
+
});
|
2000 |
+
} else {
|
2001 |
+
dfr.resolve();
|
2002 |
+
}
|
2003 |
+
return dfr.promise();
|
2004 |
+
},
|
2005 |
+
|
2006 |
+
/**
|
2007 |
+
* Unset loading mode
|
2008 |
+
* @see set_loading()
|
2009 |
+
* @return jQuery.Promise Promise that resovles when loading mode is set
|
2010 |
+
*/
|
2011 |
+
unset_loading: function() {
|
2012 |
+
return this.set_loading(false);
|
2013 |
+
},
|
2014 |
+
|
2015 |
+
/**
|
2016 |
+
* Retrieve loading status
|
2017 |
+
* @return bool Loading status (Default: FALSE)
|
2018 |
+
*/
|
2019 |
+
get_loading: function() {
|
2020 |
+
return ( this.util.is_bool(this.loading) ) ? this.loading : false;
|
2021 |
+
},
|
2022 |
+
|
2023 |
+
/**
|
2024 |
+
* Check if viewer is currently loading content
|
2025 |
+
* @return bool Loading status (Default: FALSE)
|
2026 |
+
*/
|
2027 |
+
is_loading: function() {
|
2028 |
+
return this.get_loading();
|
2029 |
+
},
|
2030 |
+
|
2031 |
+
/* Display */
|
2032 |
+
|
2033 |
+
/**
|
2034 |
+
* Display content in viewer
|
2035 |
+
* @param Content_Item item Item to show
|
2036 |
+
* @param obj options (optional) Display options
|
2037 |
+
*/
|
2038 |
+
show: function(item) {
|
2039 |
+
this.item_queued = item;
|
2040 |
+
var fin_set = 'show_deferred';
|
2041 |
+
//Validate theme
|
2042 |
+
var vt = 'theme_valid';
|
2043 |
+
var valid = true;
|
2044 |
+
if ( !this.has_attribute(vt)) {
|
2045 |
+
valid = this.set_attribute(vt, ( this.get_theme() && this.get_theme().get_template().get_layout(false) ) );
|
2046 |
+
} else {
|
2047 |
+
valid = this.get_attribute(vt, true);
|
2048 |
+
}
|
2049 |
+
|
2050 |
+
if ( !valid ) {
|
2051 |
+
this.close();
|
2052 |
+
return false;
|
2053 |
+
}
|
2054 |
+
var v = this;
|
2055 |
+
var fin = function() {
|
2056 |
+
//Lock viewer
|
2057 |
+
v.lock();
|
2058 |
+
//Reset callback flag (for new lock)
|
2059 |
+
v.set_status(fin_set, false);
|
2060 |
+
//Validate request
|
2061 |
+
if ( !v.set_item(v.item_queued) ) {
|
2062 |
+
v.close();
|
2063 |
+
return false;
|
2064 |
+
}
|
2065 |
+
//Add item to history stack
|
2066 |
+
v.history_add();
|
2067 |
+
//Activate
|
2068 |
+
v.set_active();
|
2069 |
+
//Display
|
2070 |
+
v.render();
|
2071 |
+
}
|
2072 |
+
if ( !this.is_locked() ) {
|
2073 |
+
fin();
|
2074 |
+
} else if ( !this.get_status(fin_set) ) {
|
2075 |
+
//Set flag to avoid duplicate callbacks
|
2076 |
+
this.set_status(fin_set);
|
2077 |
+
this.get_lock().always(function() {
|
2078 |
+
fin();
|
2079 |
+
});
|
2080 |
+
}
|
2081 |
+
},
|
2082 |
+
|
2083 |
+
/* History Management */
|
2084 |
+
|
2085 |
+
history_handle: function(e) {
|
2086 |
+
var state = e.originalEvent.state;
|
2087 |
+
//Load item
|
2088 |
+
if ( this.util.is_int(state.item, false) ) {
|
2089 |
+
this.get_parent().get_item(state.item).show({'event': e});
|
2090 |
+
this.trigger('item-change');
|
2091 |
+
} else {
|
2092 |
+
var count = this.history_get(true);
|
2093 |
+
//Reset count
|
2094 |
+
this.history_set(0);
|
2095 |
+
//Close viewer
|
2096 |
+
if ( -1 != count ) {
|
2097 |
+
this.close();
|
2098 |
+
}
|
2099 |
+
}
|
2100 |
+
},
|
2101 |
+
|
2102 |
+
history_get: function(full) {
|
2103 |
+
return this.get_status('history_count', full);
|
2104 |
+
},
|
2105 |
+
history_set: function(val) {
|
2106 |
+
return this.set_status('history_count', val);
|
2107 |
+
},
|
2108 |
+
history_add: function() {
|
2109 |
+
if ( !history.pushState ) {
|
2110 |
+
return false;
|
2111 |
+
}
|
2112 |
+
//Get display options
|
2113 |
+
var item = this.get_item();
|
2114 |
+
var opts = item.get_attribute('options_show');
|
2115 |
+
//Save history state
|
2116 |
+
var count = ( this.history_get() ) ? this.history_get(true) : 0;
|
2117 |
+
if ( !this.util.in_obj(opts, 'event') ) {
|
2118 |
+
//Create state
|
2119 |
+
var state = {
|
2120 |
+
'viewer': this.get_id(),
|
2121 |
+
'item': null,
|
2122 |
+
'count': count
|
2123 |
+
};
|
2124 |
+
//Init: Save viewer state
|
2125 |
+
if ( !count ) {
|
2126 |
+
history.replaceState(state, null);
|
2127 |
+
}
|
2128 |
+
//Always: Save item state
|
2129 |
+
state.item = this.get_parent().save_item(item);
|
2130 |
+
state.count = ++count;
|
2131 |
+
history.pushState(state, '');
|
2132 |
+
} else {
|
2133 |
+
var e = opts.event.originalEvent;
|
2134 |
+
if ( this.util.in_obj(e, 'state') && this.util.in_obj(e.state, 'count') ) {
|
2135 |
+
count = e.state.count;
|
2136 |
+
}
|
2137 |
+
}
|
2138 |
+
//Save history item count
|
2139 |
+
this.history_set(count);
|
2140 |
+
},
|
2141 |
+
history_reset: function() {
|
2142 |
+
var count = this.history_get(true);
|
2143 |
+
if ( count ) {
|
2144 |
+
//Clear history status
|
2145 |
+
this.history_set(-1);
|
2146 |
+
//Restore history stack
|
2147 |
+
history.go( -1 * count );
|
2148 |
+
}
|
2149 |
+
},
|
2150 |
+
|
2151 |
+
/**
|
2152 |
+
* Check if viewer is currently open
|
2153 |
+
* Checks if node is actually visible in DOM
|
2154 |
+
* @return bool TRUE if viewer is open, FALSE otherwise
|
2155 |
+
*/
|
2156 |
+
is_open: function() {
|
2157 |
+
return ( this.dom_get().css('display') == 'none' ) ? false : true;
|
2158 |
+
},
|
2159 |
+
|
2160 |
+
/**
|
2161 |
+
* Load output into DOM
|
2162 |
+
*/
|
2163 |
+
render: function() {
|
2164 |
+
//Get theme output
|
2165 |
+
var v = this;
|
2166 |
+
var thm = this.get_theme();
|
2167 |
+
//Register theme event handlers
|
2168 |
+
if ( !this.get_status('render-events') ) {
|
2169 |
+
this.set_status('render-events');
|
2170 |
+
thm
|
2171 |
+
//Loading
|
2172 |
+
.on('render-loading', function(ev, thm) {
|
2173 |
+
var dfr = $.Deferred();
|
2174 |
+
if ( !v.is_active() ) {
|
2175 |
+
dfr.reject();
|
2176 |
+
return dfr.promise();
|
2177 |
+
}
|
2178 |
+
var set_pos = function() {
|
2179 |
+
//Set position
|
2180 |
+
v.dom_get().css('top', $(window).scrollTop());
|
2181 |
+
};
|
2182 |
+
var always = function() {
|
2183 |
+
//Set loading flag
|
2184 |
+
v.set_loading().always(function() {
|
2185 |
+
dfr.resolve();
|
2186 |
+
});
|
2187 |
+
};
|
2188 |
+
if ( v.is_open() ) {
|
2189 |
+
thm.transition('unload')
|
2190 |
+
.fail(function() {
|
2191 |
+
set_pos();
|
2192 |
+
thm.dom_get_tag('item', 'content').attr('style', '');
|
2193 |
+
})
|
2194 |
+
.always(always);
|
2195 |
+
} else {
|
2196 |
+
thm.transition('open')
|
2197 |
+
.always(function() {
|
2198 |
+
always();
|
2199 |
+
v.events_open();
|
2200 |
+
v.open = true;
|
2201 |
+
})
|
2202 |
+
.fail(function() {
|
2203 |
+
set_pos();
|
2204 |
+
//Fallback open
|
2205 |
+
v.get_overlay().show();
|
2206 |
+
v.dom_get().show();
|
2207 |
+
});
|
2208 |
+
}
|
2209 |
+
return dfr.promise();
|
2210 |
+
})
|
2211 |
+
//Complete
|
2212 |
+
.on('render-complete', function(ev, thm) {
|
2213 |
+
//Stop if viewer not active
|
2214 |
+
if ( !v.is_active() ) {
|
2215 |
+
return false;
|
2216 |
+
}
|
2217 |
+
//Set classes
|
2218 |
+
var d = v.dom_get();
|
2219 |
+
var classes = ['item_single', 'item_multi'];
|
2220 |
+
var ms = ['addClass', 'removeClass'];
|
2221 |
+
if ( !v.get_item().get_group().is_single() ) {
|
2222 |
+
ms.reverse();
|
2223 |
+
}
|
2224 |
+
$.each(ms, function(idx, val) {
|
2225 |
+
d[val](classes[idx]);
|
2226 |
+
});
|
2227 |
+
//Bind events
|
2228 |
+
v.events_complete();
|
2229 |
+
//Transition
|
2230 |
+
thm.transition('complete')
|
2231 |
+
.fail(function() {
|
2232 |
+
//Autofit content
|
2233 |
+
if ( v.get_attribute('autofit', true) ) {
|
2234 |
+
var dims = $.extend({'display': 'inline-block'}, thm.get_item_dimensions());
|
2235 |
+
var tag = thm.dom_get_tag('item', 'content').css(dims);
|
2236 |
+
}
|
2237 |
+
})
|
2238 |
+
.always(function() {
|
2239 |
+
//Unset loading flag
|
2240 |
+
v.unset_loading();
|
2241 |
+
//Trigger event
|
2242 |
+
v.trigger('render-complete');
|
2243 |
+
//Set viewer as initialized
|
2244 |
+
v.init = true;
|
2245 |
+
});
|
2246 |
+
});
|
2247 |
+
}
|
2248 |
+
//Render
|
2249 |
+
thm.render();
|
2250 |
+
},
|
2251 |
+
|
2252 |
+
/**
|
2253 |
+
* Retrieve container element
|
2254 |
+
* Creates default container element if not yet created
|
2255 |
+
* @return jQuery Container element
|
2256 |
+
*/
|
2257 |
+
dom_get_container: function() {
|
2258 |
+
var sel = this.get_attribute('container');
|
2259 |
+
//Set default container
|
2260 |
+
if ( this.util.is_empty(sel) ) {
|
2261 |
+
sel = '#' + this.add_ns('wrap');
|
2262 |
+
}
|
2263 |
+
//Add default container to DOM if not yet present
|
2264 |
+
var c = $(sel);
|
2265 |
+
if ( !c.length ) {
|
2266 |
+
//Prepare ID
|
2267 |
+
var id = ( sel.indexOf('#') === 0 ) ? sel.substr(1) : sel;
|
2268 |
+
//Add element
|
2269 |
+
c = $('<div />', {'id': id}).appendTo('body');
|
2270 |
+
}
|
2271 |
+
return c;
|
2272 |
+
},
|
2273 |
+
|
2274 |
+
/**
|
2275 |
+
* Custom Viewer DOM initialization
|
2276 |
+
*/
|
2277 |
+
dom_init: function() {
|
2278 |
+
//Create element & add to DOM
|
2279 |
+
//Save element to instance
|
2280 |
+
var d = this.dom_set($('<div/>', {
|
2281 |
+
'id': this.get_id(true),
|
2282 |
+
'class': this.get_ns()
|
2283 |
+
})).appendTo(this.dom_get_container()).hide();
|
2284 |
+
//Add theme classes
|
2285 |
+
var thm = this.get_theme();
|
2286 |
+
d.addClass(thm.get_classes(' '));
|
2287 |
+
//Add theme layout (basic)
|
2288 |
+
var v = this;
|
2289 |
+
if ( !this.get_status('render-init') ) {
|
2290 |
+
this.set_status('render-init');
|
2291 |
+
thm.on('render-init', function(ev) {
|
2292 |
+
//Add rendered theme layout to viewer DOM
|
2293 |
+
v.dom_put('layout', ev.data);
|
2294 |
+
});
|
2295 |
+
}
|
2296 |
+
thm.render(true);
|
2297 |
+
},
|
2298 |
+
|
2299 |
+
/**
|
2300 |
+
* Restore DOM
|
2301 |
+
* Show overlapping DOM elements, etc.
|
2302 |
+
* @TODO Build functionality
|
2303 |
+
*/
|
2304 |
+
dom_restore: function() {},
|
2305 |
+
|
2306 |
+
/* Layout */
|
2307 |
+
|
2308 |
+
get_layout: function() {
|
2309 |
+
var ret = this.dom_get('layout', true, {
|
2310 |
+
'put_success': function() {
|
2311 |
+
$(this).hide();
|
2312 |
+
}
|
2313 |
+
});
|
2314 |
+
return ret;
|
2315 |
+
},
|
2316 |
+
|
2317 |
+
/* Animation */
|
2318 |
+
|
2319 |
+
animation_enabled: function() {
|
2320 |
+
return this.get_attribute('animate', true);
|
2321 |
+
},
|
2322 |
+
|
2323 |
+
/* Overlay */
|
2324 |
+
|
2325 |
+
/**
|
2326 |
+
* Determine if overlay is enabled for viewer
|
2327 |
+
* @return bool TRUE if overlay is enabled, FALSE otherwise
|
2328 |
+
*/
|
2329 |
+
overlay_enabled: function() {
|
2330 |
+
var ov = this.get_attribute('overlay_enabled');
|
2331 |
+
return ( this.util.is_bool(ov) ) ? ov : false;
|
2332 |
+
},
|
2333 |
+
|
2334 |
+
/**
|
2335 |
+
* Retrieve overlay DOM element
|
2336 |
+
* @return jQuery Overlay element (NULL if no overlay set for viewer)
|
2337 |
+
*/
|
2338 |
+
get_overlay: function() {
|
2339 |
+
var o = null;
|
2340 |
+
var v = this;
|
2341 |
+
if ( this.overlay_enabled() ) {
|
2342 |
+
o = this.dom_get('overlay', true, {
|
2343 |
+
'put_success': function() {
|
2344 |
+
$(this).hide().css('opacity', v.get_attribute('overlay_opacity'));
|
2345 |
+
}
|
2346 |
+
});
|
2347 |
+
}
|
2348 |
+
return $(o);
|
2349 |
+
},
|
2350 |
+
|
2351 |
+
unload: function() {
|
2352 |
+
|
2353 |
+
},
|
2354 |
+
|
2355 |
+
/**
|
2356 |
+
* Reset viewer
|
2357 |
+
*/
|
2358 |
+
reset: function() {
|
2359 |
+
//Hide viewer
|
2360 |
+
this.dom_get().hide();
|
2361 |
+
//Restore DOM
|
2362 |
+
this.dom_restore();
|
2363 |
+
//History
|
2364 |
+
this.history_reset();
|
2365 |
+
//Item
|
2366 |
+
this.clear_item();
|
2367 |
+
//Reset properties
|
2368 |
+
this.set_active(false);
|
2369 |
+
this.set_loading(false);
|
2370 |
+
this.slideshow_stop();
|
2371 |
+
this.keys_disable();
|
2372 |
+
//Clear for next item
|
2373 |
+
this.get_status('item_working', true).resolve();
|
2374 |
+
},
|
2375 |
+
|
2376 |
+
/* Content */
|
2377 |
+
|
2378 |
+
get_labels: function() {
|
2379 |
+
return this.get_attribute('labels', {});
|
2380 |
+
},
|
2381 |
+
|
2382 |
+
get_label: function(name) {
|
2383 |
+
var lbls = this.get_labels();
|
2384 |
+
return ( name in lbls ) ? lbls[name] : '';
|
2385 |
+
},
|
2386 |
+
|
2387 |
+
/* Interactivity */
|
2388 |
+
|
2389 |
+
/**
|
2390 |
+
* Initialize event handlers upon opening lightbox
|
2391 |
+
*/
|
2392 |
+
events_open: function() {
|
2393 |
+
//Keyboard bindings
|
2394 |
+
this.keys_enable();
|
2395 |
+
if ( this.open ) {
|
2396 |
+
return false;
|
2397 |
+
}
|
2398 |
+
|
2399 |
+
//Control event bubbling
|
2400 |
+
var l = this.get_layout();
|
2401 |
+
l.children().click(function(ev) {
|
2402 |
+
ev.stopPropagation();
|
2403 |
+
});
|
2404 |
+
|
2405 |
+
/* Close */
|
2406 |
+
var v = this;
|
2407 |
+
var close = function() {
|
2408 |
+
v.close();
|
2409 |
+
}
|
2410 |
+
//Layout
|
2411 |
+
l.click(close);
|
2412 |
+
//Overlay
|
2413 |
+
this.get_overlay().click(close);
|
2414 |
+
//Fire event
|
2415 |
+
this.trigger('events-open');
|
2416 |
+
},
|
2417 |
+
|
2418 |
+
/**
|
2419 |
+
* Initialize event handlers upon completing lightbox rendering
|
2420 |
+
*/
|
2421 |
+
events_complete: function() {
|
2422 |
+
if ( this.init ) {
|
2423 |
+
return false;
|
2424 |
+
}
|
2425 |
+
//Fire event
|
2426 |
+
this.trigger('events-complete');
|
2427 |
+
},
|
2428 |
+
|
2429 |
+
keys_enable: function(mode) {
|
2430 |
+
if ( !this.util.is_bool(mode) ) {
|
2431 |
+
mode = true;
|
2432 |
+
}
|
2433 |
+
var e = ['keyup', this.util.get_prefix()].join('.');
|
2434 |
+
var v = this;
|
2435 |
+
var h = function(ev) {
|
2436 |
+
return v.keys_control(ev);
|
2437 |
+
}
|
2438 |
+
if ( mode ) {
|
2439 |
+
$(document).on(e, h);
|
2440 |
+
} else {
|
2441 |
+
$(document).off(e);
|
2442 |
+
}
|
2443 |
+
},
|
2444 |
+
|
2445 |
+
keys_disable: function() {
|
2446 |
+
this.keys_enable(false);
|
2447 |
+
},
|
2448 |
+
|
2449 |
+
keys_control: function(ev) {
|
2450 |
+
var handlers = {
|
2451 |
+
27: this.close,
|
2452 |
+
37: this.item_prev,
|
2453 |
+
39: this.item_next
|
2454 |
+
};
|
2455 |
+
if ( ev.which in handlers ) {
|
2456 |
+
handlers[ev.which].call(this);
|
2457 |
+
return false;
|
2458 |
+
}
|
2459 |
+
},
|
2460 |
+
|
2461 |
+
/**
|
2462 |
+
* Check if slideshow functionality is enabled
|
2463 |
+
* @return bool TRUE if slideshow is enabled, FALSE otherwise
|
2464 |
+
*/
|
2465 |
+
slideshow_enabled: function() {
|
2466 |
+
var o = this.get_attribute('slideshow_enabled');
|
2467 |
+
return ( this.util.is_bool(o) && o && this.get_item() && !this.get_item().get_group().is_single() ) ? true : false;
|
2468 |
+
},
|
2469 |
+
|
2470 |
+
/**
|
2471 |
+
* Checks if slideshow is currently active
|
2472 |
+
* @return bool TRUE if slideshow is active, FALSE otherwise
|
2473 |
+
*/
|
2474 |
+
slideshow_active: function() {
|
2475 |
+
return ( this.slideshow_enabled() && ( this.get_attribute('slideshow_active') || ( !this.init && this.get_attribute('slideshow_autostart') ) ) ) ? true : false;
|
2476 |
+
},
|
2477 |
+
|
2478 |
+
/**
|
2479 |
+
* Clear slideshow timer
|
2480 |
+
*/
|
2481 |
+
slideshow_clear_timer: function() {
|
2482 |
+
clearInterval(this.get_attribute('slideshow_timer'));
|
2483 |
+
},
|
2484 |
+
|
2485 |
+
/**
|
2486 |
+
* Start slideshow timer
|
2487 |
+
* @param function callback Callback function
|
2488 |
+
*/
|
2489 |
+
slideshow_set_timer: function(callback) {
|
2490 |
+
this.set_attribute('slideshow_timer', setInterval(callback, this.get_attribute('slideshow_duration') * 1000));
|
2491 |
+
},
|
2492 |
+
|
2493 |
+
/**
|
2494 |
+
* Start Slideshow
|
2495 |
+
*/
|
2496 |
+
slideshow_start: function() {
|
2497 |
+
if ( !this.slideshow_enabled() ) {
|
2498 |
+
return false;
|
2499 |
+
}
|
2500 |
+
this.set_attribute('slideshow_active', true);
|
2501 |
+
this.dom_get().addClass('slideshow_active');
|
2502 |
+
//Clear residual timers
|
2503 |
+
this.slideshow_clear_timer();
|
2504 |
+
//Start timer
|
2505 |
+
var v = this;
|
2506 |
+
this.slideshow_set_timer(function() {
|
2507 |
+
//Pause slideshow until next item fully loaded
|
2508 |
+
v.slideshow_pause();
|
2509 |
+
|
2510 |
+
//Show next item
|
2511 |
+
v.item_next();
|
2512 |
+
});
|
2513 |
+
this.trigger('slideshow-start');
|
2514 |
+
},
|
2515 |
+
|
2516 |
+
/**
|
2517 |
+
* Stop Slideshow
|
2518 |
+
* @param bool full (optional) Full stop (TRUE) or pause (FALSE) (Default: TRUE)
|
2519 |
+
*/
|
2520 |
+
slideshow_stop: function(full) {
|
2521 |
+
if ( !this.util.is_bool(full) ) {
|
2522 |
+
full = true;
|
2523 |
+
}
|
2524 |
+
if ( full ) {
|
2525 |
+
this.set_attribute('slideshow_active', false);
|
2526 |
+
this.dom_get().removeClass('slideshow_active');
|
2527 |
+
}
|
2528 |
+
//Kill timers
|
2529 |
+
this.slideshow_clear_timer();
|
2530 |
+
this.trigger('slideshow-stop');
|
2531 |
+
},
|
2532 |
+
|
2533 |
+
slideshow_toggle: function() {
|
2534 |
+
if ( !this.slideshow_enabled() ) {
|
2535 |
+
return false;
|
2536 |
+
}
|
2537 |
+
if ( this.slideshow_active() ) {
|
2538 |
+
this.slideshow_stop();
|
2539 |
+
} else {
|
2540 |
+
this.slideshow_start();
|
2541 |
+
}
|
2542 |
+
this.trigger('slideshow-toggle');
|
2543 |
+
},
|
2544 |
+
|
2545 |
+
/**
|
2546 |
+
* Pause Slideshow
|
2547 |
+
* @param bool mode (optional) Pause (TRUE) or Resume (FALSE) slideshow (default: TRUE)
|
2548 |
+
*/
|
2549 |
+
slideshow_pause: function(mode) {
|
2550 |
+
//Validate
|
2551 |
+
if ( !this.util.is_bool(mode) ) {
|
2552 |
+
mode = true;
|
2553 |
+
}
|
2554 |
+
//Set viewer slideshow properties
|
2555 |
+
if ( this.slideshow_active() ) {
|
2556 |
+
if ( !mode ) {
|
2557 |
+
//Slideshow resumed
|
2558 |
+
this.slideshow_start();
|
2559 |
+
} else {
|
2560 |
+
//Slideshow paused
|
2561 |
+
this.slideshow_stop(false);
|
2562 |
+
}
|
2563 |
+
}
|
2564 |
+
this.trigger('slideshow-pause');
|
2565 |
+
},
|
2566 |
+
|
2567 |
+
/**
|
2568 |
+
* Resume slideshow
|
2569 |
+
*/
|
2570 |
+
slideshow_resume: function() {
|
2571 |
+
this.slideshow_pause(false);
|
2572 |
+
},
|
2573 |
+
|
2574 |
+
/**
|
2575 |
+
* Next item
|
2576 |
+
*/
|
2577 |
+
item_next: function() {
|
2578 |
+
var g = this.get_item().get_group(true);
|
2579 |
+
var v = this;
|
2580 |
+
var ev = 'item-next';
|
2581 |
+
var st = ['events', 'viewer', ev].join('_');
|
2582 |
+
//Setup event handler
|
2583 |
+
if ( !g.get_status(st) ) {
|
2584 |
+
g.set_status(st);
|
2585 |
+
g.on(ev, function(e) {
|
2586 |
+
v.trigger(e.type);
|
2587 |
+
});
|
2588 |
+
}
|
2589 |
+
g.show_next();
|
2590 |
+
},
|
2591 |
+
|
2592 |
+
/**
|
2593 |
+
* Previous item
|
2594 |
+
*/
|
2595 |
+
item_prev: function() {
|
2596 |
+
var g = this.get_item().get_group(true);
|
2597 |
+
var v = this;
|
2598 |
+
var ev = 'item-prev';
|
2599 |
+
var st = ['events', 'viewer', ev].join('_');
|
2600 |
+
if ( !g.get_status(st) ) {
|
2601 |
+
g.set_status(st);
|
2602 |
+
g.on(ev, function() {
|
2603 |
+
v.trigger(ev);
|
2604 |
+
});
|
2605 |
+
}
|
2606 |
+
g.show_prev();
|
2607 |
+
},
|
2608 |
+
|
2609 |
+
/**
|
2610 |
+
* Close viewer
|
2611 |
+
*/
|
2612 |
+
close: function() {
|
2613 |
+
//Deactivate
|
2614 |
+
this.set_active(false);
|
2615 |
+
var v = this;
|
2616 |
+
var thm = this.get_theme();
|
2617 |
+
thm.transition('unload')
|
2618 |
+
.always(function() {
|
2619 |
+
thm.transition('close', true).always(function() {
|
2620 |
+
//End processes
|
2621 |
+
v.reset();
|
2622 |
+
v.trigger('close');
|
2623 |
+
});
|
2624 |
+
})
|
2625 |
+
.fail(function() {
|
2626 |
+
thm.dom_get_tag('item', 'content').attr('style', '');
|
2627 |
+
});
|
2628 |
+
return false;
|
2629 |
+
}
|
2630 |
+
};
|
2631 |
+
|
2632 |
+
View.Viewer = Component.extend(Viewer);
|
2633 |
+
|
2634 |
+
/**
|
2635 |
+
* Content group
|
2636 |
+
* @param obj options Init options
|
2637 |
+
*/
|
2638 |
+
var Group = {
|
2639 |
+
/* Configuration */
|
2640 |
+
|
2641 |
+
_slug: 'group',
|
2642 |
+
_reciprocal: true,
|
2643 |
+
_refs: {
|
2644 |
+
'current': 'Content_Item'
|
2645 |
+
},
|
2646 |
+
|
2647 |
+
/* References */
|
2648 |
+
|
2649 |
+
current: null,
|
2650 |
+
|
2651 |
+
/* Properties */
|
2652 |
+
|
2653 |
+
/**
|
2654 |
+
* Selector for getting group items
|
2655 |
+
* @var string
|
2656 |
+
*/
|
2657 |
+
selector: null,
|
2658 |
+
|
2659 |
+
/* Methods */
|
2660 |
+
|
2661 |
+
/* Init */
|
2662 |
+
|
2663 |
+
register_hooks: function() {
|
2664 |
+
var t = this;
|
2665 |
+
this.on(['item-prev', 'item-next'], function() {
|
2666 |
+
t.trigger('item-change');
|
2667 |
+
});
|
2668 |
+
},
|
2669 |
+
|
2670 |
+
/* Properties */
|
2671 |
+
|
2672 |
+
/**
|
2673 |
+
* Retrieve selector for group items
|
2674 |
+
* @return string Group items selector
|
2675 |
+
*/
|
2676 |
+
get_selector: function() {
|
2677 |
+
if ( this.util.is_empty(this.selector) ) {
|
2678 |
+
//Build selector
|
2679 |
+
this.selector = this.util.format('a[%s="%s"]', this.dom_get_attribute(), this.get_id());
|
2680 |
+
}
|
2681 |
+
return this.selector;
|
2682 |
+
},
|
2683 |
+
|
2684 |
+
/**
|
2685 |
+
* Retrieve group items
|
2686 |
+
*/
|
2687 |
+
get_items: function() {
|
2688 |
+
var items = ( !this.util.is_empty(this.get_id()) ) ? $(this.get_selector()) : this.get_current().dom_get();
|
2689 |
+
return items;
|
2690 |
+
},
|
2691 |
+
|
2692 |
+
/**
|
2693 |
+
* Retrieve item at specified index
|
2694 |
+
* If no index specified, first item is returned
|
2695 |
+
* @param int idx Index of item to return
|
2696 |
+
* @return Content_Item Item
|
2697 |
+
*/
|
2698 |
+
get_item: function(idx) {
|
2699 |
+
//Validation
|
2700 |
+
if ( !this.util.is_int(idx) ) {
|
2701 |
+
idx = 0;
|
2702 |
+
}
|
2703 |
+
//Retrieve all items
|
2704 |
+
var items = this.get_items();
|
2705 |
+
//Validate index
|
2706 |
+
var max = this.get_size() - 1;
|
2707 |
+
if ( idx > max ) {
|
2708 |
+
idx = max;
|
2709 |
+
}
|
2710 |
+
//Return specified item
|
2711 |
+
return items.get(idx);
|
2712 |
+
},
|
2713 |
+
|
2714 |
+
/**
|
2715 |
+
* Retrieve (zero-based) position of specified item in group
|
2716 |
+
* @param Content_Item item Item to locate in group
|
2717 |
+
* @return int Index position of item in group (-1 if item not in group)
|
2718 |
+
*/
|
2719 |
+
get_pos: function(item) {
|
2720 |
+
if ( this.util.is_empty(item) ) {
|
2721 |
+
//Get current item
|
2722 |
+
item = this.get_current();
|
2723 |
+
}
|
2724 |
+
return ( this.util.is_type(item, View.Content_Item) ) ? this.get_items().index(item.dom_get()) : -1;
|
2725 |
+
},
|
2726 |
+
|
2727 |
+
/**
|
2728 |
+
* Retrieve current item
|
2729 |
+
* @return Content_Item Current item
|
2730 |
+
*/
|
2731 |
+
get_current: function() {
|
2732 |
+
//Sanitize
|
2733 |
+
if ( !this.util.is_empty(this.current) && !this.util.is_type(this.current, View.Content_Item) ) {
|
2734 |
+
this.current = null;
|
2735 |
+
}
|
2736 |
+
return this.current;
|
2737 |
+
},
|
2738 |
+
|
2739 |
+
/**
|
2740 |
+
* Sets current group item
|
2741 |
+
* @param Content_Item item Item to set as current
|
2742 |
+
*/
|
2743 |
+
set_current: function(item) {
|
2744 |
+
//Validate
|
2745 |
+
if ( this.util.is_type(item, View.Content_Item) ) {
|
2746 |
+
//Set current item
|
2747 |
+
this.current = item;
|
2748 |
+
}
|
2749 |
+
},
|
2750 |
+
|
2751 |
+
get_next: function(item) {
|
2752 |
+
//Validate
|
2753 |
+
if ( !this.util.is_type(item, View.Content_Item) ) {
|
2754 |
+
item = this.get_current();
|
2755 |
+
}
|
2756 |
+
if ( this.get_size() == 1 ) {
|
2757 |
+
return item;
|
2758 |
+
}
|
2759 |
+
var next = null;
|
2760 |
+
var pos = this.get_pos(item);
|
2761 |
+
if ( pos != -1 ) {
|
2762 |
+
pos = ( pos + 1 < this.get_size() ) ? pos + 1 : 0;
|
2763 |
+
if ( 0 != pos || item.get_viewer().get_attribute('loop') ) {
|
2764 |
+
next = this.get_item(pos);
|
2765 |
+
}
|
2766 |
+
}
|
2767 |
+
return next;
|
2768 |
+
},
|
2769 |
+
|
2770 |
+
get_prev: function(item) {
|
2771 |
+
//Validate
|
2772 |
+
if ( !this.util.is_type(item, View.Content_Item) ) {
|
2773 |
+
item = this.get_current();
|
2774 |
+
}
|
2775 |
+
if ( this.get_size() == 1 ) {
|
2776 |
+
return item;
|
2777 |
+
}
|
2778 |
+
var prev = null;
|
2779 |
+
var pos = this.get_pos(item);
|
2780 |
+
if ( pos != -1 && ( 0 != pos || item.get_viewer().get_attribute('loop') ) ) {
|
2781 |
+
if ( pos == 0 ) {
|
2782 |
+
pos = this.get_size();
|
2783 |
+
}
|
2784 |
+
pos -= 1;
|
2785 |
+
prev = this.get_item(pos);
|
2786 |
+
}
|
2787 |
+
return prev;
|
2788 |
+
},
|
2789 |
+
|
2790 |
+
show_next: function(item) {
|
2791 |
+
if ( this.get_size() > 1 ) {
|
2792 |
+
//Retrieve item
|
2793 |
+
var next = this.get_next(item);
|
2794 |
+
if ( !next ) {
|
2795 |
+
if ( !this.util.is_type(item, View.Content_Item) ) {
|
2796 |
+
item = this.get_current();
|
2797 |
+
}
|
2798 |
+
item.get_viewer().close();
|
2799 |
+
}
|
2800 |
+
var i = this.get_parent().get_item(next);
|
2801 |
+
//Update current item
|
2802 |
+
this.set_current(i);
|
2803 |
+
//Show item
|
2804 |
+
i.show();
|
2805 |
+
//Fire event
|
2806 |
+
this.trigger('item-next');
|
2807 |
+
}
|
2808 |
+
},
|
2809 |
+
|
2810 |
+
show_prev: function(item) {
|
2811 |
+
if ( this.get_size() > 1 ) {
|
2812 |
+
//Retrieve item
|
2813 |
+
var prev = this.get_prev(item);
|
2814 |
+
if ( !prev ) {
|
2815 |
+
if ( !this.util.is_type(item, View.Content_Item) ) {
|
2816 |
+
item = this.get_current();
|
2817 |
+
}
|
2818 |
+
item.get_viewer().close();
|
2819 |
+
}
|
2820 |
+
var i = this.get_parent().get_item(prev);
|
2821 |
+
//Update current item
|
2822 |
+
this.set_current(i);
|
2823 |
+
//Show item
|
2824 |
+
i.show();
|
2825 |
+
//Fire event
|
2826 |
+
this.trigger('item-prev');
|
2827 |
+
}
|
2828 |
+
},
|
2829 |
+
|
2830 |
+
/**
|
2831 |
+
* Retrieve total number of items in group
|
2832 |
+
* @return int Number of items in group
|
2833 |
+
*/
|
2834 |
+
get_size: function() {
|
2835 |
+
return this.get_items().length;
|
2836 |
+
},
|
2837 |
+
|
2838 |
+
is_single: function() {
|
2839 |
+
return ( this.get_size() == 1 );
|
2840 |
+
}
|
2841 |
+
};
|
2842 |
+
|
2843 |
+
View.Group = Component.extend(Group);
|
2844 |
+
|
2845 |
+
/**
|
2846 |
+
* Content Handler
|
2847 |
+
* @param obj options Init options
|
2848 |
+
*/
|
2849 |
+
var Content_Handler = {
|
2850 |
+
|
2851 |
+
/* Configuration */
|
2852 |
+
|
2853 |
+
_slug: 'content_handler',
|
2854 |
+
_refs: {
|
2855 |
+
'item': 'Content_Item'
|
2856 |
+
},
|
2857 |
+
|
2858 |
+
/* References */
|
2859 |
+
|
2860 |
+
item: null,
|
2861 |
+
|
2862 |
+
/* Properties */
|
2863 |
+
|
2864 |
+
/**
|
2865 |
+
* Raw layout template
|
2866 |
+
* @var string
|
2867 |
+
*/
|
2868 |
+
template: '',
|
2869 |
+
|
2870 |
+
/* Methods */
|
2871 |
+
|
2872 |
+
/* Item */
|
2873 |
+
|
2874 |
+
/**
|
2875 |
+
* Check if item instance set for type
|
2876 |
+
* @uses get_item()
|
2877 |
+
* @uses clear_item() to remove invalid item values
|
2878 |
+
* @return bool TRUE if valid item set, FALSE otherwise
|
2879 |
+
*/
|
2880 |
+
has_item: function() {
|
2881 |
+
return ( this.util.is_empty(this.get_item()) ) ? false : true;
|
2882 |
+
},
|
2883 |
+
|
2884 |
+
/**
|
2885 |
+
* Retrieve item instance set on type
|
2886 |
+
* @uses get_component()
|
2887 |
+
* @return mixed Content_Item if valid item set, NULL otherwise
|
2888 |
+
*/
|
2889 |
+
get_item: function() {
|
2890 |
+
return this.get_component('item', true, false);
|
2891 |
+
},
|
2892 |
+
|
2893 |
+
/**
|
2894 |
+
* Set item instance for type
|
2895 |
+
* Items are only meant to be set/used while item is being processed
|
2896 |
+
* @uses set_component()
|
2897 |
+
* @param Content_Item item Item instance
|
2898 |
+
* @return obj|null Item instance if item successfully set, NULL otherwise
|
2899 |
+
*/
|
2900 |
+
set_item: function(item) {
|
2901 |
+
//Set reference
|
2902 |
+
var r = this.set_component('item', item);
|
2903 |
+
return r;
|
2904 |
+
},
|
2905 |
+
|
2906 |
+
/**
|
2907 |
+
* Clear item instance from type
|
2908 |
+
* Sets value to NULL
|
2909 |
+
*/
|
2910 |
+
clear_item: function() {
|
2911 |
+
this.item = null;
|
2912 |
+
},
|
2913 |
+
|
2914 |
+
/* Evaluation */
|
2915 |
+
|
2916 |
+
/**
|
2917 |
+
* Check if item matches content handler
|
2918 |
+
* @param object item Content_Item instance to check for type match
|
2919 |
+
* @return bool TRUE if type matches, FALSE otherwise
|
2920 |
+
*/
|
2921 |
+
match: function(item) {
|
2922 |
+
//Validate
|
2923 |
+
var attr = 'match';
|
2924 |
+
var m = this.get_attribute(attr);
|
2925 |
+
//Stop processing types with no matching algorithm
|
2926 |
+
if ( !this.util.is_empty(m) ) {
|
2927 |
+
//Process regex patterns
|
2928 |
+
|
2929 |
+
//String-based
|
2930 |
+
if ( this.util.is_string(m) ) {
|
2931 |
+
//Create new regexp object
|
2932 |
+
m = new RegExp(m, "i");
|
2933 |
+
this.set_attribute(attr, m);
|
2934 |
+
}
|
2935 |
+
//RegExp based
|
2936 |
+
if ( this.util.is_type(m, RegExp) ) {
|
2937 |
+
return m.test(item.get_uri());
|
2938 |
+
}
|
2939 |
+
//Process function
|
2940 |
+
if ( this.util.is_func(m) ) {
|
2941 |
+
return ( m.call(this, item) ) ? true : false;
|
2942 |
+
}
|
2943 |
+
}
|
2944 |
+
//Default
|
2945 |
+
return false;
|
2946 |
+
},
|
2947 |
+
|
2948 |
+
/* Processing/Output */
|
2949 |
+
|
2950 |
+
/**
|
2951 |
+
* Render output to display item
|
2952 |
+
* @param Content_Item item Item to render output for
|
2953 |
+
* @return obj jQuery.Promise that is resolved when item is rendered
|
2954 |
+
*/
|
2955 |
+
render: function(item) {
|
2956 |
+
var dfr = $.Deferred();
|
2957 |
+
//Validate
|
2958 |
+
var ret = this.call_attribute('render', item);
|
2959 |
+
if ( this.util.is_promise(ret) ) {
|
2960 |
+
ret.done(function(output) {
|
2961 |
+
dfr.resolve(output);
|
2962 |
+
});
|
2963 |
+
} else {
|
2964 |
+
//String format
|
2965 |
+
if ( this.util.is_string(ret) ) {
|
2966 |
+
ret = this.util.format(ret, item.get_uri());
|
2967 |
+
}
|
2968 |
+
//Resolve deferred immediately
|
2969 |
+
dfr.resolve(ret);
|
2970 |
+
}
|
2971 |
+
return dfr.promise();
|
2972 |
+
}
|
2973 |
+
};
|
2974 |
+
|
2975 |
+
View.Content_Handler = Component.extend(Content_Handler);
|
2976 |
+
|
2977 |
+
/**
|
2978 |
+
* Content Item
|
2979 |
+
* @param obj options Init options
|
2980 |
+
*/
|
2981 |
+
var Content_Item = {
|
2982 |
+
/* Configuration */
|
2983 |
+
|
2984 |
+
_slug: 'content_item',
|
2985 |
+
_reciprocal: true,
|
2986 |
+
_refs: {
|
2987 |
+
'viewer': 'Viewer',
|
2988 |
+
'group': 'Group',
|
2989 |
+
'type': 'Content_Handler'
|
2990 |
+
},
|
2991 |
+
_containers: ['group'],
|
2992 |
+
|
2993 |
+
_attr_default: {
|
2994 |
+
source: null,
|
2995 |
+
permalink: null,
|
2996 |
+
dimensions: null,
|
2997 |
+
title: '',
|
2998 |
+
group: null,
|
2999 |
+
internal: false,
|
3000 |
+
output: null
|
3001 |
+
},
|
3002 |
+
|
3003 |
+
/* References */
|
3004 |
+
|
3005 |
+
group: null,
|
3006 |
+
viewer: null,
|
3007 |
+
type: null,
|
3008 |
+
|
3009 |
+
/* Properties */
|
3010 |
+
|
3011 |
+
data: null,
|
3012 |
+
|
3013 |
+
/* Init */
|
3014 |
+
|
3015 |
+
_c: function(el) {
|
3016 |
+
//Save element to instance
|
3017 |
+
this.dom_set(el);
|
3018 |
+
//Default initialization
|
3019 |
+
this._super();
|
3020 |
+
},
|
3021 |
+
|
3022 |
+
/* Methods */
|
3023 |
+
|
3024 |
+
/*-** Attributes **-*/
|
3025 |
+
|
3026 |
+
/**
|
3027 |
+
* Build default attributes
|
3028 |
+
* Populates attributes with asset properties (attachments)
|
3029 |
+
* Overrides super class method
|
3030 |
+
* @uses Component.init_default_attributes()
|
3031 |
+
*/
|
3032 |
+
init_default_attributes: function() {
|
3033 |
+
this._super();
|
3034 |
+
//Add asset properties
|
3035 |
+
var d = this.dom_get();
|
3036 |
+
var key = d.attr('href') || null;
|
3037 |
+
var assets = this.get_parent().assets || null;
|
3038 |
+
//Merge asset data with default attributes
|
3039 |
+
if ( this.util.is_string(key) ) {
|
3040 |
+
var attrs = [{}, this._attr_default, {'permalink': key}];
|
3041 |
+
if ( this.util.is_obj(assets) ) {
|
3042 |
+
var t = this;
|
3043 |
+
var get_assets = function(key, raw) {
|
3044 |
+
var ret = {};
|
3045 |
+
if ( key in assets && t.util.is_obj(assets[key]) ) {
|
3046 |
+
var ret = assets[key];
|
3047 |
+
if ( t.util.is_string(raw) ) {
|
3048 |
+
var e = '_entries';
|
3049 |
+
if ( !( e in ret ) || -1 == $.inArray(raw, ret[e]) ) {
|
3050 |
+
ret = {};
|
3051 |
+
}
|
3052 |
+
}
|
3053 |
+
}
|
3054 |
+
return ret;
|
3055 |
+
};
|
3056 |
+
var asset = get_assets(key);
|
3057 |
+
if ( this.util.is_empty(asset) && ( kpos = key.indexOf('?') ) && kpos != -1 ) {
|
3058 |
+
var key_base = key.substr(0, kpos);
|
3059 |
+
asset = get_assets(key_base, key);
|
3060 |
+
}
|
3061 |
+
if ( !this.util.is_empty(asset) ) {
|
3062 |
+
attrs.push(asset);
|
3063 |
+
}
|
3064 |
+
}
|
3065 |
+
this._attr_default = $.extend.apply(this, attrs);
|
3066 |
+
}
|
3067 |
+
return this._attr_default;
|
3068 |
+
},
|
3069 |
+
|
3070 |
+
/*-** Properties **-*/
|
3071 |
+
|
3072 |
+
/**
|
3073 |
+
* Retrieve item output
|
3074 |
+
* Output generated based on content handler if not previously generated
|
3075 |
+
* @uses get_attribute() to retrieve cached output
|
3076 |
+
* @uses set_attribute() to cache generated output
|
3077 |
+
* @uses get_type() to retrieve item type
|
3078 |
+
* @uses Content_Handler.render() to generate item output
|
3079 |
+
* @return obj jQuery.Promise that is resolved when output is retrieved
|
3080 |
+
*/
|
3081 |
+
get_output: function() {
|
3082 |
+
var dfr = $.Deferred();
|
3083 |
+
//Check for cached output
|
3084 |
+
var ret = this.get_attribute('output');
|
3085 |
+
if ( this.util.is_string(ret) ) {
|
3086 |
+
dfr.resolve(ret);
|
3087 |
+
} else if ( this.has_type() ) {
|
3088 |
+
//Render output from scratch (if necessary)
|
3089 |
+
//Get item type
|
3090 |
+
var type = this.get_type();
|
3091 |
+
//Render type-based output
|
3092 |
+
var item = this;
|
3093 |
+
type.render(this).done(function(output) {
|
3094 |
+
//Cache output
|
3095 |
+
item.set_output(output);
|
3096 |
+
dfr.resolve(output);
|
3097 |
+
});
|
3098 |
+
} else {
|
3099 |
+
dfr.resolve('');
|
3100 |
+
}
|
3101 |
+
return dfr.promise();
|
3102 |
+
},
|
3103 |
+
|
3104 |
+
/**
|
3105 |
+
* Cache output for future retrieval
|
3106 |
+
* @uses set_attribute() to cache output
|
3107 |
+
*/
|
3108 |
+
set_output: function(out) {
|
3109 |
+
if ( this.util.is_string(out, false) ) {
|
3110 |
+
this.set_attribute('output', out);
|
3111 |
+
}
|
3112 |
+
},
|
3113 |
+
|
3114 |
+
/**
|
3115 |
+
* Retrieve item output
|
3116 |
+
* Alias for `get_output()`
|
3117 |
+
* @return jQuery.Promise Deferred that is resolved when content is retrieved
|
3118 |
+
*/
|
3119 |
+
get_content: function() {
|
3120 |
+
return this.get_output();
|
3121 |
+
},
|
3122 |
+
|
3123 |
+
/**
|
3124 |
+
* Retrieve item URI
|
3125 |
+
* @param string mode (optional) Which URI should be retrieved
|
3126 |
+
* > source: Media source
|
3127 |
+
* > permalink: Item permalink
|
3128 |
+
* @return string Item URI
|
3129 |
+
*/
|
3130 |
+
get_uri: function(mode) {
|
3131 |
+
//Validate
|
3132 |
+
if ( $.inArray(mode ,['source', 'permalink']) == -1 ) {
|
3133 |
+
mode = 'source';
|
3134 |
+
}
|
3135 |
+
//Retrieve URI
|
3136 |
+
var ret = this.get_attribute(mode);
|
3137 |
+
if ( !this.util.is_string(ret) ) {
|
3138 |
+
ret = ( 'source' == mode ) ? this.get_attribute('permalink') : '';
|
3139 |
+
}
|
3140 |
+
return ret;
|
3141 |
+
},
|
3142 |
+
|
3143 |
+
/**
|
3144 |
+
* Retrieve item title
|
3145 |
+
*/
|
3146 |
+
get_title: function() {
|
3147 |
+
var prop = 'title';
|
3148 |
+
var prop_cached = prop + '_cached';
|
3149 |
+
//Check for cached value
|
3150 |
+
if ( this.has_attribute(prop_cached) ) {
|
3151 |
+
return this.get_attribute(prop_cached, '');
|
3152 |
+
}
|
3153 |
+
|
3154 |
+
var title = '';
|
3155 |
+
var sel_cap = '.wp-caption-text';
|
3156 |
+
//Generate title from DOM values
|
3157 |
+
var dom = this.dom_get();
|
3158 |
+
|
3159 |
+
//Standalone link
|
3160 |
+
if ( dom.length && !this.in_gallery() ) {
|
3161 |
+
//Link title
|
3162 |
+
title = dom.attr(prop);
|
3163 |
+
|
3164 |
+
//Caption
|
3165 |
+
if ( !title ) {
|
3166 |
+
title = dom.siblings(sel_cap).html();
|
3167 |
+
}
|
3168 |
+
}
|
3169 |
+
|
3170 |
+
//Saved attributes
|
3171 |
+
if ( !title ) {
|
3172 |
+
var props = ['caption', 'title'];
|
3173 |
+
for ( var x = 0; x < props.length; x++ ) {
|
3174 |
+
title = this.get_attribute(props[x], '');
|
3175 |
+
if ( !this.util.is_empty(title) ) {
|
3176 |
+
break;
|
3177 |
+
}
|
3178 |
+
}
|
3179 |
+
}
|
3180 |
+
|
3181 |
+
//Fallbacks
|
3182 |
+
if ( !title && dom.length ) {
|
3183 |
+
//Alt attribute
|
3184 |
+
title = dom.find('img').first().attr('alt');
|
3185 |
+
|
3186 |
+
//Element text
|
3187 |
+
if ( !title ) {
|
3188 |
+
title = dom.text();
|
3189 |
+
}
|
3190 |
+
}
|
3191 |
+
|
3192 |
+
//Validate
|
3193 |
+
if ( !this.util.is_string(title, false) ) {
|
3194 |
+
title = '';
|
3195 |
+
}
|
3196 |
+
|
3197 |
+
//Cache retrieved value
|
3198 |
+
this.set_attribute(prop_cached, title);
|
3199 |
+
//Return value
|
3200 |
+
return title;
|
3201 |
+
},
|
3202 |
+
|
3203 |
+
/**
|
3204 |
+
* Retrieve item dimensions
|
3205 |
+
* @return obj Item `width` and `height` properties (px)
|
3206 |
+
*/
|
3207 |
+
get_dimensions: function() {
|
3208 |
+
return $.extend({'width': 0, 'height': 0}, this.get_attribute('dimensions'), {});
|
3209 |
+
},
|
3210 |
+
|
3211 |
+
/**
|
3212 |
+
* Save item data to instance
|
3213 |
+
* Item data is saved when rendered
|
3214 |
+
* @param mixed data Item data (property cleared if NULL)
|
3215 |
+
*/
|
3216 |
+
set_data: function(data) {
|
3217 |
+
this.data = data;
|
3218 |
+
},
|
3219 |
+
|
3220 |
+
/**
|
3221 |
+
* Determine gallery type
|
3222 |
+
* @return string|null Gallery type ID (NULL if item not in gallery)
|
3223 |
+
*/
|
3224 |
+
gallery_type: function() {
|
3225 |
+
var ret = null;
|
3226 |
+
var types = {
|
3227 |
+
'wp': '.gallery-icon',
|
3228 |
+
'ngg': '.ngg-gallery-thumbnail'
|
3229 |
+
};
|
3230 |
+
|
3231 |
+
var dom = this.dom_get();
|
3232 |
+
for ( var type in types ) {
|
3233 |
+
if ( dom.parent(types[type]).length > 0 ) {
|
3234 |
+
ret = type;
|
3235 |
+
break;
|
3236 |
+
}
|
3237 |
+
}
|
3238 |
+
return ret;
|
3239 |
+
},
|
3240 |
+
|
3241 |
+
/**
|
3242 |
+
* Check if current link is part of a gallery
|
3243 |
+
* @param string gType (optional) Gallery type to check for
|
3244 |
+
* @return bool TRUE if link is part of (specified) gallery (FALSE otherwise)
|
3245 |
+
*/
|
3246 |
+
in_gallery: function(gType) {
|
3247 |
+
var type = this.gallery_type();
|
3248 |
+
//No gallery
|
3249 |
+
if ( null == type ) {
|
3250 |
+
return false;
|
3251 |
+
}
|
3252 |
+
//Boolean check
|
3253 |
+
if ( !this.util.is_string(gType) ) {
|
3254 |
+
return true;
|
3255 |
+
}
|
3256 |
+
//Check for specific gallery type
|
3257 |
+
return ( gType == type ) ? true : false;
|
3258 |
+
},
|
3259 |
+
|
3260 |
+
/*-** Component References **-*/
|
3261 |
+
|
3262 |
+
/* Viewer */
|
3263 |
+
|
3264 |
+
get_viewer: function() {
|
3265 |
+
return this.get_component('viewer');
|
3266 |
+
},
|
3267 |
+
|
3268 |
+
/**
|
3269 |
+
* Sets item's viewer property
|
3270 |
+
* @uses View.get_viewer() to retrieve global viewer
|
3271 |
+
* @uses this.viewer to save item's viewer
|
3272 |
+
* @param string|View.Viewer v Viewer to set for item
|
3273 |
+
* > Item's viewer is reset if invalid viewer provided
|
3274 |
+
*/
|
3275 |
+
set_viewer: function(v) {
|
3276 |
+
return this.set_component('viewer', v);
|
3277 |
+
},
|
3278 |
+
|
3279 |
+
/* Group */
|
3280 |
+
|
3281 |
+
/**
|
3282 |
+
* Retrieve item's group
|
3283 |
+
* @param bool set_current (optional) Sets item as current item in group (Default: FALSE)
|
3284 |
+
* @return View.Group|bool Group reference item belongs to (FALSE if no group)
|
3285 |
+
*/
|
3286 |
+
get_group: function(set_current) {
|
3287 |
+
var prop = 'group';
|
3288 |
+
//Check if group reference already set
|
3289 |
+
var g = this.get_component(prop, true, false, false);
|
3290 |
+
if ( g ) {
|
3291 |
+
} else {
|
3292 |
+
//Set empty group if no group exists
|
3293 |
+
g = this.set_component(prop, new View.Group());
|
3294 |
+
set_current = true;
|
3295 |
+
}
|
3296 |
+
if ( !!set_current ) {
|
3297 |
+
g.set_current(this);
|
3298 |
+
}
|
3299 |
+
return g;
|
3300 |
+
},
|
3301 |
+
|
3302 |
+
/**
|
3303 |
+
* Sets item's group property
|
3304 |
+
* @uses View.get_group() to retrieve global group
|
3305 |
+
* @uses this.group to set item's group
|
3306 |
+
* @param string|View.Group g Group to set for item
|
3307 |
+
* > Item's group is reset if invalid group provided
|
3308 |
+
*/
|
3309 |
+
set_group: function(g) {
|
3310 |
+
//If group ID set, get object reference
|
3311 |
+
if ( this.util.is_string(g) ) {
|
3312 |
+
g = this.get_parent().get_group(g);
|
3313 |
+
}
|
3314 |
+
|
3315 |
+
//Set (or clear) group property
|
3316 |
+
this.group = ( this.util.is_type(g, View.Group) ) ? g : false;
|
3317 |
+
},
|
3318 |
+
|
3319 |
+
/* Content Handler */
|
3320 |
+
|
3321 |
+
/**
|
3322 |
+
* Retrieve item type
|
3323 |
+
* @uses get_component() to retrieve saved reference to Content_Handler instance
|
3324 |
+
* @uses View.get_content_handler() to determine item content handler (if necessary)
|
3325 |
+
* @return Content_Handler|null Content Handler of item (NULL no valid type exists)
|
3326 |
+
*/
|
3327 |
+
get_type: function() {
|
3328 |
+
var t = this.get_component('type', false, false, false);
|
3329 |
+
if ( !t ) {
|
3330 |
+
t = this.set_type(this.get_parent().get_content_handler(this));
|
3331 |
+
}
|
3332 |
+
return t;
|
3333 |
+
},
|
3334 |
+
|
3335 |
+
/**
|
3336 |
+
* Save content handler reference
|
3337 |
+
* @uses set_component() to save type reference
|
3338 |
+
* @return Content_Handler|null Saved content handler (NULL if invalid)
|
3339 |
+
*/
|
3340 |
+
set_type: function(type) {
|
3341 |
+
return this.set_component('type', type);
|
3342 |
+
},
|
3343 |
+
|
3344 |
+
/**
|
3345 |
+
* Check if content handler exists for item
|
3346 |
+
* @return bool TRUE if content handler exists, FALSE otherwise
|
3347 |
+
*/
|
3348 |
+
has_type: function() {
|
3349 |
+
var ret = !this.util.is_empty(this.get_type());
|
3350 |
+
return ret;
|
3351 |
+
},
|
3352 |
+
|
3353 |
+
/* Actions */
|
3354 |
+
|
3355 |
+
/**
|
3356 |
+
* Display item in viewer
|
3357 |
+
* @uses get_viewer() to retrieve viewer instance for item
|
3358 |
+
* @uses Viewer.show() to display item in viewer
|
3359 |
+
* @param obj options (optional) Options
|
3360 |
+
*/
|
3361 |
+
show: function(options) {
|
3362 |
+
//Validate content handler
|
3363 |
+
if ( !this.has_type() ) {
|
3364 |
+
return false;
|
3365 |
+
}
|
3366 |
+
//Set display options
|
3367 |
+
this.set_attribute('options_show', options);
|
3368 |
+
//Retrieve viewer
|
3369 |
+
var v = this.get_viewer();
|
3370 |
+
//Load item
|
3371 |
+
var ret = v.show(this);
|
3372 |
+
return ret;
|
3373 |
+
},
|
3374 |
+
|
3375 |
+
reset: function() {
|
3376 |
+
this.set_attribute('options_show', null);
|
3377 |
+
}
|
3378 |
+
};
|
3379 |
+
|
3380 |
+
View.Content_Item = Component.extend(Content_Item);
|
3381 |
+
|
3382 |
+
/**
|
3383 |
+
* Modeled Component
|
3384 |
+
*/
|
3385 |
+
var Modeled_Component = {
|
3386 |
+
|
3387 |
+
_slug: 'modeled_component',
|
3388 |
+
|
3389 |
+
/* Methods */
|
3390 |
+
|
3391 |
+
/* Attributes */
|
3392 |
+
|
3393 |
+
/**
|
3394 |
+
* Retrieve attribute
|
3395 |
+
* Gives priority to model values
|
3396 |
+
* @see Component.get_attribute()
|
3397 |
+
* @param string key Attribute to retrieve
|
3398 |
+
* @param mixed def (optional) Default value (Default: NULL)
|
3399 |
+
* @param bool check_model (optional) Check model for value (Default: TRUE)
|
3400 |
+
* @param bool enforce_type (optional) Return value data type should match default value data type (Default: TRUE)
|
3401 |
+
* @return mixed Attribute value
|
3402 |
+
*/
|
3403 |
+
get_attribute: function(key, def, check_model, enforce_type) {
|
3404 |
+
//Validate
|
3405 |
+
if ( !this.util.is_string(key) ) {
|
3406 |
+
//Invalid requests sent straight to super method
|
3407 |
+
return this._super(key, def, enforce_type);
|
3408 |
+
}
|
3409 |
+
if ( !this.util.is_bool(check_model) ) {
|
3410 |
+
check_model = true;
|
3411 |
+
}
|
3412 |
+
var ret = null;
|
3413 |
+
//Check model for attribute
|
3414 |
+
if ( check_model ) {
|
3415 |
+
var m = this.get_ancestor(key, false);
|
3416 |
+
if ( this.util.in_obj(m, key) ) {
|
3417 |
+
ret = m[key];
|
3418 |
+
}
|
3419 |
+
}
|
3420 |
+
//Check standard attributes as fallback
|
3421 |
+
if ( null == ret ) {
|
3422 |
+
ret = this._super(key, def, enforce_type);
|
3423 |
+
}
|
3424 |
+
return ret;
|
3425 |
+
},
|
3426 |
+
|
3427 |
+
/**
|
3428 |
+
* Set attribute value
|
3429 |
+
* Gives priority to model values
|
3430 |
+
* @see Component.set_attribute()
|
3431 |
+
* @param string key Attribute to set
|
3432 |
+
* @param mixed val Value to set for attribute
|
3433 |
+
* @param bool|obj use_model (optional) Set the value on the model (Default: TRUE)
|
3434 |
+
* > bool: Set attribute on current model (TRUE) or as standard attribute (FALSE)
|
3435 |
+
* > obj: Model object to set attribute on
|
3436 |
+
* @return mixed Attribute value
|
3437 |
+
*/
|
3438 |
+
set_attribute: function(key, val, use_model) {
|
3439 |
+
//Validate
|
3440 |
+
if ( ( !this.util.is_string(key) ) || !this.util.is_set(val) ) {
|
3441 |
+
return false;
|
3442 |
+
}
|
3443 |
+
if ( !this.util.is_bool(use_model) && !this.util.is_obj(use_model) ) {
|
3444 |
+
use_model = true;
|
3445 |
+
}
|
3446 |
+
//Determine where to set attribute
|
3447 |
+
if ( !!use_model ) {
|
3448 |
+
var model = this.util.is_obj(use_model) ? use_model : this.get_model();
|
3449 |
+
|
3450 |
+
//Set attribute in model
|
3451 |
+
model[key] = val;
|
3452 |
+
} else {
|
3453 |
+
//Set as standard attribute
|
3454 |
+
this._super(key, val);
|
3455 |
+
}
|
3456 |
+
return val;
|
3457 |
+
},
|
3458 |
+
|
3459 |
+
|
3460 |
+
/* Model */
|
3461 |
+
|
3462 |
+
/**
|
3463 |
+
* Retrieve Template model
|
3464 |
+
* @return obj Model (Default: Empty object)
|
3465 |
+
*/
|
3466 |
+
get_model: function() {
|
3467 |
+
var m = this.get_attribute('model', null, false);
|
3468 |
+
if ( !this.util.is_obj(m) ) {
|
3469 |
+
//Set default value
|
3470 |
+
m = {};
|
3471 |
+
this.set_attribute('model', m, false);
|
3472 |
+
}
|
3473 |
+
return m;
|
3474 |
+
},
|
3475 |
+
|
3476 |
+
|
3477 |
+
/**
|
3478 |
+
* Check if instance has model
|
3479 |
+
* @return bool TRUE if model is set, FALSE otherwise
|
3480 |
+
*/
|
3481 |
+
has_model: function() {
|
3482 |
+
return ( this.util.is_empty( this.get_model() ) ) ? false : true;
|
3483 |
+
},
|
3484 |
+
|
3485 |
+
|
3486 |
+
|
3487 |
+
/**
|
3488 |
+
* Check if specified attribute exists in model
|
3489 |
+
* @param string key Attribute to check for
|
3490 |
+
* @return bool TRUE if attribute exists, FALSE otherwise
|
3491 |
+
*/
|
3492 |
+
in_model: function(key) {
|
3493 |
+
return ( this.util.in_obj(this.get_model(), key) ) ? true : false;
|
3494 |
+
},
|
3495 |
+
|
3496 |
+
/**
|
3497 |
+
* Retrieve all ancestor models
|
3498 |
+
* @param bool inc_current (optional) Include current model in list (Default: FALSE)
|
3499 |
+
* @return array Theme ancestor models (Closest parent first)
|
3500 |
+
*/
|
3501 |
+
get_ancestors: function(inc_current) {
|
3502 |
+
var ret = [];
|
3503 |
+
var m = this.get_model();
|
3504 |
+
while ( this.util.is_obj(m) ) {
|
3505 |
+
ret.push(m);
|
3506 |
+
m = ( this.util.in_obj(m, 'parent') && this.util.is_obj(m.parent) ) ? m.parent : null;
|
3507 |
+
}
|
3508 |
+
//Remove current model from list
|
3509 |
+
if ( !inc_current ) {
|
3510 |
+
ret.shift();
|
3511 |
+
}
|
3512 |
+
return ret;
|
3513 |
+
},
|
3514 |
+
|
3515 |
+
/**
|
3516 |
+
* Retrieve first ancestor of current theme with specified attribute
|
3517 |
+
* > Current model is also evaluated
|
3518 |
+
* @param string attr Attribute to search ancestors for
|
3519 |
+
* @param bool safe_mode (optional) Return current model if no matching ancestor found (Default: TRUE)
|
3520 |
+
* @return obj Theme ancestor (Default: Current theme model)
|
3521 |
+
*/
|
3522 |
+
get_ancestor: function(attr, safe_mode) {
|
3523 |
+
//Validate
|
3524 |
+
if ( !this.util.is_string(attr) ) {
|
3525 |
+
return false;
|
3526 |
+
}
|
3527 |
+
if ( !this.util.is_bool(safe_mode) ) {
|
3528 |
+
safe_mode = true;
|
3529 |
+
}
|
3530 |
+
var mcurr;
|
3531 |
+
var m = mcurr = this.get_model();
|
3532 |
+
var found = false;
|
3533 |
+
while ( this.util.is_obj(m) ) {
|
3534 |
+
//Check if attribute exists in model
|
3535 |
+
if ( this.util.in_obj(m, attr) && !this.util.is_empty(m[attr]) ) {
|
3536 |
+
found = true;
|
3537 |
+
break;
|
3538 |
+
}
|
3539 |
+
//Get next model
|
3540 |
+
m = ( this.util.in_obj(m, 'parent') ) ? m['parent'] : null;
|
3541 |
+
}
|
3542 |
+
if ( !found ) {
|
3543 |
+
if ( safe_mode ) {
|
3544 |
+
//Use current model as fallback
|
3545 |
+
if ( this.util.is_empty(m) ) {
|
3546 |
+
m = mcurr;
|
3547 |
+
}
|
3548 |
+
//Add attribute to object
|
3549 |
+
if ( !this.util.in_obj(m, attr) ) {
|
3550 |
+
m[attr] = null;
|
3551 |
+
}
|
3552 |
+
} else {
|
3553 |
+
m = null;
|
3554 |
+
}
|
3555 |
+
}
|
3556 |
+
return m;
|
3557 |
+
}
|
3558 |
+
|
3559 |
+
};
|
3560 |
+
|
3561 |
+
Modeled_Component = Component.extend(Modeled_Component);
|
3562 |
+
|
3563 |
+
/**
|
3564 |
+
* Theme
|
3565 |
+
*/
|
3566 |
+
var Theme = {
|
3567 |
+
|
3568 |
+
/* Configuration */
|
3569 |
+
|
3570 |
+
_slug: 'theme',
|
3571 |
+
_refs: {
|
3572 |
+
'viewer': 'Viewer',
|
3573 |
+
'template': 'Template'
|
3574 |
+
},
|
3575 |
+
_models: {},
|
3576 |
+
|
3577 |
+
_containers: ['viewer'],
|
3578 |
+
|
3579 |
+
_attr_default: {
|
3580 |
+
template: null,
|
3581 |
+
model: null
|
3582 |
+
},
|
3583 |
+
|
3584 |
+
/* References */
|
3585 |
+
|
3586 |
+
viewer: null,
|
3587 |
+
template: null,
|
3588 |
+
|
3589 |
+
/* Methods */
|
3590 |
+
|
3591 |
+
/**
|
3592 |
+
* Custom constructor
|
3593 |
+
* @see Component._c()
|
3594 |
+
*/
|
3595 |
+
_c: function(id, attributes, viewer) {
|
3596 |
+
//Validate
|
3597 |
+
if ( arguments.length == 1 && this.util.is_type(arguments[0], View.Viewer) ) {
|
3598 |
+
viewer = arguments[0];
|
3599 |
+
id = null;
|
3600 |
+
}
|
3601 |
+
//Pass parameters to parent constructor
|
3602 |
+
this._super(id, attributes);
|
3603 |
+
|
3604 |
+
//Set viewer instance
|
3605 |
+
this.set_viewer(viewer);
|
3606 |
+
|
3607 |
+
//Set theme model
|
3608 |
+
this.set_model(id);
|
3609 |
+
},
|
3610 |
+
|
3611 |
+
/* Viewer */
|
3612 |
+
|
3613 |
+
get_viewer: function() {
|
3614 |
+
return this.get_component('viewer', false, true, false);
|
3615 |
+
},
|
3616 |
+
|
3617 |
+
/**
|
3618 |
+
* Sets theme's viewer property
|
3619 |
+
* @uses View.get_viewer() to retrieve global viewer
|
3620 |
+
* @uses this.viewer to save item's viewer
|
3621 |
+
* @param string|View.Viewer v Viewer to set for item
|
3622 |
+
* > Theme's viewer is reset if invalid viewer provided
|
3623 |
+
*/
|
3624 |
+
set_viewer: function(v) {
|
3625 |
+
return this.set_component('viewer', v);
|
3626 |
+
},
|
3627 |
+
|
3628 |
+
/* Template */
|
3629 |
+
|
3630 |
+
/**
|
3631 |
+
* Retrieve template instance
|
3632 |
+
* @return Template instance
|
3633 |
+
*/
|
3634 |
+
get_template: function() {
|
3635 |
+
//Get saved template
|
3636 |
+
var ret = this.get_component('template', true, false, false);
|
3637 |
+
//Template needs to be initialized
|
3638 |
+
if ( this.util.is_empty(ret) ) {
|
3639 |
+
//Pass model to Template instance
|
3640 |
+
var attr = { 'theme': this, 'model': this.get_model() };
|
3641 |
+
ret = this.set_component('template', new View.Template(attr));
|
3642 |
+
}
|
3643 |
+
return ret;
|
3644 |
+
},
|
3645 |
+
|
3646 |
+
/**
|
3647 |
+
* Retrieve tags from template
|
3648 |
+
* All tags will be retrieved by default
|
3649 |
+
* Specific tag/property instances can be retrieved as well
|
3650 |
+
* @see Template.get_tags()
|
3651 |
+
* @param string name (optional) Name of tags to retrieve
|
3652 |
+
* @param string prop (optional) Specific tag property to retrieve
|
3653 |
+
* @return array Tags in template
|
3654 |
+
*/
|
3655 |
+
get_tags: function(name, prop) {
|
3656 |
+
return this.get_template().get_tags(name, prop);
|
3657 |
+
},
|
3658 |
+
|
3659 |
+
/**
|
3660 |
+
* Retrieve tag DOM elements
|
3661 |
+
* @see Template.dom_get_tag()
|
3662 |
+
*/
|
3663 |
+
dom_get_tag: function(tag, prop) {
|
3664 |
+
return $(this.get_template().dom_get_tag(tag, prop));
|
3665 |
+
},
|
3666 |
+
|
3667 |
+
/* Model */
|
3668 |
+
|
3669 |
+
/**
|
3670 |
+
* Retrieve theme models
|
3671 |
+
* @return obj Theme models
|
3672 |
+
*/
|
3673 |
+
get_models: function() {
|
3674 |
+
return this._models;
|
3675 |
+
},
|
3676 |
+
|
3677 |
+
/**
|
3678 |
+
* Retrieve specified theme model
|
3679 |
+
* @param string id (optional) Theme model to retrieve
|
3680 |
+
* > Default model retrieved if ID is invalid/not set
|
3681 |
+
* @return obj Specified theme model
|
3682 |
+
*/
|
3683 |
+
get_model: function(id) {
|
3684 |
+
var ret = null;
|
3685 |
+
//Pass request to superclass method
|
3686 |
+
if ( !this.util.is_set(id) && this.util.is_obj( this.get_attribute('model', null, false) ) ) {
|
3687 |
+
ret = this._super();
|
3688 |
+
} else {
|
3689 |
+
//Retrieve matching theme model
|
3690 |
+
var models = this.get_models();
|
3691 |
+
if ( !this.util.is_string(id) ) {
|
3692 |
+
var id = this.get_parent().get_option('theme_default');
|
3693 |
+
}
|
3694 |
+
//Select first theme model if specified model is invalid
|
3695 |
+
if ( !this.util.in_obj(models, id) ) {
|
3696 |
+
id = $.map(models, function(v, key) { return key; })[0];
|
3697 |
+
}
|
3698 |
+
ret = models[id];
|
3699 |
+
}
|
3700 |
+
return ret;
|
3701 |
+
},
|
3702 |
+
|
3703 |
+
/**
|
3704 |
+
* Set model for current theme instance
|
3705 |
+
* @param string id (optional) Theme ID (Default theme retrieved if ID invalid)
|
3706 |
+
*/
|
3707 |
+
set_model: function(id) {
|
3708 |
+
this.set_attribute('model', this.get_model(id), false);
|
3709 |
+
//Set ID using model attributes (if necessary)
|
3710 |
+
if ( !this.check_id(true) ) {
|
3711 |
+
var m = this.get_model();
|
3712 |
+
if ( 'id' in m ) {
|
3713 |
+
this.set_id(m.id);
|
3714 |
+
}
|
3715 |
+
}
|
3716 |
+
},
|
3717 |
+
|
3718 |
+
/* Properties */
|
3719 |
+
|
3720 |
+
/**
|
3721 |
+
* Generate class names for DOM node
|
3722 |
+
* @param string rtype (optional) Return data type
|
3723 |
+
* > Default: array
|
3724 |
+
* > If string supplied: Joined classes delimited by parameter
|
3725 |
+
* @uses get_class() to generate class names
|
3726 |
+
* @uses Array.join() to convert class names array to string
|
3727 |
+
* @return array Class names
|
3728 |
+
*/
|
3729 |
+
get_classes: function(rtype) {
|
3730 |
+
//Build array of class names
|
3731 |
+
var cls = [];
|
3732 |
+
var thm = this;
|
3733 |
+
//Include theme parent's class name
|
3734 |
+
var models = this.get_ancestors(true);
|
3735 |
+
$.each(models, function(idx, model) {
|
3736 |
+
cls.push(thm.add_ns(model.id));
|
3737 |
+
});
|
3738 |
+
//Convert class names array to string
|
3739 |
+
if ( this.util.is_string(rtype) ) {
|
3740 |
+
cls = cls.join(rtype);
|
3741 |
+
}
|
3742 |
+
//Return class names
|
3743 |
+
return cls;
|
3744 |
+
},
|
3745 |
+
|
3746 |
+
/**
|
3747 |
+
* Get custom measurement
|
3748 |
+
* @param string attr Measurement to retrieve
|
3749 |
+
* @param obj def (optional) Default value
|
3750 |
+
* @return obj Attribute measurements
|
3751 |
+
*/
|
3752 |
+
get_measurement: function(attr, def) {
|
3753 |
+
var meas = null;
|
3754 |
+
//Validate
|
3755 |
+
if ( !this.util.is_string(attr) ) {
|
3756 |
+
return meas;
|
3757 |
+
}
|
3758 |
+
if ( !this.util.is_obj(def, false) ) {
|
3759 |
+
def = {};
|
3760 |
+
}
|
3761 |
+
//Manage cache
|
3762 |
+
var attr_cache = this.util.format('%s_cache', attr);
|
3763 |
+
var cache = this.get_attribute(attr_cache, {}, false);
|
3764 |
+
var status = '_status';
|
3765 |
+
var item = this.get_viewer().get_item();
|
3766 |
+
var w = $(window);
|
3767 |
+
//Check cache freshness
|
3768 |
+
if ( !( status in cache ) || !this.util.is_obj(cache[status]) || cache[status].width != w.width() || cache[status].height != w.height() ) {
|
3769 |
+
cache = {};
|
3770 |
+
}
|
3771 |
+
if ( this.util.is_empty(cache) ) {
|
3772 |
+
//Set status
|
3773 |
+
cache[status] = {
|
3774 |
+
'width': w.width(),
|
3775 |
+
'height': w.height(),
|
3776 |
+
'index': []
|
3777 |
+
};
|
3778 |
+
}
|
3779 |
+
//Retrieve cached values
|
3780 |
+
var pos = $.inArray(item, cache[status].index);
|
3781 |
+
if ( pos != -1 && pos in cache ) {
|
3782 |
+
meas = cache[pos];
|
3783 |
+
}
|
3784 |
+
//Generate measurement
|
3785 |
+
if ( !this.util.is_obj(meas) ) {
|
3786 |
+
//Get custom theme measurement
|
3787 |
+
meas = this.call_attribute(attr);
|
3788 |
+
if ( !this.util.is_obj(meas) ) {
|
3789 |
+
//Retrieve fallback value
|
3790 |
+
meas = this.get_measurement_default(attr);
|
3791 |
+
}
|
3792 |
+
}
|
3793 |
+
//Normalize measurement
|
3794 |
+
meas = ( this.util.is_obj(meas) ) ? $.extend({}, def, meas) : def;
|
3795 |
+
//Cache measurement
|
3796 |
+
pos = cache[status].index.push(item) - 1;
|
3797 |
+
cache[pos] = meas;
|
3798 |
+
this.set_attribute(attr_cache, cache, false);
|
3799 |
+
//Return measurement (copy)
|
3800 |
+
return $.extend({}, meas);
|
3801 |
+
},
|
3802 |
+
|
3803 |
+
/**
|
3804 |
+
* Get default measurement using attribute's default handler
|
3805 |
+
* @param string attr Measurement attribute
|
3806 |
+
* @return obj Measurement values
|
3807 |
+
*/
|
3808 |
+
get_measurement_default: function(attr) {
|
3809 |
+
//Validate
|
3810 |
+
if ( !this.util.is_string(attr) ) {
|
3811 |
+
return null;
|
3812 |
+
}
|
3813 |
+
//Find default handler
|
3814 |
+
attr = this.util.format('get_%s_default', attr);
|
3815 |
+
if ( this.util.in_obj(this, attr) ) {
|
3816 |
+
attr = this[attr];
|
3817 |
+
if ( this.util.is_func(attr) ) {
|
3818 |
+
//Execute default handler
|
3819 |
+
attr = attr.call(this);
|
3820 |
+
}
|
3821 |
+
} else {
|
3822 |
+
attr = null;
|
3823 |
+
}
|
3824 |
+
return attr;
|
3825 |
+
},
|
3826 |
+
|
3827 |
+
/**
|
3828 |
+
* Retrieve theme offset
|
3829 |
+
* @return obj Theme offset with `width` & `height` properties
|
3830 |
+
*/
|
3831 |
+
get_offset: function() {
|
3832 |
+
return this.get_measurement('offset', { 'width': 0, 'height': 0});
|
3833 |
+
},
|
3834 |
+
|
3835 |
+
/**
|
3836 |
+
* Generate default offset
|
3837 |
+
* @return obj Theme offsets with `width` & `height` properties
|
3838 |
+
*/
|
3839 |
+
get_offset_default: function() {
|
3840 |
+
var offset = { 'width': 0, 'height': 0 };
|
3841 |
+
var v = this.get_viewer();
|
3842 |
+
var vn = v.dom_get();
|
3843 |
+
//Clone viewer
|
3844 |
+
var vc = vn
|
3845 |
+
.clone()
|
3846 |
+
.attr('id', '')
|
3847 |
+
.css({'visibility': 'hidden', 'position': 'absolute', 'top': ''})
|
3848 |
+
.removeClass('loading')
|
3849 |
+
.appendTo(vn.parent());
|
3850 |
+
//Get offset from layout node
|
3851 |
+
var l = vc.find(v.dom_get_selector('layout'));
|
3852 |
+
if ( l.length ) {
|
3853 |
+
//Clear inline styles
|
3854 |
+
l.find('*').css({
|
3855 |
+
'width': '',
|
3856 |
+
'height': '',
|
3857 |
+
'display': ''
|
3858 |
+
});
|
3859 |
+
//Resize content nodes
|
3860 |
+
var tags = this.get_tags('item', 'content');
|
3861 |
+
if ( tags.length ) {
|
3862 |
+
var offset_item = v.get_item().get_dimensions();
|
3863 |
+
//Set content dimensions
|
3864 |
+
tags = $(l.find(tags[0].get_selector('full')).get(0)).css({'width': offset_item.width, 'height': offset_item.height});
|
3865 |
+
$.each(offset_item, function(key, val) {
|
3866 |
+
offset[key] = -1 * val;
|
3867 |
+
});
|
3868 |
+
}
|
3869 |
+
|
3870 |
+
//Set offset
|
3871 |
+
offset.width += l.width();
|
3872 |
+
offset.height += l.height();
|
3873 |
+
//Normalize
|
3874 |
+
$.each(offset, function(key, val) {
|
3875 |
+
if ( val < 0 ) {
|
3876 |
+
offset[key] = 0;
|
3877 |
+
}
|
3878 |
+
});
|
3879 |
+
}
|
3880 |
+
vc.empty().remove();
|
3881 |
+
return offset;
|
3882 |
+
},
|
3883 |
+
|
3884 |
+
/**
|
3885 |
+
* Retrieve theme margins
|
3886 |
+
* @return obj Theme margin with `width` & `height` properties
|
3887 |
+
*/
|
3888 |
+
get_margin: function() {
|
3889 |
+
return this.get_measurement('margin', {'width': 0, 'height': 0});
|
3890 |
+
},
|
3891 |
+
|
3892 |
+
/**
|
3893 |
+
* Retrieve item dimensions
|
3894 |
+
* Dimensions are adjusted to fit window (if necessary)
|
3895 |
+
* @return obj Item dimensions with `width` & `height` properties
|
3896 |
+
*/
|
3897 |
+
get_item_dimensions: function() {
|
3898 |
+
var v = this.get_viewer();
|
3899 |
+
var dims = v.get_item().get_dimensions();
|
3900 |
+
if ( v.get_attribute('autofit', false) ) {
|
3901 |
+
//Get maximum dimensions
|
3902 |
+
var margin = this.get_margin();
|
3903 |
+
var offset = this.get_offset();
|
3904 |
+
offset.height += margin.height;
|
3905 |
+
offset.width += margin.width;
|
3906 |
+
var max = {'width': $(window).width(), 'height': $(window).height() };
|
3907 |
+
if ( max.width > offset.width ) {
|
3908 |
+
max.width -= offset.width;
|
3909 |
+
}
|
3910 |
+
if ( max.height > offset.height ) {
|
3911 |
+
max.height -= offset.height;
|
3912 |
+
}
|
3913 |
+
//Get resize factor
|
3914 |
+
var factor = Math.min(max.width / dims.width, max.height / dims.height);
|
3915 |
+
//Resize dimensions
|
3916 |
+
if ( factor < 1 ) {
|
3917 |
+
$.each(dims, function(key, val) {
|
3918 |
+
dims[key] = Math.round(dims[key] * factor);
|
3919 |
+
});
|
3920 |
+
}
|
3921 |
+
}
|
3922 |
+
return $.extend({}, dims);
|
3923 |
+
},
|
3924 |
+
|
3925 |
+
/**
|
3926 |
+
* Retrieve theme dimensions
|
3927 |
+
* @return obj Theme dimensions with `width` & `height` properties
|
3928 |
+
*/
|
3929 |
+
get_dimensions: function() {
|
3930 |
+
var dims = this.get_item_dimensions();
|
3931 |
+
var offset = this.get_offset();
|
3932 |
+
$.each(dims, function(key, val) {
|
3933 |
+
dims[key] += offset[key];
|
3934 |
+
});
|
3935 |
+
return dims;
|
3936 |
+
},
|
3937 |
+
|
3938 |
+
/* Output */
|
3939 |
+
|
3940 |
+
/**
|
3941 |
+
* Render Theme output
|
3942 |
+
* @param bool init (optional) Initialize theme (Default: FALSE)
|
3943 |
+
* @see Template.render()
|
3944 |
+
*/
|
3945 |
+
render: function(init) {
|
3946 |
+
var thm = this;
|
3947 |
+
var tpl = this.get_template();
|
3948 |
+
var st = 'events_render';
|
3949 |
+
if ( !this.get_status(st) ) {
|
3950 |
+
this.set_status(st);
|
3951 |
+
//Register events
|
3952 |
+
tpl.on([
|
3953 |
+
'render-init',
|
3954 |
+
'render-loading',
|
3955 |
+
'render-complete'
|
3956 |
+
],
|
3957 |
+
function(ev) {
|
3958 |
+
return thm.trigger(ev.type, ev.data);
|
3959 |
+
});
|
3960 |
+
}
|
3961 |
+
//Render template
|
3962 |
+
tpl.render(init);
|
3963 |
+
},
|
3964 |
+
|
3965 |
+
transition: function(event, clear_queue) {
|
3966 |
+
var dfr = null;
|
3967 |
+
var attr = 'transition';
|
3968 |
+
var v = this.get_viewer();
|
3969 |
+
var fx_temp = null;
|
3970 |
+
var anim_on = v.animation_enabled();
|
3971 |
+
if ( v.get_attribute(attr, true) && this.util.is_string(event) ) {
|
3972 |
+
var anim_stop = function() {
|
3973 |
+
var l = v.get_layout();
|
3974 |
+
l.find('*').each(function() {
|
3975 |
+
var el = $(this);
|
3976 |
+
while ( el.queue().length ) {
|
3977 |
+
el.stop(false, true);
|
3978 |
+
}
|
3979 |
+
});
|
3980 |
+
}
|
3981 |
+
//Stop queued animations
|
3982 |
+
if ( !!clear_queue ) {
|
3983 |
+
anim_stop();
|
3984 |
+
}
|
3985 |
+
//Get transition handlers
|
3986 |
+
var attr_set = [attr, 'set'].join('_');
|
3987 |
+
var trns;
|
3988 |
+
if ( !this.get_attribute(attr_set) ) {
|
3989 |
+
var models = this.get_ancestors(true);
|
3990 |
+
trns = [];
|
3991 |
+
this.set_attribute(attr_set, true);
|
3992 |
+
var thm = this;
|
3993 |
+
$.each(models, function(idx, model) {
|
3994 |
+
if ( attr in model && thm.util.is_obj(model[attr]) ) {
|
3995 |
+
trns.push(model[attr]);
|
3996 |
+
}
|
3997 |
+
});
|
3998 |
+
//Merge transition handlers into current theme
|
3999 |
+
trns.push({});
|
4000 |
+
trns = this.set_attribute(attr, $.extend.apply($, trns.reverse()));
|
4001 |
+
} else {
|
4002 |
+
trns = this.get_attribute(attr, {});
|
4003 |
+
}
|
4004 |
+
if ( this.util.is_method(trns, event) ) {
|
4005 |
+
//Disable animations if necessary
|
4006 |
+
if ( !anim_on ) {
|
4007 |
+
fx_temp = $.fx.off;
|
4008 |
+
$.fx.off = true;
|
4009 |
+
}
|
4010 |
+
//Pass control to transition event
|
4011 |
+
dfr = trns[event].call(this, v, $.Deferred());
|
4012 |
+
}
|
4013 |
+
}
|
4014 |
+
if ( !this.util.is_promise(dfr) ) {
|
4015 |
+
dfr = $.Deferred();
|
4016 |
+
dfr.reject();
|
4017 |
+
}
|
4018 |
+
dfr.always(function() {
|
4019 |
+
//Restore animation state
|
4020 |
+
if ( null !== fx_temp ) {
|
4021 |
+
$.fx.off = fx_temp;
|
4022 |
+
}
|
4023 |
+
});
|
4024 |
+
return dfr.promise();
|
4025 |
+
}
|
4026 |
+
};
|
4027 |
+
|
4028 |
+
View.Theme = Modeled_Component.extend(Theme);
|
4029 |
+
|
4030 |
+
/**
|
4031 |
+
* Template handler
|
4032 |
+
* Parses and Builds layout from raw template
|
4033 |
+
*/
|
4034 |
+
var Template = {
|
4035 |
+
/* Configuration */
|
4036 |
+
|
4037 |
+
_slug: 'template',
|
4038 |
+
_reciprocal: true,
|
4039 |
+
|
4040 |
+
_refs: {
|
4041 |
+
'theme': 'Theme'
|
4042 |
+
},
|
4043 |
+
_containers: ['theme'],
|
4044 |
+
|
4045 |
+
_attr_default: {
|
4046 |
+
/**
|
4047 |
+
* URI to layout (raw) file
|
4048 |
+
* @var string
|
4049 |
+
*/
|
4050 |
+
layout_uri: '',
|
4051 |
+
|
4052 |
+
/**
|
4053 |
+
* Raw layout template
|
4054 |
+
* @var string
|
4055 |
+
*/
|
4056 |
+
layout_raw: '',
|
4057 |
+
/**
|
4058 |
+
* Parsed layout
|
4059 |
+
* Placeholders processed
|
4060 |
+
* @var string
|
4061 |
+
*/
|
4062 |
+
layout_parsed: '',
|
4063 |
+
/**
|
4064 |
+
* Tags in template
|
4065 |
+
* Populated once template has been parsed
|
4066 |
+
* @var array
|
4067 |
+
*/
|
4068 |
+
tags: null,
|
4069 |
+
/**
|
4070 |
+
* Model to use for properties
|
4071 |
+
* Usually reference to an object in other component
|
4072 |
+
* @var obj
|
4073 |
+
*/
|
4074 |
+
model: null
|
4075 |
+
},
|
4076 |
+
|
4077 |
+
/* References */
|
4078 |
+
|
4079 |
+
theme: null,
|
4080 |
+
|
4081 |
+
/* Methods */
|
4082 |
+
|
4083 |
+
_c: function(attributes) {
|
4084 |
+
this._super('', attributes);
|
4085 |
+
},
|
4086 |
+
|
4087 |
+
get_theme: function() {
|
4088 |
+
var ret = this.get_component('theme', true, false, false);
|
4089 |
+
return ret;
|
4090 |
+
},
|
4091 |
+
|
4092 |
+
/* Output */
|
4093 |
+
|
4094 |
+
/**
|
4095 |
+
* Render output
|
4096 |
+
* @param bool init (optional) Whether to initialize layout (TRUE) or render item (FALSE) (Default: FALSE)
|
4097 |
+
* Events
|
4098 |
+
* > render-init: Initialize template
|
4099 |
+
* > render-loading: DOM elements created and item content about to be loaded
|
4100 |
+
* > render-complete: Item content loaded, ready for display
|
4101 |
+
*/
|
4102 |
+
render: function(init) {
|
4103 |
+
var v = this.get_theme().get_viewer();
|
4104 |
+
if ( !this.util.is_bool(init) ) {
|
4105 |
+
init = false;
|
4106 |
+
}
|
4107 |
+
//Populate layout
|
4108 |
+
if ( !init ) {
|
4109 |
+
if ( !v.is_active() ) {
|
4110 |
+
return false;
|
4111 |
+
}
|
4112 |
+
var item = v.get_item();
|
4113 |
+
if ( !this.util.is_type(item, View.Content_Item) ) {
|
4114 |
+
v.close();
|
4115 |
+
return false;
|
4116 |
+
}
|
4117 |
+
//Iterate through tags and populate layout
|
4118 |
+
if ( v.is_active() && this.has_tags() ) {
|
4119 |
+
var loading_promise = this.trigger('render-loading');
|
4120 |
+
var tpl = this;
|
4121 |
+
var tags = this.get_tags(),
|
4122 |
+
tag_promises = [];
|
4123 |
+
//Render Tag output
|
4124 |
+
loading_promise.done(function() {
|
4125 |
+
if ( !v.is_active() ) {
|
4126 |
+
return false;
|
4127 |
+
}
|
4128 |
+
$.each(tags, function(idx, tag) {
|
4129 |
+
if ( !v.is_active() ) {
|
4130 |
+
return false;
|
4131 |
+
}
|
4132 |
+
tag_promises.push(tag.render(item).done(function(r) {
|
4133 |
+
if ( !v.is_active() ) {
|
4134 |
+
return false;
|
4135 |
+
}
|
4136 |
+
r.tag.dom_get().html(r.output);
|
4137 |
+
}));
|
4138 |
+
});
|
4139 |
+
//Fire event when all tags rendered
|
4140 |
+
if ( !v.is_active() ) {
|
4141 |
+
return false;
|
4142 |
+
}
|
4143 |
+
$.when.apply($, tag_promises).done(function() {
|
4144 |
+
tpl.trigger('render-complete');
|
4145 |
+
});
|
4146 |
+
});
|
4147 |
+
}
|
4148 |
+
} else {
|
4149 |
+
//Get Layout (basic)
|
4150 |
+
this.trigger('render-init', this.dom_get());
|
4151 |
+
}
|
4152 |
+
},
|
4153 |
+
|
4154 |
+
/*-** Layout **-*/
|
4155 |
+
|
4156 |
+
/**
|
4157 |
+
* Retrieve layout
|
4158 |
+
* @param bool parsed (optional) TRUE retrieves parsed layout, FALSE retrieves raw layout (Default: TRUE)
|
4159 |
+
* @return string Layout (HTML)
|
4160 |
+
*/
|
4161 |
+
get_layout: function(parsed) {
|
4162 |
+
//Validate
|
4163 |
+
if ( !this.util.is_bool(parsed) ) {
|
4164 |
+
parsed = true;
|
4165 |
+
}
|
4166 |
+
//Determine which layout to retrieve (raw/parsed)
|
4167 |
+
var l = ( parsed ) ? this.parse_layout() : this.get_attribute('layout_raw', '');
|
4168 |
+
return l;
|
4169 |
+
},
|
4170 |
+
|
4171 |
+
/**
|
4172 |
+
* Parse layout
|
4173 |
+
* Converts template tags to HTML elements
|
4174 |
+
* > Template tag properties saved to HTML elements for future initialization
|
4175 |
+
* Returns saved layout if previously parsed
|
4176 |
+
* @return string Parsed layout
|
4177 |
+
*/
|
4178 |
+
parse_layout: function() {
|
4179 |
+
//Check for previously-parsed layout
|
4180 |
+
var a = 'layout_parsed';
|
4181 |
+
var ret = this.get_attribute(a);
|
4182 |
+
//Return cached layout immediately
|
4183 |
+
if ( this.util.is_string(ret) ) {
|
4184 |
+
return ret;
|
4185 |
+
}
|
4186 |
+
//Parse raw layout
|
4187 |
+
ret = this.sanitize_layout( this.get_layout(false) );
|
4188 |
+
ret = this.parse_tags(ret);
|
4189 |
+
//Save parsed layout
|
4190 |
+
this.set_attribute(a, ret);
|
4191 |
+
|
4192 |
+
//Return parsed layout
|
4193 |
+
return ret;
|
4194 |
+
},
|
4195 |
+
|
4196 |
+
/**
|
4197 |
+
* Sanitize layout
|
4198 |
+
* @param obj|string l Layout string or jQuery object
|
4199 |
+
* @return obj|string Sanitized layout (Same data type that was passed to method)
|
4200 |
+
*/
|
4201 |
+
sanitize_layout: function(l) {
|
4202 |
+
//Stop processing if invalid value
|
4203 |
+
if ( this.util.is_empty(l) ) {
|
4204 |
+
return l;
|
4205 |
+
}
|
4206 |
+
//Set return type
|
4207 |
+
var rtype = ( this.util.is_string(l) ) ? 'string' : null;
|
4208 |
+
/* Quarantine hard-coded tags */
|
4209 |
+
|
4210 |
+
//Create DOM structure from raw template
|
4211 |
+
var dom = $(l);
|
4212 |
+
//Find hard-coded tag nodes
|
4213 |
+
var tag_temp = new View.Template_Tag();
|
4214 |
+
var cls = tag_temp.get_class();
|
4215 |
+
var cls_new = ['x', cls].join('_');
|
4216 |
+
$(tag_temp.get_selector(), dom).each(function(idx) {
|
4217 |
+
//Replace matching class name with blocking class
|
4218 |
+
$(this).removeClass(cls).addClass(cls_new);
|
4219 |
+
});
|
4220 |
+
//Format return value
|
4221 |
+
switch ( rtype ) {
|
4222 |
+
case 'string' :
|
4223 |
+
dom = dom.wrap('<div />').parent().html();
|
4224 |
+
default :
|
4225 |
+
l = dom;
|
4226 |
+
}
|
4227 |
+
return l;
|
4228 |
+
},
|
4229 |
+
|
4230 |
+
/*-** Tags **-*/
|
4231 |
+
|
4232 |
+
/**
|
4233 |
+
* Extract tags from template
|
4234 |
+
* Tags are replaced with DOM element placeholders
|
4235 |
+
* Extracted tags are saved as element attribute values (for future use)
|
4236 |
+
* @param string l Raw layout to parse
|
4237 |
+
* @return string Parsed layout
|
4238 |
+
*/
|
4239 |
+
parse_tags: function(l) {
|
4240 |
+
//Validate
|
4241 |
+
if ( !this.util.is_string(l) ) {
|
4242 |
+
return '';
|
4243 |
+
}
|
4244 |
+
//Parse tags in layout
|
4245 |
+
//Tag regex
|
4246 |
+
var re = /\{{2}\s*(\w.*?)\s*\}{2}/gim;
|
4247 |
+
//Tag match results
|
4248 |
+
var match;
|
4249 |
+
//Iterate through template and find tags
|
4250 |
+
while ( match = re.exec(l) ) {
|
4251 |
+
//Replace tag in layout with DOM container
|
4252 |
+
l = l.substring(0, match.index) + this.get_tag_container(match[1]) + l.substring(match.index + match[0].length);
|
4253 |
+
}
|
4254 |
+
return l;
|
4255 |
+
},
|
4256 |
+
|
4257 |
+
/**
|
4258 |
+
* Create DOM element container for tag
|
4259 |
+
* @param string Tag ID (will be prefixed)
|
4260 |
+
* @return string DOM element
|
4261 |
+
*/
|
4262 |
+
get_tag_container: function(tag) {
|
4263 |
+
//Build element
|
4264 |
+
var attr = this.get_tag_attribute();
|
4265 |
+
return this.util.format('<span %s="%s"></span>', attr, escape(tag));
|
4266 |
+
},
|
4267 |
+
|
4268 |
+
get_tag_attribute: function() {
|
4269 |
+
return this.get_parent().get_component_temp(View.Template_Tag).dom_get_attribute();
|
4270 |
+
},
|
4271 |
+
|
4272 |
+
/**
|
4273 |
+
* Retrieve Template_Tag instance at specified index
|
4274 |
+
* @param int idx (optional) Index to retrieve tag from
|
4275 |
+
* @return Template_Tag Tag instance
|
4276 |
+
*/
|
4277 |
+
get_tag: function(idx) {
|
4278 |
+
var ret = null;
|
4279 |
+
if ( this.has_tags() ) {
|
4280 |
+
var tags = this.get_tags();
|
4281 |
+
if ( !this.util.is_int(idx) || 0 > idx || idx >= tags.length ) {
|
4282 |
+
idx = 0;
|
4283 |
+
}
|
4284 |
+
ret = tags[idx];
|
4285 |
+
}
|
4286 |
+
return ret;
|
4287 |
+
},
|
4288 |
+
|
4289 |
+
/**
|
4290 |
+
* Retrieve tags from template
|
4291 |
+
* Subset of tags may be retrieved based on parameter values
|
4292 |
+
* Template is parsed if tags not set
|
4293 |
+
* @param string name (optional) Tag type to retrieve instances of
|
4294 |
+
* @param string prop (optional) Tag property to retrieve instances of
|
4295 |
+
* @return array Template_Tag instances
|
4296 |
+
*/
|
4297 |
+
get_tags: function(name, prop) {
|
4298 |
+
var a = 'tags';
|
4299 |
+
var tags = this.get_attribute(a);
|
4300 |
+
//Initialize tags
|
4301 |
+
if ( !this.util.is_array(tags) ) {
|
4302 |
+
tags = [];
|
4303 |
+
//Retrieve layout DOM tree
|
4304 |
+
var d = this.dom_get();
|
4305 |
+
//Select tag nodes
|
4306 |
+
var attr = this.get_tag_attribute();
|
4307 |
+
var nodes = $(d).find('[' + attr + ']');
|
4308 |
+
//Build tag instances from nodes
|
4309 |
+
$(nodes).each(function(idx) {
|
4310 |
+
//Get tag placeholder
|
4311 |
+
var el = $(this);
|
4312 |
+
var tag = new View.Template_Tag(unescape(el.attr(attr)));
|
4313 |
+
//Populate valid tags
|
4314 |
+
if ( tag.has_handler() ) {
|
4315 |
+
//Add tag to array
|
4316 |
+
tags.push(tag);
|
4317 |
+
//Connect tag to DOM node
|
4318 |
+
tag.dom_set(el);
|
4319 |
+
//Set classes
|
4320 |
+
el.addClass(tag.get_classes(' '));
|
4321 |
+
}
|
4322 |
+
//Clear data attribute
|
4323 |
+
el.removeAttr(attr);
|
4324 |
+
});
|
4325 |
+
//Save tags
|
4326 |
+
this.set_attribute(a, tags, false);
|
4327 |
+
}
|
4328 |
+
tags = this.get_attribute(a, [], false);
|
4329 |
+
//Filter tags by parameters
|
4330 |
+
if ( !this.util.is_empty(tags) && this.util.is_string(name) ) {
|
4331 |
+
//Normalize
|
4332 |
+
if ( !this.util.is_string(prop) ) {
|
4333 |
+
prop = false;
|
4334 |
+
}
|
4335 |
+
var tags_filtered = [];
|
4336 |
+
var tc = null;
|
4337 |
+
for ( var x = 0; x < tags.length; x++ ) {
|
4338 |
+
tc = tags[x];
|
4339 |
+
if ( name == tc.get_name() ) {
|
4340 |
+
//Check tag property
|
4341 |
+
if ( !prop || prop == tc.get_prop() ) {
|
4342 |
+
tags_filtered.push(tc);
|
4343 |
+
}
|
4344 |
+
}
|
4345 |
+
}
|
4346 |
+
tags = tags_filtered;
|
4347 |
+
}
|
4348 |
+
return ( this.util.is_array(tags, false) ) ? tags : [];
|
4349 |
+
},
|
4350 |
+
|
4351 |
+
/**
|
4352 |
+
* Check if template contains tags
|
4353 |
+
* @return bool TRUE if tags exist, FALSE otherwise
|
4354 |
+
*/
|
4355 |
+
has_tags: function() {
|
4356 |
+
return ( this.get_tags().length > 0 ) ? true : false;
|
4357 |
+
},
|
4358 |
+
|
4359 |
+
/*-** DOM **-*/
|
4360 |
+
|
4361 |
+
/**
|
4362 |
+
* Custom DOM initialization
|
4363 |
+
*/
|
4364 |
+
dom_init: function() {
|
4365 |
+
//Create DOM object from parsed layout
|
4366 |
+
this.dom_set(this.get_layout());
|
4367 |
+
},
|
4368 |
+
|
4369 |
+
/**
|
4370 |
+
* Retrieve DOM element(s) for specified tag
|
4371 |
+
* @param string tag Name of tag to retrieve
|
4372 |
+
* @param string prop (optional) Specific tag property to retrieve
|
4373 |
+
* @return array DOM elements for tag
|
4374 |
+
*/
|
4375 |
+
dom_get_tag: function(tag, prop) {
|
4376 |
+
var ret = $();
|
4377 |
+
var tags = this.get_tags(tag, prop);
|
4378 |
+
if ( tags.length ) {
|
4379 |
+
//Build selector
|
4380 |
+
var level = null;
|
4381 |
+
if ( this.util.is_string(tag) ) {
|
4382 |
+
level = ( this.util.is_string(prop) ) ? 'full' : 'tag';
|
4383 |
+
}
|
4384 |
+
var sel = '.' + tags[0].get_class(level);
|
4385 |
+
ret = this.dom_get().find(sel);
|
4386 |
+
}
|
4387 |
+
return ret;
|
4388 |
+
}
|
4389 |
+
};
|
4390 |
+
|
4391 |
+
View.Template = Modeled_Component.extend(Template);
|
4392 |
+
|
4393 |
+
/**
|
4394 |
+
* Template tag
|
4395 |
+
*/
|
4396 |
+
var Template_Tag = {
|
4397 |
+
/* Configuration */
|
4398 |
+
_slug: 'template_tag',
|
4399 |
+
_reciprocal: true,
|
4400 |
+
/* Properties */
|
4401 |
+
_attr_default: {
|
4402 |
+
name: null,
|
4403 |
+
prop: null,
|
4404 |
+
match: null
|
4405 |
+
},
|
4406 |
+
/**
|
4407 |
+
* Tag Handlers
|
4408 |
+
* Collection of Template_Tag_Handler instances
|
4409 |
+
* @var obj
|
4410 |
+
*/
|
4411 |
+
handlers: {},
|
4412 |
+
/* Methods */
|
4413 |
+
|
4414 |
+
/**
|
4415 |
+
* Constructor
|
4416 |
+
* @param
|
4417 |
+
*/
|
4418 |
+
_c: function(tag_match) {
|
4419 |
+
this.parse(tag_match);
|
4420 |
+
},
|
4421 |
+
|
4422 |
+
/**
|
4423 |
+
* Set instance attributes using tag extracted from template
|
4424 |
+
* @param string tag_match Extracted tag match
|
4425 |
+
*/
|
4426 |
+
parse: function(tag_match) {
|
4427 |
+
//Return default value for invalid instances
|
4428 |
+
if ( !this.util.is_string(tag_match) ) {
|
4429 |
+
return false;
|
4430 |
+
}
|
4431 |
+
//Parse instance options
|
4432 |
+
var parts = tag_match.split('|'),
|
4433 |
+
part;
|
4434 |
+
if ( !parts.length ) {
|
4435 |
+
return null;
|
4436 |
+
}
|
4437 |
+
var attrs = {
|
4438 |
+
name: null,
|
4439 |
+
prop: null,
|
4440 |
+
match: tag_match
|
4441 |
+
};
|
4442 |
+
//Get tag ID
|
4443 |
+
attrs.name = parts[0];
|
4444 |
+
//Get main property
|
4445 |
+
if ( attrs.name.indexOf('.') != -1 ) {
|
4446 |
+
attrs.name = attrs.name.split('.', 2);
|
4447 |
+
attrs.prop = attrs.name[1];
|
4448 |
+
attrs.name = attrs.name[0];
|
4449 |
+
}
|
4450 |
+
//Get other attributes
|
4451 |
+
for ( var x = 1; x < parts.length; x++ ) {
|
4452 |
+
part = parts[x].split(':', 1);
|
4453 |
+
if ( part.length > 1 && !( part[0] in attrs ) ) {
|
4454 |
+
//Add key/value pair to attributes
|
4455 |
+
attrs[part[0]] = part[1];
|
4456 |
+
}
|
4457 |
+
}
|
4458 |
+
//Save to instance
|
4459 |
+
this.set_attributes(attrs, true);
|
4460 |
+
},
|
4461 |
+
|
4462 |
+
/**
|
4463 |
+
* Render tag output
|
4464 |
+
* @param Content_Item item
|
4465 |
+
* @return obj jQuery.Promise object that is resolved when tag is rendered
|
4466 |
+
* Parameters passed to callbacks
|
4467 |
+
* > tag obj Current tag instance
|
4468 |
+
* > output string Tag output
|
4469 |
+
*/
|
4470 |
+
render: function(item) {
|
4471 |
+
var tag = this;
|
4472 |
+
return tag.get_handler().render(item, tag).pipe(function(output) {
|
4473 |
+
return {'tag': tag, 'output': output};
|
4474 |
+
});
|
4475 |
+
},
|
4476 |
+
|
4477 |
+
/**
|
4478 |
+
* Retrieve tag name
|
4479 |
+
* @return string Tag name (DEFAULT: NULL)
|
4480 |
+
*/
|
4481 |
+
get_name: function() {
|
4482 |
+
return this.get_attribute('name');
|
4483 |
+
},
|
4484 |
+
|
4485 |
+
/**
|
4486 |
+
* Retrieve tag property
|
4487 |
+
*/
|
4488 |
+
get_prop: function() {
|
4489 |
+
return this.get_attribute('prop');
|
4490 |
+
},
|
4491 |
+
|
4492 |
+
/**
|
4493 |
+
* Retrieve tag handler
|
4494 |
+
* @return Template_Tag_Handler Handler instance (Empty instance if handler does not exist)
|
4495 |
+
*/
|
4496 |
+
get_handler: function() {
|
4497 |
+
return ( this.has_handler() ) ? this.handlers[this.get_name()] : new View.Template_Tag_Handler('');
|
4498 |
+
},
|
4499 |
+
|
4500 |
+
/**
|
4501 |
+
* Check if handler exists for tag
|
4502 |
+
* @return bool TRUE if handler exists, FALSE otherwise
|
4503 |
+
*/
|
4504 |
+
has_handler: function() {
|
4505 |
+
return ( this.get_name() in this.handlers );
|
4506 |
+
},
|
4507 |
+
|
4508 |
+
/**
|
4509 |
+
* Generate class names for DOM node
|
4510 |
+
* @param string rtype (optional) Return data type
|
4511 |
+
* > Default: array
|
4512 |
+
* > If string supplied: Joined classes delimited by parameter
|
4513 |
+
* @uses get_class() to generate class names
|
4514 |
+
* @uses Array.join() to convert class names array to string
|
4515 |
+
* @return array Class names
|
4516 |
+
*/
|
4517 |
+
get_classes: function(rtype) {
|
4518 |
+
//Build array of class names
|
4519 |
+
var cls = [
|
4520 |
+
//General tag class
|
4521 |
+
this.get_class(),
|
4522 |
+
//Tag name
|
4523 |
+
this.get_class('tag'),
|
4524 |
+
//Tag name + property
|
4525 |
+
this.get_class('full')
|
4526 |
+
];
|
4527 |
+
//Convert class names array to string
|
4528 |
+
if ( this.util.is_string(rtype) ) {
|
4529 |
+
cls = cls.join(rtype);
|
4530 |
+
}
|
4531 |
+
//Return class names
|
4532 |
+
return cls;
|
4533 |
+
},
|
4534 |
+
|
4535 |
+
/**
|
4536 |
+
* Generate DOM-compatible class name based with varied levels of specificity
|
4537 |
+
* @param int level (optional) Class name specificity
|
4538 |
+
* > Default: General tag class (common to all tag elements)
|
4539 |
+
* > tag: Tag Name
|
4540 |
+
* > full: Tag Name + Property
|
4541 |
+
* @return string Class name
|
4542 |
+
*/
|
4543 |
+
get_class: function(level) {
|
4544 |
+
var cls = '';
|
4545 |
+
switch ( level ) {
|
4546 |
+
case 'tag' :
|
4547 |
+
//Tag name
|
4548 |
+
cls = this.add_ns(this.get_name());
|
4549 |
+
break;
|
4550 |
+
case 'full' :
|
4551 |
+
//Tag name + property
|
4552 |
+
cls = this.add_ns([this.get_name(), this.get_prop()].join('_'));
|
4553 |
+
break;
|
4554 |
+
default :
|
4555 |
+
//General
|
4556 |
+
cls = this.get_ns();
|
4557 |
+
break;
|
4558 |
+
}
|
4559 |
+
return cls;
|
4560 |
+
},
|
4561 |
+
|
4562 |
+
/**
|
4563 |
+
* Generate tag selector based on specified class name level
|
4564 |
+
* @param string level (optional) Class name specificity (@see get_class() for parameter values)
|
4565 |
+
* @return string Tag selector
|
4566 |
+
*/
|
4567 |
+
get_selector: function(level) {
|
4568 |
+
return '.' + this.get_class(level);
|
4569 |
+
}
|
4570 |
+
};
|
4571 |
+
|
4572 |
+
View.Template_Tag = Component.extend(Template_Tag);
|
4573 |
+
|
4574 |
+
/**
|
4575 |
+
* Theme tag handler
|
4576 |
+
*/
|
4577 |
+
var Template_Tag_Handler = {
|
4578 |
+
/* Configuration */
|
4579 |
+
_slug: 'template_tag_handler',
|
4580 |
+
/* Properties */
|
4581 |
+
_attr_default: {
|
4582 |
+
supports_modifiers: false,
|
4583 |
+
dynamic: false,
|
4584 |
+
props: {}
|
4585 |
+
},
|
4586 |
+
|
4587 |
+
/* Methods */
|
4588 |
+
|
4589 |
+
/**
|
4590 |
+
* Render tag output
|
4591 |
+
* @param Content_Item item Item currently being displayed
|
4592 |
+
* @param Template_Tag Tag instance (from template)
|
4593 |
+
* @return obj jQuery.Promise linked to rendering process
|
4594 |
+
*/
|
4595 |
+
render: function(item, instance) {
|
4596 |
+
var dfr = $.Deferred();
|
4597 |
+
//Pass to attribute method
|
4598 |
+
var ret = this.call_attribute('render', item, instance);
|
4599 |
+
//Check for promise
|
4600 |
+
if ( this.util.is_promise(ret) ) {
|
4601 |
+
ret.done(function(output) {
|
4602 |
+
dfr.resolve(output);
|
4603 |
+
});
|
4604 |
+
} else {
|
4605 |
+
//Resolve non-promises immediately
|
4606 |
+
dfr.resolve(ret);
|
4607 |
+
}
|
4608 |
+
//Return promise
|
4609 |
+
return dfr.promise();
|
4610 |
+
},
|
4611 |
+
|
4612 |
+
add_prop: function(prop, fn) {
|
4613 |
+
//Get attribute
|
4614 |
+
var a = 'props';
|
4615 |
+
var props = this.get_attribute(a);
|
4616 |
+
//Validate
|
4617 |
+
if ( !this.util.is_string(prop) || !this.util.is_func(fn) ) {
|
4618 |
+
return false;
|
4619 |
+
}
|
4620 |
+
if ( !this.util.is_obj(props, false) ) {
|
4621 |
+
props = {};
|
4622 |
+
}
|
4623 |
+
//Add property
|
4624 |
+
props[prop] = fn;
|
4625 |
+
//Save attribute
|
4626 |
+
this.set_attribute(a, props);
|
4627 |
+
},
|
4628 |
+
|
4629 |
+
handle_prop: function(prop, item, instance) {
|
4630 |
+
//Locate property
|
4631 |
+
var props = this.get_attribute('props');
|
4632 |
+
var out = '';
|
4633 |
+
if ( this.util.is_obj(props) && ( prop in props ) && this.util.is_func(props[prop]) ) {
|
4634 |
+
out = props[prop].call(this, item, instance);
|
4635 |
+
} else {
|
4636 |
+
out = item.get_viewer().get_label(prop);
|
4637 |
+
}
|
4638 |
+
return out;
|
4639 |
+
}
|
4640 |
+
};
|
4641 |
+
|
4642 |
+
View.Template_Tag_Handler = Component.extend(Template_Tag_Handler);
|
4643 |
+
/* Update References */
|
4644 |
+
|
4645 |
+
//Attach to global object
|
4646 |
+
SLB.attach('View', View);
|
4647 |
+
View = SLB.View;
|
4648 |
+
View.update_refs();
|
4649 |
+
})(jQuery);
|
client/sass/admin.scss
ADDED
@@ -0,0 +1,31 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
.slb_section_head {
|
2 |
+
display: block;
|
3 |
+
padding: 2em 0 0;
|
4 |
+
}
|
5 |
+
|
6 |
+
.slb_option_item {
|
7 |
+
.block {
|
8 |
+
display: inline-block;
|
9 |
+
}
|
10 |
+
|
11 |
+
label.title {
|
12 |
+
width: 200px;
|
13 |
+
padding: 10px;
|
14 |
+
}
|
15 |
+
|
16 |
+
.input {
|
17 |
+
font-size: 11px;
|
18 |
+
line-height: 20px;
|
19 |
+
margin-bottom: 9px;
|
20 |
+
padding: 8px 10px;
|
21 |
+
}
|
22 |
+
|
23 |
+
.input select {
|
24 |
+
min-width: 12em;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
.slb_notice {
|
29 |
+
color: #f00;
|
30 |
+
font-weight: bold;
|
31 |
+
}
|
content-handlers/image/handler.image.js
ADDED
@@ -0,0 +1,29 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function($) {
|
2 |
+
return {
|
3 |
+
render: function(item) {
|
4 |
+
var dfr = $.Deferred();
|
5 |
+
//Create image object
|
6 |
+
var img = new Image();
|
7 |
+
var type = this;
|
8 |
+
//Set load event
|
9 |
+
var handler = function(e) {
|
10 |
+
//Save Data
|
11 |
+
item.set_data(img);
|
12 |
+
//Set attributes
|
13 |
+
var dim = {'width': img.width, 'height': img.height};
|
14 |
+
item.set_attribute('dimensions', dim);
|
15 |
+
//Build output
|
16 |
+
var out = $('<img />', {'src': item.get_uri()});
|
17 |
+
//Resolve deferred
|
18 |
+
dfr.resolve(out);
|
19 |
+
};
|
20 |
+
|
21 |
+
//Attach event handler
|
22 |
+
$(img).on('load', function(e) { handler(e); });
|
23 |
+
//Load image
|
24 |
+
img.src = item.get_uri();
|
25 |
+
//Return promise
|
26 |
+
return dfr.promise();
|
27 |
+
}
|
28 |
+
}
|
29 |
+
})(jQuery);
|
css/admin.css
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
.subhead {
|
2 |
-
margin-bottom: .2em;
|
3 |
-
}
|
Â
|
|
Â
|
|
Â
|
css/lightbox.css
DELETED
@@ -1,135 +0,0 @@
|
|
1 |
-
#lightbox{
|
2 |
-
position: absolute;
|
3 |
-
top: 20px;
|
4 |
-
left: 0;
|
5 |
-
width: 100%;
|
6 |
-
z-index: 3100;
|
7 |
-
text-align: center;
|
8 |
-
line-height: 0;
|
9 |
-
color:#151410;
|
10 |
-
}
|
11 |
-
|
12 |
-
#lightbox a, #lightbox a:hover {
|
13 |
-
border-bottom:none;
|
14 |
-
color:#151410;
|
15 |
-
text-decoration:underline;
|
16 |
-
}
|
17 |
-
|
18 |
-
#lightbox a img{ border: none; }
|
19 |
-
|
20 |
-
#outerImageContainer{
|
21 |
-
position: relative;
|
22 |
-
background-color: #fff;
|
23 |
-
width: 250px;
|
24 |
-
height: 250px;
|
25 |
-
margin: 0 auto;
|
26 |
-
}
|
27 |
-
|
28 |
-
#imageContainer{
|
29 |
-
padding: 10px;
|
30 |
-
}
|
31 |
-
|
32 |
-
#loading{
|
33 |
-
position: absolute;
|
34 |
-
top: 40%;
|
35 |
-
left: 0%;
|
36 |
-
height: 25%;
|
37 |
-
width: 100%;
|
38 |
-
text-align: center;
|
39 |
-
line-height: 0;
|
40 |
-
}
|
41 |
-
#loadingLink {
|
42 |
-
display:block;
|
43 |
-
margin:0 auto;
|
44 |
-
padding:0;
|
45 |
-
width:32px;
|
46 |
-
height:32px;
|
47 |
-
background:url("../images/loading.gif") center center no-repeat;
|
48 |
-
text-indent:-9999px;
|
49 |
-
}
|
50 |
-
#hoverNav{
|
51 |
-
position: absolute;
|
52 |
-
top: 0;
|
53 |
-
left: 0;
|
54 |
-
height: 100%;
|
55 |
-
width: 100%;
|
56 |
-
z-index: 10;
|
57 |
-
}
|
58 |
-
#imageContainer>#hoverNav{ left: 0;}
|
59 |
-
#hoverNav a{ outline: none;}
|
60 |
-
|
61 |
-
#prevLinkImg, #nextLinkImg{
|
62 |
-
width: 49%;
|
63 |
-
height: 100%;
|
64 |
-
background: transparent url("../images/blank.gif") no-repeat; /* Trick IE into showing hover */
|
65 |
-
display: block;
|
66 |
-
text-indent:-9999px;
|
67 |
-
}
|
68 |
-
#prevLinkImg { left: 0; float: left;}
|
69 |
-
#nextLinkImg { right: 0; float: right;}
|
70 |
-
#prevLinkImg:hover, #prevLinkImg:visited:hover { background: url("../images/prevlabel.gif") left 15% no-repeat; }
|
71 |
-
#nextLinkImg:hover, #nextLinkImg:visited:hover { background: url("../images/nextlabel.gif") right 15% no-repeat; }
|
72 |
-
|
73 |
-
|
74 |
-
#imageDataContainer{
|
75 |
-
font: 10px Verdana, Helvetica, sans-serif;
|
76 |
-
background-color: #fff;
|
77 |
-
margin: 0 auto;
|
78 |
-
line-height: 1.4em;
|
79 |
-
}
|
80 |
-
|
81 |
-
#imageData{
|
82 |
-
padding:0 10px;
|
83 |
-
}
|
84 |
-
#imageDetails{ width: 70%; float: left; text-align: left; }
|
85 |
-
#caption{ font-weight: bold; }
|
86 |
-
#numberDisplay{ display: block; clear: left; }
|
87 |
-
#detailsNav{ display: block; clear: left; padding:0 0 10px 0; }
|
88 |
-
#prevLinkDetails { margin:0 8px 0 0; }
|
89 |
-
#nextLinkDetails { margin:0 8px 0 0; }
|
90 |
-
#closeLink {
|
91 |
-
display:block;
|
92 |
-
margin:0;
|
93 |
-
padding:0 0 10px 0;
|
94 |
-
text-decoration:none;
|
95 |
-
float:right;
|
96 |
-
width:66px;
|
97 |
-
height:28px;
|
98 |
-
background:url("../images/closelabel.gif") no-repeat;
|
99 |
-
text-indent:-9999px;
|
100 |
-
overflow:hidden;
|
101 |
-
}
|
102 |
-
|
103 |
-
#overlay{
|
104 |
-
position: absolute;
|
105 |
-
top: 0;
|
106 |
-
left: 0;
|
107 |
-
z-index: 3090;
|
108 |
-
width: 100%;
|
109 |
-
height: 500px;
|
110 |
-
background-color: #151410;
|
111 |
-
filter:alpha(opacity=60);
|
112 |
-
-moz-opacity: 0.6;
|
113 |
-
opacity: 0.6;
|
114 |
-
}
|
115 |
-
|
116 |
-
|
117 |
-
.clearfix:after {
|
118 |
-
content: ".";
|
119 |
-
display: block;
|
120 |
-
height: 0;
|
121 |
-
clear: both;
|
122 |
-
visibility: hidden;
|
123 |
-
}
|
124 |
-
|
125 |
-
* html>body .clearfix {
|
126 |
-
display: inline-block;
|
127 |
-
width: 100%;
|
128 |
-
}
|
129 |
-
|
130 |
-
* html .clearfix {
|
131 |
-
/* Hides from IE-mac \*/
|
132 |
-
height: 1%;
|
133 |
-
/* End hide from IE-mac */
|
134 |
-
}
|
135 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
images/blank.gif
DELETED
Binary file
|
images/closelabel.gif
DELETED
Binary file
|
images/nextlabel.gif
DELETED
Binary file
|
images/prevlabel.gif
DELETED
Binary file
|
includes/class.admin.php
ADDED
@@ -0,0 +1,1576 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Admin functionality
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Admin
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Admin extends SLB_Base {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
protected $mode = 'sub';
|
13 |
+
|
14 |
+
/* Files */
|
15 |
+
|
16 |
+
var $scripts = array (
|
17 |
+
'admin' => array (
|
18 |
+
'file' => 'client/js/lib.admin.js',
|
19 |
+
'deps' => array('[core]'),
|
20 |
+
'context' => array( 'admin_page_slb_options' ),
|
21 |
+
'in_footer' => true,
|
22 |
+
),
|
23 |
+
);
|
24 |
+
|
25 |
+
var $styles = array (
|
26 |
+
'admin' => array (
|
27 |
+
'file' => 'client/css/admin.css',
|
28 |
+
'context' => array( 'admin_page_slb_options', 'admin_page_plugins' )
|
29 |
+
)
|
30 |
+
);
|
31 |
+
|
32 |
+
/* Properties */
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Parent object
|
36 |
+
* Set on initialization
|
37 |
+
* @var obj
|
38 |
+
*/
|
39 |
+
var $parent = null;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Messages
|
43 |
+
* @var array
|
44 |
+
*/
|
45 |
+
var $messages = array();
|
46 |
+
|
47 |
+
/* Views */
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Custom admin top-level menus
|
51 |
+
* Associative Array
|
52 |
+
* > Key: Menu ID
|
53 |
+
* > Val: Menu properties
|
54 |
+
* @var array
|
55 |
+
*/
|
56 |
+
var $menus = array();
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Custom admin pages
|
60 |
+
* Associative Array
|
61 |
+
* > Key: Page ID
|
62 |
+
* > Val: Page properties
|
63 |
+
* @var array
|
64 |
+
*/
|
65 |
+
var $pages = array();
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Custom admin sections
|
69 |
+
* Associative Array
|
70 |
+
* > Key: Section ID
|
71 |
+
* > Val: Section properties
|
72 |
+
* @var array
|
73 |
+
*/
|
74 |
+
var $sections = array();
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Reset options
|
78 |
+
* Indexed Array
|
79 |
+
* @var array
|
80 |
+
*/
|
81 |
+
var $resets = array();
|
82 |
+
|
83 |
+
/* Constructor */
|
84 |
+
|
85 |
+
/**
|
86 |
+
* TODO Determine if $parent needed
|
87 |
+
*/
|
88 |
+
function __construct(&$parent) {
|
89 |
+
parent::__construct();
|
90 |
+
//Set parent
|
91 |
+
if ( is_object($parent) )
|
92 |
+
$this->parent =& $parent;
|
93 |
+
}
|
94 |
+
|
95 |
+
/* Init */
|
96 |
+
|
97 |
+
protected function _hooks() {
|
98 |
+
parent::_hooks();
|
99 |
+
//Init
|
100 |
+
add_action('admin_menu', $this->m('init_menus'), 11);
|
101 |
+
|
102 |
+
//Reset Settings
|
103 |
+
add_action('admin_action_' . $this->add_prefix('admin'), $this->m('handle_action'));
|
104 |
+
|
105 |
+
//Notices
|
106 |
+
add_action('admin_notices', $this->m('handle_notices'));
|
107 |
+
|
108 |
+
//Plugin listing
|
109 |
+
add_filter('plugin_action_links_' . $this->util->get_plugin_base_name(), $this->m('plugin_action_links'), 10, 4);
|
110 |
+
add_action('in_plugin_update_message-' . $this->util->get_plugin_base_name(), $this->m('plugin_update_message'), 10, 2);
|
111 |
+
add_filter('site_transient_update_plugins', $this->m('plugin_update_transient'));
|
112 |
+
}
|
113 |
+
|
114 |
+
/* Handlers */
|
115 |
+
|
116 |
+
function handle_action() {
|
117 |
+
//Parse action
|
118 |
+
$t = 'type';
|
119 |
+
$g = 'group';
|
120 |
+
$o = 'obj';
|
121 |
+
$this->add_prefix_ref($t);
|
122 |
+
$this->add_prefix_ref($g);
|
123 |
+
$this->add_prefix_ref($o);
|
124 |
+
$r =& $_REQUEST;
|
125 |
+
|
126 |
+
//Retrieve view that initiated the action
|
127 |
+
if ( isset($r[$t]) && 'view' == $r[$t] ) {
|
128 |
+
if ( isset($r[$g]) && ( $prop = $r[$g] . 's' ) && property_exists($this, $prop) && is_array($this->{$prop}) && isset($r[$o]) && isset($this->{$prop}[$r[$o]]) ) {
|
129 |
+
$view =& $this->{$prop}[$r[$o]];
|
130 |
+
//Pass request to view
|
131 |
+
$view->do_callback();
|
132 |
+
}
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Display notices
|
138 |
+
* Messages are localized upon display
|
139 |
+
* @uses `admin_notices` action hook to display messages
|
140 |
+
*/
|
141 |
+
function handle_notices() {
|
142 |
+
$msgs = $this->util->apply_filters('admin_messages', array());
|
143 |
+
foreach ( $msgs as $mid => $msg ) {
|
144 |
+
//Filter out empty messages
|
145 |
+
if ( empty($msg) )
|
146 |
+
continue;
|
147 |
+
//Build and display message
|
148 |
+
$mid = $this->add_prefix('msg_' . $mid);
|
149 |
+
?>
|
150 |
+
<div id="<?php echo esc_attr($mid); ?>" class="updated fade">
|
151 |
+
<p>
|
152 |
+
<?php echo esc_html($msg);?>
|
153 |
+
</p>
|
154 |
+
</div>
|
155 |
+
<?php
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Displays notices for admin operations
|
161 |
+
*/
|
162 |
+
function show_notices() {
|
163 |
+
if ( is_admin() && isset($_REQUEST[$this->add_prefix('action')]) ) {
|
164 |
+
$action = $_REQUEST[$this->add_prefix('action')];
|
165 |
+
$msg = null;
|
166 |
+
if ( $action ) {
|
167 |
+
$msg = $this->get_message($action);
|
168 |
+
if ( ! empty($msg) ) {
|
169 |
+
|
170 |
+
}
|
171 |
+
}
|
172 |
+
}
|
173 |
+
}
|
174 |
+
/* Views */
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Adds settings section for plugin functionality
|
178 |
+
* Section is added to specified admin section/menu
|
179 |
+
* @uses `admin_init` hook
|
180 |
+
*/
|
181 |
+
function init_menus() {
|
182 |
+
//Add top level menus (when necessary)
|
183 |
+
/**
|
184 |
+
* @var SLB_Admin_Menu
|
185 |
+
*/
|
186 |
+
$menu;
|
187 |
+
foreach ( $this->menus as $menu ) {
|
188 |
+
//Register menu
|
189 |
+
$hook = add_menu_page($menu->get_label('title'), $menu->get_label('menu'), $menu->get_capability(), $menu->get_id(), $menu->get_callback());
|
190 |
+
//Add hook to menu object
|
191 |
+
$menu->set_hookname($hook);
|
192 |
+
$this->menus[$menu->get_id_raw()] =& $menu;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* @var SLB_Admin_Page
|
197 |
+
*/
|
198 |
+
$page;
|
199 |
+
//Add subpages
|
200 |
+
foreach ( $this->pages as $page ) {
|
201 |
+
//Build Arguments
|
202 |
+
$args = array ( $page->get_label('header'), $page->get_label('menu'), $page->get_capability(), $page->get_id(), $page->get_callback() );
|
203 |
+
$f = null;
|
204 |
+
//Handle pages for default WP menus
|
205 |
+
if ( $page->is_parent_wp() ) {
|
206 |
+
$f = 'add_' . $page->get_parent() . '_page';
|
207 |
+
}
|
208 |
+
|
209 |
+
//Handle pages for custom menus
|
210 |
+
if ( ! function_exists($f) ) {
|
211 |
+
array_unshift( $args, $page->get_parent() );
|
212 |
+
$f = 'add_submenu_page';
|
213 |
+
}
|
214 |
+
|
215 |
+
//Add admin page
|
216 |
+
$hook = call_user_func_array($f, $args);
|
217 |
+
//Save hook to page properties
|
218 |
+
$page->set_hookname($hook);
|
219 |
+
$this->pages[$page->get_id_raw()] =& $page;
|
220 |
+
}
|
221 |
+
|
222 |
+
//Add sections
|
223 |
+
/**
|
224 |
+
* @var SLB_Admin_Section
|
225 |
+
*/
|
226 |
+
$section;
|
227 |
+
foreach ( $this->sections as $section ) {
|
228 |
+
add_settings_section($section->get_id(), $section->get_title(), $section->get_callback(), $section->get_parent());
|
229 |
+
if ( $section->is_options_valid() )
|
230 |
+
register_setting($section->get_parent(), $section->get_id(), $section->get_options()->m('validate'));
|
231 |
+
}
|
232 |
+
}
|
233 |
+
|
234 |
+
|
235 |
+
/* Methods */
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Add a new view
|
239 |
+
* @param string $type View type
|
240 |
+
* @param string $id Unique view ID
|
241 |
+
* @param array $args Arguments to pass to view constructor
|
242 |
+
* @return int|bool View ID (FALSE if view was not properly initialized)
|
243 |
+
*/
|
244 |
+
private function add_view($type, $id, $args) {
|
245 |
+
//Validate request
|
246 |
+
$class = $this->add_prefix('admin_' . $type);
|
247 |
+
$collection = $type . 's';
|
248 |
+
if ( !class_exists($class) || !property_exists($this, $collection) || !is_array($this->{$collection}) )
|
249 |
+
return false;
|
250 |
+
//Create new instance
|
251 |
+
$r = new ReflectionClass($class);
|
252 |
+
$view =& $r->newInstanceArgs($args);
|
253 |
+
if ( $view->is_valid() )
|
254 |
+
$this->{$collection}[$id] =& $view;
|
255 |
+
else
|
256 |
+
$id = false;
|
257 |
+
unset($view, $r);
|
258 |
+
return $id;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Add reset option to plugin action links
|
263 |
+
* @param string $id Unique ID
|
264 |
+
* @param array $labels Text for reset instance
|
265 |
+
* > title - Link text (also title attribute value)
|
266 |
+
* > confirm - Confirmation message
|
267 |
+
* > success - Success message
|
268 |
+
* > failure - Failure message
|
269 |
+
* @param SLB_Options|array $options Options instance (or instance + specific groups)
|
270 |
+
*/
|
271 |
+
function add_reset($id, $labels, $options) {
|
272 |
+
$args = func_get_args();
|
273 |
+
return $this->add_view('reset', $id, $args);
|
274 |
+
}
|
275 |
+
|
276 |
+
/*-** Menus **-*/
|
277 |
+
|
278 |
+
/**
|
279 |
+
* Adds custom admin panel
|
280 |
+
* @param string $id Menu ID
|
281 |
+
* @param string|array $labels Text labels
|
282 |
+
* @param int $pos (optional) Menu position in navigation (index order)
|
283 |
+
* @return string Menu ID
|
284 |
+
*/
|
285 |
+
function add_menu($id, $labels, $position = null) {
|
286 |
+
$args = array ( $id, $labels, null, null, null, $position );
|
287 |
+
return $this->add_view('menu', $id, $args);
|
288 |
+
}
|
289 |
+
|
290 |
+
/* Page */
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Add admin page
|
294 |
+
* @uses this->pages
|
295 |
+
* @param string $id Page ID (unique)
|
296 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
297 |
+
* > menu: Menu title
|
298 |
+
* > header: Page header
|
299 |
+
* @param string $menu Menu ID to add page to
|
300 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
301 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
302 |
+
* @param callback $callback (optional) Callback for custom page building
|
303 |
+
* @param string $capability (optional) Custom capability for accessing page
|
304 |
+
* @return string Page ID
|
305 |
+
*/
|
306 |
+
function add_page($id, $parent, $labels, $options = null, $callback = null, $capability = null) {
|
307 |
+
$args = func_get_args();
|
308 |
+
wp_enqueue_script('postbox');
|
309 |
+
return $this->add_view('page', $id, $args);
|
310 |
+
}
|
311 |
+
|
312 |
+
/* WP Pages */
|
313 |
+
|
314 |
+
/**
|
315 |
+
* Add admin page to a standard WP menu
|
316 |
+
* @uses this->add_page()
|
317 |
+
* @param string $id Page ID (unique)
|
318 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
319 |
+
* > menu: Menu title
|
320 |
+
* > header: Page header
|
321 |
+
* @param string $menu Name of WP menu to add page to
|
322 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
323 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
324 |
+
* @param callback $callback (optional) Callback for custom page building
|
325 |
+
* @param string $capability (optional) Custom capability for accessing page
|
326 |
+
* @return string Page ID
|
327 |
+
*/
|
328 |
+
function add_wp_page($id, $parent, $labels, $options = null, $callback = null, $capability = null) {
|
329 |
+
//Add page
|
330 |
+
$pid = $this->add_page($id, $parent, $labels, $options, $callback, $capability);
|
331 |
+
//Set parent as WP
|
332 |
+
if ( $pid ) {
|
333 |
+
$this->pages[$pid]->set_parent_wp();
|
334 |
+
}
|
335 |
+
return $pid;
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* Add admin page to Dashboard menu
|
340 |
+
* @see add_dashboard_page()
|
341 |
+
* @uses this->add_wp_page()
|
342 |
+
* @param string $id Page ID (unique)
|
343 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
344 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
345 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
346 |
+
* @param callback $callback (optional) Callback for custom page building
|
347 |
+
* @param string $capability (optional) Custom capability for accessing page
|
348 |
+
* @return string Page ID
|
349 |
+
*/
|
350 |
+
function add_dashboard_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
351 |
+
$id = $this->add_wp_page($id, 'dashboard', $labels, $options, $callback, $capability);
|
352 |
+
return $id;
|
353 |
+
}
|
354 |
+
|
355 |
+
/**
|
356 |
+
* Add admin page to Comments menu
|
357 |
+
* @see add_comments_page()
|
358 |
+
* @uses this->add_wp_page()
|
359 |
+
* @param string $id Page ID (unique)
|
360 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
361 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
362 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
363 |
+
* @param callback $callback (optional) Callback for custom page building
|
364 |
+
* @param string $capability (optional) Custom capability for accessing page
|
365 |
+
* @return string Page ID
|
366 |
+
*/
|
367 |
+
function add_comments_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
368 |
+
$id = $this->add_wp_page($id, 'comments', $labels, $options, $callback, $capability);
|
369 |
+
return $id;
|
370 |
+
}
|
371 |
+
|
372 |
+
/**
|
373 |
+
* Add admin page to Links menu
|
374 |
+
* @see add_links_page()
|
375 |
+
* @uses this->add_wp_page()
|
376 |
+
* @param string $id Page ID (unique)
|
377 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
378 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
379 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
380 |
+
* @param callback $callback (optional) Callback for custom page building
|
381 |
+
* @param string $capability (optional) Custom capability for accessing page
|
382 |
+
* @return string Page ID
|
383 |
+
*/
|
384 |
+
function add_links_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
385 |
+
$id = $this->add_wp_page($id, 'links', $labels, $options, $callback, $capability);
|
386 |
+
return $id;
|
387 |
+
}
|
388 |
+
|
389 |
+
|
390 |
+
/**
|
391 |
+
* Add admin page to Posts menu
|
392 |
+
* @see add_posts_page()
|
393 |
+
* @uses this->add_wp_page()
|
394 |
+
* @param string $id Page ID (unique)
|
395 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
396 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
397 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
398 |
+
* @param callback $callback (optional) Callback for custom page building
|
399 |
+
* @param string $capability (optional) Custom capability for accessing page
|
400 |
+
* @return string Page ID
|
401 |
+
*/
|
402 |
+
function add_posts_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
403 |
+
$id = $this->add_wp_page($id, 'posts', $labels, $options, $callback, $capability);
|
404 |
+
return $id;
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* Add admin page to Pages menu
|
409 |
+
* @see add_pages_page()
|
410 |
+
* @uses this->add_wp_page()
|
411 |
+
* @param string $id Page ID (unique)
|
412 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
413 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
414 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
415 |
+
* @param callback $callback (optional) Callback for custom page building
|
416 |
+
* @param string $capability (optional) Custom capability for accessing page
|
417 |
+
* @return string Page ID
|
418 |
+
*/
|
419 |
+
function add_pages_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
420 |
+
$id = $this->add_wp_page($id, 'pages', $labels, $options, $callback, $capability);
|
421 |
+
return $id;
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Add admin page to Media menu
|
426 |
+
* @see add_media_page()
|
427 |
+
* @uses this->add_wp_page()
|
428 |
+
* @param string $id Page ID (unique)
|
429 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
430 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
431 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
432 |
+
* @param callback $callback (optional) Callback for custom page building
|
433 |
+
* @param string $capability (optional) Custom capability for accessing page
|
434 |
+
* @return string Page ID
|
435 |
+
*/
|
436 |
+
function add_media_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
437 |
+
$id = $this->add_wp_page($id, 'media', $labels, $options, $callback, $capability);
|
438 |
+
return $id;
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Add admin page to Themes menu
|
443 |
+
* @see add_theme_page()
|
444 |
+
* @uses this->add_wp_page()
|
445 |
+
* @param string $id Page ID (unique)
|
446 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
447 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
448 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
449 |
+
* @param callback $callback (optional) Callback for custom page building
|
450 |
+
* @param string $capability (optional) Custom capability for accessing page
|
451 |
+
* @return string Page ID
|
452 |
+
*/
|
453 |
+
function add_theme_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
454 |
+
$id = $this->add_wp_page($id, 'theme', $labels, $options, $callback, $capability);
|
455 |
+
return $id;
|
456 |
+
}
|
457 |
+
|
458 |
+
/**
|
459 |
+
* Add admin page to Plugins menu
|
460 |
+
* @see add_plugins_page()
|
461 |
+
* @uses this->add_wp_page()
|
462 |
+
* @param string $id Page ID (unique)
|
463 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
464 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
465 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
466 |
+
* @param callback $callback (optional) Callback for custom page building
|
467 |
+
* @param string $capability (optional) Custom capability for accessing page
|
468 |
+
* @return string Page ID
|
469 |
+
*/
|
470 |
+
function add_plugins_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
471 |
+
$id = $this->add_wp_page($id, 'plugins', $labels, $options, $callback, $capability);
|
472 |
+
return $id;
|
473 |
+
}
|
474 |
+
|
475 |
+
/**
|
476 |
+
* Add admin page to Options menu
|
477 |
+
* @see add_options_page()
|
478 |
+
* @uses this->add_wp_page()
|
479 |
+
* @param string $id Page ID (unique)
|
480 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
481 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
482 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
483 |
+
* @param callback $callback (optional) Callback for custom page building
|
484 |
+
* @param string $capability (optional) Custom capability for accessing page
|
485 |
+
* @return string Page ID
|
486 |
+
*/
|
487 |
+
function add_options_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
488 |
+
$id = $this->add_wp_page($id, 'options', $labels, $options, $callback, $capability);
|
489 |
+
return $id;
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Add admin page to Tools menu
|
494 |
+
* @see add_management_page()
|
495 |
+
* @uses this->add_wp_page()
|
496 |
+
* @param string $id Page ID (unique)
|
497 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
498 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
499 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
500 |
+
* @param callback $callback (optional) Callback for custom page building
|
501 |
+
* @param string $capability (optional) Custom capability for accessing page
|
502 |
+
* @return string Page ID
|
503 |
+
*/
|
504 |
+
function add_management_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
505 |
+
$id = $this->add_wp_page($id, 'management', $labels, $options, $callback, $capability);
|
506 |
+
return $id;
|
507 |
+
}
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Add admin page to Users menu
|
511 |
+
* @uses this->add_wp_page()
|
512 |
+
* @param string $id Page ID (unique)
|
513 |
+
* @param string|array $labels Text labels (Associative array for multiple labels)
|
514 |
+
* @param obj|array $options (optional) Options object (Use array to define options object & specific group(s))
|
515 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
516 |
+
* @param callback $callback (optional) Callback for custom page building
|
517 |
+
* @param string $capability (optional) Custom capability for accessing page
|
518 |
+
* @return string Page ID
|
519 |
+
*/
|
520 |
+
function add_users_page($id, $labels, $options = null, $callback = null, $capability = null) {
|
521 |
+
$id = $this->add_wp_page($id, 'users', $labels, $options, $callback, $capability);
|
522 |
+
return $id;
|
523 |
+
}
|
524 |
+
|
525 |
+
/* Section */
|
526 |
+
|
527 |
+
/**
|
528 |
+
* Add section
|
529 |
+
* @uses this->sections
|
530 |
+
* @param string $id Unique section ID
|
531 |
+
* @param string $page Page ID
|
532 |
+
* @param string $labels Label text
|
533 |
+
* @param obj|array $options Options object (Use array to define options object & specific group(s))
|
534 |
+
* > Array Example: array($options, 'group_1') or array($options, array('group_1', 'group_3'))
|
535 |
+
* @param callback $callback (optional) Callback for custom building
|
536 |
+
* @return string Section ID
|
537 |
+
*/
|
538 |
+
function add_section($id, $parent, $labels, $options = null, $callback = null) {
|
539 |
+
$section = new SLB_Admin_Section($id, $parent, $labels, $options, $callback);
|
540 |
+
|
541 |
+
//Add Section
|
542 |
+
if ( $section->is_valid() )
|
543 |
+
$this->sections[$id] =& $section;
|
544 |
+
else
|
545 |
+
$id = false;
|
546 |
+
return $id;
|
547 |
+
}
|
548 |
+
|
549 |
+
/* Operations */
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Adds custom links below plugin on plugin listing page
|
553 |
+
* @uses `plugin_action_links_$plugin-name` Filter hook
|
554 |
+
* @param $actions
|
555 |
+
* @param $plugin_file
|
556 |
+
* @param $plugin_data
|
557 |
+
* @param $context
|
558 |
+
*/
|
559 |
+
function plugin_action_links($actions, $plugin_file, $plugin_data, $context) {
|
560 |
+
global $admin_page_hooks;
|
561 |
+
//Add link to settings (only if active)
|
562 |
+
if ( is_plugin_active($this->util->get_plugin_base_name()) ) {
|
563 |
+
/* Get Actions */
|
564 |
+
|
565 |
+
$acts = array();
|
566 |
+
$type = 'plugin_action';
|
567 |
+
|
568 |
+
/* Get view links */
|
569 |
+
foreach ( array('menus', 'pages', 'sections') as $views ) {
|
570 |
+
foreach ( $this->{$views} as $view ) {
|
571 |
+
if ( !$view->has_label($type) )
|
572 |
+
continue;
|
573 |
+
$acts[] = (object) array (
|
574 |
+
'id' => $views . '_' . $view->get_id(),
|
575 |
+
'label' => $view->get_label($type),
|
576 |
+
'uri' => $view->get_uri(),
|
577 |
+
'attributes' => array()
|
578 |
+
);
|
579 |
+
}
|
580 |
+
}
|
581 |
+
|
582 |
+
/* Get reset links */
|
583 |
+
$type = 'title';
|
584 |
+
foreach ( $this->resets as $reset ) {
|
585 |
+
if ( !$reset->has_label($type) )
|
586 |
+
continue;
|
587 |
+
$id = 'reset_' . $reset->get_id();
|
588 |
+
$acts[] = (object) array (
|
589 |
+
'id' => $id,
|
590 |
+
'label' => $reset->get_label($type),
|
591 |
+
'uri' => $reset->get_uri(),
|
592 |
+
'attributes' => $reset->get_link_attr()
|
593 |
+
);
|
594 |
+
}
|
595 |
+
|
596 |
+
//Add links
|
597 |
+
$links = array();
|
598 |
+
foreach ( $acts as $act ) {
|
599 |
+
$links[$act->id] = $this->util->build_html_link($act->uri, $act->label, $act->attributes);
|
600 |
+
}
|
601 |
+
|
602 |
+
//Add links
|
603 |
+
$actions = array_merge($links, $actions);
|
604 |
+
}
|
605 |
+
return $actions;
|
606 |
+
}
|
607 |
+
|
608 |
+
/*-** START: Refactor **-*/
|
609 |
+
|
610 |
+
/**
|
611 |
+
* Adds additional message for plugin updates
|
612 |
+
* @uses `in_plugin_update_message-$plugin-name` Action hook
|
613 |
+
* @uses this->plugin_update_get_message()
|
614 |
+
* @var array $plugin_data Current plugin data
|
615 |
+
* @var object $r Update response data
|
616 |
+
*/
|
617 |
+
function plugin_update_message($plugin_data, $r) {
|
618 |
+
if ( !isset($r->new_version) )
|
619 |
+
return false;
|
620 |
+
if ( stripos($r->new_version, 'beta') !== false ) {
|
621 |
+
$cls_notice = $this->add_prefix('notice');
|
622 |
+
echo '<br />' . $this->plugin_update_get_message($r);
|
623 |
+
}
|
624 |
+
}
|
625 |
+
|
626 |
+
/**
|
627 |
+
* Modify update plugins response data if necessary
|
628 |
+
* @uses `site_transient_update_plugins` Filter hook
|
629 |
+
* @uses this->plugin_update_get_message()
|
630 |
+
* @param obj $transient Transient data
|
631 |
+
* @return obj Modified transient data
|
632 |
+
*/
|
633 |
+
function plugin_update_transient($transient) {
|
634 |
+
$n = $this->util->get_plugin_base_name();
|
635 |
+
if ( isset($transient->response) && isset($transient->response[$n]) && is_object($transient->response[$n]) && !isset($transient->response[$n]->upgrade_notice) ) {
|
636 |
+
$r =& $transient->response[$n];
|
637 |
+
$r->upgrade_notice = $this->plugin_update_get_message($r);
|
638 |
+
}
|
639 |
+
return $transient;
|
640 |
+
}
|
641 |
+
|
642 |
+
/**
|
643 |
+
* Retrieve custom update message
|
644 |
+
* @uses this->get_message()
|
645 |
+
* @param obj $r Response data from plugin update API
|
646 |
+
* @return string Message (Default: empty string)
|
647 |
+
*/
|
648 |
+
function plugin_update_get_message($r) {
|
649 |
+
$msg = '';
|
650 |
+
$cls_notice = $this->add_prefix('notice');
|
651 |
+
if ( !is_object($r) || !isset($r->new_version) )
|
652 |
+
return $msg;
|
653 |
+
if ( stripos($r->new_version, 'beta') !== false ) {
|
654 |
+
$msg = sprintf($this->get_message('beta'), $cls_notice);
|
655 |
+
}
|
656 |
+
return $msg;
|
657 |
+
}
|
658 |
+
|
659 |
+
/*-** Messages **-*/
|
660 |
+
|
661 |
+
/**
|
662 |
+
* Retrieve stored messages
|
663 |
+
* @param string $msg_id Message ID
|
664 |
+
* @return string Message text
|
665 |
+
*/
|
666 |
+
function get_message($msg_id) {
|
667 |
+
$msg = '';
|
668 |
+
$msgs = $this->get_messages();
|
669 |
+
if ( is_string($msg_id) && isset($msgs[$msg_id]) ) {
|
670 |
+
$msg = $msgs[$msg_id];
|
671 |
+
}
|
672 |
+
return $msg;
|
673 |
+
}
|
674 |
+
|
675 |
+
/**
|
676 |
+
* Retrieve all messages
|
677 |
+
* Initializes messages if necessary
|
678 |
+
* @uses $messages
|
679 |
+
* @return array Messages
|
680 |
+
*/
|
681 |
+
function get_messages() {
|
682 |
+
if ( empty($this->messages) ) {
|
683 |
+
//Initialize messages if necessary
|
684 |
+
$this->messages = array(
|
685 |
+
'reset' => __('The settings have been reset', 'simple-lightbox'),
|
686 |
+
'beta' => __('<strong class="%1$s">Notice:</strong> This update is a <strong class="%1$s">Beta version</strong>. It is highly recommended that you test the update on a test server before updating the plugin on a production server.', 'simple-lightbox'),
|
687 |
+
'access_denied' => __('Access Denied', 'simple-lightbox'),
|
688 |
+
);
|
689 |
+
}
|
690 |
+
return $this->messages;
|
691 |
+
}
|
692 |
+
|
693 |
+
/**
|
694 |
+
* Set message text
|
695 |
+
* @uses this->messages
|
696 |
+
* @param string $id Message ID
|
697 |
+
* @param string $text Message text
|
698 |
+
*/
|
699 |
+
function set_message($id, $text) {
|
700 |
+
$this->messages[trim($id)] = $text;
|
701 |
+
}
|
702 |
+
/*-** END: Refactor **-*/
|
703 |
+
|
704 |
+
}
|
705 |
+
|
706 |
+
/**
|
707 |
+
* Admin View Base functionality
|
708 |
+
* Core functionality for Menus/Pages/Sections
|
709 |
+
* @package Simple Lightbox
|
710 |
+
* @subpackage Admin
|
711 |
+
* @author Archetyped
|
712 |
+
*/
|
713 |
+
class SLB_Admin_View extends SLB_Base {
|
714 |
+
/* Properties */
|
715 |
+
|
716 |
+
/**
|
717 |
+
* Unique ID
|
718 |
+
* @var string
|
719 |
+
*/
|
720 |
+
var $id = null;
|
721 |
+
|
722 |
+
/**
|
723 |
+
* Labels
|
724 |
+
* @var array (Associative)
|
725 |
+
*/
|
726 |
+
var $labels = array();
|
727 |
+
|
728 |
+
/**
|
729 |
+
* Options object to use
|
730 |
+
* @var SLB_Options
|
731 |
+
*/
|
732 |
+
var $options = null;
|
733 |
+
|
734 |
+
/**
|
735 |
+
* Option groups to use
|
736 |
+
* If empty, use entire options object
|
737 |
+
* @var array
|
738 |
+
*/
|
739 |
+
var $option_groups = array();
|
740 |
+
|
741 |
+
/**
|
742 |
+
* Option building arguments
|
743 |
+
* @var array
|
744 |
+
*/
|
745 |
+
var $option_args = array();
|
746 |
+
|
747 |
+
/**
|
748 |
+
* Function to handle building UI
|
749 |
+
* @var callback
|
750 |
+
*/
|
751 |
+
var $callback = null;
|
752 |
+
|
753 |
+
/**
|
754 |
+
* Capability for access control
|
755 |
+
* @var string
|
756 |
+
*/
|
757 |
+
var $capability = 'manage_options';
|
758 |
+
|
759 |
+
/**
|
760 |
+
* Icon to use
|
761 |
+
* @var string
|
762 |
+
*/
|
763 |
+
var $icon = null;
|
764 |
+
|
765 |
+
/**
|
766 |
+
* View parent ID/Slug
|
767 |
+
* @var string
|
768 |
+
*/
|
769 |
+
var $parent = null;
|
770 |
+
|
771 |
+
/**
|
772 |
+
* Whether parent is a custom view or a default WP one
|
773 |
+
* @var bool
|
774 |
+
*/
|
775 |
+
var $parent_custom = true;
|
776 |
+
|
777 |
+
/**
|
778 |
+
* If view requires a parent
|
779 |
+
* @var bool
|
780 |
+
*/
|
781 |
+
var $parent_required = false;
|
782 |
+
|
783 |
+
/**
|
784 |
+
* WP-Generated hook name for view
|
785 |
+
* @var string
|
786 |
+
*/
|
787 |
+
var $hookname = null;
|
788 |
+
|
789 |
+
/**
|
790 |
+
* Messages to be displayed
|
791 |
+
* Indexed Array
|
792 |
+
* @var array
|
793 |
+
*/
|
794 |
+
var $messages = array();
|
795 |
+
|
796 |
+
/**
|
797 |
+
* Required properties
|
798 |
+
* Associative array
|
799 |
+
* > Key: Property name
|
800 |
+
* > Value: Required data type
|
801 |
+
* @var array
|
802 |
+
*/
|
803 |
+
protected $required = array();
|
804 |
+
|
805 |
+
/**
|
806 |
+
* Default required properties
|
807 |
+
* Merged into $required array with this->init_required()
|
808 |
+
* @see this->required for more information
|
809 |
+
* @var array
|
810 |
+
*/
|
811 |
+
protected $_required = array ( 'id' => 'string', 'labels' => 'array' );
|
812 |
+
|
813 |
+
/* Init */
|
814 |
+
|
815 |
+
function __construct($id, $labels, $options = null, $callback = null, $capability = null, $icon = null) {
|
816 |
+
parent::__construct();
|
817 |
+
|
818 |
+
$this->init_required();
|
819 |
+
$this->set_id($id);
|
820 |
+
$this->set_labels($labels);
|
821 |
+
$this->set_options($options);
|
822 |
+
$this->set_callback($callback);
|
823 |
+
$this->set_capability($capability);
|
824 |
+
$this->set_icon($icon);
|
825 |
+
}
|
826 |
+
|
827 |
+
function init_required() {
|
828 |
+
$this->required = array_merge($this->_required, $this->required);
|
829 |
+
//Check for parent requirement
|
830 |
+
if ( $this->parent_required )
|
831 |
+
$this->required['parent'] = 'string';
|
832 |
+
}
|
833 |
+
|
834 |
+
/* Property Methods */
|
835 |
+
|
836 |
+
/**
|
837 |
+
* Retrieve ID (Formatted by default)
|
838 |
+
* @param bool $formatted (optional) Whether ID should be formatted for external use or not
|
839 |
+
* @return string ID
|
840 |
+
*/
|
841 |
+
function get_id($formatted = true) {
|
842 |
+
$id = $this->id;
|
843 |
+
if ( $formatted )
|
844 |
+
$this->add_prefix_ref($id);
|
845 |
+
return $id;
|
846 |
+
}
|
847 |
+
|
848 |
+
/**
|
849 |
+
* Retrieve raw ID
|
850 |
+
* @return string Raw ID
|
851 |
+
*/
|
852 |
+
function get_id_raw() {
|
853 |
+
return $this->get_id(false);
|
854 |
+
}
|
855 |
+
|
856 |
+
/**
|
857 |
+
* Set ID
|
858 |
+
* @param string ID
|
859 |
+
*/
|
860 |
+
function set_id($id) {
|
861 |
+
if ( is_scalar($id) ) {
|
862 |
+
$this->id = trim(strval($id));
|
863 |
+
return true;
|
864 |
+
}
|
865 |
+
return false;
|
866 |
+
}
|
867 |
+
|
868 |
+
/**
|
869 |
+
* Retrieve label
|
870 |
+
* Uses first label (or default if defined) if specified type does not exist
|
871 |
+
* @param string $type Label type to retrieve
|
872 |
+
* @param string $default (optional) Default value if label type does not exist
|
873 |
+
* @return string Label text
|
874 |
+
*/
|
875 |
+
function get_label($type, $default = null) {
|
876 |
+
//Retrieve existing label type
|
877 |
+
if ( $this->has_label($type) )
|
878 |
+
return $this->labels[$type];
|
879 |
+
//Use default label if type is not set
|
880 |
+
if ( empty($default) && !empty($this->labels) ) {
|
881 |
+
reset($this->labels);
|
882 |
+
$default = current($this->labels);
|
883 |
+
}
|
884 |
+
|
885 |
+
return ( empty($default) ) ? '' : $default;
|
886 |
+
}
|
887 |
+
|
888 |
+
/**
|
889 |
+
* Set text labels
|
890 |
+
* @param array|string $labels
|
891 |
+
*/
|
892 |
+
function set_labels($labels) {
|
893 |
+
if ( empty($labels) )
|
894 |
+
return false;
|
895 |
+
//Single string
|
896 |
+
if ( is_string($labels) ) {
|
897 |
+
$labels = array ( $labels );
|
898 |
+
}
|
899 |
+
|
900 |
+
//Array
|
901 |
+
if ( is_array($labels) ) {
|
902 |
+
//Merge with existing labels
|
903 |
+
if ( empty($this->labels) || !is_array($this->labels) ) {
|
904 |
+
$this->labels = array();
|
905 |
+
}
|
906 |
+
$this->labels = array_merge($this->labels, $labels);
|
907 |
+
}
|
908 |
+
}
|
909 |
+
|
910 |
+
/**
|
911 |
+
* Set single text label
|
912 |
+
* @uses this->set_labels()
|
913 |
+
* @param string $type Label type to set
|
914 |
+
* @param string $value Label value
|
915 |
+
*/
|
916 |
+
function set_label($type, $value) {
|
917 |
+
if ( is_string($type) && is_string($value) ) {
|
918 |
+
$label = array( $type => $value );
|
919 |
+
$this->set_labels($label);
|
920 |
+
}
|
921 |
+
}
|
922 |
+
|
923 |
+
/**
|
924 |
+
* Checks if specified label is set on view
|
925 |
+
* @param string $type Label type
|
926 |
+
* @return bool TRUE if label exists, FALSE otherwise
|
927 |
+
*/
|
928 |
+
function has_label($type) {
|
929 |
+
return ( isset($this->labels[$type]) );
|
930 |
+
}
|
931 |
+
|
932 |
+
/**
|
933 |
+
* Retrieve instance options
|
934 |
+
* @return SLB_Options Options instance
|
935 |
+
*/
|
936 |
+
function &get_options() {
|
937 |
+
return $this->options;
|
938 |
+
}
|
939 |
+
|
940 |
+
/**
|
941 |
+
* Set options object
|
942 |
+
* @param obj|array $options Options instance
|
943 |
+
* > If array, Options instance and specific groups are specified
|
944 |
+
* > 0: Options instance
|
945 |
+
* > 1: Group(s)
|
946 |
+
*/
|
947 |
+
function set_options($options) {
|
948 |
+
if ( empty($options) )
|
949 |
+
return false;
|
950 |
+
|
951 |
+
$groups = null;
|
952 |
+
|
953 |
+
if ( is_array($options) ) {
|
954 |
+
$options = array_values($options);
|
955 |
+
//Set option groups
|
956 |
+
if ( isset($options[1]) ) {
|
957 |
+
$groups = $options[1];
|
958 |
+
}
|
959 |
+
//Set options object
|
960 |
+
$options =& $options[0];
|
961 |
+
}
|
962 |
+
|
963 |
+
if ( $this->util->is_a($options, 'Options') ) {
|
964 |
+
//Save options
|
965 |
+
$this->options =& $options;
|
966 |
+
|
967 |
+
//Save option groups for valid options
|
968 |
+
$this->set_option_groups($groups);
|
969 |
+
}
|
970 |
+
}
|
971 |
+
|
972 |
+
/**
|
973 |
+
* Set option groups
|
974 |
+
* @param string|array $groups Specified group(s)
|
975 |
+
*/
|
976 |
+
function set_option_groups($groups) {
|
977 |
+
if ( empty($groups) )
|
978 |
+
return false;
|
979 |
+
|
980 |
+
//Validate data
|
981 |
+
if ( !is_array($groups) ) {
|
982 |
+
if ( is_scalar($groups) ) {
|
983 |
+
$groups = array(strval($groups));
|
984 |
+
}
|
985 |
+
}
|
986 |
+
|
987 |
+
if ( is_array($groups) ) {
|
988 |
+
$this->option_groups = $groups;
|
989 |
+
}
|
990 |
+
}
|
991 |
+
|
992 |
+
/**
|
993 |
+
* Retrieve view messages
|
994 |
+
* @return array Messages
|
995 |
+
*/
|
996 |
+
function &get_messages() {
|
997 |
+
if ( !is_array($this->messages) )
|
998 |
+
$this->messages = array();
|
999 |
+
return $this->messages;
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
/**
|
1003 |
+
* Save message
|
1004 |
+
* @param string $text Message text
|
1005 |
+
*/
|
1006 |
+
function set_message($text) {
|
1007 |
+
$msgs =& $this->get_messages();
|
1008 |
+
$text = trim($text);
|
1009 |
+
if ( empty($msgs) && !empty($text) )
|
1010 |
+
$this->util->add_filter('admin_messages', $this->m('do_messages'));
|
1011 |
+
$msgs[] = $text;
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
/**
|
1015 |
+
* Add messages to array
|
1016 |
+
* Called by internal `admin_messages` filter hook
|
1017 |
+
* @param array $msgs Aggregated messages
|
1018 |
+
* @return array Merged messages array
|
1019 |
+
*/
|
1020 |
+
function do_messages($msgs = array()) {
|
1021 |
+
$m =& $this->get_messages();
|
1022 |
+
if ( !empty($m) )
|
1023 |
+
$msgs = array_merge($msgs, $m);
|
1024 |
+
return $msgs;
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
/**
|
1028 |
+
* Retrieve view callback
|
1029 |
+
* @return callback Callback
|
1030 |
+
*/
|
1031 |
+
function get_callback() {
|
1032 |
+
return ( $this->has_callback() ) ? $this->callback : $this->m('handle');
|
1033 |
+
}
|
1034 |
+
|
1035 |
+
/**
|
1036 |
+
* Set callback function for building item
|
1037 |
+
* @param callback $callback Callback function to use
|
1038 |
+
*/
|
1039 |
+
function set_callback($callback) {
|
1040 |
+
if ( is_callable($callback) )
|
1041 |
+
$this->callback = $callback;
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
function has_callback() {
|
1045 |
+
return ( !empty($this->callback) ) ? true : false;
|
1046 |
+
}
|
1047 |
+
|
1048 |
+
function do_callback() {
|
1049 |
+
call_user_func($this->get_callback());
|
1050 |
+
}
|
1051 |
+
|
1052 |
+
/**
|
1053 |
+
* Retrieve capability
|
1054 |
+
* @return string Capability
|
1055 |
+
*/
|
1056 |
+
function get_capability() {
|
1057 |
+
return $this->capability;
|
1058 |
+
}
|
1059 |
+
|
1060 |
+
/**
|
1061 |
+
* Set capability for access control
|
1062 |
+
* @param string $capability Capability
|
1063 |
+
*/
|
1064 |
+
function set_capability($capability) {
|
1065 |
+
if ( is_string($capability) && !empty($capability) )
|
1066 |
+
$this->capability = $capability;
|
1067 |
+
}
|
1068 |
+
|
1069 |
+
/**
|
1070 |
+
* Set icon
|
1071 |
+
* @param string $icon Icon URI
|
1072 |
+
*/
|
1073 |
+
function set_icon($icon) {
|
1074 |
+
if ( !empty($icon) && is_string($icon) )
|
1075 |
+
$this->icon = $icon;
|
1076 |
+
}
|
1077 |
+
|
1078 |
+
function get_hookname() {
|
1079 |
+
return ( empty($this->hookname) ) ? '' : $this->hookname;
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
/**
|
1083 |
+
* Set hookname
|
1084 |
+
* @param string $hookname Hookname value
|
1085 |
+
*/
|
1086 |
+
function set_hookname($hookname) {
|
1087 |
+
if ( !empty($hookname) && is_string($hookname) )
|
1088 |
+
$this->hookname = $hookname;
|
1089 |
+
}
|
1090 |
+
|
1091 |
+
/**
|
1092 |
+
* Retrieve parent
|
1093 |
+
* Formats parent ID for custom parents
|
1094 |
+
* @return string Parent ID
|
1095 |
+
*/
|
1096 |
+
function get_parent() {
|
1097 |
+
$parent = $this->parent;
|
1098 |
+
return ( $this->is_parent_custom() ) ? $this->add_prefix($parent) : $parent;
|
1099 |
+
}
|
1100 |
+
|
1101 |
+
/**
|
1102 |
+
* Set parent for view
|
1103 |
+
* @param string $parent Parent ID
|
1104 |
+
*/
|
1105 |
+
function set_parent($parent) {
|
1106 |
+
if ( $this->parent_required ) {
|
1107 |
+
if ( !empty($parent) && is_string($parent) )
|
1108 |
+
$this->parent = $parent;
|
1109 |
+
} else {
|
1110 |
+
$this->parent = null;
|
1111 |
+
}
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
/**
|
1115 |
+
* Specify whether parent is a custom view or a WP view
|
1116 |
+
* @param bool $custom (optional) TRUE if custom, FALSE if WP
|
1117 |
+
*/
|
1118 |
+
function set_parent_custom($custom = true) {
|
1119 |
+
if ( $this->parent_required ) {
|
1120 |
+
$this->parent_custom = !!$custom;
|
1121 |
+
}
|
1122 |
+
}
|
1123 |
+
|
1124 |
+
/**
|
1125 |
+
* Set parent as WP view
|
1126 |
+
* @uses this->set_parent_custom()
|
1127 |
+
*/
|
1128 |
+
function set_parent_wp() {
|
1129 |
+
$this->set_parent_custom(false);
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
/**
|
1133 |
+
* Get view URI
|
1134 |
+
* URI Structures:
|
1135 |
+
* > Top Level Menus: admin.php?page={menu_id}
|
1136 |
+
* > Pages: [parent_page_file.php|admin.php]?page={page_id}
|
1137 |
+
* > Section: [parent_menu_uri]#{section_id}
|
1138 |
+
*
|
1139 |
+
* @uses $admin_page_hooks to determine if page is child of default WP page
|
1140 |
+
* @return string Object URI
|
1141 |
+
*/
|
1142 |
+
function get_uri($file = null, $format = null) {
|
1143 |
+
static $page_hooks = null;
|
1144 |
+
$uri = '';
|
1145 |
+
if ( empty($file) )
|
1146 |
+
$file = 'admin.php';
|
1147 |
+
if ( $this->is_child() ) {
|
1148 |
+
$parent = str_replace('_page_' . $this->get_id(), '', $this->get_hookname());
|
1149 |
+
if ( is_null($page_hooks) ) {
|
1150 |
+
$page_hooks = array_flip($GLOBALS['admin_page_hooks']);
|
1151 |
+
}
|
1152 |
+
if ( isset($page_hooks[$parent]) )
|
1153 |
+
$file = $page_hooks[$parent];
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
if ( empty($format) ) {
|
1157 |
+
$delim = ( strpos($file, '?') === false ) ? '?' : '&';
|
1158 |
+
$format = '%1$s' . $delim . 'page=%2$s';
|
1159 |
+
}
|
1160 |
+
$uri = sprintf($format, $file, $this->get_id());
|
1161 |
+
|
1162 |
+
return $uri;
|
1163 |
+
}
|
1164 |
+
|
1165 |
+
/* Handlers */
|
1166 |
+
|
1167 |
+
/**
|
1168 |
+
* Default View handler
|
1169 |
+
* Used as callback when none set
|
1170 |
+
*/
|
1171 |
+
function handle() {}
|
1172 |
+
|
1173 |
+
/* Validation */
|
1174 |
+
|
1175 |
+
/**
|
1176 |
+
* Check if instance is valid based on required properties/data types
|
1177 |
+
* @return bool TRUE if valid, FALSE if not valid
|
1178 |
+
*/
|
1179 |
+
function is_valid() {
|
1180 |
+
$valid = true;
|
1181 |
+
foreach ( $this->required as $prop => $type ) {
|
1182 |
+
if ( empty($this->{$prop} )
|
1183 |
+
|| ( !empty($type) && is_string($type) && ( $f = 'is_' . $type ) && function_exists($f) && !$f($this->{$prop}) ) ) {
|
1184 |
+
$valid = false;
|
1185 |
+
break;
|
1186 |
+
}
|
1187 |
+
}
|
1188 |
+
return $valid;
|
1189 |
+
}
|
1190 |
+
|
1191 |
+
function is_child() {
|
1192 |
+
return $this->parent_required;
|
1193 |
+
}
|
1194 |
+
|
1195 |
+
function is_parent_custom() {
|
1196 |
+
return ( $this->is_child() && $this->parent_custom ) ? true : false;
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
function is_parent_wp() {
|
1200 |
+
return ( $this->is_child() && !$this->parent_custom ) ? true : false;
|
1201 |
+
}
|
1202 |
+
|
1203 |
+
function is_options_valid() {
|
1204 |
+
return ( is_object($this->get_options()) && $this->util->is_a($this->get_options(), $this->util->get_class('Options')) ) ? true : false;
|
1205 |
+
}
|
1206 |
+
|
1207 |
+
/* Options */
|
1208 |
+
|
1209 |
+
/**
|
1210 |
+
* Parse options build vars
|
1211 |
+
* @uses `options_parse_build_vars` filter hook
|
1212 |
+
*/
|
1213 |
+
function options_parse_build_vars($vars, $opts) {
|
1214 |
+
//Handle form submission
|
1215 |
+
if ( isset($_REQUEST[$opts->get_id('formatted')]) ) {
|
1216 |
+
$vars['validate_pre'] = $vars['save_pre'] = true;
|
1217 |
+
}
|
1218 |
+
return $vars;
|
1219 |
+
}
|
1220 |
+
|
1221 |
+
function options_build_pre(&$opts) {
|
1222 |
+
//Build form output
|
1223 |
+
$form_id = $this->add_prefix('admin_form_' . $this->get_id_raw());
|
1224 |
+
?>
|
1225 |
+
<form id="<?php esc_attr_e($form_id); ?>" name="<?php esc_attr_e($form_id); ?>" action="" method="post">
|
1226 |
+
<?php
|
1227 |
+
}
|
1228 |
+
|
1229 |
+
function options_build_post(&$opts) {
|
1230 |
+
submit_button();
|
1231 |
+
?>
|
1232 |
+
</form>
|
1233 |
+
<?php
|
1234 |
+
}
|
1235 |
+
|
1236 |
+
/**
|
1237 |
+
* Builds option groups output
|
1238 |
+
* @param SLB_Options $options Options instance
|
1239 |
+
* @param array $groups Groups to build
|
1240 |
+
*/
|
1241 |
+
function options_build_groups($options, $groups) {
|
1242 |
+
//Add meta box for each group
|
1243 |
+
$screen = get_current_screen();
|
1244 |
+
foreach ( $groups as $gid ) {
|
1245 |
+
$g = $options->get_group($gid);
|
1246 |
+
if ( !count($options->get_items($gid)) ) {
|
1247 |
+
continue;
|
1248 |
+
}
|
1249 |
+
add_meta_box($gid, $g->title, $this->m('options_build_group'), $screen, 'normal', 'default', array('options' => $options, 'group' => $gid));
|
1250 |
+
}
|
1251 |
+
//Build options
|
1252 |
+
do_meta_boxes($screen, 'normal', null);
|
1253 |
+
}
|
1254 |
+
|
1255 |
+
function options_build_group($obj, $args) {
|
1256 |
+
$args = $args['args'];
|
1257 |
+
$group = $args['group'];
|
1258 |
+
$opts = $args['options'];
|
1259 |
+
$opts->build_group($group);
|
1260 |
+
}
|
1261 |
+
|
1262 |
+
function show_options($show_submit = true) {
|
1263 |
+
//Build options output
|
1264 |
+
if ( !$this->is_options_valid() ) {
|
1265 |
+
return false;
|
1266 |
+
}
|
1267 |
+
/**
|
1268 |
+
* @var SLB_Options
|
1269 |
+
*/
|
1270 |
+
$opts =& $this->get_options();
|
1271 |
+
$hooks = array (
|
1272 |
+
'filter' => array (
|
1273 |
+
'parse_build_vars' => array( $this->m('options_parse_build_vars'), 10, 2 )
|
1274 |
+
),
|
1275 |
+
'action' => array (
|
1276 |
+
'build_pre' => array( $this->m('options_build_pre') ),
|
1277 |
+
'build_post' => array ( $this->m('options_build_post') ),
|
1278 |
+
)
|
1279 |
+
);
|
1280 |
+
//Add hooks
|
1281 |
+
foreach ( $hooks as $type => $hook ) {
|
1282 |
+
$m = 'add_' . $type;
|
1283 |
+
foreach ( $hook as $tag => $args ) {
|
1284 |
+
array_unshift($args, $tag);
|
1285 |
+
call_user_func_array($opts->util->m($m), $args);
|
1286 |
+
}
|
1287 |
+
}
|
1288 |
+
?>
|
1289 |
+
<div class="metabox-holder">
|
1290 |
+
<?php
|
1291 |
+
//Build output
|
1292 |
+
$opts->build(array('build_groups' => $this->m('options_build_groups')));
|
1293 |
+
?>
|
1294 |
+
</div>
|
1295 |
+
<?php
|
1296 |
+
//Remove hooks
|
1297 |
+
foreach ( $hooks as $type => $hook ) {
|
1298 |
+
$m = 'remove_' . $type;
|
1299 |
+
foreach ( $hook as $tag => $args ) {
|
1300 |
+
call_user_func($opts->util->m($m), $tag, $args[0]);
|
1301 |
+
}
|
1302 |
+
}
|
1303 |
+
}
|
1304 |
+
|
1305 |
+
/* UI Elements */
|
1306 |
+
|
1307 |
+
/**
|
1308 |
+
* Build submit button element
|
1309 |
+
* @param string $text (optional) Button text
|
1310 |
+
* @param string $id (optional) Button ID (prefixed on output)
|
1311 |
+
* @param object $parent (optional) Page/Section object that contains button
|
1312 |
+
* @return object Button properties (id, output)
|
1313 |
+
*/
|
1314 |
+
function get_button_submit($text = null, $id = null, $parent = null) {
|
1315 |
+
//Format values
|
1316 |
+
if ( !is_string($text) || empty($text) )
|
1317 |
+
$text = __('Save Changes');
|
1318 |
+
if ( is_object($parent) && isset($parent->id) )
|
1319 |
+
$parent = $parent->id . '_';
|
1320 |
+
else
|
1321 |
+
$parent = '';
|
1322 |
+
if ( !is_string($id) || empty($id) )
|
1323 |
+
$id = 'submit';
|
1324 |
+
$id = $this->add_prefix($parent . $id);
|
1325 |
+
//Build HTML
|
1326 |
+
$out = $this->util->build_html_element(array(
|
1327 |
+
'tag' => 'input',
|
1328 |
+
'wrap' => false,
|
1329 |
+
'attributes' => array(
|
1330 |
+
'type' => 'submit',
|
1331 |
+
'class' => 'button-primary',
|
1332 |
+
'id' => $id,
|
1333 |
+
'name' => $id,
|
1334 |
+
'value' => $text
|
1335 |
+
)
|
1336 |
+
));
|
1337 |
+
$out = '<p class="submit">' . $out . '</p>';
|
1338 |
+
$ret = new stdClass;
|
1339 |
+
$ret->id = $id;
|
1340 |
+
$ret->output = $out;
|
1341 |
+
return $ret;
|
1342 |
+
}
|
1343 |
+
|
1344 |
+
/**
|
1345 |
+
* Output submit button element
|
1346 |
+
* @param string $text (optional) Button text
|
1347 |
+
* @param string $id (optional) Button ID (prefixed on output)
|
1348 |
+
* @param object $parent (optional) Page/Section object that contains button
|
1349 |
+
* @return object Button properties (id, output)
|
1350 |
+
*/
|
1351 |
+
function button_submit($text = null, $id = null, $parent = null) {
|
1352 |
+
$btn = $this->get_button_submit($text, $id, $parent);
|
1353 |
+
echo $btn->output;
|
1354 |
+
return $btn;
|
1355 |
+
}
|
1356 |
+
}
|
1357 |
+
|
1358 |
+
/**
|
1359 |
+
* Admin Menu functionality
|
1360 |
+
* @package Simple Lightbox
|
1361 |
+
* @subpackage Admin
|
1362 |
+
* @author Archetyped
|
1363 |
+
*/
|
1364 |
+
class SLB_Admin_Menu extends SLB_Admin_View {
|
1365 |
+
/* Properties */
|
1366 |
+
|
1367 |
+
/**
|
1368 |
+
* Menu position
|
1369 |
+
* @var int
|
1370 |
+
*/
|
1371 |
+
var $position = null;
|
1372 |
+
|
1373 |
+
/* Init */
|
1374 |
+
|
1375 |
+
function __construct($id, $labels, $options = null, $callback = null, $capability = null, $icon = null, $position = null) {
|
1376 |
+
//Default
|
1377 |
+
parent::__construct($id, $labels, $options, $callback, $capability, $icon);
|
1378 |
+
//Class specific
|
1379 |
+
$this->set_position($position);
|
1380 |
+
}
|
1381 |
+
|
1382 |
+
/* Getters/Setters */
|
1383 |
+
|
1384 |
+
function set_position($position) {
|
1385 |
+
if ( is_int($position) )
|
1386 |
+
$this->position = $position;
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
/* Handlers */
|
1390 |
+
|
1391 |
+
function handle() {
|
1392 |
+
if ( !current_user_can($this->get_capability()) )
|
1393 |
+
wp_die(__('Access Denied', 'simple-lightbox'));
|
1394 |
+
?>
|
1395 |
+
<div class="wrap">
|
1396 |
+
<h2><?php esc_html_e( $this->get_label('header') ); ?></h2>
|
1397 |
+
<?php
|
1398 |
+
$this->show_options();
|
1399 |
+
?>
|
1400 |
+
</div>
|
1401 |
+
<?php
|
1402 |
+
}
|
1403 |
+
}
|
1404 |
+
|
1405 |
+
/**
|
1406 |
+
* Admin Page functionality
|
1407 |
+
* @package Simple Lightbox
|
1408 |
+
* @subpackage Admin
|
1409 |
+
* @author Archetyped
|
1410 |
+
*/
|
1411 |
+
class SLB_Admin_Page extends SLB_Admin_View {
|
1412 |
+
/* Properties */
|
1413 |
+
|
1414 |
+
var $parent_required = true;
|
1415 |
+
|
1416 |
+
/* Init */
|
1417 |
+
|
1418 |
+
function __construct($id, $parent, $labels, $options = null, $callback = null, $capability = null, $icon = null) {
|
1419 |
+
//Default
|
1420 |
+
parent::__construct($id, $labels, $options, $callback, $capability, $icon);
|
1421 |
+
//Class specific
|
1422 |
+
$this->set_parent($parent);
|
1423 |
+
}
|
1424 |
+
|
1425 |
+
/* Operations */
|
1426 |
+
|
1427 |
+
function show_icon() {
|
1428 |
+
echo screen_icon();
|
1429 |
+
}
|
1430 |
+
|
1431 |
+
/* Handlers */
|
1432 |
+
|
1433 |
+
/**
|
1434 |
+
* Default Page handler
|
1435 |
+
* Builds options form UI for page
|
1436 |
+
* @see this->init_menus() Set as callback for custom admin pages
|
1437 |
+
* @uses current_user_can() to check if user has access to current page
|
1438 |
+
* @uses wp_die() to end execution when user does not have permission to access page
|
1439 |
+
*/
|
1440 |
+
function handle() {
|
1441 |
+
if ( !current_user_can($this->get_capability()) )
|
1442 |
+
wp_die(__('Access Denied', 'simple-lightbox'));
|
1443 |
+
?>
|
1444 |
+
<div class="wrap">
|
1445 |
+
<?php $this->show_icon(); ?>
|
1446 |
+
<h2><?php esc_html_e( $this->get_label('header') ); ?></h2>
|
1447 |
+
<?php
|
1448 |
+
$this->show_options();
|
1449 |
+
?>
|
1450 |
+
</div>
|
1451 |
+
<?php
|
1452 |
+
}
|
1453 |
+
}
|
1454 |
+
|
1455 |
+
/**
|
1456 |
+
* Admin Section functionality
|
1457 |
+
* @package Simple Lightbox
|
1458 |
+
* @subpackage Admin
|
1459 |
+
* @author Archetyped
|
1460 |
+
*/
|
1461 |
+
class SLB_Admin_Section extends SLB_Admin_View {
|
1462 |
+
/* Properties */
|
1463 |
+
|
1464 |
+
var $parent_required = true;
|
1465 |
+
var $parent_custom = false;
|
1466 |
+
|
1467 |
+
/* Init */
|
1468 |
+
|
1469 |
+
function __construct($id, $parent, $labels, $options = null, $callback = null, $capability = null) {
|
1470 |
+
//Default
|
1471 |
+
parent::__construct($id, $labels, $options, $callback, $capability);
|
1472 |
+
//Class specific
|
1473 |
+
$this->set_parent($parent);
|
1474 |
+
}
|
1475 |
+
|
1476 |
+
/* Getters/Setters */
|
1477 |
+
|
1478 |
+
function get_uri() {
|
1479 |
+
$file = 'options-' . $this->get_parent() . '.php';
|
1480 |
+
return parent::get_uri($file, '%1$s#%2$s');
|
1481 |
+
}
|
1482 |
+
|
1483 |
+
/**
|
1484 |
+
* Retrieve formatted title for section
|
1485 |
+
* Wraps title text in element with anchor so that it can be linked to
|
1486 |
+
* @return string Title
|
1487 |
+
*/
|
1488 |
+
function get_title() {
|
1489 |
+
return '<div id="' . $this->get_id() . '" class="' . $this->add_prefix('section_head') . '">' . $this->get_label('title') . '</div>';
|
1490 |
+
}
|
1491 |
+
|
1492 |
+
/* Handlers */
|
1493 |
+
|
1494 |
+
function handle() {
|
1495 |
+
$this->show_options(false);
|
1496 |
+
}
|
1497 |
+
|
1498 |
+
function options_parse_build_vars($vars, $opts) {
|
1499 |
+
return $vars;
|
1500 |
+
}
|
1501 |
+
|
1502 |
+
function options_build_pre() {}
|
1503 |
+
|
1504 |
+
function options_build_post() {}
|
1505 |
+
}
|
1506 |
+
|
1507 |
+
class SLB_Admin_Reset extends SLB_Admin_View {
|
1508 |
+
/* Properties */
|
1509 |
+
|
1510 |
+
var $required = array ( 'options' => 'object' );
|
1511 |
+
|
1512 |
+
var $parent_required = false;
|
1513 |
+
|
1514 |
+
/* Init */
|
1515 |
+
|
1516 |
+
function __construct($id, $labels, $options) {
|
1517 |
+
parent::__construct($id, $labels, $options);
|
1518 |
+
}
|
1519 |
+
|
1520 |
+
/* Handlers */
|
1521 |
+
|
1522 |
+
/**
|
1523 |
+
* Default handler
|
1524 |
+
* Resets plugin settings
|
1525 |
+
* @return string Status message (success, fail, etc.)
|
1526 |
+
*/
|
1527 |
+
function handle() {
|
1528 |
+
//Validate user
|
1529 |
+
if ( ! current_user_can('activate_plugins') || ! check_admin_referer($this->get_id()) )
|
1530 |
+
wp_die(__('Access Denied', 'simple-lightbox'));
|
1531 |
+
|
1532 |
+
//Reset settings
|
1533 |
+
if ( $this->is_options_valid() )
|
1534 |
+
$this->get_options()->reset(true);
|
1535 |
+
|
1536 |
+
//Set Status Message
|
1537 |
+
$this->set_message($this->get_label('success'));
|
1538 |
+
|
1539 |
+
/*
|
1540 |
+
//Redirect user
|
1541 |
+
$uri = remove_query_arg(array('_wpnonce', 'action'), add_query_arg(array($this->add_prefix('action') => $action), $_SERVER['REQUEST_URI']));
|
1542 |
+
wp_redirect($uri);
|
1543 |
+
exit;
|
1544 |
+
*/
|
1545 |
+
}
|
1546 |
+
|
1547 |
+
function get_uri() {
|
1548 |
+
return wp_nonce_url(add_query_arg($this->get_query_args(), remove_query_arg($this->get_query_args_remove(), $_SERVER['REQUEST_URI'])), $this->get_id());
|
1549 |
+
}
|
1550 |
+
|
1551 |
+
function get_query_args() {
|
1552 |
+
return array (
|
1553 |
+
'action' => $this->add_prefix('admin'),
|
1554 |
+
$this->add_prefix('type') => 'view',
|
1555 |
+
$this->add_prefix('group') => 'reset',
|
1556 |
+
$this->add_prefix('obj') => $this->get_id_raw()
|
1557 |
+
);
|
1558 |
+
}
|
1559 |
+
|
1560 |
+
function get_query_args_remove() {
|
1561 |
+
$args_r = array (
|
1562 |
+
'_wpnonce',
|
1563 |
+
$this->add_prefix('action')
|
1564 |
+
);
|
1565 |
+
|
1566 |
+
return array_unique( array_merge( array_keys( $this->get_query_args() ), $args_r ) );
|
1567 |
+
}
|
1568 |
+
|
1569 |
+
function get_link_attr() {
|
1570 |
+
return array (
|
1571 |
+
'class' => 'delete',
|
1572 |
+
'onclick' => "return confirm('" . $this->get_label('confirm') . "')"
|
1573 |
+
);
|
1574 |
+
}
|
1575 |
+
|
1576 |
+
}
|
includes/class.base.php
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
-
require_once 'class.utilities.php';
|
4 |
-
|
5 |
Â
/**
|
6 |
Â
* @package Simple Lightbox
|
7 |
Â
* @subpackage Base
|
@@ -9,12 +7,88 @@ require_once 'class.utilities.php';
|
|
9 |
Â
*
|
10 |
Â
*/
|
11 |
Â
class SLB_Base {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
12 |
Â
|
Â
|
|
Â
|
|
13 |
Â
/**
|
14 |
-
*
|
15 |
Â
* @var string
|
16 |
Â
*/
|
17 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
18 |
Â
|
19 |
Â
/**
|
20 |
Â
* Utilities
|
@@ -23,150 +97,426 @@ class SLB_Base {
|
|
23 |
Â
var $util = null;
|
24 |
Â
|
25 |
Â
/**
|
26 |
-
*
|
Â
|
|
27 |
Â
*/
|
28 |
-
|
29 |
-
|
30 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
31 |
Â
|
32 |
Â
/**
|
33 |
Â
* Constructor
|
34 |
Â
*/
|
35 |
Â
function __construct() {
|
36 |
-
$this->util
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
37 |
Â
}
|
38 |
Â
|
39 |
Â
/**
|
40 |
Â
* Default initialization method
|
41 |
-
*
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
42 |
Â
*/
|
43 |
-
function
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
44 |
Â
|
45 |
Â
/**
|
46 |
-
*
|
47 |
-
* @param string $method Method name
|
48 |
-
* @return array Callback array
|
49 |
Â
*/
|
50 |
-
function
|
51 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
52 |
Â
}
|
53 |
Â
|
54 |
Â
/**
|
55 |
-
*
|
56 |
-
*
|
57 |
-
* @see get_post_meta()
|
58 |
-
* @param int $post_id Post ID
|
59 |
-
* @param string $key Name of metadata to retrieve
|
60 |
-
* @param boolean $single Whether or not to retrieve single value or not
|
61 |
-
* @return mixed Retrieved post metadata
|
62 |
Â
*/
|
63 |
-
function
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
68 |
Â
}
|
69 |
Â
|
70 |
Â
/**
|
71 |
-
*
|
72 |
-
* @param mixed $meta_value Value to be set as metadata
|
73 |
-
* @return array Wrapped metadata value
|
74 |
Â
*/
|
75 |
-
function
|
76 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
77 |
Â
}
|
78 |
Â
|
79 |
Â
/**
|
80 |
-
*
|
81 |
-
* For internal methods
|
82 |
-
* @see add_post_meta
|
83 |
-
* @param $post_id
|
84 |
-
* @param $meta_key
|
85 |
-
* @param $meta_value
|
86 |
-
* @param $unique
|
87 |
-
* @return boolean Result of operation
|
88 |
Â
*/
|
89 |
-
function
|
90 |
-
|
91 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
92 |
Â
}
|
93 |
Â
|
94 |
Â
/**
|
95 |
-
*
|
96 |
-
* @see
|
97 |
-
* @
|
98 |
-
* @
|
99 |
-
* @param $meta_value
|
100 |
-
* @param $prev_value
|
101 |
-
* @return boolean Result of operation
|
102 |
Â
*/
|
103 |
-
function
|
104 |
-
$
|
105 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
106 |
Â
}
|
107 |
Â
|
108 |
Â
/**
|
109 |
-
*
|
110 |
-
* @
|
111 |
-
* @
|
Â
|
|
112 |
Â
*/
|
113 |
-
function
|
114 |
-
|
115 |
-
|
116 |
-
$
|
117 |
-
if (
|
118 |
-
|
119 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
120 |
Â
}
|
121 |
Â
}
|
122 |
-
|
123 |
-
return $key;
|
124 |
Â
}
|
125 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
126 |
Â
/**
|
127 |
Â
* Retrieve class prefix (with separator if set)
|
128 |
Â
* @param bool|string $sep Separator to append to class prefix (Default: no separator)
|
129 |
Â
* @return string Class prefix
|
130 |
Â
*/
|
131 |
-
function get_prefix($sep =
|
132 |
-
$
|
133 |
-
|
134 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
135 |
Â
}
|
136 |
Â
|
137 |
Â
/**
|
138 |
Â
* Prepend plugin prefix to some text
|
139 |
Â
* @param string $text Text to add to prefix
|
140 |
-
* @param string $sep Text used to separate prefix and text
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
141 |
Â
* @return string Text with prefix prepended
|
142 |
Â
*/
|
143 |
-
function
|
144 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
145 |
Â
}
|
146 |
Â
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
151 |
Â
}
|
152 |
Â
|
Â
|
|
Â
|
|
153 |
Â
/**
|
154 |
-
*
|
155 |
-
*
|
156 |
-
* @param string $
|
157 |
-
* @
|
Â
|
|
158 |
Â
*/
|
159 |
-
function
|
160 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
161 |
Â
}
|
162 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
163 |
Â
/**
|
164 |
-
*
|
165 |
-
* @
|
Â
|
|
166 |
Â
*/
|
167 |
-
function
|
168 |
-
|
169 |
-
|
Â
|
|
Â
|
|
Â
|
|
170 |
Â
}
|
171 |
Â
}
|
172 |
Â
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
/**
|
4 |
Â
* @package Simple Lightbox
|
5 |
Â
* @subpackage Base
|
7 |
Â
*
|
8 |
Â
*/
|
9 |
Â
class SLB_Base {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class type
|
14 |
+
* Controls initialization, etc.
|
15 |
+
* > full - Fully-functional class
|
16 |
+
* > sub - Sub-class (attached to an instance)
|
17 |
+
* > object - Simple object class (no hooks, etc.)
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
protected $mode = 'full';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Indicates that instance is model (main controller)
|
24 |
+
* @var bool
|
25 |
+
*/
|
26 |
+
protected $model = false;
|
27 |
Â
|
28 |
+
/* Properties */
|
29 |
+
|
30 |
Â
/**
|
31 |
+
* Variable name of base object in global scope
|
32 |
Â
* @var string
|
33 |
Â
*/
|
34 |
+
protected $base = 'slb';
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Prefix for plugin-related data (attributes, DB tables, etc.)
|
38 |
+
* @var string
|
39 |
+
*/
|
40 |
+
public $prefix = 'slb';
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Prefix to be added when creating internal hook (action/filter) tags
|
44 |
+
* Used by Utilities
|
45 |
+
* @var string
|
46 |
+
*/
|
47 |
+
public $hook_prefix = '';
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Global data
|
51 |
+
* Facilitates sharing between decoupled objects
|
52 |
+
* @var array
|
53 |
+
*/
|
54 |
+
private static $globals = array();
|
55 |
+
|
56 |
+
protected $shared = array('options', 'admin');
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Capabilities
|
60 |
+
* @var array
|
61 |
+
*/
|
62 |
+
protected $caps = null;
|
63 |
+
|
64 |
+
protected $_init = false;
|
65 |
+
|
66 |
+
private static $_init_passed = false;
|
67 |
+
|
68 |
+
/* Client */
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Client files
|
72 |
+
* @var array
|
73 |
+
* Structure
|
74 |
+
* > Key: unique file ID
|
75 |
+
* > Properties
|
76 |
+
* > file (string) File path (Relative to plugin base)
|
77 |
+
* > deps (array) Script dependencies
|
78 |
+
* > Internal dependencies are wrapped in square brackets ([])
|
79 |
+
* > context (string|array)
|
80 |
+
* > Context in which the script should be included
|
81 |
+
* > in_footer (bool) optional [Default: FALSE]
|
82 |
+
* > If TRUE, file will be included in footer of page, otherwise it will be included in the header
|
83 |
+
*
|
84 |
+
* Array is processed and converted to an object on init
|
85 |
+
*/
|
86 |
+
var $client_files = array(
|
87 |
+
'scripts' => array(),
|
88 |
+
'styles' => array()
|
89 |
+
);
|
90 |
+
|
91 |
+
/*-** Instances **-*/
|
92 |
Â
|
93 |
Â
/**
|
94 |
Â
* Utilities
|
97 |
Â
var $util = null;
|
98 |
Â
|
99 |
Â
/**
|
100 |
+
* Options
|
101 |
+
* @var SLB_Options
|
102 |
Â
*/
|
103 |
+
var $options = null;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Admin
|
107 |
+
* @var SLB_Admin
|
108 |
+
*/
|
109 |
+
var $admin = null;
|
110 |
+
|
111 |
+
/*-** Initialization **-*/
|
112 |
Â
|
113 |
Â
/**
|
114 |
Â
* Constructor
|
115 |
Â
*/
|
116 |
Â
function __construct() {
|
117 |
+
$this->util = new SLB_Utilities($this);
|
118 |
+
if ( $this->can('init') ) {
|
119 |
+
$hook = 'plugins_loaded';
|
120 |
+
if ( current_filter() == $hook || self::$_init_passed ) {
|
121 |
+
$this->_init();
|
122 |
+
} else {
|
123 |
+
add_action($hook, $this->m('_init'));
|
124 |
+
}
|
125 |
+
}
|
126 |
Â
}
|
127 |
Â
|
128 |
Â
/**
|
129 |
Â
* Default initialization method
|
130 |
+
* @uses _init_passed
|
131 |
+
* @uses _env()
|
132 |
+
* @uses _options()
|
133 |
+
* @uses _admin()
|
134 |
+
* @uses _hooks()
|
135 |
+
* @uses _client_files()
|
136 |
Â
*/
|
137 |
+
public function _init() {
|
138 |
+
self::$_init_passed = true;
|
139 |
+
if ( $this->_init || !isset($this) || !$this->can('init') )
|
140 |
+
return false;
|
141 |
+
$this->_init = true;
|
142 |
+
//Environment
|
143 |
+
$this->_env();
|
144 |
+
|
145 |
+
if ( $this->can('control') ) {
|
146 |
+
//Options
|
147 |
+
$this->_options();
|
148 |
+
|
149 |
+
//Admin
|
150 |
+
if ( is_admin() )
|
151 |
+
$this->_admin();
|
152 |
+
}
|
153 |
+
|
154 |
+
//Hooks
|
155 |
+
$this->_hooks();
|
156 |
+
|
157 |
+
//Client files
|
158 |
+
$this->_client_files();
|
159 |
+
}
|
160 |
Â
|
161 |
Â
/**
|
162 |
+
* Initialize environment (Localization, etc.)
|
Â
|
|
Â
|
|
163 |
Â
*/
|
164 |
+
private function _env() {
|
165 |
+
if ( !$this->can('singleton') ) {
|
166 |
+
return false;
|
167 |
+
}
|
168 |
+
//Localization
|
169 |
+
$ldir = 'l10n';
|
170 |
+
$lpath = $this->util->get_plugin_file_path($ldir, array(false, false));
|
171 |
+
$lpath_abs = $this->util->get_file_path($ldir);
|
172 |
+
if ( is_dir($lpath_abs) ) {
|
173 |
+
load_plugin_textdomain('ar-series', false, $lpath);
|
174 |
+
}
|
175 |
+
|
176 |
+
//Context
|
177 |
+
add_action( ( is_admin() ) ? 'admin_print_footer_scripts' : 'wp_footer', $this->util->m('set_client_context'), $this->util->priority('client_footer_output') );
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Initialize options
|
182 |
+
* To be called by child class
|
183 |
+
*/
|
184 |
+
protected function _options($options_config = null) {
|
185 |
+
$class = $this->util->get_class('Options');
|
186 |
+
$key = 'options';
|
187 |
+
if ( $this->shares($key) ) {
|
188 |
+
/**
|
189 |
+
* @var SLB_Options
|
190 |
+
*/
|
191 |
+
$opts = $this->gvar($key);
|
192 |
+
//Setup options instance
|
193 |
+
if ( !is_a($opts, $class) ) {
|
194 |
+
$opts = $this->gvar($key, new $class());
|
195 |
+
}
|
196 |
+
} else {
|
197 |
+
$opts = new $class();
|
198 |
+
}
|
199 |
+
//Load options
|
200 |
+
if ( $this->is_options_valid($options_config, false) ) {
|
201 |
+
$opts->load($options_config);
|
202 |
+
}
|
203 |
+
//Set instance property
|
204 |
+
$this->options = $opts;
|
205 |
Â
}
|
206 |
Â
|
207 |
Â
/**
|
208 |
+
* Initialize admin
|
209 |
+
* To be called by child class
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
210 |
Â
*/
|
211 |
+
private function _admin() {
|
212 |
+
if ( !is_admin() ) {
|
213 |
+
return false;
|
214 |
+
}
|
215 |
+
$class = $this->util->get_class('Admin');
|
216 |
+
$key = 'admin';
|
217 |
+
if ( $this->shares($key) ) {
|
218 |
+
/**
|
219 |
+
* @var SLB_Admin
|
220 |
+
*/
|
221 |
+
$adm = $this->gvar($key);
|
222 |
+
//Setup options instance
|
223 |
+
if ( !is_a($adm, $class) ) {
|
224 |
+
$adm = $this->gvar($key, new $class($this));
|
225 |
+
}
|
226 |
+
} else {
|
227 |
+
$adm = new $class($this);
|
228 |
+
}
|
229 |
+
//Set instance property
|
230 |
+
$this->admin = $adm;
|
231 |
Â
}
|
232 |
Â
|
233 |
Â
/**
|
234 |
+
* Register default hooks
|
Â
|
|
Â
|
|
235 |
Â
*/
|
236 |
+
protected function _hooks() {
|
237 |
+
$base = $this->util->get_plugin_base_file();
|
238 |
+
//Activation
|
239 |
+
$func_activate = '_activate';
|
240 |
+
if ( method_exists($this, $func_activate) )
|
241 |
+
register_activation_hook($base, $this->m($func_activate));
|
242 |
+
|
243 |
+
//Deactivation
|
244 |
+
$func_deactivate = '_deactivate';
|
245 |
+
if ( method_exists($this, $func_deactivate) )
|
246 |
+
register_deactivation_hook($base, $this->m($func_deactivate));
|
247 |
Â
}
|
248 |
Â
|
249 |
Â
/**
|
250 |
+
* Initialize client files
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
251 |
Â
*/
|
252 |
+
protected function _client_files() {
|
253 |
+
foreach ( $this->client_files as $key => $val ) {
|
254 |
+
if ( empty($val) && isset($this->{$key}) )
|
255 |
+
$this->client_files[$key] =& $this->{$key};
|
256 |
+
$g =& $this->client_files[$key];
|
257 |
+
if ( is_array($g) && !empty($g) ) {
|
258 |
+
$g = $this->util->parse_client_files($g, $key);
|
259 |
+
}
|
260 |
+
//Remove empty file groups
|
261 |
+
if ( empty($g) )
|
262 |
+
unset($this->client_files[$key]);
|
263 |
+
}
|
264 |
+
|
265 |
+
//Register
|
266 |
+
add_action('init', $this->m('register_client_files'));
|
267 |
+
|
268 |
+
//Enqueue
|
269 |
+
$hook_enqueue = ( ( is_admin() ) ? 'admin' : 'wp' ) . '_enqueue_scripts' ;
|
270 |
+
add_action($hook_enqueue, $this->m('enqueue_client_files'));
|
271 |
Â
}
|
272 |
Â
|
273 |
Â
/**
|
274 |
+
* Register client files
|
275 |
+
* @see enqueue_client_files() for actual loading of files based on context
|
276 |
+
* @uses `init` Action hook for execution
|
277 |
+
* @return void
|
Â
|
|
Â
|
|
Â
|
|
278 |
Â
*/
|
279 |
+
public function register_client_files() {
|
280 |
+
$v = $this->util->get_plugin_version();
|
281 |
+
foreach ( $this->client_files as $type => $files ) {
|
282 |
+
$func = $this->get_client_files_handler($type, 'register');
|
283 |
+
if ( !$func )
|
284 |
+
continue;
|
285 |
+
foreach ( $files as $f ) {
|
286 |
+
//Get file URI
|
287 |
+
$f->file = ( !$this->util->is_file($f->file) && is_callable($f->file) ) ? call_user_func($f->file) : $this->util->get_file_url($f->file);
|
288 |
+
$params = array($f->id, $f->file, $f->deps, $v);
|
289 |
+
//Set additional parameters based on file type (script, style, etc.)
|
290 |
+
switch ( $type ) {
|
291 |
+
case 'scripts':
|
292 |
+
$params[] = $f->in_footer;
|
293 |
+
break;
|
294 |
+
case 'styles':
|
295 |
+
$params[] = $f->media;
|
296 |
+
break;
|
297 |
+
}
|
298 |
+
//Register file
|
299 |
+
call_user_func_array($func, $params);
|
300 |
+
}
|
301 |
+
}
|
302 |
Â
}
|
303 |
Â
|
304 |
Â
/**
|
305 |
+
* Enqueues files for client output (scripts/styles) based on context
|
306 |
+
* @uses `admin_enqueue_scripts` Action hook depending on context
|
307 |
+
* @uses `wp_enqueue_scripts` Action hook depending on context
|
308 |
+
* @return void
|
309 |
Â
*/
|
310 |
+
function enqueue_client_files() {
|
311 |
+
//Enqueue files
|
312 |
+
foreach ( $this->client_files as $type => $files ) {
|
313 |
+
$func = $this->get_client_files_handler($type, 'enqueue');
|
314 |
+
if ( !$func ) {
|
315 |
+
continue;
|
316 |
+
}
|
317 |
+
foreach ( $files as $f ) {
|
318 |
+
//Skip shadow files
|
319 |
+
if ( !$f->enqueue ) {
|
320 |
+
continue;
|
321 |
+
}
|
322 |
+
$load = true;
|
323 |
+
//Global Callback
|
324 |
+
if ( is_callable($f->callback) && !call_user_func($f->callback) ) {
|
325 |
+
$load = false;
|
326 |
+
}
|
327 |
+
//Context
|
328 |
+
if ( $load && !empty($f->context) ) {
|
329 |
+
//Reset $load before evaluating context
|
330 |
+
$load = false;
|
331 |
+
//Iterate through contexts
|
332 |
+
foreach ( $f->context as $ctx ) {
|
333 |
+
//Context + Callback
|
334 |
+
if ( is_array($ctx) ) {
|
335 |
+
//Stop checking context if callback is invalid
|
336 |
+
if ( !is_callable($ctx[1]) || !call_user_func($ctx[1]) )
|
337 |
+
continue;
|
338 |
+
$ctx = $ctx[0];
|
339 |
+
}
|
340 |
+
//Stop checking context if valid context found
|
341 |
+
if ( $this->util->is_context($ctx) ) {
|
342 |
+
$load = true;
|
343 |
+
break;
|
344 |
+
}
|
345 |
+
}
|
346 |
+
}
|
347 |
+
|
348 |
+
//Load valid file
|
349 |
+
if ( $load ) {
|
350 |
+
$func($f->id);
|
351 |
+
}
|
352 |
Â
}
|
353 |
Â
}
|
Â
|
|
Â
|
|
354 |
Â
}
|
355 |
Â
|
356 |
+
/**
|
357 |
+
* Build function name for handling client operations
|
358 |
+
*/
|
359 |
+
function get_client_files_handler($type, $action) {
|
360 |
+
$func = 'wp_' . $action . '_' . substr($type, 0, -1);
|
361 |
+
if ( !function_exists($func) )
|
362 |
+
$func = false;
|
363 |
+
return $func;
|
364 |
+
}
|
365 |
+
|
366 |
+
/*-** Reflection **-*/
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Retrieve base object
|
370 |
+
* @return object|bool Base object (FALSE if object does not exist)
|
371 |
+
*/
|
372 |
+
function &get_base() {
|
373 |
+
$base = false;
|
374 |
+
if ( isset($GLOBALS[$this->base]) )
|
375 |
+
$base =& $GLOBALS[$this->base];
|
376 |
+
return $base;
|
377 |
+
}
|
378 |
+
|
379 |
+
/*-** Method/Function calling **-*/
|
380 |
+
|
381 |
+
/**
|
382 |
+
* Returns callback to instance method
|
383 |
+
* @param string $method Method name
|
384 |
+
* @return array Callback array
|
385 |
+
*/
|
386 |
+
function m($method) {
|
387 |
+
return $this->util->m($this, $method);
|
388 |
+
}
|
389 |
+
|
390 |
+
/*-** Prefix **-*/
|
391 |
+
|
392 |
Â
/**
|
393 |
Â
* Retrieve class prefix (with separator if set)
|
394 |
Â
* @param bool|string $sep Separator to append to class prefix (Default: no separator)
|
395 |
Â
* @return string Class prefix
|
396 |
Â
*/
|
397 |
+
function get_prefix($sep = null) {
|
398 |
+
$args = func_get_args();
|
399 |
+
return call_user_func_array($this->util->m($this->util, 'get_prefix'), $args);
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Check if a string is prefixed
|
404 |
+
* @param string $text Text to check for prefix
|
405 |
+
* @param string $sep (optional) Separator used
|
406 |
+
*/
|
407 |
+
function has_prefix($text, $sep = null) {
|
408 |
+
$args = func_get_args();
|
409 |
+
return call_user_func_array($this->util->m($this->util, 'has_prefix'), $args);
|
410 |
Â
}
|
411 |
Â
|
412 |
Â
/**
|
413 |
Â
* Prepend plugin prefix to some text
|
414 |
Â
* @param string $text Text to add to prefix
|
415 |
+
* @param string $sep (optional) Text used to separate prefix and text
|
416 |
+
* @param bool $once (optional) Whether to add prefix to text that already contains a prefix or not
|
417 |
+
* @return string Text with prefix prepended
|
418 |
+
*/
|
419 |
+
function add_prefix($text, $sep = null, $once = true) {
|
420 |
+
$args = func_get_args();
|
421 |
+
return call_user_func_array($this->util->m($this->util, 'add_prefix'), $args);
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Prepend uppercased plugin prefix to some text
|
426 |
+
* @param string $text Text to add to prefix
|
427 |
+
* @param string $sep (optional) Text used to separate prefix and text
|
428 |
+
* @param bool $once (optional) Whether to add prefix to text that already contains a prefix or not
|
429 |
Â
* @return string Text with prefix prepended
|
430 |
Â
*/
|
431 |
+
function add_prefix_uc($text, $sep = null, $once = true) {
|
432 |
+
$args = func_get_args();
|
433 |
+
return call_user_func_array($this->util->m($this->util, 'add_prefix_uc'), $args);
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Add prefix to variable reference
|
438 |
+
* Updates actual variable rather than return value
|
439 |
+
* @uses SLB_Utilities::add_prefix_ref();
|
440 |
+
* @param string $var Variable to add prefix to
|
441 |
+
* @param string $sep (optional) Separator text
|
442 |
+
* @param bool $once (optional) Add prefix only once
|
443 |
+
* @return void
|
444 |
+
*/
|
445 |
+
function add_prefix_ref(&$var, $sep = null, $once = true) {
|
446 |
+
$args = func_get_args();
|
447 |
+
$args[0] =& $var;
|
448 |
+
call_user_func_array($this->util->m($this->util, 'add_prefix_ref'), $args);
|
449 |
Â
}
|
450 |
Â
|
451 |
+
/**
|
452 |
+
* Remove prefix from specified string
|
453 |
+
* @param string $text String to remove prefix from
|
454 |
+
* @param string $sep (optional) Separator used with prefix
|
455 |
+
*/
|
456 |
+
function remove_prefix($text, $sep = null) {
|
457 |
+
$args = func_get_args();
|
458 |
+
return call_user_func_array($this->util->m($this->util, 'remove_prefix'), $args);
|
459 |
+
}
|
460 |
+
|
461 |
+
/*-** Capabilities **-*/
|
462 |
+
|
463 |
+
protected function can($cap) {
|
464 |
+
if ( is_null($this->caps) ) {
|
465 |
+
//Build capabilities based on instance properties
|
466 |
+
$this->caps = array(
|
467 |
+
'init' => ( 'object' != $this->mode ) ? true : false,
|
468 |
+
'singleton' => ( !!$this->model ) ? true : false,
|
469 |
+
'control' => ( 'sub' == $this->mode || 'object' == $this->mode ) ? false : true,
|
470 |
+
);
|
471 |
+
}
|
472 |
+
return ( isset($this->caps[$cap]) ) ? $this->caps[$cap] : false;
|
473 |
Â
}
|
474 |
Â
|
475 |
+
/*-** Globals **-*/
|
476 |
+
|
477 |
Â
/**
|
478 |
+
* Get/Set (internal) global variables
|
479 |
+
* @uses $globals to get/set global variables
|
480 |
+
* @param string $name Variable name - If no name is specified, entire globals array is returned
|
481 |
+
* @param mixed $val (optional) Set the value of a variable (Returns variable value if omitted)
|
482 |
+
* @return mixed Variable value
|
483 |
Â
*/
|
484 |
+
private function gvar($name = null, $val = null) {
|
485 |
+
$g =& self::$globals;
|
486 |
+
if ( !is_array($g) ) {
|
487 |
+
$g = array();
|
488 |
+
}
|
489 |
+
if ( !is_string($name) || empty($name) ) {
|
490 |
+
return $g;
|
491 |
+
}
|
492 |
+
$ret = $val;
|
493 |
+
if ( null !== $val ) {
|
494 |
+
//Set Value
|
495 |
+
$g[$name] = $val;
|
496 |
+
} elseif ( isset($g[$name]) ) {
|
497 |
+
//Retrieve variable
|
498 |
+
$ret = $g[$name];
|
499 |
+
}
|
500 |
+
return $ret;
|
501 |
Â
}
|
502 |
Â
|
503 |
+
private function shares($name) {
|
504 |
+
return ( !empty($this->shared) && in_array($name, $this->shared) ) ? true : false;
|
505 |
+
}
|
506 |
+
|
507 |
+
/*-** Options **-*/
|
508 |
+
|
509 |
Â
/**
|
510 |
+
* Checks if options are valid
|
511 |
+
* @param array $data Data to be used on options
|
512 |
+
* @return bool TRUE if options are valid, FALSE otherwise
|
513 |
Â
*/
|
514 |
+
function is_options_valid($data, $check_var = true) {
|
515 |
+
$class = $this->util->get_class('Options');
|
516 |
+
$ret = ( empty($data) || !is_array($data) || !class_exists($class) ) ? false : true;
|
517 |
+
if ( $ret && $check_var && !is_a($this->options, $class) )
|
518 |
+
$ret = false;
|
519 |
+
return $ret;
|
520 |
Â
}
|
521 |
Â
}
|
522 |
Â
|
includes/class.base_collection.php
ADDED
@@ -0,0 +1,369 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Managed collection
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Base
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Base_Collection extends SLB_Base {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Set object mode
|
14 |
+
* @var string
|
15 |
+
*/
|
16 |
+
protected $mode = 'object';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Item type
|
20 |
+
* @var string
|
21 |
+
*/
|
22 |
+
protected $item_type = null;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Property to use for item key
|
26 |
+
* Example: A property or method of the item
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
protected $key_prop = null;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Should $key_prop be called or retrieved?
|
33 |
+
* Default: Retrieved (FALSE)
|
34 |
+
* @var bool
|
35 |
+
*/
|
36 |
+
protected $key_call = false;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Items in collection unique?
|
40 |
+
* Default: FALSE
|
41 |
+
* @var bool
|
42 |
+
*/
|
43 |
+
protected $unique = false;
|
44 |
+
|
45 |
+
/* Properties */
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Indexed array of items in collection
|
49 |
+
* @var array
|
50 |
+
*/
|
51 |
+
protected $items = null;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Item metadata
|
55 |
+
* Indexed by item key
|
56 |
+
* @var array
|
57 |
+
*/
|
58 |
+
protected $items_meta = array();
|
59 |
+
|
60 |
+
/* Item Management */
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Initialize collections
|
64 |
+
* Calls `init` action if collection has a hook prefix
|
65 |
+
*/
|
66 |
+
private function init() {
|
67 |
+
//Initialize
|
68 |
+
if ( is_null($this->items) ) {
|
69 |
+
$this->items = array();
|
70 |
+
if ( !empty($this->hook_prefix) ) {
|
71 |
+
$this->util->do_action('init', $this);
|
72 |
+
}
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Normalize/Validate item(s)
|
78 |
+
* TODO: If no items are specified, then collection is normalized
|
79 |
+
* Single items are wrapped in an array
|
80 |
+
* @param array|object $items Item(s) to validate
|
81 |
+
* @return array Validated items
|
82 |
+
*/
|
83 |
+
protected function normalize($items) {
|
84 |
+
if ( !is_array($items) ) {
|
85 |
+
$items = array($items);
|
86 |
+
}
|
87 |
+
//Validate item type
|
88 |
+
if ( !is_null($this->item_type) ) {
|
89 |
+
foreach ( $items as $idx => $item ) {
|
90 |
+
//Remove invalid items
|
91 |
+
if ( !( $item instanceof $this->item_type ) ) {
|
92 |
+
unset($items[$idx]);
|
93 |
+
}
|
94 |
+
}
|
95 |
+
}
|
96 |
+
if ( !empty($items) ) {
|
97 |
+
$items = array_values($items);
|
98 |
+
}
|
99 |
+
return $items;
|
100 |
+
}
|
101 |
+
|
102 |
+
protected function item_valid($item) {
|
103 |
+
//Validate item type
|
104 |
+
return ( empty($this->item_type) || ( $item instanceof $this->item_type ) ) ? true : false;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Validate item key
|
109 |
+
* Checks collection for existence of key as well
|
110 |
+
* @param string|int $key Key to check collection for
|
111 |
+
* @return bool TRUE if key is valid
|
112 |
+
*/
|
113 |
+
protected function key_valid($key) {
|
114 |
+
$this->init();
|
115 |
+
return ( ( ( is_string($key) && !empty($key) ) || is_int($key) ) && isset($this->items[$key]) ) ? true : false;
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Generate key for item (for storing in collection, etc.)
|
120 |
+
* @param mixed $item Item to generate key for
|
121 |
+
* @return string|null Item key (NULL if no key generated)
|
122 |
+
*/
|
123 |
+
protected function get_key($item, $check_existing = false) {
|
124 |
+
$ret = null;
|
125 |
+
if ( $this->unique || !!$check_existing ) {
|
126 |
+
//Check for item in collection
|
127 |
+
if ( $this->has($item) ) {
|
128 |
+
$ret = array_search($item, $this->items);
|
129 |
+
} elseif ( !!$this->key_prop && ( is_object($item) || is_array($item) ) ) {
|
130 |
+
if ( !!$this->key_call ) {
|
131 |
+
$cb = $this->util->m($item, $this->key_prop);
|
132 |
+
if ( is_callable($cb) ) {
|
133 |
+
$ret = call_user_func($cb);
|
134 |
+
}
|
135 |
+
} elseif ( is_array($item) && isset($item[$this->key_prop]) ) {
|
136 |
+
$ret = $item[$this->key_prop];
|
137 |
+
} elseif ( is_object($item) && isset($item->{$this->key_prop}) ) {
|
138 |
+
$ret = $item->{$this->key_prop};
|
139 |
+
}
|
140 |
+
}
|
141 |
+
}
|
142 |
+
return $ret;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Add item to collection
|
147 |
+
* @param mixed $item Item to add to collection
|
148 |
+
* @param array $meta (optional) Item metadata
|
149 |
+
* @return Current instance
|
150 |
+
*/
|
151 |
+
public function add($item, $meta = null) {
|
152 |
+
$this->init();
|
153 |
+
//Validate
|
154 |
+
if ( $this->item_valid($item) ) {
|
155 |
+
//Add item to collection
|
156 |
+
$key = $this->get_key($item);
|
157 |
+
if ( !$key ) {
|
158 |
+
$this->items[] = $item;
|
159 |
+
$key = key($this->items);
|
160 |
+
} else {
|
161 |
+
$this->items[$key] = $item;
|
162 |
+
}
|
163 |
+
//Add metadata
|
164 |
+
if ( !!$key && is_array($meta) ) {
|
165 |
+
$this->add_meta($key, $meta);
|
166 |
+
}
|
167 |
+
}
|
168 |
+
return $this;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Remove item from collection
|
173 |
+
* @param int|string $item Key of item to remove
|
174 |
+
* @return Current instance
|
175 |
+
*/
|
176 |
+
public function remove($item) {
|
177 |
+
if ( $this->key_valid($item) ) {
|
178 |
+
unset($this->items[$item]);
|
179 |
+
}
|
180 |
+
return $this;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Clear collection
|
185 |
+
* @return Current instance
|
186 |
+
*/
|
187 |
+
public function clear() {
|
188 |
+
$this->items = array();
|
189 |
+
return $this;
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Checks if item exists in the collection
|
194 |
+
* @param mixed $item Item(s) to check for
|
195 |
+
* @return bool TRUE if item(s) in collection
|
196 |
+
*/
|
197 |
+
public function has($items) {
|
198 |
+
//Attempt to locate item
|
199 |
+
return false;
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Retrieve item(s) from collection
|
204 |
+
* If no items specified, entire collection returned
|
205 |
+
* @param array $args (optional) Query arguments
|
206 |
+
* @return object|array Specified item(s)
|
207 |
+
*/
|
208 |
+
public function get($args = null) {
|
209 |
+
$this->init();
|
210 |
+
//Parse args
|
211 |
+
$args_default = array(
|
212 |
+
'orderby' => null,
|
213 |
+
'order' => 'DESC',
|
214 |
+
'include' => array(),
|
215 |
+
'exclude' => array(),
|
216 |
+
);
|
217 |
+
$r = wp_parse_args($args, $args_default);
|
218 |
+
|
219 |
+
$items = $this->items;
|
220 |
+
|
221 |
+
/* Sort */
|
222 |
+
if ( !is_null($r['orderby']) ) {
|
223 |
+
//Validate
|
224 |
+
if ( !is_array($r['orderby']) ) {
|
225 |
+
$r['orderby'] = array('item' => $r['orderby']);
|
226 |
+
}
|
227 |
+
//Prep
|
228 |
+
$metas = ( isset($r['orderby']['meta']) ) ? $this->items_meta : array();
|
229 |
+
//Sort
|
230 |
+
foreach ( $r['orderby'] as $stype => $sval ) {
|
231 |
+
/* Meta sorting */
|
232 |
+
if ( 'meta' == $stype ) {
|
233 |
+
//Build sorting buckets
|
234 |
+
$buckets = array();
|
235 |
+
foreach ( $metas as $item => $meta ) {
|
236 |
+
if ( !isset($meta[$sval]) ) {
|
237 |
+
continue;
|
238 |
+
}
|
239 |
+
//Create bucket
|
240 |
+
$idx = $meta[$sval];
|
241 |
+
if ( !isset($buckets[ $idx ]) ) {
|
242 |
+
$buckets[ $idx ] = array();
|
243 |
+
}
|
244 |
+
//Add item to bucket
|
245 |
+
$buckets[ $idx ][] = $item;
|
246 |
+
}
|
247 |
+
//Sort buckets
|
248 |
+
ksort($buckets, SORT_NUMERIC);
|
249 |
+
//Merge buckets
|
250 |
+
$pool = array();
|
251 |
+
foreach ( $buckets as $bucket ) {
|
252 |
+
$pool = array_merge($pool, $bucket);
|
253 |
+
}
|
254 |
+
//Fill with items
|
255 |
+
$items = array_merge( array_fill_keys($pool, null), $items);
|
256 |
+
}
|
257 |
+
}
|
258 |
+
//Clear workers
|
259 |
+
unset($stype, $sval, $buckets, $pool, $item, $metas, $meta, $idx);
|
260 |
+
}
|
261 |
+
return $items;
|
262 |
+
}
|
263 |
+
|
264 |
+
/* Metadata */
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Add metadata for item
|
268 |
+
* @param string|int $item Item key
|
269 |
+
* @param string|array $meta_key Meta key to set (or array of metadata)
|
270 |
+
* @param mixed $meta_value (optional) Metadata value (if key set)
|
271 |
+
* @param bool $reset (optional) Whether to remove existing metadata first (Default: FALSE)
|
272 |
+
* @return object Current instance
|
273 |
+
*/
|
274 |
+
protected function add_meta($item, $meta_key, $meta_value = null, $reset = false) {
|
275 |
+
//Validate
|
276 |
+
if ( $this->key_valid($item) && ( is_array($meta_key) || is_string($meta_key) ) ) {
|
277 |
+
//Prepare metadata
|
278 |
+
$meta = ( is_string($meta_key) ) ? array($meta_key => $meta_value) : $meta_key;
|
279 |
+
//Reset existing meta (if necessary)
|
280 |
+
if ( is_array($meta_key) && func_num_args() > 2) {
|
281 |
+
$reset = func_get_arg(2);
|
282 |
+
}
|
283 |
+
if ( !!$reset ) {
|
284 |
+
unset($this->items_meta[$item]);
|
285 |
+
}
|
286 |
+
//Add metadata
|
287 |
+
if ( !isset($this->items_meta[$item]) ) {
|
288 |
+
$this->items_meta[$item] = array();
|
289 |
+
}
|
290 |
+
$this->items_meta[$item] = array_merge($this->items_meta[$item], $meta);
|
291 |
+
}
|
292 |
+
return $this;
|
293 |
+
}
|
294 |
+
|
295 |
+
/**
|
296 |
+
* Remove item metadata
|
297 |
+
* @param string $item Item key
|
298 |
+
* @return object Current instance
|
299 |
+
*/
|
300 |
+
protected function remove_meta($item, $meta_key = null) {
|
301 |
+
if ( $this->key_valid($item) && isset($this->items_meta[$item]) ) {
|
302 |
+
if ( is_string($meta_key) ) {
|
303 |
+
//Remove specific meta value
|
304 |
+
unset($this->items_meta[$item][$meta_key]);
|
305 |
+
} else {
|
306 |
+
//Remove all metadata
|
307 |
+
unset($this->items_meta[$item]);
|
308 |
+
}
|
309 |
+
}
|
310 |
+
return $this;
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Retrieve metadata
|
315 |
+
* @param string $item Item key
|
316 |
+
* @param string $meta_key (optional) Meta key (All metadata retrieved if no key specified)
|
317 |
+
* @return mixed|null Metadata value
|
318 |
+
*/
|
319 |
+
protected function get_meta($item, $meta_key = null) {
|
320 |
+
$ret = null;
|
321 |
+
if ( $this->key_valid($item) && isset($this->items_meta[$item]) ) {
|
322 |
+
if ( is_null($meta_key) ) {
|
323 |
+
$ret = $this->items_meta[$item];
|
324 |
+
} elseif ( is_string($meta_key) && isset($this->items_meta[$item][$meta_key]) ) {
|
325 |
+
$ret = $this->items_meta[$item][$meta_key];
|
326 |
+
}
|
327 |
+
}
|
328 |
+
return $ret;
|
329 |
+
}
|
330 |
+
|
331 |
+
/* Collection */
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Build entire collection of items
|
335 |
+
* Prints output
|
336 |
+
*/
|
337 |
+
function build($build_vars = array()) {
|
338 |
+
//Parse vars
|
339 |
+
$this->parse_build_vars($build_vars);
|
340 |
+
$this->util->do_action_ref_array('build_init', array(&$this));
|
341 |
+
//Pre-build output
|
342 |
+
$this->util->do_action_ref_array('build_pre', array(&$this));
|
343 |
+
//Build groups
|
344 |
+
$this->build_groups();
|
345 |
+
//Post-build output
|
346 |
+
$this->util->do_action_ref_array('build_post', array(&$this));
|
347 |
+
}
|
348 |
+
|
349 |
+
/**
|
350 |
+
* Parses build variables prior to use
|
351 |
+
* @uses this->reset_build_vars() to reset build variables for each request
|
352 |
+
* @param array $build_vars Variables to use for current request
|
353 |
+
*/
|
354 |
+
function parse_build_vars($build_vars = array()) {
|
355 |
+
$this->reset_build_vars();
|
356 |
+
$this->build_vars = $this->util->apply_filters('parse_build_vars', wp_parse_args($build_vars, $this->build_vars), $this);
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* Reset build variables to defaults
|
361 |
+
* Default Variables
|
362 |
+
* > groups - array - Names of groups to build
|
363 |
+
* > context - string - Context of current request
|
364 |
+
* > layout - string - Name of default layout to use
|
365 |
+
*/
|
366 |
+
function reset_build_vars() {
|
367 |
+
$this->build_vars = wp_parse_args($this->build_vars, $this->build_vars_default);
|
368 |
+
}
|
369 |
+
}
|
includes/class.base_object.php
ADDED
@@ -0,0 +1,277 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Base Object
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Base
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Base_Object extends SLB_Base {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var string
|
14 |
+
* @see Base::$mode
|
15 |
+
*/
|
16 |
+
protected $mode = 'object';
|
17 |
+
|
18 |
+
/*-** Properties **-*/
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Unique ID
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected $id = '';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Parent object
|
28 |
+
* @var Base_Object
|
29 |
+
*/
|
30 |
+
protected $parent = null;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Attached files
|
34 |
+
* @var array
|
35 |
+
* > scripts array JS scripts
|
36 |
+
* > styles array Stylesheets
|
37 |
+
*/
|
38 |
+
protected $files = array(
|
39 |
+
'scripts' => array(),
|
40 |
+
'styles' => array()
|
41 |
+
);
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Properties that can be inherited from parent
|
45 |
+
* @var array
|
46 |
+
*/
|
47 |
+
protected $parent_props = array();
|
48 |
+
|
49 |
+
/*-** Methods **-*/
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor
|
53 |
+
* @param string $id Unique ID for content type
|
54 |
+
* @param array $props (optional) Type properties (optional because props can be set post-init)
|
55 |
+
*/
|
56 |
+
public function __construct($id, $props = null) {
|
57 |
+
parent::__construct();
|
58 |
+
$this
|
59 |
+
->set_id($id)
|
60 |
+
->set_props($props);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Checks if object is valid
|
65 |
+
* To be overriden by child classes
|
66 |
+
*/
|
67 |
+
public function is_valid() {
|
68 |
+
return true;
|
69 |
+
}
|
70 |
+
|
71 |
+
/*-** Getters/Setters **-*/
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Get ID
|
75 |
+
* @return string ID
|
76 |
+
*/
|
77 |
+
public function get_id() {
|
78 |
+
return $this->id;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Set ID
|
83 |
+
* @param string $id ID
|
84 |
+
* @return object Current instance
|
85 |
+
*/
|
86 |
+
public function set_id($id) {
|
87 |
+
$id = ( is_string($id) ) ? trim($id) : '';
|
88 |
+
if ( !empty($id) ) {
|
89 |
+
$this->id = $id;
|
90 |
+
}
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Set type properties
|
96 |
+
* @param array $props Type properties to set
|
97 |
+
*/
|
98 |
+
protected function set_props($props) {
|
99 |
+
if ( is_array($props) && !empty($props) ) {
|
100 |
+
foreach ( $props as $key => $val ) {
|
101 |
+
//Check for setter method
|
102 |
+
$m = 'set_' . $key;
|
103 |
+
if ( method_exists($this, $m) ) {
|
104 |
+
$this->{$m}($val);
|
105 |
+
}
|
106 |
+
}
|
107 |
+
}
|
108 |
+
return $this;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Get parent
|
113 |
+
* @return object|null Parent
|
114 |
+
*/
|
115 |
+
public function get_parent() {
|
116 |
+
return $this->parent;
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Set parent
|
121 |
+
* @param object $parent Parent object
|
122 |
+
* @return object Current instance
|
123 |
+
*/
|
124 |
+
public function set_parent($parent) {
|
125 |
+
$this->parent = ( $parent instanceof $this ) ? $parent : null;
|
126 |
+
return $this;
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Check if parent is set
|
131 |
+
* @return bool TRUE if parent is set
|
132 |
+
*/
|
133 |
+
public function has_parent() {
|
134 |
+
return ( is_null($this->parent) ) ? false : true;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Retrieve all ancestors
|
139 |
+
* @return array Ancestors
|
140 |
+
*/
|
141 |
+
public function get_ancestors() {
|
142 |
+
$ret = array();
|
143 |
+
$curr = $this;
|
144 |
+
while ( $curr->has_parent() ) {
|
145 |
+
//Add ancestor
|
146 |
+
$ret[] = $par = $curr->get_parent();
|
147 |
+
//Get next ancestor
|
148 |
+
$curr = $par;
|
149 |
+
}
|
150 |
+
return $ret;
|
151 |
+
}
|
152 |
+
|
153 |
+
/* Files */
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Add file
|
157 |
+
* @param string $type Group to add file to
|
158 |
+
* @param string $handle Name for resource
|
159 |
+
* @param string $src File URI
|
160 |
+
* @return object Current instance
|
161 |
+
*/
|
162 |
+
protected function add_file($type, $handle, $src, $deps = array()) {
|
163 |
+
if ( is_string($type) && is_string($handle) && is_string($src) ) {
|
164 |
+
//Validate dependencies
|
165 |
+
if ( !is_array($deps) ) {
|
166 |
+
$deps = array();
|
167 |
+
}
|
168 |
+
//Init file group
|
169 |
+
if ( !isset($this->files[$type]) || !is_array($this->files[$type]) ) {
|
170 |
+
$this->files[$type] = array();
|
171 |
+
}
|
172 |
+
//Add file to group
|
173 |
+
$this->files[$type][$handle] = array('handle' => $handle, 'uri' => $src, 'deps' => $deps);
|
174 |
+
}
|
175 |
+
return $this;
|
176 |
+
}
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Retrieve files
|
180 |
+
* All files or a specific group of files can be retrieved
|
181 |
+
* @param string $type (optional) File group to retrieve
|
182 |
+
* @return array Files
|
183 |
+
*/
|
184 |
+
protected function get_files($type = null) {
|
185 |
+
$ret = $this->files;
|
186 |
+
if ( is_string($type) ) {
|
187 |
+
$ret = ( isset($ret[$type]) ) ? $ret[$type] : array();
|
188 |
+
}
|
189 |
+
if ( !is_array($ret) ) {
|
190 |
+
$ret = array();
|
191 |
+
}
|
192 |
+
return $ret;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Retrieve file
|
197 |
+
* @param string $type Group to retrieve file from
|
198 |
+
* @param string $handle
|
199 |
+
* @param string $format (optional) Format of return value (Default: array)
|
200 |
+
* @return array|null File properties (Default: NULL)
|
201 |
+
*/
|
202 |
+
protected function get_file($type, $handle, $format = null) {
|
203 |
+
//Get files
|
204 |
+
$files = $this->get_files($type);
|
205 |
+
//Get specified file
|
206 |
+
$ret = ( is_string($type) && isset($files[$handle]) ) ? $files[$handle] : null;
|
207 |
+
//Format return value
|
208 |
+
if ( !empty($ret) && !!$format ) {
|
209 |
+
switch ( $format ) {
|
210 |
+
case 'uri':
|
211 |
+
$ret = $ret['uri'];
|
212 |
+
break;
|
213 |
+
case 'object':
|
214 |
+
$ret = (object) $ret;
|
215 |
+
break;
|
216 |
+
}
|
217 |
+
}
|
218 |
+
return $ret;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Add stylesheet
|
223 |
+
* @param string $handle Name of the stylesheet
|
224 |
+
* @param string $src Stylesheet URI
|
225 |
+
* @return object Current instance
|
226 |
+
*/
|
227 |
+
public function add_style($handle, $src, $deps = array()) {
|
228 |
+
return $this->add_file('styles', $handle, $src, $deps);
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Retrieve stylesheet files
|
233 |
+
* @return array Stylesheet files
|
234 |
+
*/
|
235 |
+
public function get_styles() {
|
236 |
+
return $this->get_files('styles');
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Retrieve stylesheet file
|
241 |
+
* @param string $handle Name of stylesheet
|
242 |
+
* @param string $format (optional) Format of return value (@see `get_file()`)
|
243 |
+
* @return array|null File properties (Default: NULL)
|
244 |
+
*/
|
245 |
+
public function get_style($handle, $format = null) {
|
246 |
+
return $this->get_file('styles', $handle, $format);
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Add script
|
251 |
+
* @param string $handle Name of the script
|
252 |
+
* @param string $src Script URI
|
253 |
+
* @return object Current instance
|
254 |
+
*/
|
255 |
+
public function add_script($handle, $src, $deps = array()) {
|
256 |
+
return $this->add_file('scripts', $handle, $src, $deps);
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Retrieve script files
|
261 |
+
* @return array Script files
|
262 |
+
*/
|
263 |
+
public function get_scripts() {
|
264 |
+
return $this->get_files('scripts');
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Retrieve script file
|
269 |
+
* @param string $handle Name of script
|
270 |
+
* @param string $format (optional) Format of return value (@see `get_file()`)
|
271 |
+
* @return array|null File properties (Default: NULL)
|
272 |
+
*/
|
273 |
+
public function get_script($handle, $format = null) {
|
274 |
+
return $this->get_file('scripts', $handle, $format);
|
275 |
+
}
|
276 |
+
|
277 |
+
}
|
includes/class.collection_controller.php
ADDED
@@ -0,0 +1,57 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Collection Controller
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Collection
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Collection_Controller extends SLB_Base_Collection {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
protected $mode = 'full';
|
13 |
+
|
14 |
+
protected $unique = true;
|
15 |
+
|
16 |
+
/* Properties */
|
17 |
+
|
18 |
+
protected $parent = null;
|
19 |
+
|
20 |
+
/* Methods */
|
21 |
+
|
22 |
+
public function __construct($parent = null) {
|
23 |
+
$this->set_parent($parent);
|
24 |
+
parent::__construct();
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Initialization */
|
28 |
+
|
29 |
+
/* Parent */
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Set parent instance
|
33 |
+
* @param SLB_Base $parent (optional) Parent instance
|
34 |
+
* @return obj Current instance
|
35 |
+
*/
|
36 |
+
protected function set_parent($parent = null) {
|
37 |
+
$this->parent = ( $parent instanceof SLB_Base ) ? $parent : null;
|
38 |
+
return $this;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Check if parent set
|
43 |
+
* @return bool TRUE if parent set
|
44 |
+
*/
|
45 |
+
protected function has_parent() {
|
46 |
+
return ( is_object($this->get_parent()) ) ? true : false;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Retrieve parent
|
51 |
+
* @uses $parent
|
52 |
+
* @return null|obj Parent instance (NULL if no parent set)
|
53 |
+
*/
|
54 |
+
protected function get_parent() {
|
55 |
+
return $this->parent;
|
56 |
+
}
|
57 |
+
}
|
includes/class.component.php
ADDED
@@ -0,0 +1,89 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Component
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Base
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Component extends SLB_Base_Object {
|
10 |
+
/* Properties */
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Pretty name
|
14 |
+
* @var string
|
15 |
+
*/
|
16 |
+
protected $name = '';
|
17 |
+
|
18 |
+
protected $props_required = array();
|
19 |
+
|
20 |
+
private $props_required_base = array('id');
|
21 |
+
|
22 |
+
/* Get/Set */
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Set name
|
26 |
+
* @param string $name Name
|
27 |
+
* @return Current instance
|
28 |
+
*/
|
29 |
+
public function set_name($name) {
|
30 |
+
if ( is_string($name) ) {
|
31 |
+
$name = trim($name);
|
32 |
+
if ( !empty($name) ) {
|
33 |
+
$this->name = $name;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
return $this;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function get_name() {
|
40 |
+
return $this->name;
|
41 |
+
}
|
42 |
+
|
43 |
+
/* Helpers */
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Validate instance
|
47 |
+
* @see `Base_Object::is_valid()`
|
48 |
+
* @return bool Valid (TRUE) / Invalid (FALSE)
|
49 |
+
*/
|
50 |
+
public function is_valid() {
|
51 |
+
$ret = parent::is_valid();
|
52 |
+
if ( $ret ) {
|
53 |
+
//Check required component properties
|
54 |
+
$props = array_merge($this->props_required_base, $this->props_required);
|
55 |
+
foreach ( $props as $prop ) {
|
56 |
+
if ( !isset($this->{$prop}) || empty($this->{$prop}) ) {
|
57 |
+
$ret = false;
|
58 |
+
break;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
return $ret;
|
63 |
+
}
|
64 |
+
|
65 |
+
/* Client */
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Set client script file
|
69 |
+
* @see Base_Object::add_script()
|
70 |
+
* @param string $src Script URI
|
71 |
+
* @param array $deps (optional) File dependencies
|
72 |
+
*/
|
73 |
+
public function set_client_script($src, $deps = array()) {
|
74 |
+
if ( is_array($src) ) {
|
75 |
+
list($src, $deps) = func_get_arg(0);
|
76 |
+
}
|
77 |
+
return $this->add_script('client', $src, $deps);
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Retrieve client script
|
82 |
+
* @see Base_Object::get_script()
|
83 |
+
* @param string $format (optional) Data format of return value
|
84 |
+
* @return mixed Client script data (formatted according to $format parameter)
|
85 |
+
*/
|
86 |
+
public function get_client_script($format = null) {
|
87 |
+
return $this->get_script('client', $format);
|
88 |
+
}
|
89 |
+
}
|
includes/class.content_handler.php
ADDED
@@ -0,0 +1,57 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Content Handler
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Content Handlers
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Content_Handler extends SLB_Component {
|
10 |
+
/* Properties */
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Match handler
|
14 |
+
* @var callback
|
15 |
+
*/
|
16 |
+
protected $match;
|
17 |
+
|
18 |
+
/* Matching */
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Set matching handler
|
22 |
+
* @param callback $callback Handler callback
|
23 |
+
* @return object Current instance
|
24 |
+
*/
|
25 |
+
public function set_match($callback) {
|
26 |
+
$this->match = ( is_callable($callback) ) ? $callback : null;
|
27 |
+
return $this;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Retrieve match handler
|
32 |
+
* @return callback|null Match handler
|
33 |
+
*/
|
34 |
+
protected function get_match() {
|
35 |
+
return $this->match;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Check if valid match set
|
40 |
+
*/
|
41 |
+
protected function has_match() {
|
42 |
+
return ( is_null($this->match) ) ? false : true;
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Match handler against URI
|
47 |
+
* @param string $uri URI to check for match
|
48 |
+
* @return bool TRUE if handler matches URI
|
49 |
+
*/
|
50 |
+
public function match($uri) {
|
51 |
+
$ret = false;
|
52 |
+
if ( !!$uri && is_string($uri) && $this->has_match() ) {
|
53 |
+
$ret = call_user_func($this->get_match(), $uri);
|
54 |
+
}
|
55 |
+
return $ret;
|
56 |
+
}
|
57 |
+
}
|
includes/class.content_handlers.php
ADDED
@@ -0,0 +1,228 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Content Handler Collection
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Content Handler
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Content_Handlers extends SLB_Collection_Controller {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
protected $item_type = 'SLB_Content_Handler';
|
13 |
+
|
14 |
+
public $hook_prefix = 'content_handlers';
|
15 |
+
|
16 |
+
protected $key_prop = 'get_id';
|
17 |
+
|
18 |
+
protected $key_call = true;
|
19 |
+
|
20 |
+
/* Properties */
|
21 |
+
|
22 |
+
protected $request_matches = array();
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Cache properties (key, group)
|
26 |
+
* @var object
|
27 |
+
*/
|
28 |
+
protected $cache_props = null;
|
29 |
+
|
30 |
+
/* Initialization */
|
31 |
+
|
32 |
+
protected function _hooks() {
|
33 |
+
parent::_hooks();
|
34 |
+
$this->util->add_action('init', $this->m('init_defaults'));
|
35 |
+
|
36 |
+
add_action('wp_footer', $this->m('client_output'), $this->util->priority('client_footer_output'));
|
37 |
+
}
|
38 |
+
|
39 |
+
/* Collection Management */
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Add content type handler
|
43 |
+
* Accepts properties to create new handler OR previously-initialized handler instance
|
44 |
+
* @uses clear_cache()
|
45 |
+
* @see parent::add()
|
46 |
+
* @param string $id Handler ID
|
47 |
+
* @param array $props Handler properties
|
48 |
+
* @return object Current instance
|
49 |
+
*/
|
50 |
+
public function add($id, $props = array(), $priority = 10) {
|
51 |
+
$this->clear_cache();
|
52 |
+
if ( is_string($id) ) {
|
53 |
+
//Initialize new handler
|
54 |
+
$handler = new $this->item_type($id, $props);
|
55 |
+
} else {
|
56 |
+
//Remap parameters
|
57 |
+
$handler = func_get_arg(0);
|
58 |
+
if ( func_num_args() == 2 ) {
|
59 |
+
$priority = func_get_arg(1);
|
60 |
+
}
|
61 |
+
}
|
62 |
+
if ( !is_int($priority) ) {
|
63 |
+
$priority = 10;
|
64 |
+
}
|
65 |
+
//Add to collection
|
66 |
+
return parent::add($handler, array('priority' => $priority));
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Remove item
|
71 |
+
* @uses clear_cache()
|
72 |
+
* @see parent::remove()
|
73 |
+
* @return object Current instance
|
74 |
+
*/
|
75 |
+
public function remove($item) {
|
76 |
+
$this->clear_cache();
|
77 |
+
return parent::remove($item);
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Clear collection
|
82 |
+
* @uses clear_cache()
|
83 |
+
* @see parent::clear()
|
84 |
+
* @return object Current instance
|
85 |
+
*/
|
86 |
+
public function clear() {
|
87 |
+
$this->clear_cache();
|
88 |
+
return parent::clear();
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Retrieves handlers sorted by priority
|
93 |
+
* @see parent::get()
|
94 |
+
* @uses get_cache()
|
95 |
+
* @return array Handlers
|
96 |
+
*/
|
97 |
+
public function get() {
|
98 |
+
$items = $this->get_cache();
|
99 |
+
if ( empty($items) ) {
|
100 |
+
//Retrieve items
|
101 |
+
$items = parent::get( array( 'orderby' => array('meta' => 'priority') ) );
|
102 |
+
$this->update_cache($items);
|
103 |
+
}
|
104 |
+
return $items;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Get matching handler for URI
|
109 |
+
* @param string $uri URI to find match for
|
110 |
+
* @return SLB_Content_Handler Matching handler (NULL if no handler matched)
|
111 |
+
*/
|
112 |
+
public function match($uri) {
|
113 |
+
foreach ( $this->get() as $handler ) {
|
114 |
+
if ( $handler->match($uri) ) {
|
115 |
+
//Save match
|
116 |
+
$hid = $handler->get_id();
|
117 |
+
if ( !isset($this->request_matches[$hid]) ) {
|
118 |
+
$this->request_matches[$hid] = $handler;
|
119 |
+
}
|
120 |
+
return $handler;
|
121 |
+
}
|
122 |
+
}
|
123 |
+
return null;
|
124 |
+
}
|
125 |
+
|
126 |
+
/* Cache */
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Retrieve cached items
|
130 |
+
* @uses get_cache_props()
|
131 |
+
* @uses wp_cache_get()
|
132 |
+
* @return array Cached items (Default: empty array)
|
133 |
+
*/
|
134 |
+
protected function get_cache() {
|
135 |
+
$cprops= $this->get_cache_props();
|
136 |
+
$items = wp_cache_get($cprops->key, $cprops->group);
|
137 |
+
return ( is_array($items) ) ? $items : array();
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Update cached items
|
142 |
+
* Cache is cleared if no items specified
|
143 |
+
* @uses get_cache_props()
|
144 |
+
* @uses wp_cache_get()
|
145 |
+
* @param array $data Item data to cache
|
146 |
+
*/
|
147 |
+
protected function update_cache($data = null) {
|
148 |
+
$props = $this->get_cache_props();
|
149 |
+
wp_cache_set($props->key, $data, $props->group);
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Clear cache
|
154 |
+
* @uses update_cache()
|
155 |
+
*/
|
156 |
+
protected function clear_cache() {
|
157 |
+
$this->update_cache();
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Retrieve cache properites (key, group)
|
162 |
+
* @return object Cache properties
|
163 |
+
*/
|
164 |
+
protected function get_cache_props() {
|
165 |
+
if ( !is_object($this->cache_props) ) {
|
166 |
+
$this->cache_props = (object) array (
|
167 |
+
'key' => $this->hook_prefix . '_items',
|
168 |
+
'group' => $this->get_prefix(),
|
169 |
+
);
|
170 |
+
}
|
171 |
+
return $this->cache_props;
|
172 |
+
}
|
173 |
+
|
174 |
+
/* Handlers */
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Initialize default handlers
|
178 |
+
* @param SLB_Content_Handlers $controller Handlers controller
|
179 |
+
*/
|
180 |
+
public function init_defaults($controller) {
|
181 |
+
$handlers = array (
|
182 |
+
'image' => array (
|
183 |
+
'match' => $this->m('match_image'),
|
184 |
+
'client_script' => $this->util->get_file_url('content-handlers/image/handler.image.js'),
|
185 |
+
),
|
186 |
+
);
|
187 |
+
foreach ( $handlers as $id => $props ) {
|
188 |
+
$controller->add($id, $props);
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Matches image URIs
|
194 |
+
* @param string $uri URI to match
|
195 |
+
* @return bool TRUE if URI is image
|
196 |
+
*/
|
197 |
+
public function match_image($uri) {
|
198 |
+
return ( $this->util->has_file_extension($uri, array('jpg', 'jpeg', 'jpe', 'jfif', 'jif', 'gif', 'png')) ) ? true : false;
|
199 |
+
}
|
200 |
+
|
201 |
+
/* Output */
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Client output
|
205 |
+
*/
|
206 |
+
public function client_output() {
|
207 |
+
//Stop if not enabled
|
208 |
+
if ( !$this->has_parent() || !$this->get_parent()->is_enabled() ) {
|
209 |
+
return;
|
210 |
+
}
|
211 |
+
$id_fmt = 'add_handler_%s';
|
212 |
+
$out = array();
|
213 |
+
$out[] = '<!-- SLB-HDL -->' . PHP_EOL;
|
214 |
+
$code = array();
|
215 |
+
//Load matched handlers
|
216 |
+
foreach ( $this->request_matches as $handler ) {
|
217 |
+
//Define
|
218 |
+
$params = array(
|
219 |
+
sprintf("'%s'", $handler->get_id()),
|
220 |
+
sprintf("'%s'", $handler->get_client_script('uri')),
|
221 |
+
);
|
222 |
+
$code[] = $this->util->call_client_method('View.add_content_handler', $params, false);
|
223 |
+
}
|
224 |
+
$out[] = $this->util->build_script_element(implode('', $code), 'add_content_handlers', true, true);
|
225 |
+
$out[] = '<!-- /SLB-HDL -->' . PHP_EOL;
|
226 |
+
echo implode('', $out);
|
227 |
+
}
|
228 |
+
}
|
includes/class.fields.php
ADDED
@@ -0,0 +1,2590 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Fields - Base class
|
5 |
+
* Core properties/methods for fields
|
6 |
+
* @package Simple Lightbox
|
7 |
+
* @subpackage Fields
|
8 |
+
* @author Archetyped
|
9 |
+
*/
|
10 |
+
class SLB_Field_Base extends SLB_Base {
|
11 |
+
/*-** Config **-*/
|
12 |
+
protected $mode = 'object';
|
13 |
+
protected $shared = false;
|
14 |
+
|
15 |
+
/*-** Properties **-*/
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string Unique name
|
19 |
+
*/
|
20 |
+
var $id = '';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* ID formatting options
|
24 |
+
* Merged with defaults during initialization
|
25 |
+
* @see $id_formats_default
|
26 |
+
* @var array
|
27 |
+
*/
|
28 |
+
var $id_formats = null;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Default ID Formatting options
|
32 |
+
* Structure:
|
33 |
+
* > Key (string): Format name
|
34 |
+
* > Val (array): Options
|
35 |
+
* @var array
|
36 |
+
*/
|
37 |
+
var $id_formats_default = array(
|
38 |
+
'attr_id' => array(
|
39 |
+
'wrap' => array('open' => '_', 'segment_open' => '_'),
|
40 |
+
'prefix' => array('get_container', 'get_id', 'add_prefix'),
|
41 |
+
'recursive' => true
|
42 |
+
),
|
43 |
+
'attr_name' => array(
|
44 |
+
'wrap' => array('open' => '[', 'close' => ']', 'segment_open' => '[', 'segment_close' => ']'),
|
45 |
+
'recursive' => true,
|
46 |
+
'prefix' => array('get_container', 'get_id', 'add_prefix')
|
47 |
+
)
|
48 |
+
);
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Special characters/phrases
|
52 |
+
* Used for preserving special characters during formatting
|
53 |
+
* Merged with $special_chars_default
|
54 |
+
* Array Structure
|
55 |
+
* > Key: Special character/phrase
|
56 |
+
* > Value: Placeholder for special character
|
57 |
+
* @var array
|
58 |
+
*/
|
59 |
+
var $special_chars = null;
|
60 |
+
|
61 |
+
var $special_chars_default = array(
|
62 |
+
'{' => '%SQB_L%',
|
63 |
+
'}' => '%SQB_R%',
|
64 |
+
);
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Reference to parent object that current instance inherits from
|
68 |
+
* @var object
|
69 |
+
*/
|
70 |
+
var $parent = null;
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Title
|
74 |
+
* @var string
|
75 |
+
*/
|
76 |
+
var $title = '';
|
77 |
+
|
78 |
+
/**
|
79 |
+
* @var string Short description
|
80 |
+
*/
|
81 |
+
var $description = '';
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @var array Object Properties
|
85 |
+
*/
|
86 |
+
var $properties = array();
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Initialization properties
|
90 |
+
* @var array
|
91 |
+
*/
|
92 |
+
protected $properties_init = null;
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Structure: Property names stored as keys in group
|
96 |
+
* Root
|
97 |
+
* -> Group Name
|
98 |
+
* -> Property Name => Null
|
99 |
+
* Reason: Faster searching over large arrays
|
100 |
+
* @var array Groupings of Properties
|
101 |
+
*/
|
102 |
+
var $property_groups = array();
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Keys to filter out of properties array before setting properties
|
106 |
+
* @var array
|
107 |
+
*/
|
108 |
+
var $property_filter = array('group');
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Define order of properties
|
112 |
+
* Useful when processing order is important (e.g. one property depends on another)
|
113 |
+
* @var array
|
114 |
+
*/
|
115 |
+
var $property_priority = array();
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Data for object
|
119 |
+
* May also contain data for nested objects
|
120 |
+
* @var mixed
|
121 |
+
*/
|
122 |
+
var $data = null;
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Whether data has been fetched or not
|
126 |
+
* @var bool
|
127 |
+
*/
|
128 |
+
var $data_loaded = false;
|
129 |
+
|
130 |
+
/**
|
131 |
+
* @var array Script resources to include for object
|
132 |
+
*/
|
133 |
+
var $scripts = array();
|
134 |
+
|
135 |
+
/**
|
136 |
+
* @var array CSS style resources to include for object
|
137 |
+
*/
|
138 |
+
var $styles = array();
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Hooks (Filters/Actions) for object
|
142 |
+
* @var array
|
143 |
+
*/
|
144 |
+
var $hooks = array();
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Mapping of child properties to parent members
|
148 |
+
* Allows more flexibility when creating new instances of child objects using property arrays
|
149 |
+
* Associative array structure:
|
150 |
+
* > Key: Child property to map FROM
|
151 |
+
* > Val: Parent property to map TO
|
152 |
+
* @var array
|
153 |
+
*/
|
154 |
+
var $map = null;
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Options used when building collection (callbacks, etc.)
|
158 |
+
* Associative array
|
159 |
+
* > Key: Option name
|
160 |
+
* > Value: Option value
|
161 |
+
* @var array
|
162 |
+
*/
|
163 |
+
var $build_vars = array();
|
164 |
+
|
165 |
+
var $build_vars_default = array();
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Constructor
|
169 |
+
*/
|
170 |
+
function __construct($id = '', $properties = null) {
|
171 |
+
parent::__construct();
|
172 |
+
//Normalize Properties
|
173 |
+
$args = func_get_args();
|
174 |
+
$defaults = $this->integrate_id($id);
|
175 |
+
$properties = $this->make_properties($args, $defaults);
|
176 |
+
//Save init properties
|
177 |
+
$this->properties_init = $properties;
|
178 |
+
//Set Properties
|
179 |
+
$this->set_properties($properties);
|
180 |
+
}
|
181 |
+
|
182 |
+
/* Getters/Setters */
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Checks if the specified path exists in the object
|
186 |
+
* @param array $path Path to check for
|
187 |
+
* @return bool TRUE if path exists in object, FALSE otherwise
|
188 |
+
*/
|
189 |
+
function path_isset($path = '') {
|
190 |
+
//Stop execution if no path is supplied
|
191 |
+
if ( empty($path) )
|
192 |
+
return false;
|
193 |
+
$args = func_get_args();
|
194 |
+
$path = $this->util->build_path($args);
|
195 |
+
$item =& $this;
|
196 |
+
//Iterate over path and check if each level exists before moving on to the next
|
197 |
+
for ($x = 0; $x < count($path); $x++) {
|
198 |
+
if ( $this->util->property_exists($item, $path[$x]) ) {
|
199 |
+
//Set $item as reference to next level in path for next iteration
|
200 |
+
$item =& $this->util->get_property($item, $path[$x]);
|
201 |
+
//$item =& $item[ $path[$x] ];
|
202 |
+
} else {
|
203 |
+
return false;
|
204 |
+
}
|
205 |
+
}
|
206 |
+
return true;
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Retrieves a value from object using a specified path
|
211 |
+
* Checks to make sure path exists in object before retrieving value
|
212 |
+
* @param array $path Path to retrieve value from. Each item in array is a deeper dimension
|
213 |
+
* @return mixed Value at specified path
|
214 |
+
*/
|
215 |
+
function &get_path_value($path = '') {
|
216 |
+
$ret = '';
|
217 |
+
$path = $this->util->build_path(func_get_args());
|
218 |
+
if ( $this->path_isset($path) ) {
|
219 |
+
$ret =& $this;
|
220 |
+
for ($x = 0; $x < count($path); $x++) {
|
221 |
+
if ( 0 == $x )
|
222 |
+
$ret =& $ret->{ $path[$x] };
|
223 |
+
else
|
224 |
+
$ret =& $ret[ $path[$x] ];
|
225 |
+
}
|
226 |
+
}
|
227 |
+
return $ret;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Search for specified member value in field type ancestors
|
232 |
+
* @param string $member Name of object member to search (e.g. properties, layout, etc.)
|
233 |
+
* @param string $name Value to retrieve from member
|
234 |
+
* @return mixed Member value if found (Default: empty string)
|
235 |
+
*/
|
236 |
+
function get_parent_value($member, $name = '', $default = '') {
|
237 |
+
$parent =& $this->get_parent();
|
238 |
+
return $this->get_object_value($parent, $member, $name, $default, 'parent');
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Retrieves specified member value
|
243 |
+
* Handles inherited values
|
244 |
+
* Merging corresponding parents if value is an array (e.g. for property groups)
|
245 |
+
* @param string|array $member Member to search. May also contain a path to the desired member
|
246 |
+
* @param string $name Value to retrieve from member
|
247 |
+
* @param mixed $default Default value if no value found (Default: empty string)
|
248 |
+
* @param string $dir Direction to move through hierarchy to find value
|
249 |
+
* Possible Values:
|
250 |
+
* parent (default) - Search through field parents
|
251 |
+
* current - Do not search through connected objects
|
252 |
+
* container - Search through field containers
|
253 |
+
* caller - Search through field callers
|
254 |
+
* @return mixed Specified member value
|
255 |
+
* @todo Return reference
|
256 |
+
*/
|
257 |
+
function &get_member_value($member, $name = '', $default = '', $dir = 'parent') {
|
258 |
+
//Check if path to member is supplied
|
259 |
+
$path = array();
|
260 |
+
if ( is_array($member) && isset($member['tag']) ) {
|
261 |
+
if ( isset($member['attributes']['ref_base']) ) {
|
262 |
+
if ( 'root' != $member['attributes']['ref_base'] )
|
263 |
+
$path[] = $member['attributes']['ref_base'];
|
264 |
+
} else {
|
265 |
+
$path[] = 'properties';
|
266 |
+
}
|
267 |
+
|
268 |
+
$path[] = $member['tag'];
|
269 |
+
} else {
|
270 |
+
$path = $member;
|
271 |
+
}
|
272 |
+
|
273 |
+
$path = $this->util->build_path($path, $name);
|
274 |
+
//Set defaults and prepare data
|
275 |
+
$val = $default;
|
276 |
+
$inherit = false;
|
277 |
+
$inherit_tag = '{inherit}';
|
278 |
+
|
279 |
+
/* Determine whether the value must be retrieved from a parent/container object
|
280 |
+
* Conditions:
|
281 |
+
* > Path does not exist in current field
|
282 |
+
* > Path exists and is not an object, but at least one of the following is true:
|
283 |
+
* > Value at path is an array (e.g. properties, elements, etc. array)
|
284 |
+
* > Parent/container values should be merged with retrieved array
|
285 |
+
* > Value at path is a string that inherits from another field
|
286 |
+
* > Value from other field will be retrieved and will replace inheritance placeholder in retrieved value
|
287 |
+
*/
|
288 |
+
|
289 |
+
$deeper = false;
|
290 |
+
|
291 |
+
if ( !$this->path_isset($path) )
|
292 |
+
$deeper = true;
|
293 |
+
else {
|
294 |
+
$val = $this->get_path_value($path);
|
295 |
+
if ( !is_object($val) && ( is_array($val) || ($inherit = strpos($val, $inherit_tag)) !== false ) )
|
296 |
+
$deeper = true;
|
297 |
+
else
|
298 |
+
$deeper = false;
|
299 |
+
}
|
300 |
+
if ( $deeper && 'current' != $dir ) {
|
301 |
+
$ex_val = '';
|
302 |
+
//Get Parent value (recursive)
|
303 |
+
if ( 'parent' == $dir )
|
304 |
+
$ex_val = $this->get_parent_value($member, $name, $default);
|
305 |
+
elseif ( method_exists($this, 'get_container_value') )
|
306 |
+
$ex_val = $this->get_container_value($member, $name, $default);
|
307 |
+
//Handle inheritance
|
308 |
+
if ( is_array($val) ) {
|
309 |
+
//Combine Arrays
|
310 |
+
if ( is_array($ex_val) )
|
311 |
+
$val = array_merge($ex_val, $val);
|
312 |
+
} elseif ( $inherit !== false ) {
|
313 |
+
//Replace placeholder with inherited string
|
314 |
+
$val = str_replace($inherit_tag, $ex_val, $val);
|
315 |
+
} else {
|
316 |
+
//Default: Set parent value as value
|
317 |
+
$val = $ex_val;
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
return $val;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Search for specified member value in an object
|
326 |
+
* @param object $object Reference to object to retrieve value from
|
327 |
+
* @param string $member Name of object member to search (e.g. properties, layout, etc.)
|
328 |
+
* @param string $name (optional) Value to retrieve from member
|
329 |
+
* @param mixed $default (optional) Default value to use if no value found (Default: empty string)
|
330 |
+
* @param string $dir Direction to move through hierarchy to find value @see SLB_Field_Type::get_member_value() for possible values
|
331 |
+
* @return mixed Member value if found (Default: $default)
|
332 |
+
*/
|
333 |
+
function get_object_value(&$object, $member, $name = '', $default = '', $dir = 'parent') {
|
334 |
+
$ret = $default;
|
335 |
+
if ( is_object($object) && method_exists($object, 'get_member_value') )
|
336 |
+
$ret = $object->get_member_value($member, $name, $default, $dir);
|
337 |
+
return $ret;
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Set item ID
|
342 |
+
* @param string $id Unique item ID
|
343 |
+
*/
|
344 |
+
function set_id($id) {
|
345 |
+
if ( empty($id) || !is_string($id) )
|
346 |
+
return false;
|
347 |
+
$this->id = trim($id);
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Retrieves field ID
|
352 |
+
* @param array|string $options (optional) Options or ID of format to use
|
353 |
+
* @return string item ID
|
354 |
+
*/
|
355 |
+
function get_id($options = array()) {
|
356 |
+
$item_id = trim($this->id);
|
357 |
+
$formats = $this->get_id_formats();
|
358 |
+
|
359 |
+
//Setup options
|
360 |
+
$wrap_default = array('open' => '', 'close' => '', 'segment_open' => '', 'segment_close' => '');
|
361 |
+
|
362 |
+
$options_default = array(
|
363 |
+
'format' => null,
|
364 |
+
'wrap' => array(),
|
365 |
+
'segments_pre' => null,
|
366 |
+
'prefix' => '',
|
367 |
+
'recursive' => false
|
368 |
+
);
|
369 |
+
|
370 |
+
//Load options based on format
|
371 |
+
if ( !is_array($options) )
|
372 |
+
$options = array('format' => $options);
|
373 |
+
if ( isset($options['format']) && is_string($options['format']) && isset($formats[$options['format']]) )
|
374 |
+
$options_default = wp_parse_args($formats[$options['format']], $options_default);
|
375 |
+
else
|
376 |
+
unset($options['format']);
|
377 |
+
$options = wp_parse_args($options, $options_default);
|
378 |
+
//Import options into function
|
379 |
+
extract($options);
|
380 |
+
|
381 |
+
//Validate options
|
382 |
+
$wrap = wp_parse_args($wrap, $wrap_default);
|
383 |
+
|
384 |
+
if ( !is_array($segments_pre) )
|
385 |
+
$segments_pre = array($segments_pre);
|
386 |
+
$segments_pre = array_reverse($segments_pre);
|
387 |
+
|
388 |
+
//Format ID based on options
|
389 |
+
$item_id = array($item_id);
|
390 |
+
|
391 |
+
//Add parent objects to ID
|
392 |
+
if ( !!$recursive ) {
|
393 |
+
//Create array of ID components
|
394 |
+
$m = 'get_caller';
|
395 |
+
$c = ( method_exists($this, $m) ) ? $this->{$m}() : null;
|
396 |
+
while ( !!$c ) {
|
397 |
+
//Add ID of current caller to array
|
398 |
+
if ( method_exists($c, 'get_id') && ( $itemp = $c->get_id() ) && !empty($itemp) )
|
399 |
+
$item_id = $itemp;
|
400 |
+
//Get parent object
|
401 |
+
$c = ( method_exists($c, $m) ) ? $c->{$m}() : null;
|
402 |
+
$itemp = '';
|
403 |
+
}
|
404 |
+
unset($c);
|
405 |
+
}
|
406 |
+
|
407 |
+
//Additional segments (Pre)
|
408 |
+
foreach ( $segments_pre as $seg ) {
|
409 |
+
if ( is_null($seg) )
|
410 |
+
continue;
|
411 |
+
if ( is_object($seg) )
|
412 |
+
$seg = (array)$seg;
|
413 |
+
if ( is_array($seg) )
|
414 |
+
$item_id = array_merge($item_id, array_reverse($seg));
|
415 |
+
elseif ( '' != strval($seg) )
|
416 |
+
$item_id[] = strval($seg);
|
417 |
+
}
|
418 |
+
|
419 |
+
//Prefix
|
420 |
+
if ( is_array($prefix) ) {
|
421 |
+
//Array is sequence of instance methods to call on object
|
422 |
+
//Last array member can be an array of parameters to pass to methods
|
423 |
+
$count = count($prefix);
|
424 |
+
$args = ( $count > 1 && is_array($prefix[$count - 1]) ) ? array_pop($prefix) : array();
|
425 |
+
$p = $this;
|
426 |
+
$val = '';
|
427 |
+
//Iterate through methods
|
428 |
+
foreach ( $prefix as $m ) {
|
429 |
+
if ( !method_exists($p, $m) )
|
430 |
+
continue;
|
431 |
+
//Build callback
|
432 |
+
$m = $this->util->m($p, $m);
|
433 |
+
//Call callback
|
434 |
+
$val = call_user_func_array($m, $args);
|
435 |
+
//Returned value may be an instance object
|
436 |
+
if ( is_object($val) )
|
437 |
+
$p = $val; //Use returned object in next round
|
438 |
+
else
|
439 |
+
array_unshift($args, $val); //Pass returned value as parameter to next method on using current object
|
440 |
+
}
|
441 |
+
$prefix = $val;
|
442 |
+
unset($p, $val);
|
443 |
+
}
|
444 |
+
if ( is_numeric($prefix) )
|
445 |
+
$prefix = strval($prefix);
|
446 |
+
if ( empty($prefix) || !is_string($prefix) )
|
447 |
+
$prefix = '';
|
448 |
+
|
449 |
+
//Convert array to string
|
450 |
+
$item_id = $prefix . $wrap['open'] . implode($wrap['segment_close'] . $wrap['segment_open'], array_reverse($item_id)) . $wrap['close'];
|
451 |
+
return $item_id;
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* Retrieve ID formatting options for class
|
456 |
+
* Format options arrays are merged together and saved to $id_formats
|
457 |
+
* @uses $id_formats
|
458 |
+
* @uses $id_formats_default
|
459 |
+
* @return array ID Formatting options
|
460 |
+
*/
|
461 |
+
function &get_id_formats() {
|
462 |
+
if ( is_null($this->id_formats) ) {
|
463 |
+
$this->id_formats = wp_parse_args($this->id_formats, $this->id_formats_default);
|
464 |
+
}
|
465 |
+
return $this->id_formats;
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
* Retrieve value from data member
|
470 |
+
* @param string $context Context to format data for
|
471 |
+
* @param bool $top (optional) Whether to traverse through the field hierarchy to get data for field (Default: TRUE)
|
472 |
+
* @return mixed Value at specified path
|
473 |
+
*/
|
474 |
+
function get_data($context = '', $top = true) {
|
475 |
+
$opt_d = array('context' => '', 'top' => true);
|
476 |
+
$args = func_get_args();
|
477 |
+
$a = false;
|
478 |
+
if ( count($args) == 1 && is_array($args[0]) && !empty($args[0]) ) {
|
479 |
+
$a = true;
|
480 |
+
$args = wp_parse_args($args[0], $opt_d);
|
481 |
+
extract($args);
|
482 |
+
}
|
483 |
+
|
484 |
+
if ( is_string($top) ) {
|
485 |
+
if ( 'false' == $top )
|
486 |
+
$top = false;
|
487 |
+
elseif ( 'true' == $top )
|
488 |
+
$top = true;
|
489 |
+
elseif ( is_numeric($top) )
|
490 |
+
$top = intval($top);
|
491 |
+
}
|
492 |
+
$top = !!$top;
|
493 |
+
$obj =& $this;
|
494 |
+
$obj_path = array(&$this);
|
495 |
+
$path = array();
|
496 |
+
if ( $top ) {
|
497 |
+
//Iterate through hiearchy to get top-most object
|
498 |
+
while ( !empty($obj) ) {
|
499 |
+
$new = null;
|
500 |
+
//Try to get caller first
|
501 |
+
if ( method_exists($obj, 'get_caller') ) {
|
502 |
+
$checked = true;
|
503 |
+
$new =& $obj->get_caller();
|
504 |
+
}
|
505 |
+
//Try to get container if no caller found
|
506 |
+
if ( empty($new) && method_exists($obj, 'get_container') ) {
|
507 |
+
$checked = true;
|
508 |
+
$new =& $obj->get_container();
|
509 |
+
//Load data
|
510 |
+
if ( method_exists($new, 'load_data') ) {
|
511 |
+
$new->load_data();
|
512 |
+
}
|
513 |
+
}
|
514 |
+
|
515 |
+
$obj =& $new;
|
516 |
+
unset($new);
|
517 |
+
//Stop iteration
|
518 |
+
if ( !empty($obj) ) {
|
519 |
+
//Add object to path if it is valid
|
520 |
+
$obj_path[] =& $obj;
|
521 |
+
}
|
522 |
+
}
|
523 |
+
unset($obj);
|
524 |
+
}
|
525 |
+
|
526 |
+
//Check each object (starting with top-most) for matching data for current field
|
527 |
+
|
528 |
+
//Reverse array
|
529 |
+
$obj_path = array_reverse($obj_path);
|
530 |
+
//Build path for data location
|
531 |
+
foreach ( $obj_path as $obj ) {
|
532 |
+
if ( method_exists($obj, 'get_id') )
|
533 |
+
$path[] = $obj->get_id();
|
534 |
+
}
|
535 |
+
//Iterate through objects
|
536 |
+
while ( !empty($obj_path) ) {
|
537 |
+
//Get next object
|
538 |
+
$obj =& array_shift($obj_path);
|
539 |
+
//Shorten path
|
540 |
+
array_shift($path);
|
541 |
+
//Check for value in object and stop iteration if matching data found
|
542 |
+
$val = $this->get_object_value($obj, 'data', $path, null, 'current');
|
543 |
+
if ( !is_null($val) ) {
|
544 |
+
break;
|
545 |
+
}
|
546 |
+
}
|
547 |
+
return $this->format($val, $context);
|
548 |
+
}
|
549 |
+
|
550 |
+
/**
|
551 |
+
* Sets value in data member
|
552 |
+
* Sets value to data member itself by default
|
553 |
+
* @param mixed $value Value to set
|
554 |
+
* @param string|array $name Name of value to set (Can also be path to value)
|
555 |
+
*/
|
556 |
+
function set_data($value, $name = '') {
|
557 |
+
$ref =& $this->get_path_value('data', $name);
|
558 |
+
$ref = $value;
|
559 |
+
}
|
560 |
+
|
561 |
+
/**
|
562 |
+
* Sets parent object of current instance
|
563 |
+
* Parent objects must be the same object type as current instance
|
564 |
+
* @uses SLB to get field type definition
|
565 |
+
* @uses SLB_Fields::has() to check if field type exists
|
566 |
+
* @uses SLB_Fields::get() to retrieve field type object reference
|
567 |
+
* @param string|object $parent Parent ID or reference
|
568 |
+
*/
|
569 |
+
function set_parent($parent = null) {
|
570 |
+
//Stop processing if parent empty
|
571 |
+
if ( empty($parent) && !is_string($this->parent) )
|
572 |
+
return false;
|
573 |
+
//Parent passed as object reference wrapped in array
|
574 |
+
if ( is_array($parent) && isset($parent[0]) && is_object($parent[0]) )
|
575 |
+
$parent =& $parent[0];
|
576 |
+
|
577 |
+
//No parent set but parent ID (previously) set in object
|
578 |
+
if ( empty($parent) && is_string($this->parent) )
|
579 |
+
$parent = $this->parent;
|
580 |
+
|
581 |
+
//Retrieve reference object if ID was supplied
|
582 |
+
if ( is_string($parent) ) {
|
583 |
+
$parent = trim($parent);
|
584 |
+
//Get parent object reference
|
585 |
+
/**
|
586 |
+
* @var SLB
|
587 |
+
*/
|
588 |
+
$b =& $this->get_base();
|
589 |
+
if ( $b && isset($b->fields) && $b->fields->has($parent) ) {
|
590 |
+
$parent =& $b->fields->get($parent);
|
591 |
+
}
|
592 |
+
}
|
593 |
+
|
594 |
+
//Set parent value on object
|
595 |
+
if ( is_string($parent) || is_object($parent) )
|
596 |
+
$this->parent =& $parent;
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Retrieve field type parent
|
601 |
+
* @return SLB_Field_Type Reference to parent field
|
602 |
+
*/
|
603 |
+
function &get_parent() {
|
604 |
+
return $this->parent;
|
605 |
+
}
|
606 |
+
|
607 |
+
/**
|
608 |
+
* Set object title
|
609 |
+
* @param string $title Title for object
|
610 |
+
* @param string $plural Plural form of title
|
611 |
+
*/
|
612 |
+
function set_title($title = '') {
|
613 |
+
if ( is_scalar($title) )
|
614 |
+
$this->title = strip_tags(trim($title));
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Retrieve object title
|
619 |
+
*/
|
620 |
+
function get_title() {
|
621 |
+
return $this->get_member_value('title', '','', 'current');
|
622 |
+
}
|
623 |
+
|
624 |
+
/**
|
625 |
+
* Set object description
|
626 |
+
* @param string $description Description for object
|
627 |
+
*/
|
628 |
+
function set_description($description = '') {
|
629 |
+
$this->description = strip_tags(trim($description));
|
630 |
+
}
|
631 |
+
|
632 |
+
/**
|
633 |
+
* Retrieve object description
|
634 |
+
* @return string Object description
|
635 |
+
*/
|
636 |
+
function get_description() {
|
637 |
+
$dir = 'current';
|
638 |
+
return $this->get_member_value('description', '','', $dir);
|
639 |
+
return $desc;
|
640 |
+
}
|
641 |
+
|
642 |
+
/**
|
643 |
+
* Sets multiple properties on field type at once
|
644 |
+
* @param array $properties Properties. Each element is an array containing the arguments to set a new property
|
645 |
+
* @return boolean TRUE if successful, FALSE otherwise
|
646 |
+
*/
|
647 |
+
function set_properties($properties) {
|
648 |
+
if ( !is_array($properties) ) {
|
649 |
+
return false;
|
650 |
+
}
|
651 |
+
//Normalize properties
|
652 |
+
$properties = $this->remap_properties($properties);
|
653 |
+
$properties = $this->sort_properties($properties);
|
654 |
+
//Set Member properties
|
655 |
+
foreach ( $properties as $prop => $val ) {
|
656 |
+
if ( ( $m = 'set_' . $prop ) && method_exists($this, $m) ) {
|
657 |
+
$this->{$m}($val);
|
658 |
+
//Remove member property from array
|
659 |
+
unset($properties[$prop]);
|
660 |
+
}
|
661 |
+
}
|
662 |
+
|
663 |
+
//Filter properties
|
664 |
+
$properties = $this->filter_properties($properties);
|
665 |
+
//Set additional instance properties
|
666 |
+
foreach ( $properties as $name => $val) {
|
667 |
+
$this->set_property($name, $val);
|
668 |
+
}
|
669 |
+
}
|
670 |
+
|
671 |
+
/**
|
672 |
+
* Remap properties based on $map
|
673 |
+
* @uses $map For determine how child properties should map to parent properties
|
674 |
+
* @uses SLB_Utlities::array_remap() to perform array remapping
|
675 |
+
* @param array $properties Associative array of properties
|
676 |
+
* @return array Remapped properties
|
677 |
+
*/
|
678 |
+
function remap_properties($properties) {
|
679 |
+
//Return remapped properties
|
680 |
+
return $this->util->array_remap($properties, $this->map);
|
681 |
+
}
|
682 |
+
|
683 |
+
/**
|
684 |
+
* Sort properties based on priority
|
685 |
+
* @uses this::property_priority
|
686 |
+
* @return array Sorted priorities
|
687 |
+
*/
|
688 |
+
function sort_properties($properties) {
|
689 |
+
//Stop if sorting not necessary
|
690 |
+
if ( empty($properties) || !is_array($properties) || empty($this->property_priority) || !is_array($this->property_priority) )
|
691 |
+
return $properties;
|
692 |
+
$props = array();
|
693 |
+
foreach ( $this->property_priority as $prop ) {
|
694 |
+
if ( !array_key_exists($prop, $properties) )
|
695 |
+
continue;
|
696 |
+
//Add to new array
|
697 |
+
$props[$prop] = $properties[$prop];
|
698 |
+
//Remove from old array
|
699 |
+
unset($properties[$prop]);
|
700 |
+
}
|
701 |
+
//Append any remaining properties
|
702 |
+
$props = array_merge($props, $properties);
|
703 |
+
return $props;
|
704 |
+
}
|
705 |
+
|
706 |
+
/**
|
707 |
+
* Build properties array
|
708 |
+
* @param array $props Instance properties
|
709 |
+
* @param array $signature (optional) Default properties
|
710 |
+
* @return array Normalized properties
|
711 |
+
*/
|
712 |
+
function make_properties($props, $signature = array()) {
|
713 |
+
$p = array();
|
714 |
+
if ( is_array($props) ) {
|
715 |
+
foreach ( $props as $prop ) {
|
716 |
+
if ( is_array($prop) ) {
|
717 |
+
$p = array_merge($prop, $p);
|
718 |
+
}
|
719 |
+
}
|
720 |
+
}
|
721 |
+
$props = $p;
|
722 |
+
if ( is_array($signature) ) {
|
723 |
+
$props = array_merge($signature, $props);
|
724 |
+
}
|
725 |
+
return $props;
|
726 |
+
}
|
727 |
+
|
728 |
+
function validate_id($id) {
|
729 |
+
return ( is_scalar($id) && !empty($id) ) ? true : false;
|
730 |
+
}
|
731 |
+
|
732 |
+
function integrate_id($id) {
|
733 |
+
return ( $this->validate_id($id) ) ? array('id' => $id) : array();
|
734 |
+
}
|
735 |
+
|
736 |
+
/**
|
737 |
+
* Filter property members
|
738 |
+
* @uses $property_filter to remove define members to remove from $properties
|
739 |
+
* @param array $props Properties
|
740 |
+
* @return array Filtered properties
|
741 |
+
*/
|
742 |
+
function filter_properties($props = array()) {
|
743 |
+
return $this->util->array_filter_keys($props, $this->property_filter);
|
744 |
+
}
|
745 |
+
|
746 |
+
/**
|
747 |
+
* Add/Set a property on the field definition
|
748 |
+
* @param string $name Name of property
|
749 |
+
* @param mixed $value Default value for property
|
750 |
+
* @param string|array $group Group(s) property belongs to
|
751 |
+
* @return boolean TRUE if property is successfully added to field type, FALSE otherwise
|
752 |
+
*/
|
753 |
+
function set_property($name, $value = '', $group = null) {
|
754 |
+
//Do not add if property name is not a string
|
755 |
+
if ( !is_string($name) )
|
756 |
+
return false;
|
757 |
+
//Create property array
|
758 |
+
$prop_arr = array();
|
759 |
+
$prop_arr['value'] = $value;
|
760 |
+
//Add to properties array
|
761 |
+
$this->properties[$name] = $value;
|
762 |
+
//Add property to specified groups
|
763 |
+
if ( !empty($group) ) {
|
764 |
+
$this->set_group_property($group, $name);
|
765 |
+
}
|
766 |
+
return true;
|
767 |
+
}
|
768 |
+
|
769 |
+
/**
|
770 |
+
* Retreives property from field type
|
771 |
+
* @param string $name Name of property to retrieve
|
772 |
+
* @return mixed Specified Property if exists (Default: Empty string)
|
773 |
+
*/
|
774 |
+
function get_property($name) {
|
775 |
+
$val = $this->get_member_value('properties', $name);
|
776 |
+
return $val;
|
777 |
+
}
|
778 |
+
|
779 |
+
/**
|
780 |
+
* Removes a property from item
|
781 |
+
* @param string $name Property ID
|
782 |
+
*/
|
783 |
+
function remove_property($name) {
|
784 |
+
//Remove property
|
785 |
+
if ( isset($this->properties[$name]) )
|
786 |
+
unset($this->properties[$name]);
|
787 |
+
//Remove from group
|
788 |
+
foreach ( array_keys($this->property_groups) as $g ) {
|
789 |
+
if ( isset($this->property_groups[$g][$name]) ) {
|
790 |
+
unset($this->property_groups[$g][$name]);
|
791 |
+
break;
|
792 |
+
}
|
793 |
+
}
|
794 |
+
}
|
795 |
+
|
796 |
+
/**
|
797 |
+
* Adds Specified Property to a Group
|
798 |
+
* @param string|array $group Group(s) to add property to
|
799 |
+
* @param string $property Property to add to group
|
800 |
+
*/
|
801 |
+
function set_group_property($group, $property) {
|
802 |
+
if ( is_string($group) && isset($this->property_groups[$group][$property]) )
|
803 |
+
return;
|
804 |
+
if ( !is_array($group) ) {
|
805 |
+
$group = array($group);
|
806 |
+
}
|
807 |
+
|
808 |
+
foreach ($group as $g) {
|
809 |
+
$g = trim($g);
|
810 |
+
//Initialize group if it doesn't already exist
|
811 |
+
if ( !isset($this->property_groups[$g]) )
|
812 |
+
$this->property_groups[$g] = array();
|
813 |
+
|
814 |
+
//Add property to group
|
815 |
+
$this->property_groups[$g][$property] = null;
|
816 |
+
}
|
817 |
+
}
|
818 |
+
|
819 |
+
/**
|
820 |
+
* Retrieve property group
|
821 |
+
* @param string $group Group to retrieve
|
822 |
+
* @return array Array of properties in specified group
|
823 |
+
*/
|
824 |
+
function get_group($group) {
|
825 |
+
return $this->get_member_value('property_groups', $group, array());
|
826 |
+
}
|
827 |
+
|
828 |
+
/**
|
829 |
+
* Save field data
|
830 |
+
* Child classes will define their own
|
831 |
+
* functionality for this method
|
832 |
+
* @return bool TRUE if save was successful (FALSE otherwise)
|
833 |
+
*/
|
834 |
+
function save() {
|
835 |
+
return true;
|
836 |
+
}
|
837 |
+
|
838 |
+
/*-** Hooks **-*/
|
839 |
+
|
840 |
+
/**
|
841 |
+
* Retrieve hooks added to object
|
842 |
+
* @return array Hooks
|
843 |
+
*/
|
844 |
+
function get_hooks() {
|
845 |
+
return $this->get_member_value('hooks', '', array());
|
846 |
+
}
|
847 |
+
|
848 |
+
/**
|
849 |
+
* Add hook for object
|
850 |
+
* @see add_filter() for parameter defaults
|
851 |
+
* @param $tag
|
852 |
+
* @param $function_to_add
|
853 |
+
* @param $priority
|
854 |
+
* @param $accepted_args
|
855 |
+
*/
|
856 |
+
function add_hook($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
|
857 |
+
//Create new array for tag (if not already set)
|
858 |
+
if ( !isset($this->hooks[$tag]) )
|
859 |
+
$this->hooks[$tag] = array();
|
860 |
+
//Build Unique ID
|
861 |
+
if ( is_string($function_to_add) )
|
862 |
+
$id = $function_to_add;
|
863 |
+
elseif ( is_array($function_to_add) && !empty($function_to_add) )
|
864 |
+
$id = strval($function_to_add[count($function_to_add) - 1]);
|
865 |
+
else
|
866 |
+
$id = 'function_' . ( count($this->hooks[$tag]) + 1 );
|
867 |
+
//Add hook
|
868 |
+
$this->hooks[$tag][$id] = func_get_args();
|
869 |
+
}
|
870 |
+
|
871 |
+
/**
|
872 |
+
* Convenience method for adding an action for object
|
873 |
+
* @see add_filter() for parameter defaults
|
874 |
+
* @param $tag
|
875 |
+
* @param $function_to_add
|
876 |
+
* @param $priority
|
877 |
+
* @param $accepted_args
|
878 |
+
*/
|
879 |
+
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
|
880 |
+
$this->add_hook($tag, $function_to_add, $priority, $accepted_args);
|
881 |
+
}
|
882 |
+
|
883 |
+
/**
|
884 |
+
* Convenience method for adding a filter for object
|
885 |
+
* @see add_filter() for parameter defaults
|
886 |
+
* @param $tag
|
887 |
+
* @param $function_to_add
|
888 |
+
* @param $priority
|
889 |
+
* @param $accepted_args
|
890 |
+
*/
|
891 |
+
function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
|
892 |
+
$this->add_hook($tag, $function_to_add, $priority, $accepted_args);
|
893 |
+
}
|
894 |
+
|
895 |
+
/*-** Dependencies **-*/
|
896 |
+
|
897 |
+
/**
|
898 |
+
* Adds dependency to object
|
899 |
+
* @param string $type Type of dependency to add (script, style)
|
900 |
+
* @param array|string $context When dependency will be added (@see SLB_Utilities::get_action() for possible contexts)
|
901 |
+
* @see wp_enqueue_script for the following of the parameters
|
902 |
+
* @param $handle
|
903 |
+
* @param $src
|
904 |
+
* @param $deps
|
905 |
+
* @param $ver
|
906 |
+
* @param $ex
|
907 |
+
*/
|
908 |
+
function add_dependency($type, $context, $handle, $src = false, $deps = array(), $ver = false, $ex = false) {
|
909 |
+
$args = func_get_args();
|
910 |
+
//Remove type/context from arguments
|
911 |
+
$args = array_slice($args, 2);
|
912 |
+
|
913 |
+
//Set context
|
914 |
+
if ( !is_array($context) ) {
|
915 |
+
//Wrap single contexts in an array
|
916 |
+
if ( is_string($context) )
|
917 |
+
$context = array($context);
|
918 |
+
else
|
919 |
+
$context = array();
|
920 |
+
}
|
921 |
+
//Add file to instance property
|
922 |
+
if ( isset($this->{$type}) && is_array($this->{$type}) )
|
923 |
+
$this->{$type}[$handle] = array('context' => $context, 'params' => $args);
|
924 |
+
}
|
925 |
+
|
926 |
+
/**
|
927 |
+
* Add script to object to be added in specified contexts
|
928 |
+
* @param array|string $context Array of contexts to add script to page
|
929 |
+
* @see wp_enqueue_script for the following of the parameters
|
930 |
+
* @param $handle
|
931 |
+
* @param $src
|
932 |
+
* @param $deps
|
933 |
+
* @param $ver
|
934 |
+
* @param $in_footer
|
935 |
+
*/
|
936 |
+
function add_script( $context, $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) {
|
937 |
+
$args = func_get_args();
|
938 |
+
//Add file type to front of arguments array
|
939 |
+
array_unshift($args, 'scripts');
|
940 |
+
call_user_func_array($this->m('add_dependency'), $args);
|
941 |
+
}
|
942 |
+
|
943 |
+
/**
|
944 |
+
* Retrieve script dependencies for object
|
945 |
+
* @return array Script dependencies
|
946 |
+
*/
|
947 |
+
function get_scripts() {
|
948 |
+
return $this->get_member_value('scripts', '', array());
|
949 |
+
}
|
950 |
+
|
951 |
+
/**
|
952 |
+
* Add style to object to be added in specified contexts
|
953 |
+
* @param array|string $context Array of contexts to add style to page
|
954 |
+
* @see wp_enqueue_style for the following of the parameters
|
955 |
+
* @param $handle
|
956 |
+
* @param $src
|
957 |
+
* @param $deps
|
958 |
+
* @param $ver
|
959 |
+
* @param $in_footer
|
960 |
+
*/
|
961 |
+
function add_style( $handle, $src = false, $deps = array(), $ver = false, $media = false ) {
|
962 |
+
$args = func_get_args();
|
963 |
+
array_unshift($args, 'styles');
|
964 |
+
call_user_func_array($this->m('add_dependency'), $args);
|
965 |
+
}
|
966 |
+
|
967 |
+
/**
|
968 |
+
* Retrieve Style dependencies for object
|
969 |
+
* @return array Style dependencies
|
970 |
+
*/
|
971 |
+
function get_styles() {
|
972 |
+
return $this->get_member_value('styles', '', array());
|
973 |
+
}
|
974 |
+
|
975 |
+
/* Helpers */
|
976 |
+
|
977 |
+
/**
|
978 |
+
* Format value based on specified context
|
979 |
+
* @param mixed $value Value to format
|
980 |
+
* @param string $context Current context
|
981 |
+
* @return mixed Formatted value
|
982 |
+
*/
|
983 |
+
function format($value, $context = '') {
|
984 |
+
$handler = 'format_' . trim(strval($context));
|
985 |
+
//Only process if context is valid and has a handler
|
986 |
+
if ( !empty($context) && method_exists($this, $handler) ) {
|
987 |
+
//Pass value to handler
|
988 |
+
$value = $this->{$handler}($value, $context);
|
989 |
+
}
|
990 |
+
//Return formatted value
|
991 |
+
return $value;
|
992 |
+
}
|
993 |
+
|
994 |
+
/**
|
995 |
+
* Format value for output in form field
|
996 |
+
* @param mixed $value Value to format
|
997 |
+
* @return mixed Formatted value
|
998 |
+
*/
|
999 |
+
function format_form($value) {
|
1000 |
+
if ( is_string($value) )
|
1001 |
+
$value = htmlspecialchars($value);
|
1002 |
+
return $value;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
/**
|
1006 |
+
* Final formatting before output
|
1007 |
+
* Restores special characters, etc.
|
1008 |
+
* @uses $special_chars
|
1009 |
+
* @uses $special_chars_default
|
1010 |
+
* @param mixed $value Pre-final field output
|
1011 |
+
* @param string $context (Optional) Formatting context
|
1012 |
+
* @return mixed Formatted value
|
1013 |
+
*/
|
1014 |
+
function format_final($value, $context = '') {
|
1015 |
+
if ( !is_string($value) )
|
1016 |
+
return $value;
|
1017 |
+
|
1018 |
+
//Restore special chars
|
1019 |
+
return $this->restore_special_chars($value, $context);
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
function preserve_special_chars($value, $context = '') {
|
1023 |
+
if ( !is_string($value) )
|
1024 |
+
return $value;
|
1025 |
+
$specials = $this->get_special_chars();
|
1026 |
+
return str_replace(array_keys($specials), $specials, $value);
|
1027 |
+
}
|
1028 |
+
|
1029 |
+
function restore_special_chars($value, $context = '') {
|
1030 |
+
if ( !is_string($value) )
|
1031 |
+
return $value;
|
1032 |
+
$specials = $this->get_special_chars();
|
1033 |
+
return str_replace($specials, array_keys($specials), $value);
|
1034 |
+
}
|
1035 |
+
|
1036 |
+
/**
|
1037 |
+
* Retrieve special characters/placeholders
|
1038 |
+
* Merges defaults with class-specific characters
|
1039 |
+
* @uses $special_chars
|
1040 |
+
* @uses $special_chars_default
|
1041 |
+
* @return array Special characters/placeholders
|
1042 |
+
*/
|
1043 |
+
function get_special_chars() {
|
1044 |
+
return wp_parse_args($this->special_chars, $this->special_chars_default);
|
1045 |
+
}
|
1046 |
+
}
|
1047 |
+
|
1048 |
+
/**
|
1049 |
+
* Field Types
|
1050 |
+
* Stores properties for a specific field
|
1051 |
+
* @package Simple Lightbox
|
1052 |
+
* @subpackage Fields
|
1053 |
+
* @author Archetyped
|
1054 |
+
*/
|
1055 |
+
class SLB_Field_Type extends SLB_Field_Base {
|
1056 |
+
/* Properties */
|
1057 |
+
|
1058 |
+
/**
|
1059 |
+
* @var array Array of Field types that make up current Field type
|
1060 |
+
*/
|
1061 |
+
var $elements = array();
|
1062 |
+
|
1063 |
+
/**
|
1064 |
+
* @var array Field type layouts
|
1065 |
+
*/
|
1066 |
+
var $layout = array();
|
1067 |
+
|
1068 |
+
/**
|
1069 |
+
* @var SLB_Field_Type Parent field type (reference)
|
1070 |
+
*/
|
1071 |
+
var $parent = null;
|
1072 |
+
|
1073 |
+
/**
|
1074 |
+
* Object that field is in
|
1075 |
+
* @var SLB_Field|SLB_Field_Type|SLB_Field_Collection
|
1076 |
+
*/
|
1077 |
+
var $container = null;
|
1078 |
+
|
1079 |
+
/**
|
1080 |
+
* Object that called field
|
1081 |
+
* Used to determine field hierarchy/nesting
|
1082 |
+
* @var SLB_Field|SLB_Field_Type|SLB_Field_Collection
|
1083 |
+
*/
|
1084 |
+
var $caller = null;
|
1085 |
+
|
1086 |
+
function __construct($id = '', $parent = null) {
|
1087 |
+
$args = func_get_args();
|
1088 |
+
$defaults = $this->integrate_id($id);
|
1089 |
+
if ( !is_array($parent) )
|
1090 |
+
$defaults['parent'] = $parent;
|
1091 |
+
|
1092 |
+
$props = $this->make_properties($args, $defaults);
|
1093 |
+
parent::__construct($props);
|
1094 |
+
}
|
1095 |
+
|
1096 |
+
/* Getters/Setters */
|
1097 |
+
|
1098 |
+
/**
|
1099 |
+
* Search for specified member value in field's container object (if exists)
|
1100 |
+
* @param string $member Name of object member to search (e.g. properties, layout, etc.)
|
1101 |
+
* @param string $name Value to retrieve from member
|
1102 |
+
* @return mixed Member value if found (Default: empty string)
|
1103 |
+
*/
|
1104 |
+
function get_container_value($member, $name = '', $default = '') {
|
1105 |
+
$container =& $this->get_container();
|
1106 |
+
return $this->get_object_value($container, $member, $name, $default, 'container');
|
1107 |
+
}
|
1108 |
+
|
1109 |
+
/**
|
1110 |
+
* Search for specified member value in field's container object (if exists)
|
1111 |
+
* @param string $member Name of object member to search (e.g. properties, layout, etc.)
|
1112 |
+
* @param string $name Value to retrieve from member
|
1113 |
+
* @return mixed Member value if found (Default: empty string)
|
1114 |
+
*/
|
1115 |
+
function get_caller_value($member, $name = '', $default = '') {
|
1116 |
+
$caller =& $this->get_caller();
|
1117 |
+
return $this->get_object_value($caller, $member, $name, $default, 'caller');
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
/**
|
1121 |
+
* Sets reference to container object of current field
|
1122 |
+
* Reference is cleared if no valid object is passed to method
|
1123 |
+
* @param object $container
|
1124 |
+
*/
|
1125 |
+
function set_container(&$container) {
|
1126 |
+
if ( !empty($container) && is_object($container) ) {
|
1127 |
+
//Set as param as container for current field
|
1128 |
+
$this->container =& $container;
|
1129 |
+
} else {
|
1130 |
+
//Clear container member if argument is invalid
|
1131 |
+
$this->clear_container();
|
1132 |
+
}
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
/**
|
1136 |
+
* Clears reference to container object of current field
|
1137 |
+
*/
|
1138 |
+
function clear_container() {
|
1139 |
+
$this->container = null;
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
/**
|
1143 |
+
* Retrieves reference to container object of current field
|
1144 |
+
* @return object Reference to container object
|
1145 |
+
*/
|
1146 |
+
function &get_container() {
|
1147 |
+
$ret = null;
|
1148 |
+
if ( $this->has_container() )
|
1149 |
+
$ret =& $this->container;
|
1150 |
+
return $ret;
|
1151 |
+
}
|
1152 |
+
|
1153 |
+
/**
|
1154 |
+
* Checks if field has a container reference
|
1155 |
+
* @return bool TRUE if field is contained, FALSE otherwise
|
1156 |
+
*/
|
1157 |
+
function has_container() {
|
1158 |
+
return !empty($this->container);
|
1159 |
+
}
|
1160 |
+
|
1161 |
+
/**
|
1162 |
+
* Sets reference to calling object of current field
|
1163 |
+
* Any existing reference is cleared if no valid object is passed to method
|
1164 |
+
* @param object $caller Calling object
|
1165 |
+
*/
|
1166 |
+
function set_caller(&$caller) {
|
1167 |
+
if ( !empty($caller) && is_object($caller) )
|
1168 |
+
$this->caller =& $caller;
|
1169 |
+
else
|
1170 |
+
$this->clear_caller();
|
1171 |
+
}
|
1172 |
+
|
1173 |
+
/**
|
1174 |
+
* Clears reference to calling object of current field
|
1175 |
+
*/
|
1176 |
+
function clear_caller() {
|
1177 |
+
unset($this->caller);
|
1178 |
+
}
|
1179 |
+
|
1180 |
+
/**
|
1181 |
+
* Retrieves reference to caller object of current field
|
1182 |
+
* @return object Reference to caller object
|
1183 |
+
*/
|
1184 |
+
function &get_caller() {
|
1185 |
+
$ret = null;
|
1186 |
+
if ( $this->has_caller() )
|
1187 |
+
$ret =& $this->caller;
|
1188 |
+
return $ret;
|
1189 |
+
}
|
1190 |
+
|
1191 |
+
/**
|
1192 |
+
* Checks if field has a caller reference
|
1193 |
+
* @return bool TRUE if field is called by another field, FALSE otherwise
|
1194 |
+
*/
|
1195 |
+
function has_caller() {
|
1196 |
+
return !empty($this->caller);
|
1197 |
+
}
|
1198 |
+
|
1199 |
+
|
1200 |
+
|
1201 |
+
/**
|
1202 |
+
* Sets an element for the field type
|
1203 |
+
* @param string $name Name of element
|
1204 |
+
* @param SLB_Field_Type $type Reference of field type to use for element
|
1205 |
+
* @param array $properties Properties for element (passed as keyed associative array)
|
1206 |
+
* @param string $id_prop Name of property to set $name to (e.g. ID, etc.)
|
1207 |
+
*/
|
1208 |
+
function set_element($name, $type, $properties = array(), $id_prop = 'id') {
|
1209 |
+
$name = trim(strval($name));
|
1210 |
+
if ( empty($name) )
|
1211 |
+
return false;
|
1212 |
+
//Create new field for element
|
1213 |
+
$el = new SLB_Field($name, $type);
|
1214 |
+
//Set container to current field instance
|
1215 |
+
$el->set_container($this);
|
1216 |
+
//Add properties to element
|
1217 |
+
$el->set_properties($properties);
|
1218 |
+
//Save element to current instance
|
1219 |
+
$this->elements[$name] =& $el;
|
1220 |
+
}
|
1221 |
+
|
1222 |
+
/**
|
1223 |
+
* Add a layout to the field
|
1224 |
+
* @param string $name Name of layout
|
1225 |
+
* @param string $value Layout text
|
1226 |
+
*/
|
1227 |
+
function set_layout($name, $value = '') {
|
1228 |
+
if ( !is_string($name) )
|
1229 |
+
return false;
|
1230 |
+
$name = trim($name);
|
1231 |
+
$this->layout[$name] = $value;
|
1232 |
+
return true;
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
/**
|
1236 |
+
* Retrieve specified layout
|
1237 |
+
* @param string $name Layout name
|
1238 |
+
* @param bool $parse_nested (optional) Whether nested layouts should be expanded in retreived layout or not (Default: TRUE)
|
1239 |
+
* @return string Specified layout text
|
1240 |
+
*/
|
1241 |
+
function get_layout($name = 'form', $parse_nested = true) {
|
1242 |
+
//Retrieve specified layout (use $name value if no layout by that name exists)
|
1243 |
+
if ( empty($name) )
|
1244 |
+
$name = $this->get_container_value('build_vars', 'layout', 'form');
|
1245 |
+
$layout = $this->get_member_value('layout', $name, $name);
|
1246 |
+
|
1247 |
+
//Find all nested layouts in current layout
|
1248 |
+
if ( !empty($layout) && !!$parse_nested ) {
|
1249 |
+
$ph = $this->get_placeholder_defaults();
|
1250 |
+
|
1251 |
+
while ($ph->match = $this->parse_layout($layout, $ph->pattern_layout)) {
|
1252 |
+
//Iterate through the different types of layout placeholders
|
1253 |
+
foreach ($ph->match as $tag => $instances) {
|
1254 |
+
//Iterate through instances of a specific type of layout placeholder
|
1255 |
+
foreach ($instances as $instance) {
|
1256 |
+
//Get nested layout
|
1257 |
+
$nested_layout = $this->get_member_value($instance);
|
1258 |
+
|
1259 |
+
//Replace layout placeholder with retrieved item data
|
1260 |
+
if ( !empty($nested_layout) )
|
1261 |
+
$layout = str_replace($ph->start . $instance['match'] . $ph->end, $nested_layout, $layout);
|
1262 |
+
}
|
1263 |
+
}
|
1264 |
+
}
|
1265 |
+
}
|
1266 |
+
|
1267 |
+
return $layout;
|
1268 |
+
}
|
1269 |
+
|
1270 |
+
/**
|
1271 |
+
* Checks if specified layout exists
|
1272 |
+
* Finds layout if it exists in current object or any of its parents
|
1273 |
+
* @param string $layout Name of layout to check for
|
1274 |
+
* @return bool TRUE if layout exists, FALSE otherwise
|
1275 |
+
*/
|
1276 |
+
function has_layout($layout) {
|
1277 |
+
$ret = false;
|
1278 |
+
if ( is_string($layout) && ($layout = trim($layout)) && !empty($layout) ) {
|
1279 |
+
$layout = $this->get_member_value('layout', $layout, false);
|
1280 |
+
if ( $layout !== false )
|
1281 |
+
$ret = true;
|
1282 |
+
}
|
1283 |
+
|
1284 |
+
return $ret;
|
1285 |
+
}
|
1286 |
+
|
1287 |
+
/**
|
1288 |
+
* Checks if layout content is valid
|
1289 |
+
* Layouts need to have placeholders to be valid
|
1290 |
+
* @param string $layout_content Layout content (markup)
|
1291 |
+
* @return bool TRUE if layout is valid, FALSE otherwise
|
1292 |
+
*/
|
1293 |
+
function is_valid_layout($layout_content) {
|
1294 |
+
$ph = $this->get_placeholder_defaults();
|
1295 |
+
return preg_match($ph->pattern_general, $layout_content);
|
1296 |
+
}
|
1297 |
+
|
1298 |
+
/**
|
1299 |
+
* Parse field layout with a regular expression
|
1300 |
+
* @param string $layout Layout data
|
1301 |
+
* @param string $search Regular expression pattern to search layout for
|
1302 |
+
* @return array Associative array containing all of the regular expression matches in the layout data
|
1303 |
+
* Array Structure:
|
1304 |
+
* root => placeholder tags
|
1305 |
+
* => Tag instances (array)
|
1306 |
+
* 'tag' => (string) tag name
|
1307 |
+
* 'match' => (string) placeholder match
|
1308 |
+
* 'attributes' => (array) attributes
|
1309 |
+
*/
|
1310 |
+
function parse_layout($layout, $search) {
|
1311 |
+
$ph_xml = '';
|
1312 |
+
$parse_match = '';
|
1313 |
+
$ph_root_tag = 'ph_root_element';
|
1314 |
+
$ph_start_xml = '<';
|
1315 |
+
$ph_end_xml = ' />';
|
1316 |
+
$ph_wrap_start = '<' . $ph_root_tag . '>';
|
1317 |
+
$ph_wrap_end = '</' . $ph_root_tag . '>';
|
1318 |
+
$parse_result = false;
|
1319 |
+
|
1320 |
+
//Find all nested layouts in layout
|
1321 |
+
$match_value = preg_match_all($search, $layout, $parse_match, PREG_PATTERN_ORDER);
|
1322 |
+
|
1323 |
+
if ($match_value !== false && $match_value > 0) {
|
1324 |
+
$parse_result = array();
|
1325 |
+
//Get all matched elements
|
1326 |
+
$parse_match = $parse_match[1];
|
1327 |
+
|
1328 |
+
//Build XML string from placeholders
|
1329 |
+
foreach ($parse_match as $ph) {
|
1330 |
+
$ph_xml .= $ph_start_xml . $ph . $ph_end_xml . ' ';
|
1331 |
+
}
|
1332 |
+
$ph_xml = $ph_wrap_start . $ph_xml . $ph_wrap_end;
|
1333 |
+
//Parse XML data
|
1334 |
+
$ph_prs = xml_parser_create();
|
1335 |
+
xml_parser_set_option($ph_prs, XML_OPTION_SKIP_WHITE, 1);
|
1336 |
+
xml_parser_set_option($ph_prs, XML_OPTION_CASE_FOLDING, 0);
|
1337 |
+
$ret = xml_parse_into_struct($ph_prs, $ph_xml, $parse_result['values'], $parse_result['index']);
|
1338 |
+
xml_parser_free($ph_prs);
|
1339 |
+
|
1340 |
+
//Build structured array with all parsed data
|
1341 |
+
|
1342 |
+
unset($parse_result['index'][$ph_root_tag]);
|
1343 |
+
|
1344 |
+
//Build structured array
|
1345 |
+
$result = array();
|
1346 |
+
foreach ($parse_result['index'] as $tag => $instances) {
|
1347 |
+
$result[$tag] = array();
|
1348 |
+
//Instances
|
1349 |
+
foreach ($instances as $instance) {
|
1350 |
+
//Skip instance if it doesn't exist in parse results
|
1351 |
+
if (!isset($parse_result['values'][$instance]))
|
1352 |
+
continue;
|
1353 |
+
|
1354 |
+
//Stop processing instance if a previously-saved instance with the same options already exists
|
1355 |
+
foreach ($result[$tag] as $tag_match) {
|
1356 |
+
if ($tag_match['match'] == $parse_match[$instance - 1])
|
1357 |
+
continue 2;
|
1358 |
+
}
|
1359 |
+
|
1360 |
+
//Init instance data array
|
1361 |
+
$inst_data = array();
|
1362 |
+
|
1363 |
+
//Add Tag to array
|
1364 |
+
$inst_data['tag'] = $parse_result['values'][$instance]['tag'];
|
1365 |
+
|
1366 |
+
//Add instance data to array
|
1367 |
+
$inst_data['attributes'] = (isset($parse_result['values'][$instance]['attributes'])) ? $inst_data['attributes'] = $parse_result['values'][$instance]['attributes'] : '';
|
1368 |
+
|
1369 |
+
//Add match to array
|
1370 |
+
$inst_data['match'] = $parse_match[$instance - 1];
|
1371 |
+
|
1372 |
+
//Add to result array
|
1373 |
+
$result[$tag][] = $inst_data;
|
1374 |
+
}
|
1375 |
+
}
|
1376 |
+
$parse_result = $result;
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
return $parse_result;
|
1380 |
+
}
|
1381 |
+
|
1382 |
+
/**
|
1383 |
+
* Retrieves default properties to use when evaluating layout placeholders
|
1384 |
+
* @return object Object with properties for evaluating layout placeholders
|
1385 |
+
*/
|
1386 |
+
function get_placeholder_defaults() {
|
1387 |
+
$ph = new stdClass();
|
1388 |
+
$ph->start = '{';
|
1389 |
+
$ph->end = '}';
|
1390 |
+
$ph->reserved = array('ref' => 'ref_base');
|
1391 |
+
$ph->pattern_general = '/' . $ph->start . '([a-zA-Z0-9_].*?)' . $ph->end . '/i';
|
1392 |
+
$ph->pattern_layout = '/' . $ph->start . '([a-zA-Z0-9].*?\s+' . $ph->reserved['ref'] . '="layout.*?".*?)' . $ph->end . '/i';
|
1393 |
+
return $ph;
|
1394 |
+
}
|
1395 |
+
|
1396 |
+
/**
|
1397 |
+
* Build item output
|
1398 |
+
* @param string $layout (optional) Layout to build
|
1399 |
+
* @param string $data Data to pass to layout
|
1400 |
+
*/
|
1401 |
+
function build($layout = null, $data = null) {
|
1402 |
+
$this->util->do_action_ref_array('build_pre', array(&$this));
|
1403 |
+
echo $this->build_layout($layout, $data);
|
1404 |
+
$this->util->do_action_ref_array('build_post', array(&$this));
|
1405 |
+
}
|
1406 |
+
|
1407 |
+
/**
|
1408 |
+
* Builds HTML for a field based on its properties
|
1409 |
+
* @param string $layout (optional) Name of layout to build
|
1410 |
+
* @param array $data Additional data for current item
|
1411 |
+
*/
|
1412 |
+
function build_layout($layout = 'form', $data = null) {
|
1413 |
+
$out_default = '';
|
1414 |
+
//Get base layout
|
1415 |
+
$out = $this->get_layout($layout);
|
1416 |
+
//Only parse valid layouts
|
1417 |
+
if ( $this->is_valid_layout($out) ) {
|
1418 |
+
//Parse Layout
|
1419 |
+
$ph = $this->get_placeholder_defaults();
|
1420 |
+
|
1421 |
+
//Search layout for placeholders
|
1422 |
+
while ( $ph->match = $this->parse_layout($out, $ph->pattern_general) ) {
|
1423 |
+
//Iterate through placeholders (tag, id, etc.)
|
1424 |
+
foreach ( $ph->match as $tag => $instances ) {
|
1425 |
+
//Iterate through instances of current placeholder
|
1426 |
+
foreach ( $instances as $instance ) {
|
1427 |
+
//Process value based on placeholder name
|
1428 |
+
$target_property = apply_filters($this->add_prefix('process_placeholder_' . $tag), '', $this, $instance, $layout, $data);
|
1429 |
+
//Process value using default processors (if necessary)
|
1430 |
+
if ( '' == $target_property ) {
|
1431 |
+
$target_property = apply_filters($this->add_prefix('process_placeholder'), $target_property, $this, $instance, $layout, $data);
|
1432 |
+
}
|
1433 |
+
|
1434 |
+
//Clear value if value not a string
|
1435 |
+
if ( !is_scalar($target_property) ) {
|
1436 |
+
$target_property = '';
|
1437 |
+
}
|
1438 |
+
|
1439 |
+
//Replace layout placeholder with retrieved item data
|
1440 |
+
$out = str_replace($ph->start . $instance['match'] . $ph->end, $target_property, $out);
|
1441 |
+
}
|
1442 |
+
}
|
1443 |
+
}
|
1444 |
+
} else {
|
1445 |
+
$out = $out_default;
|
1446 |
+
}
|
1447 |
+
/* Return generated value */
|
1448 |
+
$out = $this->format_final($out);
|
1449 |
+
return $out;
|
1450 |
+
}
|
1451 |
+
}
|
1452 |
+
|
1453 |
+
class SLB_Field extends SLB_Field_Type {}
|
1454 |
+
|
1455 |
+
/**
|
1456 |
+
* Managed collection of fields
|
1457 |
+
* @package Simple Lightbox
|
1458 |
+
* @subpackage Fields
|
1459 |
+
* @author Archetyped
|
1460 |
+
*/
|
1461 |
+
class SLB_Field_Collection extends SLB_Field_Base {
|
1462 |
+
|
1463 |
+
/* Configuration */
|
1464 |
+
|
1465 |
+
protected $mode = 'sub';
|
1466 |
+
|
1467 |
+
/* Properties */
|
1468 |
+
|
1469 |
+
/**
|
1470 |
+
* Item type
|
1471 |
+
* @var string
|
1472 |
+
*/
|
1473 |
+
var $item_type = 'SLB_Field';
|
1474 |
+
|
1475 |
+
/**
|
1476 |
+
* Indexed array of items in collection
|
1477 |
+
* @var array
|
1478 |
+
*/
|
1479 |
+
var $items = array();
|
1480 |
+
|
1481 |
+
var $id_formats = array (
|
1482 |
+
'formatted' => array(
|
1483 |
+
'wrap' => array ( 'open' => '_' ),
|
1484 |
+
'recursive' => false,
|
1485 |
+
'prefix' => array('get_prefix')
|
1486 |
+
)
|
1487 |
+
);
|
1488 |
+
|
1489 |
+
var $build_vars_default = array (
|
1490 |
+
'groups' => array(),
|
1491 |
+
'context' => '',
|
1492 |
+
'layout' => 'form',
|
1493 |
+
'build' => true,
|
1494 |
+
'build_groups' => true,
|
1495 |
+
);
|
1496 |
+
|
1497 |
+
/**
|
1498 |
+
* Associative array of groups in collection
|
1499 |
+
* Key: Group name
|
1500 |
+
* Value: object of group properties
|
1501 |
+
* > title
|
1502 |
+
* > description string Group description
|
1503 |
+
* > items array Items in group
|
1504 |
+
* @var array
|
1505 |
+
*/
|
1506 |
+
var $groups = array();
|
1507 |
+
|
1508 |
+
protected $properties_init = null;
|
1509 |
+
|
1510 |
+
/* Constructors */
|
1511 |
+
|
1512 |
+
/**
|
1513 |
+
* Class constructor
|
1514 |
+
* @uses parent::__construct()
|
1515 |
+
* @uses self::make_properties()
|
1516 |
+
* @uses self::init()
|
1517 |
+
* @uses self::add_groups()
|
1518 |
+
* @uses self::add_items()
|
1519 |
+
* @param string $id Collection ID
|
1520 |
+
* @param array $properties (optional) Properties to set for collection (Default: none)
|
1521 |
+
*/
|
1522 |
+
public function __construct($id, $properties = null) {
|
1523 |
+
$args = func_get_args();
|
1524 |
+
$properties = $this->make_properties($args);
|
1525 |
+
//Parent constructor
|
1526 |
+
parent::__construct($properties);
|
1527 |
+
|
1528 |
+
//Save initial properties
|
1529 |
+
$this->properties_init = $properties;
|
1530 |
+
}
|
1531 |
+
|
1532 |
+
public function _init() {
|
1533 |
+
parent::_init();
|
1534 |
+
$this->load($this->properties_init, false);
|
1535 |
+
}
|
1536 |
+
|
1537 |
+
/*-** Getters/Setters **-*/
|
1538 |
+
|
1539 |
+
/* Setup */
|
1540 |
+
|
1541 |
+
/**
|
1542 |
+
* Load collection with specified properties
|
1543 |
+
* Updates existing properties
|
1544 |
+
* @param array $properties Properties to load
|
1545 |
+
* @param bool $update (optional) Update (TRUE) or overwrite (FALSE) items/groups (Default: TRUE)
|
1546 |
+
* @return object Current instance
|
1547 |
+
*/
|
1548 |
+
public function load($properties, $update = true) {
|
1549 |
+
$args = func_get_args();
|
1550 |
+
$properties = $this->make_properties($args);
|
1551 |
+
if ( !empty($properties) ) {
|
1552 |
+
//Groups
|
1553 |
+
if ( isset($properties['groups']) ) {
|
1554 |
+
$this->add_groups($properties['groups'], $update);
|
1555 |
+
}
|
1556 |
+
//Items
|
1557 |
+
if ( isset($properties['items']) ) {
|
1558 |
+
$this->add_items($properties['items'], $update);
|
1559 |
+
}
|
1560 |
+
}
|
1561 |
+
return $this;
|
1562 |
+
}
|
1563 |
+
|
1564 |
+
/* Data */
|
1565 |
+
|
1566 |
+
/**
|
1567 |
+
* Retrieve external data for items in collection
|
1568 |
+
* Retrieved data is saved to the collection's $data property
|
1569 |
+
* Uses class properties to determine how data is retrieved
|
1570 |
+
* Examples:
|
1571 |
+
* > DB
|
1572 |
+
* > XML
|
1573 |
+
* > JSON
|
1574 |
+
* @return void
|
1575 |
+
*/
|
1576 |
+
function load_data() {
|
1577 |
+
$this->data_loaded = true;
|
1578 |
+
}
|
1579 |
+
|
1580 |
+
/**
|
1581 |
+
* Set data for an item
|
1582 |
+
* @param mixed $item Field to set data for
|
1583 |
+
* > string Field ID
|
1584 |
+
* > object Field Reference
|
1585 |
+
* > array Data for multiple items (associative array [field ID => data])
|
1586 |
+
* @param mixed $value Data to set
|
1587 |
+
* @param bool $save (optional) Whether or not data should be saved to DB (Default: Yes)
|
1588 |
+
*/
|
1589 |
+
function set_data($item, $value = '', $save = true, $force_set = false) {
|
1590 |
+
//Set data for entire collection
|
1591 |
+
if ( is_array($item) ) {
|
1592 |
+
$this->data = wp_parse_args($item, $this->data);
|
1593 |
+
//Update save option
|
1594 |
+
$args = func_get_args();
|
1595 |
+
if ( 2 == count($args) && is_bool($args[1]) ) {
|
1596 |
+
$save = $args[1];
|
1597 |
+
}
|
1598 |
+
}
|
1599 |
+
//Get $item's ID
|
1600 |
+
elseif ( is_object($item) && method_exists($item, 'get_id') )
|
1601 |
+
$item = $item->get_id();
|
1602 |
+
//Set data
|
1603 |
+
if ( is_string($item) && !empty($item) && ( isset($this->items[$item]) || !!$force_set ) )
|
1604 |
+
$this->data[$item] = $value;
|
1605 |
+
if ( !!$save )
|
1606 |
+
$this->save();
|
1607 |
+
}
|
1608 |
+
|
1609 |
+
/* Item */
|
1610 |
+
|
1611 |
+
/**
|
1612 |
+
* Adds item to collection
|
1613 |
+
* @param string|obj $id Unique name for item or item instance
|
1614 |
+
* @param array $properties (optional) Item properties
|
1615 |
+
* @param bool $update (optional) Update or overwrite existing item (Default: FALSE)
|
1616 |
+
* @return object Reference to new item
|
1617 |
+
*/
|
1618 |
+
function &add($id, $properties = array(), $update = false) {
|
1619 |
+
$item;
|
1620 |
+
$args = func_get_args();
|
1621 |
+
//Properties
|
1622 |
+
foreach ( array_reverse($args) as $arg ) {
|
1623 |
+
if ( is_array($arg) ) {
|
1624 |
+
$properties = $arg;
|
1625 |
+
break;
|
1626 |
+
}
|
1627 |
+
}
|
1628 |
+
if ( !is_array($properties) ) {
|
1629 |
+
$properties = array();
|
1630 |
+
}
|
1631 |
+
|
1632 |
+
//Handle item instance
|
1633 |
+
if ( $id instanceof $this->item_type ) {
|
1634 |
+
$item = $id;
|
1635 |
+
$item->set_properties($properties);
|
1636 |
+
} elseif ( class_exists($this->item_type) ) {
|
1637 |
+
$defaults = array (
|
1638 |
+
'parent' => null,
|
1639 |
+
'group' => null
|
1640 |
+
);
|
1641 |
+
$properties = array_merge($defaults, $properties);
|
1642 |
+
if ( is_string($id) ) {
|
1643 |
+
$properties['id'] = $id;
|
1644 |
+
}
|
1645 |
+
if ( !!$update && $this->has($properties['id']) ) {
|
1646 |
+
//Update existing item
|
1647 |
+
$item = $this->get($properties['id']);
|
1648 |
+
$item->set_properties($properties);
|
1649 |
+
} else {
|
1650 |
+
//Init item
|
1651 |
+
$type = $this->item_type;
|
1652 |
+
$item = new $type($properties);
|
1653 |
+
}
|
1654 |
+
}
|
1655 |
+
|
1656 |
+
if ( empty($item) || 0 == strlen($item->get_id()) ) {
|
1657 |
+
return false;
|
1658 |
+
}
|
1659 |
+
|
1660 |
+
//Set container
|
1661 |
+
$item->set_container($this);
|
1662 |
+
|
1663 |
+
//Add item to collection
|
1664 |
+
$this->items[$item->get_id()] = $item;
|
1665 |
+
|
1666 |
+
if ( isset($properties['group']) ) {
|
1667 |
+
$this->add_to_group($properties['group'], $item->get_id());
|
1668 |
+
}
|
1669 |
+
|
1670 |
+
return $item;
|
1671 |
+
}
|
1672 |
+
|
1673 |
+
/**
|
1674 |
+
* Removes item from collection
|
1675 |
+
* @param string|object $item Object or item ID to remove
|
1676 |
+
* @param bool $save (optional) Whether to save the collection after removing item (Default: YES)
|
1677 |
+
*/
|
1678 |
+
function remove($item, $save = true) {
|
1679 |
+
//Remove item
|
1680 |
+
if ( $this->has($item) ) {
|
1681 |
+
$item = $this->get($item);
|
1682 |
+
$item = $item->get_id();
|
1683 |
+
//Remove from items array
|
1684 |
+
unset($this->items[$item]);
|
1685 |
+
//Remove item from groups
|
1686 |
+
$this->remove_from_group($item);
|
1687 |
+
}
|
1688 |
+
//Remove item data from collection
|
1689 |
+
$this->remove_data($item, false);
|
1690 |
+
|
1691 |
+
if ( !!$save )
|
1692 |
+
$this->save();
|
1693 |
+
}
|
1694 |
+
|
1695 |
+
/**
|
1696 |
+
* Remove item data from collection
|
1697 |
+
* @param string|object $item Object or item ID to remove
|
1698 |
+
* @param bool $save (optional) Whether to save the collection after removing item (Default: YES)
|
1699 |
+
*/
|
1700 |
+
function remove_data($item, $save = true) {
|
1701 |
+
//Get item ID from object
|
1702 |
+
if ( $this->has($item) ) {
|
1703 |
+
$item = $this->get($item);
|
1704 |
+
$item = $item->get_id();
|
1705 |
+
}
|
1706 |
+
|
1707 |
+
//Remove data from data member
|
1708 |
+
if ( is_string($item) && is_array($this->data) ) {
|
1709 |
+
unset($this->data[$item]);
|
1710 |
+
if ( !!$save )
|
1711 |
+
$this->save();
|
1712 |
+
}
|
1713 |
+
}
|
1714 |
+
|
1715 |
+
/**
|
1716 |
+
* Checks if item exists in the collection
|
1717 |
+
* @param string $item Item ID
|
1718 |
+
* @return bool TRUE if item exists, FALSE otherwise
|
1719 |
+
*/
|
1720 |
+
function has($item) {
|
1721 |
+
return ( !is_string($item) || empty($item) || is_null($this->get_member_value('items', $item, null)) ) ? false : true;
|
1722 |
+
}
|
1723 |
+
|
1724 |
+
/**
|
1725 |
+
* Retrieve specified item in collection
|
1726 |
+
* @param string|object $item Item object or ID to retrieve
|
1727 |
+
* @return SLB_Field Specified item
|
1728 |
+
*/
|
1729 |
+
function get($item, $safe_mode = false) {
|
1730 |
+
if ( $this->has($item) ) {
|
1731 |
+
if ( !is_object($item) || !is_a($item, $this->item_type) ) {
|
1732 |
+
if ( is_string($item) ) {
|
1733 |
+
$item = trim($item);
|
1734 |
+
$item =& $this->items[$item];
|
1735 |
+
}
|
1736 |
+
else {
|
1737 |
+
$item = false;
|
1738 |
+
}
|
1739 |
+
}
|
1740 |
+
} else {
|
1741 |
+
$item = false;
|
1742 |
+
}
|
1743 |
+
|
1744 |
+
if ( !!$safe_mode && !is_object($item) ) {
|
1745 |
+
//Fallback: Return empty item if no item exists
|
1746 |
+
$type = $this->item_type;
|
1747 |
+
$item = new $type('');
|
1748 |
+
}
|
1749 |
+
return $item;
|
1750 |
+
}
|
1751 |
+
|
1752 |
+
/**
|
1753 |
+
* Retrieve item data
|
1754 |
+
* @param $item Item to get data for
|
1755 |
+
* @param $context (optional) Context
|
1756 |
+
* @param $top (optional) Iterate through ancestors to get data (Default: Yes)
|
1757 |
+
* @return mixed Item data
|
1758 |
+
*/
|
1759 |
+
function get_data($item = null, $context = '', $top = true) {
|
1760 |
+
$this->load_data();
|
1761 |
+
$ret = null;
|
1762 |
+
if ( $this->has($item) ) {
|
1763 |
+
$item =& $this->get($item);
|
1764 |
+
$ret = $item->get_data($context, $top);
|
1765 |
+
} else {
|
1766 |
+
$ret = parent::get_data($context, $top);
|
1767 |
+
}
|
1768 |
+
|
1769 |
+
if ( is_string($item) && is_array($ret) && isset($ret[$item]) )
|
1770 |
+
$ret = $ret[$item];
|
1771 |
+
return $ret;
|
1772 |
+
}
|
1773 |
+
|
1774 |
+
/* Items (Collection) */
|
1775 |
+
|
1776 |
+
/**
|
1777 |
+
* Add multiple items to collection
|
1778 |
+
* @param array $items Items to add to collection
|
1779 |
+
* Array Structure:
|
1780 |
+
* > Key (string): Item ID
|
1781 |
+
* > Val (array): Item properties
|
1782 |
+
* @return void
|
1783 |
+
*/
|
1784 |
+
function add_items($items = array(), $update = false) {
|
1785 |
+
//Validate
|
1786 |
+
if ( !is_array($items) || empty($items) ) {
|
1787 |
+
return false;
|
1788 |
+
}
|
1789 |
+
//Add items
|
1790 |
+
foreach ( $items as $id => $props ) {
|
1791 |
+
$this->add($id, $props, $update);
|
1792 |
+
}
|
1793 |
+
}
|
1794 |
+
|
1795 |
+
/**
|
1796 |
+
* Retrieve reference to items in collection
|
1797 |
+
* @return array Collection items (reference)
|
1798 |
+
*/
|
1799 |
+
function get_items($group = null, $sort = 'priority') {
|
1800 |
+
$gset = $this->group_exists($group);
|
1801 |
+
if ( $gset ) {
|
1802 |
+
$items = $this->get_group_items($group);
|
1803 |
+
} elseif ( !empty($group) ) {
|
1804 |
+
$items = array();
|
1805 |
+
} else {
|
1806 |
+
$items = $this->items;
|
1807 |
+
}
|
1808 |
+
if ( !empty($items) ) {
|
1809 |
+
//Sort items
|
1810 |
+
if ( !empty($sort) && is_string($sort) ) {
|
1811 |
+
if ( 'priority' == $sort ) {
|
1812 |
+
if ( $gset ) {
|
1813 |
+
//Sort by priority
|
1814 |
+
ksort($items, SORT_NUMERIC);
|
1815 |
+
}
|
1816 |
+
}
|
1817 |
+
}
|
1818 |
+
//Release from buckets
|
1819 |
+
if ( $gset ) {
|
1820 |
+
$items = call_user_func_array('array_merge', $items);
|
1821 |
+
}
|
1822 |
+
}
|
1823 |
+
return $items;
|
1824 |
+
}
|
1825 |
+
|
1826 |
+
/**
|
1827 |
+
* Build output for items in specified group
|
1828 |
+
* If no group specified, all items in collection are built
|
1829 |
+
* @param string|object $group (optional) Group to build items for (ID or instance object)
|
1830 |
+
*/
|
1831 |
+
function build_items($group = null) {
|
1832 |
+
//Get group items
|
1833 |
+
$items =& $this->get_items($group);
|
1834 |
+
if ( empty($items) ) {
|
1835 |
+
return false;
|
1836 |
+
}
|
1837 |
+
|
1838 |
+
$this->util->do_action_ref_array('build_items_pre', array(&$this));
|
1839 |
+
foreach ( $items as $item ) {
|
1840 |
+
$item->build();
|
1841 |
+
}
|
1842 |
+
$this->util->do_action_ref_array('build_items_post', array(&$this));
|
1843 |
+
}
|
1844 |
+
|
1845 |
+
/* Group */
|
1846 |
+
|
1847 |
+
/**
|
1848 |
+
* Add groups to collection
|
1849 |
+
* @param array $groups Associative array of group properties
|
1850 |
+
* Array structure:
|
1851 |
+
* > Key (string): group ID
|
1852 |
+
* > Val (string): Group Title
|
1853 |
+
*/
|
1854 |
+
function add_groups($groups = array(), $update = false) {
|
1855 |
+
//Validate
|
1856 |
+
if ( !is_array($groups) || empty($groups) ) {
|
1857 |
+
return false;
|
1858 |
+
}
|
1859 |
+
//Iterate
|
1860 |
+
foreach ( $groups as $id => $props ) {
|
1861 |
+
$this->add_group($id, $props, null, $update);
|
1862 |
+
}
|
1863 |
+
}
|
1864 |
+
|
1865 |
+
/**
|
1866 |
+
* Adds group to collection
|
1867 |
+
* Groups are used to display related items in the UI
|
1868 |
+
* @param string $id Unique name for group
|
1869 |
+
* @param string $title Group title
|
1870 |
+
* @param string $description Short description of group's purpose
|
1871 |
+
* @param array $items (optional) ID's of existing items to add to group
|
1872 |
+
* @return object Group object
|
1873 |
+
*/
|
1874 |
+
function &add_group($id, $properties = array(), $items = array(), $update = false) {
|
1875 |
+
//Create new group and set properties
|
1876 |
+
$default = array (
|
1877 |
+
'title' => '',
|
1878 |
+
'description' => '',
|
1879 |
+
'priority' => 10
|
1880 |
+
);
|
1881 |
+
$p = ( is_array($properties) ) ? array_merge($default, $properties) : $default;
|
1882 |
+
if ( !is_int($p['priority']) || $p['priority'] < 0 ) {
|
1883 |
+
$p['priority'] = $default['priority'];
|
1884 |
+
}
|
1885 |
+
$id = trim($id);
|
1886 |
+
//Retrieve or init group
|
1887 |
+
if ( !!$update && $this->group_exists($id) ) {
|
1888 |
+
$grp = $this->get_group($id);
|
1889 |
+
$grp->title = $p['title'];
|
1890 |
+
$grp->description = $p['description'];
|
1891 |
+
$grp->priority = $p['priority'];
|
1892 |
+
} else {
|
1893 |
+
$this->groups[$id] =& $this->create_group($p['title'], $p['description'], $p['priority']);
|
1894 |
+
}
|
1895 |
+
//Add items to group (if supplied)
|
1896 |
+
if ( !empty($items) && is_array($items) ) {
|
1897 |
+
$this->add_to_group($id, $items);
|
1898 |
+
}
|
1899 |
+
return $this->groups[$id];
|
1900 |
+
}
|
1901 |
+
|
1902 |
+
/**
|
1903 |
+
* Remove specified group from collection
|
1904 |
+
* @param string $id Group ID to remove
|
1905 |
+
*/
|
1906 |
+
function remove_group($id) {
|
1907 |
+
$id = trim($id);
|
1908 |
+
if ( $this->group_exists($id) ) {
|
1909 |
+
unset($this->groups[$id]);
|
1910 |
+
}
|
1911 |
+
}
|
1912 |
+
|
1913 |
+
/**
|
1914 |
+
* Standardized method to create a new item group
|
1915 |
+
* @param string $title Group title (used in meta boxes, etc.)
|
1916 |
+
* @param string $description Short description of group's purpose
|
1917 |
+
* @param int $priority (optional) Group priority (e.g. used to sort groups during output)
|
1918 |
+
* @return object Group object
|
1919 |
+
*/
|
1920 |
+
function &create_group($title = '', $description = '', $priority = 10) {
|
1921 |
+
//Create new group object
|
1922 |
+
$group = new stdClass();
|
1923 |
+
/* Set group properties */
|
1924 |
+
|
1925 |
+
//Set Title
|
1926 |
+
$title = ( is_scalar($title) ) ? trim($title) : '';
|
1927 |
+
$group->title = $title;
|
1928 |
+
//Set Description
|
1929 |
+
$description = ( is_scalar($description) ) ? trim($description) : '';
|
1930 |
+
$group->description = $description;
|
1931 |
+
//Priority
|
1932 |
+
$group->priority = ( is_int($priority) ) ? $priority : 10;
|
1933 |
+
//Create array to hold items
|
1934 |
+
$group->items = array();
|
1935 |
+
return $group;
|
1936 |
+
}
|
1937 |
+
|
1938 |
+
/**
|
1939 |
+
* Checks if group exists in collection
|
1940 |
+
* @param string $id Group name
|
1941 |
+
* @return bool TRUE if group exists, FALSE otherwise
|
1942 |
+
*/
|
1943 |
+
function group_exists($group) {
|
1944 |
+
$ret = false;
|
1945 |
+
if ( is_object($group) ) {
|
1946 |
+
$ret = true;
|
1947 |
+
} elseif ( is_string($group) && ($group = trim($group)) && strlen($group) > 0 ) {
|
1948 |
+
$group = trim($group);
|
1949 |
+
//Check if group exists
|
1950 |
+
$ret = !is_null($this->get_member_value('groups', $group, null));
|
1951 |
+
}
|
1952 |
+
return $ret;
|
1953 |
+
}
|
1954 |
+
|
1955 |
+
/**
|
1956 |
+
* Adds item to a group in the collection
|
1957 |
+
* Group is created if it does not already exist
|
1958 |
+
* @param string|array $group ID of group (or group parameters if new group) to add item to
|
1959 |
+
* @param string|array $items Name or array of item(s) to add to group
|
1960 |
+
*/
|
1961 |
+
function add_to_group($group, $items, $priority = 10) {
|
1962 |
+
//Validate
|
1963 |
+
if ( empty($items) || empty($group) || ( !is_string($group) && !is_array($group) ) ) {
|
1964 |
+
return false;
|
1965 |
+
}
|
1966 |
+
|
1967 |
+
//Get group ID
|
1968 |
+
if ( is_string($group) ) {
|
1969 |
+
$group = array($group);
|
1970 |
+
}
|
1971 |
+
list($gid, $priority) = $group;
|
1972 |
+
$gid = trim(sanitize_title_with_dashes($gid));
|
1973 |
+
if ( empty($gid) ) {
|
1974 |
+
return false;
|
1975 |
+
}
|
1976 |
+
//Item priority
|
1977 |
+
if ( !is_int($priority) ) {
|
1978 |
+
$priority = 10;
|
1979 |
+
}
|
1980 |
+
|
1981 |
+
//Prepare group
|
1982 |
+
if ( !$this->group_exists($gid) ) {
|
1983 |
+
//TODO Follow
|
1984 |
+
call_user_func($this->m('add_group'), $gid, $group);
|
1985 |
+
}
|
1986 |
+
//Prepare items
|
1987 |
+
if ( !is_array($items) ) {
|
1988 |
+
$items = array($items);
|
1989 |
+
}
|
1990 |
+
//Add Items
|
1991 |
+
foreach ( $items as $item ) {
|
1992 |
+
//Skip if not in current collection
|
1993 |
+
$itm_ref =& $this->get($item);
|
1994 |
+
if ( !$itm_ref ) {
|
1995 |
+
continue;
|
1996 |
+
}
|
1997 |
+
$itm_id = $itm_ref->get_id();
|
1998 |
+
//Remove item from any other group it's in (items can only be in one group)
|
1999 |
+
foreach ( $this->get_groups() as $group ) {
|
2000 |
+
foreach ( $group->items as $tmp_pri => $tmp_items ) {
|
2001 |
+
if ( isset($group->items[$tmp_pri][$itm_id]) ) {
|
2002 |
+
unset($group->items[$tmp_pri][$itm_id]);
|
2003 |
+
}
|
2004 |
+
}
|
2005 |
+
}
|
2006 |
+
//Add reference to item in group
|
2007 |
+
$items =& $this->get_group($gid)->items;
|
2008 |
+
if ( !isset($items[$priority]) ) {
|
2009 |
+
$items[$priority] = array();
|
2010 |
+
}
|
2011 |
+
$items[$priority][$itm_id] =& $itm_ref;
|
2012 |
+
}
|
2013 |
+
unset($itm_ref);
|
2014 |
+
}
|
2015 |
+
|
2016 |
+
/**
|
2017 |
+
* Remove item from a group
|
2018 |
+
* If no group is specified, then item is removed from all groups
|
2019 |
+
* @param string|object $item Object or ID of item to remove from group
|
2020 |
+
* @param string $group (optional) Group ID to remove item from
|
2021 |
+
*/
|
2022 |
+
function remove_from_group($item, $group = '') {
|
2023 |
+
//Get ID of item to remove or stop execution if item invalid
|
2024 |
+
$item = $this->get($item);
|
2025 |
+
$item = $item->get_id();
|
2026 |
+
if ( !$item )
|
2027 |
+
return false;
|
2028 |
+
|
2029 |
+
//Remove item from group
|
2030 |
+
if ( !empty($group) ) {
|
2031 |
+
//Remove item from single group
|
2032 |
+
if ( ($group =& $this->get_group($group)) && isset($group->items[$item]) ) {
|
2033 |
+
unset($group->items[$item]);
|
2034 |
+
}
|
2035 |
+
} else {
|
2036 |
+
//Remove item from all groups
|
2037 |
+
foreach ( array_keys($this->groups) as $group ) {
|
2038 |
+
if ( ($group =& $this->get_group($group)) && isset($group->items[$item]) ) {
|
2039 |
+
unset($group->items[$item]);
|
2040 |
+
}
|
2041 |
+
}
|
2042 |
+
}
|
2043 |
+
}
|
2044 |
+
|
2045 |
+
/**
|
2046 |
+
* Retrieve specified group
|
2047 |
+
* @param string $group ID of group to retrieve
|
2048 |
+
* @return object Reference to specified group
|
2049 |
+
*/
|
2050 |
+
function &get_group($group) {
|
2051 |
+
if ( is_object($group) ) {
|
2052 |
+
return $group;
|
2053 |
+
}
|
2054 |
+
if ( is_string($group) ) {
|
2055 |
+
$group = trim($group);
|
2056 |
+
}
|
2057 |
+
//Create group if it doesn't already exist
|
2058 |
+
if ( ! $this->group_exists($group) ) {
|
2059 |
+
$this->add_group($group);
|
2060 |
+
}
|
2061 |
+
return $this->get_member_value('groups', $group);
|
2062 |
+
}
|
2063 |
+
|
2064 |
+
/**
|
2065 |
+
* Retrieve a group's items
|
2066 |
+
* @uses SLB_Field_Collection::get_group() to retrieve group object
|
2067 |
+
* @param object|string $group Group object or group ID
|
2068 |
+
* @return array Group's items
|
2069 |
+
*/
|
2070 |
+
function &get_group_items($group) {
|
2071 |
+
$group =& $this->get_group($group);
|
2072 |
+
return $group->items;
|
2073 |
+
}
|
2074 |
+
|
2075 |
+
/**
|
2076 |
+
* Retrieve all groups in collection
|
2077 |
+
* @return array Reference to group objects
|
2078 |
+
*/
|
2079 |
+
function &get_groups($opts = array()) {
|
2080 |
+
$groups =& $this->get_member_value('groups');
|
2081 |
+
if ( is_array($opts) && !empty($opts) ) {
|
2082 |
+
extract($opts, EXTR_SKIP);
|
2083 |
+
if ( !empty($groups) && !empty($sort) && is_string($sort) ) {
|
2084 |
+
if ( property_exists(current($groups), $sort) ) {
|
2085 |
+
//Sort groups by property
|
2086 |
+
$sfunc = create_function('$a,$b', '$ap = $a->' . $sort . '; $bp = $b->' . $sort . '; if ( $ap == $bp ) return 0; return ( $ap > $bp ) ? 1 : -1;');
|
2087 |
+
uasort($groups, $sfunc);
|
2088 |
+
}
|
2089 |
+
}
|
2090 |
+
}
|
2091 |
+
return $groups;
|
2092 |
+
}
|
2093 |
+
|
2094 |
+
/**
|
2095 |
+
* Output groups
|
2096 |
+
* @uses self::build_vars to determine groups to build
|
2097 |
+
*/
|
2098 |
+
function build_groups() {
|
2099 |
+
$this->util->do_action_ref_array('build_groups_pre', array(&$this));
|
2100 |
+
|
2101 |
+
//Get groups to build
|
2102 |
+
$groups = ( !empty($this->build_vars['groups']) ) ? $this->build_vars['groups'] : array_keys($this->get_groups(array('sort' => 'priority')));
|
2103 |
+
//Check options
|
2104 |
+
if ( is_callable($this->build_vars['build_groups']) ) {
|
2105 |
+
//Pass groups to callback to build output
|
2106 |
+
call_user_func_array($this->build_vars['build_groups'], array($this, $groups));
|
2107 |
+
} elseif ( !!$this->build_vars['build_groups'] ) {
|
2108 |
+
//Build groups
|
2109 |
+
foreach ( $groups as $group ) {
|
2110 |
+
$this->build_group($group);
|
2111 |
+
}
|
2112 |
+
}
|
2113 |
+
|
2114 |
+
$this->util->do_action_ref_array('build_groups_post', array(&$this));
|
2115 |
+
}
|
2116 |
+
|
2117 |
+
/**
|
2118 |
+
* Build group
|
2119 |
+
*/
|
2120 |
+
function build_group($group) {
|
2121 |
+
if ( !$this->group_exists($group) ) {
|
2122 |
+
return false;
|
2123 |
+
}
|
2124 |
+
$group =& $this->get_group($group);
|
2125 |
+
//Stop processing if group contains no items
|
2126 |
+
if ( !count($this->get_items($group)) ) {
|
2127 |
+
return false;
|
2128 |
+
}
|
2129 |
+
|
2130 |
+
//Pre action
|
2131 |
+
$this->util->do_action_ref_array('build_group_pre', array(&$this, $group));
|
2132 |
+
|
2133 |
+
//Build items
|
2134 |
+
$this->build_items($group);
|
2135 |
+
|
2136 |
+
//Post action
|
2137 |
+
$this->util->do_action_ref_array('build_group_post', array(&$this, $group));
|
2138 |
+
}
|
2139 |
+
|
2140 |
+
/* Collection */
|
2141 |
+
|
2142 |
+
/**
|
2143 |
+
* Build entire collection of items
|
2144 |
+
* Prints output
|
2145 |
+
*/
|
2146 |
+
function build($build_vars = array()) {
|
2147 |
+
//Parse vars
|
2148 |
+
$this->parse_build_vars($build_vars);
|
2149 |
+
$this->util->do_action_ref_array('build_init', array(&$this));
|
2150 |
+
//Pre-build output
|
2151 |
+
$this->util->do_action_ref_array('build_pre', array(&$this));
|
2152 |
+
//Build groups
|
2153 |
+
$this->build_groups();
|
2154 |
+
//Post-build output
|
2155 |
+
$this->util->do_action_ref_array('build_post', array(&$this));
|
2156 |
+
}
|
2157 |
+
|
2158 |
+
/**
|
2159 |
+
* Parses build variables prior to use
|
2160 |
+
* @uses this->reset_build_vars() to reset build variables for each request
|
2161 |
+
* @param array $build_vars Variables to use for current request
|
2162 |
+
*/
|
2163 |
+
function parse_build_vars($build_vars = array()) {
|
2164 |
+
$this->reset_build_vars();
|
2165 |
+
$this->build_vars = $this->util->apply_filters('parse_build_vars', wp_parse_args($build_vars, $this->build_vars), $this);
|
2166 |
+
}
|
2167 |
+
|
2168 |
+
/**
|
2169 |
+
* Reset build variables to defaults
|
2170 |
+
* Default Variables
|
2171 |
+
* > groups - array - Names of groups to build
|
2172 |
+
* > context - string - Context of current request
|
2173 |
+
* > layout - string - Name of default layout to use
|
2174 |
+
*/
|
2175 |
+
function reset_build_vars() {
|
2176 |
+
$this->build_vars = wp_parse_args($this->build_vars, $this->build_vars_default);
|
2177 |
+
}
|
2178 |
+
}
|
2179 |
+
|
2180 |
+
/**
|
2181 |
+
* Collection of default system-wide fields
|
2182 |
+
* @package Simple Lightbox
|
2183 |
+
* @subpackage Fields
|
2184 |
+
* @author Archetyped
|
2185 |
+
*
|
2186 |
+
*/
|
2187 |
+
class SLB_Fields extends SLB_Field_Collection {
|
2188 |
+
|
2189 |
+
var $item_type = 'SLB_Field_Type';
|
2190 |
+
|
2191 |
+
/**
|
2192 |
+
* Placeholder handlers
|
2193 |
+
* @var array
|
2194 |
+
*/
|
2195 |
+
var $placholders = null;
|
2196 |
+
|
2197 |
+
/* Constructor */
|
2198 |
+
|
2199 |
+
function __construct() {
|
2200 |
+
parent::__construct('fields');
|
2201 |
+
}
|
2202 |
+
|
2203 |
+
protected function _hooks() {
|
2204 |
+
parent::_hooks();
|
2205 |
+
//Init fields
|
2206 |
+
add_action('init', $this->m('register_types'));
|
2207 |
+
//Init placeholders
|
2208 |
+
add_action('init', $this->m('register_placeholders'));
|
2209 |
+
}
|
2210 |
+
|
2211 |
+
/* Field Types */
|
2212 |
+
|
2213 |
+
/**
|
2214 |
+
* Initialize fields
|
2215 |
+
*/
|
2216 |
+
function register_types() {
|
2217 |
+
/* Field Types */
|
2218 |
+
|
2219 |
+
//Base
|
2220 |
+
$base = new SLB_Field_Type('base');
|
2221 |
+
$base->set_description(__('Default Element', 'simple-lightbox'));
|
2222 |
+
$base->set_property('tag', 'span');
|
2223 |
+
$base->set_property('class', '', 'attr');
|
2224 |
+
$base->set_layout('form_attr', '{tag} name="{field_name}" id="{field_id}" {properties ref_base="root" group="attr"}');
|
2225 |
+
$base->set_layout('form', '<{form_attr ref_base="layout"} />');
|
2226 |
+
$base->set_layout('label', '<label for="{field_id}">{label}</label>');
|
2227 |
+
$base->set_layout('display', '{data context="display"}');
|
2228 |
+
$this->add($base);
|
2229 |
+
|
2230 |
+
//Base closed
|
2231 |
+
$base_closed = new SLB_Field_Type('base_closed');
|
2232 |
+
$base_closed->set_parent('base');
|
2233 |
+
$base_closed->set_description(__('Default Element (Closed Tag)', 'simple-lightbox'));
|
2234 |
+
$base_closed->set_layout('form_start', '<{tag} id="{field_id}" name="{field_name}" {properties ref_base="root" group="attr"}>');
|
2235 |
+
$base_closed->set_layout('form_end', '</{tag}>');
|
2236 |
+
$base_closed->set_layout('form', '{form_start ref_base="layout"}{data}{form_end ref_base="layout"}');
|
2237 |
+
$this->add($base_closed);
|
2238 |
+
|
2239 |
+
//Input
|
2240 |
+
$input = new SLB_Field_Type('input', 'base');
|
2241 |
+
$input->set_description(__('Default Input Element', 'simple-lightbox'));
|
2242 |
+
$input->set_property('tag', 'input');
|
2243 |
+
$input->set_property('type', 'text', 'attr');
|
2244 |
+
$input->set_property('value', '{data}', 'attr');
|
2245 |
+
$this->add($input);
|
2246 |
+
|
2247 |
+
//Text input
|
2248 |
+
$text = new SLB_Field_Type('text', 'input');
|
2249 |
+
$text->set_description(__('Text Box', 'simple-lightbox'));
|
2250 |
+
$text->set_property('size', 15, 'attr');
|
2251 |
+
$text->set_property('label');
|
2252 |
+
$text->set_layout('form', '{label ref_base="layout"} {inherit}');
|
2253 |
+
$this->add($text);
|
2254 |
+
|
2255 |
+
//Checkbox
|
2256 |
+
$cb = new SLB_Field_Type('checkbox', 'input');
|
2257 |
+
$cb->set_property('type', 'checkbox');
|
2258 |
+
$cb->set_property('value', null);
|
2259 |
+
$cb->set_layout('form_attr', '{inherit} {checked}');
|
2260 |
+
$cb->set_layout('form', '{label ref_base="layout"} <{form_attr ref_base="layout"} />');
|
2261 |
+
$this->add($cb);
|
2262 |
+
|
2263 |
+
//Textarea
|
2264 |
+
$ta = new SLB_Field_Type('textarea', 'base_closed');
|
2265 |
+
$ta->set_property('tag', 'textarea');
|
2266 |
+
$ta->set_property('cols', 40, 'attr');
|
2267 |
+
$ta->set_property('rows', 3, 'attr');
|
2268 |
+
$this->add($ta);
|
2269 |
+
|
2270 |
+
//Rich Text
|
2271 |
+
$rt = new SLB_Field_Type('richtext', 'textarea');
|
2272 |
+
$rt->set_property('class', 'theEditor {inherit}');
|
2273 |
+
$rt->set_layout('form', '<div class="rt_container">{inherit}</div>');
|
2274 |
+
$rt->add_action('admin_print_footer_scripts', 'wp_tiny_mce', 25);
|
2275 |
+
$this->add($rt);
|
2276 |
+
|
2277 |
+
//Hidden
|
2278 |
+
$hidden = new SLB_Field_Type('hidden');
|
2279 |
+
$hidden->set_parent('input');
|
2280 |
+
$hidden->set_description(__('Hidden Field', 'simple-lightbox'));
|
2281 |
+
$hidden->set_property('type', 'hidden');
|
2282 |
+
$this->add($hidden);
|
2283 |
+
|
2284 |
+
//Select
|
2285 |
+
$select = new SLB_Field_Type('select', 'base_closed');
|
2286 |
+
$select->set_description(__('Select tag', 'simple-lightbox'));
|
2287 |
+
$select->set_property('tag', 'select');
|
2288 |
+
$select->set_property('tag_option', 'option');
|
2289 |
+
$select->set_property('options', array());
|
2290 |
+
$select->set_layout('form', '{label ref_base="layout"} {form_start ref_base="layout"}{option_loop ref_base="layout"}{form_end ref_base="layout"}');
|
2291 |
+
$select->set_layout('option_loop', '{loop data="properties.options" layout="option" layout_data="option_data"}');
|
2292 |
+
$select->set_layout('option', '<{tag_option} value="{data_ext id="option_value"}">{data_ext id="option_text"}</{tag_option}>');
|
2293 |
+
$select->set_layout('option_data', '<{tag_option} value="{data_ext id="option_value"}" selected="selected">{data_ext id="option_text"}</{tag_option}>');
|
2294 |
+
$this->add($select);
|
2295 |
+
|
2296 |
+
//Span
|
2297 |
+
$span = new SLB_Field_Type('span', 'base_closed');
|
2298 |
+
$span->set_description(__('Inline wrapper', 'simple-lightbox'));
|
2299 |
+
$span->set_property('tag', 'span');
|
2300 |
+
$span->set_property('value', 'Hello there!');
|
2301 |
+
$this->add($span);
|
2302 |
+
|
2303 |
+
//Enable plugins to modify (add, remove, etc.) field types
|
2304 |
+
do_action_ref_array($this->add_prefix('register_fields'), array(&$this));
|
2305 |
+
|
2306 |
+
//Signal completion of field registration
|
2307 |
+
do_action_ref_array($this->add_prefix('fields_registered'), array(&$this));
|
2308 |
+
}
|
2309 |
+
|
2310 |
+
/* Placeholder handlers */
|
2311 |
+
|
2312 |
+
function register_placeholders() {
|
2313 |
+
//Default placeholder handlers
|
2314 |
+
$this->register_placeholder('all', $this->m('process_placeholder_default'), 11);
|
2315 |
+
$this->register_placeholder('field_id', $this->m('process_placeholder_id'));
|
2316 |
+
$this->register_placeholder('field_name', $this->m('process_placeholder_name'));
|
2317 |
+
$this->register_placeholder('data', $this->m('process_placeholder_data'));
|
2318 |
+
$this->register_placeholder('data_ext',$this->m('process_placeholder_data_ext'));
|
2319 |
+
$this->register_placeholder('loop', $this->m('process_placeholder_loop'));
|
2320 |
+
$this->register_placeholder('label', $this->m('process_placeholder_label'));
|
2321 |
+
$this->register_placeholder('checked', $this->m('process_placeholder_checked'));
|
2322 |
+
|
2323 |
+
//Allow other code to register placeholders
|
2324 |
+
do_action_ref_array($this->add_prefix('register_field_placeholders'), array(&$this));
|
2325 |
+
|
2326 |
+
//Signal completion of field placeholder registration
|
2327 |
+
do_action_ref_array($this->add_prefix('field_placeholders_registered'), array(&$this));
|
2328 |
+
}
|
2329 |
+
|
2330 |
+
/**
|
2331 |
+
* Register a function to handle a placeholder
|
2332 |
+
* Multiple handlers may be registered for a single placeholder
|
2333 |
+
* Adds filter hook to WP for handling specified placeholder
|
2334 |
+
* Placeholders are in layouts and are replaced with data at runtime
|
2335 |
+
* @uses add_filter()
|
2336 |
+
* @param string $placeholder Name of placeholder to add handler for (Using 'all' will set the function as a handler for all placeholders
|
2337 |
+
* @param callback $callback Function to set as a handler
|
2338 |
+
* @param int $priority (optional) Priority of handler
|
2339 |
+
* @return void
|
2340 |
+
*/
|
2341 |
+
function register_placeholder($placeholder, $callback, $priority = 10) {
|
2342 |
+
if ( 'all' == $placeholder )
|
2343 |
+
$placeholder = '';
|
2344 |
+
else
|
2345 |
+
$placeholder = '_' . $placeholder;
|
2346 |
+
$hook = $this->add_prefix('process_placeholder' . $placeholder);
|
2347 |
+
add_filter($hook, $callback, $priority, 5);
|
2348 |
+
}
|
2349 |
+
|
2350 |
+
/**
|
2351 |
+
* Default placeholder processing
|
2352 |
+
* To be executed when current placeholder has not been handled by another handler
|
2353 |
+
* @param string $output Value to be used in place of placeholder
|
2354 |
+
* @param SLB_Field $item Field containing placeholder
|
2355 |
+
* @param array $placeholder Current placeholder
|
2356 |
+
* @see SLB_Field::parse_layout for structure of $placeholder array
|
2357 |
+
* @param string $layout Layout to build
|
2358 |
+
* @param array $data Extended data for item
|
2359 |
+
* @return string Value to use in place of current placeholder
|
2360 |
+
*/
|
2361 |
+
function process_placeholder_default($output, $item, $placeholder, $layout, $data) {
|
2362 |
+
//Validate parameters before processing
|
2363 |
+
if ( empty($output) && is_a($item, 'SLB_Field_Type') && is_array($placeholder) ) {
|
2364 |
+
//Build path to replacement data
|
2365 |
+
$output = $item->get_member_value($placeholder);
|
2366 |
+
|
2367 |
+
//Check if value is group (properties, etc.)
|
2368 |
+
//All groups must have additional attributes (beyond reserved attributes) that define how items in group are used
|
2369 |
+
if (is_array($output)
|
2370 |
+
&& !empty($placeholder['attributes'])
|
2371 |
+
&& is_array($placeholder['attributes'])
|
2372 |
+
&& ($ph = $item->get_placeholder_defaults())
|
2373 |
+
&& $attribs = array_diff(array_keys($placeholder['attributes']), array_values($ph->reserved))
|
2374 |
+
) {
|
2375 |
+
/* Targeted property is an array, but the placeholder contains additional options on how property is to be used */
|
2376 |
+
|
2377 |
+
//Find items matching criteria in $output
|
2378 |
+
//Check for group criteria
|
2379 |
+
if ( 'properties' == $placeholder['tag'] && ($prop_group = $item->get_group($placeholder['attributes']['group'])) && !empty($prop_group) ) {
|
2380 |
+
/* Process group */
|
2381 |
+
$group_out = array();
|
2382 |
+
//Iterate through properties in group and build string
|
2383 |
+
foreach ( array_keys($prop_group) as $prop_key ) {
|
2384 |
+
$prop_val = $item->get_property($prop_key);
|
2385 |
+
if ( !is_null($prop_val) )
|
2386 |
+
$group_out[] = $prop_key . '="' . $prop_val . '"';
|
2387 |
+
}
|
2388 |
+
$output = implode(' ', $group_out);
|
2389 |
+
}
|
2390 |
+
} elseif ( is_object($output) && is_a($output, $item->base_class) ) {
|
2391 |
+
/* Targeted property is actually a nested item */
|
2392 |
+
//Set caller to current item
|
2393 |
+
$output->set_caller($item);
|
2394 |
+
//Build layout for nested element
|
2395 |
+
$output = $output->build_layout($layout);
|
2396 |
+
}
|
2397 |
+
}
|
2398 |
+
|
2399 |
+
return $output;
|
2400 |
+
}
|
2401 |
+
|
2402 |
+
/**
|
2403 |
+
* Build Field ID attribute
|
2404 |
+
* @see SLB_Field_Type::process_placeholder_default for parameter descriptions
|
2405 |
+
* @return string Placeholder output
|
2406 |
+
*/
|
2407 |
+
function process_placeholder_id($output, $item, $placeholder, $layout, $data) {
|
2408 |
+
//Get attributes
|
2409 |
+
$args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_id'));
|
2410 |
+
return $item->get_id($args);
|
2411 |
+
}
|
2412 |
+
|
2413 |
+
/**
|
2414 |
+
* Build Field name attribute
|
2415 |
+
* Name is formatted as an associative array for processing by PHP after submission
|
2416 |
+
* @see SLB_Field_Type::process_placeholder_default for parameter descriptions
|
2417 |
+
* @return string Placeholder output
|
2418 |
+
*/
|
2419 |
+
function process_placeholder_name($output, $item, $placeholder, $layout, $data) {
|
2420 |
+
//Get attributes
|
2421 |
+
$args = wp_parse_args($placeholder['attributes'], array('format' => 'attr_name'));
|
2422 |
+
return $item->get_id($args);
|
2423 |
+
}
|
2424 |
+
|
2425 |
+
/**
|
2426 |
+
* Build item label
|
2427 |
+
* @see SLB_Fields::process_placeholder_default for parameter descriptions
|
2428 |
+
* @return string Field label
|
2429 |
+
*/
|
2430 |
+
function process_placeholder_label($output, $item, $placeholder, $layout, $data) {
|
2431 |
+
//Check if item has label property (e.g. sub-elements)
|
2432 |
+
$out = $item->get_property('label');
|
2433 |
+
//If property not set, use item title
|
2434 |
+
if ( empty($out) )
|
2435 |
+
$out = $item->get_title();
|
2436 |
+
return $out;
|
2437 |
+
}
|
2438 |
+
|
2439 |
+
/**
|
2440 |
+
* Retrieve data for item
|
2441 |
+
* @see SLB_Field_Type::process_placeholder_default for parameter descriptions
|
2442 |
+
* @return string Placeholder output
|
2443 |
+
*/
|
2444 |
+
function process_placeholder_data($output, $item, $placeholder, $layout) {
|
2445 |
+
$attr_default = array (
|
2446 |
+
'context' => '',
|
2447 |
+
);
|
2448 |
+
$opts = wp_parse_args($placeholder['attributes'], $attr_default);
|
2449 |
+
//Save context to separate variable
|
2450 |
+
$context = $opts['context'];
|
2451 |
+
unset($opts['context']);
|
2452 |
+
//Get data
|
2453 |
+
$out = $item->get_data($opts);
|
2454 |
+
if ( !is_null($out) ) {
|
2455 |
+
//Get specific member in value (e.g. value from a specific item element)
|
2456 |
+
if ( isset($opts['element']) && is_array($out) && ( $el = $opts['element'] ) && isset($out[$el]) )
|
2457 |
+
$out = $out[$el];
|
2458 |
+
}
|
2459 |
+
|
2460 |
+
//Format data based on context
|
2461 |
+
$out = $item->preserve_special_chars($out, $context);
|
2462 |
+
$out = $item->format($out, $context);
|
2463 |
+
//Return data
|
2464 |
+
return $out;
|
2465 |
+
}
|
2466 |
+
|
2467 |
+
/**
|
2468 |
+
* Set checked attribute on item
|
2469 |
+
* Evaluates item's data to see if item should be checked or not
|
2470 |
+
* @see SLB_Fields::process_placeholder_default for parameter descriptions
|
2471 |
+
* @return string Appropriate checkbox attribute
|
2472 |
+
*/
|
2473 |
+
function process_placeholder_checked($output, $item, $placeholder, $layout, $data) {
|
2474 |
+
$out = '';
|
2475 |
+
$c = $item->get_container();
|
2476 |
+
$d = ( isset($c->data[$item->get_id()]) ) ? $c->data[$item->get_id()] : null;
|
2477 |
+
$item->set_property('d', true);
|
2478 |
+
if ( $item->get_data() )
|
2479 |
+
$out = 'checked="checked"';
|
2480 |
+
$item->set_property('d', false);
|
2481 |
+
return $out;
|
2482 |
+
}
|
2483 |
+
|
2484 |
+
/**
|
2485 |
+
* Loops over data to build item output
|
2486 |
+
* Options:
|
2487 |
+
* data - Dot-delimited path in item that contains data to loop through
|
2488 |
+
* layout - Name of layout to use for each data item in loop
|
2489 |
+
* layout_data - Name of layout to use for data item that matches previously-saved item data
|
2490 |
+
* @see SLB_Field_Type::process_placeholder_default for parameter descriptions
|
2491 |
+
* @return string Placeholder output
|
2492 |
+
*/
|
2493 |
+
function process_placeholder_loop($output, $item, $placeholder, $layout, $data) {
|
2494 |
+
//Setup loop options
|
2495 |
+
$attr_defaults = array (
|
2496 |
+
'layout' => '',
|
2497 |
+
'layout_data' => null,
|
2498 |
+
'data' => ''
|
2499 |
+
);
|
2500 |
+
$attr = wp_parse_args($placeholder['attributes'], $attr_defaults);
|
2501 |
+
if ( is_null($attr['layout_data']) )
|
2502 |
+
$attr['layout_data'] =& $attr['layout'];
|
2503 |
+
//Get data for loop
|
2504 |
+
$path = explode('.', $attr['data']);
|
2505 |
+
$loop_data = $item->get_member_value($path);
|
2506 |
+
|
2507 |
+
//Check if data is callback
|
2508 |
+
if ( is_callable($loop_data) )
|
2509 |
+
$loop_data = call_user_func($loop_data);
|
2510 |
+
|
2511 |
+
//Get item data
|
2512 |
+
$data = $item->get_data();
|
2513 |
+
|
2514 |
+
//Iterate over data and build output
|
2515 |
+
$out = array();
|
2516 |
+
if ( is_array($loop_data) && !empty($loop_data) ) {
|
2517 |
+
foreach ( $loop_data as $value => $label ) {
|
2518 |
+
//Load appropriate layout based on item value
|
2519 |
+
$layout = ( ($data === 0 && $value === $data) xor $data == $value ) ? $attr['layout_data'] : $attr['layout'];
|
2520 |
+
//Stop processing if no valid layout is returned
|
2521 |
+
if ( empty($layout) )
|
2522 |
+
continue;
|
2523 |
+
//Prep extended item data
|
2524 |
+
$data_ext = array('option_value' => $value, 'option_text' => $label);
|
2525 |
+
$out[] = $item->build_layout($layout, $data_ext);
|
2526 |
+
}
|
2527 |
+
}
|
2528 |
+
|
2529 |
+
//Return output
|
2530 |
+
return implode($out);
|
2531 |
+
}
|
2532 |
+
|
2533 |
+
/**
|
2534 |
+
* Returns specified value from extended data array for item
|
2535 |
+
* @see SLB_Field_Type::process_placeholder_default for parameter descriptions
|
2536 |
+
* @return string Placeholder output
|
2537 |
+
*/
|
2538 |
+
function process_placeholder_data_ext($output, $item, $placeholder, $layout, $data) {
|
2539 |
+
if ( isset($placeholder['attributes']['id']) && ($key = $placeholder['attributes']['id']) && isset($data[$key]) ) {
|
2540 |
+
$output = strval($data[$key]);
|
2541 |
+
}
|
2542 |
+
|
2543 |
+
return $output;
|
2544 |
+
}
|
2545 |
+
|
2546 |
+
/* Build */
|
2547 |
+
|
2548 |
+
/**
|
2549 |
+
* Output items in a group
|
2550 |
+
* @param string $group ID of Group to output
|
2551 |
+
* @return string Group output
|
2552 |
+
* TODO Make compatible with parent::build_group()
|
2553 |
+
*/
|
2554 |
+
function build_group($group) {
|
2555 |
+
$out = array();
|
2556 |
+
$classnames = (object) array(
|
2557 |
+
'multi' => 'multi_field',
|
2558 |
+
'single' => 'single_field',
|
2559 |
+
'elements' => 'has_elements'
|
2560 |
+
);
|
2561 |
+
|
2562 |
+
//Stop execution if group does not exist
|
2563 |
+
if ( $this->group_exists($group) && $group =& $this->get_group($group) ) {
|
2564 |
+
$group_items = ( count($group->items) > 1 ) ? $classnames->multi : $classnames->single . ( ( ( $fs = array_keys($group->items) ) && ( $f =& $group->items[$fs[0]] ) && ( $els = $f->get_member_value('elements', '', null) ) && !empty($els) ) ? '_' . $classnames->elements : '' );
|
2565 |
+
$classname = array($this->add_prefix('attributes_wrap'), $group_items);
|
2566 |
+
$out[] = '<div class="' . implode(' ', $classname) . '">'; //Wrap all items in group
|
2567 |
+
|
2568 |
+
//Build layout for each item in group
|
2569 |
+
foreach ( array_keys($group->items) as $item_id ) {
|
2570 |
+
$item =& $group->items[$item_id];
|
2571 |
+
$item->set_caller($this);
|
2572 |
+
//Start item output
|
2573 |
+
$id = $this->add_prefix('field_' . $item->get_id());
|
2574 |
+
$out[] = '<div id="' . $id . '_wrap" class=' . $this->add_prefix('attribute_wrap') . '>';
|
2575 |
+
//Build item layout
|
2576 |
+
$out[] = $item->build_layout();
|
2577 |
+
//end item output
|
2578 |
+
$out[] = '</div>';
|
2579 |
+
$item->clear_caller();
|
2580 |
+
}
|
2581 |
+
$out[] = '</div>'; //Close items container
|
2582 |
+
//Add description if exists
|
2583 |
+
if ( !empty($group->description) )
|
2584 |
+
$out[] = '<p class=' . $this->add_prefix('group_description') . '>' . $group->description . '</p>';
|
2585 |
+
}
|
2586 |
+
|
2587 |
+
//Return group output
|
2588 |
+
return implode($out);
|
2589 |
+
}
|
2590 |
+
}
|
includes/class.options.php
ADDED
@@ -0,0 +1,673 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Option object
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Options
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Option extends SLB_Field {
|
10 |
+
|
11 |
+
/* Properties */
|
12 |
+
|
13 |
+
public $hook_prefix = 'option';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Determines whether option will be sent to client
|
17 |
+
* @var bool
|
18 |
+
*/
|
19 |
+
var $in_client = false;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Child mapping
|
23 |
+
* @see SLB_Field_Base::map
|
24 |
+
* @var array
|
25 |
+
*/
|
26 |
+
var $map = array (
|
27 |
+
'default' => 'data',
|
28 |
+
'attr' => 'properties'
|
29 |
+
);
|
30 |
+
|
31 |
+
var $property_priority = array ('id', 'data', 'parent');
|
32 |
+
|
33 |
+
/* Init */
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @see SLB_Field::__construct()
|
37 |
+
* @uses parent::__construct() to initialize instance
|
38 |
+
* @param $id
|
39 |
+
* @param $title
|
40 |
+
* @param $default
|
41 |
+
*/
|
42 |
+
function __construct($id, $title = '', $default = '') {
|
43 |
+
//Normalize properties
|
44 |
+
$args = func_get_args();
|
45 |
+
$defaults = array ('title' => '', 'default' => '');
|
46 |
+
$props = $this->make_properties($args, $defaults);
|
47 |
+
//Validate
|
48 |
+
if ( is_scalar($id) )
|
49 |
+
$props['id'] = $id;
|
50 |
+
if ( !is_string($props['title']) )
|
51 |
+
$props['title'] = '';
|
52 |
+
//Send to parent constructor
|
53 |
+
parent::__construct($props);
|
54 |
+
}
|
55 |
+
|
56 |
+
/* Getters/Setters */
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Retrieve default value for option
|
60 |
+
* @return mixed Default option value
|
61 |
+
*/
|
62 |
+
function get_default($context = '') {
|
63 |
+
return $this->get_data($context, false);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Sets parent based on default value
|
68 |
+
*/
|
69 |
+
function set_parent($parent = null) {
|
70 |
+
$p =& $this->get_parent();
|
71 |
+
if ( empty($parent) && empty($p) ) {
|
72 |
+
$parent = 'text';
|
73 |
+
$d = $this->get_default();
|
74 |
+
if ( is_bool($d) )
|
75 |
+
$parent = 'checkbox';
|
76 |
+
$parent = 'option_' . $parent;
|
77 |
+
} elseif ( !empty($p) && !is_object($p) ) {
|
78 |
+
$parent =& $p;
|
79 |
+
}
|
80 |
+
parent::set_parent($parent);
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Set in_client property
|
85 |
+
* @uses this::in_client
|
86 |
+
* @param bool Whether or not option should be included in client output (Default: false)
|
87 |
+
* @return void
|
88 |
+
*/
|
89 |
+
function set_in_client($in_client = false) {
|
90 |
+
$this->in_client = !!$in_client;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Determines whether option should be included in client output
|
95 |
+
* @uses this::in_client
|
96 |
+
* @return bool TRUE if option is included in client output
|
97 |
+
*/
|
98 |
+
function get_in_client() {
|
99 |
+
return $this->in_client;
|
100 |
+
}
|
101 |
+
|
102 |
+
/* Formatting */
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Format data as string for browser output
|
106 |
+
* @see SLB_Field_Base::format()
|
107 |
+
* @param mixed $value Data to format
|
108 |
+
* @param string $context (optional) Current context
|
109 |
+
* @return string Formatted value
|
110 |
+
*/
|
111 |
+
function format_display($value, $context = '') {
|
112 |
+
if ( !is_string($value) ) {
|
113 |
+
if ( is_bool($value) ) {
|
114 |
+
$value = ( $value ) ? __('Enabled', 'simple-lightbox') : __('Disabled', 'simple-lightbox');
|
115 |
+
}
|
116 |
+
elseif ( is_null($value) )
|
117 |
+
$value = '';
|
118 |
+
else
|
119 |
+
$value = strval($value);
|
120 |
+
} elseif ( empty($value) ) {
|
121 |
+
$value = 'empty';
|
122 |
+
}
|
123 |
+
return htmlentities($value);
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Format data using same format as default value
|
128 |
+
* @see SLB_Field_Base::format()
|
129 |
+
* @param mixed $value Data to format
|
130 |
+
* @param string $context (optional) Current context
|
131 |
+
* @return mixed Formatted option value
|
132 |
+
*/
|
133 |
+
function format_default($value, $context = '') {
|
134 |
+
//Get default value
|
135 |
+
$d = $this->get_default();
|
136 |
+
if ( empty($d) )
|
137 |
+
return $value;
|
138 |
+
if ( is_bool($d) )
|
139 |
+
$value = $this->format_bool($value);
|
140 |
+
elseif ( is_string($d) )
|
141 |
+
$value = $this->format_string($value);
|
142 |
+
return $value;
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Format data as boolean (true/false)
|
147 |
+
* @see SLB_Field_Base::format()
|
148 |
+
* @param mixed $value Data to format
|
149 |
+
* @param string $context (optional) Current context
|
150 |
+
* @return bool Option value
|
151 |
+
*/
|
152 |
+
function format_bool($value, $context = '') {
|
153 |
+
if ( !is_bool($value) )
|
154 |
+
$value = !!$value;
|
155 |
+
return $value;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Format data as string
|
160 |
+
* @see SLB_Field_Base::format()
|
161 |
+
* @param mixed $value Data to format
|
162 |
+
* @param string $context (optional) Current context
|
163 |
+
* @return string Option string value
|
164 |
+
*/
|
165 |
+
function format_string($value, $context = '') {
|
166 |
+
if ( is_bool($value) ) {
|
167 |
+
$value = ( $value ) ? 'true' : 'false';
|
168 |
+
}
|
169 |
+
elseif ( is_object($value) ) {
|
170 |
+
$value = get_class($value);
|
171 |
+
}
|
172 |
+
elseif ( is_array($value) ) {
|
173 |
+
$value = implode(' ', $value);
|
174 |
+
}
|
175 |
+
else {
|
176 |
+
$value = strval($value);
|
177 |
+
}
|
178 |
+
return $value;
|
179 |
+
}
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Options collection
|
184 |
+
* @package Simple Lightbox
|
185 |
+
* @subpackage Options
|
186 |
+
* @author Archetyped
|
187 |
+
* @uses SLB_Field_Collection
|
188 |
+
*/
|
189 |
+
class SLB_Options extends SLB_Field_Collection {
|
190 |
+
|
191 |
+
/* Properties */
|
192 |
+
|
193 |
+
public $hook_prefix = 'options';
|
194 |
+
|
195 |
+
var $item_type = 'SLB_Option';
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Key for saving version to DB
|
199 |
+
* @var string
|
200 |
+
*/
|
201 |
+
private $version_key = 'version';
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Whether version has been checked
|
205 |
+
* @var bool
|
206 |
+
*/
|
207 |
+
var $version_checked = false;
|
208 |
+
|
209 |
+
var $items_migrated = false;
|
210 |
+
|
211 |
+
var $build_vars = array (
|
212 |
+
'validate_pre' => false,
|
213 |
+
'validate_post' => false,
|
214 |
+
'save_pre' => false,
|
215 |
+
'save_post' => false
|
216 |
+
);
|
217 |
+
|
218 |
+
/* Init */
|
219 |
+
|
220 |
+
function __construct($id = '', $props = array()) {
|
221 |
+
//Validate arguments
|
222 |
+
$args = func_get_args();
|
223 |
+
//Set default ID
|
224 |
+
if ( !$this->validate_id($id) ) {
|
225 |
+
$id = 'options';
|
226 |
+
}
|
227 |
+
$defaults = $this->integrate_id($id);
|
228 |
+
$props = $this->make_properties($args, $defaults);
|
229 |
+
parent::__construct($props);
|
230 |
+
$this->add_prefix_ref($this->version_key);
|
231 |
+
}
|
232 |
+
|
233 |
+
protected function _hooks() {
|
234 |
+
parent::_hooks();
|
235 |
+
//Register fields
|
236 |
+
add_action($this->add_prefix('register_fields'), $this->m('register_fields'));
|
237 |
+
//Set option parents
|
238 |
+
add_action($this->add_prefix('fields_registered'), $this->m('set_parents'));
|
239 |
+
//Building
|
240 |
+
$this->util->add_action('build_init', $this->m('build_init'));
|
241 |
+
}
|
242 |
+
|
243 |
+
/* Legacy/Migration */
|
244 |
+
|
245 |
+
/**
|
246 |
+
* Checks whether new version has been installed and migrates necessary settings
|
247 |
+
* @uses $version_key as option name
|
248 |
+
* @uses get_option() to retrieve saved version number
|
249 |
+
* @uses SLB_Utilities::get_plugin_version() to retrieve current version
|
250 |
+
* @return bool TRUE if version has been changed
|
251 |
+
*/
|
252 |
+
function check_update() {
|
253 |
+
if ( !$this->version_checked ) {
|
254 |
+
$this->version_checked = true;
|
255 |
+
$version_changed = false;
|
256 |
+
//Get version from DB
|
257 |
+
$vo = $this->get_version();
|
258 |
+
//Get current version
|
259 |
+
$vn = $this->util->get_plugin_version();
|
260 |
+
//Compare versions
|
261 |
+
if ( $vo != $vn ) {
|
262 |
+
//Update saved version
|
263 |
+
$this->set_version($vn);
|
264 |
+
//Migrate old version to new version
|
265 |
+
if ( strcasecmp($vo, $vn) < 0 ) {
|
266 |
+
//Force full migration
|
267 |
+
$version_changed = true;
|
268 |
+
}
|
269 |
+
}
|
270 |
+
//Migrate
|
271 |
+
$this->migrate($version_changed);
|
272 |
+
}
|
273 |
+
|
274 |
+
return $this->version_checked;
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Save plugin version to DB
|
279 |
+
* If no version supplied, will fetch plugin data to determine version
|
280 |
+
* @uses $version_key as option name
|
281 |
+
* @uses update_option() to save version to options table
|
282 |
+
* @param string $ver (optional) Plugin version
|
283 |
+
*/
|
284 |
+
function set_version($ver = null) {
|
285 |
+
if ( empty($ver) ) {
|
286 |
+
$ver = $this->util->get_plugin_version();
|
287 |
+
}
|
288 |
+
return update_option($this->version_key, $ver);
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Retrieve saved version data
|
293 |
+
* @return string Saved version
|
294 |
+
*/
|
295 |
+
function get_version() {
|
296 |
+
return get_option($this->version_key, '');
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Migrate options from old versions to current version
|
301 |
+
* @uses self::items_migrated to determine if simple migration has been performed in current request or not
|
302 |
+
* @uses self::save() to save data after migration
|
303 |
+
* @param bool $full Whether to perform a full migration or not (Default: No)
|
304 |
+
*/
|
305 |
+
function migrate($full = false) {
|
306 |
+
if ( !$full && $this->items_migrated )
|
307 |
+
return false;
|
308 |
+
|
309 |
+
//Legacy options
|
310 |
+
$d = null;
|
311 |
+
$this->load_data();
|
312 |
+
|
313 |
+
$items =& $this->get_items();
|
314 |
+
|
315 |
+
//Migrate separate options to unified option
|
316 |
+
if ( $full ) {
|
317 |
+
foreach ( $items as $opt => $props ) {
|
318 |
+
$oid = $this->add_prefix($opt);
|
319 |
+
$o = get_option($oid, $d);
|
320 |
+
if ( $o !== $d ) {
|
321 |
+
//Migrate value to data array
|
322 |
+
$this->set_data($opt, $o, false);
|
323 |
+
//Delete legacy option
|
324 |
+
delete_option($oid);
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
328 |
+
|
329 |
+
//Migrate legacy items
|
330 |
+
if ( is_array($this->properties_init) && isset($this->properties_init['legacy']) && is_array($this->properties_init['legacy']) ) {
|
331 |
+
$l =& $this->properties_init['legacy'];
|
332 |
+
//Normalize legacy map
|
333 |
+
foreach ( $l as $opt => $dest ) {
|
334 |
+
if ( !is_array($dest) ) {
|
335 |
+
if ( is_string($dest) )
|
336 |
+
$l[$opt] = array($dest);
|
337 |
+
else
|
338 |
+
unset($l[$opt]);
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
/* Separate options */
|
343 |
+
if ( $full ) {
|
344 |
+
foreach ( $l as $opt => $dest ) {
|
345 |
+
$oid = $this->add_prefix($opt);
|
346 |
+
$o = get_option($oid, $d);
|
347 |
+
//Only migrate valid values
|
348 |
+
if ( $o !== $d ) {
|
349 |
+
//Process destinations
|
350 |
+
foreach ( $dest as $id ) {
|
351 |
+
$this->set_data($id, $o, false, true);
|
352 |
+
}
|
353 |
+
}
|
354 |
+
//Remove legacy option
|
355 |
+
delete_option($oid);
|
356 |
+
}
|
357 |
+
}
|
358 |
+
|
359 |
+
/* Simple Migration (Internal options only) */
|
360 |
+
|
361 |
+
//Get existing items that are also legacy items
|
362 |
+
$opts = array_intersect_key($this->get_data(), $l);
|
363 |
+
foreach ( $opts as $opt => $val ) {
|
364 |
+
$d = $this->get_data($opt);
|
365 |
+
//Migrate data from old option to new option
|
366 |
+
$dest = $l[$opt];
|
367 |
+
//Validate new options to send data to
|
368 |
+
foreach ( $dest as $id ) {
|
369 |
+
$this->set_data($id, $d, false, true);
|
370 |
+
}
|
371 |
+
//Remove legacy option
|
372 |
+
$this->remove($opt, false);
|
373 |
+
}
|
374 |
+
}
|
375 |
+
//Save changes
|
376 |
+
$this->save();
|
377 |
+
//Set flag
|
378 |
+
$this->items_migrated = true;
|
379 |
+
}
|
380 |
+
|
381 |
+
/* Option setup */
|
382 |
+
|
383 |
+
/**
|
384 |
+
* Get elements for creating fields
|
385 |
+
* @return obj
|
386 |
+
*/
|
387 |
+
function get_field_elements() {
|
388 |
+
static $o = null;
|
389 |
+
if ( empty($o) ) {
|
390 |
+
$o = new stdClass();
|
391 |
+
/* Layout */
|
392 |
+
$layout = new stdClass();
|
393 |
+
$layout->label = '<label for="{field_id}" class="title block">{label}</label>';
|
394 |
+
$layout->label_ref = '{label ref_base="layout"}';
|
395 |
+
$layout->field_pre = '<div class="input block">';
|
396 |
+
$layout->field_post = '</div>';
|
397 |
+
$layout->opt_pre = '<div class="' . $this->add_prefix('option_item') . '">';
|
398 |
+
$layout->opt_post = '</div>';
|
399 |
+
$layout->form = '<{form_attr ref_base="layout"} /> <span class="description">(' . __('Default', 'simple-lightbox') . ': {data context="display" top="0"})</span>';
|
400 |
+
/* Combine */
|
401 |
+
$o->layout =& $layout;
|
402 |
+
}
|
403 |
+
return $o;
|
404 |
+
}
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Register option-specific fields
|
408 |
+
* @param SLB_Fields $fields Reference to global fields object
|
409 |
+
* @return void
|
410 |
+
*/
|
411 |
+
function register_fields(&$fields) {
|
412 |
+
//Layouts
|
413 |
+
$o = $this->get_field_elements();
|
414 |
+
|
415 |
+
$form = $o->layout->opt_pre . $o->layout->label_ref . $o->layout->field_pre . $o->layout->form . $o->layout->field_post . $o->layout->opt_post;
|
416 |
+
|
417 |
+
//Text input
|
418 |
+
$otxt = new SLB_Field_Type('option_text', 'text');
|
419 |
+
$otxt->set_property('class', '{inherit} code');
|
420 |
+
$otxt->set_property('size', null);
|
421 |
+
$otxt->set_property('value', '{data context="form"}');
|
422 |
+
$otxt->set_layout('label', $o->layout->label);
|
423 |
+
$otxt->set_layout('form', $form);
|
424 |
+
$fields->add($otxt);
|
425 |
+
|
426 |
+
//Checkbox
|
427 |
+
$ocb = new SLB_Field_Type('option_checkbox', 'checkbox');
|
428 |
+
$ocb->set_layout('label', $o->layout->label);
|
429 |
+
$ocb->set_layout('form', $form);
|
430 |
+
$fields->add($ocb);
|
431 |
+
|
432 |
+
//Select
|
433 |
+
$othm = new SLB_Field_Type('option_select', 'select');
|
434 |
+
$othm->set_layout('label', $o->layout->label);
|
435 |
+
$othm->set_layout('form_start', $o->layout->field_pre . '{inherit}');
|
436 |
+
$othm->set_layout('form_end', '{inherit}' . $o->layout->field_post);
|
437 |
+
$othm->set_layout('form', $o->layout->opt_pre . '{inherit}' . $o->layout->opt_post);
|
438 |
+
$fields->add($othm);
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Set parent field types for options
|
443 |
+
* Parent only set for Admin pages
|
444 |
+
* @uses SLB_Option::set_parent() to set parent field for each option item
|
445 |
+
* @uses is_admin() to determine if current request is admin page
|
446 |
+
* @param object $fields Collection of default field types
|
447 |
+
* @return void
|
448 |
+
*/
|
449 |
+
function set_parents(&$fields) {
|
450 |
+
if ( !is_admin() )
|
451 |
+
return false;
|
452 |
+
$items =& $this->get_items();
|
453 |
+
foreach ( array_keys($items) as $opt ) {
|
454 |
+
$items[$opt]->set_parent();
|
455 |
+
}
|
456 |
+
foreach ( $this->items as $opt ) {
|
457 |
+
$p = $opt->parent;
|
458 |
+
if ( is_object($p) )
|
459 |
+
$p = 'o:' . $p->id;
|
460 |
+
}
|
461 |
+
}
|
462 |
+
|
463 |
+
/* Processing */
|
464 |
+
|
465 |
+
/**
|
466 |
+
* Validate option values
|
467 |
+
* Used for validating options (e.g. admin form submission) prior to saving options to DB
|
468 |
+
* Reformats values based on options' default values (i.e. bool, int, string, etc.)
|
469 |
+
* Adds option items not included in original submission
|
470 |
+
* @param array $values (optional) Option values
|
471 |
+
* @return array Full options data
|
472 |
+
*/
|
473 |
+
function validate($values = null, $force_save = false) {
|
474 |
+
if ( empty($values) && isset($_REQUEST[$this->add_prefix('options')]) ) {
|
475 |
+
$values_orig = $values;
|
476 |
+
if ( is_string($values_orig) )
|
477 |
+
$force_save = true;
|
478 |
+
$values = $_REQUEST[$this->add_prefix('options')];
|
479 |
+
}
|
480 |
+
if ( is_array($values) ) {
|
481 |
+
//Format data based on option type (bool, string, etc.)
|
482 |
+
foreach ( $values as $id => $val ) {
|
483 |
+
//Get default
|
484 |
+
$d = $this->get_default($id);
|
485 |
+
if ( is_bool($d) && !empty($val) )
|
486 |
+
$values[$id] = true;
|
487 |
+
}
|
488 |
+
//Merge in additional options that are not in post data
|
489 |
+
//Missing options (e.g. disabled checkboxes) & defaults
|
490 |
+
$items =& $this->get_items();
|
491 |
+
foreach ( $items as $id => $opt ) {
|
492 |
+
//Add options that were not included in form submission
|
493 |
+
if ( !array_key_exists($id, $values) ) {
|
494 |
+
if ( is_bool($opt->get_default()) )
|
495 |
+
$values[$id] = false;
|
496 |
+
else
|
497 |
+
$values[$id] = $opt->get_default();
|
498 |
+
}
|
499 |
+
}
|
500 |
+
}
|
501 |
+
|
502 |
+
if ( $force_save ) {
|
503 |
+
$this->set_data($values);
|
504 |
+
$values = $values_orig;
|
505 |
+
}
|
506 |
+
|
507 |
+
//Return value
|
508 |
+
return $values;
|
509 |
+
}
|
510 |
+
|
511 |
+
/* Data */
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Retrieve options from database
|
515 |
+
* @uses get_option to retrieve option data
|
516 |
+
* @return array Options data
|
517 |
+
*/
|
518 |
+
function fetch_data($sanitize = true) {
|
519 |
+
//Get data
|
520 |
+
$data = get_option($this->get_key(), null);
|
521 |
+
if ( $sanitize && is_array($data) ) {
|
522 |
+
//Sanitize loaded data based on default values
|
523 |
+
foreach ( $data as $id => $val ) {
|
524 |
+
if ( $this->has($id) ) {
|
525 |
+
$opt = $this->get($id);
|
526 |
+
if ( is_bool($opt->get_default()) )
|
527 |
+
$data[$id] = !!$val;
|
528 |
+
}/* else {
|
529 |
+
//Remove data that has no matching item
|
530 |
+
unset($data[$id]);
|
531 |
+
}*/
|
532 |
+
}
|
533 |
+
}
|
534 |
+
return $data;
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Retrieves option data for collection
|
539 |
+
* @see SLB_Field_Collection::load_data()
|
540 |
+
*/
|
541 |
+
function load_data() {
|
542 |
+
if ( !$this->data_loaded ) {
|
543 |
+
//Retrieve data
|
544 |
+
$this->data = $this->fetch_data();
|
545 |
+
$this->data_loaded = true;
|
546 |
+
//Check update
|
547 |
+
$this->check_update();
|
548 |
+
}
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Resets option values to their default values
|
553 |
+
* @param bool $hard Reset all options if TRUE (default), Reset only unset options if FALSE
|
554 |
+
*/
|
555 |
+
function reset($hard = true) {
|
556 |
+
$this->load_data();
|
557 |
+
//Reset data
|
558 |
+
if ( $hard ) {
|
559 |
+
$this->data = null;
|
560 |
+
}
|
561 |
+
//Save
|
562 |
+
$this->save();
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Save options data to database
|
567 |
+
*/
|
568 |
+
function save() {
|
569 |
+
$this->normalize_data();
|
570 |
+
update_option($this->get_key(), $this->data);
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Normalize data
|
575 |
+
* Assures that data in collection match items
|
576 |
+
* @uses self::data to reset and save collection data after normalization
|
577 |
+
*/
|
578 |
+
function normalize_data() {
|
579 |
+
$data = array();
|
580 |
+
foreach ( $this->get_items() as $id => $opt ) {
|
581 |
+
$data[$id] = $opt->get_data();
|
582 |
+
}
|
583 |
+
$this->data =& $data;
|
584 |
+
return $data;
|
585 |
+
}
|
586 |
+
|
587 |
+
/* Collection */
|
588 |
+
|
589 |
+
/**
|
590 |
+
* Build key for saving/retrieving data to options table
|
591 |
+
* @return string Key
|
592 |
+
*/
|
593 |
+
function get_key() {
|
594 |
+
return $this->add_prefix($this->get_id());
|
595 |
+
}
|
596 |
+
|
597 |
+
/**
|
598 |
+
* Add option to collection
|
599 |
+
* @uses SLB_Field_Collection::add() to add item
|
600 |
+
* @param string $id Unique item ID
|
601 |
+
* @param array $properties Item properties
|
602 |
+
* @param bool $update (optional) Should item be updated or overwritten (Default: FALSE)
|
603 |
+
* @return SLB_Option Option instance
|
604 |
+
*/
|
605 |
+
function &add($id, $properties = array(), $update = false) {
|
606 |
+
//Create item
|
607 |
+
$args = func_get_args();
|
608 |
+
$ret =& call_user_func_array(array('parent', 'add'), $args);
|
609 |
+
return $ret;
|
610 |
+
}
|
611 |
+
|
612 |
+
/**
|
613 |
+
* Retrieve option value
|
614 |
+
* @uses get_data() to retrieve option data
|
615 |
+
* @param string $option Option ID to retrieve value for
|
616 |
+
* @param string $context (optional) Context for formatting data
|
617 |
+
* @return mixed Option value
|
618 |
+
*/
|
619 |
+
function get_value($option, $context = '') {
|
620 |
+
return $this->get_data($option, $context);
|
621 |
+
}
|
622 |
+
|
623 |
+
/**
|
624 |
+
* Retrieve option value as boolean (true/false)
|
625 |
+
* @uses get_data() to retrieve option data
|
626 |
+
* @param string $option Option ID to retrieve value for
|
627 |
+
* @return bool Option value
|
628 |
+
*/
|
629 |
+
function get_bool($option) {
|
630 |
+
return $this->get_value($option, 'bool');
|
631 |
+
}
|
632 |
+
|
633 |
+
function get_string($option) {
|
634 |
+
return $this->get_value($option, 'string');
|
635 |
+
}
|
636 |
+
|
637 |
+
/**
|
638 |
+
* Retrieve option's default value
|
639 |
+
* @uses get_data() to retrieve option data
|
640 |
+
* @param string $option Option ID to retrieve value for
|
641 |
+
* @param string $context (optional) Context for formatting data
|
642 |
+
* @return mixed Option's default value
|
643 |
+
*/
|
644 |
+
function get_default($option, $context = '') {
|
645 |
+
return $this->get_data($option, $context, false);
|
646 |
+
}
|
647 |
+
|
648 |
+
/* Output */
|
649 |
+
|
650 |
+
function build_init() {
|
651 |
+
if ( $this->build_vars['validate_pre'] ) {
|
652 |
+
$values = $this->validate();
|
653 |
+
if ( $this->build_vars['save_pre'] ) {
|
654 |
+
$this->set_data($values);
|
655 |
+
}
|
656 |
+
}
|
657 |
+
}
|
658 |
+
|
659 |
+
/**
|
660 |
+
* Build array of option values for client output
|
661 |
+
* @return array Associative array of options
|
662 |
+
*/
|
663 |
+
function build_client_output() {
|
664 |
+
$items =& $this->get_items();
|
665 |
+
$out = array();
|
666 |
+
foreach ( $items as $option ) {
|
667 |
+
if ( !$option->get_in_client() )
|
668 |
+
continue;
|
669 |
+
$out[$option->get_id()] = $option->get_data('default');
|
670 |
+
}
|
671 |
+
return $out;
|
672 |
+
}
|
673 |
+
}
|
includes/class.template_tag.php
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Template Tag
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Template
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Template_Tag extends SLB_Component { }
|
includes/class.template_tags.php
ADDED
@@ -0,0 +1,101 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Content Handler Collection
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Content Handler
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Template_Tags extends SLB_Collection_Controller {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
protected $item_type = 'SLB_Template_Tag';
|
13 |
+
|
14 |
+
public $hook_prefix = 'template_tags';
|
15 |
+
|
16 |
+
//Use tag ID as key
|
17 |
+
protected $key_prop = 'get_id';
|
18 |
+
|
19 |
+
//Call $key_prop is a method to be called
|
20 |
+
protected $key_call = true;
|
21 |
+
|
22 |
+
/* Properties */
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Cache properties (key, group)
|
26 |
+
* @var object
|
27 |
+
*/
|
28 |
+
protected $cache_props = null;
|
29 |
+
|
30 |
+
/* Initialization */
|
31 |
+
|
32 |
+
protected function _hooks() {
|
33 |
+
parent::_hooks();
|
34 |
+
$this->util->add_action('init', $this->m('init_defaults'));
|
35 |
+
|
36 |
+
add_action('wp_footer', $this->m('client_output'), $this->util->priority('client_footer_output'));
|
37 |
+
}
|
38 |
+
|
39 |
+
/* Collection Management */
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Add template tag
|
43 |
+
* Accepts properties to create new template tag OR previously-initialized tag instance
|
44 |
+
* @see parent::add()
|
45 |
+
* @param string $id Tag ID
|
46 |
+
* @param array $props Tag properties
|
47 |
+
* @return object Current instance
|
48 |
+
*/
|
49 |
+
public function add($id, $props = array()) {
|
50 |
+
$o = ( is_string($id) ) ? new $this->item_type($id, $props) : $id;
|
51 |
+
//Add to collection
|
52 |
+
return parent::add($o);
|
53 |
+
}
|
54 |
+
|
55 |
+
/* Defaults */
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Initialize default template tags
|
59 |
+
* @param SLB_Template_Tags $tags Tags controller
|
60 |
+
*/
|
61 |
+
public function init_defaults($tags) {
|
62 |
+
$defaults = array (
|
63 |
+
'item' => array (
|
64 |
+
'client_script' => $this->util->get_file_url('template-tags/item/tag.item.js'),
|
65 |
+
),
|
66 |
+
'ui' => array (
|
67 |
+
'client_script' => $this->util->get_file_url('template-tags/ui/tag.ui.js'),
|
68 |
+
),
|
69 |
+
);
|
70 |
+
foreach ( $defaults as $id => $props ) {
|
71 |
+
$tags->add($id, $props);
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/* Output */
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Client output
|
79 |
+
*/
|
80 |
+
public function client_output() {
|
81 |
+
//Stop if not enabled
|
82 |
+
if ( !$this->has_parent() || !$this->get_parent()->is_enabled() ) {
|
83 |
+
return;
|
84 |
+
}
|
85 |
+
$out = array();
|
86 |
+
$out[] = '<!-- SLB-TPTG -->' . PHP_EOL;
|
87 |
+
$code = array();
|
88 |
+
//Load matched handlers
|
89 |
+
foreach ( $this->get() as $id => $tag ) {
|
90 |
+
//Define
|
91 |
+
$params = array(
|
92 |
+
sprintf("'%s'", $id),
|
93 |
+
sprintf("'%s'", $tag->get_client_script('uri')),
|
94 |
+
);
|
95 |
+
$code[] = $this->util->call_client_method('View.add_template_tag_handler', $params, false);
|
96 |
+
}
|
97 |
+
$out[] = $this->util->build_script_element(implode('', $code), 'add_template_tags', true, true);
|
98 |
+
$out[] = '<!-- /SLB-TPTG -->' . PHP_EOL;
|
99 |
+
echo implode('', $out);
|
100 |
+
}
|
101 |
+
}
|
includes/class.theme.php
ADDED
@@ -0,0 +1,103 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Theme
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Themes
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Theme extends SLB_Component {
|
10 |
+
/* Properties */
|
11 |
+
|
12 |
+
protected $props_required = array('name');
|
13 |
+
|
14 |
+
/* Get/Set */
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Retrieve theme's ancestors
|
18 |
+
* @return array Theme's ancestors (sorted by nearest to most distant ancestor)
|
19 |
+
*/
|
20 |
+
public function get_ancestors() {
|
21 |
+
$ret = array();
|
22 |
+
/**
|
23 |
+
* @var SLB_Theme
|
24 |
+
*/
|
25 |
+
$thm = $this;
|
26 |
+
while ( $thm->has_parent() ) {
|
27 |
+
$par = $thm->get_parent();
|
28 |
+
//Add ancestor
|
29 |
+
if ( $par->is_valid() && !in_array($par, $ret, true) ) {
|
30 |
+
$ret[] = $par;
|
31 |
+
}
|
32 |
+
//Get next ancestor
|
33 |
+
$thm = $par;
|
34 |
+
}
|
35 |
+
return $ret;
|
36 |
+
}
|
37 |
+
|
38 |
+
/* Style */
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Set Theme style path
|
42 |
+
* @see `add_style()`
|
43 |
+
*/
|
44 |
+
public function set_client_style($src, $deps = array()) {
|
45 |
+
if ( is_array($src) ) {
|
46 |
+
list($src, $deps) = func_get_arg(0);
|
47 |
+
}
|
48 |
+
return $this->add_style('client', $src, $deps);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get Theme style path
|
53 |
+
* @see `get_style()`
|
54 |
+
*/
|
55 |
+
public function get_client_style($format = null) {
|
56 |
+
return $this->get_style('client', $format);
|
57 |
+
}
|
58 |
+
|
59 |
+
/* Templates */
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Add template file
|
63 |
+
* @see `add_file()`
|
64 |
+
* @param string $handle Template handle
|
65 |
+
* @param string $src Template URI
|
66 |
+
* @return obj Current instance
|
67 |
+
*/
|
68 |
+
protected function add_template($handle, $src) {
|
69 |
+
return $this->add_file('template', $handle, $src);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Retrieve template file
|
74 |
+
* @see `get_file()`
|
75 |
+
* @param string $handle Template handle
|
76 |
+
* @param string $format (optional) Return value format
|
77 |
+
* @return mixed Template file (Default: array of file properties @see `Base_Object::add_file()`)
|
78 |
+
*/
|
79 |
+
protected function get_template($handle, $format = null) {
|
80 |
+
return $this->get_file('template', $handle, $format);
|
81 |
+
}
|
82 |
+
|
83 |
+
/* Layout */
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set theme layout
|
87 |
+
* @uses `add_template()`
|
88 |
+
* @param string $src Layout file URI
|
89 |
+
* @return Current instance
|
90 |
+
*/
|
91 |
+
public function set_layout($src) {
|
92 |
+
return $this->add_template('layout', $src);
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Get layout
|
97 |
+
* @param string $format (optional) Layout data format
|
98 |
+
* @return mixed Theme layout
|
99 |
+
*/
|
100 |
+
public function get_layout($format = null) {
|
101 |
+
return $this->get_template('layout', $format);
|
102 |
+
}
|
103 |
+
}
|
includes/class.themes.php
ADDED
@@ -0,0 +1,225 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Themes Collection
|
5 |
+
* @package Simple Lightbox
|
6 |
+
* @subpackage Themes
|
7 |
+
* @author Archetyped
|
8 |
+
*/
|
9 |
+
class SLB_Themes extends SLB_Collection_Controller {
|
10 |
+
/* Configuration */
|
11 |
+
|
12 |
+
protected $item_type = 'SLB_Theme';
|
13 |
+
|
14 |
+
public $hook_prefix = 'themes';
|
15 |
+
|
16 |
+
protected $key_prop = 'get_id';
|
17 |
+
|
18 |
+
protected $key_call = true;
|
19 |
+
|
20 |
+
/* Properties */
|
21 |
+
|
22 |
+
protected $id_default = null;
|
23 |
+
|
24 |
+
/* Initialization */
|
25 |
+
|
26 |
+
protected function _hooks() {
|
27 |
+
parent::_hooks();
|
28 |
+
//Register themes
|
29 |
+
$this->util->add_action('init', $this->m('init_defaults'), 1);
|
30 |
+
|
31 |
+
//Client output
|
32 |
+
add_action('wp_footer', $this->m('client_output'), $this->util->priority('client_footer_output'));
|
33 |
+
}
|
34 |
+
|
35 |
+
protected function _options() {
|
36 |
+
$opts = array (
|
37 |
+
'items' => array (
|
38 |
+
'theme_default' => array (
|
39 |
+
'title' => __('Theme', 'simple-lightbox'),
|
40 |
+
'default' => $this->get_default_id(),
|
41 |
+
'group' => array('ui', 0),
|
42 |
+
'parent' => 'option_select',
|
43 |
+
'options' => $this->m('opt_get_field_values'),
|
44 |
+
'in_client' => true
|
45 |
+
),
|
46 |
+
)
|
47 |
+
);
|
48 |
+
|
49 |
+
parent::_options($opts);
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Add default themes
|
54 |
+
* @param SLB_Themes $themes Themes controller
|
55 |
+
*/
|
56 |
+
function init_defaults($themes) {
|
57 |
+
$defaults = array (
|
58 |
+
$this->get_default_id() => array (
|
59 |
+
'name' => __('Default (Light)', 'simple-lightbox'),
|
60 |
+
'layout' => $this->util->get_file_url('themes/default/layout.html'),
|
61 |
+
'client_script' => $this->util->get_file_url('themes/default/client.js'),
|
62 |
+
'client_style' => $this->util->get_file_url('themes/default/css/style.css'),
|
63 |
+
),
|
64 |
+
$this->add_prefix('black') => array (
|
65 |
+
'name' => __('Default (Dark)', 'simple-lightbox'),
|
66 |
+
'parent' => $this->get_default_id(),
|
67 |
+
'client_style' => $this->util->get_file_url('themes/black/css/style.css'),
|
68 |
+
),
|
69 |
+
);
|
70 |
+
|
71 |
+
foreach ( $defaults as $id => $props ) {
|
72 |
+
$themes->add($id, $props);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
/* Collection management */
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Add theme
|
80 |
+
* Accepts properties to create new theme or previously-created theme instance
|
81 |
+
* @uses parent::add()
|
82 |
+
* @param string|object $id Theme ID (or Theme object)
|
83 |
+
* @param array $props Theme properties
|
84 |
+
* @return object Current instance
|
85 |
+
*/
|
86 |
+
public function add($id, $props = array()) {
|
87 |
+
//Prepare parent
|
88 |
+
if ( isset($props['parent']) && !($props['parent'] instanceof $this->item_type) ) {
|
89 |
+
$pid = $props['parent'];
|
90 |
+
$items = $this->get();
|
91 |
+
if ( isset($items[$pid]) ) {
|
92 |
+
$props['parent'] = $items[$pid];
|
93 |
+
}
|
94 |
+
}
|
95 |
+
$o = ( is_string($id) ) ? new $this->item_type($id, $props) : $id;
|
96 |
+
//Add to collection
|
97 |
+
return parent::add($o);
|
98 |
+
}
|
99 |
+
|
100 |
+
/* Helpers */
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Retrieve default theme ID
|
104 |
+
* @uses `$id_default`
|
105 |
+
* @return string Default theme ID
|
106 |
+
*/
|
107 |
+
public function get_default_id() {
|
108 |
+
if ( !$this->id_default ) {
|
109 |
+
$this->id_default = $this->add_prefix('default');
|
110 |
+
}
|
111 |
+
return $this->id_default;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Retrieve currently-selected theme
|
116 |
+
* @return SLB_Theme Selected theme
|
117 |
+
*/
|
118 |
+
protected function get_selected() {
|
119 |
+
//Get themes
|
120 |
+
$thms = $this->get();
|
121 |
+
//Retrieve currently-selected theme
|
122 |
+
$id = $this->options->get_value('theme_default');
|
123 |
+
if ( !isset($thms[$id]) ) {
|
124 |
+
$id = $this->get_default_id();
|
125 |
+
}
|
126 |
+
return $thms[$id];
|
127 |
+
}
|
128 |
+
|
129 |
+
/* Output */
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Client output
|
133 |
+
*/
|
134 |
+
public function client_output() {
|
135 |
+
//Stop if not enabled
|
136 |
+
if ( !$this->has_parent() || !$this->get_parent()->is_enabled() ) {
|
137 |
+
return;
|
138 |
+
}
|
139 |
+
|
140 |
+
//Theme
|
141 |
+
/**
|
142 |
+
* @var SLB_Theme
|
143 |
+
*/
|
144 |
+
$thm = $this->get_selected();
|
145 |
+
|
146 |
+
//Process theme ancestors
|
147 |
+
$thms = array_reverse($thm->get_ancestors());
|
148 |
+
$thms[] = $thm;
|
149 |
+
|
150 |
+
$id_fmt = 'add_theme_%s';
|
151 |
+
$out = array();
|
152 |
+
$out[] = '<!-- SLB-THM -->' . PHP_EOL;
|
153 |
+
$code = array();
|
154 |
+
|
155 |
+
//Build output for each theme
|
156 |
+
foreach ( $thms as $thm ) {
|
157 |
+
//Setup client parameters
|
158 |
+
$params = array(
|
159 |
+
sprintf("'%s'", $thm->get_id()),
|
160 |
+
);
|
161 |
+
//Theme properties
|
162 |
+
$thm_props = array(
|
163 |
+
'name' => $thm->get_name(),
|
164 |
+
'parent' => ( $thm->has_parent() ) ? $thm->get_parent()->get_id() : '',
|
165 |
+
);
|
166 |
+
/* Optional properties */
|
167 |
+
//Layout
|
168 |
+
$uri = $thm->get_layout('uri');
|
169 |
+
if ( !empty($uri) ) {
|
170 |
+
$thm_props['layout_uri'] = $uri;
|
171 |
+
}
|
172 |
+
//Script
|
173 |
+
$script = $thm->get_client_script('uri');
|
174 |
+
if ( !empty($script) ) {
|
175 |
+
$thm_props['client_script'] = $script;
|
176 |
+
}
|
177 |
+
//Style
|
178 |
+
$style = $thm->get_client_style('uri');
|
179 |
+
if ( !empty($style) ) {
|
180 |
+
$thm_props['client_style'] = $style;
|
181 |
+
}
|
182 |
+
//Add properties to parameters
|
183 |
+
$params[] = json_encode($thm_props);
|
184 |
+
|
185 |
+
//Add theme to client
|
186 |
+
$code[] = $this->util->call_client_method('View.add_theme', $params, false);
|
187 |
+
}
|
188 |
+
|
189 |
+
$out[] = $this->util->build_script_element(implode('', $code), 'add_themes', true, true);
|
190 |
+
$out[] = '<!-- /SLB-THM -->' . PHP_EOL;
|
191 |
+
echo implode('', $out);
|
192 |
+
}
|
193 |
+
|
194 |
+
/* Options */
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Retrieve themes for use in option field
|
198 |
+
* @uses self::theme_default
|
199 |
+
* @return array Theme options
|
200 |
+
*/
|
201 |
+
public function opt_get_field_values() {
|
202 |
+
//Get themes
|
203 |
+
$items = $this->get();
|
204 |
+
$d = $this->get_default_id();
|
205 |
+
//Pop out default theme
|
206 |
+
if ( isset($items[$d]) ) {
|
207 |
+
$itm_d = $items[$d];
|
208 |
+
unset($items[$d]);
|
209 |
+
}
|
210 |
+
|
211 |
+
//Sort themes by name
|
212 |
+
uasort($items, create_function('$a,$b', 'return strcmp($a->get_name(), $b->get_name());'));
|
213 |
+
|
214 |
+
//Insert default theme at top of array
|
215 |
+
if ( isset($itm_d) ) {
|
216 |
+
$items = array( $d => $itm_d ) + $items;
|
217 |
+
}
|
218 |
+
|
219 |
+
//Build options
|
220 |
+
foreach ( $items as $item ) {
|
221 |
+
$items[$item->get_id()] = $item->get_name();
|
222 |
+
}
|
223 |
+
return $items;
|
224 |
+
}
|
225 |
+
}
|
includes/class.utilities.php
CHANGED
@@ -10,12 +10,47 @@
|
|
10 |
Â
*/
|
11 |
Â
class SLB_Utilities {
|
12 |
Â
|
13 |
-
|
14 |
-
$this->__construct();
|
15 |
-
}
|
16 |
Â
|
17 |
-
|
18 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
19 |
Â
}
|
20 |
Â
|
21 |
Â
/**
|
@@ -24,15 +59,492 @@ class SLB_Utilities {
|
|
24 |
Â
* @param string $method Name of method
|
25 |
Â
* @return array Callback array
|
26 |
Â
*/
|
27 |
-
function
|
28 |
-
if ( $obj
|
29 |
-
$
|
30 |
-
|
31 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
32 |
Â
}
|
33 |
Â
|
34 |
Â
/* Helper Functions */
|
35 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
36 |
Â
/*-** WP **-*/
|
37 |
Â
|
38 |
Â
/**
|
@@ -59,14 +571,220 @@ class SLB_Utilities {
|
|
59 |
Â
return true;
|
60 |
Â
}
|
61 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
62 |
Â
/*-** Request **-*/
|
63 |
Â
|
64 |
Â
/**
|
65 |
-
* Checks
|
66 |
Â
* @param string $filename Filename to check for
|
67 |
Â
* @return bool TRUE if current page matches specified filename, FALSE otherwise
|
68 |
Â
*/
|
69 |
-
function
|
70 |
Â
return ( $filename == basename( $_SERVER['SCRIPT_NAME'] ) );
|
71 |
Â
}
|
72 |
Â
|
@@ -76,112 +794,304 @@ class SLB_Utilities {
|
|
76 |
Â
*/
|
77 |
Â
function is_admin_management_page() {
|
78 |
Â
return ( is_admin()
|
79 |
-
&& ( $this->
|
80 |
-
|| ( $this->
|
81 |
Â
&& isset($_GET['page'])
|
82 |
Â
&& strpos($_GET['page'], 'cnr') === 0 )
|
83 |
Â
)
|
84 |
Â
);
|
85 |
Â
}
|
86 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
87 |
Â
/**
|
88 |
Â
* Joins and normalizes the slashes in the paths passed to method
|
89 |
Â
* All forward/back slashes are converted to forward slashes
|
90 |
Â
* Multiple path segments can be passed as additional argments
|
91 |
Â
* @param string $path Path to normalize
|
92 |
-
* @param bool $trailing_slash (optional) Whether or not normalized path should have a trailing slash or not (Default: FALSE)
|
93 |
-
* If
|
Â
|
|
94 |
Â
*/
|
95 |
Â
function normalize_path($path, $trailing_slash = false) {
|
96 |
Â
$sl_f = '/';
|
97 |
Â
$sl_b = '\\';
|
98 |
Â
$parts = func_get_args();
|
Â
|
|
Â
|
|
99 |
Â
if ( func_num_args() > 1 ) {
|
100 |
-
|
101 |
-
|
102 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
103 |
Â
array_pop($parts);
|
104 |
-
|
105 |
-
$
|
Â
|
|
Â
|
|
Â
|
|
106 |
Â
}
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
$first = !$first;
|
121 |
-
else
|
122 |
-
continue;
|
123 |
-
//Add back leading slash if necessary
|
124 |
-
if ( $part[0] == $sl_f || $part[0] == $sl_b )
|
125 |
-
$parts[$key] = $sl_f . $parts[$key];
|
126 |
-
|
127 |
Â
}
|
128 |
Â
}
|
Â
|
|
129 |
Â
//Join path parts together
|
130 |
Â
$parts = implode($sl_b, $parts);
|
131 |
Â
$parts = str_replace($sl_b, $sl_f, $parts);
|
132 |
Â
//Add trailing slash (if necessary)
|
133 |
Â
if ( $trailing_slash )
|
134 |
-
$parts
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
135 |
Â
return $parts;
|
136 |
Â
}
|
137 |
Â
|
138 |
Â
/**
|
139 |
Â
* Returns URL of file (assumes that it is in plugin directory)
|
140 |
Â
* @param string $file name of file get URL
|
141 |
-
* @return string File
|
142 |
Â
*/
|
143 |
Â
function get_file_url($file) {
|
144 |
-
if (is_string($file) && '' != trim($file)) {
|
145 |
-
$file = $this->normalize_path($this->get_url_base(), $file);
|
146 |
Â
}
|
147 |
Â
return $file;
|
148 |
Â
}
|
149 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
150 |
Â
/**
|
151 |
Â
* Retrieves file extension
|
152 |
Â
* @param string $file file name/path
|
Â
|
|
153 |
Â
* @return string File's extension
|
154 |
Â
*/
|
155 |
-
function get_file_extension($file) {
|
156 |
Â
$ret = '';
|
157 |
Â
$sep = '.';
|
158 |
-
if ( is_string($
|
Â
|
|
Â
|
|
159 |
Â
$ret = substr($file, $rpos + 1);
|
Â
|
|
Â
|
|
160 |
Â
return $ret;
|
161 |
Â
}
|
162 |
Â
|
163 |
Â
/**
|
164 |
Â
* Checks if file has specified extension
|
Â
|
|
165 |
Â
* @param string $file File name/path
|
166 |
-
* @param string $extension File ending to check $file for
|
Â
|
|
167 |
Â
* @return bool TRUE if file has extension
|
168 |
Â
*/
|
169 |
-
function has_file_extension($file, $extension) {
|
170 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
171 |
Â
}
|
172 |
Â
|
173 |
Â
/**
|
174 |
Â
* Retrieve base URL for plugin-specific files
|
Â
|
|
Â
|
|
175 |
Â
* @return string Base URL
|
176 |
Â
*/
|
177 |
Â
function get_url_base() {
|
178 |
Â
static $url_base = '';
|
179 |
Â
if ( '' == $url_base ) {
|
180 |
-
$url_base = $this->normalize_path(
|
181 |
Â
}
|
182 |
Â
return $url_base;
|
183 |
Â
}
|
184 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
185 |
Â
function get_path_base() {
|
186 |
Â
static $path_base = '';
|
187 |
Â
if ( '' == $path_base ) {
|
@@ -189,23 +1099,140 @@ class SLB_Utilities {
|
|
189 |
Â
}
|
190 |
Â
return $path_base;
|
191 |
Â
}
|
192 |
-
|
193 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
194 |
Â
static $plugin_dir = '';
|
195 |
Â
if ( '' == $plugin_dir ) {
|
196 |
Â
$plugin_dir = str_replace($this->normalize_path(WP_PLUGIN_DIR), '', $this->normalize_path(dirname(dirname(__FILE__))));
|
197 |
Â
}
|
Â
|
|
Â
|
|
198 |
Â
return $plugin_dir;
|
199 |
Â
}
|
200 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
201 |
Â
function get_plugin_base_file() {
|
202 |
-
$file = '
|
203 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
204 |
Â
}
|
205 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
206 |
Â
function get_plugin_base_name() {
|
207 |
-
$
|
208 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
209 |
Â
}
|
210 |
Â
|
211 |
Â
/**
|
@@ -246,6 +1273,22 @@ class SLB_Utilities {
|
|
246 |
Â
|
247 |
Â
/*-** General **-*/
|
248 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
249 |
Â
/**
|
250 |
Â
* Checks if a property exists in a class or object
|
251 |
Â
* (Compatibility method for PHP 4
|
@@ -284,6 +1327,60 @@ class SLB_Utilities {
|
|
284 |
Â
}
|
285 |
Â
}
|
286 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
287 |
Â
/**
|
288 |
Â
* Merges 1 or more arrays together
|
289 |
Â
* Methodology
|
@@ -295,7 +1392,6 @@ class SLB_Utilities {
|
|
295 |
Â
* - Merge item in base array with current item based on key name
|
296 |
Â
* - If the current item's value AND the corresponding item in the base array are BOTH arrays, recursively merge the the arrays
|
297 |
Â
* - If the current item's value OR the corresponding item in the base array is NOT an array, current item overwrites base item
|
298 |
-
* @todo Append numerical elements (as opposed to overwriting element at same index in base array)
|
299 |
Â
* @param array Variable number of arrays
|
300 |
Â
* @param array $arr1 Default array
|
301 |
Â
* @return array Merged array
|
@@ -303,24 +1399,33 @@ class SLB_Utilities {
|
|
303 |
Â
function array_merge_recursive_distinct($arr1) {
|
304 |
Â
//Get all arrays passed to function
|
305 |
Â
$args = func_get_args();
|
306 |
-
if (empty($args))
|
307 |
Â
return false;
|
Â
|
|
Â
|
|
Â
|
|
308 |
Â
//Set first array as base array
|
309 |
Â
$merged = $args[0];
|
310 |
Â
//Iterate through arrays to merge
|
311 |
Â
$arg_length = count($args);
|
312 |
-
for ($x = 1; $x < $arg_length; $x++) {
|
313 |
Â
//Skip if argument is not an array (only merge arrays)
|
314 |
-
if (!is_array($args[$x]))
|
315 |
Â
continue;
|
316 |
Â
//Iterate through argument items
|
317 |
-
foreach ($args[$x] as $key => $val) {
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
324 |
Â
}
|
325 |
Â
}
|
326 |
Â
return $merged;
|
@@ -375,6 +1480,13 @@ class SLB_Utilities {
|
|
375 |
Â
return $item;
|
376 |
Â
}
|
377 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
378 |
Â
function get_array_path($attribute = '', $format = null) {
|
379 |
Â
//Formatted value
|
380 |
Â
$fmtd = '';
|
@@ -440,6 +1552,34 @@ class SLB_Utilities {
|
|
440 |
Â
return $path;
|
441 |
Â
}
|
442 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
443 |
Â
/**
|
444 |
Â
* Builds attribute string for HTML element
|
445 |
Â
* @param array $attr Attributes
|
@@ -460,6 +1600,11 @@ class SLB_Utilities {
|
|
460 |
Â
return $ret;
|
461 |
Â
}
|
462 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
463 |
Â
/**
|
464 |
Â
* Generate external stylesheet element
|
465 |
Â
* @param $url Stylesheet URL
|
@@ -470,6 +1615,45 @@ class SLB_Utilities {
|
|
470 |
Â
return $this->build_html_element(array('tag' => 'link', 'wrap' => false, 'attributes' => $attributes));
|
471 |
Â
}
|
472 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
473 |
Â
/**
|
474 |
Â
* Generate external script element
|
475 |
Â
* @param $url Script URL
|
@@ -477,7 +1661,7 @@ class SLB_Utilities {
|
|
477 |
Â
*/
|
478 |
Â
function build_ext_script_element($url = '') {
|
479 |
Â
$attributes = array('src' => $url, 'type' => 'text/javascript');
|
480 |
-
return $this->build_html_element(array('tag' => 'script', 'attributes' => $attributes));
|
481 |
Â
}
|
482 |
Â
|
483 |
Â
/**
|
@@ -495,9 +1679,20 @@ class SLB_Utilities {
|
|
495 |
Â
$el_start = '<';
|
496 |
Â
$el_end = '>';
|
497 |
Â
$el_close = '/';
|
498 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
499 |
Â
$content = trim($content);
|
500 |
Â
|
Â
|
|
501 |
Â
if ( !$wrap && strlen($content) > 0 )
|
502 |
Â
$wrap = true;
|
503 |
Â
|
@@ -542,23 +1737,24 @@ class SLB_Utilities {
|
|
542 |
Â
//Get last submenu added
|
543 |
Â
$parent = $this->get_submenu_parent_file($parent);
|
544 |
Â
if ( isset($submenu[$parent]) ) {
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
Â
}
|
560 |
Â
}
|
561 |
Â
}
|
Â
|
|
562 |
Â
|
563 |
Â
return $hookname;
|
564 |
Â
}
|
@@ -638,4 +1834,70 @@ class SLB_Utilities {
|
|
638 |
Â
$parent = $_wp_real_parent_file[$parent];
|
639 |
Â
return $parent;
|
640 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
641 |
Â
}
|
10 |
Â
*/
|
11 |
Â
class SLB_Utilities {
|
12 |
Â
|
13 |
+
/* Properties */
|
Â
|
|
Â
|
|
14 |
Â
|
15 |
+
/**
|
16 |
+
* Instance parent
|
17 |
+
* @var object
|
18 |
+
*/
|
19 |
+
var $parent = null;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Default plugin headers
|
23 |
+
* @var array
|
24 |
+
*/
|
25 |
+
private $plugin_headers = array (
|
26 |
+
'Name' => 'Plugin Name',
|
27 |
+
'PluginURI' => 'Plugin URI',
|
28 |
+
'Version' => 'Version',
|
29 |
+
'Description' => 'Description',
|
30 |
+
'Author' => 'Author',
|
31 |
+
'AuthorURI' => 'Author URI',
|
32 |
+
'TextDomain' => 'Text Domain',
|
33 |
+
'DomainPath' => 'Domain Path',
|
34 |
+
'Network' => 'Network',
|
35 |
+
);
|
36 |
+
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Standard hook priorities
|
40 |
+
* @var array
|
41 |
+
*/
|
42 |
+
private $priorities = array (
|
43 |
+
'high' => 1,
|
44 |
+
'low' => 99,
|
45 |
+
'safe' => 15,
|
46 |
+
'client_footer_output' => 25,
|
47 |
+
);
|
48 |
+
|
49 |
+
/* Constructors */
|
50 |
+
|
51 |
+
function __construct(&$obj) {
|
52 |
+
if ( is_object($obj) )
|
53 |
+
$this->parent =& $obj;
|
54 |
Â
}
|
55 |
Â
|
56 |
Â
/**
|
59 |
Â
* @param string $method Name of method
|
60 |
Â
* @return array Callback array
|
61 |
Â
*/
|
62 |
+
function m($obj, $method = '') {
|
63 |
+
if ( is_string($obj) ) {
|
64 |
+
$method = $obj;
|
65 |
+
$obj = null;
|
66 |
+
}
|
67 |
+
if ( !is_object($obj) && isset($this) ) {
|
68 |
+
$obj = $this;
|
69 |
+
}
|
70 |
+
$cb = array($obj, $method);
|
71 |
+
return $cb;
|
72 |
Â
}
|
73 |
Â
|
74 |
Â
/* Helper Functions */
|
75 |
Â
|
76 |
+
/*-** Prefix **-*/
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Get valid separator
|
80 |
+
* @param string $sep (optional) Separator supplied
|
81 |
+
* @return string Separator
|
82 |
+
*/
|
83 |
+
function get_sep($sep = false) {
|
84 |
+
if ( is_null($sep) )
|
85 |
+
$sep = '';
|
86 |
+
return ( is_string($sep) ) ? $sep : '_';
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Retrieve class prefix (with separator if set)
|
91 |
+
* @param bool|string $sep Separator to append to class prefix (Default: no separator)
|
92 |
+
* @return string Class prefix
|
93 |
+
*/
|
94 |
+
function get_prefix($sep = null) {
|
95 |
+
$sep = $this->get_sep($sep);
|
96 |
+
$prefix = ( !empty($this->parent->prefix) ) ? $this->parent->prefix . $sep : '';
|
97 |
+
return $prefix;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Check if a string is prefixed
|
102 |
+
* @param string $text Text to check for prefix
|
103 |
+
* @param string $sep (optional) Separator used
|
104 |
+
*/
|
105 |
+
function has_prefix($text, $sep = null) {
|
106 |
+
return ( !empty($text) && stripos($text, $this->get_prefix($sep)) === 0 );
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Prepend plugin prefix to some text
|
111 |
+
* @param string $text Text to add to prefix
|
112 |
+
* @param string $sep (optional) Text used to separate prefix and text
|
113 |
+
* @param bool $once (optional) Whether to add prefix to text that already contains a prefix or not
|
114 |
+
* @return string Text with prefix prepended
|
115 |
+
*/
|
116 |
+
function add_prefix($text, $sep = '_', $once = true) {
|
117 |
+
if ( $once && $this->has_prefix($text, $sep) )
|
118 |
+
return $text;
|
119 |
+
return $this->get_prefix($sep) . $text;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Prepend uppercased plugin prefix to some text
|
124 |
+
* @param string $text Text to add to prefix
|
125 |
+
* @param string $sep (optional) Text used to separate prefix and text
|
126 |
+
* @param bool $once (optional) Whether to add prefix to text that already contains a prefix or not
|
127 |
+
* @return string Text with prefix prepended
|
128 |
+
*/
|
129 |
+
function add_prefix_uc($text, $sep = '_', $once = true) {
|
130 |
+
$args = func_get_args();
|
131 |
+
$var = call_user_func_array($this->m($this, 'add_prefix'), $args);
|
132 |
+
$pre = $this->get_prefix();
|
133 |
+
return str_replace($pre . $sep, strtoupper($pre) . $sep, $var);
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Add prefix to variable reference
|
138 |
+
* Updates actual variable rather than return value
|
139 |
+
* @uses add_prefix() to add prefix to variable
|
140 |
+
* @param string $var Variable to add prefix to
|
141 |
+
* @param string $sep (optional) Separator text
|
142 |
+
* @param bool $once (optional) Add prefix only once
|
143 |
+
* @return void
|
144 |
+
*/
|
145 |
+
function add_prefix_ref(&$var, $sep = null, $once = true) {
|
146 |
+
$args = func_get_args();
|
147 |
+
$var = call_user_func_array($this->m($this, 'add_prefix'), $args);
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Remove prefix from specified string
|
152 |
+
* @param string $text String to remove prefix from
|
153 |
+
* @param string $sep (optional) Separator used with prefix
|
154 |
+
*/
|
155 |
+
function remove_prefix($text, $sep = '_') {
|
156 |
+
if ( $this->has_prefix($text,$sep) )
|
157 |
+
$text = substr($text, strlen($this->get_prefix($sep)));
|
158 |
+
return $text;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Returns Database prefix for plugin-related DB Tables
|
163 |
+
* @return string Database prefix
|
164 |
+
*/
|
165 |
+
function get_db_prefix() {
|
166 |
+
global $wpdb;
|
167 |
+
return $wpdb->prefix . $this->get_prefix('_');
|
168 |
+
}
|
169 |
+
|
170 |
+
/*-** Priority **-*/
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Retrieve standard priority
|
174 |
+
* @var string $id Priority ID to retrieve
|
175 |
+
* @return int Priority
|
176 |
+
*/
|
177 |
+
public function priority($id = null) {
|
178 |
+
$pri = 10;
|
179 |
+
if ( !is_null($id) && array_key_exists($id, $this->priorities) ) {
|
180 |
+
$pri = $this->priorities[$id];
|
181 |
+
}
|
182 |
+
return $pri;
|
183 |
+
}
|
184 |
+
|
185 |
+
/* Wrapped Values */
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Returns validated object of start/end wrapper values
|
189 |
+
* @param string|array $start Start text (Can also be array defining start & end values)
|
190 |
+
* @param string $end (optional) End text
|
191 |
+
* If $end not defined, then $start is used
|
192 |
+
* @return obj Wrapper
|
193 |
+
*/
|
194 |
+
function get_wrapper($start = null, $end = null) {
|
195 |
+
//Return pre-built wrapper
|
196 |
+
if ( is_object($start) && isset($start->start) && isset($start->end) )
|
197 |
+
return $start;
|
198 |
+
//Default wrapper
|
199 |
+
if ( is_null($start) && is_null($end) )
|
200 |
+
$start = array('[', ']');
|
201 |
+
$wrapper = compact('start', 'end');
|
202 |
+
if ( is_array($start) && count($start) > 1 ) {
|
203 |
+
$wrapper['start'] = $start[0];
|
204 |
+
$wrapper['end'] = $start[1];
|
205 |
+
}
|
206 |
+
if ( !is_string($wrapper['start']) || empty($wrapper['start'] ) )
|
207 |
+
$wrapper['start'] = '';
|
208 |
+
if ( !is_string($wrapper['end']) || empty($wrapper['end']) )
|
209 |
+
$wrapper['end'] = $wrapper['start'];
|
210 |
+
|
211 |
+
return (object) $wrapper;
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Check if text is wrapped by specified character(s)
|
216 |
+
* @uses this->get_wrapper() to Validate wrapper text
|
217 |
+
* @param string $text Text to check
|
218 |
+
* @param string|array $start (optional) Start text (Array defines both start/end text)
|
219 |
+
* @param string $end (optional) End text
|
220 |
+
*/
|
221 |
+
function has_wrapper($text, $start = null, $end = null) {
|
222 |
+
if ( !is_string($text) || empty($text) )
|
223 |
+
return false;
|
224 |
+
//Validate wrapper)
|
225 |
+
$w = $this->get_wrapper($start, $end);
|
226 |
+
|
227 |
+
//Check for wrapper
|
228 |
+
return ( substr($text, 0, 1) == $w->start && substr($text, -1, 1) == $w->end ) ? true : false;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Remove wrapper from specified text
|
233 |
+
* @uses this->has_wrapper() to check if text is wrapped
|
234 |
+
* @uses this->get_wrapper() to retrieve wrapper object
|
235 |
+
* @param string $text Text to check
|
236 |
+
* @param string|array $start (optional) Start text (Array defines both start/end text)
|
237 |
+
* @param string $end (optional) End text
|
238 |
+
* @return string Unwrapped text
|
239 |
+
*/
|
240 |
+
function remove_wrapper($text, $start = null, $end = null) {
|
241 |
+
if ( $this->has_wrapper($text, $start, $end) ) {
|
242 |
+
$w = $this->get_wrapper($start, $end);
|
243 |
+
$text = substr($text, strlen($w->start), strlen($text) - strlen($w->start) - strlen($w->end) );
|
244 |
+
}
|
245 |
+
|
246 |
+
return $text;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Add wrapper to specified text
|
251 |
+
* @uses this->get_wrapper() to retrieve wrapper object
|
252 |
+
* @param string $text Text to wrap
|
253 |
+
* @param string|array $start (optional) Start text (Array defines both start/end text)
|
254 |
+
* @param string $end (optional) End text
|
255 |
+
* @param bool $once (optional) Whether to wrap text only once (Default: TRUE)
|
256 |
+
* @return string Wrapped text
|
257 |
+
*/
|
258 |
+
function add_wrapper($text, $start = null, $end = null, $once = true) {
|
259 |
+
$w = $this->get_wrapper($start, $end);
|
260 |
+
if ( !$once || !$this->has_wrapper($text, $w) )
|
261 |
+
$text = $w->start . $text . $w->end;
|
262 |
+
return $text;
|
263 |
+
}
|
264 |
+
|
265 |
+
/*-** Client **-*/
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Parses client files array
|
269 |
+
* > Adds ID property (prefixed file key)
|
270 |
+
* > Parses and validates internal dependencies
|
271 |
+
* > Converts properties array to object
|
272 |
+
* Properties
|
273 |
+
* > file (string|array): File name (string) or callback (array) to retrieve file name
|
274 |
+
* > deps (array) [optional]: Dependencies
|
275 |
+
* > Values wrapped in square brackets (`[` & `]`) are internal files
|
276 |
+
* > callback (string|array) [optional]: Global callback to determine whether file should be loaded
|
277 |
+
* > Values wrapped in square brackets (`[` & `]`) are internal methods (of parent object)
|
278 |
+
* > context (array) [optional]: Context(s) in which to load the file
|
279 |
+
* Acceptable values
|
280 |
+
* > string: Context name
|
281 |
+
* > array: Context name + callback (both must return TRUE to load file)
|
282 |
+
* > Callback follows same pattern as `callback` member
|
283 |
+
* @param array $files Files array
|
284 |
+
* @return object Client files
|
285 |
+
*/
|
286 |
+
function parse_client_files($files, $type = 'scripts') {
|
287 |
+
if ( is_array($files) && !empty($files) ) {
|
288 |
+
//Defaults
|
289 |
+
$defaults = array(
|
290 |
+
'file' => null,
|
291 |
+
'deps' => array(),
|
292 |
+
'callback' => null,
|
293 |
+
'context' => array(),
|
294 |
+
'enqueue' => true,
|
295 |
+
);
|
296 |
+
switch ( $type ) {
|
297 |
+
case 'styles':
|
298 |
+
$defaults['media'] = 'all';
|
299 |
+
break;
|
300 |
+
default:
|
301 |
+
$defaults['in_footer'] = false;
|
302 |
+
}
|
303 |
+
//Iterate through files
|
304 |
+
foreach ( $files as $h => $p ) {
|
305 |
+
unset($file, $cb, $ctxs, $ctx);
|
306 |
+
//Set ID
|
307 |
+
$p['id'] = $this->add_prefix($h);
|
308 |
+
//Type Validation
|
309 |
+
foreach ( $defaults as $m => $d ) {
|
310 |
+
//Check if value requires validation
|
311 |
+
if ( !is_array($d) || !isset($p[$m]) || is_array($p[$m]) )
|
312 |
+
continue;
|
313 |
+
//Wrap value in array or destroy it
|
314 |
+
if ( is_scalar($p[$m]) )
|
315 |
+
$p[$m] = array($p[$m]);
|
316 |
+
else
|
317 |
+
unset($p[$m]);
|
318 |
+
}
|
319 |
+
|
320 |
+
$p = array_merge($defaults, $p);
|
321 |
+
|
322 |
+
/* File name */
|
323 |
+
|
324 |
+
//Validate file
|
325 |
+
$file =& $p['file'];
|
326 |
+
|
327 |
+
//Determine if filename or callback
|
328 |
+
if ( !$this->is_file($file) )
|
329 |
+
$file = $this->parse_client_file_callback($file);
|
330 |
+
//Remove invalid file and move on to next
|
331 |
+
if ( empty($file) ) {
|
332 |
+
unset($files[$h]);
|
333 |
+
continue;
|
334 |
+
}
|
335 |
+
|
336 |
+
/* Dependencies */
|
337 |
+
|
338 |
+
//Format internal dependencies
|
339 |
+
foreach ( $p['deps'] as $idx => $dep ) {
|
340 |
+
if ( $this->has_wrapper($dep) ) {
|
341 |
+
$dep = $this->remove_wrapper($dep);
|
342 |
+
$p['deps'][$idx] = $this->add_prefix($dep);
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
/* Context */
|
347 |
+
|
348 |
+
//Validate callback
|
349 |
+
$cb =& $p['callback'];
|
350 |
+
if ( !is_null($cb) ) {
|
351 |
+
$cb = $this->parse_client_file_callback($cb);
|
352 |
+
//Remove files with invalid callbacks (will never be loaded)
|
353 |
+
if ( is_null($cb) ) {
|
354 |
+
unset($files[$h]);
|
355 |
+
continue;
|
356 |
+
}
|
357 |
+
}
|
358 |
+
|
359 |
+
//Validate contexts
|
360 |
+
$ctxs =& $p['context'];
|
361 |
+
$ctxs = array_unique($ctxs);
|
362 |
+
$has_contexts = ( count($ctxs) > 0 ) ? true : false;
|
363 |
+
foreach ( $ctxs as $idx => $ctx ) {
|
364 |
+
//Convert to array
|
365 |
+
$ctx = array_values( array_slice( (array) $ctx, 0, 2 ) );
|
366 |
+
switch ( count($ctx) ) {
|
367 |
+
case 1 :
|
368 |
+
//Simple context
|
369 |
+
$ctx = $ctx[0];
|
370 |
+
break;
|
371 |
+
case 2 :
|
372 |
+
//Context + Callback
|
373 |
+
$ctx[1] = $this->parse_client_file_callback($ctx[1]);
|
374 |
+
if ( !is_null($ctx[1]) ) {
|
375 |
+
break;
|
376 |
+
}
|
377 |
+
//Continue to default case if callback is invalid
|
378 |
+
default :
|
379 |
+
//Context is invalid
|
380 |
+
$ctx = false;
|
381 |
+
break;
|
382 |
+
}
|
383 |
+
|
384 |
+
//Remove invalid contexts
|
385 |
+
if ( empty($ctx) ) {
|
386 |
+
unset($ctxs[$idx]);
|
387 |
+
} else {
|
388 |
+
$ctxs[$idx] = $ctx;
|
389 |
+
}
|
390 |
+
}
|
391 |
+
//Remove file if all specified contexts invalid (no context is OK)
|
392 |
+
if ( $has_contexts && empty($ctxs) ) {
|
393 |
+
unset($files[$h]);
|
394 |
+
continue;
|
395 |
+
}
|
396 |
+
$ctxs = array_values($ctxs);
|
397 |
+
|
398 |
+
/* Finalize Properties */
|
399 |
+
|
400 |
+
//Convert properties to object
|
401 |
+
$files[$h] = (object) $p;
|
402 |
+
}
|
403 |
+
}
|
404 |
+
//Cast to object before returning
|
405 |
+
$files = (object) $files;
|
406 |
+
return $files;
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* Parses callbacks set for client files
|
411 |
+
* @param string $callback Callback value
|
412 |
+
* > Values wrapped in square brackets (`[` & `]`) are internal methods (of parent object)
|
413 |
+
* @return callback|null Validated callback (NULL if callback is invalid)
|
414 |
+
*/
|
415 |
+
function parse_client_file_callback($callback) {
|
416 |
+
if ( $this->has_wrapper($callback) ) {
|
417 |
+
$callback = $this->m($this->parent, $this->remove_wrapper($callback));
|
418 |
+
}
|
419 |
+
if ( !is_callable($callback) )
|
420 |
+
$callback = null;
|
421 |
+
return $callback;
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Build JS client object
|
426 |
+
* @param string (optional) $path Additional object path
|
427 |
+
* @return string Client object
|
428 |
+
*/
|
429 |
+
function get_client_object($path = null) {
|
430 |
+
$obj = strtoupper($this->get_prefix());
|
431 |
+
if ( !empty($path) && is_string($path) ) {
|
432 |
+
if ( 0 !== strpos($path, '[') )
|
433 |
+
$obj .= '.';
|
434 |
+
$obj .= $path;
|
435 |
+
}
|
436 |
+
return $obj;
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Build jQuery JS expression to add data to specified client object
|
441 |
+
* @param string|obj $obj Name of client object (Set to root object if not a valid name)
|
442 |
+
* @param mixed $data Data to add to client object
|
443 |
+
* @param bool (optional) $out Whether or not to output code (Default: false)
|
444 |
+
* @return string JS expression to extend client object
|
445 |
+
*/
|
446 |
+
function extend_client_object($obj, $data = null, $out = false) {
|
447 |
+
//Validate parameters
|
448 |
+
$args = func_get_args();
|
449 |
+
switch ( count($args) ) {
|
450 |
+
case 2:
|
451 |
+
if ( !is_scalar($args[0]) ) {
|
452 |
+
if ( is_bool($args[1]) )
|
453 |
+
$out = $args[1];
|
454 |
+
} else {
|
455 |
+
break;
|
456 |
+
}
|
457 |
+
case 1:
|
458 |
+
$data = $args[0];
|
459 |
+
$obj = null;
|
460 |
+
break;
|
461 |
+
}
|
462 |
+
//Default client object
|
463 |
+
if ( !is_string($obj) || empty($obj) )
|
464 |
+
$obj = null;
|
465 |
+
//Default data
|
466 |
+
if ( is_array($data) ) {
|
467 |
+
$data = (object)$data;
|
468 |
+
}
|
469 |
+
//Build expression
|
470 |
+
if ( empty($data) || ( empty($obj) && is_scalar($data) ) ) {
|
471 |
+
$ret = '';
|
472 |
+
} else {
|
473 |
+
$c_obj = $this->get_client_object($obj);
|
474 |
+
$ret = $this->validate_client_object($obj, sprintf('{$.extend(%1$s, %2$s);}', $c_obj, json_encode($data)) );
|
475 |
+
if ( $out )
|
476 |
+
echo $this->build_script_element($ret, 'context', true, true);
|
477 |
+
}
|
478 |
+
return $ret;
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Validate client object $obj before running command $cmd
|
483 |
+
*
|
484 |
+
* @param string $obj Full object name
|
485 |
+
* @param string $cmd (optional) Command to wrap in validation
|
486 |
+
* @return string Command wrapped in validation block
|
487 |
+
* If no command is specified the validation conditions are returned
|
488 |
+
*/
|
489 |
+
public function validate_client_object($obj, $cmd = null) {
|
490 |
+
//Build condition
|
491 |
+
$sep = '.';
|
492 |
+
$obj = trim( $this->get_client_object($obj) , $sep);
|
493 |
+
$offset = 0;
|
494 |
+
$len = strlen($obj);
|
495 |
+
$pos = $len;
|
496 |
+
$fmt = '(typeof %s != \'undefined\')';
|
497 |
+
$objs = array();
|
498 |
+
//Add segments to array (in reverse)
|
499 |
+
do {
|
500 |
+
$objs[] = sprintf($fmt, substr($obj, 0, $pos));
|
501 |
+
$offset = $pos - $len - 1;
|
502 |
+
} while ( $offset < $len && ( $pos = strrpos($obj, $sep, $offset) ) && $pos !== false );
|
503 |
+
//Format condition
|
504 |
+
$condition = implode(' && ', array_reverse($objs));
|
505 |
+
|
506 |
+
//Wrap command in validation
|
507 |
+
if ( is_string($cmd) && !empty($cmd) ) {
|
508 |
+
$condition = sprintf('if ( %1$s ) { %2$s }', $condition, $cmd);
|
509 |
+
}
|
510 |
+
return $condition;
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Build client method call
|
515 |
+
* @uses get_client_object() to generate the body of the method call
|
516 |
+
* @param string $method Method name
|
517 |
+
* @param array|string $params (optional) Parameters to pass to method
|
518 |
+
* @param bool $encode (optional) JSON-encode parameters? (Default: TRUE)
|
519 |
+
* @param bool $validate (optional) Validate method before calling it?
|
520 |
+
* @return string Method call
|
521 |
+
*/
|
522 |
+
function call_client_method($method, $params = null, $encode = true, $validate = true) {
|
523 |
+
$ret = '';
|
524 |
+
if ( !is_string($method) || empty($method) ) {
|
525 |
+
return $ret;
|
526 |
+
}
|
527 |
+
$encode = !!$encode;
|
528 |
+
$validate = !!$validate;
|
529 |
+
|
530 |
+
//Build parameters
|
531 |
+
if ( !is_null($params) ) {
|
532 |
+
if ( $encode ) {
|
533 |
+
$params = json_encode($params);
|
534 |
+
} elseif ( is_array($params) ) {
|
535 |
+
$params = implode(',', $params);
|
536 |
+
}
|
537 |
+
}
|
538 |
+
if ( !is_string($params) ) {
|
539 |
+
$params = '';
|
540 |
+
}
|
541 |
+
$ret = sprintf('%s(%s);', $this->get_client_object($method), $params);
|
542 |
+
if ( $validate ) {
|
543 |
+
$ret = $this->validate_client_object($method, $ret);
|
544 |
+
}
|
545 |
+
return $ret;
|
546 |
+
}
|
547 |
+
|
548 |
Â
/*-** WP **-*/
|
549 |
Â
|
550 |
Â
/**
|
571 |
Â
return true;
|
572 |
Â
}
|
573 |
Â
|
574 |
+
/* Hooks */
|
575 |
+
|
576 |
+
/**
|
577 |
+
* Retrieve parent object
|
578 |
+
* @return obj|bool Parent object (FALSE if no valid parent set)
|
579 |
+
*/
|
580 |
+
function &get_parent() {
|
581 |
+
if ( is_object($this->parent) )
|
582 |
+
return $this->parent;
|
583 |
+
else
|
584 |
+
return false;
|
585 |
+
}
|
586 |
+
|
587 |
+
/**
|
588 |
+
* Retrieve parent property value
|
589 |
+
* @uses self::get_parent()
|
590 |
+
* @param string $prop Property name
|
591 |
+
* @param mixed $default Default value
|
592 |
+
* @return mixed Parent property value
|
593 |
+
*/
|
594 |
+
function get_parent_property($prop, $default = '') {
|
595 |
+
$p =& $this->get_parent();
|
596 |
+
return ( !!$p && property_exists($p, $prop) ) ? $p->{$prop} : $default;
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Retrieve formatted name for internal hooks
|
601 |
+
* Prefixes with parent prefix and hook prefix
|
602 |
+
* @uses self::get_parent_property() to retrieve hook prefix
|
603 |
+
* @uses self::add_prefix()
|
604 |
+
* @param string $tag Base tag
|
605 |
+
* @return string Formatted hook
|
606 |
+
*/
|
607 |
+
function get_hook($tag) {
|
608 |
+
//Hook prefix
|
609 |
+
$hook = $this->get_parent_property('hook_prefix', '');
|
610 |
+
if ( !empty($hook) )
|
611 |
+
$hook .= '_';
|
612 |
+
//Prefix
|
613 |
+
return $this->add_prefix($hook . $tag);
|
614 |
+
}
|
615 |
+
|
616 |
+
/**
|
617 |
+
* Run internal action
|
618 |
+
* Namespaces $tag
|
619 |
+
* @uses self::get_hook()
|
620 |
+
* @see do_action()
|
621 |
+
*/
|
622 |
+
function do_action($tag, $arg = '') {
|
623 |
+
$args = func_get_args();
|
624 |
+
$args[0] = $this->get_hook($tag);
|
625 |
+
return call_user_func_array('do_action', $args);
|
626 |
+
}
|
627 |
+
|
628 |
+
/**
|
629 |
+
* Run internal action passing arguments in array
|
630 |
+
* @uses do_action_ref_array()
|
631 |
+
*/
|
632 |
+
function do_action_ref_array($tag, $args) {
|
633 |
+
return do_action_ref_array($this->get_hook($tag), $args);
|
634 |
+
}
|
635 |
+
|
636 |
+
/**
|
637 |
+
* Run internal filter
|
638 |
+
* Namespaces $tag
|
639 |
+
* @uses self::get_hook()
|
640 |
+
* @see apply_filters()
|
641 |
+
*/
|
642 |
+
function apply_filters($tag, $value) {
|
643 |
+
$args = func_get_args();
|
644 |
+
$args[0] = $this->get_hook($tag);
|
645 |
+
return call_user_func_array('apply_filters', $args);
|
646 |
+
}
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Run internal filter passing arguments in array
|
650 |
+
* @uses apply_filters_ref_array()
|
651 |
+
*/
|
652 |
+
function apply_filters_ref_array($tag, $args) {
|
653 |
+
return apply_filters_ref_array($this->get_hook($tag), $args);
|
654 |
+
}
|
655 |
+
|
656 |
+
/**
|
657 |
+
* Add internal action
|
658 |
+
* Namespaces $tag
|
659 |
+
* @uses self::get_hook()
|
660 |
+
* @see add_action()
|
661 |
+
*/
|
662 |
+
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
|
663 |
+
return add_action($this->get_hook($tag), $function_to_add, $priority, $accepted_args);
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* Add internal filter
|
668 |
+
* Namespaces $tag
|
669 |
+
* @uses self::get_hook()
|
670 |
+
* @see add_filter()
|
671 |
+
*/
|
672 |
+
function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
|
673 |
+
return add_filter($this->get_hook($tag), $function_to_add, $priority, $accepted_args);
|
674 |
+
}
|
675 |
+
|
676 |
+
/**
|
677 |
+
* Remove internal action
|
678 |
+
* Namespaces $tag
|
679 |
+
* @uses self::get_hook()
|
680 |
+
* @uses remove_action()
|
681 |
+
*/
|
682 |
+
function remove_action($tag, $function_to_remove, $priority = 10, $accepted_args = 1) {
|
683 |
+
return remove_action($this->get_hook($tag), $function_to_remove, $priority, $accepted_args);
|
684 |
+
}
|
685 |
+
|
686 |
+
/**
|
687 |
+
* Remove internal filter
|
688 |
+
* Namespaces $tag
|
689 |
+
* @uses self::get_hook()
|
690 |
+
* @uses remove_filter()
|
691 |
+
*/
|
692 |
+
function remove_filter($tag, $function_to_remove, $priority = 10, $accepted_args = 1) {
|
693 |
+
return remove_filter($this->get_hook($tag), $function_to_remove, $priority, $accepted_args);
|
694 |
+
}
|
695 |
+
|
696 |
+
/* Meta */
|
697 |
+
|
698 |
+
/**
|
699 |
+
* Retrieves post metadata for internal methods
|
700 |
+
* Metadata set internally is wrapped in an array so it is unwrapped before returned the retrieved value
|
701 |
+
* @see get_post_meta()
|
702 |
+
* @param int $post_id Post ID
|
703 |
+
* @param string $key Name of metadata to retrieve
|
704 |
+
* @param boolean $single Whether or not to retrieve single value or not
|
705 |
+
* @return mixed Retrieved post metadata
|
706 |
+
*/
|
707 |
+
function post_meta_get($post_id, $key, $single = false) {
|
708 |
+
$meta_value = get_post_meta($post_id, $this->post_meta_get_key($key), $single);
|
709 |
+
if (is_array($meta_value) && count($meta_value) == 1)
|
710 |
+
$meta_value = $meta_value[0];
|
711 |
+
return $meta_value;
|
712 |
+
}
|
713 |
+
|
714 |
+
/**
|
715 |
+
* Wraps metadata in array for storage in database
|
716 |
+
* @param mixed $meta_value Value to be set as metadata
|
717 |
+
* @return array Wrapped metadata value
|
718 |
+
*/
|
719 |
+
function post_meta_prepare_value($meta_value) {
|
720 |
+
return array($meta_value);
|
721 |
+
}
|
722 |
+
|
723 |
+
/**
|
724 |
+
* Adds Metadata for a post to database
|
725 |
+
* For internal methods
|
726 |
+
* @see add_post_meta
|
727 |
+
* @param $post_id
|
728 |
+
* @param $meta_key
|
729 |
+
* @param $meta_value
|
730 |
+
* @param $unique
|
731 |
+
* @return boolean Result of operation
|
732 |
+
*/
|
733 |
+
function post_meta_add($post_id, $meta_key, $meta_value, $unique = false) {
|
734 |
+
$meta_value = $this->post_meta_value_prepare($meta_value);
|
735 |
+
return add_post_meta($post_id, $meta_key, $meta_value, $unique);
|
736 |
+
}
|
737 |
+
|
738 |
+
/**
|
739 |
+
* Updates post metadata for internal data/methods
|
740 |
+
* @see update_post_meta()
|
741 |
+
* @param $post_id
|
742 |
+
* @param $meta_key
|
743 |
+
* @param $meta_value
|
744 |
+
* @param $prev_value
|
745 |
+
* @return boolean Result of operation
|
746 |
+
*/
|
747 |
+
function post_meta_update($post_id, $meta_key, $meta_value, $prev_value = '') {
|
748 |
+
$meta_value = $this->post_meta_prepare_value($meta_value);
|
749 |
+
return update_post_meta($post_id, $meta_key, $meta_value, $prev_value);
|
750 |
+
}
|
751 |
+
|
752 |
+
/**
|
753 |
+
* Builds postmeta key for custom data set by plugin
|
754 |
+
* @param string $key Base key name
|
755 |
+
* @return string Formatted postmeta key
|
756 |
+
*/
|
757 |
+
function post_meta_get_key($key) {
|
758 |
+
$sep = '_';
|
759 |
+
if ( strpos($key, $sep . $this->prefix) !== 0 ) {
|
760 |
+
$key_base = func_get_args();
|
761 |
+
if ( !empty($key_base) ) {
|
762 |
+
$key = array_merge((array)$this->prefix, $key_base);
|
763 |
+
return $sep . implode($sep, $key);
|
764 |
+
}
|
765 |
+
}
|
766 |
+
|
767 |
+
return $key;
|
768 |
+
}
|
769 |
+
|
770 |
+
/**
|
771 |
+
* Creates a meta key for storing post meta data
|
772 |
+
* Prefixes standard prefixed text with underscore to hide meta data on post edit forms
|
773 |
+
* @param string $text Text to use as base of meta key
|
774 |
+
* @return string Formatted meta key
|
775 |
+
*/
|
776 |
+
function make_meta_key($text = '') {
|
777 |
+
return '_' . $this->add_prefix($text);
|
778 |
+
}
|
779 |
+
|
780 |
Â
/*-** Request **-*/
|
781 |
Â
|
782 |
Â
/**
|
783 |
+
* Checks if the currently executing file matches specified file name
|
784 |
Â
* @param string $filename Filename to check for
|
785 |
Â
* @return bool TRUE if current page matches specified filename, FALSE otherwise
|
786 |
Â
*/
|
787 |
+
function is_current_file( $filename ) {
|
788 |
Â
return ( $filename == basename( $_SERVER['SCRIPT_NAME'] ) );
|
789 |
Â
}
|
790 |
Â
|
794 |
Â
*/
|
795 |
Â
function is_admin_management_page() {
|
796 |
Â
return ( is_admin()
|
797 |
+
&& ( $this->is_current_file('edit.php')
|
798 |
+
|| ( $this->is_current_file('admin.php')
|
799 |
Â
&& isset($_GET['page'])
|
800 |
Â
&& strpos($_GET['page'], 'cnr') === 0 )
|
801 |
Â
)
|
802 |
Â
);
|
803 |
Â
}
|
804 |
Â
|
805 |
+
/* Class */
|
806 |
+
|
807 |
+
function is_a($obj, $class_name) {
|
808 |
+
return ( is_object($obj) && is_a($obj, $this->add_prefix_uc($class_name)) ) ? true : false;
|
809 |
+
}
|
810 |
+
|
811 |
+
/**
|
812 |
+
* Retrieve name of internal class
|
813 |
+
* @param string $class Base name of class
|
814 |
+
* @return string Full name of internal class
|
815 |
+
*/
|
816 |
+
function get_class($class) {
|
817 |
+
return $this->add_prefix_uc($class);
|
818 |
+
}
|
819 |
+
|
820 |
+
/* Context */
|
821 |
+
|
822 |
+
/**
|
823 |
+
* Retrieve context for current request
|
824 |
+
* @return array Context
|
825 |
+
*/
|
826 |
+
function get_context() {
|
827 |
+
//Context
|
828 |
+
static $ctx = null;
|
829 |
+
if ( !is_array($ctx) ) {
|
830 |
+
//Standard
|
831 |
+
$ctx = array($this->build_context());
|
832 |
+
//Action
|
833 |
+
$action = $this->get_action();
|
834 |
+
if ( !empty($action) ) {
|
835 |
+
$ctx[] = $this->build_context('action', $action);
|
836 |
+
}
|
837 |
+
//Post type
|
838 |
+
$post_type = $this->get_post_type();
|
839 |
+
if ( !empty($action) ) {
|
840 |
+
$ctx[] = $this->build_context('post-type', $post_type);
|
841 |
+
}
|
842 |
+
//Admin page
|
843 |
+
if ( is_admin() ) {
|
844 |
+
global $pagenow;
|
845 |
+
$pg = $this->strip_file_extension($pagenow);
|
846 |
+
$ctx[] = $this->build_context('page', $pg);
|
847 |
+
//Query String
|
848 |
+
parse_str($_SERVER['QUERY_STRING'], $qv);
|
849 |
+
if ( isset($qv['page']) ) {
|
850 |
+
$ctx[] = $this->build_context('page', $qv['page']);
|
851 |
+
}
|
852 |
+
//Action
|
853 |
+
if ( !empty($action) ) {
|
854 |
+
$ctx[] = $this->build_context('page', $pg, 'action', $action);
|
855 |
+
$ctx[] = $this->build_context('post-type', $post_type, 'action', $action);
|
856 |
+
}
|
857 |
+
}
|
858 |
+
//User
|
859 |
+
$u = wp_get_current_user();
|
860 |
+
$ctx[] = $this->build_context('user', ( $u->ID ) ? 'registered' : 'guest', false);
|
861 |
+
}
|
862 |
+
|
863 |
+
return $ctx;
|
864 |
+
}
|
865 |
+
|
866 |
+
/**
|
867 |
+
* Builds context from multiple components
|
868 |
+
* Usage:
|
869 |
+
* > $prefix can be omitted and context strings can be added as needed
|
870 |
+
* > Multiple context strings may be passed to be joined together
|
871 |
+
*
|
872 |
+
* @param string (optional) $context Variable number of components to add to context
|
873 |
+
* @param bool (optional) $prefix Whether or not to prefix context with request type (public or admin) [Default: TRUE]
|
874 |
+
* @return string Context
|
875 |
+
*/
|
876 |
+
function build_context($context = null, $prefix = true) {
|
877 |
+
$args = func_get_args();
|
878 |
+
//Get prefix option
|
879 |
+
if ( !empty($args) ) {
|
880 |
+
$prefix = ( is_bool($args[count($args) - 1]) ) ? array_pop($args) : true;
|
881 |
+
}
|
882 |
+
|
883 |
+
//Validate
|
884 |
+
$context = array_filter($args, 'is_string');
|
885 |
+
$sep = '_';
|
886 |
+
|
887 |
+
//Context Prefix
|
888 |
+
if ( $prefix )
|
889 |
+
array_unshift($context, ( is_admin() ) ? 'admin' : 'public' );
|
890 |
+
return implode($sep, $context);
|
891 |
+
}
|
892 |
+
|
893 |
+
/**
|
894 |
+
* Check if context exists in current request
|
895 |
+
* @param string $context Context to check for
|
896 |
+
* @return bool TRUE if context exists FALSE otherwise
|
897 |
+
*/
|
898 |
+
function is_context($context) {
|
899 |
+
$ret = false;
|
900 |
+
if ( is_scalar($context) )
|
901 |
+
$context = array($context);
|
902 |
+
if ( is_array($context) && !empty($context) ) {
|
903 |
+
$ictx = array_intersect($this->get_context(), $context);
|
904 |
+
if ( !empty($ictx) )
|
905 |
+
$ret = true;
|
906 |
+
}
|
907 |
+
return $ret;
|
908 |
+
}
|
909 |
+
|
910 |
+
/**
|
911 |
+
* Output current context to client-side
|
912 |
+
* @uses `wp_head` action hook
|
913 |
+
* @uses `admin_head` action hook
|
914 |
+
* @return void
|
915 |
+
*/
|
916 |
+
function set_client_context() {
|
917 |
+
$ctx = new stdClass();
|
918 |
+
$ctx->context = $this->get_context();
|
919 |
+
$this->extend_client_object($ctx, true);
|
920 |
+
}
|
921 |
+
|
922 |
Â
/**
|
923 |
Â
* Joins and normalizes the slashes in the paths passed to method
|
924 |
Â
* All forward/back slashes are converted to forward slashes
|
925 |
Â
* Multiple path segments can be passed as additional argments
|
926 |
Â
* @param string $path Path to normalize
|
927 |
+
* @param bool|array $trailing_slash (optional) Whether or not normalized path should have a trailing slash or not (Default: FALSE)
|
928 |
+
* If array is passed, first index is trailing, second is leading slash
|
929 |
+
* If multiple path segments are passed, $trailing_slash will be the LAST parameter (default value used if omitted)
|
930 |
Â
*/
|
931 |
Â
function normalize_path($path, $trailing_slash = false) {
|
932 |
Â
$sl_f = '/';
|
933 |
Â
$sl_b = '\\';
|
934 |
Â
$parts = func_get_args();
|
935 |
+
//Slash defaults (trailing, leading);
|
936 |
+
$slashes = array(false, true);
|
937 |
Â
if ( func_num_args() > 1 ) {
|
938 |
+
//Get last argument
|
939 |
+
$arg_last = $parts[count($parts) - 1];
|
940 |
+
if ( is_bool($arg_last) ) {
|
941 |
+
$arg_last = array($arg_last);
|
942 |
+
}
|
943 |
+
|
944 |
+
if ( is_array($arg_last) && count($arg_last) > 0 && is_bool($arg_last[0]) ) {
|
945 |
+
//Remove slash paramter from args array
|
946 |
Â
array_pop($parts);
|
947 |
+
//Normalize slashes options
|
948 |
+
if ( isset($arg_last[0]) )
|
949 |
+
$slashes[0] = $arg_last[0];
|
950 |
+
if ( isset($arg_last[1]) )
|
951 |
+
$slashes[1] = $arg_last[1];
|
952 |
Â
}
|
953 |
+
}
|
954 |
+
//Extract to slash options local variables
|
955 |
+
list($trailing_slash, $leading_slash) = $slashes;
|
956 |
+
|
957 |
+
//Clean path segments
|
958 |
+
foreach ( $parts as $key => $part ) {
|
959 |
+
//Trim slashes/spaces
|
960 |
+
$parts[$key] = trim($part, " " . $sl_f . $sl_b);
|
961 |
+
|
962 |
+
//Verify path segment still contains value
|
963 |
+
if ( empty($parts[$key]) ) {
|
964 |
+
unset($parts[$key]);
|
965 |
+
continue;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
966 |
Â
}
|
967 |
Â
}
|
968 |
+
|
969 |
Â
//Join path parts together
|
970 |
Â
$parts = implode($sl_b, $parts);
|
971 |
Â
$parts = str_replace($sl_b, $sl_f, $parts);
|
972 |
Â
//Add trailing slash (if necessary)
|
973 |
Â
if ( $trailing_slash )
|
974 |
+
$parts .= $sl_f;
|
975 |
+
//Add leading slash (if necessary)
|
976 |
+
$regex = '#^.+:[\\/]#';
|
977 |
+
if ( $leading_slash && !preg_match($regex, $parts) ) {
|
978 |
+
$parts = $sl_f . $parts;
|
979 |
+
}
|
980 |
Â
return $parts;
|
981 |
Â
}
|
982 |
Â
|
983 |
Â
/**
|
984 |
Â
* Returns URL of file (assumes that it is in plugin directory)
|
985 |
Â
* @param string $file name of file get URL
|
986 |
+
* @return string File URL
|
987 |
Â
*/
|
988 |
Â
function get_file_url($file) {
|
989 |
+
if ( is_string($file) && '' != trim($file) ) {
|
990 |
+
$file = str_replace(' ', '%20', $this->normalize_path($this->get_url_base(), $file));
|
991 |
Â
}
|
992 |
Â
return $file;
|
993 |
Â
}
|
994 |
Â
|
995 |
+
/**
|
996 |
+
* Returns path to plugin file
|
997 |
+
* @param string $file file name
|
998 |
+
* @return string File path
|
999 |
+
*/
|
1000 |
+
function get_file_path($file) {
|
1001 |
+
if ( is_string($file) && '' != trim($file) ) {
|
1002 |
+
$file = $this->normalize_path($this->get_path_base(), $file);
|
1003 |
+
}
|
1004 |
+
return $file;
|
1005 |
+
}
|
1006 |
+
|
1007 |
+
function get_plugin_file_path($file, $trailing_slash = false) {
|
1008 |
+
if ( is_string($file) && '' != trim($file) )
|
1009 |
+
$file = $this->normalize_path($this->get_plugin_base(), $file, $trailing_slash);
|
1010 |
+
return $file;
|
1011 |
+
}
|
1012 |
+
|
1013 |
+
/**
|
1014 |
+
* Checks if value is valid file name
|
1015 |
+
* @param string $filename File name to check
|
1016 |
+
* @return bool TRUE if valid file name, FALSE otherwise
|
1017 |
+
*/
|
1018 |
+
function is_file($filename) {
|
1019 |
+
$ext = $this->get_file_extension($filename);
|
1020 |
+
return ( empty($ext) ) ? false : true;
|
1021 |
+
}
|
1022 |
+
|
1023 |
Â
/**
|
1024 |
Â
* Retrieves file extension
|
1025 |
Â
* @param string $file file name/path
|
1026 |
+
* @param bool (optional) $lowercase Whether lowercase extension should be returned (Default: TRUE)
|
1027 |
Â
* @return string File's extension
|
1028 |
Â
*/
|
1029 |
+
function get_file_extension($file, $lowercase = true) {
|
1030 |
Â
$ret = '';
|
1031 |
Â
$sep = '.';
|
1032 |
+
if ( !is_string($file) )
|
1033 |
+
return $ret;
|
1034 |
+
if ( ( $rpos = strrpos($file, $sep) ) > 0 )
|
1035 |
Â
$ret = substr($file, $rpos + 1);
|
1036 |
+
if ( !!$lowercase )
|
1037 |
+
$ret = strtolower($ret);
|
1038 |
Â
return $ret;
|
1039 |
Â
}
|
1040 |
Â
|
1041 |
Â
/**
|
1042 |
Â
* Checks if file has specified extension
|
1043 |
+
* @uses get_file_extension()
|
1044 |
Â
* @param string $file File name/path
|
1045 |
+
* @param string|array $extension File ending(s) to check $file for
|
1046 |
+
* @param bool (optional) Whether check should be case senstive or not (Default: FALSE)
|
1047 |
Â
* @return bool TRUE if file has extension
|
1048 |
Â
*/
|
1049 |
+
function has_file_extension($file, $extension, $case_sensitive = false) {
|
1050 |
+
if ( !is_array($extension) )
|
1051 |
+
$extension = array(strval($extension));
|
1052 |
+
if ( !$case_sensitive ) {
|
1053 |
+
//Normalize extensions
|
1054 |
+
$extension = array_map('strtolower', $extension);
|
1055 |
+
}
|
1056 |
+
return ( in_array($this->get_file_extension($file, !$case_sensitive), $extension) ) ? true : false;
|
1057 |
+
}
|
1058 |
+
|
1059 |
+
/**
|
1060 |
+
* Removes file extension from file name
|
1061 |
+
* The extension is the text following the last period ('.') in the file name
|
1062 |
+
* @uses get_file_extension()
|
1063 |
+
* @param string $file File name
|
1064 |
+
* @return string File name without extension
|
1065 |
+
*/
|
1066 |
+
function strip_file_extension($file) {
|
1067 |
+
$ext = $this->get_file_extension($file);
|
1068 |
+
if ( !empty($ext) ) {
|
1069 |
+
$file = substr($file, 0, (strlen($ext) + 1) * -1);
|
1070 |
+
}
|
1071 |
+
return $file;
|
1072 |
Â
}
|
1073 |
Â
|
1074 |
Â
/**
|
1075 |
Â
* Retrieve base URL for plugin-specific files
|
1076 |
+
* @uses get_plugin_base()
|
1077 |
+
* @uses normalize_path()
|
1078 |
Â
* @return string Base URL
|
1079 |
Â
*/
|
1080 |
Â
function get_url_base() {
|
1081 |
Â
static $url_base = '';
|
1082 |
Â
if ( '' == $url_base ) {
|
1083 |
+
$url_base = $this->normalize_path(plugins_url(), $this->get_plugin_base());
|
1084 |
Â
}
|
1085 |
Â
return $url_base;
|
1086 |
Â
}
|
1087 |
Â
|
1088 |
+
/**
|
1089 |
+
* Retrieve plugin's base path
|
1090 |
+
* @uses WP_PLUGIN_DIR
|
1091 |
+
* @uses get_plugin_base()
|
1092 |
+
* @uses normalize_path()
|
1093 |
+
* @return string Base path
|
1094 |
+
*/
|
1095 |
Â
function get_path_base() {
|
1096 |
Â
static $path_base = '';
|
1097 |
Â
if ( '' == $path_base ) {
|
1099 |
Â
}
|
1100 |
Â
return $path_base;
|
1101 |
Â
}
|
1102 |
+
|
1103 |
+
/**
|
1104 |
+
* Retrieve plugin's base directory
|
1105 |
+
* @uses WP_PLUGIN_DIR
|
1106 |
+
* @uses normalize_path()
|
1107 |
+
* @return string Base directory
|
1108 |
+
*/
|
1109 |
+
function get_plugin_base($trim = false) {
|
1110 |
Â
static $plugin_dir = '';
|
1111 |
Â
if ( '' == $plugin_dir ) {
|
1112 |
Â
$plugin_dir = str_replace($this->normalize_path(WP_PLUGIN_DIR), '', $this->normalize_path(dirname(dirname(__FILE__))));
|
1113 |
Â
}
|
1114 |
+
if ( $trim )
|
1115 |
+
$plugin_dir = trim($plugin_dir, ' \/');
|
1116 |
Â
return $plugin_dir;
|
1117 |
Â
}
|
1118 |
Â
|
1119 |
+
/**
|
1120 |
+
* Retrieve plugin's base file path
|
1121 |
+
* @uses get_path_base()
|
1122 |
+
* @uses get_file_path()
|
1123 |
+
* @return string Base file path
|
1124 |
+
*/
|
1125 |
Â
function get_plugin_base_file() {
|
1126 |
+
static $file = '';
|
1127 |
+
if ( empty($file) ) {
|
1128 |
+
$dir = @ opendir($this->get_path_base());
|
1129 |
+
if ( $dir ) {
|
1130 |
+
while ( ($ftemp = readdir($dir)) !== false ) {
|
1131 |
+
//Only process PHP files
|
1132 |
+
$ftemp = $this->get_file_path($ftemp);
|
1133 |
+
if ( !$this->has_file_extension($ftemp, 'php') || !is_readable($ftemp) )
|
1134 |
+
continue;
|
1135 |
+
//Check for data
|
1136 |
+
$data = get_file_data($ftemp, $this->plugin_headers);
|
1137 |
+
if ( !empty($data['Name']) ) {
|
1138 |
+
//Set base file
|
1139 |
+
$file = $ftemp;
|
1140 |
+
break;
|
1141 |
+
}
|
1142 |
+
}
|
1143 |
+
}
|
1144 |
+
@closedir($dir);
|
1145 |
+
}
|
1146 |
+
//Return
|
1147 |
+
return $file;
|
1148 |
Â
}
|
1149 |
Â
|
1150 |
+
/**
|
1151 |
+
* Retrieve plugin's internal name
|
1152 |
+
* Internal name is used by WP core
|
1153 |
+
* @uses get_plugin_base_file()
|
1154 |
+
* @uses plugin_basename()
|
1155 |
+
* @return string Internal plugin name
|
1156 |
+
*/
|
1157 |
Â
function get_plugin_base_name() {
|
1158 |
+
static $name = false;
|
1159 |
+
if ( !$name ) {
|
1160 |
+
$file = $this->get_plugin_base_file();
|
1161 |
+
$name = plugin_basename($file);
|
1162 |
+
}
|
1163 |
+
return $name;
|
1164 |
+
}
|
1165 |
+
|
1166 |
+
/**
|
1167 |
+
* Retrieve plugin info
|
1168 |
+
* Parses info comment in main plugin file
|
1169 |
+
* @uses get_plugin_base_file()
|
1170 |
+
*/
|
1171 |
+
function get_plugin_info($field = '') {
|
1172 |
+
static $data = array();
|
1173 |
+
$ret = '';
|
1174 |
+
//Get plugin data
|
1175 |
+
if ( empty($data) ) {
|
1176 |
+
$file = $this->get_plugin_base_file();
|
1177 |
+
$data = get_file_data($file, $this->plugin_headers);
|
1178 |
+
}
|
1179 |
+
//Return specified field
|
1180 |
+
if ( !empty($field) ) {
|
1181 |
+
if ( isset($data[$field]) )
|
1182 |
+
$ret = $data[$field];
|
1183 |
+
} else {
|
1184 |
+
$ret = $data;
|
1185 |
+
}
|
1186 |
+
return $ret;
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
/**
|
1190 |
+
* Retrieve plugin version
|
1191 |
+
* @uses get_plugin_info()
|
1192 |
+
* @param bool $strip_desc Strip any additional version text
|
1193 |
+
* @return string Plugin version
|
1194 |
+
*/
|
1195 |
+
function get_plugin_version($strip_desc = true) {
|
1196 |
+
static $v = '';
|
1197 |
+
//Retrieve version
|
1198 |
+
if ( empty($v) ) {
|
1199 |
+
$field = 'Version';
|
1200 |
+
$v = $this->get_plugin_info($field);
|
1201 |
+
}
|
1202 |
+
//Format
|
1203 |
+
$ret = $v;
|
1204 |
+
if ( $strip_desc ) {
|
1205 |
+
$ret = explode(' ', $ret, 2);
|
1206 |
+
$ret = $ret[0];
|
1207 |
+
}
|
1208 |
+
//Return
|
1209 |
+
return $ret;
|
1210 |
+
}
|
1211 |
+
|
1212 |
+
/**
|
1213 |
+
* Retrieve plugin textdomain (for localization)
|
1214 |
+
* @return string
|
1215 |
+
*/
|
1216 |
+
function get_plugin_textdomain() {
|
1217 |
+
static $dom = '';
|
1218 |
+
if ( empty($dom) )
|
1219 |
+
$dom = $this->get_plugin_base(true);
|
1220 |
+
return $dom;
|
1221 |
+
}
|
1222 |
+
|
1223 |
+
/**
|
1224 |
+
* Retrieve current post type based on URL query variables
|
1225 |
+
* @return string|null Current post type
|
1226 |
+
*/
|
1227 |
+
public function get_post_type() {
|
1228 |
+
if ( isset($_GET['post_type']) && !empty($_GET['post_type']) ) {
|
1229 |
+
return $_GET['post_type'];
|
1230 |
+
}
|
1231 |
+
$pt = null;
|
1232 |
+
if ( isset($_GET['post']) && is_numeric($_GET['post']) ) {
|
1233 |
+
$pt = get_post_type($_GET['post']);
|
1234 |
+
}
|
1235 |
+
return $pt;
|
1236 |
Â
}
|
1237 |
Â
|
1238 |
Â
/**
|
1273 |
Â
|
1274 |
Â
/*-** General **-*/
|
1275 |
Â
|
1276 |
+
/**
|
1277 |
+
* Checks if last parameter sent to a function is an array of options and returns it
|
1278 |
+
* Calling function should use `func_get_args()` and pass the value to this method
|
1279 |
+
* @param array $args Parameters passed to calling function
|
1280 |
+
* @return array Options array (Default: empty array)
|
1281 |
+
*/
|
1282 |
+
function func_get_options($args) {
|
1283 |
+
$r = array();
|
1284 |
+
if ( is_array($args) && !empty($args) ) {
|
1285 |
+
$last = count($args) - 1;
|
1286 |
+
if ( is_array($args[$last]) )
|
1287 |
+
$r = $args[$last];
|
1288 |
+
}
|
1289 |
+
return $r;
|
1290 |
+
}
|
1291 |
+
|
1292 |
Â
/**
|
1293 |
Â
* Checks if a property exists in a class or object
|
1294 |
Â
* (Compatibility method for PHP 4
|
1327 |
Â
}
|
1328 |
Â
}
|
1329 |
Â
|
1330 |
+
/**
|
1331 |
+
* Remap array members based on a
|
1332 |
+
* mapping of source/destination keys
|
1333 |
+
* @param array $properties Associative array of properties
|
1334 |
+
* @param array $map Source/Destination mapping
|
1335 |
+
* > Key: Source member
|
1336 |
+
* > Val: Destination member
|
1337 |
+
* @param bool $overwrite If TRUE, source value will be set in destination regardless of whether member already exists or not
|
1338 |
+
* @return array Remapped properties
|
1339 |
+
*/
|
1340 |
+
function array_remap($arr, $map = array(), $overwrite = false) {
|
1341 |
+
if ( !empty($map) && is_array($map) ) {
|
1342 |
+
//Iterate through mappings
|
1343 |
+
foreach ( $map as $from => $to ) {
|
1344 |
+
if ( !array_key_exists($from, $arr) )
|
1345 |
+
continue;
|
1346 |
+
$move = $overwrite;
|
1347 |
+
//Only remap if parent property doesn't already exist in array
|
1348 |
+
if ( !array_key_exists($to, $arr) )
|
1349 |
+
$move = true;
|
1350 |
+
if ( $move ) {
|
1351 |
+
//Move member value to new key
|
1352 |
+
$arr[$to] = $arr[$from];
|
1353 |
+
//Remove source member
|
1354 |
+
unset($arr[$from]);
|
1355 |
+
}
|
1356 |
+
}
|
1357 |
+
}
|
1358 |
+
//Return remapped properties
|
1359 |
+
return $arr;
|
1360 |
+
}
|
1361 |
+
|
1362 |
+
function array_filter_keys($arr, $keys) {
|
1363 |
+
if ( is_array($arr) && !empty($arr) && is_array($keys) && !empty($keys) ) {
|
1364 |
+
foreach ( $keys as $rem ) {
|
1365 |
+
if ( array_key_exists($rem, $arr) )
|
1366 |
+
unset($arr[$rem]);
|
1367 |
+
}
|
1368 |
+
}
|
1369 |
+
|
1370 |
+
return $arr;
|
1371 |
+
}
|
1372 |
+
|
1373 |
+
/**
|
1374 |
+
* Insert an item into an array at the specified position
|
1375 |
+
* @param mixed $item Item to insert into array
|
1376 |
+
* @param int $pos Index position to insert item into array
|
1377 |
+
* @return array Modified array
|
1378 |
+
*/
|
1379 |
+
function array_insert($array, $item, $pos = null) {
|
1380 |
+
array_splice($array, $pos, 0, $item);
|
1381 |
+
return $array;
|
1382 |
+
}
|
1383 |
+
|
1384 |
Â
/**
|
1385 |
Â
* Merges 1 or more arrays together
|
1386 |
Â
* Methodology
|
1392 |
Â
* - Merge item in base array with current item based on key name
|
1393 |
Â
* - If the current item's value AND the corresponding item in the base array are BOTH arrays, recursively merge the the arrays
|
1394 |
Â
* - If the current item's value OR the corresponding item in the base array is NOT an array, current item overwrites base item
|
Â
|
|
1395 |
Â
* @param array Variable number of arrays
|
1396 |
Â
* @param array $arr1 Default array
|
1397 |
Â
* @return array Merged array
|
1399 |
Â
function array_merge_recursive_distinct($arr1) {
|
1400 |
Â
//Get all arrays passed to function
|
1401 |
Â
$args = func_get_args();
|
1402 |
+
if ( empty($args) )
|
1403 |
Â
return false;
|
1404 |
+
//Return empty array if first parameter is not an array
|
1405 |
+
if ( !is_array($args[0]) )
|
1406 |
+
return array();
|
1407 |
Â
//Set first array as base array
|
1408 |
Â
$merged = $args[0];
|
1409 |
Â
//Iterate through arrays to merge
|
1410 |
Â
$arg_length = count($args);
|
1411 |
+
for ( $x = 1; $x < $arg_length; $x++ ) {
|
1412 |
Â
//Skip if argument is not an array (only merge arrays)
|
1413 |
+
if ( !is_array($args[$x]) )
|
1414 |
Â
continue;
|
1415 |
Â
//Iterate through argument items
|
1416 |
+
foreach ( $args[$x] as $key => $val ) {
|
1417 |
+
//Generate key for numeric indexes
|
1418 |
+
if ( is_int($key) ) {
|
1419 |
+
//Add new item to merged array
|
1420 |
+
$merged[] = null;
|
1421 |
+
//Get key of new item
|
1422 |
+
$key = array_pop(array_keys($merged));
|
1423 |
+
}
|
1424 |
+
if ( !isset($merged[$key]) || !is_array($merged[$key]) || !is_array($val) ) {
|
1425 |
+
$merged[$key] = $val;
|
1426 |
+
} elseif ( is_array($merged[$key]) && is_array($val) ) {
|
1427 |
+
$merged[$key] = $this->array_merge_recursive_distinct($merged[$key], $val);
|
1428 |
+
}
|
1429 |
Â
}
|
1430 |
Â
}
|
1431 |
Â
return $merged;
|
1480 |
Â
return $item;
|
1481 |
Â
}
|
1482 |
Â
|
1483 |
+
/**
|
1484 |
+
* Build formatted string based on array values
|
1485 |
+
* Array values in formatted string will be ordered by index order
|
1486 |
+
* @param array $attribute Values to build string with
|
1487 |
+
* @param string $format (optional) Format name (Default: Multidimensional array representation > ['value1']['value2']['value3'], etc.)
|
1488 |
+
* @return string Formatted string based on array values
|
1489 |
+
*/
|
1490 |
Â
function get_array_path($attribute = '', $format = null) {
|
1491 |
Â
//Formatted value
|
1492 |
Â
$fmtd = '';
|
1552 |
Â
return $path;
|
1553 |
Â
}
|
1554 |
Â
|
1555 |
+
/**
|
1556 |
+
* Parse string of attributes into array
|
1557 |
+
* For XML/XHTML tag attributes
|
1558 |
+
* @param string $txt Attribute text (Can be full tag or just attributes)
|
1559 |
+
* @return array Attributes as associative array
|
1560 |
+
*/
|
1561 |
+
function parse_attribute_string($txt, $defaults = array()) {
|
1562 |
+
$txt = trim($txt, ' >');
|
1563 |
+
$matches = $attr = array();
|
1564 |
+
//Strip tag
|
1565 |
+
if ( $txt[0] == '<' && ($s = strpos($txt, ' ')) && $s !== false ) {
|
1566 |
+
$txt = trim(substr($txt, $s + 1));
|
1567 |
+
}
|
1568 |
+
//Parse attributes
|
1569 |
+
$rgx = "/\b(\w+.*?)=([\"'])(.*?)\\2(?:\s|$)/i";
|
1570 |
+
preg_match_all($rgx, $txt, $matches);
|
1571 |
+
if ( count($matches) > 3 ) {
|
1572 |
+
foreach ( $matches[1] as $sub_idx => $val ) {
|
1573 |
+
if ( isset($matches[3][$sub_idx]) )
|
1574 |
+
$attr[trim($val)] = trim($matches[3][$sub_idx]);
|
1575 |
+
}
|
1576 |
+
}
|
1577 |
+
//Destroy parsing vars
|
1578 |
+
unset($txt, $matches);
|
1579 |
+
|
1580 |
+
return array_merge($defaults, $attr);
|
1581 |
+
}
|
1582 |
+
|
1583 |
Â
/**
|
1584 |
Â
* Builds attribute string for HTML element
|
1585 |
Â
* @param array $attr Attributes
|
1600 |
Â
return $ret;
|
1601 |
Â
}
|
1602 |
Â
|
1603 |
+
function build_html_link($uri, $content, $attributes = array()) {
|
1604 |
+
$attributes = array_merge(array('href' => $uri, 'title' => $content), $attributes);
|
1605 |
+
return $this->build_html_element(array('tag' => 'a', 'wrap' => true, 'content' => $content, 'attributes' => $attributes));
|
1606 |
+
}
|
1607 |
+
|
1608 |
Â
/**
|
1609 |
Â
* Generate external stylesheet element
|
1610 |
Â
* @param $url Stylesheet URL
|
1615 |
Â
return $this->build_html_element(array('tag' => 'link', 'wrap' => false, 'attributes' => $attributes));
|
1616 |
Â
}
|
1617 |
Â
|
1618 |
+
/**
|
1619 |
+
* Build client-side script element
|
1620 |
+
*
|
1621 |
+
* @param string $content Script content
|
1622 |
+
* @param string $id (optional) Element ID
|
1623 |
+
* @param bool $wrap_jquery (optional) Wrap commands in jQuery? (Default: Yes)
|
1624 |
+
* @param bool $wait_doc_ready (optional) Wait until document is fully loaded before executing commands? (Default: No)
|
1625 |
+
*/
|
1626 |
+
function build_script_element($content = '', $id = '', $wrap_jquery = true, $wait_doc_ready = false) {
|
1627 |
+
//Stop processing invalid content
|
1628 |
+
if ( is_array($content) && !empty($content) ) {
|
1629 |
+
$content = implode(PHP_EOL, $content);
|
1630 |
+
}
|
1631 |
+
if ( empty($content) || !is_string($content) ) {
|
1632 |
+
return '';
|
1633 |
+
}
|
1634 |
+
$attributes = array('type' => 'text/javascript');
|
1635 |
+
$start = array('/* <![CDATA[ */');
|
1636 |
+
$end = array('/* ]]> */');
|
1637 |
+
if ( $wrap_jquery ) {
|
1638 |
+
$start[] = '(function($){';
|
1639 |
+
$end[] = '})(jQuery);';
|
1640 |
+
|
1641 |
+
//Add event handler (if necessary)
|
1642 |
+
if ( $wait_doc_ready ) {
|
1643 |
+
$start[] = '$(document).ready(function(){';
|
1644 |
+
$end[] = '})';
|
1645 |
+
}
|
1646 |
+
}
|
1647 |
+
|
1648 |
+
//Reverse order of end values
|
1649 |
+
$end = array_reverse($end);
|
1650 |
+
$content = implode('', array_merge($start, array($content), $end));
|
1651 |
+
if ( is_string($id) && !empty($id) ) {
|
1652 |
+
$attributes['id'] = $this->add_prefix($id);
|
1653 |
+
}
|
1654 |
+
return $this->build_html_element(array('tag' => 'script', 'content' => $content, 'attributes' => $attributes)) . PHP_EOL;
|
1655 |
+
}
|
1656 |
+
|
1657 |
Â
/**
|
1658 |
Â
* Generate external script element
|
1659 |
Â
* @param $url Script URL
|
1661 |
Â
*/
|
1662 |
Â
function build_ext_script_element($url = '') {
|
1663 |
Â
$attributes = array('src' => $url, 'type' => 'text/javascript');
|
1664 |
+
return $this->build_html_element(array('tag' => 'script', 'attributes' => $attributes)) . PHP_EOL;
|
1665 |
Â
}
|
1666 |
Â
|
1667 |
Â
/**
|
1679 |
Â
$el_start = '<';
|
1680 |
Â
$el_end = '>';
|
1681 |
Â
$el_close = '/';
|
1682 |
+
$args = wp_parse_args($args, $defaults);
|
1683 |
+
//Collect attributes
|
1684 |
+
$attr_exclude = array( 'content', 'tag', 'wrap', 'attributes' );
|
1685 |
+
$attr_extra = array_diff_key($args, array_fill_keys($attr_exclude, null));
|
1686 |
+
if ( count($attr_extra) ) {
|
1687 |
+
//Merge attributes
|
1688 |
+
$args['attributes'] = wp_parse_args($attr_extra, $args['attributes']);
|
1689 |
+
//Remove attributes from top-level arguments
|
1690 |
+
$args = array_diff_key($args, $attr_extra);
|
1691 |
+
}
|
1692 |
+
extract($args, EXTR_SKIP);
|
1693 |
Â
$content = trim($content);
|
1694 |
Â
|
1695 |
+
|
1696 |
Â
if ( !$wrap && strlen($content) > 0 )
|
1697 |
Â
$wrap = true;
|
1698 |
Â
|
1737 |
Â
//Get last submenu added
|
1738 |
Â
$parent = $this->get_submenu_parent_file($parent);
|
1739 |
Â
if ( isset($submenu[$parent]) ) {
|
1740 |
+
$subs =& $submenu[$parent];
|
1741 |
+
|
1742 |
+
//Make sure menu isn't already in the desired position
|
1743 |
+
if ( $pos <= ( count($subs) - 1 ) ) {
|
1744 |
+
//Get submenu that was just added
|
1745 |
+
$sub = array_pop($subs);
|
1746 |
+
//Insert into desired position
|
1747 |
+
if ( 0 == $pos ) {
|
1748 |
+
array_unshift($subs, $sub);
|
1749 |
+
} else {
|
1750 |
+
$top = array_slice($subs, 0, $pos);
|
1751 |
+
$bottom = array_slice($subs, $pos);
|
1752 |
+
array_push($top, $sub);
|
1753 |
+
$subs = array_merge($top, $bottom);
|
1754 |
Â
}
|
1755 |
Â
}
|
1756 |
Â
}
|
1757 |
+
}
|
1758 |
Â
|
1759 |
Â
return $hookname;
|
1760 |
Â
}
|
1834 |
Â
$parent = $_wp_real_parent_file[$parent];
|
1835 |
Â
return $parent;
|
1836 |
Â
}
|
1837 |
+
|
1838 |
+
/* Shortcodes */
|
1839 |
+
|
1840 |
+
/**
|
1841 |
+
* Generate shortcode to be used in content
|
1842 |
+
* @param string $tag Shortcode tag
|
1843 |
+
* @param array $attr Associative array of attributes
|
1844 |
+
* @return string Shortcode markup
|
1845 |
+
*/
|
1846 |
+
public function make_shortcode($tag, $attr = array()) {
|
1847 |
+
return '[' . $tag . ']';
|
1848 |
+
}
|
1849 |
+
|
1850 |
+
/**
|
1851 |
+
* Build shortcode regex pattern for specific shortcode
|
1852 |
+
* @uses $shortcode_tags
|
1853 |
+
* @param string $tag Shortcode tag
|
1854 |
+
* @return string Shortcode regex pattern
|
1855 |
+
*/
|
1856 |
+
public function get_shortcode_regex($tag) {
|
1857 |
+
global $shortcode_tags;
|
1858 |
+
//Backup shortcodes
|
1859 |
+
$tgs_temp = $shortcode_tags;
|
1860 |
+
$ret = '';
|
1861 |
+
if ( !is_string($tag) || empty($tag) ) {
|
1862 |
+
return $ret;
|
1863 |
+
}
|
1864 |
+
//Modify
|
1865 |
+
$shortcode_tags = array( $tag => null );
|
1866 |
+
//Build pattern
|
1867 |
+
$ret = get_shortcode_regex();
|
1868 |
+
//Restore shortcodes
|
1869 |
+
$shortcode_tags = $tgs_temp;
|
1870 |
+
|
1871 |
+
return $ret;
|
1872 |
+
}
|
1873 |
+
/**
|
1874 |
+
* Check if content contains shortcode
|
1875 |
+
* @param string $tag Name of shortcode to check for
|
1876 |
+
* @param string $content Content to check for shortcode
|
1877 |
+
* @return bool TRUE if content contains shortcode
|
1878 |
+
*/
|
1879 |
+
public function has_shortcode($content, $tag) {
|
1880 |
+
$ptn = $this->get_shortcode_regex($tag);
|
1881 |
+
$ret = ( is_string($content) && preg_match("/$ptn/s", $content) == 1 ) ? true : false;
|
1882 |
+
return $ret;
|
1883 |
+
}
|
1884 |
+
|
1885 |
+
/**
|
1886 |
+
* Add shortcode to content
|
1887 |
+
* @param string $content Content to add shortcode to
|
1888 |
+
* @param bool $in_footer (optional) Add shortcode to head or footer of content (Default: footer)
|
1889 |
+
* @return string Modified content
|
1890 |
+
*/
|
1891 |
+
public function add_shortcode($content, $tag, $attr = null, $in_footer = true) {
|
1892 |
+
if ( !is_string($content) ) {
|
1893 |
+
$content = '';
|
1894 |
+
}
|
1895 |
+
$sc = $this->make_shortcode($tag, $attr);
|
1896 |
+
if ( !!$in_footer ) {
|
1897 |
+
$content .= $sc;
|
1898 |
+
} else {
|
1899 |
+
$content = $sc . $content;
|
1900 |
+
}
|
1901 |
+
return $content;
|
1902 |
+
}
|
1903 |
Â
}
|
js/dev/lightbox.js
DELETED
@@ -1,736 +0,0 @@
|
|
1 |
-
// -----------------------------------------------------------------------------------
|
2 |
-
//
|
3 |
-
// Simple Lightbox
|
4 |
-
// by Archetyped - http://archetyped.com/tools/simple-lightbox/
|
5 |
-
// Updated: 2010-06-11
|
6 |
-
//
|
7 |
-
// Largely based on Lightbox Slideshow v1.1
|
8 |
-
// by Justin Barkhuff - http://www.justinbarkhuff.com/lab/lightbox_slideshow/
|
9 |
-
// 2007/08/15
|
10 |
-
//
|
11 |
-
// Largely based on Lightbox v2.02
|
12 |
-
// by Lokesh Dhakar - http://huddletogether.com/projects/lightbox2/
|
13 |
-
// 2006/03/31
|
14 |
-
//
|
15 |
-
// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
|
16 |
-
//
|
17 |
-
// The code inserts html at the bottom of the page that looks similar to this:
|
18 |
-
//
|
19 |
-
// <div id="overlay"></div>
|
20 |
-
// <div id="lightbox">
|
21 |
-
// <div id="outerImageContainer">
|
22 |
-
// <div id="imageContainer">
|
23 |
-
// <img id="lightboxImage" />
|
24 |
-
// <div id="hoverNav">
|
25 |
-
// <a href="javascript:void(0);" id="prevLinkImg">« prev</a>
|
26 |
-
// <a href="javascript:void(0);" id="nextLinkImg">next »</a>
|
27 |
-
// </div>
|
28 |
-
// <div id="loading">
|
29 |
-
// <a href="javascript:void(0);" id="loadingLink">loading</a>
|
30 |
-
// </div>
|
31 |
-
// </div>
|
32 |
-
// </div>
|
33 |
-
// <div id="imageDataContainer">
|
34 |
-
// <div id="imageData">
|
35 |
-
// <div id="imageDetails">
|
36 |
-
// <span id="caption"></span>
|
37 |
-
// <span id="numberDisplay"></span>
|
38 |
-
// <span id="detailsNav">
|
39 |
-
// <a id="prevLinkDetails" href="javascript:void(0);">« prev</a>
|
40 |
-
// <a id="nextLinkDetails" href="javascript:void(0);">next »</a>
|
41 |
-
// <a id="slideShowControl" href="javascript:void(0);">stop slideshow</a>
|
42 |
-
// </span>
|
43 |
-
// </div>
|
44 |
-
// <div id="close">
|
45 |
-
// <a id="closeLink" href="javascript:void(0);">close</a>
|
46 |
-
// </div>
|
47 |
-
// </div>
|
48 |
-
// </div>
|
49 |
-
// </div>
|
50 |
-
//
|
51 |
-
// -----------------------------------------------------------------------------------
|
52 |
-
|
53 |
-
//
|
54 |
-
// Lightbox Object
|
55 |
-
//
|
56 |
-
var Lightbox = null;
|
57 |
-
(function($) {
|
58 |
-
Lightbox = {
|
59 |
-
activeImage : null,
|
60 |
-
badObjects : ['select','object','embed'],
|
61 |
-
container : null,
|
62 |
-
enableSlideshow : null,
|
63 |
-
groupName : null,
|
64 |
-
imageArray : [],
|
65 |
-
options : null,
|
66 |
-
overlayDuration : null,
|
67 |
-
overlayOpacity : null,
|
68 |
-
playSlides : null,
|
69 |
-
refTags : ['a','area'],
|
70 |
-
relAttribute : null,
|
71 |
-
resizeDuration : null,
|
72 |
-
slideShowTimer : null,
|
73 |
-
startImage : null,
|
74 |
-
|
75 |
-
//
|
76 |
-
// initialize()
|
77 |
-
// Constructor sets class properties and configuration options and
|
78 |
-
// inserts html at the bottom of the page which is used to display the shadow
|
79 |
-
// overlay and the image container.
|
80 |
-
//
|
81 |
-
initialize: function(options) {
|
82 |
-
this.options = $.extend(true, {
|
83 |
-
animate : true, // resizing animations
|
84 |
-
autoPlay : true, // should slideshow start automatically
|
85 |
-
borderSize : 10, // if you adjust the padding in the CSS, you will need to update this variable
|
86 |
-
containerID : document, // lightbox container object
|
87 |
-
enableSlideshow : true, // enable slideshow feature
|
88 |
-
googleAnalytics : false, // track individual image views using Google Analytics
|
89 |
-
imageDataLocation : 'south', // location of image caption information
|
90 |
-
initImage : '', // ID of image link to automatically launch when upon script initialization
|
91 |
-
loop : true, // whether to continuously loop slideshow images
|
92 |
-
overlayDuration : .2, // time to fade in shadow overlay
|
93 |
-
overlayOpacity : .8, // transparency of shadow overlay
|
94 |
-
prefix : '', // ID prefix for all dynamically created html elements
|
95 |
-
relAttribute : 'lightbox', // specifies the rel attribute value that triggers lightbox
|
96 |
-
resizeSpeed : 400, // controls the speed of the image resizing (milliseconds)
|
97 |
-
showGroupName : false, // show group name of images in image details
|
98 |
-
slideTime : 4, // time to display images during slideshow
|
99 |
-
strings : { // allows for localization
|
100 |
-
closeLink : 'close',
|
101 |
-
loadingMsg : 'loading',
|
102 |
-
nextLink : 'next »',
|
103 |
-
prevLink : '« prev',
|
104 |
-
startSlideshow : 'start slideshow',
|
105 |
-
stopSlideshow : 'stop slideshow',
|
106 |
-
numDisplayPrefix : 'Image',
|
107 |
-
numDisplaySeparator : 'of'
|
108 |
-
}
|
109 |
-
}, options);
|
110 |
-
|
111 |
-
if ( this.options.animate ) {
|
112 |
-
this.overlayDuration = Math.max(this.options.overlayDuration,0);
|
113 |
-
this.resizeDuration = this.options.resizeSpeed;
|
114 |
-
} else {
|
115 |
-
this.overlayDuration = 0;
|
116 |
-
this.resizeDuration = 0;
|
117 |
-
}
|
118 |
-
|
119 |
-
this.enableSlideshow = this.options.enableSlideshow;
|
120 |
-
this.overlayOpacity = Math.max(Math.min(this.options.overlayOpacity,1),0);
|
121 |
-
this.playSlides = this.options.autoPlay;
|
122 |
-
this.container = $(this.options.containerID);
|
123 |
-
this.relAttribute = this.options.relAttribute;
|
124 |
-
this.updateImageList();
|
125 |
-
var t = this;
|
126 |
-
var objBody = $(this.container).get(0) != document ? this.container : $('body');
|
127 |
-
|
128 |
-
var objOverlay = $('<div/>', {
|
129 |
-
'id': this.getID('overlay'),
|
130 |
-
'css': {'display': 'none'}
|
131 |
-
}).appendTo(objBody)
|
132 |
-
.click(function() {t.end()});
|
133 |
-
|
134 |
-
var objLightbox = $('<div/>', {
|
135 |
-
'id': this.getID('lightbox'),
|
136 |
-
'css': {'display': 'none'}
|
137 |
-
}).appendTo(objBody)
|
138 |
-
.click(function() {t.end()});
|
139 |
-
|
140 |
-
var objImageDataContainer = $('<div/>', {
|
141 |
-
'id': this.getID('imageDataContainer'),
|
142 |
-
'class': this.getID('clearfix')
|
143 |
-
}).click(function(ev) {ev.stopPropagation();});
|
144 |
-
|
145 |
-
var objImageData = $('<div/>', {
|
146 |
-
'id': this.getID('imageData')
|
147 |
-
}).appendTo(objImageDataContainer);
|
148 |
-
|
149 |
-
var objImageDetails = $('<div/>', {
|
150 |
-
'id': this.getID('imageDetails')
|
151 |
-
}).appendTo(objImageData);
|
152 |
-
|
153 |
-
var objCaption = $('<span/>', {
|
154 |
-
'id': this.getID('caption')
|
155 |
-
}).appendTo(objImageDetails);
|
156 |
-
|
157 |
-
var objNumberDisplay = $('<span/>', {
|
158 |
-
'id': this.getID('numberDisplay')
|
159 |
-
}).appendTo(objImageDetails);
|
160 |
-
|
161 |
-
var objDetailsNav = $('<span/>', {
|
162 |
-
'id': this.getID('detailsNav')
|
163 |
-
}).appendTo(objImageDetails);
|
164 |
-
|
165 |
-
var objPrevLink = $('<a/>', {
|
166 |
-
'id': this.getID('prevLinkDetails'),
|
167 |
-
'href': 'javascript:void(0);',
|
168 |
-
'html': this.options.strings.prevLink
|
169 |
-
}).appendTo(objDetailsNav)
|
170 |
-
.click(function() {t.showPrev()});
|
171 |
-
|
172 |
-
var objNextLink = $('<a/>', {
|
173 |
-
'id': this.getID('nextLinkDetails'),
|
174 |
-
'href': 'javascript:void(0);',
|
175 |
-
'html': this.options.strings.nextLink
|
176 |
-
}).appendTo(objDetailsNav)
|
177 |
-
.click(function() {t.showNext()});
|
178 |
-
|
179 |
-
var objSlideShowControl = $('<a/>', {
|
180 |
-
'id': this.getID('slideShowControl'),
|
181 |
-
'href': 'javascript:void(0);'
|
182 |
-
}).appendTo(objDetailsNav)
|
183 |
-
.click(function() {t.toggleSlideShow()});
|
184 |
-
|
185 |
-
var objClose = $('<div/>', {
|
186 |
-
'id': this.getID('close')
|
187 |
-
}).appendTo(objImageData);
|
188 |
-
|
189 |
-
var objCloseLink = $('<a/>', {
|
190 |
-
'id': this.getID('closeLink'),
|
191 |
-
'href': 'javascript:void(0);',
|
192 |
-
'html': this.options.strings.closeLink
|
193 |
-
}).appendTo(objClose)
|
194 |
-
.click(function() {t.end()});
|
195 |
-
|
196 |
-
if (this.options.imageDataLocation == 'north') {
|
197 |
-
$(objLightbox).append(objImageDataContainer);
|
198 |
-
}
|
199 |
-
|
200 |
-
var objOuterImageContainer = $('<div/>', {
|
201 |
-
'id': this.getID('outerImageContainer')
|
202 |
-
}).appendTo(objLightbox)
|
203 |
-
.click(function(ev) {ev.stopPropagation();});
|
204 |
-
|
205 |
-
var objImageContainer = $('<div/>', {
|
206 |
-
'id': this.getID('imageContainer')
|
207 |
-
}).appendTo(objOuterImageContainer);
|
208 |
-
|
209 |
-
var objLightboxImage = $('<img/>', {
|
210 |
-
'id': this.getID('lightboxImage')
|
211 |
-
}).appendTo(objImageContainer);
|
212 |
-
|
213 |
-
var objHoverNav = $('<div/>', {
|
214 |
-
'id': this.getID('hoverNav')
|
215 |
-
}).appendTo(objImageContainer);
|
216 |
-
|
217 |
-
var objPrevLinkImg = $('<a/>', {
|
218 |
-
'id': this.getID('prevLinkImg'),
|
219 |
-
'href': 'javascript:void(0);'
|
220 |
-
}).appendTo(objHoverNav)
|
221 |
-
.click(function() {t.showPrev()});
|
222 |
-
|
223 |
-
var objNextLinkImg = $('<a/>', {
|
224 |
-
'id': this.getID('nextLinkImg'),
|
225 |
-
'href': 'javascript:void(0);'
|
226 |
-
}).appendTo(objHoverNav)
|
227 |
-
.click(function() {t.showNext()});
|
228 |
-
|
229 |
-
var objLoading = $('<div/>', {
|
230 |
-
'id': this.getID('loading')
|
231 |
-
}).appendTo(objImageContainer);
|
232 |
-
|
233 |
-
var objLoadingLink = $('<a/>', {
|
234 |
-
'id': this.getID('loadingLink'),
|
235 |
-
'href': 'javascript:void(0);',
|
236 |
-
'html': this.options.strings.loadingMsg
|
237 |
-
}).appendTo(objLoading)
|
238 |
-
.click(function() {t.end()});
|
239 |
-
|
240 |
-
if (this.options.imageDataLocation != 'north') {
|
241 |
-
$(objLightbox).append(objImageDataContainer);
|
242 |
-
}
|
243 |
-
|
244 |
-
if (this.options.initImage != '') {
|
245 |
-
this.start($(this.options.initImage));
|
246 |
-
}
|
247 |
-
},
|
248 |
-
|
249 |
-
//
|
250 |
-
// updateImageList()
|
251 |
-
// Loops through specific tags within 'container' looking for
|
252 |
-
// 'lightbox' references and applies onclick events to them.
|
253 |
-
//
|
254 |
-
updateImageList: function() {
|
255 |
-
var el, els, rel;
|
256 |
-
var t = this;
|
257 |
-
for(var i=0; i < this.refTags.length; i++) {
|
258 |
-
els = $(this.container).find(this.refTags[i]);
|
259 |
-
for(var j=0; j < els.length; j++) {
|
260 |
-
el = els[j];
|
261 |
-
rel = $(el).attr('rel');
|
262 |
-
if ($(el).attr('href') && (rel.toLowerCase().match(this.relAttribute))) {
|
263 |
-
$(el).click(function() {
|
264 |
-
t.start(this);
|
265 |
-
return false;
|
266 |
-
});
|
267 |
-
}
|
268 |
-
}
|
269 |
-
}
|
270 |
-
},
|
271 |
-
|
272 |
-
getCaption: function(imageLink) {
|
273 |
-
imageLink = $(imageLink);
|
274 |
-
var caption = imageLink.attr('title') || '';
|
275 |
-
if ( caption == '' ) {
|
276 |
-
var inner = $(imageLink).find('img').first();
|
277 |
-
if ( $(inner).length )
|
278 |
-
caption = $(inner).attr('title') || $(inner).attr('alt');
|
279 |
-
if ( !caption )
|
280 |
-
caption = imageLink.text() || imageLink.attr('href') || '';
|
281 |
-
}
|
282 |
-
return caption;
|
283 |
-
},
|
284 |
-
|
285 |
-
//
|
286 |
-
// start()
|
287 |
-
// Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
|
288 |
-
//
|
289 |
-
start: function(imageLink) {
|
290 |
-
imageLink = $(imageLink);
|
291 |
-
this.hideBadObjects();
|
292 |
-
|
293 |
-
// stretch overlay to fill page and fade in
|
294 |
-
var pageSize = this.getPageSize();
|
295 |
-
this.getEl('overlay')
|
296 |
-
.height(pageSize.pageHeight)
|
297 |
-
.fadeTo(this.overlayDuration, this.overlayOpacity);
|
298 |
-
|
299 |
-
this.imageArray = [];
|
300 |
-
this.groupName = null;
|
301 |
-
|
302 |
-
var rel = $(imageLink).attr('rel');
|
303 |
-
var imageTitle = '';
|
304 |
-
|
305 |
-
// if image is NOT part of a group..
|
306 |
-
if (rel == this.relAttribute) {
|
307 |
-
// add single image to imageArray
|
308 |
-
imageTitle = this.getCaption(imageLink);
|
309 |
-
this.imageArray.push({'link':$(imageLink).attr('href'), 'title':imageTitle});
|
310 |
-
this.startImage = 0;
|
311 |
-
} else {
|
312 |
-
// if image is part of a group..
|
313 |
-
|
314 |
-
var els = $(this.container).find($(imageLink).get(0).tagName.toLowerCase());
|
315 |
-
// loop through anchors, find other images in group, and add them to imageArray
|
316 |
-
for (var i=0; i < els.length; i++) {
|
317 |
-
var el = $(els[i]);
|
318 |
-
if (el.attr('href') && (el.attr('rel') == rel)) {
|
319 |
-
imageTitle = this.getCaption(el);
|
320 |
-
this.imageArray.push({'link':el.attr('href'),'title':imageTitle});
|
321 |
-
if ($(el).get(0) == $(imageLink).get(0)) {
|
322 |
-
this.startImage = this.imageArray.length - 1;
|
323 |
-
}
|
324 |
-
}
|
325 |
-
}
|
326 |
-
// get group name
|
327 |
-
this.groupName = rel.substring(this.relAttribute.length + 1, rel.length - 1);
|
328 |
-
}
|
329 |
-
|
330 |
-
// calculate top offset for the lightbox and display
|
331 |
-
var pageScroll = this.getPageScroll();
|
332 |
-
var lightboxTop = pageScroll.y + (pageSize.winHeight / 15);
|
333 |
-
|
334 |
-
this.getEl('lightbox').css('top', lightboxTop + 'px').show();
|
335 |
-
this.changeImage(this.startImage);
|
336 |
-
},
|
337 |
-
|
338 |
-
//
|
339 |
-
// changeImage()
|
340 |
-
// Hide most elements and preload image in preparation for resizing image container.
|
341 |
-
//
|
342 |
-
changeImage: function(imageNum) {
|
343 |
-
this.activeImage = imageNum;
|
344 |
-
|
345 |
-
this.disableKeyboardNav();
|
346 |
-
this.pauseSlideShow();
|
347 |
-
|
348 |
-
// hide elements during transition
|
349 |
-
this.getEl('loading').show();
|
350 |
-
this.getEl('lightboxImage').hide();
|
351 |
-
this.getEl('hoverNav').hide();
|
352 |
-
this.getEl('imageDataContainer').hide();
|
353 |
-
this.getEl('numberDisplay').hide();
|
354 |
-
this.getEl('detailsNav').hide();
|
355 |
-
var imgPreloader = new Image();
|
356 |
-
var t = this;
|
357 |
-
// once image is preloaded, resize image container
|
358 |
-
$(imgPreloader).bind('load', function() {
|
359 |
-
t.getEl('lightboxImage').attr('src', imgPreloader.src);
|
360 |
-
t.resizeImageContainer(imgPreloader.width, imgPreloader.height);
|
361 |
-
//Restart slideshow if active
|
362 |
-
if ( t.isSlideShowActive() )
|
363 |
-
t.startSlideshow();
|
364 |
-
});
|
365 |
-
|
366 |
-
imgPreloader.src = this.imageArray[this.activeImage].link;
|
367 |
-
|
368 |
-
if (this.options.googleAnalytics) {
|
369 |
-
urchinTracker(this.imageArray[this.activeImage].link);
|
370 |
-
}
|
371 |
-
},
|
372 |
-
|
373 |
-
//
|
374 |
-
// resizeImageContainer()
|
375 |
-
//
|
376 |
-
resizeImageContainer: function(imgWidth, imgHeight) {
|
377 |
-
// get current height and width
|
378 |
-
var el = this.getEl('outerImageContainer');
|
379 |
-
var borderSize = this.options.borderSize * 2;
|
380 |
-
|
381 |
-
this.getEl('outerImageContainer').animate({width: imgWidth + borderSize, height: imgHeight + borderSize}, this.resizeDuration)
|
382 |
-
|
383 |
-
this.getEl('prevLinkImg').height(imgHeight);
|
384 |
-
this.getEl('nextLinkImg').height(imgHeight);
|
385 |
-
this.getEl('imageDataContainer').width(imgWidth + borderSize)
|
386 |
-
|
387 |
-
this.showImage();
|
388 |
-
},
|
389 |
-
|
390 |
-
//
|
391 |
-
// showImage()
|
392 |
-
// Display image and begin preloading neighbors.
|
393 |
-
//
|
394 |
-
showImage: function() {
|
395 |
-
this.getEl('loading').hide();
|
396 |
-
var t = this;
|
397 |
-
this.getEl('lightboxImage').fadeIn(500, function() { t.updateDetails(); });
|
398 |
-
this.preloadNeighborImages();
|
399 |
-
},
|
400 |
-
|
401 |
-
//
|
402 |
-
// updateDetails()
|
403 |
-
// Display caption, image number, and bottom nav.
|
404 |
-
//
|
405 |
-
updateDetails: function() {
|
406 |
-
this.getEl('caption').text(this.imageArray[this.activeImage].title);
|
407 |
-
this.getEl('caption').show();
|
408 |
-
|
409 |
-
// if image is part of set display 'Image x of y'
|
410 |
-
if (this.hasImages()) {
|
411 |
-
var num_display = this.options.strings.numDisplayPrefix + ' ' + eval(this.activeImage + 1) + ' ' + this.options.strings.numDisplaySeparator + ' ' + this.imageArray.length;
|
412 |
-
if (this.options.showGroupName && this.groupName != '') {
|
413 |
-
num_display += ' ' + this.options.strings.numDisplaySeparator + ' ' + this.groupName;
|
414 |
-
}
|
415 |
-
this.getEl('numberDisplay')
|
416 |
-
.text(num_display)
|
417 |
-
.show();
|
418 |
-
if (!this.enableSlideshow) {
|
419 |
-
this.getEl('slideShowControl').hide();
|
420 |
-
}
|
421 |
-
this.getEl('detailsNav').show();
|
422 |
-
}
|
423 |
-
|
424 |
-
var t = this;
|
425 |
-
this.getEl('imageDataContainer').animate({height: 'toggle', opacity: 'toggle'}, 650, function() {t.updateNav();});
|
426 |
-
},
|
427 |
-
|
428 |
-
//
|
429 |
-
// updateNav()
|
430 |
-
// Display appropriate previous and next hover navigation.
|
431 |
-
//
|
432 |
-
updateNav: function() {
|
433 |
-
if (this.hasImages()) {
|
434 |
-
this.getEl('hoverNav').show();
|
435 |
-
if (this.enableSlideshow) {
|
436 |
-
if (this.playSlides) {
|
437 |
-
this.startSlideShow();
|
438 |
-
} else {
|
439 |
-
this.stopSlideShow();
|
440 |
-
}
|
441 |
-
}
|
442 |
-
}
|
443 |
-
this.enableKeyboardNav();
|
444 |
-
},
|
445 |
-
|
446 |
-
isSlideShowActive: function() {
|
447 |
-
return this.playSlides;
|
448 |
-
},
|
449 |
-
|
450 |
-
//
|
451 |
-
// startSlideShow()
|
452 |
-
// Starts the slide show
|
453 |
-
//
|
454 |
-
startSlideShow: function() {
|
455 |
-
this.playSlides = true;
|
456 |
-
var t = this;
|
457 |
-
this.slideShowTimer = setInterval(function() { t.showNext(); t.pauseSlideShow(); }, this.options.slideTime * 1000);
|
458 |
-
this.getEl('slideShowControl').text(this.options.strings.stopSlideshow);
|
459 |
-
},
|
460 |
-
|
461 |
-
//
|
462 |
-
// stopSlideShow()
|
463 |
-
// Stops the slide show
|
464 |
-
//
|
465 |
-
stopSlideShow: function() {
|
466 |
-
this.playSlides = false;
|
467 |
-
if (this.slideShowTimer) {
|
468 |
-
clearInterval(this.slideShowTimer);
|
469 |
-
}
|
470 |
-
this.getEl('slideShowControl').text(this.options.strings.startSlideshow);
|
471 |
-
},
|
472 |
-
|
473 |
-
//
|
474 |
-
// stopSlideShow()
|
475 |
-
// Stops the slide show
|
476 |
-
//
|
477 |
-
toggleSlideShow: function() {
|
478 |
-
if (this.playSlides) {
|
479 |
-
this.stopSlideShow();
|
480 |
-
}else{
|
481 |
-
this.startSlideShow();
|
482 |
-
}
|
483 |
-
},
|
484 |
-
|
485 |
-
//
|
486 |
-
// pauseSlideShow()
|
487 |
-
// Pauses the slide show (doesn't change the value of this.playSlides)
|
488 |
-
//
|
489 |
-
pauseSlideShow: function() {
|
490 |
-
if (this.slideShowTimer) {
|
491 |
-
clearInterval(this.slideShowTimer);
|
492 |
-
}
|
493 |
-
},
|
494 |
-
|
495 |
-
hasImage: function() {
|
496 |
-
return ( this.imageArray.length > 0 );
|
497 |
-
},
|
498 |
-
|
499 |
-
hasImages: function() {
|
500 |
-
return ( this.imageArray.length > 1 );
|
501 |
-
},
|
502 |
-
|
503 |
-
isFirstImage: function() {
|
504 |
-
return ( this.activeImage == 0 );
|
505 |
-
},
|
506 |
-
|
507 |
-
isLastImage: function() {
|
508 |
-
return ( this.activeImage == this.imageArray.length - 1 );
|
509 |
-
},
|
510 |
-
|
511 |
-
//
|
512 |
-
// showNext()
|
513 |
-
// Display the next image in a group
|
514 |
-
//
|
515 |
-
showNext : function() {
|
516 |
-
if (this.hasImages()) {
|
517 |
-
if ( !this.options.loop && this.isLastImage() ) {
|
518 |
-
return this.end();
|
519 |
-
}
|
520 |
-
if ( this.isLastImage() ) {
|
521 |
-
this.showFirst();
|
522 |
-
} else {
|
523 |
-
this.changeImage(this.activeImage + 1);
|
524 |
-
}
|
525 |
-
}
|
526 |
-
},
|
527 |
-
|
528 |
-
//
|
529 |
-
// showPrev()
|
530 |
-
// Display the next image in a group
|
531 |
-
//
|
532 |
-
showPrev : function() {
|
533 |
-
if (this.hasImages()) {
|
534 |
-
if ( !this.options.loop && this.isFirstImage() )
|
535 |
-
return this.end();
|
536 |
-
if (this.activeImage == 0) {
|
537 |
-
this.showLast();
|
538 |
-
} else {
|
539 |
-
this.changeImage(this.activeImage - 1);
|
540 |
-
}
|
541 |
-
}
|
542 |
-
},
|
543 |
-
|
544 |
-
//
|
545 |
-
// showFirst()
|
546 |
-
// Display the first image in a group
|
547 |
-
//
|
548 |
-
showFirst : function() {
|
549 |
-
if (this.hasImages()) {
|
550 |
-
this.changeImage(0);
|
551 |
-
}
|
552 |
-
},
|
553 |
-
|
554 |
-
//
|
555 |
-
// showFirst()
|
556 |
-
// Display the first image in a group
|
557 |
-
//
|
558 |
-
showLast : function() {
|
559 |
-
if (this.hasImages()) {
|
560 |
-
this.changeImage(this.imageArray.length - 1);
|
561 |
-
}
|
562 |
-
},
|
563 |
-
|
564 |
-
//
|
565 |
-
// enableKeyboardNav()
|
566 |
-
//
|
567 |
-
enableKeyboardNav: function() {
|
568 |
-
document.onkeydown = this.keyboardAction;
|
569 |
-
},
|
570 |
-
|
571 |
-
//
|
572 |
-
// disableKeyboardNav()
|
573 |
-
//
|
574 |
-
disableKeyboardNav: function() {
|
575 |
-
document.onkeydown = '';
|
576 |
-
},
|
577 |
-
|
578 |
-
//
|
579 |
-
// keyboardAction()
|
580 |
-
//
|
581 |
-
keyboardAction: function(e) {
|
582 |
-
if (e == null) { // ie
|
583 |
-
keycode = event.keyCode;
|
584 |
-
} else { // mozilla
|
585 |
-
keycode = e.which;
|
586 |
-
}
|
587 |
-
|
588 |
-
key = String.fromCharCode(keycode).toLowerCase();
|
589 |
-
var t = this;
|
590 |
-
|
591 |
-
if (key == 'x' || key == 'o' || key == 'c') { // close lightbox
|
592 |
-
t.end();
|
593 |
-
} else if (key == 'p' || key == '%') { // display previous image
|
594 |
-
t.showPrev();
|
595 |
-
} else if (key == 'n' || key =='\'') { // display next image
|
596 |
-
t.showNext();
|
597 |
-
} else if (key == 'f') { // display first image
|
598 |
-
t.showFirst();
|
599 |
-
} else if (key == 'l') { // display last image
|
600 |
-
t.showLast();
|
601 |
-
} else if (key == 's') { // toggle slideshow
|
602 |
-
if (t.hasImage() && t.options.enableSlideshow) {
|
603 |
-
t.toggleSlideShow();
|
604 |
-
}
|
605 |
-
}
|
606 |
-
},
|
607 |
-
|
608 |
-
//
|
609 |
-
// preloadNeighborImages()
|
610 |
-
// Preload previous and next images.
|
611 |
-
//
|
612 |
-
preloadNeighborImages: function() {
|
613 |
-
var nextImageID = this.imageArray.length - 1 == this.activeImage ? 0 : this.activeImage + 1;
|
614 |
-
nextImage = new Image();
|
615 |
-
nextImage.src = this.imageArray[nextImageID].link;
|
616 |
-
|
617 |
-
var prevImageID = this.activeImage == 0 ? this.imageArray.length - 1 : this.activeImage - 1;
|
618 |
-
prevImage = new Image();
|
619 |
-
prevImage.src = this.imageArray[prevImageID].link;
|
620 |
-
},
|
621 |
-
|
622 |
-
//
|
623 |
-
// end()
|
624 |
-
//
|
625 |
-
end: function() {
|
626 |
-
this.disableKeyboardNav();
|
627 |
-
this.pauseSlideShow();
|
628 |
-
this.getEl('lightbox').hide();
|
629 |
-
this.getEl('overlay').fadeOut(this.overlayDuration);
|
630 |
-
this.showBadObjects();
|
631 |
-
},
|
632 |
-
|
633 |
-
//
|
634 |
-
// showBadObjects()
|
635 |
-
//
|
636 |
-
showBadObjects: function (show) {
|
637 |
-
show = ( typeof(show) == 'undefined' ) ? true : !!show;
|
638 |
-
var vis = (show) ? 'visible' : 'hidden';
|
639 |
-
$(this.badObjects.join(',')).css('visibility', vis);
|
640 |
-
},
|
641 |
-
|
642 |
-
//
|
643 |
-
// hideBadObjects()
|
644 |
-
//
|
645 |
-
hideBadObjects: function () {
|
646 |
-
this.showBadObjects(false);
|
647 |
-
},
|
648 |
-
|
649 |
-
//
|
650 |
-
// pause(numberMillis)
|
651 |
-
// Pauses code execution for specified time. Uses busy code, not good.
|
652 |
-
// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
|
653 |
-
//
|
654 |
-
pause: function(numberMillis) {
|
655 |
-
var now = new Date();
|
656 |
-
var exitTime = now.getTime() + numberMillis;
|
657 |
-
while(true) {
|
658 |
-
now = new Date();
|
659 |
-
if (now.getTime() > exitTime)
|
660 |
-
return;
|
661 |
-
}
|
662 |
-
},
|
663 |
-
|
664 |
-
//
|
665 |
-
// getPageScroll()
|
666 |
-
// Returns array with x,y page scroll values.
|
667 |
-
// Core code from - quirksmode.org
|
668 |
-
//
|
669 |
-
getPageScroll: function() {
|
670 |
-
var x,y;
|
671 |
-
if (self.pageYOffset) {
|
672 |
-
x = self.pageXOffset;
|
673 |
-
y = self.pageYOffset;
|
674 |
-
} else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
|
675 |
-
x = document.documentElement.scrollLeft;
|
676 |
-
y = document.documentElement.scrollTop;
|
677 |
-
} else if (document.body) {// all other Explorers
|
678 |
-
x = document.body.scrollLeft;
|
679 |
-
y = document.body.scrollTop;
|
680 |
-
}
|
681 |
-
return {x:x,y:y};
|
682 |
-
},
|
683 |
-
|
684 |
-
//
|
685 |
-
// getPageSize()
|
686 |
-
// Returns array with page width, height and window width, height
|
687 |
-
// Core code from - quirksmode.org
|
688 |
-
// Edit for Firefox by pHaez
|
689 |
-
//
|
690 |
-
getPageSize: function() {
|
691 |
-
var scrollX,scrollY,windowX,windowY,pageX,pageY;
|
692 |
-
if (window.innerHeight && window.scrollMaxY) {
|
693 |
-
scrollX = document.body.scrollWidth;
|
694 |
-
scrollY = window.innerHeight + window.scrollMaxY;
|
695 |
-
} else if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
|
696 |
-
scrollX = document.body.scrollWidth;
|
697 |
-
scrollY = document.body.scrollHeight;
|
698 |
-
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
|
699 |
-
scrollX = document.body.offsetWidth;
|
700 |
-
scrollY = document.body.offsetHeight;
|
701 |
-
}
|
702 |
-
|
703 |
-
if (self.innerHeight) { // all except Explorer
|
704 |
-
windowX = self.innerWidth;
|
705 |
-
windowY = self.innerHeight;
|
706 |
-
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
|
707 |
-
windowX = document.documentElement.clientWidth;
|
708 |
-
windowY = document.documentElement.clientHeight;
|
709 |
-
} else if (document.body) { // other Explorers
|
710 |
-
windowX = document.body.clientWidth;
|
711 |
-
windowY = document.body.clientHeight;
|
712 |
-
}
|
713 |
-
|
714 |
-
pageY = (scrollY < windowY) ? windowY : scrollY; // for small pages with total height less then height of the viewport
|
715 |
-
pageX = (scrollX < windowX) ? windowX : scrollX; // for small pages with total width less then width of the viewport
|
716 |
-
|
717 |
-
return {pageWidth:pageX,pageHeight:pageY,winWidth:windowX,winHeight:windowY};
|
718 |
-
},
|
719 |
-
|
720 |
-
//
|
721 |
-
// getID()
|
722 |
-
// Returns formatted Lightbox element ID
|
723 |
-
//
|
724 |
-
getID: function(id) {
|
725 |
-
return this.options.prefix+id;
|
726 |
-
},
|
727 |
-
|
728 |
-
getSel: function(id) {
|
729 |
-
return '#' + this.getID(id);
|
730 |
-
},
|
731 |
-
|
732 |
-
getEl: function(id) {
|
733 |
-
return $(this.getSel(id));
|
734 |
-
}
|
735 |
-
}
|
736 |
-
})(jQuery);
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
js/lib.js
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
var Lightbox=null;
|
2 |
-
(function(c){Lightbox={activeImage:null,badObjects:["select","object","embed"],container:null,enableSlideshow:null,groupName:null,imageArray:[],options:null,overlayDuration:null,overlayOpacity:null,playSlides:null,refTags:["a","area"],relAttribute:null,resizeDuration:null,slideShowTimer:null,startImage:null,initialize:function(a){this.options=c.extend(true,{animate:true,autoPlay:true,borderSize:10,containerID:document,enableSlideshow:true,googleAnalytics:false,imageDataLocation:"south",initImage:"",
|
3 |
-
loop:true,overlayDuration:0.2,overlayOpacity:0.8,prefix:"",relAttribute:"lightbox",resizeSpeed:400,showGroupName:false,slideTime:4,strings:{closeLink:"close",loadingMsg:"loading",nextLink:"next »",prevLink:"« prev",startSlideshow:"start slideshow",stopSlideshow:"stop slideshow",numDisplayPrefix:"Image",numDisplaySeparator:"of"}},a);if(this.options.animate){this.overlayDuration=Math.max(this.options.overlayDuration,0);this.resizeDuration=this.options.resizeSpeed}else this.resizeDuration=
|
4 |
-
this.overlayDuration=0;this.enableSlideshow=this.options.enableSlideshow;this.overlayOpacity=Math.max(Math.min(this.options.overlayOpacity,1),0);this.playSlides=this.options.autoPlay;this.container=c(this.options.containerID);this.relAttribute=this.options.relAttribute;this.updateImageList();var b=this;a=c(this.container).get(0)!=document?this.container:c("body");c("<div/>",{id:this.getID("overlay"),css:{display:"none"}}).appendTo(a).click(function(){b.end()});a=c("<div/>",{id:this.getID("lightbox"),
|
5 |
-
css:{display:"none"}}).appendTo(a).click(function(){b.end()});var d=c("<div/>",{id:this.getID("imageDataContainer"),"class":this.getID("clearfix")}).click(function(g){g.stopPropagation()}),e=c("<div/>",{id:this.getID("imageData")}).appendTo(d),f=c("<div/>",{id:this.getID("imageDetails")}).appendTo(e);c("<span/>",{id:this.getID("caption")}).appendTo(f);c("<span/>",{id:this.getID("numberDisplay")}).appendTo(f);f=c("<span/>",{id:this.getID("detailsNav")}).appendTo(f);c("<a/>",{id:this.getID("prevLinkDetails"),
|
6 |
-
href:"javascript:void(0);",html:this.options.strings.prevLink}).appendTo(f).click(function(){b.showPrev()});c("<a/>",{id:this.getID("nextLinkDetails"),href:"javascript:void(0);",html:this.options.strings.nextLink}).appendTo(f).click(function(){b.showNext()});c("<a/>",{id:this.getID("slideShowControl"),href:"javascript:void(0);"}).appendTo(f).click(function(){b.toggleSlideShow()});e=c("<div/>",{id:this.getID("close")}).appendTo(e);c("<a/>",{id:this.getID("closeLink"),href:"javascript:void(0);",html:this.options.strings.closeLink}).appendTo(e).click(function(){b.end()});
|
7 |
-
this.options.imageDataLocation=="north"&&c(a).append(d);e=c("<div/>",{id:this.getID("outerImageContainer")}).appendTo(a).click(function(g){g.stopPropagation()});e=c("<div/>",{id:this.getID("imageContainer")}).appendTo(e);c("<img/>",{id:this.getID("lightboxImage")}).appendTo(e);f=c("<div/>",{id:this.getID("hoverNav")}).appendTo(e);c("<a/>",{id:this.getID("prevLinkImg"),href:"javascript:void(0);"}).appendTo(f).click(function(){b.showPrev()});c("<a/>",{id:this.getID("nextLinkImg"),href:"javascript:void(0);"}).appendTo(f).click(function(){b.showNext()});
|
8 |
-
e=c("<div/>",{id:this.getID("loading")}).appendTo(e);c("<a/>",{id:this.getID("loadingLink"),href:"javascript:void(0);",html:this.options.strings.loadingMsg}).appendTo(e).click(function(){b.end()});this.options.imageDataLocation!="north"&&c(a).append(d);this.options.initImage!=""&&this.start(c(this.options.initImage))},updateImageList:function(){for(var a,b,d,e=this,f=0;f<this.refTags.length;f++){b=c(this.container).find(this.refTags[f]);for(var g=0;g<b.length;g++){a=b[g];d=c(a).attr("rel");c(a).attr("href")&&
|
9 |
-
d.toLowerCase().match(this.relAttribute)&&c(a).click(function(){e.start(this);return false})}}},getCaption:function(a){a=c(a);var b=a.attr("title")||"";if(b==""){var d=c(a).find("img").first();if(c(d).length)b=c(d).attr("title")||c(d).attr("alt");b||(b=a.text()||a.attr("href")||"")}return b},start:function(a){a=c(a);this.hideBadObjects();var b=this.getPageSize();this.getEl("overlay").height(b.pageHeight).fadeTo(this.overlayDuration,this.overlayOpacity);this.imageArray=[];this.groupName=null;var d=
|
10 |
-
c(a).attr("rel"),e="";if(d==this.relAttribute){e=this.getCaption(a);this.imageArray.push({link:c(a).attr("href"),title:e});this.startImage=0}else{for(var f=c(this.container).find(c(a).get(0).tagName.toLowerCase()),g=0;g<f.length;g++){var h=c(f[g]);if(h.attr("href")&&h.attr("rel")==d){e=this.getCaption(h);this.imageArray.push({link:h.attr("href"),title:e});if(c(h).get(0)==c(a).get(0))this.startImage=this.imageArray.length-1}}this.groupName=d.substring(this.relAttribute.length+1,d.length-1)}a=this.getPageScroll().y+
|
11 |
-
b.winHeight/15;this.getEl("lightbox").css("top",a+"px").show();this.changeImage(this.startImage)},changeImage:function(a){this.activeImage=a;this.disableKeyboardNav();this.pauseSlideShow();this.getEl("loading").show();this.getEl("lightboxImage").hide();this.getEl("hoverNav").hide();this.getEl("imageDataContainer").hide();this.getEl("numberDisplay").hide();this.getEl("detailsNav").hide();var b=new Image,d=this;c(b).bind("load",function(){d.getEl("lightboxImage").attr("src",b.src);d.resizeImageContainer(b.width,
|
12 |
-
b.height);d.isSlideShowActive()&&d.startSlideshow()});b.src=this.imageArray[this.activeImage].link;this.options.googleAnalytics&&urchinTracker(this.imageArray[this.activeImage].link)},resizeImageContainer:function(a,b){this.getEl("outerImageContainer");var d=this.options.borderSize*2;this.getEl("outerImageContainer").animate({width:a+d,height:b+d},this.resizeDuration);this.getEl("prevLinkImg").height(b);this.getEl("nextLinkImg").height(b);this.getEl("imageDataContainer").width(a+d);this.showImage()},
|
13 |
-
showImage:function(){this.getEl("loading").hide();var a=this;this.getEl("lightboxImage").fadeIn(500,function(){a.updateDetails()});this.preloadNeighborImages()},updateDetails:function(){this.getEl("caption").text(this.imageArray[this.activeImage].title);this.getEl("caption").show();if(this.hasImages()){var a=this.options.strings.numDisplayPrefix+" "+eval(this.activeImage+1)+" "+this.options.strings.numDisplaySeparator+" "+this.imageArray.length;if(this.options.showGroupName&&this.groupName!="")a+=
|
14 |
-
" "+this.options.strings.numDisplaySeparator+" "+this.groupName;this.getEl("numberDisplay").text(a).show();this.enableSlideshow||this.getEl("slideShowControl").hide();this.getEl("detailsNav").show()}var b=this;this.getEl("imageDataContainer").animate({height:"toggle",opacity:"toggle"},650,function(){b.updateNav()})},updateNav:function(){if(this.hasImages()){this.getEl("hoverNav").show();if(this.enableSlideshow)this.playSlides?this.startSlideShow():this.stopSlideShow()}this.enableKeyboardNav()},isSlideShowActive:function(){return this.playSlides},
|
15 |
-
startSlideShow:function(){this.playSlides=true;var a=this;this.slideShowTimer=setInterval(function(){a.showNext();a.pauseSlideShow()},this.options.slideTime*1E3);this.getEl("slideShowControl").text(this.options.strings.stopSlideshow)},stopSlideShow:function(){this.playSlides=false;this.slideShowTimer&&clearInterval(this.slideShowTimer);this.getEl("slideShowControl").text(this.options.strings.startSlideshow)},toggleSlideShow:function(){this.playSlides?this.stopSlideShow():this.startSlideShow()},pauseSlideShow:function(){this.slideShowTimer&&
|
16 |
-
clearInterval(this.slideShowTimer)},hasImage:function(){return this.imageArray.length>0},hasImages:function(){return this.imageArray.length>1},isFirstImage:function(){return this.activeImage==0},isLastImage:function(){return this.activeImage==this.imageArray.length-1},showNext:function(){if(this.hasImages()){if(!this.options.loop&&this.isLastImage())return this.end();this.isLastImage()?this.showFirst():this.changeImage(this.activeImage+1)}},showPrev:function(){if(this.hasImages()){if(!this.options.loop&&
|
17 |
-
this.isFirstImage())return this.end();this.activeImage==0?this.showLast():this.changeImage(this.activeImage-1)}},showFirst:function(){this.hasImages()&&this.changeImage(0)},showLast:function(){this.hasImages()&&this.changeImage(this.imageArray.length-1)},enableKeyboardNav:function(){document.onkeydown=this.keyboardAction},disableKeyboardNav:function(){document.onkeydown=""},keyboardAction:function(a){keycode=a==null?event.keyCode:a.which;key=String.fromCharCode(keycode).toLowerCase();if(key=="x"||
|
18 |
-
key=="o"||key=="c")this.end();else if(key=="p"||key=="%")this.showPrev();else if(key=="n"||key=="'")this.showNext();else if(key=="f")this.showFirst();else if(key=="l")this.showLast();else key=="s"&&this.hasImage()&&this.options.enableSlideshow&&this.toggleSlideShow()},preloadNeighborImages:function(){var a=this.imageArray.length-1==this.activeImage?0:this.activeImage+1;nextImage=new Image;nextImage.src=this.imageArray[a].link;a=this.activeImage==0?this.imageArray.length-1:this.activeImage-1;prevImage=
|
19 |
-
new Image;prevImage.src=this.imageArray[a].link},end:function(){this.disableKeyboardNav();this.pauseSlideShow();this.getEl("lightbox").hide();this.getEl("overlay").fadeOut(this.overlayDuration);this.showBadObjects()},showBadObjects:function(a){c(this.badObjects.join(",")).css("visibility",(typeof a=="undefined"?true:!!a)?"visible":"hidden")},hideBadObjects:function(){this.showBadObjects(false)},pause:function(a){var b=new Date;for(a=b.getTime()+a;;){b=new Date;if(b.getTime()>a)return}},getPageScroll:function(){var a,
|
20 |
-
b;if(self.pageYOffset){a=self.pageXOffset;b=self.pageYOffset}else if(document.documentElement&&document.documentElement.scrollTop){a=document.documentElement.scrollLeft;b=document.documentElement.scrollTop}else if(document.body){a=document.body.scrollLeft;b=document.body.scrollTop}return{x:a,y:b}},getPageSize:function(){var a,b,d,e;if(window.innerHeight&&window.scrollMaxY){a=document.body.scrollWidth;b=window.innerHeight+window.scrollMaxY}else if(document.body.scrollHeight>document.body.offsetHeight){a=
|
21 |
-
document.body.scrollWidth;b=document.body.scrollHeight}else{a=document.body.offsetWidth;b=document.body.offsetHeight}if(self.innerHeight){d=self.innerWidth;e=self.innerHeight}else if(document.documentElement&&document.documentElement.clientHeight){d=document.documentElement.clientWidth;e=document.documentElement.clientHeight}else if(document.body){d=document.body.clientWidth;e=document.body.clientHeight}return{pageWidth:a<d?d:a,pageHeight:b<e?e:b,winWidth:d,winHeight:e}},getID:function(a){return this.options.prefix+
|
22 |
-
a},getSel:function(a){return"#"+this.getID(a)},getEl:function(a){return c(this.getSel(a))}}})(jQuery);
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
l10n/simple-lightbox-tr_TR.mo
ADDED
Binary file
|
l10n/simple-lightbox-tr_TR.po
ADDED
@@ -0,0 +1,163 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# Copyright (C) 2010
|
2 |
+
# This file is distributed under the same license as the package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: Simple-Lightbox\n"
|
6 |
+
"Report-Msgid-Bugs-To: http://wordpress.org/tag/simple-lightbox\n"
|
7 |
+
"POT-Creation-Date: 2011-10-14 03:38:17+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2011-11-21 19:22-1000\n"
|
12 |
+
"Last-Translator: Archetyped <contact@archetyped.com>\n"
|
13 |
+
"Language-Team: <support@lettoblog.com>\n"
|
14 |
+
"X-Poedit-Country: Turkey\n"
|
15 |
+
|
16 |
+
#: model.php:88
|
17 |
+
msgid "Activation"
|
18 |
+
msgstr "EtkinleÅŸtirme"
|
19 |
+
|
20 |
+
#: model.php:89
|
21 |
+
msgid "Grouping"
|
22 |
+
msgstr "Gruplama"
|
23 |
+
|
24 |
+
#: model.php:90
|
25 |
+
msgid "UI"
|
26 |
+
msgstr "UI"
|
27 |
+
|
28 |
+
#: model.php:91
|
29 |
+
msgid "Labels"
|
30 |
+
msgstr "Etiketler"
|
31 |
+
|
32 |
+
#: model.php:94
|
33 |
+
msgid "Enable Lightbox Functionality"
|
34 |
+
msgstr "Lightbox FonksiyonelliÄŸini EtkinleÅŸtir"
|
35 |
+
|
36 |
+
#: model.php:95
|
37 |
+
msgid "Enable on Home page"
|
38 |
+
msgstr "Anasayfa'da etkin"
|
39 |
+
|
40 |
+
#: model.php:96
|
41 |
+
msgid "Enable on Posts"
|
42 |
+
msgstr "Gönderi Sayfasında Etkin"
|
43 |
+
|
44 |
+
#: model.php:97
|
45 |
+
msgid "Enable on Pages"
|
46 |
+
msgstr "Sayfalarda Etkin"
|
47 |
+
|
48 |
+
#: model.php:98
|
49 |
+
msgid "Enable on Archive Pages (tags, categories, etc.)"
|
50 |
+
msgstr "Arşiv Sayfalarında Etkin (etiketler, kategoriler, gibi.)"
|
51 |
+
|
52 |
+
#: model.php:99
|
53 |
+
msgid "Enable backwards-compatibility with legacy lightbox links"
|
54 |
+
msgstr "Eski lightbox bağlantılar ile geri- uyumluluk etkinleştir"
|
55 |
+
|
56 |
+
#: model.php:100
|
57 |
+
msgid "Activate image attachment links"
|
58 |
+
msgstr "Resimlerdeki bağlantıları etkinleştir"
|
59 |
+
|
60 |
+
#: model.php:101
|
61 |
+
msgid "Validate links"
|
62 |
+
msgstr "Bağlantı kontrolü"
|
63 |
+
|
64 |
+
#: model.php:102
|
65 |
+
msgid "Group image links (for displaying as a slideshow)"
|
66 |
+
msgstr "Grup resimleri bağlantıları (slayt gösterisi olarak yayınlamak için)"
|
67 |
+
|
68 |
+
#: model.php:103
|
69 |
+
msgid "Group image links by Post (e.g. on pages with multiple posts)"
|
70 |
+
msgstr "Grup resimleri linki (örneğin, birden fazla ileti ile sayfalarda)"
|
71 |
+
|
72 |
+
#: model.php:104
|
73 |
+
msgid "Group gallery links separately"
|
74 |
+
msgstr "Grup galeri linkleri (ayrı ayrı)"
|
75 |
+
|
76 |
+
#: model.php:105
|
77 |
+
msgid "Theme"
|
78 |
+
msgstr "Tema"
|
79 |
+
|
80 |
+
#: model.php:106
|
81 |
+
msgid "Animate lightbox resizing"
|
82 |
+
msgstr "Lightbox yeniden boyutlandırma efekti"
|
83 |
+
|
84 |
+
#: model.php:107
|
85 |
+
msgid "Automatically Start Slideshow"
|
86 |
+
msgstr "Otomatik olarak Slayt gösterisi"
|
87 |
+
|
88 |
+
#: model.php:108
|
89 |
+
msgid "Slide Duration (Seconds)"
|
90 |
+
msgstr "Slayt Süresi (Saniye)"
|
91 |
+
|
92 |
+
#: model.php:109
|
93 |
+
msgid "Loop through images"
|
94 |
+
msgstr "Döngü görüntüleri üzerinden"
|
95 |
+
|
96 |
+
#: model.php:110
|
97 |
+
msgid "Overlay Opacity (0 - 1)"
|
98 |
+
msgstr ""
|
99 |
+
|
100 |
+
#: model.php:111
|
101 |
+
msgid "Enable caption"
|
102 |
+
msgstr "Balığı etkinleştir"
|
103 |
+
|
104 |
+
#: model.php:112
|
105 |
+
msgid "Use image URI as caption when link title not set"
|
106 |
+
msgstr ""
|
107 |
+
|
108 |
+
#: model.php:113
|
109 |
+
msgid "Enable description"
|
110 |
+
msgstr "Açıklama etkin"
|
111 |
+
|
112 |
+
#: model.php:114
|
113 |
+
msgid "Close link (for accessibility only, image used for button)"
|
114 |
+
msgstr ""
|
115 |
+
|
116 |
+
#: model.php:115
|
117 |
+
msgid "Loading indicator"
|
118 |
+
msgstr "Yükleniyor göstergesi"
|
119 |
+
|
120 |
+
#: model.php:116
|
121 |
+
msgid "Next Image link"
|
122 |
+
msgstr "Sonraki Görselin linki"
|
123 |
+
|
124 |
+
#: model.php:117
|
125 |
+
msgid "Previous Image link"
|
126 |
+
msgstr "Önceki Resme bağlantı"
|
127 |
+
|
128 |
+
#: model.php:118
|
129 |
+
msgid "Start Slideshow link"
|
130 |
+
msgstr "Slay gösterisine başlama linki"
|
131 |
+
|
132 |
+
#: model.php:119
|
133 |
+
msgid "Stop Slideshow link"
|
134 |
+
msgstr "Slayt gösterisini durdurma linki"
|
135 |
+
|
136 |
+
#: model.php:120
|
137 |
+
msgid "Image number prefix (e.g. <strong>Image</strong> x of y)"
|
138 |
+
msgstr "Görsel numaraları öneki (örn. <strong>Image</strong> x of y)"
|
139 |
+
|
140 |
+
#: model.php:121
|
141 |
+
msgid "Image number separator (e.g. Image x <strong>of</strong> y)"
|
142 |
+
msgstr "Görsel numaralarını ayırıcı (örn. Image x <strong>of</strong> y)"
|
143 |
+
|
144 |
+
#: model.php:728
|
145 |
+
msgid "Settings"
|
146 |
+
msgstr "Ayarlar"
|
147 |
+
|
148 |
+
#: model.php:729
|
149 |
+
msgid "Reset"
|
150 |
+
msgstr "Sıfırla"
|
151 |
+
|
152 |
+
#: model.php:730
|
153 |
+
msgid "Are you sure you want to reset your settings?"
|
154 |
+
msgstr "Ayarlarınızı sıfırlamak istediğinizden emin misiniz?"
|
155 |
+
|
156 |
+
#: model.php:746
|
157 |
+
msgid "You do not have sufficient permissions to manage plugins for this blog."
|
158 |
+
msgstr "Bu blogun eklentileri yönetmek için yeterli izinlere sahip değilsiniz."
|
159 |
+
|
160 |
+
#: model.php:796
|
161 |
+
msgid "Lightbox Settings"
|
162 |
+
msgstr "Lightbox Ayarları"
|
163 |
+
|
l10n/simple-lightbox.pot
ADDED
@@ -0,0 +1,218 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# Copyright (C) 2013
|
2 |
+
# This file is distributed under the same license as the package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: \n"
|
6 |
+
"Report-Msgid-Bugs-To: https://github.com/archetyped/simple-lightbox/wiki/Reporting-Issues\n"
|
7 |
+
"POT-Creation-Date: 2013-04-16 00:22:28+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2013-MO-DA HO:MI+ZONE\n"
|
12 |
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
+
|
15 |
+
#: includes/class.admin.php:686
|
16 |
+
msgid "The settings have been reset"
|
17 |
+
msgstr ""
|
18 |
+
|
19 |
+
#: includes/class.admin.php:687
|
20 |
+
msgid "<strong class=\"%1$s\">Notice:</strong> This update is a <strong class=\"%1$s\">Beta version</strong>. It is highly recommended that you test the update on a test server before updating the plugin on a production server."
|
21 |
+
msgstr ""
|
22 |
+
|
23 |
+
#: includes/class.admin.php:688 includes/class.admin.php:1394
|
24 |
+
#: includes/class.admin.php:1443 includes/class.admin.php:1531
|
25 |
+
msgid "Access Denied"
|
26 |
+
msgstr ""
|
27 |
+
|
28 |
+
#: includes/class.admin.php:1318
|
29 |
+
msgid "Save Changes"
|
30 |
+
msgstr ""
|
31 |
+
|
32 |
+
#: includes/class.fields.php:2223
|
33 |
+
msgid "Default Element"
|
34 |
+
msgstr ""
|
35 |
+
|
36 |
+
#: includes/class.fields.php:2235
|
37 |
+
msgid "Default Element (Closed Tag)"
|
38 |
+
msgstr ""
|
39 |
+
|
40 |
+
#: includes/class.fields.php:2243
|
41 |
+
msgid "Default Input Element"
|
42 |
+
msgstr ""
|
43 |
+
|
44 |
+
#: includes/class.fields.php:2251
|
45 |
+
msgid "Text Box"
|
46 |
+
msgstr ""
|
47 |
+
|
48 |
+
#: includes/class.fields.php:2282
|
49 |
+
msgid "Hidden Field"
|
50 |
+
msgstr ""
|
51 |
+
|
52 |
+
#: includes/class.fields.php:2288
|
53 |
+
msgid "Select tag"
|
54 |
+
msgstr ""
|
55 |
+
|
56 |
+
#: includes/class.fields.php:2300
|
57 |
+
msgid "Inline wrapper"
|
58 |
+
msgstr ""
|
59 |
+
|
60 |
+
#: includes/class.options.php:115
|
61 |
+
msgid "Enabled"
|
62 |
+
msgstr ""
|
63 |
+
|
64 |
+
#: includes/class.options.php:115
|
65 |
+
msgid "Disabled"
|
66 |
+
msgstr ""
|
67 |
+
|
68 |
+
#: includes/class.options.php:400
|
69 |
+
msgid "Default"
|
70 |
+
msgstr ""
|
71 |
+
|
72 |
+
#: includes/class.themes.php:41
|
73 |
+
msgid "Theme"
|
74 |
+
msgstr ""
|
75 |
+
|
76 |
+
#: includes/class.themes.php:61
|
77 |
+
msgid "Default (Light)"
|
78 |
+
msgstr ""
|
79 |
+
|
80 |
+
#: includes/class.themes.php:67
|
81 |
+
msgid "Default (Dark)"
|
82 |
+
msgstr ""
|
83 |
+
|
84 |
+
#: model.php:151
|
85 |
+
msgid "Activation"
|
86 |
+
msgstr ""
|
87 |
+
|
88 |
+
#: model.php:152
|
89 |
+
msgid "Grouping"
|
90 |
+
msgstr ""
|
91 |
+
|
92 |
+
#: model.php:153
|
93 |
+
msgid "UI"
|
94 |
+
msgstr ""
|
95 |
+
|
96 |
+
#: model.php:154
|
97 |
+
msgid "Labels"
|
98 |
+
msgstr ""
|
99 |
+
|
100 |
+
#: model.php:157
|
101 |
+
msgid "Enable Lightbox Functionality"
|
102 |
+
msgstr ""
|
103 |
+
|
104 |
+
#: model.php:158
|
105 |
+
msgid "Enable on Home page"
|
106 |
+
msgstr ""
|
107 |
+
|
108 |
+
#: model.php:159
|
109 |
+
msgid "Enable on Posts"
|
110 |
+
msgstr ""
|
111 |
+
|
112 |
+
#: model.php:160
|
113 |
+
msgid "Enable on Pages"
|
114 |
+
msgstr ""
|
115 |
+
|
116 |
+
#: model.php:161
|
117 |
+
msgid "Enable on Archive Pages (tags, categories, etc.)"
|
118 |
+
msgstr ""
|
119 |
+
|
120 |
+
#: model.php:162
|
121 |
+
msgid "Enable for Widgets"
|
122 |
+
msgstr ""
|
123 |
+
|
124 |
+
#: model.php:163
|
125 |
+
msgid "Group items (for displaying as a slideshow)"
|
126 |
+
msgstr ""
|
127 |
+
|
128 |
+
#: model.php:164
|
129 |
+
msgid "Group items by Post (e.g. on pages with multiple posts)"
|
130 |
+
msgstr ""
|
131 |
+
|
132 |
+
#: model.php:165
|
133 |
+
msgid "Group gallery items separately"
|
134 |
+
msgstr ""
|
135 |
+
|
136 |
+
#: model.php:166
|
137 |
+
msgid "Group widget items separately"
|
138 |
+
msgstr ""
|
139 |
+
|
140 |
+
#: model.php:167
|
141 |
+
msgid "Resize lightbox to fit in window"
|
142 |
+
msgstr ""
|
143 |
+
|
144 |
+
#: model.php:168
|
145 |
+
msgid "Enable animations"
|
146 |
+
msgstr ""
|
147 |
+
|
148 |
+
#: model.php:169
|
149 |
+
msgid "Start Slideshow Automatically"
|
150 |
+
msgstr ""
|
151 |
+
|
152 |
+
#: model.php:170
|
153 |
+
msgid "Slide Duration (Seconds)"
|
154 |
+
msgstr ""
|
155 |
+
|
156 |
+
#: model.php:171
|
157 |
+
msgid "Loop through items"
|
158 |
+
msgstr ""
|
159 |
+
|
160 |
+
#: model.php:172
|
161 |
+
msgid "Overlay Opacity (0 - 1)"
|
162 |
+
msgstr ""
|
163 |
+
|
164 |
+
#: model.php:173
|
165 |
+
msgid "Loading indicator"
|
166 |
+
msgstr ""
|
167 |
+
|
168 |
+
#: model.php:174
|
169 |
+
msgid "Close button"
|
170 |
+
msgstr ""
|
171 |
+
|
172 |
+
#: model.php:175
|
173 |
+
msgid "Next Item button"
|
174 |
+
msgstr ""
|
175 |
+
|
176 |
+
#: model.php:176
|
177 |
+
msgid "Previous Item button"
|
178 |
+
msgstr ""
|
179 |
+
|
180 |
+
#: model.php:177
|
181 |
+
msgid "Start Slideshow button"
|
182 |
+
msgstr ""
|
183 |
+
|
184 |
+
#: model.php:178
|
185 |
+
msgid "Stop Slideshow button"
|
186 |
+
msgstr ""
|
187 |
+
|
188 |
+
#: model.php:179
|
189 |
+
msgid "Slideshow status format"
|
190 |
+
msgstr ""
|
191 |
+
|
192 |
+
#: model.php:228
|
193 |
+
msgid "Lightbox"
|
194 |
+
msgstr ""
|
195 |
+
|
196 |
+
#: model.php:229
|
197 |
+
msgid "Lightbox Settings"
|
198 |
+
msgstr ""
|
199 |
+
|
200 |
+
#: model.php:230
|
201 |
+
msgid "Settings"
|
202 |
+
msgstr ""
|
203 |
+
|
204 |
+
#: model.php:234
|
205 |
+
msgid "Reset"
|
206 |
+
msgstr ""
|
207 |
+
|
208 |
+
#: model.php:235
|
209 |
+
msgid "Are you sure you want to reset settings?"
|
210 |
+
msgstr ""
|
211 |
+
|
212 |
+
#: model.php:236
|
213 |
+
msgid "Settings have been reset"
|
214 |
+
msgstr ""
|
215 |
+
|
216 |
+
#: model.php:237
|
217 |
+
msgid "Settings were not reset"
|
218 |
+
msgstr ""
|
main.php
CHANGED
@@ -1,14 +1,14 @@
|
|
1 |
Â
<?php
|
2 |
Â
/*
|
3 |
-
Plugin Name: Simple Lightbox
|
4 |
-
Plugin URI: http://archetyped.com/
|
5 |
-
Description:
|
6 |
-
Version:
|
7 |
Â
Author: Archetyped
|
8 |
Â
Author URI: http://archetyped.com
|
9 |
Â
*/
|
10 |
Â
/*
|
11 |
-
Copyright
|
12 |
Â
|
13 |
Â
This program is free software; you can redistribute it and/or
|
14 |
Â
modify it under the terms of the GNU General Public License
|
@@ -25,13 +25,33 @@ along with this program; if not, write to the Free Software
|
|
25 |
Â
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
26 |
Â
*/
|
27 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
28 |
Â
require_once 'model.php';
|
29 |
Â
|
30 |
-
$slb
|
31 |
Â
|
32 |
-
function
|
33 |
Â
global $slb;
|
34 |
-
|
35 |
-
}
|
36 |
-
|
37 |
-
?>
|
1 |
Â
<?php
|
2 |
Â
/*
|
3 |
+
Plugin Name: Simple Lightbox
|
4 |
+
Plugin URI: http://archetyped.com/lab/slb-2-0rc4/
|
5 |
+
Description: The highly customizable lightbox for WordPress
|
6 |
+
Version: 2.0
|
7 |
Â
Author: Archetyped
|
8 |
Â
Author URI: http://archetyped.com
|
9 |
Â
*/
|
10 |
Â
/*
|
11 |
+
Copyright 2013 Solomon Marchessault (sol@archetyped.com)
|
12 |
Â
|
13 |
Â
This program is free software; you can redistribute it and/or
|
14 |
Â
modify it under the terms of the GNU General Public License
|
25 |
Â
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
26 |
Â
*/
|
27 |
Â
|
28 |
+
/**
|
29 |
+
* Class loading handler
|
30 |
+
* @param string $classname Class to load
|
31 |
+
*/
|
32 |
+
function slb_autoload($classname) {
|
33 |
+
$prefix = 'SLB_';
|
34 |
+
//Remove prefix
|
35 |
+
if ( 0 !== strpos($classname, $prefix) ) {
|
36 |
+
return false;
|
37 |
+
}
|
38 |
+
//Format class for filename
|
39 |
+
$fn = 'class.' . strtolower( substr($classname, strlen($prefix)) ) . '.php';
|
40 |
+
//Build path
|
41 |
+
$path = dirname(__FILE__) . '/' . "includes/" . $fn;
|
42 |
+
//Load file
|
43 |
+
if ( is_readable($path) ) {
|
44 |
+
require $path;
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
spl_autoload_register('slb_autoload');
|
49 |
+
|
50 |
Â
require_once 'model.php';
|
51 |
Â
|
52 |
+
$slb = new SLB_Lightbox();
|
53 |
Â
|
54 |
+
function slb_register_theme($name, $title, $stylesheet_url, $layout) {
|
55 |
Â
global $slb;
|
56 |
+
$slb->register_theme($name, $title, $stylesheet_url, $layout);
|
57 |
+
}
|
Â
|
|
Â
|
model.php
CHANGED
@@ -1,9 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
-
require_once 'includes/class.base.php';
|
4 |
-
|
5 |
Â
/**
|
6 |
-
*
|
7 |
Â
* @package Simple Lightbox
|
8 |
Â
* @author Archetyped
|
9 |
Â
*/
|
@@ -11,487 +9,1089 @@ class SLB_Lightbox extends SLB_Base {
|
|
11 |
Â
|
12 |
Â
/*-** Properties **-*/
|
13 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
14 |
Â
/**
|
15 |
-
*
|
16 |
-
* @var
|
17 |
Â
*/
|
18 |
-
|
19 |
Â
|
20 |
Â
/**
|
21 |
-
*
|
22 |
-
* @var
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
23 |
Â
*/
|
24 |
-
var $
|
25 |
Â
|
26 |
Â
/**
|
27 |
-
*
|
28 |
-
*
|
29 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
30 |
Â
* @var array
|
31 |
Â
*/
|
32 |
-
var $
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
'autostart' => array(true, 'Automatically Start Slideshow'),
|
45 |
-
'duration' => array(6, 'Slide Duration (Seconds)', array('size' => 3, 'maxlength' => 3)),
|
46 |
-
'loop' => array(true, 'Loop through images'),
|
47 |
-
'overlay_opacity' => array(0.8, 'Overlay Opacity (0 - 1)', array('size' => 3, 'maxlength' => 3)),
|
48 |
-
'header_strings' => 'Labels',
|
49 |
-
'txt_closeLink' => array('close', 'Close link (for accessibility only, image used for button)'),
|
50 |
-
'txt_loadingMsg' => array('loading', 'Loading indicator'),
|
51 |
-
'txt_nextLink' => array('next »', 'Next Image link'),
|
52 |
-
'txt_prevLink' => array('« prev', 'Previous Image link'),
|
53 |
-
'txt_startSlideshow' => array('start slideshow', 'Start Slideshow link'),
|
54 |
-
'txt_stopSlideshow' => array('stop slideshow', 'Stop Slideshow link'),
|
55 |
-
'txt_numDisplayPrefix' => array('Image', 'Image number prefix (e.g. <strong>Image</strong> x of y)'),
|
56 |
-
'txt_numDisplaySeparator' => array('of', 'Image number separator (e.g. Image x <strong>of</strong> y)')
|
57 |
-
);
|
58 |
Â
|
59 |
-
|
60 |
Â
|
61 |
-
|
62 |
-
|
63 |
-
|
Â
|
|
Â
|
|
64 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
65 |
Â
function __construct() {
|
66 |
Â
parent::__construct();
|
67 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
68 |
Â
}
|
69 |
Â
|
70 |
-
|
71 |
-
$this->register_hooks();
|
72 |
-
}
|
73 |
Â
|
74 |
-
|
75 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
76 |
Â
/* Admin */
|
77 |
-
|
78 |
-
add_action('admin_init', $this->m('admin_settings'));
|
79 |
-
//Enqueue header files (CSS/JS)
|
80 |
-
add_action('admin_enqueue_scripts', $this->m('admin_enqueue_files'));
|
81 |
-
//Reset Settings
|
82 |
-
add_action('admin_action_' . $this->add_prefix('reset'), $this->m('admin_reset'));
|
83 |
-
add_action('admin_notices', $this->m('admin_notices'));
|
84 |
Â
|
85 |
Â
/* Client-side */
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
91 |
Â
}
|
92 |
Â
|
93 |
-
|
94 |
-
|
95 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
96 |
Â
}
|
Â
|
|
Â
|
|
97 |
Â
|
Â
|
|
Â
|
|
98 |
Â
/**
|
99 |
-
*
|
100 |
-
* @
|
101 |
Â
*/
|
102 |
-
function
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
110 |
Â
}
|
111 |
-
|
112 |
-
/*-**
|
113 |
Â
|
114 |
Â
/**
|
115 |
Â
* Checks whether lightbox is currently enabled/disabled
|
116 |
Â
* @return bool TRUE if lightbox is currently enabled, FALSE otherwise
|
117 |
Â
*/
|
118 |
Â
function is_enabled($check_request = true) {
|
119 |
-
$ret = (
|
120 |
Â
if ( $ret && $check_request ) {
|
121 |
Â
$opt = '';
|
122 |
Â
//Determine option to check
|
123 |
Â
if ( is_home() )
|
124 |
Â
$opt = 'home';
|
125 |
-
elseif (
|
126 |
-
$opt = '
|
Â
|
|
127 |
Â
elseif ( is_archive() || is_search() )
|
128 |
Â
$opt = 'archive';
|
129 |
Â
//Check option
|
130 |
-
if ( !
|
131 |
-
$ret =
|
132 |
Â
}
|
133 |
Â
}
|
134 |
Â
return $ret;
|
135 |
Â
}
|
136 |
Â
|
137 |
Â
/**
|
138 |
-
*
|
139 |
-
* Properties:
|
140 |
-
* > id: Option ID
|
141 |
-
* > value: Option's value (uses default value if option not yet set)
|
142 |
-
* > value_default: Option's default value (formatted)
|
143 |
Â
*
|
144 |
-
*
|
145 |
-
* @
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
155 |
Â
}
|
156 |
Â
|
157 |
Â
/**
|
158 |
-
*
|
159 |
-
* @
|
160 |
-
* @
|
Â
|
|
Â
|
|
Â
|
|
161 |
Â
*/
|
162 |
-
function
|
163 |
-
|
164 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
165 |
Â
}
|
166 |
-
|
167 |
Â
/**
|
168 |
-
* Retrieve
|
169 |
-
* @param string $
|
170 |
-
* @
|
Â
|
|
171 |
Â
*/
|
172 |
-
function
|
173 |
-
$
|
174 |
-
|
175 |
-
|
176 |
-
|
Â
|
|
Â
|
|
Â
|
|
177 |
Â
}
|
178 |
Â
|
179 |
Â
/**
|
180 |
-
*
|
181 |
-
* @
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
$ret = '';
|
187 |
-
if ( isset($this->options_default[$option][0]) ) {
|
188 |
-
$ret = $this->options_default[$option][0];
|
189 |
-
//Format value (if required)
|
190 |
-
if ( $formatted ) {
|
191 |
-
if ( is_bool($ret) || ( is_string($ret) && 'on' == $ret ) )
|
192 |
-
$ret = ( $ret ) ? 'Enabled' : 'Disabled';
|
193 |
-
if ( is_numeric($ret) )
|
194 |
-
$ret = strval($ret);
|
195 |
-
$ret = htmlentities($ret);
|
196 |
-
}
|
197 |
-
} elseif ( ! is_array($this->options_default[$option]) ) {
|
198 |
-
$ret = $this->options_default[$option];
|
199 |
Â
}
|
200 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
201 |
Â
}
|
202 |
-
|
203 |
-
/*-** Frontend **-*/
|
204 |
Â
|
205 |
Â
/**
|
206 |
-
*
|
207 |
-
*
|
208 |
-
*
|
209 |
-
* @
|
210 |
Â
*/
|
211 |
-
function
|
212 |
-
|
213 |
-
if
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
227 |
Â
}
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
$
|
233 |
-
//
|
234 |
-
$
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
235 |
Â
}
|
236 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
237 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
238 |
Â
}
|
239 |
-
return $content;
|
240 |
Â
}
|
241 |
Â
|
242 |
Â
/**
|
243 |
-
*
|
Â
|
|
Â
|
|
244 |
Â
*/
|
245 |
-
function
|
246 |
-
|
247 |
-
return;
|
248 |
-
wp_enqueue_script($this->add_prefix('lib'), $this->util->get_file_url('js/lib.js'), array('jquery'));
|
249 |
-
wp_enqueue_style($this->add_prefix('lightbox_css'), $this->util->get_file_url('css/lightbox.css'));
|
250 |
Â
}
|
251 |
Â
|
252 |
Â
/**
|
253 |
-
*
|
254 |
-
* @
|
Â
|
|
255 |
Â
*/
|
256 |
-
function
|
257 |
-
|
258 |
-
return;
|
259 |
-
|
260 |
-
$options = array();
|
261 |
-
$out = array();
|
262 |
-
$out['script_start'] = '<script type="text/javascript">(function($){$(document).ready(function(){';
|
263 |
-
$out['script_end'] = '})})(jQuery);</script>';
|
264 |
-
$js_code = array();
|
265 |
-
//Activate links on page
|
266 |
-
if ( $this->get_option_value('activate_links') ) {
|
267 |
-
$rel = ( $this->get_option_value('group_links') ) ? 'lightbox[' . $this->get_prefix() . ']' : 'lightbox';
|
268 |
-
ob_start();
|
269 |
-
?>
|
270 |
-
$('a[href$=".jpg"]:not([rel~="lightbox"])','a[href$=".jpeg"]:not([rel~="lightbox"])','a[href$=".gif"]:not([rel~="lightbox"])','a[href$=".png"]:not([rel~="lightbox"])').each(function(i, el){if (! /(^|\b)lightbox\[.+\]($|\b)/i.test($(el).attr('rel'))){var rel=($(el).attr('rel').length > 0) ? $(el).attr('rel') + ' ' : '';$(el).attr('rel', =rel + '<?php echo $rel; ?>');}});
|
271 |
-
<?php
|
272 |
-
$test = ob_get_clean();
|
273 |
-
}
|
274 |
-
//Get options
|
275 |
-
$options = array(
|
276 |
-
'autoPlay' => $this->get_option_value('autostart'),
|
277 |
-
'slideTime' => $this->get_option_value('duration'),
|
278 |
-
'loop' => $this->get_option_value('loop'),
|
279 |
-
'overlayOpacity' => $this->get_option_value('overlay_opacity'),
|
280 |
-
'animate' => $this->get_option_value('animate')
|
281 |
-
);
|
282 |
-
$lb_obj = array();
|
283 |
-
foreach ($options as $option => $val) {
|
284 |
-
if ($val === TRUE || $val == 'on')
|
285 |
-
$val = 'true';
|
286 |
-
elseif ($val === FALSE || empty($val))
|
287 |
-
$val = 'false';
|
288 |
-
$lb_obj[] = "'{$option}':{$val}";
|
289 |
-
}
|
290 |
-
//Load UI Strings
|
291 |
-
if ( ($strings = $this->build_strings()) && !empty($strings) )
|
292 |
-
$lb_obj[] = $strings;
|
293 |
-
$js_code[] = 'Lightbox.initialize({' . implode(',', $lb_obj) . '});';
|
294 |
-
echo $out['script_start'] . implode('', $js_code) . $out['script_end'];
|
295 |
Â
}
|
296 |
Â
|
297 |
Â
/**
|
298 |
-
*
|
299 |
-
* @return
|
300 |
Â
*/
|
301 |
-
function
|
302 |
-
$
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
310 |
Â
}
|
311 |
-
$ret = "'strings':{" . implode(',', $strings) . "}";
|
312 |
Â
}
|
313 |
-
return $
|
314 |
Â
}
|
Â
|
|
Â
|
|
315 |
Â
|
316 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
317 |
Â
|
318 |
Â
/**
|
319 |
-
*
|
320 |
-
* @param $
|
321 |
-
* @param $
|
322 |
-
* @param $
|
323 |
-
* @
|
324 |
-
*/
|
325 |
-
function
|
326 |
-
//
|
327 |
-
|
328 |
-
|
329 |
-
$
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
array_splice($actions, 1, 0, '<a id="' . $this->add_prefix('reset') . '" href="' . $reset_link . '" onclick="return confirm(' . $reset_confirm . ');" title="' . $reset . '">' . $reset . '</a>');
|
335 |
-
}
|
336 |
-
return $actions;
|
337 |
Â
}
|
338 |
Â
|
339 |
Â
/**
|
340 |
-
*
|
341 |
-
*
|
Â
|
|
Â
|
|
342 |
Â
*/
|
343 |
-
function
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
$
|
352 |
-
|
353 |
-
wp_redirect($uri);
|
354 |
-
exit;
|
355 |
Â
}
|
Â
|
|
356 |
Â
}
|
357 |
Â
|
Â
|
|
Â
|
|
358 |
Â
/**
|
359 |
-
*
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
360 |
Â
*/
|
361 |
-
function
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
375 |
Â
}
|
376 |
Â
}
|
377 |
Â
}
|
Â
|
|
Â
|
|
378 |
Â
}
|
379 |
Â
|
380 |
Â
/**
|
381 |
-
*
|
382 |
-
*
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
383 |
Â
*/
|
384 |
-
function
|
385 |
-
|
386 |
-
$
|
387 |
-
|
388 |
-
if ( $
|
389 |
-
return;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
390 |
Â
}
|
391 |
-
|
392 |
-
$
|
393 |
-
$
|
394 |
-
//
|
395 |
-
|
396 |
-
|
397 |
-
foreach ($this->options_default as $key => $defaults) {
|
398 |
-
$id = $this->add_prefix($key);
|
399 |
-
$func = 'admin_field_' . $key;
|
400 |
-
$label = ( isset($defaults[1]) ) ? $defaults[1] : '';
|
401 |
-
$callback = ( method_exists($this, $func) ) ? $this->m($func) : $this->m('admin_field_default');
|
402 |
-
$args = array('opt' => $key);
|
403 |
-
//Check if option is a section header
|
404 |
-
if ( ! is_array($defaults) ) {
|
405 |
-
$label = '<h4 class="subhead">' . $defaults . '</h4>';
|
406 |
-
$callback = $this->m('admin_field_header');
|
407 |
-
} elseif ( is_null(get_option($id, null)) ) {
|
408 |
-
//Add option to DB if not yet set
|
409 |
-
$args['label_for'] = $id;
|
410 |
-
update_option($id, htmlentities2($defaults[0]));
|
411 |
-
}
|
412 |
-
add_settings_field($id, __($label), $callback, $page, $section, $args);
|
413 |
-
register_setting($page, $id);
|
414 |
Â
}
|
Â
|
|
415 |
Â
}
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
420 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
421 |
Â
}
|
422 |
Â
|
423 |
Â
/**
|
424 |
-
*
|
425 |
-
* @
|
Â
|
|
Â
|
|
426 |
Â
*/
|
427 |
-
function
|
428 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
429 |
Â
}
|
430 |
Â
|
431 |
Â
/**
|
432 |
-
*
|
433 |
-
*
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
* 2. Field Value
|
445 |
-
* 3. Field Default Value (formatted)
|
446 |
-
* 4. Field Type
|
447 |
-
*/
|
448 |
-
function admin_the_field($option, $format = '', $type = '') {
|
449 |
-
$opt = $this->get_option($option);
|
450 |
-
$format_default = '<input id="%1$s" name="%1$s" %4$s class="code" /> (Default: %3$s)';
|
451 |
-
if ( empty($format) && $format !== false )
|
452 |
-
$format = $format_default;
|
453 |
-
if ( empty($type) || !is_string($type) ) {
|
454 |
-
$type_default = 'text';
|
455 |
-
$type = ( is_bool($opt->value_default) ) ? 'checkbox' : $type_default;
|
456 |
-
}
|
457 |
-
//Adjust type and value formatting based on type
|
458 |
-
switch ( $type ) {
|
459 |
-
case 'checkbox' :
|
460 |
-
if ( $opt->value )
|
461 |
-
$opt->attr['checked'] = 'checked';
|
462 |
-
break;
|
463 |
-
case 'text' :
|
464 |
-
if ( $format == $format_default )
|
465 |
-
$format = str_replace('%4$s', '%4$s value="%2$s"', $format);
|
466 |
-
break;
|
467 |
-
}
|
468 |
-
$opt->attr['type'] = $type;
|
469 |
-
//Build attribute string
|
470 |
-
$attr = '';
|
471 |
-
if ( ! empty($opt->attr) ) {
|
472 |
-
$attr = $this->util->build_attribute_string($opt->attr);
|
473 |
Â
}
|
474 |
-
|
475 |
-
|
Â
|
|
Â
|
|
476 |
Â
}
|
477 |
Â
|
478 |
Â
/**
|
479 |
-
*
|
480 |
-
*
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
481 |
Â
*/
|
482 |
-
function
|
483 |
-
$
|
484 |
-
$
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
485 |
Â
}
|
486 |
Â
|
487 |
Â
/**
|
488 |
-
*
|
489 |
-
* @
|
490 |
Â
*/
|
491 |
-
function
|
492 |
-
$
|
493 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
494 |
Â
}
|
495 |
-
}
|
496 |
-
|
497 |
-
?>
|
1 |
Â
<?php
|
2 |
Â
|
Â
|
|
Â
|
|
3 |
Â
/**
|
4 |
+
* Model (Core functionality)
|
5 |
Â
* @package Simple Lightbox
|
6 |
Â
* @author Archetyped
|
7 |
Â
*/
|
9 |
Â
|
10 |
Â
/*-** Properties **-*/
|
11 |
Â
|
12 |
+
protected $model = true;
|
13 |
+
|
14 |
+
/* Files */
|
15 |
+
|
16 |
+
var $scripts = array (
|
17 |
+
'core' => array (
|
18 |
+
'file' => 'client/js/lib.core.js',
|
19 |
+
'deps' => 'jquery',
|
20 |
+
'enqueue' => false,
|
21 |
+
'in_footer' => true,
|
22 |
+
),
|
23 |
+
'view' => array (
|
24 |
+
'file' => 'client/js/lib.view.js',
|
25 |
+
'deps' => array('jquery', '[core]'),
|
26 |
+
'context' => array( array('public', '[is_enabled]') ),
|
27 |
+
'in_footer' => true,
|
28 |
+
),
|
29 |
+
);
|
30 |
+
|
31 |
Â
/**
|
32 |
+
* Fields
|
33 |
+
* @var SLB_Fields
|
34 |
Â
*/
|
35 |
+
public $fields = null;
|
36 |
Â
|
37 |
Â
/**
|
38 |
+
* Themes collection
|
39 |
+
* @var SLB_Themes
|
40 |
+
*/
|
41 |
+
var $themes = null;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Content types
|
45 |
+
* @var SLB_Content_Handlers
|
46 |
Â
*/
|
47 |
+
var $handlers = null;
|
48 |
Â
|
49 |
Â
/**
|
50 |
+
* Template tags
|
51 |
+
* @var SLB_Template_Tags
|
52 |
+
*/
|
53 |
+
var $template_tags = null;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Properties for media attachments in current request
|
57 |
+
* > Key (string) Attachment URI
|
58 |
+
* > Value (assoc-array) Attachment properties (url, etc.)
|
59 |
+
* > source: Source URL
|
60 |
Â
* @var array
|
61 |
Â
*/
|
62 |
+
var $media_items = array();
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Raw media items
|
66 |
+
* Used for populating media object on client-side
|
67 |
+
* > Key: Item URI
|
68 |
+
* > Value: Associative array of media properties
|
69 |
+
* > type: Item type (Default: null)
|
70 |
+
* > id: Item ID (Default: null)
|
71 |
+
* @var array
|
72 |
+
*/
|
73 |
+
private $media_items_raw = array();
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
74 |
Â
|
75 |
+
/* Widget properties */
|
76 |
Â
|
77 |
+
/**
|
78 |
+
* Widget callback key
|
79 |
+
* @var string
|
80 |
+
*/
|
81 |
+
var $widget_callback = 'callback';
|
82 |
Â
|
83 |
+
/**
|
84 |
+
* Key to use to store original callback
|
85 |
+
* @var string
|
86 |
+
*/
|
87 |
+
var $widget_callback_orig = 'callback_orig';
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Used to track if widget is currently being processed or not
|
91 |
+
* @var bool
|
92 |
+
*/
|
93 |
+
var $widget_processing = false;
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Constructor
|
97 |
+
*/
|
98 |
Â
function __construct() {
|
99 |
Â
parent::__construct();
|
100 |
+
//Init instances
|
101 |
+
$this->fields = new SLB_Fields();
|
102 |
+
$this->themes = new SLB_Themes($this);
|
103 |
+
if ( !is_admin() ) {
|
104 |
+
$this->template_tags = new SLB_Template_Tags($this);
|
105 |
+
}
|
106 |
Â
}
|
107 |
Â
|
108 |
+
/* Init */
|
Â
|
|
Â
|
|
109 |
Â
|
110 |
+
/**
|
111 |
+
* Register hooks
|
112 |
+
* @uses parent::_hooks()
|
113 |
+
*/
|
114 |
+
protected function _hooks() {
|
115 |
+
parent::_hooks();
|
116 |
+
|
117 |
Â
/* Admin */
|
118 |
+
add_action('admin_menu', $this->m('admin_menus'));
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
119 |
Â
|
120 |
Â
/* Client-side */
|
121 |
+
|
122 |
+
//Init lightbox
|
123 |
+
$priority = $this->util->priority('low');
|
124 |
+
add_action('wp_footer', $this->m('client_init'), $this->util->priority('client_footer_output'));
|
125 |
+
add_action('wp_footer', $this->m('client_footer'), $priority);
|
126 |
+
//Link activation
|
127 |
+
add_filter('the_content', $this->m('activate_links'), $priority);
|
128 |
+
//Gallery wrapping
|
129 |
+
add_filter('the_content', $this->m('gallery_wrap'), 1);
|
130 |
+
add_filter('the_content', $this->m('gallery_unwrap'), $priority + 1);
|
131 |
+
|
132 |
+
/* Widgets */
|
133 |
+
add_filter('sidebars_widgets', $this->m('sidebars_widgets'));
|
134 |
Â
}
|
135 |
Â
|
136 |
+
/**
|
137 |
+
* Init options
|
138 |
+
*
|
139 |
+
*/
|
140 |
+
protected function _options() {
|
141 |
+
//Setup options
|
142 |
+
$opts = array (
|
143 |
+
'groups' => array (
|
144 |
+
'activation' => array ( 'title' => __('Activation', 'simple-lightbox'), 'priority' => 10),
|
145 |
+
'grouping' => array ( 'title' => __('Grouping', 'simple-lightbox'), 'priority' => 20),
|
146 |
+
'ui' => array ( 'title' => __('UI', 'simple-lightbox'), 'priority' => 30),
|
147 |
+
'labels' => array ( 'title' => __('Labels', 'simple-lightbox'), 'priority' => 40),
|
148 |
+
),
|
149 |
+
'items' => array (
|
150 |
+
'enabled' => array('title' => __('Enable Lightbox Functionality', 'simple-lightbox'), 'default' => true, 'group' => array('activation', 10)),
|
151 |
+
'enabled_home' => array('title' => __('Enable on Home page', 'simple-lightbox'), 'default' => true, 'group' => array('activation', 20)),
|
152 |
+
'enabled_post' => array('title' => __('Enable on Posts', 'simple-lightbox'), 'default' => true, 'group' => array('activation', 30)),
|
153 |
+
'enabled_page' => array('title' => __('Enable on Pages', 'simple-lightbox'), 'default' => true, 'group' => array('activation', 40)),
|
154 |
+
'enabled_archive' => array('title' => __('Enable on Archive Pages (tags, categories, etc.)', 'simple-lightbox'), 'default' => true, 'group' => array('activation', 50)),
|
155 |
+
'enabled_widget' => array('title' => __('Enable for Widgets', 'simple-lightbox'), 'default' => false, 'group' => array('activation', 60)),
|
156 |
+
'group_links' => array('title' => __('Group items (for displaying as a slideshow)', 'simple-lightbox'), 'default' => true, 'group' => array('grouping', 10)),
|
157 |
+
'group_post' => array('title' => __('Group items by Post (e.g. on pages with multiple posts)', 'simple-lightbox'), 'default' => true, 'group' => array('grouping', 20)),
|
158 |
+
'group_gallery' => array('title' => __('Group gallery items separately', 'simple-lightbox'), 'default' => false, 'group' => array('grouping', 30)),
|
159 |
+
'group_widget' => array('title' => __('Group widget items separately', 'simple-lightbox'), 'default' => false, 'group' => array('grouping', 40)),
|
160 |
+
'ui_autofit' => array('title' => __('Resize lightbox to fit in window', 'simple-lightbox'), 'default' => true, 'group' => array('ui', 10), 'in_client' => true),
|
161 |
+
'ui_animate' => array('title' => __('Enable animations', 'simple-lightbox'), 'default' => true, 'group' => array('ui', 20), 'in_client' => true),
|
162 |
+
'slideshow_autostart' => array('title' => __('Start Slideshow Automatically', 'simple-lightbox'), 'default' => true, 'group' => array('ui', 30), 'in_client' => true),
|
163 |
+
'slideshow_duration' => array('title' => __('Slide Duration (Seconds)', 'simple-lightbox'), 'default' => '6', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => array('ui', 40), 'in_client' => true),
|
164 |
+
'group_loop' => array('title' => __('Loop through items', 'simple-lightbox'),'default' => true, 'group' => array('ui', 50), 'in_client' => true),
|
165 |
+
'ui_overlay_opacity' => array('title' => __('Overlay Opacity (0 - 1)', 'simple-lightbox'), 'default' => '0.8', 'attr' => array('size' => 3, 'maxlength' => 3), 'group' => array('ui', 60), 'in_client' => true),
|
166 |
+
'txt_loading' => array('title' => __('Loading indicator', 'simple-lightbox'), 'default' => 'Loading', 'group' => array('labels', 20)),
|
167 |
+
'txt_close' => array('title' => __('Close button', 'simple-lightbox'), 'default' => 'Close', 'group' => array('labels', 10)),
|
168 |
+
'txt_nav_next' => array('title' => __('Next Item button', 'simple-lightbox'), 'default' => 'Next', 'group' => array('labels', 30)),
|
169 |
+
'txt_nav_prev' => array('title' => __('Previous Item button', 'simple-lightbox'), 'default' => 'Previous', 'group' => array('labels', 40)),
|
170 |
+
'txt_slideshow_start' => array('title' => __('Start Slideshow button', 'simple-lightbox'), 'default' => 'Start slideshow', 'group' => array('labels', 50)),
|
171 |
+
'txt_slideshow_stop' => array('title' => __('Stop Slideshow button', 'simple-lightbox'),'default' => 'Stop slideshow', 'group' => array('labels', 60)),
|
172 |
+
'txt_group_status' => array('title' => __('Slideshow status format', 'simple-lightbox'), 'default' => 'Item %current% of %total%', 'group' => array('labels', 70))
|
173 |
+
),
|
174 |
+
'legacy' => array (
|
175 |
+
'header_activation' => null,
|
176 |
+
'header_enabled' => null,
|
177 |
+
'header_strings' => null,
|
178 |
+
'header_ui' => null,
|
179 |
+
'activate_attachments' => null,
|
180 |
+
'validate_links' => null,
|
181 |
+
'enabled_compat' => null,
|
182 |
+
'enabled_single' => array('enabled_post', 'enabled_page'),
|
183 |
+
'enabled_caption' => null,
|
184 |
+
'enabled_desc' => null,
|
185 |
+
'ui_enabled_caption' => null,
|
186 |
+
'ui_caption_src' => null,
|
187 |
+
'ui_enabled_desc' => null,
|
188 |
+
'caption_src' => null,
|
189 |
+
'animate' => 'ui_animate',
|
190 |
+
'overlay_opacity' => 'ui_overlay_opacity',
|
191 |
+
'loop' => 'group_loop',
|
192 |
+
'autostart' => 'slideshow_autostart',
|
193 |
+
'duration' => 'slideshow_duration',
|
194 |
+
'txt_numDisplayPrefix' => null,
|
195 |
+
'txt_numDisplaySeparator' => null,
|
196 |
+
'txt_closeLink' => 'txt_link_close',
|
197 |
+
'txt_nextLink' => 'txt_link_next',
|
198 |
+
'txt_prevLink' => 'txt_link_prev',
|
199 |
+
'txt_startSlideshow' => 'txt_slideshow_start',
|
200 |
+
'txt_stopSlideshow' => 'txt_slideshow_stop',
|
201 |
+
'txt_loadingMsg' => 'txt_loading',
|
202 |
+
'txt_link_next' => 'txt_nav_next',
|
203 |
+
'txt_link_prev' => 'txt_nav_prev',
|
204 |
+
'txt_link_close' => 'txt_close',
|
205 |
+
)
|
206 |
+
);
|
207 |
+
|
208 |
+
parent::_options($opts);
|
209 |
Â
}
|
210 |
+
|
211 |
+
/* Methods */
|
212 |
Â
|
213 |
+
/*-** Admin **-*/
|
214 |
+
|
215 |
Â
/**
|
216 |
+
* Add admin menus
|
217 |
+
* @uses this->admin->add_theme_page
|
218 |
Â
*/
|
219 |
+
function admin_menus() {
|
220 |
+
$options_labels = array(
|
221 |
+
'menu' => __('Lightbox', 'simple-lightbox'),
|
222 |
+
'header' => __('Lightbox Settings', 'simple-lightbox'),
|
223 |
+
'plugin_action' => __('Settings', 'simple-lightbox')
|
224 |
+
);
|
225 |
+
|
226 |
+
$labels_reset = array (
|
227 |
+
'title' => __('Reset', 'simple-lightbox'),
|
228 |
+
'confirm' => __('Are you sure you want to reset settings?', 'simple-lightbox'),
|
229 |
+
'success' => __('Settings have been reset', 'simple-lightbox'),
|
230 |
+
'failure' => __('Settings were not reset', 'simple-lightbox')
|
231 |
+
);
|
232 |
+
|
233 |
+
$this->admin->add_theme_page('options', $options_labels, $this->options);
|
234 |
+
$this->admin->add_reset('reset', $labels_reset, $this->options);
|
235 |
Â
}
|
236 |
+
|
237 |
+
/*-** Functionality **-*/
|
238 |
Â
|
239 |
Â
/**
|
240 |
Â
* Checks whether lightbox is currently enabled/disabled
|
241 |
Â
* @return bool TRUE if lightbox is currently enabled, FALSE otherwise
|
242 |
Â
*/
|
243 |
Â
function is_enabled($check_request = true) {
|
244 |
+
$ret = ( $this->options->get_bool('enabled') && !is_feed() ) ? true : false;
|
245 |
Â
if ( $ret && $check_request ) {
|
246 |
Â
$opt = '';
|
247 |
Â
//Determine option to check
|
248 |
Â
if ( is_home() )
|
249 |
Â
$opt = 'home';
|
250 |
+
elseif ( is_singular() ) {
|
251 |
+
$opt = ( is_page() ) ? 'page' : 'post';
|
252 |
+
}
|
253 |
Â
elseif ( is_archive() || is_search() )
|
254 |
Â
$opt = 'archive';
|
255 |
Â
//Check option
|
256 |
+
if ( !empty($opt) && ( $opt = 'enabled_' . $opt ) && $this->options->has($opt) ) {
|
257 |
+
$ret = $this->options->get_bool($opt);
|
258 |
Â
}
|
259 |
Â
}
|
260 |
Â
return $ret;
|
261 |
Â
}
|
262 |
Â
|
263 |
Â
/**
|
264 |
+
* Scans post content for image links and activates them
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
265 |
Â
*
|
266 |
+
* Lightbox will not be activated for feeds
|
267 |
+
* @param $content
|
268 |
+
* @return string Post content
|
269 |
+
*/
|
270 |
+
function activate_links($content) {
|
271 |
+
//Activate links only if enabled
|
272 |
+
if ( !$this->is_enabled() ) {
|
273 |
+
return $content;
|
274 |
+
}
|
275 |
+
|
276 |
+
$groups = array();
|
277 |
+
$w = $this->group_get_wrapper();
|
278 |
+
$g_ph_f = '[%s]';
|
279 |
+
|
280 |
+
//Strip groups
|
281 |
+
if ( $this->options->get_bool('group_gallery') ) {
|
282 |
+
$groups = array();
|
283 |
+
static $g_idx = 1;
|
284 |
+
$g_end_idx = 0;
|
285 |
+
//Iterate through galleries
|
286 |
+
while ( ($g_start_idx = strpos($content, $w->open, $g_end_idx)) && $g_start_idx !== false
|
287 |
+
&& ($g_end_idx = strpos($content, $w->close, $g_start_idx)) && $g_end_idx != false ) {
|
288 |
+
$g_start_idx += strlen($w->open);
|
289 |
+
//Extract gallery content & save for processing
|
290 |
+
$g_len = $g_end_idx - $g_start_idx;
|
291 |
+
$groups[$g_idx] = substr($content, $g_start_idx, $g_len);
|
292 |
+
//Replace content with placeholder
|
293 |
+
$g_ph = sprintf($g_ph_f, $g_idx);
|
294 |
+
$content = substr_replace($content, $g_ph, $g_start_idx, $g_len);
|
295 |
+
//Increment gallery count
|
296 |
+
$g_idx++;
|
297 |
+
//Update end index
|
298 |
+
$g_end_idx = $g_start_idx + strlen($w->open);
|
299 |
+
}
|
300 |
+
}
|
301 |
+
|
302 |
+
//General link processing
|
303 |
+
$content = $this->process_links($content);
|
304 |
+
|
305 |
+
//Reintegrate Groups
|
306 |
+
foreach ( $groups as $group => $g_content ) {
|
307 |
+
$g_ph = $w->open . sprintf($g_ph_f, $group) . $w->close;
|
308 |
+
//Skip group if placeholder does not exist in content
|
309 |
+
if ( strpos($content, $g_ph) === false ) {
|
310 |
+
continue;
|
311 |
+
}
|
312 |
+
//Replace placeholder with processed content
|
313 |
+
$content = str_replace($g_ph, $w->open . $this->process_links($g_content, 'gallery_' . $group) . $w->close, $content);
|
314 |
+
}
|
315 |
+
return $content;
|
316 |
Â
}
|
317 |
Â
|
318 |
Â
/**
|
319 |
+
* Process links in content
|
320 |
+
* @global obj $wpdb DB instance
|
321 |
+
* @global obj $post Current post
|
322 |
+
* @param string $content Text containing links
|
323 |
+
* @param string (optional) $group Group to add links to (Default: none)
|
324 |
+
* @return string Content with processed links
|
325 |
Â
*/
|
326 |
+
function process_links($content, $group = null) {
|
327 |
+
//Validate
|
328 |
+
if ( !is_string($content) || empty($content) ) {
|
329 |
+
return $content;
|
330 |
+
}
|
331 |
+
//Extract links
|
332 |
+
$links = $this->get_links($content, true);
|
333 |
+
//Do not process content without links
|
334 |
+
if ( empty($links) ) {
|
335 |
+
return $content;
|
336 |
+
}
|
337 |
+
//Process links
|
338 |
+
$protocol = array('http://', 'https://');
|
339 |
+
$domain = str_replace($protocol, '', strtolower(get_bloginfo('url')));
|
340 |
+
$qv_att = 'attachment_id';
|
341 |
+
|
342 |
+
//Setup group properties
|
343 |
+
$g_props = (object) array(
|
344 |
+
'enabled' => $this->options->get_bool('group_links'),
|
345 |
+
'attr' => 'group',
|
346 |
+
'base' => '',
|
347 |
+
'legacy_prefix' => 'lightbox[',
|
348 |
+
'legacy_suffix' => ']'
|
349 |
+
);
|
350 |
+
if ( $g_props->enabled ) {
|
351 |
+
$g_props->base = ( is_scalar($group) ) ? trim(strval($group)) : '';
|
352 |
+
}
|
353 |
+
|
354 |
+
//Initialize content handlers
|
355 |
+
if ( !( $this->handlers instanceof SLB_Content_Handlers ) ) {
|
356 |
+
$this->handlers = new SLB_Content_Handlers($this);
|
357 |
+
}
|
358 |
+
|
359 |
+
//Iterate through links & add lightbox if necessary
|
360 |
+
foreach ( $links as $link ) {
|
361 |
+
//Init vars
|
362 |
+
$pid = 0;
|
363 |
+
$link_new = $link;
|
364 |
+
$internal = false;
|
365 |
+
$q = null;
|
366 |
+
$uri = (object) array('raw' => '', 'base' => '', 'source' => '');
|
367 |
+
$type = false;
|
368 |
+
|
369 |
+
//Parse link attributes
|
370 |
+
$attrs = $this->util->parse_attribute_string($link_new, array('href' => ''));
|
371 |
+
$attrs_legacy = ( isset($attrs['rel']) && !empty($attrs['rel']) ) ? explode(' ', trim($attrs['rel'])) : array();
|
372 |
+
//Get URI
|
373 |
+
$uri->raw = $uri->base = $uri->source = $attrs['href'];
|
374 |
+
|
375 |
+
//Stop processing invalid links
|
376 |
+
if ( empty($uri->raw) //Empty
|
377 |
+
|| 0 === strpos($uri->raw, '#') //Invalid
|
378 |
+
|| $this->has_attribute($attrs, 'active', false) //Prev-processed
|
379 |
+
|| in_array($this->add_prefix('off'), $attrs_legacy) //Disabled
|
380 |
+
) {
|
381 |
+
continue;
|
382 |
+
}
|
383 |
+
|
384 |
+
//Process legacy attributes
|
385 |
+
if ( !empty($attrs_legacy) ) {
|
386 |
+
//Group
|
387 |
+
if ( $g_props->enabled ) {
|
388 |
+
foreach ( $attrs_legacy as $attr ) {
|
389 |
+
if ( 0 === strpos($attr, $g_props->legacy_prefix) && substr($attr, -1) == $g_props->legacy_suffix ) {
|
390 |
+
$this->set_attribute($attrs, $g_props->attr, substr($attr, strlen($g_props->legacy_prefix), -1));
|
391 |
+
break;
|
392 |
+
}
|
393 |
+
}
|
394 |
+
unset($attr);
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
//Check if item links to internal media (attachment)
|
399 |
+
$uri_dom = str_replace($protocol, '', strtolower($uri->raw));
|
400 |
+
if ( strpos($uri_dom, $domain) === 0 ) {
|
401 |
+
//Save URL for further processing
|
402 |
+
$internal = true;
|
403 |
+
}
|
404 |
+
|
405 |
+
//Sanitize URI
|
406 |
+
$qpos = strpos($uri->raw, '?');
|
407 |
+
if ( $qpos !== false ) {
|
408 |
+
$uri->base = substr($uri->raw, 0, $qpos);
|
409 |
+
if ( $internal ) {
|
410 |
+
//Extract query string
|
411 |
+
$q = substr($uri->raw, $qpos + 1);
|
412 |
+
//Check for attachment ID
|
413 |
+
if ( strpos($q, $qv_att . '=') !== false ) {
|
414 |
+
//Parse query string
|
415 |
+
wp_parse_str($q, $q);
|
416 |
+
//Strip other variables from query string
|
417 |
+
$uri->base = add_query_arg($qv_att, $q[$qv_att], $uri->base);
|
418 |
+
}
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
//Get source URI
|
423 |
+
$uri->source = $uri->base;
|
424 |
+
if ( $internal && is_local_attachment($uri->source) ) {
|
425 |
+
$pid = url_to_postid($uri->base);
|
426 |
+
$src = wp_get_attachment_url($pid);
|
427 |
+
if ( !!$src ) {
|
428 |
+
$uri->source = $src;
|
429 |
+
}
|
430 |
+
unset($src);
|
431 |
+
}
|
432 |
+
|
433 |
+
/* Determine link type */
|
434 |
+
|
435 |
+
//Check if URI has already been processed
|
436 |
+
if ( $this->media_item_cached($uri->base) ) {
|
437 |
+
$i = $this->get_cached_media_item($uri->base);
|
438 |
+
$type = $i->type;
|
439 |
+
}
|
440 |
+
|
441 |
+
//Get handler match
|
442 |
+
else {
|
443 |
+
$handler = $this->handlers->match($uri->source);
|
444 |
+
if ( !!$handler ) {
|
445 |
+
$type = $handler->get_id();
|
446 |
+
}
|
447 |
+
}
|
448 |
+
|
449 |
+
//Stop processing if link type not valid
|
450 |
+
if ( !$type ) {
|
451 |
+
continue;
|
452 |
+
}
|
453 |
+
|
454 |
+
//Set group (if necessary)
|
455 |
+
if ( $g_props->enabled ) {
|
456 |
+
//Get preset group attribute
|
457 |
+
$g = ( $this->has_attribute($attrs, $g_props->attr) ) ? $this->get_attribute($attrs, $g_props->attr) : '';
|
458 |
+
if ( is_string($g) && ($g = trim($g)) && !empty($g) ) {
|
459 |
+
$group = $g;
|
460 |
+
} else {
|
461 |
+
$group = $g_props->base;
|
462 |
+
}
|
463 |
+
//Group links by post?
|
464 |
+
if ( !$this->widget_processing && $this->options->get_bool('group_post') ) {
|
465 |
+
global $post;
|
466 |
+
$group = ( !empty($group) ) ? implode('_', array($post->ID, $group)) : $post->ID;
|
467 |
+
}
|
468 |
+
//Default group
|
469 |
+
if ( empty($group) ) {
|
470 |
+
$group = $this->get_prefix();
|
471 |
+
}
|
472 |
+
|
473 |
+
//Set group attribute
|
474 |
+
$this->set_attribute($attrs, $g_props->attr, $group);
|
475 |
+
unset($g);
|
476 |
+
}
|
477 |
+
|
478 |
+
//Activate link
|
479 |
+
$this->set_attribute($attrs, 'active');
|
480 |
+
|
481 |
+
//Process internal links
|
482 |
+
if ( $internal ) {
|
483 |
+
//Mark as internal
|
484 |
+
$this->set_attribute($attrs, 'internal', $pid);
|
485 |
+
}
|
486 |
+
|
487 |
+
//Cache item attributes
|
488 |
+
$this->cache_media_item($uri, $type, $internal, $pid);
|
489 |
+
|
490 |
+
//Update link in content
|
491 |
+
$link_new = '<a ' . $this->util->build_attribute_string($attrs) . '>';
|
492 |
+
$content = str_replace($link, $link_new, $content);
|
493 |
+
}
|
494 |
+
return $content;
|
495 |
Â
}
|
496 |
+
|
497 |
Â
/**
|
498 |
+
* Retrieve HTML links in content
|
499 |
+
* @param string $content Content to get links from
|
500 |
+
* @param bool (optional) $unique Remove duplicates from returned links (Default: FALSE)
|
501 |
+
* @return array Links in content
|
502 |
Â
*/
|
503 |
+
function get_links($content, $unique = false) {
|
504 |
+
$rgx = "/\<a[^\>]+href=.*?\>/i";
|
505 |
+
$links = array();
|
506 |
+
preg_match_all($rgx, $content, $links);
|
507 |
+
$links = $links[0];
|
508 |
+
if ( $unique )
|
509 |
+
$links = array_unique($links);
|
510 |
+
return $links;
|
511 |
Â
}
|
512 |
Â
|
513 |
Â
/**
|
514 |
+
* Sets options/settings to initialize lightbox functionality on page load
|
515 |
+
* @return void
|
516 |
+
*/
|
517 |
+
function client_init() {
|
518 |
+
if ( ! $this->is_enabled() ) {
|
519 |
+
return;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
520 |
Â
}
|
521 |
+
echo PHP_EOL . '<!-- SLB -->' . PHP_EOL;
|
522 |
+
//Get options
|
523 |
+
$options = $this->options->build_client_output();
|
524 |
+
|
525 |
+
//Load UI Strings
|
526 |
+
if ( ($labels = $this->build_labels()) && !empty($labels) ) {
|
527 |
+
$options['ui_labels'] = $labels;
|
528 |
+
}
|
529 |
+
|
530 |
+
//Build client output
|
531 |
+
echo $this->util->build_script_element($this->util->call_client_method('View.init', $options), 'init', true, true);
|
532 |
+
echo '<!-- /SLB -->' . PHP_EOL;
|
533 |
Â
}
|
Â
|
|
Â
|
|
534 |
Â
|
535 |
Â
/**
|
536 |
+
* Output code in footer
|
537 |
+
* > Media attachment URLs
|
538 |
+
* @uses `_wp_attached_file` to match attachment ID to URI
|
539 |
+
* @uses `_wp_attachment_metadata` to retrieve attachment metadata
|
540 |
Â
*/
|
541 |
+
function client_footer() {
|
542 |
+
echo '<!-- X-M -->';
|
543 |
+
//Stop if not enabled
|
544 |
+
if ( !$this->is_enabled() ) {
|
545 |
+
return;
|
546 |
+
}
|
547 |
+
echo '<!-- SLB-M -->' . PHP_EOL;
|
548 |
+
|
549 |
+
$client_out = array();
|
550 |
+
|
551 |
+
/* Load cached media */
|
552 |
+
if ( $this->has_cached_media_items() ) {
|
553 |
+
global $wpdb;
|
554 |
+
|
555 |
+
$this->media_items = array();
|
556 |
+
$props = array('id', 'type', 'description', 'title', 'source', 'caption');
|
557 |
+
$props = (object) array_combine($props, $props);
|
558 |
+
$props_map = array('description' => 'post_content', 'title' => 'post_title', 'caption' => 'post_excerpt');
|
559 |
+
|
560 |
+
//Separate media into buckets by type
|
561 |
+
$m_bucket = array();
|
562 |
+
$m_internals = array();
|
563 |
+
$type = $id = null;
|
564 |
+
|
565 |
+
$m_items = $this->media_items = $this->get_cached_media_items();
|
566 |
+
foreach ( $m_items as $uri => $p ) {
|
567 |
+
$type = $p->{$props->type};
|
568 |
+
//Initialize bucket (if necessary)
|
569 |
+
if ( !isset($m_bucket[$type]) ) {
|
570 |
+
$m_bucket[$type] = array();
|
571 |
+
}
|
572 |
+
//Add item to bucket
|
573 |
+
$m_bucket[$type][$uri] =& $m_items[$uri];
|
574 |
+
//Set aside internal links for additional processing
|
575 |
+
if ( $p->internal && !isset($m_internals[$uri]) ) {
|
576 |
+
$m_internals[$uri] =& $m_items[$uri];
|
577 |
+
}
|
578 |
+
}
|
579 |
+
unset($uri, $p);
|
580 |
+
|
581 |
+
//Process internal links
|
582 |
+
if ( !empty($m_internals) ) {
|
583 |
+
$uris_base = array();
|
584 |
+
$uri_prefix = wp_upload_dir();
|
585 |
+
$uri_prefix = $this->util->normalize_path($uri_prefix['baseurl'], true);
|
586 |
+
foreach ( $m_internals as $uri => $p ) {
|
587 |
+
//Prepare internal links
|
588 |
+
if ( !$p->id && strpos($p->source, $uri_prefix) === 0 ) {
|
589 |
+
$uris_base[str_replace($uri_prefix, '', $p->source)] = $uri;
|
590 |
+
}
|
591 |
+
}
|
592 |
+
unset($uri, $p);
|
593 |
+
|
594 |
+
//Retrieve attachment IDs
|
595 |
+
$uris_flat = "('" . implode("','", array_keys($uris_base)) . "')";
|
596 |
+
$q = $wpdb->prepare("SELECT post_id, meta_value FROM $wpdb->postmeta WHERE `meta_key` = %s AND LOWER(`meta_value`) IN $uris_flat LIMIT %d", '_wp_attached_file', count($uris_base));
|
597 |
+
$pids = $wpdb->get_results($q);
|
598 |
+
//Match IDs to URIs
|
599 |
+
if ( $pids ) {
|
600 |
+
foreach ( $pids as $pd ) {
|
601 |
+
$file =& $pd->meta_value;
|
602 |
+
if ( isset($uris_base[$file]) ) {
|
603 |
+
$m_internals[ $uris_base[$file] ]->{$props->id} = absint($pd->post_id);
|
604 |
+
}
|
605 |
+
}
|
606 |
+
}
|
607 |
+
//Destroy worker vars
|
608 |
+
unset($uris_base, $uris_flat, $q, $pids, $pd);
|
609 |
+
}
|
610 |
+
|
611 |
+
//Process items with attachment IDs
|
612 |
+
$pids = array();
|
613 |
+
foreach ( $m_items as $uri => $p ) {
|
614 |
+
//Add post ID to query
|
615 |
+
if ( !!$p->id ) {
|
616 |
+
//Create array for ID (support multiple URIs per ID)
|
617 |
+
if ( !isset($pids[$p->id]) ) {
|
618 |
+
$pids[$p->id] = array();
|
619 |
+
}
|
620 |
+
//Add URI to ID
|
621 |
+
$pids[$p->id][] = $uri;
|
622 |
+
}
|
623 |
+
}
|
624 |
+
unset($uri, $p);
|
625 |
+
|
626 |
+
//Retrieve attachment properties
|
627 |
+
if ( !empty($pids) ) {
|
628 |
+
$pids_flat = array_keys($pids);
|
629 |
+
//Retrieve attachment post data
|
630 |
+
$atts = get_posts(array('post_type' => 'attachment', 'include' => $pids_flat));
|
631 |
+
|
632 |
+
//Process attachments
|
633 |
+
if ( $atts ) {
|
634 |
+
//Retrieve attachment metadata
|
635 |
+
$pids_flat = "('" . implode("','", $pids_flat) . "')";
|
636 |
+
$atts_meta = $wpdb->get_results($wpdb->prepare("SELECT `post_id`,`meta_value` FROM $wpdb->postmeta WHERE `post_id` IN $pids_flat AND `meta_key` = %s LIMIT %d", '_wp_attachment_metadata', count($atts)));
|
637 |
+
//Restructure metadata array by post ID
|
638 |
+
if ( $atts_meta ) {
|
639 |
+
$meta = array();
|
640 |
+
foreach ( $atts_meta as $att_meta ) {
|
641 |
+
$meta[$att_meta->post_id] = $att_meta->meta_value;
|
642 |
+
}
|
643 |
+
$atts_meta = $meta;
|
644 |
+
unset($meta);
|
645 |
+
} else {
|
646 |
+
$atts_meta = array();
|
647 |
Â
}
|
648 |
+
$props_size = array('file', 'width', 'height');
|
649 |
+
$props_exclude = array('hwstring_small');
|
650 |
+
foreach ( $atts as $att ) {
|
651 |
+
//Set post data
|
652 |
+
$m = array();
|
653 |
+
//Remap post data to properties
|
654 |
+
foreach ( $props_map as $prop_key => $prop_source ) {
|
655 |
+
$m[$props->{$prop_key}] = $att->{$prop_source};
|
656 |
+
}
|
657 |
+
unset($prop_key, $prop_source);
|
658 |
+
|
659 |
+
//Add metadata
|
660 |
+
if ( isset($atts_meta[$att->ID]) && ($a = unserialize($atts_meta[$att->ID])) && is_array($a) ) {
|
661 |
+
//Move original size into `sizes` array
|
662 |
+
foreach ( $props_size as $d ) {
|
663 |
+
if ( !isset($a[$d]) ) {
|
664 |
+
continue;
|
665 |
+
}
|
666 |
+
$a['sizes']['original'][$d] = $a[$d];
|
667 |
+
unset($a[$d]);
|
668 |
+
}
|
669 |
+
|
670 |
+
//Strip extraneous metadata
|
671 |
+
foreach ( $props_exclude as $d ) {
|
672 |
+
if ( isset($a[$d]) ) {
|
673 |
+
unset($a[$d]);
|
674 |
+
}
|
675 |
+
}
|
676 |
+
|
677 |
+
//Merge post data & meta data
|
678 |
+
$m = array_merge($a, $m);
|
679 |
+
//Destroy worker vars
|
680 |
+
unset($a, $d);
|
681 |
+
}
|
682 |
+
|
683 |
+
//Save attachment data (post & meta) to original object(s)
|
684 |
+
foreach ( $pids[$att->ID] as $uri ) {
|
685 |
+
$this->media_items[$uri] = (object) array_merge( (array) $m_items[$uri], $m);
|
686 |
+
}
|
687 |
Â
}
|
688 |
Â
}
|
689 |
+
unset($atts, $atts_meta, $m, $a, $uri, $pids, $pids_flat);
|
690 |
+
}
|
691 |
+
|
692 |
+
//Build client output
|
693 |
+
$obj = 'View.assets';
|
694 |
+
$client_out[] = $this->util->extend_client_object($obj, $this->media_items);
|
695 |
+
}
|
696 |
+
if ( !empty($client_out) ) {
|
697 |
+
echo $this->util->build_script_element($client_out, 'footer', true, true);
|
698 |
+
}
|
699 |
+
echo PHP_EOL . '<!-- /SLB-M -->' . PHP_EOL;
|
700 |
+
}
|
701 |
+
|
702 |
+
/*-** Media **-*/
|
703 |
+
|
704 |
+
/**
|
705 |
+
* Cache media properties for later processing
|
706 |
+
* @param object $uri URI to cache
|
707 |
+
* Members
|
708 |
+
* > raw: Raw Link URI
|
709 |
+
* > base: Sanitized URI
|
710 |
+
* > source: Source URI (e.g. for attachment URIs)
|
711 |
+
* @param string $type Media type (image, attachment, etc.)
|
712 |
+
* @param int $id (optional) ID of media item (for internal items) (Default: NULL)
|
713 |
+
*/
|
714 |
+
private function cache_media_item($uri, $type, $internal, $id = null) {
|
715 |
+
//Validate
|
716 |
+
if ( !is_object($uri) || !is_string($type) ) {
|
717 |
+
return false;
|
718 |
+
}
|
719 |
+
if ( !$this->media_item_cached($uri->base) ) {
|
720 |
+
//Set properties
|
721 |
+
$i = array('type' => $type, 'source' => $uri->source, 'internal' => $internal, 'id' => null, '_entries' => array());
|
722 |
+
//ID
|
723 |
+
if ( is_numeric($id) && !!$id ) {
|
724 |
+
$i['id'] = absint($id);
|
725 |
Â
}
|
726 |
+
//Cache media item
|
727 |
+
$this->media_items_raw[$uri->base] = (object) $i;
|
728 |
+
}
|
729 |
+
//Add URI variants
|
730 |
+
$entries =& $this->media_items_raw[$uri->base]->_entries;
|
731 |
+
if ( !in_array($uri->raw, $entries) ) {
|
732 |
+
$entries[] = $uri->raw;
|
733 |
Â
}
|
Â
|
|
734 |
Â
}
|
735 |
Â
|
736 |
Â
/**
|
737 |
+
* Checks if media item has already been cached
|
738 |
+
* @param string $uri URI of media item
|
739 |
+
* @return boolean Whether media item has been cached
|
740 |
Â
*/
|
741 |
+
private function media_item_cached($uri) {
|
742 |
+
return ( is_string($uri) && isset($this->media_items_raw[$uri]) ) ? true : false;
|
Â
|
|
Â
|
|
Â
|
|
743 |
Â
}
|
744 |
Â
|
745 |
Â
/**
|
746 |
+
* Retrieve cached media item
|
747 |
+
* @param string $uri Media item URI
|
748 |
+
* @return object|null Media item properties (NULL if not set)
|
749 |
Â
*/
|
750 |
+
private function get_cached_media_item($uri) {
|
751 |
+
return ( $this->media_item_cached($uri) ) ? $this->media_items_raw[$uri] : null;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
752 |
Â
}
|
753 |
Â
|
754 |
Â
/**
|
755 |
+
* Retrieve cached media items
|
756 |
+
* @return array Cached media items
|
757 |
Â
*/
|
758 |
+
private function &get_cached_media_items() {
|
759 |
+
return $this->media_items_raw;
|
760 |
+
}
|
761 |
+
|
762 |
+
/**
|
763 |
+
* Check if media items have been cached
|
764 |
+
* @return boolean
|
765 |
+
*/
|
766 |
+
private function has_cached_media_items() {
|
767 |
+
return ( empty($this->media_items_raw) ) ? false : true;
|
768 |
+
}
|
769 |
+
|
770 |
+
/*-** Theme **-*/
|
771 |
+
|
772 |
+
/**
|
773 |
+
* Retrieve theme
|
774 |
+
* @param string $id ID of theme to retrieve
|
775 |
+
* @return SLB_Theme Theme instance
|
776 |
+
* @TODO Refactor
|
777 |
+
*/
|
778 |
+
function get_theme($id = '') {
|
779 |
+
//Default: Get current theme if no theme specified
|
780 |
+
if ( !$this->themes->has_item($id) ) {
|
781 |
+
$id = $this->options->get_value('theme');
|
782 |
+
if ( !$this->themes->has_item($id) ) {
|
783 |
+
$id = $this->themes->get_default_id();
|
784 |
Â
}
|
Â
|
|
785 |
Â
}
|
786 |
+
return $this->themes->get_item($id);
|
787 |
Â
}
|
788 |
+
|
789 |
+
/*-** Grouping **-*/
|
790 |
Â
|
791 |
+
/**
|
792 |
+
* Builds wrapper for grouping
|
793 |
+
* @return object Wrapper properties
|
794 |
+
* > open
|
795 |
+
* > close
|
796 |
+
*/
|
797 |
+
function group_get_wrapper() {
|
798 |
+
static $wrapper = null;
|
799 |
+
if ( is_null($wrapper) ) {
|
800 |
+
$start = '<';
|
801 |
+
$end = '>';
|
802 |
+
$terminate = '/';
|
803 |
+
$val = $this->add_prefix('group');
|
804 |
+
//Build properties
|
805 |
+
$wrapper = array(
|
806 |
+
'open' => $start . $val . $end,
|
807 |
+
'close' => $start . $terminate . $val . $end
|
808 |
+
);
|
809 |
+
//Convert to object
|
810 |
+
$wrapper = (object) $wrapper;
|
811 |
+
}
|
812 |
+
return $wrapper;
|
813 |
+
}
|
814 |
+
|
815 |
+
/**
|
816 |
+
* Wraps galleries for grouping
|
817 |
+
* @uses `the_content` Filter hook
|
818 |
+
* @uses gallery_wrap_callback to Wrap shortcodes for grouping
|
819 |
+
* @param string $content Post content
|
820 |
+
* @return string Modified post content
|
821 |
+
*/
|
822 |
+
function gallery_wrap($content) {
|
823 |
+
if ( !$this->is_enabled() )
|
824 |
+
return $content;
|
825 |
+
//Stop processing if option not enabled
|
826 |
+
if ( !$this->options->get_bool('group_gallery') )
|
827 |
+
return $content;
|
828 |
+
global $shortcode_tags;
|
829 |
+
//Save default shortcode handlers to temp variable
|
830 |
+
$sc_temp = $shortcode_tags;
|
831 |
+
//Find gallery shortcodes
|
832 |
+
$shortcodes = array('gallery', 'nggallery');
|
833 |
+
$m = $this->m('gallery_wrap_callback');
|
834 |
+
$shortcode_tags = array();
|
835 |
+
foreach ( $shortcodes as $tag ) {
|
836 |
+
$shortcode_tags[$tag] = $m;
|
837 |
+
}
|
838 |
+
//Wrap gallery shortcodes
|
839 |
+
$content = do_shortcode($content);
|
840 |
+
//Restore default shortcode handlers
|
841 |
+
$shortcode_tags = $sc_temp;
|
842 |
+
|
843 |
+
return $content;
|
844 |
+
}
|
845 |
Â
|
846 |
Â
/**
|
847 |
+
* Wraps gallery shortcodes for later processing
|
848 |
+
* @param array $attr Shortcode attributes
|
849 |
+
* @param string $content Content enclosed in shortcode
|
850 |
+
* @param string $tag Shortcode name
|
851 |
+
* @return string Wrapped gallery shortcode
|
852 |
+
*/
|
853 |
+
function gallery_wrap_callback($attr, $content = null, $tag) {
|
854 |
+
//Rebuild shortcode
|
855 |
+
$sc = '[' . $tag . ' ' . $this->util->build_attribute_string($attr) . ']';
|
856 |
+
if ( !empty($content) )
|
857 |
+
$sc .= $content . '[/' . $tag .']';
|
858 |
+
//Wrap shortcode
|
859 |
+
$w = $this->group_get_wrapper();
|
860 |
+
$sc = $w->open . $sc . $w->close;
|
861 |
+
return $sc;
|
Â
|
|
Â
|
|
Â
|
|
862 |
Â
}
|
863 |
Â
|
864 |
Â
/**
|
865 |
+
* Removes wrapping from galleries
|
866 |
+
* @uses `the_content` filter hook
|
867 |
+
* @param $content Post content
|
868 |
+
* @return string Modified post content
|
869 |
Â
*/
|
870 |
+
function gallery_unwrap($content) {
|
871 |
+
if ( !$this->is_enabled() )
|
872 |
+
return $content;
|
873 |
+
//Stop processing if option not enabled
|
874 |
+
if ( !$this->options->get_bool('group_gallery') )
|
875 |
+
return $content;
|
876 |
+
$w = $this->group_get_wrapper();
|
877 |
+
if ( strpos($content, $w->open) !== false ) {
|
878 |
+
$content = str_replace($w->open, '', $content);
|
879 |
+
$content = str_replace($w->close, '', $content);
|
Â
|
|
Â
|
|
880 |
Â
}
|
881 |
+
return $content;
|
882 |
Â
}
|
883 |
Â
|
884 |
+
/*-** Widgets **-*/
|
885 |
+
|
886 |
Â
/**
|
887 |
+
* Reroute widget display handlers to internal method
|
888 |
+
* @param array $sidebar_widgets List of sidebars & their widgets
|
889 |
+
* @uses WP Hook `sidebars_widgets` to intercept widget list
|
890 |
+
* @global $wp_registered_widgets to reroute display callback
|
891 |
+
* @return array Sidebars and widgets (unmodified)
|
892 |
Â
*/
|
893 |
+
function sidebars_widgets($sidebars_widgets) {
|
894 |
+
global $wp_registered_widgets;
|
895 |
+
static $widgets_processed = false;
|
896 |
+
if ( is_admin() || empty($wp_registered_widgets) || $widgets_processed || !is_object($this->options) || !$this->is_enabled() || !$this->options->get_bool('enabled_widget') )
|
897 |
+
return $sidebars_widgets;
|
898 |
+
$widgets_processed = true;
|
899 |
+
//Fetch active widgets from all sidebars
|
900 |
+
foreach ( $sidebars_widgets as $sb => $ws ) {
|
901 |
+
//Skip inactive widgets and empty sidebars
|
902 |
+
if ( 'wp_inactive_widgets' == $sb || empty($ws) || !is_array($ws) )
|
903 |
+
continue;
|
904 |
+
foreach ( $ws as $w ) {
|
905 |
+
if ( isset($wp_registered_widgets[$w]) && isset($wp_registered_widgets[$w][$this->widget_callback]) ) {
|
906 |
+
$wref =& $wp_registered_widgets[$w];
|
907 |
+
//Backup original callback
|
908 |
+
$wref[$this->widget_callback_orig] = $wref[$this->widget_callback];
|
909 |
+
//Reroute callback
|
910 |
+
$wref[$this->widget_callback] = $this->m('widget_callback');
|
911 |
+
unset($wref);
|
912 |
Â
}
|
913 |
Â
}
|
914 |
Â
}
|
915 |
+
|
916 |
+
return $sidebars_widgets;
|
917 |
Â
}
|
918 |
Â
|
919 |
Â
/**
|
920 |
+
* Widget display handler
|
921 |
+
* Original widget display handler is called inside of an output buffer & links in output are processed before sending to browser
|
922 |
+
* @param array $args Widget instance properties
|
923 |
+
* @param int (optional) $widget_args Additional widget args (usually the widget's instance number)
|
924 |
+
* @see WP_Widget::display_callback() for more information
|
925 |
+
* @see sidebars_widgets() for callback modification
|
926 |
+
* @global $wp_registered_widgets
|
927 |
+
* @uses widget_process_links() to Process links in widget content
|
928 |
+
* @return void
|
929 |
Â
*/
|
930 |
+
function widget_callback($args, $widget_args = 1) {
|
931 |
+
global $wp_registered_widgets;
|
932 |
+
$wid = ( isset($args['widget_id']) ) ? $args['widget_id'] : false;
|
933 |
+
//Stop processing if widget data invalid
|
934 |
+
if ( !$wid || !isset($wp_registered_widgets[$wid]) || !($w =& $wp_registered_widgets[$wid]) || !isset($w['id']) || $wid != $w['id'] )
|
935 |
+
return false;
|
936 |
+
//Get original callback
|
937 |
+
if ( !isset($w[$this->widget_callback_orig]) || !($cb = $w[$this->widget_callback_orig]) || !is_callable($cb) )
|
938 |
+
return false;
|
939 |
+
$params = func_get_args();
|
940 |
+
$this->widget_processing = true;
|
941 |
+
//Start output buffer
|
942 |
+
ob_start();
|
943 |
+
//Call original callback
|
944 |
+
call_user_func_array($cb, $params);
|
945 |
+
//Flush output buffer
|
946 |
+
echo $this->widget_process_links(ob_get_clean(), $wid);
|
947 |
+
$this->widget_processing = false;
|
948 |
+
}
|
949 |
+
|
950 |
+
/**
|
951 |
+
* Process links in widget content
|
952 |
+
* @param string $content Widget content
|
953 |
+
* @return string Processed widget content
|
954 |
+
* @uses process_links() to process links
|
955 |
+
*/
|
956 |
+
function widget_process_links($content, $id) {
|
957 |
+
$id = ( $this->options->get_bool('group_widget') ) ? "widget_$id" : null;
|
958 |
+
return $this->process_links($content, $id);
|
959 |
+
}
|
960 |
+
|
961 |
+
/*-** Helpers **-*/
|
962 |
+
|
963 |
+
/**
|
964 |
+
* Build attribute name
|
965 |
+
* Makes sure name is only prefixed once
|
966 |
+
* @param string $name (optional) Attribute base name
|
967 |
+
* @return string Formatted attribute name
|
968 |
+
*/
|
969 |
+
function make_attribute_name($name = '') {
|
970 |
+
//Validate
|
971 |
+
if ( !is_string($name) ) {
|
972 |
+
$name = '';
|
973 |
+
} else {
|
974 |
+
$name = trim($name);
|
975 |
Â
}
|
976 |
+
//Setup
|
977 |
+
$sep = '-';
|
978 |
+
$top = 'data';
|
979 |
+
//Generate valid name
|
980 |
+
if ( strpos($name, $top . $sep . $this->get_prefix()) !== 0 ) {
|
981 |
+
$name = $top . $sep . $this->add_prefix($name, $sep);
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
982 |
Â
}
|
983 |
+
return $name;
|
984 |
Â
}
|
985 |
+
|
986 |
+
/**
|
987 |
+
* Set attribute to array
|
988 |
+
* Attribute is added to array if it does not exist
|
989 |
+
* @param array $attrs Array to add attribute to (Passed by reference)
|
990 |
+
* @param string $name Name of attribute to add
|
991 |
+
* @param string (optional) $value Attribute value
|
992 |
+
* @return array Updated attribute array
|
993 |
+
*/
|
994 |
+
function set_attribute(&$attrs, $name, $value = true) {
|
995 |
+
//Validate
|
996 |
+
$attrs = $this->get_attributes($attrs, false);
|
997 |
+
if ( !is_string($name) || empty($name) ) {
|
998 |
+
return $attrs;
|
999 |
Â
}
|
1000 |
+
if ( !is_scalar($value) ) {
|
1001 |
+
$value = true;
|
1002 |
+
}
|
1003 |
+
//Add attribute
|
1004 |
+
$attrs = array_merge($attrs, array( $this->make_attribute_name($name) => strval($value) ));
|
1005 |
+
|
1006 |
+
return $attrs;
|
1007 |
Â
}
|
1008 |
Â
|
1009 |
Â
/**
|
1010 |
+
* Convert attribute string into array
|
1011 |
+
* @param string $attr_string Attribute string
|
1012 |
+
* @param bool (optional) $internal Whether only internal attributes should be evaluated (Default: TRUE)
|
1013 |
+
* @return array Attributes as associative array
|
1014 |
Â
*/
|
1015 |
+
function get_attributes($attr_string, $internal = true) {
|
1016 |
+
if ( is_string($attr_string) ) {
|
1017 |
+
$attr_string = $this->util->parse_attribute_string($attr_string);
|
1018 |
+
}
|
1019 |
+
$ret = ( is_array($attr_string) ) ? $attr_string : array();
|
1020 |
+
//Filter out external attributes
|
1021 |
+
if ( !empty($ret) && is_bool($internal) && $internal ) {
|
1022 |
+
$ret_f = array();
|
1023 |
+
foreach ( $ret as $key => $val ) {
|
1024 |
+
if ( strpos($key, $this->make_attribute_name()) == 0 ) {
|
1025 |
+
$ret_f[$key] = $val;
|
1026 |
+
}
|
1027 |
+
}
|
1028 |
+
if ( !empty($ret_f) ) {
|
1029 |
+
$ret = $ret_f;
|
1030 |
+
}
|
1031 |
+
}
|
1032 |
+
|
1033 |
+
return $ret;
|
1034 |
Â
}
|
1035 |
Â
|
1036 |
Â
/**
|
1037 |
+
* Retrieve attribute value
|
1038 |
+
* @param string|array $attrs Attributes to retrieve attribute value from
|
1039 |
+
* @param string $attr Attribute name to retrieve
|
1040 |
+
* @param bool (optional) $internal Whether only internal attributes should be evaluated (Default: TRUE)
|
1041 |
+
* @return string|bool Attribute value (Default: FALSE)
|
1042 |
+
*/
|
1043 |
+
function get_attribute($attrs, $attr, $internal = true) {
|
1044 |
+
$ret = false;
|
1045 |
+
//Validate
|
1046 |
+
$attrs = $this->get_attributes($attrs, $internal);
|
1047 |
+
if ( $internal ) {
|
1048 |
+
$attr = $this->make_attribute_name($attr);
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
1049 |
Â
}
|
1050 |
+
if ( isset($attrs[$attr]) ) {
|
1051 |
+
$ret = $attrs[$attr];
|
1052 |
+
}
|
1053 |
+
return $ret;
|
1054 |
Â
}
|
1055 |
Â
|
1056 |
Â
/**
|
1057 |
+
* Checks if attribute exists
|
1058 |
+
* If supplied, the attribute's value is also validated
|
1059 |
+
* @param string|array $attrs Attributes to retrieve attribute value from
|
1060 |
+
* @param string $attr Attribute name to retrieve
|
1061 |
+
* @param mixed $value (optional) Attribute value to check for
|
1062 |
+
* @param bool $internal (optional) Whether to check only internal attributes (Default: TRUE)
|
1063 |
+
* @see get_attribute()
|
1064 |
+
* @return bool Whether or not attribute (with matching value if specified) exists
|
1065 |
Â
*/
|
1066 |
+
function has_attribute($attrs, $attr, $value = null, $internal = true) {
|
1067 |
+
$a = $this->get_attribute($attrs, $attr, $internal);
|
1068 |
+
$ret = false;
|
1069 |
+
if ( $a !== false ) {
|
1070 |
+
$ret = true;
|
1071 |
+
//Check value
|
1072 |
+
if ( null != $value && is_scalar($value) ) {
|
1073 |
+
$ret = ( $a == strval($value) ) ? true : false;
|
1074 |
+
}
|
1075 |
+
}
|
1076 |
+
return $ret;
|
1077 |
Â
}
|
1078 |
Â
|
1079 |
Â
/**
|
1080 |
+
* Build JS object of UI strings when initializing lightbox
|
1081 |
+
* @return array UI strings
|
1082 |
Â
*/
|
1083 |
+
function build_labels() {
|
1084 |
+
$ret = array();
|
1085 |
+
//Get all UI options
|
1086 |
+
$prefix = 'txt_';
|
1087 |
+
$opt_strings = array_filter(array_keys($this->options->get_items()), create_function('$opt', 'return ( strpos($opt, "' . $prefix . '") === 0 );'));
|
1088 |
+
if ( count($opt_strings) ) {
|
1089 |
+
//Build array of UI options
|
1090 |
+
foreach ( $opt_strings as $key ) {
|
1091 |
+
$name = substr($key, strlen($prefix));
|
1092 |
+
$ret[$name] = $this->options->get_value($key);
|
1093 |
+
}
|
1094 |
+
}
|
1095 |
+
return $ret;
|
1096 |
Â
}
|
1097 |
+
}
|
Â
|
|
Â
|
readme.txt
CHANGED
@@ -1,80 +1,202 @@
|
|
1 |
-
===
|
2 |
-
Contributors:
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
*
|
19 |
-
* Automatically
|
20 |
-
*
|
21 |
-
*
|
22 |
-
*
|
23 |
-
*
|
24 |
-
*
|
25 |
-
*
|
26 |
-
*
|
27 |
-
|
28 |
-
|
29 |
-
*
|
30 |
-
*
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
*
|
62 |
-
*
|
63 |
-
*
|
64 |
-
|
65 |
-
|
66 |
-
*
|
67 |
-
|
68 |
-
|
69 |
-
*
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
*
|
74 |
-
*
|
75 |
-
*
|
76 |
-
*
|
77 |
-
*
|
78 |
-
*
|
79 |
-
|
80 |
-
*
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
=== Simple Lightbox ===
|
2 |
+
Contributors: Archetyped
|
3 |
+
Donate link: http://gum.co/slb-donate
|
4 |
+
License: GPLv2
|
5 |
+
Tags: lightbox, gallery, photography, images, theme, template, style
|
6 |
+
Requires at least: 3.6
|
7 |
+
Tested up to: 3.6.1
|
8 |
+
Stable tag: trunk
|
9 |
+
|
10 |
+
The highly customizable lightbox for WordPress
|
11 |
+
|
12 |
+
== Description ==
|
13 |
+
Simple Lightbox is a very simple and customizable lightbox that is easy to add to your WordPress website.
|
14 |
+
|
15 |
+
#### Features
|
16 |
+
Options for customizing the lightbox behavior are located in the **Appearance > Lightbox** admin menu (or just click the **Settings** link below the plugin's name when viewing the list of installed plugins)
|
17 |
+
|
18 |
+
* Automatically activate links (no manual coding required)
|
19 |
+
* Automatically resize lightbox to fit in window
|
20 |
+
* Customize lightbox with **themes**
|
21 |
+
* Mobile-optimized responsive themes included
|
22 |
+
* Customizable lightbox animations
|
23 |
+
* Infinitely customizable with **add-ons**
|
24 |
+
* Supports WordPress **image attachment** links
|
25 |
+
* Supports links in **widgets**
|
26 |
+
* Keyboard Navigation
|
27 |
+
* Display media metadata (caption, description, etc.) in lightbox
|
28 |
+
* Enable Lightbox depending on Page Type (Home, Pages, Archive, etc.)
|
29 |
+
* Group image links (play as a slideshow)
|
30 |
+
* Group image links by Post (separate slideshow for each post on page)
|
31 |
+
|
32 |
+
#### Usage
|
33 |
+
1. Insert links to images/image attachments into your posts/pages
|
34 |
+
|
35 |
+
**That's it! The image will be displayed in a lightbox automatically.**
|
36 |
+
|
37 |
+
* For more usage tips, go to [Simple Lightbox's official page](http://archetyped.com/tools/simple-lightbox/)
|
38 |
+
|
39 |
+
== Installation ==
|
40 |
+
|
41 |
+
1. Install and activate SLB
|
42 |
+
1. Verify that your site's theme uses the `wp_head()`, `wp_footer()`, & `the_content()` template tags (standard in any professional theme)
|
43 |
+
|
44 |
+
== Upgrade Notice ==
|
45 |
+
|
46 |
+
No upgrade notices
|
47 |
+
|
48 |
+
== Frequently Asked Questions ==
|
49 |
+
|
50 |
+
Get more information on [Simple Lightbox's official page](http://archetyped.com/tools/simple-lightbox/)
|
51 |
+
|
52 |
+
== Screenshots ==
|
53 |
+
|
54 |
+
1. Lightbox Customization Options
|
55 |
+
2. Light Theme
|
56 |
+
3. Dark Theme
|
57 |
+
|
58 |
+
== Changelog ==
|
59 |
+
|
60 |
+
= 2.0 =
|
61 |
+
* Completely rewritten lightbox code
|
62 |
+
* Add: Automatically resize lightbox to fit window
|
63 |
+
* Add: APIs for third-party add-ons
|
64 |
+
* Add: Flexible theme support
|
65 |
+
* Add: Flexible content handler support
|
66 |
+
* Add: Mobile-optimized responsive themes (2)
|
67 |
+
* Optimize: PHP class autoloading
|
68 |
+
* Optimize: Improved performance and compatibility
|
69 |
+
* Optimize: Full internationalization support
|
70 |
+
|
71 |
+
= 1.6 =
|
72 |
+
* Add: Widget support
|
73 |
+
* Add: WordPress 3.3 support
|
74 |
+
* Add: Localization support
|
75 |
+
* Add: Option to group gallery links separately (supports WordPress & NextGen galleries)
|
76 |
+
* Add: Upgrade notice
|
77 |
+
* Optimize: WP 3.3 compatibility
|
78 |
+
* Optimize: Improved compatibility with URI case-sensitivity
|
79 |
+
* Optimize: Activation processing
|
80 |
+
* Optimize: Image grouping
|
81 |
+
* Optimize: Image metadata loading performance
|
82 |
+
* Optimize: File loading
|
83 |
+
* Optimize: Improved safeguards against interference by bugs in other plugins
|
84 |
+
* Optimize: Link processing performance
|
85 |
+
* Optimize: Lightbox styling isolated from site styles
|
86 |
+
* Optimize: Improved link processing performance
|
87 |
+
* Optimize: Improved image metadata support
|
88 |
+
* Optimize: Improved support for HTTP/HTTPS requests
|
89 |
+
* Fix: SLB is not defined in JS (Jezz Hands)
|
90 |
+
* Fix: Boolean case-sensitivity (78 Truths)
|
91 |
+
* Fix: YouTube embed using iFrame overlaps lightbox (Elena in Hiding)
|
92 |
+
* Fix: Issue when scanning links without valid URLs (McCloskey Iteration)
|
93 |
+
* Fix: Image activation is case-sensitive (Sensitive Tanya)
|
94 |
+
* Fix: Visible lightbox overlay edges when image larger than browser window (Chibi Overlay)
|
95 |
+
* Fix: Options availability for some users
|
96 |
+
* Fix: Inconsistent loading of image metadata
|
97 |
+
* Fix: Links not fully processed when group is set manually
|
98 |
+
|
99 |
+
= 1.5.6 =
|
100 |
+
* Add: Display image description in lightbox (with HTML support)
|
101 |
+
* Add: Support for W3 Total Cache plugin
|
102 |
+
* Add: Initial support for NextGEN galleries
|
103 |
+
* Update: **Important:** [System Requirements](http://wordpress.org/about/requirements/) aligned with WP 3.2.1
|
104 |
+
* Optimize: Improved support for small images in default template
|
105 |
+
* Optimize: Support for non-English text in user options
|
106 |
+
* Optimize: Improved IE compatibility
|
107 |
+
* Optimize: Improved data handling
|
108 |
+
* Optimize: Skin loading performance
|
109 |
+
* Optimize: Skin CSS Cleanup
|
110 |
+
* Optimize: Caption support for galleries
|
111 |
+
* Optimize: Options code cleanup (Juga Sweep)
|
112 |
+
* Fix: User-defined UI text not used (Ivan gets Even (cooler))
|
113 |
+
* Fix: Options reset after update (KRazy Donna)
|
114 |
+
|
115 |
+
= 1.5.5.1 =
|
116 |
+
* Fix: Disabled links not being disabled (Disabling Sascha)
|
117 |
+
|
118 |
+
= 1.5.5 =
|
119 |
+
* Add: Distinct link activation (will not affect other lightboxes)
|
120 |
+
* Add: Backwards compatibility with legacy lightbox links (optional)
|
121 |
+
* Add: Support for WordPress 3.2
|
122 |
+
* Add: Support for links added after page load (e.g. via AJAX, etc.)
|
123 |
+
* Add: Admin option to enable/disable attachment links
|
124 |
+
* Add: Support for image attachment links
|
125 |
+
* Update: Options management overhaul
|
126 |
+
* Update: Additional WordPress 3.2 support (Gallery)
|
127 |
+
* Update: Cache-management for enqueued files
|
128 |
+
* Update: Improved UI consistency
|
129 |
+
* Update: Improved compatibility for older versions of PHP
|
130 |
+
* Update: Internal optimizations
|
131 |
+
* Update: Improved URL handling
|
132 |
+
* Fix: Improved options migration from old versions (Hutchison Migration)
|
133 |
+
* Fix: XHTML Validation (Hajo Validation)
|
134 |
+
|
135 |
+
= 1.5.4 =
|
136 |
+
* Add: Optional Link validation
|
137 |
+
* Add: Keyboard Navigation
|
138 |
+
* Add: Option to enable/disable image caption
|
139 |
+
* Add: `rel` attribute supported again
|
140 |
+
* Add: Use `slb_off` in link's `rel` attribute to disable automatic activation for link
|
141 |
+
* Fix: HTTPS compatibility (Jürgen Protocol)
|
142 |
+
* Fix: Enabling SLB on Pages issue
|
143 |
+
* Fix: Zmanu is_single
|
144 |
+
* Fix: Image order is sometimes incorrect
|
145 |
+
* Optimize: Filter double clicks
|
146 |
+
* Optimize: Separate options to enable/disable SLB on Posts and Pages
|
147 |
+
* Optimize: Better grouping support
|
148 |
+
|
149 |
+
= 1.5.3 =
|
150 |
+
* Fix: Caption may not display under certain circumstances (Caption Erin)
|
151 |
+
* Fix: Images not grouped when "separate by post" option is activated (Logical Ross)
|
152 |
+
* Update: Lightbox will not be activated for links that already have `rel` attribute set
|
153 |
+
|
154 |
+
= 1.5.2 =
|
155 |
+
* Fix: Slideshow loops out of control (Mirage of Wallentin)
|
156 |
+
* Fix: Lightbox fails when group by posts disabled (Lange Find)
|
157 |
+
* Add: Option to use the image's URI as caption when link title not set (Under UI options)
|
158 |
+
|
159 |
+
= 1.5.1 =
|
160 |
+
* Add: WP Gallery support
|
161 |
+
* Fix: Navigation hidden when only one image
|
162 |
+
* Fix: Use user-defined UI text
|
163 |
+
|
164 |
+
= 1.5 =
|
165 |
+
* Add: Theme support
|
166 |
+
* Optimize: Javascript cleanup and file size reductions
|
167 |
+
* Optimize: CSS cleanup
|
168 |
+
|
169 |
+
= 1.4 =
|
170 |
+
* Update: Integrated with jQuery
|
171 |
+
* Optimize: Javascript filesize 9x smaller
|
172 |
+
* Add: Close lightbox by clicking to left/right outside of image (an oft-requested feature)
|
173 |
+
|
174 |
+
= 1.3.2 =
|
175 |
+
* Add: Option to enable/disable lightbox resizing animation (thanks Maria!)
|
176 |
+
|
177 |
+
= 1.3.1 =
|
178 |
+
* Update: Utilities code (internal)
|
179 |
+
|
180 |
+
= 1.3 =
|
181 |
+
* Add: Customizable UI label text (close, next, and prev button images can be replaced in `images` directory)
|
182 |
+
* Add: Group image links by Post (separate slideshow for each post)
|
183 |
+
* Add: Reset settings link on plugin listings page
|
184 |
+
* Optimize: Organized settings page
|
185 |
+
|
186 |
+
= 1.2.1 =
|
187 |
+
* Fixed: Image title given higher precedence than Image alt (more compatible w/WP workflow)
|
188 |
+
|
189 |
+
= 1.2 =
|
190 |
+
* Added: Option to group automatically activated links
|
191 |
+
* Optimized: Lightbox caption retrieval
|
192 |
+
|
193 |
+
= 1.1 =
|
194 |
+
* Added: Enable/disable lightbox functionality by page type (Home, Pages/Posts, Archive, etc.)
|
195 |
+
* Added: Automatically activate lightbox functionality for image links
|
196 |
+
* Added: Link to settings menu on plugin listing page
|
197 |
+
* Optimized: Options menu field building
|
198 |
+
* Optimized: Loading of default values for plugin options
|
199 |
+
* Optimized: General code optimizations
|
200 |
+
|
201 |
+
= 1.0 =
|
202 |
+
* Initial release
|
screenshot-1.gif
DELETED
Binary file
|
screenshot-2.gif
DELETED
Binary file
|
template-tags/item/tag.item.js
ADDED
@@ -0,0 +1,17 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function($) {
|
2 |
+
return {
|
3 |
+
render: function(item, tag) {
|
4 |
+
var dfr = $.Deferred();
|
5 |
+
var m = 'get_' + tag.get_prop();
|
6 |
+
var ret = ( this.util.is_method(item, m) ) ? item[m]() : item.get_attribute(tag.get_prop(), '');
|
7 |
+
if ( this.util.is_promise(ret) ) {
|
8 |
+
ret.done(function(output) {
|
9 |
+
dfr.resolve(output);
|
10 |
+
});
|
11 |
+
} else {
|
12 |
+
dfr.resolve(ret);
|
13 |
+
}
|
14 |
+
return dfr.promise();
|
15 |
+
}
|
16 |
+
}
|
17 |
+
})(jQuery);
|
template-tags/ui/tag.ui.js
ADDED
@@ -0,0 +1,108 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function($) {
|
2 |
+
return {
|
3 |
+
init: function(item, tag, v) {
|
4 |
+
//Add event handlers
|
5 |
+
v.on('events-complete', function(ev, v) {
|
6 |
+
//Register event handlers
|
7 |
+
|
8 |
+
/* Close */
|
9 |
+
|
10 |
+
var close = function() {
|
11 |
+
return v.close();
|
12 |
+
};
|
13 |
+
//Close button
|
14 |
+
v.get_theme().dom_get_tag('ui', 'close').click(close);
|
15 |
+
|
16 |
+
/* Navigation */
|
17 |
+
|
18 |
+
var nav_next = function() {
|
19 |
+
v.item_next();
|
20 |
+
};
|
21 |
+
|
22 |
+
var nav_prev = function() {
|
23 |
+
v.item_prev();
|
24 |
+
};
|
25 |
+
|
26 |
+
v.get_theme().dom_get_tag('ui', 'nav_next').click(nav_next);
|
27 |
+
v.get_theme().dom_get_tag('ui', 'nav_prev').click(nav_prev);
|
28 |
+
|
29 |
+
/* Slideshow */
|
30 |
+
|
31 |
+
var slideshow_control = function() {
|
32 |
+
v.slideshow_toggle();
|
33 |
+
};
|
34 |
+
|
35 |
+
v.get_theme().dom_get_tag('ui', 'slideshow_control').click(slideshow_control);
|
36 |
+
});
|
37 |
+
|
38 |
+
v.on('slideshow-toggle', function(ev, v) {
|
39 |
+
//Update slideshow control tag
|
40 |
+
var tags = v.get_theme().get_tags('ui', 'slideshow_control');
|
41 |
+
if ( tags.length ) {
|
42 |
+
for ( var x = 0; x < tags.length; x++ ) {
|
43 |
+
tags[x].render(v.get_item()).done(function(r) {
|
44 |
+
r.tag.dom_get().html(r.output);
|
45 |
+
});
|
46 |
+
}
|
47 |
+
}
|
48 |
+
});
|
49 |
+
},
|
50 |
+
render: function(item, tag) {
|
51 |
+
//Initialize event handlers (once per viewer)
|
52 |
+
var v = item.get_viewer();
|
53 |
+
var st = ['events-init', tag.get_ns(), tag.get_name()].join('_');
|
54 |
+
var fmt = function(output) {
|
55 |
+
return output;
|
56 |
+
};
|
57 |
+
if ( !v.get_status(st) ) {
|
58 |
+
v.set_status(st);
|
59 |
+
this.call_attribute('init', item, tag, v);
|
60 |
+
}
|
61 |
+
//Process content
|
62 |
+
var dfr = $.Deferred();
|
63 |
+
var ret = this.handle_prop(tag.get_prop(), item, tag);
|
64 |
+
if ( this.util.is_promise(ret) ) {
|
65 |
+
ret.done(function(output) {
|
66 |
+
dfr.resolve(fmt(output));
|
67 |
+
});
|
68 |
+
} else {
|
69 |
+
dfr.resolve(fmt(ret));
|
70 |
+
}
|
71 |
+
return dfr.promise();
|
72 |
+
},
|
73 |
+
props: {
|
74 |
+
'slideshow_control': function(item, tag) {
|
75 |
+
//Get slideshow status
|
76 |
+
var prop = ( item.get_viewer().slideshow_active() ) ? 'slideshow_stop' : 'slideshow_start';
|
77 |
+
return item.get_viewer().get_label(prop);
|
78 |
+
},
|
79 |
+
'group_status': function(item, tag) {
|
80 |
+
//Handle single items
|
81 |
+
if ( item.get_group().is_single() ) {
|
82 |
+
return '';
|
83 |
+
}
|
84 |
+
//Handle groups with multiple items
|
85 |
+
var out = item.get_viewer().get_label('group_status');
|
86 |
+
var key,
|
87 |
+
ph,
|
88 |
+
delim = '%',
|
89 |
+
handlers = {
|
90 |
+
current: function() {
|
91 |
+
return item.get_group(true).get_pos() + 1;
|
92 |
+
},
|
93 |
+
total: function() {
|
94 |
+
return item.get_group().get_size();
|
95 |
+
}
|
96 |
+
};
|
97 |
+
//Parse placeholders
|
98 |
+
for ( key in handlers ) {
|
99 |
+
ph = delim + key + delim;
|
100 |
+
if ( out.indexOf(ph) != -1 ) {
|
101 |
+
out = out.replace(ph, handlers[key]());
|
102 |
+
}
|
103 |
+
}
|
104 |
+
return out;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
}
|
108 |
+
})(jQuery);
|
themes/black/config.rb
ADDED
@@ -0,0 +1,23 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# Require any additional compass plugins here.
|
2 |
+
|
3 |
+
# Set this to the root of your project when deployed:
|
4 |
+
http_path = "/"
|
5 |
+
css_dir = "css"
|
6 |
+
sass_dir = "sass"
|
7 |
+
images_dir = "images"
|
8 |
+
|
9 |
+
# You can select your preferred output style here (can be overridden via the command line):
|
10 |
+
output_style = :compressed
|
11 |
+
|
12 |
+
# To enable relative paths to assets via compass helper functions. Uncomment:
|
13 |
+
# relative_assets = true
|
14 |
+
|
15 |
+
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
16 |
+
# line_comments = false
|
17 |
+
|
18 |
+
|
19 |
+
# If you prefer the indented syntax, you might want to regenerate this
|
20 |
+
# project again passing --syntax sass, or you can uncomment this:
|
21 |
+
# preferred_syntax = :sass
|
22 |
+
# and then run:
|
23 |
+
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
themes/black/css/style.css
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
#slb_viewer_wrap .slb_theme_slb_black a,#slb_viewer_wrap .slb_theme_slb_black a:hover{color:#fff}#slb_viewer_wrap .slb_theme_slb_black .slb_loading{background-image:url("../images/loading.gif")}#slb_viewer_wrap .slb_theme_slb_black .slb_container{background-color:#151515}#slb_viewer_wrap .slb_theme_slb_black .slb_prev a{background-image:url("../images/nav_prev.png")}#slb_viewer_wrap .slb_theme_slb_black .slb_next a{background-image:url("../images/nav_next.png")}#slb_viewer_wrap .slb_theme_slb_black .slb_data_title{color:#e3e3e3}#slb_viewer_wrap .slb_theme_slb_black .slb_data_desc{color:#cecece}#slb_viewer_wrap .slb_theme_slb_black .slb_group_status{color:#999}
|
themes/black/images/loading.gif
ADDED
Binary file
|
themes/black/images/nav_next.png
ADDED
Binary file
|
themes/black/images/nav_prev.png
ADDED
Binary file
|
themes/black/sass/style.scss
ADDED
@@ -0,0 +1,37 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
#slb_viewer_wrap {
|
2 |
+
.slb_theme_slb_black {
|
3 |
+
|
4 |
+
a,
|
5 |
+
a:hover {
|
6 |
+
color: #fff;
|
7 |
+
}
|
8 |
+
|
9 |
+
.slb_loading {
|
10 |
+
background-image: url('../images/loading.gif');
|
11 |
+
}
|
12 |
+
|
13 |
+
.slb_container {
|
14 |
+
background-color: #151515;
|
15 |
+
}
|
16 |
+
|
17 |
+
.slb_prev a {
|
18 |
+
background-image: url('../images/nav_prev.png');
|
19 |
+
}
|
20 |
+
|
21 |
+
.slb_next a {
|
22 |
+
background-image: url('../images/nav_next.png');
|
23 |
+
}
|
24 |
+
|
25 |
+
.slb_data_title {
|
26 |
+
color: #e3e3e3;
|
27 |
+
}
|
28 |
+
|
29 |
+
.slb_data_desc {
|
30 |
+
color: #cecece;
|
31 |
+
}
|
32 |
+
|
33 |
+
.slb_group_status {
|
34 |
+
color: #999;
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
themes/default/client.js
ADDED
@@ -0,0 +1,202 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function($) {
|
2 |
+
return {
|
3 |
+
/**
|
4 |
+
* State transition handlers
|
5 |
+
*/
|
6 |
+
'transition': {
|
7 |
+
/**
|
8 |
+
* Open event
|
9 |
+
* @param View.Viewer v Viewer instance
|
10 |
+
* @param jQuery.Deferred dfr Deferred instance to be resolved when animation is complete
|
11 |
+
* @return jQuery.Promise Resolved when transition is complete
|
12 |
+
*/
|
13 |
+
'open': function(v, dfr) {
|
14 |
+
var t = this;
|
15 |
+
var d = v.dom_get(),
|
16 |
+
l = v.get_layout().hide(),
|
17 |
+
o = v.get_overlay().hide();
|
18 |
+
var pos = {'top' : ''};
|
19 |
+
var final = function() {
|
20 |
+
//Show overlay
|
21 |
+
o.fadeIn(function() {
|
22 |
+
l.css(pos);
|
23 |
+
dfr.resolve();
|
24 |
+
});
|
25 |
+
};
|
26 |
+
//Clean UI
|
27 |
+
d.find('.slb_content').css({width: '', height: ''}).find('.slb_template_tag').hide();
|
28 |
+
d.find('.slb_details').height(0);
|
29 |
+
//Show viewer DOM
|
30 |
+
d.show(function() {
|
31 |
+
if ( document.documentElement.clientWidth > 480 ) {
|
32 |
+
/* Standard */
|
33 |
+
//Center vertically
|
34 |
+
var top_scr = $(document).scrollTop();
|
35 |
+
pos.top = ( top_scr + $(window).height() / 2 ) - ( l.height() / 2 );
|
36 |
+
if ( pos.top < top_scr ) {
|
37 |
+
pos.top = top_scr;
|
38 |
+
}
|
39 |
+
} else {
|
40 |
+
//Position at top
|
41 |
+
/* Small screen */
|
42 |
+
pos.top = $(document).scrollTop();
|
43 |
+
}
|
44 |
+
final();
|
45 |
+
});
|
46 |
+
return dfr.promise();
|
47 |
+
},
|
48 |
+
/**
|
49 |
+
* Close event
|
50 |
+
* @param View.Viewer v Viewer instance
|
51 |
+
* @param jQuery.Deferred dfr Deferred instance to be resolved when animation is complete
|
52 |
+
* @return jQuery.Promise Resolved when transition is complete
|
53 |
+
*/
|
54 |
+
'close': function(v, dfr) {
|
55 |
+
var l = v.get_layout(),
|
56 |
+
c = l.find('.slb_content');
|
57 |
+
var t = this;
|
58 |
+
var reset = function() {
|
59 |
+
//Reset state
|
60 |
+
c.width('').height('');
|
61 |
+
l.css('opacity', '');
|
62 |
+
dfr.resolve();
|
63 |
+
}
|
64 |
+
if ( v.animation_enabled() && document.documentElement.clientWidth > 480 ) { /* Standard */
|
65 |
+
var lanim = {opacity: 0, top: $(document).scrollTop() + ( $(window).height() / 2 )},
|
66 |
+
canim = {width: 0, height: 0};
|
67 |
+
//Shrink & fade out viewer
|
68 |
+
var pos = l.animate(lanim).promise();
|
69 |
+
var size = ( $.isEmptyObject(canim) ) ? true : c.animate(canim).promise();
|
70 |
+
$.when(pos, size).done(function() {
|
71 |
+
//Fade out overlay
|
72 |
+
v.get_overlay().fadeOut(function() {
|
73 |
+
reset();
|
74 |
+
});
|
75 |
+
});
|
76 |
+
} else {
|
77 |
+
l.css('opacity', 0);
|
78 |
+
reset();
|
79 |
+
}
|
80 |
+
return dfr.promise();
|
81 |
+
},
|
82 |
+
/**
|
83 |
+
* Item loading event
|
84 |
+
* @param View.Viewer v Viewer instance
|
85 |
+
* @param jQuery.Deferred dfr Deferred instance to be resolved when animation is complete
|
86 |
+
* @return jQuery.Promise Resolved when transition is complete
|
87 |
+
*/
|
88 |
+
'load': function(v, dfr) {
|
89 |
+
v.get_layout().find('.slb_loading').show();
|
90 |
+
if ( document.documentElement.clientWidth > 480 ) {
|
91 |
+
return v.get_layout().fadeIn().promise()
|
92 |
+
} else {
|
93 |
+
v.get_layout().show();
|
94 |
+
dfr.resolve();
|
95 |
+
return dfr;
|
96 |
+
}
|
97 |
+
},
|
98 |
+
/**
|
99 |
+
* Item unloaded event
|
100 |
+
* @param View.Viewer v Viewer instance
|
101 |
+
* @param jQuery.Deferred dfr Deferred instance to be resolved when animation is complete
|
102 |
+
* @return jQuery.Promise Resolved when transition is complete
|
103 |
+
*/
|
104 |
+
'unload': function(v, dfr) {
|
105 |
+
var l = v.get_layout(),
|
106 |
+
det = l.find('.slb_details'),
|
107 |
+
cont = l.find('.slb_content .slb_template_tag');
|
108 |
+
var props = {height: 0};
|
109 |
+
if ( document.documentElement.clientWidth > 480 ) {
|
110 |
+
//Hide details
|
111 |
+
det.animate(props, 'slow');
|
112 |
+
//Hide content
|
113 |
+
cont.fadeOut();
|
114 |
+
} else {
|
115 |
+
det.css(props);
|
116 |
+
cont.hide();
|
117 |
+
}
|
118 |
+
$.when(det.promise(), cont.promise()).done(function() {
|
119 |
+
dfr.resolve();
|
120 |
+
});
|
121 |
+
return dfr.promise();
|
122 |
+
},
|
123 |
+
/**
|
124 |
+
* Item loading completed event
|
125 |
+
* @param View.Viewer v Viewer instance
|
126 |
+
* @param jQuery.Deferred dfr Deferred instance to be resolved when animation is complete
|
127 |
+
* @return jQuery.Promise Resolved when transition is complete
|
128 |
+
*/
|
129 |
+
'complete': function(v, dfr) {
|
130 |
+
//Elements
|
131 |
+
var l = v.get_layout(),
|
132 |
+
loader = l.find('.slb_loading'),
|
133 |
+
det = l.find('.slb_details'),
|
134 |
+
det_data = det.find('.slb_data'),
|
135 |
+
c = l.find('.slb_content'),
|
136 |
+
c_tag = c.find('.slb_template_tag'),
|
137 |
+
c_tag_cont = c.find('.slb_template_tag_item_content');
|
138 |
+
//Transition
|
139 |
+
if ( document.documentElement.clientWidth > 480 ) {
|
140 |
+
//Resize viewer to fit item
|
141 |
+
var dims = this.get_item_dimensions();
|
142 |
+
//Show detail tags (container still hidden)
|
143 |
+
det.find('.slb_template_tag').show();
|
144 |
+
var top_scr = $(document).scrollTop();
|
145 |
+
var pos = { 'top': top_scr + ( $(window).height() / 2 ) - ( this.get_dimensions().height / 2 ) };
|
146 |
+
if ( pos.top < top_scr ) {
|
147 |
+
pos.top = top_scr;
|
148 |
+
}
|
149 |
+
pos.top = pos.top || 0;
|
150 |
+
//Resize container
|
151 |
+
pos = l.animate(pos).promise();
|
152 |
+
dims = c.animate(dims).promise();
|
153 |
+
$.when(pos, dims).done(function() {
|
154 |
+
//Hide loading indicator
|
155 |
+
loader.fadeOut('fast', function() {
|
156 |
+
//Display content
|
157 |
+
c_tag_cont.fadeIn(function() {
|
158 |
+
//Show UI
|
159 |
+
c_tag.show();
|
160 |
+
//Show details
|
161 |
+
det.animate({height: det_data.outerHeight()}, 'slow').promise().done(function() {
|
162 |
+
det.height('');
|
163 |
+
dfr.resolve();
|
164 |
+
});
|
165 |
+
});
|
166 |
+
});
|
167 |
+
});
|
168 |
+
} else {
|
169 |
+
loader.hide();
|
170 |
+
c_tag.show();
|
171 |
+
det.height('');
|
172 |
+
dfr.resolve();
|
173 |
+
}
|
174 |
+
return dfr.promise();
|
175 |
+
}
|
176 |
+
},
|
177 |
+
/**
|
178 |
+
* Theme offsets
|
179 |
+
* Reports additional space required for theme UI
|
180 |
+
*/
|
181 |
+
'offset': function() {
|
182 |
+
var dims = {'width': 0, 'height': 0};
|
183 |
+
if ( document.documentElement.clientWidth > 480 ) {
|
184 |
+
var d = this.get_viewer().get_layout().find('.slb_details');
|
185 |
+
d.find('.slb_template_tag').show();
|
186 |
+
$.extend(dims, {'width': 32, 'height': d.find('.slb_data').outerHeight()})
|
187 |
+
}
|
188 |
+
return dims;
|
189 |
+
},
|
190 |
+
/**
|
191 |
+
* Theme margins
|
192 |
+
* Reports additional margins used for positioning viewer
|
193 |
+
*/
|
194 |
+
'margin': function() {
|
195 |
+
var m = {'height': 0, 'width': 0};
|
196 |
+
if ( document.documentElement.clientWidth > 480 ) {
|
197 |
+
$.extend(m, {'height': 50, 'width': 20});
|
198 |
+
}
|
199 |
+
return m;
|
200 |
+
}
|
201 |
+
};
|
202 |
+
})(jQuery);
|
themes/default/config.rb
ADDED
@@ -0,0 +1,23 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# Require any additional compass plugins here.
|
2 |
+
|
3 |
+
# Set this to the root of your project when deployed:
|
4 |
+
http_path = "/"
|
5 |
+
css_dir = "css"
|
6 |
+
sass_dir = "sass"
|
7 |
+
images_dir = "images"
|
8 |
+
|
9 |
+
# You can select your preferred output style here (can be overridden via the command line):
|
10 |
+
output_style = :compressed
|
11 |
+
|
12 |
+
# To enable relative paths to assets via compass helper functions. Uncomment:
|
13 |
+
# relative_assets = true
|
14 |
+
|
15 |
+
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
16 |
+
# line_comments = false
|
17 |
+
|
18 |
+
|
19 |
+
# If you prefer the indented syntax, you might want to regenerate this
|
20 |
+
# project again passing --syntax sass, or you can uncomment this:
|
21 |
+
# preferred_syntax = :sass
|
22 |
+
# and then run:
|
23 |
+
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
themes/default/css/style.css
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
@import url("//fonts.googleapis.com/css?family=Yanone+Kaffeesatz");#slb_viewer_wrap .slb_theme_slb_default{position:absolute;top:0;left:0;width:100%;z-index:99999;text-align:center;line-height:0;color:#000;font-family:arial, verdana, sans-serif;font-size:12px}#slb_viewer_wrap .slb_theme_slb_default *{margin:0;padding:0;line-height:1.4em;text-align:left;vertical-align:baseline;white-space:normal;outline:none;border:0px;background:none;opacity:1;width:auto;height:auto;position:static;float:none;clear:none}#slb_viewer_wrap .slb_theme_slb_default a,#slb_viewer_wrap .slb_theme_slb_default a:hover{border-bottom:none;color:#000;text-decoration:underline}#slb_viewer_wrap .slb_theme_slb_default a img{border:none}#slb_viewer_wrap .slb_theme_slb_default .slb_viewer_layout{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;z-index:2;position:absolute;top:20px;width:100%;text-align:center}#slb_viewer_wrap .slb_theme_slb_default .slb_viewer_overlay{position:fixed;top:0;left:0;z-index:1;min-height:105%;min-width:100%;background-color:#151410;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);opacity:0.8}#slb_viewer_wrap .slb_theme_slb_default .slb_container{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0 0 64px -40px #fcfcfc;-moz-box-shadow:0 0 64px -40px #fcfcfc;box-shadow:0 0 64px -40px #fcfcfc;position:relative;display:inline-block;background-color:#fff;margin:0 auto;border-radius:5px;padding:16px}#slb_viewer_wrap .slb_theme_slb_default .slb_loading{background:url("../images/loading.gif") center center no-repeat;position:absolute;left:0%;top:0;width:100%;height:100%;min-width:31px;min-height:31px;text-align:center;text-indent:-2000em;line-height:0;display:none}#slb_viewer_wrap .slb_theme_slb_default .slb_template_tag_ui{cursor:pointer;transition:opacity .5s}#slb_viewer_wrap .slb_theme_slb_default .slb_controls{position:absolute;top:8px;right:8px;width:75%;text-align:right}#slb_viewer_wrap .slb_theme_slb_default .slb_controls .slb_template_tag_ui{width:25px;height:25px;float:right;margin-left:2px;text-indent:-2000em;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:0.5}#slb_viewer_wrap .slb_theme_slb_default .slb_controls .slb_template_tag_ui:hover{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);opacity:0.8}#slb_viewer_wrap .slb_theme_slb_default .slb_controls .slb_slideshow .slb_template_tag{background:url("../images/ui_slideshow_play.png") 0 0 no-repeat}#slb_viewer_wrap .slb_theme_slb_default .slb_controls .slb_close .slb_template_tag{background:url("../images/ui_close.png") 0 0 no-repeat}#slb_viewer_wrap .slb_theme_slb_default.slideshow_active .slb_controls .slb_slideshow .slb_template_tag{background:url("../images/ui_slideshow_pause.png") 0 0 no-repeat}#slb_viewer_wrap .slb_theme_slb_default .slb_prev .slb_template_tag,#slb_viewer_wrap .slb_theme_slb_default .slb_next .slb_template_tag{position:absolute;top:20%;height:71%;width:45%;margin-left:4px;background-repeat:no-repeat;text-indent:-2000em;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=50);opacity:0.5}#slb_viewer_wrap .slb_theme_slb_default .slb_prev .slb_template_tag{background-image:url("../images/nav_prev.png");background-position:left 45%}#slb_viewer_wrap .slb_theme_slb_default .slb_next .slb_template_tag{right:4px;background-image:url("../images/nav_next.png");background-position:right 45%}#slb_viewer_wrap .slb_theme_slb_default .slb_prev .slb_template_tag:hover,#slb_viewer_wrap .slb_theme_slb_default .slb_next .slb_template_tag:hover{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}#slb_viewer_wrap .slb_theme_slb_default .slb_content{min-width:200px;min-height:200px;position:relative}#slb_viewer_wrap .slb_theme_slb_default .slb_details{margin:0 auto;line-height:1.4em;text-align:left;overflow:hidden;position:relative}#slb_viewer_wrap .slb_theme_slb_default .slb_details .inner{display:table;width:100%}#slb_viewer_wrap .slb_theme_slb_default .slb_details .slb_data{display:table-caption;caption-side:bottom}#slb_viewer_wrap .slb_theme_slb_default .slb_template_tag_item_content *{width:100%;height:100%}#slb_viewer_wrap .slb_theme_slb_default .slb_data_title,#slb_viewer_wrap .slb_theme_slb_default .slb_group_status{font-family:'Yanone Kaffeesatz', sans-serif;font-size:23px}#slb_viewer_wrap .slb_theme_slb_default .slb_group_status{color:#777;font-style:italic;font-size:18.4px}#slb_viewer_wrap .slb_theme_slb_default .slb_data_desc{display:block;margin-top:0.5em}#slb_viewer_wrap .slb_theme_slb_default.item_single .slb_group_status,#slb_viewer_wrap .slb_theme_slb_default.item_single .slb_nav,#slb_viewer_wrap .slb_theme_slb_default.item_single .slb_slideshow{display:none}#slb_viewer_wrap .slb_theme_slb_default.loading .slb_loading{display:block}#slb_viewer_wrap .slb_theme_slb_default.loading .slb_template_tag_ui{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}@media screen and (max-width: 480px){#slb_viewer_wrap .slb_theme_slb_default{min-height:100%;min-width:320px;width:100%}#slb_viewer_wrap .slb_theme_slb_default .slb_viewer_layout{min-height:100%;min-width:320px;width:100%;display:block}#slb_viewer_wrap .slb_theme_slb_default .slb_container{min-height:100%;min-width:320px;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;max-width:100%;border-radius:0;margin:0;padding:5px;position:absolute;top:0;left:0}#slb_viewer_wrap .slb_theme_slb_default .slb_container .slb_content img,#slb_viewer_wrap .slb_theme_slb_default .slb_container .slb_content iframe,#slb_viewer_wrap .slb_theme_slb_default .slb_container .slb_content object,#slb_viewer_wrap .slb_theme_slb_default .slb_container .slb_content .slb_inner{max-width:100%}#slb_viewer_wrap .slb_theme_slb_default .slb_container .slb_content img{height:auto}#slb_viewer_wrap .slb_theme_slb_default .slb_controls{top:3px;right:3px}#slb_viewer_wrap .slb_theme_slb_default .slb_prev .slb_template_tag,#slb_viewer_wrap .slb_theme_slb_default .slb_next .slb_template_tag{top:17%;height:79%}}
|
{images → themes/default/images}/loading.gif
RENAMED
File without changes
|
themes/default/images/nav_next.png
ADDED
Binary file
|
themes/default/images/nav_prev.png
ADDED
Binary file
|
themes/default/images/ui_close.png
ADDED
Binary file
|
themes/default/images/ui_slideshow_pause.png
ADDED
Binary file
|
themes/default/images/ui_slideshow_play.png
ADDED
Binary file
|
themes/default/layout.html
ADDED
@@ -0,0 +1,41 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<div class="slb_container">
|
2 |
+
<div class="slb_content">
|
3 |
+
{{item.content}}
|
4 |
+
<span class="slb_nav">
|
5 |
+
<div class="slb_prev">
|
6 |
+
{{ui.nav_prev}}
|
7 |
+
</div>
|
8 |
+
<div class="slb_next">
|
9 |
+
{{ui.nav_next}}
|
10 |
+
</div>
|
11 |
+
</span>
|
12 |
+
<span class="slb_controls">
|
13 |
+
<div class="slb_close">
|
14 |
+
{{ui.close}}
|
15 |
+
</div>
|
16 |
+
<div class="slb_slideshow">
|
17 |
+
{{ui.slideshow_control}}
|
18 |
+
</div>
|
19 |
+
</span>
|
20 |
+
<div class="slb_loading">
|
21 |
+
{{ui.loading}}
|
22 |
+
</div>
|
23 |
+
</div>
|
24 |
+
<div class="slb_details">
|
25 |
+
<div class="inner">
|
26 |
+
<div class="slb_data">
|
27 |
+
<div class="slb_data_content">
|
28 |
+
<span class="slb_data_title">
|
29 |
+
{{item.title}}
|
30 |
+
</span>
|
31 |
+
<span class="slb_group_status">
|
32 |
+
{{ui.group_status}}
|
33 |
+
</span>
|
34 |
+
<span class="slb_data_desc">
|
35 |
+
{{item.description}}
|
36 |
+
</span>
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
</div>
|
themes/default/sass/style.scss
ADDED
@@ -0,0 +1,294 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
//Imports
|
2 |
+
|
3 |
+
@import "compass";
|
4 |
+
@import url('//fonts.googleapis.com/css?family=Yanone+Kaffeesatz');
|
5 |
+
|
6 |
+
//Mixins
|
7 |
+
|
8 |
+
@mixin box-sizing-border {
|
9 |
+
@include box-sizing(border-box);
|
10 |
+
}
|
11 |
+
|
12 |
+
@mixin min-dims($width: 200px, $height: 200px) {
|
13 |
+
min-width: $width;
|
14 |
+
min-height: $height;
|
15 |
+
}
|
16 |
+
|
17 |
+
#slb_viewer_wrap {
|
18 |
+
.slb_theme_slb_default {
|
19 |
+
position: absolute;
|
20 |
+
top: 0;
|
21 |
+
left: 0;
|
22 |
+
width: 100%;
|
23 |
+
z-index: 99999;
|
24 |
+
text-align: center;
|
25 |
+
line-height: 0;
|
26 |
+
color:#000;
|
27 |
+
font: {
|
28 |
+
family: arial, verdana, sans-serif;
|
29 |
+
size: 12px;
|
30 |
+
}
|
31 |
+
|
32 |
+
/* Reset */
|
33 |
+
* {
|
34 |
+
margin: 0;
|
35 |
+
padding: 0;
|
36 |
+
line-height: 1.4em;
|
37 |
+
text-align: left;
|
38 |
+
vertical-align: baseline;
|
39 |
+
white-space: normal;
|
40 |
+
outline: none;
|
41 |
+
border: 0px;
|
42 |
+
background: none;
|
43 |
+
opacity: 1;
|
44 |
+
width: auto;
|
45 |
+
height: auto;
|
46 |
+
position: static;
|
47 |
+
float: none;
|
48 |
+
clear: none;
|
49 |
+
}
|
50 |
+
|
51 |
+
/* General */
|
52 |
+
a,
|
53 |
+
a:hover {
|
54 |
+
border-bottom:none;
|
55 |
+
color:#000;
|
56 |
+
text-decoration:underline;
|
57 |
+
}
|
58 |
+
|
59 |
+
a img {
|
60 |
+
border: none;
|
61 |
+
}
|
62 |
+
|
63 |
+
.slb_viewer_layout {
|
64 |
+
@include box-sizing-border;
|
65 |
+
z-index: 2;
|
66 |
+
position: absolute;
|
67 |
+
top: 20px;
|
68 |
+
width: 100%;
|
69 |
+
text-align: center;
|
70 |
+
}
|
71 |
+
|
72 |
+
.slb_viewer_overlay {
|
73 |
+
position: fixed;
|
74 |
+
top: 0;
|
75 |
+
left: 0;
|
76 |
+
z-index: 1;
|
77 |
+
min-height: 105%;
|
78 |
+
min-width: 100%;
|
79 |
+
background-color: #151410;
|
80 |
+
@include opacity(0.8);
|
81 |
+
}
|
82 |
+
|
83 |
+
.slb_container {
|
84 |
+
@include box-sizing-border;
|
85 |
+
@include box-shadow(0 0 64px -40px #fcfcfc);
|
86 |
+
position: relative;
|
87 |
+
display: inline-block;
|
88 |
+
background-color: #fff;
|
89 |
+
margin: 0 auto;
|
90 |
+
border-radius: 5px;
|
91 |
+
padding: 16px;
|
92 |
+
}
|
93 |
+
|
94 |
+
.slb_loading {
|
95 |
+
background: url('../images/loading.gif') center center no-repeat;
|
96 |
+
position: absolute;
|
97 |
+
left: 0%;
|
98 |
+
top: 0;
|
99 |
+
width: 100%;
|
100 |
+
height: 100%;
|
101 |
+
min-width: 31px;
|
102 |
+
min-height: 31px;
|
103 |
+
text-align: center;
|
104 |
+
text-indent: -2000em;
|
105 |
+
line-height: 0;
|
106 |
+
display: none;
|
107 |
+
}
|
108 |
+
|
109 |
+
.slb_template_tag_ui {
|
110 |
+
cursor: pointer;
|
111 |
+
transition: opacity .5s;
|
112 |
+
}
|
113 |
+
|
114 |
+
/* UI */
|
115 |
+
.slb_controls {
|
116 |
+
position: absolute;
|
117 |
+
top: 8px;
|
118 |
+
right: 8px;
|
119 |
+
width: 75%;
|
120 |
+
text-align: right;
|
121 |
+
|
122 |
+
.slb_template_tag_ui {
|
123 |
+
width: 25px;
|
124 |
+
height: 25px;
|
125 |
+
float: right;
|
126 |
+
margin-left: 2px;
|
127 |
+
text-indent: -2000em;
|
128 |
+
@include opacity(.5);
|
129 |
+
}
|
130 |
+
|
131 |
+
.slb_template_tag_ui:hover {
|
132 |
+
@include opacity(.8);
|
133 |
+
}
|
134 |
+
|
135 |
+
.slb_slideshow .slb_template_tag {
|
136 |
+
background: url('../images/ui_slideshow_play.png') 0 0 no-repeat;
|
137 |
+
}
|
138 |
+
|
139 |
+
.slb_close .slb_template_tag {
|
140 |
+
background: url('../images/ui_close.png') 0 0 no-repeat;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
&.slideshow_active .slb_controls .slb_slideshow .slb_template_tag {
|
145 |
+
background: url('../images/ui_slideshow_pause.png') 0 0 no-repeat;
|
146 |
+
}
|
147 |
+
|
148 |
+
/* Navigation */
|
149 |
+
$ui_nav_pos: 45%;
|
150 |
+
%ui_nav {
|
151 |
+
position: absolute;
|
152 |
+
top: 20%;
|
153 |
+
height: 71%;
|
154 |
+
width: 45%;
|
155 |
+
margin-left: 4px;
|
156 |
+
background-repeat: no-repeat;
|
157 |
+
text-indent: -2000em;
|
158 |
+
@include opacity(.5);
|
159 |
+
}
|
160 |
+
|
161 |
+
.slb_prev .slb_template_tag {
|
162 |
+
background-image: url('../images/nav_prev.png');
|
163 |
+
background-position: left $ui_nav_pos;
|
164 |
+
}
|
165 |
+
|
166 |
+
.slb_next .slb_template_tag {
|
167 |
+
right: 4px;
|
168 |
+
background-image: url('../images/nav_next.png');
|
169 |
+
background-position: right $ui_nav_pos;
|
170 |
+
}
|
171 |
+
|
172 |
+
.slb_prev, .slb_next {
|
173 |
+
.slb_template_tag {
|
174 |
+
@extend %ui_nav;
|
175 |
+
&:hover { @include opacity(1); }
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
/* Content */
|
180 |
+
.slb_content {
|
181 |
+
@include min-dims;
|
182 |
+
position: relative;
|
183 |
+
}
|
184 |
+
|
185 |
+
.slb_details {
|
186 |
+
margin: 0 auto;
|
187 |
+
line-height: 1.4em;
|
188 |
+
text-align: left;
|
189 |
+
overflow: hidden;
|
190 |
+
position: relative;
|
191 |
+
.inner {
|
192 |
+
display: table;
|
193 |
+
width: 100%;
|
194 |
+
}
|
195 |
+
.slb_data {
|
196 |
+
display: table-caption;
|
197 |
+
caption-side: bottom;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
.slb_template_tag_item_content * {
|
202 |
+
width: 100%;
|
203 |
+
height: 100%;
|
204 |
+
}
|
205 |
+
|
206 |
+
/* Title */
|
207 |
+
$title-size: 23px;
|
208 |
+
|
209 |
+
.slb_data_title {
|
210 |
+
font-family: 'Yanone Kaffeesatz', sans-serif;
|
211 |
+
font-size: $title-size;
|
212 |
+
}
|
213 |
+
|
214 |
+
.slb_group_status {
|
215 |
+
@extend .slb_data_title;
|
216 |
+
color: #777;
|
217 |
+
font-style: italic;
|
218 |
+
font-size: $title-size * .8;
|
219 |
+
}
|
220 |
+
|
221 |
+
.slb_data_desc {
|
222 |
+
display: block;
|
223 |
+
margin-top: 0.5em;
|
224 |
+
}
|
225 |
+
|
226 |
+
/* Single */
|
227 |
+
&.item_single {
|
228 |
+
.slb_group_status,
|
229 |
+
.slb_nav,
|
230 |
+
.slb_slideshow {
|
231 |
+
display: none;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
/* Loading */
|
235 |
+
&.loading {
|
236 |
+
.slb_loading {
|
237 |
+
display: block;
|
238 |
+
}
|
239 |
+
.slb_details,
|
240 |
+
.slb_template_tag {
|
241 |
+
//display: none;
|
242 |
+
}
|
243 |
+
|
244 |
+
.slb_template_tag_ui {
|
245 |
+
@include opacity(0);
|
246 |
+
}
|
247 |
+
}
|
248 |
+
|
249 |
+
//Media
|
250 |
+
|
251 |
+
//Small screen
|
252 |
+
@media screen and (max-width: 480px) {
|
253 |
+
@mixin vsizing {
|
254 |
+
min-height: 100%;
|
255 |
+
min-width: 320px;
|
256 |
+
width: 100%;
|
257 |
+
}
|
258 |
+
@include vsizing;
|
259 |
+
.slb_viewer_layout {
|
260 |
+
@include vsizing;
|
261 |
+
display: block;
|
262 |
+
}
|
263 |
+
.slb_container {
|
264 |
+
@include vsizing;
|
265 |
+
@include box-sizing-border;
|
266 |
+
@include box-shadow(none);
|
267 |
+
max-width: 100%;
|
268 |
+
border-radius: 0;
|
269 |
+
margin: 0;
|
270 |
+
padding: 5px;
|
271 |
+
position: absolute;
|
272 |
+
top: 0;
|
273 |
+
left: 0;
|
274 |
+
.slb_content {
|
275 |
+
img, iframe, object, .slb_inner {
|
276 |
+
max-width: 100%;
|
277 |
+
}
|
278 |
+
img {
|
279 |
+
height: auto;
|
280 |
+
}
|
281 |
+
}
|
282 |
+
}
|
283 |
+
.slb_controls {
|
284 |
+
top: 3px;
|
285 |
+
right: 3px;
|
286 |
+
}
|
287 |
+
|
288 |
+
%ui_nav {
|
289 |
+
top: 17%;
|
290 |
+
height: 79%;
|
291 |
+
}
|
292 |
+
}
|
293 |
+
}
|
294 |
+
}
|