Version Description
- This version is just for beta testers
<?php code(); // goes in backticks ?>
Download this release
Release Info
Developer | MaryVogt |
Plugin | Editorial Calendar |
Version | 0.1 |
Comparing to | |
See all releases |
Version 0.1
- LICENSE.txt +236 -0
- edcal.css +172 -0
- edcal.js +911 -0
- edcal.php +374 -0
- images/loading.gif +0 -0
- images/loading_post.gif +0 -0
- lib/date.js +104 -0
- lib/humanmsg.css +36 -0
- lib/humanmsg.js +82 -0
- lib/jquery.bgiframe.js +104 -0
- lib/jquery.delegate.js +56 -0
- lib/jquery.tools.min.js +27 -0
- lib/jquery.tooltip.css +9 -0
- lib/jquery.tooltip.js +329 -0
- lib/json2.js +480 -0
- lib/tools.scrollable-1.1.2.js +439 -0
- lib/tools.scrollable.mousewheel-1.0.1.js +103 -0
- lib/ui.core.js +519 -0
- lib/ui.draggable.js +773 -0
- lib/ui.droppable.js +282 -0
- readme.txt +33 -0
LICENSE.txt
ADDED
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Apache License
|
2 |
+
Version 2.0, January 2004
|
3 |
+
http://www.apache.org/licenses/
|
4 |
+
|
5 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6 |
+
|
7 |
+
1. Definitions.
|
8 |
+
|
9 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
10 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
11 |
+
|
12 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13 |
+
the copyright owner that is granting the License.
|
14 |
+
|
15 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
16 |
+
other entities that control, are controlled by, or are under common
|
17 |
+
control with that entity. For the purposes of this definition,
|
18 |
+
"control" means (i) the power, direct or indirect, to cause the
|
19 |
+
direction or management of such entity, whether by contract or
|
20 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22 |
+
|
23 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24 |
+
exercising permissions granted by this License.
|
25 |
+
|
26 |
+
"Source" form shall mean the preferred form for making modifications,
|
27 |
+
including but not limited to software source code, documentation
|
28 |
+
source, and configuration files.
|
29 |
+
|
30 |
+
"Object" form shall mean any form resulting from mechanical
|
31 |
+
transformation or translation of a Source form, including but
|
32 |
+
not limited to compiled object code, generated documentation,
|
33 |
+
and conversions to other media types.
|
34 |
+
|
35 |
+
"Work" shall mean the work of authorship, whether in Source or
|
36 |
+
Object form, made available under the License, as indicated by a
|
37 |
+
copyright notice that is included in or attached to the work
|
38 |
+
(an example is provided in the Appendix below).
|
39 |
+
|
40 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41 |
+
form, that is based on (or derived from) the Work and for which the
|
42 |
+
editorial revisions, annotations, elaborations, or other modifications
|
43 |
+
represent, as a whole, an original work of authorship. For the purposes
|
44 |
+
of this License, Derivative Works shall not include works that remain
|
45 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46 |
+
the Work and Derivative Works thereof.
|
47 |
+
|
48 |
+
"Contribution" shall mean any work of authorship, including
|
49 |
+
the original version of the Work and any modifications or additions
|
50 |
+
to that Work or Derivative Works thereof, that is intentionally
|
51 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
54 |
+
means any form of electronic, verbal, or written communication sent
|
55 |
+
to the Licensor or its representatives, including but not limited to
|
56 |
+
communication on electronic mailing lists, source code control systems,
|
57 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
58 |
+
Licensor for the purpose of discussing and improving the Work, but
|
59 |
+
excluding communication that is conspicuously marked or otherwise
|
60 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
61 |
+
|
62 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63 |
+
on behalf of whom a Contribution has been received by Licensor and
|
64 |
+
subsequently incorporated within the Work.
|
65 |
+
|
66 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67 |
+
this License, each Contributor hereby grants to You a perpetual,
|
68 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69 |
+
copyright license to reproduce, prepare Derivative Works of,
|
70 |
+
publicly display, publicly perform, sublicense, and distribute the
|
71 |
+
Work and such Derivative Works in Source or Object form.
|
72 |
+
|
73 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74 |
+
this License, each Contributor hereby grants to You a perpetual,
|
75 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76 |
+
(except as stated in this section) patent license to make, have made,
|
77 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78 |
+
where such license applies only to those patent claims licensable
|
79 |
+
by such Contributor that are necessarily infringed by their
|
80 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
81 |
+
with the Work to which such Contribution(s) was submitted. If You
|
82 |
+
institute patent litigation against any entity (including a
|
83 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84 |
+
or a Contribution incorporated within the Work constitutes direct
|
85 |
+
or contributory patent infringement, then any patent licenses
|
86 |
+
granted to You under this License for that Work shall terminate
|
87 |
+
as of the date such litigation is filed.
|
88 |
+
|
89 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
90 |
+
Work or Derivative Works thereof in any medium, with or without
|
91 |
+
modifications, and in Source or Object form, provided that You
|
92 |
+
meet the following conditions:
|
93 |
+
|
94 |
+
(a) You must give any other recipients of the Work or
|
95 |
+
Derivative Works a copy of this License; and
|
96 |
+
|
97 |
+
(b) You must cause any modified files to carry prominent notices
|
98 |
+
stating that You changed the files; and
|
99 |
+
|
100 |
+
(c) You must retain, in the Source form of any Derivative Works
|
101 |
+
that You distribute, all copyright, patent, trademark, and
|
102 |
+
attribution notices from the Source form of the Work,
|
103 |
+
excluding those notices that do not pertain to any part of
|
104 |
+
the Derivative Works; and
|
105 |
+
|
106 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107 |
+
distribution, then any Derivative Works that You distribute must
|
108 |
+
include a readable copy of the attribution notices contained
|
109 |
+
within such NOTICE file, excluding those notices that do not
|
110 |
+
pertain to any part of the Derivative Works, in at least one
|
111 |
+
of the following places: within a NOTICE text file distributed
|
112 |
+
as part of the Derivative Works; within the Source form or
|
113 |
+
documentation, if provided along with the Derivative Works; or,
|
114 |
+
within a display generated by the Derivative Works, if and
|
115 |
+
wherever such third-party notices normally appear. The contents
|
116 |
+
of the NOTICE file are for informational purposes only and
|
117 |
+
do not modify the License. You may add Your own attribution
|
118 |
+
notices within Derivative Works that You distribute, alongside
|
119 |
+
or as an addendum to the NOTICE text from the Work, provided
|
120 |
+
that such additional attribution notices cannot be construed
|
121 |
+
as modifying the License.
|
122 |
+
|
123 |
+
You may add Your own copyright statement to Your modifications and
|
124 |
+
may provide additional or different license terms and conditions
|
125 |
+
for use, reproduction, or distribution of Your modifications, or
|
126 |
+
for any such Derivative Works as a whole, provided Your use,
|
127 |
+
reproduction, and distribution of the Work otherwise complies with
|
128 |
+
the conditions stated in this License.
|
129 |
+
|
130 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131 |
+
any Contribution intentionally submitted for inclusion in the Work
|
132 |
+
by You to the Licensor shall be under the terms and conditions of
|
133 |
+
this License, without any additional terms or conditions.
|
134 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135 |
+
the terms of any separate license agreement you may have executed
|
136 |
+
with Licensor regarding such Contributions.
|
137 |
+
|
138 |
+
6. Trademarks. This License does not grant permission to use the trade
|
139 |
+
names, trademarks, service marks, or product names of the Licensor,
|
140 |
+
except as required for reasonable and customary use in describing the
|
141 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
142 |
+
|
143 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144 |
+
agreed to in writing, Licensor provides the Work (and each
|
145 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147 |
+
implied, including, without limitation, any warranties or conditions
|
148 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150 |
+
appropriateness of using or redistributing the Work and assume any
|
151 |
+
risks associated with Your exercise of permissions under this License.
|
152 |
+
|
153 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
154 |
+
whether in tort (including negligence), contract, or otherwise,
|
155 |
+
unless required by applicable law (such as deliberate and grossly
|
156 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157 |
+
liable to You for damages, including any direct, indirect, special,
|
158 |
+
incidental, or consequential damages of any character arising as a
|
159 |
+
result of this License or out of the use or inability to use the
|
160 |
+
Work (including but not limited to damages for loss of goodwill,
|
161 |
+
work stoppage, computer failure or malfunction, or any and all
|
162 |
+
other commercial damages or losses), even if such Contributor
|
163 |
+
has been advised of the possibility of such damages.
|
164 |
+
|
165 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
167 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168 |
+
or other liability obligations and/or rights consistent with this
|
169 |
+
License. However, in accepting such obligations, You may act only
|
170 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171 |
+
of any other Contributor, and only if You agree to indemnify,
|
172 |
+
defend, and hold each Contributor harmless for any liability
|
173 |
+
incurred by, or claims asserted against, such Contributor by reason
|
174 |
+
of your accepting any such warranty or additional liability.
|
175 |
+
|
176 |
+
END OF TERMS AND CONDITIONS
|
177 |
+
|
178 |
+
APPENDIX: How to apply the Apache License to your work.
|
179 |
+
|
180 |
+
To apply the Apache License to your work, attach the following
|
181 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
182 |
+
replaced with your own identifying information. (Don't include
|
183 |
+
the brackets!) The text should be enclosed in the appropriate
|
184 |
+
comment syntax for the file format. We also recommend that a
|
185 |
+
file or class name and description of purpose be included on the
|
186 |
+
same "printed page" as the copyright notice for easier
|
187 |
+
identification within third-party archives.
|
188 |
+
|
189 |
+
Copyright [yyyy] [name of copyright owner]
|
190 |
+
|
191 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192 |
+
you may not use this file except in compliance with the License.
|
193 |
+
You may obtain a copy of the License at
|
194 |
+
|
195 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
196 |
+
|
197 |
+
Unless required by applicable law or agreed to in writing, software
|
198 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200 |
+
See the License for the specific language governing permissions and
|
201 |
+
limitations under the License.
|
202 |
+
|
203 |
+
|
204 |
+
/*
|
205 |
+
* One-JAR� (http://www.simontuffs.com/one-jar). Copyright (c) 2004-2007,
|
206 |
+
* P. Simon Tuffs (simon@simontuffs.com). All rights reserved.
|
207 |
+
*
|
208 |
+
* Redistribution and use in source and binary forms, with or without
|
209 |
+
* modification, are permitted provided that the following conditions are met:
|
210 |
+
*
|
211 |
+
* Redistributions of source code must retain the above copyright notice, this
|
212 |
+
* list of conditions and the following disclaimer.
|
213 |
+
*
|
214 |
+
* Redistributions in binary form must reproduce the above copyright notice,
|
215 |
+
* this list of conditions and the following disclaimer in the documentation
|
216 |
+
* and/or other materials provided with the distribution.
|
217 |
+
*
|
218 |
+
* Neither the name of P. Simon Tuffs, nor the names of any contributors,
|
219 |
+
* nor the name One-JAR may be used to endorse or promote products derived
|
220 |
+
* from this software without specific prior written permission.
|
221 |
+
*
|
222 |
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
223 |
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
224 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
225 |
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
226 |
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
227 |
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
228 |
+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
229 |
+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
230 |
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
231 |
+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
232 |
+
* POSSIBILITY OF SUCH DAMAGE.
|
233 |
+
*
|
234 |
+
* Including this file inside the built One-JAR file conforms with these terms.
|
235 |
+
*/
|
236 |
+
|
edcal.css
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#edcal_scrollable {
|
2 |
+
width: 98%;
|
3 |
+
/* required settings */
|
4 |
+
position:relative;
|
5 |
+
overflow:hidden;
|
6 |
+
|
7 |
+
/* This height will be reset with JavaScript */
|
8 |
+
height: 100%;
|
9 |
+
}
|
10 |
+
|
11 |
+
#cal {
|
12 |
+
position:absolute;
|
13 |
+
|
14 |
+
/* this time we have very large space for the height */
|
15 |
+
height:100%;
|
16 |
+
}
|
17 |
+
|
18 |
+
.day {
|
19 |
+
/*background-color: #F2F2F2;*/
|
20 |
+
background-color: #e0e0e0;;
|
21 |
+
}
|
22 |
+
|
23 |
+
.scrollHover {
|
24 |
+
background: lightblue;
|
25 |
+
}
|
26 |
+
|
27 |
+
.row {
|
28 |
+
height: 100%;
|
29 |
+
}
|
30 |
+
|
31 |
+
.jan, .mar, .may, .jul, .sep, .nov {
|
32 |
+
background-color: #F1F1F1;
|
33 |
+
}
|
34 |
+
|
35 |
+
.today {
|
36 |
+
background-color: wheat;
|
37 |
+
}
|
38 |
+
|
39 |
+
.today .daylabel {
|
40 |
+
font-weight: bold;
|
41 |
+
}
|
42 |
+
|
43 |
+
.dayobj {
|
44 |
+
position: relative;
|
45 |
+
width: 100%;
|
46 |
+
height: 100%;
|
47 |
+
}
|
48 |
+
|
49 |
+
.daylabel {
|
50 |
+
position: absolute;
|
51 |
+
top: 0px;
|
52 |
+
right: 5px;
|
53 |
+
}
|
54 |
+
|
55 |
+
.saturday .daylabel {
|
56 |
+
right: 20px;
|
57 |
+
}
|
58 |
+
|
59 |
+
.post {
|
60 |
+
display: block;
|
61 |
+
list-style-type: none;
|
62 |
+
background: #FFFFE0;
|
63 |
+
z-index: 10;
|
64 |
+
cursor: move;
|
65 |
+
}
|
66 |
+
|
67 |
+
.day-active {
|
68 |
+
background-color: lightyellow;
|
69 |
+
}
|
70 |
+
|
71 |
+
.dayhead {
|
72 |
+
font-weight: bold;
|
73 |
+
text-align: center;
|
74 |
+
}
|
75 |
+
|
76 |
+
#rowhead {
|
77 |
+
height: 1.5em;
|
78 |
+
top: 0px;
|
79 |
+
width: 98%
|
80 |
+
}
|
81 |
+
|
82 |
+
#topbar {
|
83 |
+
margin-bottom: 1em;
|
84 |
+
width: 98%;
|
85 |
+
margin-top: 1em;
|
86 |
+
position: relative;
|
87 |
+
height: 2em;
|
88 |
+
}
|
89 |
+
|
90 |
+
#topleft {
|
91 |
+
position: absolute;
|
92 |
+
left: 75px;
|
93 |
+
top: 5px;
|
94 |
+
}
|
95 |
+
|
96 |
+
#topright {
|
97 |
+
position: absolute;
|
98 |
+
left: 15%;
|
99 |
+
top: 0px;
|
100 |
+
width: 85%;
|
101 |
+
text-align: right;
|
102 |
+
}
|
103 |
+
|
104 |
+
#moveToToday {
|
105 |
+
margin-left: 2em;
|
106 |
+
}
|
107 |
+
|
108 |
+
.future {
|
109 |
+
background-color: #FFFFE0;
|
110 |
+
}
|
111 |
+
|
112 |
+
.draft {
|
113 |
+
background-color: #cccccc;
|
114 |
+
|
115 |
+
}
|
116 |
+
|
117 |
+
.publish {
|
118 |
+
background-color: #dde4fb;
|
119 |
+
}
|
120 |
+
|
121 |
+
#loading {
|
122 |
+
background-image: url('images/loading.gif');
|
123 |
+
background-repeat: no-repeat;
|
124 |
+
width: 43px;
|
125 |
+
height: 11px;
|
126 |
+
display: block;
|
127 |
+
position: absolute;
|
128 |
+
top: 5px;
|
129 |
+
right: 5px;
|
130 |
+
}
|
131 |
+
|
132 |
+
.loadingclass {
|
133 |
+
background-image: url('images/loading_post.gif');
|
134 |
+
background-position: top right;
|
135 |
+
background-repeat: no-repeat;
|
136 |
+
cursor: auto;
|
137 |
+
}
|
138 |
+
|
139 |
+
.postlist {
|
140 |
+
position: relative;
|
141 |
+
top: 1.5em;
|
142 |
+
height: 85%;
|
143 |
+
overflow: auto;
|
144 |
+
}
|
145 |
+
|
146 |
+
.page-numbers {
|
147 |
+
text-decoration: none;
|
148 |
+
border: none;
|
149 |
+
border-bottom-style: none;
|
150 |
+
}
|
151 |
+
|
152 |
+
#tooltip p {
|
153 |
+
margin-left: 1.5em;
|
154 |
+
}
|
155 |
+
|
156 |
+
#tooltip h3 {
|
157 |
+
max-width: 15em;
|
158 |
+
margin-bottom: -10px;
|
159 |
+
}
|
160 |
+
|
161 |
+
#tooltip {
|
162 |
+
background: white;
|
163 |
+
opacity: 1;
|
164 |
+
padding: 1em;
|
165 |
+
padding-bottom: 0em;
|
166 |
+
border: thin solid lightgray;
|
167 |
+
-moz-border-radius:11px;
|
168 |
+
}
|
169 |
+
|
170 |
+
.ui-draggable-dragging {
|
171 |
+
width: 8em;
|
172 |
+
}
|
edcal.js
ADDED
@@ -0,0 +1,911 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*******************************************************************************
|
2 |
+
*
|
3 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
* you may not use this file except in compliance with the License.
|
5 |
+
* You may obtain a copy of the License at
|
6 |
+
*
|
7 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
*
|
9 |
+
* Unless required by applicable law or agreed to in writing, software
|
10 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
* See the License for the specific language governing permissions and
|
13 |
+
* limitations under the License.
|
14 |
+
*
|
15 |
+
******************************************************************************/
|
16 |
+
|
17 |
+
/*
|
18 |
+
This is the WordPress editorial calendar. It is a continuous
|
19 |
+
calendar in both directions. That means instead of showing only
|
20 |
+
one month at a time it shows the months running together. Users
|
21 |
+
can scroll from one month to the next using the up and down
|
22 |
+
arrow keys, the page up and page down keys, the next and previous
|
23 |
+
month buttons, and their mouse wheel.
|
24 |
+
|
25 |
+
The calendar shows five weeks visible at a time and maintains 11
|
26 |
+
weeks of rendered HTML. Only the middle weeks are visible.
|
27 |
+
|
28 |
+
Week 1
|
29 |
+
Week 2
|
30 |
+
Week 3
|
31 |
+
- Week 4 -
|
32 |
+
| Week 5 |
|
33 |
+
| Week 6 |
|
34 |
+
| Week 7 |
|
35 |
+
- Week 8 -
|
36 |
+
Week 9
|
37 |
+
Week 10
|
38 |
+
Week 11
|
39 |
+
|
40 |
+
When the user scrolls down one week the new week is added at the
|
41 |
+
end of the calendar and the first week is removed. In this way
|
42 |
+
the calendar will only ever have 11 weeks total and won't use up
|
43 |
+
excessive memory.
|
44 |
+
|
45 |
+
This calendar uses AJAX to call into the functions defined in
|
46 |
+
edcal.php. These functions get posts and change post dates.
|
47 |
+
|
48 |
+
The HTML structure of the calendar is:
|
49 |
+
|
50 |
+
<div id="cal">
|
51 |
+
<div id="row08Nov2009">
|
52 |
+
<div id="row08Nov2009row">
|
53 |
+
<div class="day sunday nov" id="08Nov2009">
|
54 |
+
<div class="dayobj">
|
55 |
+
<div class="daylabel">8</div>
|
56 |
+
<ul class="postlist">
|
57 |
+
</ul>
|
58 |
+
</div>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
*/
|
64 |
+
var edcal = {
|
65 |
+
/*
|
66 |
+
* True if the calendar is in the process of moving
|
67 |
+
*/
|
68 |
+
isMoving: false,
|
69 |
+
|
70 |
+
/*
|
71 |
+
This is the base URL we use to make AJAX calls back
|
72 |
+
to the server. This values is set in code generated
|
73 |
+
from edcal.php.
|
74 |
+
*/
|
75 |
+
ajax_url: '',
|
76 |
+
|
77 |
+
/*
|
78 |
+
* The cache of dates we have already loaded posts for.
|
79 |
+
*/
|
80 |
+
cacheDates : new Array(),
|
81 |
+
|
82 |
+
/*
|
83 |
+
* The ID of the timer we use to batch new post requests
|
84 |
+
*/
|
85 |
+
tID: null,
|
86 |
+
|
87 |
+
/*
|
88 |
+
* The number of steps moving for this timer.
|
89 |
+
*/
|
90 |
+
steps: 0,
|
91 |
+
|
92 |
+
/*
|
93 |
+
* The constant for the concurrency error.
|
94 |
+
*/
|
95 |
+
CONCURRENCY_ERROR: 4,
|
96 |
+
|
97 |
+
/*
|
98 |
+
* The constant for the user permission error
|
99 |
+
*/
|
100 |
+
PERMISSION_ERROR: 5,
|
101 |
+
|
102 |
+
/*
|
103 |
+
The direction the calendar last moved.
|
104 |
+
true = down = to the future
|
105 |
+
false = up = to the past
|
106 |
+
|
107 |
+
*/
|
108 |
+
currentDirection: true,
|
109 |
+
|
110 |
+
/*
|
111 |
+
This date is our index. When the calendar moves we
|
112 |
+
update this date to indicate the next rows we need
|
113 |
+
to add.
|
114 |
+
*/
|
115 |
+
_wDate: Date.today(),
|
116 |
+
|
117 |
+
/*
|
118 |
+
* The date since the previous move
|
119 |
+
*/
|
120 |
+
moveDate: null,
|
121 |
+
|
122 |
+
/*
|
123 |
+
A cache of all the posts we have loaded so far. The
|
124 |
+
data structure is:
|
125 |
+
|
126 |
+
posts [date - ddMMMyyyy][posts array - post object from JSON data]
|
127 |
+
*/
|
128 |
+
posts: new Array(50),
|
129 |
+
|
130 |
+
/*
|
131 |
+
IE will sometimes fire the resize event twice for the same resize
|
132 |
+
action. We save it so we only resize the calendar once and avoid
|
133 |
+
any flickering.
|
134 |
+
*/
|
135 |
+
windowHeight: 0,
|
136 |
+
|
137 |
+
/*
|
138 |
+
This function aligns the grid in two directions. There
|
139 |
+
is a vertical grid with a row of each week and a horizontal
|
140 |
+
grid for each week with a list of days.
|
141 |
+
*/
|
142 |
+
alignGrid: function(/*string*/ gridid, /*int*/ cols, /*int*/ cellWidth, /*int*/ cellHeight, /*int*/ padding) {
|
143 |
+
var x = 0;
|
144 |
+
var y = 0;
|
145 |
+
var count = 1;
|
146 |
+
|
147 |
+
jQuery(gridid).each(function(){
|
148 |
+
jQuery(this).css("position", "relative");
|
149 |
+
|
150 |
+
jQuery(this).children("div").each(function(){
|
151 |
+
jQuery(this).css({
|
152 |
+
width: cellWidth + "%",
|
153 |
+
height: cellHeight + "%",
|
154 |
+
position: "absolute",
|
155 |
+
left: x + "%",
|
156 |
+
top: y + "%"
|
157 |
+
});
|
158 |
+
|
159 |
+
if ((count % cols) === 0){
|
160 |
+
x = 0;
|
161 |
+
y += cellHeight + padding;
|
162 |
+
}else{
|
163 |
+
x += cellWidth + padding;
|
164 |
+
}
|
165 |
+
|
166 |
+
count++;
|
167 |
+
});
|
168 |
+
});
|
169 |
+
},
|
170 |
+
|
171 |
+
/*
|
172 |
+
This is a helper function to align the calendar so we don't
|
173 |
+
have to change the cell sizes in multiple places.
|
174 |
+
*/
|
175 |
+
alignCal: function() {
|
176 |
+
edcal.alignGrid("#cal", 1, 100, 20, 0.25);
|
177 |
+
},
|
178 |
+
|
179 |
+
|
180 |
+
/*
|
181 |
+
This function creates the days header at the top of the
|
182 |
+
calendar.
|
183 |
+
|
184 |
+
TODO: We should localize these values
|
185 |
+
*/
|
186 |
+
createDaysHeader: function() {
|
187 |
+
var html = '<div class="dayhead">Sunday</div>';
|
188 |
+
html += '<div class="dayhead">Monday</div>';
|
189 |
+
html += '<div class="dayhead">Tuesday</div>';
|
190 |
+
html += '<div class="dayhead">Wednesday</div>';
|
191 |
+
html += '<div class="dayhead">Thursday</div>';
|
192 |
+
html += '<div class="dayhead">Friday</div>';
|
193 |
+
html += '<div class="dayhead">Saturday</div>';
|
194 |
+
|
195 |
+
jQuery("#rowhead").append(html);
|
196 |
+
|
197 |
+
edcal.alignGrid("#rowhead", 7, 14.2, 100, 0.25);
|
198 |
+
},
|
199 |
+
|
200 |
+
/*
|
201 |
+
Creates a row of the calendar and adds all of the CSS classes
|
202 |
+
and listeners for each calendar day.
|
203 |
+
*/
|
204 |
+
createRow: function(/*jQuery*/ parent, /*bool*/ append) {
|
205 |
+
var _date = edcal._wDate.clone();
|
206 |
+
|
207 |
+
var newrow = '<div class="rowcont" id="' + 'row' + edcal._wDate.toString("ddMMMyyyy") + '">' +
|
208 |
+
'<div id="' + 'row' + edcal._wDate.toString("ddMMMyyyy") + 'row" class="row">';
|
209 |
+
for (var i = 0; i < 7; i++) {
|
210 |
+
newrow +='<div id="' + _date.toString("ddMMMyyyy") + '" class="day ' + _date.toString("dddd").toLowerCase() + ' ' +
|
211 |
+
_date.toString("MMM").toLowerCase() + '">';
|
212 |
+
|
213 |
+
newrow += '<div class="dayobj">';
|
214 |
+
|
215 |
+
newrow += '<div class="daylabel">';
|
216 |
+
if (_date.toString("dd") == "01") {
|
217 |
+
newrow += _date.toString("MMM d");
|
218 |
+
} else {
|
219 |
+
newrow += _date.toString("d");
|
220 |
+
}
|
221 |
+
newrow += '</div>';
|
222 |
+
|
223 |
+
newrow += '<ul class="postlist">';
|
224 |
+
|
225 |
+
newrow += edcal.getPostItems(_date.toString("ddMMMyyyy"));
|
226 |
+
|
227 |
+
newrow += '</ul>';
|
228 |
+
|
229 |
+
newrow += '</div>';
|
230 |
+
newrow += '</div>';
|
231 |
+
_date.add(1).days();
|
232 |
+
}
|
233 |
+
|
234 |
+
newrow += '</div></div';
|
235 |
+
|
236 |
+
if (append) {
|
237 |
+
parent.append(newrow);
|
238 |
+
|
239 |
+
} else {
|
240 |
+
parent.prepend(newrow);
|
241 |
+
}
|
242 |
+
|
243 |
+
edcal.alignGrid("#row" + edcal._wDate.toString("ddMMMyyyy") + "row", 7, 14.2, 100, 0.25);
|
244 |
+
|
245 |
+
jQuery('#row' + edcal._wDate.toString("ddMMMyyyy") + ' .day').each( function() {
|
246 |
+
edcal.addTooltip(jQuery(this).attr("id"));
|
247 |
+
});
|
248 |
+
|
249 |
+
edcal.draggablePost('#row' + edcal._wDate.toString("ddMMMyyyy") + ' .post');
|
250 |
+
|
251 |
+
jQuery('#row' + edcal._wDate.toString("ddMMMyyyy") + ' .day').droppable({
|
252 |
+
hoverClass: 'day-active',
|
253 |
+
accept: '.post',
|
254 |
+
greedy: true,
|
255 |
+
tolerance: 'pointer',
|
256 |
+
drop: function(event, ui) {
|
257 |
+
//output('dropped ui.draggable.attr("id"): ' + ui.draggable.attr("id"));
|
258 |
+
//output('dropped on jQuery(this).attr("id"): ' + jQuery(this).attr("id"));
|
259 |
+
//output('ui.draggable.html(): ' + ui.draggable.html());
|
260 |
+
|
261 |
+
var dayId = ui.draggable.parent().parent().parent().attr("id");
|
262 |
+
|
263 |
+
// Step 0. Get the post object from the map
|
264 |
+
var post = edcal.findPostForId(ui.draggable.parent().parent().parent().attr("id"), ui.draggable.attr("id"));
|
265 |
+
output("post: " + post);
|
266 |
+
|
267 |
+
// Step 1. Remove the post from the posts map
|
268 |
+
edcal.removePostFromMap(ui.draggable.parent().parent().attr("id"),
|
269 |
+
ui.draggable.attr("id"));
|
270 |
+
|
271 |
+
// Step 2. Remove the old element from the old parent.
|
272 |
+
jQuery('#' + ui.draggable.attr("id")).remove();
|
273 |
+
|
274 |
+
// Step 3. Add the item to the new DOM parent
|
275 |
+
jQuery('#' + jQuery(this).attr("id") + ' .postlist').append(edcal.createPostItem(post,
|
276 |
+
jQuery(this).attr("id")));
|
277 |
+
|
278 |
+
// Step 4. Don't forget to make the new item draggable
|
279 |
+
//jQuery('#' + jQuery(this).attr("id") + ' .post').draggable({ revert: 'invalid'});
|
280 |
+
|
281 |
+
// Step 5. And add the tooltip
|
282 |
+
edcal.addTooltip(jQuery(this).attr("id"));
|
283 |
+
|
284 |
+
if (dayId == jQuery(this).attr("id")) {
|
285 |
+
/*
|
286 |
+
* If they dropped back on to the day they started with we
|
287 |
+
* don't want to go back to the server.
|
288 |
+
*/
|
289 |
+
edcal.draggablePost('#' + jQuery(this).attr("id") + ' .post');
|
290 |
+
} else {
|
291 |
+
// Step6. Update the date on the server
|
292 |
+
edcal.changeDate(jQuery(this).attr("id"), post);
|
293 |
+
}
|
294 |
+
}
|
295 |
+
});
|
296 |
+
|
297 |
+
return jQuery('row' + edcal._wDate.toString("ddMMMyyyy"));
|
298 |
+
},
|
299 |
+
|
300 |
+
draggablePost: function(/*post selector*/ post) {
|
301 |
+
jQuery(post).draggable({
|
302 |
+
revert: 'invalid',
|
303 |
+
appendTo: 'body',
|
304 |
+
helper: "clone",
|
305 |
+
addClasses: false
|
306 |
+
});
|
307 |
+
},
|
308 |
+
|
309 |
+
/*
|
310 |
+
This is a utility method to find a post and remove it
|
311 |
+
from the cache map.
|
312 |
+
*/
|
313 |
+
removePostFromMap: function(/*string*/ dayobjId, /*string*/ postId) {
|
314 |
+
if (edcal.posts[dayobjId]) {
|
315 |
+
for (var i = 0; i < edcal.posts[dayobjId].length; i++) {
|
316 |
+
if (edcal.posts[dayobjId][i] &&
|
317 |
+
"post-" + edcal.posts[dayobjId][i].POST_ID === postId) {
|
318 |
+
edcal.posts[dayobjId][i] = null;
|
319 |
+
return true;
|
320 |
+
}
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
return false;
|
325 |
+
},
|
326 |
+
|
327 |
+
/*
|
328 |
+
* Adds a post to al already existing calendar day.
|
329 |
+
*/
|
330 |
+
addPostItem: function(/*post*/ post, /*string*/ dayobjId) {
|
331 |
+
jQuery('#' + dayobjId + ' .postlist').append(edcal.createPostItem(post, dayobjId));
|
332 |
+
},
|
333 |
+
|
334 |
+
addPostItemDragAndToolltip: function(/*string*/ dayobjId) {
|
335 |
+
edcal.draggablePost('#' + dayobjId + ' .post');
|
336 |
+
edcal.addTooltip(dayobjId);
|
337 |
+
},
|
338 |
+
|
339 |
+
confirmDelete: function(/*string*/ posttitle) {
|
340 |
+
if (confirm('You are about to delete this post ' + posttitle + '.\n\n Press cancel to stop, OK to delete.')) {
|
341 |
+
return true;
|
342 |
+
} else {
|
343 |
+
return false;
|
344 |
+
}
|
345 |
+
},
|
346 |
+
|
347 |
+
/*
|
348 |
+
* Adds a tooltip to every post in the specified day.
|
349 |
+
*/
|
350 |
+
addTooltip: function(/*string*/ dayobjId) {
|
351 |
+
jQuery('#' + dayobjId + ' .post').tooltip({
|
352 |
+
delay: 1500,
|
353 |
+
bodyHandler: function() {
|
354 |
+
var post = edcal.findPostForId(dayobjId, jQuery(this).attr("id"));
|
355 |
+
edcal.findPostForId(jQuery(this).parent().parent().attr("id"),
|
356 |
+
jQuery(this).attr("id"));
|
357 |
+
var tooltip = '<div class="tooltip">' +
|
358 |
+
'<h3>' + post.title + '</h3>' +
|
359 |
+
'<p>' +
|
360 |
+
'<i>by</i> ' + post.author + ' <i>on</i> ' +
|
361 |
+
edcal.getDayFromDayId(post.date).toString("MMMM d, yyyy") +
|
362 |
+
'</p>' +
|
363 |
+
'<p>' +
|
364 |
+
'Status<b>: ' + post.status + '</b>' +
|
365 |
+
' ';
|
366 |
+
if (post.editlink) {
|
367 |
+
/*
|
368 |
+
* If the user doesn't have permission to edit a post then
|
369 |
+
* then server won't send the edit link URL and we shouldn't
|
370 |
+
* show the edit link
|
371 |
+
*/
|
372 |
+
tooltip += '<a href="' + post.editlink + '" title="Edit ' + post.title +
|
373 |
+
'">Edit</a> | ';
|
374 |
+
}
|
375 |
+
|
376 |
+
if (post.dellink) {
|
377 |
+
tooltip += '<a class="submitdelete" href="' + post.dellink + '" ' +
|
378 |
+
'onclick="return edcal.confirmDelete(\'' + post.title + '\');"' +
|
379 |
+
'title="Delete ' + post.title + '">Delete</a> | ';
|
380 |
+
}
|
381 |
+
|
382 |
+
tooltip += '<a href="' + post.permalink + '" title="View ' + post.title + '">View</a>' +
|
383 |
+
'</p>' +
|
384 |
+
'</div>';
|
385 |
+
|
386 |
+
return tooltip;
|
387 |
+
}
|
388 |
+
});
|
389 |
+
},
|
390 |
+
|
391 |
+
/*
|
392 |
+
Creates the HTML for a post item and adds the data for
|
393 |
+
the post to the posts cache.
|
394 |
+
*/
|
395 |
+
createPostItem: function(/*post*/ post, /*string*/ dayobjId) {
|
396 |
+
var postHtml = edcal.getPostItemString(post);
|
397 |
+
if (!edcal.posts[dayobjId]) {
|
398 |
+
edcal.posts[dayobjId] = new Array(0);
|
399 |
+
}
|
400 |
+
|
401 |
+
edcal.posts[dayobjId][edcal.posts[dayobjId].length] = post;
|
402 |
+
|
403 |
+
return postHtml;
|
404 |
+
},
|
405 |
+
|
406 |
+
/*
|
407 |
+
Finds the post object for the specified post ID in the
|
408 |
+
specified day.
|
409 |
+
*/
|
410 |
+
findPostForId: function(/*string*/ dayobjId, /*string*/ postId) {
|
411 |
+
if (edcal.posts[dayobjId]) {
|
412 |
+
for (var i = 0; i < edcal.posts[dayobjId].length; i++) {
|
413 |
+
if (edcal.posts[dayobjId][i] &&
|
414 |
+
"post-" + edcal.posts[dayobjId][i].id === postId) {
|
415 |
+
return edcal.posts[dayobjId][i];
|
416 |
+
}
|
417 |
+
}
|
418 |
+
}
|
419 |
+
},
|
420 |
+
|
421 |
+
/*
|
422 |
+
* Removes a post from the HTML and the posts cache.
|
423 |
+
*/
|
424 |
+
removePostItem: function(/*string*/ dayobjId, /*string*/ postId) {
|
425 |
+
if (edcal.findPostForId(dayobjId, postId)) {
|
426 |
+
for (var i = 0; i < edcal.posts[dayobjId].length; i++) {
|
427 |
+
if (edcal.posts[dayobjId][i] &&
|
428 |
+
"post-" + edcal.posts[dayobjId][i].id === postId) {
|
429 |
+
edcal.posts[dayobjId][i] = null;
|
430 |
+
jQuery("#" + postId).remove();
|
431 |
+
}
|
432 |
+
}
|
433 |
+
|
434 |
+
}
|
435 |
+
},
|
436 |
+
|
437 |
+
/*
|
438 |
+
Gets all the post items for the specified day from
|
439 |
+
the post cache.
|
440 |
+
|
441 |
+
TODO - This function adds all of the posts to a
|
442 |
+
specific day in the calendar. If there are too
|
443 |
+
many posts they'll overrun the calendar day. We
|
444 |
+
need a better UI solution.
|
445 |
+
*/
|
446 |
+
getPostItems: function(/*string*/ dayobjId) {
|
447 |
+
var postsString = "";
|
448 |
+
|
449 |
+
if (edcal.posts[dayobjId]) {
|
450 |
+
for (var i = 0; i < edcal.posts[dayobjId].length; i++) {
|
451 |
+
if (edcal.posts[dayobjId][i]) {
|
452 |
+
postsString += edcal.getPostItemString(edcal.posts[dayobjId][i]);
|
453 |
+
}
|
454 |
+
}
|
455 |
+
}
|
456 |
+
|
457 |
+
return postsString;
|
458 |
+
},
|
459 |
+
|
460 |
+
/*
|
461 |
+
* Gets the HTML string for a post.
|
462 |
+
*/
|
463 |
+
getPostItemString: function(/*post*/ post) {
|
464 |
+
return '<li id="post-' + post.id + '" class="post ' + post.status + '">' + post.title + '</li>';
|
465 |
+
},
|
466 |
+
|
467 |
+
/*
|
468 |
+
Finds the calendar cell for the current day and adds the
|
469 |
+
class "today" to that cell.
|
470 |
+
*/
|
471 |
+
setClassforToday: function() {
|
472 |
+
/*
|
473 |
+
We want to set a class for the cell that represents the current day so we ca
|
474 |
+
give it a background color.
|
475 |
+
*/
|
476 |
+
jQuery('#' + Date.today().toString("ddMMMyyyy")).addClass("today");
|
477 |
+
},
|
478 |
+
|
479 |
+
/*
|
480 |
+
Most browsers need us to set a calendar height in pixels instead
|
481 |
+
of percent. This function get the correct pixel height for the
|
482 |
+
calendar based on the window height.
|
483 |
+
*/
|
484 |
+
getCalHeight: function() {
|
485 |
+
var myHeight = 0;
|
486 |
+
if ( typeof( window.innerWidth ) == 'number' ) {
|
487 |
+
//Non-IE
|
488 |
+
myHeight = window.innerHeight;
|
489 |
+
} else if ( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
|
490 |
+
//IE 6+ in 'standards compliant mode'
|
491 |
+
myHeight = document.documentElement.clientHeight;
|
492 |
+
} else if ( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
|
493 |
+
//IE 4 compatible
|
494 |
+
myHeight = document.body.clientHeight;
|
495 |
+
}
|
496 |
+
return myHeight - 150;
|
497 |
+
},
|
498 |
+
|
499 |
+
/*
|
500 |
+
Moves the calendar a certain number of steps in the specified direction.
|
501 |
+
True moves the calendar down into the future and false moves the calendar
|
502 |
+
up into the past.
|
503 |
+
*/
|
504 |
+
move: function(steps, direction) {
|
505 |
+
/*
|
506 |
+
The working date is a marker for the last calendar row we created.
|
507 |
+
If we are moving forward that will be the last row, if we are moving
|
508 |
+
backward it will be the first row. If we switch direction we need
|
509 |
+
to bump up our date by 11 rows times 7 days a week or 77 days.
|
510 |
+
*/
|
511 |
+
if (edcal.currentDirection != direction) {
|
512 |
+
if (direction) { // into the future
|
513 |
+
edcal._wDate = edcal._wDate.add(77).days();
|
514 |
+
} else { // into the past
|
515 |
+
edcal._wDate = edcal._wDate.add(-77).days();
|
516 |
+
}
|
517 |
+
|
518 |
+
edcal.steps = 0;
|
519 |
+
edcal.moveDate = edcal._wDate;
|
520 |
+
}
|
521 |
+
|
522 |
+
edcal.currentDirection = direction;
|
523 |
+
|
524 |
+
|
525 |
+
if (direction) {
|
526 |
+
for (var i = 0; i < steps; i++) {
|
527 |
+
jQuery("#cal > div:first").remove();
|
528 |
+
edcal.createRow(jQuery("#cal"), true);
|
529 |
+
edcal._wDate.add(7).days();
|
530 |
+
}
|
531 |
+
edcal.alignCal();
|
532 |
+
} else {
|
533 |
+
for (var i = 0; i < steps; i++) {
|
534 |
+
jQuery("#cal > div:last").remove();
|
535 |
+
edcal.createRow(jQuery("#cal"), false);
|
536 |
+
edcal._wDate.add(-7).days();
|
537 |
+
}
|
538 |
+
edcal.alignCal();
|
539 |
+
}
|
540 |
+
|
541 |
+
edcal.setClassforToday();
|
542 |
+
edcal.setDateLabel();
|
543 |
+
|
544 |
+
/*
|
545 |
+
* If the user clicks quickly or uses the mouse wheel they can
|
546 |
+
* get a lot of move events very quickly and we need to batch
|
547 |
+
* them up together. We set a timeout and clear it if there is
|
548 |
+
* another move before the timeout happens.
|
549 |
+
*/
|
550 |
+
edcal.steps += steps;
|
551 |
+
if (edcal.tID) {
|
552 |
+
clearTimeout(edcal.tID);
|
553 |
+
} else {
|
554 |
+
edcal.moveDate = edcal._wDate;
|
555 |
+
}
|
556 |
+
|
557 |
+
edcal.tID = setTimeout(function() {
|
558 |
+
/*
|
559 |
+
* Now that we are done moving the calendar we need to get the posts for the
|
560 |
+
* new dates. We want to load the posts between the place the calendar was
|
561 |
+
* at when the user started moving it and the place the calendar is at now.
|
562 |
+
*/
|
563 |
+
if (!direction) {
|
564 |
+
edcal.getPosts(edcal._wDate.clone(),
|
565 |
+
edcal._wDate.clone().add(7 * (edcal.steps + 2)).days());
|
566 |
+
} else {
|
567 |
+
edcal.getPosts(edcal._wDate.clone().add(-7 * (edcal.steps + 2)).days(),
|
568 |
+
edcal._wDate.clone());
|
569 |
+
}
|
570 |
+
|
571 |
+
edcal.steps = 0;
|
572 |
+
edcal.tID = null;
|
573 |
+
edcal.moveDate = edcal._wDate;
|
574 |
+
}, 1000);
|
575 |
+
},
|
576 |
+
|
577 |
+
/*
|
578 |
+
We use the date as the ID for day elements, but the Date
|
579 |
+
library can't parse the date without spaces and using
|
580 |
+
spaces in IDs can cause problems. We work around the
|
581 |
+
issue by adding the spaces back before we parse.
|
582 |
+
*/
|
583 |
+
getDayFromDayId: function(/*dayId*/ day) {
|
584 |
+
return Date.parse(day.substring(0, 2) + ' ' + day.substring(2, 5) + ' ' + day.substring(5));
|
585 |
+
},
|
586 |
+
|
587 |
+
/*
|
588 |
+
This is a helper method to set the date label on the top of
|
589 |
+
the calendar. It looks like November 2009-December2009
|
590 |
+
*/
|
591 |
+
setDateLabel: function(year) {
|
592 |
+
var api = jQuery(".edcal_scrollable").scrollable();
|
593 |
+
var items = api.getVisibleItems();
|
594 |
+
|
595 |
+
/*
|
596 |
+
We need to get the first day in the first week and the
|
597 |
+
last day in the last week. We call children twice to
|
598 |
+
work around a small JQuery issue.
|
599 |
+
*/
|
600 |
+
var firstDate = edcal.getDayFromDayId(items.eq(0).children(".row").children(".day:first").attr("id"));
|
601 |
+
var lastDate = edcal.getDayFromDayId(items.eq(items.length - 1).children(".row").children(".day:last").attr("id"));
|
602 |
+
|
603 |
+
jQuery("#currentRange").text(firstDate.toString("MMMM yyyy") + " - " + lastDate.toString("MMMM yyyy"));
|
604 |
+
},
|
605 |
+
|
606 |
+
/*
|
607 |
+
* Moves the calendar to the specified date.
|
608 |
+
*/
|
609 |
+
moveTo : function(/*Date*/ date) {
|
610 |
+
edcal.isMoving = true;
|
611 |
+
jQuery("#cal").empty();
|
612 |
+
|
613 |
+
/*
|
614 |
+
When we first start up our working date is 4 weeks before
|
615 |
+
the next Sunday.
|
616 |
+
*/
|
617 |
+
edcal._wDate = date.next().sunday().add(-28).days();
|
618 |
+
|
619 |
+
/*
|
620 |
+
After we remove and readd all the rows we are back to
|
621 |
+
moving in a going down direction.
|
622 |
+
*/
|
623 |
+
edcal.currentDirection = true;
|
624 |
+
|
625 |
+
for (var i = 0; i < 10; i++) {
|
626 |
+
edcal.createRow(jQuery("#cal"), true);
|
627 |
+
edcal._wDate.add(7).days();
|
628 |
+
}
|
629 |
+
|
630 |
+
edcal.alignCal();
|
631 |
+
|
632 |
+
var api = jQuery(".edcal_scrollable").scrollable();
|
633 |
+
api.move(2);
|
634 |
+
|
635 |
+
edcal.setDateLabel();
|
636 |
+
edcal.setClassforToday();
|
637 |
+
edcal.isMoving = false;
|
638 |
+
|
639 |
+
},
|
640 |
+
|
641 |
+
/*
|
642 |
+
* Initializes the calendar
|
643 |
+
*/
|
644 |
+
init : function() {
|
645 |
+
if (jQuery("#edcal_scrollable").length === 0) {
|
646 |
+
/*
|
647 |
+
* This means we are on a page without the editorial
|
648 |
+
* calendar
|
649 |
+
*/
|
650 |
+
return;
|
651 |
+
}
|
652 |
+
|
653 |
+
jQuery("#loading").hide();
|
654 |
+
|
655 |
+
jQuery("#edcal_scrollable").css("height", edcal.getCalHeight() + "px");
|
656 |
+
edcal.windowHeight = jQuery(window).height();
|
657 |
+
|
658 |
+
/*
|
659 |
+
* Add the days of the week
|
660 |
+
*/
|
661 |
+
edcal.createDaysHeader();
|
662 |
+
|
663 |
+
// initialize scrollable
|
664 |
+
jQuery(".edcal_scrollable").scrollable({
|
665 |
+
vertical:true,
|
666 |
+
size: 6,
|
667 |
+
keyboardSteps: 1,
|
668 |
+
speed: 100
|
669 |
+
// use mousewheel plugin
|
670 |
+
}).mousewheel();
|
671 |
+
|
672 |
+
var api = jQuery(".edcal_scrollable").scrollable();
|
673 |
+
|
674 |
+
edcal.moveTo(Date.today());
|
675 |
+
|
676 |
+
var steps = 1;
|
677 |
+
|
678 |
+
/*
|
679 |
+
* The scrollable handles some basic binding. This gets us
|
680 |
+
* up arrow, down arrow and the mouse wheel.
|
681 |
+
*/
|
682 |
+
api.onBeforeSeek(function(evt, direction) {
|
683 |
+
// inside callbacks the "this" variable is a reference to the API
|
684 |
+
if (!edcal.isMoving) {
|
685 |
+
edcal.move(1, direction);
|
686 |
+
}
|
687 |
+
|
688 |
+
return false;
|
689 |
+
});
|
690 |
+
|
691 |
+
/*
|
692 |
+
* We also want to listen for a few other key events
|
693 |
+
*/
|
694 |
+
jQuery(document).bind("keydown", function(evt) {
|
695 |
+
//if (evt.altKey || evt.ctrlKey) { return; }
|
696 |
+
//output("evt.altKey: " + evt.altKey);
|
697 |
+
//output("evt.keyCode: " + evt.keyCode);
|
698 |
+
//output("evt.ctrlKey: " + evt.ctrlKey);
|
699 |
+
|
700 |
+
if ((evt.keyCode === 34 && !(evt.altKey || evt.ctrlKey)) || //page down
|
701 |
+
evt.keyCode === 40 && evt.ctrlKey){ // Ctrl+down down arrow
|
702 |
+
edcal.move(4, true);
|
703 |
+
return false;
|
704 |
+
} else if ((evt.keyCode === 33 && !(evt.altKey || evt.ctrlKey)) || //page up
|
705 |
+
evt.keyCode === 38 && evt.ctrlKey){ // Ctrl+up up arrow
|
706 |
+
edcal.move(4, false);
|
707 |
+
return false;
|
708 |
+
}
|
709 |
+
});
|
710 |
+
|
711 |
+
edcal.getPosts(Date.today().next().sunday().add(-61).days(),
|
712 |
+
Date.today().next().sunday().add(61).days());
|
713 |
+
|
714 |
+
/*
|
715 |
+
Now we bind the listeners for all of our links and the window
|
716 |
+
resize.
|
717 |
+
*/
|
718 |
+
jQuery("#moveToToday").click(function() {
|
719 |
+
edcal.moveTo(Date.today());
|
720 |
+
return false;
|
721 |
+
});
|
722 |
+
|
723 |
+
jQuery("#prevmonth").click(function() {
|
724 |
+
edcal.move(4, false);
|
725 |
+
return false;
|
726 |
+
});
|
727 |
+
|
728 |
+
jQuery("#nextmonth").click(function() {
|
729 |
+
edcal.move(4, true);
|
730 |
+
return false;
|
731 |
+
});
|
732 |
+
|
733 |
+
function resizeWindow(e) {
|
734 |
+
if (edcal.windowHeight != jQuery(window).height()) {
|
735 |
+
jQuery("#edcal_scrollable").css("height", edcal.getCalHeight() + "px");
|
736 |
+
edcal.windowHeight = jQuery(window).height();
|
737 |
+
}
|
738 |
+
}
|
739 |
+
jQuery(window).bind("resize", resizeWindow);
|
740 |
+
},
|
741 |
+
|
742 |
+
/*
|
743 |
+
This function makes an AJAX call and changes the date of
|
744 |
+
the specified post on the server.
|
745 |
+
*/
|
746 |
+
changeDate: function(/*string*/ newdate, /*Post*/ post) {
|
747 |
+
output("changeDate(" + newdate + ", " + post + ")");
|
748 |
+
|
749 |
+
newdate = edcal.getDayFromDayId(newdate).toString("yyyy-MM-dd");
|
750 |
+
|
751 |
+
var postStatus = "";
|
752 |
+
|
753 |
+
if (post.status === "draft") {
|
754 |
+
/*
|
755 |
+
* If the status of the post was a draft we leave it as a draft
|
756 |
+
*/
|
757 |
+
postStatus = "draft";
|
758 |
+
} else {
|
759 |
+
/*
|
760 |
+
If the post status was published or future we need to adjust
|
761 |
+
it. If you take a post that is published a move it after
|
762 |
+
the current day we change the status to future. If the post
|
763 |
+
was scheduled to get published in the future and they drag
|
764 |
+
it into the past we change the status to publish.
|
765 |
+
*/
|
766 |
+
var compare = Date.parse(newdate).compareTo(Date.today());
|
767 |
+
if (compare === -1) {
|
768 |
+
if (post.status === "publish") {
|
769 |
+
postStatus = "publish";
|
770 |
+
} else {
|
771 |
+
postStatus = "draft";
|
772 |
+
}
|
773 |
+
|
774 |
+
} else {
|
775 |
+
postStatus = "future";
|
776 |
+
}
|
777 |
+
}
|
778 |
+
|
779 |
+
var url = edcal.ajax_url + "?action=edcal_changedate&postid=" + post.id +
|
780 |
+
"&postStatus=" + postStatus +
|
781 |
+
"&newdate=" + newdate + "&olddate=" + edcal.getDayFromDayId(post.date).toString("yyyy-MM-dd");
|
782 |
+
|
783 |
+
jQuery("#post-" + post.id).addClass("loadingclass");
|
784 |
+
|
785 |
+
jQuery.ajax( {
|
786 |
+
url: url,
|
787 |
+
type: "POST",
|
788 |
+
processData: false,
|
789 |
+
timeout: 10000,
|
790 |
+
dataType: "json",
|
791 |
+
success: function(res) {
|
792 |
+
edcal.removePostItem(res.post.date, "post-" + res.post.id);
|
793 |
+
edcal.addPostItem(res.post, res.post.date);
|
794 |
+
edcal.addPostItemDragAndToolltip(res.post.date);
|
795 |
+
|
796 |
+
if (res.error) {
|
797 |
+
if (res.error === edcal.CONCURRENCY_ERROR) {
|
798 |
+
edcal.showError("Someone else already moved " + res.post.title);
|
799 |
+
} else if (res.error === edcal.PERMISSION_ERROR) {
|
800 |
+
edcal.showError("You don't have permission to edit posts");
|
801 |
+
}
|
802 |
+
}
|
803 |
+
},
|
804 |
+
error: function(xhr) {
|
805 |
+
showError("There was an error contacting your blog.")
|
806 |
+
if (xhr.responseText) {
|
807 |
+
output("xhr.responseText: " + xhr.responseText);
|
808 |
+
}
|
809 |
+
}
|
810 |
+
});
|
811 |
+
|
812 |
+
},
|
813 |
+
|
814 |
+
/*
|
815 |
+
* Shows an error message
|
816 |
+
*/
|
817 |
+
showError: function(/*string*/ msg) {
|
818 |
+
humanMsg.displayMsg(msg);
|
819 |
+
},
|
820 |
+
|
821 |
+
/*
|
822 |
+
Makes an AJAX call to get the posts from the server within the
|
823 |
+
specified dates.
|
824 |
+
*/
|
825 |
+
getPosts: function(/*Date*/ from, /*Date*/ to) {
|
826 |
+
output("getPosts(" + from.toString("dd-MMM-yyyy") + ", " + to.toString("dd-MMM-yyyy") + ")");
|
827 |
+
|
828 |
+
var shouldGet = edcal.cacheDates[from];
|
829 |
+
|
830 |
+
if (shouldGet) {
|
831 |
+
/*
|
832 |
+
* TODO: We don't want to make extra AJAX calls for dates
|
833 |
+
* that we have already coverred. This is cutting down on
|
834 |
+
* it somewhat, but we could get much better about this.
|
835 |
+
*/
|
836 |
+
output("We already have the results.");
|
837 |
+
return;
|
838 |
+
}
|
839 |
+
|
840 |
+
edcal.cacheDates[from] = true;
|
841 |
+
|
842 |
+
|
843 |
+
var url = edcal.ajax_url + "?action=edcal_posts&from=" + from.toString("yyyy-MM-dd") + "&to=" + to.toString("yyyy-MM-dd");
|
844 |
+
output("url: " + url);
|
845 |
+
|
846 |
+
jQuery("#loading").show();
|
847 |
+
|
848 |
+
jQuery.ajax( {
|
849 |
+
url: url,
|
850 |
+
type: "GET",
|
851 |
+
processData: false,
|
852 |
+
timeout: 10000,
|
853 |
+
dataType: "text",
|
854 |
+
success: function(res) {
|
855 |
+
jQuery("#loading").hide();
|
856 |
+
|
857 |
+
/*
|
858 |
+
* These result here can get pretty large on a busy blog and
|
859 |
+
* the JSON parser from JSON.org works faster than the native
|
860 |
+
* one used by JQuery.
|
861 |
+
*/
|
862 |
+
var parsedRes = JSON.parseIt(res);
|
863 |
+
var postDates = new Array();
|
864 |
+
jQuery.each(parsedRes, function(i, post) {
|
865 |
+
if (post) {
|
866 |
+
edcal.removePostItem(post.date, "post-" + post.id);
|
867 |
+
edcal.addPostItem(post, post.date);
|
868 |
+
postDates[postDates.length] = post.date;
|
869 |
+
}
|
870 |
+
});
|
871 |
+
|
872 |
+
/*
|
873 |
+
* If the blog has a very larger number of posts then adding
|
874 |
+
* them all can make the UI a little slow. Particularly IE
|
875 |
+
* pops up a warning giving the user a chance to abort the
|
876 |
+
* script. Adding tooltips and making the items draggable is
|
877 |
+
* a lot of what makes things slow. Delaying those two operations
|
878 |
+
* makes the UI show up much faster and the user has to wait
|
879 |
+
* three seconds before they can drag. It also makes IE
|
880 |
+
* stop complaining.
|
881 |
+
*/
|
882 |
+
setTimeout(function() {
|
883 |
+
output("adding tooltips and draggables to " + postDates.length + " items.");
|
884 |
+
jQuery.each(postDates, function(i, postDate) {
|
885 |
+
edcal.addPostItemDragAndToolltip(postDate);
|
886 |
+
});
|
887 |
+
}, 300);
|
888 |
+
},
|
889 |
+
error: function(xhr) {
|
890 |
+
showError("There was an error contacting your blog.")
|
891 |
+
if (xhr.responseText) {
|
892 |
+
output("xhr.responseText: " + xhr.responseText);
|
893 |
+
}
|
894 |
+
}
|
895 |
+
});
|
896 |
+
}
|
897 |
+
};
|
898 |
+
|
899 |
+
jQuery(document).ready(function(){
|
900 |
+
edcal.init();
|
901 |
+
});
|
902 |
+
|
903 |
+
/**
|
904 |
+
* This is a helper function to output messages on the HTML page. It
|
905 |
+
* write them out to a text area.
|
906 |
+
*
|
907 |
+
* @param msg the message to write
|
908 |
+
*/
|
909 |
+
function output(msg) {
|
910 |
+
//console.info(msg);
|
911 |
+
}
|
edcal.php
ADDED
@@ -0,0 +1,374 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*******************************************************************************
|
3 |
+
*
|
4 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5 |
+
* you may not use this file except in compliance with the License.
|
6 |
+
* You may obtain a copy of the License at
|
7 |
+
*
|
8 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9 |
+
*
|
10 |
+
* Unless required by applicable law or agreed to in writing, software
|
11 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13 |
+
* See the License for the specific language governing permissions and
|
14 |
+
* limitations under the License.
|
15 |
+
*
|
16 |
+
******************************************************************************/
|
17 |
+
|
18 |
+
/*
|
19 |
+
Plugin Name: WordPress Editorial Calendar
|
20 |
+
Description: An editorial calendar for setting the dates of your WordPress posts
|
21 |
+
Author: EdCal Project
|
22 |
+
Author URI: TBD
|
23 |
+
*/
|
24 |
+
|
25 |
+
add_action('wp_ajax_edcal_changedate', 'edcal_changedate' );
|
26 |
+
add_action('admin_menu', 'edcal_list_add_management_page');
|
27 |
+
add_action('wp_ajax_edcal_posts', 'edcal_posts' );
|
28 |
+
add_action("admin_print_scripts", 'edcal_scripts');
|
29 |
+
|
30 |
+
/*
|
31 |
+
* This function adds our calendar page to the admin UI
|
32 |
+
*/
|
33 |
+
function edcal_list_add_management_page( ) {
|
34 |
+
if ( function_exists('add_management_page') ) {
|
35 |
+
$page = add_posts_page( 'Calendar', 'Calendar', 'manage_categories', 'posts_list', 'edcal_list_admin' );
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
/*
|
40 |
+
* This is a utility function to open a file add it to our
|
41 |
+
* output stream. We use this to embed JavaScript and CSS
|
42 |
+
* files and cut down on the number of HTTP requests.
|
43 |
+
*/
|
44 |
+
function echoEdCalFile($myFile) {
|
45 |
+
$fh = fopen($myFile, 'r');
|
46 |
+
$theData = fread($fh, filesize($myFile));
|
47 |
+
fclose($fh);
|
48 |
+
echo $theData;
|
49 |
+
}
|
50 |
+
|
51 |
+
/*
|
52 |
+
* This is the function that generates our admin page. It adds the CSS files and
|
53 |
+
* generates the divs that we need for the JavaScript to work.
|
54 |
+
*/
|
55 |
+
function edcal_list_admin() {
|
56 |
+
include_once('edcal.php');
|
57 |
+
|
58 |
+
/*
|
59 |
+
* This section of code embeds certain CSS and
|
60 |
+
* JavaScript files into the HTML. This has the
|
61 |
+
* advantage of fewer HTTP requests, but the
|
62 |
+
* disadvantage that the browser can't cache the
|
63 |
+
* results. We only do this for files that will
|
64 |
+
* be used on this page and nowhere else.
|
65 |
+
*/
|
66 |
+
|
67 |
+
echo '<!-- This is the styles from jquery.tooltip.css -->';
|
68 |
+
echo '<style type="text/css">';
|
69 |
+
echoEdCalFile(dirname( __FILE__ ) . "/lib/jquery.tooltip.css");
|
70 |
+
echo '</style>';
|
71 |
+
|
72 |
+
echo '<!-- This is the styles from humanmsg.css -->';
|
73 |
+
echo '<style type="text/css">';
|
74 |
+
echoEdCalFile(dirname( __FILE__ ) . "/lib/humanmsg.css");
|
75 |
+
echo '</style>';
|
76 |
+
|
77 |
+
echo '<!-- This is the styles from edcal.css -->';
|
78 |
+
echo '<style type="text/css">';
|
79 |
+
echoEdCalFile(dirname( __FILE__ ) . "/edcal.css");
|
80 |
+
echo '</style>';
|
81 |
+
|
82 |
+
?>
|
83 |
+
<!-- This is just a little script so we can pass the AJAX URL -->
|
84 |
+
<script type="text/javascript">
|
85 |
+
jQuery(document).ready(function(){
|
86 |
+
edcal.ajax_url = '<?php echo admin_url("admin-ajax.php"); ?>';
|
87 |
+
});
|
88 |
+
</script>
|
89 |
+
|
90 |
+
<style type="text/css">
|
91 |
+
.loadingclass {
|
92 |
+
background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/images/loading_post.gif")); ?>');
|
93 |
+
}
|
94 |
+
|
95 |
+
#loading {
|
96 |
+
background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/images/loading.gif")); ?>');
|
97 |
+
}
|
98 |
+
</style>
|
99 |
+
<?php
|
100 |
+
|
101 |
+
echo '<!-- This is the code from edcal.js -->';
|
102 |
+
echo '<script type="text/javascript">';
|
103 |
+
echoEdCalFile(dirname( __FILE__ ) . "/edcal.js");
|
104 |
+
echo '</script>';
|
105 |
+
|
106 |
+
?>
|
107 |
+
<div class="wrap">
|
108 |
+
<div class="icon32" id="icon-edit"><br/></div>
|
109 |
+
<h2>Posts Calendar</h2>
|
110 |
+
|
111 |
+
<div id="topbar">
|
112 |
+
<div id="topleft">
|
113 |
+
<div id="loading"> </div>
|
114 |
+
</div>
|
115 |
+
<div id="topright">
|
116 |
+
<a href="#" class="prev page-numbers" id="prevmonth" style="border: none";>«</a><span id="currentRange"></span><a href="#" class="next page-numbers" id="nextmonth" style="border: none";>»</a> <a href="#" id="moveToToday">Jump to Today</a>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
|
120 |
+
<div id="rowhead"></div>
|
121 |
+
<div id="edcal_scrollable" class="edcal_scrollable vertical">
|
122 |
+
<div id="cal"></div>
|
123 |
+
</div>
|
124 |
+
</div>
|
125 |
+
<?php
|
126 |
+
}
|
127 |
+
|
128 |
+
/*
|
129 |
+
* We use these variables to hold the post dates for the filter when
|
130 |
+
* we do our post query.
|
131 |
+
*/
|
132 |
+
$edcal_startDate;
|
133 |
+
$edcal_endDate;
|
134 |
+
|
135 |
+
/*
|
136 |
+
* When we get a set of posts to populate the calendar we don't want
|
137 |
+
* to get all of the posts. This filter allows us to specify the dates
|
138 |
+
* we want.
|
139 |
+
*/
|
140 |
+
function edcal_filter_where($where = '') {
|
141 |
+
global $edcal_startDate, $edcal_endDate;
|
142 |
+
//posts in the last 30 days
|
143 |
+
//$where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'";
|
144 |
+
//posts 30 to 60 days old
|
145 |
+
//$where .= " AND post_date >= '" . date('Y-m-d', strtotime('-60 days')) . "'" . " AND post_date <= '" . date('Y-m-d', strtotime('-30 days')) . "'";
|
146 |
+
//posts for March 1 to March 15, 2009
|
147 |
+
$where .= " AND post_date >= '" . $edcal_startDate . "' AND post_date < '" . $edcal_endDate . "'";
|
148 |
+
return $where;
|
149 |
+
}
|
150 |
+
|
151 |
+
/*
|
152 |
+
* This function adds all of the JavaScript files we need.
|
153 |
+
*
|
154 |
+
* TODO: This list is way too long. We need to minimize and
|
155 |
+
* combine most of these files. I'm still on the fence if we
|
156 |
+
* should include these files inline.
|
157 |
+
*/
|
158 |
+
function edcal_scripts( ) {
|
159 |
+
wp_enqueue_script( "ui-core", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/ui.core.js"), array( 'jquery' ) );
|
160 |
+
wp_enqueue_script( "ui-draggable", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/ui.draggable.js"), array( 'jquery' ) );
|
161 |
+
wp_enqueue_script( "ui-droppable", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/ui.droppable.js"), array( 'jquery' ) );
|
162 |
+
|
163 |
+
|
164 |
+
wp_enqueue_script( "bgiframe", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/jquery.bgiframe.js"), array( 'jquery' ) );
|
165 |
+
wp_enqueue_script( "tooltip", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/jquery.tooltip.js"), array( 'jquery' ) );
|
166 |
+
wp_enqueue_script( "humanMsg", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/humanmsg.js"), array( 'jquery' ) );
|
167 |
+
|
168 |
+
|
169 |
+
wp_enqueue_script( "date", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/date.js"), array( 'jquery' ) );
|
170 |
+
wp_enqueue_script( "scrollable", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/tools.scrollable-1.1.2.js"), array( 'jquery' ) );
|
171 |
+
wp_enqueue_script( "mouse-wheel", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/tools.scrollable.mousewheel-1.0.1.js"), array( 'jquery' ) );
|
172 |
+
|
173 |
+
wp_enqueue_script( "json-parse2", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/json2.js"), array( 'jquery' ) );
|
174 |
+
}
|
175 |
+
|
176 |
+
/*
|
177 |
+
* This is an AJAX call that gets the posts between the from date
|
178 |
+
* and the to date.
|
179 |
+
*/
|
180 |
+
function edcal_posts( ) {
|
181 |
+
header("Content-Type: application/json");
|
182 |
+
global $edcal_startDate, $edcal_endDate;
|
183 |
+
$edcal_startDate = isset($_GET['from'])?$_GET['from']:null;
|
184 |
+
$edcal_endDate = isset($_GET['to'])?$_GET['to']:null;
|
185 |
+
global $post;
|
186 |
+
$args = array(
|
187 |
+
'posts_per_page' => -1,
|
188 |
+
'post_status' => "publish&future&draft",
|
189 |
+
'post_parent' => null, // any parent
|
190 |
+
'post_type' => 'post',
|
191 |
+
);
|
192 |
+
|
193 |
+
add_filter('posts_where', 'edcal_filter_where');
|
194 |
+
$myposts = query_posts($args);
|
195 |
+
remove_filter('posts_where', 'edcal_filter_where');
|
196 |
+
|
197 |
+
?>[
|
198 |
+
<?php
|
199 |
+
foreach($myposts as $post) {
|
200 |
+
edcal_postJSON($post);
|
201 |
+
}
|
202 |
+
|
203 |
+
?> ]
|
204 |
+
<?php
|
205 |
+
die;
|
206 |
+
}
|
207 |
+
|
208 |
+
/*
|
209 |
+
* This function sets up the post data and prints out the values we
|
210 |
+
* care about in a JSON data structure. This prints out just the
|
211 |
+
* value part.
|
212 |
+
*/
|
213 |
+
function edcal_postJSON($post) {
|
214 |
+
setup_postdata($post);
|
215 |
+
?>
|
216 |
+
{
|
217 |
+
"date" : "<?php the_time('d') ?><?php the_time('M') ?><?php the_time('Y') ?>",
|
218 |
+
"url" : "<?php the_permalink(); ?>",
|
219 |
+
"status" : "<?php echo(get_post_status()); ?>",
|
220 |
+
"title" : "<?php the_title(); ?>",
|
221 |
+
"author" : "<?php the_author(); ?>",
|
222 |
+
<?php if ( current_user_can('edit_post', $post->ID) ) {?>
|
223 |
+
"editlink" : "<?php echo(get_edit_post_link($id)); ?>",
|
224 |
+
<?php } ?>
|
225 |
+
|
226 |
+
<?php if ( current_user_can('delete_post', $post->ID) ) {?>
|
227 |
+
"dellink" : "<?php echo(wp_nonce_url("post.php?action=delete&post=$post->ID", 'delete-post_' . $post->ID)); ?>",
|
228 |
+
<?php } ?>
|
229 |
+
|
230 |
+
"permalink" : "<?php echo(get_permalink($id)); ?>",
|
231 |
+
"id" : "<?php the_ID(); ?>"
|
232 |
+
},
|
233 |
+
<?php
|
234 |
+
}
|
235 |
+
|
236 |
+
/*
|
237 |
+
* This function changes the date on a post. It does optimistic
|
238 |
+
* concurrency checking by comparing the original post date from
|
239 |
+
* the browser with the one from the database. If they don't match
|
240 |
+
* then it returns an error code and the updated post data.
|
241 |
+
*
|
242 |
+
* If the call is successful then it returns the updated post data.
|
243 |
+
*/
|
244 |
+
function edcal_changedate() {
|
245 |
+
if (!current_user_can('edit_others_posts')) {
|
246 |
+
/*
|
247 |
+
* This is just a sanity check to make sure that the current
|
248 |
+
* user has permission to edit posts. Most of the time this
|
249 |
+
* will never be run because you can't see the calendar unless
|
250 |
+
* you are at least an editor
|
251 |
+
*/
|
252 |
+
?>
|
253 |
+
{
|
254 |
+
"error": 5,
|
255 |
+
<?php
|
256 |
+
|
257 |
+
|
258 |
+
global $post;
|
259 |
+
$args = array(
|
260 |
+
'posts_id' => $edcal_postid,
|
261 |
+
);
|
262 |
+
|
263 |
+
$post = get_post($edcal_postid);
|
264 |
+
?>
|
265 |
+
"post" :
|
266 |
+
<?php
|
267 |
+
edcal_postJSON($post);
|
268 |
+
|
269 |
+
|
270 |
+
|
271 |
+
?> }
|
272 |
+
<?php
|
273 |
+
}
|
274 |
+
|
275 |
+
header("Content-Type: application/json");
|
276 |
+
global $edcal_startDate, $edcal_endDate;
|
277 |
+
$edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
|
278 |
+
$edcal_newDate = isset($_GET['newdate'])?$_GET['newdate']:null;
|
279 |
+
$edcal_oldDate = isset($_GET['olddate'])?$_GET['olddate']:null;
|
280 |
+
$edcal_postStatus = isset($_GET['postStatus'])?$_GET['postStatus']:null;
|
281 |
+
|
282 |
+
$post = get_post($edcal_postid, ARRAY_A);
|
283 |
+
setup_postdata($post);
|
284 |
+
|
285 |
+
$matches = strpos($post['post_date'], $edcal_oldDate) === 0;
|
286 |
+
|
287 |
+
/*
|
288 |
+
* We are doing optimistic concurrency checking on the dates. If
|
289 |
+
* the user tries to move a post we want to make sure nobody else
|
290 |
+
* has moved that post since the page was last updated. If the
|
291 |
+
* old date in the database doesn't match the old date from the
|
292 |
+
* browser then we return an error to the browser along with the
|
293 |
+
* updated post data.
|
294 |
+
*/
|
295 |
+
if ($matches != 1) {
|
296 |
+
?>
|
297 |
+
{
|
298 |
+
"error": 4,
|
299 |
+
<?php
|
300 |
+
|
301 |
+
|
302 |
+
global $post;
|
303 |
+
$args = array(
|
304 |
+
'posts_id' => $edcal_postid,
|
305 |
+
);
|
306 |
+
|
307 |
+
$post = get_post($edcal_postid);
|
308 |
+
?>
|
309 |
+
"post" :
|
310 |
+
<?php
|
311 |
+
edcal_postJSON($post);
|
312 |
+
|
313 |
+
?> }
|
314 |
+
<?php
|
315 |
+
//return new WP_Error('broke', __("no match error"));
|
316 |
+
die();
|
317 |
+
}
|
318 |
+
|
319 |
+
/*
|
320 |
+
* Posts in WordPress have more than one date. There is the GMT date,
|
321 |
+
* the date in the local time zone, the modified date in GMT and the
|
322 |
+
* modified date in the local time zone. We update all of them.
|
323 |
+
*/
|
324 |
+
$updated_post = array();
|
325 |
+
$updated_post['ID'] = $edcal_postid;
|
326 |
+
$updated_post['post_date'] = $edcal_newDate . substr($post['post_date'], strlen($edcal_newDate));
|
327 |
+
$updated_post['post_date_gmt'] = $edcal_newDate . substr($post['post_date_gmt'], strlen($edcal_newDate));
|
328 |
+
$updated_post['post_modified'] = $edcal_newDate . substr($post['post_modified'], strlen($edcal_newDate));
|
329 |
+
$updated_post['post_modified_gmt'] = $edcal_newDate . substr($post['post_modified_gmt'], strlen($edcal_newDate));
|
330 |
+
|
331 |
+
if ( $edcal_postStatus != $post['post_status'] ) {
|
332 |
+
/*
|
333 |
+
* We only want to update the post status if it has changed.
|
334 |
+
* If the post status has changed that takes a few more steps
|
335 |
+
*/
|
336 |
+
wp_transition_post_status($edcal_postStatus, $post['post_status'], $post);
|
337 |
+
$updated_post['post_status'] = $edcal_postStatus;
|
338 |
+
|
339 |
+
// Update counts for the post's terms.
|
340 |
+
foreach ( (array) get_object_taxonomies('post') as $taxonomy ) {
|
341 |
+
$tt_ids = wp_get_object_terms($post_id, $taxonomy, 'fields=tt_ids');
|
342 |
+
wp_update_term_count($tt_ids, $taxonomy);
|
343 |
+
}
|
344 |
+
|
345 |
+
do_action('edit_post', $edcal_postid, $post);
|
346 |
+
do_action('save_post', $edcal_postid, $post);
|
347 |
+
do_action('wp_insert_post', $edcal_postid, $post);
|
348 |
+
}
|
349 |
+
|
350 |
+
/*
|
351 |
+
* Now we finally update the post into the database
|
352 |
+
*/
|
353 |
+
wp_update_post( $updated_post );
|
354 |
+
|
355 |
+
/*
|
356 |
+
* We finish by returning the latest data for the post in the JSON
|
357 |
+
*/
|
358 |
+
global $post;
|
359 |
+
$args = array(
|
360 |
+
'posts_id' => $edcal_postid,
|
361 |
+
);
|
362 |
+
|
363 |
+
$post = get_post($edcal_postid);
|
364 |
+
?>{
|
365 |
+
"post" :
|
366 |
+
<?php
|
367 |
+
edcal_postJSON($post);
|
368 |
+
?>
|
369 |
+
}
|
370 |
+
<?php
|
371 |
+
|
372 |
+
|
373 |
+
die;
|
374 |
+
}
|
images/loading.gif
ADDED
Binary file
|
images/loading_post.gif
ADDED
Binary file
|
lib/date.js
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Version: 1.0 Alpha-1
|
3 |
+
* Build Date: 13-Nov-2007
|
4 |
+
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
5 |
+
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
6 |
+
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
7 |
+
*/
|
8 |
+
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
9 |
+
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
10 |
+
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
11 |
+
return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
|
12 |
+
return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
|
13 |
+
if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
|
14 |
+
var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
|
15 |
+
if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
|
16 |
+
if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
|
17 |
+
if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
|
18 |
+
if(x.month||x.months){this.addMonths(x.month||x.months);}
|
19 |
+
if(x.year||x.years){this.addYears(x.year||x.years);}
|
20 |
+
if(x.day||x.days){this.addDays(x.day||x.days);}
|
21 |
+
return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
|
22 |
+
return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
|
23 |
+
if(!x.second&&x.second!==0){x.second=-1;}
|
24 |
+
if(!x.minute&&x.minute!==0){x.minute=-1;}
|
25 |
+
if(!x.hour&&x.hour!==0){x.hour=-1;}
|
26 |
+
if(!x.day&&x.day!==0){x.day=-1;}
|
27 |
+
if(!x.month&&x.month!==0){x.month=-1;}
|
28 |
+
if(!x.year&&x.year!==0){x.year=-1;}
|
29 |
+
if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
|
30 |
+
if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
|
31 |
+
if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
|
32 |
+
if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
|
33 |
+
if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
|
34 |
+
if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
|
35 |
+
if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
|
36 |
+
if(x.timezone){this.setTimezone(x.timezone);}
|
37 |
+
if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
|
38 |
+
return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
|
39 |
+
var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
|
40 |
+
return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
|
41 |
+
Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
|
42 |
+
return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
|
43 |
+
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
|
44 |
+
return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
|
45 |
+
var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
|
46 |
+
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
|
47 |
+
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
|
48 |
+
break;}
|
49 |
+
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
|
50 |
+
rx.push(r[0]);s=r[1];}
|
51 |
+
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
|
52 |
+
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
|
53 |
+
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
|
54 |
+
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
|
55 |
+
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
56 |
+
try{r=(px[i].call(this,s));}catch(e){r=null;}
|
57 |
+
if(r){return r;}}
|
58 |
+
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
59 |
+
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
|
60 |
+
rx.push(r[0]);s=r[1];}
|
61 |
+
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
|
62 |
+
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
|
63 |
+
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
|
64 |
+
s=q[1];}
|
65 |
+
if(!r){throw new $P.Exception(s);}
|
66 |
+
if(q){throw new $P.Exception(q[1]);}
|
67 |
+
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
|
68 |
+
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
|
69 |
+
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
|
70 |
+
if(!last&&q[1].length===0){last=true;}
|
71 |
+
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
|
72 |
+
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
|
73 |
+
if(rx[1].length<best[1].length){best=rx;}
|
74 |
+
if(best[1].length===0){break;}}
|
75 |
+
if(best[0].length===0){return best;}
|
76 |
+
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
|
77 |
+
best[1]=q[1];}
|
78 |
+
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
|
79 |
+
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
|
80 |
+
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
|
81 |
+
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
|
82 |
+
return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
|
83 |
+
this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
|
84 |
+
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
|
85 |
+
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
|
86 |
+
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
|
87 |
+
if(this.now){return new Date();}
|
88 |
+
var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
|
89 |
+
if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
|
90 |
+
if(!this.unit){this.unit="day";}
|
91 |
+
if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
|
92 |
+
if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
|
93 |
+
this[this.unit+"s"]=this.value*orient;}
|
94 |
+
return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
|
95 |
+
if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
|
96 |
+
if(this.month&&!this.day){this.day=1;}
|
97 |
+
return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
|
98 |
+
fn=_C[keys]=_.any.apply(null,px);}
|
99 |
+
return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
|
100 |
+
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
|
101 |
+
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
102 |
+
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
103 |
+
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
104 |
+
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
lib/humanmsg.css
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
HUMANIZED MESSAGES 1.0
|
3 |
+
idea - http://www.humanized.com/weblog/2006/09/11/monolog_boxes_and_transparent_messages
|
4 |
+
home - http://humanmsg.googlecode.com
|
5 |
+
*/
|
6 |
+
|
7 |
+
.humanMsg {
|
8 |
+
font: normal 2em Helvetica, Arial, Sans-Serif;
|
9 |
+
letter-spacing: -1px;
|
10 |
+
position: fixed;
|
11 |
+
top: 130px;
|
12 |
+
left: 25%;
|
13 |
+
width: 50%;
|
14 |
+
color: white;
|
15 |
+
background-color: red;
|
16 |
+
text-align: center;
|
17 |
+
display: none;
|
18 |
+
opacity: 0;
|
19 |
+
z-index: 100000;
|
20 |
+
}
|
21 |
+
|
22 |
+
.humanMsg .round {
|
23 |
+
border-left: solid 2px white;
|
24 |
+
border-right: solid 2px white;
|
25 |
+
font-size: 1px; height: 2px;
|
26 |
+
}
|
27 |
+
|
28 |
+
.humanMsg p {
|
29 |
+
padding: .3em;
|
30 |
+
display: inline;
|
31 |
+
font-size: 1.5em;
|
32 |
+
}
|
33 |
+
|
34 |
+
.humanMsg a {
|
35 |
+
display: none;
|
36 |
+
}
|
lib/humanmsg.js
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
HUMANIZED MESSAGES 1.0
|
3 |
+
idea - http://www.humanized.com/weblog/2006/09/11/monolog_boxes_and_transparent_messages
|
4 |
+
home - http://humanmsg.googlecode.com
|
5 |
+
*/
|
6 |
+
|
7 |
+
var humanMsg = {
|
8 |
+
setup: function(appendTo, msgOpacity) {
|
9 |
+
humanMsg.msgID = 'humanMsg';
|
10 |
+
humanMsg.logID = 'humanMsgLog';
|
11 |
+
|
12 |
+
// appendTo is the element the msg is appended to
|
13 |
+
if (appendTo == undefined)
|
14 |
+
appendTo = 'body';
|
15 |
+
|
16 |
+
// Opacity of the message
|
17 |
+
humanMsg.msgOpacity = .8;
|
18 |
+
|
19 |
+
if (msgOpacity != undefined)
|
20 |
+
humanMsg.msgOpacity = parseFloat(msgOpacity);
|
21 |
+
|
22 |
+
// Inject the message structure
|
23 |
+
jQuery(appendTo).append('<div id="'+humanMsg.msgID+'" class="humanMsg"><div class="round"></div><p></p><div class="round"></div></div>');
|
24 |
+
|
25 |
+
jQuery('#'+humanMsg.logID+' p').click(
|
26 |
+
function() { jQuery(this).siblings('ul').slideToggle() }
|
27 |
+
)
|
28 |
+
},
|
29 |
+
|
30 |
+
displayMsg: function(msg) {
|
31 |
+
if (msg == '')
|
32 |
+
return;
|
33 |
+
|
34 |
+
clearTimeout(humanMsg.t2);
|
35 |
+
|
36 |
+
// Inject message
|
37 |
+
jQuery('#'+humanMsg.msgID+' p').html(msg)
|
38 |
+
|
39 |
+
// Show message
|
40 |
+
jQuery('#'+humanMsg.msgID+'').show().animate({ opacity: humanMsg.msgOpacity}, 200, function() {
|
41 |
+
jQuery('#'+humanMsg.logID)
|
42 |
+
.show().children('ul').prepend('<li>'+msg+'</li>') // Prepend message to log
|
43 |
+
.children('li:first').slideDown(200) // Slide it down
|
44 |
+
|
45 |
+
if ( jQuery('#'+humanMsg.logID+' ul').css('display') == 'none') {
|
46 |
+
jQuery('#'+humanMsg.logID+' p').animate({ bottom: 40 }, 200, 'linear', function() {
|
47 |
+
jQuery(this).animate({ bottom: 0 }, 300, 'easeOutBounce', function() { jQuery(this).css({ bottom: 0 }) })
|
48 |
+
})
|
49 |
+
}
|
50 |
+
|
51 |
+
})
|
52 |
+
|
53 |
+
// Watch for mouse & keyboard in .5s
|
54 |
+
humanMsg.t1 = setTimeout("humanMsg.bindEvents()", 700)
|
55 |
+
// Remove message after 5s
|
56 |
+
humanMsg.t2 = setTimeout("humanMsg.removeMsg()", 5000)
|
57 |
+
},
|
58 |
+
|
59 |
+
bindEvents: function() {
|
60 |
+
// Remove message if mouse is moved or key is pressed
|
61 |
+
jQuery(window)
|
62 |
+
.mousemove(humanMsg.removeMsg)
|
63 |
+
.click(humanMsg.removeMsg)
|
64 |
+
.keypress(humanMsg.removeMsg)
|
65 |
+
},
|
66 |
+
|
67 |
+
removeMsg: function() {
|
68 |
+
// Unbind mouse & keyboard
|
69 |
+
jQuery(window)
|
70 |
+
.unbind('mousemove', humanMsg.removeMsg)
|
71 |
+
.unbind('click', humanMsg.removeMsg)
|
72 |
+
.unbind('keypress', humanMsg.removeMsg)
|
73 |
+
|
74 |
+
// If message is fully transparent, fade it out
|
75 |
+
if (jQuery('#'+humanMsg.msgID).css('opacity') == humanMsg.msgOpacity)
|
76 |
+
jQuery('#'+humanMsg.msgID).animate({ opacity: 0 }, 500, function() { jQuery(this).hide() })
|
77 |
+
}
|
78 |
+
};
|
79 |
+
|
80 |
+
jQuery(document).ready(function(){
|
81 |
+
humanMsg.setup();
|
82 |
+
})
|
lib/jquery.bgiframe.js
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
|
2 |
+
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
3 |
+
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
4 |
+
*
|
5 |
+
* jQueryLastChangedDate: 2007-06-20 03:23:36 +0200 (Mi, 20 Jun 2007) jQuery
|
6 |
+
* jQueryRev: 2110 jQuery
|
7 |
+
*
|
8 |
+
* Version 2.1
|
9 |
+
*/
|
10 |
+
|
11 |
+
(function(jQuery){
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The bgiframe is chainable and applies the iframe hack to get
|
15 |
+
* around zIndex issues in IE6. It will only apply itself in IE
|
16 |
+
* and adds a class to the iframe called 'bgiframe'. The iframe
|
17 |
+
* is appeneded as the first child of the matched element(s)
|
18 |
+
* with a tabIndex and zIndex of -1.
|
19 |
+
*
|
20 |
+
* By default the plugin will take borders, sized with pixel units,
|
21 |
+
* into account. If a different unit is used for the border's width,
|
22 |
+
* then you will need to use the top and left settings as explained below.
|
23 |
+
*
|
24 |
+
* NOTICE: This plugin has been reported to cause perfromance problems
|
25 |
+
* when used on elements that change properties (like width, height and
|
26 |
+
* opacity) a lot in IE6. Most of these problems have been caused by
|
27 |
+
* the expressions used to calculate the elements width, height and
|
28 |
+
* borders. Some have reported it is due to the opacity filter. All
|
29 |
+
* these settings can be changed if needed as explained below.
|
30 |
+
*
|
31 |
+
* @example jQuery('div').bgiframe();
|
32 |
+
* @before <div><p>Paragraph</p></div>
|
33 |
+
* @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
|
34 |
+
*
|
35 |
+
* @param Map settings Optional settings to configure the iframe.
|
36 |
+
* @option String|Number top The iframe must be offset to the top
|
37 |
+
* by the width of the top border. This should be a negative
|
38 |
+
* number representing the border-top-width. If a number is
|
39 |
+
* is used here, pixels will be assumed. Otherwise, be sure
|
40 |
+
* to specify a unit. An expression could also be used.
|
41 |
+
* By default the value is "auto" which will use an expression
|
42 |
+
* to get the border-top-width if it is in pixels.
|
43 |
+
* @option String|Number left The iframe must be offset to the left
|
44 |
+
* by the width of the left border. This should be a negative
|
45 |
+
* number representing the border-left-width. If a number is
|
46 |
+
* is used here, pixels will be assumed. Otherwise, be sure
|
47 |
+
* to specify a unit. An expression could also be used.
|
48 |
+
* By default the value is "auto" which will use an expression
|
49 |
+
* to get the border-left-width if it is in pixels.
|
50 |
+
* @option String|Number width This is the width of the iframe. If
|
51 |
+
* a number is used here, pixels will be assume. Otherwise, be sure
|
52 |
+
* to specify a unit. An experssion could also be used.
|
53 |
+
* By default the value is "auto" which will use an experssion
|
54 |
+
* to get the offsetWidth.
|
55 |
+
* @option String|Number height This is the height of the iframe. If
|
56 |
+
* a number is used here, pixels will be assume. Otherwise, be sure
|
57 |
+
* to specify a unit. An experssion could also be used.
|
58 |
+
* By default the value is "auto" which will use an experssion
|
59 |
+
* to get the offsetHeight.
|
60 |
+
* @option Boolean opacity This is a boolean representing whether or not
|
61 |
+
* to use opacity. If set to true, the opacity of 0 is applied. If
|
62 |
+
* set to false, the opacity filter is not applied. Default: true.
|
63 |
+
* @option String src This setting is provided so that one could change
|
64 |
+
* the src of the iframe to whatever they need.
|
65 |
+
* Default: "javascript:false;"
|
66 |
+
*
|
67 |
+
* @name bgiframe
|
68 |
+
* @type jQuery
|
69 |
+
* @cat Plugins/bgiframe
|
70 |
+
* @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
|
71 |
+
*/
|
72 |
+
jQuery.fn.bgIframe = jQuery.fn.bgiframe = function(s) {
|
73 |
+
// This is only for IE6
|
74 |
+
if ( jQuery.browser.msie && parseInt(jQuery.browser.version) <= 6 ) {
|
75 |
+
s = jQuery.extend({
|
76 |
+
top : 'auto', // auto == .currentStyle.borderTopWidth
|
77 |
+
left : 'auto', // auto == .currentStyle.borderLeftWidth
|
78 |
+
width : 'auto', // auto == offsetWidth
|
79 |
+
height : 'auto', // auto == offsetHeight
|
80 |
+
opacity : true,
|
81 |
+
src : 'javascript:false;'
|
82 |
+
}, s || {});
|
83 |
+
var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
|
84 |
+
html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
|
85 |
+
'style="display:block;position:absolute;z-index:-1;'+
|
86 |
+
(s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
|
87 |
+
'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
|
88 |
+
'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
|
89 |
+
'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
|
90 |
+
'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
|
91 |
+
'"/>';
|
92 |
+
return this.each(function() {
|
93 |
+
if ( jQuery('> iframe.bgiframe', this).length == 0 )
|
94 |
+
this.insertBefore( document.createElement(html), this.firstChild );
|
95 |
+
});
|
96 |
+
}
|
97 |
+
return this;
|
98 |
+
};
|
99 |
+
|
100 |
+
// Add browser.version if it doesn't exist
|
101 |
+
if (!jQuery.browser.version)
|
102 |
+
jQuery.browser.version = navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1];
|
103 |
+
|
104 |
+
})(jQuery);
|
lib/jquery.delegate.js
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery delegate plug-in v1.0
|
3 |
+
*
|
4 |
+
* Copyright (c) 2007 Jörn Zaefferer
|
5 |
+
*
|
6 |
+
* jQueryId: jquery.delegate.js 4786 2008-02-19 20:02:34Z joern.zaefferer jQuery
|
7 |
+
*
|
8 |
+
* Dual licensed under the MIT and GPL licenses:
|
9 |
+
* http://www.opensource.org/licenses/mit-license.php
|
10 |
+
* http://www.gnu.org/licenses/gpl.html
|
11 |
+
*/
|
12 |
+
|
13 |
+
// provides cross-browser focusin and focusout events
|
14 |
+
// IE has native support, in other browsers, use event caputuring (neither bubbles)
|
15 |
+
|
16 |
+
// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
|
17 |
+
// handler is only called when jQuery(event.target).is(delegate), in the scope of the jQuery-object for event.target
|
18 |
+
|
19 |
+
// provides triggerEvent(type: String, target: Element) to trigger delegated events
|
20 |
+
;(function(jQuery) {
|
21 |
+
jQuery.each({
|
22 |
+
focus: 'focusin',
|
23 |
+
blur: 'focusout'
|
24 |
+
}, function( original, fix ){
|
25 |
+
jQuery.event.special[fix] = {
|
26 |
+
setup:function() {
|
27 |
+
if ( jQuery.browser.msie ) return false;
|
28 |
+
this.addEventListener( original, jQuery.event.special[fix].handler, true );
|
29 |
+
},
|
30 |
+
teardown:function() {
|
31 |
+
if ( jQuery.browser.msie ) return false;
|
32 |
+
this.removeEventListener( original,
|
33 |
+
jQuery.event.special[fix].handler, true );
|
34 |
+
},
|
35 |
+
handler: function(e) {
|
36 |
+
arguments[0] = jQuery.event.fix(e);
|
37 |
+
arguments[0].type = fix;
|
38 |
+
return jQuery.event.handle.apply(this, arguments);
|
39 |
+
}
|
40 |
+
};
|
41 |
+
});
|
42 |
+
|
43 |
+
jQuery.extend(jQuery.fn, {
|
44 |
+
delegate: function(type, delegate, handler) {
|
45 |
+
return this.bind(type, function(event) {
|
46 |
+
var target = jQuery(event.target);
|
47 |
+
if (target.is(delegate)) {
|
48 |
+
return handler.apply(target, arguments);
|
49 |
+
}
|
50 |
+
});
|
51 |
+
},
|
52 |
+
triggerEvent: function(type, target) {
|
53 |
+
return this.triggerHandler(type, [jQuery.event.fix({ type: type, target: target })]);
|
54 |
+
}
|
55 |
+
})
|
56 |
+
})(jQuery);
|
lib/jquery.tools.min.js
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jquery.tools 1.1.2 - The missing UI library for the Web
|
3 |
+
*
|
4 |
+
* [tools.scrollable-1.1.2, tools.scrollable.autoscroll-1.0.1, tools.scrollable.navigator-1.0.2, tools.scrollable.mousewheel-1.0.1]
|
5 |
+
*
|
6 |
+
* Copyright (c) 2009 Tero Piirainen
|
7 |
+
* http://flowplayer.org/tools/
|
8 |
+
*
|
9 |
+
* Dual licensed under MIT and GPL 2+ licenses
|
10 |
+
* http://www.opensource.org/licenses
|
11 |
+
*
|
12 |
+
* -----
|
13 |
+
*
|
14 |
+
* jquery.event.wheel.js - rev 1
|
15 |
+
* Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
|
16 |
+
* Liscensed under the MIT License (MIT-LICENSE.txt)
|
17 |
+
* http://www.opensource.org/licenses/mit-license.php
|
18 |
+
* Created: 2008-07-01 | Updated: 2008-07-14
|
19 |
+
*
|
20 |
+
* -----
|
21 |
+
*
|
22 |
+
* File generated: Wed Oct 07 19:54:35 GMT+00:00 2009
|
23 |
+
*/
|
24 |
+
(function(b){b.tools=b.tools||{};b.tools.scrollable={version:"1.1.2",conf:{size:5,vertical:false,speed:400,keyboard:true,keyboardSteps:null,disabledClass:"disabled",hoverClass:null,clickable:true,activeClass:"active",easing:"swing",loop:false,items:".items",item:null,prev:".prev",next:".next",prevPage:".prevPage",nextPage:".nextPage",api:false}};var c;function a(o,m){var r=this,p=b(this),d=!m.vertical,e=o.children(),k=0,i;if(!c){c=r}b.each(m,function(s,t){if(b.isFunction(t)){p.bind(s,t)}});if(e.length>1){e=b(m.items,o)}function l(t){var s=b(t);return m.globalNav?s:o.parent().find(t)}o.data("finder",l);var f=l(m.prev),h=l(m.next),g=l(m.prevPage),n=l(m.nextPage);b.extend(r,{getIndex:function(){return k},getClickIndex:function(){var s=r.getItems();return s.index(s.filter("."+m.activeClass))},getConf:function(){return m},getSize:function(){return r.getItems().size()},getPageAmount:function(){return Math.ceil(this.getSize()/m.size)},getPageIndex:function(){return Math.ceil(k/m.size)},getNaviButtons:function(){return f.add(h).add(g).add(n)},getRoot:function(){return o},getItemWrap:function(){return e},getItems:function(){return e.children(m.item)},getVisibleItems:function(){return r.getItems().slice(k,k+m.size)},seekTo:function(s,w,t){if(s<0){s=0}if(k===s){return r}if(b.isFunction(w)){t=w}if(s>r.getSize()-m.size){return m.loop?r.begin():this.end()}var u=r.getItems().eq(s);if(!u.length){return r}var v=b.Event("onBeforeSeek");p.trigger(v,[s]);if(v.isDefaultPrevented()){return r}if(w===undefined||b.isFunction(w)){w=m.speed}function x(){if(t){t.call(r,s)}p.trigger("onSeek",[s])}if(d){e.animate({left:-u.position().left},w,m.easing,x)}else{e.animate({top:-u.position().top},w,m.easing,x)}c=r;k=s;v=b.Event("onStart");p.trigger(v,[s]);if(v.isDefaultPrevented()){return r}f.add(g).toggleClass(m.disabledClass,s===0);h.add(n).toggleClass(m.disabledClass,s>=r.getSize()-m.size);return r},move:function(u,t,s){i=u>0;return this.seekTo(k+u,t,s)},next:function(t,s){return this.move(1,t,s)},prev:function(t,s){return this.move(-1,t,s)},movePage:function(w,v,u){i=w>0;var s=m.size*w;var t=k%m.size;if(t>0){s+=(w>0?-t:m.size-t)}return this.move(s,v,u)},prevPage:function(t,s){return this.movePage(-1,t,s)},nextPage:function(t,s){return this.movePage(1,t,s)},setPage:function(t,u,s){return this.seekTo(t*m.size,u,s)},begin:function(t,s){i=false;return this.seekTo(0,t,s)},end:function(t,s){i=true;var u=this.getSize()-m.size;return u>0?this.seekTo(u,t,s):r},reload:function(){p.trigger("onReload");return r},focus:function(){c=r;return r},click:function(u){var v=r.getItems().eq(u),s=m.activeClass,t=m.size;if(u<0||u>=r.getSize()){return r}if(t==1){if(m.loop){return r.next()}if(u===0||u==r.getSize()-1){i=(i===undefined)?true:!i}return i===false?r.prev():r.next()}if(t==2){if(u==k){u--}r.getItems().removeClass(s);v.addClass(s);return r.seekTo(u,time,fn)}if(!v.hasClass(s)){r.getItems().removeClass(s);v.addClass(s);var x=Math.floor(t/2);var w=u-x;if(w>r.getSize()-t){w=r.getSize()-t}if(w!==u){return r.seekTo(w)}}return r},bind:function(s,t){p.bind(s,t);return r},unbind:function(s){p.unbind(s);return r}});b.each("onBeforeSeek,onStart,onSeek,onReload".split(","),function(s,t){r[t]=function(u){return r.bind(t,u)}});f.addClass(m.disabledClass).click(function(){r.prev()});h.click(function(){r.next()});n.click(function(){r.nextPage()});if(r.getSize()<m.size){h.add(n).addClass(m.disabledClass)}g.addClass(m.disabledClass).click(function(){r.prevPage()});var j=m.hoverClass,q="keydown."+Math.random().toString().substring(10);r.onReload(function(){if(j){r.getItems().hover(function(){b(this).addClass(j)},function(){b(this).removeClass(j)})}if(m.clickable){r.getItems().each(function(s){b(this).unbind("click.scrollable").bind("click.scrollable",function(t){if(b(t.target).is("a")){return}return r.click(s)})})}if(m.keyboard){b(document).unbind(q).bind(q,function(t){if(t.altKey||t.ctrlKey){return}if(m.keyboard!="static"&&c!=r){return}var u=m.keyboardSteps;if(d&&(t.keyCode==37||t.keyCode==39)){r.move(t.keyCode==37?-u:u);return t.preventDefault()}if(!d&&(t.keyCode==38||t.keyCode==40)){r.move(t.keyCode==38?-u:u);return t.preventDefault()}return true})}else{b(document).unbind(q)}});r.reload()}b.fn.scrollable=function(d){var e=this.eq(typeof d=="number"?d:0).data("scrollable");if(e){return e}var f=b.extend({},b.tools.scrollable.conf);d=b.extend(f,d);d.keyboardSteps=d.keyboardSteps||d.size;this.each(function(){e=new a(b(this),d);b(this).data("scrollable",e)});return d.api?e:this}})(jQuery);
|
25 |
+
(function(b){var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.autoscroll={version:"1.0.1",conf:{autoplay:true,interval:3000,autopause:true,steps:1,api:false}};b.fn.autoscroll=function(d){if(typeof d=="number"){d={interval:d}}var e=b.extend({},a.plugins.autoscroll.conf),c;b.extend(e,d);this.each(function(){var g=b(this).scrollable();if(g){c=g}var i,f,h=true;g.play=function(){if(i){return}h=false;i=setInterval(function(){g.move(e.steps)},e.interval);g.move(e.steps)};g.pause=function(){i=clearInterval(i)};g.stop=function(){g.pause();h=true};if(e.autopause){g.getRoot().add(g.getNaviButtons()).hover(function(){g.pause();clearInterval(f)},function(){if(!h){f=setTimeout(g.play,e.interval)}})}if(e.autoplay){setTimeout(g.play,e.interval)}});return e.api?c:this}})(jQuery);
|
26 |
+
(function(b){var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.navigator={version:"1.0.2",conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:false,api:false,idPrefix:null}};b.fn.navigator=function(d){var e=b.extend({},a.plugins.navigator.conf),c;if(typeof d=="string"){d={navi:d}}d=b.extend(e,d);this.each(function(){var i=b(this).scrollable(),f=i.getRoot(),l=f.data("finder").call(null,d.navi),g=null,k=i.getNaviButtons();if(i){c=i}i.getNaviButtons=function(){return k.add(l)};function j(){if(!l.children().length||l.data("navi")==i){l.empty();l.data("navi",i);for(var m=0;m<i.getPageAmount();m++){l.append(b("<"+(d.naviItem||"a")+"/>"))}g=l.children().each(function(n){var o=b(this);o.click(function(p){i.setPage(n);return p.preventDefault()});if(d.indexed){o.text(n)}if(d.idPrefix){o.attr("id",d.idPrefix+n)}})}else{g=d.naviItem?l.find(d.naviItem):l.children();g.each(function(n){var o=b(this);o.click(function(p){i.setPage(n);return p.preventDefault()})})}g.eq(0).addClass(d.activeClass)}i.onStart(function(o,n){var m=d.activeClass;g.removeClass(m).eq(i.getPageIndex()).addClass(m)});i.onReload(function(){j()});j();var h=g.filter("[href="+location.hash+"]");if(h.length){i.move(g.index(h))}});return d.api?c:this}})(jQuery);
|
27 |
+
(function(b){b.fn.wheel=function(e){return this[e?"bind":"trigger"]("wheel",e)};b.event.special.wheel={setup:function(){b.event.add(this,d,c,{})},teardown:function(){b.event.remove(this,d,c)}};var d=!b.browser.mozilla?"mousewheel":"DOMMouseScroll"+(b.browser.version<"1.9"?" mousemove":"");function c(e){switch(e.type){case"mousemove":return b.extend(e.data,{clientX:e.clientX,clientY:e.clientY,pageX:e.pageX,pageY:e.pageY});case"DOMMouseScroll":b.extend(e,e.data);e.delta=-e.detail/3;break;case"mousewheel":e.delta=e.wheelDelta/120;break}e.type="wheel";return b.event.handle.call(this,e,e.delta)}var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.mousewheel={version:"1.0.1",conf:{api:false,speed:50}};b.fn.mousewheel=function(f){var g=b.extend({},a.plugins.mousewheel.conf),e;if(typeof f=="number"){f={speed:f}}f=b.extend(g,f);this.each(function(){var h=b(this).scrollable();if(h){e=h}h.getRoot().wheel(function(i,j){h.move(j<0?1:-1,f.speed||50);return false})});return f.api?e:this}})(jQuery);
|
lib/jquery.tooltip.css
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#tooltip {
|
2 |
+
position: absolute;
|
3 |
+
z-index: 3000;
|
4 |
+
border: 1px solid #111;
|
5 |
+
background-color: #eee;
|
6 |
+
padding: 5px;
|
7 |
+
opacity: 0.85;
|
8 |
+
}
|
9 |
+
#tooltip h3, #tooltip div { margin: 0; }
|
lib/jquery.tooltip.js
ADDED
@@ -0,0 +1,329 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery Tooltip plugin 1.3
|
3 |
+
*
|
4 |
+
* http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
|
5 |
+
* http://docs.jquery.com/Plugins/Tooltip
|
6 |
+
*
|
7 |
+
* Copyright (c) 2006 - 2008 Jörn Zaefferer
|
8 |
+
*
|
9 |
+
* jQueryId: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer jQuery
|
10 |
+
*
|
11 |
+
* Dual licensed under the MIT and GPL licenses:
|
12 |
+
* http://www.opensource.org/licenses/mit-license.php
|
13 |
+
* http://www.gnu.org/licenses/gpl.html
|
14 |
+
*/
|
15 |
+
|
16 |
+
;(function(jQuery) {
|
17 |
+
|
18 |
+
// the tooltip element
|
19 |
+
var helper = {},
|
20 |
+
// the current tooltipped element
|
21 |
+
current,
|
22 |
+
// the title of the current element, used for restoring
|
23 |
+
title,
|
24 |
+
// timeout id for delayed tooltips
|
25 |
+
tID,
|
26 |
+
//timout for hiding delayed tooltips
|
27 |
+
htID,
|
28 |
+
// IE 5.5 or 6
|
29 |
+
IE = jQuery.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
|
30 |
+
// flag for mouse tracking
|
31 |
+
track = false;
|
32 |
+
|
33 |
+
jQuery.tooltip = {
|
34 |
+
blocked: false,
|
35 |
+
defaults: {
|
36 |
+
delay: 200,
|
37 |
+
fade: false,
|
38 |
+
showURL: true,
|
39 |
+
extraClass: "",
|
40 |
+
top: 15,
|
41 |
+
left: 15,
|
42 |
+
id: "tooltip"
|
43 |
+
},
|
44 |
+
block: function() {
|
45 |
+
jQuery.tooltip.blocked = !jQuery.tooltip.blocked;
|
46 |
+
}
|
47 |
+
};
|
48 |
+
|
49 |
+
jQuery.fn.extend({
|
50 |
+
tooltip: function(settings) {
|
51 |
+
settings = jQuery.extend({}, jQuery.tooltip.defaults, settings);
|
52 |
+
createHelper(settings);
|
53 |
+
return this.each(function() {
|
54 |
+
jQuery.data(this, "tooltip", settings);
|
55 |
+
this.tOpacity = helper.parent.css("opacity");
|
56 |
+
// copy tooltip into its own expando and remove the title
|
57 |
+
this.tooltipText = this.title;
|
58 |
+
jQuery(this).removeAttr("title");
|
59 |
+
// also remove alt attribute to prevent default tooltip in IE
|
60 |
+
this.alt = "";
|
61 |
+
})
|
62 |
+
.mouseover(save)
|
63 |
+
.mouseout(hide)
|
64 |
+
.click(hide);
|
65 |
+
},
|
66 |
+
fixPNG: IE ? function() {
|
67 |
+
return this.each(function () {
|
68 |
+
var image = jQuery(this).css('backgroundImage');
|
69 |
+
if (image.match(/^url\(["']?(.*\.png)["']?\)jQuery/i)) {
|
70 |
+
image = RegExp.jQuery1;
|
71 |
+
jQuery(this).css({
|
72 |
+
'backgroundImage': 'none',
|
73 |
+
'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
|
74 |
+
}).each(function () {
|
75 |
+
var position = jQuery(this).css('position');
|
76 |
+
if (position != 'absolute' && position != 'relative')
|
77 |
+
jQuery(this).css('position', 'relative');
|
78 |
+
});
|
79 |
+
}
|
80 |
+
});
|
81 |
+
} : function() { return this; },
|
82 |
+
unfixPNG: IE ? function() {
|
83 |
+
return this.each(function () {
|
84 |
+
jQuery(this).css({'filter': '', backgroundImage: ''});
|
85 |
+
});
|
86 |
+
} : function() { return this; },
|
87 |
+
hideWhenEmpty: function() {
|
88 |
+
return this.each(function() {
|
89 |
+
jQuery(this)[ jQuery(this).html() ? "show" : "hide" ]();
|
90 |
+
});
|
91 |
+
},
|
92 |
+
url: function() {
|
93 |
+
return this.attr('href') || this.attr('src');
|
94 |
+
}
|
95 |
+
});
|
96 |
+
|
97 |
+
function createHelper(settings) {
|
98 |
+
// there can be only one tooltip helper
|
99 |
+
if( helper.parent )
|
100 |
+
return;
|
101 |
+
// create the helper, h3 for title, div for url
|
102 |
+
helper.parent = jQuery('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>')
|
103 |
+
// add to document
|
104 |
+
.appendTo(document.body)
|
105 |
+
// hide it at first
|
106 |
+
.hide();
|
107 |
+
|
108 |
+
// apply bgiframe if available
|
109 |
+
if ( jQuery.fn.bgiframe )
|
110 |
+
helper.parent.bgiframe();
|
111 |
+
|
112 |
+
// save references to title and url elements
|
113 |
+
helper.title = jQuery('h3', helper.parent);
|
114 |
+
helper.body = jQuery('div.body', helper.parent);
|
115 |
+
helper.url = jQuery('div.url', helper.parent);
|
116 |
+
jQuery("#" + settings.id).click(function() {
|
117 |
+
hide();
|
118 |
+
});
|
119 |
+
}
|
120 |
+
|
121 |
+
function tooltipsettings(element) {
|
122 |
+
if (element) {
|
123 |
+
return jQuery.data(element, "tooltip");
|
124 |
+
} else {
|
125 |
+
jQuery("#tooltip").hide();
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
// main event handler to start showing tooltips
|
130 |
+
function handle(event) {
|
131 |
+
// show helper, either with timeout or on instant
|
132 |
+
if( tooltipsettings(this).delay )
|
133 |
+
tID = setTimeout(show, tooltipsettings(this).delay);
|
134 |
+
else
|
135 |
+
show();
|
136 |
+
|
137 |
+
// if selected, update the helper position when the mouse moves
|
138 |
+
track = !!tooltipsettings(this).track;
|
139 |
+
jQuery(document.body).bind('mousemove', update);
|
140 |
+
|
141 |
+
// update at least once
|
142 |
+
update(event);
|
143 |
+
}
|
144 |
+
|
145 |
+
// save elements title before the tooltip is displayed
|
146 |
+
function save() {
|
147 |
+
// if this is the current source, or it has no title (occurs with click event), stop
|
148 |
+
if ( jQuery.tooltip.blocked || this == current || (!this.tooltipText && !tooltipsettings(this).bodyHandler) )
|
149 |
+
return;
|
150 |
+
|
151 |
+
// save current
|
152 |
+
current = this;
|
153 |
+
title = this.tooltipText;
|
154 |
+
|
155 |
+
if ( tooltipsettings(this).bodyHandler ) {
|
156 |
+
helper.title.hide();
|
157 |
+
var bodyContent = tooltipsettings(this).bodyHandler.call(this);
|
158 |
+
if (bodyContent.nodeType || bodyContent.jquery) {
|
159 |
+
helper.body.empty().append(bodyContent)
|
160 |
+
} else {
|
161 |
+
helper.body.html( bodyContent );
|
162 |
+
}
|
163 |
+
helper.body.show();
|
164 |
+
} else if ( tooltipsettings(this).showBody ) {
|
165 |
+
var parts = title.split(tooltipsettings(this).showBody);
|
166 |
+
helper.title.html(parts.shift()).show();
|
167 |
+
helper.body.empty();
|
168 |
+
for(var i = 0, part; (part = parts[i]); i++) {
|
169 |
+
if(i > 0)
|
170 |
+
helper.body.append("<br/>");
|
171 |
+
helper.body.append(part);
|
172 |
+
}
|
173 |
+
helper.body.hideWhenEmpty();
|
174 |
+
} else {
|
175 |
+
helper.title.html(title).show();
|
176 |
+
helper.body.hide();
|
177 |
+
}
|
178 |
+
|
179 |
+
// if element has href or src, add and show it, otherwise hide it
|
180 |
+
if( tooltipsettings(this).showURL && jQuery(this).url() )
|
181 |
+
helper.url.html( jQuery(this).url().replace('http://', '') ).show();
|
182 |
+
else
|
183 |
+
helper.url.hide();
|
184 |
+
|
185 |
+
// add an optional class for this tip
|
186 |
+
helper.parent.addClass(tooltipsettings(this).extraClass);
|
187 |
+
|
188 |
+
// fix PNG background for IE
|
189 |
+
if (tooltipsettings(this).fixPNG )
|
190 |
+
helper.parent.fixPNG();
|
191 |
+
|
192 |
+
handle.apply(this, arguments);
|
193 |
+
}
|
194 |
+
|
195 |
+
// delete timeout and show helper
|
196 |
+
function show() {
|
197 |
+
if (!tooltipsettings(current)) {
|
198 |
+
return;
|
199 |
+
}
|
200 |
+
tID = null;
|
201 |
+
if ((!IE || !jQuery.fn.bgiframe) && tooltipsettings(current).fade) {
|
202 |
+
if (helper.parent.is(":animated"))
|
203 |
+
helper.parent.stop().show().fadeTo(tooltipsettings(current).fade, current.tOpacity);
|
204 |
+
else
|
205 |
+
helper.parent.is(':visible') ? helper.parent.fadeTo(tooltipsettings(current).fade, current.tOpacity) : helper.parent.fadeIn(tooltipsettings(current).fade);
|
206 |
+
} else {
|
207 |
+
helper.parent.show();
|
208 |
+
}
|
209 |
+
update();
|
210 |
+
}
|
211 |
+
|
212 |
+
/**
|
213 |
+
* callback for mousemove
|
214 |
+
* updates the helper position
|
215 |
+
* removes itself when no current element
|
216 |
+
*/
|
217 |
+
function update(event) {
|
218 |
+
if(jQuery.tooltip.blocked)
|
219 |
+
return;
|
220 |
+
if (!tooltipsettings(current)) {
|
221 |
+
return;
|
222 |
+
}
|
223 |
+
|
224 |
+
if (event && event.target.tagName == "OPTION") {
|
225 |
+
return;
|
226 |
+
}
|
227 |
+
|
228 |
+
// stop updating when tracking is disabled and the tooltip is visible
|
229 |
+
if ( !track && helper.parent.is(":visible")) {
|
230 |
+
jQuery(document.body).unbind('mousemove', update)
|
231 |
+
}
|
232 |
+
|
233 |
+
// if no current element is available, remove this listener
|
234 |
+
if( current == null ) {
|
235 |
+
jQuery(document.body).unbind('mousemove', update);
|
236 |
+
return;
|
237 |
+
}
|
238 |
+
|
239 |
+
// remove position helper classes
|
240 |
+
helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
|
241 |
+
|
242 |
+
var left = helper.parent[0].offsetLeft;
|
243 |
+
var top = helper.parent[0].offsetTop;
|
244 |
+
if (event) {
|
245 |
+
// position the helper 15 pixel to bottom right, starting from mouse position
|
246 |
+
left = event.pageX + tooltipsettings(current).left;
|
247 |
+
top = event.pageY + tooltipsettings(current).top;
|
248 |
+
var right='auto';
|
249 |
+
if (tooltipsettings(current).positionLeft) {
|
250 |
+
right = jQuery(window).width() - left;
|
251 |
+
left = 'auto';
|
252 |
+
}
|
253 |
+
helper.parent.css({
|
254 |
+
left: left,
|
255 |
+
right: right,
|
256 |
+
top: top
|
257 |
+
});
|
258 |
+
}
|
259 |
+
|
260 |
+
var v = viewport(),
|
261 |
+
h = helper.parent[0];
|
262 |
+
// check horizontal position
|
263 |
+
if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
|
264 |
+
left -= h.offsetWidth + 20 + tooltipsettings(current).left + 75;
|
265 |
+
helper.parent.css({left: left + 'px'}).addClass("viewport-right");
|
266 |
+
}
|
267 |
+
// check vertical position
|
268 |
+
if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
|
269 |
+
top -= h.offsetHeight + 20 + tooltipsettings(current).top;
|
270 |
+
helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
function viewport() {
|
275 |
+
return {
|
276 |
+
x: jQuery(window).scrollLeft(),
|
277 |
+
y: jQuery(window).scrollTop(),
|
278 |
+
cx: jQuery(window).width(),
|
279 |
+
cy: jQuery(window).height()
|
280 |
+
};
|
281 |
+
}
|
282 |
+
|
283 |
+
// hide helper and restore added classes and the title
|
284 |
+
function hide(event) {
|
285 |
+
if(jQuery.tooltip.blocked)
|
286 |
+
return;
|
287 |
+
|
288 |
+
if (!event) {
|
289 |
+
jQuery("#tooltip").hide();
|
290 |
+
return;
|
291 |
+
}
|
292 |
+
|
293 |
+
var offset = jQuery("#tooltip").offset();
|
294 |
+
/*
|
295 |
+
* We want to give the user a chance to get their mouse over the tooltip
|
296 |
+
* before we hide it.
|
297 |
+
*/
|
298 |
+
if (event.pageX >= offset.left - 15 &&
|
299 |
+
event.pageY >= offset.top - 15 &&
|
300 |
+
event.pageX <= jQuery("#tooltip").width() + offset.left + 15 &&
|
301 |
+
event.pageY <= jQuery("#tooltip").height() + offset.top + 15) {
|
302 |
+
return;
|
303 |
+
}
|
304 |
+
|
305 |
+
// clear timeout if possible
|
306 |
+
if(tID)
|
307 |
+
clearTimeout(tID);
|
308 |
+
// no more current element
|
309 |
+
current = null;
|
310 |
+
|
311 |
+
var tsettings = tooltipsettings(this);
|
312 |
+
function complete() {
|
313 |
+
helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
|
314 |
+
}
|
315 |
+
if ((!IE || !jQuery.fn.bgiframe) && tsettings.fade) {
|
316 |
+
if (helper.parent.is(':animated'))
|
317 |
+
helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
|
318 |
+
else
|
319 |
+
helper.parent.stop().fadeOut(tsettings.fade, complete);
|
320 |
+
} else
|
321 |
+
complete();
|
322 |
+
|
323 |
+
if( tooltipsettings(this).fixPNG )
|
324 |
+
helper.parent.unfixPNG();
|
325 |
+
|
326 |
+
htID = null;
|
327 |
+
}
|
328 |
+
|
329 |
+
})(jQuery);
|
lib/json2.js
ADDED
@@ -0,0 +1,480 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
http://www.JSON.org/json2.js
|
3 |
+
2009-09-29
|
4 |
+
|
5 |
+
Public Domain.
|
6 |
+
|
7 |
+
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
8 |
+
|
9 |
+
See http://www.JSON.org/js.html
|
10 |
+
|
11 |
+
This file creates a global JSON object containing two methods: stringify
|
12 |
+
and parse.
|
13 |
+
|
14 |
+
JSON.stringify(value, replacer, space)
|
15 |
+
value any JavaScript value, usually an object or array.
|
16 |
+
|
17 |
+
replacer an optional parameter that determines how object
|
18 |
+
values are stringified for objects. It can be a
|
19 |
+
function or an array of strings.
|
20 |
+
|
21 |
+
space an optional parameter that specifies the indentation
|
22 |
+
of nested structures. If it is omitted, the text will
|
23 |
+
be packed without extra whitespace. If it is a number,
|
24 |
+
it will specify the number of spaces to indent at each
|
25 |
+
level. If it is a string (such as '\t' or ' '),
|
26 |
+
it contains the characters used to indent at each level.
|
27 |
+
|
28 |
+
This method produces a JSON text from a JavaScript value.
|
29 |
+
|
30 |
+
When an object value is found, if the object contains a toJSON
|
31 |
+
method, its toJSON method will be called and the result will be
|
32 |
+
stringified. A toJSON method does not serialize: it returns the
|
33 |
+
value represented by the name/value pair that should be serialized,
|
34 |
+
or undefined if nothing should be serialized. The toJSON method
|
35 |
+
will be passed the key associated with the value, and this will be
|
36 |
+
bound to the value
|
37 |
+
|
38 |
+
For example, this would serialize Dates as ISO strings.
|
39 |
+
|
40 |
+
Date.prototype.toJSON = function (key) {
|
41 |
+
function f(n) {
|
42 |
+
// Format integers to have at least two digits.
|
43 |
+
return n < 10 ? '0' + n : n;
|
44 |
+
}
|
45 |
+
|
46 |
+
return this.getUTCFullYear() + '-' +
|
47 |
+
f(this.getUTCMonth() + 1) + '-' +
|
48 |
+
f(this.getUTCDate()) + 'T' +
|
49 |
+
f(this.getUTCHours()) + ':' +
|
50 |
+
f(this.getUTCMinutes()) + ':' +
|
51 |
+
f(this.getUTCSeconds()) + 'Z';
|
52 |
+
};
|
53 |
+
|
54 |
+
You can provide an optional replacer method. It will be passed the
|
55 |
+
key and value of each member, with this bound to the containing
|
56 |
+
object. The value that is returned from your method will be
|
57 |
+
serialized. If your method returns undefined, then the member will
|
58 |
+
be excluded from the serialization.
|
59 |
+
|
60 |
+
If the replacer parameter is an array of strings, then it will be
|
61 |
+
used to select the members to be serialized. It filters the results
|
62 |
+
such that only members with keys listed in the replacer array are
|
63 |
+
stringified.
|
64 |
+
|
65 |
+
Values that do not have JSON representations, such as undefined or
|
66 |
+
functions, will not be serialized. Such values in objects will be
|
67 |
+
dropped; in arrays they will be replaced with null. You can use
|
68 |
+
a replacer function to replace those with JSON values.
|
69 |
+
JSON.stringify(undefined) returns undefined.
|
70 |
+
|
71 |
+
The optional space parameter produces a stringification of the
|
72 |
+
value that is filled with line breaks and indentation to make it
|
73 |
+
easier to read.
|
74 |
+
|
75 |
+
If the space parameter is a non-empty string, then that string will
|
76 |
+
be used for indentation. If the space parameter is a number, then
|
77 |
+
the indentation will be that many spaces.
|
78 |
+
|
79 |
+
Example:
|
80 |
+
|
81 |
+
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
82 |
+
// text is '["e",{"pluribus":"unum"}]'
|
83 |
+
|
84 |
+
|
85 |
+
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
86 |
+
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
87 |
+
|
88 |
+
text = JSON.stringify([new Date()], function (key, value) {
|
89 |
+
return this[key] instanceof Date ?
|
90 |
+
'Date(' + this[key] + ')' : value;
|
91 |
+
});
|
92 |
+
// text is '["Date(---current time---)"]'
|
93 |
+
|
94 |
+
|
95 |
+
JSON.parse(text, reviver)
|
96 |
+
This method parses a JSON text to produce an object or array.
|
97 |
+
It can throw a SyntaxError exception.
|
98 |
+
|
99 |
+
The optional reviver parameter is a function that can filter and
|
100 |
+
transform the results. It receives each of the keys and values,
|
101 |
+
and its return value is used instead of the original value.
|
102 |
+
If it returns what it received, then the structure is not modified.
|
103 |
+
If it returns undefined then the member is deleted.
|
104 |
+
|
105 |
+
Example:
|
106 |
+
|
107 |
+
// Parse the text. Values that look like ISO date strings will
|
108 |
+
// be converted to Date objects.
|
109 |
+
|
110 |
+
myData = JSON.parse(text, function (key, value) {
|
111 |
+
var a;
|
112 |
+
if (typeof value === 'string') {
|
113 |
+
a =
|
114 |
+
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
115 |
+
if (a) {
|
116 |
+
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
117 |
+
+a[5], +a[6]));
|
118 |
+
}
|
119 |
+
}
|
120 |
+
return value;
|
121 |
+
});
|
122 |
+
|
123 |
+
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
124 |
+
var d;
|
125 |
+
if (typeof value === 'string' &&
|
126 |
+
value.slice(0, 5) === 'Date(' &&
|
127 |
+
value.slice(-1) === ')') {
|
128 |
+
d = new Date(value.slice(5, -1));
|
129 |
+
if (d) {
|
130 |
+
return d;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
return value;
|
134 |
+
});
|
135 |
+
|
136 |
+
|
137 |
+
This is a reference implementation. You are free to copy, modify, or
|
138 |
+
redistribute.
|
139 |
+
|
140 |
+
This code should be minified before deployment.
|
141 |
+
See http://javascript.crockford.com/jsmin.html
|
142 |
+
|
143 |
+
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
144 |
+
NOT CONTROL.
|
145 |
+
*/
|
146 |
+
|
147 |
+
/*jslint evil: true, strict: false */
|
148 |
+
|
149 |
+
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
150 |
+
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
151 |
+
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
152 |
+
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
153 |
+
test, toJSON, toString, valueOf
|
154 |
+
*/
|
155 |
+
|
156 |
+
|
157 |
+
// Create a JSON object only if one does not already exist. We create the
|
158 |
+
// methods in a closure to avoid creating global variables.
|
159 |
+
|
160 |
+
if (!this.JSON) {
|
161 |
+
this.JSON = {};
|
162 |
+
}
|
163 |
+
|
164 |
+
(function () {
|
165 |
+
|
166 |
+
function f(n) {
|
167 |
+
// Format integers to have at least two digits.
|
168 |
+
return n < 10 ? '0' + n : n;
|
169 |
+
}
|
170 |
+
|
171 |
+
if (typeof Date.prototype.toJSON !== 'function') {
|
172 |
+
|
173 |
+
Date.prototype.toJSON = function (key) {
|
174 |
+
|
175 |
+
return isFinite(this.valueOf()) ?
|
176 |
+
this.getUTCFullYear() + '-' +
|
177 |
+
f(this.getUTCMonth() + 1) + '-' +
|
178 |
+
f(this.getUTCDate()) + 'T' +
|
179 |
+
f(this.getUTCHours()) + ':' +
|
180 |
+
f(this.getUTCMinutes()) + ':' +
|
181 |
+
f(this.getUTCSeconds()) + 'Z' : null;
|
182 |
+
};
|
183 |
+
|
184 |
+
String.prototype.toJSON =
|
185 |
+
Number.prototype.toJSON =
|
186 |
+
Boolean.prototype.toJSON = function (key) {
|
187 |
+
return this.valueOf();
|
188 |
+
};
|
189 |
+
}
|
190 |
+
|
191 |
+
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
192 |
+
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
193 |
+
gap,
|
194 |
+
indent,
|
195 |
+
meta = { // table of character substitutions
|
196 |
+
'\b': '\\b',
|
197 |
+
'\t': '\\t',
|
198 |
+
'\n': '\\n',
|
199 |
+
'\f': '\\f',
|
200 |
+
'\r': '\\r',
|
201 |
+
'"' : '\\"',
|
202 |
+
'\\': '\\\\'
|
203 |
+
},
|
204 |
+
rep;
|
205 |
+
|
206 |
+
|
207 |
+
function quote(string) {
|
208 |
+
|
209 |
+
// If the string contains no control characters, no quote characters, and no
|
210 |
+
// backslash characters, then we can safely slap some quotes around it.
|
211 |
+
// Otherwise we must also replace the offending characters with safe escape
|
212 |
+
// sequences.
|
213 |
+
|
214 |
+
escapable.lastIndex = 0;
|
215 |
+
return escapable.test(string) ?
|
216 |
+
'"' + string.replace(escapable, function (a) {
|
217 |
+
var c = meta[a];
|
218 |
+
return typeof c === 'string' ? c :
|
219 |
+
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
220 |
+
}) + '"' :
|
221 |
+
'"' + string + '"';
|
222 |
+
}
|
223 |
+
|
224 |
+
|
225 |
+
function str(key, holder) {
|
226 |
+
|
227 |
+
// Produce a string from holder[key].
|
228 |
+
|
229 |
+
var i, // The loop counter.
|
230 |
+
k, // The member key.
|
231 |
+
v, // The member value.
|
232 |
+
length,
|
233 |
+
mind = gap,
|
234 |
+
partial,
|
235 |
+
value = holder[key];
|
236 |
+
|
237 |
+
// If the value has a toJSON method, call it to obtain a replacement value.
|
238 |
+
|
239 |
+
if (value && typeof value === 'object' &&
|
240 |
+
typeof value.toJSON === 'function') {
|
241 |
+
value = value.toJSON(key);
|
242 |
+
}
|
243 |
+
|
244 |
+
// If we were called with a replacer function, then call the replacer to
|
245 |
+
// obtain a replacement value.
|
246 |
+
|
247 |
+
if (typeof rep === 'function') {
|
248 |
+
value = rep.call(holder, key, value);
|
249 |
+
}
|
250 |
+
|
251 |
+
// What happens next depends on the value's type.
|
252 |
+
|
253 |
+
switch (typeof value) {
|
254 |
+
case 'string':
|
255 |
+
return quote(value);
|
256 |
+
|
257 |
+
case 'number':
|
258 |
+
|
259 |
+
// JSON numbers must be finite. Encode non-finite numbers as null.
|
260 |
+
|
261 |
+
return isFinite(value) ? String(value) : 'null';
|
262 |
+
|
263 |
+
case 'boolean':
|
264 |
+
case 'null':
|
265 |
+
|
266 |
+
// If the value is a boolean or null, convert it to a string. Note:
|
267 |
+
// typeof null does not produce 'null'. The case is included here in
|
268 |
+
// the remote chance that this gets fixed someday.
|
269 |
+
|
270 |
+
return String(value);
|
271 |
+
|
272 |
+
// If the type is 'object', we might be dealing with an object or an array or
|
273 |
+
// null.
|
274 |
+
|
275 |
+
case 'object':
|
276 |
+
|
277 |
+
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
278 |
+
// so watch out for that case.
|
279 |
+
|
280 |
+
if (!value) {
|
281 |
+
return 'null';
|
282 |
+
}
|
283 |
+
|
284 |
+
// Make an array to hold the partial results of stringifying this object value.
|
285 |
+
|
286 |
+
gap += indent;
|
287 |
+
partial = [];
|
288 |
+
|
289 |
+
// Is the value an array?
|
290 |
+
|
291 |
+
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
292 |
+
|
293 |
+
// The value is an array. Stringify every element. Use null as a placeholder
|
294 |
+
// for non-JSON values.
|
295 |
+
|
296 |
+
length = value.length;
|
297 |
+
for (i = 0; i < length; i += 1) {
|
298 |
+
partial[i] = str(i, value) || 'null';
|
299 |
+
}
|
300 |
+
|
301 |
+
// Join all of the elements together, separated with commas, and wrap them in
|
302 |
+
// brackets.
|
303 |
+
|
304 |
+
v = partial.length === 0 ? '[]' :
|
305 |
+
gap ? '[\n' + gap +
|
306 |
+
partial.join(',\n' + gap) + '\n' +
|
307 |
+
mind + ']' :
|
308 |
+
'[' + partial.join(',') + ']';
|
309 |
+
gap = mind;
|
310 |
+
return v;
|
311 |
+
}
|
312 |
+
|
313 |
+
// If the replacer is an array, use it to select the members to be stringified.
|
314 |
+
|
315 |
+
if (rep && typeof rep === 'object') {
|
316 |
+
length = rep.length;
|
317 |
+
for (i = 0; i < length; i += 1) {
|
318 |
+
k = rep[i];
|
319 |
+
if (typeof k === 'string') {
|
320 |
+
v = str(k, value);
|
321 |
+
if (v) {
|
322 |
+
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
323 |
+
}
|
324 |
+
}
|
325 |
+
}
|
326 |
+
} else {
|
327 |
+
|
328 |
+
// Otherwise, iterate through all of the keys in the object.
|
329 |
+
|
330 |
+
for (k in value) {
|
331 |
+
if (Object.hasOwnProperty.call(value, k)) {
|
332 |
+
v = str(k, value);
|
333 |
+
if (v) {
|
334 |
+
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
335 |
+
}
|
336 |
+
}
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
// Join all of the member texts together, separated with commas,
|
341 |
+
// and wrap them in braces.
|
342 |
+
|
343 |
+
v = partial.length === 0 ? '{}' :
|
344 |
+
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
345 |
+
mind + '}' : '{' + partial.join(',') + '}';
|
346 |
+
gap = mind;
|
347 |
+
return v;
|
348 |
+
}
|
349 |
+
}
|
350 |
+
|
351 |
+
// If the JSON object does not yet have a stringify method, give it one.
|
352 |
+
|
353 |
+
if (typeof JSON.stringify !== 'function') {
|
354 |
+
JSON.stringify = function (value, replacer, space) {
|
355 |
+
|
356 |
+
// The stringify method takes a value and an optional replacer, and an optional
|
357 |
+
// space parameter, and returns a JSON text. The replacer can be a function
|
358 |
+
// that can replace values, or an array of strings that will select the keys.
|
359 |
+
// A default replacer method can be provided. Use of the space parameter can
|
360 |
+
// produce text that is more easily readable.
|
361 |
+
|
362 |
+
var i;
|
363 |
+
gap = '';
|
364 |
+
indent = '';
|
365 |
+
|
366 |
+
// If the space parameter is a number, make an indent string containing that
|
367 |
+
// many spaces.
|
368 |
+
|
369 |
+
if (typeof space === 'number') {
|
370 |
+
for (i = 0; i < space; i += 1) {
|
371 |
+
indent += ' ';
|
372 |
+
}
|
373 |
+
|
374 |
+
// If the space parameter is a string, it will be used as the indent string.
|
375 |
+
|
376 |
+
} else if (typeof space === 'string') {
|
377 |
+
indent = space;
|
378 |
+
}
|
379 |
+
|
380 |
+
// If there is a replacer, it must be a function or an array.
|
381 |
+
// Otherwise, throw an error.
|
382 |
+
|
383 |
+
rep = replacer;
|
384 |
+
if (replacer && typeof replacer !== 'function' &&
|
385 |
+
(typeof replacer !== 'object' ||
|
386 |
+
typeof replacer.length !== 'number')) {
|
387 |
+
throw new Error('JSON.stringify');
|
388 |
+
}
|
389 |
+
|
390 |
+
// Make a fake root object containing our value under the key of ''.
|
391 |
+
// Return the result of stringifying the value.
|
392 |
+
|
393 |
+
return str('', {'': value});
|
394 |
+
};
|
395 |
+
}
|
396 |
+
|
397 |
+
|
398 |
+
// If the JSON object does not yet have a parse method, give it one.
|
399 |
+
|
400 |
+
if (typeof JSON.parseIt !== 'function') {
|
401 |
+
JSON.parseIt = function (text, reviver) {
|
402 |
+
|
403 |
+
// The parse method takes a text and an optional reviver function, and returns
|
404 |
+
// a JavaScript value if the text is a valid JSON text.
|
405 |
+
|
406 |
+
var j;
|
407 |
+
|
408 |
+
function walk(holder, key) {
|
409 |
+
|
410 |
+
// The walk method is used to recursively walk the resulting structure so
|
411 |
+
// that modifications can be made.
|
412 |
+
|
413 |
+
var k, v, value = holder[key];
|
414 |
+
if (value && typeof value === 'object') {
|
415 |
+
for (k in value) {
|
416 |
+
if (Object.hasOwnProperty.call(value, k)) {
|
417 |
+
v = walk(value, k);
|
418 |
+
if (v !== undefined) {
|
419 |
+
value[k] = v;
|
420 |
+
} else {
|
421 |
+
delete value[k];
|
422 |
+
}
|
423 |
+
}
|
424 |
+
}
|
425 |
+
}
|
426 |
+
return reviver.call(holder, key, value);
|
427 |
+
}
|
428 |
+
|
429 |
+
|
430 |
+
// Parsing happens in four stages. In the first stage, we replace certain
|
431 |
+
// Unicode characters with escape sequences. JavaScript handles many characters
|
432 |
+
// incorrectly, either silently deleting them, or treating them as line endings.
|
433 |
+
|
434 |
+
cx.lastIndex = 0;
|
435 |
+
if (cx.test(text)) {
|
436 |
+
text = text.replace(cx, function (a) {
|
437 |
+
return '\\u' +
|
438 |
+
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
439 |
+
});
|
440 |
+
}
|
441 |
+
|
442 |
+
// In the second stage, we run the text against regular expressions that look
|
443 |
+
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
444 |
+
// because they can cause invocation, and '=' because it can cause mutation.
|
445 |
+
// But just to be safe, we want to reject all unexpected forms.
|
446 |
+
|
447 |
+
// We split the second stage into 4 regexp operations in order to work around
|
448 |
+
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
449 |
+
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
450 |
+
// replace all simple value tokens with ']' characters. Third, we delete all
|
451 |
+
// open brackets that follow a colon or comma or that begin the text. Finally,
|
452 |
+
// we look to see that the remaining characters are only whitespace or ']' or
|
453 |
+
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
454 |
+
|
455 |
+
if (/^[\],:{}\s]*$/.
|
456 |
+
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
457 |
+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
458 |
+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
459 |
+
|
460 |
+
// In the third stage we use the eval function to compile the text into a
|
461 |
+
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
462 |
+
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
463 |
+
// in parens to eliminate the ambiguity.
|
464 |
+
|
465 |
+
j = eval('(' + text + ')');
|
466 |
+
|
467 |
+
// In the optional fourth stage, we recursively walk the new structure, passing
|
468 |
+
// each name/value pair to a reviver function for possible transformation.
|
469 |
+
|
470 |
+
return typeof reviver === 'function' ?
|
471 |
+
walk({'': j}, '') : j;
|
472 |
+
}
|
473 |
+
|
474 |
+
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
475 |
+
|
476 |
+
throw new SyntaxError('JSON.parseIt');
|
477 |
+
};
|
478 |
+
}
|
479 |
+
}());
|
480 |
+
|
lib/tools.scrollable-1.1.2.js
ADDED
@@ -0,0 +1,439 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* tools.scrollable 1.1.2 - Scroll your HTML with eye candy.
|
3 |
+
*
|
4 |
+
* Copyright (c) 2009 Tero Piirainen
|
5 |
+
* http://flowplayer.org/tools/scrollable.html
|
6 |
+
*
|
7 |
+
* Dual licensed under MIT and GPL 2+ licenses
|
8 |
+
* http://www.opensource.org/licenses
|
9 |
+
*
|
10 |
+
* Launch : March 2008
|
11 |
+
* Date: jQuery{date}
|
12 |
+
* Revision: jQuery{revision}
|
13 |
+
*/
|
14 |
+
(function(jQuery) {
|
15 |
+
|
16 |
+
// static constructs
|
17 |
+
jQuery.tools = jQuery.tools || {};
|
18 |
+
|
19 |
+
jQuery.tools.scrollable = {
|
20 |
+
version: '1.1.2',
|
21 |
+
|
22 |
+
conf: {
|
23 |
+
|
24 |
+
// basics
|
25 |
+
size: 5,
|
26 |
+
vertical: false,
|
27 |
+
speed: 400,
|
28 |
+
keyboard: true,
|
29 |
+
|
30 |
+
// by default this is the same as size
|
31 |
+
keyboardSteps: null,
|
32 |
+
|
33 |
+
// other
|
34 |
+
disabledClass: 'disabled',
|
35 |
+
hoverClass: null,
|
36 |
+
clickable: true,
|
37 |
+
activeClass: 'active',
|
38 |
+
easing: 'swing',
|
39 |
+
loop: false,
|
40 |
+
|
41 |
+
items: '.items',
|
42 |
+
item: null,
|
43 |
+
|
44 |
+
// navigational elements
|
45 |
+
prev: '.prev',
|
46 |
+
next: '.next',
|
47 |
+
prevPage: '.prevPage',
|
48 |
+
nextPage: '.nextPage',
|
49 |
+
api: false
|
50 |
+
|
51 |
+
// CALLBACKS: onBeforeSeek, onSeek, onReload
|
52 |
+
}
|
53 |
+
};
|
54 |
+
|
55 |
+
var current;
|
56 |
+
|
57 |
+
// constructor
|
58 |
+
function Scrollable(root, conf) {
|
59 |
+
|
60 |
+
// current instance
|
61 |
+
var self = this, jQueryself = jQuery(this),
|
62 |
+
horizontal = !conf.vertical,
|
63 |
+
wrap = root.children(),
|
64 |
+
index = 0,
|
65 |
+
forward;
|
66 |
+
|
67 |
+
|
68 |
+
if (!current) { current = self; }
|
69 |
+
|
70 |
+
// bind all callbacks from configuration
|
71 |
+
jQuery.each(conf, function(name, fn) {
|
72 |
+
if (jQuery.isFunction(fn)) { jQueryself.bind(name, fn); }
|
73 |
+
});
|
74 |
+
|
75 |
+
if (wrap.length > 1) { wrap = jQuery(conf.items, root); }
|
76 |
+
|
77 |
+
// navigational items can be anywhere when globalNav = true
|
78 |
+
function find(query) {
|
79 |
+
var els = jQuery(query);
|
80 |
+
return conf.globalNav ? els : root.parent().find(query);
|
81 |
+
}
|
82 |
+
|
83 |
+
// to be used by plugins
|
84 |
+
root.data("finder", find);
|
85 |
+
|
86 |
+
// get handle to navigational elements
|
87 |
+
var prev = find(conf.prev),
|
88 |
+
next = find(conf.next),
|
89 |
+
prevPage = find(conf.prevPage),
|
90 |
+
nextPage = find(conf.nextPage);
|
91 |
+
|
92 |
+
|
93 |
+
// methods
|
94 |
+
jQuery.extend(self, {
|
95 |
+
|
96 |
+
getIndex: function() {
|
97 |
+
return index;
|
98 |
+
},
|
99 |
+
|
100 |
+
getClickIndex: function() {
|
101 |
+
var items = self.getItems();
|
102 |
+
return items.index(items.filter("." + conf.activeClass));
|
103 |
+
},
|
104 |
+
|
105 |
+
getConf: function() {
|
106 |
+
return conf;
|
107 |
+
},
|
108 |
+
|
109 |
+
getSize: function() {
|
110 |
+
return self.getItems().size();
|
111 |
+
},
|
112 |
+
|
113 |
+
getPageAmount: function() {
|
114 |
+
return Math.ceil(this.getSize() / conf.size);
|
115 |
+
},
|
116 |
+
|
117 |
+
getPageIndex: function() {
|
118 |
+
return Math.ceil(index / conf.size);
|
119 |
+
},
|
120 |
+
|
121 |
+
getNaviButtons: function() {
|
122 |
+
return prev.add(next).add(prevPage).add(nextPage);
|
123 |
+
},
|
124 |
+
|
125 |
+
getRoot: function() {
|
126 |
+
return root;
|
127 |
+
},
|
128 |
+
|
129 |
+
getItemWrap: function() {
|
130 |
+
return wrap;
|
131 |
+
},
|
132 |
+
|
133 |
+
getItems: function() {
|
134 |
+
return wrap.children(conf.item);
|
135 |
+
},
|
136 |
+
|
137 |
+
getVisibleItems: function() {
|
138 |
+
return self.getItems().slice(index, index + conf.size);
|
139 |
+
},
|
140 |
+
|
141 |
+
/* all seeking functions depend on this */
|
142 |
+
seekTo: function(i, time, fn) {
|
143 |
+
|
144 |
+
if (i < 0) { i = 0; }
|
145 |
+
|
146 |
+
// nothing happens
|
147 |
+
if (index === i) { return self; }
|
148 |
+
|
149 |
+
// function given as second argument
|
150 |
+
if (jQuery.isFunction(time)) {
|
151 |
+
fn = time;
|
152 |
+
}
|
153 |
+
|
154 |
+
// seeking exceeds the end
|
155 |
+
if (i > self.getSize() - conf.size) {
|
156 |
+
return conf.loop ? self.begin() : this.end();
|
157 |
+
}
|
158 |
+
|
159 |
+
var item = self.getItems().eq(i);
|
160 |
+
if (!item.length) { return self; }
|
161 |
+
|
162 |
+
// onBeforeSeek
|
163 |
+
var e = jQuery.Event("onBeforeSeek");
|
164 |
+
|
165 |
+
jQueryself.trigger(e, i > index);
|
166 |
+
if (e.isDefaultPrevented()) { return self; }
|
167 |
+
|
168 |
+
// get the (possibly altered) speed
|
169 |
+
if (time === undefined || jQuery.isFunction(time)) { time = conf.speed; }
|
170 |
+
|
171 |
+
function callback() {
|
172 |
+
if (fn) { fn.call(self, i); }
|
173 |
+
jQueryself.trigger("onSeek", [i]);
|
174 |
+
}
|
175 |
+
|
176 |
+
if (horizontal) {
|
177 |
+
wrap.animate({left: -item.position().left}, time, conf.easing, callback);
|
178 |
+
} else {
|
179 |
+
wrap.animate({top: -item.position().top}, time, conf.easing, callback);
|
180 |
+
}
|
181 |
+
|
182 |
+
|
183 |
+
current = self;
|
184 |
+
index = i;
|
185 |
+
|
186 |
+
// onStart
|
187 |
+
e = jQuery.Event("onStart");
|
188 |
+
jQueryself.trigger(e, [i]);
|
189 |
+
if (e.isDefaultPrevented()) { return self; }
|
190 |
+
|
191 |
+
|
192 |
+
/* default behaviour */
|
193 |
+
|
194 |
+
// prev/next buttons disabled flags
|
195 |
+
prev.add(prevPage).toggleClass(conf.disabledClass, i === 0);
|
196 |
+
next.add(nextPage).toggleClass(conf.disabledClass, i >= self.getSize() - conf.size);
|
197 |
+
|
198 |
+
return self;
|
199 |
+
},
|
200 |
+
|
201 |
+
|
202 |
+
move: function(offset, time, fn) {
|
203 |
+
forward = offset > 0;
|
204 |
+
return this.seekTo(index + offset, time, fn);
|
205 |
+
},
|
206 |
+
|
207 |
+
next: function(time, fn) {
|
208 |
+
return this.move(1, time, fn);
|
209 |
+
},
|
210 |
+
|
211 |
+
prev: function(time, fn) {
|
212 |
+
return this.move(-1, time, fn);
|
213 |
+
},
|
214 |
+
|
215 |
+
movePage: function(offset, time, fn) {
|
216 |
+
forward = offset > 0;
|
217 |
+
var steps = conf.size * offset;
|
218 |
+
|
219 |
+
var i = index % conf.size;
|
220 |
+
if (i > 0) {
|
221 |
+
steps += (offset > 0 ? -i : conf.size - i);
|
222 |
+
}
|
223 |
+
|
224 |
+
return this.move(steps, time, fn);
|
225 |
+
},
|
226 |
+
|
227 |
+
prevPage: function(time, fn) {
|
228 |
+
return this.movePage(-1, time, fn);
|
229 |
+
},
|
230 |
+
|
231 |
+
nextPage: function(time, fn) {
|
232 |
+
return this.movePage(1, time, fn);
|
233 |
+
},
|
234 |
+
|
235 |
+
setPage: function(page, time, fn) {
|
236 |
+
return this.seekTo(page * conf.size, time, fn);
|
237 |
+
},
|
238 |
+
|
239 |
+
begin: function(time, fn) {
|
240 |
+
forward = false;
|
241 |
+
return this.seekTo(0, time, fn);
|
242 |
+
},
|
243 |
+
|
244 |
+
end: function(time, fn) {
|
245 |
+
forward = true;
|
246 |
+
var to = this.getSize() - conf.size;
|
247 |
+
return to > 0 ? this.seekTo(to, time, fn) : self;
|
248 |
+
},
|
249 |
+
|
250 |
+
reload: function() {
|
251 |
+
jQueryself.trigger("onReload");
|
252 |
+
return self;
|
253 |
+
},
|
254 |
+
|
255 |
+
focus: function() {
|
256 |
+
current = self;
|
257 |
+
return self;
|
258 |
+
},
|
259 |
+
|
260 |
+
click: function(i) {
|
261 |
+
|
262 |
+
var item = self.getItems().eq(i),
|
263 |
+
klass = conf.activeClass,
|
264 |
+
size = conf.size;
|
265 |
+
|
266 |
+
// check that i is sane
|
267 |
+
if (i < 0 || i >= self.getSize()) { return self; }
|
268 |
+
|
269 |
+
// size == 1
|
270 |
+
if (size == 1) {
|
271 |
+
if (conf.loop) { return self.next(); }
|
272 |
+
|
273 |
+
if (i === 0 || i == self.getSize() -1) {
|
274 |
+
forward = (forward === undefined) ? true : !forward;
|
275 |
+
}
|
276 |
+
return forward === false ? self.prev() : self.next();
|
277 |
+
}
|
278 |
+
|
279 |
+
// size == 2
|
280 |
+
if (size == 2) {
|
281 |
+
if (i == index) { i--; }
|
282 |
+
self.getItems().removeClass(klass);
|
283 |
+
item.addClass(klass);
|
284 |
+
return self.seekTo(i, time, fn);
|
285 |
+
}
|
286 |
+
|
287 |
+
if (!item.hasClass(klass)) {
|
288 |
+
self.getItems().removeClass(klass);
|
289 |
+
item.addClass(klass);
|
290 |
+
var delta = Math.floor(size / 2);
|
291 |
+
var to = i - delta;
|
292 |
+
|
293 |
+
// next to last item must work
|
294 |
+
if (to > self.getSize() - size) {
|
295 |
+
to = self.getSize() - size;
|
296 |
+
}
|
297 |
+
|
298 |
+
if (to !== i) {
|
299 |
+
return self.seekTo(to);
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
return self;
|
304 |
+
},
|
305 |
+
|
306 |
+
// bind / unbind
|
307 |
+
bind: function(name, fn) {
|
308 |
+
jQueryself.bind(name, fn);
|
309 |
+
return self;
|
310 |
+
},
|
311 |
+
|
312 |
+
unbind: function(name) {
|
313 |
+
jQueryself.unbind(name);
|
314 |
+
return self;
|
315 |
+
}
|
316 |
+
|
317 |
+
});
|
318 |
+
|
319 |
+
// callbacks
|
320 |
+
jQuery.each("onBeforeSeek,onStart,onSeek,onReload".split(","), function(i, ev) {
|
321 |
+
self[ev] = function(fn) {
|
322 |
+
return self.bind(ev, fn);
|
323 |
+
};
|
324 |
+
});
|
325 |
+
|
326 |
+
|
327 |
+
// prev button
|
328 |
+
prev.addClass(conf.disabledClass).click(function() {
|
329 |
+
self.prev();
|
330 |
+
});
|
331 |
+
|
332 |
+
|
333 |
+
// next button
|
334 |
+
next.click(function() {
|
335 |
+
self.next();
|
336 |
+
});
|
337 |
+
|
338 |
+
// prev page button
|
339 |
+
nextPage.click(function() {
|
340 |
+
self.nextPage();
|
341 |
+
});
|
342 |
+
|
343 |
+
if (self.getSize() < conf.size) {
|
344 |
+
next.add(nextPage).addClass(conf.disabledClass);
|
345 |
+
}
|
346 |
+
|
347 |
+
|
348 |
+
// next page button
|
349 |
+
prevPage.addClass(conf.disabledClass).click(function() {
|
350 |
+
self.prevPage();
|
351 |
+
});
|
352 |
+
|
353 |
+
|
354 |
+
// hover
|
355 |
+
var hc = conf.hoverClass, keyId = "keydown." + Math.random().toString().substring(10);
|
356 |
+
|
357 |
+
self.onReload(function() {
|
358 |
+
|
359 |
+
// hovering
|
360 |
+
if (hc) {
|
361 |
+
self.getItems().hover(function() {
|
362 |
+
jQuery(this).addClass(hc);
|
363 |
+
}, function() {
|
364 |
+
jQuery(this).removeClass(hc);
|
365 |
+
});
|
366 |
+
}
|
367 |
+
|
368 |
+
// clickable
|
369 |
+
if (conf.clickable) {
|
370 |
+
self.getItems().each(function(i) {
|
371 |
+
jQuery(this).unbind("click.scrollable").bind("click.scrollable", function(e) {
|
372 |
+
if (jQuery(e.target).is("a")) { return; }
|
373 |
+
return self.click(i);
|
374 |
+
});
|
375 |
+
});
|
376 |
+
}
|
377 |
+
|
378 |
+
// keyboard
|
379 |
+
if (conf.keyboard) {
|
380 |
+
|
381 |
+
// keyboard works on one instance at the time. thus we need to unbind first
|
382 |
+
jQuery(document).unbind(keyId).bind(keyId, function(evt) {
|
383 |
+
|
384 |
+
// do nothing with CTRL / ALT buttons
|
385 |
+
if (evt.altKey || evt.ctrlKey) { return; }
|
386 |
+
|
387 |
+
// do nothing for unstatic and unfocused instances
|
388 |
+
if (conf.keyboard != 'static' && current != self) { return; }
|
389 |
+
|
390 |
+
var s = conf.keyboardSteps;
|
391 |
+
|
392 |
+
if (horizontal && (evt.keyCode == 37 || evt.keyCode == 39)) {
|
393 |
+
self.move(evt.keyCode == 37 ? -s : s);
|
394 |
+
return evt.preventDefault();
|
395 |
+
}
|
396 |
+
|
397 |
+
if (!horizontal && (evt.keyCode == 38 || evt.keyCode == 40)) {
|
398 |
+
self.move(evt.keyCode == 38 ? -s : s);
|
399 |
+
return evt.preventDefault();
|
400 |
+
}
|
401 |
+
|
402 |
+
return true;
|
403 |
+
|
404 |
+
});
|
405 |
+
|
406 |
+
} else {
|
407 |
+
jQuery(document).unbind(keyId);
|
408 |
+
}
|
409 |
+
|
410 |
+
});
|
411 |
+
|
412 |
+
self.reload();
|
413 |
+
|
414 |
+
}
|
415 |
+
|
416 |
+
|
417 |
+
// jQuery plugin implementation
|
418 |
+
jQuery.fn.scrollable = function(conf) {
|
419 |
+
|
420 |
+
// already constructed --> return API
|
421 |
+
var el = this.eq(typeof conf == 'number' ? conf : 0).data("scrollable");
|
422 |
+
if (el) { return el; }
|
423 |
+
|
424 |
+
var globals = jQuery.extend({}, jQuery.tools.scrollable.conf);
|
425 |
+
conf = jQuery.extend(globals, conf);
|
426 |
+
|
427 |
+
conf.keyboardSteps = conf.keyboardSteps || conf.size;
|
428 |
+
|
429 |
+
this.each(function() {
|
430 |
+
el = new Scrollable(jQuery(this), conf);
|
431 |
+
jQuery(this).data("scrollable", el);
|
432 |
+
});
|
433 |
+
|
434 |
+
return conf.api ? el: this;
|
435 |
+
|
436 |
+
};
|
437 |
+
|
438 |
+
|
439 |
+
})(jQuery);
|
lib/tools.scrollable.mousewheel-1.0.1.js
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* jQuery TOOLS plugin :: scrollable.mousewheel 1.0.1
|
3 |
+
*
|
4 |
+
* Copyright (c) 2009 Tero Piirainen
|
5 |
+
* http://flowplayer.org/tools/scrollable.html#mousewheel
|
6 |
+
*
|
7 |
+
* Dual licensed under MIT and GPL 2+ licenses
|
8 |
+
* http://www.opensource.org/licenses
|
9 |
+
*
|
10 |
+
* Launch : September 2009
|
11 |
+
* Date: jQuery{date}
|
12 |
+
* Revision: jQuery{revision}
|
13 |
+
*
|
14 |
+
*
|
15 |
+
* jquery.event.wheel.js - rev 1
|
16 |
+
* Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
|
17 |
+
* Liscensed under the MIT License (MIT-LICENSE.txt)
|
18 |
+
* http://www.opensource.org/licenses/mit-license.php
|
19 |
+
* Created: 2008-07-01 | Updated: 2008-07-14
|
20 |
+
*/
|
21 |
+
(function(jQuery) {
|
22 |
+
|
23 |
+
jQuery.fn.wheel = function( fn ){
|
24 |
+
return this[ fn ? "bind" : "trigger" ]( "wheel", fn );
|
25 |
+
};
|
26 |
+
|
27 |
+
// special event config
|
28 |
+
jQuery.event.special.wheel = {
|
29 |
+
setup: function(){
|
30 |
+
jQuery.event.add( this, wheelEvents, wheelHandler, {} );
|
31 |
+
},
|
32 |
+
teardown: function(){
|
33 |
+
jQuery.event.remove( this, wheelEvents, wheelHandler );
|
34 |
+
}
|
35 |
+
};
|
36 |
+
|
37 |
+
// events to bind ( browser sniffed... )
|
38 |
+
var wheelEvents = !jQuery.browser.mozilla ? "mousewheel" : // IE, opera, safari
|
39 |
+
"DOMMouseScroll"+( jQuery.browser.version<"1.9" ? " mousemove" : "" ); // firefox
|
40 |
+
|
41 |
+
// shared event handler
|
42 |
+
function wheelHandler( event ) {
|
43 |
+
|
44 |
+
switch ( event.type ){
|
45 |
+
|
46 |
+
// FF2 has incorrect event positions
|
47 |
+
case "mousemove":
|
48 |
+
return jQuery.extend( event.data, { // store the correct properties
|
49 |
+
clientX: event.clientX, clientY: event.clientY,
|
50 |
+
pageX: event.pageX, pageY: event.pageY
|
51 |
+
});
|
52 |
+
|
53 |
+
// firefox
|
54 |
+
case "DOMMouseScroll":
|
55 |
+
jQuery.extend( event, event.data ); // fix event properties in FF2
|
56 |
+
event.delta = -event.detail / 3; // normalize delta
|
57 |
+
break;
|
58 |
+
|
59 |
+
// IE, opera, safari
|
60 |
+
case "mousewheel":
|
61 |
+
event.delta = event.wheelDelta / 120;
|
62 |
+
break;
|
63 |
+
}
|
64 |
+
|
65 |
+
event.type = "wheel"; // hijack the event
|
66 |
+
return jQuery.event.handle.call( this, event, event.delta );
|
67 |
+
}
|
68 |
+
|
69 |
+
|
70 |
+
// version number
|
71 |
+
var t = jQuery.tools.scrollable;
|
72 |
+
t.plugins = t.plugins || {};
|
73 |
+
t.plugins.mousewheel = {
|
74 |
+
version: '1.0.1',
|
75 |
+
conf: {
|
76 |
+
api: false,
|
77 |
+
speed: 50
|
78 |
+
}
|
79 |
+
};
|
80 |
+
|
81 |
+
// scrollable mousewheel implementation
|
82 |
+
jQuery.fn.mousewheel = function(conf) {
|
83 |
+
|
84 |
+
var globals = jQuery.extend({}, t.plugins.mousewheel.conf), ret;
|
85 |
+
if (typeof conf == 'number') { conf = {speed: conf}; }
|
86 |
+
conf = jQuery.extend(globals, conf);
|
87 |
+
|
88 |
+
this.each(function() {
|
89 |
+
|
90 |
+
var api = jQuery(this).scrollable();
|
91 |
+
if (api) { ret = api; }
|
92 |
+
|
93 |
+
api.getRoot().wheel(function(e, delta) {
|
94 |
+
api.move(delta < 0 ? 1 : -1, conf.speed || 50);
|
95 |
+
return false;
|
96 |
+
});
|
97 |
+
});
|
98 |
+
|
99 |
+
return conf.api ? ret : this;
|
100 |
+
};
|
101 |
+
|
102 |
+
})(jQuery);
|
103 |
+
|
lib/ui.core.js
ADDED
@@ -0,0 +1,519 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery UI 1.7.2
|
3 |
+
*
|
4 |
+
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
5 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
6 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
7 |
+
*
|
8 |
+
* http://docs.jquery.com/UI
|
9 |
+
*/
|
10 |
+
;jQuery.ui || (function(jQuery) {
|
11 |
+
|
12 |
+
var _remove = jQuery.fn.remove,
|
13 |
+
isFF2 = jQuery.browser.mozilla && (parseFloat(jQuery.browser.version) < 1.9);
|
14 |
+
|
15 |
+
//Helper functions and ui object
|
16 |
+
jQuery.ui = {
|
17 |
+
version: "1.7.2",
|
18 |
+
|
19 |
+
// jQuery.ui.plugin is deprecated. Use the proxy pattern instead.
|
20 |
+
plugin: {
|
21 |
+
add: function(module, option, set) {
|
22 |
+
var proto = jQuery.ui[module].prototype;
|
23 |
+
for(var i in set) {
|
24 |
+
proto.plugins[i] = proto.plugins[i] || [];
|
25 |
+
proto.plugins[i].push([option, set[i]]);
|
26 |
+
}
|
27 |
+
},
|
28 |
+
call: function(instance, name, args) {
|
29 |
+
var set = instance.plugins[name];
|
30 |
+
if(!set || !instance.element[0].parentNode) { return; }
|
31 |
+
|
32 |
+
for (var i = 0; i < set.length; i++) {
|
33 |
+
if (instance.options[set[i][0]]) {
|
34 |
+
set[i][1].apply(instance.element, args);
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
38 |
+
},
|
39 |
+
|
40 |
+
contains: function(a, b) {
|
41 |
+
return document.compareDocumentPosition
|
42 |
+
? a.compareDocumentPosition(b) & 16
|
43 |
+
: a !== b && a.contains(b);
|
44 |
+
},
|
45 |
+
|
46 |
+
hasScroll: function(el, a) {
|
47 |
+
|
48 |
+
//If overflow is hidden, the element might have extra content, but the user wants to hide it
|
49 |
+
if (jQuery(el).css('overflow') == 'hidden') { return false; }
|
50 |
+
|
51 |
+
var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
|
52 |
+
has = false;
|
53 |
+
|
54 |
+
if (el[scroll] > 0) { return true; }
|
55 |
+
|
56 |
+
// TODO: determine which cases actually cause this to happen
|
57 |
+
// if the element doesn't have the scroll set, see if it's possible to
|
58 |
+
// set the scroll
|
59 |
+
el[scroll] = 1;
|
60 |
+
has = (el[scroll] > 0);
|
61 |
+
el[scroll] = 0;
|
62 |
+
return has;
|
63 |
+
},
|
64 |
+
|
65 |
+
isOverAxis: function(x, reference, size) {
|
66 |
+
//Determines when x coordinate is over "b" element axis
|
67 |
+
return (x > reference) && (x < (reference + size));
|
68 |
+
},
|
69 |
+
|
70 |
+
isOver: function(y, x, top, left, height, width) {
|
71 |
+
//Determines when x, y coordinates is over "b" element
|
72 |
+
return jQuery.ui.isOverAxis(y, top, height) && jQuery.ui.isOverAxis(x, left, width);
|
73 |
+
},
|
74 |
+
|
75 |
+
keyCode: {
|
76 |
+
BACKSPACE: 8,
|
77 |
+
CAPS_LOCK: 20,
|
78 |
+
COMMA: 188,
|
79 |
+
CONTROL: 17,
|
80 |
+
DELETE: 46,
|
81 |
+
DOWN: 40,
|
82 |
+
END: 35,
|
83 |
+
ENTER: 13,
|
84 |
+
ESCAPE: 27,
|
85 |
+
HOME: 36,
|
86 |
+
INSERT: 45,
|
87 |
+
LEFT: 37,
|
88 |
+
NUMPAD_ADD: 107,
|
89 |
+
NUMPAD_DECIMAL: 110,
|
90 |
+
NUMPAD_DIVIDE: 111,
|
91 |
+
NUMPAD_ENTER: 108,
|
92 |
+
NUMPAD_MULTIPLY: 106,
|
93 |
+
NUMPAD_SUBTRACT: 109,
|
94 |
+
PAGE_DOWN: 34,
|
95 |
+
PAGE_UP: 33,
|
96 |
+
PERIOD: 190,
|
97 |
+
RIGHT: 39,
|
98 |
+
SHIFT: 16,
|
99 |
+
SPACE: 32,
|
100 |
+
TAB: 9,
|
101 |
+
UP: 38
|
102 |
+
}
|
103 |
+
};
|
104 |
+
|
105 |
+
// WAI-ARIA normalization
|
106 |
+
if (isFF2) {
|
107 |
+
var attr = jQuery.attr,
|
108 |
+
removeAttr = jQuery.fn.removeAttr,
|
109 |
+
ariaNS = "http://www.w3.org/2005/07/aaa",
|
110 |
+
ariaState = /^aria-/,
|
111 |
+
ariaRole = /^wairole:/;
|
112 |
+
|
113 |
+
jQuery.attr = function(elem, name, value) {
|
114 |
+
var set = value !== undefined;
|
115 |
+
|
116 |
+
return (name == 'role'
|
117 |
+
? (set
|
118 |
+
? attr.call(this, elem, name, "wairole:" + value)
|
119 |
+
: (attr.apply(this, arguments) || "").replace(ariaRole, ""))
|
120 |
+
: (ariaState.test(name)
|
121 |
+
? (set
|
122 |
+
? elem.setAttributeNS(ariaNS,
|
123 |
+
name.replace(ariaState, "aaa:"), value)
|
124 |
+
: attr.call(this, elem, name.replace(ariaState, "aaa:")))
|
125 |
+
: attr.apply(this, arguments)));
|
126 |
+
};
|
127 |
+
|
128 |
+
jQuery.fn.removeAttr = function(name) {
|
129 |
+
return (ariaState.test(name)
|
130 |
+
? this.each(function() {
|
131 |
+
this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
|
132 |
+
}) : removeAttr.call(this, name));
|
133 |
+
};
|
134 |
+
}
|
135 |
+
|
136 |
+
//jQuery plugins
|
137 |
+
jQuery.fn.extend({
|
138 |
+
remove: function() {
|
139 |
+
// Safari has a native remove event which actually removes DOM elements,
|
140 |
+
// so we have to use triggerHandler instead of trigger (#3037).
|
141 |
+
jQuery("*", this).add(this).each(function() {
|
142 |
+
jQuery(this).triggerHandler("remove");
|
143 |
+
});
|
144 |
+
return _remove.apply(this, arguments );
|
145 |
+
},
|
146 |
+
|
147 |
+
enableSelection: function() {
|
148 |
+
return this
|
149 |
+
.attr('unselectable', 'off')
|
150 |
+
.css('MozUserSelect', '')
|
151 |
+
.unbind('selectstart.ui');
|
152 |
+
},
|
153 |
+
|
154 |
+
disableSelection: function() {
|
155 |
+
return this
|
156 |
+
.attr('unselectable', 'on')
|
157 |
+
.css('MozUserSelect', 'none')
|
158 |
+
.bind('selectstart.ui', function() { return false; });
|
159 |
+
},
|
160 |
+
|
161 |
+
scrollParent: function() {
|
162 |
+
var scrollParent;
|
163 |
+
if((jQuery.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
|
164 |
+
scrollParent = this.parents().filter(function() {
|
165 |
+
return (/(relative|absolute|fixed)/).test(jQuery.curCSS(this,'position',1)) && (/(auto|scroll)/).test(jQuery.curCSS(this,'overflow',1)+jQuery.curCSS(this,'overflow-y',1)+jQuery.curCSS(this,'overflow-x',1));
|
166 |
+
}).eq(0);
|
167 |
+
} else {
|
168 |
+
scrollParent = this.parents().filter(function() {
|
169 |
+
return (/(auto|scroll)/).test(jQuery.curCSS(this,'overflow',1)+jQuery.curCSS(this,'overflow-y',1)+jQuery.curCSS(this,'overflow-x',1));
|
170 |
+
}).eq(0);
|
171 |
+
}
|
172 |
+
|
173 |
+
return (/fixed/).test(this.css('position')) || !scrollParent.length ? jQuery(document) : scrollParent;
|
174 |
+
}
|
175 |
+
});
|
176 |
+
|
177 |
+
|
178 |
+
//Additional selectors
|
179 |
+
jQuery.extend(jQuery.expr[':'], {
|
180 |
+
data: function(elem, i, match) {
|
181 |
+
return !!jQuery.data(elem, match[3]);
|
182 |
+
},
|
183 |
+
|
184 |
+
focusable: function(element) {
|
185 |
+
var nodeName = element.nodeName.toLowerCase(),
|
186 |
+
tabIndex = jQuery.attr(element, 'tabindex');
|
187 |
+
return (/input|select|textarea|button|object/.test(nodeName)
|
188 |
+
? !element.disabled
|
189 |
+
: 'a' == nodeName || 'area' == nodeName
|
190 |
+
? element.href || !isNaN(tabIndex)
|
191 |
+
: !isNaN(tabIndex))
|
192 |
+
// the element and all of its ancestors must be visible
|
193 |
+
// the browser may report that the area is hidden
|
194 |
+
&& !jQuery(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
|
195 |
+
},
|
196 |
+
|
197 |
+
tabbable: function(element) {
|
198 |
+
var tabIndex = jQuery.attr(element, 'tabindex');
|
199 |
+
return (isNaN(tabIndex) || tabIndex >= 0) && jQuery(element).is(':focusable');
|
200 |
+
}
|
201 |
+
});
|
202 |
+
|
203 |
+
|
204 |
+
// jQuery.widget is a factory to create jQuery plugins
|
205 |
+
// taking some boilerplate code out of the plugin code
|
206 |
+
function getter(namespace, plugin, method, args) {
|
207 |
+
function getMethods(type) {
|
208 |
+
var methods = jQuery[namespace][plugin][type] || [];
|
209 |
+
return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
|
210 |
+
}
|
211 |
+
|
212 |
+
var methods = getMethods('getter');
|
213 |
+
if (args.length == 1 && typeof args[0] == 'string') {
|
214 |
+
methods = methods.concat(getMethods('getterSetter'));
|
215 |
+
}
|
216 |
+
return (jQuery.inArray(method, methods) != -1);
|
217 |
+
}
|
218 |
+
|
219 |
+
jQuery.widget = function(name, prototype) {
|
220 |
+
var namespace = name.split(".")[0];
|
221 |
+
name = name.split(".")[1];
|
222 |
+
|
223 |
+
// create plugin method
|
224 |
+
jQuery.fn[name] = function(options) {
|
225 |
+
var isMethodCall = (typeof options == 'string'),
|
226 |
+
args = Array.prototype.slice.call(arguments, 1);
|
227 |
+
|
228 |
+
// prevent calls to internal methods
|
229 |
+
if (isMethodCall && options.substring(0, 1) == '_') {
|
230 |
+
return this;
|
231 |
+
}
|
232 |
+
|
233 |
+
// handle getter methods
|
234 |
+
if (isMethodCall && getter(namespace, name, options, args)) {
|
235 |
+
var instance = jQuery.data(this[0], name);
|
236 |
+
return (instance ? instance[options].apply(instance, args)
|
237 |
+
: undefined);
|
238 |
+
}
|
239 |
+
|
240 |
+
// handle initialization and non-getter methods
|
241 |
+
return this.each(function() {
|
242 |
+
var instance = jQuery.data(this, name);
|
243 |
+
|
244 |
+
// constructor
|
245 |
+
(!instance && !isMethodCall &&
|
246 |
+
jQuery.data(this, name, new jQuery[namespace][name](this, options))._init());
|
247 |
+
|
248 |
+
// method call
|
249 |
+
(instance && isMethodCall && jQuery.isFunction(instance[options]) &&
|
250 |
+
instance[options].apply(instance, args));
|
251 |
+
});
|
252 |
+
};
|
253 |
+
|
254 |
+
// create widget constructor
|
255 |
+
jQuery[namespace] = jQuery[namespace] || {};
|
256 |
+
jQuery[namespace][name] = function(element, options) {
|
257 |
+
var self = this;
|
258 |
+
|
259 |
+
this.namespace = namespace;
|
260 |
+
this.widgetName = name;
|
261 |
+
this.widgetEventPrefix = jQuery[namespace][name].eventPrefix || name;
|
262 |
+
this.widgetBaseClass = namespace + '-' + name;
|
263 |
+
|
264 |
+
this.options = jQuery.extend({},
|
265 |
+
jQuery.widget.defaults,
|
266 |
+
jQuery[namespace][name].defaults,
|
267 |
+
jQuery.metadata && jQuery.metadata.get(element)[name],
|
268 |
+
options);
|
269 |
+
|
270 |
+
this.element = jQuery(element)
|
271 |
+
.bind('setData.' + name, function(event, key, value) {
|
272 |
+
if (event.target == element) {
|
273 |
+
return self._setData(key, value);
|
274 |
+
}
|
275 |
+
})
|
276 |
+
.bind('getData.' + name, function(event, key) {
|
277 |
+
if (event.target == element) {
|
278 |
+
return self._getData(key);
|
279 |
+
}
|
280 |
+
})
|
281 |
+
.bind('remove', function() {
|
282 |
+
return self.destroy();
|
283 |
+
});
|
284 |
+
};
|
285 |
+
|
286 |
+
// add widget prototype
|
287 |
+
jQuery[namespace][name].prototype = jQuery.extend({}, jQuery.widget.prototype, prototype);
|
288 |
+
|
289 |
+
// TODO: merge getter and getterSetter properties from widget prototype
|
290 |
+
// and plugin prototype
|
291 |
+
jQuery[namespace][name].getterSetter = 'option';
|
292 |
+
};
|
293 |
+
|
294 |
+
jQuery.widget.prototype = {
|
295 |
+
_init: function() {},
|
296 |
+
destroy: function() {
|
297 |
+
this.element.removeData(this.widgetName)
|
298 |
+
.removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
|
299 |
+
.removeAttr('aria-disabled');
|
300 |
+
},
|
301 |
+
|
302 |
+
option: function(key, value) {
|
303 |
+
var options = key,
|
304 |
+
self = this;
|
305 |
+
|
306 |
+
if (typeof key == "string") {
|
307 |
+
if (value === undefined) {
|
308 |
+
return this._getData(key);
|
309 |
+
}
|
310 |
+
options = {};
|
311 |
+
options[key] = value;
|
312 |
+
}
|
313 |
+
|
314 |
+
jQuery.each(options, function(key, value) {
|
315 |
+
self._setData(key, value);
|
316 |
+
});
|
317 |
+
},
|
318 |
+
_getData: function(key) {
|
319 |
+
return this.options[key];
|
320 |
+
},
|
321 |
+
_setData: function(key, value) {
|
322 |
+
this.options[key] = value;
|
323 |
+
|
324 |
+
if (key == 'disabled') {
|
325 |
+
this.element
|
326 |
+
[value ? 'addClass' : 'removeClass'](
|
327 |
+
this.widgetBaseClass + '-disabled' + ' ' +
|
328 |
+
this.namespace + '-state-disabled')
|
329 |
+
.attr("aria-disabled", value);
|
330 |
+
}
|
331 |
+
},
|
332 |
+
|
333 |
+
enable: function() {
|
334 |
+
this._setData('disabled', false);
|
335 |
+
},
|
336 |
+
disable: function() {
|
337 |
+
this._setData('disabled', true);
|
338 |
+
},
|
339 |
+
|
340 |
+
_trigger: function(type, event, data) {
|
341 |
+
var callback = this.options[type],
|
342 |
+
eventName = (type == this.widgetEventPrefix
|
343 |
+
? type : this.widgetEventPrefix + type);
|
344 |
+
|
345 |
+
event = jQuery.Event(event);
|
346 |
+
event.type = eventName;
|
347 |
+
|
348 |
+
// copy original event properties over to the new event
|
349 |
+
// this would happen if we could call jQuery.event.fix instead of jQuery.Event
|
350 |
+
// but we don't have a way to force an event to be fixed multiple times
|
351 |
+
if (event.originalEvent) {
|
352 |
+
for (var i = jQuery.event.props.length, prop; i;) {
|
353 |
+
prop = jQuery.event.props[--i];
|
354 |
+
event[prop] = event.originalEvent[prop];
|
355 |
+
}
|
356 |
+
}
|
357 |
+
|
358 |
+
this.element.trigger(event, data);
|
359 |
+
|
360 |
+
return !(jQuery.isFunction(callback) && callback.call(this.element[0], event, data) === false
|
361 |
+
|| event.isDefaultPrevented());
|
362 |
+
}
|
363 |
+
};
|
364 |
+
|
365 |
+
jQuery.widget.defaults = {
|
366 |
+
disabled: false
|
367 |
+
};
|
368 |
+
|
369 |
+
|
370 |
+
/** Mouse Interaction Plugin **/
|
371 |
+
|
372 |
+
jQuery.ui.mouse = {
|
373 |
+
_mouseInit: function() {
|
374 |
+
var self = this;
|
375 |
+
|
376 |
+
this.element
|
377 |
+
.bind('mousedown.'+this.widgetName, function(event) {
|
378 |
+
return self._mouseDown(event);
|
379 |
+
})
|
380 |
+
.bind('click.'+this.widgetName, function(event) {
|
381 |
+
if(self._preventClickEvent) {
|
382 |
+
self._preventClickEvent = false;
|
383 |
+
event.stopImmediatePropagation();
|
384 |
+
return false;
|
385 |
+
}
|
386 |
+
});
|
387 |
+
|
388 |
+
// Prevent text selection in IE
|
389 |
+
if (jQuery.browser.msie) {
|
390 |
+
this._mouseUnselectable = this.element.attr('unselectable');
|
391 |
+
this.element.attr('unselectable', 'on');
|
392 |
+
}
|
393 |
+
|
394 |
+
this.started = false;
|
395 |
+
},
|
396 |
+
|
397 |
+
// TODO: make sure destroying one instance of mouse doesn't mess with
|
398 |
+
// other instances of mouse
|
399 |
+
_mouseDestroy: function() {
|
400 |
+
this.element.unbind('.'+this.widgetName);
|
401 |
+
|
402 |
+
// Restore text selection in IE
|
403 |
+
(jQuery.browser.msie
|
404 |
+
&& this.element.attr('unselectable', this._mouseUnselectable));
|
405 |
+
},
|
406 |
+
|
407 |
+
_mouseDown: function(event) {
|
408 |
+
// don't let more than one widget handle mouseStart
|
409 |
+
// TODO: figure out why we have to use originalEvent
|
410 |
+
event.originalEvent = event.originalEvent || {};
|
411 |
+
if (event.originalEvent.mouseHandled) { return; }
|
412 |
+
|
413 |
+
// we may have missed mouseup (out of window)
|
414 |
+
(this._mouseStarted && this._mouseUp(event));
|
415 |
+
|
416 |
+
this._mouseDownEvent = event;
|
417 |
+
|
418 |
+
var self = this,
|
419 |
+
btnIsLeft = (event.which == 1),
|
420 |
+
elIsCancel = (typeof this.options.cancel == "string" ? jQuery(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
|
421 |
+
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
|
422 |
+
return true;
|
423 |
+
}
|
424 |
+
|
425 |
+
this.mouseDelayMet = !this.options.delay;
|
426 |
+
if (!this.mouseDelayMet) {
|
427 |
+
this._mouseDelayTimer = setTimeout(function() {
|
428 |
+
self.mouseDelayMet = true;
|
429 |
+
}, this.options.delay);
|
430 |
+
}
|
431 |
+
|
432 |
+
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
|
433 |
+
this._mouseStarted = (this._mouseStart(event) !== false);
|
434 |
+
if (!this._mouseStarted) {
|
435 |
+
event.preventDefault();
|
436 |
+
return true;
|
437 |
+
}
|
438 |
+
}
|
439 |
+
|
440 |
+
// these delegates are required to keep context
|
441 |
+
this._mouseMoveDelegate = function(event) {
|
442 |
+
return self._mouseMove(event);
|
443 |
+
};
|
444 |
+
this._mouseUpDelegate = function(event) {
|
445 |
+
return self._mouseUp(event);
|
446 |
+
};
|
447 |
+
jQuery(document)
|
448 |
+
.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
|
449 |
+
.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
|
450 |
+
|
451 |
+
// preventDefault() is used to prevent the selection of text here -
|
452 |
+
// however, in Safari, this causes select boxes not to be selectable
|
453 |
+
// anymore, so this fix is needed
|
454 |
+
(jQuery.browser.safari || event.preventDefault());
|
455 |
+
|
456 |
+
event.originalEvent.mouseHandled = true;
|
457 |
+
return true;
|
458 |
+
},
|
459 |
+
|
460 |
+
_mouseMove: function(event) {
|
461 |
+
// IE mouseup check - mouseup happened when mouse was out of window
|
462 |
+
if (jQuery.browser.msie && !event.button) {
|
463 |
+
return this._mouseUp(event);
|
464 |
+
}
|
465 |
+
|
466 |
+
if (this._mouseStarted) {
|
467 |
+
this._mouseDrag(event);
|
468 |
+
return event.preventDefault();
|
469 |
+
}
|
470 |
+
|
471 |
+
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
|
472 |
+
this._mouseStarted =
|
473 |
+
(this._mouseStart(this._mouseDownEvent, event) !== false);
|
474 |
+
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
|
475 |
+
}
|
476 |
+
|
477 |
+
return !this._mouseStarted;
|
478 |
+
},
|
479 |
+
|
480 |
+
_mouseUp: function(event) {
|
481 |
+
jQuery(document)
|
482 |
+
.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
|
483 |
+
.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
|
484 |
+
|
485 |
+
if (this._mouseStarted) {
|
486 |
+
this._mouseStarted = false;
|
487 |
+
this._preventClickEvent = (event.target == this._mouseDownEvent.target);
|
488 |
+
this._mouseStop(event);
|
489 |
+
}
|
490 |
+
|
491 |
+
return false;
|
492 |
+
},
|
493 |
+
|
494 |
+
_mouseDistanceMet: function(event) {
|
495 |
+
return (Math.max(
|
496 |
+
Math.abs(this._mouseDownEvent.pageX - event.pageX),
|
497 |
+
Math.abs(this._mouseDownEvent.pageY - event.pageY)
|
498 |
+
) >= this.options.distance
|
499 |
+
);
|
500 |
+
},
|
501 |
+
|
502 |
+
_mouseDelayMet: function(event) {
|
503 |
+
return this.mouseDelayMet;
|
504 |
+
},
|
505 |
+
|
506 |
+
// These are placeholder methods, to be overriden by extending plugin
|
507 |
+
_mouseStart: function(event) {},
|
508 |
+
_mouseDrag: function(event) {},
|
509 |
+
_mouseStop: function(event) {},
|
510 |
+
_mouseCapture: function(event) { return true; }
|
511 |
+
};
|
512 |
+
|
513 |
+
jQuery.ui.mouse.defaults = {
|
514 |
+
cancel: null,
|
515 |
+
distance: 1,
|
516 |
+
delay: 0
|
517 |
+
};
|
518 |
+
|
519 |
+
})(jQuery);
|
lib/ui.draggable.js
ADDED
@@ -0,0 +1,773 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery UI Draggable 1.7.2
|
3 |
+
*
|
4 |
+
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
5 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
6 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
7 |
+
*
|
8 |
+
* http://docs.jquery.com/UI/Draggables
|
9 |
+
*
|
10 |
+
* Depends:
|
11 |
+
* ui.core.js
|
12 |
+
*/
|
13 |
+
(function(jQuery) {
|
14 |
+
|
15 |
+
jQuery.widget("ui.draggable", jQuery.extend({}, jQuery.ui.mouse, {
|
16 |
+
|
17 |
+
_init: function() {
|
18 |
+
|
19 |
+
if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
|
20 |
+
this.element[0].style.position = 'relative';
|
21 |
+
|
22 |
+
(this.options.addClasses && this.element.addClass("ui-draggable"));
|
23 |
+
(this.options.disabled && this.element.addClass("ui-draggable-disabled"));
|
24 |
+
|
25 |
+
this._mouseInit();
|
26 |
+
|
27 |
+
},
|
28 |
+
|
29 |
+
destroy: function() {
|
30 |
+
if(!this.element.data('draggable')) return;
|
31 |
+
this.element
|
32 |
+
.removeData("draggable")
|
33 |
+
.unbind(".draggable")
|
34 |
+
.removeClass("ui-draggable"
|
35 |
+
+ " ui-draggable-dragging"
|
36 |
+
+ " ui-draggable-disabled");
|
37 |
+
this._mouseDestroy();
|
38 |
+
},
|
39 |
+
|
40 |
+
_mouseCapture: function(event) {
|
41 |
+
|
42 |
+
var o = this.options;
|
43 |
+
|
44 |
+
if (this.helper || o.disabled || jQuery(event.target).is('.ui-resizable-handle'))
|
45 |
+
return false;
|
46 |
+
|
47 |
+
//Quit if we're not on a valid handle
|
48 |
+
this.handle = this._getHandle(event);
|
49 |
+
if (!this.handle)
|
50 |
+
return false;
|
51 |
+
|
52 |
+
return true;
|
53 |
+
|
54 |
+
},
|
55 |
+
|
56 |
+
_mouseStart: function(event) {
|
57 |
+
|
58 |
+
var o = this.options;
|
59 |
+
|
60 |
+
//Create and append the visible helper
|
61 |
+
this.helper = this._createHelper(event);
|
62 |
+
|
63 |
+
//Cache the helper size
|
64 |
+
this._cacheHelperProportions();
|
65 |
+
|
66 |
+
//If ddmanager is used for droppables, set the global draggable
|
67 |
+
if(jQuery.ui.ddmanager)
|
68 |
+
jQuery.ui.ddmanager.current = this;
|
69 |
+
|
70 |
+
/*
|
71 |
+
* - Position generation -
|
72 |
+
* This block generates everything position related - it's the core of draggables.
|
73 |
+
*/
|
74 |
+
|
75 |
+
//Cache the margins of the original element
|
76 |
+
this._cacheMargins();
|
77 |
+
|
78 |
+
//Store the helper's css position
|
79 |
+
this.cssPosition = this.helper.css("position");
|
80 |
+
this.scrollParent = this.helper.scrollParent();
|
81 |
+
|
82 |
+
//The element's absolute position on the page minus margins
|
83 |
+
this.offset = this.element.offset();
|
84 |
+
this.offset = {
|
85 |
+
top: this.offset.top - this.margins.top,
|
86 |
+
left: this.offset.left - this.margins.left
|
87 |
+
};
|
88 |
+
|
89 |
+
jQuery.extend(this.offset, {
|
90 |
+
click: { //Where the click happened, relative to the element
|
91 |
+
left: event.pageX - this.offset.left,
|
92 |
+
top: event.pageY - this.offset.top
|
93 |
+
},
|
94 |
+
parent: this._getParentOffset(),
|
95 |
+
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
|
96 |
+
});
|
97 |
+
|
98 |
+
//Generate the original position
|
99 |
+
this.originalPosition = this._generatePosition(event);
|
100 |
+
this.originalPageX = event.pageX;
|
101 |
+
this.originalPageY = event.pageY;
|
102 |
+
|
103 |
+
//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
|
104 |
+
if(o.cursorAt)
|
105 |
+
this._adjustOffsetFromHelper(o.cursorAt);
|
106 |
+
|
107 |
+
//Set a containment if given in the options
|
108 |
+
if(o.containment)
|
109 |
+
this._setContainment();
|
110 |
+
|
111 |
+
//Call plugins and callbacks
|
112 |
+
this._trigger("start", event);
|
113 |
+
|
114 |
+
//Recache the helper size
|
115 |
+
this._cacheHelperProportions();
|
116 |
+
|
117 |
+
//Prepare the droppable offsets
|
118 |
+
if (jQuery.ui.ddmanager && !o.dropBehaviour)
|
119 |
+
jQuery.ui.ddmanager.prepareOffsets(this, event);
|
120 |
+
|
121 |
+
this.helper.addClass("ui-draggable-dragging");
|
122 |
+
this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
|
123 |
+
return true;
|
124 |
+
},
|
125 |
+
|
126 |
+
_mouseDrag: function(event, noPropagation) {
|
127 |
+
|
128 |
+
//Compute the helpers position
|
129 |
+
this.position = this._generatePosition(event);
|
130 |
+
this.positionAbs = this._convertPositionTo("absolute");
|
131 |
+
|
132 |
+
//Call plugins and callbacks and use the resulting position if something is returned
|
133 |
+
if (!noPropagation) {
|
134 |
+
var ui = this._uiHash();
|
135 |
+
this._trigger('drag', event, ui);
|
136 |
+
this.position = ui.position;
|
137 |
+
}
|
138 |
+
|
139 |
+
if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
|
140 |
+
if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
|
141 |
+
if(jQuery.ui.ddmanager) jQuery.ui.ddmanager.drag(this, event);
|
142 |
+
|
143 |
+
return false;
|
144 |
+
},
|
145 |
+
|
146 |
+
_mouseStop: function(event) {
|
147 |
+
|
148 |
+
//If we are using droppables, inform the manager about the drop
|
149 |
+
var dropped = false;
|
150 |
+
if (jQuery.ui.ddmanager && !this.options.dropBehaviour)
|
151 |
+
dropped = jQuery.ui.ddmanager.drop(this, event);
|
152 |
+
|
153 |
+
//if a drop comes from outside (a sortable)
|
154 |
+
if(this.dropped) {
|
155 |
+
dropped = this.dropped;
|
156 |
+
this.dropped = false;
|
157 |
+
}
|
158 |
+
|
159 |
+
if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || (jQuery.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
|
160 |
+
var self = this;
|
161 |
+
jQuery(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
|
162 |
+
self._trigger("stop", event);
|
163 |
+
self._clear();
|
164 |
+
});
|
165 |
+
} else {
|
166 |
+
this._trigger("stop", event);
|
167 |
+
this._clear();
|
168 |
+
}
|
169 |
+
|
170 |
+
return false;
|
171 |
+
},
|
172 |
+
|
173 |
+
_getHandle: function(event) {
|
174 |
+
|
175 |
+
var handle = !this.options.handle || !jQuery(this.options.handle, this.element).length ? true : false;
|
176 |
+
jQuery(this.options.handle, this.element)
|
177 |
+
.find("*")
|
178 |
+
.andSelf()
|
179 |
+
.each(function() {
|
180 |
+
if(this == event.target) handle = true;
|
181 |
+
});
|
182 |
+
|
183 |
+
return handle;
|
184 |
+
|
185 |
+
},
|
186 |
+
|
187 |
+
_createHelper: function(event) {
|
188 |
+
|
189 |
+
var o = this.options;
|
190 |
+
var helper = jQuery.isFunction(o.helper) ? jQuery(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
|
191 |
+
|
192 |
+
if(!helper.parents('body').length)
|
193 |
+
helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
|
194 |
+
|
195 |
+
if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
|
196 |
+
helper.css("position", "absolute");
|
197 |
+
|
198 |
+
return helper;
|
199 |
+
|
200 |
+
},
|
201 |
+
|
202 |
+
_adjustOffsetFromHelper: function(obj) {
|
203 |
+
if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
|
204 |
+
if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
|
205 |
+
if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
|
206 |
+
if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
|
207 |
+
},
|
208 |
+
|
209 |
+
_getParentOffset: function() {
|
210 |
+
|
211 |
+
//Get the offsetParent and cache its position
|
212 |
+
this.offsetParent = this.helper.offsetParent();
|
213 |
+
var po = this.offsetParent.offset();
|
214 |
+
|
215 |
+
// This is a special case where we need to modify a offset calculated on start, since the following happened:
|
216 |
+
// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
|
217 |
+
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
|
218 |
+
// the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
|
219 |
+
if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && jQuery.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
|
220 |
+
po.left += this.scrollParent.scrollLeft();
|
221 |
+
po.top += this.scrollParent.scrollTop();
|
222 |
+
}
|
223 |
+
|
224 |
+
if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
|
225 |
+
|| (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && jQuery.browser.msie)) //Ugly IE fix
|
226 |
+
po = { top: 0, left: 0 };
|
227 |
+
|
228 |
+
return {
|
229 |
+
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
|
230 |
+
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
|
231 |
+
};
|
232 |
+
|
233 |
+
},
|
234 |
+
|
235 |
+
_getRelativeOffset: function() {
|
236 |
+
|
237 |
+
if(this.cssPosition == "relative") {
|
238 |
+
var p = this.element.position();
|
239 |
+
return {
|
240 |
+
top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
|
241 |
+
left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
|
242 |
+
};
|
243 |
+
} else {
|
244 |
+
return { top: 0, left: 0 };
|
245 |
+
}
|
246 |
+
|
247 |
+
},
|
248 |
+
|
249 |
+
_cacheMargins: function() {
|
250 |
+
this.margins = {
|
251 |
+
left: (parseInt(this.element.css("marginLeft"),10) || 0),
|
252 |
+
top: (parseInt(this.element.css("marginTop"),10) || 0)
|
253 |
+
};
|
254 |
+
},
|
255 |
+
|
256 |
+
_cacheHelperProportions: function() {
|
257 |
+
this.helperProportions = {
|
258 |
+
width: this.helper.outerWidth(),
|
259 |
+
height: this.helper.outerHeight()
|
260 |
+
};
|
261 |
+
},
|
262 |
+
|
263 |
+
_setContainment: function() {
|
264 |
+
|
265 |
+
var o = this.options;
|
266 |
+
if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
|
267 |
+
if(o.containment == 'document' || o.containment == 'window') this.containment = [
|
268 |
+
0 - this.offset.relative.left - this.offset.parent.left,
|
269 |
+
0 - this.offset.relative.top - this.offset.parent.top,
|
270 |
+
jQuery(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
|
271 |
+
(jQuery(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
|
272 |
+
];
|
273 |
+
|
274 |
+
if(!(/^(document|window|parent)jQuery/).test(o.containment) && o.containment.constructor != Array) {
|
275 |
+
var ce = jQuery(o.containment)[0]; if(!ce) return;
|
276 |
+
var co = jQuery(o.containment).offset();
|
277 |
+
var over = (jQuery(ce).css("overflow") != 'hidden');
|
278 |
+
|
279 |
+
this.containment = [
|
280 |
+
co.left + (parseInt(jQuery(ce).css("borderLeftWidth"),10) || 0) + (parseInt(jQuery(ce).css("paddingLeft"),10) || 0) - this.margins.left,
|
281 |
+
co.top + (parseInt(jQuery(ce).css("borderTopWidth"),10) || 0) + (parseInt(jQuery(ce).css("paddingTop"),10) || 0) - this.margins.top,
|
282 |
+
co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt(jQuery(ce).css("borderLeftWidth"),10) || 0) - (parseInt(jQuery(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
|
283 |
+
co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt(jQuery(ce).css("borderTopWidth"),10) || 0) - (parseInt(jQuery(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
|
284 |
+
];
|
285 |
+
} else if(o.containment.constructor == Array) {
|
286 |
+
this.containment = o.containment;
|
287 |
+
}
|
288 |
+
|
289 |
+
},
|
290 |
+
|
291 |
+
_convertPositionTo: function(d, pos) {
|
292 |
+
|
293 |
+
if(!pos) pos = this.position;
|
294 |
+
var mod = d == "absolute" ? 1 : -1;
|
295 |
+
var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && jQuery.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
|
296 |
+
|
297 |
+
return {
|
298 |
+
top: (
|
299 |
+
pos.top // The absolute mouse position
|
300 |
+
+ this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
|
301 |
+
+ this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
|
302 |
+
- (jQuery.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
|
303 |
+
),
|
304 |
+
left: (
|
305 |
+
pos.left // The absolute mouse position
|
306 |
+
+ this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
|
307 |
+
+ this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
|
308 |
+
- (jQuery.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
|
309 |
+
)
|
310 |
+
};
|
311 |
+
|
312 |
+
},
|
313 |
+
|
314 |
+
_generatePosition: function(event) {
|
315 |
+
|
316 |
+
var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && jQuery.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
|
317 |
+
|
318 |
+
// This is another very weird special case that only happens for relative elements:
|
319 |
+
// 1. If the css position is relative
|
320 |
+
// 2. and the scroll parent is the document or similar to the offset parent
|
321 |
+
// we have to refresh the relative offset during the scroll so there are no jumps
|
322 |
+
if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
|
323 |
+
this.offset.relative = this._getRelativeOffset();
|
324 |
+
}
|
325 |
+
|
326 |
+
var pageX = event.pageX;
|
327 |
+
var pageY = event.pageY;
|
328 |
+
|
329 |
+
/*
|
330 |
+
* - Position constraining -
|
331 |
+
* Constrain the position to a mix of grid, containment.
|
332 |
+
*/
|
333 |
+
|
334 |
+
if(this.originalPosition) { //If we are not dragging yet, we won't check for options
|
335 |
+
|
336 |
+
if(this.containment) {
|
337 |
+
if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
|
338 |
+
if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
|
339 |
+
if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
|
340 |
+
if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
|
341 |
+
}
|
342 |
+
|
343 |
+
if(o.grid) {
|
344 |
+
var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
|
345 |
+
pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
|
346 |
+
|
347 |
+
var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
|
348 |
+
pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
|
349 |
+
}
|
350 |
+
|
351 |
+
}
|
352 |
+
|
353 |
+
return {
|
354 |
+
top: (
|
355 |
+
pageY // The absolute mouse position
|
356 |
+
- this.offset.click.top // Click offset (relative to the element)
|
357 |
+
- this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
|
358 |
+
- this.offset.parent.top // The offsetParent's offset without borders (offset + border)
|
359 |
+
+ (jQuery.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
|
360 |
+
),
|
361 |
+
left: (
|
362 |
+
pageX // The absolute mouse position
|
363 |
+
- this.offset.click.left // Click offset (relative to the element)
|
364 |
+
- this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
|
365 |
+
- this.offset.parent.left // The offsetParent's offset without borders (offset + border)
|
366 |
+
+ (jQuery.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
|
367 |
+
)
|
368 |
+
};
|
369 |
+
|
370 |
+
},
|
371 |
+
|
372 |
+
_clear: function() {
|
373 |
+
this.helper.removeClass("ui-draggable-dragging");
|
374 |
+
if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
|
375 |
+
//if(jQuery.ui.ddmanager) jQuery.ui.ddmanager.current = null;
|
376 |
+
this.helper = null;
|
377 |
+
this.cancelHelperRemoval = false;
|
378 |
+
},
|
379 |
+
|
380 |
+
// From now on bulk stuff - mainly helpers
|
381 |
+
|
382 |
+
_trigger: function(type, event, ui) {
|
383 |
+
ui = ui || this._uiHash();
|
384 |
+
jQuery.ui.plugin.call(this, type, [event, ui]);
|
385 |
+
if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
|
386 |
+
return jQuery.widget.prototype._trigger.call(this, type, event, ui);
|
387 |
+
},
|
388 |
+
|
389 |
+
plugins: {},
|
390 |
+
|
391 |
+
_uiHash: function(event) {
|
392 |
+
return {
|
393 |
+
helper: this.helper,
|
394 |
+
position: this.position,
|
395 |
+
absolutePosition: this.positionAbs, //deprecated
|
396 |
+
offset: this.positionAbs
|
397 |
+
};
|
398 |
+
}
|
399 |
+
|
400 |
+
}));
|
401 |
+
|
402 |
+
jQuery.extend(jQuery.ui.draggable, {
|
403 |
+
version: "1.7.2",
|
404 |
+
eventPrefix: "drag",
|
405 |
+
defaults: {
|
406 |
+
addClasses: true,
|
407 |
+
appendTo: "parent",
|
408 |
+
axis: false,
|
409 |
+
cancel: ":input,option",
|
410 |
+
connectToSortable: false,
|
411 |
+
containment: false,
|
412 |
+
cursor: "auto",
|
413 |
+
cursorAt: false,
|
414 |
+
delay: 0,
|
415 |
+
distance: 1,
|
416 |
+
grid: false,
|
417 |
+
handle: false,
|
418 |
+
helper: "original",
|
419 |
+
iframeFix: false,
|
420 |
+
opacity: false,
|
421 |
+
refreshPositions: false,
|
422 |
+
revert: false,
|
423 |
+
revertDuration: 500,
|
424 |
+
scope: "default",
|
425 |
+
scroll: true,
|
426 |
+
scrollSensitivity: 20,
|
427 |
+
scrollSpeed: 20,
|
428 |
+
snap: false,
|
429 |
+
snapMode: "both",
|
430 |
+
snapTolerance: 20,
|
431 |
+
stack: false,
|
432 |
+
zIndex: false
|
433 |
+
}
|
434 |
+
});
|
435 |
+
|
436 |
+
jQuery.ui.plugin.add("draggable", "connectToSortable", {
|
437 |
+
start: function(event, ui) {
|
438 |
+
|
439 |
+
var inst = jQuery(this).data("draggable"), o = inst.options,
|
440 |
+
uiSortable = jQuery.extend({}, ui, { item: inst.element });
|
441 |
+
inst.sortables = [];
|
442 |
+
jQuery(o.connectToSortable).each(function() {
|
443 |
+
var sortable = jQuery.data(this, 'sortable');
|
444 |
+
if (sortable && !sortable.options.disabled) {
|
445 |
+
inst.sortables.push({
|
446 |
+
instance: sortable,
|
447 |
+
shouldRevert: sortable.options.revert
|
448 |
+
});
|
449 |
+
sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache
|
450 |
+
sortable._trigger("activate", event, uiSortable);
|
451 |
+
}
|
452 |
+
});
|
453 |
+
|
454 |
+
},
|
455 |
+
stop: function(event, ui) {
|
456 |
+
|
457 |
+
//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
|
458 |
+
var inst = jQuery(this).data("draggable"),
|
459 |
+
uiSortable = jQuery.extend({}, ui, { item: inst.element });
|
460 |
+
|
461 |
+
jQuery.each(inst.sortables, function() {
|
462 |
+
if(this.instance.isOver) {
|
463 |
+
|
464 |
+
this.instance.isOver = 0;
|
465 |
+
|
466 |
+
inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
|
467 |
+
this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
|
468 |
+
|
469 |
+
//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
|
470 |
+
if(this.shouldRevert) this.instance.options.revert = true;
|
471 |
+
|
472 |
+
//Trigger the stop of the sortable
|
473 |
+
this.instance._mouseStop(event);
|
474 |
+
|
475 |
+
this.instance.options.helper = this.instance.options._helper;
|
476 |
+
|
477 |
+
//If the helper has been the original item, restore properties in the sortable
|
478 |
+
if(inst.options.helper == 'original')
|
479 |
+
this.instance.currentItem.css({ top: 'auto', left: 'auto' });
|
480 |
+
|
481 |
+
} else {
|
482 |
+
this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
|
483 |
+
this.instance._trigger("deactivate", event, uiSortable);
|
484 |
+
}
|
485 |
+
|
486 |
+
});
|
487 |
+
|
488 |
+
},
|
489 |
+
drag: function(event, ui) {
|
490 |
+
|
491 |
+
var inst = jQuery(this).data("draggable"), self = this;
|
492 |
+
|
493 |
+
var checkPos = function(o) {
|
494 |
+
var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
|
495 |
+
var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
|
496 |
+
var itemHeight = o.height, itemWidth = o.width;
|
497 |
+
var itemTop = o.top, itemLeft = o.left;
|
498 |
+
|
499 |
+
return jQuery.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
|
500 |
+
};
|
501 |
+
|
502 |
+
jQuery.each(inst.sortables, function(i) {
|
503 |
+
|
504 |
+
//Copy over some variables to allow calling the sortable's native _intersectsWith
|
505 |
+
this.instance.positionAbs = inst.positionAbs;
|
506 |
+
this.instance.helperProportions = inst.helperProportions;
|
507 |
+
this.instance.offset.click = inst.offset.click;
|
508 |
+
|
509 |
+
if(this.instance._intersectsWith(this.instance.containerCache)) {
|
510 |
+
|
511 |
+
//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
|
512 |
+
if(!this.instance.isOver) {
|
513 |
+
|
514 |
+
this.instance.isOver = 1;
|
515 |
+
//Now we fake the start of dragging for the sortable instance,
|
516 |
+
//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
|
517 |
+
//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
|
518 |
+
this.instance.currentItem = jQuery(self).clone().appendTo(this.instance.element).data("sortable-item", true);
|
519 |
+
this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
|
520 |
+
this.instance.options.helper = function() { return ui.helper[0]; };
|
521 |
+
|
522 |
+
event.target = this.instance.currentItem[0];
|
523 |
+
this.instance._mouseCapture(event, true);
|
524 |
+
this.instance._mouseStart(event, true, true);
|
525 |
+
|
526 |
+
//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
|
527 |
+
this.instance.offset.click.top = inst.offset.click.top;
|
528 |
+
this.instance.offset.click.left = inst.offset.click.left;
|
529 |
+
this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
|
530 |
+
this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
|
531 |
+
|
532 |
+
inst._trigger("toSortable", event);
|
533 |
+
inst.dropped = this.instance.element; //draggable revert needs that
|
534 |
+
//hack so receive/update callbacks work (mostly)
|
535 |
+
inst.currentItem = inst.element;
|
536 |
+
this.instance.fromOutside = inst;
|
537 |
+
|
538 |
+
}
|
539 |
+
|
540 |
+
//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
|
541 |
+
if(this.instance.currentItem) this.instance._mouseDrag(event);
|
542 |
+
|
543 |
+
} else {
|
544 |
+
|
545 |
+
//If it doesn't intersect with the sortable, and it intersected before,
|
546 |
+
//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
|
547 |
+
if(this.instance.isOver) {
|
548 |
+
|
549 |
+
this.instance.isOver = 0;
|
550 |
+
this.instance.cancelHelperRemoval = true;
|
551 |
+
|
552 |
+
//Prevent reverting on this forced stop
|
553 |
+
this.instance.options.revert = false;
|
554 |
+
|
555 |
+
// The out event needs to be triggered independently
|
556 |
+
this.instance._trigger('out', event, this.instance._uiHash(this.instance));
|
557 |
+
|
558 |
+
this.instance._mouseStop(event, true);
|
559 |
+
this.instance.options.helper = this.instance.options._helper;
|
560 |
+
|
561 |
+
//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
|
562 |
+
this.instance.currentItem.remove();
|
563 |
+
if(this.instance.placeholder) this.instance.placeholder.remove();
|
564 |
+
|
565 |
+
inst._trigger("fromSortable", event);
|
566 |
+
inst.dropped = false; //draggable revert needs that
|
567 |
+
}
|
568 |
+
|
569 |
+
};
|
570 |
+
|
571 |
+
});
|
572 |
+
|
573 |
+
}
|
574 |
+
});
|
575 |
+
|
576 |
+
jQuery.ui.plugin.add("draggable", "cursor", {
|
577 |
+
start: function(event, ui) {
|
578 |
+
var t = jQuery('body'), o = jQuery(this).data('draggable').options;
|
579 |
+
if (t.css("cursor")) o._cursor = t.css("cursor");
|
580 |
+
t.css("cursor", o.cursor);
|
581 |
+
},
|
582 |
+
stop: function(event, ui) {
|
583 |
+
/*
|
584 |
+
* ZTG - Firefox and Chrome and fine with this, but
|
585 |
+
* IE throws an error when we try access the draggable
|
586 |
+
* options. This is just a safety precaution.
|
587 |
+
*/
|
588 |
+
if(jQuery(this).data('draggable')) {
|
589 |
+
var o = jQuery(this).data('draggable').options;
|
590 |
+
if (o._cursor) jQuery('body').css("cursor", o._cursor);
|
591 |
+
}
|
592 |
+
}
|
593 |
+
});
|
594 |
+
|
595 |
+
jQuery.ui.plugin.add("draggable", "iframeFix", {
|
596 |
+
start: function(event, ui) {
|
597 |
+
var o = jQuery(this).data('draggable').options;
|
598 |
+
jQuery(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
|
599 |
+
jQuery('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
|
600 |
+
.css({
|
601 |
+
width: this.offsetWidth+"px", height: this.offsetHeight+"px",
|
602 |
+
position: "absolute", opacity: "0.001", zIndex: 1000
|
603 |
+
})
|
604 |
+
.css(jQuery(this).offset())
|
605 |
+
.appendTo("body");
|
606 |
+
});
|
607 |
+
},
|
608 |
+
stop: function(event, ui) {
|
609 |
+
jQuery("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
|
610 |
+
}
|
611 |
+
});
|
612 |
+
|
613 |
+
jQuery.ui.plugin.add("draggable", "opacity", {
|
614 |
+
start: function(event, ui) {
|
615 |
+
var t = jQuery(ui.helper), o = jQuery(this).data('draggable').options;
|
616 |
+
if(t.css("opacity")) o._opacity = t.css("opacity");
|
617 |
+
t.css('opacity', o.opacity);
|
618 |
+
},
|
619 |
+
stop: function(event, ui) {
|
620 |
+
var o = jQuery(this).data('draggable').options;
|
621 |
+
if(o._opacity) jQuery(ui.helper).css('opacity', o._opacity);
|
622 |
+
}
|
623 |
+
});
|
624 |
+
|
625 |
+
jQuery.ui.plugin.add("draggable", "scroll", {
|
626 |
+
start: function(event, ui) {
|
627 |
+
var i = jQuery(this).data("draggable");
|
628 |
+
if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
|
629 |
+
},
|
630 |
+
drag: function(event, ui) {
|
631 |
+
|
632 |
+
var i = jQuery(this).data("draggable"), o = i.options, scrolled = false;
|
633 |
+
|
634 |
+
if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
|
635 |
+
|
636 |
+
if(!o.axis || o.axis != 'x') {
|
637 |
+
if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
|
638 |
+
i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
|
639 |
+
else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
|
640 |
+
i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
|
641 |
+
}
|
642 |
+
|
643 |
+
if(!o.axis || o.axis != 'y') {
|
644 |
+
if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
|
645 |
+
i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
|
646 |
+
else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
|
647 |
+
i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
|
648 |
+
}
|
649 |
+
|
650 |
+
} else {
|
651 |
+
|
652 |
+
if(!o.axis || o.axis != 'x') {
|
653 |
+
if(event.pageY - jQuery(document).scrollTop() < o.scrollSensitivity)
|
654 |
+
scrolled = jQuery(document).scrollTop(jQuery(document).scrollTop() - o.scrollSpeed);
|
655 |
+
else if(jQuery(window).height() - (event.pageY - jQuery(document).scrollTop()) < o.scrollSensitivity)
|
656 |
+
scrolled = jQuery(document).scrollTop(jQuery(document).scrollTop() + o.scrollSpeed);
|
657 |
+
}
|
658 |
+
|
659 |
+
if(!o.axis || o.axis != 'y') {
|
660 |
+
if(event.pageX - jQuery(document).scrollLeft() < o.scrollSensitivity)
|
661 |
+
scrolled = jQuery(document).scrollLeft(jQuery(document).scrollLeft() - o.scrollSpeed);
|
662 |
+
else if(jQuery(window).width() - (event.pageX - jQuery(document).scrollLeft()) < o.scrollSensitivity)
|
663 |
+
scrolled = jQuery(document).scrollLeft(jQuery(document).scrollLeft() + o.scrollSpeed);
|
664 |
+
}
|
665 |
+
|
666 |
+
}
|
667 |
+
|
668 |
+
if(scrolled !== false && jQuery.ui.ddmanager && !o.dropBehaviour)
|
669 |
+
jQuery.ui.ddmanager.prepareOffsets(i, event);
|
670 |
+
|
671 |
+
}
|
672 |
+
});
|
673 |
+
|
674 |
+
jQuery.ui.plugin.add("draggable", "snap", {
|
675 |
+
start: function(event, ui) {
|
676 |
+
|
677 |
+
var i = jQuery(this).data("draggable"), o = i.options;
|
678 |
+
i.snapElements = [];
|
679 |
+
|
680 |
+
jQuery(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
|
681 |
+
var jQueryt = jQuery(this); var jQueryo = jQueryt.offset();
|
682 |
+
if(this != i.element[0]) i.snapElements.push({
|
683 |
+
item: this,
|
684 |
+
width: jQueryt.outerWidth(), height: jQueryt.outerHeight(),
|
685 |
+
top: jQueryo.top, left: jQueryo.left
|
686 |
+
});
|
687 |
+
});
|
688 |
+
|
689 |
+
},
|
690 |
+
drag: function(event, ui) {
|
691 |
+
|
692 |
+
var inst = jQuery(this).data("draggable"), o = inst.options;
|
693 |
+
var d = o.snapTolerance;
|
694 |
+
|
695 |
+
var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
|
696 |
+
y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
|
697 |
+
|
698 |
+
for (var i = inst.snapElements.length - 1; i >= 0; i--){
|
699 |
+
|
700 |
+
var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
|
701 |
+
t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
|
702 |
+
|
703 |
+
//Yes, I know, this is insane ;)
|
704 |
+
if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
|
705 |
+
if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, jQuery.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
|
706 |
+
inst.snapElements[i].snapping = false;
|
707 |
+
continue;
|
708 |
+
}
|
709 |
+
|
710 |
+
if(o.snapMode != 'inner') {
|
711 |
+
var ts = Math.abs(t - y2) <= d;
|
712 |
+
var bs = Math.abs(b - y1) <= d;
|
713 |
+
var ls = Math.abs(l - x2) <= d;
|
714 |
+
var rs = Math.abs(r - x1) <= d;
|
715 |
+
if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
|
716 |
+
if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
|
717 |
+
if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
|
718 |
+
if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
|
719 |
+
}
|
720 |
+
|
721 |
+
var first = (ts || bs || ls || rs);
|
722 |
+
|
723 |
+
if(o.snapMode != 'outer') {
|
724 |
+
var ts = Math.abs(t - y1) <= d;
|
725 |
+
var bs = Math.abs(b - y2) <= d;
|
726 |
+
var ls = Math.abs(l - x1) <= d;
|
727 |
+
var rs = Math.abs(r - x2) <= d;
|
728 |
+
if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
|
729 |
+
if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
|
730 |
+
if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
|
731 |
+
if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
|
732 |
+
}
|
733 |
+
|
734 |
+
if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
|
735 |
+
(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, jQuery.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
|
736 |
+
inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
|
737 |
+
|
738 |
+
};
|
739 |
+
|
740 |
+
}
|
741 |
+
});
|
742 |
+
|
743 |
+
jQuery.ui.plugin.add("draggable", "stack", {
|
744 |
+
start: function(event, ui) {
|
745 |
+
|
746 |
+
var o = jQuery(this).data("draggable").options;
|
747 |
+
|
748 |
+
var group = jQuery.makeArray(jQuery(o.stack.group)).sort(function(a,b) {
|
749 |
+
return (parseInt(jQuery(a).css("zIndex"),10) || o.stack.min) - (parseInt(jQuery(b).css("zIndex"),10) || o.stack.min);
|
750 |
+
});
|
751 |
+
|
752 |
+
jQuery(group).each(function(i) {
|
753 |
+
this.style.zIndex = o.stack.min + i;
|
754 |
+
});
|
755 |
+
|
756 |
+
this[0].style.zIndex = o.stack.min + group.length;
|
757 |
+
|
758 |
+
}
|
759 |
+
});
|
760 |
+
|
761 |
+
jQuery.ui.plugin.add("draggable", "zIndex", {
|
762 |
+
start: function(event, ui) {
|
763 |
+
var t = jQuery(ui.helper), o = jQuery(this).data("draggable").options;
|
764 |
+
if(t.css("zIndex")) o._zIndex = t.css("zIndex");
|
765 |
+
t.css('zIndex', o.zIndex);
|
766 |
+
},
|
767 |
+
stop: function(event, ui) {
|
768 |
+
var o = jQuery(this).data("draggable").options;
|
769 |
+
if(o._zIndex) jQuery(ui.helper).css('zIndex', o._zIndex);
|
770 |
+
}
|
771 |
+
});
|
772 |
+
|
773 |
+
})(jQuery);
|
lib/ui.droppable.js
ADDED
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
* jQuery UI Droppable 1.7.2
|
3 |
+
*
|
4 |
+
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
|
5 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
6 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
7 |
+
*
|
8 |
+
* http://docs.jquery.com/UI/Droppables
|
9 |
+
*
|
10 |
+
* Depends:
|
11 |
+
* ui.core.js
|
12 |
+
* ui.draggable.js
|
13 |
+
*/
|
14 |
+
(function(jQuery) {
|
15 |
+
|
16 |
+
jQuery.widget("ui.droppable", {
|
17 |
+
|
18 |
+
_init: function() {
|
19 |
+
|
20 |
+
var o = this.options, accept = o.accept;
|
21 |
+
this.isover = 0; this.isout = 1;
|
22 |
+
|
23 |
+
this.options.accept = this.options.accept && jQuery.isFunction(this.options.accept) ? this.options.accept : function(d) {
|
24 |
+
return d.is(accept);
|
25 |
+
};
|
26 |
+
|
27 |
+
//Store the droppable's proportions
|
28 |
+
this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
|
29 |
+
|
30 |
+
// Add the reference and positions to the manager
|
31 |
+
jQuery.ui.ddmanager.droppables[this.options.scope] = jQuery.ui.ddmanager.droppables[this.options.scope] || [];
|
32 |
+
jQuery.ui.ddmanager.droppables[this.options.scope].push(this);
|
33 |
+
|
34 |
+
(this.options.addClasses && this.element.addClass("ui-droppable"));
|
35 |
+
|
36 |
+
},
|
37 |
+
|
38 |
+
destroy: function() {
|
39 |
+
var drop = jQuery.ui.ddmanager.droppables[this.options.scope];
|
40 |
+
for ( var i = 0; i < drop.length; i++ )
|
41 |
+
if ( drop[i] == this )
|
42 |
+
drop.splice(i, 1);
|
43 |
+
|
44 |
+
this.element
|
45 |
+
.removeClass("ui-droppable ui-droppable-disabled")
|
46 |
+
.removeData("droppable")
|
47 |
+
.unbind(".droppable");
|
48 |
+
},
|
49 |
+
|
50 |
+
_setData: function(key, value) {
|
51 |
+
|
52 |
+
if(key == 'accept') {
|
53 |
+
this.options.accept = value && jQuery.isFunction(value) ? value : function(d) {
|
54 |
+
return d.is(value);
|
55 |
+
};
|
56 |
+
} else {
|
57 |
+
jQuery.widget.prototype._setData.apply(this, arguments);
|
58 |
+
}
|
59 |
+
|
60 |
+
},
|
61 |
+
|
62 |
+
_activate: function(event) {
|
63 |
+
var draggable = jQuery.ui.ddmanager.current;
|
64 |
+
if(this.options.activeClass) this.element.addClass(this.options.activeClass);
|
65 |
+
(draggable && this._trigger('activate', event, this.ui(draggable)));
|
66 |
+
},
|
67 |
+
|
68 |
+
_deactivate: function(event) {
|
69 |
+
var draggable = jQuery.ui.ddmanager.current;
|
70 |
+
if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
|
71 |
+
(draggable && this._trigger('deactivate', event, this.ui(draggable)));
|
72 |
+
},
|
73 |
+
|
74 |
+
_over: function(event) {
|
75 |
+
|
76 |
+
var draggable = jQuery.ui.ddmanager.current;
|
77 |
+
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
|
78 |
+
|
79 |
+
if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
|
80 |
+
if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
|
81 |
+
this._trigger('over', event, this.ui(draggable));
|
82 |
+
}
|
83 |
+
|
84 |
+
},
|
85 |
+
|
86 |
+
_out: function(event) {
|
87 |
+
|
88 |
+
var draggable = jQuery.ui.ddmanager.current;
|
89 |
+
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
|
90 |
+
|
91 |
+
if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
|
92 |
+
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
|
93 |
+
this._trigger('out', event, this.ui(draggable));
|
94 |
+
}
|
95 |
+
|
96 |
+
},
|
97 |
+
|
98 |
+
_drop: function(event,custom) {
|
99 |
+
|
100 |
+
var draggable = custom || jQuery.ui.ddmanager.current;
|
101 |
+
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
|
102 |
+
|
103 |
+
var childrenIntersection = false;
|
104 |
+
this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
|
105 |
+
var inst = jQuery.data(this, 'droppable');
|
106 |
+
if(inst.options.greedy && jQuery.ui.intersect(draggable, jQuery.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
|
107 |
+
childrenIntersection = true; return false;
|
108 |
+
}
|
109 |
+
});
|
110 |
+
if(childrenIntersection) return false;
|
111 |
+
|
112 |
+
if(this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
|
113 |
+
if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
|
114 |
+
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
|
115 |
+
this._trigger('drop', event, this.ui(draggable));
|
116 |
+
return this.element;
|
117 |
+
}
|
118 |
+
|
119 |
+
return false;
|
120 |
+
|
121 |
+
},
|
122 |
+
|
123 |
+
ui: function(c) {
|
124 |
+
return {
|
125 |
+
draggable: (c.currentItem || c.element),
|
126 |
+
helper: c.helper,
|
127 |
+
position: c.position,
|
128 |
+
absolutePosition: c.positionAbs, //deprecated
|
129 |
+
offset: c.positionAbs
|
130 |
+
};
|
131 |
+
}
|
132 |
+
|
133 |
+
});
|
134 |
+
|
135 |
+
jQuery.extend(jQuery.ui.droppable, {
|
136 |
+
version: "1.7.2",
|
137 |
+
eventPrefix: 'drop',
|
138 |
+
defaults: {
|
139 |
+
accept: '*',
|
140 |
+
activeClass: false,
|
141 |
+
addClasses: true,
|
142 |
+
greedy: false,
|
143 |
+
hoverClass: false,
|
144 |
+
scope: 'default',
|
145 |
+
tolerance: 'intersect'
|
146 |
+
}
|
147 |
+
});
|
148 |
+
|
149 |
+
jQuery.ui.intersect = function(draggable, droppable, toleranceMode) {
|
150 |
+
|
151 |
+
if (!droppable.offset) return false;
|
152 |
+
|
153 |
+
var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
|
154 |
+
y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
|
155 |
+
var l = droppable.offset.left, r = l + droppable.proportions.width,
|
156 |
+
t = droppable.offset.top, b = t + droppable.proportions.height;
|
157 |
+
|
158 |
+
switch (toleranceMode) {
|
159 |
+
case 'fit':
|
160 |
+
return (l < x1 && x2 < r
|
161 |
+
&& t < y1 && y2 < b);
|
162 |
+
break;
|
163 |
+
case 'intersect':
|
164 |
+
return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
|
165 |
+
&& x2 - (draggable.helperProportions.width / 2) < r // Left Half
|
166 |
+
&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
|
167 |
+
&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
|
168 |
+
break;
|
169 |
+
case 'pointer':
|
170 |
+
var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
|
171 |
+
draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
|
172 |
+
isOver = jQuery.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
|
173 |
+
return isOver;
|
174 |
+
break;
|
175 |
+
case 'touch':
|
176 |
+
return (
|
177 |
+
(y1 >= t && y1 <= b) || // Top edge touching
|
178 |
+
(y2 >= t && y2 <= b) || // Bottom edge touching
|
179 |
+
(y1 < t && y2 > b) // Surrounded vertically
|
180 |
+
) && (
|
181 |
+
(x1 >= l && x1 <= r) || // Left edge touching
|
182 |
+
(x2 >= l && x2 <= r) || // Right edge touching
|
183 |
+
(x1 < l && x2 > r) // Surrounded horizontally
|
184 |
+
);
|
185 |
+
break;
|
186 |
+
default:
|
187 |
+
return false;
|
188 |
+
break;
|
189 |
+
}
|
190 |
+
|
191 |
+
};
|
192 |
+
|
193 |
+
/*
|
194 |
+
This manager tracks offsets of draggables and droppables
|
195 |
+
*/
|
196 |
+
jQuery.ui.ddmanager = {
|
197 |
+
current: null,
|
198 |
+
droppables: { 'default': [] },
|
199 |
+
prepareOffsets: function(t, event) {
|
200 |
+
|
201 |
+
var m = jQuery.ui.ddmanager.droppables[t.options.scope];
|
202 |
+
var type = event ? event.type : null; // workaround for #2317
|
203 |
+
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
|
204 |
+
|
205 |
+
droppablesLoop: for (var i = 0; i < m.length; i++) {
|
206 |
+
|
207 |
+
if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
|
208 |
+
for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
|
209 |
+
m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
|
210 |
+
|
211 |
+
m[i].offset = m[i].element.offset();
|
212 |
+
m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
|
213 |
+
|
214 |
+
if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
|
215 |
+
|
216 |
+
}
|
217 |
+
|
218 |
+
},
|
219 |
+
drop: function(draggable, event) {
|
220 |
+
|
221 |
+
var dropped = false;
|
222 |
+
jQuery.each(jQuery.ui.ddmanager.droppables[draggable.options.scope], function() {
|
223 |
+
|
224 |
+
if(!this.options) return;
|
225 |
+
if (!this.options.disabled && this.visible && jQuery.ui.intersect(draggable, this, this.options.tolerance))
|
226 |
+
dropped = this._drop.call(this, event);
|
227 |
+
|
228 |
+
if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
|
229 |
+
this.isout = 1; this.isover = 0;
|
230 |
+
this._deactivate.call(this, event);
|
231 |
+
}
|
232 |
+
|
233 |
+
});
|
234 |
+
return dropped;
|
235 |
+
|
236 |
+
},
|
237 |
+
drag: function(draggable, event) {
|
238 |
+
|
239 |
+
//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
|
240 |
+
if(draggable.options.refreshPositions) jQuery.ui.ddmanager.prepareOffsets(draggable, event);
|
241 |
+
|
242 |
+
//Run through all droppables and check their positions based on specific tolerance options
|
243 |
+
|
244 |
+
jQuery.each(jQuery.ui.ddmanager.droppables[draggable.options.scope], function() {
|
245 |
+
|
246 |
+
if(this.options.disabled || this.greedyChild || !this.visible) return;
|
247 |
+
var intersects = jQuery.ui.intersect(draggable, this, this.options.tolerance);
|
248 |
+
|
249 |
+
var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
|
250 |
+
if(!c) return;
|
251 |
+
|
252 |
+
var parentInstance;
|
253 |
+
if (this.options.greedy) {
|
254 |
+
var parent = this.element.parents(':data(droppable):eq(0)');
|
255 |
+
if (parent.length) {
|
256 |
+
parentInstance = jQuery.data(parent[0], 'droppable');
|
257 |
+
parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
// we just moved into a greedy child
|
262 |
+
if (parentInstance && c == 'isover') {
|
263 |
+
parentInstance['isover'] = 0;
|
264 |
+
parentInstance['isout'] = 1;
|
265 |
+
parentInstance._out.call(parentInstance, event);
|
266 |
+
}
|
267 |
+
|
268 |
+
this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
|
269 |
+
this[c == "isover" ? "_over" : "_out"].call(this, event);
|
270 |
+
|
271 |
+
// we just moved out of a greedy child
|
272 |
+
if (parentInstance && c == 'isout') {
|
273 |
+
parentInstance['isout'] = 0;
|
274 |
+
parentInstance['isover'] = 1;
|
275 |
+
parentInstance._over.call(parentInstance, event);
|
276 |
+
}
|
277 |
+
});
|
278 |
+
|
279 |
+
}
|
280 |
+
};
|
281 |
+
|
282 |
+
})(jQuery);
|
readme.txt
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Editorial Calendar ===
|
2 |
+
Contributors: MaryVogt, zgrossbart
|
3 |
+
Tags: posts
|
4 |
+
Requires at least: 2.8.5
|
5 |
+
Tested up to: 2.8.6
|
6 |
+
Stable tag: 0.1
|
7 |
+
|
8 |
+
THIS PLUGIN IS NOT READY FOR DOWNLOAD. Editorial calendar lets you see all your posts and drag and drop them to change the date.
|
9 |
+
|
10 |
+
== Description ==
|
11 |
+
|
12 |
+
*THIS PLUGIN IS NOT READY FOR DOWNLOAD. DO NOT RUN IT OUTSIDE OF A TEST ENVIRONMENT.*
|
13 |
+
|
14 |
+
The editorial calendar lets WordPress administrators and editors manage the dates for multiple posts at once. You see all of your posts in a calendar view and can arrange them via an easy drag and drop interface. The editorial calendar great improves any blog that plans posts in advance or takes contributions from multiple users.
|
15 |
+
|
16 |
+
== Installation ==
|
17 |
+
|
18 |
+
1. Upload the plugin directory <code>editorial-calendar</code> to the <code>wp-content/plugins</code> directory.
|
19 |
+
1. Activate the plugin through the 'Plugins' menu in WordPress.
|
20 |
+
1. Click the new 'Calendar' option under the 'Posts' menu.
|
21 |
+
|
22 |
+
|
23 |
+
|
24 |
+
== Screenshots ==
|
25 |
+
|
26 |
+
1. We'll get some screen shots soon
|
27 |
+
|
28 |
+
== Changelog ==
|
29 |
+
|
30 |
+
= 0.1 =
|
31 |
+
* This version is just for beta testers
|
32 |
+
|
33 |
+
`<?php code(); // goes in backticks ?>`
|