Version Description
- Improved error message notifications
- FAQ and installation instructions corrections/adjustments
- Added "Debug Mode" listing all settings and queries with statistics
- Resolved bug in minification of feeds
- Support for multiple wordpress installations added
- Improved cache stability for large objects
Download this release
Release Info
Developer | fredericktownes |
Plugin | W3 Total Cache |
Version | 0.6 |
Comparing to | |
See all releases |
Code changes from version 0.5 to 0.6
- inc/css/options.css +7 -6
- inc/css/popup.css +146 -142
- inc/define.php +172 -29
- inc/js/options.js +20 -7
- inc/js/popup.js +180 -27
- inc/options/about.phtml +30 -30
- inc/options/cdn.phtml +153 -141
- inc/options/common/footer.phtml +1 -1
- inc/options/common/header.phtml +31 -31
- inc/options/dbcache.phtml +22 -23
- inc/options/faq.phtml +450 -455
- inc/options/general.phtml +122 -112
- inc/options/install.phtml +162 -161
- inc/options/minify.phtml +112 -113
- inc/options/pgcache.phtml +71 -68
- inc/popup/cdn_export_file.phtml +38 -34
- inc/popup/cdn_export_library.phtml +34 -0
- inc/popup/cdn_export_table.phtml +0 -26
- inc/popup/cdn_import_library.phtml +54 -0
- inc/popup/cdn_queue.phtml +59 -59
- inc/popup/common/footer.phtml +2 -2
- inc/popup/common/header.phtml +42 -42
- lib/Minify/UPGRADING.txt +1 -1
- lib/Minify/min/README.txt +2 -2
- lib/Minify/min/builder/ocCheck.php +2 -2
- lib/Minify/min/index.php +5 -4
- lib/Minify/min/lib/HTTP/Encoder.php +24 -24
- lib/Minify/min/lib/Minify.php +1 -1
- lib/Minify/min/lib/Minify/CSS.php +75 -75
- lib/Minify/min/lib/Minify/CSS/Compressor.php +250 -250
- lib/Minify/min/lib/Minify/CSS/UriRewriter.php +10 -10
- lib/Minify/min/lib/Minify/Cache/File.php +33 -33
- lib/Minify/min/lib/Minify/Controller/Page.php +1 -1
- lib/Minify/min/lib/Minify/Javascript.php +0 -31
- lib/Minify/min/lib/Minify/Lines.php +4 -4
- lib/Minify/min/lib/MyMin.php +0 -289
- lib/Minify/min/pageBuffer.php +92 -0
- lib/Minify/min/pageConfig.php +82 -0
- lib/Minify/min/test/_inc.php +182 -0
- lib/Minify/min/test/index.php +161 -0
- lib/Minify/min/test/pageBuffer.php +96 -0
- lib/Minify/min_extras/README.txt +15 -0
- lib/Minify/min_extras/ab_tests/README.txt +10 -0
- lib/Minify/min_extras/ab_tests/_delimiter +3 -0
- lib/Minify/min_extras/ab_tests/ideal_php/before.php +25 -0
- lib/Minify/min_extras/ab_tests/minify/before.js +3408 -0
- lib/Minify/min_extras/ab_tests/minify/test_Files.php +15 -0
- lib/Minify/min_extras/ab_tests/minify/test_Files_Memcache.php +35 -0
- lib/Minify/min_extras/ab_tests/minify/test_Groups.php +15 -0
- lib/Minify/min_extras/ab_tests/minify/test_Version1.php +13 -0
- lib/Minify/min_extras/ab_tests/minify/test_memcache.php +19 -0
- lib/Minify/min_extras/ab_tests/mod_deflate/.htaccess-dev +30 -0
- lib/Minify/min_extras/ab_tests/mod_deflate/before.js +374 -0
- lib/Minify/min_extras/ab_tests/results_summary.txt +37 -0
- lib/Minify/min_extras/ab_tests/test_all.bat +67 -0
- lib/Minify/min_extras/ab_tests/test_memcache.bat +13 -0
- lib/Minify/min_extras/ab_tests/type-map/.htaccess-dev +40 -0
- lib/Minify/min_extras/ab_tests/type-map/before.js +374 -0
- lib/Minify/min_extras/ab_tests/type-map/before.js.var +14 -0
- lib/Minify/min_extras/ab_tests/type-map/before.js.zc +0 -0
- lib/Minify/min_extras/ab_tests/type-map/before.js.zd +0 -0
- lib/Minify/min_extras/ab_tests/type-map/before.js.zg +0 -0
- lib/Minify/min_extras/ab_tests/v1.0/minify.php +500 -0
- lib/Minify/min_extras/config.php +11 -0
- lib/Minify/min_extras/examples/1/_groupsSources.php +11 -0
- lib/Minify/min_extras/examples/1/index.php +50 -0
- lib/Minify/min_extras/examples/1/m.php +14 -0
- lib/Minify/min_extras/examples/2/_groupsSources.php +11 -0
- lib/Minify/min_extras/examples/2/index.php +94 -0
- lib/Minify/min_extras/examples/2/m.php +14 -0
- lib/Minify/min_extras/examples/index.php +3 -0
- lib/Minify/min_extras/examples/lib.js +6 -0
- lib/Minify/min_extras/examples/test space.js +5 -0
- lib/Minify/min_extras/examples/test.css +41 -0
- lib/Minify/min_extras/tools/encodeFile.php +34 -0
- lib/Minify/min_extras/tools/minifyFile.php +50 -0
- lib/Minify/min_extras/tools/minifyTextarea.php +98 -0
- lib/Minify/min_extras/tools/minifyUrl.php +166 -0
- lib/Minify/min_extras/tools/testRewriteUri.php +59 -0
- lib/Minify/min_unit_tests/HTTP_ConditionalGet/3.php +1 -1
- lib/Minify/min_unit_tests/HTTP_ConditionalGet/_include.php +1 -1
- lib/Minify/min_unit_tests/HTTP_ConditionalGet/index.php +1 -1
- lib/Minify/min_unit_tests/README.txt +4 -0
- lib/Minify/min_unit_tests/_test_files/css/hacks.css +66 -66
- lib/Minify/min_unit_tests/_test_files/css/issue62.css +889 -889
- lib/Minify/min_unit_tests/_test_files/css/paths_prepend.css +11 -11
- lib/Minify/min_unit_tests/_test_files/css/selectors.css +37 -37
- lib/Minify/min_unit_tests/_test_files/css/subsilver.css +433 -433
- lib/Minify/min_unit_tests/_test_files/css/unusual_strings.css +10 -10
- lib/Minify/min_unit_tests/_test_files/html/before.html +1 -1
- lib/Minify/min_unit_tests/_test_files/html/before2.html +1 -1
- lib/Minify/min_unit_tests/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE +348 -0
- lib/Minify/min_unit_tests/simpletest/LICENSE +502 -0
- lib/Minify/min_unit_tests/simpletest/README +108 -0
- lib/Minify/min_unit_tests/simpletest/TODO.xml +176 -0
- lib/Minify/min_unit_tests/simpletest/VERSION +1 -0
- lib/Minify/min_unit_tests/simpletest/authentication.php +238 -0
- lib/Minify/min_unit_tests/simpletest/autorun.php +87 -0
- lib/Minify/min_unit_tests/simpletest/browser.php +1098 -0
- lib/Minify/min_unit_tests/simpletest/collector.php +122 -0
- lib/Minify/min_unit_tests/simpletest/compatibility.php +173 -0
- lib/Minify/min_unit_tests/simpletest/cookies.php +380 -0
- lib/Minify/min_unit_tests/simpletest/default_reporter.php +133 -0
- lib/Minify/min_unit_tests/simpletest/detached.php +96 -0
- lib/Minify/min_unit_tests/simpletest/docs/en/docs.css +121 -0
- lib/Minify/min_unit_tests/simpletest/docs/fr/docs.css +84 -0
- lib/Minify/min_unit_tests/simpletest/docs/lastcraft/README +1 -0
- lib/Minify/min_unit_tests/simpletest/docs/onpk/README +1 -0
- lib/Minify/min_unit_tests/simpletest/docs/pkg/README +1 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/README +1 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/favicon.ico +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/book-domain-driven-design.jpg +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/book-guide-to-php-design-patterns.jpg +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/book-the-php-anthology-object-oriented-php-solutions.jpg +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/quote.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-contribute.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-download.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-external-bottom.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-external-middle.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-external-top.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-internal-bottom.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-internal-middle.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-internal-top.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-logo.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-start-testing.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-support.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/test-in-cli.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/test-with-1-fail.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/test-with-1-pass.png +0 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/index.html +188 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/js/jquery-1.2.1.pack.js +11 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/js/jquery-speakers_coaches_consultants.js +30 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/simpletest.css +39 -0
- lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/views/photos_stream.php +36 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/about.xml +116 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/authentication_documentation.xml +317 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/books_website.xml +73 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/boundary_classes_tutorial.xml +407 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/browser_documentation.xml +263 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/coding_standards.xml +82 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/display_subclass_tutorial.xml +274 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/download_website.xml +100 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/expectation_documentation.xml +339 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_autorun.xml +209 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_dom_tester.xml +231 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_intro.xml +54 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_recorder.xml +170 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/extension_eclipse.xml +279 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/first_test_tutorial.xml +443 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/form_testing_documentation.xml +299 -0
- lib/Minify/min_unit_tests/simpletest/docs/source/en/gain_control_tutorial.xml +296 -0
inc/css/options.css
CHANGED
@@ -1,22 +1,22 @@
|
|
1 |
Â
#icon-w3tc-logo {
|
2 |
Â
background:url(../images/logo.png) no-repeat;
|
3 |
Â
float:left;
|
4 |
-
height:36px;
|
5 |
Â
width:36px
|
6 |
Â
}
|
7 |
Â
.w3tc-options-menu-selected {
|
8 |
Â
font-weight:bold
|
9 |
Â
}
|
10 |
Â
.w3tc-enabled {
|
11 |
-
color
|
12 |
Â
font-weight:bold
|
13 |
Â
}
|
14 |
Â
.w3tc-disabled {
|
15 |
-
color
|
16 |
Â
font-weight:bold
|
17 |
Â
}
|
18 |
Â
.w3tc-empty {
|
19 |
-
font-weight:bold;
|
20 |
Â
font-style:italic
|
21 |
Â
}
|
22 |
Â
.w3tc-success {
|
@@ -35,7 +35,6 @@
|
|
35 |
Â
list-style-type:disc;
|
36 |
Â
list-style-position:inside
|
37 |
Â
}
|
38 |
-
/* FAQ BEGIN */
|
39 |
Â
#w3tc blockquote {
|
40 |
Â
font-style:italic;
|
41 |
Â
width:700px
|
@@ -84,4 +83,6 @@
|
|
84 |
Â
padding:10px;
|
85 |
Â
width:760px
|
86 |
Â
}
|
87 |
-
|
Â
|
|
Â
|
1 |
Â
#icon-w3tc-logo {
|
2 |
Â
background:url(../images/logo.png) no-repeat;
|
3 |
Â
float:left;
|
4 |
+
height: 36px;
|
5 |
Â
width:36px
|
6 |
Â
}
|
7 |
Â
.w3tc-options-menu-selected {
|
8 |
Â
font-weight:bold
|
9 |
Â
}
|
10 |
Â
.w3tc-enabled {
|
11 |
+
color: #090;
|
12 |
Â
font-weight:bold
|
13 |
Â
}
|
14 |
Â
.w3tc-disabled {
|
15 |
+
color: #f00;
|
16 |
Â
font-weight:bold
|
17 |
Â
}
|
18 |
Â
.w3tc-empty {
|
19 |
+
font-weight: bold;
|
20 |
Â
font-style:italic
|
21 |
Â
}
|
22 |
Â
.w3tc-success {
|
35 |
Â
list-style-type:disc;
|
36 |
Â
list-style-position:inside
|
37 |
Â
}
|
Â
|
|
38 |
Â
#w3tc blockquote {
|
39 |
Â
font-style:italic;
|
40 |
Â
width:700px
|
83 |
Â
padding:10px;
|
84 |
Â
width:760px
|
85 |
Â
}
|
86 |
+
#w3tc #about, #w3tc #install {
|
87 |
+
width: 760px;
|
88 |
+
}
|
inc/css/popup.css
CHANGED
@@ -1,142 +1,146 @@
|
|
1 |
-
* {
|
2 |
-
margin: 0;
|
3 |
-
padding: 0;
|
4 |
-
color: #464646;
|
5 |
-
}
|
6 |
-
html,body {
|
7 |
-
height: 100%;
|
8 |
-
}
|
9 |
-
body {
|
10 |
-
line-height: 1;
|
11 |
-
background: #f9f9f9;
|
12 |
-
}
|
13 |
-
body,td,textarea,input,select {
|
14 |
-
font-family: "Lucida Grande", Verdana, Arial;
|
15 |
-
font-size: 13px;
|
16 |
-
}
|
17 |
-
p {
|
18 |
-
margin: 1em 0;
|
19 |
-
}
|
20 |
-
h1 {
|
21 |
-
font-family: Georgia, "Times New Roman", "Bitstream Charter";
|
22 |
-
font-size: 24px;
|
23 |
-
font-style: italic;
|
24 |
-
font-weight: normal;
|
25 |
-
line-height: 35px;
|
26 |
-
margin-bottom: 0.8em 0;
|
27 |
-
text-shadow: 0 1px 0 #fff;
|
28 |
-
}
|
29 |
-
a {
|
30 |
-
color: #21759B;
|
31 |
-
}
|
32 |
-
a:hover {
|
33 |
-
color: #D54E21;
|
34 |
-
}
|
35 |
-
#content {
|
36 |
-
padding: 40px 50px;
|
37 |
-
}
|
38 |
-
.clear {
|
39 |
-
clear: both;
|
40 |
-
}
|
41 |
-
.button,input[type="button"],input[type="submit"] {
|
42 |
-
font-size: 11px;
|
43 |
-
line-height: 16px;
|
44 |
-
background: #F2F2F2 url(/wp-admin/images/white-grad.png) repeat-x scroll
|
45 |
-
left top;
|
46 |
-
border: 1px solid #bbb;
|
47 |
-
color: #464646;
|
48 |
-
text-shadow: 0 1px 0 #fff;
|
49 |
-
cursor: pointer;
|
50 |
-
padding: 2px 8px;
|
51 |
-
-moz-background-clip: border;
|
52 |
-
-moz-background-inline-policy: continuous;
|
53 |
-
-moz-background-origin: padding;
|
54 |
-
-moz-border-radius: 11px;
|
55 |
-
-moz-box-sizing: content-box;
|
56 |
-
}
|
57 |
-
.button:hover,input[type="button"]:hover,input[type="submit"]:hover {
|
58 |
-
border-color: #666;
|
59 |
-
color: #000;
|
60 |
-
}
|
61 |
-
.button:active,input[type="button"]:active,input[type="submit"]:active {
|
62 |
-
background: #F2F2F2 url(/wp-admin/images/white-grad-active.png) repeat-x
|
63 |
-
scroll left top;
|
64 |
-
}
|
65 |
-
.progress {
|
66 |
-
background: #fff;
|
67 |
-
border: 1px solid #464646;
|
68 |
-
padding: 1px;
|
69 |
-
margin: 1em 0;
|
70 |
-
position: relative;
|
71 |
-
}
|
72 |
-
.progress-value {
|
73 |
-
position: absolute;
|
74 |
-
line-height: 30px;
|
75 |
-
font-size: 16px;
|
76 |
-
font-weight: bold;
|
77 |
-
color: #000;
|
78 |
-
text-align: center;
|
79 |
-
width: 100%;
|
80 |
-
}
|
81 |
-
.progress-bar {
|
82 |
-
float: left;
|
83 |
-
width: 0;
|
84 |
-
height: 30px;
|
85 |
-
background: #fc2;
|
86 |
-
}
|
87 |
-
.log {
|
88 |
-
border: 1px solid #464646;
|
89 |
-
height: 298px;
|
90 |
-
overflow: auto;
|
91 |
-
}
|
92 |
-
.log div {
|
93 |
-
padding: 3px;
|
94 |
-
border-bottom: 1px solid #464646;
|
95 |
-
}
|
96 |
-
.log-success {
|
97 |
-
background: #bfb;
|
98 |
-
}
|
99 |
-
.log-error {
|
100 |
-
background: #f99;
|
101 |
-
}
|
102 |
-
.empty {
|
103 |
-
font-weight: bold;
|
104 |
-
font-style: italic;
|
105 |
-
}
|
106 |
-
.table {
|
107 |
-
width: 100%;
|
108 |
-
border-collapse: collapse;
|
109 |
-
}
|
110 |
-
.table td,th {
|
111 |
-
border: 1px solid #ccc;
|
112 |
-
padding: 3px 2px;
|
113 |
-
}
|
114 |
-
.table th {
|
115 |
-
background: #eee;
|
116 |
-
}
|
117 |
-
.updated,.error {
|
118 |
-
-moz-border-radius-bottomleft: 3px;
|
119 |
-
-moz-border-radius-bottomright: 3px;
|
120 |
-
-moz-border-radius-topleft: 3px;
|
121 |
-
-moz-border-radius-topright: 3px;
|
122 |
-
border-style: solid;
|
123 |
-
border-width: 1px;
|
124 |
-
padding: 0 0.6em;
|
125 |
-
margin: 0.5em 0;
|
126 |
-
}
|
127 |
-
.updated {
|
128 |
-
background: #FFFFE0;
|
129 |
-
border-color: #E6DB55;
|
130 |
-
}
|
131 |
-
.error {
|
132 |
-
background-color: #FFEBE8;
|
133 |
-
border-color: #CC0000;
|
134 |
-
}
|
135 |
-
.updated p,.error p {
|
136 |
-
line-height: 1;
|
137 |
-
margin: 0.5em 0;
|
138 |
-
padding: 2px;
|
139 |
-
}
|
140 |
-
.tab-selected {
|
141 |
-
font-weight: bold;
|
142 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
* {
|
2 |
+
margin: 0;
|
3 |
+
padding: 0;
|
4 |
+
color: #464646;
|
5 |
+
}
|
6 |
+
html,body {
|
7 |
+
height: 100%;
|
8 |
+
}
|
9 |
+
body {
|
10 |
+
line-height: 1;
|
11 |
+
background: #f9f9f9;
|
12 |
+
}
|
13 |
+
body,td,textarea,input,select {
|
14 |
+
font-family: "Lucida Grande", Verdana, Arial;
|
15 |
+
font-size: 13px;
|
16 |
+
}
|
17 |
+
p {
|
18 |
+
margin: 1em 0;
|
19 |
+
}
|
20 |
+
h1 {
|
21 |
+
font-family: Georgia, "Times New Roman", "Bitstream Charter";
|
22 |
+
font-size: 24px;
|
23 |
+
font-style: italic;
|
24 |
+
font-weight: normal;
|
25 |
+
line-height: 35px;
|
26 |
+
margin-bottom: 0.8em 0;
|
27 |
+
text-shadow: 0 1px 0 #fff;
|
28 |
+
}
|
29 |
+
a {
|
30 |
+
color: #21759B;
|
31 |
+
}
|
32 |
+
a:hover {
|
33 |
+
color: #D54E21;
|
34 |
+
}
|
35 |
+
#content {
|
36 |
+
padding: 40px 50px;
|
37 |
+
}
|
38 |
+
.clear {
|
39 |
+
clear: both;
|
40 |
+
}
|
41 |
+
.button,input[type="button"],input[type="submit"] {
|
42 |
+
font-size: 11px;
|
43 |
+
line-height: 16px;
|
44 |
+
background: #F2F2F2 url(/wp-admin/images/white-grad.png) repeat-x scroll
|
45 |
+
left top;
|
46 |
+
border: 1px solid #bbb;
|
47 |
+
color: #464646;
|
48 |
+
text-shadow: 0 1px 0 #fff;
|
49 |
+
cursor: pointer;
|
50 |
+
padding: 2px 8px;
|
51 |
+
-moz-background-clip: border;
|
52 |
+
-moz-background-inline-policy: continuous;
|
53 |
+
-moz-background-origin: padding;
|
54 |
+
-moz-border-radius: 11px;
|
55 |
+
-moz-box-sizing: content-box;
|
56 |
+
}
|
57 |
+
.button:hover,input[type="button"]:hover,input[type="submit"]:hover {
|
58 |
+
border-color: #666;
|
59 |
+
color: #000;
|
60 |
+
}
|
61 |
+
.button:active,input[type="button"]:active,input[type="submit"]:active {
|
62 |
+
background: #F2F2F2 url(/wp-admin/images/white-grad-active.png) repeat-x
|
63 |
+
scroll left top;
|
64 |
+
}
|
65 |
+
.progress {
|
66 |
+
background: #fff;
|
67 |
+
border: 1px solid #464646;
|
68 |
+
padding: 1px;
|
69 |
+
margin: 1em 0;
|
70 |
+
position: relative;
|
71 |
+
}
|
72 |
+
.progress-value {
|
73 |
+
position: absolute;
|
74 |
+
line-height: 30px;
|
75 |
+
font-size: 16px;
|
76 |
+
font-weight: bold;
|
77 |
+
color: #000;
|
78 |
+
text-align: center;
|
79 |
+
width: 100%;
|
80 |
+
}
|
81 |
+
.progress-bar {
|
82 |
+
float: left;
|
83 |
+
width: 0;
|
84 |
+
height: 30px;
|
85 |
+
background: #fc2;
|
86 |
+
}
|
87 |
+
.log {
|
88 |
+
border: 1px solid #464646;
|
89 |
+
height: 298px;
|
90 |
+
overflow: auto;
|
91 |
+
}
|
92 |
+
.log div {
|
93 |
+
padding: 3px;
|
94 |
+
border-bottom: 1px solid #464646;
|
95 |
+
}
|
96 |
+
.log-success {
|
97 |
+
background: #bfb;
|
98 |
+
}
|
99 |
+
.log-error {
|
100 |
+
background: #f99;
|
101 |
+
}
|
102 |
+
.empty {
|
103 |
+
font-weight: bold;
|
104 |
+
font-style: italic;
|
105 |
+
}
|
106 |
+
.table {
|
107 |
+
width: 100%;
|
108 |
+
border-collapse: collapse;
|
109 |
+
}
|
110 |
+
.table td,th {
|
111 |
+
border: 1px solid #ccc;
|
112 |
+
padding: 3px 2px;
|
113 |
+
}
|
114 |
+
.table th {
|
115 |
+
background: #eee;
|
116 |
+
}
|
117 |
+
.updated,.error {
|
118 |
+
-moz-border-radius-bottomleft: 3px;
|
119 |
+
-moz-border-radius-bottomright: 3px;
|
120 |
+
-moz-border-radius-topleft: 3px;
|
121 |
+
-moz-border-radius-topright: 3px;
|
122 |
+
border-style: solid;
|
123 |
+
border-width: 1px;
|
124 |
+
padding: 0 0.6em;
|
125 |
+
margin: 0.5em 0;
|
126 |
+
}
|
127 |
+
.updated {
|
128 |
+
background: #FFFFE0;
|
129 |
+
border-color: #E6DB55;
|
130 |
+
}
|
131 |
+
.error {
|
132 |
+
background-color: #FFEBE8;
|
133 |
+
border-color: #CC0000;
|
134 |
+
}
|
135 |
+
.updated p,.error p {
|
136 |
+
line-height: 1;
|
137 |
+
margin: 0.5em 0;
|
138 |
+
padding: 2px;
|
139 |
+
}
|
140 |
+
.tab-selected {
|
141 |
+
font-weight: bold;
|
142 |
+
}
|
143 |
+
.rules {
|
144 |
+
width: 100%;
|
145 |
+
font-size: 9px;
|
146 |
+
}
|
inc/define.php
CHANGED
@@ -1,29 +1,172 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if (! defined('
|
4 |
-
define('
|
5 |
-
}
|
6 |
-
|
7 |
-
if (! defined('
|
8 |
-
define('
|
9 |
-
}
|
10 |
-
|
11 |
-
if (! defined('
|
12 |
-
define('
|
13 |
-
}
|
14 |
-
|
15 |
-
if (! defined('
|
16 |
-
define('
|
17 |
-
}
|
18 |
-
|
19 |
-
if (! defined('
|
20 |
-
define('
|
21 |
-
}
|
22 |
-
|
23 |
-
if (! defined('
|
24 |
-
define('
|
25 |
-
}
|
26 |
-
|
27 |
-
if (! defined('
|
28 |
-
define('
|
29 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (! defined('W3_PLUGIN_VERSION')) {
|
4 |
+
define('W3_PLUGIN_VERSION', '0.6');
|
5 |
+
}
|
6 |
+
|
7 |
+
if (! defined('W3_PLUGIN_POWERED_BY')) {
|
8 |
+
define('W3_PLUGIN_POWERED_BY', 'W3 Total Cache/' . W3_PLUGIN_VERSION);
|
9 |
+
}
|
10 |
+
|
11 |
+
if (! defined('WP_CONTENT_DIR')) {
|
12 |
+
define('WP_CONTENT_DIR', dirname(__FILE__) . '/../../../');
|
13 |
+
}
|
14 |
+
|
15 |
+
if (! defined('W3_PLUGIN_DIR')) {
|
16 |
+
define('W3_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins/w3-total-cache');
|
17 |
+
}
|
18 |
+
|
19 |
+
if (! defined('W3_PLUGIN_CONTENT_DIR')) {
|
20 |
+
define('W3_PLUGIN_CONTENT_DIR', W3_PLUGIN_DIR . '/wp-content');
|
21 |
+
}
|
22 |
+
|
23 |
+
if (! defined('W3_PLUGIN_FILE')) {
|
24 |
+
define('W3_PLUGIN_FILE', 'w3-total-cache/w3-total-cache.php');
|
25 |
+
}
|
26 |
+
|
27 |
+
if (! defined('W3_CONFIG_PATH')) {
|
28 |
+
define('W3_CONFIG_PATH', WP_CONTENT_DIR . '/w3-total-cache-config.php');
|
29 |
+
}
|
30 |
+
|
31 |
+
if (! defined('W3_CONFIG_DEFAULT_PATH')) {
|
32 |
+
define('W3_CONFIG_DEFAULT_PATH', W3_PLUGIN_DIR . '/w3-total-cache-config-default.php');
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* W3 writable error
|
37 |
+
*
|
38 |
+
* @param string $path
|
39 |
+
* @param boolean $die
|
40 |
+
* @return string
|
41 |
+
*/
|
42 |
+
function w3_writable_error($path, $die = true)
|
43 |
+
{
|
44 |
+
$error = sprintf('<strong>%s</strong> could not be created, please run following command:<br /><strong style="color: #f00;">chmod 777 %s</strong><br />then re-activate plugin.', $path, dirname($path));
|
45 |
+
|
46 |
+
if ($die) {
|
47 |
+
die($error);
|
48 |
+
}
|
49 |
+
|
50 |
+
return $error;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Returns current microtime
|
55 |
+
*
|
56 |
+
* @return float
|
57 |
+
*/
|
58 |
+
function w3_microtime()
|
59 |
+
{
|
60 |
+
list ($usec, $sec) = explode(" ", microtime());
|
61 |
+
return ((float) $usec + (float) $sec);
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Check if URL is valid
|
66 |
+
*
|
67 |
+
* @param string $url
|
68 |
+
* @return boolean
|
69 |
+
*/
|
70 |
+
function w3_is_url($url)
|
71 |
+
{
|
72 |
+
return preg_match('~^https?://~', $url);
|
73 |
+
}
|
74 |
+
|
75 |
+
if (! function_exists('gzdecode')) {
|
76 |
+
/**
|
77 |
+
* Decodes gzip-encoded string
|
78 |
+
*
|
79 |
+
* @param string $data
|
80 |
+
* @return string
|
81 |
+
*/
|
82 |
+
function gzdecode($data)
|
83 |
+
{
|
84 |
+
$flags = ord(substr($data, 3, 1));
|
85 |
+
$headerlen = 10;
|
86 |
+
$extralen = 0;
|
87 |
+
|
88 |
+
if ($flags & 4) {
|
89 |
+
$extralen = unpack('v', substr($data, 10, 2));
|
90 |
+
$extralen = $extralen[1];
|
91 |
+
$headerlen += 2 + $extralen;
|
92 |
+
}
|
93 |
+
|
94 |
+
if ($flags & 8) {
|
95 |
+
$headerlen = strpos($data, chr(0), $headerlen) + 1;
|
96 |
+
}
|
97 |
+
|
98 |
+
if ($flags & 16) {
|
99 |
+
$headerlen = strpos($data, chr(0), $headerlen) + 1;
|
100 |
+
}
|
101 |
+
|
102 |
+
if ($flags & 2) {
|
103 |
+
$headerlen += 2;
|
104 |
+
}
|
105 |
+
|
106 |
+
$unpacked = gzinflate(substr($data, $headerlen));
|
107 |
+
|
108 |
+
if ($unpacked === FALSE) {
|
109 |
+
$unpacked = $data;
|
110 |
+
}
|
111 |
+
|
112 |
+
return $unpacked;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Creates thumbnail
|
118 |
+
*
|
119 |
+
* @param string $file
|
120 |
+
* @param integer $max_w
|
121 |
+
* @param integer $max_h
|
122 |
+
* @param boolean $crop
|
123 |
+
* @param string $suffix
|
124 |
+
* @param string $dest_path
|
125 |
+
* @param integer $jpeg_quality
|
126 |
+
* @return string
|
127 |
+
*/
|
128 |
+
function w3_create_thumbnail($file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90)
|
129 |
+
{
|
130 |
+
$thumbpath = image_resize($file, $max_w, $max_h, $crop, $suffix, $dest_path, $jpeg_quality);
|
131 |
+
|
132 |
+
return apply_filters('wp_create_thumbnail', $thumbpath);
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Recursive creates directory
|
137 |
+
*
|
138 |
+
* @param string $path
|
139 |
+
* @param integer $mask
|
140 |
+
* @return boolean
|
141 |
+
*/
|
142 |
+
function w3_mkdir($path, $mask = 0777)
|
143 |
+
{
|
144 |
+
$dirs = preg_split('~[\\/]+~', $path);
|
145 |
+
$curr_path = '';
|
146 |
+
foreach ($dirs as $dir) {
|
147 |
+
if (empty($dir)) {
|
148 |
+
return false;
|
149 |
+
}
|
150 |
+
$curr_path .= $dir;
|
151 |
+
if (! is_dir($curr_path)) {
|
152 |
+
if (@mkdir($curr_path, $mask)) {
|
153 |
+
@chmod($curr_path, $mask);
|
154 |
+
} else {
|
155 |
+
return false;
|
156 |
+
}
|
157 |
+
}
|
158 |
+
$curr_path .= DIRECTORY_SEPARATOR;
|
159 |
+
}
|
160 |
+
return true;
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Check if content is HTML or XML
|
165 |
+
*
|
166 |
+
* @param string $content
|
167 |
+
* @return boolean
|
168 |
+
*/
|
169 |
+
function w3_is_xml($content)
|
170 |
+
{
|
171 |
+
return (stristr($content, '<?xml') !== false || stristr($content, '<html') !== false);
|
172 |
+
}
|
inc/js/options.js
CHANGED
@@ -1,6 +1,13 @@
|
|
1 |
-
function w3tc_popup(url, name)
|
2 |
Â
{
|
3 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
4 |
Â
}
|
5 |
Â
|
6 |
Â
jQuery(function($) {
|
@@ -32,11 +39,13 @@ jQuery(function($) {
|
|
32 |
Â
if (enabled) {
|
33 |
Â
$(this).next(':hidden').remove();
|
34 |
Â
} else {
|
35 |
-
var me = $(this);
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
Â
|
|
Â
|
|
40 |
Â
}
|
41 |
Â
});
|
42 |
Â
}
|
@@ -185,6 +194,10 @@ jQuery(function($) {
|
|
185 |
Â
w3tc_popup('options-general.php?page=w3-total-cache/w3-total-cache.php&w3tc_action=cdn_export_library', 'cdn_export_library');
|
186 |
Â
});
|
187 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
188 |
Â
$('#cdn_queue').click(function() {
|
189 |
Â
w3tc_popup('options-general.php?page=w3-total-cache/w3-total-cache.php&w3tc_action=cdn_queue', 'cdn_queue');
|
190 |
Â
});
|
1 |
+
function w3tc_popup(url, name, width, height)
|
2 |
Â
{
|
3 |
+
if (width === undefined) {
|
4 |
+
width = 800;
|
5 |
+
}
|
6 |
+
if (height === undefined) {
|
7 |
+
height = 600;
|
8 |
+
}
|
9 |
+
|
10 |
+
return window.open(url, name, 'width=' + width + ',height=' + height +',status=no,toolbar=no,menubar=no,scrollbars=yes');
|
11 |
Â
}
|
12 |
Â
|
13 |
Â
jQuery(function($) {
|
39 |
Â
if (enabled) {
|
40 |
Â
$(this).next(':hidden').remove();
|
41 |
Â
} else {
|
42 |
+
var me = $(this), t = me.attr('type');
|
43 |
+
if ((t != 'radio' && t != 'checkbox') || this.checked) {
|
44 |
+
me.after($('<input />').attr({
|
45 |
+
type: 'hidden',
|
46 |
+
name: me.attr('name')
|
47 |
+
}).val(me.val()));
|
48 |
+
}
|
49 |
Â
}
|
50 |
Â
});
|
51 |
Â
}
|
194 |
Â
w3tc_popup('options-general.php?page=w3-total-cache/w3-total-cache.php&w3tc_action=cdn_export_library', 'cdn_export_library');
|
195 |
Â
});
|
196 |
Â
|
197 |
+
$('#cdn_import_library').click(function() {
|
198 |
+
w3tc_popup('options-general.php?page=w3-total-cache/w3-total-cache.php&w3tc_action=cdn_import_library', 'cdn_import_library');
|
199 |
+
});
|
200 |
+
|
201 |
Â
$('#cdn_queue').click(function() {
|
202 |
Â
w3tc_popup('options-general.php?page=w3-total-cache/w3-total-cache.php&w3tc_action=cdn_queue', 'cdn_queue');
|
203 |
Â
});
|
inc/js/popup.js
CHANGED
@@ -26,11 +26,16 @@ var Cdn_Export_File = {
|
|
26 |
Â
jQuery('#cdn_export_file_start').val(text);
|
27 |
Â
},
|
28 |
Â
|
29 |
-
|
30 |
Â
{
|
31 |
Â
jQuery('#cdn_export_file_log').prepend('<div class="log-' + (result == 1 ? 'success' : 'error') + '">' + path + ' <strong>' + error + '</strong></div>');
|
32 |
Â
},
|
33 |
Â
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
34 |
Â
process: function()
|
35 |
Â
{
|
36 |
Â
if (this.paused) {
|
@@ -59,7 +64,7 @@ var Cdn_Export_File = {
|
|
59 |
Â
{
|
60 |
Â
var failed = false;
|
61 |
Â
for (var i = 0; i < data.results.length; i++) {
|
62 |
-
this.
|
63 |
Â
if (data.results[i].result == -1) {
|
64 |
Â
failed = true;
|
65 |
Â
break;
|
@@ -87,7 +92,7 @@ var Cdn_Export_File = {
|
|
87 |
Â
}
|
88 |
Â
},
|
89 |
Â
|
90 |
-
init: function(files) {
|
91 |
Â
if (files === undefined) {
|
92 |
Â
files = [];
|
93 |
Â
}
|
@@ -101,6 +106,9 @@ var Cdn_Export_File = {
|
|
101 |
Â
me.set_button_text('Resume');
|
102 |
Â
me.set_status('paused');
|
103 |
Â
} else {
|
Â
|
|
Â
|
|
Â
|
|
104 |
Â
me.paused = 0;
|
105 |
Â
me.set_button_text('Pause');
|
106 |
Â
me.set_status('processing');
|
@@ -109,43 +117,47 @@ var Cdn_Export_File = {
|
|
109 |
Â
me.process();
|
110 |
Â
});
|
111 |
Â
}
|
112 |
-
}
|
113 |
Â
|
114 |
-
var
|
115 |
-
action: '',
|
116 |
Â
paused: 0,
|
117 |
Â
limit: 25,
|
118 |
Â
offset: 0,
|
119 |
Â
|
120 |
Â
set_progress: function(percent)
|
121 |
Â
{
|
122 |
-
jQuery('#
|
123 |
-
jQuery('#
|
124 |
Â
},
|
125 |
Â
|
126 |
Â
set_status: function(status)
|
127 |
Â
{
|
128 |
-
jQuery('#
|
129 |
Â
},
|
130 |
Â
|
131 |
Â
set_processed: function(processed)
|
132 |
Â
{
|
133 |
-
jQuery('#
|
134 |
Â
},
|
135 |
Â
|
136 |
Â
set_total: function(total)
|
137 |
Â
{
|
138 |
-
jQuery('#
|
139 |
Â
},
|
140 |
Â
|
141 |
Â
set_button_text: function(text)
|
142 |
Â
{
|
143 |
-
jQuery('#
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
144 |
Â
},
|
145 |
Â
|
146 |
-
|
147 |
Â
{
|
148 |
-
jQuery('#
|
149 |
Â
},
|
150 |
Â
|
151 |
Â
process: function()
|
@@ -157,7 +169,7 @@ var Cdn_Export_Table = {
|
|
157 |
Â
var me = this;
|
158 |
Â
jQuery.post('options-general.php', {
|
159 |
Â
page: 'w3-total-cache/w3-total-cache.php',
|
160 |
-
w3tc_action:
|
161 |
Â
limit: this.limit,
|
162 |
Â
offset: this.offset
|
163 |
Â
}, function(data) {
|
@@ -175,7 +187,7 @@ var Cdn_Export_Table = {
|
|
175 |
Â
|
176 |
Â
var failed = false;
|
177 |
Â
for (var i = 0; i < data.results.length; i++) {
|
178 |
-
this.
|
179 |
Â
if (data.results[i].result == -1) {
|
180 |
Â
failed = true;
|
181 |
Â
break;
|
@@ -199,20 +211,166 @@ var Cdn_Export_Table = {
|
|
199 |
Â
}
|
200 |
Â
},
|
201 |
Â
|
202 |
-
init: function(
|
203 |
-
|
204 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
205 |
Â
}
|
206 |
Â
|
207 |
-
this.
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
208 |
Â
|
209 |
Â
var me = this;
|
210 |
-
jQuery('
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
211 |
Â
if (this.value == 'Pause') {
|
212 |
Â
me.paused = 1;
|
213 |
Â
me.set_button_text('Resume');
|
214 |
Â
me.set_status('paused');
|
215 |
Â
} else {
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
216 |
Â
me.paused = 0;
|
217 |
Â
me.set_button_text('Pause');
|
218 |
Â
me.set_status('processing');
|
@@ -221,7 +379,7 @@ var Cdn_Export_Table = {
|
|
221 |
Â
me.process();
|
222 |
Â
});
|
223 |
Â
}
|
224 |
-
}
|
225 |
Â
|
226 |
Â
jQuery(function($) {
|
227 |
Â
$('.tab').click(function() {
|
@@ -238,9 +396,4 @@ jQuery(function($) {
|
|
238 |
Â
$('.cdn_queue_empty').click(function() {
|
239 |
Â
return confirm('Are you sure you want to empty the queue?');
|
240 |
Â
});
|
241 |
-
|
242 |
-
Cdn_Export_Table.init('cdn_export_library_process');
|
243 |
-
if (typeof files !== 'undefined') {
|
244 |
-
Cdn_Export_File.init(files);
|
245 |
-
}
|
246 |
Â
});
|
26 |
Â
jQuery('#cdn_export_file_start').val(text);
|
27 |
Â
},
|
28 |
Â
|
29 |
+
add_log: function(path, result, error)
|
30 |
Â
{
|
31 |
Â
jQuery('#cdn_export_file_log').prepend('<div class="log-' + (result == 1 ? 'success' : 'error') + '">' + path + ' <strong>' + error + '</strong></div>');
|
32 |
Â
},
|
33 |
Â
|
34 |
+
clear_log: function()
|
35 |
+
{
|
36 |
+
jQuery('#cdn_export_library_log').val('');
|
37 |
+
},
|
38 |
+
|
39 |
Â
process: function()
|
40 |
Â
{
|
41 |
Â
if (this.paused) {
|
64 |
Â
{
|
65 |
Â
var failed = false;
|
66 |
Â
for (var i = 0; i < data.results.length; i++) {
|
67 |
+
this.add_log(data.results[i].remote_path, data.results[i].result, data.results[i].error);
|
68 |
Â
if (data.results[i].result == -1) {
|
69 |
Â
failed = true;
|
70 |
Â
break;
|
92 |
Â
}
|
93 |
Â
},
|
94 |
Â
|
95 |
+
init: function(files, cdn_url) {
|
96 |
Â
if (files === undefined) {
|
97 |
Â
files = [];
|
98 |
Â
}
|
106 |
Â
me.set_button_text('Resume');
|
107 |
Â
me.set_status('paused');
|
108 |
Â
} else {
|
109 |
+
if (this.value == 'Start') {
|
110 |
+
me.clear_log();
|
111 |
+
}
|
112 |
Â
me.paused = 0;
|
113 |
Â
me.set_button_text('Pause');
|
114 |
Â
me.set_status('processing');
|
117 |
Â
me.process();
|
118 |
Â
});
|
119 |
Â
}
|
120 |
+
};
|
121 |
Â
|
122 |
+
var Cdn_Export_Library = {
|
Â
|
|
123 |
Â
paused: 0,
|
124 |
Â
limit: 25,
|
125 |
Â
offset: 0,
|
126 |
Â
|
127 |
Â
set_progress: function(percent)
|
128 |
Â
{
|
129 |
+
jQuery('#cdn_export_library_progress .progress-bar').width(percent + '%');
|
130 |
+
jQuery('#cdn_export_library_progress .progress-value').html(percent + '%');
|
131 |
Â
},
|
132 |
Â
|
133 |
Â
set_status: function(status)
|
134 |
Â
{
|
135 |
+
jQuery('#cdn_export_library_status').html(status);
|
136 |
Â
},
|
137 |
Â
|
138 |
Â
set_processed: function(processed)
|
139 |
Â
{
|
140 |
+
jQuery('#cdn_export_library_processed').html(processed);
|
141 |
Â
},
|
142 |
Â
|
143 |
Â
set_total: function(total)
|
144 |
Â
{
|
145 |
+
jQuery('#cdn_export_library_total').html(total);
|
146 |
Â
},
|
147 |
Â
|
148 |
Â
set_button_text: function(text)
|
149 |
Â
{
|
150 |
+
jQuery('#cdn_export_library_start').val(text);
|
151 |
+
},
|
152 |
+
|
153 |
+
add_log: function(path, result, error)
|
154 |
+
{
|
155 |
+
jQuery('#cdn_export_library_log').prepend('<div class="log-' + (result == 1 ? 'success' : 'error') + '">' + path + ' <strong>' + error + '</strong></div>');
|
156 |
Â
},
|
157 |
Â
|
158 |
+
clear_log: function()
|
159 |
Â
{
|
160 |
+
jQuery('#cdn_export_library_log').html('');
|
161 |
Â
},
|
162 |
Â
|
163 |
Â
process: function()
|
169 |
Â
var me = this;
|
170 |
Â
jQuery.post('options-general.php', {
|
171 |
Â
page: 'w3-total-cache/w3-total-cache.php',
|
172 |
+
w3tc_action: 'cdn_export_library_process',
|
173 |
Â
limit: this.limit,
|
174 |
Â
offset: this.offset
|
175 |
Â
}, function(data) {
|
187 |
Â
|
188 |
Â
var failed = false;
|
189 |
Â
for (var i = 0; i < data.results.length; i++) {
|
190 |
+
this.add_log(data.results[i].remote_path, data.results[i].result, data.results[i].error);
|
191 |
Â
if (data.results[i].result == -1) {
|
192 |
Â
failed = true;
|
193 |
Â
break;
|
211 |
Â
}
|
212 |
Â
},
|
213 |
Â
|
214 |
+
init: function() {
|
215 |
+
var me = this;
|
216 |
+
jQuery('#cdn_export_library_start').click(function() {
|
217 |
+
if (this.value == 'Pause') {
|
218 |
+
me.paused = 1;
|
219 |
+
me.set_button_text('Resume');
|
220 |
+
me.set_status('paused');
|
221 |
+
} else {
|
222 |
+
if (this.value == 'Start') {
|
223 |
+
me.clear_log();
|
224 |
+
}
|
225 |
+
me.paused = 0;
|
226 |
+
me.set_button_text('Pause');
|
227 |
+
me.set_status('processing');
|
228 |
+
}
|
229 |
+
|
230 |
+
me.process();
|
231 |
+
});
|
232 |
+
}
|
233 |
+
};
|
234 |
+
|
235 |
+
var Cdn_Import_Library = {
|
236 |
+
paused: 0,
|
237 |
+
limit: 5,
|
238 |
+
offset: 0,
|
239 |
+
cdn_host: '',
|
240 |
+
|
241 |
+
set_progress: function(percent)
|
242 |
+
{
|
243 |
+
jQuery('#cdn_import_library_progress .progress-bar').width(percent + '%');
|
244 |
+
jQuery('#cdn_import_library_progress .progress-value').html(percent + '%');
|
245 |
+
},
|
246 |
+
|
247 |
+
set_status: function(status)
|
248 |
+
{
|
249 |
+
jQuery('#cdn_import_library_status').html(status);
|
250 |
+
},
|
251 |
+
|
252 |
+
set_processed: function(processed)
|
253 |
+
{
|
254 |
+
jQuery('#cdn_import_library_processed').html(processed);
|
255 |
+
},
|
256 |
+
|
257 |
+
set_total: function(total)
|
258 |
+
{
|
259 |
+
jQuery('#cdn_import_library_total').html(total);
|
260 |
+
},
|
261 |
+
|
262 |
+
set_button_text: function(text)
|
263 |
+
{
|
264 |
+
jQuery('#cdn_import_library_start').val(text);
|
265 |
+
},
|
266 |
+
|
267 |
+
is_redirect_permanent: function()
|
268 |
+
{
|
269 |
+
return (jQuery('#cdn_import_library_redirect_permanent:checked').size() > 0);
|
270 |
+
},
|
271 |
+
|
272 |
+
is_redirect_cdn: function()
|
273 |
+
{
|
274 |
+
return (jQuery('#cdn_import_library_redirect_cdn:checked').size() > 0);
|
275 |
+
},
|
276 |
+
|
277 |
+
add_log: function(path, result, error)
|
278 |
+
{
|
279 |
+
jQuery('#cdn_import_library_log').prepend('<div class="log-' + (result == 1 ? 'success' : 'error') + '">' + path + ' <strong>' + error + '</strong></div>');
|
280 |
+
},
|
281 |
+
|
282 |
+
clear_log: function()
|
283 |
+
{
|
284 |
+
jQuery('#cdn_import_library_log').html('');
|
285 |
+
},
|
286 |
+
|
287 |
+
add_rule: function(src, dst)
|
288 |
+
{
|
289 |
+
if (/^https?:\/\//.test(src)) {
|
290 |
+
return;
|
291 |
Â
}
|
292 |
Â
|
293 |
+
if (this.is_redirect_cdn()) {
|
294 |
+
dst = 'http://' + this.cdn_host + '/' + dst;
|
295 |
+
} else {
|
296 |
+
dst = '/' + dst;
|
297 |
+
}
|
298 |
+
|
299 |
+
var rules = jQuery('#cdn_import_library_rules');
|
300 |
+
rules.val(rules.val() + 'Redirect ' + (this.is_redirect_permanent() ? '302 ' : '') + '/' + src + ' ' + dst + '\r\n');
|
301 |
+
},
|
302 |
+
|
303 |
+
clear_rules: function()
|
304 |
+
{
|
305 |
+
jQuery('#cdn_import_library_rules').val('');
|
306 |
+
},
|
307 |
+
|
308 |
+
process: function()
|
309 |
+
{
|
310 |
+
if (this.paused) {
|
311 |
+
return;
|
312 |
+
}
|
313 |
Â
|
314 |
Â
var me = this;
|
315 |
+
jQuery.post('options-general.php', {
|
316 |
+
page: 'w3-total-cache/w3-total-cache.php',
|
317 |
+
w3tc_action: 'cdn_import_library_process',
|
318 |
+
limit: this.limit,
|
319 |
+
offset: this.offset
|
320 |
+
}, function(data) {
|
321 |
+
me.process_callback(data);
|
322 |
+
}, 'json');
|
323 |
+
},
|
324 |
+
|
325 |
+
process_callback: function(data)
|
326 |
+
{
|
327 |
+
this.offset += data.count;
|
328 |
+
|
329 |
+
this.set_total(data.total);
|
330 |
+
this.set_processed(this.offset);
|
331 |
+
this.set_progress((this.offset * 100 / data.total).toFixed(0));
|
332 |
+
|
333 |
+
var failed = false;
|
334 |
+
for (var i = 0; i < data.results.length; i++) {
|
335 |
+
this.add_log(data.results[i].src, data.results[i].result, data.results[i].error);
|
336 |
+
if (data.results[i].result == 1) {
|
337 |
+
this.add_rule(data.results[i].src, data.results[i].dst);
|
338 |
+
} else if (data.results[i].result == -1) {
|
339 |
+
failed = true;
|
340 |
+
break;
|
341 |
+
}
|
342 |
+
}
|
343 |
+
|
344 |
+
if (failed) {
|
345 |
+
this.offset = 0;
|
346 |
+
this.set_progress(0);
|
347 |
+
this.set_processed(1);
|
348 |
+
this.set_status('failed');
|
349 |
+
this.set_button_text('Start');
|
350 |
+
} else {
|
351 |
+
if (this.offset < data.total) {
|
352 |
+
this.process();
|
353 |
+
} else {
|
354 |
+
this.offset = 0;
|
355 |
+
this.set_status('done');
|
356 |
+
this.set_button_text('Start');
|
357 |
+
}
|
358 |
+
}
|
359 |
+
},
|
360 |
+
|
361 |
+
init: function(cdn_host) {
|
362 |
+
var me = this;
|
363 |
+
this.cdn_host = cdn_host;
|
364 |
+
jQuery('#cdn_import_library_start').click(function() {
|
365 |
Â
if (this.value == 'Pause') {
|
366 |
Â
me.paused = 1;
|
367 |
Â
me.set_button_text('Resume');
|
368 |
Â
me.set_status('paused');
|
369 |
Â
} else {
|
370 |
+
if (this.value == 'Start') {
|
371 |
+
me.clear_log();
|
372 |
+
me.clear_rules();
|
373 |
+
}
|
374 |
Â
me.paused = 0;
|
375 |
Â
me.set_button_text('Pause');
|
376 |
Â
me.set_status('processing');
|
379 |
Â
me.process();
|
380 |
Â
});
|
381 |
Â
}
|
382 |
+
};
|
383 |
Â
|
384 |
Â
jQuery(function($) {
|
385 |
Â
$('.tab').click(function() {
|
396 |
Â
$('.cdn_queue_empty').click(function() {
|
397 |
Â
return confirm('Are you sure you want to empty the queue?');
|
398 |
Â
});
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
399 |
Â
});
|
inc/options/about.phtml
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
<
|
2 |
-
<
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
Â
</div>
|
1 |
+
<div id="about">
|
2 |
+
<h3>About</h3>
|
3 |
+
|
4 |
+
<p>User experience is an important aspect of every web site and all web sites can benefit from effective caching and file size reduction. We have applied web site optimization methods typically used with high traffic sites and simplified their implementation. Coupling these methods either <a href="http://www.danga.com/memcached/" target="_blank">memcached</a> and/or <a href="http://pecl.php.net/package/APC" target="_blank"><acronym title="Alternative PHP Cache">APC</acronym></a> and the <acronym title="Content Delivery Network">CDN</acronym> of your choosing to provide the following benefits:</p>
|
5 |
+
<ul>
|
6 |
+
<li>Improved progressive render (non-blocking <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> embedding)</li>
|
7 |
+
<li>Transparent content delivery network (<acronym title="Content Delivery Network">CDN</acronym>) support with automated media library import</li>
|
8 |
+
<li>Bandwidth savings via Minify and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate) for <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym></li>
|
9 |
+
<li>Minification (concatenation, white space removal) of inline, external or 3rd party <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> with scheduled updates</li>
|
10 |
+
<li>Caching of <acronym title="Really Simple Syndication">RSS</acronym>/Atom Feeds (comments, page and site), <acronym title="Uniform Resource Identifier">URI</acronym>s with query string variables (like search result pages), database objects, pages, posts, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> in memory via <a href="http://pecl.php.net/apc">APC</a> or <a href="http://www.danga.com/memcached/">memcached</a> or both</li>
|
11 |
+
<li>Increased web server concurrency and reduced resource consumption, increased scale</li>
|
12 |
+
<li>Reduced <acronym title="Hypertext Transfer Protocol">HTTP</acronym> Transactions, <acronym title="Domain Name System">DNS</acronym> lookups, reduced document load time</li>
|
13 |
+
<li>Complete header management including <a href="http://en.wikipedia.org/wiki/HTTP_ETag">Etags</a></li>
|
14 |
+
<li>Optional embedding of <acronym title="JavaScript">JS</acronym> just above </body></li>
|
15 |
+
</ul>
|
16 |
+
<p>Your users have less data to download, you can now handle more requests with your existing equipment and you don't have to change how you do anything; just set it and forget it.</p>
|
17 |
+
<p><strong>Who do I thank for all of this?</strong><br />It's quite difficult to recall all of the innovators that have shared their thoughts, code and experiences in the blogosphere over the years, but here are some names to get you started:</p>
|
18 |
+
<ul>
|
19 |
+
<li><a href="http://mrclay.org/" target="_blank">Steve Clay</a></li>
|
20 |
+
<li><a href="http://wonko.com/" target="_blank">Ryan Grove</a></li>
|
21 |
+
<li><a href="http://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/" target="_blank">Nicholas Zakas</a> </li>
|
22 |
+
<li><a href="http://stevesouders.com/" target="_blank">Steve Souders</a></li>
|
23 |
+
<li><a href="http://rtdean.livejournal.com/" target="_blank">Ryan Dean</a></li>
|
24 |
+
<li><a href="http://gravitonic.com/" target="_blank">Andrei Zmievski</a></li>
|
25 |
+
<li>George Schlossnagle</li>
|
26 |
+
<li>Daniel Cowgill</li>
|
27 |
+
<li><a href="http://toys.lerdorf.com/" target="_blank">Rasmus Lerdorf</a></li>
|
28 |
+
<li><a href="http://t3.dotgnu.info/" target="_blank">Gopal Vijayaraghavan</a></li>
|
29 |
+
</ul>
|
30 |
+
<p>Please reach out to all of these people and support their projects if you're so inclined.</p>
|
31 |
Â
</div>
|
inc/options/cdn.phtml
CHANGED
@@ -1,143 +1,155 @@
|
|
1 |
Â
<h3><acronym title="Content Delivery Network">CDN</acronym> Settings</h3>
|
2 |
-
|
3 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
4 |
Â
|
5 |
-
<
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
<
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
<
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
<
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
</p>
|
142 |
-
</form>
|
143 |
-
</div>
|
1 |
Â
<h3><acronym title="Content Delivery Network">CDN</acronym> Settings</h3>
|
2 |
+
|
3 |
+
<p><acronym title="Content Delivery Network">CDN</acronym> support is currently <span class="w3tc-<?php if ($config->get_boolean('cdn.enabled')): ?>enabled">enabled<?php else: ?>disabled">disabled<?php endif; ?></span>.</p>
|
4 |
+
|
5 |
+
<p>
|
6 |
+
You can
|
7 |
+
<input id="cdn_export_library" class="button" type="button" value="export media library to CDN" /> or
|
8 |
+
<input id="cdn_import_library" class="button" type="button" value="import post files to media library & CDN" /> or
|
9 |
+
<input id="cdn_queue" class="button" type="button" value="view unsuccessfull transfers" /> now.
|
10 |
+
</p>
|
11 |
+
|
12 |
+
<form action="options-general.php?page=<?php echo urldecode(W3_PLUGIN_FILE); ?>&tab=<?php echo $tab; ?>" method="post">
|
13 |
+
|
14 |
+
<!-- <p>
|
15 |
+
<a href="#cdn_ftp" class="w3tc-tab" rel="#cdn_ftp"><acronym title="File Transfer Protocol">FTP</acronym> settings</a> |
|
16 |
+
<a href="#cdn_cf" class="w3tc-tab" rel="#cdn_cf">Amazon CloudFront settings</a> |
|
17 |
+
<a href="#cdn_s3" class="w3tc-tab" rel="#cdn_s3">Amazon S3 settings</a>
|
18 |
+
</p> -->
|
19 |
Â
|
20 |
+
<div id="cdn_ftp" class="w3tc-tab-content">
|
21 |
+
<table class="form-table">
|
22 |
+
<tr>
|
23 |
+
<th><label for="cdn_ftp_host"><acronym title="File Transfer Protocol">FTP</acronym> Hostname:</label></th>
|
24 |
+
<td>
|
25 |
+
<input id="cdn_ftp_host" type="text" name="cdn.ftp.host" value="<?php echo htmlspecialchars($config->get_string('cdn.ftp.host')); ?>" size="30" />
|
26 |
+
</td>
|
27 |
+
</tr>
|
28 |
+
<tr>
|
29 |
+
<th><label for="cdn_ftp_user"><acronym title="File Transfer Protocol">FTP</acronym> Username:</label></th>
|
30 |
+
<td>
|
31 |
+
<input id="cdn_ftp_user" type="text" name="cdn.ftp.user" value="<?php echo htmlspecialchars($config->get_string('cdn.ftp.user')); ?>" size="30" />
|
32 |
+
</td>
|
33 |
+
</tr>
|
34 |
+
<tr>
|
35 |
+
<th><label for="cdn_ftp_pass"><acronym title="File Transfer Protocol">FTP</acronym> Password:</label></th>
|
36 |
+
<td>
|
37 |
+
<input id="cdn_ftp_pass" type="text" name="cdn.ftp.pass" value="<?php echo htmlspecialchars($config->get_string('cdn.ftp.pass')); ?>" size="30" />
|
38 |
+
</td>
|
39 |
+
</tr>
|
40 |
+
<tr>
|
41 |
+
<th><label for="cdn_ftp_path"><acronym title="File Transfer Protocol">FTP</acronym> Path:</label></th>
|
42 |
+
<td>
|
43 |
+
<input id="cdn_ftp_path" type="text" name="cdn.ftp.path" value="<?php echo htmlspecialchars($config->get_string('cdn.ftp.path')); ?>" size="30" />
|
44 |
+
</td>
|
45 |
+
</tr>
|
46 |
+
<tr>
|
47 |
+
<th colspan="2">
|
48 |
+
<input type="hidden" name="cdn.ftp.pasv" value="0" />
|
49 |
+
<label><input type="checkbox" name="cdn.ftp.pasv" value="1"<?php checked($config->get_boolean('cdn.ftp.pasv')); ?> /> Use Passive <acronym title="File Transfer Protocol">FTP</acronym> Mode</label>
|
50 |
+
</th>
|
51 |
+
</tr>
|
52 |
+
</table>
|
53 |
+
<p>
|
54 |
+
<input id="test_ftp" class="button" type="button" value="Test FTP server" /> <span id="test_ftp_status" class="w3tc-cdn-status w3tc-process"></span>
|
55 |
+
</p>
|
56 |
+
</div>
|
57 |
+
<div id="cdn_cf" class="w3tc-tab-content" style="display: none;">
|
58 |
+
to do...
|
59 |
+
<p>
|
60 |
+
<input class="button" type="button" value="Test CloudFront server" />
|
61 |
+
</p>
|
62 |
+
</div>
|
63 |
+
<div id="cdn_s3" class="w3tc-tab-content" style="display: none;">
|
64 |
+
to do...
|
65 |
+
<p>
|
66 |
+
<input class="button" type="button" value="Test S3 server" />
|
67 |
+
</p>
|
68 |
+
</div>
|
69 |
+
|
70 |
+
<table class="form-table">
|
71 |
+
<tr>
|
72 |
+
<th style="width: 300px;"><label for="cdn_domain">Replace domain in <acronym title="Uniform Resource Locator">URL</acronym> with:</label></th>
|
73 |
+
<td>
|
74 |
+
<input id="cdn_domain" type="text" name="cdn.domain" value="<?php echo htmlspecialchars($config->get_string('cdn.domain')); ?>" size="40" />
|
75 |
+
</td>
|
76 |
+
</tr>
|
77 |
+
<tr>
|
78 |
+
<th><label for="cdn_limit_queue">Re-transfer cycle limit:</label></th>
|
79 |
+
<td>
|
80 |
+
<input id="cdn_limit_queue" type="text" name="cdn.limit.queue" value="<?php echo htmlspecialchars($config->get_integer('cdn.limit.queue')); ?>" size="10" /><br />
|
81 |
+
<span class="description">Number of files processed per cycle.</span>
|
82 |
+
</td>
|
83 |
+
</tr>
|
84 |
+
<tr>
|
85 |
+
<th>
|
86 |
+
<input type="hidden" name="cdn.includes.enable" value="0" />
|
87 |
+
<label><input type="checkbox" name="cdn.includes.enable" value="1"<?php checked($config->get_boolean('cdn.includes.enable')); ?> /> Host wp-includes/ files</label>
|
88 |
+
</th>
|
89 |
+
<td>
|
90 |
+
<input class="button cdn_export" type="button" name="includes" value="Upload includes files" />
|
91 |
+
</td>
|
92 |
+
</tr>
|
93 |
+
<tr>
|
94 |
+
<th>
|
95 |
+
<input type="hidden" name="cdn.theme.enable" value="0" />
|
96 |
+
<label><input type="checkbox" name="cdn.theme.enable" value="1"<?php checked($config->get_boolean('cdn.theme.enable')); ?> /> Host active theme files</label>
|
97 |
+
</th>
|
98 |
+
<td>
|
99 |
+
<input class="button cdn_export" type="button" name="theme" value="Upload theme files" />
|
100 |
+
</td>
|
101 |
+
</tr>
|
102 |
+
<tr>
|
103 |
+
<th>
|
104 |
+
<input type="hidden" name="cdn.minify.enable" value="0" />
|
105 |
+
<label><input type="checkbox" name="cdn.minify.enable" value="1"<?php checked($config->get_boolean('cdn.minify.enable')); ?> /> Host minified <acronym title="Cascading Style Sheets">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files</label>
|
106 |
+
</th>
|
107 |
+
<td>
|
108 |
+
<input class="button cdn_export" type="button" name="minify" value="Upload minify files" />
|
109 |
+
</td>
|
110 |
+
</tr>
|
111 |
+
<tr>
|
112 |
+
<th>
|
113 |
+
<input type="hidden" name="cdn.custom.enable" value="0" />
|
114 |
+
<label><input type="checkbox" name="cdn.custom.enable" value="1"<?php checked($config->get_boolean('cdn.custom.enable')); ?> /> Host custom files</label>
|
115 |
+
</th>
|
116 |
+
<td>
|
117 |
+
<input class="button cdn_export" type="button" name="custom" value="Upload custom files" />
|
118 |
+
</td>
|
119 |
+
</tr>
|
120 |
+
<tr>
|
121 |
+
<th><label for="cdn_includes_files">Search wp-includes/ directory for files:</label></th>
|
122 |
+
<td>
|
123 |
+
<input id="cdn_includes_files" type="text" name="cdn.includes.files" value="<?php echo htmlspecialchars($config->get_string('cdn.includes.files')); ?>" size="40" />
|
124 |
+
</td>
|
125 |
+
</tr>
|
126 |
+
<tr>
|
127 |
+
<th><label for="cdn_theme_files">Search current theme directory for files:</label></th>
|
128 |
+
<td>
|
129 |
+
<input id="cdn_theme_files" type="text" name="cdn.theme.files" value="<?php echo htmlspecialchars($config->get_string('cdn.theme.files')); ?>" size="40" />
|
130 |
+
</td>
|
131 |
+
</tr>
|
132 |
+
<tr>
|
133 |
+
<th valign="top"><label for="cdn_custom_files">Custom file list:</label></th>
|
134 |
+
<td>
|
135 |
+
<textarea id="cdn_custom_files" name="cdn.custom.files" cols="30" rows="5"><?php echo htmlspecialchars(implode("\r\n", $config->get_array('cdn.custom.files'))); ?></textarea>
|
136 |
+
</td>
|
137 |
+
</tr>
|
138 |
+
<tr>
|
139 |
+
<th colspan="2">
|
140 |
+
<input type="hidden" name="cdn.import.external" value="0" />
|
141 |
+
<label><input type="checkbox" name="cdn.import.external" value="1"<?php checked($config->get_boolean('cdn.import.external')); ?> /> Import external files</label>
|
142 |
+
</th>
|
143 |
+
</tr>
|
144 |
+
<tr>
|
145 |
+
<th><label for="cdn_import_files">Import files:</label></th>
|
146 |
+
<td>
|
147 |
+
<input id="cdn_import_files" type="text" name="cdn.import.files" value="<?php echo htmlspecialchars($config->get_string('cdn.import.files')); ?>" size="40" />
|
148 |
+
</td>
|
149 |
+
</tr>
|
150 |
+
</table>
|
151 |
+
|
152 |
+
<p class="submit">
|
153 |
+
<input type="submit" name="Submit" class="button-primary" value="Save changes" />
|
154 |
+
</p>
|
155 |
+
</form>
|
Â
|
|
Â
|
|
Â
|
inc/options/common/footer.phtml
CHANGED
@@ -1 +1 @@
|
|
1 |
-
</div>
|
1 |
+
</div>
|
inc/options/common/header.phtml
CHANGED
@@ -1,31 +1,31 @@
|
|
1 |
-
<div class="wrap">
|
2 |
-
<?php screen_icon('w3tc-logo'); ?>
|
3 |
-
|
4 |
-
<h2>W3 Total Cache</h2>
|
5 |
-
|
6 |
-
<?php if (count($errors)): ?>
|
7 |
-
<div id="message" class="error">
|
8 |
-
<?php foreach ($errors as $error): ?>
|
9 |
-
<p><?php echo $error; ?></p>
|
10 |
-
<?php endforeach; ?>
|
11 |
-
</div>
|
12 |
-
<?php endif; ?>
|
13 |
-
|
14 |
-
<?php if (count($notes)): ?>
|
15 |
-
<div id="message" class="updated fade">
|
16 |
-
<?php foreach ($notes as $note): ?>
|
17 |
-
<p><?php echo $note; ?></p>
|
18 |
-
<?php endforeach; ?>
|
19 |
-
</div>
|
20 |
-
<?php endif; ?>
|
21 |
-
|
22 |
-
<p id="w3tc-options-menu">
|
23 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=general"<?php if ($tab == 'general'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>General Settings</a> |
|
24 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=pgcache"<?php if ($tab == 'pgcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Page Cache Settings</a> |
|
25 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=minify"<?php if ($tab == 'minify'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Minify Settings</a> |
|
26 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=dbcache"<?php if ($tab == 'dbcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Database Cache Settings</a> |
|
27 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=cdn"<?php if ($tab == 'cdn'): ?> class="w3tc-options-menu-selected"<?php endif; ?>><acronym title="Content Delivery Network">CDN</acronym> Settings</a> |
|
28 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=faq"<?php if ($tab == 'faq'): ?> class="w3tc-options-menu-selected"<?php endif; ?>><acronym title="Frequently Asked Questions">FAQ</acronym></a> |
|
29 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=install"<?php if ($tab == 'install'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Installation</a> |
|
30 |
-
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=about"<?php if ($tab == 'about'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>About</a>
|
31 |
-
</p>
|
1 |
+
<div class="wrap" id="w3tc">
|
2 |
+
<?php screen_icon('w3tc-logo'); ?>
|
3 |
+
|
4 |
+
<h2>W3 Total Cache</h2>
|
5 |
+
|
6 |
+
<?php if (count($errors)): ?>
|
7 |
+
<div id="message" class="error">
|
8 |
+
<?php foreach ($errors as $error): ?>
|
9 |
+
<p><?php echo $error; ?></p>
|
10 |
+
<?php endforeach; ?>
|
11 |
+
</div>
|
12 |
+
<?php endif; ?>
|
13 |
+
|
14 |
+
<?php if (count($notes)): ?>
|
15 |
+
<div id="message" class="updated fade">
|
16 |
+
<?php foreach ($notes as $note): ?>
|
17 |
+
<p><?php echo $note; ?></p>
|
18 |
+
<?php endforeach; ?>
|
19 |
+
</div>
|
20 |
+
<?php endif; ?>
|
21 |
+
|
22 |
+
<p id="w3tc-options-menu">
|
23 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=general"<?php if ($tab == 'general'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>General Settings</a> |
|
24 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=pgcache"<?php if ($tab == 'pgcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Page Cache Settings</a> |
|
25 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=minify"<?php if ($tab == 'minify'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Minify Settings</a> |
|
26 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=dbcache"<?php if ($tab == 'dbcache'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Database Cache Settings</a> |
|
27 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=cdn"<?php if ($tab == 'cdn'): ?> class="w3tc-options-menu-selected"<?php endif; ?>><acronym title="Content Delivery Network">CDN</acronym> Settings</a> |
|
28 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=faq"<?php if ($tab == 'faq'): ?> class="w3tc-options-menu-selected"<?php endif; ?>><acronym title="Frequently Asked Questions">FAQ</acronym></a> |
|
29 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=install"<?php if ($tab == 'install'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>Installation</a> |
|
30 |
+
<a href="?page=<?php echo W3_PLUGIN_FILE; ?>&tab=about"<?php if ($tab == 'about'): ?> class="w3tc-options-menu-selected"<?php endif; ?>>About</a>
|
31 |
+
</p>
|
inc/options/dbcache.phtml
CHANGED
@@ -1,24 +1,23 @@
|
|
1 |
Â
<h3>Database Caching Settings</h3>
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
</div>
|
1 |
Â
<h3>Database Caching Settings</h3>
|
2 |
+
|
3 |
+
<p>Database caching is currently <span class="w3tc-<?php if ($config->get_boolean('dbcache.enabled')): ?>enabled">enabled<?php else: ?>disabled">disabled<?php endif; ?></span>.</p>
|
4 |
+
|
5 |
+
<form action="options-general.php?page=<?php echo urldecode(W3_PLUGIN_FILE); ?>&tab=<?php echo $tab; ?>" method="post">
|
6 |
+
<table class="form-table">
|
7 |
+
<tr>
|
8 |
+
<th style="width: 250px;"><label for="dbcache_memcached_servers">Memcached Hostname:Port / IP:Port:</label></th>
|
9 |
+
<td>
|
10 |
+
<input id="dbcache_memcached_servers" type="text" name="dbcache.memcached.servers" value="<?php echo htmlspecialchars(implode(',', $config->get_array('dbcache.memcached.servers'))); ?>" size="100"<?php if ($config->get_string('dbcache.engine', 'memcached') != 'memcached'): ?> disabled="disabled"<?php endif; ?> /><br />
|
11 |
+
<span class="description">Multiple servers may be used and seperated by a comma; e.g. 192.168.1.100:11211, domain.com:22122</span>
|
12 |
+
</td>
|
13 |
+
</tr>
|
14 |
+
<tr>
|
15 |
+
<th><label for="dbcache_lifetime_default">Maximum lifetime of cache objects:</label></th>
|
16 |
+
<td><input id="dbcache_lifetime_default" type="text" name="dbcache.lifetime.default" value="<?php echo $config->get_integer('dbcache.lifetime.default'); ?>" size="8" /> seconds</td>
|
17 |
+
</tr>
|
18 |
+
</table>
|
19 |
+
|
20 |
+
<p class="submit">
|
21 |
+
<input type="submit" name="Submit" class="button-primary" value="Save changes" />
|
22 |
+
</p>
|
23 |
+
</form>
|
Â
|
inc/options/faq.phtml
CHANGED
@@ -1,483 +1,478 @@
|
|
1 |
-
<h3
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
</
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
</
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
</
|
112 |
-
</
|
113 |
-
</
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
</
|
128 |
-
|
Â
|
|
129 |
Â
<p>As a practical matter, Akamai and JupiterResearch did a study on <a href="http://www.akamai.com/html/about/press/releases/2006/press_110606.html" target="_blank">acceptable wait time for retail web sites</a> to load back in late 2006 concluding that users may leave after 4 seconds of waiting. That was several years ago now, even before 3G was available for mobile devices, what do you think web users expect today? <a href="http://blogs.zdnet.com/BTL/?p=3925" target="_blank">According to Marissa Mayer</a> of Google, as she stated the same year as Akamai, improving the speed of sites/applications reduces the learning curve for applications and contributes to higher use. It's time to bring the performance major corporations enjoy to the blogosphere.</p>
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
Â
<li>Bandwidth savings via <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate) for <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym></li>
|
140 |
-
|
141 |
-
|
142 |
Â
<li>Support for caching pages, posts, feeds, database objects, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> in memory with <acronym title="Alternative PHP Cache">APC</acronym> or memcached or both</li>
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
</
|
182 |
-
|
Â
|
|
183 |
Â
<p id="q13"><strong>Does this plugin work with WordPress <acronym title="Multi-User">MU</acronym>?</strong><br />
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
Â
We'll just quote the fine folks at yahoo on this one:</p>
|
194 |
-
|
195 |
Â
<p>"Minification is the practice of removing unnecessary characters from code to reduce its size thereby improving load times. When code is minified all comments are removed, as well as unneeded white space characters (space, newline, and tab). In the case of JavaScript, this improves response time performance because the size of the downloaded file is reduced. Two popular tools for minifying JavaScript code are <a href="http://www.crockford.com/javascript/jsmin.html" target="_blank"><acronym title="JavaScript">JS</acronym>Min</a> and <a href="http://developer.yahoo.com/yui/compressor/" target="_blank"><acronym title="Yahoo! User Interface">YUI</acronym> Compressor</a>. The <acronym title="Yahoo! User Interface">YUI</acronym> compressor can also minify <acronym title="Cascading Style Sheet">CSS</acronym>.</p>
|
196 |
-
|
197 |
Â
<p>In addition to minifying external scripts and styles, inline <script> and <style> blocks can and should also be minified. Even if you <acronym title="GNU zip">gzip</acronym> your scripts and styles, minifying them will still reduce the size by 5% or more. As the use and size of JavaScript and <acronym title="Cascading Style Sheet">CSS</acronym> increases so will the savings gained by minifying your code."</p>
|
198 |
Â
<cite><a href="http://developer.yahoo.com/performance/rules.html#minify" target="_blank">developer.yahoo.com</a></cite> </blockquote>
|
199 |
-
|
200 |
-
|
201 |
Â
We use: <a href="http://code.google.com/p/minify/" target="_blank">minify</a> but may support various engines in the future. Based on <a href="http://ejohn.org/" target="_blank">John Resig's</a> suggestion we're currently looking at <a href="http://yuilibrary.com/projects/yuicompressor/wiki" target="_blank"><acronym title="Yahoo! User Interface">YUI</acronym> Compressor</a> also.</p>
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
Â
Definitely. Removing white space from your files make <acronym title="GNU zip">gzip</acronym> and deflate (<acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression) more effective.</p>
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
Â
<p id="q31"><strong>Who in the world uses memcached or <acronym title="Alternative PHP Cache">APC</acronym> etc anyway?</strong><br />
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
Â
Yes, especially if you have a cluster and many WordPress installations or a WordPress <acronym title="Multi-User">MU</acronym> installation, then plugin is for you. It will allow you to move easily from multiple installations to WordPress <acronym title="Multi-User">MU</acronym> and continue to use multiple <acronym title="Hypertext Transfer Protocol">HTTP</acronym>, Database, Network Attached Storage etc servers in any configuration you wish. You can also specify as many memcached servers as you wish, although you cannot yet delegate a memcached server to a specific type of caching, i.e. there's no pool management yet.</p>
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
Â
<p>Fact of the matter, there was a time when the semantics and size of your <acronym title="Hypertext Markup Language">HTML</acronym> file (code-to-content ratio), was a factor in a more favorable ranking. <a href="http://microformats.org/wiki/posh" target="_blank"><acronym title="Plain Old Semantic HTML">POSH</acronym></a> <acronym title="Hypertext Markup Language">HTML</acronym> has always been preferred by search engines. In some markets this may still be true, so give the search engines what they want.</p>
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
Â
Yes and no. In general, packed <acronym title="JavaScript">JS</acronym> cannot be minified reliably. Obfuscated <acronym title="JavaScript">JS</acronym> also is hit or miss. A minified and <acronym title="GNU zip">gzip</acronym>ped <acronym title="JavaScript">JS</acronym> file will be smaller than a packed file in any case, so using the (uncompressed, unpacked or un obfuscated) developer versions of your plugins is no longer a concern when using this plugin. Alternatively, you can use the non-blocking embed option to continue to use your packed or obfuscated file without minification.</p>
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
Â
It's quite difficult to recall all of the innovators that have shared their thoughts, code and experiences in the blogosphere over the years, but here are some names to get you started:</p>
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
Â
<p><!--[if lte IE 8]><link rel="stylesheet" type="text/css" href="/wp-content/themes/default/lte.css" media="screen,projection" /><![endif]--></p>
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
Â
<p id="q52" align="right"><a href="#toc">back to top</a></p>
|
327 |
Â
<p><strong>I have some <acronym title="Cascading Style Sheet">CSS</acronym> classes with declarations being overwritten or <acronym title="JavaScript">JS</acronym> with dependencies, do I really have to copy and paste all my <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> file settings around?</strong><br />
|
328 |
Â
No, you can drag and drop them into the desired order on the minify settings page.</p>-->
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
Â
Right now we do not show the statistics in <acronym title="WordPress">WP</acronym> Admin, but soon we will provide graphs of: Page Cache Memory Use, Page Cache Hits/Misses, <acronym title="Database">DB</acronym> Cache Memory Use, <acronym title="Database">DB</acronym> Hits/Misses, Average Page Compression Savings, Average <acronym title="Cascading Style Sheet">CSS</acronym> Compression Savings, Average <acronym title="JavaScript">JS</acronym> Compression Savings, Average Requests per Second, and Average Page Execution Time.</p>
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
Â
<p id="q62"><strong>Which features can I use if I haven't yet installed <acronym title="Alternative PHP Cache">APC</acronym> or memcached?</strong><br />
|
361 |
Â
Memory caching will not be possible. However you will be able to use minify as well <acronym title="Content Delivery Network">CDN</acronym> functionality without issue. Remember that W3 Total Cache is not compatible with other caching plugins, so you'll want to install <acronym title="Alternative PHP Cache">APC</acronym> and/or memcached as soon as possible.</p>
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
</
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
<
|
409 |
-
|
410 |
-
<
|
411 |
-
<
|
412 |
-
|
413 |
-
<
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
</
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
<
|
431 |
-
|
432 |
-
|
433 |
-
<
|
434 |
-
|
435 |
-
<p id="q80"><strong>Is this plugin compatible with varnish or squid?</strong><br />
|
436 |
-
We are still testing the performance of this plugin with <a href="http://varnish.projects.linpro.no/" target="_blank">varnish</a>. It currently appears that varnish is not necessary when this plugin fully utilized, even when using apache versus litespeed or lig<acronym title="Hypertext Transfer Protocol">HTTP</acronym>d due to the concurrency achieved by memory access for all objects required to handle requests. We have not tested <a href="http://www.squid-cache.org/" target="_blank">squid</a> with our plugin.</p>
|
437 |
-
<p align="right"><a href="#toc">back to top</a></p>
|
438 |
-
<p id="q81"><strong>My server is state of the art with 15,000 RPM RAID, why do I need to cache anything in memory?</strong><br />
|
439 |
-
Even if your server was using an array of solid state disks (SSD), your server's <acronym title="Random Access Memory">RAM</acronym> is still going to be faster and introduce less overhead to access than even the fastest solid state drives on a PCIe bus. If you didn't invest in solid state disks for your server, then even worse off - at least an order of magnitude speed difference in read operations in <acronym title="Random Access Memory">RAM</acronym> versus HDD. For write operations delta the latency differences is even more pronounced. <acronym title="Random Access Memory">RAM</acronym> is the winner hands down. We won't even discuss the blocking and arbitration issues that happen with disk arrays under certain circumstances.</p>
|
440 |
-
<p align="right"><a href="#toc">back to top</a></p>
|
441 |
Â
<p id="q82"><strong>Why would I choose <acronym title="Alternative PHP Cache">APC</acronym> over memcached or vice versa?</strong><br />
|
442 |
Â
There's no straight answer for this one. Since WordPress is a PHP-based application, we encourage everyone to install <acronym title="Alternative PHP Cache">APC</acronym> and subsequently realize a minimum of 10x performance gain. It will obviously make our plugin faster as well, so again please check out the installation instructions if you do not already use <acronym title="Alternative PHP Cache">APC</acronym>. Once installed, you can select <acronym title="Alternative PHP Cache">APC</acronym> as your caching engine in our plugin and get back to blogging.</p>
|
443 |
Â
<p><acronym title="Alternative PHP Cache">APC</acronym>'s only weakness is that if you frequently restart your web server (e.g. apache) especially during high traffic periods, you will lose your cache and your site will slow down as it rebuilds the cache (which happens very quickly). However if you use memcached you would not lose your cache if your web server is restarted. It would appear that using <acronym title="Alternative PHP Cache">APC</acronym> for all cases is best, but your mileage may vary. So depending on what software you install and how you manage your server, you can choose the options to fit your needs.</p>
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
Â
Probably the hardest question of all. At the time of this writing the default WordPress install and theme will consume about 50MB of memory in an <acronym title="Alternative PHP Cache">APC</acronym> cache while running our plugin. Keep in mind that the following factors will determine the minimum size of your cache beyond this noted 50MB:</p>
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
Â
Version 4.3 is supported, version 5 preferred (it's much much faster especially with <acronym title="Alternative PHP Cache">APC</acronym>).</p>
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
Â
We feel that shared or virtual hosting providers will begin offering secure containers (similar to what <a href="http://mediatemple.net/" target="_blank">mediatemple.net</a> does for mySQL and Ruby etc) for <acronym title="Alternative PHP Cache">APC</acronym> and memcached. Whoever brings this offering to market first will lower the bar for more web sites/applications (and startups) to build better performing applications with greater ease. The same hosting provider would also possess a new value added service, thereby realizing a competitive advantage in a highly competitive marketplace. Not to mention be able to increase the density of domains per server (or cluster) without shortchanging customers.</p>
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
</div>
|
1 |
+
<h3><acronym title="Frequently Asked Questions">FAQ</acronym></h3>
|
2 |
+
|
3 |
+
<h4>Table of Contents</h4>
|
4 |
+
|
5 |
+
<div id="toc">
|
6 |
+
<ul>
|
7 |
+
<li class="col">
|
8 |
+
<h5>GENERAL:</h5>
|
9 |
+
<ul>
|
10 |
+
<li><a href="#q1">Who is this plugin for?</a></li>
|
11 |
+
<li><a href="#q2">Umm, why?</a></li>
|
12 |
+
<li><a href="#q3">So give me the skinny, what are the highlights?</a></li>
|
13 |
+
<li><a href="#q4">I've never heard of any of this stuff; my blog is fine, no one complains about the speed. Why should I install this?</a></li>
|
14 |
+
<li><a href="#q5">But even Matt Mullenweg doesn't agree that additional caching is so important, why bother?</a></li>
|
15 |
+
<li><a href="#q6">And how many years of university do I need to use this thing?</a></li>
|
16 |
+
<li><a href="#q7">Ok, so the benefits are clear. What exactly is so special about *how* this plugin works?</a></li>
|
17 |
+
<li><a href="#q8">Why would I want to cache my feeds?</a></li>
|
18 |
+
<li><a href="#q9">Why would I want to put my <acronym title="JavaScript">JS</acronym> at the bottom of the page?</a></li>
|
19 |
+
<li><a href="#q10">What's an Etag and why do I need one?</a></li>
|
20 |
+
<li><a href="#q11">So let me get this straight; you're telling me this plugin is designed to improve performance of any WordPress blog?</a></li>
|
21 |
+
<li><a href="#q12">This is too good to be true, how can I test the results?</a></li>
|
22 |
+
<li><a href="#q13">Does this plugin work with WordPress <acronym title="Multi-User">MU</acronym>?</a></li>
|
23 |
+
<li><a href="#q14">Does this plugin work with BuddyPress (bbPress)?</a></li>
|
24 |
+
<li><a href="#q15">Which WordPress versions are supported?</a></li>
|
25 |
+
<li><a href="#q16">I understand the database caching and the page caching, but what's minify all about?</a></li>
|
26 |
+
<li><a href="#q17">What do you use to minify?</a></li>
|
27 |
+
<li><a href="#q18">What's the point of downloading and caching 3rd party files (e.g. <acronym title="JavaScript">JS</acronym>)?</a></li>
|
28 |
+
<li><a href="#q19">Will you support other memory or opcode caches</a>?</li>
|
29 |
+
<li><a href="#q20">Will this plugin break my theme by changing the order of conditional statements or the like?</a></li>
|
30 |
+
<li><a href="#q21">Will this speed up <acronym title="WordPress">WP</acronym> Admin?</a></li>
|
31 |
+
<li><a href="#q22">Does this plugin modify how the WordPress core works?</a></li>
|
32 |
+
<li><a href="#q23">Does it really matter if I remove the line breaks from my code?</a></li>
|
33 |
+
<li><a href="#q24">What's the benefit of removing <acronym title="Hypertext Markup Language">HTML</acronym> comments from my code?</a></li>
|
34 |
+
<li><a href="#q25">Why is <link> used to embed <acronym title="Cascading Style Sheet">CSS</acronym> instead of <style>?</a></li>
|
35 |
+
<li><a href="#q26">Why do I care of <acronym title="JavaScript">JS</acronym> or <acronym title="Cascading Style Sheet">CSS</acronym> is "blocking" or not?</a></li>
|
36 |
+
<li><a href="#q27">What does this plugin do to inline <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym>?</a></li>
|
37 |
+
<li><a href="#q28">Ok I get it, this all sounds nice and everything, but is this perfect?</a></li>
|
38 |
+
<li><a href="#q29">Seriously, tell me what the downside is, there must be something?</a></li>
|
39 |
+
<li><a href="#q30">If this plugin does everything you claim, why would you give it away free? Cui Bono?</a></li>
|
40 |
+
<li><a href="#q31">Who in the world uses memcached or <acronym title="Alternative PHP Cache">APC</acronym> etc anyway?</a></li>
|
41 |
+
<li><a href="#q32">I don't understand what a <acronym title="Content Delivery Network">CDN</acronym> has to do with caching, that's completely different, no?</a></li>
|
42 |
+
<li><a href="#q33">We run many blogs on many servers here at my company, is this plugin still for me?</a></li>
|
43 |
+
<li><a href="#q34">So you appear to know what you're talking about, will there be any negative effect on my SEO rankings?</a></li>
|
44 |
+
<li><a href="#q35">Will the plugin interfere with other plugins or widgets?</a></li>
|
45 |
+
<li><a href="#q36">What about my robots.txt, sitemap.xml and all my site verification files etc, what happens with those?</a></li>
|
46 |
+
<li><a href="#q37">Do you have any tricks for "post-loading", "lazy-loading" and other render optimizations in this plugin?</a></li>
|
47 |
+
<li><a href="#q38">I want to obfuscate my <acronym title="JavaScript">JS</acronym>, does the plugin do that? Will it ever?</a></li>
|
48 |
+
<li><a href="#q39">Can I use packed or obfuscated <acronym title="JavaScript">JS</acronym> with this plugin?</a></li>
|
49 |
+
<li><a href="#q40">I have some ideas for more features, can I write my own add-ons for your plugin?</a></li>
|
50 |
+
<li><a href="#q41">Who do I thank for all of this?</a></li>
|
51 |
+
</ul>
|
52 |
+
</li>
|
53 |
+
<li class="col">
|
54 |
+
<h5>USAGE:</h5>
|
55 |
+
<ul>
|
56 |
+
<li><a href="#q42">So how do I find the <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> to optimize them with this plugin?</a></li>
|
57 |
+
<li><a href="#q43">I've used the plugin to optimize all my theme's <acronym title="JavaScript">JS</acronym> and plugins <acronym title="JavaScript">JS</acronym>, but there are some function calls, where do those go?</a></li>
|
58 |
+
<li><a href="#q44">Can I use scripts that generate <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> with this plugin?</a></li>
|
59 |
+
<li><a href="#q45">In the past, I always had to modify my theme to run dynamic code. Don't I need to do that again for this plugin?</a></li>
|
60 |
+
<li><a href="#q46">How fast will the cache be updated?</a></li>
|
61 |
+
<li><a href="#q47">How do I make some specific pages stay dynamic?</a></li>
|
62 |
+
<li><a href="#q48">What about comments? Does the plugin slow down the rate at which comments appear?</a></li>
|
63 |
+
<li><a href="#q49">What if I accidentally specify an incorrect path to a <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> file?</a></li>
|
64 |
+
<li><a href="#q50">Does the plugin automatically remove duplicate <acronym title="JavaScript">JS</acronym>?</a></li>
|
65 |
+
<li><a href="#q51">I've been using the plugin for some time, I updated one of my other plugins and now it doesn't work anymore. What's up?</a></li>
|
66 |
+
<!--<li><a href="#q52">I have some <acronym title="Cascading Style Sheet">CSS</acronym> classes with declarations being overwritten or <acronym title="JavaScript">JS</acronym> with dependencies, do I really have to copy and paste all my <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> file settings around?</a></li>-->
|
67 |
+
<li><a href="#q53">Why does your plugin change the order of my <script> and <link> tags (in the <head>)?</a></li>
|
68 |
+
<li><a href="#q54">I can't read this minified <acronym title="Hypertext Markup Language">HTML</acronym>; can you give me a break please?</a></li>
|
69 |
+
<li><a href="#q55">When are you going to translate this plugin into more languages?</a></li>
|
70 |
+
<li><a href="#q56">I'm not a hardcore developer, can you explain to me how this // and / stuff works and how I should specify the paths for <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files?</a></li>
|
71 |
+
<li><a href="#q57">What about Etags?</a></li>
|
72 |
+
<li><a href="#q58">Which encodings do you support?</a></li>
|
73 |
+
<li><a href="#q59">What's this thing doing? Where are the statistics?</a></li>
|
74 |
+
<li><a href="#q60">How can I tell if it's working? Aren't there any statistics at all?</a></li>
|
75 |
+
<li><a href="#q61">I'm an advanced theme developer and I want to have different combinations of <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> files on different types of pages in my theme; how is this done?</a></li>
|
76 |
+
<li><a href="#q62">Which features can I use if I haven't yet installed <acronym title="Alternative PHP Cache">APC</acronym> or memcached?</a></li>
|
77 |
+
<li><a href="#q63">How can I serve my favicon from the <acronym title="Content Delivery Network">CDN</acronym>?</a></li>
|
78 |
+
<li><a href="#q64">Why do you set the value of the media attribute of <link> to all?</a></li>
|
79 |
+
<li><a href="#q65">Why can't I specify other <script> types or encoding?</a></li>
|
80 |
+
<li><a href="#q66">My theme doesn't call wp_head() or wp_footer(), how do I set this plugin up?</a></li>
|
81 |
+
<li><a href="#q67">Is this plugin compatible with other popular caching plugins?</a></li>
|
82 |
+
<li><a href="#q68">Some WordPress caching plugins fail when markup is not well-formed, is this plugin similar?</a></li>
|
83 |
+
<li><a href="#q69">Won't various 3rd parties who's <acronym title="JavaScript">JS</acronym> I download and cache be concerned?</a></li>
|
84 |
+
<li><a href="#q70">Google already minified and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compressed jQuery (and other libraries ) for me, why can't I just use their bandwidth and embed other code after it?</a></li>
|
85 |
+
<li><a href="#q71">I wanted to use a different version jQuery with my theme, how do I replace WordPress' jQuery with Google's minified version using your plugin?</a></li>
|
86 |
+
<li><a href="#q72">What about the wp-includes files, can those be served from the <acronym title="Content Delivery Network">CDN</acronym>?</a></li>
|
87 |
+
<li><a href="#q73">What if I don't want to work with a <acronym title="Content Delivery Network">CDN</acronym> right now, is there any other use for this feature?</a></li>
|
88 |
+
<li><a href="#q74">Are minified files uploaded to my <acronym title="Content Delivery Network">CDN</acronym> provider?</a></li>
|
89 |
+
<li><a href="#q75">Who do you recommend as a <acronym title="Content Delivery Network">CDN</acronym> provider?</a></li>
|
90 |
+
<li><a href="#q76">Hang on, don't I need to modify my <acronym title="Cascading Style Sheet">CSS</acronym> files so they'll work on the <acronym title="Content Delivery Network">CDN</acronym>?</a></li>
|
91 |
+
<li><a href="#q77">I don't have time to deal with this, but I know I need it. Will you help me?</a></li>
|
92 |
+
</ul>
|
93 |
+
</li>
|
94 |
+
<li class="col">
|
95 |
+
<h5>WEB HOSTING & REQUIREMENTS:</h5>
|
96 |
+
<ul>
|
97 |
+
<li><a href="#q78">Which web servers do you support?</a></li>
|
98 |
+
<li><a href="#q79">Do I need to enable mod_gzip, mod_rewrite or install any <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression software on my server?</a></li>
|
99 |
+
<li><a href="#q80">Is this plugin compatible with varnish or squid?</a></li>
|
100 |
+
<li><a href="#q81">My server is state of the art with 15,000 <acronym title="Rotations per Minute">RPM</acronym> <acronym title="Redundant Array of Independent Disks">RAID</acronym>, why do I need to cache anything in memory?</a></li>
|
101 |
+
<li><a href="#q82">Why would I choose <acronym title="Alternative PHP Cache">APC</acronym> over memcached or vice versa?</a></li>
|
102 |
+
<li><a href="#q83">I already use <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression on my server, why does it matter if I minify my code?</a></li>
|
103 |
+
<li><a href="#q84">How much memory (<acronym title="Random Access Memory">RAM</acronym>) do I need to delegate to caching?</a></li>
|
104 |
+
<li><a href="#q85">What version of <acronym title="Hypertext Preprocessor">PHP</acronym> do I need for this thing?</a></li>
|
105 |
+
<li><a href="#q86">What version of mySQL is needed?</a></li>
|
106 |
+
<li><a href="#q87">And I need mod_rewrite (or equivalent for my web server) installed too, no?</a></li>
|
107 |
+
<li><a href="#q88">How much hardware do I have to throw at something like this before I see a benefit?</a></li>
|
108 |
+
<li><a href="#q89">Is this plugin server cluster and load balancer friendly?</a></li>
|
109 |
+
<li><a href="#q90">I'm a web hosting provider and I heard about this plugin from my clients, is this plugin safe for a shared hosting environment?</a></li>
|
110 |
+
<li><a href="#q91">What is the intended impact of this plugin on the web hosting landscape?</a></li>
|
111 |
+
</ul>
|
112 |
+
</li>
|
113 |
+
</ul>
|
114 |
+
</div>
|
115 |
+
<div id="qa">
|
116 |
+
<hr />
|
117 |
+
<p id="q1"><strong>Who is this plugin for?</strong><br />
|
118 |
+
Anyone that wants to provide an optimal user experience to their readers.</p>
|
119 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
120 |
+
<p id="q2"><strong>Umm, why?</strong><br />
|
121 |
+
We needed an elegant remedy to common performance issues we spent countless hours addressing on various blogs we work with. They all suffered from similar issues and we found that same remedies would sort all of them. Issues like <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transaction reduction, object size reduction and blocking objects are performance killers and have been remedied with this plugin. Rather than release our various plugins individually (and support them independently) we saw an opportunity to demonstrate how all of this functionality is intertwined and combines to realize far more than the sum of its parts.</p>
|
122 |
+
<p>One of the WordPress community's strengths is also its weakness; we found that numerous plugins are very handy and save some development time in a pinch, but the maintenance and performance penalties blogs suffer from as a result contribute to a poor user experience, which is never acceptable.</p>
|
123 |
+
<p>Experience has shown that fast loading web sites have (at least) the following characteristics:</p>
|
124 |
+
<ul>
|
125 |
+
<li>Reduced <a href="http://en.wikipedia.org/wiki/Customer_attrition" target="_blank">attrition</a></li>
|
126 |
+
<li>Higher conversion rates for e-commerce / affiliate etc sites</li>
|
127 |
+
<li>Increased time on site /more page views per visitor</li>
|
128 |
+
</ul>
|
129 |
+
<p><em>In fact, if wordpress.com (for example) applied some of the techniques used in this plugin, we imagine they'd realize ~10% performance improvement on the <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> and <acronym title="Hypertext Markup Language">HTML</acronym> (respectively) on the millions of blogs they host.</em></p>
|
130 |
Â
<p>As a practical matter, Akamai and JupiterResearch did a study on <a href="http://www.akamai.com/html/about/press/releases/2006/press_110606.html" target="_blank">acceptable wait time for retail web sites</a> to load back in late 2006 concluding that users may leave after 4 seconds of waiting. That was several years ago now, even before 3G was available for mobile devices, what do you think web users expect today? <a href="http://blogs.zdnet.com/BTL/?p=3925" target="_blank">According to Marissa Mayer</a> of Google, as she stated the same year as Akamai, improving the speed of sites/applications reduces the learning curve for applications and contributes to higher use. It's time to bring the performance major corporations enjoy to the blogosphere.</p>
|
131 |
+
<p>As an aside, don't you think your site's <acronym title="Key Performance Indicators">KPI</acronym> would be more meaningful if you could be confident that all users were having the exact same performance experience with your site? It's too early to say for sure, but we feel that the statistics and metrics we all use to track our progress and results will be more realistic when W3 Total Cache is actively removing bottlenecks from our blogs.</p>
|
132 |
+
<p><a href="mailto:wordpressexperts@w3-edge.com">Please let us know</a> what kind of mileage you have.</p>
|
133 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
134 |
+
<p id="q3"><strong>So give me the skinny, what are the highlights?</strong><br />
|
135 |
+
W3 Total Cache is a suite of functionality designed to optimize the performance of all WordPress blogs. Features and benefits include:</p>
|
136 |
+
<ul>
|
137 |
+
<li>Improved progressive render (non-blocking <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> embedding)</li>
|
138 |
+
<li>Reduced <acronym title="Hypertext Transfer Protocol">HTTP</acronym> Transactions, <acronym title="Domain Name System">DNS</acronym> lookups, reduced document load time</li>
|
139 |
+
<li>Transparent content delivery network (<acronym title="Content Delivery Network">CDN</acronym>) support with automated media library import</li>
|
140 |
Â
<li>Bandwidth savings via <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate) for <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym></li>
|
141 |
+
<li>Minification (concatenation, white space removal) of inline, external or 3rd party <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> with scheduled updates</li>
|
142 |
+
<li>Optional embedding of <acronym title="JavaScript">JS</acronym> just above </body></li>
|
143 |
Â
<li>Support for caching pages, posts, feeds, database objects, <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> in memory with <acronym title="Alternative PHP Cache">APC</acronym> or memcached or both</li>
|
144 |
+
<li>Caching of RSS/Atom Feeds (Comments, Page and site), URIs with query string variables (like search result pages), Database queries, Pages, Posts, <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym></li>
|
145 |
+
<li>Complete header management including Etags</li>
|
146 |
+
<li>Increased web server concurrency and reduced resource consumption, increased scale</li>
|
147 |
+
</ul>
|
148 |
+
<p>In essence, anything that can be automated to squeeze out every bit of server performance and minimize bandwidth utilization has been done, leaving your readers with an optimized user experience.</p>
|
149 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
150 |
+
<p id="q4"><strong>I've never heard of any of this stuff; my blog is fine, no one complains about the speed. Why should I install this?<br />
|
151 |
+
</strong>Rarely do readers take the time to complain. They typically just stop browsing earlier than you'd prefer and may not return altogether. It's in every web site owner's best interest is to make sure that the performance of your blog is not hindering its success.</p>
|
152 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
153 |
+
<p id="q5"><strong>But even Matt Mullenweg doesn't agree that additional caching is so important, why bother?</strong><br />
|
154 |
+
You're right, <a href="http://ma.tt/2008/03/wordpress-is-open-source/#comment-439787" target="_blank">Matt did say that</a>. However, this plugin provides more than just "caching". Because he is correct, the web is dynamic and must remain so. But as we explain throughout this FAQ, our goal is to improve the performance of any blog. Furthermore, some techniques we use are well documented from past <a href="http://www.slideshare.net/bazza/high-performance-wordpress" target="_blank">WordCamp presentations</a>; we combined them in a way that we have found stands up to the highest traffic spikes.</p>
|
155 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
156 |
+
<p id="q6"><strong>And how many years of university do I need to use this thing?</strong><br />
|
157 |
+
-4 — That's right; a youngster in junior high school can get started with this plugin. Seriously, if you did your own WordPress install or have ever installed a plugin before you're in good shape. If you need help, <a href="mailto:wordpressexperts@w3-edge.com">let us know</a> or perhaps we'll make some videos or the like.</p>
|
158 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
159 |
+
<p id="q7"><strong>Ok, so the benefits are clear. What exactly is so special about *how* this plugin works?</strong><br />
|
160 |
+
Thanks for asking. We just decided not try to use the typical WordPress hooks and methodologies to implement our features, instead we take the normal output and perform optimizations to it before we send it to the user agent using a method they support and then cache the result afterwards. This concept is applied to objects you decide to cache.</p>
|
161 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
162 |
+
<p id="q8"><strong>Why would I want to cache my feeds?</strong><br />
|
163 |
+
We feel that caching objects after the first request and checking for updates before responding subsequent requests (which is kind of how web browsers work too) creates more opportunities for interesting applications and mashups where the blogosphere doesn't require institutional investment to be able to handle developers making hundreds of requests every day the same way we use Google, Twitter and Facebook (for example) APIs today. Think about it, even when major search engines crawl your site, they have to be "gentle" so they don't bring it down, let's turn the paradigm around so that every blog can deliver content in real-time in various formats.</p>
|
164 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
165 |
+
<p id="q9"><strong>Why would I want to put my <acronym title="JavaScript">JS</acronym> at the bottom of the page?</strong><br />
|
166 |
+
First let me point out that in many cases we suggest putting all the <acronym title="JavaScript">JS</acronym> that's not required for interactivity with your site at the bottom of the document. Anything <acronym title="JavaScript">JS</acronym> that makes the site work as intended we suggested embedding in the <head>. Depending on your specific situation, having the majority of your <acronym title="JavaScript">JS</acronym> at the bottom of the document will mean that your visitors won't have to download things they don't want to begin interacting with your site or reading it's content. Quite often the additional <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transaction is worthwhile.</p>
|
167 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
168 |
+
<p id="q10"><strong>What's an Etag and why do I need one?</strong><br />
|
169 |
+
Etags were created to add more reliability to client side caching my providing a simple method for a browser to verify that a file had not changed since last it was downloaded. Using them enables your server to return 304 or "not modified" responses instead of other responses which are much much slower. The result is a visitor viewing multiple pages of your site would have that "instant loading" experience that we all definitely enjoy. Don't worry we don't use inodes to create our Etags so this solution is reliable for multi server hosting solutions.</p>
|
170 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
171 |
+
<p id="q11"><strong>So let me get this straight; you're telling me this plugin is designed to improve performance of any WordPress blog?</strong><br />
|
172 |
+
Precisely, that is unless you don't write any posts in your blog nor have any readers. If you're someone that's always into the latest web development technique or plugin, now you can "have it all" without making your readers suffer.</p>
|
173 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
174 |
+
<p id="q12"><strong>This is too good to be true, how can I test the results?</strong><br />
|
175 |
+
You will be able to see it instantly on each page load, but for tangible metrics, consider the following tools:</p>
|
176 |
+
<ul>
|
177 |
+
<li><a href="http://www.mozilla.com/firefox/" target="_blank">Firefox</a> + <a href="http://getfirebug.com/" target="_blank">Firebug</a> + <a href="http://developer.yahoo.com/yslow/" target="_blank">Yahoo! YSlow</a></li>
|
178 |
+
<li><a href="http://www.gomez.com/instant-test-pro/" target="_blank">Gomez Instant Test Pro</a></li>
|
179 |
+
<li><a href="http://www.webpagetest.org/test" target="_blank">WebPagetest</a></li>
|
180 |
+
<li><a href="http://www.port80software.com/tools/compresscheck.asp" target="_blank">Port80 Compression Check</a> (requires <acronym title="Microsoft Internet Explorer">MSIE</acronym>6 support to be enabled)</li>
|
181 |
+
<li><a href="http://www.gidnetwork.com/tools/gzip-test.php" target="_blank">A simple online web page compression / deflate / <acronym title="GNU zip">gzip</acronym> test tool</a></li>
|
182 |
+
<li><a href="http://www.websiteoptimization.com/services/analyze/" target="_blank">Web Page Analyzer</a></li>
|
183 |
+
</ul>
|
184 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
185 |
Â
<p id="q13"><strong>Does this plugin work with WordPress <acronym title="Multi-User">MU</acronym>?</strong><br />
|
186 |
+
Indeed it does.</p>
|
187 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
188 |
+
<p id="q14"><strong>Does this plugin work with BuddyPress (bbPress)?</strong><br />
|
189 |
+
Not sure, we'll get to that soon.</p>
|
190 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
191 |
+
<p id="q15"><strong>Which WordPress versions are supported?</strong><br />
|
192 |
+
To use all features in the suite, a minimum of version 2.5 is required. Earlier versions will benefit from our Media Library Importer to get them back on the upgrade path and into a <acronym title="Content Delivery Network">CDN</acronym> of their choosing.</p>
|
193 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
194 |
+
<p id="q16"><strong>I understand the database caching and the page caching, but what's minify all about?</strong><br />
|
195 |
Â
We'll just quote the fine folks at yahoo on this one:</p>
|
196 |
+
<blockquote>
|
197 |
Â
<p>"Minification is the practice of removing unnecessary characters from code to reduce its size thereby improving load times. When code is minified all comments are removed, as well as unneeded white space characters (space, newline, and tab). In the case of JavaScript, this improves response time performance because the size of the downloaded file is reduced. Two popular tools for minifying JavaScript code are <a href="http://www.crockford.com/javascript/jsmin.html" target="_blank"><acronym title="JavaScript">JS</acronym>Min</a> and <a href="http://developer.yahoo.com/yui/compressor/" target="_blank"><acronym title="Yahoo! User Interface">YUI</acronym> Compressor</a>. The <acronym title="Yahoo! User Interface">YUI</acronym> compressor can also minify <acronym title="Cascading Style Sheet">CSS</acronym>.</p>
|
198 |
+
<p>Obfuscation is an alternative optimization that can be applied to source code. It's more complex than minification and thus more likely to generate bugs as a result of the obfuscation step itself. In a survey of ten top U.S. web sites, minification achieved a 21% size reduction versus 25% for obfuscation. Although obfuscation has a higher size reduction, minifying JavaScript is less risky.</p>
|
199 |
Â
<p>In addition to minifying external scripts and styles, inline <script> and <style> blocks can and should also be minified. Even if you <acronym title="GNU zip">gzip</acronym> your scripts and styles, minifying them will still reduce the size by 5% or more. As the use and size of JavaScript and <acronym title="Cascading Style Sheet">CSS</acronym> increases so will the savings gained by minifying your code."</p>
|
200 |
Â
<cite><a href="http://developer.yahoo.com/performance/rules.html#minify" target="_blank">developer.yahoo.com</a></cite> </blockquote>
|
201 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
202 |
+
<p id="q17"><strong>What do you use to minify?</strong><br />
|
203 |
Â
We use: <a href="http://code.google.com/p/minify/" target="_blank">minify</a> but may support various engines in the future. Based on <a href="http://ejohn.org/" target="_blank">John Resig's</a> suggestion we're currently looking at <a href="http://yuilibrary.com/projects/yuicompressor/wiki" target="_blank"><acronym title="Yahoo! User Interface">YUI</acronym> Compressor</a> also.</p>
|
204 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
205 |
+
<p id="q18"><strong>What's the point of downloading and caching 3rd party files (e.g. <acronym title="JavaScript">JS</acronym>)?</strong><br />
|
206 |
+
With the various hosted 3rd party applications available (from web site statistics to social media sharing widgets), the problems we've noticed are: additional <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transactions, <acronym title="Domain Name System">DNS</acronym> lookups and latencies from busy servers that we can't control and often un-minified files with no <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression all add up to a very slow page load and poor user experience. With your own copy of external files, updated as frequently as you wish, none of these problems exist.</p>
|
207 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
208 |
+
<p id="q19"><strong>Will you support other memory or </strong><a href="http://en.wikipedia.org/wiki/PHP_accelerator" target="_blank"><strong>opcode caches</strong></a><strong>?</strong><br />
|
209 |
+
Possibly, we just <a href="mailto:wordpressexperts@w3-edge.com">need to know which</a> others are popular in the WordPress community and we will address them.</p>
|
210 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
211 |
+
<p id="q20"><strong>Will this plugin break my theme by changing the order of conditional statements or the like?</strong><br />
|
212 |
+
No, the plugin looks for conditional statements in your markup used for <acronym title="Cascading Style Sheet">CSS</acronym> (and sometimes <acronym title="JavaScript">JS</acronym>) and makes sure that the minified files precede it, so keep that in mind.</p>
|
213 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
214 |
+
<p id="q21"><strong>Will this speed up <acronym title="WordPress">WP</acronym> Admin?</strong><br />
|
215 |
+
Yes, indirectly — if you have a lot of bloggers working with you, you will find that it feels like you have a server dedicated only to <acronym title="WordPress">WP</acronym> Admin once this plugin is enabled; the result, increased productivity.</p>
|
216 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
217 |
+
<p id="q22"><strong>Does this plugin modify how the WordPress core works?</strong><br />
|
218 |
+
No. No theme changes, special files, WordPress core file modifications or special permissions need to be set.</p>
|
219 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
220 |
+
<p id="q23"><strong>Does it really matter if I remove the line breaks from my code?</strong><br />
|
221 |
Â
Definitely. Removing white space from your files make <acronym title="GNU zip">gzip</acronym> and deflate (<acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression) more effective.</p>
|
222 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
223 |
+
<p id="q24"><strong>What's the benefit of removing <acronym title="Hypertext Markup Language">HTML</acronym> comments from my code?</strong><br />
|
224 |
+
Many developers like to have comments in the code for various reasons, however these comments add no value from the blog readers (or search engine for that matter) point of view and only contribute to increased load time and wasted bandwidth as a result. Now only you can use them and view them in your site (as a logged in administrator viewing the page source), which is really what (we assume) you intended.</p>
|
225 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
226 |
+
<p id="q25"><strong>Why is <link> used to embed <acronym title="Cascading Style Sheet">CSS</acronym> instead of <style>?</strong><br />
|
227 |
+
<link> is a non-blocking method to embed <acronym title="Cascading Style Sheet">CSS</acronym> into a document. We recommend this approach for optimal performance.</p>
|
228 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
229 |
+
<p id="q26"><strong>Why do I care of <acronym title="JavaScript">JS</acronym> or <acronym title="Cascading Style Sheet">CSS</acronym> is "blocking" or not?</strong><br />
|
230 |
+
In the case of objects (files) you don't host yourself, this could add several seconds to your page's load time as the <acronym title="Domain Name System">DNS</acronym> lookups, <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transaction roundtrip times and wait times add up. Even when all the scripts are hosted locally, the same adversities exist. Since all objects in the <head> of a document have to be ready before the page can be rendered, having them load in a parallel fashion as opposed to linear (or near linear) gives night and day results.</p>
|
231 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
232 |
+
<p id="q27"><strong>What does this plugin do to inline <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym>?</strong><br />
|
233 |
+
Nothing yet. We're evaluating use cases to deal with common issues (like inline <acronym title="Cascading Style Sheet">CSS</acronym> for tag clouds for example).</p>
|
234 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
235 |
+
<p id="q28"><strong>Ok I get it, this all sounds nice and everything, but is this perfect?</strong><br />
|
236 |
+
Pretty much. If you monetize your blog with ads you will want to spend some time making sure that the ad code works well with your optimization settings. There are also the occasional pieces of code that conflict with the others and have to be in a specific order to work well, but that's not a problem that this plugin introduces.</p>
|
237 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
238 |
+
<p id="q29"><strong>Seriously, tell me what the downside is, there must be something?</strong><br />
|
239 |
+
Well, no there isn't. Installing the server side software might be challenging for some, but <a href="mailto:wordpressexperts@w3-edge.com">we can assist</a> with that if you ask. Other than that, unless you enjoy frequently upgrading your server plan or buying more servers and paying for bandwidth overages or wincing every time you add another "must have" plugin to your blog, we cannot find any reason to deter you from the use of this one.</p>
|
240 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
241 |
+
<p id="q30"><strong>If this plugin does everything you claim, why would you give it away free? Cui Bono?</strong><br />
|
242 |
+
Who benefits? Everyone. Of the numerous, here are the three the most important reasons we share with the WordPress community:</p>
|
243 |
+
<ul>
|
244 |
+
<li>WordPress is free and high quality, plugins should be too.</li>
|
245 |
+
<li>There's no reason your blog shouldn't be able to perform as well as well as any major corporation's web site/application.</li>
|
246 |
+
<li><a href="http://code.google.com/speed/articles/" target="_blank">Google</a> and <a href="http://developer.yahoo.com/yui/" target="_blank">Yahoo</a> offer quite a bit, but they did not offer a WordPress solution yet. This is our contribution to speeding up the web (starting with the blogosphere).</li>
|
247 |
+
</ul>
|
248 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
249 |
Â
<p id="q31"><strong>Who in the world uses memcached or <acronym title="Alternative PHP Cache">APC</acronym> etc anyway?</strong><br />
|
250 |
+
Great question! Basically anyone that needs to make their application scale. For example, <a href="http://www.wordpress.com/" target="_blank">WordPress.com</a>, <a href="http://twitter.com" target="_blank">Twitter</a>, <a href="http://www.facebook.com/" target="_blank">Facebook</a>, LiveJournal (the inventors of the software) and so on all use some sort of memory cache to increase application performance.</p>
|
251 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
252 |
+
<p id="q32"><strong>I don't understand what a <acronym title="Content Delivery Network">CDN</acronym> has to do with caching, that's completely different, no?</strong><br />
|
253 |
+
Technically no, a <acronym title="Content Delivery Network">CDN</acronym> is a high performance cache that stores static assets (your theme files, media library etc) in various locations throughout the world in order to provide low latency access to them by readers in those regions. So indeed a <acronym title="Content Delivery Network">CDN</acronym> is a high performance cache, many of which actually store your frequently requested assets in memory for fastest possible response.</p>
|
254 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
255 |
+
<p id="q33"><strong>We run many blogs on many servers here at my company, is this plugin still for me?</strong><br />
|
256 |
Â
Yes, especially if you have a cluster and many WordPress installations or a WordPress <acronym title="Multi-User">MU</acronym> installation, then plugin is for you. It will allow you to move easily from multiple installations to WordPress <acronym title="Multi-User">MU</acronym> and continue to use multiple <acronym title="Hypertext Transfer Protocol">HTTP</acronym>, Database, Network Attached Storage etc servers in any configuration you wish. You can also specify as many memcached servers as you wish, although you cannot yet delegate a memcached server to a specific type of caching, i.e. there's no pool management yet.</p>
|
257 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
258 |
+
<p id="q34"><strong>So you appear to know what you're talking about, will there be any negative effect on my SEO rankings?</strong><br />
|
259 |
+
To answer, first we must assume that you're using all of the options we offer: <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression, minify etc. Having said that, we are only sending compressed data to user agents that support it; even <a href="http://www.google.com/search?q=search+engine+crawler+http+compression" target="_blank">most search engine crawlers do</a>. As for minified <acronym title="Hypertext Markup Language">HTML</acronym>, this is essentially how crawlers see your page anyway when they download it. So no, there's no penalty or compromise.</p>
|
260 |
Â
<p>Fact of the matter, there was a time when the semantics and size of your <acronym title="Hypertext Markup Language">HTML</acronym> file (code-to-content ratio), was a factor in a more favorable ranking. <a href="http://microformats.org/wiki/posh" target="_blank"><acronym title="Plain Old Semantic HTML">POSH</acronym></a> <acronym title="Hypertext Markup Language">HTML</acronym> has always been preferred by search engines. In some markets this may still be true, so give the search engines what they want.</p>
|
261 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
262 |
+
<p id="q35"><strong>Will the plugin interfere with other plugins or widgets?</strong><br />
|
263 |
+
No, on the contrary if you use the minify settings you will improve their performance by several times.</p>
|
264 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
265 |
+
<p id="q36"><strong>What about my robots.txt, sitemap.xml and all my site verification files etc, what happens with those?</strong><br />
|
266 |
+
If you're concerned about what happens with these when the <acronym title="Content Delivery Network">CDN</acronym> functionality is active, nothing does. You do not want or need these files moved from their original locations and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (or minification for that matter) is of no consequence in most cases.</p>
|
267 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
268 |
+
<p id="q37"><strong>Do you have any tricks for "post-loading", "lazy-loading" and other render optimizations in this plugin?</strong><br />
|
269 |
+
Yes we do, we're currently evaluating if they are best introduced into this plugin or as standalones. Feel free to <a href="mailto:wordpressexperts@w3-edge.com">chime in</a>.</p>
|
270 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
271 |
+
<p id="q38"><strong>I want to obfuscate my <acronym title="JavaScript">JS</acronym>, does the plugin do that? Will it ever?</strong><br />
|
272 |
+
No the plugin will not do that and it's unlikely that we'll support that.</p>
|
273 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
274 |
+
<p id="q39"><strong>Can I use packed or obfuscated <acronym title="JavaScript">JS</acronym> with this plugin?</strong><br />
|
275 |
Â
Yes and no. In general, packed <acronym title="JavaScript">JS</acronym> cannot be minified reliably. Obfuscated <acronym title="JavaScript">JS</acronym> also is hit or miss. A minified and <acronym title="GNU zip">gzip</acronym>ped <acronym title="JavaScript">JS</acronym> file will be smaller than a packed file in any case, so using the (uncompressed, unpacked or un obfuscated) developer versions of your plugins is no longer a concern when using this plugin. Alternatively, you can use the non-blocking embed option to continue to use your packed or obfuscated file without minification.</p>
|
276 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
277 |
+
<p id="q40"><strong>I have some ideas for more features, can I write my own add-ons for your plugin?</strong><br />
|
278 |
+
Not yet, we are considering support for add-ons. Meanwhile, please <a href="mailto:wordpressexperts@w3-edge.com">reach out to us</a> and let us know what you think would benefit the community.</p>
|
279 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
280 |
+
<p id="q41"><strong>Who do I thank for all of this?</strong><br />
|
281 |
Â
It's quite difficult to recall all of the innovators that have shared their thoughts, code and experiences in the blogosphere over the years, but here are some names to get you started:</p>
|
282 |
+
<ul>
|
283 |
+
<li><a href="http://mrclay.org/" target="_blank">Steve Clay</a></li>
|
284 |
+
<li><a href="http://wonko.com/" target="_blank">Ryan Grove</a></li>
|
285 |
+
<li><a href="http://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/" target="_blank">Nicholas Zakas</a> </li>
|
286 |
+
<li><a href="http://stevesouders.com/" target="_blank">Steve Souders</a></li>
|
287 |
+
<li><a href="http://rtdean.livejournal.com/" target="_blank">Ryan Dean</a></li>
|
288 |
+
<li><a href="http://gravitonic.com/" target="_blank">Andrei Zmievski</a></li>
|
289 |
+
<li>George Schlossnagle</li>
|
290 |
+
<li>Daniel Cowgill</li>
|
291 |
+
<li><a href="http://toys.lerdorf.com/" target="_blank">Rasmus Lerdorf</a></li>
|
292 |
+
<li><a href="http://t3.dotgnu.info/" target="_blank">Gopal Vijayaraghavan</a></li>
|
293 |
+
</ul>
|
294 |
+
<p>Please reach out to all of these people and support their projects if you're so inclined.</p>
|
295 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
296 |
+
<p id="q42"><strong>So how do I find the <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> to optimize them with this plugin?</strong><br />
|
297 |
+
View your page source in your browser and search for any <style>, <link> or <script> tags that contain external <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> files and one by one add them to the minify settings page. Do not include any <acronym title="Cascading Style Sheet">CSS</acronym> in conditional statements (unless you know what you are doing) like:</p>
|
298 |
Â
<p><!--[if lte IE 8]><link rel="stylesheet" type="text/css" href="/wp-content/themes/default/lte.css" media="screen,projection" /><![endif]--></p>
|
299 |
+
<p>The plugin will concatenate, minify, <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compress and check for updates to these files automatically from now on. If you have any <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> that are inline consider making them external files so that you can use them with minify.</p>
|
300 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
301 |
+
<p id="q43"><strong>I've used the plugin to optimize all my theme's <acronym title="JavaScript">JS</acronym> and plugins <acronym title="JavaScript">JS</acronym>, but there are some function calls, where do those go?</strong><br />
|
302 |
+
Just place them above </head> if that's where your embed is done or above </body> if that's where you need them. Wherever they need to be to be called after the <acronym title="JavaScript">JS</acronym> that needs them, it'll be fine.</p>
|
303 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
304 |
+
<p id="q44"><strong>Can I use scripts that generate <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> with this plugin?</strong><br />
|
305 |
+
Yes you can, but since there are numerous ways to do so, so be sure to test your results carefully. Having said that we do encourage it as it will mean that less processing has to be done to deliver your pages.</p>
|
306 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
307 |
+
<p id="q45"><strong>In the past, I always had to modify my theme to run dynamic code. Don't I need to do that again for this plugin?</strong><br />
|
308 |
+
Absolutely not. This plugin doesn't require you to do anything differently to develop or maintain your blog. You'll want to remove any special calls you had in place for your old plugins, although they will be ignored by our plugin in any case.</p>
|
309 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
310 |
+
<p id="q46"><strong>How fast will the cache be updated?</strong><br />
|
311 |
+
Items expire from the cache at a rate that you specify. As far as how fast changes appear to your visitors, they appear instantly in most cases and if you're an administrator who's logged in they will always be immediately visible.</p>
|
312 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
313 |
+
<p id="q47"><strong>How do I make some specific pages stay dynamic?</strong><br />
|
314 |
+
They never stop being dynamic, we just don't create pages that have not been changed. If you have a page that updated frequently in your blog before, it will still remain up-to-date at all times.</p>
|
315 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
316 |
+
<p id="q48"><strong>What about comments? Does the plugin slow down the rate at which comments appear?</strong><br />
|
317 |
+
On the contrary, as with any other action a user can perform on a site, faster performance will encourage more of it. The cache is so quickly rebuilt in memory that it's no trouble to show visitors the most current version of a post that's experiencing Digg, Slashdot, Drudge Report, Yahoo Buzz or Twitter effect.</p>
|
318 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
319 |
+
<p id="q49"><strong>What if I accidentally specify an incorrect path to a <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> file?</strong><br />
|
320 |
+
Unfortunately a 400 bad request error may be generated. So use the "Check URI" button to make sure that you have entered the correct URI or path to the file.</p>
|
321 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
322 |
+
<p id="q50"><strong>Does the plugin automatically remove duplicate <acronym title="JavaScript">JS</acronym>?</strong><br />
|
323 |
+
No. If you include a script in the minfy settings twice or it already exists in your theme we do not automatically remove the extra code. That's tricky business and it's better for us to just let you make the decisions conscientiously.</p>
|
324 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
325 |
+
<p id="q51"><strong>I've been using the plugin for some time, I updated one of my other plugins and now it doesn't work anymore. What's up?</strong><br />
|
326 |
+
It's likely the plugin author modified the <acronym title="JavaScript">JS</acronym> or <acronym title="Cascading Style Sheet">CSS</acronym> in the new release and any old <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> you optimized with our plugin has introduced duplicate code as a result (creating a conflict). Simply check out the source code, identify any new <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> and update your <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> optimizations our plugin and you're good to go.</p>
|
327 |
+
<!--
|
328 |
Â
<p id="q52" align="right"><a href="#toc">back to top</a></p>
|
329 |
Â
<p><strong>I have some <acronym title="Cascading Style Sheet">CSS</acronym> classes with declarations being overwritten or <acronym title="JavaScript">JS</acronym> with dependencies, do I really have to copy and paste all my <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> file settings around?</strong><br />
|
330 |
Â
No, you can drag and drop them into the desired order on the minify settings page.</p>-->
|
331 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
332 |
+
<p id="q53"><strong>Why does your plugin change the order of my <script> and <link> tags (in the <head>)?</strong><br />
|
333 |
+
Steve Souders <a href="http://www.youtube.com/watch?v=oaxZtKAlLRk" target="_blank">identified</a> that placing inline scripts between <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> embeds creates a blocking situation, so we're try to help you avoid that. If you'd like to experiment with various scenarios related specifically to your blog, we recommend Steve's tool, <a href="http://stevesouders.com/cuzillion/" target="_blank">Cuzillion</a>. Have some beneficial input on other common cases for WordPress users? <a href="mailto:wordpressexperts@w3-edge.com">Reach out to us</a>.</p>
|
334 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
335 |
+
<p id="q54"><strong>I can't read this minified <acronym title="Hypertext Markup Language">HTML</acronym>; can you give me a break please?</strong><br />
|
336 |
+
Happy to! Login as an administrator, go to the Minify Settings page and check off "Show un-minified pages to administrators" and save the changes. Now stay logged in as an administrator in the same browser you used to change the settings and now when you view the source of a given page in the site, the source will not be minified.</p>
|
337 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
338 |
+
<p id="q55"><strong>When are you going to translate this plugin into more languages?</strong><br />
|
339 |
+
When you help us! :-) Localization is tricky and we're happy to work with those willing to support the WordPress community. We will most likely follow the <a href="http://en.wordpress.com/stats/" target="_blank">trends of WordPress</a> itself to determine which languages are addressed first.</p>
|
340 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
341 |
+
<p id="q56"><strong>I'm not a hardcore developer, can you explain to me how this // and / stuff works and how I should specify the paths for <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files?</strong><br />
|
342 |
+
You mean on the minify settings page right? Ok, it's simple:<br />
|
343 |
+
// tells the plugin to search for the file with the provided path from the document root, e.g.: //wp-includes/JS/jquery/jquery.<acronym title="JavaScript">JS</acronym><br />
|
344 |
+
/ tells the plugin to search for the file with the provided path from the server root, e.g. /wp-includes/JS/jquery/jquery.<acronym title="JavaScript">JS</acronym></p>
|
345 |
+
<p>In most cases providing an absolute path is sufficient and most reliable. You can of course use relative paths, but we discourage it unless you really know what you are doing.</p>
|
346 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
347 |
+
<p id="q57"><strong>What about Etags?</strong><br />
|
348 |
+
Yes, we have Etags covered. Even if you have a clustered hosting environment, your <a href="http://en.wikipedia.org/wiki/HTTP_ETag" target="_blank">Etags</a> will be consistent (across multiple servers in your cluster) so you don't have to worry about using special session cookies when you introduce our plugin. If you would like to specify headers for various reasons, you can do that as well.</p>
|
349 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
350 |
+
<p id="q58"><strong>Which encodings do you support?</strong><br />
|
351 |
+
We recommend UTF-8, but we do not modify the encoding in any files, instead we simply return the code as it is provided.</p>
|
352 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
353 |
+
<p id="q59"><strong>What's this thing doing? Where are the statistics?</strong><br />
|
354 |
Â
Right now we do not show the statistics in <acronym title="WordPress">WP</acronym> Admin, but soon we will provide graphs of: Page Cache Memory Use, Page Cache Hits/Misses, <acronym title="Database">DB</acronym> Cache Memory Use, <acronym title="Database">DB</acronym> Hits/Misses, Average Page Compression Savings, Average <acronym title="Cascading Style Sheet">CSS</acronym> Compression Savings, Average <acronym title="JavaScript">JS</acronym> Compression Savings, Average Requests per Second, and Average Page Execution Time.</p>
|
355 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
356 |
+
<p id="q60"><strong>How can I tell if it's working? Aren't there any statistics at all?</strong><br />
|
357 |
+
Well yes actually there are. If you're logged in as an administrator they will be appended to the bottom of the source code. Keep in mind that there's a bit of work to show the stats so effort to produce the pages for the visitors is a bit less.</p>
|
358 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
359 |
+
<p id="q61"><strong>I'm an advanced theme developer and I want to have different combinations of <acronym title="Cascading Style Sheet">CSS</acronym> or <acronym title="JavaScript">JS</acronym> files on different types of pages in my theme; how is this done?</strong><br />
|
360 |
+
Great question, we understand the use case all too well. Right now you cannot create different groups of <acronym title="JavaScript">JS</acronym> and <acronym title="Cascading Style Sheet">CSS</acronym> files for your home, page, post, archive or 404 etc. This feature is coming soon; it did not make the first cut.</p>
|
361 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
362 |
Â
<p id="q62"><strong>Which features can I use if I haven't yet installed <acronym title="Alternative PHP Cache">APC</acronym> or memcached?</strong><br />
|
363 |
Â
Memory caching will not be possible. However you will be able to use minify as well <acronym title="Content Delivery Network">CDN</acronym> functionality without issue. Remember that W3 Total Cache is not compatible with other caching plugins, so you'll want to install <acronym title="Alternative PHP Cache">APC</acronym> and/or memcached as soon as possible.</p>
|
364 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
365 |
+
<p id="q63"><strong>How can I serve my favicon from the <acronym title="Content Delivery Network">CDN</acronym>?</strong><br />
|
366 |
+
If the file exists in your document root (i.e. http://domain.com/favicon.ico), the plugin can take care of that for you using custom upload options. If the file is in your theme directory you can also have the plugin uploaded from there.</p>
|
367 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
368 |
+
<p id="q64"><strong>Why do you set the value of the media attribute of <link> to all?</strong><br />
|
369 |
+
In case you were using @media declarations in your document, we'd have you covered. We will likely allow you to modify this attribute as subsequent features are finalized.</p>
|
370 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
371 |
+
<p id="q65"><strong>Why can't I specify other <script> types or encoding?</strong><br />
|
372 |
+
We have not found a use case where this appears to be of any consequence. If you're aware of one <a href="mailto:wordpressexperts@w3-edge.com">please let us know</a>.</p>
|
373 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
374 |
+
<p id="q66"><strong>My theme doesn't call wp_head() or wp_footer(), how do I set this plugin up?</strong><br />
|
375 |
+
The calls you'll want to make for the various cases are:</p>
|
376 |
+
<ul>
|
377 |
+
<li><?php w3tc_scripts('include-footer'); ?><br />
|
378 |
+
Inserts the footer <acronym title="JavaScript">JS</acronym> group at the location you specify in your theme.</li>
|
379 |
+
<li><?php w3tc_scripts('include-footer_nb'); ?><br />
|
380 |
+
Inserts the footer non-blocking <acronym title="JavaScript">JS</acronym> group at the location you specify in your theme.</li>
|
381 |
+
</ul>
|
382 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
383 |
+
<p id="q67"><strong>Is this plugin compatible with other popular caching plugins?</strong><br />
|
384 |
+
No. Any disk based page caching plugin you're currently using would need to be completely uninstalled (not just disabled) in order to use this plugin. So if you have a development environment where you can try this out or testing during low traffic periods to get your preferences set, that is recommended. You can always backup your full WordPress installation before testing pretty quickly if you skip the /uploads/ (media library) directory.</p>
|
385 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
386 |
+
<p id="q68"><strong>Some WordPress caching plugins fail when markup is not well-formed, is this plugin similar?</strong><br />
|
387 |
+
No, this plugin is not similar. While valid <acronym title="Hypertext Markup Language">HTML</acronym> and <acronym title="World Wide Web Consortium">W3C</acronym> standards ensure consistent behavior across user agents and promote accessibility, any invalidity that exist in the code is not going to bring your site to its knees.</p>
|
388 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
389 |
+
<p id="q69"><strong>Won't various 3rd parties who's <acronym title="JavaScript">JS</acronym> I download and cache be concerned?</strong><br />
|
390 |
+
Unlikely, you're saving them bandwidth and using their applications, so they will probably appreciate it as long as their application still works as intended and you're using their software in an authorized manner. Look at it this way, even before this plugin, you and thousands of other people were still downloading it, now you're just downloading it first.</p>
|
391 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
392 |
+
<p id="q70"><strong>Google already minified and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compressed jQuery (and other libraries ) for me, why can't I just use their bandwidth and embed other code after it?</strong><br />
|
393 |
+
You can! Just add Google's script to your minify settings use non-blocking mode and your visitors will download jQuery directly from them as you wish. And the same is obviously true for any other library you wish. Remember you are creating additional <acronym title="Domain Name System">DNS</acronym> Lookups and <acronym title="Hypertext Transfer Protocol">HTTP</acronym> transactions when you do this.</p>
|
394 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
395 |
+
<p id="q71"><strong>I wanted to use a different version jQuery with my theme, how do I replace WordPress' jQuery with Google's minified version using your plugin?</strong><br />
|
396 |
+
Currently you cannot, replacement is not yet supported.</p>
|
397 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
398 |
+
<p id="q72"><strong>What about the wp-includes files, can those be served from the <acronym title="Content Delivery Network">CDN</acronym>?</strong><br />
|
399 |
+
Yes, you can specify which file types you would like served from your <acronym title="Content Delivery Network">CDN</acronym> and they will be uploaded and always downloaded from that location. This includes the smiles, manfest.xml et al. By default we take care of them all.</p>
|
400 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
401 |
+
<p id="q73"><strong>What if I don't want to work with a <acronym title="Content Delivery Network">CDN</acronym> right now, is there any other use for this feature?</strong><br />
|
402 |
+
Yes! You can take advantage of the <a href="http://www.mozilla.org/projects/netlib/http/pipelining-faq.html">pipelining</a> support in some browsers by creating a sub-domain for the static content for your site. So you could create static.domain.com on your server (and update your <acronym title="Domain Name System">DNS</acronym> zone) and then specify the <acronym title="File Transfer Protocol">FTP</acronym> details for it in the plugin configuration panel and you're done. If you disable the scripting options on your server you'll find that your server will actually respond slightly faster from that sub-domain because it's just sending files and not processing them.</p>
|
403 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
404 |
+
<p id="q74"><strong>Are minified files uploaded to my <acronym title="Content Delivery Network">CDN</acronym> provider?</strong><br />
|
405 |
+
Yes, any <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> you manage with the plugin are minified before being uploaded to your <acronym title="Content Delivery Network">CDN</acronym>. You don't have to make any special changes to your theme. We encourage you to make sure that your provider supports <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression as the benefit of having your static assets available from more than one <acronym title="Point of Presence">POP</acronym> alone is not enough.</p>
|
406 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
407 |
+
<p id="q75"><strong>Who do you recommend as a <acronym title="Content Delivery Network">CDN</acronym> provider?</strong><br />
|
408 |
+
That depends on how you use your blog and where most of your readers read your blog (regionally). Here's a shortlist:</p>
|
409 |
+
<ul>
|
410 |
+
<li><a href="http://www.simplecdn.com/" target="_blank">Simple<acronym title="Content Delivery Network">CDN</acronym></a></li>
|
411 |
+
<li><a href="http://www.edgecast.com/" target="_blank">EdgeCast</a></li>
|
412 |
+
<li><a href="http://www.limelightnetworks.com/" target="_blank">Limelight Networks</a></li>
|
413 |
+
<li><a href="http://aws.amazon.com/s3/" target="_blank">Amazon S3</a> / <a href="http://aws.amazon.com/cloudfront/" target="_blank">Cloudfront</a></li>
|
414 |
+
<li><a href="http://www.akamai.com/" target="_blank">Akamai</a></li>
|
415 |
+
<li><a href="http://www.voxel.net/products-services/voxcast-cdn" target="_blank">Voxel</a></li>
|
416 |
+
</ul>
|
417 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
418 |
+
<p id="q76"><strong>Hang on, don't I need to modify my <acronym title="Cascading Style Sheet">CSS</acronym> files so they'll work on the <acronym title="Content Delivery Network">CDN</acronym>?</strong><br />
|
419 |
+
No, that is taken care of for you. Your <acronym title="Cascading Style Sheet">CSS</acronym> files will originate from your <acronym title="Content Delivery Network">CDN</acronym> provider and all paths to any images in your <acronym title="Cascading Style Sheet">CSS</acronym> will be changed from relative to absolute, making sure that they load just fine. Do nothing differently, yet reap all the benefits.</p>
|
420 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
421 |
+
<p id="q77"><strong>I don't have time to deal with this, but I know I need it. Will you help me?</strong><br />
|
422 |
+
Yes! Please <a href="mailto:wordpressexperts@w3-edge.com">reach out to us</a> and we'll get you acclimated so you can "set it and forget it."</p>
|
423 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
424 |
+
<p id="q78"><strong>Which web servers do you support?</strong><br />
|
425 |
+
We are aware of no incompatibilities with <a href="http://httpd.apache.org/" target="_blank">apache</a> 1.3+ or <a href="http://www.iis.net/" target="_blank">IIS</a> 5+. We are still testing <a href="http://nginx.net/" target="_blank">nginx</a>, <a href="http://litespeedtech.com/products/webserver/overview/" target="_blank">litespeed</a> and <a href="http://www.lighttpd.net/" target="_blank">lighttpd</a>. If you have thoughts or an opinion, we're <a href="mailto:wordpressexperts@w3-edge.com">interested in hearing</a>.</p>
|
426 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
427 |
+
<p id="q79"><strong>Do I need to enable mod_gzip, mod_rewrite or install any <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression software on my server?</strong><br />
|
428 |
+
No, but we do find that it does help some rich internet applications to compress their AJAX responses, so you might look at it just for that case.</p>
|
429 |
+
<p>If you're larger organization or a web hosting company, consider looking into solutions that exist like <a href="http://www.gear6.com/">Gear6</a> which could be useful now that you have a plugin that makes management memcached pain free.</p>
|
430 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
431 |
+
<p id="q80"><strong>Is this plugin compatible with varnish or squid?</strong><br />
|
432 |
+
We are still testing the performance of this plugin with <a href="http://varnish.projects.linpro.no/" target="_blank">varnish</a>. It currently appears that varnish is not necessary when this plugin fully utilized, even when using apache versus litespeed or lig<acronym title="Hypertext Transfer Protocol">HTTP</acronym>d due to the concurrency achieved by memory access for all objects required to handle requests. We have not tested <a href="http://www.squid-cache.org/" target="_blank">squid</a> with our plugin.</p>
|
433 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
434 |
+
<p id="q81"><strong>My server is state of the art with 15,000 RPM RAID, why do I need to cache anything in memory?</strong><br />
|
435 |
+
Even if your server was using an array of solid state disks (SSD), your server's <acronym title="Random Access Memory">RAM</acronym> is still going to be faster and introduce less overhead to access than even the fastest solid state drives on a PCIe bus. If you didn't invest in solid state disks for your server, then even worse off - at least an order of magnitude speed difference in read operations in <acronym title="Random Access Memory">RAM</acronym> versus HDD. For write operations delta the latency differences is even more pronounced. <acronym title="Random Access Memory">RAM</acronym> is the winner hands down. We won't even discuss the blocking and arbitration issues that happen with disk arrays under certain circumstances.</p>
|
436 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
437 |
Â
<p id="q82"><strong>Why would I choose <acronym title="Alternative PHP Cache">APC</acronym> over memcached or vice versa?</strong><br />
|
438 |
Â
There's no straight answer for this one. Since WordPress is a PHP-based application, we encourage everyone to install <acronym title="Alternative PHP Cache">APC</acronym> and subsequently realize a minimum of 10x performance gain. It will obviously make our plugin faster as well, so again please check out the installation instructions if you do not already use <acronym title="Alternative PHP Cache">APC</acronym>. Once installed, you can select <acronym title="Alternative PHP Cache">APC</acronym> as your caching engine in our plugin and get back to blogging.</p>
|
439 |
Â
<p><acronym title="Alternative PHP Cache">APC</acronym>'s only weakness is that if you frequently restart your web server (e.g. apache) especially during high traffic periods, you will lose your cache and your site will slow down as it rebuilds the cache (which happens very quickly). However if you use memcached you would not lose your cache if your web server is restarted. It would appear that using <acronym title="Alternative PHP Cache">APC</acronym> for all cases is best, but your mileage may vary. So depending on what software you install and how you manage your server, you can choose the options to fit your needs.</p>
|
440 |
+
<p>If you need help with the install on your dedicated or virtual dedicated linux-based server ask us!</p>
|
441 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
442 |
+
<p id="q83"><strong>I already use <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression on my server, why does it matter if I minify my code?</strong><br />
|
443 |
+
Let's say you had a file of 10240 bytes, which becomes 2048 bytes when compressed, savings of ~80% (typical for <acronym title="Cascading Style Sheet">CSS</acronym> files). That same file will now have an <strong>additional</strong> ~3x-10x transfer speed improvement when minified. That's a big return from a small operation. The larger your files, the more significant the proportional performance gains.</p>
|
444 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
445 |
+
<p id="q84"><strong>How much memory (<acronym title="Random Access Memory">RAM</acronym>) do I need to delegate to caching?</strong><br />
|
446 |
Â
Probably the hardest question of all. At the time of this writing the default WordPress install and theme will consume about 50MB of memory in an <acronym title="Alternative PHP Cache">APC</acronym> cache while running our plugin. Keep in mind that the following factors will determine the minimum size of your cache beyond this noted 50MB:</p>
|
447 |
+
<ul>
|
448 |
+
<li>Number of typically requested pages per day (if your blog is popular this number is quite large)</li>
|
449 |
+
<li>Size of minified <acronym title="Cascading Style Sheet">CSS</acronym>, <acronym title="JavaScript">JS</acronym> and <acronym title="Hypertext Markup Language">HTML</acronym> pages (smaller is better)</li>
|
450 |
+
<li>Number and complexity of plugins active on your blog (fewer is better)</li>
|
451 |
+
<li>Expiry time of the cache (larger expiry time, larger cache)</li>
|
452 |
+
</ul>
|
453 |
+
<p>So we recommend an absolute minimum of 128MB for a typical blog; this figure is greater than some defaults, so keep that in mind. With statistics you'll be able to react accordingly and make adjustments.</p>
|
454 |
+
<p>For those that don't want or have time to learn anything new to get started, sample configuration files are included with the plugin containing inline comments for you.</p>
|
455 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
456 |
+
<p id="q85"><strong>What version of <acronym title="Hypertext Preprocessor">PHP</acronym> do I need for this thing?</strong><br />
|
457 |
Â
Version 4.3 is supported, version 5 preferred (it's much much faster especially with <acronym title="Alternative PHP Cache">APC</acronym>).</p>
|
458 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
459 |
+
<p id="q86"><strong>What version of mySQL is needed?</strong><br />
|
460 |
+
If your WordPress installation is works, you're all set.</p>
|
461 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
462 |
+
<p id="q87"><strong>And I need mod_rewrite (or equivalent for my web server) installed too, no?</strong><br />
|
463 |
+
That's correct; everything you need for WordPress (i.e. fancy URLs) will get you started with this plugin also.</p>
|
464 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
465 |
+
<p id="q88"><strong>How much hardware do I have to throw at something like this before I see a benefit?</strong><br />
|
466 |
+
This plugin was actually designed with virtual dedicated servers in mind. As long as your server has at least 256M of <acronym title="Random Access Memory">RAM</acronym>, you can get started.</p>
|
467 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
468 |
+
<p id="q89"><strong>Is this plugin server cluster and load balancer friendly?</strong><br />
|
469 |
+
Yes, built from the ground up with scale and current hosting paradigms in mind.</p>
|
470 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
471 |
+
<p id="q90"><strong>I'm a web hosting provider and I heard about this plugin from my clients, is this plugin safe for a shared hosting environment?<br />
|
472 |
+
</strong>Not yet. The next release has ~30 more features and one of them is the remedy to data security concerns for a shared (virtual) hosting environment.</p>
|
473 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
474 |
+
<p id="q91"><strong>What is the intended impact of this plugin on the web hosting landscape?</strong><br />
|
475 |
Â
We feel that shared or virtual hosting providers will begin offering secure containers (similar to what <a href="http://mediatemple.net/" target="_blank">mediatemple.net</a> does for mySQL and Ruby etc) for <acronym title="Alternative PHP Cache">APC</acronym> and memcached. Whoever brings this offering to market first will lower the bar for more web sites/applications (and startups) to build better performing applications with greater ease. The same hosting provider would also possess a new value added service, thereby realizing a competitive advantage in a highly competitive marketplace. Not to mention be able to increase the density of domains per server (or cluster) without shortchanging customers.</p>
|
476 |
+
<p>One day hopefully this plugin will contribute to making web servers greener and reduce the ecological footprint of the web by reducing the computational effort required to deliver high performance rich user experiences.</p>
|
477 |
+
<p align="right"><a href="#toc">back to top</a></p>
|
478 |
+
</div>
|
Â
|
inc/options/general.phtml
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
Â
<?php
|
2 |
Â
|
3 |
Â
$enabled = ($config->get_boolean('dbcache.enabled') || $config->get_boolean('pgcache.enabled') || $config->get_boolean('minify.enabled') || $config->get_boolean('cdn.enabled'));
|
Â
|
|
4 |
Â
$supportType = $config->get_string('common.support.type', 'footer');
|
5 |
Â
|
6 |
Â
$canEmptyMemcache = ($config->get_string('dbcache.engine') == 'memcached' || $config->get_string('pgcache.engine') == 'memcached' || $config->get_string('minify.engine') == 'memcached');
|
@@ -8,116 +9,125 @@ $canEmptyApc = ($config->get_string('dbcache.engine') == 'apc' || $config->get_s
|
|
8 |
Â
$canEmptyDisk = ($config->get_string('minify.engine') == 'file');
|
9 |
Â
|
10 |
Â
?>
|
11 |
-
|
12 |
Â
<h3>General Settings</h3>
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
<
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
<
|
102 |
-
|
103 |
-
<
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
</
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
Â
<?php
|
2 |
Â
|
3 |
Â
$enabled = ($config->get_boolean('dbcache.enabled') || $config->get_boolean('pgcache.enabled') || $config->get_boolean('minify.enabled') || $config->get_boolean('cdn.enabled'));
|
4 |
+
$debug = ($config->get_boolean('dbcache.debug') || $config->get_boolean('pgcache.debug') || $config->get_boolean('minify.debug') || $config->get_boolean('cdn.debug'));
|
5 |
Â
$supportType = $config->get_string('common.support.type', 'footer');
|
6 |
Â
|
7 |
Â
$canEmptyMemcache = ($config->get_string('dbcache.engine') == 'memcached' || $config->get_string('pgcache.engine') == 'memcached' || $config->get_string('minify.engine') == 'memcached');
|
9 |
Â
$canEmptyDisk = ($config->get_string('minify.engine') == 'file');
|
10 |
Â
|
11 |
Â
?>
|
Â
|
|
12 |
Â
<h3>General Settings</h3>
|
13 |
+
|
14 |
+
<p>The plugin is currently <span class="w3tc-<?php if ($enabled): ?>enabled">enabled<?php else: ?>disabled">disabled<?php endif; ?></span>. Changing any of the following settings will clear all caches. If an option is disabled it means that either your current installation is not compatible or installation is required.</p>
|
15 |
+
|
16 |
+
<p><label><input id="enabled" type="checkbox" name="enabled" value="1"<?php checked($enabled); ?> /> Deselect this option to disable all caching functionality.</label></p>
|
17 |
+
|
18 |
+
<form action="options-general.php">
|
19 |
+
<p>You can
|
20 |
+
<input type="hidden" name="page" value="<?php echo W3_PLUGIN_FILE; ?>" />
|
21 |
+
<input class="button" type="submit" name="flush_all" value="empty all caches" /> at once or
|
22 |
+
<input class="button" type="submit" name="flush_memcached" value="empty only the memcached cache"<?php if (! $canEmptyMemcache): ?> disabled="disabled"<?php endif; ?> /> or
|
23 |
+
<input class="button" type="submit" name="flush_apc" value="empty only the APC cache"<?php if (! $canEmptyApc): ?> disabled="disabled"<?php endif; ?> /> or
|
24 |
+
<input class="button" type="submit" name="flush_file" value="empty only the minify disk cache"<?php if (! $canEmptyDisk): ?> disabled="disabled"<?php endif; ?> />.
|
25 |
+
</p>
|
26 |
+
</form>
|
27 |
+
|
28 |
+
<p>Enable page caching to decrease the response time of your blog.</p>
|
29 |
+
|
30 |
+
<form action="options-general.php?page=<?php echo urldecode(W3_PLUGIN_FILE); ?>&tab=<?php echo $tab; ?>" method="post">
|
31 |
+
<table class="form-table">
|
32 |
+
<tr>
|
33 |
+
<th valign="top">Page Caching:</th>
|
34 |
+
<td>
|
35 |
+
<input type="hidden" name="pgcache.enabled" value="0" />
|
36 |
+
<label><input class="enabled" type="checkbox" name="pgcache.enabled" value="1"<?php checked($config->get_boolean('pgcache.enabled')); ?> /> <strong>Enable</strong></label><br />
|
37 |
+
<span class="description">Caching pages will reduce the response time of and increase the concurrency potential of your web server.</span>
|
38 |
+
</td>
|
39 |
+
</tr>
|
40 |
+
<tr>
|
41 |
+
<th valign="top">Page Caching Method:</th>
|
42 |
+
<td>
|
43 |
+
<label><input type="radio" name="pgcache.engine" value="memcached"<?php checked($config->get_string('pgcache.engine'), 'memcached'); ?> /> Memcached</label><br />
|
44 |
+
<label><input type="radio" name="pgcache.engine" value="apc"<?php checked($config->get_string('pgcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?> /> <acronym title="Alternative PHP Cache">APC</acronym></label><br />
|
45 |
+
</td>
|
46 |
+
</tr>
|
47 |
+
</table>
|
48 |
+
|
49 |
+
<p>Enable minify to concatenate, remove white space / comments and compress (<acronym title="GNU zip">gzip</acronym> / deflate) your (theme's / plugin's / external) <acronym title="Cascading Style Sheets">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files.</p>
|
50 |
+
|
51 |
+
<table class="form-table">
|
52 |
+
<tr>
|
53 |
+
<th valign="top">Minify:</th>
|
54 |
+
<td>
|
55 |
+
<input type="hidden" name="minify.enabled" value="0" />
|
56 |
+
<label><input class="enabled" type="checkbox" name="minify.enabled" value="1"<?php checked($config->get_boolean('minify.enabled')); ?> /> <strong>Enable</strong></label><br />
|
57 |
+
<span class="description">Minification can decrease file size of <acronym title="Hypertext Markup Language">HTML</acronym>, <acronym title="Cascading Style Sheets">CSS</acronym> and <acronym title="JavaScript">JS</acronym> respectively by ~10% on average.</span>
|
58 |
+
</td>
|
59 |
+
</tr>
|
60 |
+
<tr>
|
61 |
+
<th valign="top">Minify Caching Method:</th>
|
62 |
+
<td>
|
63 |
+
<label><input type="radio" name="minify.engine" value="file"<?php checked($config->get_string('minify.engine'), 'file'); ?> /> Disk</label><br />
|
64 |
+
<label><input type="radio" name="minify.engine" value="memcached"<?php checked($config->get_string('minify.engine'), 'memcached'); ?> /> Memcached</label><br />
|
65 |
+
<label><input type="radio" name="minify.engine" value="apc"<?php checked($config->get_string('minify.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?> /> <acronym title="Alternative PHP Cache">APC</acronym></label><br />
|
66 |
+
</td>
|
67 |
+
</tr>
|
68 |
+
</table>
|
69 |
+
|
70 |
+
<p>Enable database caching to remove database performance bottlenecks from your blog.</p>
|
71 |
+
|
72 |
+
<table class="form-table">
|
73 |
+
<tr>
|
74 |
+
<th valign="top">Database Caching:</th>
|
75 |
+
<td>
|
76 |
+
<input type="hidden" name="dbcache.enabled" value="0" />
|
77 |
+
<label><input class="enabled" type="checkbox" name="dbcache.enabled" value="1"<?php checked($config->get_boolean('dbcache.enabled')); ?> /> <strong>Enable</strong></label><br />
|
78 |
+
<span class="description">Caching database objects will increase the response time of your blog by at least an order of magnitude in most cases.</span>
|
79 |
+
</td>
|
80 |
+
</tr>
|
81 |
+
<tr>
|
82 |
+
<th valign="top">Database Caching Method:</th>
|
83 |
+
<td>
|
84 |
+
<label><input type="radio" name="dbcache.engine" value="memcached"<?php checked($config->get_string('dbcache.engine', 'memcached')); ?> /> Memcached</label><br />
|
85 |
+
<label><input type="radio" name="dbcache.engine" value="apc"<?php checked($config->get_string('dbcache.engine'), 'apc'); ?><?php if (! $check_apc): ?> disabled="disabled"<?php endif; ?> /> <acronym title="Alternative PHP Cache">APC</acronym></label><br />
|
86 |
+
</td>
|
87 |
+
</tr>
|
88 |
+
</table>
|
89 |
+
|
90 |
+
<p>Host your wp-includes/ (images and scripts only), media library, theme images / <acronym title="Cascading Style Sheets">CSS</acronym> / <acronym title="JavaScript">JS</acronym> with your <acronym title="Content Delivery Network">CDN</acronym> provider.</p>
|
91 |
+
|
92 |
+
<table class="form-table">
|
93 |
+
<tr>
|
94 |
+
<th><acronym title="Content Delivery Network">CDN</acronym>:</th>
|
95 |
+
<td>
|
96 |
+
<input type="hidden" name="cdn.enabled" value="0" />
|
97 |
+
<label><input class="enabled" type="checkbox" name="cdn.enabled" value="1"<?php checked($config->get_boolean('cdn.enabled')); ?> /> <strong>Enable</strong></label><br />
|
98 |
+
</td>
|
99 |
+
</tr>
|
100 |
+
<tr>
|
101 |
+
<th><acronym title="Content Delivery Network">CDN</acronym> Type:</th>
|
102 |
+
<td>
|
103 |
+
<label><input type="radio" name="cdn.engine" value="ftp"<?php checked($config->get_string('cdn.engine'), 'ftp'); ?> /> <acronym title="File Transfer Protocol">FTP</acronym></label><br />
|
104 |
+
<!--<label><input type="radio" name="cdn.engine" value="cf"<?php checked($config->get_string('cdn.engine'), 'cf'); ?> /> Amazon CloudFront</label><br />
|
105 |
+
<label><input type="radio" name="cdn.engine" value="s3"<?php checked($config->get_string('cdn.engine'), 's3'); ?> /> Amazon S3</label><br />-->
|
106 |
+
<span class="description">Select the <acronym title="Content Delivery Network">CDN</acronym> type you wish to use.</span>
|
107 |
+
</td>
|
108 |
+
</tr>
|
109 |
+
</table>
|
110 |
+
|
111 |
+
<p>View detailed data on the operations being performed using debug mode. Performance in this mode will not be optimal nor private, use sparingly.</p>
|
112 |
+
|
113 |
+
<table class="form-table">
|
114 |
+
<tr>
|
115 |
+
<th valign="top">Debug Mode:</th>
|
116 |
+
<td>
|
117 |
+
<input type="hidden" name="debug" value="0" />
|
118 |
+
<label><input type="checkbox" name="debug" value="1"<?php checked($debug); ?> /> <strong>Enable</strong></label>
|
119 |
+
</td>
|
120 |
+
</tr>
|
121 |
+
</table>
|
122 |
+
|
123 |
+
<h3>Support Us</h3>
|
124 |
+
|
125 |
+
<p>If this plugin has saved you money, made your server more stable and/or improved user experience for the readers of your blog, support us with a link!</p>
|
126 |
+
<p><input type="hidden" name="common.support" value="0" /><label><input type="checkbox" name="common.support"<?php checked($config->get_boolean('common.support')); ?> /> Yes, I'd love to support you guys, please add the link to my site's</label> <select name="common.support.type"><option value="blogroll"<?php if ($supportType == 'blogroll'): ?> selected="selected"<?php endif; ?>>blogroll</option><option value="footer"<?php if ($supportType == 'footer'): ?> selected="selected"<?php endif; ?>>footer</option></select>.</p>
|
127 |
+
<p>If you want to place the link manually here is the code:</p>
|
128 |
+
<p><textarea cols="100" rows="3">Performance Optimization <a href="http://www.w3-edge.com/wordpress-plugins/" rel="external">WordPress Plugins</a> by W3 EDGE</textarea></p>
|
129 |
+
|
130 |
+
<p class="submit">
|
131 |
+
<input type="submit" name="Submit" class="button-primary" value="Save changes" />
|
132 |
+
</p>
|
133 |
+
</form>
|
inc/options/install.phtml
CHANGED
@@ -1,162 +1,163 @@
|
|
1 |
-
<
|
2 |
-
<
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
Â
|
|
162 |
Â
</div>
|
1 |
+
<div id="install">
|
2 |
+
<h3>Installation</h3>
|
3 |
+
|
4 |
+
<ol>
|
5 |
+
<li>Disable and remove any other caching plugin you may be using — most plugins have uninstall procedures you can follow. Make sure wp-content/ has 777 permissions (e.g.: # chmod 777 /var/www/vhosts/domain.com/httpdocs/wp-content/) before proceeding.</li>
|
6 |
+
<li>Unzip and upload the plugin to your plugins directory (wp-content/plugins/) when done wp-content/plugins/w3-total-cache/ should exist. If you have WordPress <acronym title="Multi-User">MU</acronym> you will need to install this in wp-content/mu-plugins/w3-total-cache/.</li>
|
7 |
+
<li>Locate and activate the plugin on the <a href="/wp-admin/plugins.php">Plugins</a> page. Set the permisions of wp-content back to 755 (e.g.: # chmod 755 /var/www/vhosts/domain.com/httpdocs/wp-content/) and click through to the <a href="/wp-admin/options-general.php?page=w3-total-cache/w3-total-cache.php&tab=general">General Settings</a> tab.</li>
|
8 |
+
<li>Select your caching preferences for page, database and minify. If memcached is used this will require you to confirm or modify the default settings and add any additional memcached servers you wish to use. To utilize <a href="#APC"><acronym title="Alternative PHP Cache">APC</acronym></a> and <a href="#memcached">memcached</a> + <a href="#memcache">memcache</a> installation guides have been provided for those with virtual dedicated or dedicated servers. For those in shared hosting environments, contact your provider to see if either of these are supported.</li>
|
9 |
+
<li>If you already have a content delivery network provider, proceed to the <a href="/wp-admin/options-general.php?page=w3-total-cache/w3-total-cache.php&tab=cdn"><acronym title="Content Delivery Network">CDN</acronym> Settings</a> tab and populate the fields and set your preferences. If you're not running a version of WordPress with the Media Library feature, use the Media Library Import Tool to migrate your post images etc to appropriate locations.<br />
|
10 |
+
<br />
|
11 |
+
If you do not have a <acronym title="Content Delivery Network">CDN</acronym> provider, you can create and use a subdomain instead, e.g. subdomain.domain.com to improve server response, pipelining performance and progressive render.</li>
|
12 |
+
<li>On the <a href="/wp-admin/options-general.php?page=w3-total-cache/w3-total-cache.php&tab=minify">Minify Settings</a> tab all of the recommended settings are preset. Specify any <acronym title="Cascading Style Sheet">CSS</acronym> and <acronym title="JavaScript">JS</acronym> files in the respective sections, view your site's <acronym title="Hypertext Markup Language">HTML</acronym> source and search for .<acronym title="Cascading Style Sheet">css</acronym> and .<acronym title="JavaScript">js</acronym> files. In the case of <acronym title="JavaScript">JS</acronym> files you can determine the type and location of the embedding using the drop down menu. Avoid the inclusion of packed or obfuscated <acronym title="JavaScript">JS</acronym> files in this step.</li>
|
13 |
+
<li>Enable the plugin on the <a href="/wp-admin/options-general.php?page=w3-total-cache/w3-total-cache.php&tab=general">General Settings</a> tab.</li>
|
14 |
+
<li>You're done! Get back to blogging!</li>
|
15 |
+
</ol>
|
16 |
+
Check out the <acronym title="Frequently Asked Questions">FAQ</acronym> for more details on <a href="/wp-admin/options-general.php?page=w3-total-cache/w3-total-cache.php&tab=faq">usage</a>.
|
17 |
+
<hr />
|
18 |
+
<p><strong>Server Preparation:</strong><br />
|
19 |
+
<em>Time required: ~1 minute</em></p>
|
20 |
+
<ol>
|
21 |
+
<li><a href="http://www.google.com/search?q=installing%20yum&output=search&tbs=qdr:y&tbo=1" target="_blank">Install yum</a> for your operating system if you don't already have it. If you like, you can update all of your installed software, but do so only if you have the experience and time to double check configurations afterwards:<br />
|
22 |
+
# yum -y update</li>
|
23 |
+
<li>Install <acronym title="PHP Extension Community Library">PECL</acronym>:<br />
|
24 |
+
# yum install php-pear</li>
|
25 |
+
<li>Install the <acronym title="Hypertext Preprocessor">PHP</acronym> Development package:<br />
|
26 |
+
# yum install php-devel</li>
|
27 |
+
<li>Install apxs with the following command:<br />
|
28 |
+
# yum install httpd-devel</li>
|
29 |
+
</ol>
|
30 |
+
<hr />
|
31 |
+
<p id="memcached"><strong>Memcached (Daemon) Installation:</strong><br />
|
32 |
+
<em>Time required: 3 minutes</em></p>
|
33 |
+
<ol>
|
34 |
+
<li>Try to install with yum:<br />
|
35 |
+
# yum install libevent<br />
|
36 |
+
<br />
|
37 |
+
If this succeeds skip to #5. If this fails, then let's compile. Download and extract the <a href="http://www.monkey.org/~provos/libevent/" target="_blank">latest stable version</a>:<br />
|
38 |
+
# cd /usr/local/src<br />
|
39 |
+
# wget <a href="http://monkey.org/~provos/libevent-1.4.12-stable.tar.gz">http://monkey.org/~provos/libevent-1.4.12-stable.tar.gz</a><br />
|
40 |
+
# gunzip -c libevent-1.4.12-stable.tar.gz | tar xf -<br />
|
41 |
+
# cd libevent-1.4.12-stable</li>
|
42 |
+
<li>Let's compile:<br />
|
43 |
+
# ./configure<br />
|
44 |
+
# make && make install</li>
|
45 |
+
<li>In the output you should see:<br />
|
46 |
+
<br />
|
47 |
+
Libraries have been installed in:<br />
|
48 |
+
/usr/local/lib<br />
|
49 |
+
<br />
|
50 |
+
If so you can:<br />
|
51 |
+
# echo "/usr/local/lib/" > /etc/ld.so.conf.d/libevent.conf</li>
|
52 |
+
<li>Configure your server for the new install:<br />
|
53 |
+
# ldconfig -v</li>
|
54 |
+
<li>Now find the <a href="http://www.danga.com/memcached/download.bml" target="_blank">latest stable memcached</a>, download and extract:<br />
|
55 |
+
# cd /usr/local/src<br />
|
56 |
+
# wget <a href="http://memcached.googlecode.com/files/memcached-1.4.0.tar.gz" target="_blank">http://memcached.googlecode.com/files/memcached-1.4.0.tar.gz</a><br />
|
57 |
+
# gunzip -c memcached-1.4.0.tar.gz | tar xf -<br />
|
58 |
+
# cd memcached-1.4.0</li>
|
59 |
+
<li>Let's compile:<br />
|
60 |
+
# ./configure<br />
|
61 |
+
# make && make install</li>
|
62 |
+
<li>We can optionally create memcached.conf in /etc/:<br />
|
63 |
+
# cp -p /var/www/vhosts/domain.com/httpdocs/wp-content/plugins/w3-total-cache/ini/memcached.conf /etc/</li>
|
64 |
+
<li>Make sure memcached is starts automatically on server boot:<br />
|
65 |
+
# touch /etc/init.d/memcached<br />
|
66 |
+
# echo '#!/bin/sh -e' >> /etc/init.d/memcached<br />
|
67 |
+
# echo '/usr/local/bin/memcached -d -m 128 -p 11211 -u nobody' >> /etc/init.d/memcached<br />
|
68 |
+
# chmod u+x /etc/init.d/memcached</li>
|
69 |
+
<li>And finally, let's start memcached:<br />
|
70 |
+
# /etc/init.d/memcached</li>
|
71 |
+
</ol>
|
72 |
+
<p>For windows users we recommend checking the following sites for more installation tips:</p>
|
73 |
+
<ul>
|
74 |
+
<li><a href="http://pureform.wordpress.com/2008/01/10/installing-memcache-on-windows-for-php/" target="_blank">Installing memcache on Windows for <acronym title="Hypertext Preprocessor">PHP</acronym></a></li>
|
75 |
+
<li><a href="http://pecl4win.php.net/ext.php/php_memcache.dll" target="_blank"><acronym title="PHP Extension Community Library">PECL</acronym> memcached Extensions</a> </li>
|
76 |
+
</ul>
|
77 |
+
<hr />
|
78 |
+
<p id="memcache"><strong><acronym title="PHP Extension Community Library">PECL</acronym> Memcache Module Installation:</strong><br />
|
79 |
+
<em>Time required: 2 minutes</em></p>
|
80 |
+
<ol>
|
81 |
+
<li>Either use <acronym title="PHP Extension Community Library">PECL</acronym> (and skip to #4 if successful):<br />
|
82 |
+
# pecl install memcache</li>
|
83 |
+
<li>Or via compilation. Download the <a href="http://pecl.php.net/package/memcache" target="_blank">latest stable version</a> and extract:<br />
|
84 |
+
# cd /usr/local/src/<br />
|
85 |
+
# wget <a href="http://pecl.php.net/get/memcache-2.2.5.tgz">http://pecl.php.net/get/memcache-2.2.5.tgz</a><br />
|
86 |
+
# gunzip -c memcache-2.2.5.tgz | tar xf -<br />
|
87 |
+
# cd memcache-2.2.5</li>
|
88 |
+
<li>Now we start to compile:<br />
|
89 |
+
# phpize<br />
|
90 |
+
# ./configure<br />
|
91 |
+
# make && make install</li>
|
92 |
+
<li>If the output is like this:<br />
|
93 |
+
Installing shared extensions: /usr/lib/php/modules/<br />
|
94 |
+
<br />
|
95 |
+
Then:<br />
|
96 |
+
# echo "extension=memcache.so" > /etc/php.d/memcache.ini<br />
|
97 |
+
<br />
|
98 |
+
or you can also use the memcache.ini file we prepared for you:<br />
|
99 |
+
# cp -p /var/www/vhosts/domain.com/httpdocs/wp-content/plugins/w3-total-cache/ini/apc.ini /etc/php.d/</li>
|
100 |
+
<li>Finally restart apache:<br />
|
101 |
+
# /etc/init.d/httpd restart</li>
|
102 |
+
<li>You're done! Memcache should now be available. You can verify by creating a .<acronym title="Hypertext Preprocessor">php</acronym> script containing the following code and searching for "memcache" after opening the page in your browser:<br />
|
103 |
+
<?php phpinfo(); ?></li>
|
104 |
+
</ol>
|
105 |
+
<hr />
|
106 |
+
<p id="APC"><strong><acronym title="Alternative PHP Cache">APC</acronym> Installation via Yum or <acronym title="PHP Extension Community Library">PECL</acronym>: </strong><br />
|
107 |
+
<em>Time required: 1 minute</em></p>
|
108 |
+
<ol>
|
109 |
+
<li>Install <acronym title="Alternative PHP Cache">APC</acronym> using the <acronym title="PHP Extension Community Library">PECL</acronym> command:<br />
|
110 |
+
# pecl install apc<br />
|
111 |
+
<br />
|
112 |
+
or using yum:<br />
|
113 |
+
# yum install php-pecl-apc</li>
|
114 |
+
<li>Make sure the module is loaded:<br />
|
115 |
+
# echo "extension=apc.so" > /etc/php.d/apc.ini<br />
|
116 |
+
<br />
|
117 |
+
or customize /etc/php.d/apc.ini using our included sample config file:<br />
|
118 |
+
# cp -p /var/www/vhosts/domain.com/httpdocs/wp-content/plugins/w3-total-cache/ini/apc.ini /etc/php.d/</li>
|
119 |
+
<li>When ready, restart apache:<br />
|
120 |
+
# /etc/init.d/httpd restart</li>
|
121 |
+
<li>You're done! <acronym title="Alternative PHP Cache">APC</acronym> should now be available. You can verify by creating a .<acronym title="Hypertext Preprocessor">php</acronym> script containing the following code and opening the page in your browser:<br />
|
122 |
+
<?php phpinfo(); ?></li>
|
123 |
+
</ol>
|
124 |
+
<p>For windows users we recommend checking the following sites for more installation tips:</p>
|
125 |
+
<ul>
|
126 |
+
<li><a href="http://www.sitebuddy.com/PHP/Accelerators/apc_windows_binaries_builds" target="_blank"><acronym title="Alternative PHP Cache">APC</acronym> binaries for <acronym title="Hypertext Preprocessor">PHP</acronym> 5.x (windows builds)</a> </li>
|
127 |
+
<li><a href="http://pecl4win.php.net/ext.php/php_apc.dll" target="_blank"><acronym title="PHP Extension Community Library">PECL</acronym> <acronym title="Alternative PHP Cache">APC</acronym> Extensions</a> </li>
|
128 |
+
</ul>
|
129 |
+
<hr />
|
130 |
+
<p><strong><acronym title="Alternative PHP Cache">APC</acronym> Installation via Compilation: </strong><br />
|
131 |
+
<em>Time required: 2 minutes</em></p>
|
132 |
+
<ol>
|
133 |
+
<li>Download the <a href="http://pecl.php.net/package/APC">latest stable version</a> and extract:<br />
|
134 |
+
# cd /usr/local/src<br />
|
135 |
+
# wget <a href="http://pecl.php.net/get/APC-3.0.19.tgz">http://pecl.php.net/get/APC-3.0.19.tgz</a><br />
|
136 |
+
# gunzip -c APC-3.0.19.tgz | tar xf -<br />
|
137 |
+
# cd APC-3.0.19</li>
|
138 |
+
<li>Note the paths returned for the following commands:<br />
|
139 |
+
# whereis phpize<br />
|
140 |
+
# whereis php-config</li>
|
141 |
+
<li>Use the output from #2 to modify the --with-apxs and --with-php-config flags in the following compile command:<br />
|
142 |
+
# phpize<br />
|
143 |
+
# ./configure --enable-apc --enable-apc-mmap --with-apxs=/usr/bin/phpize --with-php-config=/usr/bin/php-config<br />
|
144 |
+
# make && make install<br />
|
145 |
+
<br />The result should be similar to:<br />
|
146 |
+
Installing shared extensions: /usr/lib/php/modules/</li>
|
147 |
+
<li>Use our customed <acronym title="Alternative PHP Cache">APC</acronym> settings by overwriting apc.ini in /etc/php.d/:<br />
|
148 |
+
# cp -p /var/www/vhosts/domain.com/httpdocs/wp-content/plugins/w3-total-cache/ini/apc.ini /etc/php.d/</li>
|
149 |
+
<li>Restart apache when ready:<br />
|
150 |
+
# /etc/init.d/httpd restart</li>
|
151 |
+
<li>You're done! <acronym title="Alternative PHP Cache">APC</acronym> should now be available. You can verify by creating a .<acronym title="Hypertext Preprocessor">php</acronym> script containing the following code and searching for "<acronym title="Alternative PHP Cache">APC</acronym>" after opening the page in your browser:<br />
|
152 |
+
<?php phpinfo(); ?></li>
|
153 |
+
</ol>
|
154 |
+
<hr />
|
155 |
+
<p><strong>Note(s):</strong></p>
|
156 |
+
<ul>
|
157 |
+
<li>These server instructions are for CentOS, however we can provide others based on <a href="mailto:wordpressexperts@w3-edge.com">your requests</a>.</li>
|
158 |
+
<li>In the case where the "Rewrite <acronym>URL</acronym> Structure" (in <a href="/wp-admin/options-general.php?page=w3-total-cache/w3-total-cache.php&tab=minify">Minify Settings</a> tab) is desired, and apache is not used, the file located in wp-content/plugins/w3-total-cache/wp-content/w3tc-cache/.htaccess contains directives that must be created for the directory: wp-content/uploads/w3tc-cache/.</li>
|
159 |
+
<li>Restarting the web server will empty your <acronym title="Alternative PHP Cache">APC</acronym> cache, which means it will have to be rebuilt over time and your site's performance will suffer during this period. Still, <acronym title="Alternative PHP Cache">APC</acronym> should be installed in any case to maximize WordPress performance.</li>
|
160 |
+
<li>Consider using memcached for objects that must persist across web server restarts or that you wish to share amongst your pool of servers (or cluster), e.g.: database objects or page cache.</li>
|
161 |
+
<li>Some yum or <acronym title="PHP Extension Community Library">PECL</acronym> mirrors may not have your the necessary packages, in such cases you may have to do a manual installation.</li>
|
162 |
+
</ul>
|
163 |
Â
</div>
|
inc/options/minify.phtml
CHANGED
@@ -26,117 +26,116 @@ foreach ($js_check_groups as $js_check_group) {
|
|
26 |
Â
|
27 |
Â
?>
|
28 |
Â
<h3>Minify Settings</h3>
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
Â
<label><input type="checkbox" name="minify.compress" value="1"<?php checked($config->get_boolean('minify.compress')); ?> /> <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate)</label><br />
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
</div>
|
26 |
Â
|
27 |
Â
?>
|
28 |
Â
<h3>Minify Settings</h3>
|
29 |
+
|
30 |
+
<p>Minify is currently <span class="w3tc-<?php if ($config->get_boolean('minify.enabled')): ?>enabled">enabled<?php else: ?>disabled">disabled<?php endif; ?></span>.</p>
|
31 |
+
|
32 |
+
<form id="minify_form" action="options-general.php?page=<?php echo urldecode(W3_PLUGIN_FILE); ?>&tab=<?php echo $tab; ?>" method="post">
|
33 |
+
<table class="form-table">
|
34 |
+
<tr>
|
35 |
+
<th style="width: 250px;"><label for="minify_memcached_servers">Memcached Hostname:Port / IP:Port:</label></th>
|
36 |
+
<td>
|
37 |
+
<input id="minify_memcached_servers" type="text" name="minify.memcached.servers" value="<?php echo htmlspecialchars(implode(',', $config->get_array('minify.memcached.servers'))); ?>" size="100"<?php if ($config->get_string('minify.engine', 'memcached') != 'memcached'): ?> disabled="disabled"<?php endif; ?> /><br />
|
38 |
+
<span class="description">Multiple servers may be used and seperated by a comma; e.g. 192.168.1.100:11211, domain.com:22122</span>
|
39 |
+
</td>
|
40 |
+
</tr>
|
41 |
+
<tr>
|
42 |
+
<th colspan="2">
|
43 |
+
<input type="hidden" name="minify.compress" value="0" />
|
44 |
Â
<label><input type="checkbox" name="minify.compress" value="1"<?php checked($config->get_boolean('minify.compress')); ?> /> <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate)</label><br />
|
45 |
+
<span class="description">Reduce file size by utomatically detecting the user agent's supported compression method of any.</span>
|
46 |
+
</th>
|
47 |
+
</tr>
|
48 |
+
<tr>
|
49 |
+
<th colspan="2">
|
50 |
+
<input type="hidden" name="minify.compress.ie6" value="0" />
|
51 |
+
<label><input type="checkbox" name="minify.compress.ie6" value="1"<?php checked($config->get_boolean('minify.compress.ie6')); ?> /> <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression for <acronym title="Microsoft Internet Explorer">MSIE</acronym>6</label><br />
|
52 |
+
<span class="description">Workaround for <acronym title="Microsoft Internet Explorer">MSIE</acronym>6 <acronym title="Service Pack">SP</acronym>2 compression bug.</span>
|
53 |
+
</th>
|
54 |
+
</tr>
|
55 |
+
<tr>
|
56 |
+
<th colspan="2">
|
57 |
+
<input type="hidden" name="minify.rewrite" value="0" />
|
58 |
+
<label><input type="checkbox" name="minify.rewrite" value="1"<?php checked($config->get_boolean('minify.rewrite')); ?> /> Rewrite <acronym title="Uniform Resource Locator">URL</acronym> Structure</label><br />
|
59 |
+
<span class="description">If disabled, <acronym title="Cascading Style Sheets">CSS</acronym> and <acronym title="JavaScript">JS</acronym> embeddings will use of GET variables, enabling this option is recommended unless you really want to avoid the redirects.</span>
|
60 |
+
</th>
|
61 |
+
</tr>
|
62 |
+
<tr>
|
63 |
+
<th><label for="minify_lifetime">Update external files every:</label></th>
|
64 |
+
<td><input id="minify_lifetime" type="text" name="minify.lifetime" value="<?php echo $config->get_integer('minify.lifetime'); ?>" size="8" /> seconds<br />
|
65 |
+
<span class="description">Specify the interval between download and update of external files in the minify cache. Hint: 6 hours is 21600 seconds. 12 hours is 43200 seconds. 24 hours is 86400 seconds.</span></td>
|
66 |
+
</tr>
|
67 |
+
<tr>
|
68 |
+
<th valign="top"><acronym title="Hypertext Markup Language">HTML</acronym> Settings:</th>
|
69 |
+
<td>
|
70 |
+
<input type="hidden" name="minify.html.enable" value="0" />
|
71 |
+
<input type="hidden" name="minify.html.reject.admin" value="0" />
|
72 |
+
<input type="hidden" name="minify.html.strip.comments" value="0" />
|
73 |
+
<input type="hidden" name="minify.html.strip.crlf" value="0" />
|
74 |
+
<label><input id="html_enabled" type="checkbox" name="minify.html.enable" value="1"<?php checked($config->get_boolean('minify.html.enable')); ?> /> Minify</label><br />
|
75 |
+
<label><input class="html_enabled" type="checkbox" name="minify.html.reject.admin" value="1"<?php checked($config->get_boolean('minify.html.reject.admin')); ?> /> Don't Minify <acronym title="Hypertext Markup Language">HTML</acronym> for logged in administrators</label><br />
|
76 |
+
<label><input class="html_enabled" type="checkbox" name="minify.html.strip.comments" value="1"<?php checked($config->get_boolean('minify.html.strip.comments')); ?> /> Comment removal</label><br />
|
77 |
+
<label><input class="html_enabled" type="checkbox" name="minify.html.strip.crlf" value="1"<?php checked($config->get_boolean('minify.html.strip.crlf')); ?> /> Line break removal</label><br />
|
78 |
+
</td>
|
79 |
+
</tr>
|
80 |
+
<tr>
|
81 |
+
<th valign="top"><acronym title="JavaScript">JS</acronym> Minify Settings:</th>
|
82 |
+
<td>
|
83 |
+
<input type="hidden" name="minify.js.enable" value="0" />
|
84 |
+
<input type="hidden" name="minify.js.clean" value="0" />
|
85 |
+
<input type="hidden" name="minify.js.strip.comments" value="0" />
|
86 |
+
<input type="hidden" name="minify.js.strip.crlf" value="0" />
|
87 |
+
<label><input id="js_enabled" type="checkbox" name="minify.js.enable" value="1"<?php checked($config->get_boolean('minify.js.enable')); ?> /> Minify</label><br />
|
88 |
+
<label><input class="js_enabled" type="checkbox" name="minify.js.clean" value="1"<?php checked($config->get_boolean('minify.js.clean')); ?> /> Clean <acronym title="JavaScript">JS</acronym></label><br />
|
89 |
+
<label><input class="js_enabled" type="checkbox" name="minify.js.strip.comments" value="1"<?php checked($config->get_boolean('minify.js.strip.comments')); ?> /> Comment removal</label><br />
|
90 |
+
<label><input class="js_enabled" type="checkbox" name="minify.js.strip.crlf" value="1"<?php checked($config->get_boolean('minify.js.strip.crlf')); ?> /> Line break removal</label><br />
|
91 |
+
</td>
|
92 |
+
</tr>
|
93 |
+
<tr>
|
94 |
+
<th valign="top"><acronym title="Cascading Style Sheets">CSS</acronym> Minify Settings:</th>
|
95 |
+
<td>
|
96 |
+
<input type="hidden" name="minify.css.enable" value="0" />
|
97 |
+
<input type="hidden" name="minify.css.clean" value="0" />
|
98 |
+
<input type="hidden" name="minify.css.strip.comments" value="0" />
|
99 |
+
<input type="hidden" name="minify.css.strip.crlf" value="0" />
|
100 |
+
<label><input id="css_enabled" type="checkbox" name="minify.css.enable" value="1"<?php checked($config->get_boolean('minify.css.enable')); ?> /> Minify</label><br />
|
101 |
+
<label><input class="css_enabled" type="checkbox" name="minify.css.clean" value="1"<?php checked($config->get_boolean('minify.css.clean')); ?> /> Clean <acronym title="Cascading Style Sheets">CSS</acronym></label><br />
|
102 |
+
<label><input class="css_enabled" type="checkbox" name="minify.css.strip.comments" value="1"<?php checked($config->get_boolean('minify.css.strip.comments')); ?> /> Comment removal</label><br />
|
103 |
+
<label><input class="css_enabled" type="checkbox" name="minify.css.strip.crlf" value="1"<?php checked($config->get_boolean('minify.css.strip.crlf')); ?> /> Line break removal</label><br />
|
104 |
+
</td>
|
105 |
+
</tr>
|
106 |
+
<tr>
|
107 |
+
<th valign="top"><acronym title="JavaScript">JS</acronym> File Management:</th>
|
108 |
+
<td>
|
109 |
+
<?php if (count($js_files)): ?>
|
110 |
+
<ol id="js_files">
|
111 |
+
<?php foreach($js_files as $js_file => $group): ?>
|
112 |
+
<li><input class="js_enabled" type="text" name="js_files_<?php echo htmlspecialchars($group); ?>[]" value="<?php echo htmlspecialchars($js_file); ?>" size="100" /> <select class="js_file_location js_enabled"><option value="include"<?php if ($group == 'include'): ?> selected="selected"<?php endif; ?>>Header</option><option value="include-nb"<?php if ($group == 'include-nb'): ?> selected="selected"<?php endif; ?>>Header (non-blocking)</option><option value="include-footer"<?php if ($group == 'include-footer'): ?> selected="selected"<?php endif; ?>>Footer</option><option value="include-footer-nb"<?php if ($group == 'include-footer-nb'): ?> selected="selected"<?php endif; ?>>Footer (non-blocking)</option></select> <input class="js_file_delete js_enabled button" type="button" value="Delete" /> <input class="js_file_verify js_enabled button" type="button" value="Verify URI" /></li>
|
113 |
+
<?php endforeach; ?>
|
114 |
+
</ol>
|
115 |
+
<?php else: ?>
|
116 |
+
<div id="js_files_empty" class="w3tc-empty">No <acronym title="JavaScript">JS</acronym> files added</div>
|
117 |
+
<?php endif; ?>
|
118 |
+
<input id="js_file_add" class="js_enabled button" type="button" value="Add a script" />
|
119 |
+
</td>
|
120 |
+
</tr>
|
121 |
+
<tr>
|
122 |
+
<th valign="top"><acronym title="Cascading Style Sheets">CSS</acronym> File Management:</th>
|
123 |
+
<td>
|
124 |
+
<?php if (count($css_files)): ?>
|
125 |
+
<ol id="css_files">
|
126 |
+
<?php foreach($css_files as $css_file => $group): ?>
|
127 |
+
<li><input class="css_enabled" type="text" name="css_files_<?php echo htmlspecialchars($group); ?>[]" value="<?php echo htmlspecialchars($css_file); ?>" size="100" /> <input class="css_file_delete css_enabled button" type="button" value="Delete" /> <input class="css_file_verify css_enabled button" type="button" value="Verify URI" /></li>
|
128 |
+
<?php endforeach; ?>
|
129 |
+
</ol>
|
130 |
+
<?php else: ?>
|
131 |
+
<div id="css_files_empty" class="w3tc-empty">No <acronym title="Cascading Style Sheets">CSS</acronym> files added</div>
|
132 |
+
<?php endif; ?>
|
133 |
+
<input id="css_file_add" class="css_enabled button" type="button" value="Add a style sheet" />
|
134 |
+
</td>
|
135 |
+
</tr>
|
136 |
+
</table>
|
137 |
+
|
138 |
+
<p class="submit">
|
139 |
+
<input type="submit" name="Submit" class="button-primary" value="Save changes" />
|
140 |
+
</p>
|
141 |
+
</form>
|
Â
|
inc/options/pgcache.phtml
CHANGED
@@ -1,70 +1,73 @@
|
|
1 |
Â
<h3>Page Cache Settings</h3>
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
Â
<label><input type="checkbox" name="pgcache.compress" value="1"<?php checked($config->get_boolean('pgcache.compress')); ?> /> <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate)</label>
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
Â
|
|
Â
|
|
Â
|
1 |
Â
<h3>Page Cache Settings</h3>
|
2 |
+
|
3 |
+
<p>Page Caching is currently <span class="w3tc-<?php if ($config->get_boolean('pgcache.enabled')): ?>enabled">enabled<?php else: ?>disabled">disabled<?php endif; ?></span>.</p>
|
4 |
+
|
5 |
+
<form action="options-general.php?page=<?php echo urldecode(W3_PLUGIN_FILE); ?>&tab=<?php echo $tab; ?>" method="post">
|
6 |
+
<table class="form-table">
|
7 |
+
<tr>
|
8 |
+
<th style="width: 250px;"><label for="pgcache_memcached_servers">Memcached Hostname:Port / IP:Port:</label></th>
|
9 |
+
<td>
|
10 |
+
<input id="pgcache_memcached_servers" type="text" name="pgcache.memcached.servers" value="<?php echo htmlspecialchars(implode(',', $config->get_array('pgcache.memcached.servers'))); ?>" size="100"<?php if ($config->get_string('pgcache.engine', 'memcached') != 'memcached'): ?> disabled="disabled"<?php endif; ?> />
|
11 |
+
<br /><span class="description">Multiple servers may be used and seperated by a comma; e.g. 192.168.1.100:11211, domain.com:22122</span>
|
12 |
+
</td>
|
13 |
+
</tr>
|
14 |
+
<tr>
|
15 |
+
<th><label for="pgcache_lifetime">Maximum lifetime of cache objects:</label></th>
|
16 |
+
<td><input id="pgcache_lifetime" type="text" name="pgcache.lifetime" value="<?php echo $config->get_integer('pgcache.lifetime'); ?>" size="8" /> seconds</td>
|
17 |
+
</tr>
|
18 |
+
<tr>
|
19 |
+
<th colspan="2">
|
20 |
+
<input type="hidden" name="pgcache.cache.logged" value="0" />
|
21 |
+
<label><input type="checkbox" name="pgcache.cache.logged" value="1"<?php checked($config->get_boolean('pgcache.cache.logged')); ?> /> Cache pages for logged in users</label>
|
22 |
+
</th>
|
23 |
+
</tr>
|
24 |
+
<tr>
|
25 |
+
<th colspan="2">
|
26 |
+
<input type="hidden" name="pgcache.compress" value="0" />
|
27 |
Â
<label><input type="checkbox" name="pgcache.compress" value="1"<?php checked($config->get_boolean('pgcache.compress')); ?> /> <acronym title="Hypertext Transfer Protocol">HTTP</acronym> compression (<acronym title="GNU zip">gzip</acronym> / deflate)</label>
|
28 |
+
</th>
|
29 |
+
</tr>
|
30 |
+
<tr>
|
31 |
+
<th colspan="2">
|
32 |
+
<input type="hidden" name="pgcache.cache.home" value="0" />
|
33 |
+
<label><input type="checkbox" name="pgcache.cache.home" value="1"<?php checked($config->get_boolean('pgcache.cache.home')); ?> /> Cache the home page</label>
|
34 |
+
</th>
|
35 |
+
</tr>
|
36 |
+
<tr>
|
37 |
+
<th colspan="2">
|
38 |
+
<input type="hidden" name="pgcache.cache.feed" value="0" />
|
39 |
+
<label><input type="checkbox" name="pgcache.cache.feed" value="1"<?php checked($config->get_boolean('pgcache.cache.feed')); ?> /> Cache <acronym title="Really Simple Syndication">RSS</acronym> feeds (site, post, post comments)</label>
|
40 |
+
</th>
|
41 |
+
</tr>
|
42 |
+
<tr>
|
43 |
+
<th colspan="2">
|
44 |
+
<input type="hidden" name="pgcache.cache.query" value="0" />
|
45 |
+
<label><input type="checkbox" name="pgcache.cache.query" value="1"<?php checked($config->get_boolean('pgcache.cache.query')); ?> /> Cache <acronym title="Uniform Resource Identifier">URI</acronym>s with query string variables</label>
|
46 |
+
</th>
|
47 |
+
</tr>
|
48 |
+
<tr>
|
49 |
+
<th valign="top"><label for="pgcache_reject_ua">Rejected User Agents:</label></th>
|
50 |
+
<td><textarea id="pgcache_reject_ua" name="pgcache.reject.ua" cols="30" rows="5"><?php echo htmlspecialchars(implode("\r\n", $config->get_array('pgcache.reject.ua'))); ?></textarea></td>
|
51 |
+
</tr>
|
52 |
+
<tr>
|
53 |
+
<th valign="top"><label for="pgcache_reject_cookie">Rejected Cookies:</label></th>
|
54 |
+
<td><textarea id="pgcache_reject_cookie" name="pgcache.reject.cookie" cols="30" rows="5"><?php echo htmlspecialchars(implode("\r\n", $config->get_array('pgcache.reject.cookie'))); ?></textarea></td>
|
55 |
+
</tr>
|
56 |
+
<tr>
|
57 |
+
<th valign="top"><label for="pgcache_reject_uri">Never cache the following pages:</label></th>
|
58 |
+
<td><textarea id="pgcache_reject_uri" name="pgcache.reject.uri" cols="30" rows="5"><?php echo htmlspecialchars(implode("\r\n", $config->get_array('pgcache.reject.uri'))); ?></textarea></td>
|
59 |
+
</tr>
|
60 |
+
<tr>
|
61 |
+
<th valign="top"><label for="pgcache_accept_files">Caching exception list:</label></th>
|
62 |
+
<td><textarea id="pgcache_accept_files" name="pgcache.accept.files" cols="30" rows="5"><?php echo htmlspecialchars(implode("\r\n", $config->get_array('pgcache.accept.files'))); ?></textarea></td>
|
63 |
+
</tr>
|
64 |
+
<tr>
|
65 |
+
<th valign="top"><label for="pgcache_cache_headers">Specify page headers:</label></th>
|
66 |
+
<td><textarea id="pgcache_cache_headers" name="pgcache.cache.headers" cols="30" rows="5"><?php echo htmlspecialchars(implode("\r\n", $config->get_array('pgcache.cache.headers'))); ?></textarea></td>
|
67 |
+
</tr>
|
68 |
+
</table>
|
69 |
+
|
70 |
+
<p class="submit">
|
71 |
+
<input type="submit" name="Submit" class="button-primary" value="Save changes" />
|
72 |
+
</p>
|
73 |
+
</form>
|
inc/popup/cdn_export_file.phtml
CHANGED
@@ -1,35 +1,39 @@
|
|
1 |
-
<script type="text/javascript">
|
2 |
-
var files = [
|
3 |
-
<?php $files_count = count($files); foreach ($files as $index => $file): ?>
|
4 |
-
'<?php echo addslashes($file); ?>'<?php if ($index < $files_count - 1): ?>,<?php endif; ?>
|
5 |
-
|
6 |
-
<?php endforeach; ?>
|
7 |
-
];
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
<tr>
|
16 |
-
<td>
|
17 |
-
<td
|
18 |
-
</tr>
|
19 |
-
<tr>
|
20 |
-
<td>
|
21 |
-
<td id="
|
22 |
-
</tr>
|
23 |
-
|
24 |
-
|
25 |
-
<
|
26 |
-
|
27 |
-
</
|
28 |
-
|
29 |
-
<
|
30 |
-
<
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
35 |
Â
<div id="cdn_export_file_log" class="log"></div>
|
1 |
+
<script type="text/javascript">
|
2 |
+
var files = [
|
3 |
+
<?php $files_count = count($files); foreach ($files as $index => $file): ?>
|
4 |
+
'<?php echo addslashes($file); ?>'<?php if ($index < $files_count - 1): ?>,<?php endif; ?>
|
5 |
+
|
6 |
+
<?php endforeach; ?>
|
7 |
+
];
|
8 |
+
|
9 |
+
jQuery(function() {
|
10 |
+
Cdn_Export_File.init(files);
|
11 |
+
});
|
12 |
+
</script>
|
13 |
+
|
14 |
+
<table cellspacing="5">
|
15 |
+
<tr>
|
16 |
+
<td>Total files:</td>
|
17 |
+
<td><?php echo $files_count; ?></td>
|
18 |
+
</tr>
|
19 |
+
<tr>
|
20 |
+
<td>Processed:</td>
|
21 |
+
<td id="cdn_export_file_processed">0</td>
|
22 |
+
</tr>
|
23 |
+
<tr>
|
24 |
+
<td>Status:</td>
|
25 |
+
<td id="cdn_export_file_status">-</td>
|
26 |
+
</tr>
|
27 |
+
</table>
|
28 |
+
|
29 |
+
<p>
|
30 |
+
<input id="cdn_export_file_start" class="button" type="button" value="Start"<?php if (! $files_count): ?> disabled="disabled"<?php endif; ?> />
|
31 |
+
</p>
|
32 |
+
|
33 |
+
<div id="cdn_export_file_progress" class="progress">
|
34 |
+
<div class="progress-value">0%</div>
|
35 |
+
<div class="progress-bar"></div>
|
36 |
+
<div class="clear"></div>
|
37 |
+
</div>
|
38 |
+
|
39 |
Â
<div id="cdn_export_file_log" class="log"></div>
|
inc/popup/cdn_export_library.phtml
ADDED
@@ -0,0 +1,34 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<script type="text/javascript">
|
2 |
+
/*<![CDATA[*/
|
3 |
+
jQuery(function() {
|
4 |
+
Cdn_Export_Library.init();
|
5 |
+
});
|
6 |
+
/*]]>*/
|
7 |
+
</script>
|
8 |
+
|
9 |
+
<table cellspacing="5">
|
10 |
+
<tr>
|
11 |
+
<td>Total media library attachments:</td>
|
12 |
+
<td id="cdn_export_library_total"><?php echo $total; ?></td>
|
13 |
+
</tr>
|
14 |
+
<tr>
|
15 |
+
<td>Processed:</td>
|
16 |
+
<td id="cdn_export_library_processed">0</td>
|
17 |
+
</tr>
|
18 |
+
<tr>
|
19 |
+
<td>Status:</td>
|
20 |
+
<td id="cdn_export_library_status">-</td>
|
21 |
+
</tr>
|
22 |
+
</table>
|
23 |
+
|
24 |
+
<p>
|
25 |
+
<input id="cdn_export_library_start" class="button" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
|
26 |
+
</p>
|
27 |
+
|
28 |
+
<div id="cdn_export_library_progress" class="progress">
|
29 |
+
<div class="progress-value">0%</div>
|
30 |
+
<div class="progress-bar"></div>
|
31 |
+
<div class="clear"></div>
|
32 |
+
</div>
|
33 |
+
|
34 |
+
<div id="cdn_export_library_log" class="log"></div>
|
inc/popup/cdn_export_table.phtml
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
<table cellspacing="5">
|
2 |
-
<tr>
|
3 |
-
<td>Total media library attachments:</th>
|
4 |
-
<td id="cdn_export_table_total"><?php echo $total; ?></td>
|
5 |
-
</tr>
|
6 |
-
<tr>
|
7 |
-
<td>Processed:</td>
|
8 |
-
<td id="cdn_export_table_processed">0</td>
|
9 |
-
</tr>
|
10 |
-
<tr>
|
11 |
-
<td>Status:</td>
|
12 |
-
<td id="cdn_export_table_status">-</td>
|
13 |
-
</tr>
|
14 |
-
</table>
|
15 |
-
|
16 |
-
<p>
|
17 |
-
<input id="cdn_export_table_start" class="button" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
|
18 |
-
</p>
|
19 |
-
|
20 |
-
<div id="cdn_export_table_progress" class="progress">
|
21 |
-
<div class="progress-value">0%</div>
|
22 |
-
<div class="progress-bar"></div>
|
23 |
-
<div class="clear"></div>
|
24 |
-
</div>
|
25 |
-
|
26 |
-
<div id="cdn_export_table_log" class="log"></div>
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
inc/popup/cdn_import_library.phtml
ADDED
@@ -0,0 +1,54 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<script type="text/javascript">
|
2 |
+
/*<![CDATA[*/
|
3 |
+
var cdn_host = '<?php echo $cdn_host; ?>';
|
4 |
+
|
5 |
+
jQuery(function() {
|
6 |
+
Cdn_Import_Library.init(cdn_host);
|
7 |
+
});
|
8 |
+
/*]]>*/
|
9 |
+
</script>
|
10 |
+
|
11 |
+
<table cellspacing="5">
|
12 |
+
<tr>
|
13 |
+
<td>Total posts:</td>
|
14 |
+
<td id="cdn_import_library_total"><?php echo $total; ?></td>
|
15 |
+
</tr>
|
16 |
+
<tr>
|
17 |
+
<td>Processed:</td>
|
18 |
+
<td id="cdn_import_library_processed">0</td>
|
19 |
+
</tr>
|
20 |
+
<tr>
|
21 |
+
<td>Status:</td>
|
22 |
+
<td id="cdn_import_library_status">-</td>
|
23 |
+
</tr>
|
24 |
+
<tr>
|
25 |
+
<td colspan="2">
|
26 |
+
<label><input id="cdn_import_library_redirect_permanent" type="checkbox" checked="checked" /> Use permanent redirects</label>
|
27 |
+
</td>
|
28 |
+
</tr>
|
29 |
+
<tr>
|
30 |
+
<td colspan="2">
|
31 |
+
<label><input id="cdn_import_library_redirect_cdn" type="checkbox" checked="checked" /> Redirect to CDN</label>
|
32 |
+
</td>
|
33 |
+
</tr>
|
34 |
+
</table>
|
35 |
+
|
36 |
+
<p>
|
37 |
+
<input id="cdn_import_library_start" class="button" type="button" value="Start"<?php if (! $total): ?> disabled="disabled"<?php endif; ?> />
|
38 |
+
</p>
|
39 |
+
|
40 |
+
<div id="cdn_import_library_progress" class="progress">
|
41 |
+
<div class="progress-value">0%</div>
|
42 |
+
<div class="progress-bar"></div>
|
43 |
+
<div class="clear"></div>
|
44 |
+
</div>
|
45 |
+
|
46 |
+
<div id="cdn_import_library_log" class="log"></div>
|
47 |
+
|
48 |
+
<p>
|
49 |
+
Add the following directives to your .htaccess file or if there are several hundred the should be added directly to your configuration file.
|
50 |
+
</p>
|
51 |
+
|
52 |
+
<p>
|
53 |
+
<textarea rows="10" cols="90" id="cdn_import_library_rules" class="rules"></textarea>
|
54 |
+
</p>
|
inc/popup/cdn_queue.phtml
CHANGED
@@ -1,60 +1,60 @@
|
|
1 |
-
<p id="w3tc-options-menu">
|
2 |
-
<a href="#cdn_queue_upload" rel="#cdn_queue_upload" class="tab<?php if ($cdn_queue_tab == 'upload'): ?> tab-selected<?php endif; ?>">Upload queue</a> |
|
3 |
-
<a href="#cdn_queue_delete" rel="#cdn_queue_delete" class="tab<?php if ($cdn_queue_tab == 'delete'): ?> tab-selected<?php endif; ?>">Delete queue</a>
|
4 |
-
</p>
|
5 |
-
|
6 |
-
<div id="cdn_queue_upload" class="tab-content"<?php if ($cdn_queue_tab != 'upload'): ?> style="display: none;"<?php endif; ?>>
|
7 |
-
<?php if (! empty($queue[W3_PLUGIN_CDN_COMMAND_UPLOAD])): ?>
|
8 |
-
<table class="table">
|
9 |
-
<tr>
|
10 |
-
<th>File</th>
|
11 |
-
<th>Last Error</th>
|
12 |
-
<th width="25%">Date</th>
|
13 |
-
<th width="10%">Delete</th>
|
14 |
-
</tr>
|
15 |
-
<?php foreach ((array) $queue[W3_PLUGIN_CDN_COMMAND_UPLOAD] as $result): ?>
|
16 |
-
<tr>
|
17 |
-
<td><?php echo htmlspecialchars($result->file); ?></td>
|
18 |
-
<td><?php echo htmlspecialchars($result->last_error); ?></td>
|
19 |
-
<td align="center"><?php echo htmlspecialchars($result->date); ?></td>
|
20 |
-
<td align="center">
|
21 |
-
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=upload&cdn_queue_action=delete&cdn_queue_id=<?php echo $result->id; ?>" class="cdn_queue_delete">Delete</a>
|
22 |
-
</td>
|
23 |
-
</tr>
|
24 |
-
<?php endforeach; ?>
|
25 |
-
</table>
|
26 |
-
<p>
|
27 |
-
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=upload&cdn_queue_action=empty&cdn_queue_type=<?php echo W3_PLUGIN_CDN_COMMAND_UPLOAD; ?>" class="cdn_queue_empty">Empty upload queue</a>
|
28 |
-
</p>
|
29 |
-
<?php else: ?>
|
30 |
-
<p class="empty">Upload queue is empty</p>
|
31 |
-
<?php endif; ?>
|
32 |
-
</div>
|
33 |
-
|
34 |
-
<div id="cdn_queue_delete" class="tab-content"<?php if ($cdn_queue_tab != 'delete'): ?> style="display: none;"<?php endif; ?>>
|
35 |
-
<?php if (! empty($queue[W3_PLUGIN_CDN_COMMAND_DELETE])): ?>
|
36 |
-
<table class="table">
|
37 |
-
<tr>
|
38 |
-
<th>File</th>
|
39 |
-
<th>Last Error</th>
|
40 |
-
<th width="25%">Date</th>
|
41 |
-
<th width="10%">Delete</th>
|
42 |
-
</tr>
|
43 |
-
<?php foreach ((array) $queue[W3_PLUGIN_CDN_COMMAND_DELETE] as $result): ?>
|
44 |
-
<tr>
|
45 |
-
<td><?php echo htmlspecialchars($result->file); ?></td>
|
46 |
-
<td><?php echo htmlspecialchars($result->last_error); ?></td>
|
47 |
-
<td align="center"><?php echo htmlspecialchars($result->date); ?></td>
|
48 |
-
<td align="center">
|
49 |
-
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=delete&cdn_queue_action=delete&cdn_queue_id=<?php echo $result->id; ?>" class="cdn_queue_delete">Delete</a>
|
50 |
-
</td>
|
51 |
-
</tr>
|
52 |
-
<?php endforeach; ?>
|
53 |
-
</table>
|
54 |
-
<p>
|
55 |
-
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=delete&cdn_queue_action=empty&cdn_queue_type=<?php echo W3_PLUGIN_CDN_COMMAND_DELETE; ?>" class="cdn_queue_empty">Empty upload queue</a>
|
56 |
-
</p>
|
57 |
-
<?php else: ?>
|
58 |
-
<p class="empty">
|
59 |
-
<?php endif; ?>
|
60 |
Â
</div>
|
1 |
+
<p id="w3tc-options-menu">
|
2 |
+
<a href="#cdn_queue_upload" rel="#cdn_queue_upload" class="tab<?php if ($cdn_queue_tab == 'upload'): ?> tab-selected<?php endif; ?>">Upload queue</a> |
|
3 |
+
<a href="#cdn_queue_delete" rel="#cdn_queue_delete" class="tab<?php if ($cdn_queue_tab == 'delete'): ?> tab-selected<?php endif; ?>">Delete queue</a>
|
4 |
+
</p>
|
5 |
+
|
6 |
+
<div id="cdn_queue_upload" class="tab-content"<?php if ($cdn_queue_tab != 'upload'): ?> style="display: none;"<?php endif; ?>>
|
7 |
+
<?php if (! empty($queue[W3_PLUGIN_CDN_COMMAND_UPLOAD])): ?>
|
8 |
+
<table class="table">
|
9 |
+
<tr>
|
10 |
+
<th>File</th>
|
11 |
+
<th>Last Error</th>
|
12 |
+
<th width="25%">Date</th>
|
13 |
+
<th width="10%">Delete</th>
|
14 |
+
</tr>
|
15 |
+
<?php foreach ((array) $queue[W3_PLUGIN_CDN_COMMAND_UPLOAD] as $result): ?>
|
16 |
+
<tr>
|
17 |
+
<td><?php echo htmlspecialchars($result->file); ?></td>
|
18 |
+
<td><?php echo htmlspecialchars($result->last_error); ?></td>
|
19 |
+
<td align="center"><?php echo htmlspecialchars($result->date); ?></td>
|
20 |
+
<td align="center">
|
21 |
+
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=upload&cdn_queue_action=delete&cdn_queue_id=<?php echo $result->id; ?>" class="cdn_queue_delete">Delete</a>
|
22 |
+
</td>
|
23 |
+
</tr>
|
24 |
+
<?php endforeach; ?>
|
25 |
+
</table>
|
26 |
+
<p>
|
27 |
+
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=upload&cdn_queue_action=empty&cdn_queue_type=<?php echo W3_PLUGIN_CDN_COMMAND_UPLOAD; ?>" class="cdn_queue_empty">Empty upload queue</a>
|
28 |
+
</p>
|
29 |
+
<?php else: ?>
|
30 |
+
<p class="empty">Upload queue is empty</p>
|
31 |
+
<?php endif; ?>
|
32 |
+
</div>
|
33 |
+
|
34 |
+
<div id="cdn_queue_delete" class="tab-content"<?php if ($cdn_queue_tab != 'delete'): ?> style="display: none;"<?php endif; ?>>
|
35 |
+
<?php if (! empty($queue[W3_PLUGIN_CDN_COMMAND_DELETE])): ?>
|
36 |
+
<table class="table">
|
37 |
+
<tr>
|
38 |
+
<th>File</th>
|
39 |
+
<th>Last Error</th>
|
40 |
+
<th width="25%">Date</th>
|
41 |
+
<th width="10%">Delete</th>
|
42 |
+
</tr>
|
43 |
+
<?php foreach ((array) $queue[W3_PLUGIN_CDN_COMMAND_DELETE] as $result): ?>
|
44 |
+
<tr>
|
45 |
+
<td><?php echo htmlspecialchars($result->file); ?></td>
|
46 |
+
<td><?php echo htmlspecialchars($result->last_error); ?></td>
|
47 |
+
<td align="center"><?php echo htmlspecialchars($result->date); ?></td>
|
48 |
+
<td align="center">
|
49 |
+
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=delete&cdn_queue_action=delete&cdn_queue_id=<?php echo $result->id; ?>" class="cdn_queue_delete">Delete</a>
|
50 |
+
</td>
|
51 |
+
</tr>
|
52 |
+
<?php endforeach; ?>
|
53 |
+
</table>
|
54 |
+
<p>
|
55 |
+
<a href="options-general.php?page=<?php echo W3_PLUGIN_FILE; ?>&w3tc_action=cdn_queue&cdn_queue_tab=delete&cdn_queue_action=empty&cdn_queue_type=<?php echo W3_PLUGIN_CDN_COMMAND_DELETE; ?>" class="cdn_queue_empty">Empty upload queue</a>
|
56 |
+
</p>
|
57 |
+
<?php else: ?>
|
58 |
+
<p class="empty">Delete queue is empty</p>
|
59 |
+
<?php endif; ?>
|
60 |
Â
</div>
|
inc/popup/common/footer.phtml
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
</div>
|
2 |
-
</body>
|
3 |
Â
</html>
|
1 |
+
</div>
|
2 |
+
</body>
|
3 |
Â
</html>
|
inc/popup/common/header.phtml
CHANGED
@@ -1,42 +1,42 @@
|
|
1 |
-
<?php
|
2 |
-
if (! isset($title)) {
|
3 |
-
$title = 'Untitled';
|
4 |
-
}
|
5 |
-
|
6 |
-
if (! isset($errors)) {
|
7 |
-
$errors = array();
|
8 |
-
}
|
9 |
-
|
10 |
-
if (! isset($notes)) {
|
11 |
-
$notes =array();
|
12 |
-
}
|
13 |
-
?>
|
14 |
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
15 |
-
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
|
16 |
-
<head>
|
17 |
-
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/w3-total-cache/inc/css/popup.css"></link>
|
18 |
-
<script type="text/javascript" src="/wp-includes/js/jquery/jquery.js"></script>
|
19 |
-
<script type="text/javascript" src="/wp-content/plugins/w3-total-cache/inc/js/popup.js"></script>
|
20 |
-
<title><?php echo htmlspecialchars($title); ?> - W3 Total Cache</title>
|
21 |
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
22 |
-
</head>
|
23 |
-
<body>
|
24 |
-
<div id="content">
|
25 |
-
<h1><?php echo htmlspecialchars($title); ?></h1>
|
26 |
-
|
27 |
-
<?php if (count($errors)): ?>
|
28 |
-
<div id="message" class="error">
|
29 |
-
<?php foreach ($errors as $error): ?>
|
30 |
-
<p><?php echo $error; ?></p>
|
31 |
-
<?php endforeach; ?>
|
32 |
-
</div>
|
33 |
-
<?php endif; ?>
|
34 |
-
|
35 |
-
<?php if (count($notes)): ?>
|
36 |
-
<div id="message" class="updated fade">
|
37 |
-
<?php foreach ($notes as $note): ?>
|
38 |
-
<p><?php echo $note; ?></p>
|
39 |
-
<?php endforeach; ?>
|
40 |
-
</div>
|
41 |
-
<?php endif; ?>
|
42 |
-
|
1 |
+
<?php
|
2 |
+
if (! isset($title)) {
|
3 |
+
$title = 'Untitled';
|
4 |
+
}
|
5 |
+
|
6 |
+
if (! isset($errors)) {
|
7 |
+
$errors = array();
|
8 |
+
}
|
9 |
+
|
10 |
+
if (! isset($notes)) {
|
11 |
+
$notes =array();
|
12 |
+
}
|
13 |
+
?>
|
14 |
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
15 |
+
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
|
16 |
+
<head>
|
17 |
+
<link rel="stylesheet" type="text/css" href="/wp-content/plugins/w3-total-cache/inc/css/popup.css"></link>
|
18 |
+
<script type="text/javascript" src="/wp-includes/js/jquery/jquery.js"></script>
|
19 |
+
<script type="text/javascript" src="/wp-content/plugins/w3-total-cache/inc/js/popup.js"></script>
|
20 |
+
<title><?php echo htmlspecialchars($title); ?> - W3 Total Cache</title>
|
21 |
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
22 |
+
</head>
|
23 |
+
<body>
|
24 |
+
<div id="content">
|
25 |
+
<h1><?php echo htmlspecialchars($title); ?></h1>
|
26 |
+
|
27 |
+
<?php if (count($errors)): ?>
|
28 |
+
<div id="message" class="error">
|
29 |
+
<?php foreach ($errors as $error): ?>
|
30 |
+
<p><?php echo $error; ?></p>
|
31 |
+
<?php endforeach; ?>
|
32 |
+
</div>
|
33 |
+
<?php endif; ?>
|
34 |
+
|
35 |
+
<?php if (count($notes)): ?>
|
36 |
+
<div id="message" class="updated fade">
|
37 |
+
<?php foreach ($notes as $note): ?>
|
38 |
+
<p><?php echo $note; ?></p>
|
39 |
+
<?php endforeach; ?>
|
40 |
+
</div>
|
41 |
+
<?php endif; ?>
|
42 |
+
|
lib/Minify/UPGRADING.txt
CHANGED
@@ -4,7 +4,7 @@ UPGRADING FROM 2.1.*
|
|
4 |
Â
|
5 |
Â
1. Rename the following files:
|
6 |
Â
|
7 |
-
/min/config.php --> /min/old_config.php
|
8 |
Â
/min/groupsConfig.php --> /min/old_groupsConfig.php
|
9 |
Â
|
10 |
Â
2. Overwrite all files in /min (and /min_unit_tests) with those from this zip.
|
4 |
Â
|
5 |
Â
1. Rename the following files:
|
6 |
Â
|
7 |
+
/min/config.php --> /min/old_config.php
|
8 |
Â
/min/groupsConfig.php --> /min/old_groupsConfig.php
|
9 |
Â
|
10 |
Â
2. Overwrite all files in /min (and /min_unit_tests) with those from this zip.
|
lib/Minify/min/README.txt
CHANGED
@@ -72,8 +72,8 @@ For the best performance, edit groupsConfig.php to pre-specify groups of files
|
|
72 |
Â
to be combined under preset keys. E.g., here's an example configuration in
|
73 |
Â
groupsConfig.php:
|
74 |
Â
|
75 |
-
return array(
|
76 |
-
'js' => array('//js/Class.js', '//js/email.js')
|
77 |
Â
);
|
78 |
Â
|
79 |
Â
This pre-selects the following files to be combined under the key "js":
|
72 |
Â
to be combined under preset keys. E.g., here's an example configuration in
|
73 |
Â
groupsConfig.php:
|
74 |
Â
|
75 |
+
return array(
|
76 |
+
'js' => array('//js/Class.js', '//js/email.js')
|
77 |
Â
);
|
78 |
Â
|
79 |
Â
This pre-selects the following files to be combined under the key "js":
|
lib/Minify/min/builder/ocCheck.php
CHANGED
@@ -26,8 +26,8 @@ if (isset($_GET['hello'])) {
|
|
26 |
Â
'content' => 'World!'
|
27 |
Â
,'method' => 'deflate'
|
28 |
Â
));
|
29 |
-
$he->encode();
|
30 |
-
$he->sendAll();
|
31 |
Â
|
32 |
Â
} else {
|
33 |
Â
// echo status "0" or "1"
|
26 |
Â
'content' => 'World!'
|
27 |
Â
,'method' => 'deflate'
|
28 |
Â
));
|
29 |
+
$he->encode();
|
30 |
+
$he->sendAll();
|
31 |
Â
|
32 |
Â
} else {
|
33 |
Â
// echo status "0" or "1"
|
lib/Minify/min/index.php
CHANGED
@@ -15,7 +15,7 @@ require MINIFY_MIN_DIR . '/config.php';
|
|
15 |
Â
// setup include path
|
16 |
Â
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
17 |
Â
|
18 |
-
require 'Minify.php';
|
19 |
Â
|
20 |
Â
Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
|
21 |
Â
Minify::setCache(
|
@@ -28,6 +28,7 @@ if ($min_documentRoot) {
|
|
28 |
Â
} elseif (0 === stripos(PHP_OS, 'win')) {
|
29 |
Â
Minify::setDocRoot(); // IIS may need help
|
30 |
Â
}
|
Â
|
|
31 |
Â
|
32 |
Â
$min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks;
|
33 |
Â
|
@@ -36,9 +37,9 @@ if ($min_allowDebugFlag && isset($_GET['debug'])) {
|
|
36 |
Â
}
|
37 |
Â
|
38 |
Â
if ($min_errorLogger) {
|
39 |
-
require_once 'Minify/Logger.php';
|
40 |
Â
if (true === $min_errorLogger) {
|
41 |
-
require_once 'FirePHP.php';
|
42 |
Â
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
43 |
Â
} else {
|
44 |
Â
Minify_Logger::setLogger($min_errorLogger);
|
@@ -50,7 +51,7 @@ if (preg_match('/&\\d/', $_SERVER['QUERY_STRING'])) {
|
|
50 |
Â
$min_serveOptions['maxAge'] = 31536000;
|
51 |
Â
}
|
52 |
Â
if (isset($_GET['g'])) {
|
53 |
-
//
|
54 |
Â
$min_serveOptions['minApp']['groups'] = (require MINIFY_MIN_DIR . '/groupsConfig.php');
|
55 |
Â
}
|
56 |
Â
if (isset($_GET['f']) || isset($_GET['g'])) {
|
15 |
Â
// setup include path
|
16 |
Â
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
17 |
Â
|
18 |
+
require $min_libPath . '/Minify.php';
|
19 |
Â
|
20 |
Â
Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
|
21 |
Â
Minify::setCache(
|
28 |
Â
} elseif (0 === stripos(PHP_OS, 'win')) {
|
29 |
Â
Minify::setDocRoot(); // IIS may need help
|
30 |
Â
}
|
31 |
+
$_SERVER['DOCUMENT_ROOT'] = rtrim($_SERVER['DOCUMENT_ROOT'], '/\\');
|
32 |
Â
|
33 |
Â
$min_serveOptions['minifierOptions']['text/css']['symlinks'] = $min_symlinks;
|
34 |
Â
|
37 |
Â
}
|
38 |
Â
|
39 |
Â
if ($min_errorLogger) {
|
40 |
+
require_once $min_libPath . '/Minify/Logger.php';
|
41 |
Â
if (true === $min_errorLogger) {
|
42 |
+
require_once $min_libPath . '/FirePHP.php';
|
43 |
Â
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
44 |
Â
} else {
|
45 |
Â
Minify_Logger::setLogger($min_errorLogger);
|
51 |
Â
$min_serveOptions['maxAge'] = 31536000;
|
52 |
Â
}
|
53 |
Â
if (isset($_GET['g'])) {
|
54 |
+
// we'll need groups config
|
55 |
Â
$min_serveOptions['minApp']['groups'] = (require MINIFY_MIN_DIR . '/groupsConfig.php');
|
56 |
Â
}
|
57 |
Â
if (isset($_GET['f']) || isset($_GET['g'])) {
|
lib/Minify/min/lib/HTTP/Encoder.php
CHANGED
@@ -33,11 +33,11 @@
|
|
33 |
Â
* </code>
|
34 |
Â
*
|
35 |
Â
* For more control over headers, use getHeaders() and getData() and send your
|
36 |
-
* own output.
|
37 |
-
*
|
38 |
-
* Note: If you don't need header mgmt, use PHP's native gzencode, gzdeflate,
|
39 |
-
* and gzcompress functions for gzip, deflate, and compress-encoding
|
40 |
-
* respectively.
|
41 |
Â
*
|
42 |
Â
* @package Minify
|
43 |
Â
* @subpackage HTTP
|
@@ -88,7 +88,7 @@ class HTTP_Encoder {
|
|
88 |
Â
*
|
89 |
Â
* @return null
|
90 |
Â
*/
|
91 |
-
public function __construct($spec)
|
92 |
Â
{
|
93 |
Â
$this->_content = $spec['content'];
|
94 |
Â
$this->_headers['Content-Length'] = (string)strlen($this->_content);
|
@@ -111,7 +111,7 @@ class HTTP_Encoder {
|
|
111 |
Â
*
|
112 |
Â
* return string
|
113 |
Â
*/
|
114 |
-
public function getContent()
|
115 |
Â
{
|
116 |
Â
return $this->_content;
|
117 |
Â
}
|
@@ -130,7 +130,7 @@ class HTTP_Encoder {
|
|
130 |
Â
*
|
131 |
Â
* @return array
|
132 |
Â
*/
|
133 |
-
public function getHeaders()
|
134 |
Â
{
|
135 |
Â
return $this->_headers;
|
136 |
Â
}
|
@@ -146,7 +146,7 @@ class HTTP_Encoder {
|
|
146 |
Â
*
|
147 |
Â
* @return null
|
148 |
Â
*/
|
149 |
-
public function sendHeaders()
|
150 |
Â
{
|
151 |
Â
foreach ($this->_headers as $name => $val) {
|
152 |
Â
header($name . ': ' . $val);
|
@@ -164,7 +164,7 @@ class HTTP_Encoder {
|
|
164 |
Â
*
|
165 |
Â
* @return null
|
166 |
Â
*/
|
167 |
-
public function sendAll()
|
168 |
Â
{
|
169 |
Â
$this->sendHeaders();
|
170 |
Â
echo $this->_content;
|
@@ -181,16 +181,16 @@ class HTTP_Encoder {
|
|
181 |
Â
* be non 0. The methods are favored in order of gzip, deflate, then
|
182 |
Â
* compress. Deflate is always smallest and generally faster, but is
|
183 |
Â
* rarely sent by servers, so client support could be buggier.
|
184 |
-
*
|
185 |
Â
* @param bool $allowCompress allow the older compress encoding
|
186 |
Â
*
|
187 |
-
* @param bool $allowDeflate allow the more recent deflate encoding
|
188 |
Â
*
|
189 |
Â
* @return array two values, 1st is the actual encoding method, 2nd is the
|
190 |
Â
* alias of that method to use in the Content-Encoding header (some browsers
|
191 |
Â
* call gzip "x-gzip" etc.)
|
192 |
Â
*/
|
193 |
-
public static function getAcceptedEncoding($allowCompress = true, $allowDeflate = true)
|
194 |
Â
{
|
195 |
Â
// @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
196 |
Â
|
@@ -244,14 +244,14 @@ class HTTP_Encoder {
|
|
244 |
Â
* this fails, false is returned.
|
245 |
Â
*
|
246 |
Â
* The header "Vary: Accept-Encoding" is added. If encoding is successful,
|
247 |
-
* the Content-Length header is updated, and Content-Encoding is also added.
|
248 |
-
*
|
249 |
Â
* @param int $compressionLevel given to zlib functions. If not given, the
|
250 |
Â
* class default will be used.
|
251 |
Â
*
|
252 |
Â
* @return bool success true if the content was actually compressed
|
253 |
Â
*/
|
254 |
-
public function encode($compressionLevel = null)
|
255 |
Â
{
|
256 |
Â
$this->_headers['Vary'] = 'Accept-Encoding';
|
257 |
Â
if (null === $compressionLevel) {
|
@@ -262,9 +262,9 @@ class HTTP_Encoder {
|
|
262 |
Â
|| !extension_loaded('zlib'))
|
263 |
Â
{
|
264 |
Â
return false;
|
265 |
-
}
|
266 |
-
if ($this->_encodeMethod[0] === 'deflate') {
|
267 |
-
$encoded = gzdeflate($this->_content, $compressionLevel);
|
268 |
Â
} elseif ($this->_encodeMethod[0] === 'gzip') {
|
269 |
Â
$encoded = gzencode($this->_content, $compressionLevel);
|
270 |
Â
} else {
|
@@ -285,7 +285,7 @@ class HTTP_Encoder {
|
|
285 |
Â
* This is a convenience method for common use of the class
|
286 |
Â
*
|
287 |
Â
* @param string $content
|
288 |
-
*
|
289 |
Â
* @param int $compressionLevel given to zlib functions. If not given, the
|
290 |
Â
* class default will be used.
|
291 |
Â
*
|
@@ -296,12 +296,12 @@ class HTTP_Encoder {
|
|
296 |
Â
if (null === $compressionLevel) {
|
297 |
Â
$compressionLevel = self::$compressionLevel;
|
298 |
Â
}
|
299 |
-
$he = new HTTP_Encoder(array('content' => $content));
|
300 |
-
$ret = $he->encode($compressionLevel);
|
301 |
Â
$he->sendAll();
|
302 |
Â
return $ret;
|
303 |
-
}
|
304 |
-
|
305 |
Â
protected $_content = '';
|
306 |
Â
protected $_headers = array();
|
307 |
Â
protected $_encodeMethod = array('', '');
|
33 |
Â
* </code>
|
34 |
Â
*
|
35 |
Â
* For more control over headers, use getHeaders() and getData() and send your
|
36 |
+
* own output.
|
37 |
+
*
|
38 |
+
* Note: If you don't need header mgmt, use PHP's native gzencode, gzdeflate,
|
39 |
+
* and gzcompress functions for gzip, deflate, and compress-encoding
|
40 |
+
* respectively.
|
41 |
Â
*
|
42 |
Â
* @package Minify
|
43 |
Â
* @subpackage HTTP
|
88 |
Â
*
|
89 |
Â
* @return null
|
90 |
Â
*/
|
91 |
+
public function __construct($spec)
|
92 |
Â
{
|
93 |
Â
$this->_content = $spec['content'];
|
94 |
Â
$this->_headers['Content-Length'] = (string)strlen($this->_content);
|
111 |
Â
*
|
112 |
Â
* return string
|
113 |
Â
*/
|
114 |
+
public function getContent()
|
115 |
Â
{
|
116 |
Â
return $this->_content;
|
117 |
Â
}
|
130 |
Â
*
|
131 |
Â
* @return array
|
132 |
Â
*/
|
133 |
+
public function getHeaders()
|
134 |
Â
{
|
135 |
Â
return $this->_headers;
|
136 |
Â
}
|
146 |
Â
*
|
147 |
Â
* @return null
|
148 |
Â
*/
|
149 |
+
public function sendHeaders()
|
150 |
Â
{
|
151 |
Â
foreach ($this->_headers as $name => $val) {
|
152 |
Â
header($name . ': ' . $val);
|
164 |
Â
*
|
165 |
Â
* @return null
|
166 |
Â
*/
|
167 |
+
public function sendAll()
|
168 |
Â
{
|
169 |
Â
$this->sendHeaders();
|
170 |
Â
echo $this->_content;
|
181 |
Â
* be non 0. The methods are favored in order of gzip, deflate, then
|
182 |
Â
* compress. Deflate is always smallest and generally faster, but is
|
183 |
Â
* rarely sent by servers, so client support could be buggier.
|
184 |
+
*
|
185 |
Â
* @param bool $allowCompress allow the older compress encoding
|
186 |
Â
*
|
187 |
+
* @param bool $allowDeflate allow the more recent deflate encoding
|
188 |
Â
*
|
189 |
Â
* @return array two values, 1st is the actual encoding method, 2nd is the
|
190 |
Â
* alias of that method to use in the Content-Encoding header (some browsers
|
191 |
Â
* call gzip "x-gzip" etc.)
|
192 |
Â
*/
|
193 |
+
public static function getAcceptedEncoding($allowCompress = true, $allowDeflate = true)
|
194 |
Â
{
|
195 |
Â
// @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
196 |
Â
|
244 |
Â
* this fails, false is returned.
|
245 |
Â
*
|
246 |
Â
* The header "Vary: Accept-Encoding" is added. If encoding is successful,
|
247 |
+
* the Content-Length header is updated, and Content-Encoding is also added.
|
248 |
+
*
|
249 |
Â
* @param int $compressionLevel given to zlib functions. If not given, the
|
250 |
Â
* class default will be used.
|
251 |
Â
*
|
252 |
Â
* @return bool success true if the content was actually compressed
|
253 |
Â
*/
|
254 |
+
public function encode($compressionLevel = null)
|
255 |
Â
{
|
256 |
Â
$this->_headers['Vary'] = 'Accept-Encoding';
|
257 |
Â
if (null === $compressionLevel) {
|
262 |
Â
|| !extension_loaded('zlib'))
|
263 |
Â
{
|
264 |
Â
return false;
|
265 |
+
}
|
266 |
+
if ($this->_encodeMethod[0] === 'deflate') {
|
267 |
+
$encoded = gzdeflate($this->_content, $compressionLevel);
|
268 |
Â
} elseif ($this->_encodeMethod[0] === 'gzip') {
|
269 |
Â
$encoded = gzencode($this->_content, $compressionLevel);
|
270 |
Â
} else {
|
285 |
Â
* This is a convenience method for common use of the class
|
286 |
Â
*
|
287 |
Â
* @param string $content
|
288 |
+
*
|
289 |
Â
* @param int $compressionLevel given to zlib functions. If not given, the
|
290 |
Â
* class default will be used.
|
291 |
Â
*
|
296 |
Â
if (null === $compressionLevel) {
|
297 |
Â
$compressionLevel = self::$compressionLevel;
|
298 |
Â
}
|
299 |
+
$he = new HTTP_Encoder(array('content' => $content));
|
300 |
+
$ret = $he->encode($compressionLevel);
|
301 |
Â
$he->sendAll();
|
302 |
Â
return $ret;
|
303 |
+
}
|
304 |
+
|
305 |
Â
protected $_content = '';
|
306 |
Â
protected $_headers = array();
|
307 |
Â
protected $_encodeMethod = array('', '');
|
lib/Minify/min/lib/Minify.php
CHANGED
@@ -512,7 +512,7 @@ class Minify {
|
|
512 |
Â
{
|
513 |
Â
if (self::$_options['bubbleCssImports']) {
|
514 |
Â
// bubble CSS imports
|
515 |
-
preg_match_all('/@import.*?;/', $css, $imports);
|
516 |
Â
$css = implode('', $imports[0]) . preg_replace('/@import.*?;/', '', $css);
|
517 |
Â
} else if ('' !== self::$importWarning) {
|
518 |
Â
// remove comments so we don't mistake { in a comment as a block
|
512 |
Â
{
|
513 |
Â
if (self::$_options['bubbleCssImports']) {
|
514 |
Â
// bubble CSS imports
|
515 |
+
preg_match_all('/@import.*?;/', $css, $imports);
|
516 |
Â
$css = implode('', $imports[0]) . preg_replace('/@import.*?;/', '', $css);
|
517 |
Â
} else if ('' !== self::$importWarning) {
|
518 |
Â
// remove comments so we don't mistake { in a comment as a block
|
lib/Minify/min/lib/Minify/CSS.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Class Minify_CSS
|
4 |
-
* @package Minify
|
5 |
-
*/
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Minify CSS
|
9 |
-
*
|
10 |
-
* This class uses Minify_CSS_Compressor and Minify_CSS_UriRewriter to
|
11 |
-
* minify CSS and rewrite relative URIs.
|
12 |
-
*
|
13 |
-
* @package Minify
|
14 |
-
* @author Stephen Clay <steve@mrclay.org>
|
15 |
-
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
16 |
-
*/
|
17 |
-
class Minify_CSS {
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Minify a CSS string
|
21 |
-
*
|
22 |
-
* @param string $css
|
23 |
-
*
|
24 |
-
* @param array $options available options:
|
25 |
-
*
|
26 |
-
* 'preserveComments': (default true) multi-line comments that begin
|
27 |
-
* with "/*!" will be preserved with newlines before and after to
|
28 |
-
* enhance readability.
|
29 |
-
*
|
30 |
-
* 'prependRelativePath': (default null) if given, this string will be
|
31 |
-
* prepended to all relative URIs in import/url declarations
|
32 |
-
*
|
33 |
-
* 'currentDir': (default null) if given, this is assumed to be the
|
34 |
-
* directory of the current CSS file. Using this, minify will rewrite
|
35 |
-
* all relative URIs in import/url declarations to correctly point to
|
36 |
-
* the desired files. For this to work, the files *must* exist and be
|
37 |
-
* visible by the PHP process.
|
38 |
-
*
|
39 |
Â
* 'symlinks': (default = array()) If the CSS file is stored in
|
40 |
Â
* a symlink-ed directory, provide an array of link paths to
|
41 |
Â
* target paths, where the link paths are within the document root. Because
|
@@ -44,40 +44,40 @@ class Minify_CSS {
|
|
44 |
Â
* <code>
|
45 |
Â
* array('//symlink' => '/real/target/path') // unix
|
46 |
Â
* array('//static' => 'D:\\staticStorage') // Windows
|
47 |
-
* </code>
|
48 |
-
*
|
49 |
-
* @return string
|
50 |
-
*/
|
51 |
-
public static function minify($css, $options = array())
|
52 |
-
{
|
53 |
-
require_once 'Minify/CSS/Compressor.php';
|
54 |
-
if (isset($options['preserveComments'])
|
55 |
-
&& !$options['preserveComments']) {
|
56 |
-
$css = Minify_CSS_Compressor::process($css, $options);
|
57 |
-
} else {
|
58 |
-
require_once 'Minify/CommentPreserver.php';
|
59 |
-
$css = Minify_CommentPreserver::process(
|
60 |
-
$css
|
61 |
-
,array('Minify_CSS_Compressor', 'process')
|
62 |
-
,array($options)
|
63 |
-
);
|
64 |
-
}
|
65 |
-
if (! isset($options['currentDir']) && ! isset($options['prependRelativePath'])) {
|
66 |
-
return $css;
|
67 |
-
}
|
68 |
-
require_once 'Minify/CSS/UriRewriter.php';
|
69 |
-
if (isset($options['currentDir'])) {
|
70 |
-
return Minify_CSS_UriRewriter::rewrite(
|
71 |
-
$css
|
72 |
-
,$options['currentDir']
|
73 |
-
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
74 |
-
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
75 |
-
);
|
76 |
-
} else {
|
77 |
-
return Minify_CSS_UriRewriter::prepend(
|
78 |
-
$css
|
79 |
-
,$options['prependRelativePath']
|
80 |
-
);
|
81 |
-
}
|
82 |
-
}
|
83 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_CSS
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Minify CSS
|
9 |
+
*
|
10 |
+
* This class uses Minify_CSS_Compressor and Minify_CSS_UriRewriter to
|
11 |
+
* minify CSS and rewrite relative URIs.
|
12 |
+
*
|
13 |
+
* @package Minify
|
14 |
+
* @author Stephen Clay <steve@mrclay.org>
|
15 |
+
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
16 |
+
*/
|
17 |
+
class Minify_CSS {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Minify a CSS string
|
21 |
+
*
|
22 |
+
* @param string $css
|
23 |
+
*
|
24 |
+
* @param array $options available options:
|
25 |
+
*
|
26 |
+
* 'preserveComments': (default true) multi-line comments that begin
|
27 |
+
* with "/*!" will be preserved with newlines before and after to
|
28 |
+
* enhance readability.
|
29 |
+
*
|
30 |
+
* 'prependRelativePath': (default null) if given, this string will be
|
31 |
+
* prepended to all relative URIs in import/url declarations
|
32 |
+
*
|
33 |
+
* 'currentDir': (default null) if given, this is assumed to be the
|
34 |
+
* directory of the current CSS file. Using this, minify will rewrite
|
35 |
+
* all relative URIs in import/url declarations to correctly point to
|
36 |
+
* the desired files. For this to work, the files *must* exist and be
|
37 |
+
* visible by the PHP process.
|
38 |
+
*
|
39 |
Â
* 'symlinks': (default = array()) If the CSS file is stored in
|
40 |
Â
* a symlink-ed directory, provide an array of link paths to
|
41 |
Â
* target paths, where the link paths are within the document root. Because
|
44 |
Â
* <code>
|
45 |
Â
* array('//symlink' => '/real/target/path') // unix
|
46 |
Â
* array('//static' => 'D:\\staticStorage') // Windows
|
47 |
+
* </code>
|
48 |
+
*
|
49 |
+
* @return string
|
50 |
+
*/
|
51 |
+
public static function minify($css, $options = array())
|
52 |
+
{
|
53 |
+
require_once 'Minify/CSS/Compressor.php';
|
54 |
+
if (isset($options['preserveComments'])
|
55 |
+
&& !$options['preserveComments']) {
|
56 |
+
$css = Minify_CSS_Compressor::process($css, $options);
|
57 |
+
} else {
|
58 |
+
require_once 'Minify/CommentPreserver.php';
|
59 |
+
$css = Minify_CommentPreserver::process(
|
60 |
+
$css
|
61 |
+
,array('Minify_CSS_Compressor', 'process')
|
62 |
+
,array($options)
|
63 |
+
);
|
64 |
+
}
|
65 |
+
if (! isset($options['currentDir']) && ! isset($options['prependRelativePath'])) {
|
66 |
+
return $css;
|
67 |
+
}
|
68 |
+
require_once 'Minify/CSS/UriRewriter.php';
|
69 |
+
if (isset($options['currentDir'])) {
|
70 |
+
return Minify_CSS_UriRewriter::rewrite(
|
71 |
+
$css
|
72 |
+
,$options['currentDir']
|
73 |
+
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
74 |
+
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
75 |
+
);
|
76 |
+
} else {
|
77 |
+
return Minify_CSS_UriRewriter::prepend(
|
78 |
+
$css
|
79 |
+
,$options['prependRelativePath']
|
80 |
+
);
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
lib/Minify/min/lib/Minify/CSS/Compressor.php
CHANGED
@@ -1,250 +1,250 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Class Minify_CSS_Compressor
|
4 |
-
* @package Minify
|
5 |
-
*/
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Compress CSS
|
9 |
-
*
|
10 |
-
* This is a heavy regex-based removal of whitespace, unnecessary
|
11 |
-
* comments and tokens, and some CSS value minimization, where practical.
|
12 |
-
* Many steps have been taken to avoid breaking comment-based hacks,
|
13 |
-
* including the ie5/mac filter (and its inversion), but expect tricky
|
14 |
-
* hacks involving comment tokens in 'content' value strings to break
|
15 |
-
* minimization badly. A test suite is available.
|
16 |
-
*
|
17 |
-
* @package Minify
|
18 |
-
* @author Stephen Clay <steve@mrclay.org>
|
19 |
-
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
20 |
-
*/
|
21 |
-
class Minify_CSS_Compressor {
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Minify a CSS string
|
25 |
-
*
|
26 |
-
* @param string $css
|
27 |
-
*
|
28 |
-
* @param array $options (currently ignored)
|
29 |
-
*
|
30 |
-
* @return string
|
31 |
-
*/
|
32 |
-
public static function process($css, $options = array())
|
33 |
-
{
|
34 |
-
$obj = new Minify_CSS_Compressor($options);
|
35 |
-
return $obj->_process($css);
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @var array options
|
40 |
-
*/
|
41 |
-
protected $_options = null;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* @var bool Are we "in" a hack?
|
45 |
-
*
|
46 |
-
* I.e. are some browsers targetted until the next comment?
|
47 |
-
*/
|
48 |
-
protected $_inHack = false;
|
49 |
-
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Constructor
|
53 |
-
*
|
54 |
-
* @param array $options (currently ignored)
|
55 |
-
*
|
56 |
-
* @return null
|
57 |
-
*/
|
58 |
-
private function __construct($options) {
|
59 |
-
$this->_options = $options;
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Minify a CSS string
|
64 |
-
*
|
65 |
-
* @param string $css
|
66 |
-
*
|
67 |
-
* @return string
|
68 |
-
*/
|
69 |
-
protected function _process($css)
|
70 |
-
{
|
71 |
-
$css = str_replace("\r\n", "\n", $css);
|
72 |
-
|
73 |
-
// preserve empty comment after '>'
|
74 |
-
// http://www.webdevout.net/css-hacks#in_css-selectors
|
75 |
-
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
|
76 |
-
|
77 |
-
// preserve empty comment between property and value
|
78 |
-
// http://css-discuss.incutio.com/?page=BoxModelHack
|
79 |
-
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
|
80 |
-
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
|
81 |
-
|
82 |
-
// apply callback to all valid comments (and strip out surrounding ws
|
83 |
-
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
|
84 |
-
,array($this, '_commentCB'), $css);
|
85 |
-
|
86 |
-
// remove ws around { } and last semicolon in declaration block
|
87 |
-
$css = preg_replace('/\\s*{\\s*/', '{', $css);
|
88 |
-
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
|
89 |
-
|
90 |
-
// remove ws surrounding semicolons
|
91 |
-
$css = preg_replace('/\\s*;\\s*/', ';', $css);
|
92 |
-
|
93 |
-
// remove ws around urls
|
94 |
-
$css = preg_replace('/
|
95 |
-
url\\( # url(
|
96 |
-
\\s*
|
97 |
-
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
|
98 |
-
\\s*
|
99 |
-
\\) # )
|
100 |
-
/x', 'url($1)', $css);
|
101 |
-
|
102 |
-
// remove ws between rules and colons
|
103 |
-
$css = preg_replace('/
|
104 |
-
\\s*
|
105 |
-
([{;]) # 1 = beginning of block or rule separator
|
106 |
-
\\s*
|
107 |
-
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
|
108 |
-
\\s*
|
109 |
-
:
|
110 |
-
\\s*
|
111 |
-
(\\b|[#\'"]) # 3 = first character of a value
|
112 |
-
/x', '$1$2:$3', $css);
|
113 |
-
|
114 |
-
// remove ws in selectors
|
115 |
-
$css = preg_replace_callback('/
|
116 |
-
(?: # non-capture
|
117 |
-
\\s*
|
118 |
-
[^~>+,\\s]+ # selector part
|
119 |
-
\\s*
|
120 |
-
[,>+~] # combinators
|
121 |
-
)+
|
122 |
-
\\s*
|
123 |
-
[^~>+,\\s]+ # selector part
|
124 |
-
{ # open declaration block
|
125 |
-
/x'
|
126 |
-
,array($this, '_selectorsCB'), $css);
|
127 |
-
|
128 |
-
// minimize hex colors
|
129 |
-
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
|
130 |
-
, '$1#$2$3$4$5', $css);
|
131 |
-
|
132 |
-
// remove spaces between font families
|
133 |
-
$css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
|
134 |
-
,array($this, '_fontFamilyCB'), $css);
|
135 |
-
|
136 |
-
$css = preg_replace('/@import\\s+url/', '@import url', $css);
|
137 |
-
|
138 |
-
// replace any ws involving newlines with a single newline
|
139 |
-
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
|
140 |
-
|
141 |
-
// separate common descendent selectors w/ newlines (to limit line lengths)
|
142 |
-
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
|
143 |
-
|
144 |
-
// Use newline after 1st numeric value (to limit line lengths).
|
145 |
-
$css = preg_replace('/
|
146 |
-
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
|
147 |
-
\\s+
|
148 |
-
/x'
|
149 |
-
,"$1\n", $css);
|
150 |
-
|
151 |
-
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
|
152 |
-
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
|
153 |
-
|
154 |
-
return trim($css);
|
155 |
-
}
|
156 |
-
|
157 |
-
/**
|
158 |
-
* Replace what looks like a set of selectors
|
159 |
-
*
|
160 |
-
* @param array $m regex matches
|
161 |
-
*
|
162 |
-
* @return string
|
163 |
-
*/
|
164 |
-
protected function _selectorsCB($m)
|
165 |
-
{
|
166 |
-
// remove ws around the combinators
|
167 |
-
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Process a comment and return a replacement
|
172 |
-
*
|
173 |
-
* @param array $m regex matches
|
174 |
-
*
|
175 |
-
* @return string
|
176 |
-
*/
|
177 |
-
protected function _commentCB($m)
|
178 |
-
{
|
179 |
-
$hasSurroundingWs = (trim($m[0]) !== $m[1]);
|
180 |
-
$m = $m[1];
|
181 |
-
// $m is the comment content w/o the surrounding tokens,
|
182 |
-
// but the return value will replace the entire comment.
|
183 |
-
if ($m === 'keep') {
|
184 |
-
return '/**/';
|
185 |
-
}
|
186 |
-
if ($m === '" "') {
|
187 |
-
// component of http://tantek.com/CSS/Examples/midpass.html
|
188 |
-
return '/*" "*/';
|
189 |
-
}
|
190 |
-
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
|
191 |
-
// component of http://tantek.com/CSS/Examples/midpass.html
|
192 |
-
return '/*";}}/* */';
|
193 |
-
}
|
194 |
-
if ($this->_inHack) {
|
195 |
-
// inversion: feeding only to one browser
|
196 |
-
if (preg_match('@
|
197 |
-
^/ # comment started like /*/
|
198 |
-
\\s*
|
199 |
-
(\\S[\\s\\S]+?) # has at least some non-ws content
|
200 |
-
\\s*
|
201 |
-
/\\* # ends like /*/ or /**/
|
202 |
-
@x', $m, $n)) {
|
203 |
-
// end hack mode after this comment, but preserve the hack and comment content
|
204 |
-
$this->_inHack = false;
|
205 |
-
return "/*/{$n[1]}/**/";
|
206 |
-
}
|
207 |
-
}
|
208 |
-
if (substr($m, -1) === '\\') { // comment ends like \*/
|
209 |
-
// begin hack mode and preserve hack
|
210 |
-
$this->_inHack = true;
|
211 |
-
return '/*\\*/';
|
212 |
-
}
|
213 |
-
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
214 |
-
// begin hack mode and preserve hack
|
215 |
-
$this->_inHack = true;
|
216 |
-
return '/*/*/';
|
217 |
-
}
|
218 |
-
if ($this->_inHack) {
|
219 |
-
// a regular comment ends hack mode but should be preserved
|
220 |
-
$this->_inHack = false;
|
221 |
-
return '/**/';
|
222 |
-
}
|
223 |
-
// Issue 107: if there's any surrounding whitespace, it may be important, so
|
224 |
-
// replace the comment with a single space
|
225 |
-
return $hasSurroundingWs // remove all other comments
|
226 |
-
? ' '
|
227 |
-
: '';
|
228 |
-
}
|
229 |
-
|
230 |
-
/**
|
231 |
-
* Process a font-family listing and return a replacement
|
232 |
-
*
|
233 |
-
* @param array $m regex matches
|
234 |
-
*
|
235 |
-
* @return string
|
236 |
-
*/
|
237 |
-
protected function _fontFamilyCB($m)
|
238 |
-
{
|
239 |
-
$m[1] = preg_replace('/
|
240 |
-
\\s*
|
241 |
-
(
|
242 |
-
"[^"]+" # 1 = family in double qutoes
|
243 |
-
|\'[^\']+\' # or 1 = family in single quotes
|
244 |
-
|[\\w\\-]+ # or 1 = unquoted family
|
245 |
-
)
|
246 |
-
\\s*
|
247 |
-
/x', '$1', $m[1]);
|
248 |
-
return 'font-family:' . $m[1] . $m[2];
|
249 |
-
}
|
250 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_CSS_Compressor
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Compress CSS
|
9 |
+
*
|
10 |
+
* This is a heavy regex-based removal of whitespace, unnecessary
|
11 |
+
* comments and tokens, and some CSS value minimization, where practical.
|
12 |
+
* Many steps have been taken to avoid breaking comment-based hacks,
|
13 |
+
* including the ie5/mac filter (and its inversion), but expect tricky
|
14 |
+
* hacks involving comment tokens in 'content' value strings to break
|
15 |
+
* minimization badly. A test suite is available.
|
16 |
+
*
|
17 |
+
* @package Minify
|
18 |
+
* @author Stephen Clay <steve@mrclay.org>
|
19 |
+
* @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
|
20 |
+
*/
|
21 |
+
class Minify_CSS_Compressor {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Minify a CSS string
|
25 |
+
*
|
26 |
+
* @param string $css
|
27 |
+
*
|
28 |
+
* @param array $options (currently ignored)
|
29 |
+
*
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public static function process($css, $options = array())
|
33 |
+
{
|
34 |
+
$obj = new Minify_CSS_Compressor($options);
|
35 |
+
return $obj->_process($css);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @var array options
|
40 |
+
*/
|
41 |
+
protected $_options = null;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @var bool Are we "in" a hack?
|
45 |
+
*
|
46 |
+
* I.e. are some browsers targetted until the next comment?
|
47 |
+
*/
|
48 |
+
protected $_inHack = false;
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Constructor
|
53 |
+
*
|
54 |
+
* @param array $options (currently ignored)
|
55 |
+
*
|
56 |
+
* @return null
|
57 |
+
*/
|
58 |
+
private function __construct($options) {
|
59 |
+
$this->_options = $options;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Minify a CSS string
|
64 |
+
*
|
65 |
+
* @param string $css
|
66 |
+
*
|
67 |
+
* @return string
|
68 |
+
*/
|
69 |
+
protected function _process($css)
|
70 |
+
{
|
71 |
+
$css = str_replace("\r\n", "\n", $css);
|
72 |
+
|
73 |
+
// preserve empty comment after '>'
|
74 |
+
// http://www.webdevout.net/css-hacks#in_css-selectors
|
75 |
+
$css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
|
76 |
+
|
77 |
+
// preserve empty comment between property and value
|
78 |
+
// http://css-discuss.incutio.com/?page=BoxModelHack
|
79 |
+
$css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
|
80 |
+
$css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
|
81 |
+
|
82 |
+
// apply callback to all valid comments (and strip out surrounding ws
|
83 |
+
$css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
|
84 |
+
,array($this, '_commentCB'), $css);
|
85 |
+
|
86 |
+
// remove ws around { } and last semicolon in declaration block
|
87 |
+
$css = preg_replace('/\\s*{\\s*/', '{', $css);
|
88 |
+
$css = preg_replace('/;?\\s*}\\s*/', '}', $css);
|
89 |
+
|
90 |
+
// remove ws surrounding semicolons
|
91 |
+
$css = preg_replace('/\\s*;\\s*/', ';', $css);
|
92 |
+
|
93 |
+
// remove ws around urls
|
94 |
+
$css = preg_replace('/
|
95 |
+
url\\( # url(
|
96 |
+
\\s*
|
97 |
+
([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
|
98 |
+
\\s*
|
99 |
+
\\) # )
|
100 |
+
/x', 'url($1)', $css);
|
101 |
+
|
102 |
+
// remove ws between rules and colons
|
103 |
+
$css = preg_replace('/
|
104 |
+
\\s*
|
105 |
+
([{;]) # 1 = beginning of block or rule separator
|
106 |
+
\\s*
|
107 |
+
([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
|
108 |
+
\\s*
|
109 |
+
:
|
110 |
+
\\s*
|
111 |
+
(\\b|[#\'"]) # 3 = first character of a value
|
112 |
+
/x', '$1$2:$3', $css);
|
113 |
+
|
114 |
+
// remove ws in selectors
|
115 |
+
$css = preg_replace_callback('/
|
116 |
+
(?: # non-capture
|
117 |
+
\\s*
|
118 |
+
[^~>+,\\s]+ # selector part
|
119 |
+
\\s*
|
120 |
+
[,>+~] # combinators
|
121 |
+
)+
|
122 |
+
\\s*
|
123 |
+
[^~>+,\\s]+ # selector part
|
124 |
+
{ # open declaration block
|
125 |
+
/x'
|
126 |
+
,array($this, '_selectorsCB'), $css);
|
127 |
+
|
128 |
+
// minimize hex colors
|
129 |
+
$css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
|
130 |
+
, '$1#$2$3$4$5', $css);
|
131 |
+
|
132 |
+
// remove spaces between font families
|
133 |
+
$css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
|
134 |
+
,array($this, '_fontFamilyCB'), $css);
|
135 |
+
|
136 |
+
$css = preg_replace('/@import\\s+url/', '@import url', $css);
|
137 |
+
|
138 |
+
// replace any ws involving newlines with a single newline
|
139 |
+
$css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
|
140 |
+
|
141 |
+
// separate common descendent selectors w/ newlines (to limit line lengths)
|
142 |
+
$css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
|
143 |
+
|
144 |
+
// Use newline after 1st numeric value (to limit line lengths).
|
145 |
+
$css = preg_replace('/
|
146 |
+
((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
|
147 |
+
\\s+
|
148 |
+
/x'
|
149 |
+
,"$1\n", $css);
|
150 |
+
|
151 |
+
// prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
|
152 |
+
$css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
|
153 |
+
|
154 |
+
return trim($css);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Replace what looks like a set of selectors
|
159 |
+
*
|
160 |
+
* @param array $m regex matches
|
161 |
+
*
|
162 |
+
* @return string
|
163 |
+
*/
|
164 |
+
protected function _selectorsCB($m)
|
165 |
+
{
|
166 |
+
// remove ws around the combinators
|
167 |
+
return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Process a comment and return a replacement
|
172 |
+
*
|
173 |
+
* @param array $m regex matches
|
174 |
+
*
|
175 |
+
* @return string
|
176 |
+
*/
|
177 |
+
protected function _commentCB($m)
|
178 |
+
{
|
179 |
+
$hasSurroundingWs = (trim($m[0]) !== $m[1]);
|
180 |
+
$m = $m[1];
|
181 |
+
// $m is the comment content w/o the surrounding tokens,
|
182 |
+
// but the return value will replace the entire comment.
|
183 |
+
if ($m === 'keep') {
|
184 |
+
return '/**/';
|
185 |
+
}
|
186 |
+
if ($m === '" "') {
|
187 |
+
// component of http://tantek.com/CSS/Examples/midpass.html
|
188 |
+
return '/*" "*/';
|
189 |
+
}
|
190 |
+
if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
|
191 |
+
// component of http://tantek.com/CSS/Examples/midpass.html
|
192 |
+
return '/*";}}/* */';
|
193 |
+
}
|
194 |
+
if ($this->_inHack) {
|
195 |
+
// inversion: feeding only to one browser
|
196 |
+
if (preg_match('@
|
197 |
+
^/ # comment started like /*/
|
198 |
+
\\s*
|
199 |
+
(\\S[\\s\\S]+?) # has at least some non-ws content
|
200 |
+
\\s*
|
201 |
+
/\\* # ends like /*/ or /**/
|
202 |
+
@x', $m, $n)) {
|
203 |
+
// end hack mode after this comment, but preserve the hack and comment content
|
204 |
+
$this->_inHack = false;
|
205 |
+
return "/*/{$n[1]}/**/";
|
206 |
+
}
|
207 |
+
}
|
208 |
+
if (substr($m, -1) === '\\') { // comment ends like \*/
|
209 |
+
// begin hack mode and preserve hack
|
210 |
+
$this->_inHack = true;
|
211 |
+
return '/*\\*/';
|
212 |
+
}
|
213 |
+
if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
|
214 |
+
// begin hack mode and preserve hack
|
215 |
+
$this->_inHack = true;
|
216 |
+
return '/*/*/';
|
217 |
+
}
|
218 |
+
if ($this->_inHack) {
|
219 |
+
// a regular comment ends hack mode but should be preserved
|
220 |
+
$this->_inHack = false;
|
221 |
+
return '/**/';
|
222 |
+
}
|
223 |
+
// Issue 107: if there's any surrounding whitespace, it may be important, so
|
224 |
+
// replace the comment with a single space
|
225 |
+
return $hasSurroundingWs // remove all other comments
|
226 |
+
? ' '
|
227 |
+
: '';
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Process a font-family listing and return a replacement
|
232 |
+
*
|
233 |
+
* @param array $m regex matches
|
234 |
+
*
|
235 |
+
* @return string
|
236 |
+
*/
|
237 |
+
protected function _fontFamilyCB($m)
|
238 |
+
{
|
239 |
+
$m[1] = preg_replace('/
|
240 |
+
\\s*
|
241 |
+
(
|
242 |
+
"[^"]+" # 1 = family in double qutoes
|
243 |
+
|\'[^\']+\' # or 1 = family in single quotes
|
244 |
+
|[\\w\\-]+ # or 1 = unquoted family
|
245 |
+
)
|
246 |
+
\\s*
|
247 |
+
/x', '$1', $m[1]);
|
248 |
+
return 'font-family:' . $m[1] . $m[2];
|
249 |
+
}
|
250 |
+
}
|
lib/Minify/min/lib/Minify/CSS/UriRewriter.php
CHANGED
@@ -118,9 +118,9 @@ class Minify_CSS_UriRewriter {
|
|
118 |
Â
*/
|
119 |
Â
private static $_docRoot = '';
|
120 |
Â
|
121 |
-
/**
|
122 |
-
* @var array directory replacements to map symlink targets back to their
|
123 |
-
* source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
|
124 |
Â
*/
|
125 |
Â
private static $_symlinks = array();
|
126 |
Â
|
@@ -219,16 +219,16 @@ class Minify_CSS_UriRewriter {
|
|
219 |
Â
self::$debugText .= "file-relative URI : {$uri}\n"
|
220 |
Â
. "path prepended : {$path}\n";
|
221 |
Â
|
222 |
-
// "unresolve" a symlink back to doc root
|
223 |
-
foreach ($symlinks as $link => $target) {
|
224 |
-
if (0 === strpos($path, $target)) {
|
225 |
-
// replace $target with $link
|
226 |
Â
$path = $link . substr($path, strlen($target));
|
227 |
Â
|
228 |
-
self::$debugText .= "symlink unresolved : {$path}\n";
|
229 |
Â
|
230 |
-
break;
|
231 |
-
}
|
232 |
Â
}
|
233 |
Â
// strip doc root
|
234 |
Â
$path = substr($path, strlen($realDocRoot));
|
118 |
Â
*/
|
119 |
Â
private static $_docRoot = '';
|
120 |
Â
|
121 |
+
/**
|
122 |
+
* @var array directory replacements to map symlink targets back to their
|
123 |
+
* source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
|
124 |
Â
*/
|
125 |
Â
private static $_symlinks = array();
|
126 |
Â
|
219 |
Â
self::$debugText .= "file-relative URI : {$uri}\n"
|
220 |
Â
. "path prepended : {$path}\n";
|
221 |
Â
|
222 |
+
// "unresolve" a symlink back to doc root
|
223 |
+
foreach ($symlinks as $link => $target) {
|
224 |
+
if (0 === strpos($path, $target)) {
|
225 |
+
// replace $target with $link
|
226 |
Â
$path = $link . substr($path, strlen($target));
|
227 |
Â
|
228 |
+
self::$debugText .= "symlink unresolved : {$path}\n";
|
229 |
Â
|
230 |
+
break;
|
231 |
+
}
|
232 |
Â
}
|
233 |
Â
// strip doc root
|
234 |
Â
$path = substr($path, strlen($realDocRoot));
|
lib/Minify/min/lib/Minify/Cache/File.php
CHANGED
@@ -11,7 +11,7 @@ class Minify_Cache_File {
|
|
11 |
Â
if (! $path) {
|
12 |
Â
require_once 'Solar/Dir.php';
|
13 |
Â
$path = rtrim(Solar_Dir::tmp(), DIRECTORY_SEPARATOR);
|
14 |
-
}
|
15 |
Â
$this->_locking = $fileLocking;
|
16 |
Â
$this->_path = $path;
|
17 |
Â
}
|
@@ -27,20 +27,20 @@ class Minify_Cache_File {
|
|
27 |
Â
*/
|
28 |
Â
public function store($id, $data)
|
29 |
Â
{
|
30 |
-
$flag = $this->_locking
|
31 |
-
? LOCK_EX
|
32 |
-
: null;
|
33 |
-
if (is_file($this->_path . '/' . $id)) {
|
34 |
-
@unlink($this->_path . '/' . $id);
|
35 |
-
}
|
36 |
-
if (! @file_put_contents($this->_path . '/' . $id, $data, $flag)) {
|
37 |
-
return false;
|
38 |
-
}
|
39 |
-
// write control
|
40 |
-
if ($data !== $this->fetch($id)) {
|
41 |
-
@unlink($file);
|
42 |
-
return false;
|
43 |
Â
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
44 |
Â
return true;
|
45 |
Â
}
|
46 |
Â
|
@@ -78,15 +78,15 @@ class Minify_Cache_File {
|
|
78 |
Â
*/
|
79 |
Â
public function display($id)
|
80 |
Â
{
|
81 |
-
if ($this->_locking) {
|
82 |
-
$fp = fopen($this->_path . '/' . $id, 'rb');
|
83 |
-
flock($fp, LOCK_SH);
|
84 |
-
fpassthru($fp);
|
85 |
-
flock($fp, LOCK_UN);
|
86 |
-
fclose($fp);
|
87 |
-
} else {
|
88 |
-
readfile($this->_path . '/' . $id);
|
89 |
-
}
|
90 |
Â
}
|
91 |
Â
|
92 |
Â
/**
|
@@ -98,15 +98,15 @@ class Minify_Cache_File {
|
|
98 |
Â
*/
|
99 |
Â
public function fetch($id)
|
100 |
Â
{
|
101 |
-
if ($this->_locking) {
|
102 |
-
$fp = fopen($this->_path . '/' . $id, 'rb');
|
103 |
-
flock($fp, LOCK_SH);
|
104 |
-
$ret = stream_get_contents($fp);
|
105 |
-
flock($fp, LOCK_UN);
|
106 |
-
fclose($fp);
|
107 |
-
return $ret;
|
108 |
-
} else {
|
109 |
-
return file_get_contents($this->_path . '/' . $id);
|
110 |
Â
}
|
111 |
Â
}
|
112 |
Â
|
@@ -121,5 +121,5 @@ class Minify_Cache_File {
|
|
121 |
Â
}
|
122 |
Â
|
123 |
Â
private $_path = null;
|
124 |
-
private $_locking = null;
|
125 |
Â
}
|
11 |
Â
if (! $path) {
|
12 |
Â
require_once 'Solar/Dir.php';
|
13 |
Â
$path = rtrim(Solar_Dir::tmp(), DIRECTORY_SEPARATOR);
|
14 |
+
}
|
15 |
Â
$this->_locking = $fileLocking;
|
16 |
Â
$this->_path = $path;
|
17 |
Â
}
|
27 |
Â
*/
|
28 |
Â
public function store($id, $data)
|
29 |
Â
{
|
30 |
+
$flag = $this->_locking
|
31 |
+
? LOCK_EX
|
32 |
+
: null;
|
33 |
+
if (is_file($this->_path . '/' . $id)) {
|
34 |
+
@unlink($this->_path . '/' . $id);
|
35 |
+
}
|
36 |
+
if (! @file_put_contents($this->_path . '/' . $id, $data, $flag)) {
|
37 |
+
return false;
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
38 |
Â
}
|
39 |
+
// write control
|
40 |
+
if ($data !== $this->fetch($id)) {
|
41 |
+
@unlink($file);
|
42 |
+
return false;
|
43 |
+
}
|
44 |
Â
return true;
|
45 |
Â
}
|
46 |
Â
|
78 |
Â
*/
|
79 |
Â
public function display($id)
|
80 |
Â
{
|
81 |
+
if ($this->_locking) {
|
82 |
+
$fp = fopen($this->_path . '/' . $id, 'rb');
|
83 |
+
flock($fp, LOCK_SH);
|
84 |
+
fpassthru($fp);
|
85 |
+
flock($fp, LOCK_UN);
|
86 |
+
fclose($fp);
|
87 |
+
} else {
|
88 |
+
readfile($this->_path . '/' . $id);
|
89 |
+
}
|
90 |
Â
}
|
91 |
Â
|
92 |
Â
/**
|
98 |
Â
*/
|
99 |
Â
public function fetch($id)
|
100 |
Â
{
|
101 |
+
if ($this->_locking) {
|
102 |
+
$fp = fopen($this->_path . '/' . $id, 'rb');
|
103 |
+
flock($fp, LOCK_SH);
|
104 |
+
$ret = stream_get_contents($fp);
|
105 |
+
flock($fp, LOCK_UN);
|
106 |
+
fclose($fp);
|
107 |
+
return $ret;
|
108 |
+
} else {
|
109 |
+
return file_get_contents($this->_path . '/' . $id);
|
110 |
Â
}
|
111 |
Â
}
|
112 |
Â
|
121 |
Â
}
|
122 |
Â
|
123 |
Â
private $_path = null;
|
124 |
+
private $_locking = null;
|
125 |
Â
}
|
lib/Minify/min/lib/Minify/Controller/Page.php
CHANGED
@@ -33,13 +33,13 @@ class Minify_Controller_Page extends Minify_Controller_Base {
|
|
33 |
Â
* 'minifyAll': should all CSS and Javascript blocks be individually
|
34 |
Â
* minified? (default false)
|
35 |
Â
*
|
36 |
-
* @todo Add 'file' option to read HTML file.
|
37 |
Â
*/
|
38 |
Â
public function setupSources($options) {
|
39 |
Â
if (isset($options['file'])) {
|
40 |
Â
$sourceSpec = array(
|
41 |
Â
'filepath' => $options['file']
|
42 |
Â
);
|
Â
|
|
43 |
Â
} else {
|
44 |
Â
// strip controller options
|
45 |
Â
$sourceSpec = array(
|
33 |
Â
* 'minifyAll': should all CSS and Javascript blocks be individually
|
34 |
Â
* minified? (default false)
|
35 |
Â
*
|
Â
|
|
36 |
Â
*/
|
37 |
Â
public function setupSources($options) {
|
38 |
Â
if (isset($options['file'])) {
|
39 |
Â
$sourceSpec = array(
|
40 |
Â
'filepath' => $options['file']
|
41 |
Â
);
|
42 |
+
unset($options['file']);
|
43 |
Â
} else {
|
44 |
Â
// strip controller options
|
45 |
Â
$sourceSpec = array(
|
lib/Minify/min/lib/Minify/Javascript.php
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Class Minify_Javascript
|
4 |
-
* @package Minify
|
5 |
-
*/
|
6 |
-
|
7 |
-
require 'JSMin.php';
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Compress Javascript using Ryan Grove's JSMin class
|
11 |
-
*
|
12 |
-
* @package Minify
|
13 |
-
* @author Stephen Clay <steve@mrclay.org>
|
14 |
-
*/
|
15 |
-
class Minify_Javascript {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Minify a Javascript string
|
19 |
-
*
|
20 |
-
* @param string $js
|
21 |
-
*
|
22 |
-
* @param array $options available options (none currently)
|
23 |
-
*
|
24 |
-
* @return string
|
25 |
-
*/
|
26 |
-
public static function minify($js, $options = array())
|
27 |
-
{
|
28 |
-
return trim(JSMin::minify($js));
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
lib/Minify/min/lib/Minify/Lines.php
CHANGED
@@ -26,9 +26,9 @@ class Minify_Lines {
|
|
26 |
Â
*
|
27 |
Â
* 'id': (optional) string to identify file. E.g. file name/path
|
28 |
Â
*
|
29 |
-
* 'currentDir': (default null) if given, this is assumed to be the
|
30 |
-
* directory of the current CSS file. Using this, minify will rewrite
|
31 |
-
* all relative URIs in import/url declarations to correctly point to
|
32 |
Â
* the desired files, and prepend a comment with debugging information about
|
33 |
Â
* this process.
|
34 |
Â
*
|
@@ -64,7 +64,7 @@ class Minify_Lines {
|
|
64 |
Â
$content = Minify_CSS_UriRewriter::rewrite(
|
65 |
Â
$content
|
66 |
Â
,$options['currentDir']
|
67 |
-
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
68 |
Â
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
69 |
Â
);
|
70 |
Â
$content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
|
26 |
Â
*
|
27 |
Â
* 'id': (optional) string to identify file. E.g. file name/path
|
28 |
Â
*
|
29 |
+
* 'currentDir': (default null) if given, this is assumed to be the
|
30 |
+
* directory of the current CSS file. Using this, minify will rewrite
|
31 |
+
* all relative URIs in import/url declarations to correctly point to
|
32 |
Â
* the desired files, and prepend a comment with debugging information about
|
33 |
Â
* this process.
|
34 |
Â
*
|
64 |
Â
$content = Minify_CSS_UriRewriter::rewrite(
|
65 |
Â
$content
|
66 |
Â
,$options['currentDir']
|
67 |
+
,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
|
68 |
Â
,isset($options['symlinks']) ? $options['symlinks'] : array()
|
69 |
Â
);
|
70 |
Â
$content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
|
lib/Minify/min/lib/MyMin.php
DELETED
@@ -1,289 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* MyMin - JSMin like alternative parser for JavaScript
|
4 |
-
*
|
5 |
-
* This class is a jsmin alternative, based on same parser logic but modified
|
6 |
-
* to mantain performances and to parse correctly JavaScript conditional comments too.
|
7 |
-
*
|
8 |
-
* SERVER SIDE
|
9 |
-
* PHP 5 or greater is required.
|
10 |
-
* This code is compatible with every error_reporting level (E_ALL | E_STRICT)
|
11 |
-
* The best practice to use this code is caching results without run-time
|
12 |
-
* evaluation (your server should be stressed too much with big files)
|
13 |
-
*
|
14 |
-
* Permission is hereby granted to use this version of the library under the
|
15 |
-
* same terms as jsmin.php, which has the following license:
|
16 |
-
*
|
17 |
-
* --
|
18 |
-
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
|
19 |
-
*
|
20 |
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
21 |
-
* this software and associated documentation files (the "Software"), to deal in
|
22 |
-
* the Software without restriction, including without limitation the rights to
|
23 |
-
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
24 |
-
* of the Software, and to permit persons to whom the Software is furnished to do
|
25 |
-
* so, subject to the following conditions:
|
26 |
-
*
|
27 |
-
* The above copyright notice and this permission notice shall be included in all
|
28 |
-
* copies or substantial portions of the Software.
|
29 |
-
*
|
30 |
-
* The Software shall be used for Good, not Evil.
|
31 |
-
*
|
32 |
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
33 |
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
34 |
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
35 |
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
36 |
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
37 |
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
38 |
-
* SOFTWARE.
|
39 |
-
* --
|
40 |
-
*
|
41 |
-
* @class MyMin
|
42 |
-
* @author Andrea Giammarchi <http://www.3site.eu>
|
43 |
-
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
|
44 |
-
* @copyright 2007 Ryan Grove <ryan@wonko.com> (PHP port)
|
45 |
-
* @copyright 2007 Andrea Giammarchi (improvements + MyMinCompressor + MyMinCSS)
|
46 |
-
* @license http://opensource.org/licenses/mit-license.php MIT License
|
47 |
-
* @version 1.0.1 (2007-10-05) - updated 2008-02-17
|
48 |
-
*/
|
49 |
-
|
50 |
-
// -- Class MyMin --------------------------------------------------------------
|
51 |
-
class MyMin {
|
52 |
-
|
53 |
-
const /* char */ LF = "\n",
|
54 |
-
SPACE = ' ',
|
55 |
-
EOS = "\x00";
|
56 |
-
|
57 |
-
protected /* boolean */ $cc_on;
|
58 |
-
|
59 |
-
protected /* char */ $a,
|
60 |
-
$ahead,
|
61 |
-
$b;
|
62 |
-
|
63 |
-
protected /* int */ $index = 0,
|
64 |
-
$length;
|
65 |
-
|
66 |
-
protected /* string */ $input,
|
67 |
-
$output = "";
|
68 |
-
|
69 |
-
// -- Public Static Methods ----------------------------------------------------
|
70 |
-
static public final function /* string */ parse(/* string */ $input, /* boolean */ $cc_on = true){
|
71 |
-
return "".(new MyMin($input, $cc_on));
|
72 |
-
}
|
73 |
-
|
74 |
-
// -- Public Instance Methods --------------------------------------------------
|
75 |
-
public final function /* object */ __construct(/* string */ $input, /* boolean */ $cc_on = true){
|
76 |
-
$this->input = preg_replace("/(\r\n|\n\r|\r|\n)+/", self::LF, trim($input));
|
77 |
-
$this->length = strlen($this->input);
|
78 |
-
$this->cc_on = $cc_on;
|
79 |
-
$this->b = $this->ahead = self::SPACE;
|
80 |
-
$this->a = self::LF;
|
81 |
-
$this->action(3);
|
82 |
-
while($this->a !== self::EOS){
|
83 |
-
switch($this->a){
|
84 |
-
case self::SPACE:
|
85 |
-
$this->action($this->isAlNum($this->b) ? 1 : 2);
|
86 |
-
break;
|
87 |
-
case self::LF:
|
88 |
-
switch($this->b){
|
89 |
-
case '{':
|
90 |
-
case '[':
|
91 |
-
case '(':
|
92 |
-
case '+':
|
93 |
-
case '-':
|
94 |
-
$this->action(1);
|
95 |
-
break;
|
96 |
-
case self::SPACE:
|
97 |
-
$this->action(3);
|
98 |
-
break;
|
99 |
-
default:
|
100 |
-
$this->action($this->isAlNum($this->b) ? 1 : 2);
|
101 |
-
break;
|
102 |
-
}
|
103 |
-
break;
|
104 |
-
default:
|
105 |
-
switch($this->b){
|
106 |
-
case self::SPACE:
|
107 |
-
$this->action($this->isAlNum($this->a) ? 1 : 3);
|
108 |
-
break;
|
109 |
-
case self::LF:
|
110 |
-
switch($this->a){
|
111 |
-
case '}':
|
112 |
-
case ']':
|
113 |
-
case ')':
|
114 |
-
case '+':
|
115 |
-
case '-':
|
116 |
-
case '"':
|
117 |
-
case '\'':
|
118 |
-
$this->action(1);
|
119 |
-
break;
|
120 |
-
default:
|
121 |
-
$this->action($this->isAlNum($this->a) ? 1 : 3);
|
122 |
-
break;
|
123 |
-
}
|
124 |
-
break;
|
125 |
-
default:
|
126 |
-
$this->action(1);
|
127 |
-
break;
|
128 |
-
}
|
129 |
-
break;
|
130 |
-
}
|
131 |
-
}
|
132 |
-
}
|
133 |
-
|
134 |
-
public final function /* string */ __toString(/* void */){
|
135 |
-
return str_replace("\n\n", "\n", ltrim($this->output));
|
136 |
-
}
|
137 |
-
|
138 |
-
// -- Protected Instance Methods -----------------------------------------------
|
139 |
-
protected function /* void */ action(/* int */ $i){
|
140 |
-
switch($i){
|
141 |
-
case 1:
|
142 |
-
$this->output .= $this->a;
|
143 |
-
case 2:
|
144 |
-
$this->a = $this->b;
|
145 |
-
if($this->a === '\'' || $this->a === '"'){
|
146 |
-
while(true){
|
147 |
-
$this->output .= $this->a;
|
148 |
-
if(!$this->nextCharNoSlash($this->b, "Unterminated string literal."))
|
149 |
-
break;
|
150 |
-
}
|
151 |
-
}
|
152 |
-
case 3:
|
153 |
-
$this->b = $this->next();
|
154 |
-
if($this->b === '/'){
|
155 |
-
switch($this->a){
|
156 |
-
case self::LF:
|
157 |
-
case self::SPACE:
|
158 |
-
if(!$this->spaceBeforeRegExp($this->output))
|
159 |
-
break;
|
160 |
-
|
161 |
-
case '{':
|
162 |
-
case ';':
|
163 |
-
|
164 |
-
case '(':
|
165 |
-
case ',':
|
166 |
-
case '=':
|
167 |
-
case ':':
|
168 |
-
case '[':
|
169 |
-
case '!':
|
170 |
-
case '&':
|
171 |
-
case '|':
|
172 |
-
case '?':
|
173 |
-
$this->output .= $this->a.$this->b;
|
174 |
-
while($this->nextCharNoSlash('/', "Unterminated regular expression literal."))
|
175 |
-
$this->output .= $this->a;
|
176 |
-
$this->b = $this->next();
|
177 |
-
break;
|
178 |
-
}
|
179 |
-
}
|
180 |
-
break;
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
protected function /* void */ appendComment(/* int */ $pos, /* string */ $open, /* string */ $close) {
|
185 |
-
$this->output .= $this->a.$open.(new MyMin(substr($this->input, $this->index, $pos - $this->index), $this->cc_on)).$close;
|
186 |
-
$this->index = $pos;
|
187 |
-
$this->a = self::LF;
|
188 |
-
}
|
189 |
-
|
190 |
-
protected function /* void */ conditionalComment(/* char */ $find) {
|
191 |
-
$single = $find === self::LF;
|
192 |
-
$pos = strpos($this->input, $find, $this->index);
|
193 |
-
if($pos === false){
|
194 |
-
if($single)
|
195 |
-
$pos = $this->length;
|
196 |
-
else
|
197 |
-
throw new MyMinException("Unterminated comment.");
|
198 |
-
}
|
199 |
-
$this->appendComment($pos, $single ? "//" : "/*", $find);
|
200 |
-
}
|
201 |
-
|
202 |
-
protected function /* char */ get(/* void */) {
|
203 |
-
$c = $this->ahead;
|
204 |
-
$this->ahead = self::EOS;
|
205 |
-
if($c === self::EOS && $this->index < $this->length)
|
206 |
-
$c = $this->input{$this->index++};
|
207 |
-
return ($c === self::EOS || $c === self::LF || $c >= self::SPACE) ? $c : self::SPACE;
|
208 |
-
}
|
209 |
-
|
210 |
-
protected function /* boolean */ isAlNum(/* char */ $c) {
|
211 |
-
return $c > 126 || $c === '\\' || preg_match('/^(\w|\$)$/', $c);
|
212 |
-
}
|
213 |
-
|
214 |
-
protected function /* char */ next(/* void */) {
|
215 |
-
$c = $this->get();
|
216 |
-
$loop = true;
|
217 |
-
if($c === '/'){
|
218 |
-
switch($this->ahead = $this->get()){
|
219 |
-
case '/':
|
220 |
-
if($this->cc_on && $this->input{$this->index} === '@')
|
221 |
-
$this->conditionalComment(self::LF);
|
222 |
-
while($loop){
|
223 |
-
$c = $this->get();
|
224 |
-
if($c <= self::LF)
|
225 |
-
$loop = false;
|
226 |
-
}
|
227 |
-
break;
|
228 |
-
case '*':
|
229 |
-
$this->get();
|
230 |
-
if($this->cc_on && $this->input{$this->index} === '@')
|
231 |
-
$this->conditionalComment("*/");
|
232 |
-
while($loop){
|
233 |
-
switch($this->get()){
|
234 |
-
case '*':
|
235 |
-
if(($this->ahead = $this->get()) === '/'){
|
236 |
-
$this->get();
|
237 |
-
$c = self::SPACE;
|
238 |
-
$loop = false;
|
239 |
-
}
|
240 |
-
break;
|
241 |
-
case self::EOS:
|
242 |
-
throw new MyMinException("Unterminated comment.");
|
243 |
-
}
|
244 |
-
}
|
245 |
-
break;
|
246 |
-
}
|
247 |
-
}
|
248 |
-
return $c;
|
249 |
-
}
|
250 |
-
|
251 |
-
protected function /* boolean */ nextCharNoSlash(/* char */ $c, /* string */ $message) {
|
252 |
-
$loop = true;
|
253 |
-
$this->a = $this->get();
|
254 |
-
if($this->a === $c)
|
255 |
-
$loop = false;
|
256 |
-
else{
|
257 |
-
if($this->a === '\\'){
|
258 |
-
$this->output .= $this->a;
|
259 |
-
$this->a = $this->get();
|
260 |
-
}
|
261 |
-
if($this->a <= self::LF)
|
262 |
-
throw new MyMinException($message);
|
263 |
-
}
|
264 |
-
return $loop;
|
265 |
-
}
|
266 |
-
|
267 |
-
protected function /* boolean */ spaceBeforeRegExp(/* string */ $output){
|
268 |
-
for(
|
269 |
-
$i = 0,
|
270 |
-
$length = strlen($output),
|
271 |
-
$reserved = array("case", "else", "in", "return", "typeof"),
|
272 |
-
$result = false,
|
273 |
-
$tmp = "";
|
274 |
-
$i < 5 && !$result;
|
275 |
-
$i++
|
276 |
-
){
|
277 |
-
if($length === strlen($reserved[$i]))
|
278 |
-
$result = $reserved[$i] === $output;
|
279 |
-
else if($length > strlen($reserved[$i])){
|
280 |
-
$tmp = substr($output, $length - strlen($reserved[$i]) - 1);
|
281 |
-
$result = substr($tmp, 1) === $reserved[$i] && !$this->isAlNum($tmp{0});
|
282 |
-
}
|
283 |
-
};
|
284 |
-
return $length < 2 ? true : $result;
|
285 |
-
}
|
286 |
-
}
|
287 |
-
|
288 |
-
// -- MyMin Exceptions ---------------------------------------------------------
|
289 |
-
class MyMinException extends Exception {}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
lib/Minify/min/pageBuffer.php
ADDED
@@ -0,0 +1,92 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Include for serving HTML pages through Minify
|
4 |
+
*
|
5 |
+
* DO NOT EDIT! Configure this utility via pageConfig.php
|
6 |
+
*
|
7 |
+
* @package Minify
|
8 |
+
*/
|
9 |
+
|
10 |
+
$_min_preIncludedFiles = get_included_files();
|
11 |
+
|
12 |
+
function ob_minify_page($content) {
|
13 |
+
global $min_serveOptions, $min_cacheMaxAge;
|
14 |
+
|
15 |
+
$includedFiles = array_diff(
|
16 |
+
$GLOBALS['_min_preIncludedFiles'], get_included_files()
|
17 |
+
);
|
18 |
+
$includedFiles[] = realpath($_SERVER['SCRIPT_FILENAME']);
|
19 |
+
$mtime = 0;
|
20 |
+
foreach ($includedFiles as $file) {
|
21 |
+
$mtime = max($mtime, filemtime($file));
|
22 |
+
}
|
23 |
+
|
24 |
+
define('MINIFY_MIN_DIR', dirname(__FILE__));
|
25 |
+
|
26 |
+
// load config
|
27 |
+
require MINIFY_MIN_DIR . '/pageConfig.php';
|
28 |
+
|
29 |
+
// setup include path
|
30 |
+
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
31 |
+
|
32 |
+
require $min_libPath . '/Minify.php';
|
33 |
+
|
34 |
+
Minify::$uploaderHoursBehind = $min_uploaderHoursBehind;
|
35 |
+
Minify::setCache(
|
36 |
+
isset($min_cachePath) ? $min_cachePath : ''
|
37 |
+
,$min_cacheFileLocking
|
38 |
+
);
|
39 |
+
|
40 |
+
if ($min_errorLogger) {
|
41 |
+
require_once $min_libPath . '/Minify/Logger.php';
|
42 |
+
if (true === $min_errorLogger) {
|
43 |
+
require_once $min_libPath . '/FirePHP.php';
|
44 |
+
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
45 |
+
} else {
|
46 |
+
Minify_Logger::setLogger($min_errorLogger);
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
// some array keys may already be set in globals
|
51 |
+
$min_serveOptions['id'] = $_SERVER['SCRIPT_FILENAME'];
|
52 |
+
$min_serveOptions['content'] = $content;
|
53 |
+
$min_serveOptions['lastModified'] = $mtime;
|
54 |
+
$min_serveOptions['minifyAll'] = true;
|
55 |
+
$min_serveOptions['quiet'] = true;
|
56 |
+
|
57 |
+
// page option: $min_lastModified
|
58 |
+
if (isset($GLOBALS['min_lastModified'])) {
|
59 |
+
$min_serveOptions['lastModified'] = $GLOBALS['min_lastModified'];
|
60 |
+
}
|
61 |
+
|
62 |
+
if ($min_cacheMaxAge) {
|
63 |
+
$min_serveOptions['lastModified'] = _steppedTime(
|
64 |
+
$min_cacheMaxAge, $_SERVER['SCRIPT_FILENAME']);
|
65 |
+
}
|
66 |
+
|
67 |
+
$out = Minify::serve('Page', $min_serveOptions);
|
68 |
+
|
69 |
+
foreach ($out['headers'] as $prop => $value) {
|
70 |
+
header($prop === '_responseCode' ? $value : "{$prop}: {$value}");
|
71 |
+
}
|
72 |
+
return $out['content'];
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Get a stepped version of time with a random-like constistent offset
|
77 |
+
*
|
78 |
+
* This emulates the mtime() of a file being modified regularly. The offset
|
79 |
+
* allows you to use the same period in several instances without them all
|
80 |
+
* stepping up simultaneously. Offsets should be evenly distributed.
|
81 |
+
*
|
82 |
+
* @param int $period in seconds
|
83 |
+
* @param string $instanceId
|
84 |
+
* @return int
|
85 |
+
*/
|
86 |
+
function _steppedTime($period, $instanceId = '') {
|
87 |
+
$hashInt = hexdec(substr(md5($instanceId), 0, 8));
|
88 |
+
$t = $_SERVER['REQUEST_TIME'];
|
89 |
+
return $t - ($t % $period) - ($hashInt % $period);
|
90 |
+
}
|
91 |
+
|
92 |
+
ob_start('ob_minify_page');
|
lib/Minify/min/pageConfig.php
ADDED
@@ -0,0 +1,82 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Configuration for pageBuffer.php
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Set to true to log messages to FirePHP (Firefox Firebug addon).
|
10 |
+
* Set to false for no error logging (Minify may be slightly faster).
|
11 |
+
* @link http://www.firephp.org/
|
12 |
+
*
|
13 |
+
* If you want to use a custom error logger, set this to your logger
|
14 |
+
* instance. Your object should have a method log(string $message).
|
15 |
+
*
|
16 |
+
* @todo cache system does not have error logging yet.
|
17 |
+
*/
|
18 |
+
$min_errorLogger = false;
|
19 |
+
|
20 |
+
|
21 |
+
/**
|
22 |
+
* For best performance, specify your temp directory here. Otherwise Minify
|
23 |
+
* will have to load extra code to guess. Some examples below:
|
24 |
+
*/
|
25 |
+
//$min_cachePath = 'c:\\WINDOWS\\Temp';
|
26 |
+
//$min_cachePath = '/tmp';
|
27 |
+
//$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
|
28 |
+
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Cache file locking. Set to false if filesystem is NFS. On at least one
|
32 |
+
* NFS system flock-ing attempts stalled PHP for 30 seconds!
|
33 |
+
*/
|
34 |
+
$min_cacheFileLocking = true;
|
35 |
+
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Maximum age of browser cache in seconds. After this period, the browser
|
39 |
+
* will send another conditional GET. Use a longer period for lower traffic
|
40 |
+
* but you may want to shorten this before making changes if it's crucial
|
41 |
+
* those changes are seen immediately.
|
42 |
+
*/
|
43 |
+
$min_serveOptions['maxAge'] = 1800;
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* By default Minify will check the mtime of the loaded page and any pages it
|
48 |
+
* includes to determine the last modified time. If you would rather have it
|
49 |
+
* regularly rebuild the cache, set this to the period, in seconds, that the
|
50 |
+
* cache should be rebuilt (note this only occurs if a request is made).
|
51 |
+
*/
|
52 |
+
$min_cacheMaxAge = false;
|
53 |
+
|
54 |
+
|
55 |
+
/**
|
56 |
+
* If you upload files from Windows to a non-Windows server, Windows may report
|
57 |
+
* incorrect mtimes for the files. This may cause Minify to keep serving stale
|
58 |
+
* cache files when source file changes are made too frequently (e.g. more than
|
59 |
+
* once an hour).
|
60 |
+
*
|
61 |
+
* Immediately after modifying and uploading a file, use the touch command to
|
62 |
+
* update the mtime on the server. If the mtime jumps ahead by a number of hours,
|
63 |
+
* set this variable to that number. If the mtime moves back, this should not be
|
64 |
+
* needed.
|
65 |
+
*
|
66 |
+
* In the Windows SFTP client WinSCP, there's an option that may fix this
|
67 |
+
* issue without changing the variable below. Under login > environment,
|
68 |
+
* select the option "Adjust remote timestamp with DST".
|
69 |
+
* @link http://winscp.net/eng/docs/ui_login_environment#daylight_saving_time
|
70 |
+
*/
|
71 |
+
$min_uploaderHoursBehind = 0;
|
72 |
+
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Path to Minify's lib folder. If you happen to move it, change
|
76 |
+
* this accordingly.
|
77 |
+
*/
|
78 |
+
$min_libPath = dirname(__FILE__) . '/lib';
|
79 |
+
|
80 |
+
|
81 |
+
// try to disable output_compression (may not have an effect)
|
82 |
+
ini_set('zlib.output_compression', '0');
|
lib/Minify/min/test/_inc.php
ADDED
@@ -0,0 +1,182 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
error_reporting(E_ALL | E_STRICT);
|
4 |
+
ini_set('display_errors', 1);
|
5 |
+
|
6 |
+
require dirname(__FILE__) . '/../config.php';
|
7 |
+
|
8 |
+
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
9 |
+
|
10 |
+
// set cache path and doc root if configured
|
11 |
+
$minifyCachePath = isset($min_cachePath)
|
12 |
+
? $min_cachePath
|
13 |
+
: '';
|
14 |
+
|
15 |
+
if ($min_documentRoot) {
|
16 |
+
$_SERVER['DOCUMENT_ROOT'] = $min_documentRoot;
|
17 |
+
} elseif (0 === stripos(PHP_OS, 'win')) {
|
18 |
+
require_once 'Minify.php';
|
19 |
+
Minify::setDocRoot(); // IIS may need help
|
20 |
+
}
|
21 |
+
$_SERVER['DOCUMENT_ROOT'] = rtrim($_SERVER['DOCUMENT_ROOT'], '/\\');
|
22 |
+
|
23 |
+
// default log to FirePHP
|
24 |
+
require_once 'Minify/Logger.php';
|
25 |
+
require_once 'FirePHP.php';
|
26 |
+
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
27 |
+
|
28 |
+
if (! isset($min_cachePath)) {
|
29 |
+
$min_cachePath = '';
|
30 |
+
}
|
31 |
+
// code in Minify::setCache()
|
32 |
+
if (is_string($min_cachePath)) {
|
33 |
+
require_once 'Minify/Cache/File.php';
|
34 |
+
$cache = new Minify_Cache_File($min_cachePath, $min_cacheFileLocking);
|
35 |
+
} else {
|
36 |
+
$cache = $min_cachePath;
|
37 |
+
}
|
38 |
+
|
39 |
+
|
40 |
+
/**
|
41 |
+
* pTest - PHP Unit Tester
|
42 |
+
* @param mixed $test Condition to test, evaluated as boolean
|
43 |
+
* @param string $html Descriptive message to output upon test
|
44 |
+
* @url http://www.sitepoint.com/blogs/2007/08/13/ptest-php-unit-tester-in-9-lines-of-code/
|
45 |
+
* @return bool success
|
46 |
+
*/
|
47 |
+
function assertTrue($test, $html)
|
48 |
+
{
|
49 |
+
$outMode = $test ? 'PASS' : '!FAIL';
|
50 |
+
$class = $test ? 'assert pass' : 'assert fail';
|
51 |
+
printf("<p class='%s'><strong>%s</strong>: %s</p>", $class, $outMode, $html);
|
52 |
+
return (bool)$test;
|
53 |
+
}
|
54 |
+
|
55 |
+
function h($txt)
|
56 |
+
{
|
57 |
+
return htmlspecialchars($txt);
|
58 |
+
}
|
59 |
+
|
60 |
+
function e($value)
|
61 |
+
{
|
62 |
+
return htmlspecialchars(var_export($value, 1));
|
63 |
+
}
|
64 |
+
|
65 |
+
function _gzdecode($data)
|
66 |
+
{
|
67 |
+
$filename = $error = '';
|
68 |
+
return _phpman_gzdecode($data, $filename, $error);
|
69 |
+
}
|
70 |
+
|
71 |
+
// http://www.php.net/manual/en/function.gzdecode.php#82930
|
72 |
+
function _phpman_gzdecode($data, &$filename='', &$error='', $maxlength=null)
|
73 |
+
{
|
74 |
+
$len = strlen($data);
|
75 |
+
if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
|
76 |
+
$error = "Not in GZIP format.";
|
77 |
+
return null; // Not GZIP format (See RFC 1952)
|
78 |
+
}
|
79 |
+
$method = ord(substr($data,2,1)); // Compression method
|
80 |
+
$flags = ord(substr($data,3,1)); // Flags
|
81 |
+
if ($flags & 31 != $flags) {
|
82 |
+
$error = "Reserved bits not allowed.";
|
83 |
+
return null;
|
84 |
+
}
|
85 |
+
// NOTE: $mtime may be negative (PHP integer limitations)
|
86 |
+
$mtime = unpack("V", substr($data,4,4));
|
87 |
+
$mtime = $mtime[1];
|
88 |
+
$xfl = substr($data,8,1);
|
89 |
+
$os = substr($data,8,1);
|
90 |
+
$headerlen = 10;
|
91 |
+
$extralen = 0;
|
92 |
+
$extra = "";
|
93 |
+
if ($flags & 4) {
|
94 |
+
// 2-byte length prefixed EXTRA data in header
|
95 |
+
if ($len - $headerlen - 2 < 8) {
|
96 |
+
return false; // invalid
|
97 |
+
}
|
98 |
+
$extralen = unpack("v",substr($data,8,2));
|
99 |
+
$extralen = $extralen[1];
|
100 |
+
if ($len - $headerlen - 2 - $extralen < 8) {
|
101 |
+
return false; // invalid
|
102 |
+
}
|
103 |
+
$extra = substr($data,10,$extralen);
|
104 |
+
$headerlen += 2 + $extralen;
|
105 |
+
}
|
106 |
+
$filenamelen = 0;
|
107 |
+
$filename = "";
|
108 |
+
if ($flags & 8) {
|
109 |
+
// C-style string
|
110 |
+
if ($len - $headerlen - 1 < 8) {
|
111 |
+
return false; // invalid
|
112 |
+
}
|
113 |
+
$filenamelen = strpos(substr($data,$headerlen),chr(0));
|
114 |
+
if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
|
115 |
+
return false; // invalid
|
116 |
+
}
|
117 |
+
$filename = substr($data,$headerlen,$filenamelen);
|
118 |
+
$headerlen += $filenamelen + 1;
|
119 |
+
}
|
120 |
+
$commentlen = 0;
|
121 |
+
$comment = "";
|
122 |
+
if ($flags & 16) {
|
123 |
+
// C-style string COMMENT data in header
|
124 |
+
if ($len - $headerlen - 1 < 8) {
|
125 |
+
return false; // invalid
|
126 |
+
}
|
127 |
+
$commentlen = strpos(substr($data,$headerlen),chr(0));
|
128 |
+
if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
|
129 |
+
return false; // Invalid header format
|
130 |
+
}
|
131 |
+
$comment = substr($data,$headerlen,$commentlen);
|
132 |
+
$headerlen += $commentlen + 1;
|
133 |
+
}
|
134 |
+
$headercrc = "";
|
135 |
+
if ($flags & 2) {
|
136 |
+
// 2-bytes (lowest order) of CRC32 on header present
|
137 |
+
if ($len - $headerlen - 2 < 8) {
|
138 |
+
return false; // invalid
|
139 |
+
}
|
140 |
+
$calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
|
141 |
+
$headercrc = unpack("v", substr($data,$headerlen,2));
|
142 |
+
$headercrc = $headercrc[1];
|
143 |
+
if ($headercrc != $calccrc) {
|
144 |
+
$error = "Header checksum failed.";
|
145 |
+
return false; // Bad header CRC
|
146 |
+
}
|
147 |
+
$headerlen += 2;
|
148 |
+
}
|
149 |
+
// GZIP FOOTER
|
150 |
+
$datacrc = unpack("V",substr($data,-8,4));
|
151 |
+
$datacrc = sprintf('%u',$datacrc[1] & 0xFFFFFFFF);
|
152 |
+
$isize = unpack("V",substr($data,-4));
|
153 |
+
$isize = $isize[1];
|
154 |
+
// decompression:
|
155 |
+
$bodylen = $len-$headerlen-8;
|
156 |
+
if ($bodylen < 1) {
|
157 |
+
// IMPLEMENTATION BUG!
|
158 |
+
return null;
|
159 |
+
}
|
160 |
+
$body = substr($data,$headerlen,$bodylen);
|
161 |
+
$data = "";
|
162 |
+
if ($bodylen > 0) {
|
163 |
+
switch ($method) {
|
164 |
+
case 8:
|
165 |
+
// Currently the only supported compression method:
|
166 |
+
$data = gzinflate($body,$maxlength);
|
167 |
+
break;
|
168 |
+
default:
|
169 |
+
$error = "Unknown compression method.";
|
170 |
+
return false;
|
171 |
+
}
|
172 |
+
} // zero-byte body content is allowed
|
173 |
+
// Verifiy CRC32
|
174 |
+
$crc = sprintf("%u",crc32($data));
|
175 |
+
$crcOK = $crc == $datacrc;
|
176 |
+
$lenOK = $isize == strlen($data);
|
177 |
+
if (!$lenOK || !$crcOK) {
|
178 |
+
$error = ( $lenOK ? '' : 'Length check FAILED. ') . ( $crcOK ? '' : 'Checksum FAILED.');
|
179 |
+
return false;
|
180 |
+
}
|
181 |
+
return $data;
|
182 |
+
}
|
lib/Minify/min/test/index.php
ADDED
@@ -0,0 +1,161 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
4 |
+
// called directly
|
5 |
+
if (isset($_GET['getOutputCompression'])) {
|
6 |
+
echo (int)ini_get('zlib.output_compression');
|
7 |
+
exit();
|
8 |
+
}
|
9 |
+
if (isset($_GET['hello'])) {
|
10 |
+
// try to disable (may not work)
|
11 |
+
ini_set('zlib.output_compression', '0');
|
12 |
+
echo 'World!';
|
13 |
+
exit();
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
$origDocRoot = $_SERVER['DOCUMENT_ROOT'];
|
18 |
+
|
19 |
+
require_once '_inc.php';
|
20 |
+
|
21 |
+
header('Content-Type: text/html; charset=utf-8');
|
22 |
+
|
23 |
+
?><!doctype html>
|
24 |
+
<title>Minify server environment/config tests</title>
|
25 |
+
<style>
|
26 |
+
.assert {margin:1em 0 0}
|
27 |
+
.assert + .assert {margin:0}
|
28 |
+
.pass strong {color:#090}
|
29 |
+
.fail strong, .warn strong {color:#c00}
|
30 |
+
dt {margin-top:.5em; font-weight:bold}
|
31 |
+
</style>
|
32 |
+
<h1>Minify server environment/config tests</h1>
|
33 |
+
|
34 |
+
<h2>Document Root</h2>
|
35 |
+
<dl>
|
36 |
+
<dt>Original <code>$_SERVER['DOCUMENT_ROOT']</code> (set by PHP/env)</dt>
|
37 |
+
<dd><code><?= e($origDocRoot) ?></code></dd>
|
38 |
+
<dt>Current <code>$_SERVER['DOCUMENT_ROOT']</code> (altered by Minify/your config.php)</dt>
|
39 |
+
<dd><code><?= e($_SERVER['DOCUMENT_ROOT']) ?></code></dd>
|
40 |
+
<dt><code>realpath($_SERVER['DOCUMENT_ROOT'])</code></dt>
|
41 |
+
<dd><code><?= e(realpath($_SERVER['DOCUMENT_ROOT'])) ?></code></dd>
|
42 |
+
<dt><code>__FILE__</code></dt>
|
43 |
+
<dd><code><?= e(__FILE__) ?></code></dd>
|
44 |
+
</dl>
|
45 |
+
<?php
|
46 |
+
|
47 |
+
if (isset($_SERVER['SUBDOMAIN_DOCUMENT_ROOT'])) {
|
48 |
+
echo "<p class='assert note'><strong>!NOTE</strong>: <code>\$_SERVER['SUBDOMAIN_DOCUMENT_ROOT']</code>"
|
49 |
+
. " is set to " . e($_SERVER['SUBDOMAIN_DOCUMENT_ROOT']) . ". You may need to set"
|
50 |
+
. " <code>\$min_documentRoot</code> to this in config.php.</p>";
|
51 |
+
}
|
52 |
+
|
53 |
+
$passed = assertTrue(
|
54 |
+
0 === strpos(__FILE__, realpath($_SERVER['DOCUMENT_ROOT']))
|
55 |
+
,'<code>__FILE__</code> is within realpath of docroot'
|
56 |
+
);
|
57 |
+
if ($passed) {
|
58 |
+
$thisPath = str_replace(
|
59 |
+
'\\'
|
60 |
+
,'/'
|
61 |
+
,substr(__FILE__, strlen(realpath($_SERVER['DOCUMENT_ROOT'])))
|
62 |
+
);
|
63 |
+
} else {
|
64 |
+
// try HTTP requests anyway
|
65 |
+
$thisPath = '/min/test/index.php';
|
66 |
+
}
|
67 |
+
|
68 |
+
if ($thisPath !== '/min/test/index.php') {
|
69 |
+
echo "<p class='assert note'><strong>!NOTE</strong>: /min/ is not directly inside DOCUMENT_ROOT.</p>";
|
70 |
+
}
|
71 |
+
|
72 |
+
?>
|
73 |
+
|
74 |
+
<h2>HTTP Encoding</h2>
|
75 |
+
<?php
|
76 |
+
|
77 |
+
$thisUrl = 'http://'
|
78 |
+
. $_SERVER['HTTP_HOST'] // avoid redirects when SERVER_NAME doesn't match
|
79 |
+
. ('80' === $_SERVER['SERVER_PORT'] ? '' : ":{$_SERVER['SERVER_PORT']}")
|
80 |
+
. $thisPath;
|
81 |
+
|
82 |
+
$oc = @file_get_contents($thisUrl . '?getOutputCompression=1');
|
83 |
+
|
84 |
+
if (false === $oc || ! preg_match('/^[01]$/', $oc)) {
|
85 |
+
echo "<p class='assert warn'><strong>!WARN</strong>: Local HTTP request failed. Testing cannot continue.</p>";
|
86 |
+
} else {
|
87 |
+
if ('1' === $oc) {
|
88 |
+
echo "<p class='assert note'><strong>!NOTE</strong>: zlib.output_compression"
|
89 |
+
. " was enabled by default, but this is OK if the next test passes.</p>";
|
90 |
+
}
|
91 |
+
|
92 |
+
$fp = fopen($thisUrl . '?hello=1', 'r', false, stream_context_create(array(
|
93 |
+
'http' => array(
|
94 |
+
'method' => "GET",
|
95 |
+
'header' => "Accept-Encoding: deflate, gzip\r\n"
|
96 |
+
)
|
97 |
+
)));
|
98 |
+
|
99 |
+
$meta = stream_get_meta_data($fp);
|
100 |
+
|
101 |
+
$passed = true;
|
102 |
+
foreach ($meta['wrapper_data'] as $i => $header) {
|
103 |
+
if ((preg_match('@^Content-Length: (\\d+)$@i', $header, $m) && $m[1] !== '6')
|
104 |
+
|| preg_match('@^Content-Encoding:@i', $header, $m)
|
105 |
+
) {
|
106 |
+
$passed = false;
|
107 |
+
break;
|
108 |
+
}
|
109 |
+
}
|
110 |
+
if ($passed && stream_get_contents($fp) !== 'World!') {
|
111 |
+
$passed = false;
|
112 |
+
}
|
113 |
+
assertTrue(
|
114 |
+
$passed
|
115 |
+
,'PHP/server can serve non-encoded content'
|
116 |
+
);
|
117 |
+
fclose($fp);
|
118 |
+
|
119 |
+
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
|
120 |
+
if (! $passed) {
|
121 |
+
echo "<p>Returned content should be 6 bytes and not HTTP encoded.<br>"
|
122 |
+
. "Headers returned by: <code>" . h($thisUrl . '?hello=1') . "</code></p>"
|
123 |
+
. "<pre><code>" . h(var_export($meta['wrapper_data'], 1)) . "</code></pre>";
|
124 |
+
}
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
if (assertTrue(function_exists('gzencode'), 'gzencode() exists')) {
|
129 |
+
// test encode/decode
|
130 |
+
$data = str_repeat(md5('testing'), 160);
|
131 |
+
$gzipped = @gzencode($data, 6);
|
132 |
+
assertTrue(is_string($gzipped) && strlen($gzipped) < strlen($data), 'gzip works');
|
133 |
+
assertTrue(_gzdecode($gzipped) === $data, 'gzdecode works');
|
134 |
+
}
|
135 |
+
|
136 |
+
?>
|
137 |
+
|
138 |
+
<h2>Cache</h2>
|
139 |
+
<dl>
|
140 |
+
<dt><code>$min_cachePath</code> in config.php</dt>
|
141 |
+
<dd><code><?= e($min_cachePath) ?></code></dd>
|
142 |
+
<dt>Resulting cache object</dt>
|
143 |
+
<dd><pre><code><?= e($cache) ?></code></pre></dd>
|
144 |
+
</dl>
|
145 |
+
<?php
|
146 |
+
|
147 |
+
if ($min_cachePath === '') {
|
148 |
+
echo "<p class='assert'><strong>!NOTE</strong>: Consider setting <code>\$min_cachePath</code> for best performance.</p>";
|
149 |
+
}
|
150 |
+
|
151 |
+
$data = str_repeat(md5('testing'), 160);
|
152 |
+
$id = 'Minify_test_cache';
|
153 |
+
assertTrue(true === $cache->store($id, $data), 'Cache store');
|
154 |
+
assertTrue(strlen($data) === $cache->getSize($id), 'Cache getSize');
|
155 |
+
assertTrue(true === $cache->isValid($id, $_SERVER['REQUEST_TIME'] - 10), 'Cache isValid');
|
156 |
+
ob_start();
|
157 |
+
$cache->display($id);
|
158 |
+
$displayed = ob_get_contents();
|
159 |
+
ob_end_clean();
|
160 |
+
assertTrue($data === $displayed, 'Cache display');
|
161 |
+
assertTrue($data === $cache->fetch($id), 'Cache fetch');
|
lib/Minify/min/test/pageBuffer.php
ADDED
@@ -0,0 +1,96 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
require '../pageBuffer.php';
|
3 |
+
?>
|
4 |
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
5 |
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
|
6 |
+
<head>
|
7 |
+
<!-- comments get removed -->
|
8 |
+
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
9 |
+
<meta name="author" content="Dave Shea" />
|
10 |
+
<!-- also whitespace around block or undisplayed elements -->
|
11 |
+
<meta name="keywords" content="design, css, cascading, style, sheets, xhtml, graphic design, w3c, web standards, visual, display" />
|
12 |
+
<meta name="description" content="A demonstration of what can be accomplished visually through CSS-based design." />
|
13 |
+
<meta name="robots" content="all" />
|
14 |
+
<title>css Zen Garden: The Beauty in CSS Design</title>
|
15 |
+
|
16 |
+
<!-- to correct the unsightly Flash of Unstyled Content. http://www.bluerobot.com/web/css/fouc.asp -->
|
17 |
+
<script type="text/javascript"><!--
|
18 |
+
// js comment inside SCRIPT element
|
19 |
+
var is = {
|
20 |
+
ie: navigator.appName == 'Microsoft Internet Explorer',
|
21 |
+
java: navigator.javaEnabled(),
|
22 |
+
ns: navigator.appName == 'Netscape',
|
23 |
+
ua: navigator.userAgent.toLowerCase(),
|
24 |
+
version: parseFloat(navigator.appVersion.substr(21)) ||
|
25 |
+
parseFloat(navigator.appVersion),
|
26 |
+
win: navigator.platform == 'Win32'
|
27 |
+
}
|
28 |
+
is.mac = is.ua.indexOf('mac') >= 0;
|
29 |
+
if (is.ua.indexOf('opera') >= 0) {
|
30 |
+
is.ie = is.ns = false;
|
31 |
+
is.opera = true;
|
32 |
+
}
|
33 |
+
if (is.ua.indexOf('gecko') >= 0) {
|
34 |
+
is.ie = is.ns = false;
|
35 |
+
is.gecko = true;
|
36 |
+
}
|
37 |
+
// --></script>
|
38 |
+
<script type="text/javascript">
|
39 |
+
//<![CDATA[
|
40 |
+
var i = 0;
|
41 |
+
while (++i < 10)
|
42 |
+
{
|
43 |
+
// ...
|
44 |
+
}
|
45 |
+
//]]>
|
46 |
+
</script>
|
47 |
+
<script type="text/javascript">
|
48 |
+
/* <![CDATA[ */ i = 1; /* ]]> */
|
49 |
+
</script>
|
50 |
+
<script type="text/javascript">
|
51 |
+
(i < 1); /* CDATA needed */
|
52 |
+
</script>
|
53 |
+
<!--[if IE 6]>
|
54 |
+
<style type="text/css">
|
55 |
+
/*! copyright: you'll need CDATA for this < & */
|
56 |
+
body {background:white;}
|
57 |
+
</style>
|
58 |
+
<![endif]-->
|
59 |
+
<style type="text/css" title="currentStyle" media="screen">
|
60 |
+
@import "/001/001.css";
|
61 |
+
/*\*/ css hack {} /* */
|
62 |
+
/* normal CSS comment */
|
63 |
+
/*/*/ css hack {} /* */
|
64 |
+
css hack {
|
65 |
+
display/**/:/**/none;
|
66 |
+
display:none;
|
67 |
+
}
|
68 |
+
</style>
|
69 |
+
<link
|
70 |
+
rel="alternate"
|
71 |
+
type="application/rss+xml"
|
72 |
+
title="RSS"
|
73 |
+
href="http://www.csszengarden.com/zengarden.xml" />
|
74 |
+
</head>
|
75 |
+
<body id="css-zen-garden">
|
76 |
+
<!--[if !IE]>--><p>Browser != IE</p><!--<![endif]-->
|
77 |
+
<div id="container">
|
78 |
+
<div id="pageHeader">
|
79 |
+
<h1><span>css Zen Garden</span></h1>
|
80 |
+
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym>
|
81 |
+
Design</span></h2>
|
82 |
+
</div>
|
83 |
+
<pre>
|
84 |
+
White space is important here!
|
85 |
+
</pre>
|
86 |
+
<div id="quickSummary">
|
87 |
+
<p class="p1"><span>A demonstration of what can be accomplished visually through <acronym title="Cascading Style Sheets">CSS</acronym>-based design. Select any style sheet from the list to load it into this page.</span></p>
|
88 |
+
<p class="p2"><span>Download the sample <a href="/zengarden-sample.html" title="This page's source HTML code, not to be modified.">html file</a> and <a href="/zengarden-sample.css" title="This page's sample CSS, the file you may modify.">css file</a></span></p>
|
89 |
+
</div>
|
90 |
+
<textarea name="comment" id="comment" rows="6" class="maxwidth" cols="80">66666
|
91 |
+
|
92 |
+
1234567890</textarea>
|
93 |
+
|
94 |
+
</div>
|
95 |
+
</body>
|
96 |
+
</html>
|
lib/Minify/min_extras/README.txt
ADDED
@@ -0,0 +1,15 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
2 |
+
DO NOT leave this directory on a site in production. Some scripts within may be
|
3 |
+
resource intensive and some allow file uploads.
|
4 |
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
5 |
+
|
6 |
+
This directory contains testing scripts and a few example applications built
|
7 |
+
with the Minify library classes.
|
8 |
+
|
9 |
+
ab_tests/
|
10 |
+
Windows batch files used to benchmark various Minify and Apache
|
11 |
+
configurations using Apache ab.
|
12 |
+
|
13 |
+
tools/
|
14 |
+
Two utility web apps that upload a file, alter it, and send it back to the
|
15 |
+
user. One applies HTTP encoding, the other minifies CSS/JS/HTML.
|
lib/Minify/min_extras/ab_tests/README.txt
ADDED
@@ -0,0 +1,10 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
This is a little AB testing setup for Windows. Before committing any non-trivial
|
2 |
+
change, these tests should be run so "results_summary.txt" will be an up-to-date
|
3 |
+
document of each revision's performance.
|
4 |
+
|
5 |
+
Before testing make sure all cache locations are correct.
|
6 |
+
|
7 |
+
Double-click "test_all.bat" to run the tests. At the end, "results_summary.txt"
|
8 |
+
will be opened in notepad. For more details see "results.txt".
|
9 |
+
|
10 |
+
Delete "results.txt" before committing. We don't need this much info in svn.
|
lib/Minify/min_extras/ab_tests/_delimiter
ADDED
@@ -0,0 +1,3 @@
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
|
2 |
+
--------------------------------------------------------------------------------
|
3 |
+
|
lib/Minify/min_extras/ab_tests/ideal_php/before.php
ADDED
@@ -0,0 +1,25 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The goal with this file is to benchmark serving the file doing the absolute
|
4 |
+
* least operations possible. E.g. we know we'll have to check for the file,
|
5 |
+
* check its size and the mtimes of it and the src file.
|
6 |
+
*/
|
7 |
+
|
8 |
+
$src = realpath(dirname(__FILE__) . '/../minify/before.js');
|
9 |
+
$cached = realpath(dirname(__FILE__) . '/../type-map') . '/before.js.zd';
|
10 |
+
|
11 |
+
// clearstatcache() takes over 2ms on Athlon 64 X2 5600+! Avoid at all costs!
|
12 |
+
//clearstatcache();
|
13 |
+
|
14 |
+
filemtime($src);
|
15 |
+
file_exists($cached);
|
16 |
+
filemtime($cached);
|
17 |
+
|
18 |
+
header('Cache-Control: public, max-age=31536000');
|
19 |
+
header('Expires: '. gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME'] + (86400 * 365)));
|
20 |
+
header('Content-Type: application/x-javascript; charset=utf-8');
|
21 |
+
header('Content-Encoding: deflate');
|
22 |
+
header('Content-Length: ' . filesize($cached));
|
23 |
+
header('Vary: Accept-Encoding');
|
24 |
+
|
25 |
+
readfile($cached);
|
lib/Minify/min_extras/ab_tests/minify/before.js
ADDED
@@ -0,0 +1,3408 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function(){
|
2 |
+
/*!
|
3 |
+
* jQuery 1.2.3 - New Wave Javascript
|
4 |
+
*
|
5 |
+
* Copyright (c) 2008 John Resig (jquery.com)
|
6 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
7 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
8 |
+
*
|
9 |
+
* $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
|
10 |
+
* $Rev: 4663 $
|
11 |
+
*/
|
12 |
+
|
13 |
+
// Map over jQuery in case of overwrite
|
14 |
+
if ( window.jQuery )
|
15 |
+
var _jQuery = window.jQuery;
|
16 |
+
|
17 |
+
var jQuery = window.jQuery = function( selector, context ) {
|
18 |
+
// The jQuery object is actually just the init constructor 'enhanced'
|
19 |
+
return new jQuery.prototype.init( selector, context );
|
20 |
+
};
|
21 |
+
|
22 |
+
// Map over the $ in case of overwrite
|
23 |
+
if ( window.$ )
|
24 |
+
var _$ = window.$;
|
25 |
+
|
26 |
+
// Map the jQuery namespace to the '$' one
|
27 |
+
window.$ = jQuery;
|
28 |
+
|
29 |
+
// A simple way to check for HTML strings or ID strings
|
30 |
+
// (both of which we optimize for)
|
31 |
+
var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
|
32 |
+
|
33 |
+
// Is it a simple selector
|
34 |
+
var isSimple = /^.[^:#\[\.]*$/;
|
35 |
+
|
36 |
+
jQuery.fn = jQuery.prototype = {
|
37 |
+
init: function( selector, context ) {
|
38 |
+
// Make sure that a selection was provided
|
39 |
+
selector = selector || document;
|
40 |
+
|
41 |
+
// Handle $(DOMElement)
|
42 |
+
if ( selector.nodeType ) {
|
43 |
+
this[0] = selector;
|
44 |
+
this.length = 1;
|
45 |
+
return this;
|
46 |
+
|
47 |
+
// Handle HTML strings
|
48 |
+
} else if ( typeof selector == "string" ) {
|
49 |
+
// Are we dealing with HTML string or an ID?
|
50 |
+
var match = quickExpr.exec( selector );
|
51 |
+
|
52 |
+
// Verify a match, and that no context was specified for #id
|
53 |
+
if ( match && (match[1] || !context) ) {
|
54 |
+
|
55 |
+
// HANDLE: $(html) -> $(array)
|
56 |
+
if ( match[1] )
|
57 |
+
selector = jQuery.clean( [ match[1] ], context );
|
58 |
+
|
59 |
+
// HANDLE: $("#id")
|
60 |
+
else {
|
61 |
+
var elem = document.getElementById( match[3] );
|
62 |
+
|
63 |
+
// Make sure an element was located
|
64 |
+
if ( elem )
|
65 |
+
// Handle the case where IE and Opera return items
|
66 |
+
// by name instead of ID
|
67 |
+
if ( elem.id != match[3] )
|
68 |
+
return jQuery().find( selector );
|
69 |
+
|
70 |
+
// Otherwise, we inject the element directly into the jQuery object
|
71 |
+
else {
|
72 |
+
this[0] = elem;
|
73 |
+
this.length = 1;
|
74 |
+
return this;
|
75 |
+
}
|
76 |
+
|
77 |
+
else
|
78 |
+
selector = [];
|
79 |
+
}
|
80 |
+
|
81 |
+
// HANDLE: $(expr, [context])
|
82 |
+
// (which is just equivalent to: $(content).find(expr)
|
83 |
+
} else
|
84 |
+
return new jQuery( context ).find( selector );
|
85 |
+
|
86 |
+
// HANDLE: $(function)
|
87 |
+
// Shortcut for document ready
|
88 |
+
} else if ( jQuery.isFunction( selector ) )
|
89 |
+
return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
|
90 |
+
|
91 |
+
return this.setArray(
|
92 |
+
// HANDLE: $(array)
|
93 |
+
selector.constructor == Array && selector ||
|
94 |
+
|
95 |
+
// HANDLE: $(arraylike)
|
96 |
+
// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
|
97 |
+
(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
|
98 |
+
|
99 |
+
// HANDLE: $(*)
|
100 |
+
[ selector ] );
|
101 |
+
},
|
102 |
+
|
103 |
+
// The current version of jQuery being used
|
104 |
+
jquery: "1.2.3",
|
105 |
+
|
106 |
+
// The number of elements contained in the matched element set
|
107 |
+
size: function() {
|
108 |
+
return this.length;
|
109 |
+
},
|
110 |
+
|
111 |
+
// The number of elements contained in the matched element set
|
112 |
+
length: 0,
|
113 |
+
|
114 |
+
// Get the Nth element in the matched element set OR
|
115 |
+
// Get the whole matched element set as a clean array
|
116 |
+
get: function( num ) {
|
117 |
+
return num == undefined ?
|
118 |
+
|
119 |
+
// Return a 'clean' array
|
120 |
+
jQuery.makeArray( this ) :
|
121 |
+
|
122 |
+
// Return just the object
|
123 |
+
this[ num ];
|
124 |
+
},
|
125 |
+
|
126 |
+
// Take an array of elements and push it onto the stack
|
127 |
+
// (returning the new matched element set)
|
128 |
+
pushStack: function( elems ) {
|
129 |
+
// Build a new jQuery matched element set
|
130 |
+
var ret = jQuery( elems );
|
131 |
+
|
132 |
+
// Add the old object onto the stack (as a reference)
|
133 |
+
ret.prevObject = this;
|
134 |
+
|
135 |
+
// Return the newly-formed element set
|
136 |
+
return ret;
|
137 |
+
},
|
138 |
+
|
139 |
+
// Force the current matched set of elements to become
|
140 |
+
// the specified array of elements (destroying the stack in the process)
|
141 |
+
// You should use pushStack() in order to do this, but maintain the stack
|
142 |
+
setArray: function( elems ) {
|
143 |
+
// Resetting the length to 0, then using the native Array push
|
144 |
+
// is a super-fast way to populate an object with array-like properties
|
145 |
+
this.length = 0;
|
146 |
+
Array.prototype.push.apply( this, elems );
|
147 |
+
|
148 |
+
return this;
|
149 |
+
},
|
150 |
+
|
151 |
+
// Execute a callback for every element in the matched set.
|
152 |
+
// (You can seed the arguments with an array of args, but this is
|
153 |
+
// only used internally.)
|
154 |
+
each: function( callback, args ) {
|
155 |
+
return jQuery.each( this, callback, args );
|
156 |
+
},
|
157 |
+
|
158 |
+
// Determine the position of an element within
|
159 |
+
// the matched set of elements
|
160 |
+
index: function( elem ) {
|
161 |
+
var ret = -1;
|
162 |
+
|
163 |
+
// Locate the position of the desired element
|
164 |
+
this.each(function(i){
|
165 |
+
if ( this == elem )
|
166 |
+
ret = i;
|
167 |
+
});
|
168 |
+
|
169 |
+
return ret;
|
170 |
+
},
|
171 |
+
|
172 |
+
attr: function( name, value, type ) {
|
173 |
+
var options = name;
|
174 |
+
|
175 |
+
// Look for the case where we're accessing a style value
|
176 |
+
if ( name.constructor == String )
|
177 |
+
if ( value == undefined )
|
178 |
+
return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
|
179 |
+
|
180 |
+
else {
|
181 |
+
options = {};
|
182 |
+
options[ name ] = value;
|
183 |
+
}
|
184 |
+
|
185 |
+
// Check to see if we're setting style values
|
186 |
+
return this.each(function(i){
|
187 |
+
// Set all the styles
|
188 |
+
for ( name in options )
|
189 |
+
jQuery.attr(
|
190 |
+
type ?
|
191 |
+
this.style :
|
192 |
+
this,
|
193 |
+
name, jQuery.prop( this, options[ name ], type, i, name )
|
194 |
+
);
|
195 |
+
});
|
196 |
+
},
|
197 |
+
|
198 |
+
css: function( key, value ) {
|
199 |
+
// ignore negative width and height values
|
200 |
+
if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
|
201 |
+
value = undefined;
|
202 |
+
return this.attr( key, value, "curCSS" );
|
203 |
+
},
|
204 |
+
|
205 |
+
text: function( text ) {
|
206 |
+
if ( typeof text != "object" && text != null )
|
207 |
+
return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
|
208 |
+
|
209 |
+
var ret = "";
|
210 |
+
|
211 |
+
jQuery.each( text || this, function(){
|
212 |
+
jQuery.each( this.childNodes, function(){
|
213 |
+
if ( this.nodeType != 8 )
|
214 |
+
ret += this.nodeType != 1 ?
|
215 |
+
this.nodeValue :
|
216 |
+
jQuery.fn.text( [ this ] );
|
217 |
+
});
|
218 |
+
});
|
219 |
+
|
220 |
+
return ret;
|
221 |
+
},
|
222 |
+
|
223 |
+
wrapAll: function( html ) {
|
224 |
+
if ( this[0] )
|
225 |
+
// The elements to wrap the target around
|
226 |
+
jQuery( html, this[0].ownerDocument )
|
227 |
+
.clone()
|
228 |
+
.insertBefore( this[0] )
|
229 |
+
.map(function(){
|
230 |
+
var elem = this;
|
231 |
+
|
232 |
+
while ( elem.firstChild )
|
233 |
+
elem = elem.firstChild;
|
234 |
+
|
235 |
+
return elem;
|
236 |
+
})
|
237 |
+
.append(this);
|
238 |
+
|
239 |
+
return this;
|
240 |
+
},
|
241 |
+
|
242 |
+
wrapInner: function( html ) {
|
243 |
+
return this.each(function(){
|
244 |
+
jQuery( this ).contents().wrapAll( html );
|
245 |
+
});
|
246 |
+
},
|
247 |
+
|
248 |
+
wrap: function( html ) {
|
249 |
+
return this.each(function(){
|
250 |
+
jQuery( this ).wrapAll( html );
|
251 |
+
});
|
252 |
+
},
|
253 |
+
|
254 |
+
append: function() {
|
255 |
+
return this.domManip(arguments, true, false, function(elem){
|
256 |
+
if (this.nodeType == 1)
|
257 |
+
this.appendChild( elem );
|
258 |
+
});
|
259 |
+
},
|
260 |
+
|
261 |
+
prepend: function() {
|
262 |
+
return this.domManip(arguments, true, true, function(elem){
|
263 |
+
if (this.nodeType == 1)
|
264 |
+
this.insertBefore( elem, this.firstChild );
|
265 |
+
});
|
266 |
+
},
|
267 |
+
|
268 |
+
before: function() {
|
269 |
+
return this.domManip(arguments, false, false, function(elem){
|
270 |
+
this.parentNode.insertBefore( elem, this );
|
271 |
+
});
|
272 |
+
},
|
273 |
+
|
274 |
+
after: function() {
|
275 |
+
return this.domManip(arguments, false, true, function(elem){
|
276 |
+
this.parentNode.insertBefore( elem, this.nextSibling );
|
277 |
+
});
|
278 |
+
},
|
279 |
+
|
280 |
+
end: function() {
|
281 |
+
return this.prevObject || jQuery( [] );
|
282 |
+
},
|
283 |
+
|
284 |
+
find: function( selector ) {
|
285 |
+
var elems = jQuery.map(this, function(elem){
|
286 |
+
return jQuery.find( selector, elem );
|
287 |
+
});
|
288 |
+
|
289 |
+
return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
|
290 |
+
jQuery.unique( elems ) :
|
291 |
+
elems );
|
292 |
+
},
|
293 |
+
|
294 |
+
clone: function( events ) {
|
295 |
+
// Do the clone
|
296 |
+
var ret = this.map(function(){
|
297 |
+
if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
|
298 |
+
// IE copies events bound via attachEvent when
|
299 |
+
// using cloneNode. Calling detachEvent on the
|
300 |
+
// clone will also remove the events from the orignal
|
301 |
+
// In order to get around this, we use innerHTML.
|
302 |
+
// Unfortunately, this means some modifications to
|
303 |
+
// attributes in IE that are actually only stored
|
304 |
+
// as properties will not be copied (such as the
|
305 |
+
// the name attribute on an input).
|
306 |
+
var clone = this.cloneNode(true),
|
307 |
+
container = document.createElement("div");
|
308 |
+
container.appendChild(clone);
|
309 |
+
return jQuery.clean([container.innerHTML])[0];
|
310 |
+
} else
|
311 |
+
return this.cloneNode(true);
|
312 |
+
});
|
313 |
+
|
314 |
+
// Need to set the expando to null on the cloned set if it exists
|
315 |
+
// removeData doesn't work here, IE removes it from the original as well
|
316 |
+
// this is primarily for IE but the data expando shouldn't be copied over in any browser
|
317 |
+
var clone = ret.find("*").andSelf().each(function(){
|
318 |
+
if ( this[ expando ] != undefined )
|
319 |
+
this[ expando ] = null;
|
320 |
+
});
|
321 |
+
|
322 |
+
// Copy the events from the original to the clone
|
323 |
+
if ( events === true )
|
324 |
+
this.find("*").andSelf().each(function(i){
|
325 |
+
if (this.nodeType == 3)
|
326 |
+
return;
|
327 |
+
var events = jQuery.data( this, "events" );
|
328 |
+
|
329 |
+
for ( var type in events )
|
330 |
+
for ( var handler in events[ type ] )
|
331 |
+
jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
|
332 |
+
});
|
333 |
+
|
334 |
+
// Return the cloned set
|
335 |
+
return ret;
|
336 |
+
},
|
337 |
+
|
338 |
+
filter: function( selector ) {
|
339 |
+
return this.pushStack(
|
340 |
+
jQuery.isFunction( selector ) &&
|
341 |
+
jQuery.grep(this, function(elem, i){
|
342 |
+
return selector.call( elem, i );
|
343 |
+
}) ||
|
344 |
+
|
345 |
+
jQuery.multiFilter( selector, this ) );
|
346 |
+
},
|
347 |
+
|
348 |
+
not: function( selector ) {
|
349 |
+
if ( selector.constructor == String )
|
350 |
+
// test special case where just one selector is passed in
|
351 |
+
if ( isSimple.test( selector ) )
|
352 |
+
return this.pushStack( jQuery.multiFilter( selector, this, true ) );
|
353 |
+
else
|
354 |
+
selector = jQuery.multiFilter( selector, this );
|
355 |
+
|
356 |
+
var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
|
357 |
+
return this.filter(function() {
|
358 |
+
return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
|
359 |
+
});
|
360 |
+
},
|
361 |
+
|
362 |
+
add: function( selector ) {
|
363 |
+
return !selector ? this : this.pushStack( jQuery.merge(
|
364 |
+
this.get(),
|
365 |
+
selector.constructor == String ?
|
366 |
+
jQuery( selector ).get() :
|
367 |
+
selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
|
368 |
+
selector : [selector] ) );
|
369 |
+
},
|
370 |
+
|
371 |
+
is: function( selector ) {
|
372 |
+
return selector ?
|
373 |
+
jQuery.multiFilter( selector, this ).length > 0 :
|
374 |
+
false;
|
375 |
+
},
|
376 |
+
|
377 |
+
hasClass: function( selector ) {
|
378 |
+
return this.is( "." + selector );
|
379 |
+
},
|
380 |
+
|
381 |
+
val: function( value ) {
|
382 |
+
if ( value == undefined ) {
|
383 |
+
|
384 |
+
if ( this.length ) {
|
385 |
+
var elem = this[0];
|
386 |
+
|
387 |
+
// We need to handle select boxes special
|
388 |
+
if ( jQuery.nodeName( elem, "select" ) ) {
|
389 |
+
var index = elem.selectedIndex,
|
390 |
+
values = [],
|
391 |
+
options = elem.options,
|
392 |
+
one = elem.type == "select-one";
|
393 |
+
|
394 |
+
// Nothing was selected
|
395 |
+
if ( index < 0 )
|
396 |
+
return null;
|
397 |
+
|
398 |
+
// Loop through all the selected options
|
399 |
+
for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
|
400 |
+
var option = options[ i ];
|
401 |
+
|
402 |
+
if ( option.selected ) {
|
403 |
+
// Get the specifc value for the option
|
404 |
+
value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
|
405 |
+
|
406 |
+
// We don't need an array for one selects
|
407 |
+
if ( one )
|
408 |
+
return value;
|
409 |
+
|
410 |
+
// Multi-Selects return an array
|
411 |
+
values.push( value );
|
412 |
+
}
|
413 |
+
}
|
414 |
+
|
415 |
+
return values;
|
416 |
+
|
417 |
+
// Everything else, we just grab the value
|
418 |
+
} else
|
419 |
+
return (this[0].value || "").replace(/\r/g, "");
|
420 |
+
|
421 |
+
}
|
422 |
+
|
423 |
+
return undefined;
|
424 |
+
}
|
425 |
+
|
426 |
+
return this.each(function(){
|
427 |
+
if ( this.nodeType != 1 )
|
428 |
+
return;
|
429 |
+
|
430 |
+
if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
|
431 |
+
this.checked = (jQuery.inArray(this.value, value) >= 0 ||
|
432 |
+
jQuery.inArray(this.name, value) >= 0);
|
433 |
+
|
434 |
+
else if ( jQuery.nodeName( this, "select" ) ) {
|
435 |
+
var values = value.constructor == Array ?
|
436 |
+
value :
|
437 |
+
[ value ];
|
438 |
+
|
439 |
+
jQuery( "option", this ).each(function(){
|
440 |
+
this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
|
441 |
+
jQuery.inArray( this.text, values ) >= 0);
|
442 |
+
});
|
443 |
+
|
444 |
+
if ( !values.length )
|
445 |
+
this.selectedIndex = -1;
|
446 |
+
|
447 |
+
} else
|
448 |
+
this.value = value;
|
449 |
+
});
|
450 |
+
},
|
451 |
+
|
452 |
+
html: function( value ) {
|
453 |
+
return value == undefined ?
|
454 |
+
(this.length ?
|
455 |
+
this[0].innerHTML :
|
456 |
+
null) :
|
457 |
+
this.empty().append( value );
|
458 |
+
},
|
459 |
+
|
460 |
+
replaceWith: function( value ) {
|
461 |
+
return this.after( value ).remove();
|
462 |
+
},
|
463 |
+
|
464 |
+
eq: function( i ) {
|
465 |
+
return this.slice( i, i + 1 );
|
466 |
+
},
|
467 |
+
|
468 |
+
slice: function() {
|
469 |
+
return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
|
470 |
+
},
|
471 |
+
|
472 |
+
map: function( callback ) {
|
473 |
+
return this.pushStack( jQuery.map(this, function(elem, i){
|
474 |
+
return callback.call( elem, i, elem );
|
475 |
+
}));
|
476 |
+
},
|
477 |
+
|
478 |
+
andSelf: function() {
|
479 |
+
return this.add( this.prevObject );
|
480 |
+
},
|
481 |
+
|
482 |
+
data: function( key, value ){
|
483 |
+
var parts = key.split(".");
|
484 |
+
parts[1] = parts[1] ? "." + parts[1] : "";
|
485 |
+
|
486 |
+
if ( value == null ) {
|
487 |
+
var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
|
488 |
+
|
489 |
+
if ( data == undefined && this.length )
|
490 |
+
data = jQuery.data( this[0], key );
|
491 |
+
|
492 |
+
return data == null && parts[1] ?
|
493 |
+
this.data( parts[0] ) :
|
494 |
+
data;
|
495 |
+
} else
|
496 |
+
return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
|
497 |
+
jQuery.data( this, key, value );
|
498 |
+
});
|
499 |
+
},
|
500 |
+
|
501 |
+
removeData: function( key ){
|
502 |
+
return this.each(function(){
|
503 |
+
jQuery.removeData( this, key );
|
504 |
+
});
|
505 |
+
},
|
506 |
+
|
507 |
+
domManip: function( args, table, reverse, callback ) {
|
508 |
+
var clone = this.length > 1, elems;
|
509 |
+
|
510 |
+
return this.each(function(){
|
511 |
+
if ( !elems ) {
|
512 |
+
elems = jQuery.clean( args, this.ownerDocument );
|
513 |
+
|
514 |
+
if ( reverse )
|
515 |
+
elems.reverse();
|
516 |
+
}
|
517 |
+
|
518 |
+
var obj = this;
|
519 |
+
|
520 |
+
if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
|
521 |
+
obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
|
522 |
+
|
523 |
+
var scripts = jQuery( [] );
|
524 |
+
|
525 |
+
jQuery.each(elems, function(){
|
526 |
+
var elem = clone ?
|
527 |
+
jQuery( this ).clone( true )[0] :
|
528 |
+
this;
|
529 |
+
|
530 |
+
// execute all scripts after the elements have been injected
|
531 |
+
if ( jQuery.nodeName( elem, "script" ) ) {
|
532 |
+
scripts = scripts.add( elem );
|
533 |
+
} else {
|
534 |
+
// Remove any inner scripts for later evaluation
|
535 |
+
if ( elem.nodeType == 1 )
|
536 |
+
scripts = scripts.add( jQuery( "script", elem ).remove() );
|
537 |
+
|
538 |
+
// Inject the elements into the document
|
539 |
+
callback.call( obj, elem );
|
540 |
+
}
|
541 |
+
});
|
542 |
+
|
543 |
+
scripts.each( evalScript );
|
544 |
+
});
|
545 |
+
}
|
546 |
+
};
|
547 |
+
|
548 |
+
// Give the init function the jQuery prototype for later instantiation
|
549 |
+
jQuery.prototype.init.prototype = jQuery.prototype;
|
550 |
+
|
551 |
+
function evalScript( i, elem ) {
|
552 |
+
if ( elem.src )
|
553 |
+
jQuery.ajax({
|
554 |
+
url: elem.src,
|
555 |
+
async: false,
|
556 |
+
dataType: "script"
|
557 |
+
});
|
558 |
+
|
559 |
+
else
|
560 |
+
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
|
561 |
+
|
562 |
+
if ( elem.parentNode )
|
563 |
+
elem.parentNode.removeChild( elem );
|
564 |
+
}
|
565 |
+
|
566 |
+
jQuery.extend = jQuery.fn.extend = function() {
|
567 |
+
// copy reference to target object
|
568 |
+
var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
|
569 |
+
|
570 |
+
// Handle a deep copy situation
|
571 |
+
if ( target.constructor == Boolean ) {
|
572 |
+
deep = target;
|
573 |
+
target = arguments[1] || {};
|
574 |
+
// skip the boolean and the target
|
575 |
+
i = 2;
|
576 |
+
}
|
577 |
+
|
578 |
+
// Handle case when target is a string or something (possible in deep copy)
|
579 |
+
if ( typeof target != "object" && typeof target != "function" )
|
580 |
+
target = {};
|
581 |
+
|
582 |
+
// extend jQuery itself if only one argument is passed
|
583 |
+
if ( length == 1 ) {
|
584 |
+
target = this;
|
585 |
+
i = 0;
|
586 |
+
}
|
587 |
+
|
588 |
+
for ( ; i < length; i++ )
|
589 |
+
// Only deal with non-null/undefined values
|
590 |
+
if ( (options = arguments[ i ]) != null )
|
591 |
+
// Extend the base object
|
592 |
+
for ( var name in options ) {
|
593 |
+
// Prevent never-ending loop
|
594 |
+
if ( target === options[ name ] )
|
595 |
+
continue;
|
596 |
+
|
597 |
+
// Recurse if we're merging object values
|
598 |
+
if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
|
599 |
+
target[ name ] = jQuery.extend( target[ name ], options[ name ] );
|
600 |
+
|
601 |
+
// Don't bring in undefined values
|
602 |
+
else if ( options[ name ] != undefined )
|
603 |
+
target[ name ] = options[ name ];
|
604 |
+
|
605 |
+
}
|
606 |
+
|
607 |
+
// Return the modified object
|
608 |
+
return target;
|
609 |
+
};
|
610 |
+
|
611 |
+
var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
|
612 |
+
|
613 |
+
// exclude the following css properties to add px
|
614 |
+
var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
|
615 |
+
|
616 |
+
jQuery.extend({
|
617 |
+
noConflict: function( deep ) {
|
618 |
+
window.$ = _$;
|
619 |
+
|
620 |
+
if ( deep )
|
621 |
+
window.jQuery = _jQuery;
|
622 |
+
|
623 |
+
return jQuery;
|
624 |
+
},
|
625 |
+
|
626 |
+
// See test/unit/core.js for details concerning this function.
|
627 |
+
isFunction: function( fn ) {
|
628 |
+
return !!fn && typeof fn != "string" && !fn.nodeName &&
|
629 |
+
fn.constructor != Array && /function/i.test( fn + "" );
|
630 |
+
},
|
631 |
+
|
632 |
+
// check if an element is in a (or is an) XML document
|
633 |
+
isXMLDoc: function( elem ) {
|
634 |
+
return elem.documentElement && !elem.body ||
|
635 |
+
elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
|
636 |
+
},
|
637 |
+
|
638 |
+
// Evalulates a script in a global context
|
639 |
+
globalEval: function( data ) {
|
640 |
+
data = jQuery.trim( data );
|
641 |
+
|
642 |
+
if ( data ) {
|
643 |
+
// Inspired by code by Andrea Giammarchi
|
644 |
+
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
|
645 |
+
var head = document.getElementsByTagName("head")[0] || document.documentElement,
|
646 |
+
script = document.createElement("script");
|
647 |
+
|
648 |
+
script.type = "text/javascript";
|
649 |
+
if ( jQuery.browser.msie )
|
650 |
+
script.text = data;
|
651 |
+
else
|
652 |
+
script.appendChild( document.createTextNode( data ) );
|
653 |
+
|
654 |
+
head.appendChild( script );
|
655 |
+
head.removeChild( script );
|
656 |
+
}
|
657 |
+
},
|
658 |
+
|
659 |
+
nodeName: function( elem, name ) {
|
660 |
+
return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
|
661 |
+
},
|
662 |
+
|
663 |
+
cache: {},
|
664 |
+
|
665 |
+
data: function( elem, name, data ) {
|
666 |
+
elem = elem == window ?
|
667 |
+
windowData :
|
668 |
+
elem;
|
669 |
+
|
670 |
+
var id = elem[ expando ];
|
671 |
+
|
672 |
+
// Compute a unique ID for the element
|
673 |
+
if ( !id )
|
674 |
+
id = elem[ expando ] = ++uuid;
|
675 |
+
|
676 |
+
// Only generate the data cache if we're
|
677 |
+
// trying to access or manipulate it
|
678 |
+
if ( name && !jQuery.cache[ id ] )
|
679 |
+
jQuery.cache[ id ] = {};
|
680 |
+
|
681 |
+
// Prevent overriding the named cache with undefined values
|
682 |
+
if ( data != undefined )
|
683 |
+
jQuery.cache[ id ][ name ] = data;
|
684 |
+
|
685 |
+
// Return the named cache data, or the ID for the element
|
686 |
+
return name ?
|
687 |
+
jQuery.cache[ id ][ name ] :
|
688 |
+
id;
|
689 |
+
},
|
690 |
+
|
691 |
+
removeData: function( elem, name ) {
|
692 |
+
elem = elem == window ?
|
693 |
+
windowData :
|
694 |
+
elem;
|
695 |
+
|
696 |
+
var id = elem[ expando ];
|
697 |
+
|
698 |
+
// If we want to remove a specific section of the element's data
|
699 |
+
if ( name ) {
|
700 |
+
if ( jQuery.cache[ id ] ) {
|
701 |
+
// Remove the section of cache data
|
702 |
+
delete jQuery.cache[ id ][ name ];
|
703 |
+
|
704 |
+
// If we've removed all the data, remove the element's cache
|
705 |
+
name = "";
|
706 |
+
|
707 |
+
for ( name in jQuery.cache[ id ] )
|
708 |
+
break;
|
709 |
+
|
710 |
+
if ( !name )
|
711 |
+
jQuery.removeData( elem );
|
712 |
+
}
|
713 |
+
|
714 |
+
// Otherwise, we want to remove all of the element's data
|
715 |
+
} else {
|
716 |
+
// Clean up the element expando
|
717 |
+
try {
|
718 |
+
delete elem[ expando ];
|
719 |
+
} catch(e){
|
720 |
+
// IE has trouble directly removing the expando
|
721 |
+
// but it's ok with using removeAttribute
|
722 |
+
if ( elem.removeAttribute )
|
723 |
+
elem.removeAttribute( expando );
|
724 |
+
}
|
725 |
+
|
726 |
+
// Completely remove the data cache
|
727 |
+
delete jQuery.cache[ id ];
|
728 |
+
}
|
729 |
+
},
|
730 |
+
|
731 |
+
// args is for internal usage only
|
732 |
+
each: function( object, callback, args ) {
|
733 |
+
if ( args ) {
|
734 |
+
if ( object.length == undefined ) {
|
735 |
+
for ( var name in object )
|
736 |
+
if ( callback.apply( object[ name ], args ) === false )
|
737 |
+
break;
|
738 |
+
} else
|
739 |
+
for ( var i = 0, length = object.length; i < length; i++ )
|
740 |
+
if ( callback.apply( object[ i ], args ) === false )
|
741 |
+
break;
|
742 |
+
|
743 |
+
// A special, fast, case for the most common use of each
|
744 |
+
} else {
|
745 |
+
if ( object.length == undefined ) {
|
746 |
+
for ( var name in object )
|
747 |
+
if ( callback.call( object[ name ], name, object[ name ] ) === false )
|
748 |
+
break;
|
749 |
+
} else
|
750 |
+
for ( var i = 0, length = object.length, value = object[0];
|
751 |
+
i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
|
752 |
+
}
|
753 |
+
|
754 |
+
return object;
|
755 |
+
},
|
756 |
+
|
757 |
+
prop: function( elem, value, type, i, name ) {
|
758 |
+
// Handle executable functions
|
759 |
+
if ( jQuery.isFunction( value ) )
|
760 |
+
value = value.call( elem, i );
|
761 |
+
|
762 |
+
// Handle passing in a number to a CSS property
|
763 |
+
return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
|
764 |
+
value + "px" :
|
765 |
+
value;
|
766 |
+
},
|
767 |
+
|
768 |
+
className: {
|
769 |
+
// internal only, use addClass("class")
|
770 |
+
add: function( elem, classNames ) {
|
771 |
+
jQuery.each((classNames || "").split(/\s+/), function(i, className){
|
772 |
+
if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
|
773 |
+
elem.className += (elem.className ? " " : "") + className;
|
774 |
+
});
|
775 |
+
},
|
776 |
+
|
777 |
+
// internal only, use removeClass("class")
|
778 |
+
remove: function( elem, classNames ) {
|
779 |
+
if (elem.nodeType == 1)
|
780 |
+
elem.className = classNames != undefined ?
|
781 |
+
jQuery.grep(elem.className.split(/\s+/), function(className){
|
782 |
+
return !jQuery.className.has( classNames, className );
|
783 |
+
}).join(" ") :
|
784 |
+
"";
|
785 |
+
},
|
786 |
+
|
787 |
+
// internal only, use is(".class")
|
788 |
+
has: function( elem, className ) {
|
789 |
+
return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
|
790 |
+
}
|
791 |
+
},
|
792 |
+
|
793 |
+
// A method for quickly swapping in/out CSS properties to get correct calculations
|
794 |
+
swap: function( elem, options, callback ) {
|
795 |
+
var old = {};
|
796 |
+
// Remember the old values, and insert the new ones
|
797 |
+
for ( var name in options ) {
|
798 |
+
old[ name ] = elem.style[ name ];
|
799 |
+
elem.style[ name ] = options[ name ];
|
800 |
+
}
|
801 |
+
|
802 |
+
callback.call( elem );
|
803 |
+
|
804 |
+
// Revert the old values
|
805 |
+
for ( var name in options )
|
806 |
+
elem.style[ name ] = old[ name ];
|
807 |
+
},
|
808 |
+
|
809 |
+
css: function( elem, name, force ) {
|
810 |
+
if ( name == "width" || name == "height" ) {
|
811 |
+
var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
|
812 |
+
|
813 |
+
function getWH() {
|
814 |
+
val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
|
815 |
+
var padding = 0, border = 0;
|
816 |
+
jQuery.each( which, function() {
|
817 |
+
padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
|
818 |
+
border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
|
819 |
+
});
|
820 |
+
val -= Math.round(padding + border);
|
821 |
+
}
|
822 |
+
|
823 |
+
if ( jQuery(elem).is(":visible") )
|
824 |
+
getWH();
|
825 |
+
else
|
826 |
+
jQuery.swap( elem, props, getWH );
|
827 |
+
|
828 |
+
return Math.max(0, val);
|
829 |
+
}
|
830 |
+
|
831 |
+
return jQuery.curCSS( elem, name, force );
|
832 |
+
},
|
833 |
+
|
834 |
+
curCSS: function( elem, name, force ) {
|
835 |
+
var ret;
|
836 |
+
|
837 |
+
// A helper method for determining if an element's values are broken
|
838 |
+
function color( elem ) {
|
839 |
+
if ( !jQuery.browser.safari )
|
840 |
+
return false;
|
841 |
+
|
842 |
+
var ret = document.defaultView.getComputedStyle( elem, null );
|
843 |
+
return !ret || ret.getPropertyValue("color") == "";
|
844 |
+
}
|
845 |
+
|
846 |
+
// We need to handle opacity special in IE
|
847 |
+
if ( name == "opacity" && jQuery.browser.msie ) {
|
848 |
+
ret = jQuery.attr( elem.style, "opacity" );
|
849 |
+
|
850 |
+
return ret == "" ?
|
851 |
+
"1" :
|
852 |
+
ret;
|
853 |
+
}
|
854 |
+
// Opera sometimes will give the wrong display answer, this fixes it, see #2037
|
855 |
+
if ( jQuery.browser.opera && name == "display" ) {
|
856 |
+
var save = elem.style.outline;
|
857 |
+
elem.style.outline = "0 solid black";
|
858 |
+
elem.style.outline = save;
|
859 |
+
}
|
860 |
+
|
861 |
+
// Make sure we're using the right name for getting the float value
|
862 |
+
if ( name.match( /float/i ) )
|
863 |
+
name = styleFloat;
|
864 |
+
|
865 |
+
if ( !force && elem.style && elem.style[ name ] )
|
866 |
+
ret = elem.style[ name ];
|
867 |
+
|
868 |
+
else if ( document.defaultView && document.defaultView.getComputedStyle ) {
|
869 |
+
|
870 |
+
// Only "float" is needed here
|
871 |
+
if ( name.match( /float/i ) )
|
872 |
+
name = "float";
|
873 |
+
|
874 |
+
name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
|
875 |
+
|
876 |
+
var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
|
877 |
+
|
878 |
+
if ( getComputedStyle && !color( elem ) )
|
879 |
+
ret = getComputedStyle.getPropertyValue( name );
|
880 |
+
|
881 |
+
// If the element isn't reporting its values properly in Safari
|
882 |
+
// then some display: none elements are involved
|
883 |
+
else {
|
884 |
+
var swap = [], stack = [];
|
885 |
+
|
886 |
+
// Locate all of the parent display: none elements
|
887 |
+
for ( var a = elem; a && color(a); a = a.parentNode )
|
888 |
+
stack.unshift(a);
|
889 |
+
|
890 |
+
// Go through and make them visible, but in reverse
|
891 |
+
// (It would be better if we knew the exact display type that they had)
|
892 |
+
for ( var i = 0; i < stack.length; i++ )
|
893 |
+
if ( color( stack[ i ] ) ) {
|
894 |
+
swap[ i ] = stack[ i ].style.display;
|
895 |
+
stack[ i ].style.display = "block";
|
896 |
+
}
|
897 |
+
|
898 |
+
// Since we flip the display style, we have to handle that
|
899 |
+
// one special, otherwise get the value
|
900 |
+
ret = name == "display" && swap[ stack.length - 1 ] != null ?
|
901 |
+
"none" :
|
902 |
+
( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
|
903 |
+
|
904 |
+
// Finally, revert the display styles back
|
905 |
+
for ( var i = 0; i < swap.length; i++ )
|
906 |
+
if ( swap[ i ] != null )
|
907 |
+
stack[ i ].style.display = swap[ i ];
|
908 |
+
}
|
909 |
+
|
910 |
+
// We should always get a number back from opacity
|
911 |
+
if ( name == "opacity" && ret == "" )
|
912 |
+
ret = "1";
|
913 |
+
|
914 |
+
} else if ( elem.currentStyle ) {
|
915 |
+
var camelCase = name.replace(/\-(\w)/g, function(all, letter){
|
916 |
+
return letter.toUpperCase();
|
917 |
+
});
|
918 |
+
|
919 |
+
ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
|
920 |
+
|
921 |
+
// From the awesome hack by Dean Edwards
|
922 |
+
// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
|
923 |
+
|
924 |
+
// If we're not dealing with a regular pixel number
|
925 |
+
// but a number that has a weird ending, we need to convert it to pixels
|
926 |
+
if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
|
927 |
+
// Remember the original values
|
928 |
+
var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
|
929 |
+
|
930 |
+
// Put in the new values to get a computed value out
|
931 |
+
elem.runtimeStyle.left = elem.currentStyle.left;
|
932 |
+
elem.style.left = ret || 0;
|
933 |
+
ret = elem.style.pixelLeft + "px";
|
934 |
+
|
935 |
+
// Revert the changed values
|
936 |
+
elem.style.left = style;
|
937 |
+
elem.runtimeStyle.left = runtimeStyle;
|
938 |
+
}
|
939 |
+
}
|
940 |
+
|
941 |
+
return ret;
|
942 |
+
},
|
943 |
+
|
944 |
+
clean: function( elems, context ) {
|
945 |
+
var ret = [];
|
946 |
+
context = context || document;
|
947 |
+
// !context.createElement fails in IE with an error but returns typeof 'object'
|
948 |
+
if (typeof context.createElement == 'undefined')
|
949 |
+
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
|
950 |
+
|
951 |
+
jQuery.each(elems, function(i, elem){
|
952 |
+
if ( !elem )
|
953 |
+
return;
|
954 |
+
|
955 |
+
if ( elem.constructor == Number )
|
956 |
+
elem = elem.toString();
|
957 |
+
|
958 |
+
// Convert html string into DOM nodes
|
959 |
+
if ( typeof elem == "string" ) {
|
960 |
+
// Fix "XHTML"-style tags in all browsers
|
961 |
+
elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
|
962 |
+
return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
|
963 |
+
all :
|
964 |
+
front + "></" + tag + ">";
|
965 |
+
});
|
966 |
+
|
967 |
+
// Trim whitespace, otherwise indexOf won't work as expected
|
968 |
+
var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
|
969 |
+
|
970 |
+
var wrap =
|
971 |
+
// option or optgroup
|
972 |
+
!tags.indexOf("<opt") &&
|
973 |
+
[ 1, "<select multiple='multiple'>", "</select>" ] ||
|
974 |
+
|
975 |
+
!tags.indexOf("<leg") &&
|
976 |
+
[ 1, "<fieldset>", "</fieldset>" ] ||
|
977 |
+
|
978 |
+
tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
|
979 |
+
[ 1, "<table>", "</table>" ] ||
|
980 |
+
|
981 |
+
!tags.indexOf("<tr") &&
|
982 |
+
[ 2, "<table><tbody>", "</tbody></table>" ] ||
|
983 |
+
|
984 |
+
// <thead> matched above
|
985 |
+
(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
|
986 |
+
[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
|
987 |
+
|
988 |
+
!tags.indexOf("<col") &&
|
989 |
+
[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
|
990 |
+
|
991 |
+
// IE can't serialize <link> and <script> tags normally
|
992 |
+
jQuery.browser.msie &&
|
993 |
+
[ 1, "div<div>", "</div>" ] ||
|
994 |
+
|
995 |
+
[ 0, "", "" ];
|
996 |
+
|
997 |
+
// Go to html and back, then peel off extra wrappers
|
998 |
+
div.innerHTML = wrap[1] + elem + wrap[2];
|
999 |
+
|
1000 |
+
// Move to the right depth
|
1001 |
+
while ( wrap[0]-- )
|
1002 |
+
div = div.lastChild;
|
1003 |
+
|
1004 |
+
// Remove IE's autoinserted <tbody> from table fragments
|
1005 |
+
if ( jQuery.browser.msie ) {
|
1006 |
+
|
1007 |
+
// String was a <table>, *may* have spurious <tbody>
|
1008 |
+
var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
|
1009 |
+
div.firstChild && div.firstChild.childNodes :
|
1010 |
+
|
1011 |
+
// String was a bare <thead> or <tfoot>
|
1012 |
+
wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
|
1013 |
+
div.childNodes :
|
1014 |
+
[];
|
1015 |
+
|
1016 |
+
for ( var j = tbody.length - 1; j >= 0 ; --j )
|
1017 |
+
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
|
1018 |
+
tbody[ j ].parentNode.removeChild( tbody[ j ] );
|
1019 |
+
|
1020 |
+
// IE completely kills leading whitespace when innerHTML is used
|
1021 |
+
if ( /^\s/.test( elem ) )
|
1022 |
+
div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
|
1023 |
+
|
1024 |
+
}
|
1025 |
+
|
1026 |
+
elem = jQuery.makeArray( div.childNodes );
|
1027 |
+
}
|
1028 |
+
|
1029 |
+
if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
|
1030 |
+
return;
|
1031 |
+
|
1032 |
+
if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
|
1033 |
+
ret.push( elem );
|
1034 |
+
|
1035 |
+
else
|
1036 |
+
ret = jQuery.merge( ret, elem );
|
1037 |
+
|
1038 |
+
});
|
1039 |
+
|
1040 |
+
return ret;
|
1041 |
+
},
|
1042 |
+
|
1043 |
+
attr: function( elem, name, value ) {
|
1044 |
+
// don't set attributes on text and comment nodes
|
1045 |
+
if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
|
1046 |
+
return undefined;
|
1047 |
+
|
1048 |
+
var fix = jQuery.isXMLDoc( elem ) ?
|
1049 |
+
{} :
|
1050 |
+
jQuery.props;
|
1051 |
+
|
1052 |
+
// Safari mis-reports the default selected property of a hidden option
|
1053 |
+
// Accessing the parent's selectedIndex property fixes it
|
1054 |
+
if ( name == "selected" && jQuery.browser.safari )
|
1055 |
+
elem.parentNode.selectedIndex;
|
1056 |
+
|
1057 |
+
// Certain attributes only work when accessed via the old DOM 0 way
|
1058 |
+
if ( fix[ name ] ) {
|
1059 |
+
if ( value != undefined )
|
1060 |
+
elem[ fix[ name ] ] = value;
|
1061 |
+
|
1062 |
+
return elem[ fix[ name ] ];
|
1063 |
+
|
1064 |
+
} else if ( jQuery.browser.msie && name == "style" )
|
1065 |
+
return jQuery.attr( elem.style, "cssText", value );
|
1066 |
+
|
1067 |
+
else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
|
1068 |
+
return elem.getAttributeNode( name ).nodeValue;
|
1069 |
+
|
1070 |
+
// IE elem.getAttribute passes even for style
|
1071 |
+
else if ( elem.tagName ) {
|
1072 |
+
|
1073 |
+
if ( value != undefined ) {
|
1074 |
+
// We can't allow the type property to be changed (since it causes problems in IE)
|
1075 |
+
if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
|
1076 |
+
throw "type property can't be changed";
|
1077 |
+
|
1078 |
+
// convert the value to a string (all browsers do this but IE) see #1070
|
1079 |
+
elem.setAttribute( name, "" + value );
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) )
|
1083 |
+
return elem.getAttribute( name, 2 );
|
1084 |
+
|
1085 |
+
return elem.getAttribute( name );
|
1086 |
+
|
1087 |
+
// elem is actually elem.style ... set the style
|
1088 |
+
} else {
|
1089 |
+
// IE actually uses filters for opacity
|
1090 |
+
if ( name == "opacity" && jQuery.browser.msie ) {
|
1091 |
+
if ( value != undefined ) {
|
1092 |
+
// IE has trouble with opacity if it does not have layout
|
1093 |
+
// Force it by setting the zoom level
|
1094 |
+
elem.zoom = 1;
|
1095 |
+
|
1096 |
+
// Set the alpha filter to set the opacity
|
1097 |
+
elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
|
1098 |
+
(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
|
1099 |
+
}
|
1100 |
+
|
1101 |
+
return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
|
1102 |
+
(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
|
1103 |
+
"";
|
1104 |
+
}
|
1105 |
+
|
1106 |
+
name = name.replace(/-([a-z])/ig, function(all, letter){
|
1107 |
+
return letter.toUpperCase();
|
1108 |
+
});
|
1109 |
+
|
1110 |
+
if ( value != undefined )
|
1111 |
+
elem[ name ] = value;
|
1112 |
+
|
1113 |
+
return elem[ name ];
|
1114 |
+
}
|
1115 |
+
},
|
1116 |
+
|
1117 |
+
trim: function( text ) {
|
1118 |
+
return (text || "").replace( /^\s+|\s+$/g, "" );
|
1119 |
+
},
|
1120 |
+
|
1121 |
+
makeArray: function( array ) {
|
1122 |
+
var ret = [];
|
1123 |
+
|
1124 |
+
// Need to use typeof to fight Safari childNodes crashes
|
1125 |
+
if ( typeof array != "array" )
|
1126 |
+
for ( var i = 0, length = array.length; i < length; i++ )
|
1127 |
+
ret.push( array[ i ] );
|
1128 |
+
else
|
1129 |
+
ret = array.slice( 0 );
|
1130 |
+
|
1131 |
+
return ret;
|
1132 |
+
},
|
1133 |
+
|
1134 |
+
inArray: function( elem, array ) {
|
1135 |
+
for ( var i = 0, length = array.length; i < length; i++ )
|
1136 |
+
if ( array[ i ] == elem )
|
1137 |
+
return i;
|
1138 |
+
|
1139 |
+
return -1;
|
1140 |
+
},
|
1141 |
+
|
1142 |
+
merge: function( first, second ) {
|
1143 |
+
// We have to loop this way because IE & Opera overwrite the length
|
1144 |
+
// expando of getElementsByTagName
|
1145 |
+
|
1146 |
+
// Also, we need to make sure that the correct elements are being returned
|
1147 |
+
// (IE returns comment nodes in a '*' query)
|
1148 |
+
if ( jQuery.browser.msie ) {
|
1149 |
+
for ( var i = 0; second[ i ]; i++ )
|
1150 |
+
if ( second[ i ].nodeType != 8 )
|
1151 |
+
first.push( second[ i ] );
|
1152 |
+
|
1153 |
+
} else
|
1154 |
+
for ( var i = 0; second[ i ]; i++ )
|
1155 |
+
first.push( second[ i ] );
|
1156 |
+
|
1157 |
+
return first;
|
1158 |
+
},
|
1159 |
+
|
1160 |
+
unique: function( array ) {
|
1161 |
+
var ret = [], done = {};
|
1162 |
+
|
1163 |
+
try {
|
1164 |
+
|
1165 |
+
for ( var i = 0, length = array.length; i < length; i++ ) {
|
1166 |
+
var id = jQuery.data( array[ i ] );
|
1167 |
+
|
1168 |
+
if ( !done[ id ] ) {
|
1169 |
+
done[ id ] = true;
|
1170 |
+
ret.push( array[ i ] );
|
1171 |
+
}
|
1172 |
+
}
|
1173 |
+
|
1174 |
+
} catch( e ) {
|
1175 |
+
ret = array;
|
1176 |
+
}
|
1177 |
+
|
1178 |
+
return ret;
|
1179 |
+
},
|
1180 |
+
|
1181 |
+
grep: function( elems, callback, inv ) {
|
1182 |
+
var ret = [];
|
1183 |
+
|
1184 |
+
// Go through the array, only saving the items
|
1185 |
+
// that pass the validator function
|
1186 |
+
for ( var i = 0, length = elems.length; i < length; i++ )
|
1187 |
+
if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
|
1188 |
+
ret.push( elems[ i ] );
|
1189 |
+
|
1190 |
+
return ret;
|
1191 |
+
},
|
1192 |
+
|
1193 |
+
map: function( elems, callback ) {
|
1194 |
+
var ret = [];
|
1195 |
+
|
1196 |
+
// Go through the array, translating each of the items to their
|
1197 |
+
// new value (or values).
|
1198 |
+
for ( var i = 0, length = elems.length; i < length; i++ ) {
|
1199 |
+
var value = callback( elems[ i ], i );
|
1200 |
+
|
1201 |
+
if ( value !== null && value != undefined ) {
|
1202 |
+
if ( value.constructor != Array )
|
1203 |
+
value = [ value ];
|
1204 |
+
|
1205 |
+
ret = ret.concat( value );
|
1206 |
+
}
|
1207 |
+
}
|
1208 |
+
|
1209 |
+
return ret;
|
1210 |
+
}
|
1211 |
+
});
|
1212 |
+
|
1213 |
+
var userAgent = navigator.userAgent.toLowerCase();
|
1214 |
+
|
1215 |
+
// Figure out what browser is being used
|
1216 |
+
jQuery.browser = {
|
1217 |
+
version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
|
1218 |
+
safari: /webkit/.test( userAgent ),
|
1219 |
+
opera: /opera/.test( userAgent ),
|
1220 |
+
msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
|
1221 |
+
mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
|
1222 |
+
};
|
1223 |
+
|
1224 |
+
var styleFloat = jQuery.browser.msie ?
|
1225 |
+
"styleFloat" :
|
1226 |
+
"cssFloat";
|
1227 |
+
|
1228 |
+
jQuery.extend({
|
1229 |
+
// Check to see if the W3C box model is being used
|
1230 |
+
boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
|
1231 |
+
|
1232 |
+
props: {
|
1233 |
+
"for": "htmlFor",
|
1234 |
+
"class": "className",
|
1235 |
+
"float": styleFloat,
|
1236 |
+
cssFloat: styleFloat,
|
1237 |
+
styleFloat: styleFloat,
|
1238 |
+
innerHTML: "innerHTML",
|
1239 |
+
className: "className",
|
1240 |
+
value: "value",
|
1241 |
+
disabled: "disabled",
|
1242 |
+
checked: "checked",
|
1243 |
+
readonly: "readOnly",
|
1244 |
+
selected: "selected",
|
1245 |
+
maxlength: "maxLength",
|
1246 |
+
selectedIndex: "selectedIndex",
|
1247 |
+
defaultValue: "defaultValue",
|
1248 |
+
tagName: "tagName",
|
1249 |
+
nodeName: "nodeName"
|
1250 |
+
}
|
1251 |
+
});
|
1252 |
+
|
1253 |
+
jQuery.each({
|
1254 |
+
parent: function(elem){return elem.parentNode;},
|
1255 |
+
parents: function(elem){return jQuery.dir(elem,"parentNode");},
|
1256 |
+
next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
|
1257 |
+
prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
|
1258 |
+
nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
|
1259 |
+
prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
|
1260 |
+
siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
|
1261 |
+
children: function(elem){return jQuery.sibling(elem.firstChild);},
|
1262 |
+
contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
|
1263 |
+
}, function(name, fn){
|
1264 |
+
jQuery.fn[ name ] = function( selector ) {
|
1265 |
+
var ret = jQuery.map( this, fn );
|
1266 |
+
|
1267 |
+
if ( selector && typeof selector == "string" )
|
1268 |
+
ret = jQuery.multiFilter( selector, ret );
|
1269 |
+
|
1270 |
+
return this.pushStack( jQuery.unique( ret ) );
|
1271 |
+
};
|
1272 |
+
});
|
1273 |
+
|
1274 |
+
jQuery.each({
|
1275 |
+
appendTo: "append",
|
1276 |
+
prependTo: "prepend",
|
1277 |
+
insertBefore: "before",
|
1278 |
+
insertAfter: "after",
|
1279 |
+
replaceAll: "replaceWith"
|
1280 |
+
}, function(name, original){
|
1281 |
+
jQuery.fn[ name ] = function() {
|
1282 |
+
var args = arguments;
|
1283 |
+
|
1284 |
+
return this.each(function(){
|
1285 |
+
for ( var i = 0, length = args.length; i < length; i++ )
|
1286 |
+
jQuery( args[ i ] )[ original ]( this );
|
1287 |
+
});
|
1288 |
+
};
|
1289 |
+
});
|
1290 |
+
|
1291 |
+
jQuery.each({
|
1292 |
+
removeAttr: function( name ) {
|
1293 |
+
jQuery.attr( this, name, "" );
|
1294 |
+
if (this.nodeType == 1)
|
1295 |
+
this.removeAttribute( name );
|
1296 |
+
},
|
1297 |
+
|
1298 |
+
addClass: function( classNames ) {
|
1299 |
+
jQuery.className.add( this, classNames );
|
1300 |
+
},
|
1301 |
+
|
1302 |
+
removeClass: function( classNames ) {
|
1303 |
+
jQuery.className.remove( this, classNames );
|
1304 |
+
},
|
1305 |
+
|
1306 |
+
toggleClass: function( classNames ) {
|
1307 |
+
jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
|
1308 |
+
},
|
1309 |
+
|
1310 |
+
remove: function( selector ) {
|
1311 |
+
if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
|
1312 |
+
// Prevent memory leaks
|
1313 |
+
jQuery( "*", this ).add(this).each(function(){
|
1314 |
+
jQuery.event.remove(this);
|
1315 |
+
jQuery.removeData(this);
|
1316 |
+
});
|
1317 |
+
if (this.parentNode)
|
1318 |
+
this.parentNode.removeChild( this );
|
1319 |
+
}
|
1320 |
+
},
|
1321 |
+
|
1322 |
+
empty: function() {
|
1323 |
+
// Remove element nodes and prevent memory leaks
|
1324 |
+
jQuery( ">*", this ).remove();
|
1325 |
+
|
1326 |
+
// Remove any remaining nodes
|
1327 |
+
while ( this.firstChild )
|
1328 |
+
this.removeChild( this.firstChild );
|
1329 |
+
}
|
1330 |
+
}, function(name, fn){
|
1331 |
+
jQuery.fn[ name ] = function(){
|
1332 |
+
return this.each( fn, arguments );
|
1333 |
+
};
|
1334 |
+
});
|
1335 |
+
|
1336 |
+
jQuery.each([ "Height", "Width" ], function(i, name){
|
1337 |
+
var type = name.toLowerCase();
|
1338 |
+
|
1339 |
+
jQuery.fn[ type ] = function( size ) {
|
1340 |
+
// Get window width or height
|
1341 |
+
return this[0] == window ?
|
1342 |
+
// Opera reports document.body.client[Width/Height] properly in both quirks and standards
|
1343 |
+
jQuery.browser.opera && document.body[ "client" + name ] ||
|
1344 |
+
|
1345 |
+
// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
|
1346 |
+
jQuery.browser.safari && window[ "inner" + name ] ||
|
1347 |
+
|
1348 |
+
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
|
1349 |
+
document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
|
1350 |
+
|
1351 |
+
// Get document width or height
|
1352 |
+
this[0] == document ?
|
1353 |
+
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
|
1354 |
+
Math.max(
|
1355 |
+
Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
|
1356 |
+
Math.max(document.body["offset" + name], document.documentElement["offset" + name])
|
1357 |
+
) :
|
1358 |
+
|
1359 |
+
// Get or set width or height on the element
|
1360 |
+
size == undefined ?
|
1361 |
+
// Get width or height on the element
|
1362 |
+
(this.length ? jQuery.css( this[0], type ) : null) :
|
1363 |
+
|
1364 |
+
// Set the width or height on the element (default to pixels if value is unitless)
|
1365 |
+
this.css( type, size.constructor == String ? size : size + "px" );
|
1366 |
+
};
|
1367 |
+
});
|
1368 |
+
|
1369 |
+
var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
|
1370 |
+
"(?:[\\w*_-]|\\\\.)" :
|
1371 |
+
"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
|
1372 |
+
quickChild = new RegExp("^>\\s*(" + chars + "+)"),
|
1373 |
+
quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
|
1374 |
+
quickClass = new RegExp("^([#.]?)(" + chars + "*)");
|
1375 |
+
|
1376 |
+
jQuery.extend({
|
1377 |
+
expr: {
|
1378 |
+
"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
|
1379 |
+
"#": function(a,i,m){return a.getAttribute("id")==m[2];},
|
1380 |
+
":": {
|
1381 |
+
// Position Checks
|
1382 |
+
lt: function(a,i,m){return i<m[3]-0;},
|
1383 |
+
gt: function(a,i,m){return i>m[3]-0;},
|
1384 |
+
nth: function(a,i,m){return m[3]-0==i;},
|
1385 |
+
eq: function(a,i,m){return m[3]-0==i;},
|
1386 |
+
first: function(a,i){return i==0;},
|
1387 |
+
last: function(a,i,m,r){return i==r.length-1;},
|
1388 |
+
even: function(a,i){return i%2==0;},
|
1389 |
+
odd: function(a,i){return i%2;},
|
1390 |
+
|
1391 |
+
// Child Checks
|
1392 |
+
"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
|
1393 |
+
"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
|
1394 |
+
"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},
|
1395 |
+
|
1396 |
+
// Parent Checks
|
1397 |
+
parent: function(a){return a.firstChild;},
|
1398 |
+
empty: function(a){return !a.firstChild;},
|
1399 |
+
|
1400 |
+
// Text Check
|
1401 |
+
contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},
|
1402 |
+
|
1403 |
+
// Visibility
|
1404 |
+
visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
|
1405 |
+
hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},
|
1406 |
+
|
1407 |
+
// Form attributes
|
1408 |
+
enabled: function(a){return !a.disabled;},
|
1409 |
+
disabled: function(a){return a.disabled;},
|
1410 |
+
checked: function(a){return a.checked;},
|
1411 |
+
selected: function(a){return a.selected||jQuery.attr(a,"selected");},
|
1412 |
+
|
1413 |
+
// Form elements
|
1414 |
+
text: function(a){return "text"==a.type;},
|
1415 |
+
radio: function(a){return "radio"==a.type;},
|
1416 |
+
checkbox: function(a){return "checkbox"==a.type;},
|
1417 |
+
file: function(a){return "file"==a.type;},
|
1418 |
+
password: function(a){return "password"==a.type;},
|
1419 |
+
submit: function(a){return "submit"==a.type;},
|
1420 |
+
image: function(a){return "image"==a.type;},
|
1421 |
+
reset: function(a){return "reset"==a.type;},
|
1422 |
+
button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
|
1423 |
+
input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},
|
1424 |
+
|
1425 |
+
// :has()
|
1426 |
+
has: function(a,i,m){return jQuery.find(m[3],a).length;},
|
1427 |
+
|
1428 |
+
// :header
|
1429 |
+
header: function(a){return /h\d/i.test(a.nodeName);},
|
1430 |
+
|
1431 |
+
// :animated
|
1432 |
+
animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
|
1433 |
+
}
|
1434 |
+
},
|
1435 |
+
|
1436 |
+
// The regular expressions that power the parsing engine
|
1437 |
+
parse: [
|
1438 |
+
// Match: [@value='test'], [@foo]
|
1439 |
+
/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
|
1440 |
+
|
1441 |
+
// Match: :contains('foo')
|
1442 |
+
/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
|
1443 |
+
|
1444 |
+
// Match: :even, :last-chlid, #id, .class
|
1445 |
+
new RegExp("^([:.#]*)(" + chars + "+)")
|
1446 |
+
],
|
1447 |
+
|
1448 |
+
multiFilter: function( expr, elems, not ) {
|
1449 |
+
var old, cur = [];
|
1450 |
+
|
1451 |
+
while ( expr && expr != old ) {
|
1452 |
+
old = expr;
|
1453 |
+
var f = jQuery.filter( expr, elems, not );
|
1454 |
+
expr = f.t.replace(/^\s*,\s*/, "" );
|
1455 |
+
cur = not ? elems = f.r : jQuery.merge( cur, f.r );
|
1456 |
+
}
|
1457 |
+
|
1458 |
+
return cur;
|
1459 |
+
},
|
1460 |
+
|
1461 |
+
find: function( t, context ) {
|
1462 |
+
// Quickly handle non-string expressions
|
1463 |
+
if ( typeof t != "string" )
|
1464 |
+
return [ t ];
|
1465 |
+
|
1466 |
+
// check to make sure context is a DOM element or a document
|
1467 |
+
if ( context && context.nodeType != 1 && context.nodeType != 9)
|
1468 |
+
return [ ];
|
1469 |
+
|
1470 |
+
// Set the correct context (if none is provided)
|
1471 |
+
context = context || document;
|
1472 |
+
|
1473 |
+
// Initialize the search
|
1474 |
+
var ret = [context], done = [], last, nodeName;
|
1475 |
+
|
1476 |
+
// Continue while a selector expression exists, and while
|
1477 |
+
// we're no longer looping upon ourselves
|
1478 |
+
while ( t && last != t ) {
|
1479 |
+
var r = [];
|
1480 |
+
last = t;
|
1481 |
+
|
1482 |
+
t = jQuery.trim(t);
|
1483 |
+
|
1484 |
+
var foundToken = false;
|
1485 |
+
|
1486 |
+
// An attempt at speeding up child selectors that
|
1487 |
+
// point to a specific element tag
|
1488 |
+
var re = quickChild;
|
1489 |
+
var m = re.exec(t);
|
1490 |
+
|
1491 |
+
if ( m ) {
|
1492 |
+
nodeName = m[1].toUpperCase();
|
1493 |
+
|
1494 |
+
// Perform our own iteration and filter
|
1495 |
+
for ( var i = 0; ret[i]; i++ )
|
1496 |
+
for ( var c = ret[i].firstChild; c; c = c.nextSibling )
|
1497 |
+
if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
|
1498 |
+
r.push( c );
|
1499 |
+
|
1500 |
+
ret = r;
|
1501 |
+
t = t.replace( re, "" );
|
1502 |
+
if ( t.indexOf(" ") == 0 ) continue;
|
1503 |
+
foundToken = true;
|
1504 |
+
} else {
|
1505 |
+
re = /^([>+~])\s*(\w*)/i;
|
1506 |
+
|
1507 |
+
if ( (m = re.exec(t)) != null ) {
|
1508 |
+
r = [];
|
1509 |
+
|
1510 |
+
var merge = {};
|
1511 |
+
nodeName = m[2].toUpperCase();
|
1512 |
+
m = m[1];
|
1513 |
+
|
1514 |
+
for ( var j = 0, rl = ret.length; j < rl; j++ ) {
|
1515 |
+
var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
|
1516 |
+
for ( ; n; n = n.nextSibling )
|
1517 |
+
if ( n.nodeType == 1 ) {
|
1518 |
+
var id = jQuery.data(n);
|
1519 |
+
|
1520 |
+
if ( m == "~" && merge[id] ) break;
|
1521 |
+
|
1522 |
+
if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
|
1523 |
+
if ( m == "~" ) merge[id] = true;
|
1524 |
+
r.push( n );
|
1525 |
+
}
|
1526 |
+
|
1527 |
+
if ( m == "+" ) break;
|
1528 |
+
}
|
1529 |
+
}
|
1530 |
+
|
1531 |
+
ret = r;
|
1532 |
+
|
1533 |
+
// And remove the token
|
1534 |
+
t = jQuery.trim( t.replace( re, "" ) );
|
1535 |
+
foundToken = true;
|
1536 |
+
}
|
1537 |
+
}
|
1538 |
+
|
1539 |
+
// See if there's still an expression, and that we haven't already
|
1540 |
+
// matched a token
|
1541 |
+
if ( t && !foundToken ) {
|
1542 |
+
// Handle multiple expressions
|
1543 |
+
if ( !t.indexOf(",") ) {
|
1544 |
+
// Clean the result set
|
1545 |
+
if ( context == ret[0] ) ret.shift();
|
1546 |
+
|
1547 |
+
// Merge the result sets
|
1548 |
+
done = jQuery.merge( done, ret );
|
1549 |
+
|
1550 |
+
// Reset the context
|
1551 |
+
r = ret = [context];
|
1552 |
+
|
1553 |
+
// Touch up the selector string
|
1554 |
+
t = " " + t.substr(1,t.length);
|
1555 |
+
|
1556 |
+
} else {
|
1557 |
+
// Optimize for the case nodeName#idName
|
1558 |
+
var re2 = quickID;
|
1559 |
+
var m = re2.exec(t);
|
1560 |
+
|
1561 |
+
// Re-organize the results, so that they're consistent
|
1562 |
+
if ( m ) {
|
1563 |
+
m = [ 0, m[2], m[3], m[1] ];
|
1564 |
+
|
1565 |
+
} else {
|
1566 |
+
// Otherwise, do a traditional filter check for
|
1567 |
+
// ID, class, and element selectors
|
1568 |
+
re2 = quickClass;
|
1569 |
+
m = re2.exec(t);
|
1570 |
+
}
|
1571 |
+
|
1572 |
+
m[2] = m[2].replace(/\\/g, "");
|
1573 |
+
|
1574 |
+
var elem = ret[ret.length-1];
|
1575 |
+
|
1576 |
+
// Try to do a global search by ID, where we can
|
1577 |
+
if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
|
1578 |
+
// Optimization for HTML document case
|
1579 |
+
var oid = elem.getElementById(m[2]);
|
1580 |
+
|
1581 |
+
// Do a quick check for the existence of the actual ID attribute
|
1582 |
+
// to avoid selecting by the name attribute in IE
|
1583 |
+
// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
|
1584 |
+
if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
|
1585 |
+
oid = jQuery('[@id="'+m[2]+'"]', elem)[0];
|
1586 |
+
|
1587 |
+
// Do a quick check for node name (where applicable) so
|
1588 |
+
// that div#foo searches will be really fast
|
1589 |
+
ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
|
1590 |
+
} else {
|
1591 |
+
// We need to find all descendant elements
|
1592 |
+
for ( var i = 0; ret[i]; i++ ) {
|
1593 |
+
// Grab the tag name being searched for
|
1594 |
+
var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
|
1595 |
+
|
1596 |
+
// Handle IE7 being really dumb about <object>s
|
1597 |
+
if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
|
1598 |
+
tag = "param";
|
1599 |
+
|
1600 |
+
r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
|
1601 |
+
}
|
1602 |
+
|
1603 |
+
// It's faster to filter by class and be done with it
|
1604 |
+
if ( m[1] == "." )
|
1605 |
+
r = jQuery.classFilter( r, m[2] );
|
1606 |
+
|
1607 |
+
// Same with ID filtering
|
1608 |
+
if ( m[1] == "#" ) {
|
1609 |
+
var tmp = [];
|
1610 |
+
|
1611 |
+
// Try to find the element with the ID
|
1612 |
+
for ( var i = 0; r[i]; i++ )
|
1613 |
+
if ( r[i].getAttribute("id") == m[2] ) {
|
1614 |
+
tmp = [ r[i] ];
|
1615 |
+
break;
|
1616 |
+
}
|
1617 |
+
|
1618 |
+
r = tmp;
|
1619 |
+
}
|
1620 |
+
|
1621 |
+
ret = r;
|
1622 |
+
}
|
1623 |
+
|
1624 |
+
t = t.replace( re2, "" );
|
1625 |
+
}
|
1626 |
+
|
1627 |
+
}
|
1628 |
+
|
1629 |
+
// If a selector string still exists
|
1630 |
+
if ( t ) {
|
1631 |
+
// Attempt to filter it
|
1632 |
+
var val = jQuery.filter(t,r);
|
1633 |
+
ret = r = val.r;
|
1634 |
+
t = jQuery.trim(val.t);
|
1635 |
+
}
|
1636 |
+
}
|
1637 |
+
|
1638 |
+
// An error occurred with the selector;
|
1639 |
+
// just return an empty set instead
|
1640 |
+
if ( t )
|
1641 |
+
ret = [];
|
1642 |
+
|
1643 |
+
// Remove the root context
|
1644 |
+
if ( ret && context == ret[0] )
|
1645 |
+
ret.shift();
|
1646 |
+
|
1647 |
+
// And combine the results
|
1648 |
+
done = jQuery.merge( done, ret );
|
1649 |
+
|
1650 |
+
return done;
|
1651 |
+
},
|
1652 |
+
|
1653 |
+
classFilter: function(r,m,not){
|
1654 |
+
m = " " + m + " ";
|
1655 |
+
var tmp = [];
|
1656 |
+
for ( var i = 0; r[i]; i++ ) {
|
1657 |
+
var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
|
1658 |
+
if ( !not && pass || not && !pass )
|
1659 |
+
tmp.push( r[i] );
|
1660 |
+
}
|
1661 |
+
return tmp;
|
1662 |
+
},
|
1663 |
+
|
1664 |
+
filter: function(t,r,not) {
|
1665 |
+
var last;
|
1666 |
+
|
1667 |
+
// Look for common filter expressions
|
1668 |
+
while ( t && t != last ) {
|
1669 |
+
last = t;
|
1670 |
+
|
1671 |
+
var p = jQuery.parse, m;
|
1672 |
+
|
1673 |
+
for ( var i = 0; p[i]; i++ ) {
|
1674 |
+
m = p[i].exec( t );
|
1675 |
+
|
1676 |
+
if ( m ) {
|
1677 |
+
// Remove what we just matched
|
1678 |
+
t = t.substring( m[0].length );
|
1679 |
+
|
1680 |
+
m[2] = m[2].replace(/\\/g, "");
|
1681 |
+
break;
|
1682 |
+
}
|
1683 |
+
}
|
1684 |
+
|
1685 |
+
if ( !m )
|
1686 |
+
break;
|
1687 |
+
|
1688 |
+
// :not() is a special case that can be optimized by
|
1689 |
+
// keeping it out of the expression list
|
1690 |
+
if ( m[1] == ":" && m[2] == "not" )
|
1691 |
+
// optimize if only one selector found (most common case)
|
1692 |
+
r = isSimple.test( m[3] ) ?
|
1693 |
+
jQuery.filter(m[3], r, true).r :
|
1694 |
+
jQuery( r ).not( m[3] );
|
1695 |
+
|
1696 |
+
// We can get a big speed boost by filtering by class here
|
1697 |
+
else if ( m[1] == "." )
|
1698 |
+
r = jQuery.classFilter(r, m[2], not);
|
1699 |
+
|
1700 |
+
else if ( m[1] == "[" ) {
|
1701 |
+
var tmp = [], type = m[3];
|
1702 |
+
|
1703 |
+
for ( var i = 0, rl = r.length; i < rl; i++ ) {
|
1704 |
+
var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
|
1705 |
+
|
1706 |
+
if ( z == null || /href|src|selected/.test(m[2]) )
|
1707 |
+
z = jQuery.attr(a,m[2]) || '';
|
1708 |
+
|
1709 |
+
if ( (type == "" && !!z ||
|
1710 |
+
type == "=" && z == m[5] ||
|
1711 |
+
type == "!=" && z != m[5] ||
|
1712 |
+
type == "^=" && z && !z.indexOf(m[5]) ||
|
1713 |
+
type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
|
1714 |
+
(type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
|
1715 |
+
tmp.push( a );
|
1716 |
+
}
|
1717 |
+
|
1718 |
+
r = tmp;
|
1719 |
+
|
1720 |
+
// We can get a speed boost by handling nth-child here
|
1721 |
+
} else if ( m[1] == ":" && m[2] == "nth-child" ) {
|
1722 |
+
var merge = {}, tmp = [],
|
1723 |
+
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
|
1724 |
+
test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
|
1725 |
+
m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
|
1726 |
+
!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
|
1727 |
+
// calculate the numbers (first)n+(last) including if they are negative
|
1728 |
+
first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
|
1729 |
+
|
1730 |
+
// loop through all the elements left in the jQuery object
|
1731 |
+
for ( var i = 0, rl = r.length; i < rl; i++ ) {
|
1732 |
+
var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
|
1733 |
+
|
1734 |
+
if ( !merge[id] ) {
|
1735 |
+
var c = 1;
|
1736 |
+
|
1737 |
+
for ( var n = parentNode.firstChild; n; n = n.nextSibling )
|
1738 |
+
if ( n.nodeType == 1 )
|
1739 |
+
n.nodeIndex = c++;
|
1740 |
+
|
1741 |
+
merge[id] = true;
|
1742 |
+
}
|
1743 |
+
|
1744 |
+
var add = false;
|
1745 |
+
|
1746 |
+
if ( first == 0 ) {
|
1747 |
+
if ( node.nodeIndex == last )
|
1748 |
+
add = true;
|
1749 |
+
} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
|
1750 |
+
add = true;
|
1751 |
+
|
1752 |
+
if ( add ^ not )
|
1753 |
+
tmp.push( node );
|
1754 |
+
}
|
1755 |
+
|
1756 |
+
r = tmp;
|
1757 |
+
|
1758 |
+
// Otherwise, find the expression to execute
|
1759 |
+
} else {
|
1760 |
+
var fn = jQuery.expr[ m[1] ];
|
1761 |
+
if ( typeof fn == "object" )
|
1762 |
+
fn = fn[ m[2] ];
|
1763 |
+
|
1764 |
+
if ( typeof fn == "string" )
|
1765 |
+
fn = eval("false||function(a,i){return " + fn + ";}");
|
1766 |
+
|
1767 |
+
// Execute it against the current filter
|
1768 |
+
r = jQuery.grep( r, function(elem, i){
|
1769 |
+
return fn(elem, i, m, r);
|
1770 |
+
}, not );
|
1771 |
+
}
|
1772 |
+
}
|
1773 |
+
|
1774 |
+
// Return an array of filtered elements (r)
|
1775 |
+
// and the modified expression string (t)
|
1776 |
+
return { r: r, t: t };
|
1777 |
+
},
|
1778 |
+
|
1779 |
+
dir: function( elem, dir ){
|
1780 |
+
var matched = [];
|
1781 |
+
var cur = elem[dir];
|
1782 |
+
while ( cur && cur != document ) {
|
1783 |
+
if ( cur.nodeType == 1 )
|
1784 |
+
matched.push( cur );
|
1785 |
+
cur = cur[dir];
|
1786 |
+
}
|
1787 |
+
return matched;
|
1788 |
+
},
|
1789 |
+
|
1790 |
+
nth: function(cur,result,dir,elem){
|
1791 |
+
result = result || 1;
|
1792 |
+
var num = 0;
|
1793 |
+
|
1794 |
+
for ( ; cur; cur = cur[dir] )
|
1795 |
+
if ( cur.nodeType == 1 && ++num == result )
|
1796 |
+
break;
|
1797 |
+
|
1798 |
+
return cur;
|
1799 |
+
},
|
1800 |
+
|
1801 |
+
sibling: function( n, elem ) {
|
1802 |
+
var r = [];
|
1803 |
+
|
1804 |
+
for ( ; n; n = n.nextSibling ) {
|
1805 |
+
if ( n.nodeType == 1 && (!elem || n != elem) )
|
1806 |
+
r.push( n );
|
1807 |
+
}
|
1808 |
+
|
1809 |
+
return r;
|
1810 |
+
}
|
1811 |
+
});
|
1812 |
+
|
1813 |
+
/*
|
1814 |
+
* A number of helper functions used for managing events.
|
1815 |
+
* Many of the ideas behind this code orignated from
|
1816 |
+
* Dean Edwards' addEvent library.
|
1817 |
+
*/
|
1818 |
+
jQuery.event = {
|
1819 |
+
|
1820 |
+
// Bind an event to an element
|
1821 |
+
// Original by Dean Edwards
|
1822 |
+
add: function(elem, types, handler, data) {
|
1823 |
+
if ( elem.nodeType == 3 || elem.nodeType == 8 )
|
1824 |
+
return;
|
1825 |
+
|
1826 |
+
// For whatever reason, IE has trouble passing the window object
|
1827 |
+
// around, causing it to be cloned in the process
|
1828 |
+
if ( jQuery.browser.msie && elem.setInterval != undefined )
|
1829 |
+
elem = window;
|
1830 |
+
|
1831 |
+
// Make sure that the function being executed has a unique ID
|
1832 |
+
if ( !handler.guid )
|
1833 |
+
handler.guid = this.guid++;
|
1834 |
+
|
1835 |
+
// if data is passed, bind to handler
|
1836 |
+
if( data != undefined ) {
|
1837 |
+
// Create temporary function pointer to original handler
|
1838 |
+
var fn = handler;
|
1839 |
+
|
1840 |
+
// Create unique handler function, wrapped around original handler
|
1841 |
+
handler = function() {
|
1842 |
+
// Pass arguments and context to original handler
|
1843 |
+
return fn.apply(this, arguments);
|
1844 |
+
};
|
1845 |
+
|
1846 |
+
// Store data in unique handler
|
1847 |
+
handler.data = data;
|
1848 |
+
|
1849 |
+
// Set the guid of unique handler to the same of original handler, so it can be removed
|
1850 |
+
handler.guid = fn.guid;
|
1851 |
+
}
|
1852 |
+
|
1853 |
+
// Init the element's event structure
|
1854 |
+
var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
|
1855 |
+
handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
|
1856 |
+
// returned undefined or false
|
1857 |
+
var val;
|
1858 |
+
|
1859 |
+
// Handle the second event of a trigger and when
|
1860 |
+
// an event is called after a page has unloaded
|
1861 |
+
if ( typeof jQuery == "undefined" || jQuery.event.triggered )
|
1862 |
+
return val;
|
1863 |
+
|
1864 |
+
val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
|
1865 |
+
|
1866 |
+
return val;
|
1867 |
+
});
|
1868 |
+
// Add elem as a property of the handle function
|
1869 |
+
// This is to prevent a memory leak with non-native
|
1870 |
+
// event in IE.
|
1871 |
+
handle.elem = elem;
|
1872 |
+
|
1873 |
+
// Handle multiple events seperated by a space
|
1874 |
+
// jQuery(...).bind("mouseover mouseout", fn);
|
1875 |
+
jQuery.each(types.split(/\s+/), function(index, type) {
|
1876 |
+
// Namespaced event handlers
|
1877 |
+
var parts = type.split(".");
|
1878 |
+
type = parts[0];
|
1879 |
+
handler.type = parts[1];
|
1880 |
+
|
1881 |
+
// Get the current list of functions bound to this event
|
1882 |
+
var handlers = events[type];
|
1883 |
+
|
1884 |
+
// Init the event handler queue
|
1885 |
+
if (!handlers) {
|
1886 |
+
handlers = events[type] = {};
|
1887 |
+
|
1888 |
+
// Check for a special event handler
|
1889 |
+
// Only use addEventListener/attachEvent if the special
|
1890 |
+
// events handler returns false
|
1891 |
+
if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
|
1892 |
+
// Bind the global event handler to the element
|
1893 |
+
if (elem.addEventListener)
|
1894 |
+
elem.addEventListener(type, handle, false);
|
1895 |
+
else if (elem.attachEvent)
|
1896 |
+
elem.attachEvent("on" + type, handle);
|
1897 |
+
}
|
1898 |
+
}
|
1899 |
+
|
1900 |
+
// Add the function to the element's handler list
|
1901 |
+
handlers[handler.guid] = handler;
|
1902 |
+
|
1903 |
+
// Keep track of which events have been used, for global triggering
|
1904 |
+
jQuery.event.global[type] = true;
|
1905 |
+
});
|
1906 |
+
|
1907 |
+
// Nullify elem to prevent memory leaks in IE
|
1908 |
+
elem = null;
|
1909 |
+
},
|
1910 |
+
|
1911 |
+
guid: 1,
|
1912 |
+
global: {},
|
1913 |
+
|
1914 |
+
// Detach an event or set of events from an element
|
1915 |
+
remove: function(elem, types, handler) {
|
1916 |
+
// don't do events on text and comment nodes
|
1917 |
+
if ( elem.nodeType == 3 || elem.nodeType == 8 )
|
1918 |
+
return;
|
1919 |
+
|
1920 |
+
var events = jQuery.data(elem, "events"), ret, index;
|
1921 |
+
|
1922 |
+
if ( events ) {
|
1923 |
+
// Unbind all events for the element
|
1924 |
+
if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
|
1925 |
+
for ( var type in events )
|
1926 |
+
this.remove( elem, type + (types || "") );
|
1927 |
+
else {
|
1928 |
+
// types is actually an event object here
|
1929 |
+
if ( types.type ) {
|
1930 |
+
handler = types.handler;
|
1931 |
+
types = types.type;
|
1932 |
+
}
|
1933 |
+
|
1934 |
+
// Handle multiple events seperated by a space
|
1935 |
+
// jQuery(...).unbind("mouseover mouseout", fn);
|
1936 |
+
jQuery.each(types.split(/\s+/), function(index, type){
|
1937 |
+
// Namespaced event handlers
|
1938 |
+
var parts = type.split(".");
|
1939 |
+
type = parts[0];
|
1940 |
+
|
1941 |
+
if ( events[type] ) {
|
1942 |
+
// remove the given handler for the given type
|
1943 |
+
if ( handler )
|
1944 |
+
delete events[type][handler.guid];
|
1945 |
+
|
1946 |
+
// remove all handlers for the given type
|
1947 |
+
else
|
1948 |
+
for ( handler in events[type] )
|
1949 |
+
// Handle the removal of namespaced events
|
1950 |
+
if ( !parts[1] || events[type][handler].type == parts[1] )
|
1951 |
+
delete events[type][handler];
|
1952 |
+
|
1953 |
+
// remove generic event handler if no more handlers exist
|
1954 |
+
for ( ret in events[type] ) break;
|
1955 |
+
if ( !ret ) {
|
1956 |
+
if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
|
1957 |
+
if (elem.removeEventListener)
|
1958 |
+
elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
|
1959 |
+
else if (elem.detachEvent)
|
1960 |
+
elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
|
1961 |
+
}
|
1962 |
+
ret = null;
|
1963 |
+
delete events[type];
|
1964 |
+
}
|
1965 |
+
}
|
1966 |
+
});
|
1967 |
+
}
|
1968 |
+
|
1969 |
+
// Remove the expando if it's no longer used
|
1970 |
+
for ( ret in events ) break;
|
1971 |
+
if ( !ret ) {
|
1972 |
+
var handle = jQuery.data( elem, "handle" );
|
1973 |
+
if ( handle ) handle.elem = null;
|
1974 |
+
jQuery.removeData( elem, "events" );
|
1975 |
+
jQuery.removeData( elem, "handle" );
|
1976 |
+
}
|
1977 |
+
}
|
1978 |
+
},
|
1979 |
+
|
1980 |
+
trigger: function(type, data, elem, donative, extra) {
|
1981 |
+
// Clone the incoming data, if any
|
1982 |
+
data = jQuery.makeArray(data || []);
|
1983 |
+
|
1984 |
+
if ( type.indexOf("!") >= 0 ) {
|
1985 |
+
type = type.slice(0, -1);
|
1986 |
+
var exclusive = true;
|
1987 |
+
}
|
1988 |
+
|
1989 |
+
// Handle a global trigger
|
1990 |
+
if ( !elem ) {
|
1991 |
+
// Only trigger if we've ever bound an event for it
|
1992 |
+
if ( this.global[type] )
|
1993 |
+
jQuery("*").add([window, document]).trigger(type, data);
|
1994 |
+
|
1995 |
+
// Handle triggering a single element
|
1996 |
+
} else {
|
1997 |
+
// don't do events on text and comment nodes
|
1998 |
+
if ( elem.nodeType == 3 || elem.nodeType == 8 )
|
1999 |
+
return undefined;
|
2000 |
+
|
2001 |
+
var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
|
2002 |
+
// Check to see if we need to provide a fake event, or not
|
2003 |
+
event = !data[0] || !data[0].preventDefault;
|
2004 |
+
|
2005 |
+
// Pass along a fake event
|
2006 |
+
if ( event )
|
2007 |
+
data.unshift( this.fix({ type: type, target: elem }) );
|
2008 |
+
|
2009 |
+
// Enforce the right trigger type
|
2010 |
+
data[0].type = type;
|
2011 |
+
if ( exclusive )
|
2012 |
+
data[0].exclusive = true;
|
2013 |
+
|
2014 |
+
// Trigger the event
|
2015 |
+
if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
|
2016 |
+
val = jQuery.data(elem, "handle").apply( elem, data );
|
2017 |
+
|
2018 |
+
// Handle triggering native .onfoo handlers
|
2019 |
+
if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
|
2020 |
+
val = false;
|
2021 |
+
|
2022 |
+
// Extra functions don't get the custom event object
|
2023 |
+
if ( event )
|
2024 |
+
data.shift();
|
2025 |
+
|
2026 |
+
// Handle triggering of extra function
|
2027 |
+
if ( extra && jQuery.isFunction( extra ) ) {
|
2028 |
+
// call the extra function and tack the current return value on the end for possible inspection
|
2029 |
+
ret = extra.apply( elem, val == null ? data : data.concat( val ) );
|
2030 |
+
// if anything is returned, give it precedence and have it overwrite the previous value
|
2031 |
+
if (ret !== undefined)
|
2032 |
+
val = ret;
|
2033 |
+
}
|
2034 |
+
|
2035 |
+
// Trigger the native events (except for clicks on links)
|
2036 |
+
if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
|
2037 |
+
this.triggered = true;
|
2038 |
+
try {
|
2039 |
+
elem[ type ]();
|
2040 |
+
// prevent IE from throwing an error for some hidden elements
|
2041 |
+
} catch (e) {}
|
2042 |
+
}
|
2043 |
+
|
2044 |
+
this.triggered = false;
|
2045 |
+
}
|
2046 |
+
|
2047 |
+
return val;
|
2048 |
+
},
|
2049 |
+
|
2050 |
+
handle: function(event) {
|
2051 |
+
// returned undefined or false
|
2052 |
+
var val;
|
2053 |
+
|
2054 |
+
// Empty object is for triggered events with no data
|
2055 |
+
event = jQuery.event.fix( event || window.event || {} );
|
2056 |
+
|
2057 |
+
// Namespaced event handlers
|
2058 |
+
var parts = event.type.split(".");
|
2059 |
+
event.type = parts[0];
|
2060 |
+
|
2061 |
+
var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
|
2062 |
+
args.unshift( event );
|
2063 |
+
|
2064 |
+
for ( var j in handlers ) {
|
2065 |
+
var handler = handlers[j];
|
2066 |
+
// Pass in a reference to the handler function itself
|
2067 |
+
// So that we can later remove it
|
2068 |
+
args[0].handler = handler;
|
2069 |
+
args[0].data = handler.data;
|
2070 |
+
|
2071 |
+
// Filter the functions by class
|
2072 |
+
if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) {
|
2073 |
+
var ret = handler.apply( this, args );
|
2074 |
+
|
2075 |
+
if ( val !== false )
|
2076 |
+
val = ret;
|
2077 |
+
|
2078 |
+
if ( ret === false ) {
|
2079 |
+
event.preventDefault();
|
2080 |
+
event.stopPropagation();
|
2081 |
+
}
|
2082 |
+
}
|
2083 |
+
}
|
2084 |
+
|
2085 |
+
// Clean up added properties in IE to prevent memory leak
|
2086 |
+
if (jQuery.browser.msie)
|
2087 |
+
event.target = event.preventDefault = event.stopPropagation =
|
2088 |
+
event.handler = event.data = null;
|
2089 |
+
|
2090 |
+
return val;
|
2091 |
+
},
|
2092 |
+
|
2093 |
+
fix: function(event) {
|
2094 |
+
// store a copy of the original event object
|
2095 |
+
// and clone to set read-only properties
|
2096 |
+
var originalEvent = event;
|
2097 |
+
event = jQuery.extend({}, originalEvent);
|
2098 |
+
|
2099 |
+
// add preventDefault and stopPropagation since
|
2100 |
+
// they will not work on the clone
|
2101 |
+
event.preventDefault = function() {
|
2102 |
+
// if preventDefault exists run it on the original event
|
2103 |
+
if (originalEvent.preventDefault)
|
2104 |
+
originalEvent.preventDefault();
|
2105 |
+
// otherwise set the returnValue property of the original event to false (IE)
|
2106 |
+
originalEvent.returnValue = false;
|
2107 |
+
};
|
2108 |
+
event.stopPropagation = function() {
|
2109 |
+
// if stopPropagation exists run it on the original event
|
2110 |
+
if (originalEvent.stopPropagation)
|
2111 |
+
originalEvent.stopPropagation();
|
2112 |
+
// otherwise set the cancelBubble property of the original event to true (IE)
|
2113 |
+
originalEvent.cancelBubble = true;
|
2114 |
+
};
|
2115 |
+
|
2116 |
+
// Fix target property, if necessary
|
2117 |
+
if ( !event.target )
|
2118 |
+
event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
|
2119 |
+
|
2120 |
+
// check if target is a textnode (safari)
|
2121 |
+
if ( event.target.nodeType == 3 )
|
2122 |
+
event.target = originalEvent.target.parentNode;
|
2123 |
+
|
2124 |
+
// Add relatedTarget, if necessary
|
2125 |
+
if ( !event.relatedTarget && event.fromElement )
|
2126 |
+
event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
|
2127 |
+
|
2128 |
+
// Calculate pageX/Y if missing and clientX/Y available
|
2129 |
+
if ( event.pageX == null && event.clientX != null ) {
|
2130 |
+
var doc = document.documentElement, body = document.body;
|
2131 |
+
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
|
2132 |
+
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
|
2133 |
+
}
|
2134 |
+
|
2135 |
+
// Add which for key events
|
2136 |
+
if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
|
2137 |
+
event.which = event.charCode || event.keyCode;
|
2138 |
+
|
2139 |
+
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
|
2140 |
+
if ( !event.metaKey && event.ctrlKey )
|
2141 |
+
event.metaKey = event.ctrlKey;
|
2142 |
+
|
2143 |
+
// Add which for click: 1 == left; 2 == middle; 3 == right
|
2144 |
+
// Note: button is not normalized, so don't use it
|
2145 |
+
if ( !event.which && event.button )
|
2146 |
+
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
|
2147 |
+
|
2148 |
+
return event;
|
2149 |
+
},
|
2150 |
+
|
2151 |
+
special: {
|
2152 |
+
ready: {
|
2153 |
+
setup: function() {
|
2154 |
+
// Make sure the ready event is setup
|
2155 |
+
bindReady();
|
2156 |
+
return;
|
2157 |
+
},
|
2158 |
+
|
2159 |
+
teardown: function() { return; }
|
2160 |
+
},
|
2161 |
+
|
2162 |
+
mouseenter: {
|
2163 |
+
setup: function() {
|
2164 |
+
if ( jQuery.browser.msie ) return false;
|
2165 |
+
jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
|
2166 |
+
return true;
|
2167 |
+
},
|
2168 |
+
|
2169 |
+
teardown: function() {
|
2170 |
+
if ( jQuery.browser.msie ) return false;
|
2171 |
+
jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
|
2172 |
+
return true;
|
2173 |
+
},
|
2174 |
+
|
2175 |
+
handler: function(event) {
|
2176 |
+
// If we actually just moused on to a sub-element, ignore it
|
2177 |
+
if ( withinElement(event, this) ) return true;
|
2178 |
+
// Execute the right handlers by setting the event type to mouseenter
|
2179 |
+
arguments[0].type = "mouseenter";
|
2180 |
+
return jQuery.event.handle.apply(this, arguments);
|
2181 |
+
}
|
2182 |
+
},
|
2183 |
+
|
2184 |
+
mouseleave: {
|
2185 |
+
setup: function() {
|
2186 |
+
if ( jQuery.browser.msie ) return false;
|
2187 |
+
jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
|
2188 |
+
return true;
|
2189 |
+
},
|
2190 |
+
|
2191 |
+
teardown: function() {
|
2192 |
+
if ( jQuery.browser.msie ) return false;
|
2193 |
+
jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
|
2194 |
+
return true;
|
2195 |
+
},
|
2196 |
+
|
2197 |
+
handler: function(event) {
|
2198 |
+
// If we actually just moused on to a sub-element, ignore it
|
2199 |
+
if ( withinElement(event, this) ) return true;
|
2200 |
+
// Execute the right handlers by setting the event type to mouseleave
|
2201 |
+
arguments[0].type = "mouseleave";
|
2202 |
+
return jQuery.event.handle.apply(this, arguments);
|
2203 |
+
}
|
2204 |
+
}
|
2205 |
+
}
|
2206 |
+
};
|
2207 |
+
|
2208 |
+
jQuery.fn.extend({
|
2209 |
+
bind: function( type, data, fn ) {
|
2210 |
+
return type == "unload" ? this.one(type, data, fn) : this.each(function(){
|
2211 |
+
jQuery.event.add( this, type, fn || data, fn && data );
|
2212 |
+
});
|
2213 |
+
},
|
2214 |
+
|
2215 |
+
one: function( type, data, fn ) {
|
2216 |
+
return this.each(function(){
|
2217 |
+
jQuery.event.add( this, type, function(event) {
|
2218 |
+
jQuery(this).unbind(event);
|
2219 |
+
return (fn || data).apply( this, arguments);
|
2220 |
+
}, fn && data);
|
2221 |
+
});
|
2222 |
+
},
|
2223 |
+
|
2224 |
+
unbind: function( type, fn ) {
|
2225 |
+
return this.each(function(){
|
2226 |
+
jQuery.event.remove( this, type, fn );
|
2227 |
+
});
|
2228 |
+
},
|
2229 |
+
|
2230 |
+
trigger: function( type, data, fn ) {
|
2231 |
+
return this.each(function(){
|
2232 |
+
jQuery.event.trigger( type, data, this, true, fn );
|
2233 |
+
});
|
2234 |
+
},
|
2235 |
+
|
2236 |
+
triggerHandler: function( type, data, fn ) {
|
2237 |
+
if ( this[0] )
|
2238 |
+
return jQuery.event.trigger( type, data, this[0], false, fn );
|
2239 |
+
return undefined;
|
2240 |
+
},
|
2241 |
+
|
2242 |
+
toggle: function() {
|
2243 |
+
// Save reference to arguments for access in closure
|
2244 |
+
var args = arguments;
|
2245 |
+
|
2246 |
+
return this.click(function(event) {
|
2247 |
+
// Figure out which function to execute
|
2248 |
+
this.lastToggle = 0 == this.lastToggle ? 1 : 0;
|
2249 |
+
|
2250 |
+
// Make sure that clicks stop
|
2251 |
+
event.preventDefault();
|
2252 |
+
|
2253 |
+
// and execute the function
|
2254 |
+
return args[this.lastToggle].apply( this, arguments ) || false;
|
2255 |
+
});
|
2256 |
+
},
|
2257 |
+
|
2258 |
+
hover: function(fnOver, fnOut) {
|
2259 |
+
return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
|
2260 |
+
},
|
2261 |
+
|
2262 |
+
ready: function(fn) {
|
2263 |
+
// Attach the listeners
|
2264 |
+
bindReady();
|
2265 |
+
|
2266 |
+
// If the DOM is already ready
|
2267 |
+
if ( jQuery.isReady )
|
2268 |
+
// Execute the function immediately
|
2269 |
+
fn.call( document, jQuery );
|
2270 |
+
|
2271 |
+
// Otherwise, remember the function for later
|
2272 |
+
else
|
2273 |
+
// Add the function to the wait list
|
2274 |
+
jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
|
2275 |
+
|
2276 |
+
return this;
|
2277 |
+
}
|
2278 |
+
});
|
2279 |
+
|
2280 |
+
jQuery.extend({
|
2281 |
+
isReady: false,
|
2282 |
+
readyList: [],
|
2283 |
+
// Handle when the DOM is ready
|
2284 |
+
ready: function() {
|
2285 |
+
// Make sure that the DOM is not already loaded
|
2286 |
+
if ( !jQuery.isReady ) {
|
2287 |
+
// Remember that the DOM is ready
|
2288 |
+
jQuery.isReady = true;
|
2289 |
+
|
2290 |
+
// If there are functions bound, to execute
|
2291 |
+
if ( jQuery.readyList ) {
|
2292 |
+
// Execute all of them
|
2293 |
+
jQuery.each( jQuery.readyList, function(){
|
2294 |
+
this.apply( document );
|
2295 |
+
});
|
2296 |
+
|
2297 |
+
// Reset the list of functions
|
2298 |
+
jQuery.readyList = null;
|
2299 |
+
}
|
2300 |
+
|
2301 |
+
// Trigger any bound ready events
|
2302 |
+
jQuery(document).triggerHandler("ready");
|
2303 |
+
}
|
2304 |
+
}
|
2305 |
+
});
|
2306 |
+
|
2307 |
+
var readyBound = false;
|
2308 |
+
|
2309 |
+
function bindReady(){
|
2310 |
+
if ( readyBound ) return;
|
2311 |
+
readyBound = true;
|
2312 |
+
|
2313 |
+
// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
|
2314 |
+
if ( document.addEventListener && !jQuery.browser.opera)
|
2315 |
+
// Use the handy event callback
|
2316 |
+
document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
|
2317 |
+
|
2318 |
+
// If IE is used and is not in a frame
|
2319 |
+
// Continually check to see if the document is ready
|
2320 |
+
if ( jQuery.browser.msie && window == top ) (function(){
|
2321 |
+
if (jQuery.isReady) return;
|
2322 |
+
try {
|
2323 |
+
// If IE is used, use the trick by Diego Perini
|
2324 |
+
// http://javascript.nwbox.com/IEContentLoaded/
|
2325 |
+
document.documentElement.doScroll("left");
|
2326 |
+
} catch( error ) {
|
2327 |
+
setTimeout( arguments.callee, 0 );
|
2328 |
+
return;
|
2329 |
+
}
|
2330 |
+
// and execute any waiting functions
|
2331 |
+
jQuery.ready();
|
2332 |
+
})();
|
2333 |
+
|
2334 |
+
if ( jQuery.browser.opera )
|
2335 |
+
document.addEventListener( "DOMContentLoaded", function () {
|
2336 |
+
if (jQuery.isReady) return;
|
2337 |
+
for (var i = 0; i < document.styleSheets.length; i++)
|
2338 |
+
if (document.styleSheets[i].disabled) {
|
2339 |
+
setTimeout( arguments.callee, 0 );
|
2340 |
+
return;
|
2341 |
+
}
|
2342 |
+
// and execute any waiting functions
|
2343 |
+
jQuery.ready();
|
2344 |
+
}, false);
|
2345 |
+
|
2346 |
+
if ( jQuery.browser.safari ) {
|
2347 |
+
var numStyles;
|
2348 |
+
(function(){
|
2349 |
+
if (jQuery.isReady) return;
|
2350 |
+
if ( document.readyState != "loaded" && document.readyState != "complete" ) {
|
2351 |
+
setTimeout( arguments.callee, 0 );
|
2352 |
+
return;
|
2353 |
+
}
|
2354 |
+
if ( numStyles === undefined )
|
2355 |
+
numStyles = jQuery("style, link[rel=stylesheet]").length;
|
2356 |
+
if ( document.styleSheets.length != numStyles ) {
|
2357 |
+
setTimeout( arguments.callee, 0 );
|
2358 |
+
return;
|
2359 |
+
}
|
2360 |
+
// and execute any waiting functions
|
2361 |
+
jQuery.ready();
|
2362 |
+
})();
|
2363 |
+
}
|
2364 |
+
|
2365 |
+
// A fallback to window.onload, that will always work
|
2366 |
+
jQuery.event.add( window, "load", jQuery.ready );
|
2367 |
+
}
|
2368 |
+
|
2369 |
+
jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
|
2370 |
+
"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
|
2371 |
+
"submit,keydown,keypress,keyup,error").split(","), function(i, name){
|
2372 |
+
|
2373 |
+
// Handle event binding
|
2374 |
+
jQuery.fn[name] = function(fn){
|
2375 |
+
return fn ? this.bind(name, fn) : this.trigger(name);
|
2376 |
+
};
|
2377 |
+
});
|
2378 |
+
|
2379 |
+
// Checks if an event happened on an element within another element
|
2380 |
+
// Used in jQuery.event.special.mouseenter and mouseleave handlers
|
2381 |
+
var withinElement = function(event, elem) {
|
2382 |
+
// Check if mouse(over|out) are still within the same parent element
|
2383 |
+
var parent = event.relatedTarget;
|
2384 |
+
// Traverse up the tree
|
2385 |
+
while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
|
2386 |
+
// Return true if we actually just moused on to a sub-element
|
2387 |
+
return parent == elem;
|
2388 |
+
};
|
2389 |
+
|
2390 |
+
// Prevent memory leaks in IE
|
2391 |
+
// And prevent errors on refresh with events like mouseover in other browsers
|
2392 |
+
// Window isn't included so as not to unbind existing unload events
|
2393 |
+
jQuery(window).bind("unload", function() {
|
2394 |
+
jQuery("*").add(document).unbind();
|
2395 |
+
});
|
2396 |
+
jQuery.fn.extend({
|
2397 |
+
load: function( url, params, callback ) {
|
2398 |
+
if ( jQuery.isFunction( url ) )
|
2399 |
+
return this.bind("load", url);
|
2400 |
+
|
2401 |
+
var off = url.indexOf(" ");
|
2402 |
+
if ( off >= 0 ) {
|
2403 |
+
var selector = url.slice(off, url.length);
|
2404 |
+
url = url.slice(0, off);
|
2405 |
+
}
|
2406 |
+
|
2407 |
+
callback = callback || function(){};
|
2408 |
+
|
2409 |
+
// Default to a GET request
|
2410 |
+
var type = "GET";
|
2411 |
+
|
2412 |
+
// If the second parameter was provided
|
2413 |
+
if ( params )
|
2414 |
+
// If it's a function
|
2415 |
+
if ( jQuery.isFunction( params ) ) {
|
2416 |
+
// We assume that it's the callback
|
2417 |
+
callback = params;
|
2418 |
+
params = null;
|
2419 |
+
|
2420 |
+
// Otherwise, build a param string
|
2421 |
+
} else {
|
2422 |
+
params = jQuery.param( params );
|
2423 |
+
type = "POST";
|
2424 |
+
}
|
2425 |
+
|
2426 |
+
var self = this;
|
2427 |
+
|
2428 |
+
// Request the remote document
|
2429 |
+
jQuery.ajax({
|
2430 |
+
url: url,
|
2431 |
+
type: type,
|
2432 |
+
dataType: "html",
|
2433 |
+
data: params,
|
2434 |
+
complete: function(res, status){
|
2435 |
+
// If successful, inject the HTML into all the matched elements
|
2436 |
+
if ( status == "success" || status == "notmodified" )
|
2437 |
+
// See if a selector was specified
|
2438 |
+
self.html( selector ?
|
2439 |
+
// Create a dummy div to hold the results
|
2440 |
+
jQuery("<div/>")
|
2441 |
+
// inject the contents of the document in, removing the scripts
|
2442 |
+
// to avoid any 'Permission Denied' errors in IE
|
2443 |
+
.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
|
2444 |
+
|
2445 |
+
// Locate the specified elements
|
2446 |
+
.find(selector) :
|
2447 |
+
|
2448 |
+
// If not, just inject the full result
|
2449 |
+
res.responseText );
|
2450 |
+
|
2451 |
+
self.each( callback, [res.responseText, status, res] );
|
2452 |
+
}
|
2453 |
+
});
|
2454 |
+
return this;
|
2455 |
+
},
|
2456 |
+
|
2457 |
+
serialize: function() {
|
2458 |
+
return jQuery.param(this.serializeArray());
|
2459 |
+
},
|
2460 |
+
serializeArray: function() {
|
2461 |
+
return this.map(function(){
|
2462 |
+
return jQuery.nodeName(this, "form") ?
|
2463 |
+
jQuery.makeArray(this.elements) : this;
|
2464 |
+
})
|
2465 |
+
.filter(function(){
|
2466 |
+
return this.name && !this.disabled &&
|
2467 |
+
(this.checked || /select|textarea/i.test(this.nodeName) ||
|
2468 |
+
/text|hidden|password/i.test(this.type));
|
2469 |
+
})
|
2470 |
+
.map(function(i, elem){
|
2471 |
+
var val = jQuery(this).val();
|
2472 |
+
return val == null ? null :
|
2473 |
+
val.constructor == Array ?
|
2474 |
+
jQuery.map( val, function(val, i){
|
2475 |
+
return {name: elem.name, value: val};
|
2476 |
+
}) :
|
2477 |
+
{name: elem.name, value: val};
|
2478 |
+
}).get();
|
2479 |
+
}
|
2480 |
+
});
|
2481 |
+
|
2482 |
+
// Attach a bunch of functions for handling common AJAX events
|
2483 |
+
jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
|
2484 |
+
jQuery.fn[o] = function(f){
|
2485 |
+
return this.bind(o, f);
|
2486 |
+
};
|
2487 |
+
});
|
2488 |
+
|
2489 |
+
var jsc = (new Date).getTime();
|
2490 |
+
|
2491 |
+
jQuery.extend({
|
2492 |
+
get: function( url, data, callback, type ) {
|
2493 |
+
// shift arguments if data argument was ommited
|
2494 |
+
if ( jQuery.isFunction( data ) ) {
|
2495 |
+
callback = data;
|
2496 |
+
data = null;
|
2497 |
+
}
|
2498 |
+
|
2499 |
+
return jQuery.ajax({
|
2500 |
+
type: "GET",
|
2501 |
+
url: url,
|
2502 |
+
data: data,
|
2503 |
+
success: callback,
|
2504 |
+
dataType: type
|
2505 |
+
});
|
2506 |
+
},
|
2507 |
+
|
2508 |
+
getScript: function( url, callback ) {
|
2509 |
+
return jQuery.get(url, null, callback, "script");
|
2510 |
+
},
|
2511 |
+
|
2512 |
+
getJSON: function( url, data, callback ) {
|
2513 |
+
return jQuery.get(url, data, callback, "json");
|
2514 |
+
},
|
2515 |
+
|
2516 |
+
post: function( url, data, callback, type ) {
|
2517 |
+
if ( jQuery.isFunction( data ) ) {
|
2518 |
+
callback = data;
|
2519 |
+
data = {};
|
2520 |
+
}
|
2521 |
+
|
2522 |
+
return jQuery.ajax({
|
2523 |
+
type: "POST",
|
2524 |
+
url: url,
|
2525 |
+
data: data,
|
2526 |
+
success: callback,
|
2527 |
+
dataType: type
|
2528 |
+
});
|
2529 |
+
},
|
2530 |
+
|
2531 |
+
ajaxSetup: function( settings ) {
|
2532 |
+
jQuery.extend( jQuery.ajaxSettings, settings );
|
2533 |
+
},
|
2534 |
+
|
2535 |
+
ajaxSettings: {
|
2536 |
+
global: true,
|
2537 |
+
type: "GET",
|
2538 |
+
timeout: 0,
|
2539 |
+
contentType: "application/x-www-form-urlencoded",
|
2540 |
+
processData: true,
|
2541 |
+
async: true,
|
2542 |
+
data: null,
|
2543 |
+
username: null,
|
2544 |
+
password: null,
|
2545 |
+
accepts: {
|
2546 |
+
xml: "application/xml, text/xml",
|
2547 |
+
html: "text/html",
|
2548 |
+
script: "text/javascript, application/javascript",
|
2549 |
+
json: "application/json, text/javascript",
|
2550 |
+
text: "text/plain",
|
2551 |
+
_default: "*/*"
|
2552 |
+
}
|
2553 |
+
},
|
2554 |
+
|
2555 |
+
// Last-Modified header cache for next request
|
2556 |
+
lastModified: {},
|
2557 |
+
|
2558 |
+
ajax: function( s ) {
|
2559 |
+
var jsonp, jsre = /=\?(&|$)/g, status, data;
|
2560 |
+
|
2561 |
+
// Extend the settings, but re-extend 's' so that it can be
|
2562 |
+
// checked again later (in the test suite, specifically)
|
2563 |
+
s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
|
2564 |
+
|
2565 |
+
// convert data if not already a string
|
2566 |
+
if ( s.data && s.processData && typeof s.data != "string" )
|
2567 |
+
s.data = jQuery.param(s.data);
|
2568 |
+
|
2569 |
+
// Handle JSONP Parameter Callbacks
|
2570 |
+
if ( s.dataType == "jsonp" ) {
|
2571 |
+
if ( s.type.toLowerCase() == "get" ) {
|
2572 |
+
if ( !s.url.match(jsre) )
|
2573 |
+
s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
|
2574 |
+
} else if ( !s.data || !s.data.match(jsre) )
|
2575 |
+
s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
|
2576 |
+
s.dataType = "json";
|
2577 |
+
}
|
2578 |
+
|
2579 |
+
// Build temporary JSONP function
|
2580 |
+
if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
|
2581 |
+
jsonp = "jsonp" + jsc++;
|
2582 |
+
|
2583 |
+
// Replace the =? sequence both in the query string and the data
|
2584 |
+
if ( s.data )
|
2585 |
+
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
|
2586 |
+
s.url = s.url.replace(jsre, "=" + jsonp + "$1");
|
2587 |
+
|
2588 |
+
// We need to make sure
|
2589 |
+
// that a JSONP style response is executed properly
|
2590 |
+
s.dataType = "script";
|
2591 |
+
|
2592 |
+
// Handle JSONP-style loading
|
2593 |
+
window[ jsonp ] = function(tmp){
|
2594 |
+
data = tmp;
|
2595 |
+
success();
|
2596 |
+
complete();
|
2597 |
+
// Garbage collect
|
2598 |
+
window[ jsonp ] = undefined;
|
2599 |
+
try{ delete window[ jsonp ]; } catch(e){}
|
2600 |
+
if ( head )
|
2601 |
+
head.removeChild( script );
|
2602 |
+
};
|
2603 |
+
}
|
2604 |
+
|
2605 |
+
if ( s.dataType == "script" && s.cache == null )
|
2606 |
+
s.cache = false;
|
2607 |
+
|
2608 |
+
if ( s.cache === false && s.type.toLowerCase() == "get" ) {
|
2609 |
+
var ts = (new Date()).getTime();
|
2610 |
+
// try replacing _= if it is there
|
2611 |
+
var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
|
2612 |
+
// if nothing was replaced, add timestamp to the end
|
2613 |
+
s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
|
2614 |
+
}
|
2615 |
+
|
2616 |
+
// If data is available, append data to url for get requests
|
2617 |
+
if ( s.data && s.type.toLowerCase() == "get" ) {
|
2618 |
+
s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
|
2619 |
+
|
2620 |
+
// IE likes to send both get and post data, prevent this
|
2621 |
+
s.data = null;
|
2622 |
+
}
|
2623 |
+
|
2624 |
+
// Watch for a new set of requests
|
2625 |
+
if ( s.global && ! jQuery.active++ )
|
2626 |
+
jQuery.event.trigger( "ajaxStart" );
|
2627 |
+
|
2628 |
+
// If we're requesting a remote document
|
2629 |
+
// and trying to load JSON or Script with a GET
|
2630 |
+
if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) {
|
2631 |
+
var head = document.getElementsByTagName("head")[0];
|
2632 |
+
var script = document.createElement("script");
|
2633 |
+
script.src = s.url;
|
2634 |
+
if (s.scriptCharset)
|
2635 |
+
script.charset = s.scriptCharset;
|
2636 |
+
|
2637 |
+
// Handle Script loading
|
2638 |
+
if ( !jsonp ) {
|
2639 |
+
var done = false;
|
2640 |
+
|
2641 |
+
// Attach handlers for all browsers
|
2642 |
+
script.onload = script.onreadystatechange = function(){
|
2643 |
+
if ( !done && (!this.readyState ||
|
2644 |
+
this.readyState == "loaded" || this.readyState == "complete") ) {
|
2645 |
+
done = true;
|
2646 |
+
success();
|
2647 |
+
complete();
|
2648 |
+
head.removeChild( script );
|
2649 |
+
}
|
2650 |
+
};
|
2651 |
+
}
|
2652 |
+
|
2653 |
+
head.appendChild(script);
|
2654 |
+
|
2655 |
+
// We handle everything using the script element injection
|
2656 |
+
return undefined;
|
2657 |
+
}
|
2658 |
+
|
2659 |
+
var requestDone = false;
|
2660 |
+
|
2661 |
+
// Create the request object; Microsoft failed to properly
|
2662 |
+
// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
|
2663 |
+
var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
|
2664 |
+
|
2665 |
+
// Open the socket
|
2666 |
+
xml.open(s.type, s.url, s.async, s.username, s.password);
|
2667 |
+
|
2668 |
+
// Need an extra try/catch for cross domain requests in Firefox 3
|
2669 |
+
try {
|
2670 |
+
// Set the correct header, if data is being sent
|
2671 |
+
if ( s.data )
|
2672 |
+
xml.setRequestHeader("Content-Type", s.contentType);
|
2673 |
+
|
2674 |
+
// Set the If-Modified-Since header, if ifModified mode.
|
2675 |
+
if ( s.ifModified )
|
2676 |
+
xml.setRequestHeader("If-Modified-Since",
|
2677 |
+
jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
|
2678 |
+
|
2679 |
+
// Set header so the called script knows that it's an XMLHttpRequest
|
2680 |
+
xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
|
2681 |
+
|
2682 |
+
// Set the Accepts header for the server, depending on the dataType
|
2683 |
+
xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
|
2684 |
+
s.accepts[ s.dataType ] + ", */*" :
|
2685 |
+
s.accepts._default );
|
2686 |
+
} catch(e){}
|
2687 |
+
|
2688 |
+
// Allow custom headers/mimetypes
|
2689 |
+
if ( s.beforeSend )
|
2690 |
+
s.beforeSend(xml);
|
2691 |
+
|
2692 |
+
if ( s.global )
|
2693 |
+
jQuery.event.trigger("ajaxSend", [xml, s]);
|
2694 |
+
|
2695 |
+
// Wait for a response to come back
|
2696 |
+
var onreadystatechange = function(isTimeout){
|
2697 |
+
// The transfer is complete and the data is available, or the request timed out
|
2698 |
+
if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
|
2699 |
+
requestDone = true;
|
2700 |
+
|
2701 |
+
// clear poll interval
|
2702 |
+
if (ival) {
|
2703 |
+
clearInterval(ival);
|
2704 |
+
ival = null;
|
2705 |
+
}
|
2706 |
+
|
2707 |
+
status = isTimeout == "timeout" && "timeout" ||
|
2708 |
+
!jQuery.httpSuccess( xml ) && "error" ||
|
2709 |
+
s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
|
2710 |
+
"success";
|
2711 |
+
|
2712 |
+
if ( status == "success" ) {
|
2713 |
+
// Watch for, and catch, XML document parse errors
|
2714 |
+
try {
|
2715 |
+
// process the data (runs the xml through httpData regardless of callback)
|
2716 |
+
data = jQuery.httpData( xml, s.dataType );
|
2717 |
+
} catch(e) {
|
2718 |
+
status = "parsererror";
|
2719 |
+
}
|
2720 |
+
}
|
2721 |
+
|
2722 |
+
// Make sure that the request was successful or notmodified
|
2723 |
+
if ( status == "success" ) {
|
2724 |
+
// Cache Last-Modified header, if ifModified mode.
|
2725 |
+
var modRes;
|
2726 |
+
try {
|
2727 |
+
modRes = xml.getResponseHeader("Last-Modified");
|
2728 |
+
} catch(e) {} // swallow exception thrown by FF if header is not available
|
2729 |
+
|
2730 |
+
if ( s.ifModified && modRes )
|
2731 |
+
jQuery.lastModified[s.url] = modRes;
|
2732 |
+
|
2733 |
+
// JSONP handles its own success callback
|
2734 |
+
if ( !jsonp )
|
2735 |
+
success();
|
2736 |
+
} else
|
2737 |
+
jQuery.handleError(s, xml, status);
|
2738 |
+
|
2739 |
+
// Fire the complete handlers
|
2740 |
+
complete();
|
2741 |
+
|
2742 |
+
// Stop memory leaks
|
2743 |
+
if ( s.async )
|
2744 |
+
xml = null;
|
2745 |
+
}
|
2746 |
+
};
|
2747 |
+
|
2748 |
+
if ( s.async ) {
|
2749 |
+
// don't attach the handler to the request, just poll it instead
|
2750 |
+
var ival = setInterval(onreadystatechange, 13);
|
2751 |
+
|
2752 |
+
// Timeout checker
|
2753 |
+
if ( s.timeout > 0 )
|
2754 |
+
setTimeout(function(){
|
2755 |
+
// Check to see if the request is still happening
|
2756 |
+
if ( xml ) {
|
2757 |
+
// Cancel the request
|
2758 |
+
xml.abort();
|
2759 |
+
|
2760 |
+
if( !requestDone )
|
2761 |
+
onreadystatechange( "timeout" );
|
2762 |
+
}
|
2763 |
+
}, s.timeout);
|
2764 |
+
}
|
2765 |
+
|
2766 |
+
// Send the data
|
2767 |
+
try {
|
2768 |
+
xml.send(s.data);
|
2769 |
+
} catch(e) {
|
2770 |
+
jQuery.handleError(s, xml, null, e);
|
2771 |
+
}
|
2772 |
+
|
2773 |
+
// firefox 1.5 doesn't fire statechange for sync requests
|
2774 |
+
if ( !s.async )
|
2775 |
+
onreadystatechange();
|
2776 |
+
|
2777 |
+
function success(){
|
2778 |
+
// If a local callback was specified, fire it and pass it the data
|
2779 |
+
if ( s.success )
|
2780 |
+
s.success( data, status );
|
2781 |
+
|
2782 |
+
// Fire the global callback
|
2783 |
+
if ( s.global )
|
2784 |
+
jQuery.event.trigger( "ajaxSuccess", [xml, s] );
|
2785 |
+
}
|
2786 |
+
|
2787 |
+
function complete(){
|
2788 |
+
// Process result
|
2789 |
+
if ( s.complete )
|
2790 |
+
s.complete(xml, status);
|
2791 |
+
|
2792 |
+
// The request was completed
|
2793 |
+
if ( s.global )
|
2794 |
+
jQuery.event.trigger( "ajaxComplete", [xml, s] );
|
2795 |
+
|
2796 |
+
// Handle the global AJAX counter
|
2797 |
+
if ( s.global && ! --jQuery.active )
|
2798 |
+
jQuery.event.trigger( "ajaxStop" );
|
2799 |
+
}
|
2800 |
+
|
2801 |
+
// return XMLHttpRequest to allow aborting the request etc.
|
2802 |
+
return xml;
|
2803 |
+
},
|
2804 |
+
|
2805 |
+
handleError: function( s, xml, status, e ) {
|
2806 |
+
// If a local callback was specified, fire it
|
2807 |
+
if ( s.error ) s.error( xml, status, e );
|
2808 |
+
|
2809 |
+
// Fire the global callback
|
2810 |
+
if ( s.global )
|
2811 |
+
jQuery.event.trigger( "ajaxError", [xml, s, e] );
|
2812 |
+
},
|
2813 |
+
|
2814 |
+
// Counter for holding the number of active queries
|
2815 |
+
active: 0,
|
2816 |
+
|
2817 |
+
// Determines if an XMLHttpRequest was successful or not
|
2818 |
+
httpSuccess: function( r ) {
|
2819 |
+
try {
|
2820 |
+
// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
|
2821 |
+
return !r.status && location.protocol == "file:" ||
|
2822 |
+
( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
|
2823 |
+
jQuery.browser.safari && r.status == undefined;
|
2824 |
+
} catch(e){}
|
2825 |
+
return false;
|
2826 |
+
},
|
2827 |
+
|
2828 |
+
// Determines if an XMLHttpRequest returns NotModified
|
2829 |
+
httpNotModified: function( xml, url ) {
|
2830 |
+
try {
|
2831 |
+
var xmlRes = xml.getResponseHeader("Last-Modified");
|
2832 |
+
|
2833 |
+
// Firefox always returns 200. check Last-Modified date
|
2834 |
+
return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
|
2835 |
+
jQuery.browser.safari && xml.status == undefined;
|
2836 |
+
} catch(e){}
|
2837 |
+
return false;
|
2838 |
+
},
|
2839 |
+
|
2840 |
+
httpData: function( r, type ) {
|
2841 |
+
var ct = r.getResponseHeader("content-type");
|
2842 |
+
var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
|
2843 |
+
var data = xml ? r.responseXML : r.responseText;
|
2844 |
+
|
2845 |
+
if ( xml && data.documentElement.tagName == "parsererror" )
|
2846 |
+
throw "parsererror";
|
2847 |
+
|
2848 |
+
// If the type is "script", eval it in global context
|
2849 |
+
if ( type == "script" )
|
2850 |
+
jQuery.globalEval( data );
|
2851 |
+
|
2852 |
+
// Get the JavaScript object, if JSON is used.
|
2853 |
+
if ( type == "json" )
|
2854 |
+
data = eval("(" + data + ")");
|
2855 |
+
|
2856 |
+
return data;
|
2857 |
+
},
|
2858 |
+
|
2859 |
+
// Serialize an array of form elements or a set of
|
2860 |
+
// key/values into a query string
|
2861 |
+
param: function( a ) {
|
2862 |
+
var s = [];
|
2863 |
+
|
2864 |
+
// If an array was passed in, assume that it is an array
|
2865 |
+
// of form elements
|
2866 |
+
if ( a.constructor == Array || a.jquery )
|
2867 |
+
// Serialize the form elements
|
2868 |
+
jQuery.each( a, function(){
|
2869 |
+
s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
|
2870 |
+
});
|
2871 |
+
|
2872 |
+
// Otherwise, assume that it's an object of key/value pairs
|
2873 |
+
else
|
2874 |
+
// Serialize the key/values
|
2875 |
+
for ( var j in a )
|
2876 |
+
// If the value is an array then the key names need to be repeated
|
2877 |
+
if ( a[j] && a[j].constructor == Array )
|
2878 |
+
jQuery.each( a[j], function(){
|
2879 |
+
s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
|
2880 |
+
});
|
2881 |
+
else
|
2882 |
+
s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
|
2883 |
+
|
2884 |
+
// Return the resulting serialization
|
2885 |
+
return s.join("&").replace(/%20/g, "+");
|
2886 |
+
}
|
2887 |
+
|
2888 |
+
});
|
2889 |
+
jQuery.fn.extend({
|
2890 |
+
show: function(speed,callback){
|
2891 |
+
return speed ?
|
2892 |
+
this.animate({
|
2893 |
+
height: "show", width: "show", opacity: "show"
|
2894 |
+
}, speed, callback) :
|
2895 |
+
|
2896 |
+
this.filter(":hidden").each(function(){
|
2897 |
+
this.style.display = this.oldblock || "";
|
2898 |
+
if ( jQuery.css(this,"display") == "none" ) {
|
2899 |
+
var elem = jQuery("<" + this.tagName + " />").appendTo("body");
|
2900 |
+
this.style.display = elem.css("display");
|
2901 |
+
// handle an edge condition where css is - div { display:none; } or similar
|
2902 |
+
if (this.style.display == "none")
|
2903 |
+
this.style.display = "block";
|
2904 |
+
elem.remove();
|
2905 |
+
}
|
2906 |
+
}).end();
|
2907 |
+
},
|
2908 |
+
|
2909 |
+
hide: function(speed,callback){
|
2910 |
+
return speed ?
|
2911 |
+
this.animate({
|
2912 |
+
height: "hide", width: "hide", opacity: "hide"
|
2913 |
+
}, speed, callback) :
|
2914 |
+
|
2915 |
+
this.filter(":visible").each(function(){
|
2916 |
+
this.oldblock = this.oldblock || jQuery.css(this,"display");
|
2917 |
+
this.style.display = "none";
|
2918 |
+
}).end();
|
2919 |
+
},
|
2920 |
+
|
2921 |
+
// Save the old toggle function
|
2922 |
+
_toggle: jQuery.fn.toggle,
|
2923 |
+
|
2924 |
+
toggle: function( fn, fn2 ){
|
2925 |
+
return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
|
2926 |
+
this._toggle( fn, fn2 ) :
|
2927 |
+
fn ?
|
2928 |
+
this.animate({
|
2929 |
+
height: "toggle", width: "toggle", opacity: "toggle"
|
2930 |
+
}, fn, fn2) :
|
2931 |
+
this.each(function(){
|
2932 |
+
jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
|
2933 |
+
});
|
2934 |
+
},
|
2935 |
+
|
2936 |
+
slideDown: function(speed,callback){
|
2937 |
+
return this.animate({height: "show"}, speed, callback);
|
2938 |
+
},
|
2939 |
+
|
2940 |
+
slideUp: function(speed,callback){
|
2941 |
+
return this.animate({height: "hide"}, speed, callback);
|
2942 |
+
},
|
2943 |
+
|
2944 |
+
slideToggle: function(speed, callback){
|
2945 |
+
return this.animate({height: "toggle"}, speed, callback);
|
2946 |
+
},
|
2947 |
+
|
2948 |
+
fadeIn: function(speed, callback){
|
2949 |
+
return this.animate({opacity: "show"}, speed, callback);
|
2950 |
+
},
|
2951 |
+
|
2952 |
+
fadeOut: function(speed, callback){
|
2953 |
+
return this.animate({opacity: "hide"}, speed, callback);
|
2954 |
+
},
|
2955 |
+
|
2956 |
+
fadeTo: function(speed,to,callback){
|
2957 |
+
return this.animate({opacity: to}, speed, callback);
|
2958 |
+
},
|
2959 |
+
|
2960 |
+
animate: function( prop, speed, easing, callback ) {
|
2961 |
+
var optall = jQuery.speed(speed, easing, callback);
|
2962 |
+
|
2963 |
+
return this[ optall.queue === false ? "each" : "queue" ](function(){
|
2964 |
+
if ( this.nodeType != 1)
|
2965 |
+
return false;
|
2966 |
+
|
2967 |
+
var opt = jQuery.extend({}, optall);
|
2968 |
+
var hidden = jQuery(this).is(":hidden"), self = this;
|
2969 |
+
|
2970 |
+
for ( var p in prop ) {
|
2971 |
+
if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
|
2972 |
+
return jQuery.isFunction(opt.complete) && opt.complete.apply(this);
|
2973 |
+
|
2974 |
+
if ( p == "height" || p == "width" ) {
|
2975 |
+
// Store display property
|
2976 |
+
opt.display = jQuery.css(this, "display");
|
2977 |
+
|
2978 |
+
// Make sure that nothing sneaks out
|
2979 |
+
opt.overflow = this.style.overflow;
|
2980 |
+
}
|
2981 |
+
}
|
2982 |
+
|
2983 |
+
if ( opt.overflow != null )
|
2984 |
+
this.style.overflow = "hidden";
|
2985 |
+
|
2986 |
+
opt.curAnim = jQuery.extend({}, prop);
|
2987 |
+
|
2988 |
+
jQuery.each( prop, function(name, val){
|
2989 |
+
var e = new jQuery.fx( self, opt, name );
|
2990 |
+
|
2991 |
+
if ( /toggle|show|hide/.test(val) )
|
2992 |
+
e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
|
2993 |
+
else {
|
2994 |
+
var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
|
2995 |
+
start = e.cur(true) || 0;
|
2996 |
+
|
2997 |
+
if ( parts ) {
|
2998 |
+
var end = parseFloat(parts[2]),
|
2999 |
+
unit = parts[3] || "px";
|
3000 |
+
|
3001 |
+
// We need to compute starting value
|
3002 |
+
if ( unit != "px" ) {
|
3003 |
+
self.style[ name ] = (end || 1) + unit;
|
3004 |
+
start = ((end || 1) / e.cur(true)) * start;
|
3005 |
+
self.style[ name ] = start + unit;
|
3006 |
+
}
|
3007 |
+
|
3008 |
+
// If a +=/-= token was provided, we're doing a relative animation
|
3009 |
+
if ( parts[1] )
|
3010 |
+
end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
|
3011 |
+
|
3012 |
+
e.custom( start, end, unit );
|
3013 |
+
} else
|
3014 |
+
e.custom( start, val, "" );
|
3015 |
+
}
|
3016 |
+
});
|
3017 |
+
|
3018 |
+
// For JS strict compliance
|
3019 |
+
return true;
|
3020 |
+
});
|
3021 |
+
},
|
3022 |
+
|
3023 |
+
queue: function(type, fn){
|
3024 |
+
if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
|
3025 |
+
fn = type;
|
3026 |
+
type = "fx";
|
3027 |
+
}
|
3028 |
+
|
3029 |
+
if ( !type || (typeof type == "string" && !fn) )
|
3030 |
+
return queue( this[0], type );
|
3031 |
+
|
3032 |
+
return this.each(function(){
|
3033 |
+
if ( fn.constructor == Array )
|
3034 |
+
queue(this, type, fn);
|
3035 |
+
else {
|
3036 |
+
queue(this, type).push( fn );
|
3037 |
+
|
3038 |
+
if ( queue(this, type).length == 1 )
|
3039 |
+
fn.apply(this);
|
3040 |
+
}
|
3041 |
+
});
|
3042 |
+
},
|
3043 |
+
|
3044 |
+
stop: function(clearQueue, gotoEnd){
|
3045 |
+
var timers = jQuery.timers;
|
3046 |
+
|
3047 |
+
if (clearQueue)
|
3048 |
+
this.queue([]);
|
3049 |
+
|
3050 |
+
this.each(function(){
|
3051 |
+
// go in reverse order so anything added to the queue during the loop is ignored
|
3052 |
+
for ( var i = timers.length - 1; i >= 0; i-- )
|
3053 |
+
if ( timers[i].elem == this ) {
|
3054 |
+
if (gotoEnd)
|
3055 |
+
// force the next step to be the last
|
3056 |
+
timers[i](true);
|
3057 |
+
timers.splice(i, 1);
|
3058 |
+
}
|
3059 |
+
});
|
3060 |
+
|
3061 |
+
// start the next in the queue if the last step wasn't forced
|
3062 |
+
if (!gotoEnd)
|
3063 |
+
this.dequeue();
|
3064 |
+
|
3065 |
+
return this;
|
3066 |
+
}
|
3067 |
+
|
3068 |
+
});
|
3069 |
+
|
3070 |
+
var queue = function( elem, type, array ) {
|
3071 |
+
if ( !elem )
|
3072 |
+
return undefined;
|
3073 |
+
|
3074 |
+
type = type || "fx";
|
3075 |
+
|
3076 |
+
var q = jQuery.data( elem, type + "queue" );
|
3077 |
+
|
3078 |
+
if ( !q || array )
|
3079 |
+
q = jQuery.data( elem, type + "queue",
|
3080 |
+
array ? jQuery.makeArray(array) : [] );
|
3081 |
+
|
3082 |
+
return q;
|
3083 |
+
};
|
3084 |
+
|
3085 |
+
jQuery.fn.dequeue = function(type){
|
3086 |
+
type = type || "fx";
|
3087 |
+
|
3088 |
+
return this.each(function(){
|
3089 |
+
var q = queue(this, type);
|
3090 |
+
|
3091 |
+
q.shift();
|
3092 |
+
|
3093 |
+
if ( q.length )
|
3094 |
+
q[0].apply( this );
|
3095 |
+
});
|
3096 |
+
};
|
3097 |
+
|
3098 |
+
jQuery.extend({
|
3099 |
+
|
3100 |
+
speed: function(speed, easing, fn) {
|
3101 |
+
var opt = speed && speed.constructor == Object ? speed : {
|
3102 |
+
complete: fn || !fn && easing ||
|
3103 |
+
jQuery.isFunction( speed ) && speed,
|
3104 |
+
duration: speed,
|
3105 |
+
easing: fn && easing || easing && easing.constructor != Function && easing
|
3106 |
+
};
|
3107 |
+
|
3108 |
+
opt.duration = (opt.duration && opt.duration.constructor == Number ?
|
3109 |
+
opt.duration :
|
3110 |
+
{ slow: 600, fast: 200 }[opt.duration]) || 400;
|
3111 |
+
|
3112 |
+
// Queueing
|
3113 |
+
opt.old = opt.complete;
|
3114 |
+
opt.complete = function(){
|
3115 |
+
if ( opt.queue !== false )
|
3116 |
+
jQuery(this).dequeue();
|
3117 |
+
if ( jQuery.isFunction( opt.old ) )
|
3118 |
+
opt.old.apply( this );
|
3119 |
+
};
|
3120 |
+
|
3121 |
+
return opt;
|
3122 |
+
},
|
3123 |
+
|
3124 |
+
easing: {
|
3125 |
+
linear: function( p, n, firstNum, diff ) {
|
3126 |
+
return firstNum + diff * p;
|
3127 |
+
},
|
3128 |
+
swing: function( p, n, firstNum, diff ) {
|
3129 |
+
return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
|
3130 |
+
}
|
3131 |
+
},
|
3132 |
+
|
3133 |
+
timers: [],
|
3134 |
+
timerId: null,
|
3135 |
+
|
3136 |
+
fx: function( elem, options, prop ){
|
3137 |
+
this.options = options;
|
3138 |
+
this.elem = elem;
|
3139 |
+
this.prop = prop;
|
3140 |
+
|
3141 |
+
if ( !options.orig )
|
3142 |
+
options.orig = {};
|
3143 |
+
}
|
3144 |
+
|
3145 |
+
});
|
3146 |
+
|
3147 |
+
jQuery.fx.prototype = {
|
3148 |
+
|
3149 |
+
// Simple function for setting a style value
|
3150 |
+
update: function(){
|
3151 |
+
if ( this.options.step )
|
3152 |
+
this.options.step.apply( this.elem, [ this.now, this ] );
|
3153 |
+
|
3154 |
+
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
|
3155 |
+
|
3156 |
+
// Set display property to block for height/width animations
|
3157 |
+
if ( this.prop == "height" || this.prop == "width" )
|
3158 |
+
this.elem.style.display = "block";
|
3159 |
+
},
|
3160 |
+
|
3161 |
+
// Get the current size
|
3162 |
+
cur: function(force){
|
3163 |
+
if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
|
3164 |
+
return this.elem[ this.prop ];
|
3165 |
+
|
3166 |
+
var r = parseFloat(jQuery.css(this.elem, this.prop, force));
|
3167 |
+
return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
|
3168 |
+
},
|
3169 |
+
|
3170 |
+
// Start an animation from one number to another
|
3171 |
+
custom: function(from, to, unit){
|
3172 |
+
this.startTime = (new Date()).getTime();
|
3173 |
+
this.start = from;
|
3174 |
+
this.end = to;
|
3175 |
+
this.unit = unit || this.unit || "px";
|
3176 |
+
this.now = this.start;
|
3177 |
+
this.pos = this.state = 0;
|
3178 |
+
this.update();
|
3179 |
+
|
3180 |
+
var self = this;
|
3181 |
+
function t(gotoEnd){
|
3182 |
+
return self.step(gotoEnd);
|
3183 |
+
}
|
3184 |
+
|
3185 |
+
t.elem = this.elem;
|
3186 |
+
|
3187 |
+
jQuery.timers.push(t);
|
3188 |
+
|
3189 |
+
if ( jQuery.timerId == null ) {
|
3190 |
+
jQuery.timerId = setInterval(function(){
|
3191 |
+
var timers = jQuery.timers;
|
3192 |
+
|
3193 |
+
for ( var i = 0; i < timers.length; i++ )
|
3194 |
+
if ( !timers[i]() )
|
3195 |
+
timers.splice(i--, 1);
|
3196 |
+
|
3197 |
+
if ( !timers.length ) {
|
3198 |
+
clearInterval( jQuery.timerId );
|
3199 |
+
jQuery.timerId = null;
|
3200 |
+
}
|
3201 |
+
}, 13);
|
3202 |
+
}
|
3203 |
+
},
|
3204 |
+
|
3205 |
+
// Simple 'show' function
|
3206 |
+
show: function(){
|
3207 |
+
// Remember where we started, so that we can go back to it later
|
3208 |
+
this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
|
3209 |
+
this.options.show = true;
|
3210 |
+
|
3211 |
+
// Begin the animation
|
3212 |
+
this.custom(0, this.cur());
|
3213 |
+
|
3214 |
+
// Make sure that we start at a small width/height to avoid any
|
3215 |
+
// flash of content
|
3216 |
+
if ( this.prop == "width" || this.prop == "height" )
|
3217 |
+
this.elem.style[this.prop] = "1px";
|
3218 |
+
|
3219 |
+
// Start by showing the element
|
3220 |
+
jQuery(this.elem).show();
|
3221 |
+
},
|
3222 |
+
|
3223 |
+
// Simple 'hide' function
|
3224 |
+
hide: function(){
|
3225 |
+
// Remember where we started, so that we can go back to it later
|
3226 |
+
this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
|
3227 |
+
this.options.hide = true;
|
3228 |
+
|
3229 |
+
// Begin the animation
|
3230 |
+
this.custom(this.cur(), 0);
|
3231 |
+
},
|
3232 |
+
|
3233 |
+
// Each step of an animation
|
3234 |
+
step: function(gotoEnd){
|
3235 |
+
var t = (new Date()).getTime();
|
3236 |
+
|
3237 |
+
if ( gotoEnd || t > this.options.duration + this.startTime ) {
|
3238 |
+
this.now = this.end;
|
3239 |
+
this.pos = this.state = 1;
|
3240 |
+
this.update();
|
3241 |
+
|
3242 |
+
this.options.curAnim[ this.prop ] = true;
|
3243 |
+
|
3244 |
+
var done = true;
|
3245 |
+
for ( var i in this.options.curAnim )
|
3246 |
+
if ( this.options.curAnim[i] !== true )
|
3247 |
+
done = false;
|
3248 |
+
|
3249 |
+
if ( done ) {
|
3250 |
+
if ( this.options.display != null ) {
|
3251 |
+
// Reset the overflow
|
3252 |
+
this.elem.style.overflow = this.options.overflow;
|
3253 |
+
|
3254 |
+
// Reset the display
|
3255 |
+
this.elem.style.display = this.options.display;
|
3256 |
+
if ( jQuery.css(this.elem, "display") == "none" )
|
3257 |
+
this.elem.style.display = "block";
|
3258 |
+
}
|
3259 |
+
|
3260 |
+
// Hide the element if the "hide" operation was done
|
3261 |
+
if ( this.options.hide )
|
3262 |
+
this.elem.style.display = "none";
|
3263 |
+
|
3264 |
+
// Reset the properties, if the item has been hidden or shown
|
3265 |
+
if ( this.options.hide || this.options.show )
|
3266 |
+
for ( var p in this.options.curAnim )
|
3267 |
+
jQuery.attr(this.elem.style, p, this.options.orig[p]);
|
3268 |
+
}
|
3269 |
+
|
3270 |
+
// If a callback was provided, execute it
|
3271 |
+
if ( done && jQuery.isFunction( this.options.complete ) )
|
3272 |
+
// Execute the complete function
|
3273 |
+
this.options.complete.apply( this.elem );
|
3274 |
+
|
3275 |
+
return false;
|
3276 |
+
} else {
|
3277 |
+
var n = t - this.startTime;
|
3278 |
+
this.state = n / this.options.duration;
|
3279 |
+
|
3280 |
+
// Perform the easing function, defaults to swing
|
3281 |
+
this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
|
3282 |
+
this.now = this.start + ((this.end - this.start) * this.pos);
|
3283 |
+
|
3284 |
+
// Perform the next step of the animation
|
3285 |
+
this.update();
|
3286 |
+
}
|
3287 |
+
|
3288 |
+
return true;
|
3289 |
+
}
|
3290 |
+
|
3291 |
+
};
|
3292 |
+
|
3293 |
+
jQuery.fx.step = {
|
3294 |
+
scrollLeft: function(fx){
|
3295 |
+
fx.elem.scrollLeft = fx.now;
|
3296 |
+
},
|
3297 |
+
|
3298 |
+
scrollTop: function(fx){
|
3299 |
+
fx.elem.scrollTop = fx.now;
|
3300 |
+
},
|
3301 |
+
|
3302 |
+
opacity: function(fx){
|
3303 |
+
jQuery.attr(fx.elem.style, "opacity", fx.now);
|
3304 |
+
},
|
3305 |
+
|
3306 |
+
_default: function(fx){
|
3307 |
+
fx.elem.style[ fx.prop ] = fx.now + fx.unit;
|
3308 |
+
}
|
3309 |
+
};
|
3310 |
+
// The Offset Method
|
3311 |
+
// Originally By Brandon Aaron, part of the Dimension Plugin
|
3312 |
+
// http://jquery.com/plugins/project/dimensions
|
3313 |
+
jQuery.fn.offset = function() {
|
3314 |
+
var left = 0, top = 0, elem = this[0], results;
|
3315 |
+
|
3316 |
+
if ( elem ) with ( jQuery.browser ) {
|
3317 |
+
var parent = elem.parentNode,
|
3318 |
+
offsetChild = elem,
|
3319 |
+
offsetParent = elem.offsetParent,
|
3320 |
+
doc = elem.ownerDocument,
|
3321 |
+
safari2 = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
|
3322 |
+
fixed = jQuery.css(elem, "position") == "fixed";
|
3323 |
+
|
3324 |
+
// Use getBoundingClientRect if available
|
3325 |
+
if ( elem.getBoundingClientRect ) {
|
3326 |
+
var box = elem.getBoundingClientRect();
|
3327 |
+
|
3328 |
+
// Add the document scroll offsets
|
3329 |
+
add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
|
3330 |
+
box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
|
3331 |
+
|
3332 |
+
// IE adds the HTML element's border, by default it is medium which is 2px
|
3333 |
+
// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
|
3334 |
+
// IE 7 standards mode, the border is always 2px
|
3335 |
+
// This border/offset is typically represented by the clientLeft and clientTop properties
|
3336 |
+
// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
|
3337 |
+
// Therefore this method will be off by 2px in IE while in quirksmode
|
3338 |
+
add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
|
3339 |
+
|
3340 |
+
// Otherwise loop through the offsetParents and parentNodes
|
3341 |
+
} else {
|
3342 |
+
|
3343 |
+
// Initial element offsets
|
3344 |
+
add( elem.offsetLeft, elem.offsetTop );
|
3345 |
+
|
3346 |
+
// Get parent offsets
|
3347 |
+
while ( offsetParent ) {
|
3348 |
+
// Add offsetParent offsets
|
3349 |
+
add( offsetParent.offsetLeft, offsetParent.offsetTop );
|
3350 |
+
|
3351 |
+
// Mozilla and Safari > 2 does not include the border on offset parents
|
3352 |
+
// However Mozilla adds the border for table or table cells
|
3353 |
+
if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
|
3354 |
+
border( offsetParent );
|
3355 |
+
|
3356 |
+
// Add the document scroll offsets if position is fixed on any offsetParent
|
3357 |
+
if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
|
3358 |
+
fixed = true;
|
3359 |
+
|
3360 |
+
// Set offsetChild to previous offsetParent unless it is the body element
|
3361 |
+
offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
|
3362 |
+
// Get next offsetParent
|
3363 |
+
offsetParent = offsetParent.offsetParent;
|
3364 |
+
}
|
3365 |
+
|
3366 |
+
// Get parent scroll offsets
|
3367 |
+
while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
|
3368 |
+
// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
|
3369 |
+
if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
|
3370 |
+
// Subtract parent scroll offsets
|
3371 |
+
add( -parent.scrollLeft, -parent.scrollTop );
|
3372 |
+
|
3373 |
+
// Mozilla does not add the border for a parent that has overflow != visible
|
3374 |
+
if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
|
3375 |
+
border( parent );
|
3376 |
+
|
3377 |
+
// Get next parent
|
3378 |
+
parent = parent.parentNode;
|
3379 |
+
}
|
3380 |
+
|
3381 |
+
// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
|
3382 |
+
// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
|
3383 |
+
if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) ||
|
3384 |
+
(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
|
3385 |
+
add( -doc.body.offsetLeft, -doc.body.offsetTop );
|
3386 |
+
|
3387 |
+
// Add the document scroll offsets if position is fixed
|
3388 |
+
if ( fixed )
|
3389 |
+
add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
|
3390 |
+
Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
|
3391 |
+
}
|
3392 |
+
|
3393 |
+
// Return an object with top and left properties
|
3394 |
+
results = { top: top, left: left };
|
3395 |
+
}
|
3396 |
+
|
3397 |
+
function border(elem) {
|
3398 |
+
add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
|
3399 |
+
}
|
3400 |
+
|
3401 |
+
function add(l, t) {
|
3402 |
+
left += parseInt(l) || 0;
|
3403 |
+
top += parseInt(t) || 0;
|
3404 |
+
}
|
3405 |
+
|
3406 |
+
return results;
|
3407 |
+
};
|
3408 |
+
})();
|
lib/Minify/min_extras/ab_tests/minify/test_Files.php
ADDED
@@ -0,0 +1,15 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require '../../config.php';
|
4 |
+
|
5 |
+
require 'Minify.php';
|
6 |
+
|
7 |
+
// set in /min/config.php
|
8 |
+
Minify::setCache($minifyCachePath);
|
9 |
+
|
10 |
+
Minify::serve('Files', array(
|
11 |
+
'files' => array(
|
12 |
+
dirname(__FILE__) . '/before.js'
|
13 |
+
)
|
14 |
+
,'maxAge' => 31536000 // 1 yr
|
15 |
+
));
|
lib/Minify/min_extras/ab_tests/minify/test_Files_Memcache.php
ADDED
@@ -0,0 +1,35 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require '../../config.php';
|
4 |
+
|
5 |
+
require 'Minify.php';
|
6 |
+
require 'Minify/Cache/Memcache.php';
|
7 |
+
|
8 |
+
$mc = new Memcache;
|
9 |
+
if (! @$mc->connect('localhost', 11211)) {
|
10 |
+
file_put_contents(
|
11 |
+
dirname(__FILE__) . '/../memcached_stats.txt'
|
12 |
+
,"\nFailed connection.\n"
|
13 |
+
,FILE_APPEND
|
14 |
+
);
|
15 |
+
die();
|
16 |
+
}
|
17 |
+
|
18 |
+
if (0 == rand(0, 19)) {
|
19 |
+
$stats = $mc->getStats();
|
20 |
+
file_put_contents(
|
21 |
+
dirname(__FILE__) . '/../memcached_stats.txt'
|
22 |
+
,$stats['curr_connections'] . "\n"
|
23 |
+
,FILE_APPEND
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
|
28 |
+
Minify::setCache(new Minify_Cache_Memcache($mc));
|
29 |
+
|
30 |
+
Minify::serve('Files', array(
|
31 |
+
'files' => array(
|
32 |
+
dirname(__FILE__) . '/before.js'
|
33 |
+
)
|
34 |
+
,'maxAge' => 31536000 // 1 yr
|
35 |
+
));
|
lib/Minify/min_extras/ab_tests/minify/test_Groups.php
ADDED
@@ -0,0 +1,15 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require '../../config.php';
|
4 |
+
|
5 |
+
require 'Minify.php';
|
6 |
+
|
7 |
+
// set in /min/config.php
|
8 |
+
Minify::setCache($minifyCachePath);
|
9 |
+
|
10 |
+
Minify::serve('Groups', array(
|
11 |
+
'groups' => array(
|
12 |
+
'test' => array(dirname(__FILE__) . '/before.js')
|
13 |
+
)
|
14 |
+
,'maxAge' => 31536000 // 1 yr
|
15 |
+
));
|
lib/Minify/min_extras/ab_tests/minify/test_Version1.php
ADDED
@@ -0,0 +1,13 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require '../../config.php';
|
4 |
+
|
5 |
+
define('MINIFY_BASE_DIR', realpath(
|
6 |
+
dirname(__FILE__) . '/../minify'
|
7 |
+
));
|
8 |
+
// set in /min/config.php
|
9 |
+
define('MINIFY_CACHE_DIR', $minifyCachePath);
|
10 |
+
|
11 |
+
require 'Minify.php';
|
12 |
+
|
13 |
+
Minify::serve('Version1');
|
lib/Minify/min_extras/ab_tests/minify/test_memcache.php
ADDED
@@ -0,0 +1,19 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$mc = new Memcache;
|
4 |
+
if (! @$mc->connect('localhost', 11211)) {
|
5 |
+
file_put_contents(
|
6 |
+
dirname(__FILE__) . '/../memcached_stats.txt'
|
7 |
+
,"Fail\n"
|
8 |
+
,FILE_APPEND | LOCK_EX
|
9 |
+
);
|
10 |
+
die();
|
11 |
+
}
|
12 |
+
|
13 |
+
$stats = $mc->getStats();
|
14 |
+
file_put_contents(
|
15 |
+
dirname(__FILE__) . '/../memcached_stats.txt'
|
16 |
+
,$stats['curr_connections'] . "\n"
|
17 |
+
,FILE_APPEND | LOCK_EX
|
18 |
+
);
|
19 |
+
|
lib/Minify/min_extras/ab_tests/mod_deflate/.htaccess-dev
ADDED
@@ -0,0 +1,30 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# turn off MultiViews if enabled
|
2 |
+
Options -MultiViews
|
3 |
+
|
4 |
+
# Necessary to add charset while using type-map
|
5 |
+
AddType application/x-javascript;charset=utf-8 js
|
6 |
+
AddType text/css;charset=utf-8 css
|
7 |
+
|
8 |
+
# Below we remove the ETag header and set a far-off Expires
|
9 |
+
# header. Since clients will aggressively cache, make sure
|
10 |
+
# to modify the URL (querystring or via mod_rewrite) when
|
11 |
+
# the resource changes
|
12 |
+
|
13 |
+
# remove ETag
|
14 |
+
FileETag None
|
15 |
+
|
16 |
+
# requires mod_expires
|
17 |
+
ExpiresActive On
|
18 |
+
# sets Expires and Cache-Control: max-age, but not "public"
|
19 |
+
ExpiresDefault "access plus 1 year"
|
20 |
+
|
21 |
+
# requires mod_headers
|
22 |
+
# adds the "public" to Cache-Control.
|
23 |
+
Header set Cache-Control "public, max-age=31536000"
|
24 |
+
|
25 |
+
# requires mod_deflate
|
26 |
+
AddOutputFilterByType DEFLATE application/x-javascript text/css
|
27 |
+
# IE 5 and 6 are the only ones we really care about
|
28 |
+
BrowserMatch \bMSIE\s[56] no-gzip
|
29 |
+
# but not if it's got the SV1 patch or is really Opera
|
30 |
+
BrowserMatch \b(SV1|Opera)\b !no-gzip
|
lib/Minify/min_extras/ab_tests/mod_deflate/before.js
ADDED
@@ -0,0 +1,374 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function(){
|
2 |
+
/*
|
3 |
+
* jQuery 1.2.3 - New Wave Javascript
|
4 |
+
*
|
5 |
+
* Copyright (c) 2008 John Resig (jquery.com)
|
6 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
7 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
8 |
+
*
|
9 |
+
* $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
|
10 |
+
* $Rev: 4663 $
|
11 |
+
*/
|
12 |
+
if(window.jQuery)
|
13 |
+
var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)
|
14 |
+
var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])
|
15 |
+
selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)
|
16 |
+
if(elem.id!=match[3])
|
17 |
+
return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}
|
18 |
+
else
|
19 |
+
selector=[];}}else
|
20 |
+
return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))
|
21 |
+
return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)
|
22 |
+
ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)
|
23 |
+
if(value==undefined)
|
24 |
+
return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}
|
25 |
+
return this.each(function(i){for(name in options)
|
26 |
+
jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)
|
27 |
+
value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)
|
28 |
+
return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)
|
29 |
+
ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])
|
30 |
+
jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)
|
31 |
+
elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)
|
32 |
+
this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)
|
33 |
+
this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
|
34 |
+
return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)
|
35 |
+
this[expando]=null;});if(events===true)
|
36 |
+
this.find("*").andSelf().each(function(i){if(this.nodeType==3)
|
37 |
+
return;var events=jQuery.data(this,"events");for(var type in events)
|
38 |
+
for(var handler in events[type])
|
39 |
+
jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)
|
40 |
+
if(isSimple.test(selector))
|
41 |
+
return this.pushStack(jQuery.multiFilter(selector,this,true));else
|
42 |
+
selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)
|
43 |
+
return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)
|
44 |
+
return value;values.push(value);}}
|
45 |
+
return values;}else
|
46 |
+
return(this[0].value||"").replace(/\r/g,"");}
|
47 |
+
return undefined;}
|
48 |
+
return this.each(function(){if(this.nodeType!=1)
|
49 |
+
return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))
|
50 |
+
this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)
|
51 |
+
this.selectedIndex=-1;}else
|
52 |
+
this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)
|
53 |
+
data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else
|
54 |
+
return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)
|
55 |
+
elems.reverse();}
|
56 |
+
var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))
|
57 |
+
obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)
|
58 |
+
scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)
|
59 |
+
jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
|
60 |
+
jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)
|
61 |
+
elem.parentNode.removeChild(elem);}
|
62 |
+
jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}
|
63 |
+
if(typeof target!="object"&&typeof target!="function")
|
64 |
+
target={};if(length==1){target=this;i=0;}
|
65 |
+
for(;i<length;i++)
|
66 |
+
if((options=arguments[i])!=null)
|
67 |
+
for(var name in options){if(target===options[name])
|
68 |
+
continue;if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType)
|
69 |
+
target[name]=jQuery.extend(target[name],options[name]);else if(options[name]!=undefined)
|
70 |
+
target[name]=options[name];}
|
71 |
+
return target;};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)
|
72 |
+
window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)
|
73 |
+
script.text=data;else
|
74 |
+
script.appendChild(document.createTextNode(data));head.appendChild(script);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)
|
75 |
+
id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])
|
76 |
+
jQuery.cache[id]={};if(data!=undefined)
|
77 |
+
jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])
|
78 |
+
break;if(!name)
|
79 |
+
jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)
|
80 |
+
elem.removeAttribute(expando);}
|
81 |
+
delete jQuery.cache[id];}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object)
|
82 |
+
if(callback.apply(object[name],args)===false)
|
83 |
+
break;}else
|
84 |
+
for(var i=0,length=object.length;i<length;i++)
|
85 |
+
if(callback.apply(object[i],args)===false)
|
86 |
+
break;}else{if(object.length==undefined){for(var name in object)
|
87 |
+
if(callback.call(object[name],name,object[name])===false)
|
88 |
+
break;}else
|
89 |
+
for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}
|
90 |
+
return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))
|
91 |
+
value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))
|
92 |
+
elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)
|
93 |
+
elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}
|
94 |
+
callback.call(elem);for(var name in options)
|
95 |
+
elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}
|
96 |
+
if(jQuery(elem).is(":visible"))
|
97 |
+
getWH();else
|
98 |
+
jQuery.swap(elem,props,getWH);return Math.max(0,val);}
|
99 |
+
return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)
|
100 |
+
return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}
|
101 |
+
if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}
|
102 |
+
if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}
|
103 |
+
if(name.match(/float/i))
|
104 |
+
name=styleFloat;if(!force&&elem.style&&elem.style[name])
|
105 |
+
ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))
|
106 |
+
name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))
|
107 |
+
ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)
|
108 |
+
stack.unshift(a);for(var i=0;i<stack.length;i++)
|
109 |
+
if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}
|
110 |
+
ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++)
|
111 |
+
if(swap[i]!=null)
|
112 |
+
stack[i].style.display=swap[i];}
|
113 |
+
if(name=="opacity"&&ret=="")
|
114 |
+
ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle;}}
|
115 |
+
return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')
|
116 |
+
context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)
|
117 |
+
return;if(elem.constructor==Number)
|
118 |
+
elem=elem.toString();if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)
|
119 |
+
div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)
|
120 |
+
if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)
|
121 |
+
tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))
|
122 |
+
div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}
|
123 |
+
elem=jQuery.makeArray(div.childNodes);}
|
124 |
+
if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))
|
125 |
+
return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)
|
126 |
+
ret.push(elem);else
|
127 |
+
ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)
|
128 |
+
return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)
|
129 |
+
elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)
|
130 |
+
elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")
|
131 |
+
return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))
|
132 |
+
return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)
|
133 |
+
throw"type property can't be changed";elem.setAttribute(name,""+value);}
|
134 |
+
if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))
|
135 |
+
return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+
|
136 |
+
(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}
|
137 |
+
return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}
|
138 |
+
name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)
|
139 |
+
elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")
|
140 |
+
for(var i=0,length=array.length;i<length;i++)
|
141 |
+
ret.push(array[i]);else
|
142 |
+
ret=array.slice(0);return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)
|
143 |
+
if(array[i]==elem)
|
144 |
+
return i;return-1;},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++)
|
145 |
+
if(second[i].nodeType!=8)
|
146 |
+
first.push(second[i]);}else
|
147 |
+
for(var i=0;second[i];i++)
|
148 |
+
first.push(second[i]);return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}
|
149 |
+
return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)
|
150 |
+
if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i))
|
151 |
+
ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array)
|
152 |
+
value=[value];ret=ret.concat(value);}}
|
153 |
+
return ret;}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")
|
154 |
+
ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)
|
155 |
+
jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)
|
156 |
+
this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)
|
157 |
+
this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)
|
158 |
+
this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}
|
159 |
+
return cur;},find:function(t,context){if(typeof t!="string")
|
160 |
+
return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)
|
161 |
+
return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)
|
162 |
+
for(var c=ret[i].firstChild;c;c=c.nextSibling)
|
163 |
+
if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))
|
164 |
+
r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)
|
165 |
+
if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}
|
166 |
+
if(m=="+")break;}}
|
167 |
+
ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}
|
168 |
+
if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}
|
169 |
+
m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])
|
170 |
+
oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")
|
171 |
+
tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}
|
172 |
+
if(m[1]==".")
|
173 |
+
r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)
|
174 |
+
if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}
|
175 |
+
r=tmp;}
|
176 |
+
ret=r;}
|
177 |
+
t=t.replace(re2,"");}}
|
178 |
+
if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}
|
179 |
+
if(t)
|
180 |
+
ret=[];if(ret&&context==ret[0])
|
181 |
+
ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)
|
182 |
+
tmp.push(r[i]);}
|
183 |
+
return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}
|
184 |
+
if(!m)
|
185 |
+
break;if(m[1]==":"&&m[2]=="not")
|
186 |
+
r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")
|
187 |
+
r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))
|
188 |
+
z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)
|
189 |
+
tmp.push(a);}
|
190 |
+
r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)
|
191 |
+
if(n.nodeType==1)
|
192 |
+
n.nodeIndex=c++;merge[id]=true;}
|
193 |
+
var add=false;if(first==0){if(node.nodeIndex==last)
|
194 |
+
add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)
|
195 |
+
add=true;if(add^not)
|
196 |
+
tmp.push(node);}
|
197 |
+
r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")
|
198 |
+
fn=fn[m[2]];if(typeof fn=="string")
|
199 |
+
fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}
|
200 |
+
return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)
|
201 |
+
matched.push(cur);cur=cur[dir];}
|
202 |
+
return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])
|
203 |
+
if(cur.nodeType==1&&++num==result)
|
204 |
+
break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))
|
205 |
+
r.push(n);}
|
206 |
+
return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)
|
207 |
+
return;if(jQuery.browser.msie&&elem.setInterval!=undefined)
|
208 |
+
elem=window;if(!handler.guid)
|
209 |
+
handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}
|
210 |
+
var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)
|
211 |
+
return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)
|
212 |
+
elem.addEventListener(type,handle,false);else if(elem.attachEvent)
|
213 |
+
elem.attachEvent("on"+type,handle);}}
|
214 |
+
handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)
|
215 |
+
return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))
|
216 |
+
for(var type in events)
|
217 |
+
this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}
|
218 |
+
jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)
|
219 |
+
delete events[type][handler.guid];else
|
220 |
+
for(handler in events[type])
|
221 |
+
if(!parts[1]||events[type][handler].type==parts[1])
|
222 |
+
delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)
|
223 |
+
elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)
|
224 |
+
elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}
|
225 |
+
ret=null;delete events[type];}}});}
|
226 |
+
for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}
|
227 |
+
if(!elem){if(this.global[type])
|
228 |
+
jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)
|
229 |
+
return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)
|
230 |
+
data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)
|
231 |
+
data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))
|
232 |
+
val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)
|
233 |
+
val=false;if(event)
|
234 |
+
data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)
|
235 |
+
val=ret;}
|
236 |
+
if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}
|
237 |
+
this.triggered=false;}
|
238 |
+
return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)
|
239 |
+
val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}
|
240 |
+
if(jQuery.browser.msie)
|
241 |
+
event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)
|
242 |
+
originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)
|
243 |
+
originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)
|
244 |
+
event.target=event.srcElement||document;if(event.target.nodeType==3)
|
245 |
+
event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)
|
246 |
+
event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}
|
247 |
+
if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))
|
248 |
+
event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)
|
249 |
+
event.metaKey=event.ctrlKey;if(!event.which&&event.button)
|
250 |
+
event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])
|
251 |
+
return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)
|
252 |
+
fn.call(document,jQuery);else
|
253 |
+
jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}
|
254 |
+
jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)
|
255 |
+
document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}
|
256 |
+
jQuery.ready();})();if(jQuery.browser.opera)
|
257 |
+
document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)
|
258 |
+
if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}
|
259 |
+
jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}
|
260 |
+
if(numStyles===undefined)
|
261 |
+
numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}
|
262 |
+
jQuery.ready();})();}
|
263 |
+
jQuery.event.add(window,"load",jQuery.ready);}
|
264 |
+
jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}
|
265 |
+
return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url))
|
266 |
+
return this.bind("load",url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}
|
267 |
+
callback=callback||function(){};var type="GET";if(params)
|
268 |
+
if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}
|
269 |
+
var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")
|
270 |
+
self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}
|
271 |
+
return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}
|
272 |
+
return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")
|
273 |
+
s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))
|
274 |
+
s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))
|
275 |
+
s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}
|
276 |
+
if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)
|
277 |
+
s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}
|
278 |
+
if(head)
|
279 |
+
head.removeChild(script);};}
|
280 |
+
if(s.dataType=="script"&&s.cache==null)
|
281 |
+
s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}
|
282 |
+
if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}
|
283 |
+
if(s.global&&!jQuery.active++)
|
284 |
+
jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)
|
285 |
+
script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}
|
286 |
+
head.appendChild(script);return undefined;}
|
287 |
+
var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)
|
288 |
+
xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)
|
289 |
+
xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}
|
290 |
+
if(s.beforeSend)
|
291 |
+
s.beforeSend(xml);if(s.global)
|
292 |
+
jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}
|
293 |
+
status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}
|
294 |
+
if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}
|
295 |
+
if(s.ifModified&&modRes)
|
296 |
+
jQuery.lastModified[s.url]=modRes;if(!jsonp)
|
297 |
+
success();}else
|
298 |
+
jQuery.handleError(s,xml,status);complete();if(s.async)
|
299 |
+
xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)
|
300 |
+
setTimeout(function(){if(xml){xml.abort();if(!requestDone)
|
301 |
+
onreadystatechange("timeout");}},s.timeout);}
|
302 |
+
try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}
|
303 |
+
if(!s.async)
|
304 |
+
onreadystatechange();function success(){if(s.success)
|
305 |
+
s.success(data,status);if(s.global)
|
306 |
+
jQuery.event.trigger("ajaxSuccess",[xml,s]);}
|
307 |
+
function complete(){if(s.complete)
|
308 |
+
s.complete(xml,status);if(s.global)
|
309 |
+
jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)
|
310 |
+
jQuery.event.trigger("ajaxStop");}
|
311 |
+
return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)
|
312 |
+
jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}
|
313 |
+
return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}
|
314 |
+
return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")
|
315 |
+
throw"parsererror";if(type=="script")
|
316 |
+
jQuery.globalEval(data);if(type=="json")
|
317 |
+
data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)
|
318 |
+
jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
|
319 |
+
for(var j in a)
|
320 |
+
if(a[j]&&a[j].constructor==Array)
|
321 |
+
jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
|
322 |
+
s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")
|
323 |
+
this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)
|
324 |
+
return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)
|
325 |
+
return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}
|
326 |
+
if(opt.overflow!=null)
|
327 |
+
this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))
|
328 |
+
e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}
|
329 |
+
if(parts[1])
|
330 |
+
end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
|
331 |
+
e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}
|
332 |
+
if(!type||(typeof type=="string"&&!fn))
|
333 |
+
return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)
|
334 |
+
queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)
|
335 |
+
fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)
|
336 |
+
this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)
|
337 |
+
if(timers[i].elem==this){if(gotoEnd)
|
338 |
+
timers[i](true);timers.splice(i,1);}});if(!gotoEnd)
|
339 |
+
this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)
|
340 |
+
return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)
|
341 |
+
q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)
|
342 |
+
q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)
|
343 |
+
jQuery(this).dequeue();if(jQuery.isFunction(opt.old))
|
344 |
+
opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)
|
345 |
+
options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)
|
346 |
+
this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")
|
347 |
+
this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)
|
348 |
+
return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}
|
349 |
+
t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)
|
350 |
+
if(!timers[i]())
|
351 |
+
timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")
|
352 |
+
this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)
|
353 |
+
if(this.options.curAnim[i]!==true)
|
354 |
+
done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")
|
355 |
+
this.elem.style.display="block";}
|
356 |
+
if(this.options.hide)
|
357 |
+
this.elem.style.display="none";if(this.options.hide||this.options.show)
|
358 |
+
for(var p in this.options.curAnim)
|
359 |
+
jQuery.attr(this.elem.style,p,this.options.orig[p]);}
|
360 |
+
if(done&&jQuery.isFunction(this.options.complete))
|
361 |
+
this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}
|
362 |
+
return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)
|
363 |
+
border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")
|
364 |
+
fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}
|
365 |
+
while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))
|
366 |
+
add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")
|
367 |
+
border(parent);parent=parent.parentNode;}
|
368 |
+
if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))
|
369 |
+
add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)
|
370 |
+
add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}
|
371 |
+
results={top:top,left:left};}
|
372 |
+
function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}
|
373 |
+
function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}
|
374 |
+
return results;};})();
|
lib/Minify/min_extras/ab_tests/results_summary.txt
ADDED
@@ -0,0 +1,37 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/ideal_php/before.php
|
2 |
+
Document Length: 15993 bytes
|
3 |
+
Requests per second: 354.57 [#/sec] (mean)
|
4 |
+
--------------------------------------------------------------------------------
|
5 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/v1.0/minify.php?files=before.js
|
6 |
+
Document Length: 54418 bytes
|
7 |
+
Requests per second: 261.76 [#/sec] (mean)
|
8 |
+
--------------------------------------------------------------------------------
|
9 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Files.php
|
10 |
+
Document Length: 15993 bytes
|
11 |
+
Requests per second: 203.82 [#/sec] (mean)
|
12 |
+
--------------------------------------------------------------------------------
|
13 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Files_Memcache.php
|
14 |
+
Document Length: 15993 bytes
|
15 |
+
(Connect: 0, Length: 19, Exceptions: 0)
|
16 |
+
Requests per second: 156.86 [#/sec] (mean)
|
17 |
+
--------------------------------------------------------------------------------
|
18 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Groups.php/test
|
19 |
+
Document Length: 15993 bytes
|
20 |
+
Requests per second: 207.79 [#/sec] (mean)
|
21 |
+
--------------------------------------------------------------------------------
|
22 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/minify/test_Version1.php?files=before.js
|
23 |
+
Document Length: 15993 bytes
|
24 |
+
Requests per second: 210.53 [#/sec] (mean)
|
25 |
+
--------------------------------------------------------------------------------
|
26 |
+
Document Path: /min/?f=_3rd_party/minify/min_extras/ab_tests/minify/before.js
|
27 |
+
Document Length: 15993 bytes
|
28 |
+
Requests per second: 231.46 [#/sec] (mean)
|
29 |
+
--------------------------------------------------------------------------------
|
30 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/mod_deflate/before.js
|
31 |
+
Document Length: 16053 bytes
|
32 |
+
Requests per second: 185.78 [#/sec] (mean)
|
33 |
+
--------------------------------------------------------------------------------
|
34 |
+
Document Path: /_3rd_party/minify/min_extras/ab_tests/type-map/before.js.var
|
35 |
+
Document Length: 15993 bytes
|
36 |
+
Requests per second: 472.32 [#/sec] (mean)
|
37 |
+
--------------------------------------------------------------------------------
|
lib/Minify/min_extras/ab_tests/test_all.bat
ADDED
@@ -0,0 +1,67 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@SET PATH=%PATH%;C:\xampp\apache\bin
|
2 |
+
|
3 |
+
@SET DOMAIN=http://mc.dev
|
4 |
+
|
5 |
+
@SET ABCALL=ab -d -S -c 100 -n 2000 -H "Accept-Encoding: deflate, gzip"
|
6 |
+
:: for priming cache
|
7 |
+
@SET ABPRIM=ab -d -S -c 1 -n 2 -H "Accept-Encoding: deflate, gzip"
|
8 |
+
|
9 |
+
@SET ABTESTS=%DOMAIN%/min_extras/ab_tests
|
10 |
+
|
11 |
+
::@SET TXTVIEWER=notepad.exe
|
12 |
+
@SET TXTVIEWER="C:\Program Files\Notepad++\notepad++.exe"
|
13 |
+
|
14 |
+
@SET DELIM=TYPE _delimiter
|
15 |
+
|
16 |
+
DEL results.txt
|
17 |
+
|
18 |
+
:: prime caches (though some may not need it)
|
19 |
+
%ABPRIM% %ABTESTS%/ideal_php/before.php
|
20 |
+
%ABPRIM% %ABTESTS%/v1.0/minify.php?files=before.js
|
21 |
+
%ABPRIM% %ABTESTS%/minify/test_Files.php
|
22 |
+
%ABPRIM% %ABTESTS%/minify/test_Files_Memcache.php
|
23 |
+
%ABPRIM% %ABTESTS%/minify/test_Groups.php/test
|
24 |
+
%ABPRIM% %ABTESTS%/minify/test_Version1.php?files=before.js
|
25 |
+
%ABPRIM% %DOMAIN%/min/?f=min_extras/ab_tests/minify/before.js
|
26 |
+
%ABPRIM% %ABTESTS%/mod_deflate/before.js
|
27 |
+
%ABPRIM% %ABTESTS%/type-map/before.js.var
|
28 |
+
|
29 |
+
:: baseline PHP
|
30 |
+
%ABCALL% %ABTESTS%/ideal_php/before.php >> results.txt
|
31 |
+
@%DELIM% >> results.txt
|
32 |
+
|
33 |
+
:: 1.0 release
|
34 |
+
%ABCALL% %ABTESTS%/v1.0/minify.php?files=before.js >> results.txt
|
35 |
+
@%DELIM% >> results.txt
|
36 |
+
|
37 |
+
:: Files controller
|
38 |
+
%ABCALL% %ABTESTS%/minify/test_Files.php >> results.txt
|
39 |
+
@%DELIM% >> results.txt
|
40 |
+
|
41 |
+
:: Files controller w/ Memcache as cache
|
42 |
+
%ABCALL% %ABTESTS%/minify/test_Files_Memcache.php >> results.txt
|
43 |
+
@%DELIM% >> results.txt
|
44 |
+
|
45 |
+
:: Groups controller
|
46 |
+
%ABCALL% %ABTESTS%/minify/test_Groups.php/test >> results.txt
|
47 |
+
@%DELIM% >> results.txt
|
48 |
+
|
49 |
+
:: Version1 controller
|
50 |
+
%ABCALL% %ABTESTS%/minify/test_Version1.php?files=before.js >> results.txt
|
51 |
+
@%DELIM% >> results.txt
|
52 |
+
|
53 |
+
::/min application
|
54 |
+
%ABCALL% %DOMAIN%/min/?f=min_extras/ab_tests/minify/before.js >> results.txt
|
55 |
+
@%DELIM% >> results.txt
|
56 |
+
|
57 |
+
:: mod_deflate
|
58 |
+
%ABCALL% %ABTESTS%/mod_deflate/before.js >> results.txt
|
59 |
+
@%DELIM% >> results.txt
|
60 |
+
|
61 |
+
:: type-map
|
62 |
+
%ABCALL% %ABTESTS%/type-map/before.js.var >> results.txt
|
63 |
+
@%DELIM% >> results.txt
|
64 |
+
|
65 |
+
FINDSTR "Path: Length: Requests --" results.txt > results_summary.txt
|
66 |
+
|
67 |
+
START %TXTVIEWER% results_summary.txt
|
lib/Minify/min_extras/ab_tests/test_memcache.bat
ADDED
@@ -0,0 +1,13 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
@SET PATH=%PATH%;C:\xampp\apache\bin;C:\Program Files\GnuWin32\bin
|
2 |
+
|
3 |
+
@SET DOMAIN=http://localhost/minify
|
4 |
+
|
5 |
+
@SET ABTESTS=%DOMAIN%/min_extras/ab_tests
|
6 |
+
|
7 |
+
DEL results.txt
|
8 |
+
|
9 |
+
DEL memcached_stats.txt
|
10 |
+
|
11 |
+
ab -d -S -c 100 -n 1000 %ABTESTS%/minify/test_memcache.php >> results.txt
|
12 |
+
|
13 |
+
START "C:\Program Files\Notepad++\notepad++.exe" memcached_stats.txt
|
lib/Minify/min_extras/ab_tests/type-map/.htaccess-dev
ADDED
@@ -0,0 +1,40 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
# turn off MultiViews if enabled
|
2 |
+
Options -MultiViews
|
3 |
+
|
4 |
+
# For *.var requests, negotiate using type-map
|
5 |
+
AddHandler type-map .var
|
6 |
+
|
7 |
+
# use custom extensions so existing handlers for .gz/.Z don't interfere
|
8 |
+
AddEncoding x-gzip .zg
|
9 |
+
AddEncoding x-compress .zc
|
10 |
+
AddEncoding deflate .zd
|
11 |
+
|
12 |
+
# Necessary to add charset while using type-map
|
13 |
+
AddType application/x-javascript;charset=utf-8 js
|
14 |
+
AddType text/css;charset=utf-8 css
|
15 |
+
|
16 |
+
# Below we remove the ETag header and set a far-off Expires
|
17 |
+
# header. Since clients will aggressively cache, make sure
|
18 |
+
# to modify the URL (querystring or via mod_rewrite) when
|
19 |
+
# the resource changes
|
20 |
+
|
21 |
+
# remove ETag
|
22 |
+
FileETag None
|
23 |
+
|
24 |
+
# requires mod_expires
|
25 |
+
ExpiresActive On
|
26 |
+
# sets Expires and Cache-Control: max-age, but not "public"
|
27 |
+
ExpiresDefault "access plus 1 year"
|
28 |
+
|
29 |
+
# requires mod_headers
|
30 |
+
# adds the "public" to Cache-Control.
|
31 |
+
Header set Cache-Control "public, max-age=31536000"
|
32 |
+
|
33 |
+
# requires mod_rewrite
|
34 |
+
RewriteEngine On
|
35 |
+
RewriteBase /_3rd_party/minify/web/test/statics
|
36 |
+
# IE 5 and 6 are the only ones we really care about
|
37 |
+
RewriteCond %{HTTP_USER_AGENT} MSIE\ [56]
|
38 |
+
# but not if it's got the SV1 patch or is really Opera
|
39 |
+
RewriteCond %{HTTP_USER_AGENT} !(\ SV1|Opera)
|
40 |
+
RewriteRule ^(.*)\.var$ $1 [L]
|
lib/Minify/min_extras/ab_tests/type-map/before.js
ADDED
@@ -0,0 +1,374 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
(function(){
|
2 |
+
/*
|
3 |
+
* jQuery 1.2.3 - New Wave Javascript
|
4 |
+
*
|
5 |
+
* Copyright (c) 2008 John Resig (jquery.com)
|
6 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
7 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
8 |
+
*
|
9 |
+
* $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
|
10 |
+
* $Rev: 4663 $
|
11 |
+
*/
|
12 |
+
if(window.jQuery)
|
13 |
+
var _jQuery=window.jQuery;var jQuery=window.jQuery=function(selector,context){return new jQuery.prototype.init(selector,context);};if(window.$)
|
14 |
+
var _$=window.$;window.$=jQuery;var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;var isSimple=/^.[^:#\[\.]*$/;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}else if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])
|
15 |
+
selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem)
|
16 |
+
if(elem.id!=match[3])
|
17 |
+
return jQuery().find(selector);else{this[0]=elem;this.length=1;return this;}
|
18 |
+
else
|
19 |
+
selector=[];}}else
|
20 |
+
return new jQuery(context).find(selector);}else if(jQuery.isFunction(selector))
|
21 |
+
return new jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(selector.constructor==Array&&selector||(selector.jquery||selector.length&&selector!=window&&!selector.nodeType&&selector[0]!=undefined&&selector[0].nodeType)&&jQuery.makeArray(selector)||[selector]);},jquery:"1.2.3",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;this.each(function(i){if(this==elem)
|
22 |
+
ret=i;});return ret;},attr:function(name,value,type){var options=name;if(name.constructor==String)
|
23 |
+
if(value==undefined)
|
24 |
+
return this.length&&jQuery[type||"attr"](this[0],name)||undefined;else{options={};options[name]=value;}
|
25 |
+
return this.each(function(i){for(name in options)
|
26 |
+
jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)
|
27 |
+
value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)
|
28 |
+
return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)
|
29 |
+
ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])
|
30 |
+
jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)
|
31 |
+
elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)
|
32 |
+
this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)
|
33 |
+
this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
|
34 |
+
return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)
|
35 |
+
this[expando]=null;});if(events===true)
|
36 |
+
this.find("*").andSelf().each(function(i){if(this.nodeType==3)
|
37 |
+
return;var events=jQuery.data(this,"events");for(var type in events)
|
38 |
+
for(var handler in events[type])
|
39 |
+
jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)
|
40 |
+
if(isSimple.test(selector))
|
41 |
+
return this.pushStack(jQuery.multiFilter(selector,this,true));else
|
42 |
+
selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return!selector?this:this.pushStack(jQuery.merge(this.get(),selector.constructor==String?jQuery(selector).get():selector.length!=undefined&&(!selector.nodeName||jQuery.nodeName(selector,"form"))?selector:[selector]));},is:function(selector){return selector?jQuery.multiFilter(selector,this).length>0:false;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)
|
43 |
+
return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)
|
44 |
+
return value;values.push(value);}}
|
45 |
+
return values;}else
|
46 |
+
return(this[0].value||"").replace(/\r/g,"");}
|
47 |
+
return undefined;}
|
48 |
+
return this.each(function(){if(this.nodeType!=1)
|
49 |
+
return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))
|
50 |
+
this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=value.constructor==Array?value:[value];jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)
|
51 |
+
this.selectedIndex=-1;}else
|
52 |
+
this.value=value;});},html:function(value){return value==undefined?(this.length?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value==null){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data==undefined&&this.length)
|
53 |
+
data=jQuery.data(this[0],key);return data==null&&parts[1]?this.data(parts[0]):data;}else
|
54 |
+
return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)
|
55 |
+
elems.reverse();}
|
56 |
+
var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))
|
57 |
+
obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script")){scripts=scripts.add(elem);}else{if(elem.nodeType==1)
|
58 |
+
scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.prototype.init.prototype=jQuery.prototype;function evalScript(i,elem){if(elem.src)
|
59 |
+
jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
|
60 |
+
jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)
|
61 |
+
elem.parentNode.removeChild(elem);}
|
62 |
+
jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}
|
63 |
+
if(typeof target!="object"&&typeof target!="function")
|
64 |
+
target={};if(length==1){target=this;i=0;}
|
65 |
+
for(;i<length;i++)
|
66 |
+
if((options=arguments[i])!=null)
|
67 |
+
for(var name in options){if(target===options[name])
|
68 |
+
continue;if(deep&&options[name]&&typeof options[name]=="object"&&target[name]&&!options[name].nodeType)
|
69 |
+
target[name]=jQuery.extend(target[name],options[name]);else if(options[name]!=undefined)
|
70 |
+
target[name]=options[name];}
|
71 |
+
return target;};var expando="jQuery"+(new Date()).getTime(),uuid=0,windowData={};var exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i;jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)
|
72 |
+
window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/function/i.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)
|
73 |
+
script.text=data;else
|
74 |
+
script.appendChild(document.createTextNode(data));head.appendChild(script);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)
|
75 |
+
id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])
|
76 |
+
jQuery.cache[id]={};if(data!=undefined)
|
77 |
+
jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])
|
78 |
+
break;if(!name)
|
79 |
+
jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)
|
80 |
+
elem.removeAttribute(expando);}
|
81 |
+
delete jQuery.cache[id];}},each:function(object,callback,args){if(args){if(object.length==undefined){for(var name in object)
|
82 |
+
if(callback.apply(object[name],args)===false)
|
83 |
+
break;}else
|
84 |
+
for(var i=0,length=object.length;i<length;i++)
|
85 |
+
if(callback.apply(object[i],args)===false)
|
86 |
+
break;}else{if(object.length==undefined){for(var name in object)
|
87 |
+
if(callback.call(object[name],name,object[name])===false)
|
88 |
+
break;}else
|
89 |
+
for(var i=0,length=object.length,value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}
|
90 |
+
return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))
|
91 |
+
value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))
|
92 |
+
elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)
|
93 |
+
elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}
|
94 |
+
callback.call(elem);for(var name in options)
|
95 |
+
elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}
|
96 |
+
if(jQuery(elem).is(":visible"))
|
97 |
+
getWH();else
|
98 |
+
jQuery.swap(elem,props,getWH);return Math.max(0,val);}
|
99 |
+
return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret;function color(elem){if(!jQuery.browser.safari)
|
100 |
+
return false;var ret=document.defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}
|
101 |
+
if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(elem.style,"opacity");return ret==""?"1":ret;}
|
102 |
+
if(jQuery.browser.opera&&name=="display"){var save=elem.style.outline;elem.style.outline="0 solid black";elem.style.outline=save;}
|
103 |
+
if(name.match(/float/i))
|
104 |
+
name=styleFloat;if(!force&&elem.style&&elem.style[name])
|
105 |
+
ret=elem.style[name];else if(document.defaultView&&document.defaultView.getComputedStyle){if(name.match(/float/i))
|
106 |
+
name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var getComputedStyle=document.defaultView.getComputedStyle(elem,null);if(getComputedStyle&&!color(elem))
|
107 |
+
ret=getComputedStyle.getPropertyValue(name);else{var swap=[],stack=[];for(var a=elem;a&&color(a);a=a.parentNode)
|
108 |
+
stack.unshift(a);for(var i=0;i<stack.length;i++)
|
109 |
+
if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}
|
110 |
+
ret=name=="display"&&swap[stack.length-1]!=null?"none":(getComputedStyle&&getComputedStyle.getPropertyValue(name))||"";for(var i=0;i<swap.length;i++)
|
111 |
+
if(swap[i]!=null)
|
112 |
+
stack[i].style.display=swap[i];}
|
113 |
+
if(name=="opacity"&&ret=="")
|
114 |
+
ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var style=elem.style.left,runtimeStyle=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;elem.style.left=ret||0;ret=elem.style.pixelLeft+"px";elem.style.left=style;elem.runtimeStyle.left=runtimeStyle;}}
|
115 |
+
return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')
|
116 |
+
context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)
|
117 |
+
return;if(elem.constructor==Number)
|
118 |
+
elem=elem.toString();if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)
|
119 |
+
div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)
|
120 |
+
if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)
|
121 |
+
tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))
|
122 |
+
div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}
|
123 |
+
elem=jQuery.makeArray(div.childNodes);}
|
124 |
+
if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))
|
125 |
+
return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)
|
126 |
+
ret.push(elem);else
|
127 |
+
ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)
|
128 |
+
return undefined;var fix=jQuery.isXMLDoc(elem)?{}:jQuery.props;if(name=="selected"&&jQuery.browser.safari)
|
129 |
+
elem.parentNode.selectedIndex;if(fix[name]){if(value!=undefined)
|
130 |
+
elem[fix[name]]=value;return elem[fix[name]];}else if(jQuery.browser.msie&&name=="style")
|
131 |
+
return jQuery.attr(elem.style,"cssText",value);else if(value==undefined&&jQuery.browser.msie&&jQuery.nodeName(elem,"form")&&(name=="action"||name=="method"))
|
132 |
+
return elem.getAttributeNode(name).nodeValue;else if(elem.tagName){if(value!=undefined){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)
|
133 |
+
throw"type property can't be changed";elem.setAttribute(name,""+value);}
|
134 |
+
if(jQuery.browser.msie&&/href|src/.test(name)&&!jQuery.isXMLDoc(elem))
|
135 |
+
return elem.getAttribute(name,2);return elem.getAttribute(name);}else{if(name=="opacity"&&jQuery.browser.msie){if(value!=undefined){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+
|
136 |
+
(parseFloat(value).toString()=="NaN"?"":"alpha(opacity="+value*100+")");}
|
137 |
+
return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100).toString():"";}
|
138 |
+
name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(value!=undefined)
|
139 |
+
elem[name]=value;return elem[name];}},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(typeof array!="array")
|
140 |
+
for(var i=0,length=array.length;i<length;i++)
|
141 |
+
ret.push(array[i]);else
|
142 |
+
ret=array.slice(0);return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)
|
143 |
+
if(array[i]==elem)
|
144 |
+
return i;return-1;},merge:function(first,second){if(jQuery.browser.msie){for(var i=0;second[i];i++)
|
145 |
+
if(second[i].nodeType!=8)
|
146 |
+
first.push(second[i]);}else
|
147 |
+
for(var i=0;second[i];i++)
|
148 |
+
first.push(second[i]);return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}
|
149 |
+
return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)
|
150 |
+
if(!inv&&callback(elems[i],i)||inv&&!callback(elems[i],i))
|
151 |
+
ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!==null&&value!=undefined){if(value.constructor!=Array)
|
152 |
+
value=[value];ret=ret.concat(value);}}
|
153 |
+
return ret;}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,innerHTML:"innerHTML",className:"className",value:"value",disabled:"disabled",checked:"checked",readonly:"readOnly",selected:"selected",maxlength:"maxLength",selectedIndex:"selectedIndex",defaultValue:"defaultValue",tagName:"tagName",nodeName:"nodeName"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")
|
154 |
+
ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)
|
155 |
+
jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)
|
156 |
+
this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)
|
157 |
+
this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)
|
158 |
+
this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}
|
159 |
+
return cur;},find:function(t,context){if(typeof t!="string")
|
160 |
+
return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)
|
161 |
+
return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false;var re=quickChild;var m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)
|
162 |
+
for(var c=ret[i].firstChild;c;c=c.nextSibling)
|
163 |
+
if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))
|
164 |
+
r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)
|
165 |
+
if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}
|
166 |
+
if(m=="+")break;}}
|
167 |
+
ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}
|
168 |
+
if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}
|
169 |
+
m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])
|
170 |
+
oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")
|
171 |
+
tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}
|
172 |
+
if(m[1]==".")
|
173 |
+
r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)
|
174 |
+
if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}
|
175 |
+
r=tmp;}
|
176 |
+
ret=r;}
|
177 |
+
t=t.replace(re2,"");}}
|
178 |
+
if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}
|
179 |
+
if(t)
|
180 |
+
ret=[];if(ret&&context==ret[0])
|
181 |
+
ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)
|
182 |
+
tmp.push(r[i]);}
|
183 |
+
return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}
|
184 |
+
if(!m)
|
185 |
+
break;if(m[1]==":"&&m[2]=="not")
|
186 |
+
r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")
|
187 |
+
r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))
|
188 |
+
z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)
|
189 |
+
tmp.push(a);}
|
190 |
+
r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)
|
191 |
+
if(n.nodeType==1)
|
192 |
+
n.nodeIndex=c++;merge[id]=true;}
|
193 |
+
var add=false;if(first==0){if(node.nodeIndex==last)
|
194 |
+
add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)
|
195 |
+
add=true;if(add^not)
|
196 |
+
tmp.push(node);}
|
197 |
+
r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")
|
198 |
+
fn=fn[m[2]];if(typeof fn=="string")
|
199 |
+
fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}
|
200 |
+
return{r:r,t:t};},dir:function(elem,dir){var matched=[];var cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)
|
201 |
+
matched.push(cur);cur=cur[dir];}
|
202 |
+
return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])
|
203 |
+
if(cur.nodeType==1&&++num==result)
|
204 |
+
break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&(!elem||n!=elem))
|
205 |
+
r.push(n);}
|
206 |
+
return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)
|
207 |
+
return;if(jQuery.browser.msie&&elem.setInterval!=undefined)
|
208 |
+
elem=window;if(!handler.guid)
|
209 |
+
handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=function(){return fn.apply(this,arguments);};handler.data=data;handler.guid=fn.guid;}
|
210 |
+
var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){var val;if(typeof jQuery=="undefined"||jQuery.event.triggered)
|
211 |
+
return val;val=jQuery.event.handle.apply(arguments.callee.elem,arguments);return val;});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)
|
212 |
+
elem.addEventListener(type,handle,false);else if(elem.attachEvent)
|
213 |
+
elem.attachEvent("on"+type,handle);}}
|
214 |
+
handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)
|
215 |
+
return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))
|
216 |
+
for(var type in events)
|
217 |
+
this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}
|
218 |
+
jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)
|
219 |
+
delete events[type][handler.guid];else
|
220 |
+
for(handler in events[type])
|
221 |
+
if(!parts[1]||events[type][handler].type==parts[1])
|
222 |
+
delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)
|
223 |
+
elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)
|
224 |
+
elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}
|
225 |
+
ret=null;delete events[type];}}});}
|
226 |
+
for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data||[]);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}
|
227 |
+
if(!elem){if(this.global[type])
|
228 |
+
jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)
|
229 |
+
return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event)
|
230 |
+
data.unshift(this.fix({type:type,target:elem}));data[0].type=type;if(exclusive)
|
231 |
+
data[0].exclusive=true;if(jQuery.isFunction(jQuery.data(elem,"handle")))
|
232 |
+
val=jQuery.data(elem,"handle").apply(elem,data);if(!fn&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)
|
233 |
+
val=false;if(event)
|
234 |
+
data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)
|
235 |
+
val=ret;}
|
236 |
+
if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}
|
237 |
+
this.triggered=false;}
|
238 |
+
return val;},handle:function(event){var val;event=jQuery.event.fix(event||window.event||{});var parts=event.type.split(".");event.type=parts[0];var handlers=jQuery.data(this,"events")&&jQuery.data(this,"events")[event.type],args=Array.prototype.slice.call(arguments,1);args.unshift(event);for(var j in handlers){var handler=handlers[j];args[0].handler=handler;args[0].data=handler.data;if(!parts[1]&&!event.exclusive||handler.type==parts[1]){var ret=handler.apply(this,args);if(val!==false)
|
239 |
+
val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}
|
240 |
+
if(jQuery.browser.msie)
|
241 |
+
event.target=event.preventDefault=event.stopPropagation=event.handler=event.data=null;return val;},fix:function(event){var originalEvent=event;event=jQuery.extend({},originalEvent);event.preventDefault=function(){if(originalEvent.preventDefault)
|
242 |
+
originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)
|
243 |
+
originalEvent.stopPropagation();originalEvent.cancelBubble=true;};if(!event.target)
|
244 |
+
event.target=event.srcElement||document;if(event.target.nodeType==3)
|
245 |
+
event.target=originalEvent.target.parentNode;if(!event.relatedTarget&&event.fromElement)
|
246 |
+
event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}
|
247 |
+
if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))
|
248 |
+
event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)
|
249 |
+
event.metaKey=event.ctrlKey;if(!event.which&&event.button)
|
250 |
+
event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;arguments[0].type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){return this.each(function(){jQuery.event.add(this,type,function(event){jQuery(this).unbind(event);return(fn||data).apply(this,arguments);},fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){if(this[0])
|
251 |
+
return jQuery.event.trigger(type,data,this[0],false,fn);return undefined;},toggle:function(){var args=arguments;return this.click(function(event){this.lastToggle=0==this.lastToggle?1:0;event.preventDefault();return args[this.lastToggle].apply(this,arguments)||false;});},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)
|
252 |
+
fn.call(document,jQuery);else
|
253 |
+
jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.apply(document);});jQuery.readyList=null;}
|
254 |
+
jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)
|
255 |
+
document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}
|
256 |
+
jQuery.ready();})();if(jQuery.browser.opera)
|
257 |
+
document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)
|
258 |
+
if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}
|
259 |
+
jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}
|
260 |
+
if(numStyles===undefined)
|
261 |
+
numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}
|
262 |
+
jQuery.ready();})();}
|
263 |
+
jQuery.event.add(window,"load",jQuery.ready);}
|
264 |
+
jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}
|
265 |
+
return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({load:function(url,params,callback){if(jQuery.isFunction(url))
|
266 |
+
return this.bind("load",url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}
|
267 |
+
callback=callback||function(){};var type="GET";if(params)
|
268 |
+
if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}
|
269 |
+
var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")
|
270 |
+
self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=(new Date).getTime();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}
|
271 |
+
return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}
|
272 |
+
return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){var jsonp,jsre=/=\?(&|$)/g,status,data;s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));if(s.data&&s.processData&&typeof s.data!="string")
|
273 |
+
s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(s.type.toLowerCase()=="get"){if(!s.url.match(jsre))
|
274 |
+
s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))
|
275 |
+
s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}
|
276 |
+
if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)
|
277 |
+
s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}
|
278 |
+
if(head)
|
279 |
+
head.removeChild(script);};}
|
280 |
+
if(s.dataType=="script"&&s.cache==null)
|
281 |
+
s.cache=false;if(s.cache===false&&s.type.toLowerCase()=="get"){var ts=(new Date()).getTime();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}
|
282 |
+
if(s.data&&s.type.toLowerCase()=="get"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}
|
283 |
+
if(s.global&&!jQuery.active++)
|
284 |
+
jQuery.event.trigger("ajaxStart");if((!s.url.indexOf("http")||!s.url.indexOf("//"))&&s.dataType=="script"&&s.type.toLowerCase()=="get"){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)
|
285 |
+
script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}
|
286 |
+
head.appendChild(script);return undefined;}
|
287 |
+
var requestDone=false;var xml=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();xml.open(s.type,s.url,s.async,s.username,s.password);try{if(s.data)
|
288 |
+
xml.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)
|
289 |
+
xml.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xml.setRequestHeader("X-Requested-With","XMLHttpRequest");xml.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}
|
290 |
+
if(s.beforeSend)
|
291 |
+
s.beforeSend(xml);if(s.global)
|
292 |
+
jQuery.event.trigger("ajaxSend",[xml,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xml&&(xml.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}
|
293 |
+
status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xml)&&"error"||s.ifModified&&jQuery.httpNotModified(xml,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xml,s.dataType);}catch(e){status="parsererror";}}
|
294 |
+
if(status=="success"){var modRes;try{modRes=xml.getResponseHeader("Last-Modified");}catch(e){}
|
295 |
+
if(s.ifModified&&modRes)
|
296 |
+
jQuery.lastModified[s.url]=modRes;if(!jsonp)
|
297 |
+
success();}else
|
298 |
+
jQuery.handleError(s,xml,status);complete();if(s.async)
|
299 |
+
xml=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)
|
300 |
+
setTimeout(function(){if(xml){xml.abort();if(!requestDone)
|
301 |
+
onreadystatechange("timeout");}},s.timeout);}
|
302 |
+
try{xml.send(s.data);}catch(e){jQuery.handleError(s,xml,null,e);}
|
303 |
+
if(!s.async)
|
304 |
+
onreadystatechange();function success(){if(s.success)
|
305 |
+
s.success(data,status);if(s.global)
|
306 |
+
jQuery.event.trigger("ajaxSuccess",[xml,s]);}
|
307 |
+
function complete(){if(s.complete)
|
308 |
+
s.complete(xml,status);if(s.global)
|
309 |
+
jQuery.event.trigger("ajaxComplete",[xml,s]);if(s.global&&!--jQuery.active)
|
310 |
+
jQuery.event.trigger("ajaxStop");}
|
311 |
+
return xml;},handleError:function(s,xml,status,e){if(s.error)s.error(xml,status,e);if(s.global)
|
312 |
+
jQuery.event.trigger("ajaxError",[xml,s,e]);},active:0,httpSuccess:function(r){try{return!r.status&&location.protocol=="file:"||(r.status>=200&&r.status<300)||r.status==304||r.status==1223||jQuery.browser.safari&&r.status==undefined;}catch(e){}
|
313 |
+
return false;},httpNotModified:function(xml,url){try{var xmlRes=xml.getResponseHeader("Last-Modified");return xml.status==304||xmlRes==jQuery.lastModified[url]||jQuery.browser.safari&&xml.status==undefined;}catch(e){}
|
314 |
+
return false;},httpData:function(r,type){var ct=r.getResponseHeader("content-type");var xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0;var data=xml?r.responseXML:r.responseText;if(xml&&data.documentElement.tagName=="parsererror")
|
315 |
+
throw"parsererror";if(type=="script")
|
316 |
+
jQuery.globalEval(data);if(type=="json")
|
317 |
+
data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)
|
318 |
+
jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
|
319 |
+
for(var j in a)
|
320 |
+
if(a[j]&&a[j].constructor==Array)
|
321 |
+
jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
|
322 |
+
s.push(encodeURIComponent(j)+"="+encodeURIComponent(a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")
|
323 |
+
this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle(fn,fn2):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)
|
324 |
+
return false;var opt=jQuery.extend({},optall);var hidden=jQuery(this).is(":hidden"),self=this;for(var p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)
|
325 |
+
return jQuery.isFunction(opt.complete)&&opt.complete.apply(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}
|
326 |
+
if(opt.overflow!=null)
|
327 |
+
this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))
|
328 |
+
e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}
|
329 |
+
if(parts[1])
|
330 |
+
end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
|
331 |
+
e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}
|
332 |
+
if(!type||(typeof type=="string"&&!fn))
|
333 |
+
return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)
|
334 |
+
queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)
|
335 |
+
fn.apply(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)
|
336 |
+
this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)
|
337 |
+
if(timers[i].elem==this){if(gotoEnd)
|
338 |
+
timers[i](true);timers.splice(i,1);}});if(!gotoEnd)
|
339 |
+
this.dequeue();return this;}});var queue=function(elem,type,array){if(!elem)
|
340 |
+
return undefined;type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)
|
341 |
+
q=jQuery.data(elem,type+"queue",array?jQuery.makeArray(array):[]);return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)
|
342 |
+
q[0].apply(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:{slow:600,fast:200}[opt.duration])||400;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)
|
343 |
+
jQuery(this).dequeue();if(jQuery.isFunction(opt.old))
|
344 |
+
opt.old.apply(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)
|
345 |
+
options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)
|
346 |
+
this.options.step.apply(this.elem,[this.now,this]);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")
|
347 |
+
this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)
|
348 |
+
return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=(new Date()).getTime();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}
|
349 |
+
t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)
|
350 |
+
if(!timers[i]())
|
351 |
+
timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")
|
352 |
+
this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=(new Date()).getTime();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)
|
353 |
+
if(this.options.curAnim[i]!==true)
|
354 |
+
done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")
|
355 |
+
this.elem.style.display="block";}
|
356 |
+
if(this.options.hide)
|
357 |
+
this.elem.style.display="none";if(this.options.hide||this.options.show)
|
358 |
+
for(var p in this.options.curAnim)
|
359 |
+
jQuery.attr(this.elem.style,p,this.options.orig[p]);}
|
360 |
+
if(done&&jQuery.isFunction(this.options.complete))
|
361 |
+
this.options.complete.apply(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}
|
362 |
+
return true;}};jQuery.fx.step={scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}};jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),fixed=jQuery.css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)
|
363 |
+
border(offsetParent);if(!fixed&&jQuery.css(offsetParent,"position")=="fixed")
|
364 |
+
fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}
|
365 |
+
while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(jQuery.css(parent,"display")))
|
366 |
+
add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&jQuery.css(parent,"overflow")!="visible")
|
367 |
+
border(parent);parent=parent.parentNode;}
|
368 |
+
if((safari2&&(fixed||jQuery.css(offsetChild,"position")=="absolute"))||(mozilla&&jQuery.css(offsetChild,"position")!="absolute"))
|
369 |
+
add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)
|
370 |
+
add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}
|
371 |
+
results={top:top,left:left};}
|
372 |
+
function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}
|
373 |
+
function add(l,t){left+=parseInt(l)||0;top+=parseInt(t)||0;}
|
374 |
+
return results;};})();
|
lib/Minify/min_extras/ab_tests/type-map/before.js.var
ADDED
@@ -0,0 +1,14 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
URI: before.js.zd
|
2 |
+
Content-Type: application/x-javascript; qs=0.9
|
3 |
+
Content-Encoding: deflate
|
4 |
+
|
5 |
+
URI: before.js.zg
|
6 |
+
Content-Type: application/x-javascript; qs=0.8
|
7 |
+
Content-Encoding: x-gzip
|
8 |
+
|
9 |
+
URI: before.js.zc
|
10 |
+
Content-Type: application/x-javascript; qs=0.7
|
11 |
+
Content-Encoding: x-compress
|
12 |
+
|
13 |
+
URI: before.js
|
14 |
+
Content-Type: application/x-javascript; qs=0.6
|
lib/Minify/min_extras/ab_tests/type-map/before.js.zc
ADDED
Binary file
|
lib/Minify/min_extras/ab_tests/type-map/before.js.zd
ADDED
Binary file
|
lib/Minify/min_extras/ab_tests/type-map/before.js.zg
ADDED
Binary file
|
lib/Minify/min_extras/ab_tests/v1.0/minify.php
ADDED
@@ -0,0 +1,500 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
// ab test of Minify 1.0, mostly to see how fast it can serve server-cached files.
|
3 |
+
|
4 |
+
require '../../config.php';
|
5 |
+
|
6 |
+
define('MINIFY_BASE_DIR', realpath(
|
7 |
+
dirname(__FILE__) . '/../minify'
|
8 |
+
));
|
9 |
+
define('MINIFY_CACHE_DIR', $minifyCachePath);
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Minify - Combines, minifies, and caches JavaScript and CSS files on demand.
|
13 |
+
*
|
14 |
+
* See http://code.google.com/p/minify/ for usage instructions.
|
15 |
+
*
|
16 |
+
* This library was inspired by jscsscomp by Maxim Martynyuk <flashkot@mail.ru>
|
17 |
+
* and by the article "Supercharged JavaScript" by Patrick Hunlock
|
18 |
+
* <wb@hunlock.com>.
|
19 |
+
*
|
20 |
+
* JSMin was originally written by Douglas Crockford <douglas@crockford.com>.
|
21 |
+
*
|
22 |
+
* Requires PHP 5.2.1+.
|
23 |
+
*
|
24 |
+
* @package Minify
|
25 |
+
* @author Ryan Grove <ryan@wonko.com>
|
26 |
+
* @copyright 2007 Ryan Grove. All rights reserved.
|
27 |
+
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
28 |
+
* @version 1.1.0 (?)
|
29 |
+
* @link http://code.google.com/p/minify/
|
30 |
+
*/
|
31 |
+
|
32 |
+
if (!defined('MINIFY_BASE_DIR')) {
|
33 |
+
/**
|
34 |
+
* Base path from which all relative file paths should be resolved. By default
|
35 |
+
* this is set to the document root.
|
36 |
+
*/
|
37 |
+
define('MINIFY_BASE_DIR', realpath($_SERVER['DOCUMENT_ROOT']));
|
38 |
+
}
|
39 |
+
|
40 |
+
if (!defined('MINIFY_CACHE_DIR')) {
|
41 |
+
/** Directory where compressed files will be cached. */
|
42 |
+
define('MINIFY_CACHE_DIR', sys_get_temp_dir());
|
43 |
+
}
|
44 |
+
|
45 |
+
if (!defined('MINIFY_ENCODING')) {
|
46 |
+
/** Character set to use when outputting the minified files. */
|
47 |
+
define('MINIFY_ENCODING', 'utf-8');
|
48 |
+
}
|
49 |
+
|
50 |
+
if (!defined('MINIFY_MAX_FILES')) {
|
51 |
+
/** Maximum number of files to combine in one request. */
|
52 |
+
define('MINIFY_MAX_FILES', 16);
|
53 |
+
}
|
54 |
+
|
55 |
+
if (!defined('MINIFY_REWRITE_CSS_URLS')) {
|
56 |
+
/**
|
57 |
+
* Whether or not Minify should attempt to rewrite relative URLs used in CSS
|
58 |
+
* files so that they continue to point to the correct location after the file
|
59 |
+
* is combined and minified.
|
60 |
+
*
|
61 |
+
* Minify is pretty good at getting this right, but occasionally it can make
|
62 |
+
* mistakes. If you find that URL rewriting results in problems, you should
|
63 |
+
* disable it.
|
64 |
+
*/
|
65 |
+
define('MINIFY_REWRITE_CSS_URLS', true);
|
66 |
+
}
|
67 |
+
|
68 |
+
if (!defined('MINIFY_USE_CACHE')) {
|
69 |
+
/**
|
70 |
+
* Whether or not Minify should use a disk-based cache to increase
|
71 |
+
* performance.
|
72 |
+
*/
|
73 |
+
define('MINIFY_USE_CACHE', true);
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Minify is a library for combining, minifying, and caching JavaScript and CSS
|
78 |
+
* files on demand before sending them to a web browser.
|
79 |
+
*
|
80 |
+
* @package Minify
|
81 |
+
* @author Ryan Grove <ryan@wonko.com>
|
82 |
+
* @copyright 2007 Ryan Grove. All rights reserved.
|
83 |
+
* @license http://opensource.org/licenses/bsd-license.php New BSD License
|
84 |
+
* @version 1.1.0 (?)
|
85 |
+
* @link http://code.google.com/p/minify/
|
86 |
+
*/
|
87 |
+
class Minify {
|
88 |
+
const TYPE_CSS = 'text/css';
|
89 |
+
const TYPE_HTML = 'text/html';
|
90 |
+
const TYPE_JS = 'text/javascript';
|
91 |
+
|
92 |
+
protected $files = array();
|
93 |
+
protected $type = self::TYPE_JS;
|
94 |
+
|
95 |
+
// -- Public Static Methods --------------------------------------------------
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Combines, minifies, and outputs the requested files.
|
99 |
+
*
|
100 |
+
* Inspects the $_GET array for a 'files' entry containing a comma-separated
|
101 |
+
* list and uses this as the set of files to be combined and minified.
|
102 |
+
*/
|
103 |
+
public static function handleRequest() {
|
104 |
+
// 404 if no files were requested.
|
105 |
+
if (!isset($_GET['files'])) {
|
106 |
+
header('HTTP/1.0 404 Not Found');
|
107 |
+
exit;
|
108 |
+
}
|
109 |
+
|
110 |
+
$files = array_map('trim', explode(',', $_GET['files'], MINIFY_MAX_FILES));
|
111 |
+
|
112 |
+
// 404 if the $files array is empty for some weird reason.
|
113 |
+
if (!count($files)) {
|
114 |
+
header('HTTP/1.0 404 Not Found');
|
115 |
+
exit;
|
116 |
+
}
|
117 |
+
|
118 |
+
// Determine the content type based on the extension of the first file
|
119 |
+
// requested.
|
120 |
+
if (preg_match('/\.js$/iD', $files[0])) {
|
121 |
+
$type = self::TYPE_JS;
|
122 |
+
} else if (preg_match('/\.css$/iD', $files[0])) {
|
123 |
+
$type = self::TYPE_CSS;
|
124 |
+
} else {
|
125 |
+
$type = self::TYPE_HTML;
|
126 |
+
}
|
127 |
+
|
128 |
+
// Minify and spit out the result.
|
129 |
+
try {
|
130 |
+
$minify = new Minify($type, $files);
|
131 |
+
|
132 |
+
header("Content-Type: $type;charset=".MINIFY_ENCODING);
|
133 |
+
|
134 |
+
$minify->browserCache();
|
135 |
+
echo $minify->combine();
|
136 |
+
exit;
|
137 |
+
}
|
138 |
+
catch (MinifyException $e) {
|
139 |
+
header('HTTP/1.0 404 Not Found');
|
140 |
+
echo htmlentities($e->getMessage());
|
141 |
+
exit;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Minifies the specified string and returns it.
|
147 |
+
*
|
148 |
+
* @param string $string JavaScript, CSS, or HTML string to minify
|
149 |
+
* @param string $type content type of the string (Minify::TYPE_CSS,
|
150 |
+
* Minify::TYPE_HTML, or Minify::TYPE_JS)
|
151 |
+
* @return string minified string
|
152 |
+
*/
|
153 |
+
public static function min($string, $type = self::TYPE_JS) {
|
154 |
+
switch ($type) {
|
155 |
+
case self::TYPE_CSS:
|
156 |
+
return self::minifyCSS($string);
|
157 |
+
break;
|
158 |
+
|
159 |
+
case self::TYPE_HTML:
|
160 |
+
return self::minifyHTML($string);
|
161 |
+
break;
|
162 |
+
|
163 |
+
case self::TYPE_JS:
|
164 |
+
return self::minifyJS($string);
|
165 |
+
break;
|
166 |
+
}
|
167 |
+
|
168 |
+
return $string;
|
169 |
+
}
|
170 |
+
|
171 |
+
// -- Protected Static Methods -----------------------------------------------
|
172 |
+
|
173 |
+
/**
|
174 |
+
* Minifies the specified CSS string and returns it.
|
175 |
+
*
|
176 |
+
* @param string $css CSS string
|
177 |
+
* @return string minified string
|
178 |
+
* @see minify()
|
179 |
+
* @see minifyJS()
|
180 |
+
*/
|
181 |
+
protected static function minifyCSS($css) {
|
182 |
+
// Compress whitespace.
|
183 |
+
$css = preg_replace('/\s+/', ' ', $css);
|
184 |
+
|
185 |
+
// Remove comments.
|
186 |
+
$css = preg_replace('/\/\*.*?\*\//', '', $css);
|
187 |
+
|
188 |
+
return trim($css);
|
189 |
+
}
|
190 |
+
|
191 |
+
protected static function minifyHTML($html) {
|
192 |
+
require_once dirname(__FILE__).'/lib/htmlmin.php';
|
193 |
+
return HTMLMin::minify($html);
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Minifies the specified JavaScript string and returns it.
|
198 |
+
*
|
199 |
+
* @param string $js JavaScript string
|
200 |
+
* @return string minified string
|
201 |
+
* @see minify()
|
202 |
+
* @see minifyCSS()
|
203 |
+
*/
|
204 |
+
protected static function minifyJS($js) {
|
205 |
+
require_once dirname(__FILE__).'/../../../min/lib/JSMin.php';
|
206 |
+
return JSMin::minify($js);
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Rewrites relative URLs in the specified CSS string to point to the correct
|
211 |
+
* location. URLs are assumed to be relative to the absolute path specified in
|
212 |
+
* the $path parameter.
|
213 |
+
*
|
214 |
+
* @param string $css CSS string
|
215 |
+
* @param string $path absolute path to which URLs are relative (should be a
|
216 |
+
* directory, not a file)
|
217 |
+
* @return string CSS string with rewritten URLs
|
218 |
+
*/
|
219 |
+
protected static function rewriteCSSUrls($css, $path) {
|
220 |
+
/*
|
221 |
+
Parentheses, commas, whitespace chars, single quotes, and double quotes are
|
222 |
+
escaped with a backslash as described in the CSS spec:
|
223 |
+
http://www.w3.org/TR/REC-CSS1#url
|
224 |
+
*/
|
225 |
+
$relativePath = preg_replace('/([\(\),\s\'"])/', '\\\$1',
|
226 |
+
str_replace(MINIFY_BASE_DIR, '', $path));
|
227 |
+
|
228 |
+
|
229 |
+
return preg_replace('/url\(\s*[\'"]?\/?(.+?)[\'"]?\s*\)/i', 'url('.
|
230 |
+
$relativePath.'/$1)', $css);
|
231 |
+
}
|
232 |
+
|
233 |
+
// -- Public Instance Methods ------------------------------------------------
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Instantiates a new Minify object. A filename can be in the form of a
|
237 |
+
* relative path or a URL that resolves to the same site that hosts Minify.
|
238 |
+
*
|
239 |
+
* @param string $type content type of the specified files (either
|
240 |
+
* Minify::TYPE_CSS or Minify::TYPE_JS)
|
241 |
+
* @param array|string $files filename or array of filenames to be minified
|
242 |
+
*/
|
243 |
+
public function __construct($type = self::TYPE_JS, $files = array()) {
|
244 |
+
if ($type !== self::TYPE_JS && $type !== self::TYPE_CSS) {
|
245 |
+
throw new MinifyInvalidArgumentException('Invalid argument ($type): '.
|
246 |
+
$type);
|
247 |
+
}
|
248 |
+
|
249 |
+
$this->type = $type;
|
250 |
+
|
251 |
+
if (count((array) $files)) {
|
252 |
+
$this->addFile($files);
|
253 |
+
}
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Adds the specified filename or array of filenames to the list of files to
|
258 |
+
* be minified. A filename can be in the form of a relative path or a URL
|
259 |
+
* that resolves to the same site that hosts Minify.
|
260 |
+
*
|
261 |
+
* @param array|string $files filename or array of filenames
|
262 |
+
* @see getFiles()
|
263 |
+
* @see removeFile()
|
264 |
+
*/
|
265 |
+
public function addFile($files) {
|
266 |
+
$files = @array_map(array($this, 'resolveFilePath'), (array) $files);
|
267 |
+
$this->files = array_unique(array_merge($this->files, $files));
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Attempts to serve the combined, minified files from the cache if possible.
|
272 |
+
*
|
273 |
+
* This method first checks the ETag value and If-Modified-Since timestamp
|
274 |
+
* sent by the browser and exits with an HTTP "304 Not Modified" response if
|
275 |
+
* the requested files haven't changed since they were last sent to the
|
276 |
+
* client.
|
277 |
+
*
|
278 |
+
* If the browser hasn't cached the content, we check to see if it's been
|
279 |
+
* cached on the server and, if so, we send the cached content and exit.
|
280 |
+
*
|
281 |
+
* If neither the client nor the server has the content in its cache, we don't
|
282 |
+
* do anything.
|
283 |
+
*
|
284 |
+
* @return bool
|
285 |
+
*/
|
286 |
+
public function browserCache() {
|
287 |
+
$hash = $this->getHash();
|
288 |
+
$lastModified = $this->getLastModified();
|
289 |
+
|
290 |
+
$lastModifiedGMT = gmdate('D, d M Y H:i:s', $lastModified).' GMT';
|
291 |
+
|
292 |
+
// Check/set the ETag.
|
293 |
+
$etag = $hash.'_'.$lastModified;
|
294 |
+
|
295 |
+
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
296 |
+
if (strpos($_SERVER['HTTP_IF_NONE_MATCH'], $etag) !== false) {
|
297 |
+
header("Last-Modified: $lastModifiedGMT", true, 304);
|
298 |
+
exit;
|
299 |
+
}
|
300 |
+
}
|
301 |
+
|
302 |
+
header('ETag: "'.$etag.'"');
|
303 |
+
|
304 |
+
// Check If-Modified-Since.
|
305 |
+
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
306 |
+
if ($lastModified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
307 |
+
header("Last-Modified: $lastModifiedGMT", true, 304);
|
308 |
+
exit;
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
header("Last-Modified: $lastModifiedGMT");
|
313 |
+
|
314 |
+
return false;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Combines and returns the contents of all files that have been added with
|
319 |
+
* addFile() or via this class's constructor.
|
320 |
+
*
|
321 |
+
* If MINIFY_USE_CACHE is true, the content will be returned from the server's
|
322 |
+
* cache if the cache is up to date; otherwise the new content will be saved
|
323 |
+
* to the cache for future use.
|
324 |
+
*
|
325 |
+
* @param bool $minify minify the combined contents before returning them
|
326 |
+
* @return string combined file contents
|
327 |
+
*/
|
328 |
+
public function combine($minify = true) {
|
329 |
+
// Return contents from server cache if possible.
|
330 |
+
if (MINIFY_USE_CACHE) {
|
331 |
+
if ($cacheResult = $this->serverCache(true)) {
|
332 |
+
return $cacheResult;
|
333 |
+
}
|
334 |
+
}
|
335 |
+
|
336 |
+
// Combine contents.
|
337 |
+
$combined = array();
|
338 |
+
|
339 |
+
foreach($this->files as $file) {
|
340 |
+
if ($this->type === self::TYPE_CSS && MINIFY_REWRITE_CSS_URLS) {
|
341 |
+
// Rewrite relative CSS URLs.
|
342 |
+
$combined[] = self::rewriteCSSUrls(file_get_contents($file),
|
343 |
+
dirname($file));
|
344 |
+
}
|
345 |
+
else {
|
346 |
+
$combined[] = file_get_contents($file);
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
$combined = $minify ? self::min(implode("\n", $combined), $this->type) :
|
351 |
+
implode("\n", $combined);
|
352 |
+
|
353 |
+
// Save combined contents to the cache.
|
354 |
+
if (MINIFY_USE_CACHE) {
|
355 |
+
$cacheFile = MINIFY_CACHE_DIR.'/minify_'.$this->getHash();
|
356 |
+
@file_put_contents($cacheFile, $combined, LOCK_EX);
|
357 |
+
}
|
358 |
+
|
359 |
+
return $combined;
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Gets an array of absolute pathnames of all files that have been added with
|
364 |
+
* addFile() or via this class's constructor.
|
365 |
+
*
|
366 |
+
* @return array array of absolute pathnames
|
367 |
+
* @see addFile()
|
368 |
+
* @see removeFile()
|
369 |
+
*/
|
370 |
+
public function getFiles() {
|
371 |
+
return $this->files;
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Gets the MD5 hash of the concatenated filenames from the list of files to
|
376 |
+
* be minified.
|
377 |
+
*/
|
378 |
+
public function getHash() {
|
379 |
+
return hash('md5', implode('', $this->files));
|
380 |
+
}
|
381 |
+
|
382 |
+
/**
|
383 |
+
* Gets the timestamp of the most recently modified file.
|
384 |
+
*
|
385 |
+
* @return int timestamp
|
386 |
+
*/
|
387 |
+
public function getLastModified() {
|
388 |
+
$lastModified = 0;
|
389 |
+
|
390 |
+
// Get the timestamp of the most recently modified file.
|
391 |
+
foreach($this->files as $file) {
|
392 |
+
$modified = filemtime($file);
|
393 |
+
|
394 |
+
if ($modified !== false && $modified > $lastModified) {
|
395 |
+
$lastModified = $modified;
|
396 |
+
}
|
397 |
+
}
|
398 |
+
|
399 |
+
return $lastModified;
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Removes the specified filename or array of filenames from the list of files
|
404 |
+
* to be minified.
|
405 |
+
*
|
406 |
+
* @param array|string $files filename or array of filenames
|
407 |
+
* @see addFile()
|
408 |
+
* @see getFiles()
|
409 |
+
*/
|
410 |
+
public function removeFile($files) {
|
411 |
+
$files = @array_map(array($this, 'resolveFilePath'), (array) $files);
|
412 |
+
$this->files = array_diff($this->files, $files);
|
413 |
+
}
|
414 |
+
|
415 |
+
/**
|
416 |
+
* Attempts to serve the combined, minified files from the server's disk-based
|
417 |
+
* cache if possible.
|
418 |
+
*
|
419 |
+
* @param bool $return return cached content as a string instead of outputting
|
420 |
+
* it to the client
|
421 |
+
* @return bool|string
|
422 |
+
*/
|
423 |
+
public function serverCache($return = false) {
|
424 |
+
$cacheFile = MINIFY_CACHE_DIR.'/minify_'.$this->getHash();
|
425 |
+
$lastModified = $this->getLastModified();
|
426 |
+
|
427 |
+
if (is_file($cacheFile) && $lastModified <= filemtime($cacheFile)) {
|
428 |
+
if ($return) {
|
429 |
+
return file_get_contents($cacheFile);
|
430 |
+
}
|
431 |
+
else {
|
432 |
+
echo file_get_contents($cacheFile);
|
433 |
+
exit;
|
434 |
+
}
|
435 |
+
}
|
436 |
+
|
437 |
+
|
438 |
+
return false;
|
439 |
+
}
|
440 |
+
|
441 |
+
// -- Protected Instance Methods ---------------------------------------------
|
442 |
+
|
443 |
+
/**
|
444 |
+
* Returns the canonicalized absolute pathname to the specified file or local
|
445 |
+
* URL.
|
446 |
+
*
|
447 |
+
* @param string $file relative file path
|
448 |
+
* @return string canonicalized absolute pathname
|
449 |
+
*/
|
450 |
+
protected function resolveFilePath($file) {
|
451 |
+
// Is this a URL?
|
452 |
+
if (preg_match('/^https?:\/\//i', $file)) {
|
453 |
+
if (!$parsedUrl = parse_url($file)) {
|
454 |
+
throw new MinifyInvalidUrlException("Invalid URL: $file");
|
455 |
+
}
|
456 |
+
|
457 |
+
// Does the server name match the local server name?
|
458 |
+
if (!isset($parsedUrl['host']) ||
|
459 |
+
$parsedUrl['host'] != $_SERVER['SERVER_NAME']) {
|
460 |
+
throw new MinifyInvalidUrlException('Non-local URL not supported: '.
|
461 |
+
$file);
|
462 |
+
}
|
463 |
+
|
464 |
+
// Get the file's absolute path.
|
465 |
+
$filepath = realpath(MINIFY_BASE_DIR.$parsedUrl['path']);
|
466 |
+
}
|
467 |
+
else {
|
468 |
+
// Get the file's absolute path.
|
469 |
+
$filepath = realpath(MINIFY_BASE_DIR.'/'.$file);
|
470 |
+
}
|
471 |
+
|
472 |
+
// Ensure that the file exists, that the path is under the base directory,
|
473 |
+
// that the file's extension is either '.css' or '.js', and that the file is
|
474 |
+
// actually readable.
|
475 |
+
if (!$filepath ||
|
476 |
+
!is_file($filepath) ||
|
477 |
+
!is_readable($filepath) ||
|
478 |
+
!preg_match('/^'.preg_quote(MINIFY_BASE_DIR, '/').'/', $filepath) ||
|
479 |
+
!preg_match('/\.(?:css|js)$/iD', $filepath)) {
|
480 |
+
|
481 |
+
// Even when the file exists, we still throw a
|
482 |
+
// MinifyFileNotFoundException in order to try to prevent an information
|
483 |
+
// disclosure vulnerability.
|
484 |
+
throw new MinifyFileNotFoundException("File not found: $file");
|
485 |
+
}
|
486 |
+
|
487 |
+
return $filepath;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
|
491 |
+
// -- Exception Classes --------------------------------------------------------
|
492 |
+
class MinifyException extends Exception {}
|
493 |
+
class MinifyFileNotFoundException extends MinifyException {}
|
494 |
+
class MinifyInvalidArgumentException extends MinifyException {}
|
495 |
+
class MinifyInvalidUrlException extends MinifyException {}
|
496 |
+
|
497 |
+
// -- Global Scope -------------------------------------------------------------
|
498 |
+
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
|
499 |
+
Minify::handleRequest();
|
500 |
+
}
|
lib/Minify/min_extras/config.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// using same lib path and cache path specified in /min/config.php
|
4 |
+
|
5 |
+
require dirname(__FILE__) . '/../min/config.php';
|
6 |
+
|
7 |
+
set_include_path($min_libPath . PATH_SEPARATOR . get_include_path());
|
8 |
+
|
9 |
+
$minifyCachePath = isset($min_cachePath)
|
10 |
+
? $min_cachePath
|
11 |
+
: '';
|
lib/Minify/min_extras/examples/1/_groupsSources.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$base = realpath(dirname(__FILE__) . '/..');
|
4 |
+
$groupsSources = array(
|
5 |
+
'js' => array(
|
6 |
+
"{$base}/lib.js"
|
7 |
+
,"{$base}/test space.js"
|
8 |
+
)
|
9 |
+
,'css' => array("{$base}/test.css")
|
10 |
+
);
|
11 |
+
unset($base);
|
lib/Minify/min_extras/examples/1/index.php
ADDED
@@ -0,0 +1,50 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
require '../../config.php';
|
3 |
+
require '_groupsSources.php';
|
4 |
+
|
5 |
+
require 'Minify/Build.php';
|
6 |
+
$jsBuild = new Minify_Build($groupsSources['js']);
|
7 |
+
$cssBuild = new Minify_Build($groupsSources['css']);
|
8 |
+
?>
|
9 |
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
10 |
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
11 |
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
12 |
+
<head>
|
13 |
+
<title>Minify Example 1</title>
|
14 |
+
<link rel="stylesheet" type="text/css" href="<?php echo $cssBuild->uri('m.php/css'); ?>" />
|
15 |
+
<style type="text/css">#cssFail {width:2.8em; overflow:hidden;}</style>
|
16 |
+
</head>
|
17 |
+
<body>
|
18 |
+
|
19 |
+
<?php if (! $minifyCachePath): ?>
|
20 |
+
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
21 |
+
<code>Minify::setCache()</code>. For the examples this can be set in
|
22 |
+
<code>config.php</code>.</p>
|
23 |
+
<?php endif; ?>
|
24 |
+
|
25 |
+
<h1>Minify Example 1 : Groups controller + Far-off Expires header</h1>
|
26 |
+
|
27 |
+
<p>In this example, we use a single config file <code>_groupsSources.php</code>
|
28 |
+
to specify files for minification. During HTML generation,
|
29 |
+
<code>Minify_Build</code> is used
|
30 |
+
to stamp the latest modification times onto the minify URLs. Our minify server,
|
31 |
+
<code>m.php</code>, then sends the content with far-off Expires headers.</p>
|
32 |
+
|
33 |
+
<p>If one of our sources is modified, its URL (particularly the query string) is
|
34 |
+
changed in the HTML document, causing the browser to request a new version.</p>
|
35 |
+
|
36 |
+
<h2>Minify tests</h2>
|
37 |
+
<ul>
|
38 |
+
<li id="cssFail"><span>FAIL</span>PASS</li>
|
39 |
+
<li id="jsFail1">FAIL</li>
|
40 |
+
</ul>
|
41 |
+
|
42 |
+
<h2>Test client cache</h2>
|
43 |
+
<p>When you <a href="">click here</a> to reload the page, your browser should
|
44 |
+
not have to re-download the minified files.</p>
|
45 |
+
|
46 |
+
<p style='text-align:right'><a href="../2/">example 2 »</a></p>
|
47 |
+
|
48 |
+
<script type="text/javascript" src="<?php echo $jsBuild->uri('m.php/js'); ?>"></script>
|
49 |
+
</body>
|
50 |
+
</html>
|
lib/Minify/min_extras/examples/1/m.php
ADDED
@@ -0,0 +1,14 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require '../../config.php';
|
4 |
+
require '_groupsSources.php';
|
5 |
+
require 'Minify.php';
|
6 |
+
|
7 |
+
if ($minifyCachePath) {
|
8 |
+
Minify::setCache($minifyCachePath);
|
9 |
+
}
|
10 |
+
|
11 |
+
Minify::serve('Groups', array(
|
12 |
+
'groups' => $groupsSources
|
13 |
+
,'setExpires' => time() + 86400 * 365
|
14 |
+
));
|
lib/Minify/min_extras/examples/2/_groupsSources.php
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$base = realpath(dirname(__FILE__) . '/..');
|
4 |
+
$groupsSources = array(
|
5 |
+
'js' => array(
|
6 |
+
"{$base}/lib.js"
|
7 |
+
,"{$base}/test space.js"
|
8 |
+
)
|
9 |
+
,'css' => array("{$base}/test.css")
|
10 |
+
);
|
11 |
+
unset($base);
|
lib/Minify/min_extras/examples/2/index.php
ADDED
@@ -0,0 +1,94 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
require '../../config.php';
|
3 |
+
require '_groupsSources.php';
|
4 |
+
|
5 |
+
require 'Minify/Build.php';
|
6 |
+
$jsBuild = new Minify_Build($groupsSources['js']);
|
7 |
+
$cssBuild = new Minify_Build($groupsSources['css']);
|
8 |
+
|
9 |
+
ob_start();
|
10 |
+
?>
|
11 |
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
12 |
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
13 |
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
14 |
+
<head>
|
15 |
+
<title>Minify Example 2</title>
|
16 |
+
<link rel="stylesheet" type="text/css" href="<?php echo $cssBuild->uri('m.php/css'); ?>" />
|
17 |
+
<style type="text/css">
|
18 |
+
|
19 |
+
#cssFail {
|
20 |
+
width:2.8em;
|
21 |
+
overflow:hidden;
|
22 |
+
}
|
23 |
+
</style>
|
24 |
+
</head>
|
25 |
+
<body>
|
26 |
+
|
27 |
+
<?php if (! $minifyCachePath): ?>
|
28 |
+
<p><strong>Note:</strong> You should <em>always</em> enable caching using
|
29 |
+
<code>Minify::setCache()</code>. For the examples this can be set in
|
30 |
+
<code>config.php</code>.</p>
|
31 |
+
<?php endif; ?>
|
32 |
+
|
33 |
+
<h1>Minify Example 2: Minifying <em>Everything</em></h1>
|
34 |
+
|
35 |
+
<p>In this example, external Javascript and CSS minification is identical to
|
36 |
+
example 1, but here Minify is also used to minify and serve the HTML, including
|
37 |
+
the contents of all <code><style></code> and <code><script></code>
|
38 |
+
elements.</p>
|
39 |
+
|
40 |
+
<p>As the document is XHTML, Minify_HTML places the 2nd <code><script></code>
|
41 |
+
element in a CDATA section because it contains "<". The output is valid XHTML.</p>
|
42 |
+
|
43 |
+
<h2><a href="http://validator.w3.org/check/referer"
|
44 |
+
onclick="this.target='_blank'">Validate XHTML</a></h2>
|
45 |
+
|
46 |
+
<h2>Minify tests</h2>
|
47 |
+
<ul>
|
48 |
+
<li id="cssFail"><span>FAIL</span>PASS</li>
|
49 |
+
<li id="jsFail1">FAIL</li>
|
50 |
+
<li id="jsFail2">FAIL</li>
|
51 |
+
</ul>
|
52 |
+
|
53 |
+
<h2>Test client cache</h2>
|
54 |
+
<p>When you <a href="">click here</a> to reload the page, your browser should
|
55 |
+
not have to re-download any files.</p>
|
56 |
+
|
57 |
+
<p style='text-align:right'><a href="../../">extras index »</a></p>
|
58 |
+
|
59 |
+
<script type="text/javascript" src="<?php echo $jsBuild->uri('m.php/js'); ?>"></script>
|
60 |
+
<script type="text/javascript">
|
61 |
+
|
62 |
+
var wo = window.onload;
|
63 |
+
window.onload = function () {
|
64 |
+
wo && wo();
|
65 |
+
if ( 1 < 2 ) {
|
66 |
+
html('jsFail2', 'PASS');
|
67 |
+
}
|
68 |
+
};
|
69 |
+
|
70 |
+
</script>
|
71 |
+
</body>
|
72 |
+
</html>
|
73 |
+
<?php
|
74 |
+
$content = ob_get_clean();
|
75 |
+
|
76 |
+
require 'Minify.php';
|
77 |
+
|
78 |
+
if ($minifyCachePath) {
|
79 |
+
Minify::useServerCache($minifyCachePath);
|
80 |
+
}
|
81 |
+
|
82 |
+
$pageLastUpdate = max(
|
83 |
+
filemtime(__FILE__)
|
84 |
+
,$jsBuild->lastModified
|
85 |
+
,$cssBuild->lastModified
|
86 |
+
);
|
87 |
+
|
88 |
+
Minify::serve('Page', array(
|
89 |
+
'content' => $content
|
90 |
+
,'id' => __FILE__
|
91 |
+
,'lastModifiedTime' => $pageLastUpdate
|
92 |
+
// also minify the CSS/JS inside the HTML
|
93 |
+
,'minifyAll' => true
|
94 |
+
));
|
lib/Minify/min_extras/examples/2/m.php
ADDED
@@ -0,0 +1,14 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require '../../config.php';
|
4 |
+
require '_groupsSources.php';
|
5 |
+
require 'Minify.php';
|
6 |
+
|
7 |
+
if ($minifyCachePath) {
|
8 |
+
Minify::setCache($minifyCachePath);
|
9 |
+
}
|
10 |
+
|
11 |
+
Minify::serve('Groups', array(
|
12 |
+
'groups' => $groupsSources
|
13 |
+
,'setExpires' => time() + 86400 * 365
|
14 |
+
));
|
lib/Minify/min_extras/examples/index.php
ADDED
@@ -0,0 +1,3 @@
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
header('Location: 1/');
|
lib/Minify/min_extras/examples/lib.js
ADDED
@@ -0,0 +1,6 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
|
2 |
+
function html(id, html) {
|
3 |
+
|
4 |
+
document.getElementById(id).innerHTML = html;
|
5 |
+
|
6 |
+
}
|
lib/Minify/min_extras/examples/test space.js
ADDED
@@ -0,0 +1,5 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
window.onload = function () {
|
2 |
+
|
3 |
+
html('jsFail1', 'PASS');
|
4 |
+
|
5 |
+
};
|
lib/Minify/min_extras/examples/test.css
ADDED
@@ -0,0 +1,41 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/* Test file to minify */
|
2 |
+
|
3 |
+
/*! copyright notice here... */
|
4 |
+
|
5 |
+
html {
|
6 |
+
margin:0;
|
7 |
+
padding:0;
|
8 |
+
background:#aaa;
|
9 |
+
}
|
10 |
+
body {
|
11 |
+
margin:0 auto;
|
12 |
+
padding:1em;
|
13 |
+
width:550px;
|
14 |
+
background:#fff;
|
15 |
+
}
|
16 |
+
body > *:first-child {margin-top:0;}
|
17 |
+
|
18 |
+
h1 {
|
19 |
+
color: #00cc00;
|
20 |
+
font-size: 20px;
|
21 |
+
}
|
22 |
+
h2 {
|
23 |
+
color: #009900;
|
24 |
+
font-size: 17px;
|
25 |
+
}
|
26 |
+
h1, h2 {margin:1.3em 0 .3em;}
|
27 |
+
|
28 |
+
p {
|
29 |
+
margin:0 0 1em;
|
30 |
+
}
|
31 |
+
|
32 |
+
ul, li {
|
33 |
+
padding:0;
|
34 |
+
margin:0;
|
35 |
+
display:block;
|
36 |
+
font-family: monospace;
|
37 |
+
}
|
38 |
+
|
39 |
+
#cssFail span {
|
40 |
+
display: none;
|
41 |
+
}
|
lib/Minify/min_extras/tools/encodeFile.php
ADDED
@@ -0,0 +1,34 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (isset($_FILES['subject']['name'])) {
|
4 |
+
|
5 |
+
require '../config.php';
|
6 |
+
|
7 |
+
require 'HTTP/Encoder.php';
|
8 |
+
$he = new HTTP_Encoder(array(
|
9 |
+
'content' => file_get_contents($_FILES['subject']['tmp_name'])
|
10 |
+
,'method' => $_POST['method']
|
11 |
+
));
|
12 |
+
header('Content-Type: application/octet-stream');
|
13 |
+
header('Content-Transfer-Encoding: binary');
|
14 |
+
header("Content-Disposition: attachment; filename=\"{$_FILES['subject']['name']}."
|
15 |
+
. ($_POST['method'] == 'deflate'
|
16 |
+
? 'zd'
|
17 |
+
: ($_POST['method'] == 'gzip'
|
18 |
+
? 'zg'
|
19 |
+
: 'zc'
|
20 |
+
)
|
21 |
+
) . '"');
|
22 |
+
$he->encode(9);
|
23 |
+
echo $he->getContent();
|
24 |
+
exit();
|
25 |
+
}
|
26 |
+
|
27 |
+
?>
|
28 |
+
<form enctype="multipart/form-data" action="" method="post">
|
29 |
+
<p>Encode <input type="file" name="subject" /><br />
|
30 |
+
as <input type="submit" name="method" value="deflate" />
|
31 |
+
<input type="submit" name="method" value="gzip" />
|
32 |
+
<input type="submit" name="method" value="compress" />
|
33 |
+
</p>
|
34 |
+
</form>
|
lib/Minify/min_extras/tools/minifyFile.php
ADDED
@@ -0,0 +1,50 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (isset($_FILES['subject']['name'])
|
4 |
+
&& preg_match('/\\.(js|css|x?html?)$/', $_FILES['subject']['name'], $m)
|
5 |
+
) {
|
6 |
+
require '../config.php';
|
7 |
+
|
8 |
+
// easier to just require them all
|
9 |
+
require 'Minify/HTML.php';
|
10 |
+
require 'Minify/CSS.php';
|
11 |
+
require 'JSMin.php';
|
12 |
+
|
13 |
+
$arg2 = null;
|
14 |
+
switch ($m[1]) {
|
15 |
+
case 'js':
|
16 |
+
$type = 'Javascript';
|
17 |
+
break;
|
18 |
+
case 'css':
|
19 |
+
$type = 'CSS';
|
20 |
+
break;
|
21 |
+
case 'html': // fallthrough
|
22 |
+
case 'htm': // fallthrough
|
23 |
+
case 'xhtml':
|
24 |
+
$type = 'HTML';
|
25 |
+
$arg2 = array(
|
26 |
+
'cssMinifier' => array('Minify_CSS', 'minify')
|
27 |
+
,'jsMinifier' => array('JSMin', 'minify')
|
28 |
+
);
|
29 |
+
}
|
30 |
+
$func = array('Minify_' . $type, 'minify');
|
31 |
+
|
32 |
+
$out = call_user_func($func, file_get_contents($_FILES['subject']['tmp_name']), $arg2);
|
33 |
+
|
34 |
+
header('Content-Type: application/octet-stream');
|
35 |
+
header('Content-Transfer-Encoding: binary');
|
36 |
+
header('Content-Disposition: attachment; filename="'
|
37 |
+
. preg_replace('/\\.(\w+)$/', '.min.$1', $_FILES['subject']['name'])
|
38 |
+
. '"');
|
39 |
+
|
40 |
+
//@unlink($_FILES['subject']['tmp_name']);
|
41 |
+
echo $out;
|
42 |
+
exit();
|
43 |
+
}
|
44 |
+
|
45 |
+
?>
|
46 |
+
<form enctype="multipart/form-data" action="" method="post">
|
47 |
+
<p>Minify <input type="file" name="subject" /><br />
|
48 |
+
<input type="submit" name="method" value="Go!" />
|
49 |
+
</p>
|
50 |
+
</form>
|
lib/Minify/min_extras/tools/minifyTextarea.php
ADDED
@@ -0,0 +1,98 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
function getPost($key) {
|
4 |
+
return get_magic_quotes_gpc()
|
5 |
+
? stripslashes($_POST[$key])
|
6 |
+
: $_POST[$key];
|
7 |
+
}
|
8 |
+
|
9 |
+
if (isset($_POST['textIn'])) {
|
10 |
+
require '../config.php';
|
11 |
+
$textIn = str_replace("\r\n", "\n", getPost('textIn'));
|
12 |
+
}
|
13 |
+
|
14 |
+
if (isset($_POST['method']) && $_POST['method'] === 'Minify and serve') {
|
15 |
+
require 'Minify.php';
|
16 |
+
|
17 |
+
$base = trim(getPost('base'));
|
18 |
+
if ($base) {
|
19 |
+
$textIn = preg_replace(
|
20 |
+
'@(<head\\b[^>]*>)@i'
|
21 |
+
,'$1<base href="' . htmlentities($base) . '" />'
|
22 |
+
,$textIn
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
$sourceSpec['content'] = $textIn;
|
27 |
+
$sourceSpec['id'] = 'foo';
|
28 |
+
if (isset($_POST['minJs'])) {
|
29 |
+
$sourceSpec['minifyOptions']['jsMinifier'] = array('JSMin', 'minify');
|
30 |
+
require 'JSMin.php';
|
31 |
+
}
|
32 |
+
if (isset($_POST['minCss'])) {
|
33 |
+
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSS', 'minify');
|
34 |
+
require 'Minify/CSS.php';
|
35 |
+
}
|
36 |
+
$source = new Minify_Source($sourceSpec);
|
37 |
+
require_once 'Minify/Logger.php';
|
38 |
+
require_once 'FirePHP.php';
|
39 |
+
Minify_Logger::setLogger(FirePHP::getInstance(true));
|
40 |
+
Minify::serve('Files', array(
|
41 |
+
'files' => $source
|
42 |
+
,'contentType' => Minify::TYPE_HTML
|
43 |
+
));
|
44 |
+
exit();
|
45 |
+
}
|
46 |
+
|
47 |
+
$classes = array('Minify_HTML', 'Minify_CSS', 'JSMin', 'JSMinPlus');
|
48 |
+
|
49 |
+
if (isset($_POST['method']) && in_array($_POST['method'], $classes)) {
|
50 |
+
// easier to just require them all
|
51 |
+
require 'Minify/HTML.php';
|
52 |
+
require 'Minify/CSS.php';
|
53 |
+
require 'JSMin.php';
|
54 |
+
require 'JSMinPlus.php';
|
55 |
+
|
56 |
+
$arg2 = null;
|
57 |
+
if ($_POST['method'] === 'Minify_HTML') {
|
58 |
+
$arg2 = array(
|
59 |
+
'cssMinifier' => array('Minify_CSS', 'minify')
|
60 |
+
,'jsMinifier' => array('JSMin', 'minify')
|
61 |
+
);
|
62 |
+
}
|
63 |
+
$func = array($_POST['method'], 'minify');
|
64 |
+
$inOutBytes[0] = strlen($textIn);
|
65 |
+
$textOut = call_user_func($func, $textIn, $arg2);
|
66 |
+
$inOutBytes[1] = strlen($textOut);
|
67 |
+
}
|
68 |
+
|
69 |
+
header('Content-Type: text/html; charset=utf-8');
|
70 |
+
?>
|
71 |
+
<!DOCTYPE html><head><title>minifyTextarea</title></head>
|
72 |
+
<?php
|
73 |
+
if (isset($inOutBytes)) {
|
74 |
+
echo "
|
75 |
+
<table>
|
76 |
+
<tr><th>Bytes in</th><td>{$inOutBytes[0]} (after line endings normalized to <code>\\n</code>)</td></tr>
|
77 |
+
<tr><th>Bytes out</th><td>{$inOutBytes[1]} (" . round(100 * $inOutBytes[1] / $inOutBytes[0]) . "%)</td></tr>
|
78 |
+
</table>
|
79 |
+
";
|
80 |
+
}
|
81 |
+
?>
|
82 |
+
<form action="?2" method="post">
|
83 |
+
<p><label>Content<br><textarea name="textIn" cols="80" rows="35" style="width:99%"><?php
|
84 |
+
if (isset($textOut)) {
|
85 |
+
echo htmlspecialchars($textOut);
|
86 |
+
}
|
87 |
+
?></textarea></label></p>
|
88 |
+
<p>Minify with:
|
89 |
+
<?php foreach ($classes as $minClass): ?>
|
90 |
+
<input type="submit" name="method" value="<?php echo $minClass; ?>">
|
91 |
+
<?php endForEach; ?>
|
92 |
+
</p>
|
93 |
+
<p>...or <input type="submit" name="method" value="Minify and serve"> this HTML to the browser. Also minify:
|
94 |
+
<label>CSS <input type="checkbox" name="minCss" checked></label> :
|
95 |
+
<label>JS <input type="checkbox" name="minJs" checked></label>.
|
96 |
+
<label>Insert BASE element w/ href: <input type="text" name="base" size="20"></label>
|
97 |
+
</p>
|
98 |
+
</form>
|
lib/Minify/min_extras/tools/minifyUrl.php
ADDED
@@ -0,0 +1,166 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Fetch and minify a URL (auto-detect HTML/JS/CSS)
|
4 |
+
*/
|
5 |
+
|
6 |
+
function getPost($key) {
|
7 |
+
if (! isset($_POST[$key])) {
|
8 |
+
return null;
|
9 |
+
}
|
10 |
+
return get_magic_quotes_gpc()
|
11 |
+
? stripslashes($_POST[$key])
|
12 |
+
: $_POST[$key];
|
13 |
+
}
|
14 |
+
|
15 |
+
function sniffType($headers) {
|
16 |
+
$charset = 'utf-8';
|
17 |
+
$type = null;
|
18 |
+
$headers = "\n\n" . implode("\n\n", $headers) . "\n\n";
|
19 |
+
if (preg_match(
|
20 |
+
'@\\n\\nContent-Type: *([\\w/\\+-]+)( *; *charset *= *([\\w-]+))? *\\n\\n@i'
|
21 |
+
,$headers
|
22 |
+
,$m)) {
|
23 |
+
$sentType = $m[1];
|
24 |
+
if (isset($m[3])) {
|
25 |
+
$charset = $m[3];
|
26 |
+
}
|
27 |
+
if (preg_match('@^(?:text|application)/(?:x-)?(?:java|ecma)script$@i', $sentType)) {
|
28 |
+
$type = 'application/x-javascript';
|
29 |
+
} elseif (preg_match('@^(?:text|application)/(?:html|xml|xhtml+xml)$@i', $sentType, $m)) {
|
30 |
+
$type = 'text/html';
|
31 |
+
} elseif ($sentType === 'text/css') {
|
32 |
+
$type = $sentType;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
return array(
|
36 |
+
'minify' => $type
|
37 |
+
,'sent' => $sentType
|
38 |
+
,'charset' => $charset
|
39 |
+
);
|
40 |
+
}
|
41 |
+
|
42 |
+
if (isset($_POST['url'])) {
|
43 |
+
|
44 |
+
require '../config.php';
|
45 |
+
|
46 |
+
$url = trim(getPost('url'));
|
47 |
+
$ua = trim(getPost('ua'));
|
48 |
+
$cook = trim(getPost('cook'));
|
49 |
+
|
50 |
+
if (! preg_match('@^https?://@', $url)) {
|
51 |
+
die('HTTP(s) only.');
|
52 |
+
}
|
53 |
+
|
54 |
+
$httpOpts = array(
|
55 |
+
'max_redirects' => 0
|
56 |
+
,'timeout' => 3
|
57 |
+
);
|
58 |
+
if ($ua !== '') {
|
59 |
+
$httpOpts['user_agent'] = $ua;
|
60 |
+
}
|
61 |
+
if ($cook !== '') {
|
62 |
+
$httpOpts['header'] = "Cookie: {$cook}\r\n";
|
63 |
+
}
|
64 |
+
$ctx = stream_context_create(array(
|
65 |
+
'http' => $httpOpts
|
66 |
+
));
|
67 |
+
|
68 |
+
// fetch
|
69 |
+
if (! ($fp = @fopen($url, 'r', false, $ctx))) {
|
70 |
+
die('Couldn\'t open URL.');
|
71 |
+
}
|
72 |
+
$meta = stream_get_meta_data($fp);
|
73 |
+
$content = stream_get_contents($fp);
|
74 |
+
fclose($fp);
|
75 |
+
|
76 |
+
// get type info
|
77 |
+
$type = sniffType($meta['wrapper_data']);
|
78 |
+
if (! $type['minify']) {
|
79 |
+
die('Unrecognized Content-Type: ' . $type['sent']);
|
80 |
+
}
|
81 |
+
|
82 |
+
require 'Minify.php';
|
83 |
+
require 'Minify/HTML.php';
|
84 |
+
require 'Minify/CSS.php';
|
85 |
+
require 'JSMin.php';
|
86 |
+
|
87 |
+
if ($type['minify'] === 'text/html'
|
88 |
+
&& isset($_POST['addBase'])
|
89 |
+
&& ! preg_match('@<base\\b@i', $content)) {
|
90 |
+
$content = preg_replace(
|
91 |
+
'@(<head\\b[^>]*>)@i'
|
92 |
+
,'$1<base href="' . htmlentities($url) . '" />'
|
93 |
+
,$content
|
94 |
+
);
|
95 |
+
}
|
96 |
+
|
97 |
+
$sourceSpec['content'] = $content;
|
98 |
+
$sourceSpec['id'] = 'foo';
|
99 |
+
|
100 |
+
if ($type['minify'] === 'text/html') {
|
101 |
+
if (isset($_POST['minJs'])) {
|
102 |
+
$sourceSpec['minifyOptions']['jsMinifier'] = array('JSMin', 'minify');
|
103 |
+
require 'JSMin.php';
|
104 |
+
}
|
105 |
+
if (isset($_POST['minCss'])) {
|
106 |
+
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSS', 'minify');
|
107 |
+
require 'Minify/CSS.php';
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
$source = new Minify_Source($sourceSpec);
|
112 |
+
|
113 |
+
$sendType = 'text/plain';
|
114 |
+
if ($type['minify'] === 'text/html' && ! isset($_POST['asText'])) {
|
115 |
+
$sendType = $type['sent'];
|
116 |
+
}
|
117 |
+
if ($type['charset']) {
|
118 |
+
$sendType .= ';charset=' . $type['charset'];
|
119 |
+
}
|
120 |
+
header('Content-Type: ' . $sendType);
|
121 |
+
// using combine instead of serve because it allows us to specify a
|
122 |
+
// Content-Type like application/xhtml+xml IF we need to
|
123 |
+
echo Minify::combine(array($source), array(
|
124 |
+
'contentType' => $type['minify']
|
125 |
+
));
|
126 |
+
exit();
|
127 |
+
}
|
128 |
+
|
129 |
+
header('Content-Type: text/html; charset=utf-8');
|
130 |
+
|
131 |
+
$ua = get_magic_quotes_gpc()
|
132 |
+
? stripslashes($_SERVER['HTTP_USER_AGENT'])
|
133 |
+
: $_SERVER['HTTP_USER_AGENT'];
|
134 |
+
|
135 |
+
?>
|
136 |
+
<!DOCTYPE html><head><title>Minify URL</title></head>
|
137 |
+
|
138 |
+
<p><strong>Warning! Please do not place this application on a public site.</strong> This should be used
|
139 |
+
only for testing.</p>
|
140 |
+
|
141 |
+
<h1>Fetch and Minify a URL</h1>
|
142 |
+
<p>This tool will retrieve the contents of a URL and minify it.
|
143 |
+
The fetched resource Content-Type will determine the minifier used.</p>
|
144 |
+
|
145 |
+
<form action="?2" method="post">
|
146 |
+
<p><label>URL: <input type="text" name="url" size="60"></label></p>
|
147 |
+
<p><input type="submit" value="Fetch and minify"></p>
|
148 |
+
|
149 |
+
<fieldset><legend>HTML options</legend>
|
150 |
+
<p>If the resource above is sent with an (x)HTML Content-Type, the following options will apply:</p>
|
151 |
+
<ul>
|
152 |
+
<li><label><input type="checkbox" name="asText" checked> Return plain text (o/w send the original content type)</label>
|
153 |
+
<li><label><input type="checkbox" name="minCss" checked> Minify CSS</label>
|
154 |
+
<li><label><input type="checkbox" name="minJs" checked> Minify JS</label>
|
155 |
+
<li><label><input type="checkbox" name="addBase" checked> Add BASE element (if not present)</label>
|
156 |
+
</ul>
|
157 |
+
</fieldset>
|
158 |
+
|
159 |
+
<fieldset><legend>Retreival options</legend>
|
160 |
+
<ul>
|
161 |
+
<li><label>User-Agent: <input type="text" name="ua" size="60" value="<?php echo htmlspecialchars($ua); ?>"></label>
|
162 |
+
<li><label>Cookie: <input type="text" name="cook" size="60"></label>
|
163 |
+
</ul>
|
164 |
+
</fieldset>
|
165 |
+
|
166 |
+
</form>
|
lib/Minify/min_extras/tools/testRewriteUri.php
ADDED
@@ -0,0 +1,59 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
header('Content-Type: text/html;charset=utf-8');
|
3 |
+
|
4 |
+
function h($str) { return htmlspecialchars($str, ENT_QUOTES); }
|
5 |
+
|
6 |
+
function getPost($name, $default = '') { return isset($_POST[$name]) ? $_POST[$name] : $default; }
|
7 |
+
|
8 |
+
function getInput($name, $default = '', $size = 50) {
|
9 |
+
$val = h(isset($_POST[$name]) ? $_POST[$name] : $default);
|
10 |
+
return "<input type='text' name='{$name}' value='{$val}' size='{$size}' />";
|
11 |
+
}
|
12 |
+
|
13 |
+
// validate user POST (no arrays and fix slashes)
|
14 |
+
if (! empty($_POST)) {
|
15 |
+
foreach ($_POST as $name => $val) {
|
16 |
+
if (! is_string($val)) {
|
17 |
+
unset($_POST[$name]);
|
18 |
+
continue;
|
19 |
+
}
|
20 |
+
if (get_magic_quotes_gpc()) {
|
21 |
+
$_POST[$name] = stripslashes($val);
|
22 |
+
}
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
$defaultCurrentDir = dirname(__FILE__);
|
27 |
+
$defaultDocRoot = realpath($_SERVER['DOCUMENT_ROOT']);
|
28 |
+
$defaultSymLink = '//symlinkPath';
|
29 |
+
$defaultSymTarget = ($defaultCurrentDir[0] === '/') ? '/tmp' : 'C:\\WINDOWS\\Temp';
|
30 |
+
$defaultCss = "url(hello.gif)\nurl(../hello.gif)\nurl(../../hello.gif)\nurl(up/hello.gif)";
|
31 |
+
|
32 |
+
$out = '';
|
33 |
+
|
34 |
+
if (isset($_POST['css'])) {
|
35 |
+
require '../config.php';
|
36 |
+
require 'Minify/CSS/UriRewriter.php';
|
37 |
+
$symlinks = array();
|
38 |
+
if ('' !== ($target = getPost('symTarget'))) {
|
39 |
+
$symlinks[getPost('symLink')] = $target;
|
40 |
+
}
|
41 |
+
$css = Minify_CSS_UriRewriter::rewrite(
|
42 |
+
getPost('css')
|
43 |
+
, getPost('currentDir')
|
44 |
+
, getPost('docRoot')
|
45 |
+
, $symlinks
|
46 |
+
);
|
47 |
+
$out = "<hr /><pre><code>" . h($css) . '</code></pre>';
|
48 |
+
}
|
49 |
+
|
50 |
+
?>
|
51 |
+
<h1>Test <code>Minify_CSS_UriRewriter::rewrite()</code></h1>
|
52 |
+
<form action="" method="post">
|
53 |
+
<div><label>document root: <?php echo getInput('docRoot', $defaultDocRoot); ?></label></div>
|
54 |
+
<div><label>symlink: <?php echo getInput('symLink', $defaultSymLink); ?> => <?php echo getInput('symTarget', $defaultSymTarget); ?></label></div>
|
55 |
+
<div><label>current directory: <?php echo getInput('currentDir', $defaultCurrentDir); ?></label></div>
|
56 |
+
<p><label>input CSS: <textarea name="css" cols="80" rows="5"><?php echo h(getPost('css', $defaultCss)); ?></textarea></label></p>
|
57 |
+
<p><input type="submit" value="rewrite()" /></p>
|
58 |
+
</form>
|
59 |
+
<?php echo $out; ?>
|
lib/Minify/min_unit_tests/HTTP_ConditionalGet/3.php
CHANGED
@@ -37,4 +37,4 @@ $cg->setContentLength(strlen($content));
|
|
37 |
Â
$cg->sendHeaders();
|
38 |
Â
|
39 |
Â
send_slowly($content);
|
40 |
-
|
37 |
Â
$cg->sendHeaders();
|
38 |
Â
|
39 |
Â
send_slowly($content);
|
40 |
+
|
lib/Minify/min_unit_tests/HTTP_ConditionalGet/_include.php
CHANGED
@@ -61,4 +61,4 @@ to verify headers and content being sent.</p>
|
|
61 |
Â
ob_end_clean();
|
62 |
Â
return $content;
|
63 |
Â
}
|
64 |
-
|
61 |
Â
ob_end_clean();
|
62 |
Â
return $content;
|
63 |
Â
}
|
64 |
+
|
lib/Minify/min_unit_tests/HTTP_ConditionalGet/index.php
CHANGED
@@ -33,4 +33,4 @@ echo send_slowly(get_content(array(
|
|
33 |
Â
'title' => $title
|
34 |
Â
,'explain' => $explain
|
35 |
Â
)));
|
36 |
-
|
33 |
Â
'title' => $title
|
34 |
Â
,'explain' => $explain
|
35 |
Â
)));
|
36 |
+
|
lib/Minify/min_unit_tests/README.txt
ADDED
@@ -0,0 +1,4 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
UNIT TESTING
|
2 |
+
|
3 |
+
Do not modify the "simpletest" directory as it's linked via svn:externals.
|
4 |
+
|
lib/Minify/min_unit_tests/_test_files/css/hacks.css
CHANGED
@@ -1,66 +1,66 @@
|
|
1 |
-
/* hide from ie5/mac \*/ a{}
|
2 |
-
.foo {color:red}
|
3 |
-
/* necessary comment */
|
4 |
-
|
5 |
-
/* comment to attempt to confuse parser */
|
6 |
-
|
7 |
-
/* feed to ie5/mac \*//*/
|
8 |
-
@import "ie5mac.css";
|
9 |
-
/* necessary comment */
|
10 |
-
|
11 |
-
/* comment to attempt to confuse parser */
|
12 |
-
|
13 |
-
/*/ hide from nav4 */
|
14 |
-
.foo {display:block;}
|
15 |
-
/* necessary comment */
|
16 |
-
|
17 |
-
/* comment to attempt to confuse parser */
|
18 |
-
|
19 |
-
/*/ feed to nav *//*/
|
20 |
-
.foo {display:crazy;}
|
21 |
-
/* necessary comment */
|
22 |
-
|
23 |
-
/* hide props from various IE/win */
|
24 |
-
div {
|
25 |
-
width: 140px;
|
26 |
-
width/* */:/**/100px;
|
27 |
-
width: /**/100px;
|
28 |
-
}
|
29 |
-
|
30 |
-
html>/**/body {}
|
31 |
-
|
32 |
-
/* Tantek's box model hack */
|
33 |
-
div {
|
34 |
-
width:400px;
|
35 |
-
voice-family: "\"}\"";
|
36 |
-
voice-family:inherit;
|
37 |
-
width:300px;
|
38 |
-
}
|
39 |
-
|
40 |
-
/* don't minimize hex colors in filters */
|
41 |
-
div {
|
42 |
-
filter:chroma(color=#aabbcc);
|
43 |
-
filter:mask(color=#000000) shadow(color=#9BAD71, direction=135) chroma(color=#000000);
|
44 |
-
}
|
45 |
-
|
46 |
-
@media screen {
|
47 |
-
/* for IE 5.x-6, hidden from IE 5 Mac */ /*\*/
|
48 |
-
* html div#page {
|
49 |
-
height: 1%;
|
50 |
-
}
|
51 |
-
/**/ /* end hidden from IE 5 Mac */
|
52 |
-
}
|
53 |
-
|
54 |
-
foo { /* filters for IE */
|
55 |
-
_height : 20px;
|
56 |
-
*height : 15px;
|
57 |
-
}
|
58 |
-
|
59 |
-
/* http://tantek.com/CSS/Examples/midpass.html */
|
60 |
-
@media tty {
|
61 |
-
i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
|
62 |
-
}/* */
|
63 |
-
|
64 |
-
/* leave at least 1 space between these pseudo elements and "{" for IE6: http://www.crankygeek.com/ie6pebug/ */
|
65 |
-
p:first-letter {color:red;}
|
66 |
-
p:first-line {color:red;}
|
1 |
+
/* hide from ie5/mac \*/ a{}
|
2 |
+
.foo {color:red}
|
3 |
+
/* necessary comment */
|
4 |
+
|
5 |
+
/* comment to attempt to confuse parser */
|
6 |
+
|
7 |
+
/* feed to ie5/mac \*//*/
|
8 |
+
@import "ie5mac.css";
|
9 |
+
/* necessary comment */
|
10 |
+
|
11 |
+
/* comment to attempt to confuse parser */
|
12 |
+
|
13 |
+
/*/ hide from nav4 */
|
14 |
+
.foo {display:block;}
|
15 |
+
/* necessary comment */
|
16 |
+
|
17 |
+
/* comment to attempt to confuse parser */
|
18 |
+
|
19 |
+
/*/ feed to nav *//*/
|
20 |
+
.foo {display:crazy;}
|
21 |
+
/* necessary comment */
|
22 |
+
|
23 |
+
/* hide props from various IE/win */
|
24 |
+
div {
|
25 |
+
width: 140px;
|
26 |
+
width/* */:/**/100px;
|
27 |
+
width: /**/100px;
|
28 |
+
}
|
29 |
+
|
30 |
+
html>/**/body {}
|
31 |
+
|
32 |
+
/* Tantek's box model hack */
|
33 |
+
div {
|
34 |
+
width:400px;
|
35 |
+
voice-family: "\"}\"";
|
36 |
+
voice-family:inherit;
|
37 |
+
width:300px;
|
38 |
+
}
|
39 |
+
|
40 |
+
/* don't minimize hex colors in filters */
|
41 |
+
div {
|
42 |
+
filter:chroma(color=#aabbcc);
|
43 |
+
filter:mask(color=#000000) shadow(color=#9BAD71, direction=135) chroma(color=#000000);
|
44 |
+
}
|
45 |
+
|
46 |
+
@media screen {
|
47 |
+
/* for IE 5.x-6, hidden from IE 5 Mac */ /*\*/
|
48 |
+
* html div#page {
|
49 |
+
height: 1%;
|
50 |
+
}
|
51 |
+
/**/ /* end hidden from IE 5 Mac */
|
52 |
+
}
|
53 |
+
|
54 |
+
foo { /* filters for IE */
|
55 |
+
_height : 20px;
|
56 |
+
*height : 15px;
|
57 |
+
}
|
58 |
+
|
59 |
+
/* http://tantek.com/CSS/Examples/midpass.html */
|
60 |
+
@media tty {
|
61 |
+
i{content:"\";/*" "*/}} @import 'midpassafter.css'; /*";}
|
62 |
+
}/* */
|
63 |
+
|
64 |
+
/* leave at least 1 space between these pseudo elements and "{" for IE6: http://www.crankygeek.com/ie6pebug/ */
|
65 |
+
p:first-letter {color:red;}
|
66 |
+
p:first-line {color:red;}
|
lib/Minify/min_unit_tests/_test_files/css/issue62.css
CHANGED
@@ -1,890 +1,890 @@
|
|
1 |
-
/*
|
2 |
-
* DEFINITION DES STYLES DE TEXTE
|
3 |
-
*/
|
4 |
-
/*-----------------------------------------------------------------------------------*/
|
5 |
-
h1 {
|
6 |
-
color: #339933;
|
7 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
8 |
-
font-size: 14px;
|
9 |
-
font-weight: bold;
|
10 |
-
text-decoration: none;
|
11 |
-
}
|
12 |
-
|
13 |
-
h2 {
|
14 |
-
color: #339933;
|
15 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
16 |
-
font-size: 12px;
|
17 |
-
font-weight: bold;
|
18 |
-
text-decoration: none;
|
19 |
-
}
|
20 |
-
|
21 |
-
h1,h2,h3,h4,h5 {
|
22 |
-
margin: 0px;
|
23 |
-
padding: 0px;
|
24 |
-
}
|
25 |
-
|
26 |
-
.txt_10_noir {
|
27 |
-
color: black;
|
28 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
29 |
-
font-size: 10px;
|
30 |
-
text-decoration: none;
|
31 |
-
}
|
32 |
-
|
33 |
-
.txt_10_noir:link,.txt_10_noir:visited,.txt_10_noir:active {
|
34 |
-
color: black;
|
35 |
-
}
|
36 |
-
|
37 |
-
.txt_10_noir:hover {
|
38 |
-
color: red;
|
39 |
-
}
|
40 |
-
|
41 |
-
.txt_11_noir {
|
42 |
-
color: black;
|
43 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
44 |
-
font-size: 11px;
|
45 |
-
text-decoration: none;
|
46 |
-
}
|
47 |
-
|
48 |
-
.txt_11_noir:link,.txt_11_noir:visited,.txt_11_noir:active {
|
49 |
-
color: black;
|
50 |
-
}
|
51 |
-
|
52 |
-
.txt_11_noir:hover {
|
53 |
-
color: red;
|
54 |
-
}
|
55 |
-
|
56 |
-
.txt_12_noir {
|
57 |
-
color: black;
|
58 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
59 |
-
font-size: 12px;
|
60 |
-
text-decoration: none;
|
61 |
-
}
|
62 |
-
|
63 |
-
.txt_12_noir:link,.txt_12_noir:visited,.txt_12_noir:active {
|
64 |
-
color: black;
|
65 |
-
}
|
66 |
-
|
67 |
-
.txt_12_noir:hover {
|
68 |
-
color: red;
|
69 |
-
}
|
70 |
-
|
71 |
-
.txt_14_noir {
|
72 |
-
color: black;
|
73 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
74 |
-
font-size: 14px;
|
75 |
-
text-decoration: none;
|
76 |
-
}
|
77 |
-
|
78 |
-
.txt_14_noir:link,.txt_14_noir:visited,.txt_14_noir:active {
|
79 |
-
color: black;
|
80 |
-
}
|
81 |
-
|
82 |
-
.txt_14_noir:hover {
|
83 |
-
color: red;
|
84 |
-
}
|
85 |
-
|
86 |
-
/*-----------------------------------------------------------------------------------*/
|
87 |
-
.txt_10_gris {
|
88 |
-
color: grey;
|
89 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
90 |
-
font-size: 10px;
|
91 |
-
text-decoration: none;
|
92 |
-
}
|
93 |
-
|
94 |
-
.txt_10_gris:link,.txt_10_gris:visited,.txt_10_gris:active {
|
95 |
-
color: grey;
|
96 |
-
}
|
97 |
-
|
98 |
-
.txt_10_gris:hover {
|
99 |
-
color: red;
|
100 |
-
}
|
101 |
-
|
102 |
-
.txt_11_gris {
|
103 |
-
color: grey;
|
104 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
105 |
-
font-size: 11px;
|
106 |
-
text-decoration: none;
|
107 |
-
}
|
108 |
-
|
109 |
-
.txt_11_gris:link,.txt_11_gris:visited,.txt_11_gris:active {
|
110 |
-
color: grey;
|
111 |
-
}
|
112 |
-
|
113 |
-
.txt_11_gris:hover {
|
114 |
-
color: red;
|
115 |
-
}
|
116 |
-
|
117 |
-
.txt_12_gris {
|
118 |
-
color: grey;
|
119 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
120 |
-
font-size: 12px;
|
121 |
-
text-decoration: none;
|
122 |
-
}
|
123 |
-
|
124 |
-
.txt_12_gris:link,.txt_12_gris:visited,.txt_12_gris:active {
|
125 |
-
color: grey;
|
126 |
-
}
|
127 |
-
|
128 |
-
.txt_12_gris:hover {
|
129 |
-
color: red;
|
130 |
-
}
|
131 |
-
|
132 |
-
.txt_14_gris {
|
133 |
-
color: grey;
|
134 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
135 |
-
font-size: 14px;
|
136 |
-
text-decoration: none;
|
137 |
-
}
|
138 |
-
|
139 |
-
.txt_14_gris:link,.txt_14_gris:visited,.txt_14_gris:active {
|
140 |
-
color: grey;
|
141 |
-
}
|
142 |
-
|
143 |
-
.txt_14_gris:hover {
|
144 |
-
color: red;
|
145 |
-
}
|
146 |
-
|
147 |
-
/*-----------------------------------------------------------------------------------*/
|
148 |
-
.txt_10_blanc {
|
149 |
-
color: #FFFFFF;
|
150 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
151 |
-
font-size: 10px;
|
152 |
-
text-decoration: none;
|
153 |
-
}
|
154 |
-
|
155 |
-
.txt_10_blanc:link,.txt_10_blanc:visited,.txt_10_blanc:active {
|
156 |
-
color: #FFFFFF;
|
157 |
-
}
|
158 |
-
|
159 |
-
.txt_10_blanc:hover {
|
160 |
-
color: #FF8800; /*ORANGE*/
|
161 |
-
}
|
162 |
-
|
163 |
-
.txt_11_blanc {
|
164 |
-
color: #FFFFFF;
|
165 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
166 |
-
font-size: 11px;
|
167 |
-
text-decoration: none;
|
168 |
-
}
|
169 |
-
|
170 |
-
.txt_11_blanc:link,.txt_11_blanc:visited,.txt_11_blanc:active {
|
171 |
-
color: #FFFFFF;
|
172 |
-
}
|
173 |
-
|
174 |
-
.txt_11_blanc:hover {
|
175 |
-
color: #FF8800;
|
176 |
-
}
|
177 |
-
|
178 |
-
.txt_12_blanc {
|
179 |
-
color: #FFFFFF;
|
180 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
181 |
-
font-size: 12px;
|
182 |
-
text-decoration: none;
|
183 |
-
}
|
184 |
-
|
185 |
-
.txt_12_blanc:link,.txt_12_blanc:visited,.txt_12_blanc:active {
|
186 |
-
color: #FFFFFF;
|
187 |
-
}
|
188 |
-
|
189 |
-
.txt_12_blanc:hover {
|
190 |
-
color: #FFAA00;
|
191 |
-
}
|
192 |
-
|
193 |
-
.txt_14_blanc {
|
194 |
-
color: #FFFFFF;
|
195 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
196 |
-
font-size: 14px;
|
197 |
-
text-decoration: none;
|
198 |
-
}
|
199 |
-
|
200 |
-
.txt_14_blanc:link,.txt_14_blanc:visited,.txt_14_blanc:active {
|
201 |
-
color: #FFFFFF;
|
202 |
-
}
|
203 |
-
|
204 |
-
.txt_14_blanc:hover {
|
205 |
-
color: #FF8800;
|
206 |
-
}
|
207 |
-
|
208 |
-
/*-----------------------------------------------------------------------------------*/
|
209 |
-
.txt_10_orange {
|
210 |
-
color: #FF8800;
|
211 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
212 |
-
font-size: 10px;
|
213 |
-
text-decoration: none;
|
214 |
-
}
|
215 |
-
|
216 |
-
.txt_10_orange:link,.txt_10_orange:visited,.txt_10_orange:active {
|
217 |
-
color: #FF8800;
|
218 |
-
}
|
219 |
-
|
220 |
-
.txt_10_orange:hover {
|
221 |
-
color: darkblue
|
222 |
-
}
|
223 |
-
|
224 |
-
.txt_11_orange {
|
225 |
-
color: #FF8800;
|
226 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
227 |
-
font-size: 11px;
|
228 |
-
text-decoration: none;
|
229 |
-
}
|
230 |
-
|
231 |
-
.txt_11_orange:link,.txt_11_orange:visited,.txt_11_orange:active {
|
232 |
-
color: #FF8800;
|
233 |
-
}
|
234 |
-
|
235 |
-
.txt_11_orange:hover {
|
236 |
-
color: darkblue;
|
237 |
-
}
|
238 |
-
|
239 |
-
.txt_12_orange {
|
240 |
-
color: #FF8800;
|
241 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
242 |
-
font-size: 12px;
|
243 |
-
text-decoration: none;
|
244 |
-
}
|
245 |
-
|
246 |
-
.txt_12_orange:link,.txt_12_orange:visited,.txt_12_orange:active {
|
247 |
-
color: #FF8800;
|
248 |
-
}
|
249 |
-
|
250 |
-
.txt_12_orange:hover {
|
251 |
-
color: darkblue;
|
252 |
-
}
|
253 |
-
|
254 |
-
.txt_14_orange {
|
255 |
-
color: #FF8800;
|
256 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
257 |
-
font-size: 14px;
|
258 |
-
text-decoration: none;
|
259 |
-
}
|
260 |
-
|
261 |
-
.txt_14_orange:link,.txt_14_orange:visited,.txt_14_orange:active {
|
262 |
-
color: #FF8800;
|
263 |
-
}
|
264 |
-
|
265 |
-
.txt_14_orange:hover {
|
266 |
-
color: darkblue;
|
267 |
-
}
|
268 |
-
|
269 |
-
/*-----------------------------------------------------------------------------------*/
|
270 |
-
.txt_10_rouge {
|
271 |
-
color: red;
|
272 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
273 |
-
font-size: 10px;
|
274 |
-
text-decoration: none;
|
275 |
-
}
|
276 |
-
|
277 |
-
.txt_10_rouge:link,.txt_10_rouge:visited,.txt_10_rouge:active {
|
278 |
-
color: red;
|
279 |
-
}
|
280 |
-
|
281 |
-
.txt_10_rouge:hover {
|
282 |
-
color: darkblue;
|
283 |
-
}
|
284 |
-
|
285 |
-
.txt_11_rouge {
|
286 |
-
color: red;
|
287 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
288 |
-
font-size: 11px;
|
289 |
-
text-decoration: none;
|
290 |
-
}
|
291 |
-
|
292 |
-
.txt_11_rouge:link,.txt_11_rouge:visited,.txt_11_rouge:active {
|
293 |
-
color: red;
|
294 |
-
}
|
295 |
-
|
296 |
-
.txt_11_rouge:hover {
|
297 |
-
color: darkblue;
|
298 |
-
}
|
299 |
-
|
300 |
-
.txt_12_rouge {
|
301 |
-
color: red;
|
302 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
303 |
-
font-size: 12px;
|
304 |
-
text-decoration: none;
|
305 |
-
}
|
306 |
-
|
307 |
-
.txt_12_rouge:link,.txt_12_rouge:visited,.txt_12_rouge:active {
|
308 |
-
color: red;
|
309 |
-
}
|
310 |
-
|
311 |
-
.txt_12_rouge:hover {
|
312 |
-
color: darkblue;
|
313 |
-
}
|
314 |
-
|
315 |
-
.txt_14_rouge {
|
316 |
-
color: red;
|
317 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
318 |
-
font-size: 14px;
|
319 |
-
text-decoration: none;
|
320 |
-
}
|
321 |
-
|
322 |
-
.txt_14_rouge:link,.txt_14_rouge:visited,.txt_14_rouge:active {
|
323 |
-
color: red;
|
324 |
-
}
|
325 |
-
|
326 |
-
.txt_14_rouge:hover {
|
327 |
-
color: darkblue;
|
328 |
-
}
|
329 |
-
|
330 |
-
/*-----------------------------------------------------------------------------------*/
|
331 |
-
.txt_10_bleu {
|
332 |
-
color: blue;
|
333 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
334 |
-
font-size: 10px;
|
335 |
-
text-decoration: none;
|
336 |
-
}
|
337 |
-
|
338 |
-
.txt_10_bleu:link,.txt_10_bleu:visited,.txt_10_bleu:active {
|
339 |
-
color: blue;
|
340 |
-
}
|
341 |
-
|
342 |
-
.txt_10_bleu:hover {
|
343 |
-
color: red;
|
344 |
-
}
|
345 |
-
|
346 |
-
.txt_11_bleu {
|
347 |
-
color: blue;
|
348 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
349 |
-
font-size: 11px;
|
350 |
-
text-decoration: none;
|
351 |
-
}
|
352 |
-
|
353 |
-
.txt_11_bleu:link,.txt_11_bleu:visited,.txt_11_bleu:active {
|
354 |
-
color: blue;
|
355 |
-
}
|
356 |
-
|
357 |
-
.txt_11_bleu:hover {
|
358 |
-
color: red;
|
359 |
-
}
|
360 |
-
|
361 |
-
.txt_12_bleu {
|
362 |
-
color: blue;
|
363 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
364 |
-
font-size: 12px;
|
365 |
-
text-decoration: none;
|
366 |
-
}
|
367 |
-
|
368 |
-
.txt_12_bleu:link,.txt_12_bleu:visited,.txt_12_bleu:active {
|
369 |
-
color: blue;
|
370 |
-
}
|
371 |
-
|
372 |
-
.txt_12_bleu:hover {
|
373 |
-
color: red;
|
374 |
-
}
|
375 |
-
|
376 |
-
.txt_14_bleu {
|
377 |
-
color: blue;
|
378 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
379 |
-
font-size: 14px;
|
380 |
-
text-decoration: none;
|
381 |
-
}
|
382 |
-
|
383 |
-
.txt_14_bleu:link,.txt_14_bleu:visited,.txt_14_bleu:active {
|
384 |
-
color: blue;
|
385 |
-
}
|
386 |
-
|
387 |
-
.txt_14_bleu:hover {
|
388 |
-
color: red;
|
389 |
-
}
|
390 |
-
|
391 |
-
/*-----------------------------------------------------------------------------------*/
|
392 |
-
.txt_10_bleu_f {
|
393 |
-
color: darkblue;
|
394 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
395 |
-
font-size: 10px;
|
396 |
-
text-decoration: none;
|
397 |
-
}
|
398 |
-
|
399 |
-
.txt_10_bleu_f:link,.txt_10_bleu_f:visited,.txt_10_bleu_f:active {
|
400 |
-
color: darkblue;
|
401 |
-
}
|
402 |
-
|
403 |
-
.txt_10_bleu_f:hover {
|
404 |
-
color: red;
|
405 |
-
}
|
406 |
-
|
407 |
-
.txt_11_bleu_f {
|
408 |
-
color: darkblue;
|
409 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
410 |
-
font-size: 11px;
|
411 |
-
text-decoration: none;
|
412 |
-
}
|
413 |
-
|
414 |
-
.txt_11_bleu_f:link,.txt_11_bleu_f:visited,.txt_11_bleu_f:active {
|
415 |
-
color: darkblue;
|
416 |
-
}
|
417 |
-
|
418 |
-
.txt_11_bleu_f:hover {
|
419 |
-
color: red;
|
420 |
-
}
|
421 |
-
|
422 |
-
.txt_12_bleu_f {
|
423 |
-
color: darkblue;
|
424 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
425 |
-
font-size: 12px;
|
426 |
-
text-decoration: none;
|
427 |
-
}
|
428 |
-
|
429 |
-
.txt_12_bleu_f:link,.txt_12_bleu_f:visited,.txt_12_bleu_f:active {
|
430 |
-
color: darkblue;
|
431 |
-
}
|
432 |
-
|
433 |
-
.txt_12_bleu_f:hover {
|
434 |
-
color: red;
|
435 |
-
}
|
436 |
-
|
437 |
-
.txt_14_bleu_f {
|
438 |
-
color: darkblue;
|
439 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
440 |
-
font-size: 14px;
|
441 |
-
text-decoration: none;
|
442 |
-
}
|
443 |
-
|
444 |
-
.txt_14_bleu_f:link,.txt_14_bleu_f:visited,.txt_14_bleu_f:active {
|
445 |
-
color: darkblue;
|
446 |
-
}
|
447 |
-
|
448 |
-
.txt_14_bleu_f:hover {
|
449 |
-
color: red;
|
450 |
-
}
|
451 |
-
|
452 |
-
/*-----------------------------------------------------------------------------------*/
|
453 |
-
.txt_10_vert_f {
|
454 |
-
color: darkgreen;
|
455 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
456 |
-
font-size: 10px;
|
457 |
-
text-decoration: none;
|
458 |
-
}
|
459 |
-
|
460 |
-
.txt_10_vert_f:link,.txt_10_vert_f:visited,.txt_10_vert_f:active {
|
461 |
-
color: darkgreen;
|
462 |
-
}
|
463 |
-
|
464 |
-
.txt_10_vert_f:hover {
|
465 |
-
color: red;
|
466 |
-
}
|
467 |
-
|
468 |
-
.txt_11_vert_f {
|
469 |
-
color: darkgreen;
|
470 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
471 |
-
font-size: 11px;
|
472 |
-
text-decoration: none;
|
473 |
-
}
|
474 |
-
|
475 |
-
.txt_11_vert_f:link,.txt_11_vert_f:visited,.txt_11_vert_f:active {
|
476 |
-
color: darkgreen;
|
477 |
-
}
|
478 |
-
|
479 |
-
.txt_11_vert_f:hover {
|
480 |
-
color: red;
|
481 |
-
}
|
482 |
-
|
483 |
-
.txt_12_vert_f {
|
484 |
-
color: darkgreen;
|
485 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
486 |
-
font-size: 12px;
|
487 |
-
text-decoration: none;
|
488 |
-
}
|
489 |
-
|
490 |
-
.txt_12_vert_f:link,.txt_12_vertf:visited,.txt_12_vert_f:active {
|
491 |
-
color: darkgreen;
|
492 |
-
}
|
493 |
-
|
494 |
-
.txt_12_vert_f:hover {
|
495 |
-
color: red;
|
496 |
-
}
|
497 |
-
|
498 |
-
.txt_14_vert_f {
|
499 |
-
color: darkgreen;
|
500 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
501 |
-
font-size: 14px;
|
502 |
-
text-decoration: none;
|
503 |
-
}
|
504 |
-
|
505 |
-
.txt_14_vert_f:link,.txt_14_vert_f:visited,.txt_14_vert_f:active {
|
506 |
-
color: darkgreen;
|
507 |
-
}
|
508 |
-
|
509 |
-
.txt_14_vert_f:hover {
|
510 |
-
color: red;
|
511 |
-
}
|
512 |
-
|
513 |
-
/*-----------------------------------------------------------------------------------*/
|
514 |
-
.txt_10_vert {
|
515 |
-
color: green;
|
516 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
517 |
-
font-size: 10px;
|
518 |
-
text-decoration: none;
|
519 |
-
}
|
520 |
-
|
521 |
-
.txt_10_vert:link,.txt_10_vert:visited,.txt_10_vert:active {
|
522 |
-
color: green;
|
523 |
-
}
|
524 |
-
|
525 |
-
.txt_10_vert:hover {
|
526 |
-
color: red;
|
527 |
-
}
|
528 |
-
|
529 |
-
.txt_11_vert {
|
530 |
-
color: green;
|
531 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
532 |
-
font-size: 11px;
|
533 |
-
text-decoration: none;
|
534 |
-
}
|
535 |
-
|
536 |
-
.txt_11_vert:link,.txt_11_vert:visited,.txt_11_vert:active {
|
537 |
-
color: green;
|
538 |
-
}
|
539 |
-
|
540 |
-
.txt_11_vert:hover {
|
541 |
-
color: red;
|
542 |
-
}
|
543 |
-
|
544 |
-
.txt_12_vert {
|
545 |
-
color: green;
|
546 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
547 |
-
font-size: 12px;
|
548 |
-
text-decoration: none;
|
549 |
-
}
|
550 |
-
|
551 |
-
.txt_12_vert:link,.txt_12_vert:visited,.txt_12_vert:active {
|
552 |
-
color: green;
|
553 |
-
}
|
554 |
-
|
555 |
-
.txt_12_vert:hover {
|
556 |
-
color: red;
|
557 |
-
}
|
558 |
-
|
559 |
-
.txt_14_vert {
|
560 |
-
color: green;
|
561 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
562 |
-
font-size: 14px;
|
563 |
-
text-decoration: none;
|
564 |
-
}
|
565 |
-
|
566 |
-
.txt_14_vert:link,.txt_14_vert:visited,.txt_14_vert:active {
|
567 |
-
color: green;
|
568 |
-
}
|
569 |
-
|
570 |
-
.txt_14_vert:hover {
|
571 |
-
color: red;
|
572 |
-
}
|
573 |
-
|
574 |
-
/*-----------------------------------------------------------------------------------*/
|
575 |
-
.fond_blanc {
|
576 |
-
background-color: #FFFFFF;
|
577 |
-
color: black;
|
578 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
579 |
-
font-size: 11px;
|
580 |
-
text-decoration: none;
|
581 |
-
}
|
582 |
-
|
583 |
-
.fond_gris_c, .fond_gris_c tr {
|
584 |
-
background-color: #FFFFFF;
|
585 |
-
color: black;
|
586 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
587 |
-
font-size: 11px;
|
588 |
-
text-decoration: none;
|
589 |
-
background-image: url(../images/fond_4.bmp);
|
590 |
-
background-repeat: repeat-x;
|
591 |
-
}
|
592 |
-
|
593 |
-
.fond_gris_c2, .fond_gris_c2 tr {
|
594 |
-
background-color: #FBFBFB;
|
595 |
-
color: black;
|
596 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
597 |
-
font-size: 11px;
|
598 |
-
text-decoration: none;
|
599 |
-
}
|
600 |
-
|
601 |
-
.fond_bleu_c, .fond_bleu_c tr {
|
602 |
-
background-color: #D9EEF9;
|
603 |
-
color: black;
|
604 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
605 |
-
font-size: 11px;
|
606 |
-
text-decoration: none;
|
607 |
-
background-image: url(../images/fond_1.bmp);
|
608 |
-
}
|
609 |
-
|
610 |
-
.fond_bleu_c2 {
|
611 |
-
background-color: #ECF4FF;
|
612 |
-
color: black;
|
613 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
614 |
-
font-size: 11px;
|
615 |
-
text-decoration: none;
|
616 |
-
}
|
617 |
-
|
618 |
-
.fond_bleu_f {
|
619 |
-
background-color: #003366;
|
620 |
-
color: black;
|
621 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
622 |
-
font-size: 11px;
|
623 |
-
text-decoration: none;
|
624 |
-
}
|
625 |
-
|
626 |
-
.fond_orange {
|
627 |
-
background-color: #FEEFE7;
|
628 |
-
color: darkgreen;
|
629 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
630 |
-
font-size: 12px;
|
631 |
-
font-weight: bold;
|
632 |
-
text-decoration: none;
|
633 |
-
background-image: url(../images/fond_3.jpg);
|
634 |
-
}
|
635 |
-
|
636 |
-
.fond_orange_2 {
|
637 |
-
background-color: #FFF8F4;
|
638 |
-
color: darkgreen;
|
639 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
640 |
-
font-size: 12px;
|
641 |
-
font-weight: bold;
|
642 |
-
text-decoration: none;
|
643 |
-
border: 1px solid orange;
|
644 |
-
border-collapse: collapse;
|
645 |
-
}
|
646 |
-
|
647 |
-
.vccDlgBody {
|
648 |
-
border: 3px solid #336699;
|
649 |
-
border-collapse: collapse;
|
650 |
-
color: black;
|
651 |
-
background-color: #EEFFEE;
|
652 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
653 |
-
font-size: 11px;
|
654 |
-
text-decoration: none;
|
655 |
-
}
|
656 |
-
|
657 |
-
/* DEFINITION DES STYLES DE TABLEAUX */
|
658 |
-
.bordure_0 {
|
659 |
-
border: 0px solid;
|
660 |
-
color: black;
|
661 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
662 |
-
font-size: 11px;
|
663 |
-
text-decoration: none;
|
664 |
-
}
|
665 |
-
|
666 |
-
.bordure_1_bleu {
|
667 |
-
border: 1px solid green;
|
668 |
-
border-collapse: collapse;
|
669 |
-
color: black;
|
670 |
-
background-color: #FFFFFF;
|
671 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
672 |
-
font-size: 11px;
|
673 |
-
text-decoration: none;
|
674 |
-
}
|
675 |
-
|
676 |
-
.bordure_3_bleu {
|
677 |
-
border: 3px solid #336699;
|
678 |
-
border-collapse: collapse;
|
679 |
-
color: black;
|
680 |
-
background-color: #FFFFFF;
|
681 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
682 |
-
font-size: 11px;
|
683 |
-
text-decoration: none;
|
684 |
-
}
|
685 |
-
|
686 |
-
.indent {
|
687 |
-
margin-left: 20px;
|
688 |
-
}
|
689 |
-
|
690 |
-
/* DEFINITION DES STYLES D'OBJETS DE FORMULAIRE */
|
691 |
-
.Btn {
|
692 |
-
color: #003366;
|
693 |
-
text-align: center;
|
694 |
-
font-weight: bold;
|
695 |
-
background-color: #FFFFFF;
|
696 |
-
background-image: url(../images/ongletStyle1.jpg);
|
697 |
-
background-repeat: no-repeat;
|
698 |
-
background-position: center center;
|
699 |
-
}
|
700 |
-
|
701 |
-
.Btn:hover {
|
702 |
-
color: red;
|
703 |
-
}
|
704 |
-
|
705 |
-
.menu1h {
|
706 |
-
background-color: #003366;
|
707 |
-
color: white;
|
708 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
709 |
-
font-size: 10px;
|
710 |
-
font-weight: bold;
|
711 |
-
text-decoration: none;
|
712 |
-
border-top: 1px solid #003366;
|
713 |
-
border-bottom: 1px solid #003366;
|
714 |
-
border-left: 1px solid #003366;
|
715 |
-
border-right: 1px solid white;
|
716 |
-
border-collapse: collapse;
|
717 |
-
display: block;
|
718 |
-
}
|
719 |
-
|
720 |
-
.menu1h:hover {
|
721 |
-
background-color: white;
|
722 |
-
color: red;
|
723 |
-
border: 1px solid darkgreen;
|
724 |
-
border-collapse: collapse;
|
725 |
-
}
|
726 |
-
|
727 |
-
.menu1h_f {
|
728 |
-
background-color: #003366;
|
729 |
-
color: white;
|
730 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
731 |
-
font-size: 10px;
|
732 |
-
font-weight: bold;
|
733 |
-
text-decoration: none;
|
734 |
-
border: 1px solid #003366;
|
735 |
-
display: block;
|
736 |
-
}
|
737 |
-
|
738 |
-
.menu1h_f:hover {
|
739 |
-
background-color: white;
|
740 |
-
color: red;
|
741 |
-
border: 1px solid darkgreen;
|
742 |
-
border-collapse: collapse;
|
743 |
-
}
|
744 |
-
|
745 |
-
.menu1v {
|
746 |
-
background-color: #003366;
|
747 |
-
color: white;
|
748 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
749 |
-
font-size: 10px;
|
750 |
-
font-weight: bold;
|
751 |
-
text-decoration: none;
|
752 |
-
border: 1px solid #003366;
|
753 |
-
border-collapse: collapse;
|
754 |
-
display: block;
|
755 |
-
}
|
756 |
-
|
757 |
-
.menu1v:hover {
|
758 |
-
background-color: white;
|
759 |
-
color: red;
|
760 |
-
border: 1px solid darkgreen;
|
761 |
-
border-collapse: collapse;
|
762 |
-
}
|
763 |
-
|
764 |
-
.menu2v {
|
765 |
-
background-color: #5588BB;
|
766 |
-
color: white;
|
767 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
768 |
-
font-size: 12px;
|
769 |
-
font-weight: bold;
|
770 |
-
text-decoration: none;
|
771 |
-
border: 1px solid #4277AB;
|
772 |
-
border-collapse: collapse;
|
773 |
-
float: left;
|
774 |
-
display: block;
|
775 |
-
}
|
776 |
-
|
777 |
-
.menu2v:hover {
|
778 |
-
background-color: white;
|
779 |
-
color: red;
|
780 |
-
border: 1px solid darkgreen;
|
781 |
-
border-collapse: collapse;
|
782 |
-
}
|
783 |
-
|
784 |
-
.menuEDF {
|
785 |
-
background-color: #003366;
|
786 |
-
color: white;
|
787 |
-
font-family: Verdana, Arial, Lucida, Tahoma;
|
788 |
-
font-size: 10px;
|
789 |
-
text-decoration: none;
|
790 |
-
}
|
791 |
-
|
792 |
-
.menuEDF:hover {
|
793 |
-
color: #FF8800;
|
794 |
-
}
|
795 |
-
|
796 |
-
/*bouton bleu sur blanc*/
|
797 |
-
.Bouton {
|
798 |
-
color: #003366;
|
799 |
-
text-align: center;
|
800 |
-
font-weight: bold;
|
801 |
-
/* Ricardo cursor: hand; */
|
802 |
-
cursor: pointer;
|
803 |
-
background-color: #FFFFFF;
|
804 |
-
}
|
805 |
-
|
806 |
-
input {
|
807 |
-
border: 2px solid green;
|
808 |
-
color: #003366;
|
809 |
-
background-color: #FFFFFF;
|
810 |
-
background-image: url(../images/fond_4.bmp);
|
811 |
-
background-repeat: repeat-x;
|
812 |
-
}
|
813 |
-
|
814 |
-
.disabled_input {
|
815 |
-
border: 1px solid gray;
|
816 |
-
color: grey;
|
817 |
-
background-color: #FFFFFF;
|
818 |
-
background-image: url(../images/fond_4.bmp);
|
819 |
-
background-repeat: repeat-x;
|
820 |
-
}
|
821 |
-
|
822 |
-
.input0 {
|
823 |
-
border: 0px;
|
824 |
-
color: #003366;
|
825 |
-
background-color: #FFFFFF;
|
826 |
-
background-image: url(../images/fond_4.bmp);
|
827 |
-
}
|
828 |
-
|
829 |
-
.input2 {
|
830 |
-
border: 1px solid green;
|
831 |
-
color: #003366;
|
832 |
-
background-color: #FFFFFF;
|
833 |
-
background-image: url(../images/fond_4.bmp);
|
834 |
-
background-repeat: repeat-x;
|
835 |
-
}
|
836 |
-
|
837 |
-
.input3 {
|
838 |
-
border: 1px solid black;
|
839 |
-
color: #003366;
|
840 |
-
background-color: #EEEEEE;
|
841 |
-
background-image: url();
|
842 |
-
}
|
843 |
-
|
844 |
-
.input4 {
|
845 |
-
border: 1px solid blue;
|
846 |
-
color: #003366;
|
847 |
-
background-color: #FFFFFF;
|
848 |
-
background-image: url(../images/fond_4.bmp);
|
849 |
-
background-repeat: repeat-x;
|
850 |
-
}
|
851 |
-
|
852 |
-
.input5 {
|
853 |
-
border: 1px solid darkblue;
|
854 |
-
color: #003366;
|
855 |
-
background-color: #FFFFFF;
|
856 |
-
background-image: url(../images/fond_4.bmp);
|
857 |
-
background-repeat: repeat-x;
|
858 |
-
}
|
859 |
-
|
860 |
-
.input_btn {
|
861 |
-
border: 0px;
|
862 |
-
/* cursor: hand; */
|
863 |
-
cursor: pointer;
|
864 |
-
}
|
865 |
-
|
866 |
-
textarea {
|
867 |
-
border: 2px solid green;
|
868 |
-
color: #003366;
|
869 |
-
background-color: #FFFFFF;
|
870 |
-
background-image: url(../images/fond_5.bmp);
|
871 |
-
}
|
872 |
-
|
873 |
-
.TEXTAREA3 {
|
874 |
-
border: 1px solid green;
|
875 |
-
color: #003366;
|
876 |
-
background-color: #FFFFFF;
|
877 |
-
background-image: url();
|
878 |
-
}
|
879 |
-
|
880 |
-
.TEXTAREA4 {
|
881 |
-
border: 1px solid green;
|
882 |
-
color: #003366;
|
883 |
-
background-color: #EEEEEE;
|
884 |
-
background-image: url();
|
885 |
-
}
|
886 |
-
|
887 |
-
.hand {
|
888 |
-
cursor: hand;
|
889 |
-
cursor: pointer;
|
890 |
Â
}
|
1 |
+
/*
|
2 |
+
* DEFINITION DES STYLES DE TEXTE
|
3 |
+
*/
|
4 |
+
/*-----------------------------------------------------------------------------------*/
|
5 |
+
h1 {
|
6 |
+
color: #339933;
|
7 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
8 |
+
font-size: 14px;
|
9 |
+
font-weight: bold;
|
10 |
+
text-decoration: none;
|
11 |
+
}
|
12 |
+
|
13 |
+
h2 {
|
14 |
+
color: #339933;
|
15 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
16 |
+
font-size: 12px;
|
17 |
+
font-weight: bold;
|
18 |
+
text-decoration: none;
|
19 |
+
}
|
20 |
+
|
21 |
+
h1,h2,h3,h4,h5 {
|
22 |
+
margin: 0px;
|
23 |
+
padding: 0px;
|
24 |
+
}
|
25 |
+
|
26 |
+
.txt_10_noir {
|
27 |
+
color: black;
|
28 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
29 |
+
font-size: 10px;
|
30 |
+
text-decoration: none;
|
31 |
+
}
|
32 |
+
|
33 |
+
.txt_10_noir:link,.txt_10_noir:visited,.txt_10_noir:active {
|
34 |
+
color: black;
|
35 |
+
}
|
36 |
+
|
37 |
+
.txt_10_noir:hover {
|
38 |
+
color: red;
|
39 |
+
}
|
40 |
+
|
41 |
+
.txt_11_noir {
|
42 |
+
color: black;
|
43 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
44 |
+
font-size: 11px;
|
45 |
+
text-decoration: none;
|
46 |
+
}
|
47 |
+
|
48 |
+
.txt_11_noir:link,.txt_11_noir:visited,.txt_11_noir:active {
|
49 |
+
color: black;
|
50 |
+
}
|
51 |
+
|
52 |
+
.txt_11_noir:hover {
|
53 |
+
color: red;
|
54 |
+
}
|
55 |
+
|
56 |
+
.txt_12_noir {
|
57 |
+
color: black;
|
58 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
59 |
+
font-size: 12px;
|
60 |
+
text-decoration: none;
|
61 |
+
}
|
62 |
+
|
63 |
+
.txt_12_noir:link,.txt_12_noir:visited,.txt_12_noir:active {
|
64 |
+
color: black;
|
65 |
+
}
|
66 |
+
|
67 |
+
.txt_12_noir:hover {
|
68 |
+
color: red;
|
69 |
+
}
|
70 |
+
|
71 |
+
.txt_14_noir {
|
72 |
+
color: black;
|
73 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
74 |
+
font-size: 14px;
|
75 |
+
text-decoration: none;
|
76 |
+
}
|
77 |
+
|
78 |
+
.txt_14_noir:link,.txt_14_noir:visited,.txt_14_noir:active {
|
79 |
+
color: black;
|
80 |
+
}
|
81 |
+
|
82 |
+
.txt_14_noir:hover {
|
83 |
+
color: red;
|
84 |
+
}
|
85 |
+
|
86 |
+
/*-----------------------------------------------------------------------------------*/
|
87 |
+
.txt_10_gris {
|
88 |
+
color: grey;
|
89 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
90 |
+
font-size: 10px;
|
91 |
+
text-decoration: none;
|
92 |
+
}
|
93 |
+
|
94 |
+
.txt_10_gris:link,.txt_10_gris:visited,.txt_10_gris:active {
|
95 |
+
color: grey;
|
96 |
+
}
|
97 |
+
|
98 |
+
.txt_10_gris:hover {
|
99 |
+
color: red;
|
100 |
+
}
|
101 |
+
|
102 |
+
.txt_11_gris {
|
103 |
+
color: grey;
|
104 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
105 |
+
font-size: 11px;
|
106 |
+
text-decoration: none;
|
107 |
+
}
|
108 |
+
|
109 |
+
.txt_11_gris:link,.txt_11_gris:visited,.txt_11_gris:active {
|
110 |
+
color: grey;
|
111 |
+
}
|
112 |
+
|
113 |
+
.txt_11_gris:hover {
|
114 |
+
color: red;
|
115 |
+
}
|
116 |
+
|
117 |
+
.txt_12_gris {
|
118 |
+
color: grey;
|
119 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
120 |
+
font-size: 12px;
|
121 |
+
text-decoration: none;
|
122 |
+
}
|
123 |
+
|
124 |
+
.txt_12_gris:link,.txt_12_gris:visited,.txt_12_gris:active {
|
125 |
+
color: grey;
|
126 |
+
}
|
127 |
+
|
128 |
+
.txt_12_gris:hover {
|
129 |
+
color: red;
|
130 |
+
}
|
131 |
+
|
132 |
+
.txt_14_gris {
|
133 |
+
color: grey;
|
134 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
135 |
+
font-size: 14px;
|
136 |
+
text-decoration: none;
|
137 |
+
}
|
138 |
+
|
139 |
+
.txt_14_gris:link,.txt_14_gris:visited,.txt_14_gris:active {
|
140 |
+
color: grey;
|
141 |
+
}
|
142 |
+
|
143 |
+
.txt_14_gris:hover {
|
144 |
+
color: red;
|
145 |
+
}
|
146 |
+
|
147 |
+
/*-----------------------------------------------------------------------------------*/
|
148 |
+
.txt_10_blanc {
|
149 |
+
color: #FFFFFF;
|
150 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
151 |
+
font-size: 10px;
|
152 |
+
text-decoration: none;
|
153 |
+
}
|
154 |
+
|
155 |
+
.txt_10_blanc:link,.txt_10_blanc:visited,.txt_10_blanc:active {
|
156 |
+
color: #FFFFFF;
|
157 |
+
}
|
158 |
+
|
159 |
+
.txt_10_blanc:hover {
|
160 |
+
color: #FF8800; /*ORANGE*/
|
161 |
+
}
|
162 |
+
|
163 |
+
.txt_11_blanc {
|
164 |
+
color: #FFFFFF;
|
165 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
166 |
+
font-size: 11px;
|
167 |
+
text-decoration: none;
|
168 |
+
}
|
169 |
+
|
170 |
+
.txt_11_blanc:link,.txt_11_blanc:visited,.txt_11_blanc:active {
|
171 |
+
color: #FFFFFF;
|
172 |
+
}
|
173 |
+
|
174 |
+
.txt_11_blanc:hover {
|
175 |
+
color: #FF8800;
|
176 |
+
}
|
177 |
+
|
178 |
+
.txt_12_blanc {
|
179 |
+
color: #FFFFFF;
|
180 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
181 |
+
font-size: 12px;
|
182 |
+
text-decoration: none;
|
183 |
+
}
|
184 |
+
|
185 |
+
.txt_12_blanc:link,.txt_12_blanc:visited,.txt_12_blanc:active {
|
186 |
+
color: #FFFFFF;
|
187 |
+
}
|
188 |
+
|
189 |
+
.txt_12_blanc:hover {
|
190 |
+
color: #FFAA00;
|
191 |
+
}
|
192 |
+
|
193 |
+
.txt_14_blanc {
|
194 |
+
color: #FFFFFF;
|
195 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
196 |
+
font-size: 14px;
|
197 |
+
text-decoration: none;
|
198 |
+
}
|
199 |
+
|
200 |
+
.txt_14_blanc:link,.txt_14_blanc:visited,.txt_14_blanc:active {
|
201 |
+
color: #FFFFFF;
|
202 |
+
}
|
203 |
+
|
204 |
+
.txt_14_blanc:hover {
|
205 |
+
color: #FF8800;
|
206 |
+
}
|
207 |
+
|
208 |
+
/*-----------------------------------------------------------------------------------*/
|
209 |
+
.txt_10_orange {
|
210 |
+
color: #FF8800;
|
211 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
212 |
+
font-size: 10px;
|
213 |
+
text-decoration: none;
|
214 |
+
}
|
215 |
+
|
216 |
+
.txt_10_orange:link,.txt_10_orange:visited,.txt_10_orange:active {
|
217 |
+
color: #FF8800;
|
218 |
+
}
|
219 |
+
|
220 |
+
.txt_10_orange:hover {
|
221 |
+
color: darkblue
|
222 |
+
}
|
223 |
+
|
224 |
+
.txt_11_orange {
|
225 |
+
color: #FF8800;
|
226 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
227 |
+
font-size: 11px;
|
228 |
+
text-decoration: none;
|
229 |
+
}
|
230 |
+
|
231 |
+
.txt_11_orange:link,.txt_11_orange:visited,.txt_11_orange:active {
|
232 |
+
color: #FF8800;
|
233 |
+
}
|
234 |
+
|
235 |
+
.txt_11_orange:hover {
|
236 |
+
color: darkblue;
|
237 |
+
}
|
238 |
+
|
239 |
+
.txt_12_orange {
|
240 |
+
color: #FF8800;
|
241 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
242 |
+
font-size: 12px;
|
243 |
+
text-decoration: none;
|
244 |
+
}
|
245 |
+
|
246 |
+
.txt_12_orange:link,.txt_12_orange:visited,.txt_12_orange:active {
|
247 |
+
color: #FF8800;
|
248 |
+
}
|
249 |
+
|
250 |
+
.txt_12_orange:hover {
|
251 |
+
color: darkblue;
|
252 |
+
}
|
253 |
+
|
254 |
+
.txt_14_orange {
|
255 |
+
color: #FF8800;
|
256 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
257 |
+
font-size: 14px;
|
258 |
+
text-decoration: none;
|
259 |
+
}
|
260 |
+
|
261 |
+
.txt_14_orange:link,.txt_14_orange:visited,.txt_14_orange:active {
|
262 |
+
color: #FF8800;
|
263 |
+
}
|
264 |
+
|
265 |
+
.txt_14_orange:hover {
|
266 |
+
color: darkblue;
|
267 |
+
}
|
268 |
+
|
269 |
+
/*-----------------------------------------------------------------------------------*/
|
270 |
+
.txt_10_rouge {
|
271 |
+
color: red;
|
272 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
273 |
+
font-size: 10px;
|
274 |
+
text-decoration: none;
|
275 |
+
}
|
276 |
+
|
277 |
+
.txt_10_rouge:link,.txt_10_rouge:visited,.txt_10_rouge:active {
|
278 |
+
color: red;
|
279 |
+
}
|
280 |
+
|
281 |
+
.txt_10_rouge:hover {
|
282 |
+
color: darkblue;
|
283 |
+
}
|
284 |
+
|
285 |
+
.txt_11_rouge {
|
286 |
+
color: red;
|
287 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
288 |
+
font-size: 11px;
|
289 |
+
text-decoration: none;
|
290 |
+
}
|
291 |
+
|
292 |
+
.txt_11_rouge:link,.txt_11_rouge:visited,.txt_11_rouge:active {
|
293 |
+
color: red;
|
294 |
+
}
|
295 |
+
|
296 |
+
.txt_11_rouge:hover {
|
297 |
+
color: darkblue;
|
298 |
+
}
|
299 |
+
|
300 |
+
.txt_12_rouge {
|
301 |
+
color: red;
|
302 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
303 |
+
font-size: 12px;
|
304 |
+
text-decoration: none;
|
305 |
+
}
|
306 |
+
|
307 |
+
.txt_12_rouge:link,.txt_12_rouge:visited,.txt_12_rouge:active {
|
308 |
+
color: red;
|
309 |
+
}
|
310 |
+
|
311 |
+
.txt_12_rouge:hover {
|
312 |
+
color: darkblue;
|
313 |
+
}
|
314 |
+
|
315 |
+
.txt_14_rouge {
|
316 |
+
color: red;
|
317 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
318 |
+
font-size: 14px;
|
319 |
+
text-decoration: none;
|
320 |
+
}
|
321 |
+
|
322 |
+
.txt_14_rouge:link,.txt_14_rouge:visited,.txt_14_rouge:active {
|
323 |
+
color: red;
|
324 |
+
}
|
325 |
+
|
326 |
+
.txt_14_rouge:hover {
|
327 |
+
color: darkblue;
|
328 |
+
}
|
329 |
+
|
330 |
+
/*-----------------------------------------------------------------------------------*/
|
331 |
+
.txt_10_bleu {
|
332 |
+
color: blue;
|
333 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
334 |
+
font-size: 10px;
|
335 |
+
text-decoration: none;
|
336 |
+
}
|
337 |
+
|
338 |
+
.txt_10_bleu:link,.txt_10_bleu:visited,.txt_10_bleu:active {
|
339 |
+
color: blue;
|
340 |
+
}
|
341 |
+
|
342 |
+
.txt_10_bleu:hover {
|
343 |
+
color: red;
|
344 |
+
}
|
345 |
+
|
346 |
+
.txt_11_bleu {
|
347 |
+
color: blue;
|
348 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
349 |
+
font-size: 11px;
|
350 |
+
text-decoration: none;
|
351 |
+
}
|
352 |
+
|
353 |
+
.txt_11_bleu:link,.txt_11_bleu:visited,.txt_11_bleu:active {
|
354 |
+
color: blue;
|
355 |
+
}
|
356 |
+
|
357 |
+
.txt_11_bleu:hover {
|
358 |
+
color: red;
|
359 |
+
}
|
360 |
+
|
361 |
+
.txt_12_bleu {
|
362 |
+
color: blue;
|
363 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
364 |
+
font-size: 12px;
|
365 |
+
text-decoration: none;
|
366 |
+
}
|
367 |
+
|
368 |
+
.txt_12_bleu:link,.txt_12_bleu:visited,.txt_12_bleu:active {
|
369 |
+
color: blue;
|
370 |
+
}
|
371 |
+
|
372 |
+
.txt_12_bleu:hover {
|
373 |
+
color: red;
|
374 |
+
}
|
375 |
+
|
376 |
+
.txt_14_bleu {
|
377 |
+
color: blue;
|
378 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
379 |
+
font-size: 14px;
|
380 |
+
text-decoration: none;
|
381 |
+
}
|
382 |
+
|
383 |
+
.txt_14_bleu:link,.txt_14_bleu:visited,.txt_14_bleu:active {
|
384 |
+
color: blue;
|
385 |
+
}
|
386 |
+
|
387 |
+
.txt_14_bleu:hover {
|
388 |
+
color: red;
|
389 |
+
}
|
390 |
+
|
391 |
+
/*-----------------------------------------------------------------------------------*/
|
392 |
+
.txt_10_bleu_f {
|
393 |
+
color: darkblue;
|
394 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
395 |
+
font-size: 10px;
|
396 |
+
text-decoration: none;
|
397 |
+
}
|
398 |
+
|
399 |
+
.txt_10_bleu_f:link,.txt_10_bleu_f:visited,.txt_10_bleu_f:active {
|
400 |
+
color: darkblue;
|
401 |
+
}
|
402 |
+
|
403 |
+
.txt_10_bleu_f:hover {
|
404 |
+
color: red;
|
405 |
+
}
|
406 |
+
|
407 |
+
.txt_11_bleu_f {
|
408 |
+
color: darkblue;
|
409 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
410 |
+
font-size: 11px;
|
411 |
+
text-decoration: none;
|
412 |
+
}
|
413 |
+
|
414 |
+
.txt_11_bleu_f:link,.txt_11_bleu_f:visited,.txt_11_bleu_f:active {
|
415 |
+
color: darkblue;
|
416 |
+
}
|
417 |
+
|
418 |
+
.txt_11_bleu_f:hover {
|
419 |
+
color: red;
|
420 |
+
}
|
421 |
+
|
422 |
+
.txt_12_bleu_f {
|
423 |
+
color: darkblue;
|
424 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
425 |
+
font-size: 12px;
|
426 |
+
text-decoration: none;
|
427 |
+
}
|
428 |
+
|
429 |
+
.txt_12_bleu_f:link,.txt_12_bleu_f:visited,.txt_12_bleu_f:active {
|
430 |
+
color: darkblue;
|
431 |
+
}
|
432 |
+
|
433 |
+
.txt_12_bleu_f:hover {
|
434 |
+
color: red;
|
435 |
+
}
|
436 |
+
|
437 |
+
.txt_14_bleu_f {
|
438 |
+
color: darkblue;
|
439 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
440 |
+
font-size: 14px;
|
441 |
+
text-decoration: none;
|
442 |
+
}
|
443 |
+
|
444 |
+
.txt_14_bleu_f:link,.txt_14_bleu_f:visited,.txt_14_bleu_f:active {
|
445 |
+
color: darkblue;
|
446 |
+
}
|
447 |
+
|
448 |
+
.txt_14_bleu_f:hover {
|
449 |
+
color: red;
|
450 |
+
}
|
451 |
+
|
452 |
+
/*-----------------------------------------------------------------------------------*/
|
453 |
+
.txt_10_vert_f {
|
454 |
+
color: darkgreen;
|
455 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
456 |
+
font-size: 10px;
|
457 |
+
text-decoration: none;
|
458 |
+
}
|
459 |
+
|
460 |
+
.txt_10_vert_f:link,.txt_10_vert_f:visited,.txt_10_vert_f:active {
|
461 |
+
color: darkgreen;
|
462 |
+
}
|
463 |
+
|
464 |
+
.txt_10_vert_f:hover {
|
465 |
+
color: red;
|
466 |
+
}
|
467 |
+
|
468 |
+
.txt_11_vert_f {
|
469 |
+
color: darkgreen;
|
470 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
471 |
+
font-size: 11px;
|
472 |
+
text-decoration: none;
|
473 |
+
}
|
474 |
+
|
475 |
+
.txt_11_vert_f:link,.txt_11_vert_f:visited,.txt_11_vert_f:active {
|
476 |
+
color: darkgreen;
|
477 |
+
}
|
478 |
+
|
479 |
+
.txt_11_vert_f:hover {
|
480 |
+
color: red;
|
481 |
+
}
|
482 |
+
|
483 |
+
.txt_12_vert_f {
|
484 |
+
color: darkgreen;
|
485 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
486 |
+
font-size: 12px;
|
487 |
+
text-decoration: none;
|
488 |
+
}
|
489 |
+
|
490 |
+
.txt_12_vert_f:link,.txt_12_vertf:visited,.txt_12_vert_f:active {
|
491 |
+
color: darkgreen;
|
492 |
+
}
|
493 |
+
|
494 |
+
.txt_12_vert_f:hover {
|
495 |
+
color: red;
|
496 |
+
}
|
497 |
+
|
498 |
+
.txt_14_vert_f {
|
499 |
+
color: darkgreen;
|
500 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
501 |
+
font-size: 14px;
|
502 |
+
text-decoration: none;
|
503 |
+
}
|
504 |
+
|
505 |
+
.txt_14_vert_f:link,.txt_14_vert_f:visited,.txt_14_vert_f:active {
|
506 |
+
color: darkgreen;
|
507 |
+
}
|
508 |
+
|
509 |
+
.txt_14_vert_f:hover {
|
510 |
+
color: red;
|
511 |
+
}
|
512 |
+
|
513 |
+
/*-----------------------------------------------------------------------------------*/
|
514 |
+
.txt_10_vert {
|
515 |
+
color: green;
|
516 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
517 |
+
font-size: 10px;
|
518 |
+
text-decoration: none;
|
519 |
+
}
|
520 |
+
|
521 |
+
.txt_10_vert:link,.txt_10_vert:visited,.txt_10_vert:active {
|
522 |
+
color: green;
|
523 |
+
}
|
524 |
+
|
525 |
+
.txt_10_vert:hover {
|
526 |
+
color: red;
|
527 |
+
}
|
528 |
+
|
529 |
+
.txt_11_vert {
|
530 |
+
color: green;
|
531 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
532 |
+
font-size: 11px;
|
533 |
+
text-decoration: none;
|
534 |
+
}
|
535 |
+
|
536 |
+
.txt_11_vert:link,.txt_11_vert:visited,.txt_11_vert:active {
|
537 |
+
color: green;
|
538 |
+
}
|
539 |
+
|
540 |
+
.txt_11_vert:hover {
|
541 |
+
color: red;
|
542 |
+
}
|
543 |
+
|
544 |
+
.txt_12_vert {
|
545 |
+
color: green;
|
546 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
547 |
+
font-size: 12px;
|
548 |
+
text-decoration: none;
|
549 |
+
}
|
550 |
+
|
551 |
+
.txt_12_vert:link,.txt_12_vert:visited,.txt_12_vert:active {
|
552 |
+
color: green;
|
553 |
+
}
|
554 |
+
|
555 |
+
.txt_12_vert:hover {
|
556 |
+
color: red;
|
557 |
+
}
|
558 |
+
|
559 |
+
.txt_14_vert {
|
560 |
+
color: green;
|
561 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
562 |
+
font-size: 14px;
|
563 |
+
text-decoration: none;
|
564 |
+
}
|
565 |
+
|
566 |
+
.txt_14_vert:link,.txt_14_vert:visited,.txt_14_vert:active {
|
567 |
+
color: green;
|
568 |
+
}
|
569 |
+
|
570 |
+
.txt_14_vert:hover {
|
571 |
+
color: red;
|
572 |
+
}
|
573 |
+
|
574 |
+
/*-----------------------------------------------------------------------------------*/
|
575 |
+
.fond_blanc {
|
576 |
+
background-color: #FFFFFF;
|
577 |
+
color: black;
|
578 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
579 |
+
font-size: 11px;
|
580 |
+
text-decoration: none;
|
581 |
+
}
|
582 |
+
|
583 |
+
.fond_gris_c, .fond_gris_c tr {
|
584 |
+
background-color: #FFFFFF;
|
585 |
+
color: black;
|
586 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
587 |
+
font-size: 11px;
|
588 |
+
text-decoration: none;
|
589 |
+
background-image: url(../images/fond_4.bmp);
|
590 |
+
background-repeat: repeat-x;
|
591 |
+
}
|
592 |
+
|
593 |
+
.fond_gris_c2, .fond_gris_c2 tr {
|
594 |
+
background-color: #FBFBFB;
|
595 |
+
color: black;
|
596 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
597 |
+
font-size: 11px;
|
598 |
+
text-decoration: none;
|
599 |
+
}
|
600 |
+
|
601 |
+
.fond_bleu_c, .fond_bleu_c tr {
|
602 |
+
background-color: #D9EEF9;
|
603 |
+
color: black;
|
604 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
605 |
+
font-size: 11px;
|
606 |
+
text-decoration: none;
|
607 |
+
background-image: url(../images/fond_1.bmp);
|
608 |
+
}
|
609 |
+
|
610 |
+
.fond_bleu_c2 {
|
611 |
+
background-color: #ECF4FF;
|
612 |
+
color: black;
|
613 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
614 |
+
font-size: 11px;
|
615 |
+
text-decoration: none;
|
616 |
+
}
|
617 |
+
|
618 |
+
.fond_bleu_f {
|
619 |
+
background-color: #003366;
|
620 |
+
color: black;
|
621 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
622 |
+
font-size: 11px;
|
623 |
+
text-decoration: none;
|
624 |
+
}
|
625 |
+
|
626 |
+
.fond_orange {
|
627 |
+
background-color: #FEEFE7;
|
628 |
+
color: darkgreen;
|
629 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
630 |
+
font-size: 12px;
|
631 |
+
font-weight: bold;
|
632 |
+
text-decoration: none;
|
633 |
+
background-image: url(../images/fond_3.jpg);
|
634 |
+
}
|
635 |
+
|
636 |
+
.fond_orange_2 {
|
637 |
+
background-color: #FFF8F4;
|
638 |
+
color: darkgreen;
|
639 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
640 |
+
font-size: 12px;
|
641 |
+
font-weight: bold;
|
642 |
+
text-decoration: none;
|
643 |
+
border: 1px solid orange;
|
644 |
+
border-collapse: collapse;
|
645 |
+
}
|
646 |
+
|
647 |
+
.vccDlgBody {
|
648 |
+
border: 3px solid #336699;
|
649 |
+
border-collapse: collapse;
|
650 |
+
color: black;
|
651 |
+
background-color: #EEFFEE;
|
652 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
653 |
+
font-size: 11px;
|
654 |
+
text-decoration: none;
|
655 |
+
}
|
656 |
+
|
657 |
+
/* DEFINITION DES STYLES DE TABLEAUX */
|
658 |
+
.bordure_0 {
|
659 |
+
border: 0px solid;
|
660 |
+
color: black;
|
661 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
662 |
+
font-size: 11px;
|
663 |
+
text-decoration: none;
|
664 |
+
}
|
665 |
+
|
666 |
+
.bordure_1_bleu {
|
667 |
+
border: 1px solid green;
|
668 |
+
border-collapse: collapse;
|
669 |
+
color: black;
|
670 |
+
background-color: #FFFFFF;
|
671 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
672 |
+
font-size: 11px;
|
673 |
+
text-decoration: none;
|
674 |
+
}
|
675 |
+
|
676 |
+
.bordure_3_bleu {
|
677 |
+
border: 3px solid #336699;
|
678 |
+
border-collapse: collapse;
|
679 |
+
color: black;
|
680 |
+
background-color: #FFFFFF;
|
681 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
682 |
+
font-size: 11px;
|
683 |
+
text-decoration: none;
|
684 |
+
}
|
685 |
+
|
686 |
+
.indent {
|
687 |
+
margin-left: 20px;
|
688 |
+
}
|
689 |
+
|
690 |
+
/* DEFINITION DES STYLES D'OBJETS DE FORMULAIRE */
|
691 |
+
.Btn {
|
692 |
+
color: #003366;
|
693 |
+
text-align: center;
|
694 |
+
font-weight: bold;
|
695 |
+
background-color: #FFFFFF;
|
696 |
+
background-image: url(../images/ongletStyle1.jpg);
|
697 |
+
background-repeat: no-repeat;
|
698 |
+
background-position: center center;
|
699 |
+
}
|
700 |
+
|
701 |
+
.Btn:hover {
|
702 |
+
color: red;
|
703 |
+
}
|
704 |
+
|
705 |
+
.menu1h {
|
706 |
+
background-color: #003366;
|
707 |
+
color: white;
|
708 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
709 |
+
font-size: 10px;
|
710 |
+
font-weight: bold;
|
711 |
+
text-decoration: none;
|
712 |
+
border-top: 1px solid #003366;
|
713 |
+
border-bottom: 1px solid #003366;
|
714 |
+
border-left: 1px solid #003366;
|
715 |
+
border-right: 1px solid white;
|
716 |
+
border-collapse: collapse;
|
717 |
+
display: block;
|
718 |
+
}
|
719 |
+
|
720 |
+
.menu1h:hover {
|
721 |
+
background-color: white;
|
722 |
+
color: red;
|
723 |
+
border: 1px solid darkgreen;
|
724 |
+
border-collapse: collapse;
|
725 |
+
}
|
726 |
+
|
727 |
+
.menu1h_f {
|
728 |
+
background-color: #003366;
|
729 |
+
color: white;
|
730 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
731 |
+
font-size: 10px;
|
732 |
+
font-weight: bold;
|
733 |
+
text-decoration: none;
|
734 |
+
border: 1px solid #003366;
|
735 |
+
display: block;
|
736 |
+
}
|
737 |
+
|
738 |
+
.menu1h_f:hover {
|
739 |
+
background-color: white;
|
740 |
+
color: red;
|
741 |
+
border: 1px solid darkgreen;
|
742 |
+
border-collapse: collapse;
|
743 |
+
}
|
744 |
+
|
745 |
+
.menu1v {
|
746 |
+
background-color: #003366;
|
747 |
+
color: white;
|
748 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
749 |
+
font-size: 10px;
|
750 |
+
font-weight: bold;
|
751 |
+
text-decoration: none;
|
752 |
+
border: 1px solid #003366;
|
753 |
+
border-collapse: collapse;
|
754 |
+
display: block;
|
755 |
+
}
|
756 |
+
|
757 |
+
.menu1v:hover {
|
758 |
+
background-color: white;
|
759 |
+
color: red;
|
760 |
+
border: 1px solid darkgreen;
|
761 |
+
border-collapse: collapse;
|
762 |
+
}
|
763 |
+
|
764 |
+
.menu2v {
|
765 |
+
background-color: #5588BB;
|
766 |
+
color: white;
|
767 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
768 |
+
font-size: 12px;
|
769 |
+
font-weight: bold;
|
770 |
+
text-decoration: none;
|
771 |
+
border: 1px solid #4277AB;
|
772 |
+
border-collapse: collapse;
|
773 |
+
float: left;
|
774 |
+
display: block;
|
775 |
+
}
|
776 |
+
|
777 |
+
.menu2v:hover {
|
778 |
+
background-color: white;
|
779 |
+
color: red;
|
780 |
+
border: 1px solid darkgreen;
|
781 |
+
border-collapse: collapse;
|
782 |
+
}
|
783 |
+
|
784 |
+
.menuEDF {
|
785 |
+
background-color: #003366;
|
786 |
+
color: white;
|
787 |
+
font-family: Verdana, Arial, Lucida, Tahoma;
|
788 |
+
font-size: 10px;
|
789 |
+
text-decoration: none;
|
790 |
+
}
|
791 |
+
|
792 |
+
.menuEDF:hover {
|
793 |
+
color: #FF8800;
|
794 |
+
}
|
795 |
+
|
796 |
+
/*bouton bleu sur blanc*/
|
797 |
+
.Bouton {
|
798 |
+
color: #003366;
|
799 |
+
text-align: center;
|
800 |
+
font-weight: bold;
|
801 |
+
/* Ricardo cursor: hand; */
|
802 |
+
cursor: pointer;
|
803 |
+
background-color: #FFFFFF;
|
804 |
+
}
|
805 |
+
|
806 |
+
input {
|
807 |
+
border: 2px solid green;
|
808 |
+
color: #003366;
|
809 |
+
background-color: #FFFFFF;
|
810 |
+
background-image: url(../images/fond_4.bmp);
|
811 |
+
background-repeat: repeat-x;
|
812 |
+
}
|
813 |
+
|
814 |
+
.disabled_input {
|
815 |
+
border: 1px solid gray;
|
816 |
+
color: grey;
|
817 |
+
background-color: #FFFFFF;
|
818 |
+
background-image: url(../images/fond_4.bmp);
|
819 |
+
background-repeat: repeat-x;
|
820 |
+
}
|
821 |
+
|
822 |
+
.input0 {
|
823 |
+
border: 0px;
|
824 |
+
color: #003366;
|
825 |
+
background-color: #FFFFFF;
|
826 |
+
background-image: url(../images/fond_4.bmp);
|
827 |
+
}
|
828 |
+
|
829 |
+
.input2 {
|
830 |
+
border: 1px solid green;
|
831 |
+
color: #003366;
|
832 |
+
background-color: #FFFFFF;
|
833 |
+
background-image: url(../images/fond_4.bmp);
|
834 |
+
background-repeat: repeat-x;
|
835 |
+
}
|
836 |
+
|
837 |
+
.input3 {
|
838 |
+
border: 1px solid black;
|
839 |
+
color: #003366;
|
840 |
+
background-color: #EEEEEE;
|
841 |
+
background-image: url();
|
842 |
+
}
|
843 |
+
|
844 |
+
.input4 {
|
845 |
+
border: 1px solid blue;
|
846 |
+
color: #003366;
|
847 |
+
background-color: #FFFFFF;
|
848 |
+
background-image: url(../images/fond_4.bmp);
|
849 |
+
background-repeat: repeat-x;
|
850 |
+
}
|
851 |
+
|
852 |
+
.input5 {
|
853 |
+
border: 1px solid darkblue;
|
854 |
+
color: #003366;
|
855 |
+
background-color: #FFFFFF;
|
856 |
+
background-image: url(../images/fond_4.bmp);
|
857 |
+
background-repeat: repeat-x;
|
858 |
+
}
|
859 |
+
|
860 |
+
.input_btn {
|
861 |
+
border: 0px;
|
862 |
+
/* cursor: hand; */
|
863 |
+
cursor: pointer;
|
864 |
+
}
|
865 |
+
|
866 |
+
textarea {
|
867 |
+
border: 2px solid green;
|
868 |
+
color: #003366;
|
869 |
+
background-color: #FFFFFF;
|
870 |
+
background-image: url(../images/fond_5.bmp);
|
871 |
+
}
|
872 |
+
|
873 |
+
.TEXTAREA3 {
|
874 |
+
border: 1px solid green;
|
875 |
+
color: #003366;
|
876 |
+
background-color: #FFFFFF;
|
877 |
+
background-image: url();
|
878 |
+
}
|
879 |
+
|
880 |
+
.TEXTAREA4 {
|
881 |
+
border: 1px solid green;
|
882 |
+
color: #003366;
|
883 |
+
background-color: #EEEEEE;
|
884 |
+
background-image: url();
|
885 |
+
}
|
886 |
+
|
887 |
+
.hand {
|
888 |
+
cursor: hand;
|
889 |
+
cursor: pointer;
|
890 |
Â
}
|
lib/Minify/min_unit_tests/_test_files/css/paths_prepend.css
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
-
@import "foo.css";
|
2 |
-
@import 'bar/foo.css' print;
|
3 |
-
@import '/css/foo.css'; /* abs, should not alter */
|
4 |
-
@import 'http://foo.com/css/foo.css'; /* abs, should not alter */
|
5 |
-
@import url(../foo.css) tv, projection;
|
6 |
-
@import url("/css/foo.css"); /* abs, should not alter */
|
7 |
-
@import url(/css2/foo.css); /* abs, should not alter */
|
8 |
-
@import url(data:image/gif;base64,AAAA); /* data, should not alter */
|
9 |
-
foo {background:url('bar/foo.png')}
|
10 |
-
foo {background:url('http://foo.com/css/foo.css');} /* abs, should not alter */
|
11 |
-
foo {background:url("//foo.com/css/foo.css");} /* protocol relative, should not alter */
|
12 |
Â
foo {background:url(data:image/gif;base64,AAAA);} /* data, should not alter */
|
1 |
+
@import "foo.css";
|
2 |
+
@import 'bar/foo.css' print;
|
3 |
+
@import '/css/foo.css'; /* abs, should not alter */
|
4 |
+
@import 'http://foo.com/css/foo.css'; /* abs, should not alter */
|
5 |
+
@import url(../foo.css) tv, projection;
|
6 |
+
@import url("/css/foo.css"); /* abs, should not alter */
|
7 |
+
@import url(/css2/foo.css); /* abs, should not alter */
|
8 |
+
@import url(data:image/gif;base64,AAAA); /* data, should not alter */
|
9 |
+
foo {background:url('bar/foo.png')}
|
10 |
+
foo {background:url('http://foo.com/css/foo.css');} /* abs, should not alter */
|
11 |
+
foo {background:url("//foo.com/css/foo.css");} /* protocol relative, should not alter */
|
12 |
Â
foo {background:url(data:image/gif;base64,AAAA);} /* data, should not alter */
|
lib/Minify/min_unit_tests/_test_files/css/selectors.css
CHANGED
@@ -1,42 +1,42 @@
|
|
1 |
Â
/* http://www.w3.org/TR/css3-selectors/ */
|
2 |
Â
|
3 |
-
*
|
4 |
-
E[foo]
|
5 |
-
E[foo="bar"]
|
6 |
-
E[foo~="bar"]
|
7 |
-
E[foo^="bar"]
|
8 |
-
E[foo$="bar"]
|
9 |
-
E[foo*="bar"]
|
10 |
-
E[hreflang|="en"]
|
11 |
-
E:root
|
12 |
-
E:nth-child(n)
|
13 |
-
E:nth-last-child(n)
|
14 |
-
E:nth-of-type(n)
|
15 |
-
E:nth-last-of-type(n)
|
16 |
-
E:first-child
|
17 |
-
E:last-child
|
18 |
-
E:first-of-type
|
19 |
-
E:last-of-type
|
20 |
-
E:only-child
|
21 |
-
E:only-of-type
|
22 |
-
E:empty
|
23 |
-
E:link
|
24 |
-
E:visited
|
25 |
-
E:active
|
26 |
-
E:hover
|
27 |
-
E:focus
|
28 |
-
E:target
|
29 |
-
E:lang(fr)
|
30 |
-
E:enabled
|
31 |
-
E:disabled
|
32 |
-
E:checked
|
33 |
-
E::first-line
|
34 |
-
E::first-letter
|
35 |
-
E::selection
|
36 |
-
E::before
|
37 |
-
E::after
|
38 |
-
E.warning#myid
|
39 |
-
E:not(s)
|
40 |
Â
> F
|
41 |
Â
+ F
|
42 |
Â
~ F {color: red;}
|
1 |
Â
/* http://www.w3.org/TR/css3-selectors/ */
|
2 |
Â
|
3 |
+
*
|
4 |
+
E[foo]
|
5 |
+
E[foo="bar"]
|
6 |
+
E[foo~="bar"]
|
7 |
+
E[foo^="bar"]
|
8 |
+
E[foo$="bar"]
|
9 |
+
E[foo*="bar"]
|
10 |
+
E[hreflang|="en"]
|
11 |
+
E:root
|
12 |
+
E:nth-child(n)
|
13 |
+
E:nth-last-child(n)
|
14 |
+
E:nth-of-type(n)
|
15 |
+
E:nth-last-of-type(n)
|
16 |
+
E:first-child
|
17 |
+
E:last-child
|
18 |
+
E:first-of-type
|
19 |
+
E:last-of-type
|
20 |
+
E:only-child
|
21 |
+
E:only-of-type
|
22 |
+
E:empty
|
23 |
+
E:link
|
24 |
+
E:visited
|
25 |
+
E:active
|
26 |
+
E:hover
|
27 |
+
E:focus
|
28 |
+
E:target
|
29 |
+
E:lang(fr)
|
30 |
+
E:enabled
|
31 |
+
E:disabled
|
32 |
+
E:checked
|
33 |
+
E::first-line
|
34 |
+
E::first-letter
|
35 |
+
E::selection
|
36 |
+
E::before
|
37 |
+
E::after
|
38 |
+
E.warning#myid
|
39 |
+
E:not(s)
|
40 |
Â
> F
|
41 |
Â
+ F
|
42 |
Â
~ F {color: red;}
|
lib/Minify/min_unit_tests/_test_files/css/subsilver.css
CHANGED
@@ -1,434 +1,434 @@
|
|
1 |
-
/* Based on the original Style Sheet for the fisubsilver v2 Theme for phpBB version 2+
|
2 |
-
Edited by Daz - http://www.forumimages.com - last updated 26-06-03 */
|
3 |
-
/* The content of the posts (body of text) */
|
4 |
-
/* General page style */
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
/* begin suggest post */
|
9 |
-
.float-l{
|
10 |
-
float: left;
|
11 |
-
}
|
12 |
-
|
13 |
-
.form-suggest{
|
14 |
-
height:200px;
|
15 |
-
background:#DEE2D0;
|
16 |
-
vertical-align: top;
|
17 |
-
}
|
18 |
-
|
19 |
-
.form-input input{
|
20 |
-
font-size: 10px;
|
21 |
-
}
|
22 |
-
|
23 |
-
.hide{
|
24 |
-
display:none;
|
25 |
-
}
|
26 |
-
|
27 |
-
.form-input textarea{
|
28 |
-
font-size: 11px;
|
29 |
-
width: 350px;
|
30 |
-
}
|
31 |
-
|
32 |
-
.form-label{
|
33 |
-
font-size: 10px;
|
34 |
-
font-weight: bold;
|
35 |
-
line-height: 25px;
|
36 |
-
padding-right: 10px;
|
37 |
-
text-align: right;
|
38 |
-
width: 100px;
|
39 |
-
color: #39738F;
|
40 |
-
}
|
41 |
-
|
42 |
-
.font-9{
|
43 |
-
font-size: 9px;
|
44 |
-
}
|
45 |
-
|
46 |
-
.form-topic{
|
47 |
-
font-weight:bold;
|
48 |
-
|
49 |
-
}
|
50 |
-
|
51 |
-
.form-error{
|
52 |
-
color:red;
|
53 |
-
}
|
54 |
-
|
55 |
-
.inline{
|
56 |
-
display: inline;
|
57 |
-
}
|
58 |
-
|
59 |
-
.space-10{
|
60 |
-
clear: both;
|
61 |
-
font-size: 10px;
|
62 |
-
height: 10px;
|
63 |
-
line-height: 10px;
|
64 |
-
}
|
65 |
-
|
66 |
-
.suggest-success{
|
67 |
-
color:green;
|
68 |
-
padding-left:10px;
|
69 |
-
font-size:11px;
|
70 |
-
font-weight:bold;
|
71 |
-
}
|
72 |
-
|
73 |
-
.top{
|
74 |
-
vertical-align: top;
|
75 |
-
}
|
76 |
-
/* end suggest post */
|
77 |
-
|
78 |
-
table td{
|
79 |
-
padding:3px;
|
80 |
-
}
|
81 |
-
|
82 |
-
a:link,a:active,a:visited,a.postlink{
|
83 |
-
color: #006699;
|
84 |
-
text-decoration: none;
|
85 |
-
}
|
86 |
-
|
87 |
-
a:hover{
|
88 |
-
color: #DD6900;
|
89 |
-
}
|
90 |
-
|
91 |
-
a.admin:hover,a.mod:hover{
|
92 |
-
color: #DD6900;
|
93 |
-
}
|
94 |
-
|
95 |
-
a.but,a.but:hover,a.but:visited{
|
96 |
-
color: #000000;
|
97 |
-
text-decoration: none;
|
98 |
-
}
|
99 |
-
|
100 |
-
a.topictitle:visited{
|
101 |
-
color: #5493B4;
|
102 |
-
}
|
103 |
-
|
104 |
-
a.topictitle:hover{
|
105 |
-
color: #DD6900;
|
106 |
-
}
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
body{
|
111 |
-
color: #000000;
|
112 |
-
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
113 |
-
margin: 0 10px 10px 10px;
|
114 |
-
padding: 0;
|
115 |
-
overflow:auto;
|
116 |
-
}
|
117 |
-
|
118 |
-
/* General font families for common tags */
|
119 |
-
font,th,td,p{
|
120 |
-
font: 12px Verdana,Arial,Helvetica,sans-serif;
|
121 |
-
}
|
122 |
-
|
123 |
-
/* Form elements */
|
124 |
-
form{
|
125 |
-
display: inline;
|
126 |
-
}
|
127 |
-
|
128 |
-
hr{
|
129 |
-
border: 0px solid #FFFFFF;
|
130 |
-
border-top-width: 1px;
|
131 |
-
height: 0px;
|
132 |
-
}
|
133 |
-
|
134 |
-
/* Gets rid of the need for border="0" on hyperlinked images */
|
135 |
-
img{
|
136 |
-
border: 0 solid;
|
137 |
-
}
|
138 |
-
|
139 |
-
input{
|
140 |
-
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
141 |
-
}
|
142 |
-
|
143 |
-
input.button,input.liteoption,.fakebut{
|
144 |
-
background: #FAFAFA;
|
145 |
-
border: 1px solid #000000;
|
146 |
-
font-size: 11px;
|
147 |
-
}
|
148 |
-
|
149 |
-
input.catbutton{
|
150 |
-
background: #FAFAFA;
|
151 |
-
border: 1px solid #000000;
|
152 |
-
font-size: 10px;
|
153 |
-
}
|
154 |
-
|
155 |
-
input.mainoption{
|
156 |
-
background: #FAFAFA;
|
157 |
-
border: 1px solid #000000;
|
158 |
-
font-size: 11px;
|
159 |
-
font-weight: bold;
|
160 |
-
}
|
161 |
-
|
162 |
-
input.post,textarea.post{
|
163 |
-
background: #FFFFFF;
|
164 |
-
border: 1px solid #000000;
|
165 |
-
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
166 |
-
padding-bottom: 2px;
|
167 |
-
padding-left: 2px;
|
168 |
-
}
|
169 |
-
|
170 |
-
select{
|
171 |
-
background: #FFFFFF;
|
172 |
-
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
173 |
-
}
|
174 |
-
|
175 |
-
table{
|
176 |
-
text-align: left;
|
177 |
-
}
|
178 |
-
|
179 |
-
td{
|
180 |
-
vertical-align: middle;
|
181 |
-
}
|
182 |
-
|
183 |
-
/* Category gradients*/
|
184 |
-
td.cat{
|
185 |
-
background-color: #C2C6BA;
|
186 |
-
font-weight: bold;
|
187 |
-
height: 20px;
|
188 |
-
letter-spacing: 1px;
|
189 |
-
text-indent: 4px;
|
190 |
-
}
|
191 |
-
|
192 |
-
td.genmed,.genmed{
|
193 |
-
font-size: 11px;
|
194 |
-
}
|
195 |
-
|
196 |
-
/* This is for the table cell above the Topics,Post & Last posts on the index.php */
|
197 |
-
td.rowpic{
|
198 |
-
background: #C2C6BA;
|
199 |
-
}
|
200 |
-
|
201 |
-
td.spacerow{
|
202 |
-
background: #E5E6E2;
|
203 |
-
}
|
204 |
-
|
205 |
-
/* Table Header cells */
|
206 |
-
th{
|
207 |
-
background-color: #FADD31;
|
208 |
-
background-image: url(images/cellpic3.gif);
|
209 |
-
background-repeat: repeat-x;
|
210 |
-
color: #68685E;
|
211 |
-
font-size: 11px;
|
212 |
-
font-weight: bold;
|
213 |
-
line-height:16px;
|
214 |
-
height: 16px;
|
215 |
-
padding-left: 8px;
|
216 |
-
padding-right: 8px;
|
217 |
-
text-align: center;
|
218 |
-
white-space: nowrap;
|
219 |
-
}
|
220 |
-
|
221 |
-
/* Admin & Moderator Colours MODification */
|
222 |
-
.admin,.mod{
|
223 |
-
font-size: 11px;
|
224 |
-
font-weight: bold;
|
225 |
-
}
|
226 |
-
|
227 |
-
.admin,a.admin,a.admin:visited{
|
228 |
-
color: #FFA34F;
|
229 |
-
}
|
230 |
-
|
231 |
-
/* This is the border line & background colour round the entire page */
|
232 |
-
.bodyline{
|
233 |
-
background: #FFFFFF;
|
234 |
-
border: 1px solid #98AAB1;
|
235 |
-
}
|
236 |
-
|
237 |
-
.center{
|
238 |
-
text-align: center;
|
239 |
-
}
|
240 |
-
|
241 |
-
/* Code blocks */
|
242 |
-
.code{
|
243 |
-
background: #FAFAFA;
|
244 |
-
border: 1px solid #D1D7DC;
|
245 |
-
color: #006600;
|
246 |
-
font: 12px Courier,"Courier New",sans-serif;
|
247 |
-
padding: 5px;
|
248 |
-
}
|
249 |
-
|
250 |
-
/* This is for the error messages that pop up */
|
251 |
-
.errorline{
|
252 |
-
background: #E5E6E2;
|
253 |
-
border: 1px solid #8F8B8B;
|
254 |
-
color:#D92A2A;
|
255 |
-
}
|
256 |
-
|
257 |
-
.explaintitle{
|
258 |
-
color: #5C81B1;
|
259 |
-
font-size: 11px;
|
260 |
-
font-weight: bold;
|
261 |
-
}
|
262 |
-
|
263 |
-
/* This is the outline round the main forum tables */
|
264 |
-
.forumline{
|
265 |
-
background: #FFFFFF;
|
266 |
-
}
|
267 |
-
|
268 |
-
/* General text */
|
269 |
-
.gensmall{
|
270 |
-
font-size: 10px;
|
271 |
-
}
|
272 |
-
|
273 |
-
.h1-font{
|
274 |
-
color: #006699;
|
275 |
-
display: inline;
|
276 |
-
font: bold 13px Verdana, Arial, Helvetica, sans-serif;
|
277 |
-
margin: 0;
|
278 |
-
text-decoration: none;
|
279 |
-
}
|
280 |
-
|
281 |
-
.h2-font{
|
282 |
-
display: inline;
|
283 |
-
font-family: Verdana, Arial, Helvetica, sans-serif;
|
284 |
-
font-size: 11px;
|
285 |
-
}
|
286 |
-
|
287 |
-
.height1{
|
288 |
-
height: 1px;
|
289 |
-
}
|
290 |
-
|
291 |
-
.height22{
|
292 |
-
height: 22px;
|
293 |
-
}
|
294 |
-
|
295 |
-
.height25{
|
296 |
-
height: 25px;
|
297 |
-
}
|
298 |
-
|
299 |
-
.height28{
|
300 |
-
height: 28px;
|
301 |
-
}
|
302 |
-
|
303 |
-
.height30{
|
304 |
-
height: 30px;
|
305 |
-
}
|
306 |
-
|
307 |
-
.height40{
|
308 |
-
height: 40px;
|
309 |
-
}
|
310 |
-
|
311 |
-
/* This is the line in the posting page which shows the rollover
|
312 |
-
help line. Colour value in row2 */
|
313 |
-
.helpline{
|
314 |
-
border: 0 solid;
|
315 |
-
font-size: 10px;
|
316 |
-
}
|
317 |
-
|
318 |
-
.imgfolder{
|
319 |
-
margin: 1px 4px 1px 4px;
|
320 |
-
}
|
321 |
-
|
322 |
-
.imgspace{
|
323 |
-
margin-left: 1px;
|
324 |
-
margin-right: 2px;
|
325 |
-
}
|
326 |
-
|
327 |
-
/* Specify the space around images */
|
328 |
-
.imgtopic,.imgicon{
|
329 |
-
margin-left: 3px;
|
330 |
-
}
|
331 |
-
|
332 |
-
.left{
|
333 |
-
text-align: left;
|
334 |
-
}
|
335 |
-
|
336 |
-
/* The largest text used in the index page title and toptic title etc. */
|
337 |
-
.maintitle,h1,h2{
|
338 |
-
color: #5C81B1;
|
339 |
-
font: bold 20px/120% "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;
|
340 |
-
text-decoration: none;
|
341 |
-
}
|
342 |
-
|
343 |
-
.maxwidth{
|
344 |
-
width: 100%;
|
345 |
-
}
|
346 |
-
|
347 |
-
.mod,a.mod,a.mod:visited{
|
348 |
-
color: #006600;
|
349 |
-
}
|
350 |
-
|
351 |
-
/* Name of poster in viewmsg.php and viewtopic.php and other places */
|
352 |
-
.name{
|
353 |
-
font-size: 11px;
|
354 |
-
font-weight: bold;
|
355 |
-
}
|
356 |
-
|
357 |
-
/* Used for the navigation text,(Page 1,2,3 etc) and the navigation bar when in a forum */
|
358 |
-
.nav{
|
359 |
-
font-size: 11px;
|
360 |
-
font-weight: bold;
|
361 |
-
}
|
362 |
-
|
363 |
-
.nowrap{
|
364 |
-
white-space: nowrap;
|
365 |
-
}
|
366 |
-
|
367 |
-
.postbody{
|
368 |
-
font-size: 12px;
|
369 |
-
line-height: 125%;
|
370 |
-
}
|
371 |
-
|
372 |
-
.postbody a{
|
373 |
-
text-decoration: underline;
|
374 |
-
}
|
375 |
-
|
376 |
-
/* Location,number of posts,post date etc */
|
377 |
-
.postdetails{
|
378 |
-
color: #00396A;
|
379 |
-
font-size: 10px;
|
380 |
-
}
|
381 |
-
|
382 |
-
/* Quote blocks */
|
383 |
-
.quote{
|
384 |
-
background: #F3F3EF;
|
385 |
-
border: 1px solid #C2C6BA;
|
386 |
-
color: #006699;
|
387 |
-
font-size: 11px;
|
388 |
-
line-height: 125%;
|
389 |
-
}
|
390 |
-
|
391 |
-
.right{
|
392 |
-
text-align: right;
|
393 |
-
}
|
394 |
-
|
395 |
-
/* Main table cell colours and backgrounds */
|
396 |
-
.row1{
|
397 |
-
background: #F0F0EB;
|
398 |
-
}
|
399 |
-
|
400 |
-
.row2,.helpline{
|
401 |
-
background: #E5E6E2;
|
402 |
-
}
|
403 |
-
|
404 |
-
.row3{
|
405 |
-
background: #DBDBD4;
|
406 |
-
}
|
407 |
-
|
408 |
-
.subtitle,h2{
|
409 |
-
font: bold 18px/180% "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;
|
410 |
-
text-decoration: none;
|
411 |
-
}
|
412 |
-
|
413 |
-
/* titles for the topics:could specify viewed link colour too */
|
414 |
-
.topictitle {
|
415 |
-
color: #000000;
|
416 |
-
font-size: 11px;
|
417 |
-
font-weight: bold;
|
418 |
-
}
|
419 |
-
|
420 |
-
.underline{
|
421 |
-
text-decoration: underline;
|
422 |
-
}
|
423 |
-
|
424 |
-
.top{
|
425 |
-
vertical-align:top;
|
426 |
-
}
|
427 |
-
|
428 |
-
.image-hspace{
|
429 |
-
margin-right:3px;
|
430 |
-
}
|
431 |
-
|
432 |
-
.clear{
|
433 |
-
clear:both;
|
434 |
Â
}
|
1 |
+
/* Based on the original Style Sheet for the fisubsilver v2 Theme for phpBB version 2+
|
2 |
+
Edited by Daz - http://www.forumimages.com - last updated 26-06-03 */
|
3 |
+
/* The content of the posts (body of text) */
|
4 |
+
/* General page style */
|
5 |
+
|
6 |
+
|
7 |
+
|
8 |
+
/* begin suggest post */
|
9 |
+
.float-l{
|
10 |
+
float: left;
|
11 |
+
}
|
12 |
+
|
13 |
+
.form-suggest{
|
14 |
+
height:200px;
|
15 |
+
background:#DEE2D0;
|
16 |
+
vertical-align: top;
|
17 |
+
}
|
18 |
+
|
19 |
+
.form-input input{
|
20 |
+
font-size: 10px;
|
21 |
+
}
|
22 |
+
|
23 |
+
.hide{
|
24 |
+
display:none;
|
25 |
+
}
|
26 |
+
|
27 |
+
.form-input textarea{
|
28 |
+
font-size: 11px;
|
29 |
+
width: 350px;
|
30 |
+
}
|
31 |
+
|
32 |
+
.form-label{
|
33 |
+
font-size: 10px;
|
34 |
+
font-weight: bold;
|
35 |
+
line-height: 25px;
|
36 |
+
padding-right: 10px;
|
37 |
+
text-align: right;
|
38 |
+
width: 100px;
|
39 |
+
color: #39738F;
|
40 |
+
}
|
41 |
+
|
42 |
+
.font-9{
|
43 |
+
font-size: 9px;
|
44 |
+
}
|
45 |
+
|
46 |
+
.form-topic{
|
47 |
+
font-weight:bold;
|
48 |
+
|
49 |
+
}
|
50 |
+
|
51 |
+
.form-error{
|
52 |
+
color:red;
|
53 |
+
}
|
54 |
+
|
55 |
+
.inline{
|
56 |
+
display: inline;
|
57 |
+
}
|
58 |
+
|
59 |
+
.space-10{
|
60 |
+
clear: both;
|
61 |
+
font-size: 10px;
|
62 |
+
height: 10px;
|
63 |
+
line-height: 10px;
|
64 |
+
}
|
65 |
+
|
66 |
+
.suggest-success{
|
67 |
+
color:green;
|
68 |
+
padding-left:10px;
|
69 |
+
font-size:11px;
|
70 |
+
font-weight:bold;
|
71 |
+
}
|
72 |
+
|
73 |
+
.top{
|
74 |
+
vertical-align: top;
|
75 |
+
}
|
76 |
+
/* end suggest post */
|
77 |
+
|
78 |
+
table td{
|
79 |
+
padding:3px;
|
80 |
+
}
|
81 |
+
|
82 |
+
a:link,a:active,a:visited,a.postlink{
|
83 |
+
color: #006699;
|
84 |
+
text-decoration: none;
|
85 |
+
}
|
86 |
+
|
87 |
+
a:hover{
|
88 |
+
color: #DD6900;
|
89 |
+
}
|
90 |
+
|
91 |
+
a.admin:hover,a.mod:hover{
|
92 |
+
color: #DD6900;
|
93 |
+
}
|
94 |
+
|
95 |
+
a.but,a.but:hover,a.but:visited{
|
96 |
+
color: #000000;
|
97 |
+
text-decoration: none;
|
98 |
+
}
|
99 |
+
|
100 |
+
a.topictitle:visited{
|
101 |
+
color: #5493B4;
|
102 |
+
}
|
103 |
+
|
104 |
+
a.topictitle:hover{
|
105 |
+
color: #DD6900;
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
|
110 |
+
body{
|
111 |
+
color: #000000;
|
112 |
+
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
113 |
+
margin: 0 10px 10px 10px;
|
114 |
+
padding: 0;
|
115 |
+
overflow:auto;
|
116 |
+
}
|
117 |
+
|
118 |
+
/* General font families for common tags */
|
119 |
+
font,th,td,p{
|
120 |
+
font: 12px Verdana,Arial,Helvetica,sans-serif;
|
121 |
+
}
|
122 |
+
|
123 |
+
/* Form elements */
|
124 |
+
form{
|
125 |
+
display: inline;
|
126 |
+
}
|
127 |
+
|
128 |
+
hr{
|
129 |
+
border: 0px solid #FFFFFF;
|
130 |
+
border-top-width: 1px;
|
131 |
+
height: 0px;
|
132 |
+
}
|
133 |
+
|
134 |
+
/* Gets rid of the need for border="0" on hyperlinked images */
|
135 |
+
img{
|
136 |
+
border: 0 solid;
|
137 |
+
}
|
138 |
+
|
139 |
+
input{
|
140 |
+
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
141 |
+
}
|
142 |
+
|
143 |
+
input.button,input.liteoption,.fakebut{
|
144 |
+
background: #FAFAFA;
|
145 |
+
border: 1px solid #000000;
|
146 |
+
font-size: 11px;
|
147 |
+
}
|
148 |
+
|
149 |
+
input.catbutton{
|
150 |
+
background: #FAFAFA;
|
151 |
+
border: 1px solid #000000;
|
152 |
+
font-size: 10px;
|
153 |
+
}
|
154 |
+
|
155 |
+
input.mainoption{
|
156 |
+
background: #FAFAFA;
|
157 |
+
border: 1px solid #000000;
|
158 |
+
font-size: 11px;
|
159 |
+
font-weight: bold;
|
160 |
+
}
|
161 |
+
|
162 |
+
input.post,textarea.post{
|
163 |
+
background: #FFFFFF;
|
164 |
+
border: 1px solid #000000;
|
165 |
+
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
166 |
+
padding-bottom: 2px;
|
167 |
+
padding-left: 2px;
|
168 |
+
}
|
169 |
+
|
170 |
+
select{
|
171 |
+
background: #FFFFFF;
|
172 |
+
font: 11px Verdana,Arial,Helvetica,sans-serif;
|
173 |
+
}
|
174 |
+
|
175 |
+
table{
|
176 |
+
text-align: left;
|
177 |
+
}
|
178 |
+
|
179 |
+
td{
|
180 |
+
vertical-align: middle;
|
181 |
+
}
|
182 |
+
|
183 |
+
/* Category gradients*/
|
184 |
+
td.cat{
|
185 |
+
background-color: #C2C6BA;
|
186 |
+
font-weight: bold;
|
187 |
+
height: 20px;
|
188 |
+
letter-spacing: 1px;
|
189 |
+
text-indent: 4px;
|
190 |
+
}
|
191 |
+
|
192 |
+
td.genmed,.genmed{
|
193 |
+
font-size: 11px;
|
194 |
+
}
|
195 |
+
|
196 |
+
/* This is for the table cell above the Topics,Post & Last posts on the index.php */
|
197 |
+
td.rowpic{
|
198 |
+
background: #C2C6BA;
|
199 |
+
}
|
200 |
+
|
201 |
+
td.spacerow{
|
202 |
+
background: #E5E6E2;
|
203 |
+
}
|
204 |
+
|
205 |
+
/* Table Header cells */
|
206 |
+
th{
|
207 |
+
background-color: #FADD31;
|
208 |
+
background-image: url(images/cellpic3.gif);
|
209 |
+
background-repeat: repeat-x;
|
210 |
+
color: #68685E;
|
211 |
+
font-size: 11px;
|
212 |
+
font-weight: bold;
|
213 |
+
line-height:16px;
|
214 |
+
height: 16px;
|
215 |
+
padding-left: 8px;
|
216 |
+
padding-right: 8px;
|
217 |
+
text-align: center;
|
218 |
+
white-space: nowrap;
|
219 |
+
}
|
220 |
+
|
221 |
+
/* Admin & Moderator Colours MODification */
|
222 |
+
.admin,.mod{
|
223 |
+
font-size: 11px;
|
224 |
+
font-weight: bold;
|
225 |
+
}
|
226 |
+
|
227 |
+
.admin,a.admin,a.admin:visited{
|
228 |
+
color: #FFA34F;
|
229 |
+
}
|
230 |
+
|
231 |
+
/* This is the border line & background colour round the entire page */
|
232 |
+
.bodyline{
|
233 |
+
background: #FFFFFF;
|
234 |
+
border: 1px solid #98AAB1;
|
235 |
+
}
|
236 |
+
|
237 |
+
.center{
|
238 |
+
text-align: center;
|
239 |
+
}
|
240 |
+
|
241 |
+
/* Code blocks */
|
242 |
+
.code{
|
243 |
+
background: #FAFAFA;
|
244 |
+
border: 1px solid #D1D7DC;
|
245 |
+
color: #006600;
|
246 |
+
font: 12px Courier,"Courier New",sans-serif;
|
247 |
+
padding: 5px;
|
248 |
+
}
|
249 |
+
|
250 |
+
/* This is for the error messages that pop up */
|
251 |
+
.errorline{
|
252 |
+
background: #E5E6E2;
|
253 |
+
border: 1px solid #8F8B8B;
|
254 |
+
color:#D92A2A;
|
255 |
+
}
|
256 |
+
|
257 |
+
.explaintitle{
|
258 |
+
color: #5C81B1;
|
259 |
+
font-size: 11px;
|
260 |
+
font-weight: bold;
|
261 |
+
}
|
262 |
+
|
263 |
+
/* This is the outline round the main forum tables */
|
264 |
+
.forumline{
|
265 |
+
background: #FFFFFF;
|
266 |
+
}
|
267 |
+
|
268 |
+
/* General text */
|
269 |
+
.gensmall{
|
270 |
+
font-size: 10px;
|
271 |
+
}
|
272 |
+
|
273 |
+
.h1-font{
|
274 |
+
color: #006699;
|
275 |
+
display: inline;
|
276 |
+
font: bold 13px Verdana, Arial, Helvetica, sans-serif;
|
277 |
+
margin: 0;
|
278 |
+
text-decoration: none;
|
279 |
+
}
|
280 |
+
|
281 |
+
.h2-font{
|
282 |
+
display: inline;
|
283 |
+
font-family: Verdana, Arial, Helvetica, sans-serif;
|
284 |
+
font-size: 11px;
|
285 |
+
}
|
286 |
+
|
287 |
+
.height1{
|
288 |
+
height: 1px;
|
289 |
+
}
|
290 |
+
|
291 |
+
.height22{
|
292 |
+
height: 22px;
|
293 |
+
}
|
294 |
+
|
295 |
+
.height25{
|
296 |
+
height: 25px;
|
297 |
+
}
|
298 |
+
|
299 |
+
.height28{
|
300 |
+
height: 28px;
|
301 |
+
}
|
302 |
+
|
303 |
+
.height30{
|
304 |
+
height: 30px;
|
305 |
+
}
|
306 |
+
|
307 |
+
.height40{
|
308 |
+
height: 40px;
|
309 |
+
}
|
310 |
+
|
311 |
+
/* This is the line in the posting page which shows the rollover
|
312 |
+
help line. Colour value in row2 */
|
313 |
+
.helpline{
|
314 |
+
border: 0 solid;
|
315 |
+
font-size: 10px;
|
316 |
+
}
|
317 |
+
|
318 |
+
.imgfolder{
|
319 |
+
margin: 1px 4px 1px 4px;
|
320 |
+
}
|
321 |
+
|
322 |
+
.imgspace{
|
323 |
+
margin-left: 1px;
|
324 |
+
margin-right: 2px;
|
325 |
+
}
|
326 |
+
|
327 |
+
/* Specify the space around images */
|
328 |
+
.imgtopic,.imgicon{
|
329 |
+
margin-left: 3px;
|
330 |
+
}
|
331 |
+
|
332 |
+
.left{
|
333 |
+
text-align: left;
|
334 |
+
}
|
335 |
+
|
336 |
+
/* The largest text used in the index page title and toptic title etc. */
|
337 |
+
.maintitle,h1,h2{
|
338 |
+
color: #5C81B1;
|
339 |
+
font: bold 20px/120% "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;
|
340 |
+
text-decoration: none;
|
341 |
+
}
|
342 |
+
|
343 |
+
.maxwidth{
|
344 |
+
width: 100%;
|
345 |
+
}
|
346 |
+
|
347 |
+
.mod,a.mod,a.mod:visited{
|
348 |
+
color: #006600;
|
349 |
+
}
|
350 |
+
|
351 |
+
/* Name of poster in viewmsg.php and viewtopic.php and other places */
|
352 |
+
.name{
|
353 |
+
font-size: 11px;
|
354 |
+
font-weight: bold;
|
355 |
+
}
|
356 |
+
|
357 |
+
/* Used for the navigation text,(Page 1,2,3 etc) and the navigation bar when in a forum */
|
358 |
+
.nav{
|
359 |
+
font-size: 11px;
|
360 |
+
font-weight: bold;
|
361 |
+
}
|
362 |
+
|
363 |
+
.nowrap{
|
364 |
+
white-space: nowrap;
|
365 |
+
}
|
366 |
+
|
367 |
+
.postbody{
|
368 |
+
font-size: 12px;
|
369 |
+
line-height: 125%;
|
370 |
+
}
|
371 |
+
|
372 |
+
.postbody a{
|
373 |
+
text-decoration: underline;
|
374 |
+
}
|
375 |
+
|
376 |
+
/* Location,number of posts,post date etc */
|
377 |
+
.postdetails{
|
378 |
+
color: #00396A;
|
379 |
+
font-size: 10px;
|
380 |
+
}
|
381 |
+
|
382 |
+
/* Quote blocks */
|
383 |
+
.quote{
|
384 |
+
background: #F3F3EF;
|
385 |
+
border: 1px solid #C2C6BA;
|
386 |
+
color: #006699;
|
387 |
+
font-size: 11px;
|
388 |
+
line-height: 125%;
|
389 |
+
}
|
390 |
+
|
391 |
+
.right{
|
392 |
+
text-align: right;
|
393 |
+
}
|
394 |
+
|
395 |
+
/* Main table cell colours and backgrounds */
|
396 |
+
.row1{
|
397 |
+
background: #F0F0EB;
|
398 |
+
}
|
399 |
+
|
400 |
+
.row2,.helpline{
|
401 |
+
background: #E5E6E2;
|
402 |
+
}
|
403 |
+
|
404 |
+
.row3{
|
405 |
+
background: #DBDBD4;
|
406 |
+
}
|
407 |
+
|
408 |
+
.subtitle,h2{
|
409 |
+
font: bold 18px/180% "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;
|
410 |
+
text-decoration: none;
|
411 |
+
}
|
412 |
+
|
413 |
+
/* titles for the topics:could specify viewed link colour too */
|
414 |
+
.topictitle {
|
415 |
+
color: #000000;
|
416 |
+
font-size: 11px;
|
417 |
+
font-weight: bold;
|
418 |
+
}
|
419 |
+
|
420 |
+
.underline{
|
421 |
+
text-decoration: underline;
|
422 |
+
}
|
423 |
+
|
424 |
+
.top{
|
425 |
+
vertical-align:top;
|
426 |
+
}
|
427 |
+
|
428 |
+
.image-hspace{
|
429 |
+
margin-right:3px;
|
430 |
+
}
|
431 |
+
|
432 |
+
.clear{
|
433 |
+
clear:both;
|
434 |
Â
}
|
lib/Minify/min_unit_tests/_test_files/css/unusual_strings.css
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
-
/* test unusual, but valid strings in CSS */
|
2 |
-
|
3 |
-
foo[attr="multiple spaces"] {
|
4 |
-
content: "Hello World!";
|
5 |
-
}
|
6 |
-
|
7 |
-
foo[attr="Hel\
|
8 |
-
lo"] {
|
9 |
-
content: " \"World\"";
|
10 |
-
}
|
1 |
+
/* test unusual, but valid strings in CSS */
|
2 |
+
|
3 |
+
foo[attr="multiple spaces"] {
|
4 |
+
content: "Hello World!";
|
5 |
+
}
|
6 |
+
|
7 |
+
foo[attr="Hel\
|
8 |
+
lo"] {
|
9 |
+
content: " \"World\"";
|
10 |
+
}
|
lib/Minify/min_unit_tests/_test_files/html/before.html
CHANGED
@@ -78,7 +78,7 @@ css hack {
|
|
78 |
Â
<div id="container">
|
79 |
Â
<div id="pageHeader">
|
80 |
Â
<h1><span>css Zen Garden</span></h1>
|
81 |
-
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym>
|
82 |
Â
Design</span></h2>
|
83 |
Â
</div>
|
84 |
Â
<pre>
|
78 |
Â
<div id="container">
|
79 |
Â
<div id="pageHeader">
|
80 |
Â
<h1><span>css Zen Garden</span></h1>
|
81 |
+
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym>
|
82 |
Â
Design</span></h2>
|
83 |
Â
</div>
|
84 |
Â
<pre>
|
lib/Minify/min_unit_tests/_test_files/html/before2.html
CHANGED
@@ -76,7 +76,7 @@ css hack {
|
|
76 |
Â
<div id="container">
|
77 |
Â
<div id="pageHeader">
|
78 |
Â
<h1><span>css Zen Garden</span></h1>
|
79 |
-
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym>
|
80 |
Â
Design</span></h2>
|
81 |
Â
</div>
|
82 |
Â
<pre>
|
76 |
Â
<div id="container">
|
77 |
Â
<div id="pageHeader">
|
78 |
Â
<h1><span>css Zen Garden</span></h1>
|
79 |
+
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym>
|
80 |
Â
Design</span></h2>
|
81 |
Â
</div>
|
82 |
Â
<pre>
|
lib/Minify/min_unit_tests/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE
ADDED
@@ -0,0 +1,348 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
Simple Test interface changes
|
2 |
+
=============================
|
3 |
+
Because the SimpleTest tool set is still evolving it is likely that tests
|
4 |
+
written with earlier versions will fail with the newest ones. The most
|
5 |
+
dramatic changes are in the alpha releases. Here is a list of possible
|
6 |
+
problems and their fixes...
|
7 |
+
|
8 |
+
No method getRelativeUrls() or getAbsoluteUrls()
|
9 |
+
------------------------------------------------
|
10 |
+
These methods were always a bit weird anyway, and
|
11 |
+
the new parsing of the base tag makes them more so.
|
12 |
+
They have been replaced with getUrls() instead. If
|
13 |
+
you want the old functionality then simply chop
|
14 |
+
off the current domain from getUrl().
|
15 |
+
|
16 |
+
Method setWildcard() removed in mocks
|
17 |
+
-------------------------------------
|
18 |
+
Even setWildcard() has been removed in 1.0.1beta now.
|
19 |
+
If you want to test explicitely for a '*' string, then
|
20 |
+
simply pass in new IdenticalExpectation('*') instead.
|
21 |
+
|
22 |
+
No method _getTest() on mocks
|
23 |
+
-----------------------------
|
24 |
+
This has finally been removed. It was a pretty esoteric
|
25 |
+
flex point anyway. It was there to allow the mocks to
|
26 |
+
work with other test tools, but no one does this.
|
27 |
+
|
28 |
+
No method assertError(), assertNoErrors(), swallowErrors()
|
29 |
+
----------------------------------------------------------
|
30 |
+
These have been deprecated in 1.0.1beta in favour of
|
31 |
+
expectError() and expectException(). assertNoErrors() is
|
32 |
+
redundant if you use expectError() as failures are now reported
|
33 |
+
immediately.
|
34 |
+
|
35 |
+
No method TestCase::signal()
|
36 |
+
----------------------------
|
37 |
+
This has been deprecated in favour of triggering an error or
|
38 |
+
throwing an exception. Deprecated as of 1.0.1beta.
|
39 |
+
|
40 |
+
No method TestCase::sendMessage()
|
41 |
+
---------------------------------
|
42 |
+
This has been deprecated as of 1.0.1beta.
|
43 |
+
|
44 |
+
Failure to connect now emits failures
|
45 |
+
-------------------------------------
|
46 |
+
It used to be that you would have to use the
|
47 |
+
getTransferError() call on the web tester to see if
|
48 |
+
there was a socket level error in a fetch. This check
|
49 |
+
is now always carried out by the WebTestCase unless
|
50 |
+
the fetch is prefaced with WebTestCase::ignoreErrors().
|
51 |
+
The ignore directive only lasts for test case fetching
|
52 |
+
action such as get() and click().
|
53 |
+
|
54 |
+
No method SimpleTestOptions::ignore()
|
55 |
+
-------------------------------------
|
56 |
+
This is deprecated in version 1.0.1beta and has been moved
|
57 |
+
to SimpleTest::ignore() as that is more readable. In
|
58 |
+
addition, parent classes are also ignored automatically.
|
59 |
+
If you are using PHP5 you can skip this directive simply
|
60 |
+
by marking your test case as abstract.
|
61 |
+
|
62 |
+
No method assertCopy()
|
63 |
+
----------------------
|
64 |
+
This is deprecated in 1.0.1 in favour of assertClone().
|
65 |
+
The assertClone() method is slightly different in that
|
66 |
+
the objects must be identical, but without being a
|
67 |
+
reference. It is thus not a strict inversion of
|
68 |
+
assertReference().
|
69 |
+
|
70 |
+
Constructor wildcard override has no effect in mocks
|
71 |
+
----------------------------------------------------
|
72 |
+
As of 1.0.1beta this is now set with setWildcard() instead
|
73 |
+
of in the constructor.
|
74 |
+
|
75 |
+
No methods setStubBaseClass()/getStubBaseClass()
|
76 |
+
------------------------------------------------
|
77 |
+
As mocks are now used instead of stubs, these methods
|
78 |
+
stopped working and are now removed as of the 1.0.1beta
|
79 |
+
release. The mock objects may be freely used instead.
|
80 |
+
|
81 |
+
No method addPartialMockCode()
|
82 |
+
------------------------------
|
83 |
+
The ability to insert arbitrary partial mock code
|
84 |
+
has been removed. This was a low value feature
|
85 |
+
causing needless complications. It was removed
|
86 |
+
in the 1.0.1beta release.
|
87 |
+
|
88 |
+
No method setMockBaseClass()
|
89 |
+
----------------------------
|
90 |
+
The ability to change the mock base class has been
|
91 |
+
scheduled for removal and is deprecated since the
|
92 |
+
1.0.1beta version. This was a rarely used feature
|
93 |
+
except as a workaround for PHP5 limitations. As
|
94 |
+
these limitations are being resolved it's hoped
|
95 |
+
that the bundled mocks can be used directly.
|
96 |
+
|
97 |
+
No class Stub
|
98 |
+
-------------
|
99 |
+
Server stubs are deprecated from 1.0.1 as the mocks now
|
100 |
+
have exactly the same interface. Just use mock objects
|
101 |
+
instead.
|
102 |
+
|
103 |
+
No class SimpleTestOptions
|
104 |
+
--------------------------
|
105 |
+
This was replced by the shorter SimpleTest in 1.0.1beta1
|
106 |
+
and is since deprecated.
|
107 |
+
|
108 |
+
No file simple_test.php
|
109 |
+
-----------------------
|
110 |
+
This was renamed test_case.php in 1.0.1beta to more accurately
|
111 |
+
reflect it's purpose. This file should never be directly
|
112 |
+
included in test suites though, as it's part of the
|
113 |
+
underlying mechanics and has a tendency to be refactored.
|
114 |
+
|
115 |
+
No class WantedPatternExpectation
|
116 |
+
---------------------------------
|
117 |
+
This was deprecated in 1.0.1alpha in favour of the simpler
|
118 |
+
name PatternExpectation.
|
119 |
+
|
120 |
+
No class NoUnwantedPatternExpectation
|
121 |
+
-------------------------------------
|
122 |
+
This was deprecated in 1.0.1alpha in favour of the simpler
|
123 |
+
name NoPatternExpectation.
|
124 |
+
|
125 |
+
No method assertNoUnwantedPattern()
|
126 |
+
-----------------------------------
|
127 |
+
This has been renamed to assertNoPattern() in 1.0.1alpha and
|
128 |
+
the old form is deprecated.
|
129 |
+
|
130 |
+
No method assertWantedPattern()
|
131 |
+
-------------------------------
|
132 |
+
This has been renamed to assertPattern() in 1.0.1alpha and
|
133 |
+
the old form is deprecated.
|
134 |
+
|
135 |
+
No method assertExpectation()
|
136 |
+
-----------------------------
|
137 |
+
This was renamed as assert() in 1.0.1alpha and the old form
|
138 |
+
has been deprecated.
|
139 |
+
|
140 |
+
No class WildcardExpectation
|
141 |
+
----------------------------
|
142 |
+
This was a mostly internal class for the mock objects. It was
|
143 |
+
renamed AnythingExpectation to bring it closer to JMock and
|
144 |
+
NMock in version 1.0.1alpha.
|
145 |
+
|
146 |
+
Missing UnitTestCase::assertErrorPattern()
|
147 |
+
------------------------------------------
|
148 |
+
This method is deprecated for version 1.0.1 onwards.
|
149 |
+
This method has been subsumed by assertError() that can now
|
150 |
+
take an expectation. Simply pass a PatternExpectation
|
151 |
+
into assertError() to simulate the old behaviour.
|
152 |
+
|
153 |
+
No HTML when matching page elements
|
154 |
+
-----------------------------------
|
155 |
+
This behaviour has been switched to using plain text as if it
|
156 |
+
were seen by the user of the browser. This means that HTML tags
|
157 |
+
are suppressed, entities are converted and whitespace is
|
158 |
+
normalised. This should make it easier to match items in forms.
|
159 |
+
Also images are replaced with their "alt" text so that they
|
160 |
+
can be matched as well.
|
161 |
+
|
162 |
+
No method SimpleRunner::_getTestCase()
|
163 |
+
--------------------------------------
|
164 |
+
This was made public as getTestCase() in 1.0RC2.
|
165 |
+
|
166 |
+
No method restartSession()
|
167 |
+
--------------------------
|
168 |
+
This was renamed to restart() in the WebTestCase, SimpleBrowser
|
169 |
+
and the underlying SimpleUserAgent in 1.0RC2. Because it was
|
170 |
+
undocumented anyway, no attempt was made at backward
|
171 |
+
compatibility.
|
172 |
+
|
173 |
+
My custom test case ignored by tally()
|
174 |
+
--------------------------------------
|
175 |
+
The _assertTrue method has had it's signature changed due to a bug
|
176 |
+
in the PHP 5.0.1 release. You must now use getTest() from within
|
177 |
+
that method to get the test case. Mock compatibility with other
|
178 |
+
unit testers is now deprecated as of 1.0.1alpha as PEAR::PHPUnit2
|
179 |
+
should soon have mock support of it's own.
|
180 |
+
|
181 |
+
Broken code extending SimpleRunner
|
182 |
+
----------------------------------
|
183 |
+
This was replaced with SimpleScorer so that I could use the runner
|
184 |
+
name in another class. This happened in RC1 development and there
|
185 |
+
is no easy backward compatibility fix. The solution is simply to
|
186 |
+
extend SimpleScorer instead.
|
187 |
+
|
188 |
+
Missing method getBaseCookieValue()
|
189 |
+
-----------------------------------
|
190 |
+
This was renamed getCurrentCookieValue() in RC1.
|
191 |
+
|
192 |
+
Missing files from the SimpleTest suite
|
193 |
+
---------------------------------------
|
194 |
+
Versions of SimpleTest prior to Beta6 required a SIMPLE_TEST constant
|
195 |
+
to point at the SimpleTest folder location before any of the toolset
|
196 |
+
was loaded. This is no longer documented as it is now unnecessary
|
197 |
+
for later versions. If you are using an earlier version you may
|
198 |
+
need this constant. Consult the documentation that was bundled with
|
199 |
+
the release that you are using or upgrade to Beta6 or later.
|
200 |
+
|
201 |
+
No method SimpleBrowser::getCurrentUrl()
|
202 |
+
--------------------------------------
|
203 |
+
This is replaced with the more versatile showRequest() for
|
204 |
+
debugging. It only existed in this context for version Beta5.
|
205 |
+
Later versions will have SimpleBrowser::getHistory() for tracking
|
206 |
+
paths through pages. It is renamed as getUrl() since 1.0RC1.
|
207 |
+
|
208 |
+
No method Stub::setStubBaseClass()
|
209 |
+
----------------------------------
|
210 |
+
This method has finally been removed in 1.0RC1. Use
|
211 |
+
SimpleTestOptions::setStubBaseClass() instead.
|
212 |
+
|
213 |
+
No class CommandLineReporter
|
214 |
+
----------------------------
|
215 |
+
This was renamed to TextReporter in Beta3 and the deprecated version
|
216 |
+
was removed in 1.0RC1.
|
217 |
+
|
218 |
+
No method requireReturn()
|
219 |
+
-------------------------
|
220 |
+
This was deprecated in Beta3 and is now removed.
|
221 |
+
|
222 |
+
No method expectCookie()
|
223 |
+
------------------------
|
224 |
+
This method was abruptly removed in Beta4 so as to simplify the internals
|
225 |
+
until another mechanism can replace it. As a workaround it is necessary
|
226 |
+
to assert that the cookie has changed by setting it before the page
|
227 |
+
fetch and then assert the desired value.
|
228 |
+
|
229 |
+
No method clickSubmitByFormId()
|
230 |
+
-------------------------------
|
231 |
+
This method had an incorrect name as no button was involved. It was
|
232 |
+
renamed to submitByFormId() in Beta4 and the old version deprecated.
|
233 |
+
Now removed.
|
234 |
+
|
235 |
+
No method paintStart() or paintEnd()
|
236 |
+
------------------------------------
|
237 |
+
You should only get this error if you have subclassed the lower level
|
238 |
+
reporting and test runner machinery. These methods have been broken
|
239 |
+
down into events for test methods, events for test cases and events
|
240 |
+
for group tests. The new methods are...
|
241 |
+
|
242 |
+
paintStart() --> paintMethodStart(), paintCaseStart(), paintGroupStart()
|
243 |
+
paintEnd() --> paintMethodEnd(), paintCaseEnd(), paintGroupEnd()
|
244 |
+
|
245 |
+
This change was made in Beta3, ironically to make it easier to subclass
|
246 |
+
the inner machinery. Simply duplicating the code you had in the previous
|
247 |
+
methods should provide a temporary fix.
|
248 |
+
|
249 |
+
No class TestDisplay
|
250 |
+
--------------------
|
251 |
+
This has been folded into SimpleReporter in Beta3 and is now deprecated.
|
252 |
+
It was removed in RC1.
|
253 |
+
|
254 |
+
No method WebTestCase::fetch()
|
255 |
+
------------------------------
|
256 |
+
This was renamed get() in Alpha8. It is removed in Beta3.
|
257 |
+
|
258 |
+
No method submit()
|
259 |
+
------------------
|
260 |
+
This has been renamed clickSubmit() in Beta1. The old method was
|
261 |
+
removed in Beta2.
|
262 |
+
|
263 |
+
No method clearHistory()
|
264 |
+
------------------------
|
265 |
+
This method is deprecated in Beta2 and removed in RC1.
|
266 |
+
|
267 |
+
No method getCallCount()
|
268 |
+
------------------------
|
269 |
+
This method has been deprecated since Beta1 and has now been
|
270 |
+
removed. There are now more ways to set expectations on counts
|
271 |
+
and so this method should be unecessery. Removed in RC1.
|
272 |
+
|
273 |
+
Cannot find file *
|
274 |
+
------------------
|
275 |
+
The following public name changes have occoured...
|
276 |
+
|
277 |
+
simple_html_test.php --> reporter.php
|
278 |
+
simple_mock.php --> mock_objects.php
|
279 |
+
simple_unit.php --> unit_tester.php
|
280 |
+
simple_web.php --> web_tester.php
|
281 |
+
|
282 |
+
The old names were deprecated in Alpha8 and removed in Beta1.
|
283 |
+
|
284 |
+
No method attachObserver()
|
285 |
+
--------------------------
|
286 |
+
Prior to the Alpha8 release the old internal observer pattern was
|
287 |
+
gutted and replaced with a visitor. This is to trade flexibility of
|
288 |
+
test case expansion against the ease of writing user interfaces.
|
289 |
+
|
290 |
+
Code such as...
|
291 |
+
|
292 |
+
$test = &new MyTestCase();
|
293 |
+
$test->attachObserver(new TestHtmlDisplay());
|
294 |
+
$test->run();
|
295 |
+
|
296 |
+
...should be rewritten as...
|
297 |
+
|
298 |
+
$test = &new MyTestCase();
|
299 |
+
$test->run(new HtmlReporter());
|
300 |
+
|
301 |
+
If you previously attached multiple observers then the workaround
|
302 |
+
is to run the tests twice, once with each, until they can be combined.
|
303 |
+
For one observer the old method is simulated in Alpha 8, but is
|
304 |
+
removed in Beta1.
|
305 |
+
|
306 |
+
No class TestHtmlDisplay
|
307 |
+
------------------------
|
308 |
+
This class has been renamed to HtmlReporter in Alpha8. It is supported,
|
309 |
+
but deprecated in Beta1 and removed in Beta2. If you have subclassed
|
310 |
+
the display for your own design, then you will have to extend this
|
311 |
+
class (HtmlReporter) instead.
|
312 |
+
|
313 |
+
If you have accessed the event queue by overriding the notify() method
|
314 |
+
then I am afraid you are in big trouble :(. The reporter is now
|
315 |
+
carried around the test suite by the runner classes and the methods
|
316 |
+
called directly. In the unlikely event that this is a problem and
|
317 |
+
you don't want to upgrade the test tool then simplest is to write your
|
318 |
+
own runner class and invoke the tests with...
|
319 |
+
|
320 |
+
$test->accept(new MyRunner(new MyReporter()));
|
321 |
+
|
322 |
+
...rather than the run method. This should be easier to extend
|
323 |
+
anyway and gives much more control. Even this method is overhauled
|
324 |
+
in Beta3 where the runner class can be set within the test case. Really
|
325 |
+
the best thing to do is to upgrade to this version as whatever you were
|
326 |
+
trying to achieve before should now be very much easier.
|
327 |
+
|
328 |
+
Missing set options method
|
329 |
+
--------------------------
|
330 |
+
All test suite options are now in one class called SimpleTestOptions.
|
331 |
+
This means that options are set differently...
|
332 |
+
|
333 |
+
GroupTest::ignore() --> SimpleTestOptions::ignore()
|
334 |
+
Mock::setMockBaseClass() --> SimpleTestOptions::setMockBaseClass()
|
335 |
+
|
336 |
+
These changed in Alpha8 and the old versions are now removed in RC1.
|
337 |
+
|
338 |
+
No method setExpected*()
|
339 |
+
------------------------
|
340 |
+
The mock expectations changed their names in Alpha4 and the old names
|
341 |
+
ceased to be supported in Alpha8. The changes are...
|
342 |
+
|
343 |
+
setExpectedArguments() --> expectArguments()
|
344 |
+
setExpectedArgumentsSequence() --> expectArgumentsAt()
|
345 |
+
setExpectedCallCount() --> expectCallCount()
|
346 |
+
setMaximumCallCount() --> expectMaximumCallCount()
|
347 |
+
|
348 |
+
The parameters remained the same.
|
lib/Minify/min_unit_tests/simpletest/LICENSE
ADDED
@@ -0,0 +1,502 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
GNU LESSER GENERAL PUBLIC LICENSE
|
2 |
+
Version 2.1, February 1999
|
3 |
+
|
4 |
+
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
5 |
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
6 |
+
Everyone is permitted to copy and distribute verbatim copies
|
7 |
+
of this license document, but changing it is not allowed.
|
8 |
+
|
9 |
+
[This is the first released version of the Lesser GPL. It also counts
|
10 |
+
as the successor of the GNU Library Public License, version 2, hence
|
11 |
+
the version number 2.1.]
|
12 |
+
|
13 |
+
Preamble
|
14 |
+
|
15 |
+
The licenses for most software are designed to take away your
|
16 |
+
freedom to share and change it. By contrast, the GNU General Public
|
17 |
+
Licenses are intended to guarantee your freedom to share and change
|
18 |
+
free software--to make sure the software is free for all its users.
|
19 |
+
|
20 |
+
This license, the Lesser General Public License, applies to some
|
21 |
+
specially designated software packages--typically libraries--of the
|
22 |
+
Free Software Foundation and other authors who decide to use it. You
|
23 |
+
can use it too, but we suggest you first think carefully about whether
|
24 |
+
this license or the ordinary General Public License is the better
|
25 |
+
strategy to use in any particular case, based on the explanations below.
|
26 |
+
|
27 |
+
When we speak of free software, we are referring to freedom of use,
|
28 |
+
not price. Our General Public Licenses are designed to make sure that
|
29 |
+
you have the freedom to distribute copies of free software (and charge
|
30 |
+
for this service if you wish); that you receive source code or can get
|
31 |
+
it if you want it; that you can change the software and use pieces of
|
32 |
+
it in new free programs; and that you are informed that you can do
|
33 |
+
these things.
|
34 |
+
|
35 |
+
To protect your rights, we need to make restrictions that forbid
|
36 |
+
distributors to deny you these rights or to ask you to surrender these
|
37 |
+
rights. These restrictions translate to certain responsibilities for
|
38 |
+
you if you distribute copies of the library or if you modify it.
|
39 |
+
|
40 |
+
For example, if you distribute copies of the library, whether gratis
|
41 |
+
or for a fee, you must give the recipients all the rights that we gave
|
42 |
+
you. You must make sure that they, too, receive or can get the source
|
43 |
+
code. If you link other code with the library, you must provide
|
44 |
+
complete object files to the recipients, so that they can relink them
|
45 |
+
with the library after making changes to the library and recompiling
|
46 |
+
it. And you must show them these terms so they know their rights.
|
47 |
+
|
48 |
+
We protect your rights with a two-step method: (1) we copyright the
|
49 |
+
library, and (2) we offer you this license, which gives you legal
|
50 |
+
permission to copy, distribute and/or modify the library.
|
51 |
+
|
52 |
+
To protect each distributor, we want to make it very clear that
|
53 |
+
there is no warranty for the free library. Also, if the library is
|
54 |
+
modified by someone else and passed on, the recipients should know
|
55 |
+
that what they have is not the original version, so that the original
|
56 |
+
author's reputation will not be affected by problems that might be
|
57 |
+
introduced by others.
|
58 |
+
|
59 |
+
Finally, software patents pose a constant threat to the existence of
|
60 |
+
any free program. We wish to make sure that a company cannot
|
61 |
+
effectively restrict the users of a free program by obtaining a
|
62 |
+
restrictive license from a patent holder. Therefore, we insist that
|
63 |
+
any patent license obtained for a version of the library must be
|
64 |
+
consistent with the full freedom of use specified in this license.
|
65 |
+
|
66 |
+
Most GNU software, including some libraries, is covered by the
|
67 |
+
ordinary GNU General Public License. This license, the GNU Lesser
|
68 |
+
General Public License, applies to certain designated libraries, and
|
69 |
+
is quite different from the ordinary General Public License. We use
|
70 |
+
this license for certain libraries in order to permit linking those
|
71 |
+
libraries into non-free programs.
|
72 |
+
|
73 |
+
When a program is linked with a library, whether statically or using
|
74 |
+
a shared library, the combination of the two is legally speaking a
|
75 |
+
combined work, a derivative of the original library. The ordinary
|
76 |
+
General Public License therefore permits such linking only if the
|
77 |
+
entire combination fits its criteria of freedom. The Lesser General
|
78 |
+
Public License permits more lax criteria for linking other code with
|
79 |
+
the library.
|
80 |
+
|
81 |
+
We call this license the "Lesser" General Public License because it
|
82 |
+
does Less to protect the user's freedom than the ordinary General
|
83 |
+
Public License. It also provides other free software developers Less
|
84 |
+
of an advantage over competing non-free programs. These disadvantages
|
85 |
+
are the reason we use the ordinary General Public License for many
|
86 |
+
libraries. However, the Lesser license provides advantages in certain
|
87 |
+
special circumstances.
|
88 |
+
|
89 |
+
For example, on rare occasions, there may be a special need to
|
90 |
+
encourage the widest possible use of a certain library, so that it becomes
|
91 |
+
a de-facto standard. To achieve this, non-free programs must be
|
92 |
+
allowed to use the library. A more frequent case is that a free
|
93 |
+
library does the same job as widely used non-free libraries. In this
|
94 |
+
case, there is little to gain by limiting the free library to free
|
95 |
+
software only, so we use the Lesser General Public License.
|
96 |
+
|
97 |
+
In other cases, permission to use a particular library in non-free
|
98 |
+
programs enables a greater number of people to use a large body of
|
99 |
+
free software. For example, permission to use the GNU C Library in
|
100 |
+
non-free programs enables many more people to use the whole GNU
|
101 |
+
operating system, as well as its variant, the GNU/Linux operating
|
102 |
+
system.
|
103 |
+
|
104 |
+
Although the Lesser General Public License is Less protective of the
|
105 |
+
users' freedom, it does ensure that the user of a program that is
|
106 |
+
linked with the Library has the freedom and the wherewithal to run
|
107 |
+
that program using a modified version of the Library.
|
108 |
+
|
109 |
+
The precise terms and conditions for copying, distribution and
|
110 |
+
modification follow. Pay close attention to the difference between a
|
111 |
+
"work based on the library" and a "work that uses the library". The
|
112 |
+
former contains code derived from the library, whereas the latter must
|
113 |
+
be combined with the library in order to run.
|
114 |
+
|
115 |
+
GNU LESSER GENERAL PUBLIC LICENSE
|
116 |
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
117 |
+
|
118 |
+
0. This License Agreement applies to any software library or other
|
119 |
+
program which contains a notice placed by the copyright holder or
|
120 |
+
other authorized party saying it may be distributed under the terms of
|
121 |
+
this Lesser General Public License (also called "this License").
|
122 |
+
Each licensee is addressed as "you".
|
123 |
+
|
124 |
+
A "library" means a collection of software functions and/or data
|
125 |
+
prepared so as to be conveniently linked with application programs
|
126 |
+
(which use some of those functions and data) to form executables.
|
127 |
+
|
128 |
+
The "Library", below, refers to any such software library or work
|
129 |
+
which has been distributed under these terms. A "work based on the
|
130 |
+
Library" means either the Library or any derivative work under
|
131 |
+
copyright law: that is to say, a work containing the Library or a
|
132 |
+
portion of it, either verbatim or with modifications and/or translated
|
133 |
+
straightforwardly into another language. (Hereinafter, translation is
|
134 |
+
included without limitation in the term "modification".)
|
135 |
+
|
136 |
+
"Source code" for a work means the preferred form of the work for
|
137 |
+
making modifications to it. For a library, complete source code means
|
138 |
+
all the source code for all modules it contains, plus any associated
|
139 |
+
interface definition files, plus the scripts used to control compilation
|
140 |
+
and installation of the library.
|
141 |
+
|
142 |
+
Activities other than copying, distribution and modification are not
|
143 |
+
covered by this License; they are outside its scope. The act of
|
144 |
+
running a program using the Library is not restricted, and output from
|
145 |
+
such a program is covered only if its contents constitute a work based
|
146 |
+
on the Library (independent of the use of the Library in a tool for
|
147 |
+
writing it). Whether that is true depends on what the Library does
|
148 |
+
and what the program that uses the Library does.
|
149 |
+
|
150 |
+
1. You may copy and distribute verbatim copies of the Library's
|
151 |
+
complete source code as you receive it, in any medium, provided that
|
152 |
+
you conspicuously and appropriately publish on each copy an
|
153 |
+
appropriate copyright notice and disclaimer of warranty; keep intact
|
154 |
+
all the notices that refer to this License and to the absence of any
|
155 |
+
warranty; and distribute a copy of this License along with the
|
156 |
+
Library.
|
157 |
+
|
158 |
+
You may charge a fee for the physical act of transferring a copy,
|
159 |
+
and you may at your option offer warranty protection in exchange for a
|
160 |
+
fee.
|
161 |
+
|
162 |
+
2. You may modify your copy or copies of the Library or any portion
|
163 |
+
of it, thus forming a work based on the Library, and copy and
|
164 |
+
distribute such modifications or work under the terms of Section 1
|
165 |
+
above, provided that you also meet all of these conditions:
|
166 |
+
|
167 |
+
a) The modified work must itself be a software library.
|
168 |
+
|
169 |
+
b) You must cause the files modified to carry prominent notices
|
170 |
+
stating that you changed the files and the date of any change.
|
171 |
+
|
172 |
+
c) You must cause the whole of the work to be licensed at no
|
173 |
+
charge to all third parties under the terms of this License.
|
174 |
+
|
175 |
+
d) If a facility in the modified Library refers to a function or a
|
176 |
+
table of data to be supplied by an application program that uses
|
177 |
+
the facility, other than as an argument passed when the facility
|
178 |
+
is invoked, then you must make a good faith effort to ensure that,
|
179 |
+
in the event an application does not supply such function or
|
180 |
+
table, the facility still operates, and performs whatever part of
|
181 |
+
its purpose remains meaningful.
|
182 |
+
|
183 |
+
(For example, a function in a library to compute square roots has
|
184 |
+
a purpose that is entirely well-defined independent of the
|
185 |
+
application. Therefore, Subsection 2d requires that any
|
186 |
+
application-supplied function or table used by this function must
|
187 |
+
be optional: if the application does not supply it, the square
|
188 |
+
root function must still compute square roots.)
|
189 |
+
|
190 |
+
These requirements apply to the modified work as a whole. If
|
191 |
+
identifiable sections of that work are not derived from the Library,
|
192 |
+
and can be reasonably considered independent and separate works in
|
193 |
+
themselves, then this License, and its terms, do not apply to those
|
194 |
+
sections when you distribute them as separate works. But when you
|
195 |
+
distribute the same sections as part of a whole which is a work based
|
196 |
+
on the Library, the distribution of the whole must be on the terms of
|
197 |
+
this License, whose permissions for other licensees extend to the
|
198 |
+
entire whole, and thus to each and every part regardless of who wrote
|
199 |
+
it.
|
200 |
+
|
201 |
+
Thus, it is not the intent of this section to claim rights or contest
|
202 |
+
your rights to work written entirely by you; rather, the intent is to
|
203 |
+
exercise the right to control the distribution of derivative or
|
204 |
+
collective works based on the Library.
|
205 |
+
|
206 |
+
In addition, mere aggregation of another work not based on the Library
|
207 |
+
with the Library (or with a work based on the Library) on a volume of
|
208 |
+
a storage or distribution medium does not bring the other work under
|
209 |
+
the scope of this License.
|
210 |
+
|
211 |
+
3. You may opt to apply the terms of the ordinary GNU General Public
|
212 |
+
License instead of this License to a given copy of the Library. To do
|
213 |
+
this, you must alter all the notices that refer to this License, so
|
214 |
+
that they refer to the ordinary GNU General Public License, version 2,
|
215 |
+
instead of to this License. (If a newer version than version 2 of the
|
216 |
+
ordinary GNU General Public License has appeared, then you can specify
|
217 |
+
that version instead if you wish.) Do not make any other change in
|
218 |
+
these notices.
|
219 |
+
|
220 |
+
Once this change is made in a given copy, it is irreversible for
|
221 |
+
that copy, so the ordinary GNU General Public License applies to all
|
222 |
+
subsequent copies and derivative works made from that copy.
|
223 |
+
|
224 |
+
This option is useful when you wish to copy part of the code of
|
225 |
+
the Library into a program that is not a library.
|
226 |
+
|
227 |
+
4. You may copy and distribute the Library (or a portion or
|
228 |
+
derivative of it, under Section 2) in object code or executable form
|
229 |
+
under the terms of Sections 1 and 2 above provided that you accompany
|
230 |
+
it with the complete corresponding machine-readable source code, which
|
231 |
+
must be distributed under the terms of Sections 1 and 2 above on a
|
232 |
+
medium customarily used for software interchange.
|
233 |
+
|
234 |
+
If distribution of object code is made by offering access to copy
|
235 |
+
from a designated place, then offering equivalent access to copy the
|
236 |
+
source code from the same place satisfies the requirement to
|
237 |
+
distribute the source code, even though third parties are not
|
238 |
+
compelled to copy the source along with the object code.
|
239 |
+
|
240 |
+
5. A program that contains no derivative of any portion of the
|
241 |
+
Library, but is designed to work with the Library by being compiled or
|
242 |
+
linked with it, is called a "work that uses the Library". Such a
|
243 |
+
work, in isolation, is not a derivative work of the Library, and
|
244 |
+
therefore falls outside the scope of this License.
|
245 |
+
|
246 |
+
However, linking a "work that uses the Library" with the Library
|
247 |
+
creates an executable that is a derivative of the Library (because it
|
248 |
+
contains portions of the Library), rather than a "work that uses the
|
249 |
+
library". The executable is therefore covered by this License.
|
250 |
+
Section 6 states terms for distribution of such executables.
|
251 |
+
|
252 |
+
When a "work that uses the Library" uses material from a header file
|
253 |
+
that is part of the Library, the object code for the work may be a
|
254 |
+
derivative work of the Library even though the source code is not.
|
255 |
+
Whether this is true is especially significant if the work can be
|
256 |
+
linked without the Library, or if the work is itself a library. The
|
257 |
+
threshold for this to be true is not precisely defined by law.
|
258 |
+
|
259 |
+
If such an object file uses only numerical parameters, data
|
260 |
+
structure layouts and accessors, and small macros and small inline
|
261 |
+
functions (ten lines or less in length), then the use of the object
|
262 |
+
file is unrestricted, regardless of whether it is legally a derivative
|
263 |
+
work. (Executables containing this object code plus portions of the
|
264 |
+
Library will still fall under Section 6.)
|
265 |
+
|
266 |
+
Otherwise, if the work is a derivative of the Library, you may
|
267 |
+
distribute the object code for the work under the terms of Section 6.
|
268 |
+
Any executables containing that work also fall under Section 6,
|
269 |
+
whether or not they are linked directly with the Library itself.
|
270 |
+
|
271 |
+
6. As an exception to the Sections above, you may also combine or
|
272 |
+
link a "work that uses the Library" with the Library to produce a
|
273 |
+
work containing portions of the Library, and distribute that work
|
274 |
+
under terms of your choice, provided that the terms permit
|
275 |
+
modification of the work for the customer's own use and reverse
|
276 |
+
engineering for debugging such modifications.
|
277 |
+
|
278 |
+
You must give prominent notice with each copy of the work that the
|
279 |
+
Library is used in it and that the Library and its use are covered by
|
280 |
+
this License. You must supply a copy of this License. If the work
|
281 |
+
during execution displays copyright notices, you must include the
|
282 |
+
copyright notice for the Library among them, as well as a reference
|
283 |
+
directing the user to the copy of this License. Also, you must do one
|
284 |
+
of these things:
|
285 |
+
|
286 |
+
a) Accompany the work with the complete corresponding
|
287 |
+
machine-readable source code for the Library including whatever
|
288 |
+
changes were used in the work (which must be distributed under
|
289 |
+
Sections 1 and 2 above); and, if the work is an executable linked
|
290 |
+
with the Library, with the complete machine-readable "work that
|
291 |
+
uses the Library", as object code and/or source code, so that the
|
292 |
+
user can modify the Library and then relink to produce a modified
|
293 |
+
executable containing the modified Library. (It is understood
|
294 |
+
that the user who changes the contents of definitions files in the
|
295 |
+
Library will not necessarily be able to recompile the application
|
296 |
+
to use the modified definitions.)
|
297 |
+
|
298 |
+
b) Use a suitable shared library mechanism for linking with the
|
299 |
+
Library. A suitable mechanism is one that (1) uses at run time a
|
300 |
+
copy of the library already present on the user's computer system,
|
301 |
+
rather than copying library functions into the executable, and (2)
|
302 |
+
will operate properly with a modified version of the library, if
|
303 |
+
the user installs one, as long as the modified version is
|
304 |
+
interface-compatible with the version that the work was made with.
|
305 |
+
|
306 |
+
c) Accompany the work with a written offer, valid for at
|
307 |
+
least three years, to give the same user the materials
|
308 |
+
specified in Subsection 6a, above, for a charge no more
|
309 |
+
than the cost of performing this distribution.
|
310 |
+
|
311 |
+
d) If distribution of the work is made by offering access to copy
|
312 |
+
from a designated place, offer equivalent access to copy the above
|
313 |
+
specified materials from the same place.
|
314 |
+
|
315 |
+
e) Verify that the user has already received a copy of these
|
316 |
+
materials or that you have already sent this user a copy.
|
317 |
+
|
318 |
+
For an executable, the required form of the "work that uses the
|
319 |
+
Library" must include any data and utility programs needed for
|
320 |
+
reproducing the executable from it. However, as a special exception,
|
321 |
+
the materials to be distributed need not include anything that is
|
322 |
+
normally distributed (in either source or binary form) with the major
|
323 |
+
components (compiler, kernel, and so on) of the operating system on
|
324 |
+
which the executable runs, unless that component itself accompanies
|
325 |
+
the executable.
|
326 |
+
|
327 |
+
It may happen that this requirement contradicts the license
|
328 |
+
restrictions of other proprietary libraries that do not normally
|
329 |
+
accompany the operating system. Such a contradiction means you cannot
|
330 |
+
use both them and the Library together in an executable that you
|
331 |
+
distribute.
|
332 |
+
|
333 |
+
7. You may place library facilities that are a work based on the
|
334 |
+
Library side-by-side in a single library together with other library
|
335 |
+
facilities not covered by this License, and distribute such a combined
|
336 |
+
library, provided that the separate distribution of the work based on
|
337 |
+
the Library and of the other library facilities is otherwise
|
338 |
+
permitted, and provided that you do these two things:
|
339 |
+
|
340 |
+
a) Accompany the combined library with a copy of the same work
|
341 |
+
based on the Library, uncombined with any other library
|
342 |
+
facilities. This must be distributed under the terms of the
|
343 |
+
Sections above.
|
344 |
+
|
345 |
+
b) Give prominent notice with the combined library of the fact
|
346 |
+
that part of it is a work based on the Library, and explaining
|
347 |
+
where to find the accompanying uncombined form of the same work.
|
348 |
+
|
349 |
+
8. You may not copy, modify, sublicense, link with, or distribute
|
350 |
+
the Library except as expressly provided under this License. Any
|
351 |
+
attempt otherwise to copy, modify, sublicense, link with, or
|
352 |
+
distribute the Library is void, and will automatically terminate your
|
353 |
+
rights under this License. However, parties who have received copies,
|
354 |
+
or rights, from you under this License will not have their licenses
|
355 |
+
terminated so long as such parties remain in full compliance.
|
356 |
+
|
357 |
+
9. You are not required to accept this License, since you have not
|
358 |
+
signed it. However, nothing else grants you permission to modify or
|
359 |
+
distribute the Library or its derivative works. These actions are
|
360 |
+
prohibited by law if you do not accept this License. Therefore, by
|
361 |
+
modifying or distributing the Library (or any work based on the
|
362 |
+
Library), you indicate your acceptance of this License to do so, and
|
363 |
+
all its terms and conditions for copying, distributing or modifying
|
364 |
+
the Library or works based on it.
|
365 |
+
|
366 |
+
10. Each time you redistribute the Library (or any work based on the
|
367 |
+
Library), the recipient automatically receives a license from the
|
368 |
+
original licensor to copy, distribute, link with or modify the Library
|
369 |
+
subject to these terms and conditions. You may not impose any further
|
370 |
+
restrictions on the recipients' exercise of the rights granted herein.
|
371 |
+
You are not responsible for enforcing compliance by third parties with
|
372 |
+
this License.
|
373 |
+
|
374 |
+
11. If, as a consequence of a court judgment or allegation of patent
|
375 |
+
infringement or for any other reason (not limited to patent issues),
|
376 |
+
conditions are imposed on you (whether by court order, agreement or
|
377 |
+
otherwise) that contradict the conditions of this License, they do not
|
378 |
+
excuse you from the conditions of this License. If you cannot
|
379 |
+
distribute so as to satisfy simultaneously your obligations under this
|
380 |
+
License and any other pertinent obligations, then as a consequence you
|
381 |
+
may not distribute the Library at all. For example, if a patent
|
382 |
+
license would not permit royalty-free redistribution of the Library by
|
383 |
+
all those who receive copies directly or indirectly through you, then
|
384 |
+
the only way you could satisfy both it and this License would be to
|
385 |
+
refrain entirely from distribution of the Library.
|
386 |
+
|
387 |
+
If any portion of this section is held invalid or unenforceable under any
|
388 |
+
particular circumstance, the balance of the section is intended to apply,
|
389 |
+
and the section as a whole is intended to apply in other circumstances.
|
390 |
+
|
391 |
+
It is not the purpose of this section to induce you to infringe any
|
392 |
+
patents or other property right claims or to contest validity of any
|
393 |
+
such claims; this section has the sole purpose of protecting the
|
394 |
+
integrity of the free software distribution system which is
|
395 |
+
implemented by public license practices. Many people have made
|
396 |
+
generous contributions to the wide range of software distributed
|
397 |
+
through that system in reliance on consistent application of that
|
398 |
+
system; it is up to the author/donor to decide if he or she is willing
|
399 |
+
to distribute software through any other system and a licensee cannot
|
400 |
+
impose that choice.
|
401 |
+
|
402 |
+
This section is intended to make thoroughly clear what is believed to
|
403 |
+
be a consequence of the rest of this License.
|
404 |
+
|
405 |
+
12. If the distribution and/or use of the Library is restricted in
|
406 |
+
certain countries either by patents or by copyrighted interfaces, the
|
407 |
+
original copyright holder who places the Library under this License may add
|
408 |
+
an explicit geographical distribution limitation excluding those countries,
|
409 |
+
so that distribution is permitted only in or among countries not thus
|
410 |
+
excluded. In such case, this License incorporates the limitation as if
|
411 |
+
written in the body of this License.
|
412 |
+
|
413 |
+
13. The Free Software Foundation may publish revised and/or new
|
414 |
+
versions of the Lesser General Public License from time to time.
|
415 |
+
Such new versions will be similar in spirit to the present version,
|
416 |
+
but may differ in detail to address new problems or concerns.
|
417 |
+
|
418 |
+
Each version is given a distinguishing version number. If the Library
|
419 |
+
specifies a version number of this License which applies to it and
|
420 |
+
"any later version", you have the option of following the terms and
|
421 |
+
conditions either of that version or of any later version published by
|
422 |
+
the Free Software Foundation. If the Library does not specify a
|
423 |
+
license version number, you may choose any version ever published by
|
424 |
+
the Free Software Foundation.
|
425 |
+
|
426 |
+
14. If you wish to incorporate parts of the Library into other free
|
427 |
+
programs whose distribution conditions are incompatible with these,
|
428 |
+
write to the author to ask for permission. For software which is
|
429 |
+
copyrighted by the Free Software Foundation, write to the Free
|
430 |
+
Software Foundation; we sometimes make exceptions for this. Our
|
431 |
+
decision will be guided by the two goals of preserving the free status
|
432 |
+
of all derivatives of our free software and of promoting the sharing
|
433 |
+
and reuse of software generally.
|
434 |
+
|
435 |
+
NO WARRANTY
|
436 |
+
|
437 |
+
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
438 |
+
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
439 |
+
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
440 |
+
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
441 |
+
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
442 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
443 |
+
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
444 |
+
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
445 |
+
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
446 |
+
|
447 |
+
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
448 |
+
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
449 |
+
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
450 |
+
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
451 |
+
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
452 |
+
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
453 |
+
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
454 |
+
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
455 |
+
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
456 |
+
DAMAGES.
|
457 |
+
|
458 |
+
END OF TERMS AND CONDITIONS
|
459 |
+
|
460 |
+
How to Apply These Terms to Your New Libraries
|
461 |
+
|
462 |
+
If you develop a new library, and you want it to be of the greatest
|
463 |
+
possible use to the public, we recommend making it free software that
|
464 |
+
everyone can redistribute and change. You can do so by permitting
|
465 |
+
redistribution under these terms (or, alternatively, under the terms of the
|
466 |
+
ordinary General Public License).
|
467 |
+
|
468 |
+
To apply these terms, attach the following notices to the library. It is
|
469 |
+
safest to attach them to the start of each source file to most effectively
|
470 |
+
convey the exclusion of warranty; and each file should have at least the
|
471 |
+
"copyright" line and a pointer to where the full notice is found.
|
472 |
+
|
473 |
+
<one line to give the library's name and a brief idea of what it does.>
|
474 |
+
Copyright (C) <year> <name of author>
|
475 |
+
|
476 |
+
This library is free software; you can redistribute it and/or
|
477 |
+
modify it under the terms of the GNU Lesser General Public
|
478 |
+
License as published by the Free Software Foundation; either
|
479 |
+
version 2.1 of the License, or (at your option) any later version.
|
480 |
+
|
481 |
+
This library is distributed in the hope that it will be useful,
|
482 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
483 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
484 |
+
Lesser General Public License for more details.
|
485 |
+
|
486 |
+
You should have received a copy of the GNU Lesser General Public
|
487 |
+
License along with this library; if not, write to the Free Software
|
488 |
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
489 |
+
|
490 |
+
Also add information on how to contact you by electronic and paper mail.
|
491 |
+
|
492 |
+
You should also get your employer (if you work as a programmer) or your
|
493 |
+
school, if any, to sign a "copyright disclaimer" for the library, if
|
494 |
+
necessary. Here is a sample; alter the names:
|
495 |
+
|
496 |
+
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
497 |
+
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
498 |
+
|
499 |
+
<signature of Ty Coon>, 1 April 1990
|
500 |
+
Ty Coon, President of Vice
|
501 |
+
|
502 |
+
That's all there is to it!
|
lib/Minify/min_unit_tests/simpletest/README
ADDED
@@ -0,0 +1,108 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
SimpleTest
|
2 |
+
==========
|
3 |
+
You probably got this package from...
|
4 |
+
http://simpletest.sourceforge.net/projects/simpletest/
|
5 |
+
|
6 |
+
If there is no licence agreement with this package please download
|
7 |
+
a version from the location above. You must read and accept that
|
8 |
+
licence to use this software. The file is titled simply LICENSE.
|
9 |
+
|
10 |
+
What is it? It's a framework for unit testing, web site testing and
|
11 |
+
mock objects for PHP 4.2.0+ (and PHP 5.0 to 5.3 without E_STRICT).
|
12 |
+
|
13 |
+
If you have used JUnit, you will find this PHP unit testing version very
|
14 |
+
similar. Also included is a mock objects and server stubs generator.
|
15 |
+
The stubs can have return values set for different arguments, can have
|
16 |
+
sequences set also by arguments and can return items by reference.
|
17 |
+
The mocks inherit all of this functionality and can also have
|
18 |
+
expectations set, again in sequences and for different arguments.
|
19 |
+
|
20 |
+
A web tester similar in concept to JWebUnit is also included. There is no
|
21 |
+
JavaScript or tables support, but forms, authentication, cookies and
|
22 |
+
frames are handled.
|
23 |
+
|
24 |
+
You can see a release schedule at http://www.lastcraft.com/overview.php
|
25 |
+
which is also copied to the documentation folder with this release.
|
26 |
+
A full PHPDocumenter API documentation exists at
|
27 |
+
http://simpletest.sourceforge.net/.
|
28 |
+
|
29 |
+
The user interface is minimal
|
30 |
+
in the extreme, but a lot of information flows from the test suite.
|
31 |
+
After version 1.0 we will release a better web UI, but we are leaving XUL
|
32 |
+
and GTk versions to volunteers as everybody has their own opinion
|
33 |
+
on a good GUI, and we don't want to discourage development by shipping
|
34 |
+
one with the toolkit. YOucan download an Eclipse plug-in separately.
|
35 |
+
|
36 |
+
You are looking at a second full release. The unit tests for SimpleTest
|
37 |
+
itself can be run here...
|
38 |
+
|
39 |
+
simpletest/test/unit_tests.php
|
40 |
+
|
41 |
+
And tests involving live network connections as well are here...
|
42 |
+
|
43 |
+
simpletest/test/all_tests.php
|
44 |
+
|
45 |
+
The full tests will typically overrun the 8Mb limit often allowed
|
46 |
+
to a PHP process. A workaround is to run the tests on the command
|
47 |
+
with a custom php.ini file if you do not have access to your server
|
48 |
+
version.
|
49 |
+
|
50 |
+
You will have to edit the all_tests.php file if you are accesssing
|
51 |
+
the internet through a proxy server. See the comments in all_tests.php
|
52 |
+
for instructions.
|
53 |
+
|
54 |
+
The full tests read some test data from the LastCraft site. If the site
|
55 |
+
is down or has been modified for a later version then you will get
|
56 |
+
spurious errors. A unit_tests.php failure on the other hand would be
|
57 |
+
very serious. As far as we know we haven't yet managed to check in any
|
58 |
+
unit test failures, so please correct us if you find one.
|
59 |
+
|
60 |
+
Even if all of the tests run please verify that your existing test suites
|
61 |
+
also function as expected. If they don't see the file...
|
62 |
+
|
63 |
+
HELP_MY_TESTS_DONT_WORK_ANYMORE
|
64 |
+
|
65 |
+
This contains information on interface changes. It also points out
|
66 |
+
deprecated interfaces, so you should read this even if all of
|
67 |
+
your current tests appear to run.
|
68 |
+
|
69 |
+
There is a documentation folder which contains the core reference information
|
70 |
+
in English and French, although this information is fairly basic.
|
71 |
+
You can find a tutorial on...
|
72 |
+
|
73 |
+
http://www.lastcraft.com/first_test_tutorial.php
|
74 |
+
|
75 |
+
...to get you started and this material will eventually become included
|
76 |
+
with the project documentation. A French translation exists at...
|
77 |
+
|
78 |
+
http://www.onpk.net/index.php/2005/01/12/254-tutoriel-simpletest-decouvrir-les-tests-unitaires.
|
79 |
+
|
80 |
+
If you download and use, and possibly even extend this tool, please let us
|
81 |
+
know. Any feedback, even bad, is always welcome and we will work to get
|
82 |
+
your suggestions into the next release. Ideally please send your
|
83 |
+
comments to...
|
84 |
+
|
85 |
+
simpletest-support@lists.sourceforge.net
|
86 |
+
|
87 |
+
...so that others can read them too. We usually try to respond within 48
|
88 |
+
hours.
|
89 |
+
|
90 |
+
There is no change log except at Sourceforge. You can visit the
|
91 |
+
release notes to see the completed TODO list after each cycle and also the
|
92 |
+
status of any bugs, but if the bug is recent then it will be fixed in SVN only.
|
93 |
+
The SVN check-ins always have all the tests passing and so SVN snapshots should
|
94 |
+
be pretty usable, although the code may not look so good internally.
|
95 |
+
|
96 |
+
Oh, yes. It is called "Simple" because it should be simple to
|
97 |
+
use. We intend to add a complete set of tools for a test first
|
98 |
+
and "test as you code" type of development. "Simple" does not
|
99 |
+
mean "Lite" in this context.
|
100 |
+
|
101 |
+
Thanks to everyone who has sent comments and offered suggestions. They
|
102 |
+
really are invaluable, but sadly you are too many to mention in full.
|
103 |
+
Thanks to all on the advanced PHP forum on SitePoint, especially Harry
|
104 |
+
Feucks. Early adopters are always an inspiration.
|
105 |
+
|
106 |
+
Marcus Baker, Jason Sweat, Travis Swicegood, Perrick Penet and Edward Z. Yang.
|
107 |
+
--
|
108 |
+
marcus@lastcraft.com
|
lib/Minify/min_unit_tests/simpletest/TODO.xml
ADDED
@@ -0,0 +1,176 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<page title="TODO items for the current iteration" here="TODO">
|
3 |
+
<long_title>TODO items for the current iteration</long_title>
|
4 |
+
<content>
|
5 |
+
<section name="iteration" title="Current iteration">
|
6 |
+
<p>
|
7 |
+
This is immediate stuff only for
|
8 |
+
this iteration (1.0.1RC1) of 38 hours.
|
9 |
+
</p>
|
10 |
+
</section>
|
11 |
+
<section name="unit-tester" title="Unit tester">
|
12 |
+
<dl>
|
13 |
+
<dt class="done">
|
14 |
+
Make sure expectException() works correctly
|
15 |
+
with setUp() and tearDown() methods (3).
|
16 |
+
</dt>
|
17 |
+
<dd>
|
18 |
+
In particular:
|
19 |
+
<ul>
|
20 |
+
<li>tearDown() is always run unless an exception is thrown in tearDown()/</li>
|
21 |
+
</ul>
|
22 |
+
</dd>
|
23 |
+
</dl>
|
24 |
+
</section>
|
25 |
+
<section name="reporter" title="Reporter">
|
26 |
+
<dl>
|
27 |
+
<dt class="postponed">
|
28 |
+
Add Eclipse support to DefaultReporter (2).
|
29 |
+
</dt>
|
30 |
+
<dd>
|
31 |
+
Need a way to detect the Eclipse environment (must talk to Steve) and
|
32 |
+
to use the EclipseReporter within the DefaultReporter in this case.
|
33 |
+
This removes a significant piece of set up from Steve's side.
|
34 |
+
</dd>
|
35 |
+
</dl>
|
36 |
+
</section>
|
37 |
+
<section name="mock-objects" title="Mock objects">
|
38 |
+
<dl>
|
39 |
+
<dt>
|
40 |
+
Add throwOn() method for generating exceptions (4/6).
|
41 |
+
</dt>
|
42 |
+
<dd>
|
43 |
+
Can throw exceptions on certain method call or parameters in the
|
44 |
+
same way that a return value can be set.
|
45 |
+
</dd>
|
46 |
+
</dl>
|
47 |
+
</section>
|
48 |
+
<section name="parser" title="Parser">
|
49 |
+
<dl>
|
50 |
+
<dt class="done">
|
51 |
+
Fix bug 1688238 with lost paths when absoluting a link (2).
|
52 |
+
</dt>
|
53 |
+
<dt class="done">
|
54 |
+
Fix bug 1671539 with assertText picking up JavaScript (1).
|
55 |
+
</dt>
|
56 |
+
<dt class="done">
|
57 |
+
Add U flag to regexes to allow unicode (3).
|
58 |
+
</dt>
|
59 |
+
</dl>
|
60 |
+
</section>
|
61 |
+
<section name="browser" title="Browser">
|
62 |
+
<dl>
|
63 |
+
<dt>
|
64 |
+
Acknowledge target attribute in base tag (3).
|
65 |
+
</dt>
|
66 |
+
<dt>
|
67 |
+
Investigate bug 1706283 with incorrect proxy requests (3).
|
68 |
+
</dt>
|
69 |
+
<dd>
|
70 |
+
<a href="https://sourceforge.net/tracker/index.php?func=detail&aid=1706283&group_id=76550&atid=547455">
|
71 |
+
see bug tracker 1706283
|
72 |
+
</a>
|
73 |
+
</dd>
|
74 |
+
<dt class="done">
|
75 |
+
Confirm bug 1656650 forms appearing as null is fixed (1).
|
76 |
+
</dt>
|
77 |
+
<dd>
|
78 |
+
<a href="https://sourceforge.net/tracker/index.php?func=detail&aid=1656650&group_id=76550&atid=547455">
|
79 |
+
see bug tracker 1656650
|
80 |
+
</a>
|
81 |
+
</dd>
|
82 |
+
<dt class="done">
|
83 |
+
Fix bug 1642529 with radio buttons not working (3).
|
84 |
+
</dt>
|
85 |
+
<dt>
|
86 |
+
Look at adding a file() loading command (4).
|
87 |
+
</dt>
|
88 |
+
<dd>
|
89 |
+
This is just a scoping exercise.
|
90 |
+
There are times when you want to click on an HTML email, or you want
|
91 |
+
to start the test by loading the page with something other than the
|
92 |
+
SimpleTest web browser.
|
93 |
+
Is it easy (sub a couple of days work) to load a file when given
|
94 |
+
the file:// prefix on a URL?
|
95 |
+
</dd>
|
96 |
+
</dl>
|
97 |
+
</section>
|
98 |
+
<section name="web-tester" title="Web tester">
|
99 |
+
<dl>
|
100 |
+
<dt class="done">
|
101 |
+
Fix issue 1605972 missing isLink(), probably by changing docs (1).
|
102 |
+
</dt>
|
103 |
+
</dl>
|
104 |
+
</section>
|
105 |
+
<section name="documentation" title="Documentation">
|
106 |
+
<dl>
|
107 |
+
<dt>
|
108 |
+
Update core documentation snippets
|
109 |
+
with the new features such as autoload (8).
|
110 |
+
</dt>
|
111 |
+
<dd>
|
112 |
+
Bit of a major job.
|
113 |
+
It means going through all of the core documentation and updating
|
114 |
+
it with new methods and features.
|
115 |
+
In particular, the introductory pages should switch to autoload.
|
116 |
+
Should be checked : addTestFile.
|
117 |
+
</dd>
|
118 |
+
<dt class="done">
|
119 |
+
Extension docs (1).
|
120 |
+
</dt>
|
121 |
+
<dd>
|
122 |
+
Document the file structure for extension writers.
|
123 |
+
Also, deprecate the simpletest/ui/ folder in favour of putting everything
|
124 |
+
into simpletest/extension/.
|
125 |
+
</dd>
|
126 |
+
</dl>
|
127 |
+
</section>
|
128 |
+
<section name="build" title="Build">
|
129 |
+
</section>
|
130 |
+
</content>
|
131 |
+
<internal>
|
132 |
+
<link>
|
133 |
+
<a href="#iteration">Current iteration</a> is 1.0.1RC1.
|
134 |
+
</link>
|
135 |
+
<link>
|
136 |
+
Items for
|
137 |
+
<a href="#unit-tester">Unit tester</a>,
|
138 |
+
<a href="#reporter">Reporter</a>,
|
139 |
+
<a href="#mock-objects">Mock objects</a>,
|
140 |
+
<a href="#parser">Parser</a>,
|
141 |
+
<a href="#browser">Browser</a>,
|
142 |
+
<a href="#web-tester">Web tester</a>,
|
143 |
+
<a href="#documentation">Documentation</a> and
|
144 |
+
<a href="#build">Build</a>.
|
145 |
+
</link>
|
146 |
+
</internal>
|
147 |
+
<external>
|
148 |
+
<link>
|
149 |
+
Trackers for :
|
150 |
+
<a href="https://sourceforge.net/tracker/?group_id=76550&atid=547458">feature requests</a>,
|
151 |
+
<a href="https://sourceforge.net/tracker/?group_id=76550&atid=547455">bugs</a> and
|
152 |
+
<a href="https://sourceforge.net/tracker/?group_id=76550&atid=547457">patches</a>.
|
153 |
+
</link>
|
154 |
+
</external>
|
155 |
+
<meta>
|
156 |
+
<keywords>
|
157 |
+
software development,
|
158 |
+
computer programmer,
|
159 |
+
php programming,
|
160 |
+
programming php,
|
161 |
+
software development company,
|
162 |
+
software development uk,
|
163 |
+
php tutorial,
|
164 |
+
bespoke software development uk,
|
165 |
+
corporate web development,
|
166 |
+
architecture,
|
167 |
+
freelancer,
|
168 |
+
php resources,
|
169 |
+
wordtracker,
|
170 |
+
web marketing,
|
171 |
+
serach engines,
|
172 |
+
web positioning,
|
173 |
+
internet marketing
|
174 |
+
</keywords>
|
175 |
+
</meta>
|
176 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/VERSION
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
1.0.1
|
lib/Minify/min_unit_tests/simpletest/authentication.php
ADDED
@@ -0,0 +1,238 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Base include file for SimpleTest
|
4 |
+
* @package SimpleTest
|
5 |
+
* @subpackage WebTester
|
6 |
+
* @version $Id: authentication.php 1720 2008-04-07 02:32:43Z lastcraft $
|
7 |
+
*/
|
8 |
+
/**
|
9 |
+
* include http class
|
10 |
+
*/
|
11 |
+
require_once(dirname(__FILE__) . '/http.php');
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Represents a single security realm's identity.
|
15 |
+
* @package SimpleTest
|
16 |
+
* @subpackage WebTester
|
17 |
+
*/
|
18 |
+
class SimpleRealm {
|
19 |
+
var $_type;
|
20 |
+
var $_root;
|
21 |
+
var $_username;
|
22 |
+
var $_password;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Starts with the initial entry directory.
|
26 |
+
* @param string $type Authentication type for this
|
27 |
+
* realm. Only Basic authentication
|
28 |
+
* is currently supported.
|
29 |
+
* @param SimpleUrl $url Somewhere in realm.
|
30 |
+
* @access public
|
31 |
+
*/
|
32 |
+
function SimpleRealm($type, $url) {
|
33 |
+
$this->_type = $type;
|
34 |
+
$this->_root = $url->getBasePath();
|
35 |
+
$this->_username = false;
|
36 |
+
$this->_password = false;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Adds another location to the realm.
|
41 |
+
* @param SimpleUrl $url Somewhere in realm.
|
42 |
+
* @access public
|
43 |
+
*/
|
44 |
+
function stretch($url) {
|
45 |
+
$this->_root = $this->_getCommonPath($this->_root, $url->getPath());
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Finds the common starting path.
|
50 |
+
* @param string $first Path to compare.
|
51 |
+
* @param string $second Path to compare.
|
52 |
+
* @return string Common directories.
|
53 |
+
* @access private
|
54 |
+
*/
|
55 |
+
function _getCommonPath($first, $second) {
|
56 |
+
$first = explode('/', $first);
|
57 |
+
$second = explode('/', $second);
|
58 |
+
for ($i = 0; $i < min(count($first), count($second)); $i++) {
|
59 |
+
if ($first[$i] != $second[$i]) {
|
60 |
+
return implode('/', array_slice($first, 0, $i)) . '/';
|
61 |
+
}
|
62 |
+
}
|
63 |
+
return implode('/', $first) . '/';
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Sets the identity to try within this realm.
|
68 |
+
* @param string $username Username in authentication dialog.
|
69 |
+
* @param string $username Password in authentication dialog.
|
70 |
+
* @access public
|
71 |
+
*/
|
72 |
+
function setIdentity($username, $password) {
|
73 |
+
$this->_username = $username;
|
74 |
+
$this->_password = $password;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Accessor for current identity.
|
79 |
+
* @return string Last succesful username.
|
80 |
+
* @access public
|
81 |
+
*/
|
82 |
+
function getUsername() {
|
83 |
+
return $this->_username;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Accessor for current identity.
|
88 |
+
* @return string Last succesful password.
|
89 |
+
* @access public
|
90 |
+
*/
|
91 |
+
function getPassword() {
|
92 |
+
return $this->_password;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Test to see if the URL is within the directory
|
97 |
+
* tree of the realm.
|
98 |
+
* @param SimpleUrl $url URL to test.
|
99 |
+
* @return boolean True if subpath.
|
100 |
+
* @access public
|
101 |
+
*/
|
102 |
+
function isWithin($url) {
|
103 |
+
if ($this->_isIn($this->_root, $url->getBasePath())) {
|
104 |
+
return true;
|
105 |
+
}
|
106 |
+
if ($this->_isIn($this->_root, $url->getBasePath() . $url->getPage() . '/')) {
|
107 |
+
return true;
|
108 |
+
}
|
109 |
+
return false;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Tests to see if one string is a substring of
|
114 |
+
* another.
|
115 |
+
* @param string $part Small bit.
|
116 |
+
* @param string $whole Big bit.
|
117 |
+
* @return boolean True if the small bit is
|
118 |
+
* in the big bit.
|
119 |
+
* @access private
|
120 |
+
*/
|
121 |
+
function _isIn($part, $whole) {
|
122 |
+
return strpos($whole, $part) === 0;
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Manages security realms.
|
128 |
+
* @package SimpleTest
|
129 |
+
* @subpackage WebTester
|
130 |
+
*/
|
131 |
+
class SimpleAuthenticator {
|
132 |
+
var $_realms;
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Clears the realms.
|
136 |
+
* @access public
|
137 |
+
*/
|
138 |
+
function SimpleAuthenticator() {
|
139 |
+
$this->restartSession();
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Starts with no realms set up.
|
144 |
+
* @access public
|
145 |
+
*/
|
146 |
+
function restartSession() {
|
147 |
+
$this->_realms = array();
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Adds a new realm centered the current URL.
|
152 |
+
* Browsers vary wildly on their behaviour in this
|
153 |
+
* regard. Mozilla ignores the realm and presents
|
154 |
+
* only when challenged, wasting bandwidth. IE
|
155 |
+
* just carries on presenting until a new challenge
|
156 |
+
* occours. SimpleTest tries to follow the spirit of
|
157 |
+
* the original standards committee and treats the
|
158 |
+
* base URL as the root of a file tree shaped realm.
|
159 |
+
* @param SimpleUrl $url Base of realm.
|
160 |
+
* @param string $type Authentication type for this
|
161 |
+
* realm. Only Basic authentication
|
162 |
+
* is currently supported.
|
163 |
+
* @param string $realm Name of realm.
|
164 |
+
* @access public
|
165 |
+
*/
|
166 |
+
function addRealm($url, $type, $realm) {
|
167 |
+
$this->_realms[$url->getHost()][$realm] = new SimpleRealm($type, $url);
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Sets the current identity to be presented
|
172 |
+
* against that realm.
|
173 |
+
* @param string $host Server hosting realm.
|
174 |
+
* @param string $realm Name of realm.
|
175 |
+
* @param string $username Username for realm.
|
176 |
+
* @param string $password Password for realm.
|
177 |
+
* @access public
|
178 |
+
*/
|
179 |
+
function setIdentityForRealm($host, $realm, $username, $password) {
|
180 |
+
if (isset($this->_realms[$host][$realm])) {
|
181 |
+
$this->_realms[$host][$realm]->setIdentity($username, $password);
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Finds the name of the realm by comparing URLs.
|
187 |
+
* @param SimpleUrl $url URL to test.
|
188 |
+
* @return SimpleRealm Name of realm.
|
189 |
+
* @access private
|
190 |
+
*/
|
191 |
+
function _findRealmFromUrl($url) {
|
192 |
+
if (! isset($this->_realms[$url->getHost()])) {
|
193 |
+
return false;
|
194 |
+
}
|
195 |
+
foreach ($this->_realms[$url->getHost()] as $name => $realm) {
|
196 |
+
if ($realm->isWithin($url)) {
|
197 |
+
return $realm;
|
198 |
+
}
|
199 |
+
}
|
200 |
+
return false;
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Presents the appropriate headers for this location.
|
205 |
+
* @param SimpleHttpRequest $request Request to modify.
|
206 |
+
* @param SimpleUrl $url Base of realm.
|
207 |
+
* @access public
|
208 |
+
*/
|
209 |
+
function addHeaders(&$request, $url) {
|
210 |
+
if ($url->getUsername() && $url->getPassword()) {
|
211 |
+
$username = $url->getUsername();
|
212 |
+
$password = $url->getPassword();
|
213 |
+
} elseif ($realm = $this->_findRealmFromUrl($url)) {
|
214 |
+
$username = $realm->getUsername();
|
215 |
+
$password = $realm->getPassword();
|
216 |
+
} else {
|
217 |
+
return;
|
218 |
+
}
|
219 |
+
$this->addBasicHeaders($request, $username, $password);
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Presents the appropriate headers for this
|
224 |
+
* location for basic authentication.
|
225 |
+
* @param SimpleHttpRequest $request Request to modify.
|
226 |
+
* @param string $username Username for realm.
|
227 |
+
* @param string $password Password for realm.
|
228 |
+
* @access public
|
229 |
+
* @static
|
230 |
+
*/
|
231 |
+
function addBasicHeaders(&$request, $username, $password) {
|
232 |
+
if ($username && $password) {
|
233 |
+
$request->addHeaderLine(
|
234 |
+
'Authorization: Basic ' . base64_encode("$username:$password"));
|
235 |
+
}
|
236 |
+
}
|
237 |
+
}
|
238 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/autorun.php
ADDED
@@ -0,0 +1,87 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Autorunner which runs all tests cases found in a file
|
4 |
+
* that includes this module.
|
5 |
+
* @package SimpleTest
|
6 |
+
* @version $Id: autorun.php 1721 2008-04-07 19:27:10Z lastcraft $
|
7 |
+
*/
|
8 |
+
require_once dirname(__FILE__) . '/unit_tester.php';
|
9 |
+
require_once dirname(__FILE__) . '/mock_objects.php';
|
10 |
+
require_once dirname(__FILE__) . '/collector.php';
|
11 |
+
require_once dirname(__FILE__) . '/default_reporter.php';
|
12 |
+
|
13 |
+
$GLOBALS['SIMPLETEST_AUTORUNNER_INITIAL_CLASSES'] = get_declared_classes();
|
14 |
+
register_shutdown_function('simpletest_autorun');
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Exit handler to run all recent test cases if no test has
|
18 |
+
* so far been run. Uses the DefaultReporter which can have
|
19 |
+
* it's output controlled with SimpleTest::prefer().
|
20 |
+
*/
|
21 |
+
function simpletest_autorun() {
|
22 |
+
if (tests_have_run()) {
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
$candidates = array_intersect(
|
26 |
+
capture_new_classes(),
|
27 |
+
classes_defined_in_initial_file());
|
28 |
+
$loader = new SimpleFileLoader();
|
29 |
+
$suite = $loader->createSuiteFromClasses(
|
30 |
+
basename(initial_file()),
|
31 |
+
$loader->selectRunnableTests($candidates));
|
32 |
+
$result = $suite->run(new DefaultReporter());
|
33 |
+
if (SimpleReporter::inCli()) {
|
34 |
+
exit($result ? 0 : 1);
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Checks the current test context to see if a test has
|
40 |
+
* ever been run.
|
41 |
+
* @return boolean True if tests have run.
|
42 |
+
*/
|
43 |
+
function tests_have_run() {
|
44 |
+
if ($context = SimpleTest::getContext()) {
|
45 |
+
return (boolean)$context->getTest();
|
46 |
+
}
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* The first autorun file.
|
52 |
+
* @return string Filename of first autorun script.
|
53 |
+
*/
|
54 |
+
function initial_file() {
|
55 |
+
static $file = false;
|
56 |
+
if (! $file) {
|
57 |
+
$file = reset(get_included_files());
|
58 |
+
}
|
59 |
+
return $file;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Just the classes from the first autorun script. May
|
64 |
+
* get a few false positives, as it just does a regex based
|
65 |
+
* on following the word "class".
|
66 |
+
* @return array List of all possible classes in first
|
67 |
+
* autorun script.
|
68 |
+
*/
|
69 |
+
function classes_defined_in_initial_file() {
|
70 |
+
if (preg_match_all('/\bclass\s+(\w+)/i', file_get_contents(initial_file()), $matches)) {
|
71 |
+
return array_map('strtolower', $matches[1]);
|
72 |
+
}
|
73 |
+
return array();
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Every class since the first autorun include. This
|
78 |
+
* is safe enough if require_once() is alwyas used.
|
79 |
+
* @return array Class names.
|
80 |
+
*/
|
81 |
+
function capture_new_classes() {
|
82 |
+
global $SIMPLETEST_AUTORUNNER_INITIAL_CLASSES;
|
83 |
+
return array_map('strtolower', array_diff(get_declared_classes(),
|
84 |
+
$SIMPLETEST_AUTORUNNER_INITIAL_CLASSES ?
|
85 |
+
$SIMPLETEST_AUTORUNNER_INITIAL_CLASSES : array()));
|
86 |
+
}
|
87 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/browser.php
ADDED
@@ -0,0 +1,1098 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Base include file for SimpleTest
|
4 |
+
* @package SimpleTest
|
5 |
+
* @subpackage WebTester
|
6 |
+
* @version $Id: browser.php 1723 2008-04-08 00:34:10Z lastcraft $
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**#@+
|
10 |
+
* include other SimpleTest class files
|
11 |
+
*/
|
12 |
+
require_once(dirname(__FILE__) . '/simpletest.php');
|
13 |
+
require_once(dirname(__FILE__) . '/http.php');
|
14 |
+
require_once(dirname(__FILE__) . '/encoding.php');
|
15 |
+
require_once(dirname(__FILE__) . '/page.php');
|
16 |
+
require_once(dirname(__FILE__) . '/selector.php');
|
17 |
+
require_once(dirname(__FILE__) . '/frames.php');
|
18 |
+
require_once(dirname(__FILE__) . '/user_agent.php');
|
19 |
+
/**#@-*/
|
20 |
+
|
21 |
+
if (!defined('DEFAULT_MAX_NESTED_FRAMES')) {
|
22 |
+
define('DEFAULT_MAX_NESTED_FRAMES', 3);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Browser history list.
|
27 |
+
* @package SimpleTest
|
28 |
+
* @subpackage WebTester
|
29 |
+
*/
|
30 |
+
class SimpleBrowserHistory {
|
31 |
+
var $_sequence;
|
32 |
+
var $_position;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Starts empty.
|
36 |
+
* @access public
|
37 |
+
*/
|
38 |
+
function SimpleBrowserHistory() {
|
39 |
+
$this->_sequence = array();
|
40 |
+
$this->_position = -1;
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Test for no entries yet.
|
45 |
+
* @return boolean True if empty.
|
46 |
+
* @access private
|
47 |
+
*/
|
48 |
+
function _isEmpty() {
|
49 |
+
return ($this->_position == -1);
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Test for being at the beginning.
|
54 |
+
* @return boolean True if first.
|
55 |
+
* @access private
|
56 |
+
*/
|
57 |
+
function _atBeginning() {
|
58 |
+
return ($this->_position == 0) && ! $this->_isEmpty();
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Test for being at the last entry.
|
63 |
+
* @return boolean True if last.
|
64 |
+
* @access private
|
65 |
+
*/
|
66 |
+
function _atEnd() {
|
67 |
+
return ($this->_position + 1 >= count($this->_sequence)) && ! $this->_isEmpty();
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Adds a successfully fetched page to the history.
|
72 |
+
* @param SimpleUrl $url URL of fetch.
|
73 |
+
* @param SimpleEncoding $parameters Any post data with the fetch.
|
74 |
+
* @access public
|
75 |
+
*/
|
76 |
+
function recordEntry($url, $parameters) {
|
77 |
+
$this->_dropFuture();
|
78 |
+
array_push(
|
79 |
+
$this->_sequence,
|
80 |
+
array('url' => $url, 'parameters' => $parameters));
|
81 |
+
$this->_position++;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Last fully qualified URL for current history
|
86 |
+
* position.
|
87 |
+
* @return SimpleUrl URL for this position.
|
88 |
+
* @access public
|
89 |
+
*/
|
90 |
+
function getUrl() {
|
91 |
+
if ($this->_isEmpty()) {
|
92 |
+
return false;
|
93 |
+
}
|
94 |
+
return $this->_sequence[$this->_position]['url'];
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Parameters of last fetch from current history
|
99 |
+
* position.
|
100 |
+
* @return SimpleFormEncoding Post parameters.
|
101 |
+
* @access public
|
102 |
+
*/
|
103 |
+
function getParameters() {
|
104 |
+
if ($this->_isEmpty()) {
|
105 |
+
return false;
|
106 |
+
}
|
107 |
+
return $this->_sequence[$this->_position]['parameters'];
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Step back one place in the history. Stops at
|
112 |
+
* the first page.
|
113 |
+
* @return boolean True if any previous entries.
|
114 |
+
* @access public
|
115 |
+
*/
|
116 |
+
function back() {
|
117 |
+
if ($this->_isEmpty() || $this->_atBeginning()) {
|
118 |
+
return false;
|
119 |
+
}
|
120 |
+
$this->_position--;
|
121 |
+
return true;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Step forward one place. If already at the
|
126 |
+
* latest entry then nothing will happen.
|
127 |
+
* @return boolean True if any future entries.
|
128 |
+
* @access public
|
129 |
+
*/
|
130 |
+
function forward() {
|
131 |
+
if ($this->_isEmpty() || $this->_atEnd()) {
|
132 |
+
return false;
|
133 |
+
}
|
134 |
+
$this->_position++;
|
135 |
+
return true;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Ditches all future entries beyond the current
|
140 |
+
* point.
|
141 |
+
* @access private
|
142 |
+
*/
|
143 |
+
function _dropFuture() {
|
144 |
+
if ($this->_isEmpty()) {
|
145 |
+
return;
|
146 |
+
}
|
147 |
+
while (! $this->_atEnd()) {
|
148 |
+
array_pop($this->_sequence);
|
149 |
+
}
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Simulated web browser. This is an aggregate of
|
155 |
+
* the user agent, the HTML parsing, request history
|
156 |
+
* and the last header set.
|
157 |
+
* @package SimpleTest
|
158 |
+
* @subpackage WebTester
|
159 |
+
*/
|
160 |
+
class SimpleBrowser {
|
161 |
+
var $_user_agent;
|
162 |
+
var $_page;
|
163 |
+
var $_history;
|
164 |
+
var $_ignore_frames;
|
165 |
+
var $_maximum_nested_frames;
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Starts with a fresh browser with no
|
169 |
+
* cookie or any other state information. The
|
170 |
+
* exception is that a default proxy will be
|
171 |
+
* set up if specified in the options.
|
172 |
+
* @access public
|
173 |
+
*/
|
174 |
+
function SimpleBrowser() {
|
175 |
+
$this->_user_agent = &$this->_createUserAgent();
|
176 |
+
$this->_user_agent->useProxy(
|
177 |
+
SimpleTest::getDefaultProxy(),
|
178 |
+
SimpleTest::getDefaultProxyUsername(),
|
179 |
+
SimpleTest::getDefaultProxyPassword());
|
180 |
+
$this->_page = &new SimplePage();
|
181 |
+
$this->_history = &$this->_createHistory();
|
182 |
+
$this->_ignore_frames = false;
|
183 |
+
$this->_maximum_nested_frames = DEFAULT_MAX_NESTED_FRAMES;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Creates the underlying user agent.
|
188 |
+
* @return SimpleFetcher Content fetcher.
|
189 |
+
* @access protected
|
190 |
+
*/
|
191 |
+
function &_createUserAgent() {
|
192 |
+
$user_agent = &new SimpleUserAgent();
|
193 |
+
return $user_agent;
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Creates a new empty history list.
|
198 |
+
* @return SimpleBrowserHistory New list.
|
199 |
+
* @access protected
|
200 |
+
*/
|
201 |
+
function &_createHistory() {
|
202 |
+
$history = &new SimpleBrowserHistory();
|
203 |
+
return $history;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Disables frames support. Frames will not be fetched
|
208 |
+
* and the frameset page will be used instead.
|
209 |
+
* @access public
|
210 |
+
*/
|
211 |
+
function ignoreFrames() {
|
212 |
+
$this->_ignore_frames = true;
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Enables frames support. Frames will be fetched from
|
217 |
+
* now on.
|
218 |
+
* @access public
|
219 |
+
*/
|
220 |
+
function useFrames() {
|
221 |
+
$this->_ignore_frames = false;
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Switches off cookie sending and recieving.
|
226 |
+
* @access public
|
227 |
+
*/
|
228 |
+
function ignoreCookies() {
|
229 |
+
$this->_user_agent->ignoreCookies();
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* Switches back on the cookie sending and recieving.
|
234 |
+
* @access public
|
235 |
+
*/
|
236 |
+
function useCookies() {
|
237 |
+
$this->_user_agent->useCookies();
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Parses the raw content into a page. Will load further
|
242 |
+
* frame pages unless frames are disabled.
|
243 |
+
* @param SimpleHttpResponse $response Response from fetch.
|
244 |
+
* @param integer $depth Nested frameset depth.
|
245 |
+
* @return SimplePage Parsed HTML.
|
246 |
+
* @access private
|
247 |
+
*/
|
248 |
+
function &_parse($response, $depth = 0) {
|
249 |
+
$page = &$this->_buildPage($response);
|
250 |
+
if ($this->_ignore_frames || ! $page->hasFrames() || ($depth > $this->_maximum_nested_frames)) {
|
251 |
+
return $page;
|
252 |
+
}
|
253 |
+
$frameset = &new SimpleFrameset($page);
|
254 |
+
foreach ($page->getFrameset() as $key => $url) {
|
255 |
+
$frame = &$this->_fetch($url, new SimpleGetEncoding(), $depth + 1);
|
256 |
+
$frameset->addFrame($frame, $key);
|
257 |
+
}
|
258 |
+
return $frameset;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* Assembles the parsing machinery and actually parses
|
263 |
+
* a single page. Frees all of the builder memory and so
|
264 |
+
* unjams the PHP memory management.
|
265 |
+
* @param SimpleHttpResponse $response Response from fetch.
|
266 |
+
* @return SimplePage Parsed top level page.
|
267 |
+
* @access protected
|
268 |
+
*/
|
269 |
+
function &_buildPage($response) {
|
270 |
+
$builder = &new SimplePageBuilder();
|
271 |
+
$page = &$builder->parse($response);
|
272 |
+
$builder->free();
|
273 |
+
unset($builder);
|
274 |
+
return $page;
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Fetches a page. Jointly recursive with the _parse()
|
279 |
+
* method as it descends a frameset.
|
280 |
+
* @param string/SimpleUrl $url Target to fetch.
|
281 |
+
* @param SimpleEncoding $encoding GET/POST parameters.
|
282 |
+
* @param integer $depth Nested frameset depth protection.
|
283 |
+
* @return SimplePage Parsed page.
|
284 |
+
* @access private
|
285 |
+
*/
|
286 |
+
function &_fetch($url, $encoding, $depth = 0) {
|
287 |
+
$response = &$this->_user_agent->fetchResponse($url, $encoding);
|
288 |
+
if ($response->isError()) {
|
289 |
+
$page = &new SimplePage($response);
|
290 |
+
} else {
|
291 |
+
$page = &$this->_parse($response, $depth);
|
292 |
+
}
|
293 |
+
return $page;
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Fetches a page or a single frame if that is the current
|
298 |
+
* focus.
|
299 |
+
* @param SimpleUrl $url Target to fetch.
|
300 |
+
* @param SimpleEncoding $parameters GET/POST parameters.
|
301 |
+
* @return string Raw content of page.
|
302 |
+
* @access private
|
303 |
+
*/
|
304 |
+
function _load($url, $parameters) {
|
305 |
+
$frame = $url->getTarget();
|
306 |
+
if (! $frame || ! $this->_page->hasFrames() || (strtolower($frame) == '_top')) {
|
307 |
+
return $this->_loadPage($url, $parameters);
|
308 |
+
}
|
309 |
+
return $this->_loadFrame(array($frame), $url, $parameters);
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* Fetches a page and makes it the current page/frame.
|
314 |
+
* @param string/SimpleUrl $url Target to fetch as string.
|
315 |
+
* @param SimplePostEncoding $parameters POST parameters.
|
316 |
+
* @return string Raw content of page.
|
317 |
+
* @access private
|
318 |
+
*/
|
319 |
+
function _loadPage($url, $parameters) {
|
320 |
+
$this->_page = &$this->_fetch($url, $parameters);
|
321 |
+
$this->_history->recordEntry(
|
322 |
+
$this->_page->getUrl(),
|
323 |
+
$this->_page->getRequestData());
|
324 |
+
return $this->_page->getRaw();
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Fetches a frame into the existing frameset replacing the
|
329 |
+
* original.
|
330 |
+
* @param array $frames List of names to drill down.
|
331 |
+
* @param string/SimpleUrl $url Target to fetch as string.
|
332 |
+
* @param SimpleFormEncoding $parameters POST parameters.
|
333 |
+
* @return string Raw content of page.
|
334 |
+
* @access private
|
335 |
+
*/
|
336 |
+
function _loadFrame($frames, $url, $parameters) {
|
337 |
+
$page = &$this->_fetch($url, $parameters);
|
338 |
+
$this->_page->setFrame($frames, $page);
|
339 |
+
return $page->getRaw();
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Removes expired and temporary cookies as if
|
344 |
+
* the browser was closed and re-opened.
|
345 |
+
* @param string/integer $date Time when session restarted.
|
346 |
+
* If omitted then all persistent
|
347 |
+
* cookies are kept.
|
348 |
+
* @access public
|
349 |
+
*/
|
350 |
+
function restart($date = false) {
|
351 |
+
$this->_user_agent->restart($date);
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Adds a header to every fetch.
|
356 |
+
* @param string $header Header line to add to every
|
357 |
+
* request until cleared.
|
358 |
+
* @access public
|
359 |
+
*/
|
360 |
+
function addHeader($header) {
|
361 |
+
$this->_user_agent->addHeader($header);
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Ages the cookies by the specified time.
|
366 |
+
* @param integer $interval Amount in seconds.
|
367 |
+
* @access public
|
368 |
+
*/
|
369 |
+
function ageCookies($interval) {
|
370 |
+
$this->_user_agent->ageCookies($interval);
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* Sets an additional cookie. If a cookie has
|
375 |
+
* the same name and path it is replaced.
|
376 |
+
* @param string $name Cookie key.
|
377 |
+
* @param string $value Value of cookie.
|
378 |
+
* @param string $host Host upon which the cookie is valid.
|
379 |
+
* @param string $path Cookie path if not host wide.
|
380 |
+
* @param string $expiry Expiry date.
|
381 |
+
* @access public
|
382 |
+
*/
|
383 |
+
function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
|
384 |
+
$this->_user_agent->setCookie($name, $value, $host, $path, $expiry);
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Reads the most specific cookie value from the
|
389 |
+
* browser cookies.
|
390 |
+
* @param string $host Host to search.
|
391 |
+
* @param string $path Applicable path.
|
392 |
+
* @param string $name Name of cookie to read.
|
393 |
+
* @return string False if not present, else the
|
394 |
+
* value as a string.
|
395 |
+
* @access public
|
396 |
+
*/
|
397 |
+
function getCookieValue($host, $path, $name) {
|
398 |
+
return $this->_user_agent->getCookieValue($host, $path, $name);
|
399 |
+
}
|
400 |
+
|
401 |
+
/**
|
402 |
+
* Reads the current cookies for the current URL.
|
403 |
+
* @param string $name Key of cookie to find.
|
404 |
+
* @return string Null if there is no current URL, false
|
405 |
+
* if the cookie is not set.
|
406 |
+
* @access public
|
407 |
+
*/
|
408 |
+
function getCurrentCookieValue($name) {
|
409 |
+
return $this->_user_agent->getBaseCookieValue($name, $this->_page->getUrl());
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* Sets the maximum number of redirects before
|
414 |
+
* a page will be loaded anyway.
|
415 |
+
* @param integer $max Most hops allowed.
|
416 |
+
* @access public
|
417 |
+
*/
|
418 |
+
function setMaximumRedirects($max) {
|
419 |
+
$this->_user_agent->setMaximumRedirects($max);
|
420 |
+
}
|
421 |
+
|
422 |
+
/**
|
423 |
+
* Sets the maximum number of nesting of framed pages
|
424 |
+
* within a framed page to prevent loops.
|
425 |
+
* @param integer $max Highest depth allowed.
|
426 |
+
* @access public
|
427 |
+
*/
|
428 |
+
function setMaximumNestedFrames($max) {
|
429 |
+
$this->_maximum_nested_frames = $max;
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Sets the socket timeout for opening a connection.
|
434 |
+
* @param integer $timeout Maximum time in seconds.
|
435 |
+
* @access public
|
436 |
+
*/
|
437 |
+
function setConnectionTimeout($timeout) {
|
438 |
+
$this->_user_agent->setConnectionTimeout($timeout);
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Sets proxy to use on all requests for when
|
443 |
+
* testing from behind a firewall. Set URL
|
444 |
+
* to false to disable.
|
445 |
+
* @param string $proxy Proxy URL.
|
446 |
+
* @param string $username Proxy username for authentication.
|
447 |
+
* @param string $password Proxy password for authentication.
|
448 |
+
* @access public
|
449 |
+
*/
|
450 |
+
function useProxy($proxy, $username = false, $password = false) {
|
451 |
+
$this->_user_agent->useProxy($proxy, $username, $password);
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* Fetches the page content with a HEAD request.
|
456 |
+
* Will affect cookies, but will not change the base URL.
|
457 |
+
* @param string/SimpleUrl $url Target to fetch as string.
|
458 |
+
* @param hash/SimpleHeadEncoding $parameters Additional parameters for
|
459 |
+
* HEAD request.
|
460 |
+
* @return boolean True if successful.
|
461 |
+
* @access public
|
462 |
+
*/
|
463 |
+
function head($url, $parameters = false) {
|
464 |
+
if (! is_object($url)) {
|
465 |
+
$url = new SimpleUrl($url);
|
466 |
+
}
|
467 |
+
if ($this->getUrl()) {
|
468 |
+
$url = $url->makeAbsolute($this->getUrl());
|
469 |
+
}
|
470 |
+
$response = &$this->_user_agent->fetchResponse($url, new SimpleHeadEncoding($parameters));
|
471 |
+
return ! $response->isError();
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Fetches the page content with a simple GET request.
|
476 |
+
* @param string/SimpleUrl $url Target to fetch.
|
477 |
+
* @param hash/SimpleFormEncoding $parameters Additional parameters for
|
478 |
+
* GET request.
|
479 |
+
* @return string Content of page or false.
|
480 |
+
* @access public
|
481 |
+
*/
|
482 |
+
function get($url, $parameters = false) {
|
483 |
+
if (! is_object($url)) {
|
484 |
+
$url = new SimpleUrl($url);
|
485 |
+
}
|
486 |
+
if ($this->getUrl()) {
|
487 |
+
$url = $url->makeAbsolute($this->getUrl());
|
488 |
+
}
|
489 |
+
return $this->_load($url, new SimpleGetEncoding($parameters));
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Fetches the page content with a POST request.
|
494 |
+
* @param string/SimpleUrl $url Target to fetch as string.
|
495 |
+
* @param hash/SimpleFormEncoding $parameters POST parameters.
|
496 |
+
* @return string Content of page.
|
497 |
+
* @access public
|
498 |
+
*/
|
499 |
+
function post($url, $parameters = false) {
|
500 |
+
if (! is_object($url)) {
|
501 |
+
$url = new SimpleUrl($url);
|
502 |
+
}
|
503 |
+
if ($this->getUrl()) {
|
504 |
+
$url = $url->makeAbsolute($this->getUrl());
|
505 |
+
}
|
506 |
+
return $this->_load($url, new SimplePostEncoding($parameters));
|
507 |
+
}
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Equivalent to hitting the retry button on the
|
511 |
+
* browser. Will attempt to repeat the page fetch. If
|
512 |
+
* there is no history to repeat it will give false.
|
513 |
+
* @return string/boolean Content if fetch succeeded
|
514 |
+
* else false.
|
515 |
+
* @access public
|
516 |
+
*/
|
517 |
+
function retry() {
|
518 |
+
$frames = $this->_page->getFrameFocus();
|
519 |
+
if (count($frames) > 0) {
|
520 |
+
$this->_loadFrame(
|
521 |
+
$frames,
|
522 |
+
$this->_page->getUrl(),
|
523 |
+
$this->_page->getRequestData());
|
524 |
+
return $this->_page->getRaw();
|
525 |
+
}
|
526 |
+
if ($url = $this->_history->getUrl()) {
|
527 |
+
$this->_page = &$this->_fetch($url, $this->_history->getParameters());
|
528 |
+
return $this->_page->getRaw();
|
529 |
+
}
|
530 |
+
return false;
|
531 |
+
}
|
532 |
+
|
533 |
+
/**
|
534 |
+
* Equivalent to hitting the back button on the
|
535 |
+
* browser. The browser history is unchanged on
|
536 |
+
* failure. The page content is refetched as there
|
537 |
+
* is no concept of content caching in SimpleTest.
|
538 |
+
* @return boolean True if history entry and
|
539 |
+
* fetch succeeded
|
540 |
+
* @access public
|
541 |
+
*/
|
542 |
+
function back() {
|
543 |
+
if (! $this->_history->back()) {
|
544 |
+
return false;
|
545 |
+
}
|
546 |
+
$content = $this->retry();
|
547 |
+
if (! $content) {
|
548 |
+
$this->_history->forward();
|
549 |
+
}
|
550 |
+
return $content;
|
551 |
+
}
|
552 |
+
|
553 |
+
/**
|
554 |
+
* Equivalent to hitting the forward button on the
|
555 |
+
* browser. The browser history is unchanged on
|
556 |
+
* failure. The page content is refetched as there
|
557 |
+
* is no concept of content caching in SimpleTest.
|
558 |
+
* @return boolean True if history entry and
|
559 |
+
* fetch succeeded
|
560 |
+
* @access public
|
561 |
+
*/
|
562 |
+
function forward() {
|
563 |
+
if (! $this->_history->forward()) {
|
564 |
+
return false;
|
565 |
+
}
|
566 |
+
$content = $this->retry();
|
567 |
+
if (! $content) {
|
568 |
+
$this->_history->back();
|
569 |
+
}
|
570 |
+
return $content;
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Retries a request after setting the authentication
|
575 |
+
* for the current realm.
|
576 |
+
* @param string $username Username for realm.
|
577 |
+
* @param string $password Password for realm.
|
578 |
+
* @return boolean True if successful fetch. Note
|
579 |
+
* that authentication may still have
|
580 |
+
* failed.
|
581 |
+
* @access public
|
582 |
+
*/
|
583 |
+
function authenticate($username, $password) {
|
584 |
+
if (! $this->_page->getRealm()) {
|
585 |
+
return false;
|
586 |
+
}
|
587 |
+
$url = $this->_page->getUrl();
|
588 |
+
if (! $url) {
|
589 |
+
return false;
|
590 |
+
}
|
591 |
+
$this->_user_agent->setIdentity(
|
592 |
+
$url->getHost(),
|
593 |
+
$this->_page->getRealm(),
|
594 |
+
$username,
|
595 |
+
$password);
|
596 |
+
return $this->retry();
|
597 |
+
}
|
598 |
+
|
599 |
+
/**
|
600 |
+
* Accessor for a breakdown of the frameset.
|
601 |
+
* @return array Hash tree of frames by name
|
602 |
+
* or index if no name.
|
603 |
+
* @access public
|
604 |
+
*/
|
605 |
+
function getFrames() {
|
606 |
+
return $this->_page->getFrames();
|
607 |
+
}
|
608 |
+
|
609 |
+
/**
|
610 |
+
* Accessor for current frame focus. Will be
|
611 |
+
* false if no frame has focus.
|
612 |
+
* @return integer/string/boolean Label if any, otherwise
|
613 |
+
* the position in the frameset
|
614 |
+
* or false if none.
|
615 |
+
* @access public
|
616 |
+
*/
|
617 |
+
function getFrameFocus() {
|
618 |
+
return $this->_page->getFrameFocus();
|
619 |
+
}
|
620 |
+
|
621 |
+
/**
|
622 |
+
* Sets the focus by index. The integer index starts from 1.
|
623 |
+
* @param integer $choice Chosen frame.
|
624 |
+
* @return boolean True if frame exists.
|
625 |
+
* @access public
|
626 |
+
*/
|
627 |
+
function setFrameFocusByIndex($choice) {
|
628 |
+
return $this->_page->setFrameFocusByIndex($choice);
|
629 |
+
}
|
630 |
+
|
631 |
+
/**
|
632 |
+
* Sets the focus by name.
|
633 |
+
* @param string $name Chosen frame.
|
634 |
+
* @return boolean True if frame exists.
|
635 |
+
* @access public
|
636 |
+
*/
|
637 |
+
function setFrameFocus($name) {
|
638 |
+
return $this->_page->setFrameFocus($name);
|
639 |
+
}
|
640 |
+
|
641 |
+
/**
|
642 |
+
* Clears the frame focus. All frames will be searched
|
643 |
+
* for content.
|
644 |
+
* @access public
|
645 |
+
*/
|
646 |
+
function clearFrameFocus() {
|
647 |
+
return $this->_page->clearFrameFocus();
|
648 |
+
}
|
649 |
+
|
650 |
+
/**
|
651 |
+
* Accessor for last error.
|
652 |
+
* @return string Error from last response.
|
653 |
+
* @access public
|
654 |
+
*/
|
655 |
+
function getTransportError() {
|
656 |
+
return $this->_page->getTransportError();
|
657 |
+
}
|
658 |
+
|
659 |
+
/**
|
660 |
+
* Accessor for current MIME type.
|
661 |
+
* @return string MIME type as string; e.g. 'text/html'
|
662 |
+
* @access public
|
663 |
+
*/
|
664 |
+
function getMimeType() {
|
665 |
+
return $this->_page->getMimeType();
|
666 |
+
}
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Accessor for last response code.
|
670 |
+
* @return integer Last HTTP response code received.
|
671 |
+
* @access public
|
672 |
+
*/
|
673 |
+
function getResponseCode() {
|
674 |
+
return $this->_page->getResponseCode();
|
675 |
+
}
|
676 |
+
|
677 |
+
/**
|
678 |
+
* Accessor for last Authentication type. Only valid
|
679 |
+
* straight after a challenge (401).
|
680 |
+
* @return string Description of challenge type.
|
681 |
+
* @access public
|
682 |
+
*/
|
683 |
+
function getAuthentication() {
|
684 |
+
return $this->_page->getAuthentication();
|
685 |
+
}
|
686 |
+
|
687 |
+
/**
|
688 |
+
* Accessor for last Authentication realm. Only valid
|
689 |
+
* straight after a challenge (401).
|
690 |
+
* @return string Name of security realm.
|
691 |
+
* @access public
|
692 |
+
*/
|
693 |
+
function getRealm() {
|
694 |
+
return $this->_page->getRealm();
|
695 |
+
}
|
696 |
+
|
697 |
+
/**
|
698 |
+
* Accessor for current URL of page or frame if
|
699 |
+
* focused.
|
700 |
+
* @return string Location of current page or frame as
|
701 |
+
* a string.
|
702 |
+
*/
|
703 |
+
function getUrl() {
|
704 |
+
$url = $this->_page->getUrl();
|
705 |
+
return $url ? $url->asString() : false;
|
706 |
+
}
|
707 |
+
|
708 |
+
/**
|
709 |
+
* Accessor for base URL of page if set via BASE tag
|
710 |
+
* @return string base URL
|
711 |
+
*/
|
712 |
+
function getBaseUrl() {
|
713 |
+
$url = $this->_page->getBaseUrl();
|
714 |
+
return $url ? $url->asString() : false;
|
715 |
+
}
|
716 |
+
|
717 |
+
/**
|
718 |
+
* Accessor for raw bytes sent down the wire.
|
719 |
+
* @return string Original text sent.
|
720 |
+
* @access public
|
721 |
+
*/
|
722 |
+
function getRequest() {
|
723 |
+
return $this->_page->getRequest();
|
724 |
+
}
|
725 |
+
|
726 |
+
/**
|
727 |
+
* Accessor for raw header information.
|
728 |
+
* @return string Header block.
|
729 |
+
* @access public
|
730 |
+
*/
|
731 |
+
function getHeaders() {
|
732 |
+
return $this->_page->getHeaders();
|
733 |
+
}
|
734 |
+
|
735 |
+
/**
|
736 |
+
* Accessor for raw page information.
|
737 |
+
* @return string Original text content of web page.
|
738 |
+
* @access public
|
739 |
+
*/
|
740 |
+
function getContent() {
|
741 |
+
return $this->_page->getRaw();
|
742 |
+
}
|
743 |
+
|
744 |
+
/**
|
745 |
+
* Accessor for plain text version of the page.
|
746 |
+
* @return string Normalised text representation.
|
747 |
+
* @access public
|
748 |
+
*/
|
749 |
+
function getContentAsText() {
|
750 |
+
return $this->_page->getText();
|
751 |
+
}
|
752 |
+
|
753 |
+
/**
|
754 |
+
* Accessor for parsed title.
|
755 |
+
* @return string Title or false if no title is present.
|
756 |
+
* @access public
|
757 |
+
*/
|
758 |
+
function getTitle() {
|
759 |
+
return $this->_page->getTitle();
|
760 |
+
}
|
761 |
+
|
762 |
+
/**
|
763 |
+
* Accessor for a list of all links in current page.
|
764 |
+
* @return array List of urls with scheme of
|
765 |
+
* http or https and hostname.
|
766 |
+
* @access public
|
767 |
+
*/
|
768 |
+
function getUrls() {
|
769 |
+
return $this->_page->getUrls();
|
770 |
+
}
|
771 |
+
|
772 |
+
/**
|
773 |
+
* Sets all form fields with that name.
|
774 |
+
* @param string $label Name or label of field in forms.
|
775 |
+
* @param string $value New value of field.
|
776 |
+
* @return boolean True if field exists, otherwise false.
|
777 |
+
* @access public
|
778 |
+
*/
|
779 |
+
function setField($label, $value, $position=false) {
|
780 |
+
return $this->_page->setField(new SimpleByLabelOrName($label), $value, $position);
|
781 |
+
}
|
782 |
+
|
783 |
+
/**
|
784 |
+
* Sets all form fields with that name. Will use label if
|
785 |
+
* one is available (not yet implemented).
|
786 |
+
* @param string $name Name of field in forms.
|
787 |
+
* @param string $value New value of field.
|
788 |
+
* @return boolean True if field exists, otherwise false.
|
789 |
+
* @access public
|
790 |
+
*/
|
791 |
+
function setFieldByName($name, $value, $position=false) {
|
792 |
+
return $this->_page->setField(new SimpleByName($name), $value, $position);
|
793 |
+
}
|
794 |
+
|
795 |
+
/**
|
796 |
+
* Sets all form fields with that id attribute.
|
797 |
+
* @param string/integer $id Id of field in forms.
|
798 |
+
* @param string $value New value of field.
|
799 |
+
* @return boolean True if field exists, otherwise false.
|
800 |
+
* @access public
|
801 |
+
*/
|
802 |
+
function setFieldById($id, $value) {
|
803 |
+
return $this->_page->setField(new SimpleById($id), $value);
|
804 |
+
}
|
805 |
+
|
806 |
+
/**
|
807 |
+
* Accessor for a form element value within the page.
|
808 |
+
* Finds the first match.
|
809 |
+
* @param string $label Field label.
|
810 |
+
* @return string/boolean A value if the field is
|
811 |
+
* present, false if unchecked
|
812 |
+
* and null if missing.
|
813 |
+
* @access public
|
814 |
+
*/
|
815 |
+
function getField($label) {
|
816 |
+
return $this->_page->getField(new SimpleByLabelOrName($label));
|
817 |
+
}
|
818 |
+
|
819 |
+
/**
|
820 |
+
* Accessor for a form element value within the page.
|
821 |
+
* Finds the first match.
|
822 |
+
* @param string $name Field name.
|
823 |
+
* @return string/boolean A string if the field is
|
824 |
+
* present, false if unchecked
|
825 |
+
* and null if missing.
|
826 |
+
* @access public
|
827 |
+
*/
|
828 |
+
function getFieldByName($name) {
|
829 |
+
return $this->_page->getField(new SimpleByName($name));
|
830 |
+
}
|
831 |
+
|
832 |
+
/**
|
833 |
+
* Accessor for a form element value within the page.
|
834 |
+
* @param string/integer $id Id of field in forms.
|
835 |
+
* @return string/boolean A string if the field is
|
836 |
+
* present, false if unchecked
|
837 |
+
* and null if missing.
|
838 |
+
* @access public
|
839 |
+
*/
|
840 |
+
function getFieldById($id) {
|
841 |
+
return $this->_page->getField(new SimpleById($id));
|
842 |
+
}
|
843 |
+
|
844 |
+
/**
|
845 |
+
* Clicks the submit button by label. The owning
|
846 |
+
* form will be submitted by this.
|
847 |
+
* @param string $label Button label. An unlabeled
|
848 |
+
* button can be triggered by 'Submit'.
|
849 |
+
* @param hash $additional Additional form data.
|
850 |
+
* @return string/boolean Page on success.
|
851 |
+
* @access public
|
852 |
+
*/
|
853 |
+
function clickSubmit($label = 'Submit', $additional = false) {
|
854 |
+
if (! ($form = &$this->_page->getFormBySubmit(new SimpleByLabel($label)))) {
|
855 |
+
return false;
|
856 |
+
}
|
857 |
+
$success = $this->_load(
|
858 |
+
$form->getAction(),
|
859 |
+
$form->submitButton(new SimpleByLabel($label), $additional));
|
860 |
+
return ($success ? $this->getContent() : $success);
|
861 |
+
}
|
862 |
+
|
863 |
+
/**
|
864 |
+
* Clicks the submit button by name attribute. The owning
|
865 |
+
* form will be submitted by this.
|
866 |
+
* @param string $name Button name.
|
867 |
+
* @param hash $additional Additional form data.
|
868 |
+
* @return string/boolean Page on success.
|
869 |
+
* @access public
|
870 |
+
*/
|
871 |
+
function clickSubmitByName($name, $additional = false) {
|
872 |
+
if (! ($form = &$this->_page->getFormBySubmit(new SimpleByName($name)))) {
|
873 |
+
return false;
|
874 |
+
}
|
875 |
+
$success = $this->_load(
|
876 |
+
$form->getAction(),
|
877 |
+
$form->submitButton(new SimpleByName($name), $additional));
|
878 |
+
return ($success ? $this->getContent() : $success);
|
879 |
+
}
|
880 |
+
|
881 |
+
/**
|
882 |
+
* Clicks the submit button by ID attribute of the button
|
883 |
+
* itself. The owning form will be submitted by this.
|
884 |
+
* @param string $id Button ID.
|
885 |
+
* @param hash $additional Additional form data.
|
886 |
+
* @return string/boolean Page on success.
|
887 |
+
* @access public
|
888 |
+
*/
|
889 |
+
function clickSubmitById($id, $additional = false) {
|
890 |
+
if (! ($form = &$this->_page->getFormBySubmit(new SimpleById($id)))) {
|
891 |
+
return false;
|
892 |
+
}
|
893 |
+
$success = $this->_load(
|
894 |
+
$form->getAction(),
|
895 |
+
$form->submitButton(new SimpleById($id), $additional));
|
896 |
+
return ($success ? $this->getContent() : $success);
|
897 |
+
}
|
898 |
+
|
899 |
+
/**
|
900 |
+
* Tests to see if a submit button exists with this
|
901 |
+
* label.
|
902 |
+
* @param string $label Button label.
|
903 |
+
* @return boolean True if present.
|
904 |
+
* @access public
|
905 |
+
*/
|
906 |
+
function isSubmit($label) {
|
907 |
+
return (boolean)$this->_page->getFormBySubmit(new SimpleByLabel($label));
|
908 |
+
}
|
909 |
+
|
910 |
+
/**
|
911 |
+
* Clicks the submit image by some kind of label. Usually
|
912 |
+
* the alt tag or the nearest equivalent. The owning
|
913 |
+
* form will be submitted by this. Clicking outside of
|
914 |
+
* the boundary of the coordinates will result in
|
915 |
+
* a failure.
|
916 |
+
* @param string $label ID attribute of button.
|
917 |
+
* @param integer $x X-coordinate of imaginary click.
|
918 |
+
* @param integer $y Y-coordinate of imaginary click.
|
919 |
+
* @param hash $additional Additional form data.
|
920 |
+
* @return string/boolean Page on success.
|
921 |
+
* @access public
|
922 |
+
*/
|
923 |
+
function clickImage($label, $x = 1, $y = 1, $additional = false) {
|
924 |
+
if (! ($form = &$this->_page->getFormByImage(new SimpleByLabel($label)))) {
|
925 |
+
return false;
|
926 |
+
}
|
927 |
+
$success = $this->_load(
|
928 |
+
$form->getAction(),
|
929 |
+
$form->submitImage(new SimpleByLabel($label), $x, $y, $additional));
|
930 |
+
return ($success ? $this->getContent() : $success);
|
931 |
+
}
|
932 |
+
|
933 |
+
/**
|
934 |
+
* Clicks the submit image by the name. Usually
|
935 |
+
* the alt tag or the nearest equivalent. The owning
|
936 |
+
* form will be submitted by this. Clicking outside of
|
937 |
+
* the boundary of the coordinates will result in
|
938 |
+
* a failure.
|
939 |
+
* @param string $name Name attribute of button.
|
940 |
+
* @param integer $x X-coordinate of imaginary click.
|
941 |
+
* @param integer $y Y-coordinate of imaginary click.
|
942 |
+
* @param hash $additional Additional form data.
|
943 |
+
* @return string/boolean Page on success.
|
944 |
+
* @access public
|
945 |
+
*/
|
946 |
+
function clickImageByName($name, $x = 1, $y = 1, $additional = false) {
|
947 |
+
if (! ($form = &$this->_page->getFormByImage(new SimpleByName($name)))) {
|
948 |
+
return false;
|
949 |
+
}
|
950 |
+
$success = $this->_load(
|
951 |
+
$form->getAction(),
|
952 |
+
$form->submitImage(new SimpleByName($name), $x, $y, $additional));
|
953 |
+
return ($success ? $this->getContent() : $success);
|
954 |
+
}
|
955 |
+
|
956 |
+
/**
|
957 |
+
* Clicks the submit image by ID attribute. The owning
|
958 |
+
* form will be submitted by this. Clicking outside of
|
959 |
+
* the boundary of the coordinates will result in
|
960 |
+
* a failure.
|
961 |
+
* @param integer/string $id ID attribute of button.
|
962 |
+
* @param integer $x X-coordinate of imaginary click.
|
963 |
+
* @param integer $y Y-coordinate of imaginary click.
|
964 |
+
* @param hash $additional Additional form data.
|
965 |
+
* @return string/boolean Page on success.
|
966 |
+
* @access public
|
967 |
+
*/
|
968 |
+
function clickImageById($id, $x = 1, $y = 1, $additional = false) {
|
969 |
+
if (! ($form = &$this->_page->getFormByImage(new SimpleById($id)))) {
|
970 |
+
return false;
|
971 |
+
}
|
972 |
+
$success = $this->_load(
|
973 |
+
$form->getAction(),
|
974 |
+
$form->submitImage(new SimpleById($id), $x, $y, $additional));
|
975 |
+
return ($success ? $this->getContent() : $success);
|
976 |
+
}
|
977 |
+
|
978 |
+
/**
|
979 |
+
* Tests to see if an image exists with this
|
980 |
+
* title or alt text.
|
981 |
+
* @param string $label Image text.
|
982 |
+
* @return boolean True if present.
|
983 |
+
* @access public
|
984 |
+
*/
|
985 |
+
function isImage($label) {
|
986 |
+
return (boolean)$this->_page->getFormByImage(new SimpleByLabel($label));
|
987 |
+
}
|
988 |
+
|
989 |
+
/**
|
990 |
+
* Submits a form by the ID.
|
991 |
+
* @param string $id The form ID. No submit button value
|
992 |
+
* will be sent.
|
993 |
+
* @return string/boolean Page on success.
|
994 |
+
* @access public
|
995 |
+
*/
|
996 |
+
function submitFormById($id) {
|
997 |
+
if (! ($form = &$this->_page->getFormById($id))) {
|
998 |
+
return false;
|
999 |
+
}
|
1000 |
+
$success = $this->_load(
|
1001 |
+
$form->getAction(),
|
1002 |
+
$form->submit());
|
1003 |
+
return ($success ? $this->getContent() : $success);
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
/**
|
1007 |
+
* Finds a URL by label. Will find the first link
|
1008 |
+
* found with this link text by default, or a later
|
1009 |
+
* one if an index is given. The match ignores case and
|
1010 |
+
* white space issues.
|
1011 |
+
* @param string $label Text between the anchor tags.
|
1012 |
+
* @param integer $index Link position counting from zero.
|
1013 |
+
* @return string/boolean URL on success.
|
1014 |
+
* @access public
|
1015 |
+
*/
|
1016 |
+
function getLink($label, $index = 0) {
|
1017 |
+
$urls = $this->_page->getUrlsByLabel($label);
|
1018 |
+
if (count($urls) == 0) {
|
1019 |
+
return false;
|
1020 |
+
}
|
1021 |
+
if (count($urls) < $index + 1) {
|
1022 |
+
return false;
|
1023 |
+
}
|
1024 |
+
return $urls[$index];
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
/**
|
1028 |
+
* Follows a link by label. Will click the first link
|
1029 |
+
* found with this link text by default, or a later
|
1030 |
+
* one if an index is given. The match ignores case and
|
1031 |
+
* white space issues.
|
1032 |
+
* @param string $label Text between the anchor tags.
|
1033 |
+
* @param integer $index Link position counting from zero.
|
1034 |
+
* @return string/boolean Page on success.
|
1035 |
+
* @access public
|
1036 |
+
*/
|
1037 |
+
function clickLink($label, $index = 0) {
|
1038 |
+
$url = $this->getLink($label, $index);
|
1039 |
+
if ($url === false) {
|
1040 |
+
return false;
|
1041 |
+
}
|
1042 |
+
$this->_load($url, new SimpleGetEncoding());
|
1043 |
+
return $this->getContent();
|
1044 |
+
}
|
1045 |
+
|
1046 |
+
/**
|
1047 |
+
* Finds a link by id attribute.
|
1048 |
+
* @param string $id ID attribute value.
|
1049 |
+
* @return string/boolean URL on success.
|
1050 |
+
* @access public
|
1051 |
+
*/
|
1052 |
+
function getLinkById($id) {
|
1053 |
+
return $this->_page->getUrlById($id);
|
1054 |
+
}
|
1055 |
+
|
1056 |
+
/**
|
1057 |
+
* Follows a link by id attribute.
|
1058 |
+
* @param string $id ID attribute value.
|
1059 |
+
* @return string/boolean Page on success.
|
1060 |
+
* @access public
|
1061 |
+
*/
|
1062 |
+
function clickLinkById($id) {
|
1063 |
+
if (! ($url = $this->getLinkById($id))) {
|
1064 |
+
return false;
|
1065 |
+
}
|
1066 |
+
$this->_load($url, new SimpleGetEncoding());
|
1067 |
+
return $this->getContent();
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
/**
|
1071 |
+
* Clicks a visible text item. Will first try buttons,
|
1072 |
+
* then links and then images.
|
1073 |
+
* @param string $label Visible text or alt text.
|
1074 |
+
* @return string/boolean Raw page or false.
|
1075 |
+
* @access public
|
1076 |
+
*/
|
1077 |
+
function click($label) {
|
1078 |
+
$raw = $this->clickSubmit($label);
|
1079 |
+
if (! $raw) {
|
1080 |
+
$raw = $this->clickLink($label);
|
1081 |
+
}
|
1082 |
+
if (! $raw) {
|
1083 |
+
$raw = $this->clickImage($label);
|
1084 |
+
}
|
1085 |
+
return $raw;
|
1086 |
+
}
|
1087 |
+
|
1088 |
+
/**
|
1089 |
+
* Tests to see if a click target exists.
|
1090 |
+
* @param string $label Visible text or alt text.
|
1091 |
+
* @return boolean True if target present.
|
1092 |
+
* @access public
|
1093 |
+
*/
|
1094 |
+
function isClickable($label) {
|
1095 |
+
return $this->isSubmit($label) || ($this->getLink($label) !== false) || $this->isImage($label);
|
1096 |
+
}
|
1097 |
+
}
|
1098 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/collector.php
ADDED
@@ -0,0 +1,122 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This file contains the following classes: {@link SimpleCollector},
|
4 |
+
* {@link SimplePatternCollector}.
|
5 |
+
*
|
6 |
+
* @author Travis Swicegood <development@domain51.com>
|
7 |
+
* @package SimpleTest
|
8 |
+
* @subpackage UnitTester
|
9 |
+
* @version $Id: collector.php 1723 2008-04-08 00:34:10Z lastcraft $
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* The basic collector for {@link GroupTest}
|
14 |
+
*
|
15 |
+
* @see collect(), GroupTest::collect()
|
16 |
+
* @package SimpleTest
|
17 |
+
* @subpackage UnitTester
|
18 |
+
*/
|
19 |
+
class SimpleCollector {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Strips off any kind of slash at the end so as to normalise the path.
|
23 |
+
* @param string $path Path to normalise.
|
24 |
+
* @return string Path without trailing slash.
|
25 |
+
*/
|
26 |
+
function _removeTrailingSlash($path) {
|
27 |
+
if (substr($path, -1) == DIRECTORY_SEPARATOR) {
|
28 |
+
return substr($path, 0, -1);
|
29 |
+
} elseif (substr($path, -1) == '/') {
|
30 |
+
return substr($path, 0, -1);
|
31 |
+
} else {
|
32 |
+
return $path;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Scans the directory and adds what it can.
|
38 |
+
* @param object $test Group test with {@link GroupTest::addTestFile()} method.
|
39 |
+
* @param string $path Directory to scan.
|
40 |
+
* @see _attemptToAdd()
|
41 |
+
*/
|
42 |
+
function collect(&$test, $path) {
|
43 |
+
$path = $this->_removeTrailingSlash($path);
|
44 |
+
if ($handle = opendir($path)) {
|
45 |
+
while (($entry = readdir($handle)) !== false) {
|
46 |
+
if ($this->_isHidden($entry)) {
|
47 |
+
continue;
|
48 |
+
}
|
49 |
+
$this->_handle($test, $path . DIRECTORY_SEPARATOR . $entry);
|
50 |
+
}
|
51 |
+
closedir($handle);
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* This method determines what should be done with a given file and adds
|
57 |
+
* it via {@link GroupTest::addTestFile()} if necessary.
|
58 |
+
*
|
59 |
+
* This method should be overriden to provide custom matching criteria,
|
60 |
+
* such as pattern matching, recursive matching, etc. For an example, see
|
61 |
+
* {@link SimplePatternCollector::_handle()}.
|
62 |
+
*
|
63 |
+
* @param object $test Group test with {@link GroupTest::addTestFile()} method.
|
64 |
+
* @param string $filename A filename as generated by {@link collect()}
|
65 |
+
* @see collect()
|
66 |
+
* @access protected
|
67 |
+
*/
|
68 |
+
function _handle(&$test, $file) {
|
69 |
+
if (is_dir($file)) {
|
70 |
+
return;
|
71 |
+
}
|
72 |
+
$test->addTestFile($file);
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Tests for hidden files so as to skip them. Currently
|
77 |
+
* only tests for Unix hidden files.
|
78 |
+
* @param string $filename Plain filename.
|
79 |
+
* @return boolean True if hidden file.
|
80 |
+
* @access private
|
81 |
+
*/
|
82 |
+
function _isHidden($filename) {
|
83 |
+
return strncmp($filename, '.', 1) == 0;
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* An extension to {@link SimpleCollector} that only adds files matching a
|
89 |
+
* given pattern.
|
90 |
+
*
|
91 |
+
* @package SimpleTest
|
92 |
+
* @subpackage UnitTester
|
93 |
+
* @see SimpleCollector
|
94 |
+
*/
|
95 |
+
class SimplePatternCollector extends SimpleCollector {
|
96 |
+
var $_pattern;
|
97 |
+
|
98 |
+
/**
|
99 |
+
*
|
100 |
+
* @param string $pattern Perl compatible regex to test name against
|
101 |
+
* See {@link http://us4.php.net/manual/en/reference.pcre.pattern.syntax.php PHP's PCRE}
|
102 |
+
* for full documentation of valid pattern.s
|
103 |
+
*/
|
104 |
+
function SimplePatternCollector($pattern = '/php$/i') {
|
105 |
+
$this->_pattern = $pattern;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Attempts to add files that match a given pattern.
|
110 |
+
*
|
111 |
+
* @see SimpleCollector::_handle()
|
112 |
+
* @param object $test Group test with {@link GroupTest::addTestFile()} method.
|
113 |
+
* @param string $path Directory to scan.
|
114 |
+
* @access protected
|
115 |
+
*/
|
116 |
+
function _handle(&$test, $filename) {
|
117 |
+
if (preg_match($this->_pattern, $filename)) {
|
118 |
+
parent::_handle($test, $filename);
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/compatibility.php
ADDED
@@ -0,0 +1,173 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* base include file for SimpleTest
|
4 |
+
* @package SimpleTest
|
5 |
+
* @version $Id: compatibility.php 1723 2008-04-08 00:34:10Z lastcraft $
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Static methods for compatibility between different
|
10 |
+
* PHP versions.
|
11 |
+
* @package SimpleTest
|
12 |
+
*/
|
13 |
+
class SimpleTestCompatibility {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Creates a copy whether in PHP5 or PHP4.
|
17 |
+
* @param object $object Thing to copy.
|
18 |
+
* @return object A copy.
|
19 |
+
* @access public
|
20 |
+
* @static
|
21 |
+
*/
|
22 |
+
function copy($object) {
|
23 |
+
if (version_compare(phpversion(), '5') >= 0) {
|
24 |
+
eval('$copy = clone $object;');
|
25 |
+
return $copy;
|
26 |
+
}
|
27 |
+
return $object;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Identity test. Drops back to equality + types for PHP5
|
32 |
+
* objects as the === operator counts as the
|
33 |
+
* stronger reference constraint.
|
34 |
+
* @param mixed $first Test subject.
|
35 |
+
* @param mixed $second Comparison object.
|
36 |
+
* @return boolean True if identical.
|
37 |
+
* @access public
|
38 |
+
* @static
|
39 |
+
*/
|
40 |
+
function isIdentical($first, $second) {
|
41 |
+
if (version_compare(phpversion(), '5') >= 0) {
|
42 |
+
return SimpleTestCompatibility::_isIdenticalType($first, $second);
|
43 |
+
}
|
44 |
+
if ($first != $second) {
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
return ($first === $second);
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Recursive type test.
|
52 |
+
* @param mixed $first Test subject.
|
53 |
+
* @param mixed $second Comparison object.
|
54 |
+
* @return boolean True if same type.
|
55 |
+
* @access private
|
56 |
+
* @static
|
57 |
+
*/
|
58 |
+
function _isIdenticalType($first, $second) {
|
59 |
+
if (gettype($first) != gettype($second)) {
|
60 |
+
return false;
|
61 |
+
}
|
62 |
+
if (is_object($first) && is_object($second)) {
|
63 |
+
if (get_class($first) != get_class($second)) {
|
64 |
+
return false;
|
65 |
+
}
|
66 |
+
return SimpleTestCompatibility::_isArrayOfIdenticalTypes(
|
67 |
+
get_object_vars($first),
|
68 |
+
get_object_vars($second));
|
69 |
+
}
|
70 |
+
if (is_array($first) && is_array($second)) {
|
71 |
+
return SimpleTestCompatibility::_isArrayOfIdenticalTypes($first, $second);
|
72 |
+
}
|
73 |
+
if ($first !== $second) {
|
74 |
+
return false;
|
75 |
+
}
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Recursive type test for each element of an array.
|
81 |
+
* @param mixed $first Test subject.
|
82 |
+
* @param mixed $second Comparison object.
|
83 |
+
* @return boolean True if identical.
|
84 |
+
* @access private
|
85 |
+
* @static
|
86 |
+
*/
|
87 |
+
function _isArrayOfIdenticalTypes($first, $second) {
|
88 |
+
if (array_keys($first) != array_keys($second)) {
|
89 |
+
return false;
|
90 |
+
}
|
91 |
+
foreach (array_keys($first) as $key) {
|
92 |
+
$is_identical = SimpleTestCompatibility::_isIdenticalType(
|
93 |
+
$first[$key],
|
94 |
+
$second[$key]);
|
95 |
+
if (! $is_identical) {
|
96 |
+
return false;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
return true;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Test for two variables being aliases.
|
104 |
+
* @param mixed $first Test subject.
|
105 |
+
* @param mixed $second Comparison object.
|
106 |
+
* @return boolean True if same.
|
107 |
+
* @access public
|
108 |
+
* @static
|
109 |
+
*/
|
110 |
+
function isReference(&$first, &$second) {
|
111 |
+
if (version_compare(phpversion(), '5', '>=') && is_object($first)) {
|
112 |
+
return ($first === $second);
|
113 |
+
}
|
114 |
+
if (is_object($first) && is_object($second)) {
|
115 |
+
$id = uniqid("test");
|
116 |
+
$first->$id = true;
|
117 |
+
$is_ref = isset($second->$id);
|
118 |
+
unset($first->$id);
|
119 |
+
return $is_ref;
|
120 |
+
}
|
121 |
+
$temp = $first;
|
122 |
+
$first = uniqid("test");
|
123 |
+
$is_ref = ($first === $second);
|
124 |
+
$first = $temp;
|
125 |
+
return $is_ref;
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Test to see if an object is a member of a
|
130 |
+
* class hiearchy.
|
131 |
+
* @param object $object Object to test.
|
132 |
+
* @param string $class Root name of hiearchy.
|
133 |
+
* @return boolean True if class in hiearchy.
|
134 |
+
* @access public
|
135 |
+
* @static
|
136 |
+
*/
|
137 |
+
function isA($object, $class) {
|
138 |
+
if (version_compare(phpversion(), '5') >= 0) {
|
139 |
+
if (! class_exists($class, false)) {
|
140 |
+
if (function_exists('interface_exists')) {
|
141 |
+
if (! interface_exists($class, false)) {
|
142 |
+
return false;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
146 |
+
eval("\$is_a = \$object instanceof $class;");
|
147 |
+
return $is_a;
|
148 |
+
}
|
149 |
+
if (function_exists('is_a')) {
|
150 |
+
return is_a($object, $class);
|
151 |
+
}
|
152 |
+
return ((strtolower($class) == get_class($object))
|
153 |
+
or (is_subclass_of($object, $class)));
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Sets a socket timeout for each chunk.
|
158 |
+
* @param resource $handle Socket handle.
|
159 |
+
* @param integer $timeout Limit in seconds.
|
160 |
+
* @access public
|
161 |
+
* @static
|
162 |
+
*/
|
163 |
+
function setTimeout($handle, $timeout) {
|
164 |
+
if (function_exists('stream_set_timeout')) {
|
165 |
+
stream_set_timeout($handle, $timeout, 0);
|
166 |
+
} elseif (function_exists('socket_set_timeout')) {
|
167 |
+
socket_set_timeout($handle, $timeout, 0);
|
168 |
+
} elseif (function_exists('set_socket_timeout')) {
|
169 |
+
set_socket_timeout($handle, $timeout, 0);
|
170 |
+
}
|
171 |
+
}
|
172 |
+
}
|
173 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/cookies.php
ADDED
@@ -0,0 +1,380 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Base include file for SimpleTest
|
4 |
+
* @package SimpleTest
|
5 |
+
* @subpackage WebTester
|
6 |
+
* @version $Id: cookies.php 1723 2008-04-08 00:34:10Z lastcraft $
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**#@+
|
10 |
+
* include other SimpleTest class files
|
11 |
+
*/
|
12 |
+
require_once(dirname(__FILE__) . '/url.php');
|
13 |
+
/**#@-*/
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Cookie data holder. Cookie rules are full of pretty
|
17 |
+
* arbitary stuff. I have used...
|
18 |
+
* http://wp.netscape.com/newsref/std/cookie_spec.html
|
19 |
+
* http://www.cookiecentral.com/faq/
|
20 |
+
* @package SimpleTest
|
21 |
+
* @subpackage WebTester
|
22 |
+
*/
|
23 |
+
class SimpleCookie {
|
24 |
+
var $_host;
|
25 |
+
var $_name;
|
26 |
+
var $_value;
|
27 |
+
var $_path;
|
28 |
+
var $_expiry;
|
29 |
+
var $_is_secure;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Constructor. Sets the stored values.
|
33 |
+
* @param string $name Cookie key.
|
34 |
+
* @param string $value Value of cookie.
|
35 |
+
* @param string $path Cookie path if not host wide.
|
36 |
+
* @param string $expiry Expiry date as string.
|
37 |
+
* @param boolean $is_secure Currently ignored.
|
38 |
+
*/
|
39 |
+
function SimpleCookie($name, $value = false, $path = false, $expiry = false, $is_secure = false) {
|
40 |
+
$this->_host = false;
|
41 |
+
$this->_name = $name;
|
42 |
+
$this->_value = $value;
|
43 |
+
$this->_path = ($path ? $this->_fixPath($path) : "/");
|
44 |
+
$this->_expiry = false;
|
45 |
+
if (is_string($expiry)) {
|
46 |
+
$this->_expiry = strtotime($expiry);
|
47 |
+
} elseif (is_integer($expiry)) {
|
48 |
+
$this->_expiry = $expiry;
|
49 |
+
}
|
50 |
+
$this->_is_secure = $is_secure;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Sets the host. The cookie rules determine
|
55 |
+
* that the first two parts are taken for
|
56 |
+
* certain TLDs and three for others. If the
|
57 |
+
* new host does not match these rules then the
|
58 |
+
* call will fail.
|
59 |
+
* @param string $host New hostname.
|
60 |
+
* @return boolean True if hostname is valid.
|
61 |
+
* @access public
|
62 |
+
*/
|
63 |
+
function setHost($host) {
|
64 |
+
if ($host = $this->_truncateHost($host)) {
|
65 |
+
$this->_host = $host;
|
66 |
+
return true;
|
67 |
+
}
|
68 |
+
return false;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Accessor for the truncated host to which this
|
73 |
+
* cookie applies.
|
74 |
+
* @return string Truncated hostname.
|
75 |
+
* @access public
|
76 |
+
*/
|
77 |
+
function getHost() {
|
78 |
+
return $this->_host;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Test for a cookie being valid for a host name.
|
83 |
+
* @param string $host Host to test against.
|
84 |
+
* @return boolean True if the cookie would be valid
|
85 |
+
* here.
|
86 |
+
*/
|
87 |
+
function isValidHost($host) {
|
88 |
+
return ($this->_truncateHost($host) === $this->getHost());
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Extracts just the domain part that determines a
|
93 |
+
* cookie's host validity.
|
94 |
+
* @param string $host Host name to truncate.
|
95 |
+
* @return string Domain or false on a bad host.
|
96 |
+
* @access private
|
97 |
+
*/
|
98 |
+
function _truncateHost($host) {
|
99 |
+
$tlds = SimpleUrl::getAllTopLevelDomains();
|
100 |
+
if (preg_match('/[a-z\-]+\.(' . $tlds . ')$/i', $host, $matches)) {
|
101 |
+
return $matches[0];
|
102 |
+
} elseif (preg_match('/[a-z\-]+\.[a-z\-]+\.[a-z\-]+$/i', $host, $matches)) {
|
103 |
+
return $matches[0];
|
104 |
+
}
|
105 |
+
return false;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Accessor for name.
|
110 |
+
* @return string Cookie key.
|
111 |
+
* @access public
|
112 |
+
*/
|
113 |
+
function getName() {
|
114 |
+
return $this->_name;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Accessor for value. A deleted cookie will
|
119 |
+
* have an empty string for this.
|
120 |
+
* @return string Cookie value.
|
121 |
+
* @access public
|
122 |
+
*/
|
123 |
+
function getValue() {
|
124 |
+
return $this->_value;
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Accessor for path.
|
129 |
+
* @return string Valid cookie path.
|
130 |
+
* @access public
|
131 |
+
*/
|
132 |
+
function getPath() {
|
133 |
+
return $this->_path;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Tests a path to see if the cookie applies
|
138 |
+
* there. The test path must be longer or
|
139 |
+
* equal to the cookie path.
|
140 |
+
* @param string $path Path to test against.
|
141 |
+
* @return boolean True if cookie valid here.
|
142 |
+
* @access public
|
143 |
+
*/
|
144 |
+
function isValidPath($path) {
|
145 |
+
return (strncmp(
|
146 |
+
$this->_fixPath($path),
|
147 |
+
$this->getPath(),
|
148 |
+
strlen($this->getPath())) == 0);
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Accessor for expiry.
|
153 |
+
* @return string Expiry string.
|
154 |
+
* @access public
|
155 |
+
*/
|
156 |
+
function getExpiry() {
|
157 |
+
if (! $this->_expiry) {
|
158 |
+
return false;
|
159 |
+
}
|
160 |
+
return gmdate("D, d M Y H:i:s", $this->_expiry) . " GMT";
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Test to see if cookie is expired against
|
165 |
+
* the cookie format time or timestamp.
|
166 |
+
* Will give true for a session cookie.
|
167 |
+
* @param integer/string $now Time to test against. Result
|
168 |
+
* will be false if this time
|
169 |
+
* is later than the cookie expiry.
|
170 |
+
* Can be either a timestamp integer
|
171 |
+
* or a cookie format date.
|
172 |
+
* @access public
|
173 |
+
*/
|
174 |
+
function isExpired($now) {
|
175 |
+
if (! $this->_expiry) {
|
176 |
+
return true;
|
177 |
+
}
|
178 |
+
if (is_string($now)) {
|
179 |
+
$now = strtotime($now);
|
180 |
+
}
|
181 |
+
return ($this->_expiry < $now);
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Ages the cookie by the specified number of
|
186 |
+
* seconds.
|
187 |
+
* @param integer $interval In seconds.
|
188 |
+
* @public
|
189 |
+
*/
|
190 |
+
function agePrematurely($interval) {
|
191 |
+
if ($this->_expiry) {
|
192 |
+
$this->_expiry -= $interval;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Accessor for the secure flag.
|
198 |
+
* @return boolean True if cookie needs SSL.
|
199 |
+
* @access public
|
200 |
+
*/
|
201 |
+
function isSecure() {
|
202 |
+
return $this->_is_secure;
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Adds a trailing and leading slash to the path
|
207 |
+
* if missing.
|
208 |
+
* @param string $path Path to fix.
|
209 |
+
* @access private
|
210 |
+
*/
|
211 |
+
function _fixPath($path) {
|
212 |
+
if (substr($path, 0, 1) != '/') {
|
213 |
+
$path = '/' . $path;
|
214 |
+
}
|
215 |
+
if (substr($path, -1, 1) != '/') {
|
216 |
+
$path .= '/';
|
217 |
+
}
|
218 |
+
return $path;
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Repository for cookies. This stuff is a
|
224 |
+
* tiny bit browser dependent.
|
225 |
+
* @package SimpleTest
|
226 |
+
* @subpackage WebTester
|
227 |
+
*/
|
228 |
+
class SimpleCookieJar {
|
229 |
+
var $_cookies;
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Constructor. Jar starts empty.
|
233 |
+
* @access public
|
234 |
+
*/
|
235 |
+
function SimpleCookieJar() {
|
236 |
+
$this->_cookies = array();
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Removes expired and temporary cookies as if
|
241 |
+
* the browser was closed and re-opened.
|
242 |
+
* @param string/integer $now Time to test expiry against.
|
243 |
+
* @access public
|
244 |
+
*/
|
245 |
+
function restartSession($date = false) {
|
246 |
+
$surviving_cookies = array();
|
247 |
+
for ($i = 0; $i < count($this->_cookies); $i++) {
|
248 |
+
if (! $this->_cookies[$i]->getValue()) {
|
249 |
+
continue;
|
250 |
+
}
|
251 |
+
if (! $this->_cookies[$i]->getExpiry()) {
|
252 |
+
continue;
|
253 |
+
}
|
254 |
+
if ($date && $this->_cookies[$i]->isExpired($date)) {
|
255 |
+
continue;
|
256 |
+
}
|
257 |
+
$surviving_cookies[] = $this->_cookies[$i];
|
258 |
+
}
|
259 |
+
$this->_cookies = $surviving_cookies;
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Ages all cookies in the cookie jar.
|
264 |
+
* @param integer $interval The old session is moved
|
265 |
+
* into the past by this number
|
266 |
+
* of seconds. Cookies now over
|
267 |
+
* age will be removed.
|
268 |
+
* @access public
|
269 |
+
*/
|
270 |
+
function agePrematurely($interval) {
|
271 |
+
for ($i = 0; $i < count($this->_cookies); $i++) {
|
272 |
+
$this->_cookies[$i]->agePrematurely($interval);
|
273 |
+
}
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Sets an additional cookie. If a cookie has
|
278 |
+
* the same name and path it is replaced.
|
279 |
+
* @param string $name Cookie key.
|
280 |
+
* @param string $value Value of cookie.
|
281 |
+
* @param string $host Host upon which the cookie is valid.
|
282 |
+
* @param string $path Cookie path if not host wide.
|
283 |
+
* @param string $expiry Expiry date.
|
284 |
+
* @access public
|
285 |
+
*/
|
286 |
+
function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
|
287 |
+
$cookie = new SimpleCookie($name, $value, $path, $expiry);
|
288 |
+
if ($host) {
|
289 |
+
$cookie->setHost($host);
|
290 |
+
}
|
291 |
+
$this->_cookies[$this->_findFirstMatch($cookie)] = $cookie;
|
292 |
+
}
|
293 |
+
|
294 |
+
/**
|
295 |
+
* Finds a matching cookie to write over or the
|
296 |
+
* first empty slot if none.
|
297 |
+
* @param SimpleCookie $cookie Cookie to write into jar.
|
298 |
+
* @return integer Available slot.
|
299 |
+
* @access private
|
300 |
+
*/
|
301 |
+
function _findFirstMatch($cookie) {
|
302 |
+
for ($i = 0; $i < count($this->_cookies); $i++) {
|
303 |
+
$is_match = $this->_isMatch(
|
304 |
+
$cookie,
|
305 |
+
$this->_cookies[$i]->getHost(),
|
306 |
+
$this->_cookies[$i]->getPath(),
|
307 |
+
$this->_cookies[$i]->getName());
|
308 |
+
if ($is_match) {
|
309 |
+
return $i;
|
310 |
+
}
|
311 |
+
}
|
312 |
+
return count($this->_cookies);
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* Reads the most specific cookie value from the
|
317 |
+
* browser cookies. Looks for the longest path that
|
318 |
+
* matches.
|
319 |
+
* @param string $host Host to search.
|
320 |
+
* @param string $path Applicable path.
|
321 |
+
* @param string $name Name of cookie to read.
|
322 |
+
* @return string False if not present, else the
|
323 |
+
* value as a string.
|
324 |
+
* @access public
|
325 |
+
*/
|
326 |
+
function getCookieValue($host, $path, $name) {
|
327 |
+
$longest_path = '';
|
328 |
+
foreach ($this->_cookies as $cookie) {
|
329 |
+
if ($this->_isMatch($cookie, $host, $path, $name)) {
|
330 |
+
if (strlen($cookie->getPath()) > strlen($longest_path)) {
|
331 |
+
$value = $cookie->getValue();
|
332 |
+
$longest_path = $cookie->getPath();
|
333 |
+
}
|
334 |
+
}
|
335 |
+
}
|
336 |
+
return (isset($value) ? $value : false);
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Tests cookie for matching against search
|
341 |
+
* criteria.
|
342 |
+
* @param SimpleTest $cookie Cookie to test.
|
343 |
+
* @param string $host Host must match.
|
344 |
+
* @param string $path Cookie path must be shorter than
|
345 |
+
* this path.
|
346 |
+
* @param string $name Name must match.
|
347 |
+
* @return boolean True if matched.
|
348 |
+
* @access private
|
349 |
+
*/
|
350 |
+
function _isMatch($cookie, $host, $path, $name) {
|
351 |
+
if ($cookie->getName() != $name) {
|
352 |
+
return false;
|
353 |
+
}
|
354 |
+
if ($host && $cookie->getHost() && ! $cookie->isValidHost($host)) {
|
355 |
+
return false;
|
356 |
+
}
|
357 |
+
if (! $cookie->isValidPath($path)) {
|
358 |
+
return false;
|
359 |
+
}
|
360 |
+
return true;
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Uses a URL to sift relevant cookies by host and
|
365 |
+
* path. Results are list of strings of form "name=value".
|
366 |
+
* @param SimpleUrl $url Url to select by.
|
367 |
+
* @return array Valid name and value pairs.
|
368 |
+
* @access public
|
369 |
+
*/
|
370 |
+
function selectAsPairs($url) {
|
371 |
+
$pairs = array();
|
372 |
+
foreach ($this->_cookies as $cookie) {
|
373 |
+
if ($this->_isMatch($cookie, $url->getHost(), $url->getPath(), $cookie->getName())) {
|
374 |
+
$pairs[] = $cookie->getName() . '=' . $cookie->getValue();
|
375 |
+
}
|
376 |
+
}
|
377 |
+
return $pairs;
|
378 |
+
}
|
379 |
+
}
|
380 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/default_reporter.php
ADDED
@@ -0,0 +1,133 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Optional include file for SimpleTest
|
4 |
+
* @package SimpleTest
|
5 |
+
* @subpackage UnitTester
|
6 |
+
* @version $Id: default_reporter.php 1704 2008-03-25 00:47:04Z lastcraft $
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**#@+
|
10 |
+
* include other SimpleTest class files
|
11 |
+
*/
|
12 |
+
require_once(dirname(__FILE__) . '/simpletest.php');
|
13 |
+
require_once(dirname(__FILE__) . '/scorer.php');
|
14 |
+
require_once(dirname(__FILE__) . '/reporter.php');
|
15 |
+
require_once(dirname(__FILE__) . '/xml.php');
|
16 |
+
/**#@-*/
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Parser for command line arguments. Extracts
|
20 |
+
* the a specific test to run and engages XML
|
21 |
+
* reporting when necessary.
|
22 |
+
* @package SimpleTest
|
23 |
+
* @subpackage UnitTester
|
24 |
+
*/
|
25 |
+
class SimpleCommandLineParser {
|
26 |
+
var $_to_property = array(
|
27 |
+
'case' => '_case', 'c' => '_case',
|
28 |
+
'test' => '_test', 't' => '_test',
|
29 |
+
'xml' => '_xml', 'x' => '_xml');
|
30 |
+
var $_case = '';
|
31 |
+
var $_test = '';
|
32 |
+
var $_xml = false;
|
33 |
+
var $_no_skips = false;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Parses raw command line arguments into object properties.
|
37 |
+
* @param string $arguments Raw commend line arguments.
|
38 |
+
*/
|
39 |
+
function SimpleCommandLineParser($arguments) {
|
40 |
+
if (! is_array($arguments)) {
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
foreach ($arguments as $i => $argument) {
|
44 |
+
if (preg_match('/^--?(test|case|t|c)=(.+)$/', $argument, $matches)) {
|
45 |
+
$property = $this->_to_property[$matches[1]];
|
46 |
+
$this->$property = $matches[2];
|
47 |
+
} elseif (preg_match('/^--?(test|case|t|c)$/', $argument, $matches)) {
|
48 |
+
$property = $this->_to_property[$matches[1]];
|
49 |
+
if (isset($arguments[$i + 1])) {
|
50 |
+
$this->$property = $arguments[$i + 1];
|
51 |
+
}
|
52 |
+
} elseif (preg_match('/^--?(xml|x)$/', $argument)) {
|
53 |
+
$this->_xml = true;
|
54 |
+
} elseif (preg_match('/^--?(no-skip|no-skips|s)$/', $argument)) {
|
55 |
+
$this->_no_skips = true;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Run only this test.
|
62 |
+
* @return string Test name to run.
|
63 |
+
* @access public
|
64 |
+
*/
|
65 |
+
function getTest() {
|
66 |
+
return $this->_test;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Run only this test suite.
|
71 |
+
* @return string Test class name to run.
|
72 |
+
* @access public
|
73 |
+
*/
|
74 |
+
function getTestCase() {
|
75 |
+
return $this->_case;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Output should be XML or not.
|
80 |
+
* @return boolean True if XML desired.
|
81 |
+
* @access public
|
82 |
+
*/
|
83 |
+
function isXml() {
|
84 |
+
return $this->_xml;
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Output should suppress skip messages.
|
89 |
+
* @return boolean True for no skips.
|
90 |
+
* @access public
|
91 |
+
*/
|
92 |
+
function noSkips() {
|
93 |
+
return $this->_no_skips;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* The default reporter used by SimpleTest's autorun
|
99 |
+
* feature. The actual reporters used are dependency
|
100 |
+
* injected and can be overridden.
|
101 |
+
* @package SimpleTest
|
102 |
+
* @subpackage UnitTester
|
103 |
+
*/
|
104 |
+
class DefaultReporter extends SimpleReporterDecorator {
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Assembles the appopriate reporter for the environment.
|
108 |
+
*/
|
109 |
+
function DefaultReporter() {
|
110 |
+
if (SimpleReporter::inCli()) {
|
111 |
+
global $argv;
|
112 |
+
$parser = new SimpleCommandLineParser($argv);
|
113 |
+
$interfaces = $parser->isXml() ? array('XmlReporter') : array('TextReporter');
|
114 |
+
$reporter = &new SelectiveReporter(
|
115 |
+
SimpleTest::preferred($interfaces),
|
116 |
+
$parser->getTestCase(),
|
117 |
+
$parser->getTest());
|
118 |
+
if ($parser->noSkips()) {
|
119 |
+
$reporter = &new NoSkipsReporter($reporter);
|
120 |
+
}
|
121 |
+
} else {
|
122 |
+
$reporter = &new SelectiveReporter(
|
123 |
+
SimpleTest::preferred('HtmlReporter'),
|
124 |
+
@$_GET['c'],
|
125 |
+
@$_GET['t']);
|
126 |
+
if (@$_GET['skips'] == 'no' || @$_GET['show-skips'] == 'no') {
|
127 |
+
$reporter = &new NoSkipsReporter($reporter);
|
128 |
+
}
|
129 |
+
}
|
130 |
+
$this->SimpleReporterDecorator($reporter);
|
131 |
+
}
|
132 |
+
}
|
133 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/detached.php
ADDED
@@ -0,0 +1,96 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* base include file for SimpleTest
|
4 |
+
* @package SimpleTest
|
5 |
+
* @subpackage UnitTester
|
6 |
+
* @version $Id: detached.php 1723 2008-04-08 00:34:10Z lastcraft $
|
7 |
+
*/
|
8 |
+
|
9 |
+
/**#@+
|
10 |
+
* include other SimpleTest class files
|
11 |
+
*/
|
12 |
+
require_once(dirname(__FILE__) . '/xml.php');
|
13 |
+
require_once(dirname(__FILE__) . '/shell_tester.php');
|
14 |
+
/**#@-*/
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Runs an XML formated test in a separate process.
|
18 |
+
* @package SimpleTest
|
19 |
+
* @subpackage UnitTester
|
20 |
+
*/
|
21 |
+
class DetachedTestCase {
|
22 |
+
var $_command;
|
23 |
+
var $_dry_command;
|
24 |
+
var $_size;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Sets the location of the remote test.
|
28 |
+
* @param string $command Test script.
|
29 |
+
* @param string $dry_command Script for dry run.
|
30 |
+
* @access public
|
31 |
+
*/
|
32 |
+
function DetachedTestCase($command, $dry_command = false) {
|
33 |
+
$this->_command = $command;
|
34 |
+
$this->_dry_command = $dry_command ? $dry_command : $command;
|
35 |
+
$this->_size = false;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Accessor for the test name for subclasses.
|
40 |
+
* @return string Name of the test.
|
41 |
+
* @access public
|
42 |
+
*/
|
43 |
+
function getLabel() {
|
44 |
+
return $this->_command;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Runs the top level test for this class. Currently
|
49 |
+
* reads the data as a single chunk. I'll fix this
|
50 |
+
* once I have added iteration to the browser.
|
51 |
+
* @param SimpleReporter $reporter Target of test results.
|
52 |
+
* @returns boolean True if no failures.
|
53 |
+
* @access public
|
54 |
+
*/
|
55 |
+
function run(&$reporter) {
|
56 |
+
$shell = &new SimpleShell();
|
57 |
+
$shell->execute($this->_command);
|
58 |
+
$parser = &$this->_createParser($reporter);
|
59 |
+
if (! $parser->parse($shell->getOutput())) {
|
60 |
+
trigger_error('Cannot parse incoming XML from [' . $this->_command . ']');
|
61 |
+
return false;
|
62 |
+
}
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Accessor for the number of subtests.
|
68 |
+
* @return integer Number of test cases.
|
69 |
+
* @access public
|
70 |
+
*/
|
71 |
+
function getSize() {
|
72 |
+
if ($this->_size === false) {
|
73 |
+
$shell = &new SimpleShell();
|
74 |
+
$shell->execute($this->_dry_command);
|
75 |
+
$reporter = &new SimpleReporter();
|
76 |
+
$parser = &$this->_createParser($reporter);
|
77 |
+
if (! $parser->parse($shell->getOutput())) {
|
78 |
+
trigger_error('Cannot parse incoming XML from [' . $this->_dry_command . ']');
|
79 |
+
return false;
|
80 |
+
}
|
81 |
+
$this->_size = $reporter->getTestCaseCount();
|
82 |
+
}
|
83 |
+
return $this->_size;
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Creates the XML parser.
|
88 |
+
* @param SimpleReporter $reporter Target of test results.
|
89 |
+
* @return SimpleTestXmlListener XML reader.
|
90 |
+
* @access protected
|
91 |
+
*/
|
92 |
+
function &_createParser(&$reporter) {
|
93 |
+
return new SimpleTestXmlParser($reporter);
|
94 |
+
}
|
95 |
+
}
|
96 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/docs/en/docs.css
ADDED
@@ -0,0 +1,121 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
body {
|
2 |
+
padding-left: 3%;
|
3 |
+
padding-right: 3%;
|
4 |
+
}
|
5 |
+
h1, h2, h3 {
|
6 |
+
font-family: sans-serif;
|
7 |
+
}
|
8 |
+
h1 {
|
9 |
+
text-align: center;
|
10 |
+
}
|
11 |
+
pre {
|
12 |
+
font-family: "courier new", courier, typewriter, monospace;
|
13 |
+
font-size: 90%;
|
14 |
+
border: 1px solid;
|
15 |
+
border-color: #999966;
|
16 |
+
background-color: #ffffcc;
|
17 |
+
padding: 5px;
|
18 |
+
margin-left: 20px;
|
19 |
+
margin-right: 40px;
|
20 |
+
}
|
21 |
+
.code, .new_code, pre.new_code {
|
22 |
+
font-family: "courier new", courier, typewriter, monospace;
|
23 |
+
font-weight: bold;
|
24 |
+
}
|
25 |
+
div.copyright {
|
26 |
+
font-size: 80%;
|
27 |
+
color: gray;
|
28 |
+
}
|
29 |
+
div.copyright a {
|
30 |
+
margin-top: 1em;
|
31 |
+
color: gray;
|
32 |
+
}
|
33 |
+
ul.api {
|
34 |
+
border: 2px outset;
|
35 |
+
border-color: gray;
|
36 |
+
background-color: white;
|
37 |
+
margin: 5px;
|
38 |
+
margin-left: 5%;
|
39 |
+
margin-right: 5%;
|
40 |
+
}
|
41 |
+
ul.api li {
|
42 |
+
margin-top: 0.2em;
|
43 |
+
margin-bottom: 0.2em;
|
44 |
+
list-style: none;
|
45 |
+
text-indent: -3em;
|
46 |
+
padding-left: 1em;
|
47 |
+
}
|
48 |
+
div.demo {
|
49 |
+
border: 4px ridge;
|
50 |
+
border-color: gray;
|
51 |
+
padding: 10px;
|
52 |
+
margin: 5px;
|
53 |
+
margin-left: 20px;
|
54 |
+
margin-right: 40px;
|
55 |
+
background-color: white;
|
56 |
+
}
|
57 |
+
div.demo span.fail {
|
58 |
+
color: red;
|
59 |
+
}
|
60 |
+
div.demo span.pass {
|
61 |
+
color: green;
|
62 |
+
}
|
63 |
+
div.demo h1 {
|
64 |
+
font-size: 12pt;
|
65 |
+
text-align: left;
|
66 |
+
font-weight: bold;
|
67 |
+
}
|
68 |
+
div.menu {
|
69 |
+
text-align: center;
|
70 |
+
}
|
71 |
+
table {
|
72 |
+
border: 2px outset;
|
73 |
+
border-color: gray;
|
74 |
+
background-color: white;
|
75 |
+
margin: 5px;
|
76 |
+
margin-left: 5%;
|
77 |
+
margin-right: 5%;
|
78 |
+
}
|
79 |
+
td {
|
80 |
+
font-size: 90%;
|
81 |
+
}
|
82 |
+
.shell {
|
83 |
+
color: white;
|
84 |
+
}
|
85 |
+
pre.shell {
|
86 |
+
border: 4px ridge;
|
87 |
+
border-color: gray;
|
88 |
+
padding: 10px;
|
89 |
+
margin: 5px;
|
90 |
+
margin-left: 20px;
|
91 |
+
margin-right: 40px;
|
92 |
+
background-color: #000100;
|
93 |
+
color: #99ff99;
|
94 |
+
font-size: 90%;
|
95 |
+
}
|
96 |
+
pre.file {
|
97 |
+
color: black;
|
98 |
+
border: 1px solid;
|
99 |
+
border-color: black;
|
100 |
+
padding: 10px;
|
101 |
+
margin: 5px;
|
102 |
+
margin-left: 20px;
|
103 |
+
margin-right: 40px;
|
104 |
+
background-color: white;
|
105 |
+
font-size: 90%;
|
106 |
+
}
|
107 |
+
form.demo {
|
108 |
+
background-color: lightgray;
|
109 |
+
border: 4px outset;
|
110 |
+
border-color: lightgray;
|
111 |
+
padding: 10px;
|
112 |
+
margin-right: 40%;
|
113 |
+
}
|
114 |
+
dl, dd {
|
115 |
+
margin: 10px;
|
116 |
+
margin-left: 30px;
|
117 |
+
}
|
118 |
+
em {
|
119 |
+
font-weight: bold;
|
120 |
+
font-family: "courier new", courier, typewriter, monospace;
|
121 |
+
}
|
lib/Minify/min_unit_tests/simpletest/docs/fr/docs.css
ADDED
@@ -0,0 +1,84 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
body {
|
2 |
+
padding-left: 3%;
|
3 |
+
padding-right: 3%;
|
4 |
+
}
|
5 |
+
pre {
|
6 |
+
font-family: "courier new", courier;
|
7 |
+
font-size: 80%;
|
8 |
+
border: 1px solid;
|
9 |
+
background-color: #cccccc;
|
10 |
+
padding: 5px;
|
11 |
+
margin-left: 5%;
|
12 |
+
margin-right: 8%;
|
13 |
+
}
|
14 |
+
.code, .new_code, pre.new_code {
|
15 |
+
font-weight: bold;
|
16 |
+
}
|
17 |
+
div.copyright {
|
18 |
+
font-size: 80%;
|
19 |
+
color: gray;
|
20 |
+
}
|
21 |
+
div.copyright a {
|
22 |
+
color: gray;
|
23 |
+
}
|
24 |
+
ul.api {
|
25 |
+
padding-left: 0em;
|
26 |
+
padding-right: 25%;
|
27 |
+
}
|
28 |
+
ul.api li {
|
29 |
+
margin-top: 0.2em;
|
30 |
+
margin-bottom: 0.2em;
|
31 |
+
list-style: none;
|
32 |
+
text-indent: -3em;
|
33 |
+
padding-left: 3em;
|
34 |
+
}
|
35 |
+
div.demo {
|
36 |
+
border: 4px ridge;
|
37 |
+
border-color: gray;
|
38 |
+
padding: 10px;
|
39 |
+
margin: 5px;
|
40 |
+
margin-left: 20px;
|
41 |
+
margin-right: 40px;
|
42 |
+
background-color: white;
|
43 |
+
}
|
44 |
+
div.demo span.fail {
|
45 |
+
color: red;
|
46 |
+
}
|
47 |
+
div.demo span.pass {
|
48 |
+
color: green;
|
49 |
+
}
|
50 |
+
div.demo h1 {
|
51 |
+
font-size: 12pt;
|
52 |
+
text-align: left;
|
53 |
+
font-weight: bold;
|
54 |
+
}
|
55 |
+
table {
|
56 |
+
border: 2px outset;
|
57 |
+
border-color: gray;
|
58 |
+
background-color: white;
|
59 |
+
margin: 5px;
|
60 |
+
margin-left: 5%;
|
61 |
+
margin-right: 5%;
|
62 |
+
}
|
63 |
+
td {
|
64 |
+
font-size: 80%;
|
65 |
+
}
|
66 |
+
.shell {
|
67 |
+
color: white;
|
68 |
+
}
|
69 |
+
pre.shell {
|
70 |
+
border: 4px ridge;
|
71 |
+
border-color: gray;
|
72 |
+
padding: 10px;
|
73 |
+
margin: 5px;
|
74 |
+
margin-left: 20px;
|
75 |
+
margin-right: 40px;
|
76 |
+
background-color: black;
|
77 |
+
}
|
78 |
+
form.demo {
|
79 |
+
background-color: lightgray;
|
80 |
+
border: 4px outset;
|
81 |
+
border-color: lightgray;
|
82 |
+
padding: 10px;
|
83 |
+
margin-right: 40%;
|
84 |
+
}
|
lib/Minify/min_unit_tests/simpletest/docs/lastcraft/README
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
Output folder for Lastcraft site versions of documentation.
|
lib/Minify/min_unit_tests/simpletest/docs/onpk/README
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
R�pertoire utilis� pour l'extraction de la documentation au format du site onpk.net
|
lib/Minify/min_unit_tests/simpletest/docs/pkg/README
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
Files here are generated from make_phpdoc_docs.sh
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/README
ADDED
@@ -0,0 +1 @@
|
|
Â
|
1 |
+
Output folder for SimpleTest.org site versions of content, documentation & tutorial.
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/favicon.ico
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/book-domain-driven-design.jpg
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/book-guide-to-php-design-patterns.jpg
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/book-the-php-anthology-object-oriented-php-solutions.jpg
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/quote.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-contribute.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-download.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-external-bottom.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-external-middle.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-external-top.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-internal-bottom.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-internal-middle.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-internal-top.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-logo.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-start-testing.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/simpletest-support.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/test-in-cli.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/test-with-1-fail.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/images/test-with-1-pass.png
ADDED
Binary file
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/index.html
ADDED
@@ -0,0 +1,188 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2 |
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
3 |
+
<head>
|
4 |
+
<title>SimpleTest - Unit Testing for PHP</title>
|
5 |
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
6 |
+
<link rel="stylesheet" type="text/css" href="simpletest.css" media="screen" title="Normal" />
|
7 |
+
</head>
|
8 |
+
<body>
|
9 |
+
<div>
|
10 |
+
<div id="actions">
|
11 |
+
<div id="logo">
|
12 |
+
<a href="http://simpletest.org/index.html"><img src="images/simpletest-logo.png" width="335" height="127" border="0" id="simpletestlogo" alt="" /></a>
|
13 |
+
</div>
|
14 |
+
<div>
|
15 |
+
<div>
|
16 |
+
<a href="en/download.html"><img src="images/simpletest-download.png" width="306" height="109" border="0" id="simpletestdownload" alt="" /></a>
|
17 |
+
<p>
|
18 |
+
SimpleTest 1.0.1 RC1 release is the
|
19 |
+
<a href="https://sourceforge.net/project/showfiles.php?group_id=76550">
|
20 |
+
latest version</a>.
|
21 |
+
It's very stable although PHP5 users will find it doesn't
|
22 |
+
run with E_STRICT : it's still fully PHP4 compatible.
|
23 |
+
</p>
|
24 |
+
</div>
|
25 |
+
<div>
|
26 |
+
<a href="en/start-testing.html"><img src="images/simpletest-start-testing.png" width="306" height="109" border="0" id="simpleteststarttesting" alt="" /></a>
|
27 |
+
<p>
|
28 |
+
Familiar with unit testing ? Just dive directly into SimpleTest with
|
29 |
+
<a href="en/start-testing.html">the one-page starter</a> and
|
30 |
+
<a href="http://simpletest.org/api/">the complete API</a>.
|
31 |
+
<br />
|
32 |
+
Otherwise see the ongoing
|
33 |
+
<a href="en/overview.html">documentation</a>.
|
34 |
+
<br />
|
35 |
+
And for example test cases check out the
|
36 |
+
<a href="en/first_test_tutorial.html">tutorial</a>.
|
37 |
+
</p>
|
38 |
+
</div>
|
39 |
+
<div>
|
40 |
+
<a href="en/support.html"><img src="images/simpletest-support.png" width="306" height="109" border="0" id="simpletestsupport" alt="" /></a>
|
41 |
+
<p>
|
42 |
+
Need help on your testing strategy ?
|
43 |
+
Feel free to join the
|
44 |
+
<a href="https://sourceforge.net/mail/?group_id=76550">SimpleTest support mailing-list</a>.
|
45 |
+
</p>
|
46 |
+
<p>
|
47 |
+
If you need some new functionnality in SimpleTest, you may want to look at
|
48 |
+
the <a href="https://sourceforge.net/tracker/?atid=547458&group_id=76550&func=browse">features tracker</a>.
|
49 |
+
Also the <a href="https://sourceforge.net/tracker/?atid=547455&group_id=76550&func=browse">bug</a> and
|
50 |
+
<a href="https://sourceforge.net/tracker/?group_id=76550&atid=547457">patches</a> trackers can be useful.
|
51 |
+
</p>
|
52 |
+
</div>
|
53 |
+
<div>
|
54 |
+
<a href="en/todo.html"><img src="images/simpletest-contribute.png" width="306" height="109" border="0" id="simpletestcontribute" alt="" /></a>
|
55 |
+
<p>
|
56 |
+
And if you feel like giving a hand, feel free to look around the
|
57 |
+
<a href="en/todo.html">current TODO list</a>...
|
58 |
+
</p>
|
59 |
+
</div>
|
60 |
+
<div id="credits">
|
61 |
+
<a href="http://sourceforge.net/projects/simpletest">
|
62 |
+
<img src="http://sourceforge.net/sflogo.php?group_id=76550&type=1" width="88" height="31" border="0" alt="SourceForge.net Logo" />
|
63 |
+
</a>
|
64 |
+
</div>
|
65 |
+
</div>
|
66 |
+
</div>
|
67 |
+
<div id="content">
|
68 |
+
<p id="news">
|
69 |
+
[2008/03/25]
|
70 |
+
<a href="http://sourceforge.net/project/showfiles.php?group_id=76550&package_id=77275&release_id=586797">
|
71 |
+
SimpleTest 1.0.1 RC1 is released</a>.
|
72 |
+
The last but one release that supports PHP4.2 up to PHP5.3 inclusive.
|
73 |
+
This release is mainly bug fixes and minor enhancements.
|
74 |
+
One major enhancement was making exception handling more robust.
|
75 |
+
</p>
|
76 |
+
<p>
|
77 |
+
The <strong>SimpleTest PHP unit tester</strong>
|
78 |
+
is available for download from your nearest
|
79 |
+
<a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
80 |
+
It is a PHP unit test and web test framework.
|
81 |
+
Users of <a href="http://www.junit.org/">JUnit</a> will be
|
82 |
+
familiar with most of the interface.
|
83 |
+
The <a href="http://jwebunit.sourceforge.net/">JWebUnit</a>
|
84 |
+
style functionality is more complete now.
|
85 |
+
It has support for SSL, forms, frames, proxies and basic authentication.
|
86 |
+
The current CVS code should become the 1.0.1 release real soon now and
|
87 |
+
includes file upload and many small improvements.
|
88 |
+
The idea is that common but fiddly PHP tasks, such as logging into a site,
|
89 |
+
can be tested easily.
|
90 |
+
</p>
|
91 |
+
<h2>Screenshots</h2>
|
92 |
+
<p>
|
93 |
+
Here's what the result of your first test would look like :
|
94 |
+
</p>
|
95 |
+
<p>
|
96 |
+
<img class="screenshot" alt="test with 1 pass" src="images/test-with-1-pass.png" border="0" id="test-with-1-pass" />
|
97 |
+
</p>
|
98 |
+
<p>
|
99 |
+
Well not quite. In true TDD fashion, you should see a failing test case :
|
100 |
+
</p>
|
101 |
+
<p>
|
102 |
+
<img class="screenshot" alt="test with 1 fail" src="images/test-with-1-fail.png" border="0" id="test-with-1-fail" />
|
103 |
+
</p>
|
104 |
+
<p>
|
105 |
+
You may also prefer doing your testing with the command-line :
|
106 |
+
</p>
|
107 |
+
<p>
|
108 |
+
<img alt="test in cli" src="images/test-in-cli.png" border="0" id="test-in-cli" />
|
109 |
+
</p>
|
110 |
+
<h2>Documentation</h2>
|
111 |
+
<p>
|
112 |
+
While (still) very scattered around different sites, the SimpleTest documentation is quite dense and thorough.
|
113 |
+
</p>
|
114 |
+
<ul>
|
115 |
+
<li>
|
116 |
+
in english there's <a href="en/first_test_tutorial.html">a tutorial</a>
|
117 |
+
and <a href="en/unit_test_documentation.html">the official documentation</a>.
|
118 |
+
</li>
|
119 |
+
<li>
|
120 |
+
<cite>en français, il y a aussi <a href="fr/first_test_tutorial.html">le tutoriel</a>
|
121 |
+
et <a href="fr/unit_test_documentation.html">la documentation</a></cite>.
|
122 |
+
</li>
|
123 |
+
<li>
|
124 |
+
a fully <a href="http://simpletest.org/api/">documented API</a> is also generated with phpDocumentor.
|
125 |
+
</li>
|
126 |
+
</ul>
|
127 |
+
<p>
|
128 |
+
Other type of interesting stuff while starting out with Test Driven Development and SimpleTest include :
|
129 |
+
</p>
|
130 |
+
<ul>
|
131 |
+
<li>
|
132 |
+
<a href="http://en.wikipedia.org/wiki/SimpleTest">Article on Wikipedia</a>
|
133 |
+
</li>
|
134 |
+
<li>
|
135 |
+
<a href="http://www.developerspot.com/tutorials/php/test-driven-development/page1.html">Test Driven Development</a> :
|
136 |
+
article by Marcus Baker (SimpleTest leader)
|
137 |
+
</li>
|
138 |
+
<li>
|
139 |
+
<a href="http://onpk.net/talks/fosdem2005/introduction_simpletest.html">Introduction to SimpleTest and TDD</a> :
|
140 |
+
slides from a talk given at Fosdem, Brussels in 2005 by Perrick Penet
|
141 |
+
</li>
|
142 |
+
<li>
|
143 |
+
<a href="http://www.devpapers.com/article/303">Unit Testing in PHP using SimpleTest</a> :
|
144 |
+
article by Saleh Jamal
|
145 |
+
</li>
|
146 |
+
<li>
|
147 |
+
<a href="http://drupal.org/simpletest">How to write automated tests</a> :
|
148 |
+
in Drupal style (Module how-to's)
|
149 |
+
</li>
|
150 |
+
<li>
|
151 |
+
<a href="http://blog.casey-sweat.us/?p=72">Live TDD demo</a> :
|
152 |
+
transcript of a presentation in London in 2006 by Jason E. Sweat
|
153 |
+
</li>
|
154 |
+
</ul>
|
155 |
+
<p>
|
156 |
+
A couple of books do use SimpleTest quite extensively :
|
157 |
+
</p>
|
158 |
+
<ul>
|
159 |
+
<li>
|
160 |
+
<strong>PHP|Architect's Guide to PHP Design Patterns</strong><br />
|
161 |
+
by Jason E. Sweat<br />
|
162 |
+
( <a href="http://www.phparch.com/shop_product.php?itemid=96">PHP|Architect</a> |
|
163 |
+
<a href="http://www.amazon.com/gp/product/0973589825/102-3523235-1803315">Amazon</a> )
|
164 |
+
</li>
|
165 |
+
<li>
|
166 |
+
<strong>The PHP Anthology: Object Oriented PHP Solutions</strong><br />
|
167 |
+
by Harry Fuecks<br />
|
168 |
+
( <a href="http://www.sitepoint.com/books/phpant1/">SitePoint</a> |
|
169 |
+
<a href="http://www.amazon.com/gp/product/0957921845/102-3523235-1803315">Amazon</a> |
|
170 |
+
<a href="http://developers.slashdot.org/article.pl?sid=04/08/04/1516258&tid=169&tid=192&tid=218&mode=nocomment">review on Slashdot</a> )
|
171 |
+
</li>
|
172 |
+
</ul>
|
173 |
+
<h2>Contributing</h2>
|
174 |
+
<p>
|
175 |
+
For translators the documentation is available in XML format :
|
176 |
+
we're always please to add new languages to our code base.
|
177 |
+
</p>
|
178 |
+
<p>
|
179 |
+
And while we do try our best keeping this tool bug-free, detecting defects and
|
180 |
+
submitting failing test cases and/or patches can come very handy ! Interested ?
|
181 |
+
Drop by the <a href="https://sourceforge.net/mail/?group_id=76550">mailing-list</a>,
|
182 |
+
most things tend to happen there...
|
183 |
+
</p>
|
184 |
+
</div>
|
185 |
+
</div>
|
186 |
+
|
187 |
+
</body>
|
188 |
+
</html>
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/js/jquery-1.2.1.pack.js
ADDED
@@ -0,0 +1,11 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*
|
2 |
+
* jQuery 1.2.1 - New Wave Javascript
|
3 |
+
*
|
4 |
+
* Copyright (c) 2007 John Resig (jquery.com)
|
5 |
+
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
6 |
+
* and GPL (GPL-LICENSE.txt) licenses.
|
7 |
+
*
|
8 |
+
* $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $
|
9 |
+
* $Rev: 3353 $
|
10 |
+
*/
|
11 |
+
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(G(){9(1m E!="W")H w=E;H E=18.15=G(a,b){I 6 7u E?6.5N(a,b):1u E(a,b)};9(1m $!="W")H D=$;18.$=E;H u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;E.1b=E.3A={5N:G(c,a){c=c||U;9(1m c=="1M"){H m=u.2S(c);9(m&&(m[1]||!a)){9(m[1])c=E.4D([m[1]],a);J{H b=U.3S(m[3]);9(b)9(b.22!=m[3])I E().1Y(c);J{6[0]=b;6.K=1;I 6}J c=[]}}J I 1u E(a).1Y(c)}J 9(E.1n(c))I 1u E(U)[E.1b.2d?"2d":"39"](c);I 6.6v(c.1c==1B&&c||(c.4c||c.K&&c!=18&&!c.1y&&c[0]!=W&&c[0].1y)&&E.2h(c)||[c])},4c:"1.2.1",7Y:G(){I 6.K},K:0,21:G(a){I a==W?E.2h(6):6[a]},2o:G(a){H b=E(a);b.4Y=6;I b},6v:G(a){6.K=0;1B.3A.1a.16(6,a);I 6},N:G(a,b){I E.N(6,a,b)},4I:G(a){H b=-1;6.N(G(i){9(6==a)b=i});I b},1x:G(f,d,e){H c=f;9(f.1c==3X)9(d==W)I 6.K&&E[e||"1x"](6[0],f)||W;J{c={};c[f]=d}I 6.N(G(a){L(H b 1i c)E.1x(e?6.R:6,b,E.1e(6,c[b],e,a,b))})},17:G(b,a){I 6.1x(b,a,"3C")},2g:G(e){9(1m e!="5i"&&e!=S)I 6.4n().3g(U.6F(e));H t="";E.N(e||6,G(){E.N(6.3j,G(){9(6.1y!=8)t+=6.1y!=1?6.6x:E.1b.2g([6])})});I t},5m:G(b){9(6[0])E(b,6[0].3H).6u().3d(6[0]).1X(G(){H a=6;1W(a.1w)a=a.1w;I a}).3g(6);I 6},8m:G(a){I 6.N(G(){E(6).6q().5m(a)})},8d:G(a){I 6.N(G(){E(6).5m(a)})},3g:G(){I 6.3z(1q,Q,1,G(a){6.58(a)})},6j:G(){I 6.3z(1q,Q,-1,G(a){6.3d(a,6.1w)})},6g:G(){I 6.3z(1q,P,1,G(a){6.12.3d(a,6)})},50:G(){I 6.3z(1q,P,-1,G(a){6.12.3d(a,6.2q)})},2D:G(){I 6.4Y||E([])},1Y:G(t){H b=E.1X(6,G(a){I E.1Y(t,a)});I 6.2o(/[^+>] [^+>]/.14(t)||t.1g("..")>-1?E.4V(b):b)},6u:G(e){H f=6.1X(G(){I 6.67?E(6.67)[0]:6.4R(Q)});H d=f.1Y("*").4O().N(G(){9(6[F]!=W)6[F]=S});9(e===Q)6.1Y("*").4O().N(G(i){H c=E.M(6,"2P");L(H a 1i c)L(H b 1i c[a])E.1j.1f(d[i],a,c[a][b],c[a][b].M)});I f},1E:G(t){I 6.2o(E.1n(t)&&E.2W(6,G(b,a){I t.16(b,[a])})||E.3m(t,6))},5V:G(t){I 6.2o(t.1c==3X&&E.3m(t,6,Q)||E.2W(6,G(a){I(t.1c==1B||t.4c)?E.2A(a,t)<0:a!=t}))},1f:G(t){I 6.2o(E.1R(6.21(),t.1c==3X?E(t).21():t.K!=W&&(!t.11||E.11(t,"2Y"))?t:[t]))},3t:G(a){I a?E.3m(a,6).K>0:P},7c:G(a){I 6.3t("."+a)},3i:G(b){9(b==W){9(6.K){H c=6[0];9(E.11(c,"24")){H e=c.4Z,a=[],Y=c.Y,2G=c.O=="24-2G";9(e<0)I S;L(H i=2G?e:0,33=2G?e+1:Y.K;i<33;i++){H d=Y[i];9(d.26){H b=E.V.1h&&!d.9V["1Q"].9L?d.2g:d.1Q;9(2G)I b;a.1a(b)}}I a}J I 6[0].1Q.1p(/\\r/g,"")}}J I 6.N(G(){9(b.1c==1B&&/4k|5j/.14(6.O))6.2Q=(E.2A(6.1Q,b)>=0||E.2A(6.2H,b)>=0);J 9(E.11(6,"24")){H a=b.1c==1B?b:[b];E("9h",6).N(G(){6.26=(E.2A(6.1Q,a)>=0||E.2A(6.2g,a)>=0)});9(!a.K)6.4Z=-1}J 6.1Q=b})},4o:G(a){I a==W?(6.K?6[0].3O:S):6.4n().3g(a)},6H:G(a){I 6.50(a).28()},6E:G(i){I 6.2J(i,i+1)},2J:G(){I 6.2o(1B.3A.2J.16(6,1q))},1X:G(b){I 6.2o(E.1X(6,G(a,i){I b.2O(a,i,a)}))},4O:G(){I 6.1f(6.4Y)},3z:G(f,d,g,e){H c=6.K>1,a;I 6.N(G(){9(!a){a=E.4D(f,6.3H);9(g<0)a.8U()}H b=6;9(d&&E.11(6,"1I")&&E.11(a[0],"4m"))b=6.4l("1K")[0]||6.58(U.5B("1K"));E.N(a,G(){H a=c?6.4R(Q):6;9(!5A(0,a))e.2O(b,a)})})}};G 5A(i,b){H a=E.11(b,"1J");9(a){9(b.3k)E.3G({1d:b.3k,3e:P,1V:"1J"});J E.5f(b.2g||b.6s||b.3O||"");9(b.12)b.12.3b(b)}J 9(b.1y==1)E("1J",b).N(5A);I a}E.1k=E.1b.1k=G(){H c=1q[0]||{},a=1,2c=1q.K,5e=P;9(c.1c==8o){5e=c;c=1q[1]||{}}9(2c==1){c=6;a=0}H b;L(;a<2c;a++)9((b=1q[a])!=S)L(H i 1i b){9(c==b[i])6r;9(5e&&1m b[i]==\'5i\'&&c[i])E.1k(c[i],b[i]);J 9(b[i]!=W)c[i]=b[i]}I c};H F="15"+(1u 3D()).3B(),6p=0,5c={};E.1k({8a:G(a){18.$=D;9(a)18.15=w;I E},1n:G(a){I!!a&&1m a!="1M"&&!a.11&&a.1c!=1B&&/G/i.14(a+"")},4a:G(a){I a.2V&&!a.1G||a.37&&a.3H&&!a.3H.1G},5f:G(a){a=E.36(a);9(a){9(18.6l)18.6l(a);J 9(E.V.1N)18.56(a,0);J 3w.2O(18,a)}},11:G(b,a){I b.11&&b.11.27()==a.27()},1L:{},M:G(c,d,b){c=c==18?5c:c;H a=c[F];9(!a)a=c[F]=++6p;9(d&&!E.1L[a])E.1L[a]={};9(b!=W)E.1L[a][d]=b;I d?E.1L[a][d]:a},30:G(c,b){c=c==18?5c:c;H a=c[F];9(b){9(E.1L[a]){2E E.1L[a][b];b="";L(b 1i E.1L[a])1T;9(!b)E.30(c)}}J{2a{2E c[F]}29(e){9(c.53)c.53(F)}2E E.1L[a]}},N:G(a,b,c){9(c){9(a.K==W)L(H i 1i a)b.16(a[i],c);J L(H i=0,48=a.K;i<48;i++)9(b.16(a[i],c)===P)1T}J{9(a.K==W)L(H i 1i a)b.2O(a[i],i,a[i]);J L(H i=0,48=a.K,3i=a[0];i<48&&b.2O(3i,i,3i)!==P;3i=a[++i]){}}I a},1e:G(c,b,d,e,a){9(E.1n(b))b=b.2O(c,[e]);H f=/z-?4I|7T-?7Q|1r|69|7P-?1H/i;I b&&b.1c==4W&&d=="3C"&&!f.14(a)?b+"2T":b},1o:{1f:G(b,c){E.N((c||"").2l(/\\s+/),G(i,a){9(!E.1o.3K(b.1o,a))b.1o+=(b.1o?" ":"")+a})},28:G(b,c){b.1o=c!=W?E.2W(b.1o.2l(/\\s+/),G(a){I!E.1o.3K(c,a)}).66(" "):""},3K:G(t,c){I E.2A(c,(t.1o||t).3s().2l(/\\s+/))>-1}},2k:G(e,o,f){L(H i 1i o){e.R["3r"+i]=e.R[i];e.R[i]=o[i]}f.16(e,[]);L(H i 1i o)e.R[i]=e.R["3r"+i]},17:G(e,p){9(p=="1H"||p=="2N"){H b={},42,41,d=["7J","7I","7G","7F"];E.N(d,G(){b["7C"+6]=0;b["7B"+6+"5Z"]=0});E.2k(e,b,G(){9(E(e).3t(\':3R\')){42=e.7A;41=e.7w}J{e=E(e.4R(Q)).1Y(":4k").5W("2Q").2D().17({4C:"1P",2X:"4F",19:"2Z",7o:"0",1S:"0"}).5R(e.12)[0];H a=E.17(e.12,"2X")||"3V";9(a=="3V")e.12.R.2X="7g";42=e.7e;41=e.7b;9(a=="3V")e.12.R.2X="3V";e.12.3b(e)}});I p=="1H"?42:41}I E.3C(e,p)},3C:G(h,j,i){H g,2w=[],2k=[];G 3n(a){9(!E.V.1N)I P;H b=U.3o.3Z(a,S);I!b||b.4y("3n")==""}9(j=="1r"&&E.V.1h){g=E.1x(h.R,"1r");I g==""?"1":g}9(j.1t(/4u/i))j=y;9(!i&&h.R[j])g=h.R[j];J 9(U.3o&&U.3o.3Z){9(j.1t(/4u/i))j="4u";j=j.1p(/([A-Z])/g,"-$1").2p();H d=U.3o.3Z(h,S);9(d&&!3n(h))g=d.4y(j);J{L(H a=h;a&&3n(a);a=a.12)2w.4w(a);L(a=0;a<2w.K;a++)9(3n(2w[a])){2k[a]=2w[a].R.19;2w[a].R.19="2Z"}g=j=="19"&&2k[2w.K-1]!=S?"2s":U.3o.3Z(h,S).4y(j)||"";L(a=0;a<2k.K;a++)9(2k[a]!=S)2w[a].R.19=2k[a]}9(j=="1r"&&g=="")g="1"}J 9(h.3Q){H f=j.1p(/\\-(\\w)/g,G(m,c){I c.27()});g=h.3Q[j]||h.3Q[f];9(!/^\\d+(2T)?$/i.14(g)&&/^\\d/.14(g)){H k=h.R.1S;H e=h.4v.1S;h.4v.1S=h.3Q.1S;h.R.1S=g||0;g=h.R.71+"2T";h.R.1S=k;h.4v.1S=e}}I g},4D:G(a,e){H r=[];e=e||U;E.N(a,G(i,d){9(!d)I;9(d.1c==4W)d=d.3s();9(1m d=="1M"){d=d.1p(/(<(\\w+)[^>]*?)\\/>/g,G(m,a,b){I b.1t(/^(70|6Z|6Y|9Q|4t|9N|9K|3a|9G|9E)$/i)?m:a+"></"+b+">"});H s=E.36(d).2p(),1s=e.5B("1s"),2x=[];H c=!s.1g("<9y")&&[1,"<24>","</24>"]||!s.1g("<9w")&&[1,"<6T>","</6T>"]||s.1t(/^<(9u|1K|9t|9r|9p)/)&&[1,"<1I>","</1I>"]||!s.1g("<4m")&&[2,"<1I><1K>","</1K></1I>"]||(!s.1g("<9m")||!s.1g("<9k"))&&[3,"<1I><1K><4m>","</4m></1K></1I>"]||!s.1g("<6Y")&&[2,"<1I><1K></1K><6L>","</6L></1I>"]||E.V.1h&&[1,"1s<1s>","</1s>"]||[0,"",""];1s.3O=c[1]+d+c[2];1W(c[0]--)1s=1s.5p;9(E.V.1h){9(!s.1g("<1I")&&s.1g("<1K")<0)2x=1s.1w&&1s.1w.3j;J 9(c[1]=="<1I>"&&s.1g("<1K")<0)2x=1s.3j;L(H n=2x.K-1;n>=0;--n)9(E.11(2x[n],"1K")&&!2x[n].3j.K)2x[n].12.3b(2x[n]);9(/^\\s/.14(d))1s.3d(e.6F(d.1t(/^\\s*/)[0]),1s.1w)}d=E.2h(1s.3j)}9(0===d.K&&(!E.11(d,"2Y")&&!E.11(d,"24")))I;9(d[0]==W||E.11(d,"2Y")||d.Y)r.1a(d);J r=E.1R(r,d)});I r},1x:G(c,d,a){H e=E.4a(c)?{}:E.5o;9(d=="26"&&E.V.1N)c.12.4Z;9(e[d]){9(a!=W)c[e[d]]=a;I c[e[d]]}J 9(E.V.1h&&d=="R")I E.1x(c.R,"9e",a);J 9(a==W&&E.V.1h&&E.11(c,"2Y")&&(d=="9d"||d=="9a"))I c.97(d).6x;J 9(c.37){9(a!=W){9(d=="O"&&E.11(c,"4t")&&c.12)6G"O 94 93\'t 92 91";c.90(d,a)}9(E.V.1h&&/6C|3k/.14(d)&&!E.4a(c))I c.4p(d,2);I c.4p(d)}J{9(d=="1r"&&E.V.1h){9(a!=W){c.69=1;c.1E=(c.1E||"").1p(/6O\\([^)]*\\)/,"")+(3I(a).3s()=="8S"?"":"6O(1r="+a*6A+")")}I c.1E?(3I(c.1E.1t(/1r=([^)]*)/)[1])/6A).3s():""}d=d.1p(/-([a-z])/8Q,G(z,b){I b.27()});9(a!=W)c[d]=a;I c[d]}},36:G(t){I(t||"").1p(/^\\s+|\\s+$/g,"")},2h:G(a){H r=[];9(1m a!="8P")L(H i=0,2c=a.K;i<2c;i++)r.1a(a[i]);J r=a.2J(0);I r},2A:G(b,a){L(H i=0,2c=a.K;i<2c;i++)9(a[i]==b)I i;I-1},1R:G(a,b){9(E.V.1h){L(H i=0;b[i];i++)9(b[i].1y!=8)a.1a(b[i])}J L(H i=0;b[i];i++)a.1a(b[i]);I a},4V:G(b){H r=[],2f={};2a{L(H i=0,6y=b.K;i<6y;i++){H a=E.M(b[i]);9(!2f[a]){2f[a]=Q;r.1a(b[i])}}}29(e){r=b}I r},2W:G(b,a,c){9(1m a=="1M")a=3w("P||G(a,i){I "+a+"}");H d=[];L(H i=0,4g=b.K;i<4g;i++)9(!c&&a(b[i],i)||c&&!a(b[i],i))d.1a(b[i]);I d},1X:G(c,b){9(1m b=="1M")b=3w("P||G(a){I "+b+"}");H d=[];L(H i=0,4g=c.K;i<4g;i++){H a=b(c[i],i);9(a!==S&&a!=W){9(a.1c!=1B)a=[a];d=d.8M(a)}}I d}});H v=8K.8I.2p();E.V={4s:(v.1t(/.+(?:8F|8E|8C|8B)[\\/: ]([\\d.]+)/)||[])[1],1N:/6w/.14(v),34:/34/.14(v),1h:/1h/.14(v)&&!/34/.14(v),35:/35/.14(v)&&!/(8z|6w)/.14(v)};H y=E.V.1h?"4h":"5h";E.1k({5g:!E.V.1h||U.8y=="8x",4h:E.V.1h?"4h":"5h",5o:{"L":"8w","8v":"1o","4u":y,5h:y,4h:y,3O:"3O",1o:"1o",1Q:"1Q",3c:"3c",2Q:"2Q",8u:"8t",26:"26",8s:"8r"}});E.N({1D:"a.12",8q:"15.4e(a,\'12\')",8p:"15.2I(a,2,\'2q\')",8n:"15.2I(a,2,\'4d\')",8l:"15.4e(a,\'2q\')",8k:"15.4e(a,\'4d\')",8j:"15.5d(a.12.1w,a)",8i:"15.5d(a.1w)",6q:"15.11(a,\'8h\')?a.8f||a.8e.U:15.2h(a.3j)"},G(i,n){E.1b[i]=G(a){H b=E.1X(6,n);9(a&&1m a=="1M")b=E.3m(a,b);I 6.2o(E.4V(b))}});E.N({5R:"3g",8c:"6j",3d:"6g",8b:"50",89:"6H"},G(i,n){E.1b[i]=G(){H a=1q;I 6.N(G(){L(H j=0,2c=a.K;j<2c;j++)E(a[j])[n](6)})}});E.N({5W:G(a){E.1x(6,a,"");6.53(a)},88:G(c){E.1o.1f(6,c)},87:G(c){E.1o.28(6,c)},86:G(c){E.1o[E.1o.3K(6,c)?"28":"1f"](6,c)},28:G(a){9(!a||E.1E(a,[6]).r.K){E.30(6);6.12.3b(6)}},4n:G(){E("*",6).N(G(){E.30(6)});1W(6.1w)6.3b(6.1w)}},G(i,n){E.1b[i]=G(){I 6.N(n,1q)}});E.N(["85","5Z"],G(i,a){H n=a.2p();E.1b[n]=G(h){I 6[0]==18?E.V.1N&&3y["84"+a]||E.5g&&38.33(U.2V["5a"+a],U.1G["5a"+a])||U.1G["5a"+a]:6[0]==U?38.33(U.1G["6n"+a],U.1G["6m"+a]):h==W?(6.K?E.17(6[0],n):S):6.17(n,h.1c==3X?h:h+"2T")}});H C=E.V.1N&&3x(E.V.4s)<83?"(?:[\\\\w*57-]|\\\\\\\\.)":"(?:[\\\\w\\82-\\81*57-]|\\\\\\\\.)",6k=1u 47("^>\\\\s*("+C+"+)"),6i=1u 47("^("+C+"+)(#)("+C+"+)"),6h=1u 47("^([#.]?)("+C+"*)");E.1k({55:{"":"m[2]==\'*\'||15.11(a,m[2])","#":"a.4p(\'22\')==m[2]",":":{80:"i<m[3]-0",7Z:"i>m[3]-0",2I:"m[3]-0==i",6E:"m[3]-0==i",3v:"i==0",3u:"i==r.K-1",6f:"i%2==0",6e:"i%2","3v-46":"a.12.4l(\'*\')[0]==a","3u-46":"15.2I(a.12.5p,1,\'4d\')==a","7X-46":"!15.2I(a.12.5p,2,\'4d\')",1D:"a.1w",4n:"!a.1w",7W:"(a.6s||a.7V||15(a).2g()||\'\').1g(m[3])>=0",3R:\'"1P"!=a.O&&15.17(a,"19")!="2s"&&15.17(a,"4C")!="1P"\',1P:\'"1P"==a.O||15.17(a,"19")=="2s"||15.17(a,"4C")=="1P"\',7U:"!a.3c",3c:"a.3c",2Q:"a.2Q",26:"a.26||15.1x(a,\'26\')",2g:"\'2g\'==a.O",4k:"\'4k\'==a.O",5j:"\'5j\'==a.O",54:"\'54\'==a.O",52:"\'52\'==a.O",51:"\'51\'==a.O",6d:"\'6d\'==a.O",6c:"\'6c\'==a.O",2r:\'"2r"==a.O||15.11(a,"2r")\',4t:"/4t|24|6b|2r/i.14(a.11)",3K:"15.1Y(m[3],a).K",7S:"/h\\\\d/i.14(a.11)",7R:"15.2W(15.32,G(1b){I a==1b.T;}).K"}},6a:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1u 47("^([:.#]*)("+C+"+)")],3m:G(a,c,b){H d,2b=[];1W(a&&a!=d){d=a;H f=E.1E(a,c,b);a=f.t.1p(/^\\s*,\\s*/,"");2b=b?c=f.r:E.1R(2b,f.r)}I 2b},1Y:G(t,o){9(1m t!="1M")I[t];9(o&&!o.1y)o=S;o=o||U;H d=[o],2f=[],3u;1W(t&&3u!=t){H r=[];3u=t;t=E.36(t);H l=P;H g=6k;H m=g.2S(t);9(m){H p=m[1].27();L(H i=0;d[i];i++)L(H c=d[i].1w;c;c=c.2q)9(c.1y==1&&(p=="*"||c.11.27()==p.27()))r.1a(c);d=r;t=t.1p(g,"");9(t.1g(" ")==0)6r;l=Q}J{g=/^([>+~])\\s*(\\w*)/i;9((m=g.2S(t))!=S){r=[];H p=m[2],1R={};m=m[1];L(H j=0,31=d.K;j<31;j++){H n=m=="~"||m=="+"?d[j].2q:d[j].1w;L(;n;n=n.2q)9(n.1y==1){H h=E.M(n);9(m=="~"&&1R[h])1T;9(!p||n.11.27()==p.27()){9(m=="~")1R[h]=Q;r.1a(n)}9(m=="+")1T}}d=r;t=E.36(t.1p(g,""));l=Q}}9(t&&!l){9(!t.1g(",")){9(o==d[0])d.44();2f=E.1R(2f,d);r=d=[o];t=" "+t.68(1,t.K)}J{H k=6i;H m=k.2S(t);9(m){m=[0,m[2],m[3],m[1]]}J{k=6h;m=k.2S(t)}m[2]=m[2].1p(/\\\\/g,"");H f=d[d.K-1];9(m[1]=="#"&&f&&f.3S&&!E.4a(f)){H q=f.3S(m[2]);9((E.V.1h||E.V.34)&&q&&1m q.22=="1M"&&q.22!=m[2])q=E(\'[@22="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.11(q,m[3]))?[q]:[]}J{L(H i=0;d[i];i++){H a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];9(a=="*"&&d[i].11.2p()=="5i")a="3a";r=E.1R(r,d[i].4l(a))}9(m[1]==".")r=E.4X(r,m[2]);9(m[1]=="#"){H e=[];L(H i=0;r[i];i++)9(r[i].4p("22")==m[2]){e=[r[i]];1T}r=e}d=r}t=t.1p(k,"")}}9(t){H b=E.1E(t,r);d=r=b.r;t=E.36(b.t)}}9(t)d=[];9(d&&o==d[0])d.44();2f=E.1R(2f,d);I 2f},4X:G(r,m,a){m=" "+m+" ";H c=[];L(H i=0;r[i];i++){H b=(" "+r[i].1o+" ").1g(m)>=0;9(!a&&b||a&&!b)c.1a(r[i])}I c},1E:G(t,r,h){H d;1W(t&&t!=d){d=t;H p=E.6a,m;L(H i=0;p[i];i++){m=p[i].2S(t);9(m){t=t.7O(m[0].K);m[2]=m[2].1p(/\\\\/g,"");1T}}9(!m)1T;9(m[1]==":"&&m[2]=="5V")r=E.1E(m[3],r,Q).r;J 9(m[1]==".")r=E.4X(r,m[2],h);J 9(m[1]=="["){H g=[],O=m[3];L(H i=0,31=r.K;i<31;i++){H a=r[i],z=a[E.5o[m[2]]||m[2]];9(z==S||/6C|3k|26/.14(m[2]))z=E.1x(a,m[2])||\'\';9((O==""&&!!z||O=="="&&z==m[5]||O=="!="&&z!=m[5]||O=="^="&&z&&!z.1g(m[5])||O=="$="&&z.68(z.K-m[5].K)==m[5]||(O=="*="||O=="~=")&&z.1g(m[5])>=0)^h)g.1a(a)}r=g}J 9(m[1]==":"&&m[2]=="2I-46"){H e={},g=[],14=/(\\d*)n\\+?(\\d*)/.2S(m[3]=="6f"&&"2n"||m[3]=="6e"&&"2n+1"||!/\\D/.14(m[3])&&"n+"+m[3]||m[3]),3v=(14[1]||1)-0,d=14[2]-0;L(H i=0,31=r.K;i<31;i++){H j=r[i],12=j.12,22=E.M(12);9(!e[22]){H c=1;L(H n=12.1w;n;n=n.2q)9(n.1y==1)n.4U=c++;e[22]=Q}H b=P;9(3v==1){9(d==0||j.4U==d)b=Q}J 9((j.4U+d)%3v==0)b=Q;9(b^h)g.1a(j)}r=g}J{H f=E.55[m[1]];9(1m f!="1M")f=E.55[m[1]][m[2]];f=3w("P||G(a,i){I "+f+"}");r=E.2W(r,f,h)}}I{r:r,t:t}},4e:G(b,c){H d=[];H a=b[c];1W(a&&a!=U){9(a.1y==1)d.1a(a);a=a[c]}I d},2I:G(a,e,c,b){e=e||1;H d=0;L(;a;a=a[c])9(a.1y==1&&++d==e)1T;I a},5d:G(n,a){H r=[];L(;n;n=n.2q){9(n.1y==1&&(!a||n!=a))r.1a(n)}I r}});E.1j={1f:G(g,e,c,h){9(E.V.1h&&g.4j!=W)g=18;9(!c.2u)c.2u=6.2u++;9(h!=W){H d=c;c=G(){I d.16(6,1q)};c.M=h;c.2u=d.2u}H i=e.2l(".");e=i[0];c.O=i[1];H b=E.M(g,"2P")||E.M(g,"2P",{});H f=E.M(g,"2t",G(){H a;9(1m E=="W"||E.1j.4T)I a;a=E.1j.2t.16(g,1q);I a});H j=b[e];9(!j){j=b[e]={};9(g.4S)g.4S(e,f,P);J g.7N("43"+e,f)}j[c.2u]=c;6.1Z[e]=Q},2u:1,1Z:{},28:G(d,c,b){H e=E.M(d,"2P"),2L,4I;9(1m c=="1M"){H a=c.2l(".");c=a[0]}9(e){9(c&&c.O){b=c.4Q;c=c.O}9(!c){L(c 1i e)6.28(d,c)}J 9(e[c]){9(b)2E e[c][b.2u];J L(b 1i e[c])9(!a[1]||e[c][b].O==a[1])2E e[c][b];L(2L 1i e[c])1T;9(!2L){9(d.4P)d.4P(c,E.M(d,"2t"),P);J d.7M("43"+c,E.M(d,"2t"));2L=S;2E e[c]}}L(2L 1i e)1T;9(!2L){E.30(d,"2P");E.30(d,"2t")}}},1F:G(d,b,e,c,f){b=E.2h(b||[]);9(!e){9(6.1Z[d])E("*").1f([18,U]).1F(d,b)}J{H a,2L,1b=E.1n(e[d]||S),4N=!b[0]||!b[0].2M;9(4N)b.4w(6.4M({O:d,2m:e}));b[0].O=d;9(E.1n(E.M(e,"2t")))a=E.M(e,"2t").16(e,b);9(!1b&&e["43"+d]&&e["43"+d].16(e,b)===P)a=P;9(4N)b.44();9(f&&f.16(e,b)===P)a=P;9(1b&&c!==P&&a!==P&&!(E.11(e,\'a\')&&d=="4L")){6.4T=Q;e[d]()}6.4T=P}I a},2t:G(d){H a;d=E.1j.4M(d||18.1j||{});H b=d.O.2l(".");d.O=b[0];H c=E.M(6,"2P")&&E.M(6,"2P")[d.O],3q=1B.3A.2J.2O(1q,1);3q.4w(d);L(H j 1i c){3q[0].4Q=c[j];3q[0].M=c[j].M;9(!b[1]||c[j].O==b[1]){H e=c[j].16(6,3q);9(a!==P)a=e;9(e===P){d.2M();d.3p()}}}9(E.V.1h)d.2m=d.2M=d.3p=d.4Q=d.M=S;I a},4M:G(c){H a=c;c=E.1k({},a);c.2M=G(){9(a.2M)a.2M();a.7L=P};c.3p=G(){9(a.3p)a.3p();a.7K=Q};9(!c.2m&&c.65)c.2m=c.65;9(E.V.1N&&c.2m.1y==3)c.2m=a.2m.12;9(!c.4K&&c.4J)c.4K=c.4J==c.2m?c.7H:c.4J;9(c.64==S&&c.63!=S){H e=U.2V,b=U.1G;c.64=c.63+(e&&e.2R||b.2R||0);c.7E=c.7D+(e&&e.2B||b.2B||0)}9(!c.3Y&&(c.61||c.60))c.3Y=c.61||c.60;9(!c.5F&&c.5D)c.5F=c.5D;9(!c.3Y&&c.2r)c.3Y=(c.2r&1?1:(c.2r&2?3:(c.2r&4?2:0)));I c}};E.1b.1k({3W:G(c,a,b){I c=="5Y"?6.2G(c,a,b):6.N(G(){E.1j.1f(6,c,b||a,b&&a)})},2G:G(d,b,c){I 6.N(G(){E.1j.1f(6,d,G(a){E(6).5X(a);I(c||b).16(6,1q)},c&&b)})},5X:G(a,b){I 6.N(G(){E.1j.28(6,a,b)})},1F:G(c,a,b){I 6.N(G(){E.1j.1F(c,a,6,Q,b)})},7x:G(c,a,b){9(6[0])I E.1j.1F(c,a,6[0],P,b)},25:G(){H a=1q;I 6.4L(G(e){6.4H=0==6.4H?1:0;e.2M();I a[6.4H].16(6,[e])||P})},7v:G(f,g){G 4G(e){H p=e.4K;1W(p&&p!=6)2a{p=p.12}29(e){p=6};9(p==6)I P;I(e.O=="4x"?f:g).16(6,[e])}I 6.4x(4G).5U(4G)},2d:G(f){5T();9(E.3T)f.16(U,[E]);J E.3l.1a(G(){I f.16(6,[E])});I 6}});E.1k({3T:P,3l:[],2d:G(){9(!E.3T){E.3T=Q;9(E.3l){E.N(E.3l,G(){6.16(U)});E.3l=S}9(E.V.35||E.V.34)U.4P("5S",E.2d,P);9(!18.7t.K)E(18).39(G(){E("#4E").28()})}}});E.N(("7s,7r,39,7q,6n,5Y,4L,7p,"+"7n,7m,7l,4x,5U,7k,24,"+"51,7j,7i,7h,3U").2l(","),G(i,o){E.1b[o]=G(f){I f?6.3W(o,f):6.1F(o)}});H x=P;G 5T(){9(x)I;x=Q;9(E.V.35||E.V.34)U.4S("5S",E.2d,P);J 9(E.V.1h){U.7f("<7d"+"7y 22=4E 7z=Q "+"3k=//:><\\/1J>");H a=U.3S("4E");9(a)a.62=G(){9(6.2C!="1l")I;E.2d()};a=S}J 9(E.V.1N)E.4B=4j(G(){9(U.2C=="5Q"||U.2C=="1l"){4A(E.4B);E.4B=S;E.2d()}},10);E.1j.1f(18,"39",E.2d)}E.1b.1k({39:G(g,d,c){9(E.1n(g))I 6.3W("39",g);H e=g.1g(" ");9(e>=0){H i=g.2J(e,g.K);g=g.2J(0,e)}c=c||G(){};H f="4z";9(d)9(E.1n(d)){c=d;d=S}J{d=E.3a(d);f="5P"}H h=6;E.3G({1d:g,O:f,M:d,1l:G(a,b){9(b=="1C"||b=="5O")h.4o(i?E("<1s/>").3g(a.40.1p(/<1J(.|\\s)*?\\/1J>/g,"")).1Y(i):a.40);56(G(){h.N(c,[a.40,b,a])},13)}});I 6},7a:G(){I E.3a(6.5M())},5M:G(){I 6.1X(G(){I E.11(6,"2Y")?E.2h(6.79):6}).1E(G(){I 6.2H&&!6.3c&&(6.2Q||/24|6b/i.14(6.11)||/2g|1P|52/i.14(6.O))}).1X(G(i,c){H b=E(6).3i();I b==S?S:b.1c==1B?E.1X(b,G(a,i){I{2H:c.2H,1Q:a}}):{2H:c.2H,1Q:b}}).21()}});E.N("5L,5K,6t,5J,5I,5H".2l(","),G(i,o){E.1b[o]=G(f){I 6.3W(o,f)}});H B=(1u 3D).3B();E.1k({21:G(d,b,a,c){9(E.1n(b)){a=b;b=S}I E.3G({O:"4z",1d:d,M:b,1C:a,1V:c})},78:G(b,a){I E.21(b,S,a,"1J")},77:G(c,b,a){I E.21(c,b,a,"45")},76:G(d,b,a,c){9(E.1n(b)){a=b;b={}}I E.3G({O:"5P",1d:d,M:b,1C:a,1V:c})},75:G(a){E.1k(E.59,a)},59:{1Z:Q,O:"4z",2z:0,5G:"74/x-73-2Y-72",6o:Q,3e:Q,M:S},49:{},3G:G(s){H f,2y=/=(\\?|%3F)/g,1v,M;s=E.1k(Q,s,E.1k(Q,{},E.59,s));9(s.M&&s.6o&&1m s.M!="1M")s.M=E.3a(s.M);9(s.1V=="4b"){9(s.O.2p()=="21"){9(!s.1d.1t(2y))s.1d+=(s.1d.1t(/\\?/)?"&":"?")+(s.4b||"5E")+"=?"}J 9(!s.M||!s.M.1t(2y))s.M=(s.M?s.M+"&":"")+(s.4b||"5E")+"=?";s.1V="45"}9(s.1V=="45"&&(s.M&&s.M.1t(2y)||s.1d.1t(2y))){f="4b"+B++;9(s.M)s.M=s.M.1p(2y,"="+f);s.1d=s.1d.1p(2y,"="+f);s.1V="1J";18[f]=G(a){M=a;1C();1l();18[f]=W;2a{2E 18[f]}29(e){}}}9(s.1V=="1J"&&s.1L==S)s.1L=P;9(s.1L===P&&s.O.2p()=="21")s.1d+=(s.1d.1t(/\\?/)?"&":"?")+"57="+(1u 3D()).3B();9(s.M&&s.O.2p()=="21"){s.1d+=(s.1d.1t(/\\?/)?"&":"?")+s.M;s.M=S}9(s.1Z&&!E.5b++)E.1j.1F("5L");9(!s.1d.1g("8g")&&s.1V=="1J"){H h=U.4l("9U")[0];H g=U.5B("1J");g.3k=s.1d;9(!f&&(s.1C||s.1l)){H j=P;g.9R=g.62=G(){9(!j&&(!6.2C||6.2C=="5Q"||6.2C=="1l")){j=Q;1C();1l();h.3b(g)}}}h.58(g);I}H k=P;H i=18.6X?1u 6X("9P.9O"):1u 6W();i.9M(s.O,s.1d,s.3e);9(s.M)i.5C("9J-9I",s.5G);9(s.5y)i.5C("9H-5x-9F",E.49[s.1d]||"9D, 9C 9B 9A 5v:5v:5v 9z");i.5C("X-9x-9v","6W");9(s.6U)s.6U(i);9(s.1Z)E.1j.1F("5H",[i,s]);H c=G(a){9(!k&&i&&(i.2C==4||a=="2z")){k=Q;9(d){4A(d);d=S}1v=a=="2z"&&"2z"||!E.6S(i)&&"3U"||s.5y&&E.6R(i,s.1d)&&"5O"||"1C";9(1v=="1C"){2a{M=E.6Q(i,s.1V)}29(e){1v="5k"}}9(1v=="1C"){H b;2a{b=i.5s("6P-5x")}29(e){}9(s.5y&&b)E.49[s.1d]=b;9(!f)1C()}J E.5r(s,i,1v);1l();9(s.3e)i=S}};9(s.3e){H d=4j(c,13);9(s.2z>0)56(G(){9(i){i.9q();9(!k)c("2z")}},s.2z)}2a{i.9o(s.M)}29(e){E.5r(s,i,S,e)}9(!s.3e)c();I i;G 1C(){9(s.1C)s.1C(M,1v);9(s.1Z)E.1j.1F("5I",[i,s])}G 1l(){9(s.1l)s.1l(i,1v);9(s.1Z)E.1j.1F("6t",[i,s]);9(s.1Z&&!--E.5b)E.1j.1F("5K")}},5r:G(s,a,b,e){9(s.3U)s.3U(a,b,e);9(s.1Z)E.1j.1F("5J",[a,s,e])},5b:0,6S:G(r){2a{I!r.1v&&9n.9l=="54:"||(r.1v>=6N&&r.1v<9j)||r.1v==6M||E.V.1N&&r.1v==W}29(e){}I P},6R:G(a,c){2a{H b=a.5s("6P-5x");I a.1v==6M||b==E.49[c]||E.V.1N&&a.1v==W}29(e){}I P},6Q:G(r,b){H c=r.5s("9i-O");H d=b=="6K"||!b&&c&&c.1g("6K")>=0;H a=d?r.9g:r.40;9(d&&a.2V.37=="5k")6G"5k";9(b=="1J")E.5f(a);9(b=="45")a=3w("("+a+")");I a},3a:G(a){H s=[];9(a.1c==1B||a.4c)E.N(a,G(){s.1a(3f(6.2H)+"="+3f(6.1Q))});J L(H j 1i a)9(a[j]&&a[j].1c==1B)E.N(a[j],G(){s.1a(3f(j)+"="+3f(6))});J s.1a(3f(j)+"="+3f(a[j]));I s.66("&").1p(/%20/g,"+")}});E.1b.1k({1A:G(b,a){I b?6.1U({1H:"1A",2N:"1A",1r:"1A"},b,a):6.1E(":1P").N(G(){6.R.19=6.3h?6.3h:"";9(E.17(6,"19")=="2s")6.R.19="2Z"}).2D()},1z:G(b,a){I b?6.1U({1H:"1z",2N:"1z",1r:"1z"},b,a):6.1E(":3R").N(G(){6.3h=6.3h||E.17(6,"19");9(6.3h=="2s")6.3h="2Z";6.R.19="2s"}).2D()},6J:E.1b.25,25:G(a,b){I E.1n(a)&&E.1n(b)?6.6J(a,b):a?6.1U({1H:"25",2N:"25",1r:"25"},a,b):6.N(G(){E(6)[E(6).3t(":1P")?"1A":"1z"]()})},9c:G(b,a){I 6.1U({1H:"1A"},b,a)},9b:G(b,a){I 6.1U({1H:"1z"},b,a)},99:G(b,a){I 6.1U({1H:"25"},b,a)},98:G(b,a){I 6.1U({1r:"1A"},b,a)},96:G(b,a){I 6.1U({1r:"1z"},b,a)},95:G(c,a,b){I 6.1U({1r:a},c,b)},1U:G(k,i,h,g){H j=E.6D(i,h,g);I 6[j.3L===P?"N":"3L"](G(){j=E.1k({},j);H f=E(6).3t(":1P"),3y=6;L(H p 1i k){9(k[p]=="1z"&&f||k[p]=="1A"&&!f)I E.1n(j.1l)&&j.1l.16(6);9(p=="1H"||p=="2N"){j.19=E.17(6,"19");j.2U=6.R.2U}}9(j.2U!=S)6.R.2U="1P";j.3M=E.1k({},k);E.N(k,G(c,a){H e=1u E.2j(3y,j,c);9(/25|1A|1z/.14(a))e[a=="25"?f?"1A":"1z":a](k);J{H b=a.3s().1t(/^([+-]=)?([\\d+-.]+)(.*)$/),1O=e.2b(Q)||0;9(b){H d=3I(b[2]),2i=b[3]||"2T";9(2i!="2T"){3y.R[c]=(d||1)+2i;1O=((d||1)/e.2b(Q))*1O;3y.R[c]=1O+2i}9(b[1])d=((b[1]=="-="?-1:1)*d)+1O;e.3N(1O,d,2i)}J e.3N(1O,a,"")}});I Q})},3L:G(a,b){9(E.1n(a)){b=a;a="2j"}9(!a||(1m a=="1M"&&!b))I A(6[0],a);I 6.N(G(){9(b.1c==1B)A(6,a,b);J{A(6,a).1a(b);9(A(6,a).K==1)b.16(6)}})},9f:G(){H a=E.32;I 6.N(G(){L(H i=0;i<a.K;i++)9(a[i].T==6)a.6I(i--,1)}).5n()}});H A=G(b,c,a){9(!b)I;H q=E.M(b,c+"3L");9(!q||a)q=E.M(b,c+"3L",a?E.2h(a):[]);I q};E.1b.5n=G(a){a=a||"2j";I 6.N(G(){H q=A(6,a);q.44();9(q.K)q[0].16(6)})};E.1k({6D:G(b,a,c){H d=b&&b.1c==8Z?b:{1l:c||!c&&a||E.1n(b)&&b,2e:b,3J:c&&a||a&&a.1c!=8Y&&a};d.2e=(d.2e&&d.2e.1c==4W?d.2e:{8X:8W,8V:6N}[d.2e])||8T;d.3r=d.1l;d.1l=G(){E(6).5n();9(E.1n(d.3r))d.3r.16(6)};I d},3J:{6B:G(p,n,b,a){I b+a*p},5q:G(p,n,b,a){I((-38.9s(p*38.8R)/2)+0.5)*a+b}},32:[],2j:G(b,c,a){6.Y=c;6.T=b;6.1e=a;9(!c.3P)c.3P={}}});E.2j.3A={4r:G(){9(6.Y.2F)6.Y.2F.16(6.T,[6.2v,6]);(E.2j.2F[6.1e]||E.2j.2F.6z)(6);9(6.1e=="1H"||6.1e=="2N")6.T.R.19="2Z"},2b:G(a){9(6.T[6.1e]!=S&&6.T.R[6.1e]==S)I 6.T[6.1e];H r=3I(E.3C(6.T,6.1e,a));I r&&r>-8O?r:3I(E.17(6.T,6.1e))||0},3N:G(c,b,e){6.5u=(1u 3D()).3B();6.1O=c;6.2D=b;6.2i=e||6.2i||"2T";6.2v=6.1O;6.4q=6.4i=0;6.4r();H f=6;G t(){I f.2F()}t.T=6.T;E.32.1a(t);9(E.32.K==1){H d=4j(G(){H a=E.32;L(H i=0;i<a.K;i++)9(!a[i]())a.6I(i--,1);9(!a.K)4A(d)},13)}},1A:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1A=Q;6.3N(0,6.2b());9(6.1e=="2N"||6.1e=="1H")6.T.R[6.1e]="8N";E(6.T).1A()},1z:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1z=Q;6.3N(6.2b(),0)},2F:G(){H t=(1u 3D()).3B();9(t>6.Y.2e+6.5u){6.2v=6.2D;6.4q=6.4i=1;6.4r();6.Y.3M[6.1e]=Q;H a=Q;L(H i 1i 6.Y.3M)9(6.Y.3M[i]!==Q)a=P;9(a){9(6.Y.19!=S){6.T.R.2U=6.Y.2U;6.T.R.19=6.Y.19;9(E.17(6.T,"19")=="2s")6.T.R.19="2Z"}9(6.Y.1z)6.T.R.19="2s";9(6.Y.1z||6.Y.1A)L(H p 1i 6.Y.3M)E.1x(6.T.R,p,6.Y.3P[p])}9(a&&E.1n(6.Y.1l))6.Y.1l.16(6.T);I P}J{H n=t-6.5u;6.4i=n/6.Y.2e;6.4q=E.3J[6.Y.3J||(E.3J.5q?"5q":"6B")](6.4i,n,0,1,6.Y.2e);6.2v=6.1O+((6.2D-6.1O)*6.4q);6.4r()}I Q}};E.2j.2F={2R:G(a){a.T.2R=a.2v},2B:G(a){a.T.2B=a.2v},1r:G(a){E.1x(a.T.R,"1r",a.2v)},6z:G(a){a.T.R[a.1e]=a.2v+a.2i}};E.1b.6m=G(){H c=0,3E=0,T=6[0],5t;9(T)8L(E.V){H b=E.17(T,"2X")=="4F",1D=T.12,23=T.23,2K=T.3H,4f=1N&&3x(4s)<8J;9(T.6V){5w=T.6V();1f(5w.1S+38.33(2K.2V.2R,2K.1G.2R),5w.3E+38.33(2K.2V.2B,2K.1G.2B));9(1h){H d=E("4o").17("8H");d=(d=="8G"||E.5g&&3x(4s)>=7)&&2||d;1f(-d,-d)}}J{1f(T.5l,T.5z);1W(23){1f(23.5l,23.5z);9(35&&/^t[d|h]$/i.14(1D.37)||!4f)d(23);9(4f&&!b&&E.17(23,"2X")=="4F")b=Q;23=23.23}1W(1D.37&&!/^1G|4o$/i.14(1D.37)){9(!/^8D|1I-9S.*$/i.14(E.17(1D,"19")))1f(-1D.2R,-1D.2B);9(35&&E.17(1D,"2U")!="3R")d(1D);1D=1D.12}9(4f&&b)1f(-2K.1G.5l,-2K.1G.5z)}5t={3E:3E,1S:c}}I 5t;G d(a){1f(E.17(a,"9T"),E.17(a,"8A"))}G 1f(l,t){c+=3x(l)||0;3E+=3x(t)||0}}})();',62,616,'||||||this|||if|||||||||||||||||||||||||||||||||function|var|return|else|length|for|data|each|type|false|true|style|null|elem|document|browser|undefined||options|||nodeName|parentNode||test|jQuery|apply|css|window|display|push|fn|constructor|url|prop|add|indexOf|msie|in|event|extend|complete|typeof|isFunction|className|replace|arguments|opacity|div|match|new|status|firstChild|attr|nodeType|hide|show|Array|success|parent|filter|trigger|body|height|table|script|tbody|cache|string|safari|start|hidden|value|merge|left|break|animate|dataType|while|map|find|global||get|id|offsetParent|select|toggle|selected|toUpperCase|remove|catch|try|cur|al|ready|duration|done|text|makeArray|unit|fx|swap|split|target||pushStack|toLowerCase|nextSibling|button|none|handle|guid|now|stack|tb|jsre|timeout|inArray|scrollTop|readyState|end|delete|step|one|name|nth|slice|doc|ret|preventDefault|width|call|events|checked|scrollLeft|exec|px|overflow|documentElement|grep|position|form|block|removeData|rl|timers|max|opera|mozilla|trim|tagName|Math|load|param|removeChild|disabled|insertBefore|async|encodeURIComponent|append|oldblock|val|childNodes|src|readyList|multiFilter|color|defaultView|stopPropagation|args|old|toString|is|last|first|eval|parseInt|self|domManip|prototype|getTime|curCSS|Date|top||ajax|ownerDocument|parseFloat|easing|has|queue|curAnim|custom|innerHTML|orig|currentStyle|visible|getElementById|isReady|error|static|bind|String|which|getComputedStyle|responseText|oWidth|oHeight|on|shift|json|child|RegExp|ol|lastModified|isXMLDoc|jsonp|jquery|previousSibling|dir|safari2|el|styleFloat|state|setInterval|radio|getElementsByTagName|tr|empty|html|getAttribute|pos|update|version|input|float|runtimeStyle|unshift|mouseover|getPropertyValue|GET|clearInterval|safariTimer|visibility|clean|__ie_init|absolute|handleHover|lastToggle|index|fromElement|relatedTarget|click|fix|evt|andSelf|removeEventListener|handler|cloneNode|addEventListener|triggered|nodeIndex|unique|Number|classFilter|prevObject|selectedIndex|after|submit|password|removeAttribute|file|expr|setTimeout|_|appendChild|ajaxSettings|client|active|win|sibling|deep|globalEval|boxModel|cssFloat|object|checkbox|parsererror|offsetLeft|wrapAll|dequeue|props|lastChild|swing|handleError|getResponseHeader|results|startTime|00|box|Modified|ifModified|offsetTop|evalScript|createElement|setRequestHeader|ctrlKey|callback|metaKey|contentType|ajaxSend|ajaxSuccess|ajaxError|ajaxStop|ajaxStart|serializeArray|init|notmodified|POST|loaded|appendTo|DOMContentLoaded|bindReady|mouseout|not|removeAttr|unbind|unload|Width|keyCode|charCode|onreadystatechange|clientX|pageX|srcElement|join|outerHTML|substr|zoom|parse|textarea|reset|image|odd|even|before|quickClass|quickID|prepend|quickChild|execScript|offset|scroll|processData|uuid|contents|continue|textContent|ajaxComplete|clone|setArray|webkit|nodeValue|fl|_default|100|linear|href|speed|eq|createTextNode|throw|replaceWith|splice|_toggle|xml|colgroup|304|200|alpha|Last|httpData|httpNotModified|httpSuccess|fieldset|beforeSend|getBoundingClientRect|XMLHttpRequest|ActiveXObject|col|br|abbr|pixelLeft|urlencoded|www|application|ajaxSetup|post|getJSON|getScript|elements|serialize|clientWidth|hasClass|scr|clientHeight|write|relative|keyup|keypress|keydown|change|mousemove|mouseup|mousedown|right|dblclick|resize|focus|blur|frames|instanceof|hover|offsetWidth|triggerHandler|ipt|defer|offsetHeight|border|padding|clientY|pageY|Left|Right|toElement|Bottom|Top|cancelBubble|returnValue|detachEvent|attachEvent|substring|line|weight|animated|header|font|enabled|innerText|contains|only|size|gt|lt|uFFFF|u0128|417|inner|Height|toggleClass|removeClass|addClass|replaceAll|noConflict|insertAfter|prependTo|wrap|contentWindow|contentDocument|http|iframe|children|siblings|prevAll|nextAll|wrapInner|prev|Boolean|next|parents|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|compatible|borderTopWidth|ie|ra|inline|it|rv|medium|borderWidth|userAgent|522|navigator|with|concat|1px|10000|array|ig|PI|NaN|400|reverse|fast|600|slow|Function|Object|setAttribute|changed|be|can|property|fadeTo|fadeOut|getAttributeNode|fadeIn|slideToggle|method|slideUp|slideDown|action|cssText|stop|responseXML|option|content|300|th|protocol|td|location|send|cap|abort|colg|cos|tfoot|thead|With|leg|Requested|opt|GMT|1970|Jan|01|Thu|area|Since|hr|If|Type|Content|meta|specified|open|link|XMLHTTP|Microsoft|img|onload|row|borderLeftWidth|head|attributes'.split('|'),0,{}))
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/js/jquery-speakers_coaches_consultants.js
ADDED
@@ -0,0 +1,30 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
jQuery(function($) {
|
2 |
+
var themap = $('<div id="themap"></div>').css({
|
3 |
+
'width': '90%',
|
4 |
+
'height': '500px'
|
5 |
+
}).insertBefore('ul.people');
|
6 |
+
|
7 |
+
var mapstraction = new Mapstraction('themap','google');
|
8 |
+
mapstraction.addControls({
|
9 |
+
zoom: 'large',
|
10 |
+
map_type: true
|
11 |
+
});
|
12 |
+
|
13 |
+
mapstraction.setCenterAndZoom(
|
14 |
+
new LatLonPoint(30, -0.126236),
|
15 |
+
2 // Zoom level appropriate for Brighton city centre
|
16 |
+
);
|
17 |
+
|
18 |
+
$('.vcard').each(function() {
|
19 |
+
var hcard = $(this);
|
20 |
+
|
21 |
+
var latitude = hcard.find('.geo .latitude').text();
|
22 |
+
var longitude = hcard.find('.geo .longitude').text();
|
23 |
+
|
24 |
+
var marker = new Marker(new LatLonPoint(latitude, longitude));
|
25 |
+
marker.setInfoBubble(
|
26 |
+
'<div class="bubble">' + hcard.html() + '</div>'
|
27 |
+
);
|
28 |
+
mapstraction.addMarker(marker);
|
29 |
+
});
|
30 |
+
});
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/simpletest.css
ADDED
@@ -0,0 +1,39 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/* SimpleTest - Unit Testing for PHP */
|
2 |
+
body { font-family : georgia, serif; }
|
3 |
+
img { border : 0; }
|
4 |
+
h1 { color : #009933; }
|
5 |
+
blockquote { background: transparent url('images/quote.png') left top no-repeat; font-style : italic; padding-left : 40px; margin-left : 10px; }
|
6 |
+
td { vertical-align : top; }
|
7 |
+
|
8 |
+
#logo { margin-bottom : 20px; }
|
9 |
+
#credits { margin-top : 40px; }
|
10 |
+
#actions { position : absolute; top : 20px; left : 40px; width : 335px; }
|
11 |
+
#actions div { width : 305px; }
|
12 |
+
#content { position : absolute; top : 20px; left : 400px; padding-bottom : 50px; width : 491px; }
|
13 |
+
#news { border : 2px solid #009933; padding : 20px; font-weight : bold; font-size : 18pt; width : 451px; }
|
14 |
+
#news a { color : #009933; }
|
15 |
+
#internal { background: url('images/simpletest-internal-middle.png') repeat-y; margin-top : 2em; width : 306px; }
|
16 |
+
#external { background: url('images/simpletest-external-middle.png') repeat-y; width : 306px; }
|
17 |
+
#internal > div , #external > div { padding : 0 0.5em 0 0.5em; }
|
18 |
+
|
19 |
+
div.console { background-color: black; border: 4px ridge; border-color: gray; color : white; margin: 5px 40px 20px 20px; padding: 10px; }
|
20 |
+
div.demo { background-color: white; border: 4px ridge; border-color: gray; margin: 5px; margin-left: 20px; margin-right: 40px; padding: 10px; }
|
21 |
+
div.demo span.fail { color: red; }
|
22 |
+
div.demo span.pass { color: green; }
|
23 |
+
div.demo h1 { color: black; font-size: 12pt; font-weight: bold; text-align: left; }
|
24 |
+
pre { font-family: monospaced; border-left: 1px solid #999999; background-color: white; padding: 5px; margin-left: 5px; font-size : 10pt; }
|
25 |
+
|
26 |
+
.screenshot { border : 1px solid #cccccc;}
|
27 |
+
.experimental { background-color : yellow; border : 4px dashed black; padding : 10px; }
|
28 |
+
.experimental pre { border-left : none; background-color : yellow; }
|
29 |
+
.bubble, .bubble h3 { font-size: 9pt; }
|
30 |
+
.people { margin : 0; list-style : none; padding : 0; }
|
31 |
+
.geo { color : #777777; }
|
32 |
+
.photo { margin-bottom : 2em; }
|
33 |
+
.photo span { display : block; }
|
34 |
+
.photo span.title { font-weight : bold; margin-top : 1em; }
|
35 |
+
.photo img { border : 1px solid #777777; padding : 1em; margin : 1em; }
|
36 |
+
|
37 |
+
dd { font-size : 10.5pt; }
|
38 |
+
.done, .done span, .done + dd { color : #AAAAAA; text-decoration : line-through; }
|
39 |
+
.postponed, .postponed span, .postponed + dd { color : #AAAAAA; }
|
lib/Minify/min_unit_tests/simpletest/docs/simpletest.org/views/photos_stream.php
ADDED
@@ -0,0 +1,36 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (!function_exists("simplexml_load_file")) {
|
4 |
+
die("Whenever SourceForge.net updates to PHP5 :-(");
|
5 |
+
}
|
6 |
+
|
7 |
+
$feed = "http://api.flickr.com/services/feeds/photos_public.gne?tags=simpletest&format=atom&en-us";
|
8 |
+
$source = simplexml_load_file($feed, "SimpleFlickrStreamXMLElement");
|
9 |
+
echo $source->showLastPhotos();
|
10 |
+
|
11 |
+
class SimpleFlickrStreamXMLElement extends SimpleXMLElement {
|
12 |
+
function showLastPhotos() {
|
13 |
+
$html = "";
|
14 |
+
foreach ($this->entry as $entry) {
|
15 |
+
$html .= "<div class=\"photo\">";
|
16 |
+
$html .= "<span class=\"title\">".$entry->title."</span>";
|
17 |
+
$html .= "<span class=\"image\">".$this->extractFirstImage($entry)."</span>";
|
18 |
+
$html .= "<span class=\"author\">".$this->extractAuthor($entry)."</span>";
|
19 |
+
$html .= "</div>";
|
20 |
+
}
|
21 |
+
return $html;
|
22 |
+
}
|
23 |
+
|
24 |
+
function extractAuthor($entry) {
|
25 |
+
return "<a href=\"".$entry->author->uri."\">".$entry->author->name."</a>";
|
26 |
+
}
|
27 |
+
|
28 |
+
function extractFirstImage($entry) {
|
29 |
+
$content = $entry->content;
|
30 |
+
$content = substr($content, strpos($content, "<img src"));
|
31 |
+
$image = substr($content, 0, strpos($content, " />") + 3);
|
32 |
+
|
33 |
+
return "<a href=\"".$entry->link[0]['href']."\">".$image."</a>";
|
34 |
+
}
|
35 |
+
}
|
36 |
+
?>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/about.xml
ADDED
@@ -0,0 +1,116 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: about.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="About Last Craft" here="About">
|
4 |
+
<long_title>About Last Craft</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="me" title="People">
|
7 |
+
<p>
|
8 |
+
<img src="../images/marcus.jpg" />
|
9 |
+
At the moment this site is maintained by myself,
|
10 |
+
<a href="mailto:marcus@lastcraft.com">Marcus Baker</a>
|
11 |
+
and I am an <a href="marcus_cv.html">Object Oriented web developer</a>
|
12 |
+
and father of two.
|
13 |
+
I am currently a freelancer working as a senior developer for
|
14 |
+
<a href="http://www.wordtracker.com">Wordtracker</a>
|
15 |
+
and as a consultant to various smaller companies.
|
16 |
+
Wordtracker is an internet statistics company with a huge database
|
17 |
+
of search engine keyword popularity.
|
18 |
+
The company software development is eXtreme Programming based.
|
19 |
+
</p>
|
20 |
+
<p>
|
21 |
+
My wife <a href="mailto:aviva@lastcraft.com">Aviva Racher</a> is a
|
22 |
+
microbiologist and Mother of the same two.
|
23 |
+
</p>
|
24 |
+
<p>
|
25 |
+
Bryn was born on the 30th of July 2004.
|
26 |
+
He is doing very well.
|
27 |
+
</p>
|
28 |
+
</section>
|
29 |
+
<section name="issues" title="Issues">
|
30 |
+
<p>
|
31 |
+
Read the interview <a
|
32 |
+
href="http://www.oreillynet.com/pub/a/patents/2000/05/24/PizzoFiles.html">
|
33 |
+
Who's really being protected?</a> on the
|
34 |
+
O'Reilly network if you have an interest in software patents.
|
35 |
+
</p>
|
36 |
+
</section>
|
37 |
+
<section name="associations" title="Associations">
|
38 |
+
<p>
|
39 |
+
Besides working for Wordtracker, I also act as an independent
|
40 |
+
consultant.
|
41 |
+
Usually in relation to bringing agile development practices into an
|
42 |
+
organisation.
|
43 |
+
Clients include Waterscape and Amnesty International.
|
44 |
+
</p>
|
45 |
+
<p>
|
46 |
+
I did a quick site for a graphic designer and illustrator friend of mine,
|
47 |
+
<a href="http://www.dylanbeck.com/">Dylan Beck</a>.
|
48 |
+
He has a very unique style.
|
49 |
+
</p>
|
50 |
+
<p>
|
51 |
+
The <a href="om/">Ambassadors of Om</a> are a Jazz-Funk
|
52 |
+
fusion (?) band with an internet presence going back over five
|
53 |
+
years. Site includes samples, videos and links. The band is
|
54 |
+
managed by guitarist and lead singer <a
|
55 |
+
href="mailto:wahg@cwcom.net">Paul Grimes</a> who is a friend of ours.
|
56 |
+
</p>
|
57 |
+
<p>
|
58 |
+
<a href="mailto:mark@leisurepursuits.demon.co.uk">
|
59 |
+
Mark Eichner</a> is Aviva's uncle and run's the
|
60 |
+
<a href="http://www.leisurepursuits.demon.co.uk">
|
61 |
+
Leisure Pursuits</a>
|
62 |
+
off-road driving school. Lots of wheels and mud!
|
63 |
+
</p>
|
64 |
+
</section>
|
65 |
+
</content>
|
66 |
+
<internal>
|
67 |
+
<link>
|
68 |
+
<a href="#me">Last Craft people</a>
|
69 |
+
Myself and friends and relations.
|
70 |
+
</link>
|
71 |
+
<link>
|
72 |
+
<a href="#issues">Issues</a> that I care about.
|
73 |
+
</link>
|
74 |
+
<link>
|
75 |
+
<a href="#associations">Associated companies</a>
|
76 |
+
and people.
|
77 |
+
</link>
|
78 |
+
</internal>
|
79 |
+
|
80 |
+
<external>
|
81 |
+
<link>
|
82 |
+
<a href="http://www.xpdeveloper.com/cgi-bin/wiki.cgi?MarcuS">Extreme Tuesday</a>
|
83 |
+
Club is an informal meeting in London to promote
|
84 |
+
<a href="http://www.extremeprogramming.org/">Extreme programming</a>.
|
85 |
+
</link>
|
86 |
+
<link>
|
87 |
+
<a href="http://www.phplondon.org/">PHPLondon</a>
|
88 |
+
is a user group that meets the first thursday of every month.
|
89 |
+
</link>
|
90 |
+
<link>
|
91 |
+
<a href="http://www.wordtracker.com">Wordtracker</a>
|
92 |
+
crunches internet search data for web marketing.
|
93 |
+
</link>
|
94 |
+
</external>
|
95 |
+
<meta>
|
96 |
+
<keywords>
|
97 |
+
software development,
|
98 |
+
computer programmer,
|
99 |
+
php programming,
|
100 |
+
programming php,
|
101 |
+
software development company,
|
102 |
+
software development uk,
|
103 |
+
php tutorial,
|
104 |
+
bespoke software development uk,
|
105 |
+
corporate web development,
|
106 |
+
architecture,
|
107 |
+
freelancer,
|
108 |
+
php resources,
|
109 |
+
wordtracker,
|
110 |
+
web marketing,
|
111 |
+
serach engines,
|
112 |
+
web positioning,
|
113 |
+
internet marketing
|
114 |
+
</keywords>
|
115 |
+
</meta>
|
116 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/authentication_documentation.xml
ADDED
@@ -0,0 +1,317 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: authentication_documentation.xml 1684 2008-03-06 08:36:59Z pp11 $ -->
|
3 |
+
<page title="Authentication documentation" here="Authentication">
|
4 |
+
<long_title>SimpleTest documentation for testing log-in and authentication</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<p>
|
8 |
+
One of the trickiest, and yet most important, areas
|
9 |
+
of testing web sites is the security.
|
10 |
+
Testing these schemes is one of the core goals of
|
11 |
+
the SimpleTest web tester.
|
12 |
+
</p>
|
13 |
+
</introduction>
|
14 |
+
<section name="basic" title="Basic HTTP authentication">
|
15 |
+
<p>
|
16 |
+
If you fetch a page protected by basic authentication then
|
17 |
+
rather than receiving content, you will instead get a 401
|
18 |
+
header.
|
19 |
+
We can illustrate this with this test...
|
20 |
+
<php><![CDATA[
|
21 |
+
class AuthenticationTest extends WebTestCase {<strong>
|
22 |
+
function test401Header() {
|
23 |
+
$this->get('http://www.lastcraft.com/protected/');
|
24 |
+
$this->showHeaders();
|
25 |
+
}</strong>
|
26 |
+
}
|
27 |
+
]]></php>
|
28 |
+
This allows us to see the challenge header...
|
29 |
+
<div class="demo">
|
30 |
+
<h1>File test</h1>
|
31 |
+
<pre style="background-color: lightgray; color: black"><![CDATA[
|
32 |
+
HTTP/1.1 401 Authorization Required
|
33 |
+
Date: Sat, 18 Sep 2004 19:25:18 GMT
|
34 |
+
Server: Apache/1.3.29 (Unix) PHP/4.3.4
|
35 |
+
WWW-Authenticate: Basic realm="SimpleTest basic authentication"
|
36 |
+
Connection: close
|
37 |
+
Content-Type: text/html; charset=iso-8859-1
|
38 |
+
]]></pre>
|
39 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
|
40 |
+
<strong>0</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
|
41 |
+
</div>
|
42 |
+
We are trying to get away from visual inspection though, and so SimpleTest
|
43 |
+
allows to make automated assertions against the challenge.
|
44 |
+
Here is a thorough test of our header...
|
45 |
+
<php><![CDATA[
|
46 |
+
class AuthenticationTest extends WebTestCase {
|
47 |
+
function test401Header() {
|
48 |
+
$this->get('http://www.lastcraft.com/protected/');<strong>
|
49 |
+
$this->assertAuthentication('Basic');
|
50 |
+
$this->assertResponse(401);
|
51 |
+
$this->assertRealm('SimpleTest basic authentication');</strong>
|
52 |
+
}
|
53 |
+
}
|
54 |
+
]]></php>
|
55 |
+
Any one of these tests would normally do on it's own depending
|
56 |
+
on the amount of detail you want to see.
|
57 |
+
</p>
|
58 |
+
<p>
|
59 |
+
One theme that runs through SimpleTest is the ability to use
|
60 |
+
<code>SimpleExpectation</code> objects wherever a simple
|
61 |
+
match is not enough.
|
62 |
+
If you want only an approximate match to the realm for
|
63 |
+
example, you can do this...
|
64 |
+
<php><![CDATA[
|
65 |
+
class AuthenticationTest extends WebTestCase {
|
66 |
+
function test401Header() {
|
67 |
+
$this->get('http://www.lastcraft.com/protected/');
|
68 |
+
$this->assertRealm(<strong>new PatternExpectation('/simpletest/i')</strong>);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
]]></php>
|
72 |
+
Most of the time we are not interested in testing the
|
73 |
+
authentication itself, but want to get past it to test
|
74 |
+
the pages underneath.
|
75 |
+
As soon as the challenge has been issued we can reply with
|
76 |
+
an authentication response...
|
77 |
+
<php><![CDATA[
|
78 |
+
class AuthenticationTest extends WebTestCase {
|
79 |
+
function testCanAuthenticate() {
|
80 |
+
$this->get('http://www.lastcraft.com/protected/');<strong>
|
81 |
+
$this->authenticate('Me', 'Secret');</strong>
|
82 |
+
$this->assertTitle(...);
|
83 |
+
}
|
84 |
+
}
|
85 |
+
]]></php>
|
86 |
+
The username and password will now be sent with every
|
87 |
+
subsequent request to that directory and subdirectories.
|
88 |
+
You will have to authenticate again if you step outside
|
89 |
+
the authenticated directory, but SimpleTest is smart enough
|
90 |
+
to merge subdirectories into a common realm.
|
91 |
+
</p>
|
92 |
+
<p>
|
93 |
+
You can shortcut this step further by encoding the log in
|
94 |
+
details straight into the URL...
|
95 |
+
<php><![CDATA[
|
96 |
+
class AuthenticationTest extends WebTestCase {
|
97 |
+
function testCanReadAuthenticatedPages() {
|
98 |
+
$this->get('http://<strong>Me:Secret@</strong>www.lastcraft.com/protected/');
|
99 |
+
$this->assertTitle(...);
|
100 |
+
}
|
101 |
+
}
|
102 |
+
]]></php>
|
103 |
+
If your username or password has special characters, then you
|
104 |
+
will have to URL encode them or the request will not be parsed
|
105 |
+
correctly.
|
106 |
+
Also this header will not be sent on subsequent requests if
|
107 |
+
you request a page with a fully qualified URL.
|
108 |
+
If you navigate with relative URLs though, the authentication
|
109 |
+
information will be preserved.
|
110 |
+
</p>
|
111 |
+
<p>
|
112 |
+
Only basic authentication is currently supported and this is
|
113 |
+
only really secure in tandem with HTTPS connections.
|
114 |
+
This is usually enough to protect test server from prying eyes,
|
115 |
+
however.
|
116 |
+
Digest authentication and NTLM authentication may be added
|
117 |
+
in the future.
|
118 |
+
</p>
|
119 |
+
</section>
|
120 |
+
<section name="cookies" title="Cookies">
|
121 |
+
<p>
|
122 |
+
Basic authentication doesn't give enough control over the
|
123 |
+
user interface for web developers.
|
124 |
+
More likely this functionality will be coded directly into
|
125 |
+
the web architecture using cookies and complicated timeouts.
|
126 |
+
</p>
|
127 |
+
<p>
|
128 |
+
Starting with a simple log-in form...
|
129 |
+
<pre><![CDATA[
|
130 |
+
<form>
|
131 |
+
Username:
|
132 |
+
<input type="text" name="u" value="" /><br />
|
133 |
+
Password:
|
134 |
+
<input type="password" name="p" value="" /><br />
|
135 |
+
<input type="submit" value="Log in" />
|
136 |
+
</form>
|
137 |
+
]]></pre>
|
138 |
+
Which looks like...
|
139 |
+
</p>
|
140 |
+
<p>
|
141 |
+
<form class="demo">
|
142 |
+
Username:
|
143 |
+
<input type="text" name="u" value="" /><br />
|
144 |
+
Password:
|
145 |
+
<input type="password" name="p" value="" /><br />
|
146 |
+
<input type="submit" value="Log in" />
|
147 |
+
</form>
|
148 |
+
</p>
|
149 |
+
<p>
|
150 |
+
Let's suppose that in fetching this page a cookie has been
|
151 |
+
set with a session ID.
|
152 |
+
We are not going to fill the form in yet, just test that
|
153 |
+
we are tracking the user.
|
154 |
+
Here is the test...
|
155 |
+
<php><![CDATA[
|
156 |
+
class LogInTest extends WebTestCase {
|
157 |
+
function testSessionCookieSetBeforeForm() {
|
158 |
+
$this->get('http://www.my-site.com/login.php');<strong>
|
159 |
+
$this->assertCookie('SID');</strong>
|
160 |
+
}
|
161 |
+
}
|
162 |
+
]]></php>
|
163 |
+
All we are doing is confirming that the cookie is set.
|
164 |
+
As the value is likely to be rather cryptic it's not
|
165 |
+
really worth testing this with...
|
166 |
+
<php><![CDATA[
|
167 |
+
class LogInTest extends WebTestCase {
|
168 |
+
function testSessionCookieIsCorrectPattern() {
|
169 |
+
$this->get('http://www.my-site.com/login.php');
|
170 |
+
$this->assertCookie('SID', <strong>new PatternExpectation('/[a-f0-9]{32}/i')</strong>);
|
171 |
+
}
|
172 |
+
}
|
173 |
+
]]></php>
|
174 |
+
The rest of the test would be the same as any other form,
|
175 |
+
but we might want to confirm that we still have the same
|
176 |
+
cookie after log-in as before we entered.
|
177 |
+
We wouldn't want to lose track of this after all.
|
178 |
+
Here is a possible test for this...
|
179 |
+
<php><![CDATA[
|
180 |
+
class LogInTest extends WebTestCase {
|
181 |
+
...
|
182 |
+
function testSessionCookieSameAfterLogIn() {
|
183 |
+
$this->get('http://www.my-site.com/login.php');<strong>
|
184 |
+
$session = $this->getCookie('SID');
|
185 |
+
$this->setField('u', 'Me');
|
186 |
+
$this->setField('p', 'Secret');
|
187 |
+
$this->click('Log in');
|
188 |
+
$this->assertText('Welcome Me');
|
189 |
+
$this->assertCookie('SID', $session);</strong>
|
190 |
+
}
|
191 |
+
}
|
192 |
+
]]></php>
|
193 |
+
This confirms that the session identifier is maintained
|
194 |
+
afer log-in.
|
195 |
+
</p>
|
196 |
+
<p>
|
197 |
+
We could even attempt to spoof our own system by setting
|
198 |
+
arbitrary cookies to gain access...
|
199 |
+
<php><![CDATA[
|
200 |
+
class LogInTest extends WebTestCase {
|
201 |
+
...
|
202 |
+
function testSessionCookieSameAfterLogIn() {
|
203 |
+
$this->get('http://www.my-site.com/login.php');<strong>
|
204 |
+
$this->setCookie('SID', 'Some other session');
|
205 |
+
$this->get('http://www.my-site.com/restricted.php');</strong>
|
206 |
+
$this->assertText('Access denied');
|
207 |
+
}
|
208 |
+
}
|
209 |
+
]]></php>
|
210 |
+
Is your site protected from this attack?
|
211 |
+
</p>
|
212 |
+
</section>
|
213 |
+
<section name="session" title="Browser sessions">
|
214 |
+
<p>
|
215 |
+
If you are testing an authentication system a critical piece
|
216 |
+
of behaviour is what happens when a user logs back in.
|
217 |
+
We would like to simulate closing and reopening a browser...
|
218 |
+
<php><![CDATA[
|
219 |
+
class LogInTest extends WebTestCase {
|
220 |
+
...
|
221 |
+
function testLoseAuthenticationAfterBrowserClose() {
|
222 |
+
$this->get('http://www.my-site.com/login.php');
|
223 |
+
$this->setField('u', 'Me');
|
224 |
+
$this->setField('p', 'Secret');
|
225 |
+
$this->click('Log in');
|
226 |
+
$this->assertText('Welcome Me');<strong>
|
227 |
+
|
228 |
+
$this->restart();
|
229 |
+
$this->get('http://www.my-site.com/restricted.php');
|
230 |
+
$this->assertText('Access denied');</strong>
|
231 |
+
}
|
232 |
+
}
|
233 |
+
]]></php>
|
234 |
+
The <code>WebTestCase::restart()</code> method will
|
235 |
+
preserve cookies that have unexpired timeouts, but throw away
|
236 |
+
those that are temporary or expired.
|
237 |
+
You can optionally specify the time and date that the restart
|
238 |
+
happened.
|
239 |
+
</p>
|
240 |
+
<p>
|
241 |
+
Expiring cookies can be a problem.
|
242 |
+
After all, if you have a cookie that expires after an hour,
|
243 |
+
you don't want to stall the test for an hour while the
|
244 |
+
cookie passes it's timeout.
|
245 |
+
</p>
|
246 |
+
<p>
|
247 |
+
To push the cookies over the hour limit you can age them
|
248 |
+
before you restart the session...
|
249 |
+
<php><![CDATA[
|
250 |
+
class LogInTest extends WebTestCase {
|
251 |
+
...
|
252 |
+
function testLoseAuthenticationAfterOneHour() {
|
253 |
+
$this->get('http://www.my-site.com/login.php');
|
254 |
+
$this->setField('u', 'Me');
|
255 |
+
$this->setField('p', 'Secret');
|
256 |
+
$this->click('Log in');
|
257 |
+
$this->assertText('Welcome Me');
|
258 |
+
<strong>
|
259 |
+
$this->ageCookies(3600);</strong>
|
260 |
+
$this->restart();
|
261 |
+
$this->get('http://www.my-site.com/restricted.php');
|
262 |
+
$this->assertText('Access denied');
|
263 |
+
}
|
264 |
+
}
|
265 |
+
]]></php>
|
266 |
+
After the restart it will appear that cookies are an
|
267 |
+
hour older and any that pass their expiry will have
|
268 |
+
disappeared.
|
269 |
+
</p>
|
270 |
+
</section>
|
271 |
+
</content>
|
272 |
+
<internal>
|
273 |
+
<link>
|
274 |
+
Getting through <a href="#basic">Basic HTTP authentication</a>
|
275 |
+
</link>
|
276 |
+
<link>
|
277 |
+
Testing <a href="#cookies">cookie based authentication</a>
|
278 |
+
</link>
|
279 |
+
<link>
|
280 |
+
Managing <a href="#session">browser sessions</a> and timeouts
|
281 |
+
</link>
|
282 |
+
</internal>
|
283 |
+
<external>
|
284 |
+
<link>
|
285 |
+
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
286 |
+
</link>
|
287 |
+
<link>
|
288 |
+
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
289 |
+
</link>
|
290 |
+
<link>
|
291 |
+
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
292 |
+
gives full detail on the classes and assertions available.
|
293 |
+
</link>
|
294 |
+
</external>
|
295 |
+
<meta>
|
296 |
+
<keywords>
|
297 |
+
software development,
|
298 |
+
php programming for clients,
|
299 |
+
customer focused php,
|
300 |
+
software development tools,
|
301 |
+
acceptance testing framework,
|
302 |
+
free php scripts,
|
303 |
+
log in boxes,
|
304 |
+
unit testing authentication systems,
|
305 |
+
php resources,
|
306 |
+
HTMLUnit,
|
307 |
+
JWebUnit,
|
308 |
+
php testing,
|
309 |
+
unit test resource,
|
310 |
+
web testing,
|
311 |
+
HTTP authentication,
|
312 |
+
testing log in,
|
313 |
+
authentication testing,
|
314 |
+
security tests
|
315 |
+
</keywords>
|
316 |
+
</meta>
|
317 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/books_website.xml
ADDED
@@ -0,0 +1,73 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: books_website.xml 1684 2008-03-06 08:36:59Z pp11 $ -->
|
3 |
+
<page title="Books" here="Books">
|
4 |
+
<long_title>Books in and around SimpleTest</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="latest-recommandation" title="Latest recommandation">
|
7 |
+
<p>
|
8 |
+
From time to time a book is recommanded on the mailing-list, you can find it here
|
9 |
+
with the original comments !
|
10 |
+
</p>
|
11 |
+
<p>
|
12 |
+
<a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215?ie=UTF8&tag=simpletest-21&"><img src="../images/book-domain-driven-design.jpg" alt="Domain-Driven Design: Tackling Complexity in the Heart of Software" /></a>
|
13 |
+
</p>
|
14 |
+
<blockquote>
|
15 |
+
TDD is a lot about the mechanics of coding, but it says you are done
|
16 |
+
when there is no duplication. DDD considers the code in constant churn,
|
17 |
+
always renaming as the domain becomes clear and also feeding terms back
|
18 |
+
into the domain as the code evolves.<br />
|
19 |
+
<br />
|
20 |
+
Anyways, it's a great book :) [<a href="http://sourceforge.net/mailarchive/message.php?msg_id=37546605">source</a>]
|
21 |
+
</blockquote>
|
22 |
+
</section>
|
23 |
+
<section name="books-by-contributors" title="Books by contributors">
|
24 |
+
<p>
|
25 |
+
Two of SimpleTest contributors have written books about PHP. Both have a lot
|
26 |
+
of examples with the SimpleTest Unit testing framework.
|
27 |
+
</p>
|
28 |
+
<p>
|
29 |
+
<a href="http://www.amazon.fr/gp/product/0973589825?ie=UTF8&tag=simpletest-21&linkCode=as2&camp=1642&creative=6746&creativeASIN=0973589825"><img src="../images/book-guide-to-php-design-patterns.jpg" alt="PHP|Architect's Guide to PHP Design Patterns" /></a>
|
30 |
+
<br />
|
31 |
+
<strong>PHP|Architect's Guide to PHP Design Patterns</strong><br />
|
32 |
+
by Jason E. Sweat<br />
|
33 |
+
(get it from : <a href="http://www.phparch.com/shop_product.php?itemid=96">PHP|Architect</a> |
|
34 |
+
<a href="http://www.amazon.fr/gp/product/0973589825?ie=UTF8&tag=simpletest-21&linkCode=as2&camp=1642&creative=6746&creativeASIN=0973589825">Amazon</a> )
|
35 |
+
</p>
|
36 |
+
<p>
|
37 |
+
<a href="http://www.amazon.fr/gp/product/0957921845/402-9483515-6732155?ie=UTF8&tag=simpletest-21&linkCode=xm2&camp=1642&creativeASIN=0957921845"><img src="../images/book-the-php-anthology-object-oriented-php-solutions.jpg" alt="The PHP Anthology: Object Oriented PHP Solutions" /></a>
|
38 |
+
<br />
|
39 |
+
<strong>The PHP Anthology: Object Oriented PHP Solutions</strong><br />
|
40 |
+
by Harry Fuecks<br />
|
41 |
+
(get it from : <a href="http://www.sitepoint.com/books/phpant1/">SitePoint</a> |
|
42 |
+
<a href="http://www.amazon.fr/gp/product/0957921845/402-9483515-6732155?ie=UTF8&tag=simpletest-21&linkCode=xm2&camp=1642&creativeASIN=0957921845">Amazon</a> |
|
43 |
+
<a href="http://developers.slashdot.org/article.pl?sid=04/08/04/1516258&amp;tid=169&amp;tid=192&amp;tid=218&amp;mode=nocomment">review on Slashdot</a> )
|
44 |
+
</p>
|
45 |
+
</section>
|
46 |
+
<section name="buying-books" title="Buying books">
|
47 |
+
<p>
|
48 |
+
One way to help the team of contributors is to buy books from this page through
|
49 |
+
Amazon (with the <cite>simpletest-21</cite> tag). We all love reading stuff that's
|
50 |
+
both interesting and challenging.
|
51 |
+
</p>
|
52 |
+
</section>
|
53 |
+
</content>
|
54 |
+
<internal>
|
55 |
+
<link>
|
56 |
+
<a href="#latest-recommandation">Latest recommandation</a>
|
57 |
+
</link>
|
58 |
+
<link>
|
59 |
+
<a href="#books-by-contributors">Books by contributors</a>
|
60 |
+
</link>
|
61 |
+
<link>
|
62 |
+
<a href="#buying-books">Buying books</a>
|
63 |
+
</link>
|
64 |
+
</internal>
|
65 |
+
|
66 |
+
<external>
|
67 |
+
</external>
|
68 |
+
|
69 |
+
<meta>
|
70 |
+
<keywords>
|
71 |
+
</keywords>
|
72 |
+
</meta>
|
73 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/boundary_classes_tutorial.xml
ADDED
@@ -0,0 +1,407 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: boundary_classes_tutorial.xml 1684 2008-03-06 08:36:59Z pp11 $ -->
|
3 |
+
<page title="The Application Boundary" here="Boundary classes">
|
4 |
+
<long_title>
|
5 |
+
PHP unit testing tutorial - Organising unit tests and boundary
|
6 |
+
class test cases
|
7 |
+
</long_title>
|
8 |
+
<content>
|
9 |
+
<introduction>
|
10 |
+
<p>
|
11 |
+
You are probably thinking that we have well and truly exhausted
|
12 |
+
the <code>Log</code> class by now and that there is
|
13 |
+
really nothing more to add.
|
14 |
+
Things are never that simple with object oriented programming, though.
|
15 |
+
You think you understand a problem and then something comes a long
|
16 |
+
that challenges your perspective and leads to an even deeper appreciation.
|
17 |
+
I thought I understood the logging class and that only the first page
|
18 |
+
of the tutorial would use it.
|
19 |
+
After that I would move on to something more complicated.
|
20 |
+
No one is more surprised than me that I still haven't got to
|
21 |
+
the bottom of it.
|
22 |
+
In fact I think I have only just figured out what a logger does.
|
23 |
+
</p>
|
24 |
+
</introduction>
|
25 |
+
<section name="variation" title="Log variations">
|
26 |
+
<p>
|
27 |
+
Supposing that we do not want to log to a file at all.
|
28 |
+
Perhaps we want to print to the screen, write the messages to a
|
29 |
+
socket or send them to the Unix(tm) <em>syslog</em> daemon for
|
30 |
+
dispatching across the network.
|
31 |
+
How do we incorporate this variation?
|
32 |
+
</p>
|
33 |
+
<p>
|
34 |
+
Simplest is to subclass the <code>Log</code>
|
35 |
+
overriding the <code>message()</code> method
|
36 |
+
with new versions.
|
37 |
+
This will work in the short term, but there is actually something
|
38 |
+
subtle, but deeply wrong with this.
|
39 |
+
Suppose we do subclass and have loggers that write to files,
|
40 |
+
the screen and the network.
|
41 |
+
Three classes , but that is OK.
|
42 |
+
Now suppose that we want a new logging class that adds message
|
43 |
+
filtering by priority, letting only certain types of messages
|
44 |
+
through according to some configuration file.
|
45 |
+
</p>
|
46 |
+
<p>
|
47 |
+
We are stuck. If we subclass again, we have to do it for all
|
48 |
+
three classes, giving us six classes.
|
49 |
+
The amount of duplication is horrible.
|
50 |
+
</p>
|
51 |
+
<p>
|
52 |
+
So are you now wishing that PHP had multiple inheritence?
|
53 |
+
Well, here that would reduce the short term workload, but
|
54 |
+
complicate what should be a very simple class.
|
55 |
+
Multiple inheritance, even when supported, should be used
|
56 |
+
extremely carefully as all sorts of complicated entanglements
|
57 |
+
can result.
|
58 |
+
Treat it as a loaded gun.
|
59 |
+
In fact, our sudden need for it is telling us something else - perhaps
|
60 |
+
that we have gone wrong on the conceptual level.
|
61 |
+
</p>
|
62 |
+
<p>
|
63 |
+
What does a logger do?
|
64 |
+
Does it send messages to a file?
|
65 |
+
Does it send messages to a network?
|
66 |
+
Does it send messages to a screen?
|
67 |
+
Nope.
|
68 |
+
It just sends messages (full stop).
|
69 |
+
The target of those messages can be chosen when setting
|
70 |
+
up the log, but after that the
|
71 |
+
logger should be left to combine and format the message
|
72 |
+
elements as that is its real job.
|
73 |
+
We restricted ourselves by assuming that target was a filename.
|
74 |
+
</p>
|
75 |
+
</section>
|
76 |
+
<section name="writer" title="Abstracting a file to a writer">
|
77 |
+
<p>
|
78 |
+
The solution to this plight is a real classic.
|
79 |
+
First we encapsulate the variation in a class as this will
|
80 |
+
add a level of indirection.
|
81 |
+
Instead of passing in the file name as a string we
|
82 |
+
will pass the "thing that we will write to"
|
83 |
+
which we will call a <code>Writer</code>.
|
84 |
+
Back to the tests...
|
85 |
+
<php><![CDATA[
|
86 |
+
<?php
|
87 |
+
require_once('../classes/log.php');
|
88 |
+
require_once('../classes/clock.php');<strong>
|
89 |
+
require_once('../classes/writer.php');</strong>
|
90 |
+
Mock::generate('Clock');
|
91 |
+
|
92 |
+
class TestOfLogging extends UnitTestCase {
|
93 |
+
function TestOfLogging() {
|
94 |
+
$this->UnitTestCase('Log class test');
|
95 |
+
}
|
96 |
+
function setUp() {
|
97 |
+
@unlink('../temp/test.log');
|
98 |
+
}
|
99 |
+
function tearDown() {
|
100 |
+
@unlink('../temp/test.log');
|
101 |
+
}
|
102 |
+
function getFileLine($filename, $index) {
|
103 |
+
$messages = file($filename);
|
104 |
+
return $messages[$index];
|
105 |
+
}
|
106 |
+
function testCreatingNewFile() {<strong>
|
107 |
+
$log = new Log(new FileWriter('../temp/test.log'));</strong>
|
108 |
+
$this->assertFalse(file_exists('../temp/test.log'), 'Created before message');
|
109 |
+
$log->message('Should write this to a file');
|
110 |
+
$this->assertTrue(file_exists('../temp/test.log'), 'File created');
|
111 |
+
}
|
112 |
+
function testAppendingToFile() {<strong>
|
113 |
+
$log = new Log(new FileWriter('../temp/test.log'));</strong>
|
114 |
+
$log->message('Test line 1');
|
115 |
+
$this->assertWantedPattern(
|
116 |
+
'/Test line 1/',
|
117 |
+
$this->getFileLine('../temp/test.log', 0));
|
118 |
+
$log->message('Test line 2');
|
119 |
+
$this->assertWantedPattern(
|
120 |
+
'/Test line 2/',
|
121 |
+
$this->getFileLine('../temp/test.log', 1));
|
122 |
+
}
|
123 |
+
function testTimestamps() {
|
124 |
+
$clock = &new MockClock($this);
|
125 |
+
$clock->setReturnValue('now', 'Timestamp');<strong>
|
126 |
+
$log = new Log(new FileWriter('../temp/test.log'));</strong>
|
127 |
+
$log->message('Test line', &$clock);
|
128 |
+
$this->assertWantedPattern(
|
129 |
+
'/Timestamp/',
|
130 |
+
$this->getFileLine('../temp/test.log', 0),
|
131 |
+
'Found timestamp');
|
132 |
+
}
|
133 |
+
}
|
134 |
+
?>
|
135 |
+
]]></php>
|
136 |
+
I am going to do this one step at a time so as not to get
|
137 |
+
confused.
|
138 |
+
I have replaced the file names with an imaginary
|
139 |
+
<code>FileWriter</code> class from
|
140 |
+
a file <em>classes/writer.php</em>.
|
141 |
+
This will cause the tests to crash as we have not written
|
142 |
+
the writer yet.
|
143 |
+
Should we do that now?
|
144 |
+
</p>
|
145 |
+
<p>
|
146 |
+
We could, but we don't have to.
|
147 |
+
We do need to create the interface, though, or we won't be
|
148 |
+
able to mock it.
|
149 |
+
This makes <em>classes/writer.php</em> looks like...
|
150 |
+
<php><![CDATA[
|
151 |
+
<?php
|
152 |
+
class FileWriter {
|
153 |
+
|
154 |
+
function FileWriter($file_path) {
|
155 |
+
}
|
156 |
+
|
157 |
+
function write($message) {
|
158 |
+
}
|
159 |
+
}
|
160 |
+
?>
|
161 |
+
]]></php>
|
162 |
+
We need to modify the <code>Log</code> class
|
163 |
+
as well...
|
164 |
+
<php><![CDATA[
|
165 |
+
<?php
|
166 |
+
require_once('../classes/clock.php');<strong>
|
167 |
+
require_once('../classes/writer.php');</strong>
|
168 |
+
|
169 |
+
class Log {<strong>
|
170 |
+
var $_writer;</strong>
|
171 |
+
|
172 |
+
function Log(<strong>&$writer</strong>) {<strong>
|
173 |
+
$this->_writer = &$writer;</strong>
|
174 |
+
}
|
175 |
+
|
176 |
+
function message($message, $clock = false) {
|
177 |
+
if (! is_object($clock)) {
|
178 |
+
$clock = new Clock();
|
179 |
+
}<strong>
|
180 |
+
$this->_writer->write("[" . $clock->now() . "] $message");</strong>
|
181 |
+
}
|
182 |
+
}
|
183 |
+
?>
|
184 |
+
]]></php>
|
185 |
+
There is not much that hasn't changed in our now even smaller
|
186 |
+
class.
|
187 |
+
The tests run, but fail at this point unless we add code to
|
188 |
+
the writer.
|
189 |
+
What do we do now?
|
190 |
+
</p>
|
191 |
+
<p>
|
192 |
+
We could start writing tests and code the
|
193 |
+
<code>FileWriter</code> class alongside, but
|
194 |
+
while we were doing this our <code>Log</code>
|
195 |
+
tests would be failing and disturbing our focus.
|
196 |
+
In fact we do not have to.
|
197 |
+
</p>
|
198 |
+
<p>
|
199 |
+
Part of our plan is to free the logging class from the file
|
200 |
+
system and there is a way to do this.
|
201 |
+
First we add a <em>tests/writer_test.php</em> so that
|
202 |
+
we have somewhere to place our test code from <em>log_test.php</em>
|
203 |
+
that we are going to shuffle around.
|
204 |
+
I won't yet add it to the <em>all_tests.php</em> file
|
205 |
+
though as it is the logging aspect we are tackling right now.
|
206 |
+
</p>
|
207 |
+
<p>
|
208 |
+
Now I have done that (honest) we remove any
|
209 |
+
tests from <em>log_test.php</em> that are not strictly logging
|
210 |
+
related and move them to <em>writer_test.php</em> for later.
|
211 |
+
We will also mock the writer so that it does not write
|
212 |
+
out to real files...
|
213 |
+
<php><![CDATA[
|
214 |
+
<?php
|
215 |
+
require_once('../classes/log.php');
|
216 |
+
require_once('../classes/clock.php');
|
217 |
+
require_once('../classes/writer.php');
|
218 |
+
Mock::generate('Clock');<strong>
|
219 |
+
Mock::generate('FileWriter');</strong>
|
220 |
+
|
221 |
+
class TestOfLogging extends UnitTestCase {
|
222 |
+
function TestOfLogging() {
|
223 |
+
$this->UnitTestCase('Log class test');
|
224 |
+
}<strong>
|
225 |
+
function testWriting() {
|
226 |
+
$clock = &new MockClock();
|
227 |
+
$clock->setReturnValue('now', 'Timestamp');
|
228 |
+
$writer = &new MockFileWriter($this);
|
229 |
+
$writer->expectArguments('write', array('[Timestamp] Test line'));
|
230 |
+
$writer->expectCallCount('write', 1);
|
231 |
+
$log = &new Log(\$writer);
|
232 |
+
$log->message('Test line', &$clock);
|
233 |
+
}</strong>
|
234 |
+
}
|
235 |
+
?>
|
236 |
+
]]></php>
|
237 |
+
Yes that really is the whole test case and it really is that short.
|
238 |
+
A lot has happened here...
|
239 |
+
<ol>
|
240 |
+
<li>
|
241 |
+
The requirement to create the file only when needed has
|
242 |
+
moved to the <code>FileWriter</code>.
|
243 |
+
</li>
|
244 |
+
<li>
|
245 |
+
As we are dealing with mocks, no files are actually
|
246 |
+
created and so I moved the
|
247 |
+
<code>setUp()</code> and
|
248 |
+
<code>tearDown()</code> off into the
|
249 |
+
writing tests.
|
250 |
+
</li>
|
251 |
+
<li>
|
252 |
+
The test now consists of sending a sample message and
|
253 |
+
testing the format.
|
254 |
+
</li>
|
255 |
+
</ol>
|
256 |
+
Hang on a minute, where are the assertions?
|
257 |
+
</p>
|
258 |
+
<p>
|
259 |
+
The mock objects do much more than simply behave like other
|
260 |
+
objects, they also run tests.
|
261 |
+
The <code>expectArguments()</code>
|
262 |
+
call told the mock to expect a single parameter of
|
263 |
+
the string "[Timestamp] Test line" when
|
264 |
+
the mock <code>write()</code> method is
|
265 |
+
called.
|
266 |
+
When that method is called the expected parameters are
|
267 |
+
compared with this and either a pass or a fail is sent
|
268 |
+
to the unit test as a result.
|
269 |
+
</p>
|
270 |
+
<p>
|
271 |
+
The other expectation is that <code>write()</code>
|
272 |
+
will be called only once.
|
273 |
+
Simply setting this up is not enough.
|
274 |
+
We can see all this in action by running the tests...
|
275 |
+
<div class="demo">
|
276 |
+
<h1>All tests</h1>
|
277 |
+
<span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Arguments for [write] were [String: [Timestamp] Test line]<br />
|
278 |
+
<span class="pass">Pass</span>: log_test.php->Log class test->testwriting->Expected call count for [write] was [1], but got [1]<br />
|
279 |
+
|
280 |
+
<span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br />
|
281 |
+
<span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br />
|
282 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete.
|
283 |
+
<strong>4</strong> passes and <strong>0</strong> fails.</div>
|
284 |
+
</div>
|
285 |
+
</p>
|
286 |
+
<p>
|
287 |
+
We can actually shorten our test slightly more.
|
288 |
+
The mock object expectation <code>expectOnce()</code>
|
289 |
+
can actually combine the two seperate expectations...
|
290 |
+
<php><![CDATA[
|
291 |
+
function testWriting() {
|
292 |
+
$clock = &new MockClock();
|
293 |
+
$clock->setReturnValue('now', 'Timestamp');
|
294 |
+
$writer = &new MockFileWriter($this);<strong>
|
295 |
+
$writer->expectOnce('write', array('[Timestamp] Test line'));</strong>
|
296 |
+
$log = &new Log($writer);
|
297 |
+
$log->message('Test line', &$clock);
|
298 |
+
}
|
299 |
+
]]></php>
|
300 |
+
This can be an effective shorthand.
|
301 |
+
</p>
|
302 |
+
</section>
|
303 |
+
<section name="boundary" title="Boundary classes">
|
304 |
+
<p>
|
305 |
+
Something very nice has happened to the logger besides merely
|
306 |
+
getting smaller.
|
307 |
+
</p>
|
308 |
+
<p>
|
309 |
+
The only things it depends on now are classes that we have written
|
310 |
+
ourselves and
|
311 |
+
in the tests these are mocked and so there are no dependencies
|
312 |
+
on anything other than our own PHP code.
|
313 |
+
No writing to files or waiting for clocks to tick over.
|
314 |
+
This means that the <em>log_test.php</em> test case will
|
315 |
+
run as fast as the processor will carry it.
|
316 |
+
By contrast the <code>FileWriter</code>
|
317 |
+
and <code>Clock</code> classes are very
|
318 |
+
close to the system.
|
319 |
+
This makes them harder to test as real data must be moved
|
320 |
+
around and painstakingly confirmed, often by ad hoc tricks.
|
321 |
+
</p>
|
322 |
+
<p>
|
323 |
+
Our last refactoring has helped a lot.
|
324 |
+
The hard to test classes on the boundary of the application
|
325 |
+
and the system are now smaller as the I/O code has
|
326 |
+
been further separated from the application logic.
|
327 |
+
They are direct mappings to PHP operations:
|
328 |
+
<code>FileWriter::write()</code> maps
|
329 |
+
to PHP <code>fwrite()</code> with the
|
330 |
+
file opened for appending and
|
331 |
+
<code>Clock::now()</code> maps to
|
332 |
+
PHP <code>time()</code>.
|
333 |
+
This makes debugging easier.
|
334 |
+
It also means that these classes will change less often.
|
335 |
+
</p>
|
336 |
+
<p>
|
337 |
+
If they don't change a lot then there is no reason to
|
338 |
+
keep running the tests for them.
|
339 |
+
This means that tests for the boundary classes can be moved
|
340 |
+
off into there own test suite leaving the other unit tests
|
341 |
+
to run at full speed.
|
342 |
+
In fact this is what I tend to do and the test cases
|
343 |
+
in <a href="simple_test.php">SimpleTest</a> itself are
|
344 |
+
divided this way.
|
345 |
+
</p>
|
346 |
+
<p>
|
347 |
+
That may not sound like much with one unit test and two
|
348 |
+
boundary tests, but typical applications can have
|
349 |
+
twenty boundary classes and two hundred application
|
350 |
+
classes.
|
351 |
+
To keep these running at full speed you will want
|
352 |
+
to keep them separate.
|
353 |
+
</p>
|
354 |
+
<p>
|
355 |
+
Besides, separating off decisions of which system components
|
356 |
+
to use is good development.
|
357 |
+
Perhaps all this mocking is
|
358 |
+
<a href="improving_design_tutorial.php">improving our design</a>?
|
359 |
+
</p>
|
360 |
+
</section>
|
361 |
+
</content>
|
362 |
+
<internal>
|
363 |
+
<link>
|
364 |
+
<a href="#variation">Handling variation</a> in our logger.
|
365 |
+
</link>
|
366 |
+
<link>
|
367 |
+
Abstracting further with a <a href="#writer">mock Writer</a> class.
|
368 |
+
</link>
|
369 |
+
<link>
|
370 |
+
Separating <a href="#boundary">Boundary class</a> tests
|
371 |
+
cleans things up.
|
372 |
+
</link>
|
373 |
+
</internal>
|
374 |
+
<external>
|
375 |
+
<link>
|
376 |
+
This tutorial follows the <a href="mock_objects_tutorial.php">Mock objects</a> introduction.
|
377 |
+
</link>
|
378 |
+
<link>
|
379 |
+
Next is <a href="improving_design_tutorial.php">test driven design</a>.
|
380 |
+
</link>
|
381 |
+
<link>
|
382 |
+
You will need the <a href="simple_test.php">SimpleTest testing framework</a>
|
383 |
+
to try these examples.
|
384 |
+
</link>
|
385 |
+
</external>
|
386 |
+
<meta>
|
387 |
+
<keywords>
|
388 |
+
software development,
|
389 |
+
php programming,
|
390 |
+
programming php,
|
391 |
+
software development tools,
|
392 |
+
php tutorial,
|
393 |
+
free php scripts,
|
394 |
+
organizing unit tests,
|
395 |
+
testing tips,
|
396 |
+
development tricks,
|
397 |
+
software architecture for testing,
|
398 |
+
php example code,
|
399 |
+
mock objects,
|
400 |
+
junit port,
|
401 |
+
test case examples,
|
402 |
+
php testing,
|
403 |
+
unit test tool,
|
404 |
+
php test suite
|
405 |
+
</keywords>
|
406 |
+
</meta>
|
407 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/browser_documentation.xml
ADDED
@@ -0,0 +1,263 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: browser_documentation.xml 1684 2008-03-06 08:36:59Z pp11 $ -->
|
3 |
+
<page title="PHP Scriptable Web Browser" here="Scriptable browser">
|
4 |
+
<long_title>SimpleTest documentation for the scriptable web browser component</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<p>
|
8 |
+
SimpleTest's web browser component can be used not just
|
9 |
+
outside of the <code>WebTestCase</code> class, but also
|
10 |
+
independently of the SimpleTest framework itself.
|
11 |
+
</p>
|
12 |
+
</introduction>
|
13 |
+
<section name="scripting" title="The Scriptable Browser">
|
14 |
+
<p>
|
15 |
+
You can use the web browser in PHP scripts to confirm
|
16 |
+
services are up and running, or to extract information
|
17 |
+
from them at a regular basis.
|
18 |
+
For example, here is a small script to extract the current number of
|
19 |
+
open PHP 5 bugs from the <a href="http://www.php.net/">PHP web site</a>...
|
20 |
+
<php><![CDATA[
|
21 |
+
<strong><?php
|
22 |
+
require_once('simpletest/browser.php');
|
23 |
+
|
24 |
+
$browser = &new SimpleBrowser();
|
25 |
+
$browser->get('http://php.net/');
|
26 |
+
$browser->click('reporting bugs');
|
27 |
+
$browser->click('statistics');
|
28 |
+
$page = $browser->click('PHP 5 bugs only');
|
29 |
+
preg_match('/status=Open.*?by=Any.*?(\d+)<\/a>/', $page, $matches);
|
30 |
+
print $matches[1];
|
31 |
+
?></strong>
|
32 |
+
]]></php>
|
33 |
+
There are simpler methods to do this particular example in PHP
|
34 |
+
of course.
|
35 |
+
For example you can just use the PHP <code>file()</code>
|
36 |
+
command against what here is a pretty fixed page.
|
37 |
+
However, using the web browser for scripts allows authentication,
|
38 |
+
correct handling of cookies, automatic loading of frames, redirects,
|
39 |
+
form submission and the ability to examine the page headers.
|
40 |
+
Such methods are fragile against a site that is constantly
|
41 |
+
evolving and you would want a more direct way of accessing
|
42 |
+
data in a permanent set up, but for simple tasks this can provide
|
43 |
+
a very rapid solution.
|
44 |
+
</p>
|
45 |
+
<p>
|
46 |
+
All of the navigation methods used in the
|
47 |
+
<a local="web_tester_documentation">WebTestCase</a>
|
48 |
+
are present in the <code>SimpleBrowser</code> class, but
|
49 |
+
the assertions are replaced with simpler accessors.
|
50 |
+
Here is a full list of the page navigation methods...
|
51 |
+
<table><tbody>
|
52 |
+
<tr><td><code>addHeader($header)</code></td><td>Adds a header to every fetch</td></tr>
|
53 |
+
<tr><td><code>useProxy($proxy, $username, $password)</code></td><td>Use this proxy from now on</td></tr>
|
54 |
+
<tr><td><code>head($url, $parameters)</code></td><td>Perform a HEAD request</td></tr>
|
55 |
+
<tr><td><code>get($url, $parameters)</code></td><td>Fetch a page with GET</td></tr>
|
56 |
+
<tr><td><code>post($url, $parameters)</code></td><td>Fetch a page with POST</td></tr>
|
57 |
+
<tr><td><code>clickLink($label)</code></td><td>Follows a link by label</td></tr>
|
58 |
+
<tr><td><code>clickLinkById($id)</code></td><td>Follows a link by attribute</td></tr>
|
59 |
+
<tr><td><code>getUrl()</code></td><td>Current URL of page or frame</td></tr>
|
60 |
+
<tr><td><code>getTitle()</code></td><td>Page title</td></tr>
|
61 |
+
<tr><td><code>getContent()</code></td><td>Raw page or frame</td></tr>
|
62 |
+
<tr><td><code>getContentAsText()</code></td><td>HTML removed except for alt text</td></tr>
|
63 |
+
<tr><td><code>retry()</code></td><td>Repeat the last request</td></tr>
|
64 |
+
<tr><td><code>back()</code></td><td>Use the browser back button</td></tr>
|
65 |
+
<tr><td><code>forward()</code></td><td>Use the browser forward button</td></tr>
|
66 |
+
<tr><td><code>authenticate($username, $password)</code></td><td>Retry page or frame after a 401 response</td></tr>
|
67 |
+
<tr><td><code>restart($date)</code></td><td>Restarts the browser for a new session</td></tr>
|
68 |
+
<tr><td><code>ageCookies($interval)</code></td><td>Ages the cookies by the specified time</td></tr>
|
69 |
+
<tr><td><code>setCookie($name, $value)</code></td><td>Sets an additional cookie</td></tr>
|
70 |
+
<tr><td><code>getCookieValue($host, $path, $name)</code></td><td>Reads the most specific cookie</td></tr>
|
71 |
+
<tr><td><code>getCurrentCookieValue($name)</code></td><td>Reads cookie for the current context</td></tr>
|
72 |
+
</tbody></table>
|
73 |
+
The methods <code>SimpleBrowser::useProxy()</code> and
|
74 |
+
<code>SimpleBrowser::addHeader()</code> are special.
|
75 |
+
Once called they continue to apply to all subsequent fetches.
|
76 |
+
</p>
|
77 |
+
<p>
|
78 |
+
Navigating forms is similar to the
|
79 |
+
<a local="form_testing_documentation">WebTestCase form navigation</a>...
|
80 |
+
<table><tbody>
|
81 |
+
<tr><td><code>setField($name, $value)</code></td><td>Sets all form fields with that name</td></tr>
|
82 |
+
<tr><td><code>setFieldById($id, $value)</code></td><td>Sets all form fields with that id</td></tr>
|
83 |
+
<tr><td><code>getField($name)</code></td><td>Accessor for a form element value</td></tr>
|
84 |
+
<tr><td><code>getFieldById($id)</code></td><td>Accessor for a form element value</td></tr>
|
85 |
+
<tr><td><code>clickSubmit($label)</code></td><td>Submits form by button label</td></tr>
|
86 |
+
<tr><td><code>clickSubmitByName($name)</code></td><td>Submits form by button attribute</td></tr>
|
87 |
+
<tr><td><code>clickSubmitById($id)</code></td><td>Submits form by button attribute</td></tr>
|
88 |
+
<tr><td><code>clickImage($label, $x, $y)</code></td><td>Clicks an input tag of type image by title or alt text</td></tr>
|
89 |
+
<tr><td><code>clickImageByName($name, $x, $y)</code></td><td>Clicks an input tag of type image by name</td></tr>
|
90 |
+
<tr><td><code>clickImageById($id, $x, $y)</code></td><td>Clicks an input tag of type image by ID attribute</td></tr>
|
91 |
+
<tr><td><code>submitFormById($id)</code></td><td>Submits by the form tag attribute</td></tr>
|
92 |
+
</tbody></table>
|
93 |
+
At the moment there aren't any methods to list available forms
|
94 |
+
and fields.
|
95 |
+
This will probably be added to later versions of SimpleTest.
|
96 |
+
</p>
|
97 |
+
<p>
|
98 |
+
Within a page, individual frames can be selected.
|
99 |
+
If no selection is made then all the frames are merged together
|
100 |
+
in one large conceptual page.
|
101 |
+
The content of the current page will be a concatenation of all of the
|
102 |
+
frames in the order that they were specified in the "frameset"
|
103 |
+
tags.
|
104 |
+
<table><tbody>
|
105 |
+
<tr><td><code>getFrames()</code></td><td>A dump of the current frame structure</td></tr>
|
106 |
+
<tr><td><code>getFrameFocus()</code></td><td>Current frame label or index</td></tr>
|
107 |
+
<tr><td><code>setFrameFocusByIndex($choice)</code></td><td>Select a frame numbered from 1</td></tr>
|
108 |
+
<tr><td><code>setFrameFocus($name)</code></td><td>Select frame by label</td></tr>
|
109 |
+
<tr><td><code>clearFrameFocus()</code></td><td>Treat all the frames as a single page</td></tr>
|
110 |
+
</tbody></table>
|
111 |
+
When focused on a single frame, the content will come from
|
112 |
+
that frame only.
|
113 |
+
This includes links to click and forms to submit.
|
114 |
+
</p>
|
115 |
+
</section>
|
116 |
+
<section name="debug" title="What went wrong?">
|
117 |
+
<p>
|
118 |
+
All of this functionality is great when we actually manage to fetch pages,
|
119 |
+
but that doesn't always happen.
|
120 |
+
To help figure out what went wrong, the browser has some methods to
|
121 |
+
aid in debugging...
|
122 |
+
<table><tbody>
|
123 |
+
<tr><td><code>setConnectionTimeout($timeout)</code></td><td>Close the socket on overrun</td></tr>
|
124 |
+
<tr><td><code>getRequest()</code></td><td>Raw request header of page or frame</td></tr>
|
125 |
+
<tr><td><code>getHeaders()</code></td><td>Raw response header of page or frame</td></tr>
|
126 |
+
<tr><td><code>getTransportError()</code></td><td>Any socket level errors in the last fetch</td></tr>
|
127 |
+
<tr><td><code>getResponseCode()</code></td><td>HTTP response of page or frame</td></tr>
|
128 |
+
<tr><td><code>getMimeType()</code></td><td>Mime type of page or frame</td></tr>
|
129 |
+
<tr><td><code>getAuthentication()</code></td><td>Authentication type in 401 challenge header</td></tr>
|
130 |
+
<tr><td><code>getRealm()</code></td><td>Authentication realm in 401 challenge header</td></tr>
|
131 |
+
<tr><td><code>setMaximumRedirects($max)</code></td><td>Number of redirects before page is loaded anyway</td></tr>
|
132 |
+
<tr><td><code>setMaximumNestedFrames($max)</code></td><td>Protection against recursive framesets</td></tr>
|
133 |
+
<tr><td><code>ignoreFrames()</code></td><td>Disables frames support</td></tr>
|
134 |
+
<tr><td><code>useFrames()</code></td><td>Enables frames support</td></tr>
|
135 |
+
<tr><td><code>ignoreCookies()</code></td><td>Disables sending and receiving of cookies</td></tr>
|
136 |
+
<tr><td><code>useCookies()</code></td><td>Enables cookie support</td></tr>
|
137 |
+
</tbody></table>
|
138 |
+
The methods <code>SimpleBrowser::setConnectionTimeout()</code>
|
139 |
+
<code>SimpleBrowser::setMaximumRedirects()</code>,
|
140 |
+
<code>SimpleBrowser::setMaximumNestedFrames()</code>,
|
141 |
+
<code>SimpleBrowser::ignoreFrames()</code>,
|
142 |
+
<code>SimpleBrowser::useFrames()</code>,
|
143 |
+
<code>SimpleBrowser::ignoreCookies()</code> and
|
144 |
+
<code>SimpleBrowser::useCokies()</code> continue to apply
|
145 |
+
to every subsequent request.
|
146 |
+
The other methods are frames aware.
|
147 |
+
This means that if you have an individual frame that is not
|
148 |
+
loading, navigate to it using <code>SimpleBrowser::setFrameFocus()</code>
|
149 |
+
and you can then use <code>SimpleBrowser::getRequest()</code>, etc to
|
150 |
+
see what happened.
|
151 |
+
</p>
|
152 |
+
</section>
|
153 |
+
<section name="unit" title="Complex unit tests with multiple browsers">
|
154 |
+
<p>
|
155 |
+
Anything that could be done in a
|
156 |
+
<a local="web_tester_documentation">WebTestCase</a> can
|
157 |
+
now be done in a <a local="unit_tester_documentation">UnitTestCase</a>.
|
158 |
+
This means that we can freely mix domain object testing with the
|
159 |
+
web interface...
|
160 |
+
<php><![CDATA[
|
161 |
+
<strong>class TestOfRegistration extends UnitTestCase {
|
162 |
+
function testNewUserAddedToAuthenticator() {</strong>
|
163 |
+
$browser = &new SimpleBrowser();
|
164 |
+
$browser->get('http://my-site.com/register.php');
|
165 |
+
$browser->setField('email', 'me@here');
|
166 |
+
$browser->setField('password', 'Secret');
|
167 |
+
$browser->click('Register');
|
168 |
+
<strong>
|
169 |
+
$authenticator = &new Authenticator();
|
170 |
+
$member = &$authenticator->findByEmail('me@here');
|
171 |
+
$this->assertEqual($member->getPassword(), 'Secret');
|
172 |
+
}
|
173 |
+
}</strong>
|
174 |
+
]]></php>
|
175 |
+
While this may be a useful temporary expediency, I am not a fan
|
176 |
+
of this type of testing.
|
177 |
+
The testing has cut across application layers, make it twice as
|
178 |
+
likely it will need refactoring when the code changes.
|
179 |
+
</p>
|
180 |
+
<p>
|
181 |
+
A more useful case of where using the browser directly can be helpful
|
182 |
+
is where the <code>WebTestCase</code> cannot cope.
|
183 |
+
An example is where two browsers are needed at the same time.
|
184 |
+
</p>
|
185 |
+
<p>
|
186 |
+
For example, say we want to disallow multiple simultaneous
|
187 |
+
usage of a site with the same username.
|
188 |
+
This test case will do the job...
|
189 |
+
<php><![CDATA[
|
190 |
+
class TestOfSecurity extends UnitTestCase {
|
191 |
+
function testNoMultipleLoginsFromSameUser() {<strong>
|
192 |
+
$first = &new SimpleBrowser();
|
193 |
+
$first->get('http://my-site.com/login.php');
|
194 |
+
$first->setField('name', 'Me');
|
195 |
+
$first->setField('password', 'Secret');
|
196 |
+
$first->click('Enter');
|
197 |
+
$this->assertEqual($first->getTitle(), 'Welcome');
|
198 |
+
|
199 |
+
$second = &new SimpleBrowser();
|
200 |
+
$second->get('http://my-site.com/login.php');
|
201 |
+
$second->setField('name', 'Me');
|
202 |
+
$second->setField('password', 'Secret');
|
203 |
+
$second->click('Enter');
|
204 |
+
$this->assertEqual($second->getTitle(), 'Access Denied');</strong>
|
205 |
+
}
|
206 |
+
}
|
207 |
+
]]></php>
|
208 |
+
You can also use the <code>SimpleBrowser</code> class
|
209 |
+
directly when you want to write test cases using a different
|
210 |
+
test tool than SimpleTest.
|
211 |
+
</p>
|
212 |
+
</section>
|
213 |
+
</content>
|
214 |
+
<internal>
|
215 |
+
<link>
|
216 |
+
Using the bundled <a href="#scripting">web browser in scripts</a>
|
217 |
+
</link>
|
218 |
+
<link>
|
219 |
+
<a href="#debug">Debugging</a> failed pages
|
220 |
+
</link>
|
221 |
+
<link>
|
222 |
+
Complex <a href="#unit">tests with multiple web browsers</a>
|
223 |
+
</link>
|
224 |
+
</internal>
|
225 |
+
<external>
|
226 |
+
<link>
|
227 |
+
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
228 |
+
</link>
|
229 |
+
<link>
|
230 |
+
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
231 |
+
</link>
|
232 |
+
<link>
|
233 |
+
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
234 |
+
gives full detail on the classes and assertions available.
|
235 |
+
</link>
|
236 |
+
</external>
|
237 |
+
<meta>
|
238 |
+
<keywords>
|
239 |
+
user agent,
|
240 |
+
web browser php,
|
241 |
+
fetching pages,
|
242 |
+
spider scripts,
|
243 |
+
software development,
|
244 |
+
php programming for clients,
|
245 |
+
customer focused php,
|
246 |
+
software development tools,
|
247 |
+
acceptance testing framework,
|
248 |
+
free php scripts,
|
249 |
+
log in boxes,
|
250 |
+
unit testing authentication systems,
|
251 |
+
php resources,
|
252 |
+
HTMLUnit,
|
253 |
+
JWebUnit,
|
254 |
+
php testing,
|
255 |
+
unit test resource,
|
256 |
+
web testing,
|
257 |
+
HTTP authentication,
|
258 |
+
testing log in,
|
259 |
+
authentication testing,
|
260 |
+
security tests
|
261 |
+
</keywords>
|
262 |
+
</meta>
|
263 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/coding_standards.xml
ADDED
@@ -0,0 +1,82 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: authentication.php 1672 2008-03-02 04:47:34Z edwardzyang $ -->
|
3 |
+
<page title="Coding Standards and Formatting" here="Coding Standards">
|
4 |
+
<long_title>Coding Standards within SimpleTest</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="coding-standards" title="Coding standards">
|
7 |
+
<p>
|
8 |
+
Here's the list we try to follow :
|
9 |
+
<ol>
|
10 |
+
<li>
|
11 |
+
Short method bodies, hopefully five lines or less.
|
12 |
+
</li>
|
13 |
+
<li>
|
14 |
+
No abbreviations in names,
|
15 |
+
so $parameter rather than $param.
|
16 |
+
</li>
|
17 |
+
<li>
|
18 |
+
ClassLikeThis, methodLikeThis(), $variables_like_this.
|
19 |
+
</li>
|
20 |
+
<li>
|
21 |
+
get/set for accessors.
|
22 |
+
</li>
|
23 |
+
<li>
|
24 |
+
Accessors even when a subclass calls a superclass.
|
25 |
+
</li>
|
26 |
+
<li>
|
27 |
+
Longish class and method names except for specifications.
|
28 |
+
</li>
|
29 |
+
<li>
|
30 |
+
"Simple" as a class name prefix
|
31 |
+
unless it really pollutes the domain language.
|
32 |
+
</li>
|
33 |
+
<li>
|
34 |
+
Eric Evans domain driven design style
|
35 |
+
rather than pure TDD. That is, slight over design
|
36 |
+
in order to make concepts clear.
|
37 |
+
</li>
|
38 |
+
</ol>
|
39 |
+
</p>
|
40 |
+
<p>
|
41 |
+
Obviously these reflect Marcus Bakers's average coding style
|
42 |
+
over several projects and programming languages.
|
43 |
+
</p>
|
44 |
+
<p>
|
45 |
+
Should also be obvious that
|
46 |
+
the code is riddled with exceptions to these rules :).
|
47 |
+
</p>
|
48 |
+
</section>
|
49 |
+
<section name="code-formatting" title="Code formatting">
|
50 |
+
<p>
|
51 |
+
Please no dangling brace style...
|
52 |
+
<php><![CDATA[
|
53 |
+
class MyClass
|
54 |
+
{
|
55 |
+
//stuff
|
56 |
+
}
|
57 |
+
]]></php>
|
58 |
+
It wastes vertical space
|
59 |
+
and is a hangover from long declarations in C++.
|
60 |
+
White space to me should separate something,
|
61 |
+
such as a method or class.
|
62 |
+
The same for docblocking private members.
|
63 |
+
</p>
|
64 |
+
</section>
|
65 |
+
</content>
|
66 |
+
<internal>
|
67 |
+
<link>
|
68 |
+
<a href="#coding-standards">Coding standards</a>
|
69 |
+
</link>
|
70 |
+
<link>
|
71 |
+
And other <a href="#code-formatting">Code formatting</a> stuff.
|
72 |
+
</link>
|
73 |
+
</internal>
|
74 |
+
|
75 |
+
<external>
|
76 |
+
</external>
|
77 |
+
|
78 |
+
<meta>
|
79 |
+
<keywords>
|
80 |
+
</keywords>
|
81 |
+
</meta>
|
82 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/display_subclass_tutorial.xml
ADDED
@@ -0,0 +1,274 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: display_subclass_tutorial.xml 1694 2008-03-20 16:37:40Z pp11 $ -->
|
3 |
+
<page title="Changing the test display" here="Showing passes">
|
4 |
+
<long_title>PHP unit testing tutorial - Subclassing the test display</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<p>
|
8 |
+
The display component of SimpleTest is actually the part
|
9 |
+
to be developed last.
|
10 |
+
Some of the following section will change in the future
|
11 |
+
and hopefully more sophisticated display components will
|
12 |
+
be written, but
|
13 |
+
in the meantime if a minimal display is not enough, here
|
14 |
+
is how to roll your own.
|
15 |
+
</p>
|
16 |
+
</introduction>
|
17 |
+
<section name="passes" title="I want to see the passes!">
|
18 |
+
<p>
|
19 |
+
Oh all right then, here's how.
|
20 |
+
</p>
|
21 |
+
<p>
|
22 |
+
We have to subclass the attached display, which in our case
|
23 |
+
is currently <code>HtmlReporter</code>.
|
24 |
+
The <code>HtmlReporter</code> class is in
|
25 |
+
the file <em>simpletest/reporter.php</em> and currently has
|
26 |
+
the following interface...
|
27 |
+
<php><![CDATA[
|
28 |
+
class HtmlReporter extends TestDisplay {
|
29 |
+
public TestHtmlDisplay() { ... }
|
30 |
+
public void paintHeader(string $test_name) { ... }
|
31 |
+
public void paintFooter(string $test_name) { ... }
|
32 |
+
public void paintStart(string $test_name, $size) { ... }
|
33 |
+
public void paintEnd(string $test_name, $size) { ... }
|
34 |
+
public void paintFail(string $message) { ... }
|
35 |
+
public void paintPass(string $message) { ... }
|
36 |
+
protected string _getCss() { ... }
|
37 |
+
public array getTestList() { ... }
|
38 |
+
public integer getPassCount() { ... }
|
39 |
+
public integer getFailCount() { ... }
|
40 |
+
public integer getTestCaseCount() { ... }
|
41 |
+
public integer getTestCaseProgress { ... }
|
42 |
+
}
|
43 |
+
]]></php>
|
44 |
+
Here is what the relevant methods mean.
|
45 |
+
You can see the
|
46 |
+
<a href="reporter_documentation.php#html">whole list here</a>
|
47 |
+
if you are interested.
|
48 |
+
<ul class="api">
|
49 |
+
<li>
|
50 |
+
<code>HtmlReporter()</code><br />
|
51 |
+
is the constructor.
|
52 |
+
Note that the unit test sets up the link to the display
|
53 |
+
rather than the other way around.
|
54 |
+
The display is a passive receiver of test events.
|
55 |
+
This allows easy adaption of the display for other test
|
56 |
+
systems beside unit tests, such as monitoring servers.
|
57 |
+
It also means that the unit test can write to more than
|
58 |
+
one display at a time.
|
59 |
+
</li>
|
60 |
+
<li>
|
61 |
+
<code>void paintFail(string $message)</code><br />
|
62 |
+
paints a failure.
|
63 |
+
See below.
|
64 |
+
</li>
|
65 |
+
<li>
|
66 |
+
<code>void paintPass(string $message)</code><br />
|
67 |
+
by default does nothing.
|
68 |
+
This is the method we will modify.
|
69 |
+
</li>
|
70 |
+
<li>
|
71 |
+
<code>string _getCss()</code><br />
|
72 |
+
returns the CSS styles as a string for the page header
|
73 |
+
method.
|
74 |
+
Additional styles have to be appended here.
|
75 |
+
</li>
|
76 |
+
<li>
|
77 |
+
<code>array getTestList()</code><br />
|
78 |
+
is a convenience method for subclasses.
|
79 |
+
Lists the current nesting of the tests as a list
|
80 |
+
of test names.
|
81 |
+
The first, most deeply nested test, is first in the
|
82 |
+
list and the current test method will be last.
|
83 |
+
</li>
|
84 |
+
</ul>
|
85 |
+
</p>
|
86 |
+
<p>
|
87 |
+
To show the passes we just need the
|
88 |
+
<code>paintPass()</code> method to behave
|
89 |
+
just like <code>paintFail()</code>.
|
90 |
+
Of course we won't modify the original.
|
91 |
+
We'll subclass.
|
92 |
+
</p>
|
93 |
+
</section>
|
94 |
+
<section name="subclass" title="A display subclass">
|
95 |
+
<p>
|
96 |
+
Firstly we'll create a <em>tests/show_passes.php</em> file
|
97 |
+
in our logging project and then place in it this empty class...
|
98 |
+
<php><![CDATA[
|
99 |
+
<strong><?php
|
100 |
+
if (! defined('SIMPLE_TEST')) {
|
101 |
+
define('SIMPLE_TEST', 'simpletest/');
|
102 |
+
}
|
103 |
+
require_once(SIMPLE_TEST . 'reporter.php');
|
104 |
+
|
105 |
+
class ShowPasses extends HtmlReporter {
|
106 |
+
|
107 |
+
function ShowPasses() {
|
108 |
+
$this->HtmlReporter();
|
109 |
+
}
|
110 |
+
}
|
111 |
+
?></strong>
|
112 |
+
]]></php>
|
113 |
+
A quick peruse of the
|
114 |
+
<a href="http://simpletest.svn.sourceforge.net/viewvc/simpletest/simpletest/trunk/reporter.php?view=markup">SimpleTest code base</a>
|
115 |
+
shows the <code>paintFail()</code> implementation
|
116 |
+
at the time of writing to look like this...
|
117 |
+
<php><![CDATA[
|
118 |
+
function paintFail($message) {
|
119 |
+
parent::paintFail($message);
|
120 |
+
print "<span class=\"fail\">Fail</span>: ";
|
121 |
+
$breadcrumb = $this->getTestList();
|
122 |
+
array_shift($breadcrumb);
|
123 |
+
print implode("->", $breadcrumb);
|
124 |
+
print "->$message<br />\n";
|
125 |
+
}
|
126 |
+
]]></php>
|
127 |
+
Essentially it chains to the parent's version, which we
|
128 |
+
have to do also to preserve house keeping, and then
|
129 |
+
prints a breadcrumbs trail calculated from the current test
|
130 |
+
list.
|
131 |
+
It drops the top level tests name, though.
|
132 |
+
As it is the same on every test that would be a little bit too
|
133 |
+
much information.
|
134 |
+
Transposing this to our new class...
|
135 |
+
<php><![CDATA[
|
136 |
+
class ShowPasses extends HtmlReporter {
|
137 |
+
|
138 |
+
function ShowPasses() {
|
139 |
+
$this->HtmlReporter();
|
140 |
+
}
|
141 |
+
<strong>
|
142 |
+
function paintPass($message) {
|
143 |
+
parent::paintPass($message);
|
144 |
+
print "<span class=\"pass\">Pass</span>: ";
|
145 |
+
$breadcrumb = $this->getTestList();
|
146 |
+
array_shift($breadcrumb);
|
147 |
+
print implode("->", $breadcrumb);
|
148 |
+
print "->$message<br />\n";
|
149 |
+
}</strong>
|
150 |
+
}
|
151 |
+
]]></php>
|
152 |
+
So far so good.
|
153 |
+
Now to make use of our new class we have to modify our
|
154 |
+
<em>tests/all_tests.php</em> file...
|
155 |
+
<php><![CDATA[
|
156 |
+
<?php
|
157 |
+
if (! defined('SIMPLE_TEST')) {
|
158 |
+
define('SIMPLE_TEST', 'simpletest/');
|
159 |
+
}
|
160 |
+
require_once(SIMPLE_TEST . 'unit_tester.php');<strong>
|
161 |
+
require_once('show_passes.php');</strong>
|
162 |
+
|
163 |
+
$test = &new TestSuite('All tests');
|
164 |
+
$test->addTestFile('log_test.php');
|
165 |
+
$test->addTestFile('clock_test.php');
|
166 |
+
$test->run(<strong>new ShowPasses()</strong>);
|
167 |
+
?>
|
168 |
+
]]></php>
|
169 |
+
We can run this to see the results of our handywork...
|
170 |
+
<div class="demo">
|
171 |
+
<h1>All tests</h1>
|
172 |
+
Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br />
|
173 |
+
Pass: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br />
|
174 |
+
Pass: log_test.php->Log class test->testcreatingnewfile->Created before message<br />
|
175 |
+
Pass: log_test.php->Log class test->testcreatingnewfile->File created<br />
|
176 |
+
Pass: clock_test.php->Clock class test->testclockadvance->Advancement<br />
|
177 |
+
Pass: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br />
|
178 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete.
|
179 |
+
<strong>6</strong> passes and <strong>0</strong> fails.</div>
|
180 |
+
</div>
|
181 |
+
Nice, but no gold star.
|
182 |
+
We have lost a little formatting here.
|
183 |
+
The display does not have a CSS style for
|
184 |
+
<code>span.pass</code>, but we can add this
|
185 |
+
easily by overriding one more method...
|
186 |
+
<php><![CDATA[
|
187 |
+
class ShowPasses extends HtmlReporter {
|
188 |
+
|
189 |
+
function ShowPasses() {
|
190 |
+
$this->HtmlReporter();
|
191 |
+
}
|
192 |
+
|
193 |
+
function paintPass($message) {
|
194 |
+
parent::paintPass($message);
|
195 |
+
print "<span class=\"pass\">Pass</span>: ";
|
196 |
+
$breadcrumb = $this->getTestList();
|
197 |
+
array_shift($breadcrumb);
|
198 |
+
print implode("->", $breadcrumb);
|
199 |
+
print "->$message<br />\n";
|
200 |
+
}
|
201 |
+
<strong>
|
202 |
+
function _getCss() {
|
203 |
+
return parent::_getCss() . ' .pass { color: green; }';
|
204 |
+
}</strong>
|
205 |
+
}
|
206 |
+
]]></php>
|
207 |
+
If you are adding the code as you go, you will see the style
|
208 |
+
appended when you do view source on the test results page in your browser.
|
209 |
+
To the eye the display itself should now look like this...
|
210 |
+
<div class="demo">
|
211 |
+
<h1>All tests</h1>
|
212 |
+
<span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 1/] in [Test line 1]<br />
|
213 |
+
<span class="pass">Pass</span>: log_test.php->Log class test->testappendingtofile->Expecting [/Test line 2/] in [Test line 2]<br />
|
214 |
+
<span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->Created before message<br />
|
215 |
+
<span class="pass">Pass</span>: log_test.php->Log class test->testcreatingnewfile->File created<br />
|
216 |
+
<span class="pass">Pass</span>: clock_test.php->Clock class test->testclockadvance->Advancement<br />
|
217 |
+
<span class="pass">Pass</span>: clock_test.php->Clock class test->testclocktellstime->Now is the right time<br />
|
218 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete.
|
219 |
+
<strong>6</strong> passes and <strong>0</strong> fails.</div>
|
220 |
+
</div>
|
221 |
+
Some people definitely prefer to see the passes being added
|
222 |
+
as they are working on code; the feeling that you are getting
|
223 |
+
work done is nice after all.
|
224 |
+
Once you have to scroll up and down the page to find failures
|
225 |
+
though, you soon come to realise its dark side.
|
226 |
+
</p>
|
227 |
+
<p>
|
228 |
+
Try it both ways and see which you prefer.
|
229 |
+
We'll leave it in for a bit anyhow when looking at the
|
230 |
+
<a href="mock_objects_tutorial.php">mock objects coming up</a>.
|
231 |
+
This is the first test tool that generates additional tests
|
232 |
+
and it will be useful to see what is happening behind the scenes.
|
233 |
+
</p>
|
234 |
+
</section>
|
235 |
+
</content>
|
236 |
+
<internal>
|
237 |
+
<link>
|
238 |
+
How to Change the display to <a href="#passes">show test passes</a>.
|
239 |
+
</link>
|
240 |
+
<link>
|
241 |
+
<a href="#subclass">Subclassing the <code>HtmlReporter</code> class</a>.
|
242 |
+
</link>
|
243 |
+
</internal>
|
244 |
+
<external>
|
245 |
+
<link>
|
246 |
+
The previous tutorial section was
|
247 |
+
<a href="subclass_tutorial.php">subclassing the test case</a>.
|
248 |
+
</link>
|
249 |
+
<link>
|
250 |
+
This section is very specific to
|
251 |
+
<a href="simple_test.php">SimpleTest</a>.
|
252 |
+
If you use another tool you will want to skip this.
|
253 |
+
</link>
|
254 |
+
</external>
|
255 |
+
<meta>
|
256 |
+
<keywords>
|
257 |
+
software development test first,
|
258 |
+
php general programming advice,
|
259 |
+
programming php,
|
260 |
+
software development tools,
|
261 |
+
php tutorial,
|
262 |
+
free php sample code,
|
263 |
+
architecture,
|
264 |
+
sample test cases,
|
265 |
+
php simple test framework,
|
266 |
+
php resources,
|
267 |
+
php test case examples,
|
268 |
+
phpunit,
|
269 |
+
simpletest,
|
270 |
+
unit test,
|
271 |
+
php testing
|
272 |
+
</keywords>
|
273 |
+
</meta>
|
274 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/download_website.xml
ADDED
@@ -0,0 +1,100 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: download_website.xml 1706 2008-03-25 09:24:32Z pp11 $ -->
|
3 |
+
<page title="Downloading SimpleTest" here="Download SimpleTest">
|
4 |
+
<long_title>Downloading SimpleTest</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="current-release" title="Current release">
|
7 |
+
<p>
|
8 |
+
The current release is : <a href="http://downloads.sourceforge.net/simpletest/simpletest_1.0.1RC1.tar.gz">SimpleTest v1.0.1RC1</a>.
|
9 |
+
</p>
|
10 |
+
<p>
|
11 |
+
You can download this version from
|
12 |
+
<a href="http://sourceforge.net/project/showfiles.php?group_id=76550&package_id=77275&release_id=586797">SourceForget.net</a>
|
13 |
+
and your local mirror. You may also want to look at
|
14 |
+
the <a href="changelog.html">current changelog</a>.
|
15 |
+
</p>
|
16 |
+
<p>
|
17 |
+
By the way, don't be scared away by the <quote>beta</quote> tag :
|
18 |
+
quite a few users actually use SimpleTest straight from SVN.
|
19 |
+
</p>
|
20 |
+
</section>
|
21 |
+
<section name="eclipse-release" title="Eclipse release">
|
22 |
+
<p>
|
23 |
+
If eclipse is your IDE / editor of choice, you might consider
|
24 |
+
the <a href="http://sourceforge.net/project/showfiles.php?group_id=76550&package_id=159054">Eclipse plugin</a>.
|
25 |
+
</p>
|
26 |
+
<p>
|
27 |
+
For automatic "find and install", the URL is :
|
28 |
+
<blockquote>http://simpletest.org/eclipse/</blockquote>
|
29 |
+
</p>
|
30 |
+
</section>
|
31 |
+
<section name="packages" title="Packages">
|
32 |
+
<p>
|
33 |
+
SimpleTest has been packaged by the community to different flavours.
|
34 |
+
</p>
|
35 |
+
<ul>
|
36 |
+
<li>
|
37 |
+
<a href="http://packages.debian.org/unstable/web/php-simpletest">Debian package</a>
|
38 |
+
</li>
|
39 |
+
<li>
|
40 |
+
<a href="http://www.pearified.com/index.php?package=SimpleTest">Pearified package</a>
|
41 |
+
</li>
|
42 |
+
<li>
|
43 |
+
<a href="http://drupal.org/project/simpletest">Drupal module</a>
|
44 |
+
</li>
|
45 |
+
</ul>
|
46 |
+
<p>
|
47 |
+
<cite>Note : careful, some versions are not always up-to-date.</cite>
|
48 |
+
</p>
|
49 |
+
</section>
|
50 |
+
<section name="source" title="Source">
|
51 |
+
<p>
|
52 |
+
The source code is hosted on Sourceforge as well : you can browse the
|
53 |
+
<a href="http://simpletest.svn.sourceforge.net/viewvc/simpletest/">SVN repository</a>
|
54 |
+
there.
|
55 |
+
</p>
|
56 |
+
</section>
|
57 |
+
<section name="older-stable-releases" title="Older stable releases">
|
58 |
+
<ul>
|
59 |
+
<li>
|
60 |
+
<a href="http://prdownloads.sourceforge.net/simpletest/simpletest_1.0.tar.gz">1.0.0</a>
|
61 |
+
</li>
|
62 |
+
</ul>
|
63 |
+
</section>
|
64 |
+
</content>
|
65 |
+
<internal>
|
66 |
+
<link>
|
67 |
+
<a href="#current-release">Current release</a>
|
68 |
+
</link>
|
69 |
+
<link>
|
70 |
+
<a href="#eclipse-release">Eclipse release</a>
|
71 |
+
</link>
|
72 |
+
<link>
|
73 |
+
<a href="#packages">Packages</a>
|
74 |
+
</link>
|
75 |
+
<link>
|
76 |
+
<a href="#source">Source</a>
|
77 |
+
</link>
|
78 |
+
<link>
|
79 |
+
<a href="#older-stable-releases">Older stable releases</a>
|
80 |
+
</link>
|
81 |
+
</internal>
|
82 |
+
|
83 |
+
<external>
|
84 |
+
</external>
|
85 |
+
|
86 |
+
<meta>
|
87 |
+
<keywords>
|
88 |
+
SimpleTest,
|
89 |
+
download,
|
90 |
+
source code,
|
91 |
+
stable release,
|
92 |
+
eclipse release,
|
93 |
+
eclipse plugin,
|
94 |
+
debian package,
|
95 |
+
drupal module,
|
96 |
+
pear channel,
|
97 |
+
pearified package
|
98 |
+
</keywords>
|
99 |
+
</meta>
|
100 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/expectation_documentation.xml
ADDED
@@ -0,0 +1,339 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: expectation_documentation.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Expectation documentation" here="Expectations">
|
4 |
+
<long_title>
|
5 |
+
Extending the SimpleTest unit tester with additional expectation classes
|
6 |
+
</long_title>
|
7 |
+
<content>
|
8 |
+
<section name="mock" title="More control over mock objects">
|
9 |
+
<p>
|
10 |
+
The default behaviour of the
|
11 |
+
<a local="mock_objects_documentation">mock objects</a>
|
12 |
+
in
|
13 |
+
<a href="http://sourceforge.net/projects/simpletest/">SimpleTest</a>
|
14 |
+
is either an identical match on the argument or to allow any argument at all.
|
15 |
+
For almost all tests this is sufficient.
|
16 |
+
Sometimes, though, you want to weaken a test case.
|
17 |
+
</p>
|
18 |
+
<p>
|
19 |
+
One place where a test can be too tightly coupled is with
|
20 |
+
text matching.
|
21 |
+
Suppose we have a component that outputs a helpful error
|
22 |
+
message when something goes wrong.
|
23 |
+
You want to test that the correct error was sent, but the actual
|
24 |
+
text may be rather long.
|
25 |
+
If you test for the text exactly, then every time the exact wording
|
26 |
+
of the message changes, you will have to go back and edit the test suite.
|
27 |
+
</p>
|
28 |
+
<p>
|
29 |
+
For example, suppose we have a news service that has failed
|
30 |
+
to connect to its remote source.
|
31 |
+
<php><![CDATA[
|
32 |
+
<strong>class NewsService {
|
33 |
+
...
|
34 |
+
function publish(&$writer) {
|
35 |
+
if (! $this->isConnected()) {
|
36 |
+
$writer->write('Cannot connect to news service "' .
|
37 |
+
$this->_name . '" at this time. ' .
|
38 |
+
'Please try again later.');
|
39 |
+
}
|
40 |
+
...
|
41 |
+
}
|
42 |
+
}</strong>
|
43 |
+
]]></php>
|
44 |
+
Here it is sending its content to a
|
45 |
+
<code>Writer</code> class.
|
46 |
+
We could test this behaviour with a
|
47 |
+
<code>MockWriter</code> like so...
|
48 |
+
<php><![CDATA[
|
49 |
+
class TestOfNewsService extends UnitTestCase {
|
50 |
+
...
|
51 |
+
function testConnectionFailure() {<strong>
|
52 |
+
$writer = &new MockWriter();
|
53 |
+
$writer->expectOnce('write', array(
|
54 |
+
'Cannot connect to news service ' .
|
55 |
+
'"BBC News" at this time. ' .
|
56 |
+
'Please try again later.'));
|
57 |
+
|
58 |
+
$service = &new NewsService('BBC News');
|
59 |
+
$service->publish($writer);</strong>
|
60 |
+
}
|
61 |
+
}
|
62 |
+
]]></php>
|
63 |
+
This is a good example of a brittle test.
|
64 |
+
If we decide to add additional instructions, such as
|
65 |
+
suggesting an alternative news source, we will break
|
66 |
+
our tests even though no underlying functionality
|
67 |
+
has been altered.
|
68 |
+
</p>
|
69 |
+
<p>
|
70 |
+
To get around this, we would like to do a regular expression
|
71 |
+
test rather than an exact match.
|
72 |
+
We can actually do this with...
|
73 |
+
<php><![CDATA[
|
74 |
+
class TestOfNewsService extends UnitTestCase {
|
75 |
+
...
|
76 |
+
function testConnectionFailure() {
|
77 |
+
$writer = &new MockWriter();<strong>
|
78 |
+
$writer->expectOnce(
|
79 |
+
'write',
|
80 |
+
array(new PatternExpectation('/cannot connect/i')));</strong>
|
81 |
+
|
82 |
+
$service = &new NewsService('BBC News');
|
83 |
+
$service->publish($writer);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
]]></php>
|
87 |
+
Instead of passing in the expected parameter to the
|
88 |
+
<code>MockWriter</code> we pass an
|
89 |
+
expectation class called
|
90 |
+
<code>WantedPatternExpectation</code>.
|
91 |
+
The mock object is smart enough to recognise this as special
|
92 |
+
and to treat it differently.
|
93 |
+
Rather than simply comparing the incoming argument to this
|
94 |
+
object, it uses the expectation object itself to
|
95 |
+
perform the test.
|
96 |
+
</p>
|
97 |
+
<p>
|
98 |
+
The <code>WantedPatternExpectation</code> takes
|
99 |
+
the regular expression to match in its constructor.
|
100 |
+
Whenever a comparison is made by the <code>MockWriter</code>
|
101 |
+
against this expectation class, it will do a
|
102 |
+
<code>preg_match()</code> with this pattern.
|
103 |
+
With our test case above, as long as "cannot connect"
|
104 |
+
appears in the text of the string, the mock will issue a pass
|
105 |
+
to the unit tester.
|
106 |
+
The rest of the text does not matter.
|
107 |
+
</p>
|
108 |
+
<p>
|
109 |
+
The possible expectation classes are...
|
110 |
+
<table><tbody>
|
111 |
+
<tr><td><code>AnythingExpectation</code></td><td>Will always match</td></tr>
|
112 |
+
<tr><td><code>EqualExpectation</code></td><td>An equality, rather than the stronger identity comparison</td></tr>
|
113 |
+
<tr><td><code>NotEqualExpectation</code></td><td>An inequality comparison</td></tr>
|
114 |
+
<tr><td><code>IndenticalExpectation</code></td><td>The default mock object check which must match exactly</td></tr>
|
115 |
+
<tr><td><code>NotIndenticalExpectation</code></td><td>Inverts the mock object logic</td></tr>
|
116 |
+
<tr><td><code>WithinMarginExpectation</code></td><td>Compares a value to within a margin</td></tr>
|
117 |
+
<tr><td><code>OutsideMarginExpectation</code></td><td>Checks that a value is out side the margin</td></tr>
|
118 |
+
<tr><td><code>PatternExpectation</code></td><td>Uses a Perl Regex to match a string</td></tr>
|
119 |
+
<tr><td><code>NoPatternExpectation</code></td><td>Passes only if failing a Perl Regex</td></tr>
|
120 |
+
<tr><td><code>IsAExpectation</code></td><td>Checks the type or class name only</td></tr>
|
121 |
+
<tr><td><code>NotAExpectation</code></td><td>Opposite of the <code>IsAExpectation</code></td></tr>
|
122 |
+
<tr><td><code>MethodExistsExpectation</code></td><td>Checks a method is available on an object</td></tr>
|
123 |
+
</tbody></table>
|
124 |
+
Most take the expected value in the constructor.
|
125 |
+
The exceptions are the pattern matchers, which take a regular expression,
|
126 |
+
and the <code>IsAExpectation</code> and <code>NotAExpectation</code> which takes a type
|
127 |
+
or class name as a string.
|
128 |
+
</p>
|
129 |
+
<p>
|
130 |
+
Some examples...
|
131 |
+
</p>
|
132 |
+
<p>
|
133 |
+
<php><![CDATA[
|
134 |
+
$mock->expectOnce('method', array(new IdenticalExpectation(14)));
|
135 |
+
]]></php>
|
136 |
+
This is the same as <code>$mock->expectOnce('method', array(14))</code>.
|
137 |
+
<php><![CDATA[
|
138 |
+
$mock->expectOnce('method', array(new EqualExpectation(14)));
|
139 |
+
]]></php>
|
140 |
+
This is different from the previous version in that the string
|
141 |
+
<code>"14"</code> as a parameter will also pass.
|
142 |
+
Sometimes the additional type checks of SimpleTest are too restrictive.
|
143 |
+
<php><![CDATA[
|
144 |
+
$mock->expectOnce('method', array(new AnythingExpectation(14)));
|
145 |
+
]]></php>
|
146 |
+
This is the same as <code>$mock->expectOnce('method', array('*'))</code>.
|
147 |
+
<php><![CDATA[
|
148 |
+
$mock->expectOnce('method', array(new IdenticalExpectation('*')));
|
149 |
+
]]></php>
|
150 |
+
This is handy if you want to assert a literal <code>"*"</code>.
|
151 |
+
<php><![CDATA[
|
152 |
+
new NotIdenticalExpectation(14)
|
153 |
+
]]></php>
|
154 |
+
This matches on anything other than integer 14.
|
155 |
+
Even the string <code>"14"</code> would pass.
|
156 |
+
<php><![CDATA[
|
157 |
+
new WithinMarginExpectation(14.0, 0.001)
|
158 |
+
]]></php>
|
159 |
+
This will accept any value from 13.999 to 14.001 inclusive.
|
160 |
+
</p>
|
161 |
+
</section>
|
162 |
+
<section name="behaviour" title="Using expectations to control stubs">
|
163 |
+
<p>
|
164 |
+
The expectation classes can be used not just for sending assertions
|
165 |
+
from mock objects, but also for selecting behaviour for the
|
166 |
+
<a local="mock_objects_documentation">mock objects</a>.
|
167 |
+
Anywhere a list of arguments is given, a list of expectation objects
|
168 |
+
can be inserted instead.
|
169 |
+
</p>
|
170 |
+
<p>
|
171 |
+
Suppose we want a mock authorisation server to simulate a successful login,
|
172 |
+
but only if it receives a valid session object.
|
173 |
+
We can do this as follows...
|
174 |
+
<php><![CDATA[
|
175 |
+
Mock::generate('Authorisation');
|
176 |
+
<strong>
|
177 |
+
$authorisation = new MockAuthorisation();
|
178 |
+
$authorisation->setReturnValue(
|
179 |
+
'isAllowed',
|
180 |
+
true,
|
181 |
+
array(new IsAExpectation('Session', 'Must be a session')));
|
182 |
+
$authorisation->setReturnValue('isAllowed', false);</strong>
|
183 |
+
]]></php>
|
184 |
+
We have set the default mock behaviour to return false when
|
185 |
+
<code>isAllowed</code> is called.
|
186 |
+
When we call the method with a single parameter that
|
187 |
+
is a <code>Session</code> object, it will return true.
|
188 |
+
We have also added a second parameter as a message.
|
189 |
+
This will be displayed as part of the mock object
|
190 |
+
failure message if this expectation is the cause of
|
191 |
+
a failure.
|
192 |
+
</p>
|
193 |
+
<p>
|
194 |
+
This kind of sophistication is rarely useful, but is included for
|
195 |
+
completeness.
|
196 |
+
</p>
|
197 |
+
</section>
|
198 |
+
<section name="extending" title="Creating your own expectations">
|
199 |
+
<p>
|
200 |
+
The expectation classes have a very simple structure.
|
201 |
+
So simple that it is easy to create your own versions for
|
202 |
+
commonly used test logic.
|
203 |
+
</p>
|
204 |
+
<p>
|
205 |
+
As an example here is the creation of a class to test for
|
206 |
+
valid IP addresses.
|
207 |
+
In order to work correctly with the stubs and mocks the new
|
208 |
+
expectation class should extend
|
209 |
+
<code>SimpleExpectation</code>...
|
210 |
+
<php><![CDATA[
|
211 |
+
<strong>class ValidIp extends SimpleExpectation {
|
212 |
+
|
213 |
+
function test($ip) {
|
214 |
+
return (ip2long($ip) != -1);
|
215 |
+
}
|
216 |
+
|
217 |
+
function testMessage($ip) {
|
218 |
+
return "Address [$ip] should be a valid IP address";
|
219 |
+
}
|
220 |
+
}</strong>
|
221 |
+
]]></php>
|
222 |
+
There are only two methods to implement.
|
223 |
+
The <code>test()</code> method should
|
224 |
+
evaluate to true if the expectation is to pass, and
|
225 |
+
false otherwise.
|
226 |
+
The <code>testMessage()</code> method
|
227 |
+
should simply return some helpful text explaining the test
|
228 |
+
that was carried out.
|
229 |
+
</p>
|
230 |
+
<p>
|
231 |
+
This class can now be used in place of the earlier expectation
|
232 |
+
classes.
|
233 |
+
</p>
|
234 |
+
</section>
|
235 |
+
<section name="unit" title="Under the bonnet of the unit tester">
|
236 |
+
<p>
|
237 |
+
The <a href="http://sourceforge.net/projects/simpletest/">SimpleTest unit testing framework</a>
|
238 |
+
also uses the expectation classes internally for the
|
239 |
+
<a local="unit_test_documentation">UnitTestCase class</a>.
|
240 |
+
We can also take advantage of these mechanisms to reuse our
|
241 |
+
homebrew expectation classes within the test suites directly.
|
242 |
+
</p>
|
243 |
+
<p>
|
244 |
+
The most crude way of doing this is to use the
|
245 |
+
<code>SimpleTest::assert()</code> method to
|
246 |
+
test against it directly...
|
247 |
+
<php><![CDATA[
|
248 |
+
<strong>class TestOfNetworking extends UnitTestCase {
|
249 |
+
...
|
250 |
+
function testGetValidIp() {
|
251 |
+
$server = &new Server();
|
252 |
+
$this->assert(
|
253 |
+
new ValidIp(),
|
254 |
+
$server->getIp(),
|
255 |
+
'Server IP address->%s');
|
256 |
+
}
|
257 |
+
}</strong>
|
258 |
+
]]></php>
|
259 |
+
This is a little untidy compared with our usual
|
260 |
+
<code>assert...()</code> syntax.
|
261 |
+
</p>
|
262 |
+
<p>
|
263 |
+
For such a simple case we would normally create a
|
264 |
+
separate assertion method on our test case rather
|
265 |
+
than bother using the expectation class.
|
266 |
+
If we pretend that our expectation is a little more
|
267 |
+
complicated for a moment, so that we want to reuse it,
|
268 |
+
we get...
|
269 |
+
<php><![CDATA[
|
270 |
+
class TestOfNetworking extends UnitTestCase {
|
271 |
+
...<strong>
|
272 |
+
function assertValidIp($ip, $message = '%s') {
|
273 |
+
$this->assert(new ValidIp(), $ip, $message);
|
274 |
+
}</strong>
|
275 |
+
|
276 |
+
function testGetValidIp() {
|
277 |
+
$server = &new Server();<strong>
|
278 |
+
$this->assertValidIp(
|
279 |
+
$server->getIp(),
|
280 |
+
'Server IP address->%s');</strong>
|
281 |
+
}
|
282 |
+
}
|
283 |
+
]]></php>
|
284 |
+
It is unlikely we would ever need this degree of control
|
285 |
+
over the testing machinery.
|
286 |
+
It is rare to need the expectations for more than pattern
|
287 |
+
matching.
|
288 |
+
Also, complex expectation classes could make the tests
|
289 |
+
harder to read and debug.
|
290 |
+
These mechanisms are really of most use to authors of systems
|
291 |
+
that will extend the test framework to create their own tool set.
|
292 |
+
</p>
|
293 |
+
</section>
|
294 |
+
</content>
|
295 |
+
<internal>
|
296 |
+
<link>
|
297 |
+
Using expectations for
|
298 |
+
<a href="#mock">more precise testing with mock objects</a>
|
299 |
+
</link>
|
300 |
+
<link>
|
301 |
+
<a href="#behaviour">Changing mock object behaviour</a> with expectations
|
302 |
+
</link>
|
303 |
+
<link>
|
304 |
+
<a href="#extending">Extending the expectations</a>
|
305 |
+
</link>
|
306 |
+
<link>
|
307 |
+
Underneath SimpleTest <a href="#unit">uses expectation classes</a>
|
308 |
+
</link>
|
309 |
+
</internal>
|
310 |
+
<external>
|
311 |
+
<link>
|
312 |
+
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
313 |
+
</link>
|
314 |
+
<link>
|
315 |
+
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
316 |
+
</link>
|
317 |
+
<link>
|
318 |
+
The expectations mimic the constraints in <a href="http://www.jmock.org/">JMock</a>.
|
319 |
+
</link>
|
320 |
+
<link>
|
321 |
+
<a href="http://simpletest.org/api/">Full API for SimpleTest</a>
|
322 |
+
from the PHPDoc.
|
323 |
+
</link>
|
324 |
+
</external>
|
325 |
+
<meta>
|
326 |
+
<keywords>
|
327 |
+
mock objects,
|
328 |
+
test driven development,
|
329 |
+
inheritance of expectations,
|
330 |
+
mock object constraints,
|
331 |
+
advanced PHP unit testing,
|
332 |
+
test first,
|
333 |
+
test framework architecture
|
334 |
+
expectations in simpletest
|
335 |
+
test cases
|
336 |
+
server stubs
|
337 |
+
</keywords>
|
338 |
+
</meta>
|
339 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_autorun.xml
ADDED
@@ -0,0 +1,209 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: experimental_autorun.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Running the tests, the easy way with autorun" here="Autorunning test cases">
|
4 |
+
<long_title>[experimental] Running the tests, the easy way with autorun</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<div class="experimental">
|
8 |
+
Careful : this documentation refers to un-released code. It's only available in CVS.
|
9 |
+
</div>
|
10 |
+
<p>
|
11 |
+
You started with unit testing not so long ago and
|
12 |
+
this is what you came up with... A file <em>test_of_all_modules.php</em>
|
13 |
+
containing :
|
14 |
+
<php><![CDATA[
|
15 |
+
<?php
|
16 |
+
require_once('simpletest/unit_tester.php');
|
17 |
+
require_once('simpletest/reporter.php');
|
18 |
+
|
19 |
+
$group = new TestSuite();
|
20 |
+
$group->addFile('test_of_module_ship.php');
|
21 |
+
$group->addFile('test_of_module_pay.php');
|
22 |
+
|
23 |
+
$group->run(new HtmlReporter());
|
24 |
+
?>
|
25 |
+
]]></php>
|
26 |
+
</p>
|
27 |
+
<p>
|
28 |
+
But now you have a new way of shipping your socks overseas. Easily
|
29 |
+
you just need to add a new file <em>test_of_module_ship_overseas.php</em>
|
30 |
+
to your test runner... Quickly enough, you end up with a lot of file :
|
31 |
+
<php><![CDATA[
|
32 |
+
<?php
|
33 |
+
require_once('simpletest/unit_tester.php');
|
34 |
+
require_once('simpletest/reporter.php');
|
35 |
+
|
36 |
+
$group = new TestSuite();
|
37 |
+
$group->addFile('test_of_module_ship.php');<strong>
|
38 |
+
$group->addFile('test_of_module_ship_overseas.php');
|
39 |
+
$group->addFile('test_of_module_ship_france.php');
|
40 |
+
$group->addFile('test_of_module_ship_uk.php');
|
41 |
+
$group->addFile('test_of_module_ship_us.php');
|
42 |
+
...</strong>
|
43 |
+
$group->addFile('test_of_module_pay.php');
|
44 |
+
|
45 |
+
$group->run(new HtmlReporter());
|
46 |
+
?>
|
47 |
+
]]></php>
|
48 |
+
</p>
|
49 |
+
<p>
|
50 |
+
As you list grows, running the test suite becomes too time-
|
51 |
+
consuming : the tests are actually slowing you down while writing code.
|
52 |
+
</p>
|
53 |
+
</introduction>
|
54 |
+
<section name="autorun" title="Introducing 'autorun'">
|
55 |
+
<p>
|
56 |
+
What we're looking for now is a way to run one test at a time
|
57 |
+
and still be able to run every one of them easily...
|
58 |
+
What if we could just write - in a console for example :
|
59 |
+
<div class="console">
|
60 |
+
home: /$ <strong>php test_of_module_ship_us.php</strong>
|
61 |
+
</div>
|
62 |
+
and still be able to do :
|
63 |
+
<div class="console">
|
64 |
+
home: /$ <strong>php test_of_all_modules.php</strong>
|
65 |
+
</div>
|
66 |
+
It's possible now : you just need to add one include at the top of
|
67 |
+
each test case. Your <em>test_of_module_ship_us.php</em> will
|
68 |
+
look like :
|
69 |
+
<php><![CDATA[
|
70 |
+
<?php<strong>
|
71 |
+
require_once('simpletest/autorun.php');</strong>
|
72 |
+
|
73 |
+
class TestUsingParcelForce extends UnitTestCase {
|
74 |
+
function testParcelForceIsFine() {
|
75 |
+
$this->assertTrue(true);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
class TestUsingMyOwnAirplane extends UnitTestCase {
|
80 |
+
function testUsingMyOwnAirplaneOnlyWorksForSmallGifts() {
|
81 |
+
$this->assertFalse(false);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
?>
|
85 |
+
]]></php>
|
86 |
+
</p>
|
87 |
+
</section>
|
88 |
+
<section name="preference" title="Setting the prefered runner">
|
89 |
+
<p>
|
90 |
+
PHP is mainly for web stuff : I'm guessing your first test platform is
|
91 |
+
a web browser, Firefox, Opera or Safari usually. And SimpleTest comes with
|
92 |
+
a nice HTML interface : it's the one we want to use when running one file.
|
93 |
+
We can tell our <em>test_of_module_ship_us.php</em> to use it by default :
|
94 |
+
<php><![CDATA[
|
95 |
+
<?php
|
96 |
+
require_once('simpletest/autorun.php');<strong>
|
97 |
+
SimpleTest :: prefer(new HtmlReporter());</strong>
|
98 |
+
|
99 |
+
class TestUsingParcelForce extends UnitTestCase {
|
100 |
+
function testParcelForceIsFine() {
|
101 |
+
$this->assertTrue(true);
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
class TestUsingMyOwnAirplane extends UnitTestCase {
|
106 |
+
function testUsingMyOwnAirplaneOnlyWorksForSmallGifts() {
|
107 |
+
$this->assertFalse(false);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
?>
|
111 |
+
]]></php>
|
112 |
+
</p>
|
113 |
+
<p>
|
114 |
+
We get a nice green bar :
|
115 |
+
<div class="demo">
|
116 |
+
<h1>TestSuite</h1>
|
117 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">2/2 test cases complete:
|
118 |
+
<strong>2</strong> passes, <strong>0</strong> fails and <strong>0</strong> exceptions.</div>
|
119 |
+
</div>
|
120 |
+
</p>
|
121 |
+
</section>
|
122 |
+
<section name="autorun-for-suites" title="Autorun for test suites">
|
123 |
+
<p>
|
124 |
+
So we've managed to get the time spent running the test under control
|
125 |
+
during the coding period. We now want to make sure all the tests still
|
126 |
+
pass, all the time. Or at least after every commit to the SVN (or CVS)
|
127 |
+
trunk.
|
128 |
+
</p>
|
129 |
+
<p>
|
130 |
+
Such process is called <em>continuous integration</em> : Martin Fowler writes
|
131 |
+
really well about this practice <cite>where members of a team integrate their
|
132 |
+
work frequently [...]. Each integration is verified by an automated buid
|
133 |
+
(including test) to detect integration errors as quickly as possible</cite>.
|
134 |
+
So I can just give you the link :
|
135 |
+
<a href="http://www.martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a>.
|
136 |
+
</p>
|
137 |
+
<p>
|
138 |
+
Now our post-commit hook in SVN (or Phing task if you prefer) doesn't need
|
139 |
+
the HTML reporter. We need something useful at the command line : TextReporter
|
140 |
+
to the rescue. Our <em>test_of_all_modules.php</em> becomes :
|
141 |
+
<php><![CDATA[
|
142 |
+
<?php
|
143 |
+
require_once('simpletest/autorun.php');
|
144 |
+
<strong>
|
145 |
+
SimpleTest :: prefer(new TextReporter());</strong>
|
146 |
+
|
147 |
+
class AllTests extends TestSuite {
|
148 |
+
function AllTests() {
|
149 |
+
parent::TestSuite();
|
150 |
+
$this->addFile('test_of_module_ship.php');
|
151 |
+
$this->addFile('test_of_module_ship_overseas.php');
|
152 |
+
$this->addFile('test_of_module_ship_france.php');
|
153 |
+
$this->addFile('test_of_module_ship_uk.php');
|
154 |
+
$this->addFile('test_of_module_ship_us.php');
|
155 |
+
...
|
156 |
+
$this->addFile('test_of_module_pay.php');
|
157 |
+
}
|
158 |
+
}
|
159 |
+
?>
|
160 |
+
]]></php>
|
161 |
+
</p>
|
162 |
+
<p>
|
163 |
+
The results show up nicely in the console :
|
164 |
+
<div class="console">
|
165 |
+
home: /$ php test_of_all_modules.php<br />
|
166 |
+
<strong>grouptest<br />
|
167 |
+
OK<br />
|
168 |
+
Test cases run: 10/10, Passes: 37, Failures: 0, Exceptions: 0</strong>
|
169 |
+
</div>
|
170 |
+
</p>
|
171 |
+
</section>
|
172 |
+
</content>
|
173 |
+
<internal>
|
174 |
+
<link>Introducing <a href="#autorun">'autorun'</a>.</link>
|
175 |
+
<link>Setting <a href="#preference">the prefered runner</a>.</link>
|
176 |
+
<link>Autorun for <a href="#autorun-for-suites">test suites</a>.</link>
|
177 |
+
</internal>
|
178 |
+
<external>
|
179 |
+
<link>
|
180 |
+
The <a href="http://junit.sourceforge.net/doc/faq/faq.htm">JUnit FAQ</a>
|
181 |
+
has plenty of useful testing advice.
|
182 |
+
</link>
|
183 |
+
<link>
|
184 |
+
You will need the <a href="simple_test.php">SimpleTest testing framework</a>
|
185 |
+
for these examples.
|
186 |
+
</link>
|
187 |
+
</external>
|
188 |
+
<meta>
|
189 |
+
<keywords>
|
190 |
+
software development,
|
191 |
+
php programming,
|
192 |
+
programming php,
|
193 |
+
software development tools,
|
194 |
+
php tutorial,
|
195 |
+
free php scripts,
|
196 |
+
architecture,
|
197 |
+
php resources,
|
198 |
+
mock objects,
|
199 |
+
junit,
|
200 |
+
php testing,
|
201 |
+
unit test,
|
202 |
+
automated php testing,
|
203 |
+
test cases tutorial,
|
204 |
+
explain unit test case,
|
205 |
+
unit test example,
|
206 |
+
unit test
|
207 |
+
</keywords>
|
208 |
+
</meta>
|
209 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_dom_tester.xml
ADDED
@@ -0,0 +1,231 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: experimental_dom_tester.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Testing elements by CSS selector" here="DOM tester">
|
4 |
+
<long_title>[experimental] Testing elements by CSS selector</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<div class="experimental">
|
8 |
+
Careful : this documentation refers to un-released code. It's only available in CVS.
|
9 |
+
</div>
|
10 |
+
<p>
|
11 |
+
Before SimpleTest2 gets a new browser (PHP5 only and DOM based), a new
|
12 |
+
extension made its way to the SimpleTest trunk.
|
13 |
+
</p>
|
14 |
+
<p>
|
15 |
+
Note : it's already PHP5 only.
|
16 |
+
</p>
|
17 |
+
</introduction>
|
18 |
+
<section name="recorder" title="Testing for Web2.0">
|
19 |
+
<p>
|
20 |
+
1998 seems a long time ago now : it's the year
|
21 |
+
the <a href="http://www.webstandards.org/about/">the Web Standards Project (WaSP)</a>
|
22 |
+
started fighting for standards.
|
23 |
+
</p>
|
24 |
+
<p>
|
25 |
+
Nearly ten years later, every web developper is now familiar with CSS :
|
26 |
+
<em>id</em> & <em>class</em> are the new tools of the trade.
|
27 |
+
The tricks you've learned while styling, you can re-use them when testing your web site.
|
28 |
+
</p>
|
29 |
+
<p>
|
30 |
+
I was about to start with the <a href="http://flickr.com/">Flickr home page</a>
|
31 |
+
but then again, this is what the HTML source looks like :
|
32 |
+
<php><![CDATA[
|
33 |
+
<body>
|
34 |
+
<div id="beacon"><img src="http://geo.yahoo.com/f?s=792600119&t=7797cfa4695ea4166ba6c8ee269ec1b6" width="0" height="0" alt="" /></div>
|
35 |
+
<div align="center">
|
36 |
+
<table cellspacing="0" border="0" cellpadding="0" class="Photo">
|
37 |
+
<tr valign="top">
|
38 |
+
<!-- PHOTO -->
|
39 |
+
<td>
|
40 |
+
[...]
|
41 |
+
]]></php>
|
42 |
+
Who said <cite>too many tables ?</cite> So I picked something else...
|
43 |
+
the <a href="http://simpletest.org/">SimpleTest home page</a> !
|
44 |
+
<php><![CDATA[
|
45 |
+
<body>
|
46 |
+
<div>
|
47 |
+
<div id="actions">
|
48 |
+
<div id="logo">
|
49 |
+
<a href="http://simpletest.org/index.html"><img name="simpletestlogo" src="images/simpletest-logo.png" width="335" height="127" border="0" id="simpletestlogo" alt="" /></a>
|
50 |
+
</div>
|
51 |
+
<div>
|
52 |
+
<div>
|
53 |
+
<a href="en/download.html"><img name="simpletestdownload" src="images/simpletest-download.png" width="305" height="109" border="0" id="simpletestdownload" alt="" /></a>
|
54 |
+
[...]
|
55 |
+
]]></php>
|
56 |
+
</p>
|
57 |
+
</section>
|
58 |
+
<section name="recorder-results" title="Basic CSS selectors...">
|
59 |
+
<p>
|
60 |
+
As usual we start with the necessary <code>require_once</code>
|
61 |
+
<php><![CDATA[
|
62 |
+
<?php
|
63 |
+
require_once(dirname(__FILE__) . '/../../autorun.php');
|
64 |
+
require_once(dirname(__FILE__) . '/../dom_tester.php');
|
65 |
+
?>
|
66 |
+
]]></php>
|
67 |
+
The <code>DomTestCase</code> extends the <code>WebTestCase</code>,
|
68 |
+
we can just use it the same way.
|
69 |
+
</p>
|
70 |
+
<p>
|
71 |
+
<php><![CDATA[
|
72 |
+
<?php
|
73 |
+
require_once(dirname(__FILE__) . '/../../autorun.php');
|
74 |
+
require_once(dirname(__FILE__) . '/../dom_tester.php');
|
75 |
+
|
76 |
+
class TestOfLiveCssSelectors extends DomTestCase {
|
77 |
+
function testGet() {
|
78 |
+
$url = 'http://simpletest.org/';
|
79 |
+
$this->assertTrue($this->get($url));
|
80 |
+
$this->assertEqual($this->getUrl(), $url);<strong>
|
81 |
+
$this->assertElementsBySelector(
|
82 |
+
'h2',
|
83 |
+
array('Screenshots', 'Documentation', 'Contributing')
|
84 |
+
);</strong>
|
85 |
+
}
|
86 |
+
}
|
87 |
+
?>
|
88 |
+
]]></php>
|
89 |
+
</p>
|
90 |
+
<p>
|
91 |
+
I was expecting to get a nice green bar straight away :
|
92 |
+
I did wrote the HTML template after all.
|
93 |
+
Unfortunately it didn't happen, PHP gave me some nice exceptions :
|
94 |
+
<div class="console">
|
95 |
+
home: /$ php dom_tester_doc_test.php<br />
|
96 |
+
<strong>dom_tester_doc_test.php<br />
|
97 |
+
Exception 1!<br />
|
98 |
+
Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestlogo already defined in Entity, line: 12] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br />
|
99 |
+
in testGet<br />
|
100 |
+
in TestOfLiveCssSelectors<br />
|
101 |
+
Exception 2!<br />
|
102 |
+
Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestdownload already defined in Entity, line: 16] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br />
|
103 |
+
in testGet<br />
|
104 |
+
in TestOfLiveCssSelectors<br />
|
105 |
+
Exception 3!<br />
|
106 |
+
Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpleteststarttesting already defined in Entity, line: 24] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br />
|
107 |
+
in testGet<br />
|
108 |
+
in TestOfLiveCssSelectors<br />
|
109 |
+
Exception 4!<br />
|
110 |
+
Unexpected PHP error [DOMDocument::loadHTML() [<a href='function.DOMDocument-loadHTML'>function.DOMDocument-loadHTML</a>]: ID simpletestsupport already defined in Entity, line: 38] severity [E_WARNING] in [/Users/perrick/Sites/simpletest/extensions/dom_tester.php line 103]<br />
|
111 |
+
in testGet<br />
|
112 |
+
in TestOfLiveCssSelectors<br />
|
113 |
+
FAILURES!!!<br />
|
114 |
+
Test cases run: 1/1, Passes: 3, Failures: 0, Exceptions: 4<br /></strong>
|
115 |
+
</div>
|
116 |
+
That's what validation is all about I guess.
|
117 |
+
</p>
|
118 |
+
<p>
|
119 |
+
Back to the drawing board... A simple fix later, everything is fine.
|
120 |
+
<div class="console">
|
121 |
+
home: /$ php dom_tester_doc_test.php<br />
|
122 |
+
<strong>dom_tester_doc_test.php<br />
|
123 |
+
OK<br />
|
124 |
+
Test cases run: 1/1, Passes: 3, Failures: 0, Exceptions: 0<br /></strong>
|
125 |
+
</div>
|
126 |
+
</p>
|
127 |
+
</section>
|
128 |
+
<section name="recorder-results" title="...and non so basic selectors">
|
129 |
+
<p>
|
130 |
+
If you thought it was easy, we can make things a little bit more difficult -
|
131 |
+
or precise - with attribute selectors :
|
132 |
+
<php><![CDATA[
|
133 |
+
[...]
|
134 |
+
class TestOfLiveCssSelectors extends DomTestCase {
|
135 |
+
function testGet() {
|
136 |
+
$url = 'http://simpletest.org/';
|
137 |
+
$this->assertTrue($this->get($url));
|
138 |
+
$this->assertEqual($this->getUrl(), $url);
|
139 |
+
$this->assertElementsBySelector(
|
140 |
+
'h2',
|
141 |
+
array('Screenshots', 'Documentation', 'Contributing')
|
142 |
+
);<strong>
|
143 |
+
$this->assertElementsBySelector(
|
144 |
+
'a[href="http://simpletest.org/api/"]',
|
145 |
+
array('the complete API', 'documented API')
|
146 |
+
);</strong>
|
147 |
+
}
|
148 |
+
}
|
149 |
+
[...]
|
150 |
+
]]></php>
|
151 |
+
<div class="console">
|
152 |
+
home: /$ php dom_tester_doc_test.php<br />
|
153 |
+
<strong>dom_tester_doc_test.php<br />
|
154 |
+
OK<br />
|
155 |
+
Test cases run: 1/1, Passes: 4, Failures: 0, Exceptions: 0<br /></strong>
|
156 |
+
</div>
|
157 |
+
</p>
|
158 |
+
<p>
|
159 |
+
Oh and by the way, combinators do work as well :
|
160 |
+
<php><![CDATA[
|
161 |
+
[...]
|
162 |
+
class TestOfLiveCssSelectors extends DomTestCase {
|
163 |
+
function testGet() {
|
164 |
+
$url = 'http://simpletest.org/';
|
165 |
+
$this->assertTrue($this->get($url));
|
166 |
+
$this->assertEqual($this->getUrl(), $url);
|
167 |
+
$this->assertElementsBySelector(
|
168 |
+
'h2',
|
169 |
+
array('Screenshots', 'Documentation', 'Contributing')
|
170 |
+
);
|
171 |
+
$this->assertElementsBySelector(
|
172 |
+
'a[href="http://simpletest.org/api/"]',
|
173 |
+
array('the complete API', 'documented API')
|
174 |
+
);<strong>
|
175 |
+
$this->assertElementsBySelector(
|
176 |
+
'div#content > p > strong',
|
177 |
+
array('SimpleTest PHP unit tester')
|
178 |
+
);</strong>
|
179 |
+
}
|
180 |
+
}
|
181 |
+
[...]
|
182 |
+
]]></php>
|
183 |
+
<div class="console">
|
184 |
+
home: /$ php dom_tester_doc_test.php<br />
|
185 |
+
<strong>dom_tester_doc_test.php<br />
|
186 |
+
OK<br />
|
187 |
+
Test cases run: 1/1, Passes: 5, Failures: 0, Exceptions: 0<br /></strong>
|
188 |
+
</div>
|
189 |
+
</p>
|
190 |
+
</section>
|
191 |
+
</content>
|
192 |
+
<internal>
|
193 |
+
<link>A <a href="#recorder">Recorder</a> for non-developpers.</link>
|
194 |
+
<link>Exploring the <a href="#recorder-results">Recorder results</a>.</link>
|
195 |
+
</internal>
|
196 |
+
<external>
|
197 |
+
<link>
|
198 |
+
The <a href="http://junit.sourceforge.net/doc/faq/faq.htm">JUnit FAQ</a>
|
199 |
+
has plenty of useful testing advice.
|
200 |
+
</link>
|
201 |
+
<link>
|
202 |
+
<a href="group_test_tutorial.php">Next</a> is grouping test
|
203 |
+
cases together.
|
204 |
+
</link>
|
205 |
+
<link>
|
206 |
+
You will need the <a href="simple_test.php">SimpleTest testing framework</a>
|
207 |
+
for these examples.
|
208 |
+
</link>
|
209 |
+
</external>
|
210 |
+
<meta>
|
211 |
+
<keywords>
|
212 |
+
software development,
|
213 |
+
php programming,
|
214 |
+
programming php,
|
215 |
+
software development tools,
|
216 |
+
php tutorial,
|
217 |
+
free php scripts,
|
218 |
+
architecture,
|
219 |
+
php resources,
|
220 |
+
mock objects,
|
221 |
+
junit,
|
222 |
+
php testing,
|
223 |
+
unit test,
|
224 |
+
automated php testing,
|
225 |
+
test cases tutorial,
|
226 |
+
explain unit test case,
|
227 |
+
unit test example,
|
228 |
+
unit test
|
229 |
+
</keywords>
|
230 |
+
</meta>
|
231 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_intro.xml
ADDED
@@ -0,0 +1,54 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: experimental_intro.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Experimental stuff (in CVS only)" here="Experimental stuff">
|
4 |
+
<long_title>Experimental stuff, found in CVS only</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="intro" title="Why only in CVS">
|
7 |
+
<p>
|
8 |
+
If a bug is found in SimpleTest, chances are it'll get corrected
|
9 |
+
inside the CVS tree with the corresponding test case : just to make
|
10 |
+
sure the bug doesn't make a come back later on.
|
11 |
+
</p>
|
12 |
+
<p>
|
13 |
+
Also the SimpleTest CVS trunk is usually full of little known
|
14 |
+
experiments with code : new ideas are usually tried out there
|
15 |
+
before a general release. Before it happens, the documentation need
|
16 |
+
to be completed : that's where this section comes into place. You'll
|
17 |
+
find here new features the dev team is happy with : we're looking
|
18 |
+
for comments...
|
19 |
+
</p>
|
20 |
+
<p>
|
21 |
+
The mailing-list is usually the best place to give feedback. Other options
|
22 |
+
includes submitting a bug or a patch directly on the Sourceforge trackers...
|
23 |
+
</p>
|
24 |
+
<p class="experimental">
|
25 |
+
Note : some of these features may never make to a release or not before
|
26 |
+
a long time !
|
27 |
+
</p>
|
28 |
+
</section>
|
29 |
+
</content>
|
30 |
+
<external>
|
31 |
+
<link>
|
32 |
+
SimpleTest <a href="http://sourceforge.net/mail/?group_id=76550">mailing-lists' page on SourceForge</a>.
|
33 |
+
</link>
|
34 |
+
<link>
|
35 |
+
SimpleTest <a href="http://sourceforge.net/tracker/?group_id=76550">trackers' page on Sourceforge</a> as well.
|
36 |
+
</link>
|
37 |
+
</external>
|
38 |
+
<meta>
|
39 |
+
<keywords>
|
40 |
+
php unit testing,
|
41 |
+
test integration,
|
42 |
+
documentation,
|
43 |
+
marcus baker,
|
44 |
+
simple test,
|
45 |
+
simpletest documentation,
|
46 |
+
phpunit,
|
47 |
+
pear,
|
48 |
+
experimental,
|
49 |
+
cvs,
|
50 |
+
code experiment,
|
51 |
+
feedback
|
52 |
+
</keywords>
|
53 |
+
</meta>
|
54 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/experimental_recorder.xml
ADDED
@@ -0,0 +1,170 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: experimental_recorder.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Using the test results for other tools" here="Recorder">
|
4 |
+
<long_title>[experimental] Using the test results for other tools with the Recorder</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<div class="experimental">
|
8 |
+
Careful : this documentation refers to un-released code. It's only available in CVS.
|
9 |
+
</div>
|
10 |
+
<p>
|
11 |
+
What the developer wants from his tests is immediate feedback. The <em>TextReporter</em>
|
12 |
+
and the <em>HtmlReporter</em> are there to show this feedback. As quickly as possible
|
13 |
+
and as close to your working tools as possible : the console, the browser.
|
14 |
+
</p>
|
15 |
+
</introduction>
|
16 |
+
<section name="recorder" title="A Recorder for non-developpers">
|
17 |
+
<p>
|
18 |
+
But often developers don't work alone : you may have a team contributing to
|
19 |
+
the same code base next door, a manager a little bit further away and even
|
20 |
+
a team of testers or power users on the other side of the planet.
|
21 |
+
</p>
|
22 |
+
<p>
|
23 |
+
For them as well tests' results are valuable pieces of information ! They just need
|
24 |
+
to be formatted and archived somewhere. The <em>Recorder</em> allows you to grab all
|
25 |
+
output to a simple PHP array.
|
26 |
+
<php><![CDATA[
|
27 |
+
<?php
|
28 |
+
require_once('simpletest/autorun.php');<strong>
|
29 |
+
require_once('simpletest/ui/recorder.php');</strong>
|
30 |
+
|
31 |
+
$group = new TestSuite();
|
32 |
+
$group->addTestFile('test_of_module_ship.php');
|
33 |
+
$group->addTestFile('test_of_module_pay.php');
|
34 |
+
<strong>
|
35 |
+
$recorder = new Recorder();
|
36 |
+
$group->run($recorder);</strong>
|
37 |
+
?>
|
38 |
+
]]></php>
|
39 |
+
</p>
|
40 |
+
<p>
|
41 |
+
Within this <em>$recorder</em> object lies the test suite information.
|
42 |
+
Let's dump the <em>$recorder->results</em> variable and check what's
|
43 |
+
in it :
|
44 |
+
<php><![CDATA[
|
45 |
+
<?php
|
46 |
+
array(4) {
|
47 |
+
[0]=>
|
48 |
+
array(4) {
|
49 |
+
["time"]=>
|
50 |
+
int(1173951256)
|
51 |
+
["status"]=>
|
52 |
+
string(6) "Passed"
|
53 |
+
["test"]=>
|
54 |
+
string(129) "examples/test_of_module_ship.php->TestUsingParcelForce->testParcelForceIsFine"
|
55 |
+
["message"]=>
|
56 |
+
string(97) " at [examples/test_of_module_ship.php line 7]"
|
57 |
+
}
|
58 |
+
[1]=>
|
59 |
+
array(4) {
|
60 |
+
["time"]=>
|
61 |
+
int(1173951256)
|
62 |
+
["status"]=>
|
63 |
+
string(6) "Passed"
|
64 |
+
["test"]=>
|
65 |
+
string(154) "examples/test_of_module_ship.php->TestUsingMyOwnAirplane->testUsingMyOwnAirplaneOnlyWorksForSmallGifts"
|
66 |
+
["message"]=>
|
67 |
+
string(134) "Expected false, got [Boolean: false] at [examples/test_of_module_ship.php line 13]"
|
68 |
+
}
|
69 |
+
[2]=>
|
70 |
+
array(4) {
|
71 |
+
["time"]=>
|
72 |
+
int(1173951256)
|
73 |
+
["status"]=>
|
74 |
+
string(6) "Passed"
|
75 |
+
["test"]=>
|
76 |
+
string(135) "examples/test_of_module_pay.php->TestPayForParcelForce->testPayForParcelForceIsFine"
|
77 |
+
["message"]=>
|
78 |
+
string(96) " at [examples/test_of_module_pay.php line 7]"
|
79 |
+
}
|
80 |
+
[3]=>
|
81 |
+
array(4) {
|
82 |
+
["time"]=>
|
83 |
+
int(1173951256)
|
84 |
+
["status"]=>
|
85 |
+
string(6) "Passed"
|
86 |
+
["test"]=>
|
87 |
+
string(155) "examples/test_of_module_pay.php->TestPayForMyOwnAirplane->testPayForMyOwnAirplaneOnlyWorksForSmallGifts"
|
88 |
+
["message"]=>
|
89 |
+
string(133) "Expected false, got [Boolean: false] at [examples/test_of_module_pay.php line 13]"
|
90 |
+
}
|
91 |
+
}
|
92 |
+
?>
|
93 |
+
]]></php>
|
94 |
+
</p>
|
95 |
+
</section>
|
96 |
+
<section name="recorder-results" title="Exploring the Recorder results">
|
97 |
+
<p>
|
98 |
+
Each element of the <em>$recoder->results</em> array contains one assertion's
|
99 |
+
information :
|
100 |
+
<ul>
|
101 |
+
<li><em>time</em> : when the assertion was executed, in a timestamp format.</li>
|
102 |
+
<li><em>status</em> : either <strong>Passed</strong> or <strong>Failed</strong></li>
|
103 |
+
<li><em>test</em> : the name of the test</li>
|
104 |
+
<li><em>message</em> : the actual message, useful for understanding what went wrong</li>
|
105 |
+
</ul>
|
106 |
+
</p>
|
107 |
+
<p>
|
108 |
+
Now iterating throught the results becomes really easy...
|
109 |
+
<php><![CDATA[
|
110 |
+
<?php
|
111 |
+
require_once('simpletest/autorun.php');
|
112 |
+
require_once('simpletest/ui/recorder.php');
|
113 |
+
|
114 |
+
$group = new TestSuite();
|
115 |
+
$group->addTestFile('test_of_module_ship.php');
|
116 |
+
$group->addTestFile('test_of_module_pay.php');
|
117 |
+
$recorder = new Recorder();
|
118 |
+
$group->run($recorder);
|
119 |
+
|
120 |
+
<strong>foreach (recorder->results as $result) {
|
121 |
+
if ($result->status == "Failed") {
|
122 |
+
do_something_while_it_is_time(result);
|
123 |
+
}
|
124 |
+
}
|
125 |
+
</strong>
|
126 |
+
?>
|
127 |
+
]]></php>
|
128 |
+
</p>
|
129 |
+
</section>
|
130 |
+
</content>
|
131 |
+
<internal>
|
132 |
+
<link>A <a href="#recorder">Recorder</a> for non-developpers.</link>
|
133 |
+
<link>Exploring the <a href="#recorder-results">Recorder results</a>.</link>
|
134 |
+
</internal>
|
135 |
+
<external>
|
136 |
+
<link>
|
137 |
+
The <a href="http://junit.sourceforge.net/doc/faq/faq.htm">JUnit FAQ</a>
|
138 |
+
has plenty of useful testing advice.
|
139 |
+
</link>
|
140 |
+
<link>
|
141 |
+
<a href="group_test_tutorial.php">Next</a> is grouping test
|
142 |
+
cases together.
|
143 |
+
</link>
|
144 |
+
<link>
|
145 |
+
You will need the <a href="simple_test.php">SimpleTest testing framework</a>
|
146 |
+
for these examples.
|
147 |
+
</link>
|
148 |
+
</external>
|
149 |
+
<meta>
|
150 |
+
<keywords>
|
151 |
+
software development,
|
152 |
+
php programming,
|
153 |
+
programming php,
|
154 |
+
software development tools,
|
155 |
+
php tutorial,
|
156 |
+
free php scripts,
|
157 |
+
architecture,
|
158 |
+
php resources,
|
159 |
+
mock objects,
|
160 |
+
junit,
|
161 |
+
php testing,
|
162 |
+
unit test,
|
163 |
+
automated php testing,
|
164 |
+
test cases tutorial,
|
165 |
+
explain unit test case,
|
166 |
+
unit test example,
|
167 |
+
unit test
|
168 |
+
</keywords>
|
169 |
+
</meta>
|
170 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/extension_eclipse.xml
ADDED
@@ -0,0 +1,279 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: extension_eclipse.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Simpletest Eclipse Plugin" here="Eclipse">
|
4 |
+
<long_title>Simpletest Eclipse Plugin Documentation</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="compat" title="Compatibility">
|
7 |
+
<ul>
|
8 |
+
<li>
|
9 |
+
<b>Operating System.</b><br/>
|
10 |
+
This plugin should work on any platform on which Eclipse works. Specifically
|
11 |
+
the plugin has been tested to work on Linux, OS X, and Windows. If the
|
12 |
+
plugin does not appear to work on one of these platforms a new incompatibility
|
13 |
+
may have emerged, but this is relatively unlikely.
|
14 |
+
</li>
|
15 |
+
<li>
|
16 |
+
<b>Eclipse</b><br/>
|
17 |
+
The plugin has been designed to work with Eclipse versions 3.1.X+ and 3.2.X+.
|
18 |
+
Eclipse in general requires a JVM version of 1.4.x; there are no additional requirements for the plugin.
|
19 |
+
</li>
|
20 |
+
<li>
|
21 |
+
<b>PHP</b><br/>
|
22 |
+
The plugin has been tested to work with PHP 4.3.x+ (including PHP 5.1.x.).
|
23 |
+
</li>
|
24 |
+
<li>
|
25 |
+
<b>Xdebug</b><br/>
|
26 |
+
The plugin can be configured to work with Xdebug (version 2.0.0RC1 or later).
|
27 |
+
The php.ini file which is used by the plugin (see below for specifying the php.ini file) must load the Xdebug extension.
|
28 |
+
This is usually accomplished by adding a zend_extension_ts="Some Windows Path" or zend_extension="Some Linux Path" to your php.ini file.
|
29 |
+
Specific instructions can be found at: <a href="http://xdebug.org/install.php">http://xdebug.org/install.php</a>
|
30 |
+
Do not worry about specifying any other parameters, the plugin will handle setting the necessary parameters, as needed.
|
31 |
+
</li>
|
32 |
+
<li>
|
33 |
+
<b>Simpletest</b><br/>
|
34 |
+
The plugin has been designed to work with a specific version of Simpletest
|
35 |
+
and in fact includes the associated version of Simpletest in the plugin for compatibility.
|
36 |
+
A plugin with a version number of 1.0.0_0.0.4 would indicate that the plugin was compatible
|
37 |
+
with Simpletest version 1.0.0 and was version 0.0.4 of the plugin.
|
38 |
+
Some slight modifications to the Simpletest code are required to make the plugin
|
39 |
+
work with Simpletest; these modifications may or may not be in the released version of Simpletest.
|
40 |
+
</li>
|
41 |
+
<li>
|
42 |
+
<b>PHPUnit2</b><br/>
|
43 |
+
Starting with plugin version 0.1.6 experimental support for the CVS version of PHPUnit2
|
44 |
+
is available. To use PHPUnit2 select a path to PHPUnit2 and select PHPUnit2 test instead of
|
45 |
+
SimpleTest. Note: this is the path to the folder that contains the PHPUnit2
|
46 |
+
folder. PHPUnit3 is not currently supported but will be supported in the near future.
|
47 |
+
</li>
|
48 |
+
</ul>
|
49 |
+
</section>
|
50 |
+
<section name="install" title="Installation">
|
51 |
+
<ol>
|
52 |
+
<li>Download and Install Eclipse (<a href="http://www.eclipse.org">www.eclipse.org</a>) – if you are not sure what to download, download the Eclipse 3.1.0 SDK.</li>
|
53 |
+
<li>Download the latest Simpletest Eclipse plug-in zip file (<a href="http://sourceforge.net/project/showfiles.php?group_id=76550&package_id=159054">Simpletest Sourceforge</a>)</li>
|
54 |
+
<li>Extract the zip file to a temporary location {this will be referred to later in this documentation as $unzip}</li>
|
55 |
+
<li>Start Eclipse</li>
|
56 |
+
<li>Open the Install Wizard by clicking "Help" > "Software Updates" > "Find and Install" from the menu bar.</li>
|
57 |
+
<li>Select the second button, "Search for new features to install" and click "Next".</li>
|
58 |
+
<li>Click the button on the right hand side, "New Local Site".</li>
|
59 |
+
<li>Select the folder $unzip {the folder extracted previously}.</li>
|
60 |
+
<li>Click the "OK" button.</li>
|
61 |
+
<li>In the "Edit Local Site" window, Click the "OK" button</li>
|
62 |
+
<li>Click the "Finish" button</li>
|
63 |
+
<li>In the "Search Results" window, drill down and select "Simpletest plug-in 0.0.x"</li>
|
64 |
+
<li>Click the "Next" button.</li>
|
65 |
+
<li>Read the license and accept the license by clicking the "I accept the terms in the license agreement" radio button and then clicking the "Next" button</li>
|
66 |
+
<li>In the "Installation" window you can choose to change the location -- most users should just click the "Finish" button</li>
|
67 |
+
<li>In the "Feature Verification" window, click the "Install" button.</li>
|
68 |
+
<li>When prompted, restart Eclipse</li>
|
69 |
+
<li>
|
70 |
+
<p>After starting Eclipse for the first time after installation
|
71 |
+
you will need to perform a quick configuration of the Simpletest Plug-in.
|
72 |
+
To perform this configuration:
|
73 |
+
</p>
|
74 |
+
<ol type="a">
|
75 |
+
<li>
|
76 |
+
Select "Window" > "Preferences" from the menu bar
|
77 |
+
</li>
|
78 |
+
<li>
|
79 |
+
Select "Simpletest" from the categories on the left hand side of the popup box.
|
80 |
+
</li>
|
81 |
+
<li>
|
82 |
+
Enter or Browse for the location of a PHP executable to use.
|
83 |
+
</li>
|
84 |
+
<li>
|
85 |
+
Leave the include file blank
|
86 |
+
</li>
|
87 |
+
<li>
|
88 |
+
Enter .php as the Test File Suffix.
|
89 |
+
Alternately if you name your test PHP files with a sufficiently different suffix
|
90 |
+
(e.g sometest.tst.php) you could enter in a more differentiating suffix (e.g. .tst.php).
|
91 |
+
This helps when the plug-in is looking for tests to execute.
|
92 |
+
</li>
|
93 |
+
<li>
|
94 |
+
Hit the "Ok" button to close the preferences window.
|
95 |
+
</li>
|
96 |
+
</ol>
|
97 |
+
</li>
|
98 |
+
</ol>
|
99 |
+
</section>
|
100 |
+
<section name="update" title="Update Existing Installation">
|
101 |
+
Note: this will only work if you have previously installed the plugin using the
|
102 |
+
Eclipse installation wizard. If you previously copied directories for installation,
|
103 |
+
it is recommended that you shutdown Eclipse, delete the previous version directories, and
|
104 |
+
follow the Installation instructions above (you should not have to perform the initial configuration
|
105 |
+
portion).
|
106 |
+
<ol>
|
107 |
+
<li>Select "Help" > "Software Updates" > "Manage Configuration" from the menu</li>
|
108 |
+
<li>Drill down to find the Simpletest plugin and select it</li>
|
109 |
+
<li>In the right hand pane click the link for "Scan for Updates"</li>
|
110 |
+
<li>IF no updates are found, navigate to Window > Preferences > Install/Update > Valid Updates in the Eclipse preferences and select 'Compatible', not 'equivalent'. Then repeat the steps above.</li>
|
111 |
+
<li>Select the feature versions that you wish to upgrade, and click "Next".</li>
|
112 |
+
<li>Review the license agreements for the upgraded features. If the terms of all these licenses are acceptable, check "I accept the terms in the license agreements." Do not proceed to download the features if the license terms are not acceptable.</li>
|
113 |
+
<li>Click "Install" to allow the downloading and installing to proceed.</li>
|
114 |
+
<li>Once all the features and plug-ins have been downloaded successfully and their files installed into the product on the local computer, a new configuration that incorporates these features and plug-ins will be formulated. Click Yes when asked to exit and restart the Workbench for the changes to take effect.</li>
|
115 |
+
</ol>
|
116 |
+
</section>
|
117 |
+
<section name="uninstall" title="Uninstall">
|
118 |
+
<p>
|
119 |
+
Note: this will only work if the plugin was installed via the Feature Update method. If installed via alternate methods, then the plugin can be uninstalled by deleting the directories which were previously added.
|
120 |
+
</p>
|
121 |
+
<ol>
|
122 |
+
<li>Select "Help" > "Software Updates" > "Manage Configuration"</li>
|
123 |
+
<li>Drill down to find the Simpletest plugin</li>
|
124 |
+
<li>Right-click on the Simpletest plugin and select the option "Disable"</li>
|
125 |
+
<li>when prompted, restart Eclipse</li>
|
126 |
+
<li>After Eclipse has restarted, select "Help" > "Software Updates" > "Manage Configuration" from the menu bar</li>
|
127 |
+
<li>Select the option from the toolbar "Show Disabled Features"</li>
|
128 |
+
<li>Drill down to find the Simpletest plugin</li>
|
129 |
+
<li>Right-click on the Simpletest plugin and select the option "Uninstall"</li>
|
130 |
+
<li>When prompted, restart Eclipse</li>
|
131 |
+
</ol>
|
132 |
+
</section>
|
133 |
+
<section name="usage" title="Usage">
|
134 |
+
<p>
|
135 |
+
The following details some sample usages of the plugin.
|
136 |
+
</p>
|
137 |
+
<ol>
|
138 |
+
<li>Create a new test project (a holding place for related files)
|
139 |
+
<ol>
|
140 |
+
<li>Select "File" > "New" > "Project.." from the menu</li>
|
141 |
+
<li>Expand the folder "General" and select "Project"</li>
|
142 |
+
<li>Click the "Next" button</li>
|
143 |
+
<li>On the next tab enter a project name: "Test"</li>
|
144 |
+
<li>Use the default Project Contents</li>
|
145 |
+
<li>Click the "Finish" button</li>
|
146 |
+
</ol>
|
147 |
+
</li>
|
148 |
+
<li>Create a Single Passing Test
|
149 |
+
<ol>
|
150 |
+
<li>In the Package Explorer View right-click on the "Test" project and select "New" > "File".</li>
|
151 |
+
<li>For the filename enter: test1.php and click "Finish"</li>
|
152 |
+
<li>Double-click on the test1.php entry in the Package Explorer which should open a new view to edit the file.</li>
|
153 |
+
<li>Enter the following for the contents of the file:
|
154 |
+
<php><![CDATA[
|
155 |
+
<?php
|
156 |
+
class test1 extends UnitTestCase {
|
157 |
+
function test_pass(){
|
158 |
+
$x = 1;
|
159 |
+
$y = 2;
|
160 |
+
$total = $x + $y;
|
161 |
+
$this->assertEqual(3,$total, "This should pass");
|
162 |
+
}
|
163 |
+
}
|
164 |
+
?>
|
165 |
+
]]></php>
|
166 |
+
</li>
|
167 |
+
<li>Select "File" > "Save" from the menu.</li>
|
168 |
+
<li>Right click on the test1.php entry and select "Run" > "Run Simpletest".</li>
|
169 |
+
<li>The "Result View" should populate with information about the test run and the Simpletest console should fill with some information as well.</li>
|
170 |
+
</ol>
|
171 |
+
</li>
|
172 |
+
<li>Single Test class multiple tests
|
173 |
+
<ol>
|
174 |
+
<li>In the Package Explorer View right-click on the "Test" project and select "New" > "File".</li>
|
175 |
+
<li>For the filename enter: test2.php and click "Finish".</li>
|
176 |
+
<li>Double-click on the test2.php entry in the Package Explorer which should open a new view to edit the file.</li>
|
177 |
+
<li>Enter the following for the contents of the file:
|
178 |
+
<php><![CDATA[
|
179 |
+
<?php
|
180 |
+
class test2 extends UnitTestCase {
|
181 |
+
function test_pass(){
|
182 |
+
$x = 1;
|
183 |
+
$y = 2;
|
184 |
+
$total = $x + $y;
|
185 |
+
$this->assertEqual(3,$total, "This should pass");
|
186 |
+
}
|
187 |
+
function test_fail(){
|
188 |
+
$x = 1;
|
189 |
+
$y = 2;
|
190 |
+
$total = $x + $y;
|
191 |
+
$this->assertEqual(4,$total,"This should fail");
|
192 |
+
}
|
193 |
+
}
|
194 |
+
?>
|
195 |
+
]]></php>
|
196 |
+
</li>
|
197 |
+
<li>Select "File" > "save" from the menu bar.</li>
|
198 |
+
<li>Right click on the test2.php entry and select "Run" > "Run Simpletest".</li>
|
199 |
+
<li>The Result View should populate with information about the test run and the Simpletest console should fill with some information as well</li>
|
200 |
+
</ol>
|
201 |
+
</li>
|
202 |
+
<li>Group Tests (test multiple files at once)
|
203 |
+
<ol>
|
204 |
+
<li>In the Package Explorer View right-click on the "Test" project and select "New" > "File"</li>
|
205 |
+
<li>For the filename enter: grouptest.php and click "Finish".</li>
|
206 |
+
<li>Double-click on the grouptest.php entry in the Package Explorer which should open a new view to edit the file.</li>
|
207 |
+
<li>Enter the following for the contents of the file:
|
208 |
+
<php><![CDATA[
|
209 |
+
<?php
|
210 |
+
class myGroupTest extends GroupTest {
|
211 |
+
function myGroupTest() {
|
212 |
+
parent::GroupTest('');
|
213 |
+
$this->addTestFile(dirname(__FILE__).'/test1.php');
|
214 |
+
$this->addTestFile(dirname(__FILE__).'/test2.php');
|
215 |
+
}
|
216 |
+
}
|
217 |
+
?>
|
218 |
+
]]></php>
|
219 |
+
</li>
|
220 |
+
<li>Select "File" > "save" from the menu</li>
|
221 |
+
<li>Right click on the grouptest.php entry and select "Run" > "Run Simpletest"</li>
|
222 |
+
<li>The Result View should populate with information about the test run and the Simpletest console should fill with some information as well</li>
|
223 |
+
</ol>
|
224 |
+
</li>
|
225 |
+
</ol>
|
226 |
+
</section>
|
227 |
+
<section name="known" title="Known Issues">
|
228 |
+
<ul>
|
229 |
+
<li>
|
230 |
+
Make sure that if a constructor is used in the test case
|
231 |
+
that the last line of the constructor calls the parent
|
232 |
+
constructor (e.g. parent::UnitTestCase)
|
233 |
+
</li>
|
234 |
+
<li>
|
235 |
+
Do not put any assertions into the test class constructor
|
236 |
+
</li>
|
237 |
+
<li>
|
238 |
+
If you get an error indicating that a class could not load; then restart Eclipse. Once
|
239 |
+
Eclipse restarts, open the Result View manually by selecting "Window"->"Show View"->"Other..."
|
240 |
+
Then select the SimpleTest Category and select "Result View" and click "OK".
|
241 |
+
</li>
|
242 |
+
</ul>
|
243 |
+
</section>
|
244 |
+
<section name="todo" title="Future Features">
|
245 |
+
<p>These are features that should eventually make it into this plugin</p>
|
246 |
+
<ul>
|
247 |
+
<li>
|
248 |
+
Allow different "include" file on each runner (override the "master" include)
|
249 |
+
</li>
|
250 |
+
<li>
|
251 |
+
Handle fatal errors better
|
252 |
+
</li>
|
253 |
+
</ul>
|
254 |
+
</section>
|
255 |
+
</content>
|
256 |
+
|
257 |
+
<meta>
|
258 |
+
<keywords>
|
259 |
+
software development,
|
260 |
+
eclipse plugin,
|
261 |
+
php programming,
|
262 |
+
programming php,
|
263 |
+
software development tools,
|
264 |
+
php tutorial,
|
265 |
+
free php scripts,
|
266 |
+
architecture,
|
267 |
+
php resources,
|
268 |
+
mock objects,
|
269 |
+
junit,
|
270 |
+
php testing,
|
271 |
+
unit test,
|
272 |
+
automated php testing,
|
273 |
+
test cases tutorial,
|
274 |
+
explain unit test case,
|
275 |
+
unit test example,
|
276 |
+
unit test
|
277 |
+
</keywords>
|
278 |
+
</meta>
|
279 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/first_test_tutorial.xml
ADDED
@@ -0,0 +1,443 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: first_test_tutorial.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Creating a new test case" here="PHP unit testing">
|
4 |
+
<long_title>PHP unit testing tutorial - Creating an example test case in PHP</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<p>
|
8 |
+
If you are new to unit testing it is recommended that you
|
9 |
+
actually try the code out as we go.
|
10 |
+
There is actually not very much to type and you will get
|
11 |
+
a feel for the rhythm of test first programming.
|
12 |
+
</p>
|
13 |
+
<p>
|
14 |
+
To run the examples as is, you need an empty directory with the folders
|
15 |
+
<em>classes</em>, <em>tests</em> and <em>temp</em>.
|
16 |
+
Unpack the <a href="simple_test.php">SimpleTest</a> framework
|
17 |
+
into the <em>tests</em> folder and make sure your web server
|
18 |
+
can reach these locations.
|
19 |
+
</p>
|
20 |
+
</introduction>
|
21 |
+
<section name="new" title="A new test case">
|
22 |
+
<p>
|
23 |
+
The quick <a local="{{simple_test}}">introductory example</a>
|
24 |
+
featured the unit testing of a simple log class.
|
25 |
+
In this tutorial on SimpleTest I am going to try to
|
26 |
+
tell the whole story of developing this class.
|
27 |
+
This PHP class is small and simple and in the course of
|
28 |
+
this introduction will receive far more attention than
|
29 |
+
it probably would in production.
|
30 |
+
Yet even this tiny class contains some surprisingly difficult
|
31 |
+
design decisions.
|
32 |
+
</p>
|
33 |
+
<p>
|
34 |
+
Maybe they are too difficult?
|
35 |
+
Rather than trying to design the whole thing up front
|
36 |
+
I'll start with a known requirement, namely
|
37 |
+
we want to write messages to a file.
|
38 |
+
These messages must be appended to the file if it exists.
|
39 |
+
Later we will want priorities and filters and things, but
|
40 |
+
for now we will place the file writing requirement in
|
41 |
+
the forefront of our thoughts.
|
42 |
+
We will think of nothing else for fear of getting confused.
|
43 |
+
OK, let's make a test...
|
44 |
+
<php><![CDATA[
|
45 |
+
<strong><?php
|
46 |
+
if (! defined('SIMPLE_TEST')) {
|
47 |
+
define('SIMPLE_TEST', 'simpletest/');
|
48 |
+
}
|
49 |
+
require_once(SIMPLE_TEST . 'autorun.php');
|
50 |
+
|
51 |
+
class TestOfLogging extends UnitTestCase {
|
52 |
+
function testCreatingNewFile() {
|
53 |
+
}
|
54 |
+
}
|
55 |
+
?></strong>
|
56 |
+
]]></php>
|
57 |
+
Piece by piece here is what it all means.
|
58 |
+
</p>
|
59 |
+
<p>
|
60 |
+
The <code>SIMPLE_TEST</code> constant
|
61 |
+
is the path from this file to the Simple Test classes.
|
62 |
+
The classes could be placed into the path in the
|
63 |
+
<em>php.ini</em> file, but if you are using a shared
|
64 |
+
hosting account you do not have access to this.
|
65 |
+
To keep everybody happy this path is declared explicitely
|
66 |
+
in the test script.
|
67 |
+
Later we will see how it eventually ends up in only one
|
68 |
+
place.
|
69 |
+
</p>
|
70 |
+
<p>
|
71 |
+
What is this <em>autorun.php</em> file?
|
72 |
+
The Simple Test libraries are a toolkit for creating
|
73 |
+
your own standardised test suite.
|
74 |
+
They can be used "as is" without trouble, but consist
|
75 |
+
of separate components that have to be assembled.
|
76 |
+
<em>autorun.php</em> is a special component : it provides both
|
77 |
+
the unit testing and display pieces. It catches all test classes
|
78 |
+
and runs them automagically.
|
79 |
+
</p>
|
80 |
+
<p>
|
81 |
+
It is probable that you will eventually write your own display
|
82 |
+
and so including the default set is optional.
|
83 |
+
SimpleTest includes a usable, but basic, test display class
|
84 |
+
called <code>HtmlReporter</code>.
|
85 |
+
It can record test starts, ends, errors, passes and fails.
|
86 |
+
It displays this information as quickly as possible in case
|
87 |
+
the test code crashes the script and obscures the point of
|
88 |
+
failure.
|
89 |
+
</p>
|
90 |
+
<p>
|
91 |
+
The tests themselves are gathered in test case classes.
|
92 |
+
This one is typical in extending
|
93 |
+
<code>UnitTestCase</code>.
|
94 |
+
When the test is run it will search for any method within
|
95 |
+
that starts with the name "test" and run it.
|
96 |
+
Our only test method at present is called
|
97 |
+
<code>testCreatingNewFile()</code>.
|
98 |
+
There is nothing in it yet.
|
99 |
+
</p>
|
100 |
+
<p>
|
101 |
+
Now the empty method definition on its own does not do anything.
|
102 |
+
We need to actually place some code inside it.
|
103 |
+
The <code>UnitTestCase</code> class
|
104 |
+
will typically generate test events when run and these events are
|
105 |
+
sent to an observer.
|
106 |
+
</p>
|
107 |
+
<p>
|
108 |
+
Now to add test code...
|
109 |
+
<php><![CDATA[
|
110 |
+
<?php
|
111 |
+
if (! defined('SIMPLE_TEST')) {
|
112 |
+
define('SIMPLE_TEST', 'simpletest/');
|
113 |
+
}
|
114 |
+
require_once(SIMPLE_TEST . 'autorun.php');<strong>
|
115 |
+
require_once('../classes/log.php');</strong>
|
116 |
+
|
117 |
+
class TestOfLogging extends UnitTestCase {
|
118 |
+
function testCreatingNewFile() {<strong>
|
119 |
+
@unlink('../temp/test.log');
|
120 |
+
$log = new Log('../temp/test.log');
|
121 |
+
$log->message('Should write this to a file');
|
122 |
+
$this->assertTrue(file_exists('../temp/test.log'));</strong>
|
123 |
+
}
|
124 |
+
}
|
125 |
+
?>
|
126 |
+
]]></php>
|
127 |
+
</p>
|
128 |
+
<p>
|
129 |
+
You are probably thinking that that is a lot of test code for
|
130 |
+
just one test and I would agree.
|
131 |
+
Don't worry.
|
132 |
+
This is a fixed cost and from now on we can add tests
|
133 |
+
pretty much as one liners.
|
134 |
+
Even less when using some of the test artifacts that we
|
135 |
+
will use later.
|
136 |
+
</p>
|
137 |
+
<p>
|
138 |
+
Now comes the first of our decisions.
|
139 |
+
Our test file is called <em>log_test.php</em> (any name
|
140 |
+
is fine) and is in a folder called <em>tests</em> (anywhere is fine).
|
141 |
+
We have called our code file <em>log.php</em> and this is
|
142 |
+
the code we are going to test.
|
143 |
+
I have placed it into a folder called <em>classes</em>, so that means
|
144 |
+
we are building a class, yes?
|
145 |
+
</p>
|
146 |
+
<p>
|
147 |
+
For this example I am, but the unit tester is not restricted
|
148 |
+
to testing classes.
|
149 |
+
It is just that object oriented code is easier to break
|
150 |
+
down and redesign for testing.
|
151 |
+
It is no accident that the fine grain testing style of unit
|
152 |
+
tests has arisen from the object community.
|
153 |
+
</p>
|
154 |
+
<p>
|
155 |
+
The test itself is minimal.
|
156 |
+
It first deletes any previous test file that may have
|
157 |
+
been left lying around.
|
158 |
+
Design decisions now come in thick and fast.
|
159 |
+
Our class is called <code>Log</code>
|
160 |
+
and takes the file path in the constructor.
|
161 |
+
We create a log and immediately send a message to
|
162 |
+
it using a method named
|
163 |
+
<code>message()</code>.
|
164 |
+
Sadly, original naming is not a desirable characteristic
|
165 |
+
of a software developer.
|
166 |
+
</p>
|
167 |
+
<p>
|
168 |
+
The smallest unit of a...er...unit test is the assertion.
|
169 |
+
Here we want to assert that the log file we just sent
|
170 |
+
a message to was indeed created.
|
171 |
+
<code>UnitTestCase::assertTrue()</code>
|
172 |
+
will send a pass event if the condition evaluates to
|
173 |
+
true and a fail event otherwise.
|
174 |
+
We can have a variety of different assertions and even more
|
175 |
+
if we extend our base test cases.
|
176 |
+
Here is the base list...
|
177 |
+
<table><tbody>
|
178 |
+
<tr><td><code>assertTrue($x)</code></td><td>Fail if $x is false</td></tr>
|
179 |
+
<tr><td><code>assertFalse($x)</code></td><td>Fail if $x is true</td></tr>
|
180 |
+
<tr><td><code>assertNull($x)</code></td><td>Fail if $x is set</td></tr>
|
181 |
+
<tr><td><code>assertNotNull($x)</code></td><td>Fail if $x not set</td></tr>
|
182 |
+
<tr><td><code>assertIsA($x, $t)</code></td><td>Fail if $x is not the class or type $t</td></tr>
|
183 |
+
<tr><td><code>assertEqual($x, $y)</code></td><td>Fail if $x == $y is false</td></tr>
|
184 |
+
<tr><td><code>assertNotEqual($x, $y)</code></td><td>Fail if $x == $y is true</td></tr>
|
185 |
+
<tr><td><code>assertIdentical($x, $y)</code></td><td>Fail if $x === $y is false</td></tr>
|
186 |
+
<tr><td><code>assertNotIdentical($x, $y)</code></td><td>Fail if $x === $y is true</td></tr>
|
187 |
+
<tr><td><code>assertReference($x, $y)</code></td><td>Fail unless $x and $y are the same variable</td></tr>
|
188 |
+
<tr><td><code>assertCopy($x, $y)</code></td><td>Fail if $x and $y are the same variable</td></tr>
|
189 |
+
<tr><td><code>assertWantedPattern($p, $x)</code></td><td>Fail unless the regex $p matches $x</td></tr>
|
190 |
+
<tr><td><code>assertNoUnwantedPattern($p, $x)</code></td><td>Fail if the regex $p matches $x</td></tr>
|
191 |
+
<tr><td><code>assertNoErrors()</code></td><td>Fail if any PHP error occoured</td></tr>
|
192 |
+
<tr><td><code>assertError($x)</code></td><td>Fail if no PHP error or incorrect message</td></tr>
|
193 |
+
</tbody></table>
|
194 |
+
</p>
|
195 |
+
<p>
|
196 |
+
We are now ready to execute our test script by pointing the
|
197 |
+
browser at it.
|
198 |
+
What happens?
|
199 |
+
It should crash...
|
200 |
+
<div class="demo">
|
201 |
+
<b>Fatal error</b>: Failed opening required '../classes/log.php' (include_path='') in <b>/home/marcus/projects/lastcraft/tutorial_tests/Log/tests/log_test.php</b> on line <b>7</b>
|
202 |
+
</div>
|
203 |
+
The reason is that we have not yet created <em>log.php</em>.
|
204 |
+
</p>
|
205 |
+
<p>
|
206 |
+
Hang on, that's silly!
|
207 |
+
You aren't going to build a test without creating any of the
|
208 |
+
code you are testing, surely...?
|
209 |
+
</p>
|
210 |
+
</section>
|
211 |
+
<section name="tdd" title="Test Driven Development">
|
212 |
+
<p>
|
213 |
+
Co-inventor of
|
214 |
+
<a href="http://www.extremeprogramming.org/">Extreme Programming</a>,
|
215 |
+
Kent Beck, has come up with another manifesto.
|
216 |
+
The book is called
|
217 |
+
<a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321146530/ref=lib_dp_TFCV/102-2696523-7458519?v=glance&s=books&vi=reader#reader-link">Test driven development</a>
|
218 |
+
or TDD and raises unit testing to a senior position in design.
|
219 |
+
In a nutshell you write a small test first and
|
220 |
+
then only get this passing by writing code.
|
221 |
+
Any code.
|
222 |
+
Just get it working.
|
223 |
+
</p>
|
224 |
+
<p>
|
225 |
+
You write another test and get that passing.
|
226 |
+
What you will now have is some duplication and generally lousy
|
227 |
+
code.
|
228 |
+
You re-arrange
|
229 |
+
(refactor)
|
230 |
+
that code while the tests are passing and thus while you cannot break
|
231 |
+
anything.
|
232 |
+
Once the code is as clean as possible you are ready to add more
|
233 |
+
functionality.
|
234 |
+
In turn you only achieve this by adding another test and starting the
|
235 |
+
cycle again.
|
236 |
+
</p>
|
237 |
+
<p>
|
238 |
+
This is a radical approach and one that I feel is incomplete.
|
239 |
+
However it makes for a great way to explain a unit tester!
|
240 |
+
We happen to have a failing, not to say crashing, test right now so
|
241 |
+
let's write some code into <em>log.php</em>...
|
242 |
+
<php><![CDATA[
|
243 |
+
<strong><?php
|
244 |
+
class Log {
|
245 |
+
|
246 |
+
function Log($file_path) {
|
247 |
+
}
|
248 |
+
|
249 |
+
function message($message) {
|
250 |
+
}
|
251 |
+
}
|
252 |
+
?></strong>
|
253 |
+
]]></php>
|
254 |
+
This is the minimum to avoid a PHP fatal error.
|
255 |
+
We now get the response...
|
256 |
+
<div class="demo">
|
257 |
+
<h1>testoflogging</h1>
|
258 |
+
<span class="fail">Fail</span>: testcreatingnewfile->True assertion failed.<br />
|
259 |
+
<div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
|
260 |
+
<strong>0</strong> passes and <strong>1</strong> fails.</div>
|
261 |
+
</div>
|
262 |
+
And "testoflogging" has failed.
|
263 |
+
PHP has this really annoying effect of reducing class and method
|
264 |
+
names to lower case internally.
|
265 |
+
SimpleTest uses these names by default to describe the tests, but
|
266 |
+
we can replace them with our own...
|
267 |
+
<php><![CDATA[
|
268 |
+
class TestOfLogging extends UnitTestCase {
|
269 |
+
<strong>function TestOfLogging() {
|
270 |
+
$this->UnitTestCase('Log class test');
|
271 |
+
}</strong>
|
272 |
+
function testCreatingNewFile() {
|
273 |
+
@unlink('../temp/test.log');
|
274 |
+
$log = new Log('../temp/test.log');
|
275 |
+
$log->message('Should write this to a file');<strong>
|
276 |
+
$this->assertTrue(file_exists('../temp/test.log'), 'File created');</strong>
|
277 |
+
}
|
278 |
+
}
|
279 |
+
]]></php>
|
280 |
+
Giving...
|
281 |
+
<div class="demo">
|
282 |
+
<h1>Log class test</h1>
|
283 |
+
<span class="fail">Fail</span>: testcreatingnewfile->File created.<br />
|
284 |
+
<div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">1/1 test cases complete.
|
285 |
+
<strong>0</strong> passes and <strong>1</strong> fails.</div>
|
286 |
+
</div>
|
287 |
+
There is not much we can do about the method name I am afraid.
|
288 |
+
</p>
|
289 |
+
<p>
|
290 |
+
Test messages like this are a bit like code comments.
|
291 |
+
Some organisations insist on them while others ban them as clutter
|
292 |
+
and a waste of good typing.
|
293 |
+
I am somewhere in the middle.
|
294 |
+
</p>
|
295 |
+
<p>
|
296 |
+
To get the test passing we could just create the file in the
|
297 |
+
<code>Log</code> constructor.
|
298 |
+
This "faking it" technique is very useful for checking
|
299 |
+
that your tests work when the going gets tough.
|
300 |
+
This is especially so if you have had a run of test failures
|
301 |
+
and just want to confirm that you haven't just missed something
|
302 |
+
stupid.
|
303 |
+
We are not going that slow, so...
|
304 |
+
<php><![CDATA[
|
305 |
+
<?php
|
306 |
+
class Log {<strong>
|
307 |
+
var $_file_path;</strong>
|
308 |
+
|
309 |
+
function Log($file_path) {<strong>
|
310 |
+
$this->_file_path = $file_path;</strong>
|
311 |
+
}
|
312 |
+
|
313 |
+
function message($message) {<strong>
|
314 |
+
$file = fopen($this->_file_path, 'a');
|
315 |
+
fwrite($file, $message . "\n");
|
316 |
+
fclose($file);</strong>
|
317 |
+
}
|
318 |
+
}
|
319 |
+
?>
|
320 |
+
]]></php>
|
321 |
+
It took me no less than four failures to get to the next step.
|
322 |
+
I had not created the temporary directory, I had not made it
|
323 |
+
publicly writeable, I had one typo and I did not check in the
|
324 |
+
new directory to CVS.
|
325 |
+
Any one of these could have kept me busy for several hours if
|
326 |
+
they had come to light later, but then that is what testing is for.
|
327 |
+
With the necessary fixes we get...
|
328 |
+
<div class="demo">
|
329 |
+
<h1>Log class test</h1>
|
330 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
|
331 |
+
<strong>1</strong> passes and <strong>0</strong> fails.</div>
|
332 |
+
</div>
|
333 |
+
Success!
|
334 |
+
</p>
|
335 |
+
<p>
|
336 |
+
You may not like the rather minimal style of the display.
|
337 |
+
Passes are not shown by default because generally you do
|
338 |
+
not need more information when you actually understand what is
|
339 |
+
going on.
|
340 |
+
If you do not know what is going on then you should write another test.
|
341 |
+
</p>
|
342 |
+
<p>
|
343 |
+
OK, this is a little strict.
|
344 |
+
If you want to see the passes as well then you
|
345 |
+
<a local="display_subclass_tutorial">can subclass the
|
346 |
+
<code>HtmlReporter</code> class</a>
|
347 |
+
and attach that to the test instead.
|
348 |
+
Even I like the comfort factor sometimes.
|
349 |
+
</p>
|
350 |
+
</section>
|
351 |
+
<section name="doc" title="Tests as Documentation">
|
352 |
+
<p>
|
353 |
+
There is a subtlety here.
|
354 |
+
We don't want the file created until we actually send
|
355 |
+
a message.
|
356 |
+
Rather than think about this too deeply we will just add
|
357 |
+
another test for it...
|
358 |
+
<php><![CDATA[
|
359 |
+
class TestOfLogging extends UnitTestCase {
|
360 |
+
function TestOfLogging() {
|
361 |
+
$this->UnitTestCase('Log class test');
|
362 |
+
}
|
363 |
+
function testCreatingNewFile() {
|
364 |
+
@unlink('../temp/test.log');
|
365 |
+
$log = new Log('../temp/test.log');<strong>
|
366 |
+
$this->assertFalse(file_exists('../temp/test.log'), 'No file created before first message');</strong>
|
367 |
+
$log->message('Should write this to a file');
|
368 |
+
$this->assertTrue(file_exists('../temp/test.log'), 'File created');
|
369 |
+
}
|
370 |
+
}
|
371 |
+
]]></php>
|
372 |
+
...and find it already works...
|
373 |
+
<div class="demo">
|
374 |
+
<h1>Log class test</h1>
|
375 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">1/1 test cases complete.
|
376 |
+
<strong>2</strong> passes and <strong>0</strong> fails.</div>
|
377 |
+
</div>
|
378 |
+
Actually I knew it would.
|
379 |
+
I am putting this test in to confirm this partly for peace of mind, but
|
380 |
+
also to document the behaviour.
|
381 |
+
That little extra test line says more in this context than
|
382 |
+
a dozen lines of use case or a whole UML activity diagram.
|
383 |
+
That the test suite acts as a source of documentation is a pleasant
|
384 |
+
side effect of all these tests.
|
385 |
+
</p>
|
386 |
+
<p>
|
387 |
+
Should we clean up the temporary file at the end of the test?
|
388 |
+
I usually do this once I am finished with a test method
|
389 |
+
and it is working.
|
390 |
+
I don't want to check in code that leaves remnants of
|
391 |
+
test files lying around after a test.
|
392 |
+
I don't do it while I am writing the code, though.
|
393 |
+
I probably should, but sometimes I need to see what is
|
394 |
+
going on and there is that comfort thing again.
|
395 |
+
</p>
|
396 |
+
<p>
|
397 |
+
In a real life project we usually have more than one test case,
|
398 |
+
so we next have to look at
|
399 |
+
<a local="group_test_tutorial">grouping tests into test suites</a>.
|
400 |
+
</p>
|
401 |
+
</section>
|
402 |
+
</content>
|
403 |
+
<internal>
|
404 |
+
<link>Creating a <a href="#new">new test case</a>.</link>
|
405 |
+
<link><a href="#tdd">Test driven development</a> in PHP.</link>
|
406 |
+
<link><a href="#doc">Tests as documentation</a> is one of many side effects.</link>
|
407 |
+
</internal>
|
408 |
+
<external>
|
409 |
+
<link>
|
410 |
+
The <a href="http://junit.sourceforge.net/doc/faq/faq.htm">JUnit FAQ</a>
|
411 |
+
has plenty of useful testing advice.
|
412 |
+
</link>
|
413 |
+
<link>
|
414 |
+
<a href="group_test_tutorial.php">Next</a> is grouping test
|
415 |
+
cases together.
|
416 |
+
</link>
|
417 |
+
<link>
|
418 |
+
You will need the <a href="simple_test.php">SimpleTest testing framework</a>
|
419 |
+
for these examples.
|
420 |
+
</link>
|
421 |
+
</external>
|
422 |
+
<meta>
|
423 |
+
<keywords>
|
424 |
+
software development,
|
425 |
+
php programming,
|
426 |
+
programming php,
|
427 |
+
software development tools,
|
428 |
+
php tutorial,
|
429 |
+
free php scripts,
|
430 |
+
architecture,
|
431 |
+
php resources,
|
432 |
+
mock objects,
|
433 |
+
junit,
|
434 |
+
php testing,
|
435 |
+
unit test,
|
436 |
+
automated php testing,
|
437 |
+
test cases tutorial,
|
438 |
+
explain unit test case,
|
439 |
+
unit test example,
|
440 |
+
unit test
|
441 |
+
</keywords>
|
442 |
+
</meta>
|
443 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/form_testing_documentation.xml
ADDED
@@ -0,0 +1,299 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: form_testing_documentation.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Form testing documentation" here="Testing forms">
|
4 |
+
<long_title>Simple Test documentation for testing HTML forms</long_title>
|
5 |
+
<content>
|
6 |
+
<section name="submit" title="Submitting a simple form">
|
7 |
+
<p>
|
8 |
+
When a page is fetched by the <code>WebTestCase</code>
|
9 |
+
using <code>get()</code> or
|
10 |
+
<code>post()</code> the page content is
|
11 |
+
automatically parsed.
|
12 |
+
This results in any form controls that are inside <form> tags
|
13 |
+
being available from within the test case.
|
14 |
+
For example, if we have this snippet of HTML...
|
15 |
+
<pre><![CDATA[
|
16 |
+
<form>
|
17 |
+
<input type="text" name="a" value="A default" />
|
18 |
+
<input type="submit" value="Go" />
|
19 |
+
</form>
|
20 |
+
]]></pre>
|
21 |
+
Which looks like this...
|
22 |
+
</p>
|
23 |
+
<p>
|
24 |
+
<form class="demo">
|
25 |
+
<input type="text" name="a" value="A default" />
|
26 |
+
<input type="submit" value="Go" />
|
27 |
+
</form>
|
28 |
+
</p>
|
29 |
+
<p>
|
30 |
+
We can navigate to this code, via the
|
31 |
+
<a href="http://www.lastcraft.com/form_testing_documentation.php">LastCraft</a>
|
32 |
+
site, with the following test...
|
33 |
+
<php><![CDATA[
|
34 |
+
class SimpleFormTests extends WebTestCase {
|
35 |
+
<strong>
|
36 |
+
function testDefaultValue() {
|
37 |
+
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
38 |
+
$this->assertField('a', 'A default');
|
39 |
+
}</strong>
|
40 |
+
}
|
41 |
+
]]></php>
|
42 |
+
Immediately after loading the page all of the HTML controls are set at
|
43 |
+
their default values just as they would appear in the web browser.
|
44 |
+
The assertion tests that a HTML widget exists in the page with the
|
45 |
+
name "a" and that it is currently set to the value
|
46 |
+
"A default".
|
47 |
+
As usual, we could use a pattern expectation instead if a fixed
|
48 |
+
string.
|
49 |
+
</p>
|
50 |
+
<p>
|
51 |
+
We could submit the form straight away, but first we'll change
|
52 |
+
the value of the text field and only then submit it...
|
53 |
+
<php><![CDATA[
|
54 |
+
class SimpleFormTests extends WebTestCase {
|
55 |
+
|
56 |
+
function testDefaultValue() {
|
57 |
+
$this->get('http://www.my-site.com/');
|
58 |
+
$this->assertField('a', 'A default');<strong>
|
59 |
+
$this->setField('a', 'New value');
|
60 |
+
$this->click('Go');</strong>
|
61 |
+
}
|
62 |
+
}
|
63 |
+
]]></php>
|
64 |
+
Because we didn't specify a method attribute on the form tag, and
|
65 |
+
didn't specify an action either, the test case will follow
|
66 |
+
the usual browser behaviour of submitting the form data as a <em>GET</em>
|
67 |
+
request back to the same location.
|
68 |
+
SimpleTest tries to emulate typical browser behaviour as much as possible,
|
69 |
+
rather than attempting to catch missing attributes on tags.
|
70 |
+
This is because the target of the testing framework is the PHP application
|
71 |
+
logic, not syntax or other errors in the HTML code.
|
72 |
+
For HTML errors, other tools such as
|
73 |
+
<a href="http://www.w3.org/People/Raggett/tidy/">HTMLTidy</a> should be used.
|
74 |
+
</p>
|
75 |
+
<p>
|
76 |
+
If a field is not present in any form, or if an option is unavailable,
|
77 |
+
then <code>WebTestCase::setField()</code> will return
|
78 |
+
<code>false</code>.
|
79 |
+
For example, suppose we wish to verify that a "Superuser"
|
80 |
+
option is not present in this form...
|
81 |
+
<pre><![CDATA[
|
82 |
+
<strong>Select type of user to add:</strong>
|
83 |
+
<select name="type">
|
84 |
+
<option>Subscriber</option>
|
85 |
+
<option>Author</option>
|
86 |
+
<option>Administrator</option>
|
87 |
+
</select>
|
88 |
+
]]></pre>
|
89 |
+
Which looks like...
|
90 |
+
</p>
|
91 |
+
<p>
|
92 |
+
<form class="demo">
|
93 |
+
<strong>Select type of user to add:</strong>
|
94 |
+
<select name="type">
|
95 |
+
<option>Subscriber</option>
|
96 |
+
<option>Author</option>
|
97 |
+
<option>Administrator</option>
|
98 |
+
</select>
|
99 |
+
</form>
|
100 |
+
</p>
|
101 |
+
<p>
|
102 |
+
The following test will confirm it...
|
103 |
+
<php><![CDATA[
|
104 |
+
class SimpleFormTests extends WebTestCase {
|
105 |
+
...
|
106 |
+
function testNoSuperuserChoiceAvailable() {<strong>
|
107 |
+
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
108 |
+
$this->assertFalse($this->setField('type', 'Superuser'));</strong>
|
109 |
+
}
|
110 |
+
}
|
111 |
+
]]></php>
|
112 |
+
The selection will not be changed on a failure to set
|
113 |
+
a widget value.
|
114 |
+
</p>
|
115 |
+
<p>
|
116 |
+
Here is the full list of widgets currently supported...
|
117 |
+
<ul>
|
118 |
+
<li>Text fields, including hidden and password fields.</li>
|
119 |
+
<li>Submit buttons including the button tag, although not yet reset buttons</li>
|
120 |
+
<li>Text area. This includes text wrapping behaviour.</li>
|
121 |
+
<li>Checkboxes, including multiple checkboxes in the same form.</li>
|
122 |
+
<li>Drop down selections, including multiple selects.</li>
|
123 |
+
<li>Radio buttons.</li>
|
124 |
+
<li>Images.</li>
|
125 |
+
</ul>
|
126 |
+
</p>
|
127 |
+
<p>
|
128 |
+
The browser emulation offered by SimpleTest mimics
|
129 |
+
the actions which can be perform by a user on a
|
130 |
+
standard HTML page. Javascript is not supported, and
|
131 |
+
it's unlikely that support will be added any time
|
132 |
+
soon.
|
133 |
+
</p>
|
134 |
+
<p>
|
135 |
+
Of particular note is that the Javascript idiom of
|
136 |
+
passing form results by setting a hidden field cannot
|
137 |
+
be performed using the normal SimpleTest
|
138 |
+
commands. See below for a way to test such forms.
|
139 |
+
</p>
|
140 |
+
</section>
|
141 |
+
<section name="multiple" title="Fields with multiple values">
|
142 |
+
<p>
|
143 |
+
SimpleTest can cope with two types of multivalue controls: Multiple
|
144 |
+
selection drop downs, and multiple checkboxes with the same name
|
145 |
+
within a form.
|
146 |
+
The multivalue nature of these means that setting and testing
|
147 |
+
are slightly different.
|
148 |
+
Using checkboxes as an example...
|
149 |
+
<pre><![CDATA[
|
150 |
+
<form class="demo">
|
151 |
+
<strong>Create privileges allowed:</strong>
|
152 |
+
<input type="checkbox" name="crud" value="c" checked><br>
|
153 |
+
<strong>Retrieve privileges allowed:</strong>
|
154 |
+
<input type="checkbox" name="crud" value="r" checked><br>
|
155 |
+
<strong>Update privileges allowed:</strong>
|
156 |
+
<input type="checkbox" name="crud" value="u" checked><br>
|
157 |
+
<strong>Destroy privileges allowed:</strong>
|
158 |
+
<input type="checkbox" name="crud" value="d" checked><br>
|
159 |
+
<input type="submit" value="Enable Privileges">
|
160 |
+
</form>
|
161 |
+
]]></pre>
|
162 |
+
Which renders as...
|
163 |
+
</p>
|
164 |
+
<p>
|
165 |
+
<form class="demo">
|
166 |
+
<strong>Create privileges allowed:</strong>
|
167 |
+
<input type="checkbox" name="crud" value="c" checked=""/><br/>
|
168 |
+
<strong>Retrieve privileges allowed:</strong>
|
169 |
+
<input type="checkbox" name="crud" value="r" checked=""/><br/>
|
170 |
+
<strong>Update privileges allowed:</strong>
|
171 |
+
<input type="checkbox" name="crud" value="u" checked=""/><br/>
|
172 |
+
<strong>Destroy privileges allowed:</strong>
|
173 |
+
<input type="checkbox" name="crud" value="d" checked=""/><br/>
|
174 |
+
<input type="submit" value="Enable Privileges"/>
|
175 |
+
</form>
|
176 |
+
</p>
|
177 |
+
<p>
|
178 |
+
If we wish to disable all but the retrieval privileges and
|
179 |
+
submit this information we can do it like this...
|
180 |
+
<php><![CDATA[
|
181 |
+
class SimpleFormTests extends WebTestCase {
|
182 |
+
...<strong>
|
183 |
+
function testDisableNastyPrivileges() {
|
184 |
+
$this->get('http://www.lastcraft.com/form_testing_documentation.php');
|
185 |
+
$this->assertField('crud', array('c', 'r', 'u', 'd'));
|
186 |
+
$this->setField('crud', array('r'));
|
187 |
+
$this->click('Enable Privileges');
|
188 |
+
}</strong>
|
189 |
+
}
|
190 |
+
]]></php>
|
191 |
+
Instead of setting the field to a single value, we give it a list
|
192 |
+
of values.
|
193 |
+
We do the same when testing expected values.
|
194 |
+
We can then write other test code to confirm the effect of this, perhaps
|
195 |
+
by logging in as that user and attempting an update.
|
196 |
+
</p>
|
197 |
+
</section>
|
198 |
+
<section name="hidden-field" title="Forms which use javascript to set a hidden field">
|
199 |
+
<p>
|
200 |
+
If you want to test a form which relies on javascript to set a hidden
|
201 |
+
field, you can't just call setField().
|
202 |
+
The following code will <em>not</em> work:
|
203 |
+
<php><![CDATA[
|
204 |
+
class SimpleFormTests extends WebTestCase {
|
205 |
+
function testMyJavascriptForm() {
|
206 |
+
<strong>// This does *not* work</strong>
|
207 |
+
$this->setField('a_hidden_field', '123');
|
208 |
+
$this->clickSubmit('OK');
|
209 |
+
}
|
210 |
+
}
|
211 |
+
]]></php>
|
212 |
+
Instead, you need to pass the additional form parameters to the
|
213 |
+
clickSubmit() method:
|
214 |
+
<php><![CDATA[
|
215 |
+
class SimpleFormTests extends WebTestCase {
|
216 |
+
function testMyJavascriptForm() {
|
217 |
+
// Pass the hidden field value as an additional POST variable
|
218 |
+
<strong>$this->clickSubmit('OK', array('a_hidden_field'=>'123'));</strong>
|
219 |
+
}
|
220 |
+
|
221 |
+
}
|
222 |
+
]]></php>
|
223 |
+
</p>
|
224 |
+
<p>
|
225 |
+
Bear in mind that in doing this you're effectively stubbing out a
|
226 |
+
part of your software (the javascript code in the form), and
|
227 |
+
perhaps you might be better off using something like
|
228 |
+
<a href="http://selenium.openqa.org/">Selenium</a> to ensure a complete
|
229 |
+
acceptance test.
|
230 |
+
</p>
|
231 |
+
</section>
|
232 |
+
<section name="raw" title="Raw posting">
|
233 |
+
<p>
|
234 |
+
If you want to test a form handler, but have not yet written
|
235 |
+
or do not have access to the form itself, you can create a
|
236 |
+
form submission by hand.
|
237 |
+
<php><![CDATA[
|
238 |
+
class SimpleFormTests extends WebTestCase {
|
239 |
+
...<strong>
|
240 |
+
function testAttemptedHack() {
|
241 |
+
$this->post(
|
242 |
+
'http://www.my-site.com/add_user.php',
|
243 |
+
array('type' => 'superuser'));
|
244 |
+
$this->assertNoText('user created');
|
245 |
+
}</strong>
|
246 |
+
}
|
247 |
+
]]></php>
|
248 |
+
By adding data to the <code>WebTestCase::post()</code>
|
249 |
+
method, we are attempting to fetch the page as a form submission.
|
250 |
+
</p>
|
251 |
+
</section>
|
252 |
+
</content>
|
253 |
+
<internal>
|
254 |
+
<link>
|
255 |
+
Changing form values and successfully
|
256 |
+
<a href="#submit">Submitting a simple form</a>
|
257 |
+
</link>
|
258 |
+
<link>
|
259 |
+
Handling <a href="#multiple">widgets with multiple values</a>
|
260 |
+
by setting lists.
|
261 |
+
</link>
|
262 |
+
<link>
|
263 |
+
Bypassing javascript to <a href="#hidden-field">set a hidden field</a>.
|
264 |
+
</link>
|
265 |
+
<link>
|
266 |
+
<a href="#raw">Raw posting</a> when you don't have a button
|
267 |
+
to click.
|
268 |
+
</link>
|
269 |
+
</internal>
|
270 |
+
<external>
|
271 |
+
<link>
|
272 |
+
SimpleTest project page on <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
|
273 |
+
</link>
|
274 |
+
<link>
|
275 |
+
SimpleTest download page on <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
|
276 |
+
</link>
|
277 |
+
<link>
|
278 |
+
The <a href="http://simpletest.org/api/">developer's API for SimpleTest</a>
|
279 |
+
gives full detail on the classes and assertions available.
|
280 |
+
</link>
|
281 |
+
</external>
|
282 |
+
<meta>
|
283 |
+
<keywords>
|
284 |
+
software development,
|
285 |
+
php programming for clients,
|
286 |
+
customer focused php,
|
287 |
+
software development tools,
|
288 |
+
acceptance testing framework,
|
289 |
+
free php scripts,
|
290 |
+
architecture,
|
291 |
+
php resources,
|
292 |
+
HTMLUnit,
|
293 |
+
JWebUnit,
|
294 |
+
php testing,
|
295 |
+
unit test resource,
|
296 |
+
web testing
|
297 |
+
</keywords>
|
298 |
+
</meta>
|
299 |
+
</page>
|
lib/Minify/min_unit_tests/simpletest/docs/source/en/gain_control_tutorial.xml
ADDED
@@ -0,0 +1,308 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!-- $Id: gain_control_tutorial.xml 1687 2008-03-06 13:05:45Z pp11 $ -->
|
3 |
+
<page title="Taking control of testing" here="Taking control">
|
4 |
+
<long_title>PHP unit testing tutorial - Isolating variables when testing</long_title>
|
5 |
+
<content>
|
6 |
+
<introduction>
|
7 |
+
<p>
|
8 |
+
In order to test a code module you need very tight control
|
9 |
+
of its environment.
|
10 |
+
If anything can vary behind the scenes, for example a
|
11 |
+
configuration file, then this could cause the tests
|
12 |
+
to fail unexpectedly.
|
13 |
+
This would not be a fair test of the code and could
|
14 |
+
cause you to spend fruitless hours examining code that
|
15 |
+
is actually working, rather than dealing with the configuration issue
|
16 |
+
that actually failed the test.
|
17 |
+
At the very least your test cases get more complicated in
|
18 |
+
taking account the possible variations.
|
19 |
+
</p>
|
20 |
+
</introduction>
|
21 |
+
<section name="time" title="Controlling time">
|
22 |
+
<p>
|
23 |
+
There are often a lot of obvious variables that could affect
|
24 |
+
a unit test case, especially in the web development
|
25 |
+
environment in which PHP usually operates.
|
26 |
+
These include database set up, file permissions, network
|
27 |
+
resources and configuration amongst others.
|
28 |
+
The failure or misinstall of one of these components will
|
29 |
+
break the test suite.
|
30 |
+
Do we add tests to confirm these components are installed?
|
31 |
+
This is a good idea, but if you place them into code module
|
32 |
+
tests you will start to clutter you test code with detail
|
33 |
+
that is irrelavent to the immediate task.
|
34 |
+
They should be placed in their own test group.
|
35 |
+
</p>
|
36 |
+
<p>
|
37 |
+
Another problem, though, is that our development machines
|
38 |
+
must have every system component installed to be able
|
39 |
+
to run the test suite.
|
40 |
+
Your tests run slower too.
|
41 |
+
</p>
|
42 |
+
<p>
|
43 |
+
When faced with this while coding we will often create wrapper
|
44 |
+
versions of classes that deal with these resources.
|
45 |
+
Ugly details of these resources are then coded once only.
|
46 |
+
I like to call these classes "boundary classes"
|
47 |
+
as they exist at the edges of the application,
|
48 |
+
the interface of your application with the rest of the
|
49 |
+
system.
|
50 |
+
These boundary classes are best simulated during testing
|
51 |
+
by simulated versions.
|
52 |
+
These run faster as well and are often called
|
53 |
+
"Server Stubs" or in more generic form
|
54 |
+
"Mock Objects".
|
55 |
+
It is a great time saver to wrap and stub out every such resource.
|
56 |
+
</p>
|
57 |
+
<p>
|
58 |
+
One often neglected factor is time.
|
59 |
+
For example, to test a session time-out coders will often
|
60 |
+
temporarily set the session time limit to a small value, say two seconds,
|
61 |
+
and then do a <code>sleep(3)</code>
|
62 |
+
and assert that the session is now invalid.
|
63 |
+
That adds three seconds to your test suite and is usually
|
64 |
+
a lot of extra code making your session classes that maleable.
|
65 |
+
Far simpler is to have a way to suddenly advance the clock.
|
66 |
+
To control time.
|
67 |
+
</p>
|
68 |
+
</section>
|
69 |
+
<section name="clock" title="A clock class">
|
70 |
+
<p>
|
71 |
+
Again we will design our clock wrapper by writing tests.
|
72 |
+
Firstly we add a clock test case to our <em>tests/all_tests.php</em>
|
73 |
+
test suite...
|
74 |
+
<php><![CDATA[
|
75 |
+
<?php
|
76 |
+
if (! defined('SIMPLE_TEST')) {
|
77 |
+
define('SIMPLE_TEST', 'simpletest/');
|
78 |
+
}
|
79 |
+
require_once(SIMPLE_TEST . 'autorun.php');
|
80 |
+
require_once('log_test.php');<strong>
|
81 |
+
require_once('clock_test.php');</strong>
|
82 |
+
|
83 |
+
$test = &new TestSuite('All tests');
|
84 |
+
$test->addTestCase(new TestOfLogging());<strong>
|
85 |
+
$test->addTestCase(new TestOfClock());</strong>
|
86 |
+
$test->run(new HtmlReporter());
|
87 |
+
?>
|
88 |
+
]]></php>
|
89 |
+
Then we create the test case in the new file
|
90 |
+
<em>tests/clock_test.php</em>...
|
91 |
+
<php><![CDATA[
|
92 |
+
<strong><?php
|
93 |
+
require_once('../classes/clock.php');
|
94 |
+
|
95 |
+
class TestOfClock extends UnitTestCase {
|
96 |
+
function TestOfClock() {
|
97 |
+
$this->UnitTestCase('Clock class test');
|
98 |
+
}
|
99 |
+
function testClockTellsTime() {
|
100 |
+
$clock = new Clock();
|
101 |
+
$this->assertEqual($clock->now(), time(), 'Now is the right time');
|
102 |
+
}
|
103 |
+
function testClockAdvance() {
|
104 |
+
}
|
105 |
+
}
|
106 |
+
?></strong>
|
107 |
+
]]></php>
|
108 |
+
Our only test at the moment is that our new
|
109 |
+
<code>Clock</code> class acts
|
110 |
+
as a simple PHP <code>time()</code>
|
111 |
+
function substitute.
|
112 |
+
The other method is a place holder.
|
113 |
+
It's our <em>TODO</em> item if you like.
|
114 |
+
We haven't done a test for it yet because that
|
115 |
+
would spoil our rhythm.
|
116 |
+
We will write the time shift functionality once we are green.
|
117 |
+
At the moment we are obviously not green...
|
118 |
+
<div class="demo">
|
119 |
+
<br />
|
120 |
+
<b>Fatal error</b>: Failed opening required '../classes/clock.php' (include_path='') in
|
121 |
+
<b>/home/marcus/projects/lastcraft/tutorial_tests/tests/clock_test.php</b> on line <b>2</b>
|
122 |
+
<br />
|
123 |
+
</div>
|
124 |
+
We create a <em>classes/clock.php</em> file like so...
|
125 |
+
<php><![CDATA[
|
126 |
+
<strong><?php
|
127 |
+
class Clock {
|
128 |
+
|
129 |
+
function Clock() {
|
130 |
+
}
|
131 |
+
|
132 |
+
function now() {
|
133 |
+
}
|
134 |
+
}
|
135 |
+
?></strong>
|
136 |
+
]]></php>
|
137 |
+
This regains our flow ready for coding.
|
138 |
+
<div class="demo">
|
139 |
+
<h1>All tests</h1>
|
140 |
+
<span class="fail">Fail</span>: Clock class test->testclocktellstime->[NULL: ] should be equal to [integer: 1050257362]<br />
|
141 |
+
<div style="padding: 8px; margin-top: 1em; background-color: red; color: white;">3/3 test cases complete.
|
142 |
+
<strong>4</strong> passes and <strong>1</strong> fails.</div>
|
143 |
+
</div>
|
144 |
+
This is now easy to fix...
|
145 |
+
<php><![CDATA[
|
146 |
+
class Clock {
|
147 |
+
|
148 |
+
function Clock() {
|
149 |
+
}
|
150 |
+
|
151 |
+
function now() {<strong>
|
152 |
+
return time();</strong>
|
153 |
+
}
|
154 |
+
}
|
155 |
+
]]></php>
|
156 |
+
And now we are green...
|
157 |
+
<div class="demo">
|
158 |
+
<h1>All tests</h1>
|
159 |
+
<div style="padding: 8px; margin-top: 1em; background-color: green; color: white;">3/3 test cases complete.
|
160 |
+
<strong>5</strong> passes and <strong>0</strong> fails.</div>
|
161 |
+
</div>
|
162 |
+
There is still a problem.
|
163 |
+
The clock could roll over during the assertion causing the
|
164 |
+
result to be out by one second.
|
165 |
+
The chances are small, but if there were a lot of timing tests
|
166 |
+
you would end up with a test suite that is erratic, severely
|
167 |
+
limiting its usefulness.
|
168 |
+
We will <a href="subclass_tutorial.php">tackle this shortly</a> and for now just jot it onto our
|
169 |
+
"to do" list.
|
170 |
+
</p>
|
171 |
+
<p>
|
172 |
+
The advancement test looks like this...
|
173 |
+
<php><![CDATA[
|
174 |
+
class TestOfClock extends UnitTestCase {
|
175 |
+
function TestOfClock() {
|
176 |
+
$this->UnitTestCase('Clock class test');
|
177 |
+
}
|
178 |
+
function testClockTellsTime() {
|
179 |
+
$clock = new Clock();
|
180 |
+
$this->assertEqual($clock->now(), time(), 'Now is the right time');
|
181 |
+
}<strong>
|
182 |
+
function testClockAdvance() {
|
183 |
+
$clock = new Clock();
|
184 |
+
$clock->advance(10);
|
185 |
+
$this->assertEqual($clock->now(), time() + 10, 'Advancement');
|
186 |
+
}</strong>
|
187 |
+
}
|
188 |
+
]]></php>
|
189 |
+
The code to get to green is straight forward and just involves adding
|
190 |
+
a time offset.
|
191 |
+
<php><![CDATA[
|
192 |
+
class Clock {<strong>
|
193 |
+
var $_offset;</strong>
|
194 |
+
|
195 |
+
function Clock() {<strong>
|
196 |
+
$this->_offset = 0;</strong>
|
197 |
+
}
|
198 |
+
|
199 |
+
function now() {
|
200 |
+
return time()<strong> + $this->_offset</strong>;
|
201 |
+
}
|
202 |
+
<strong>
|
203 |
+
function advance($offset) {
|
204 |
+
$this->_offset += $offset;
|
205 |
+
}</strong>
|
206 |
+
}
|
207 |
+
]]></php>
|
208 |
+
</p>
|
209 |
+
</section>
|
210 |
+
<section name="tidy" title="Group test tidy up">
|
211 |
+
<p>
|
212 |
+
Our <em>all_tests.php</em> file has some repetition we could
|
213 |
+
do without.
|
214 |
+
We have to manually add our test cases from each included
|
215 |
+
file.
|
216 |
+
It is possible to remove it, but use of the following requires care.
|
217 |
+
The <code>TestSuite</code> class has a
|
218 |
+
convenience method called <code>addFile()</code>
|
219 |
+
that takes a PHP file as a parameter.
|
220 |
+
This mechanism makes a note of all the classes, requires in the
|
221 |
+
file and then has a look at any newly created classes.
|
222 |
+
If they are descendents of <code>TestCase</code>
|
223 |
+
they are added as a new group test.
|
224 |
+
</p>
|
225 |
+
<p>
|
226 |
+
In addition the <em>autorun</em> library will run all the collected
|
227 |
+
test cases automagically after loading them.
|
228 |
+
</p>
|
229 |
+
<p>
|
230 |
+
Here is our refactored test suite using this method...
|
231 |
+
<php><![CDATA[
|
232 |
+
<?php
|
233 |
+
if (! defined('SIMPLE_TEST')) {
|
234 |
+
define('SIMPLE_TEST', 'simpletest/');
|
235 |
+
}<strong>
|
236 |
+
require_once(SIMPLE_TEST . 'autorun.php');</strong>
|
237 |
+
<strong>
|
238 |
+
class AllTests extends TestSuite {
|
239 |
+
function AllTests() {
|
240 |
+
$this->TestSuite('All tests');
|
241 |
+
$this->addFile('log_test.php');
|
242 |
+
$this->addFile('clock_test.php');
|
243 |
+
}
|
244 |
+
}</strong>
|
245 |
+
?>
|
246 |
+
]]></php>
|
247 |
+
The pitfalls of this are...
|
248 |
+
<ol>
|
249 |
+
<li>
|
250 |
+
If the test file has already been included,
|
251 |
+
no new classes will be added to this group
|
252 |
+
</li>
|
253 |
+
<li>
|
254 |
+
If the test file has other classes that are
|
255 |
+
related to <code>TestCase</code>
|
256 |
+
then these will be added to the group test as well.
|
257 |
+
</li>
|
258 |
+
</ol>
|
259 |
+
In our tests we have only test cases in the test files and
|
260 |
+
we removed their inclusion from the <em>all_tests.php</em>
|
261 |
+
script and so we are OK.
|
262 |
+
This is the usual situation.
|
263 |
+
</p>
|
264 |
+
<p>
|
265 |
+
We should really fix the glitch with the possible
|
266 |
+
clock rollover so we'll
|
267 |
+
<a href="subclass_tutorial.php">do this next</a>.
|
268 |
+
</p>
|
269 |
+
</section>
|
270 |
+
</content>
|
271 |
+
<internal>
|
272 |
+
<link><a href="#time">Time</a> is an often neglected variable in tests.</link>
|
273 |
+
<link>A <a href="#clock">clock class</a> allows us to alter time.</link>
|
274 |
+
<link><a href="#tidy">Tidying the group test</a>.</link>
|
275 |
+
</internal>
|
276 |
+
<external>
|
277 |
+
<link>
|
278 |
+
The previous section is
|
279 |
+
<a href="group_test_tutorial.php">grouping unit tests</a>.
|
280 |
+
</link>
|
281 |
+
<link>
|
282 |
+
The next section is
|
283 |
+
<a href="subclass_tutorial.php">subclassing test cases</a>.
|
284 |
+
</link>
|
285 |
+
<link>
|
286 |
+
You will need
|
287 |
+
<a href="simple_test.php">the SimpleTest unit tester</a>
|
288 |
+
for the examples.
|
289 |
+
</link>
|
290 |
+
</external>
|
291 |
+
<meta>
|
292 |
+
<keywords>
|
293 |
+
software development,
|
294 |
+
php programming,
|
295 |
+
programming php,
|
296 |
+
|