Post Thumbnail Editor - Version 1.0.0

Version Description

  • Total redesign of PHP/HTML interface
  • Allows editing multiple images
  • Switch from fancybox to wordpress' included thickbox
Download this release

Release Info

Developer sewpafly
Plugin Icon Post Thumbnail Editor
Version 1.0.0
Comparing to
See all releases

Code changes from version 0.2.2 to 1.0.0

Files changed (129) hide show
  1. Makefile +74 -0
  2. README.txt +41 -16
  3. apps/fancybox/README.markdown +0 -4
  4. apps/fancybox/blank.gif +0 -0
  5. apps/fancybox/fancy_close.png +0 -0
  6. apps/fancybox/fancy_loading.png +0 -0
  7. apps/fancybox/fancy_nav_left.png +0 -0
  8. apps/fancybox/fancy_nav_right.png +0 -0
  9. apps/fancybox/fancy_shadow_e.png +0 -0
  10. apps/fancybox/fancy_shadow_n.png +0 -0
  11. apps/fancybox/fancy_shadow_ne.png +0 -0
  12. apps/fancybox/fancy_shadow_nw.png +0 -0
  13. apps/fancybox/fancy_shadow_s.png +0 -0
  14. apps/fancybox/fancy_shadow_se.png +0 -0
  15. apps/fancybox/fancy_shadow_sw.png +0 -0
  16. apps/fancybox/fancy_shadow_w.png +0 -0
  17. apps/fancybox/fancy_title_left.png +0 -0
  18. apps/fancybox/fancy_title_main.png +0 -0
  19. apps/fancybox/fancy_title_over.png +0 -0
  20. apps/fancybox/fancy_title_right.png +0 -0
  21. apps/fancybox/fancybox-x.png +0 -0
  22. apps/fancybox/fancybox-y.png +0 -0
  23. apps/fancybox/fancybox.png +0 -0
  24. apps/fancybox/jquery.easing-1.3.pack.js +0 -72
  25. apps/fancybox/jquery.fancybox-1.3.4.css +0 -359
  26. apps/fancybox/jquery.fancybox-1.3.4.js +0 -1156
  27. apps/fancybox/jquery.fancybox-1.3.4.min.js +0 -29
  28. apps/fancybox/jquery.fancybox-1.3.4.pack.js +0 -46
  29. apps/fancybox/jquery.mousewheel-3.0.4.pack.js +0 -14
  30. apps/jquery-tmpl/.gitignore +7 -0
  31. apps/jquery-tmpl/README.md +19 -0
  32. apps/jquery-tmpl/demos/movies/PagesCore/movies.html +353 -0
  33. apps/jquery-tmpl/demos/movies/PagesCore/moviesNoGlobals.html +363 -0
  34. apps/jquery-tmpl/demos/movies/PagesTmplPlus/movies1.html +351 -0
  35. apps/jquery-tmpl/demos/movies/PagesTmplPlus/movies2.html +342 -0
  36. apps/jquery-tmpl/demos/movies/PagesTmplPlus/movies3.html +333 -0
  37. apps/jquery-tmpl/demos/movies/components/jquery-ui-1.8.1.custom.js +1929 -0
  38. apps/jquery-tmpl/demos/movies/components/jquery-ui-1.8.1.custom.min.js +96 -0
  39. apps/jquery-tmpl/demos/movies/components/jquery.pager.js +132 -0
  40. apps/jquery-tmpl/demos/movies/css/jquery-ui-1.8.1.custom.css +408 -0
  41. apps/jquery-tmpl/demos/movies/css/movies.css +279 -0
  42. apps/jquery-tmpl/demos/movies/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png +0 -0
  43. apps/jquery-tmpl/demos/movies/images/ui-bg_dots-small_65_a6a6a6_2x2.png +0 -0
  44. apps/jquery-tmpl/demos/movies/images/ui-bg_flat_0_333333_40x100.png +0 -0
  45. apps/jquery-tmpl/demos/movies/images/ui-bg_flat_65_ffffff_40x100.png +0 -0
  46. apps/jquery-tmpl/demos/movies/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  47. apps/jquery-tmpl/demos/movies/images/ui-bg_glass_55_fbf8ee_1x400.png +0 -0
  48. apps/jquery-tmpl/demos/movies/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  49. apps/jquery-tmpl/demos/movies/images/ui-bg_highlight-hard_100_eeeeee_1x100.png +0 -0
  50. apps/jquery-tmpl/demos/movies/images/ui-bg_highlight-hard_100_f6f6f6_1x100.png +0 -0
  51. apps/jquery-tmpl/demos/movies/images/ui-bg_highlight-soft_15_cc0000_1x100.png +0 -0
  52. apps/jquery-tmpl/demos/movies/images/ui-icons_004276_256x240.png +0 -0
  53. apps/jquery-tmpl/demos/movies/images/ui-icons_cc0000_256x240.png +0 -0
  54. apps/jquery-tmpl/demos/movies/images/ui-icons_ffffff_256x240.png +0 -0
  55. apps/jquery-tmpl/demos/resources/demos.css +7 -0
  56. apps/jquery-tmpl/demos/resources/movielist.css +7 -0
  57. apps/jquery-tmpl/demos/resources/syntaxhighlighter.css +513 -0
  58. apps/jquery-tmpl/demos/resources/syntaxhighlighter.min.js +30 -0
  59. apps/jquery-tmpl/demos/samplesCore/Interactive/resources/collapsed.png +0 -0
  60. apps/jquery-tmpl/demos/samplesCore/Interactive/resources/empty.png +0 -0
  61. apps/jquery-tmpl/demos/samplesCore/Interactive/resources/expanded.png +0 -0
  62. apps/jquery-tmpl/demos/samplesCore/Interactive/resources/folder.png +0 -0
  63. apps/jquery-tmpl/demos/samplesCore/Interactive/resources/tabs.css +75 -0
  64. apps/jquery-tmpl/demos/samplesCore/Interactive/resources/treeView.css +50 -0
  65. apps/jquery-tmpl/demos/samplesCore/Interactive/tabsTmpl.html +77 -0
  66. apps/jquery-tmpl/demos/samplesCore/Interactive/tabsWrap.html +94 -0
  67. apps/jquery-tmpl/demos/samplesCore/Interactive/tabsWrapImperative.html +74 -0
  68. apps/jquery-tmpl/demos/samplesCore/Interactive/tabsWrapNested.html +116 -0
  69. apps/jquery-tmpl/demos/samplesCore/Interactive/treeView.html +123 -0
  70. apps/jquery-tmpl/demos/samplesCore/basic.html +141 -0
  71. apps/jquery-tmpl/demos/samplesCore/composition.html +98 -0
  72. apps/jquery-tmpl/demos/samplesCore/conditional.html +41 -0
  73. apps/jquery-tmpl/demos/samplesCore/each.html +85 -0
  74. apps/jquery-tmpl/demos/samplesCore/parameters.html +104 -0
  75. apps/jquery-tmpl/demos/samplesTmplPlus/basic.html +105 -0
  76. apps/jquery-tmpl/demos/samplesTmplPlus/composition.html +103 -0
  77. apps/jquery-tmpl/demos/samplesTmplPlus/parameters.html +110 -0
  78. apps/jquery-tmpl/demos/step-by-step.html +33 -0
  79. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/0_local-data-source.html +63 -0
  80. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/0_local-data.html +40 -0
  81. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/1_remote-data-source.html +101 -0
  82. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/1_remote-data.html +64 -0
  83. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/2_html-tag-source.html +81 -0
  84. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/2_html-tag.html +60 -0
  85. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/3_if-else-tag-source.html +102 -0
  86. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/3_if-else-tag.html +66 -0
  87. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/4_each-tag-source.html +104 -0
  88. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/4_each-tag.html +75 -0
  89. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/5_javascript-source.html +123 -0
  90. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/5_javascript.html +89 -0
  91. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/6_hierarchical-data-source.html +96 -0
  92. apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/6_hierarchical-data.html +67 -0
  93. apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/0_accordion-switching-template-source.html +184 -0
  94. apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/0_accordion-switching-template.html +123 -0
  95. apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/1_tree-view-using-tmpl-tag-source.html +173 -0
  96. apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/1_tree-view-using-tmpl-tag.html +107 -0
  97. apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/2_tabs-using-wrap-tag-source.html +181 -0
  98. apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/2_tabs-using-wrap-tag.html +120 -0
  99. apps/jquery-tmpl/jquery.tmpl.js +484 -0
  100. apps/jquery-tmpl/jquery.tmpl.min.js +10 -0
  101. apps/jquery-tmpl/jquery.tmplPlus.js +99 -0
  102. apps/jquery-tmpl/jquery.tmplPlus.min.js +11 -0
  103. apps/jquery-tmpl/tests/core.js +395 -0
  104. apps/jquery-tmpl/tests/index.html +22 -0
  105. apps/jquery-tmpl/tests/qunit.css +196 -0
  106. apps/jquery-tmpl/tests/qunit.js +1364 -0
  107. checklist.md +26 -0
  108. css/pte.css +213 -13
  109. css/pte.min.css +1 -0
  110. css/pte.scss +210 -0
  111. css/reset.css +49 -0
  112. html/pte.html +141 -0
  113. images/back.gif +0 -0
  114. images/loading.gif +0 -0
  115. js/header.coffee +8 -0
  116. js/log.coffee +7 -0
  117. js/pte.coffee +337 -0
  118. js/pte.full.js +915 -0
  119. js/pte.full.min.js +25 -0
  120. js/pte_admin.coffee +92 -0
  121. js/pte_admin_media.js +0 -325
  122. local.mk +9 -0
  123. post-thumbnail-editor.php +87 -41
  124. pte_functions.php +561 -287
  125. screenshot-2.jpg +0 -0
  126. screenshot-3.jpg +0 -0
  127. screenshot-4.jpg +0 -0
  128. screenshot-5.jpg +0 -0
  129. screenshot-6.jpg +0 -0
Makefile ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ JSOUTPUT_DEV = js/pte.full.js
3
+ JSOUTPUT_MIN = js/pte.full.min.js
4
+ COFFEE = coffee
5
+ COFFEE_FLAGS = -s -p
6
+ COFFEE_FILES = js/header.coffee \
7
+ js/log.coffee \
8
+ js/pte_admin.coffee \
9
+ js/pte.coffee
10
+ JS_FILES = apps/jquery-tmpl/jquery.tmpl.js
11
+
12
+
13
+ CSSOUTPUT_DEV = css/pte.css
14
+ CSSOUTPUT_MIN = css/pte.min.css
15
+ SCSSFILE = css/pte.scss
16
+ SASS = sass
17
+ CSSFILES = css/reset.css
18
+
19
+ # create/overwrite the JSMINIFIER command for local
20
+ # local.mk is not tracked in git project
21
+ include $(wildcard local.mk)
22
+
23
+ # The GOOGLE macro is defined in local.mk to point to compiler.jar
24
+ ifdef GOOGLE
25
+ JSMINIFIER = java -jar "$(GOOGLE)" --js $(JSOUTPUT_DEV) --js_output_file $(JSOUTPUT_MIN)
26
+ else
27
+ JSMINIFIER = cp $(JSOUTPUT_DEV) $(JSOUTPUT_MIN)
28
+ endif
29
+
30
+ # The YUI macro is defined in local.mk to point to yuicompressor.jar
31
+ ifdef YUI
32
+ CSSMINIFIER = java -jar "$(YUI)" --type css -o $(CSSOUTPUT_MIN) $(CSSOUTPUT_DEV)
33
+ else
34
+ CSSMINIFIER = cp $(CSSOUTPUT_DEV) $(CSSOUTPUT_MIN)
35
+ endif
36
+
37
+
38
+ # A simple make will compile the js/css and minify them
39
+ all: minify-js minify-css
40
+
41
+ # Build javascript
42
+ $(JSOUTPUT_MIN): $(JSOUTPUT_DEV)
43
+ @echo "Minifying javascript"
44
+ $(JSMINIFIER)
45
+
46
+ $(JSOUTPUT_DEV): $(COFFEE_FILES) $(JS_FILES)
47
+ @echo "Building javascript"
48
+ cat $(JS_FILES) > $(JSOUTPUT_DEV)
49
+ cat $(COFFEE_FILES) | $(COFFEE) $(COFFEE_FLAGS) >> $(JSOUTPUT_DEV)
50
+
51
+
52
+ # BUILD CSS
53
+ $(CSSOUTPUT_DEV): $(SCSSFILE) $(CSSFILES)
54
+ @echo "Building CSS"
55
+ cat $(CSSFILES) > $(CSSOUTPUT_DEV)
56
+ $(SASS) $(SCSSFILE) >> $(CSSOUTPUT_DEV)
57
+
58
+ $(CSSOUTPUT_MIN): $(CSSOUTPUT_DEV)
59
+ @echo "Minifying CSS"
60
+ $(CSSMINIFIER)
61
+
62
+ # Shortcuts
63
+ js: $(JSOUTPUT_DEV)
64
+ minify-js: $(JSOUTPUT_MIN)
65
+ css: $(CSSOUTPUT_DEV)
66
+ minify-css: $(CSSOUTPUT_MIN)
67
+
68
+ # Clean
69
+ OUTPUTFILES = $(wildcard $(CSSOUTPUT_MIN) $(CSSOUTPUT_DEV) $(JSOUTPUT_MIN) $(JSOUTPUT_DEV))
70
+ clean:
71
+ @echo "Cleaning up"
72
+ $(if $(OUTPUTFILES), rm $(OUTPUTFILES))
73
+
74
+ # vi: ts=3
README.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Post Thumbnail Editor ===
2
  Contributors: sewpafly
3
  Donate link: http://github.com/sewpafly/post-thumbnail-editor
4
- Tags: post-thumbnail, post thumbnail, featured image, featured, editor, image
5
  Requires at least: 3.1
6
- Tested up to: 3.1
7
  Stable tag: trunk
8
 
9
  Fed up with the lack of automated tools to properly crop and scale post thumbnails? Maybe this plugin can help.
@@ -12,15 +12,6 @@ Fed up with the lack of automated tools to properly crop and scale post thumbnai
12
 
13
  To meet the needs of themes where the post-thumbnails have random and capricious sizes (which causes wordpress to crop images simply from the middle (either chopping off the top and bottom or chopping off the sides), this plugin attempts to give the users an interface to manually fix those thumbnail and random images.
14
 
15
- **Use**:
16
-
17
- 1. Open Media Library
18
- 2. Pick the image to edit
19
- 3. Click "Edit Image"
20
- 4. Use the dropdown box underneath the "Thumbnail Settings" section to select the thumbnail that you want to edit.
21
- 5. After you select the cropped/scaled area, click "Save"
22
- 6. You might have to refresh the cache (ctrl+f5 on the page) to see changes, but they should be there.
23
-
24
  == Installation ==
25
 
26
  1. Download the zip file from <http://downloads.wordpress.org/plugin/post-thumbnail-editor.zip>
@@ -34,22 +25,48 @@ To meet the needs of themes where the post-thumbnails have random and capricious
34
 
35
  == Frequently Asked Questions ==
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  = Did you even test this? =
38
 
39
- No, thanks for asking. But [let me know if you're having problems](https://github.com/sewpafly/post-thumbnail-editor/issues) and I'll see what I can do.
40
 
41
  = Is there a way to regenerate images created by this plugin? =
42
 
43
- Not yet, Coming in the next release (0.3). However, I'm hopeful that any images you've created with previous versions will be able to be regenerated by release 0.3.
 
 
 
 
44
 
45
  == Screenshots ==
46
 
47
  1. Before/After
48
- 2. In the Edit subpage for media locate the box title "Edit Post Thumbnails", and select the image size you wish to modify.
49
- 3. Crop the image as you see fit and click "Save".
 
 
50
 
51
  == Changelog ==
52
 
 
 
 
 
 
53
  = 0.2 =
54
  * Added support to change thumbnails aspect ratio. Previously a square image was generated. (Only works for "medium" or "large" thumbnails by default. Will work for "thumbnail" size if the crop checkbox isn't checked under Media Settings).
55
  * Thumbnails are appended with "-pte" to differentiate images created with this plugin
@@ -62,11 +79,19 @@ Not yet, Coming in the next release (0.3). However, I'm hopeful that any images
62
 
63
  == Upgrade Notice ==
64
 
 
 
 
 
 
 
 
65
  = 0.2.1 =
66
- Fixed an error with older PHP installs
67
 
68
  = 0.2 =
69
  Change thumbnails aspect ratio (only works for medium/large. Will work for thumbnail if the crop checkbox isn't checked under Media Settings)
70
 
71
  = 0.1.1 =
72
  This version fixes a IE8/firefox javascript error.
 
1
  === Post Thumbnail Editor ===
2
  Contributors: sewpafly
3
  Donate link: http://github.com/sewpafly/post-thumbnail-editor
4
+ Tags: post-thumbnail, post thumbnail, featured image, featured, editor, image, awesome
5
  Requires at least: 3.1
6
+ Tested up to: 3.2.1
7
  Stable tag: trunk
8
 
9
  Fed up with the lack of automated tools to properly crop and scale post thumbnails? Maybe this plugin can help.
12
 
13
  To meet the needs of themes where the post-thumbnails have random and capricious sizes (which causes wordpress to crop images simply from the middle (either chopping off the top and bottom or chopping off the sides), this plugin attempts to give the users an interface to manually fix those thumbnail and random images.
14
 
 
 
 
 
 
 
 
 
 
15
  == Installation ==
16
 
17
  1. Download the zip file from <http://downloads.wordpress.org/plugin/post-thumbnail-editor.zip>
25
 
26
  == Frequently Asked Questions ==
27
 
28
+ = Usage =
29
+
30
+ 1. Start with the Media Library
31
+ 1. Open Media Library
32
+ 2. Click the "Thumbnail" link in the rollover options.
33
+ 2. or start within image editor interface (when viewing image details)
34
+ 1. Click "Edit Image"
35
+ 2. Click the "Post Thumbnail Editor" link under the other thumbnail options.
36
+ 3. Using Post Thumbnail Editor Interface
37
+ 1. Select the thumbnails you want to edit. If a thumbnail defines a specific aspect ratio it will be applied to the editor. If you select thumbnails with more than 1 different aspect ratios, this feature is disabled. Be careful or you might make some of your pictures look funny.
38
+ 2. Select the cropped/scaled area, by clicking and dragging on the left-hand image.
39
+ 3. Click "Create Thumbnails" -- this button is only enabled if you have thumbnails selected and a crop area defined.
40
+ 4. Thumbnail Preview: select all the thumbnails you want to keep and click "Okay, these look good".
41
+ 4. It's possible that you might have to refresh the cache (ctrl+f5 on the page) to see changes, but they should be there.
42
+
43
  = Did you even test this? =
44
 
45
+ Yes. No. Sort of. Thanks for asking. But [let me know if you're having problems](https://github.com/sewpafly/post-thumbnail-editor/issues) and I'll see what I can do.
46
 
47
  = Is there a way to regenerate images created by this plugin? =
48
 
49
+ Do you really want this? I haven't gotten any feedback that this is desirable... So imma let it go for now.
50
+
51
+ = What version of PHP do I need? =
52
+
53
+ Using a version with [json_encode](http://www.php.net/manual/en/function.json-encode.php) enabled would be nice...
54
 
55
  == Screenshots ==
56
 
57
  1. Before/After
58
+ 2. To edit from Media Library click "Thumbnail" in the rollover options for the row.
59
+ 3. In the Edit subpage for media locate the box titled "Thumbnail Settings", and click the link to "Post Thumbnail Editor".
60
+ 4. Crop the image as you see fit and click "Create Thumbnails".
61
+ 5. Verify you want to keep the resized/recropped images by clicking "Okay, these look good..."
62
 
63
  == Changelog ==
64
 
65
+ = 1.0.0 =
66
+ * Total redesign of PHP/HTML interface
67
+ * Allows editing multiple images
68
+ * Switch from fancybox to wordpress' included thickbox
69
+
70
  = 0.2 =
71
  * Added support to change thumbnails aspect ratio. Previously a square image was generated. (Only works for "medium" or "large" thumbnails by default. Will work for "thumbnail" size if the crop checkbox isn't checked under Media Settings).
72
  * Thumbnails are appended with "-pte" to differentiate images created with this plugin
79
 
80
  == Upgrade Notice ==
81
 
82
+ = 1.0.0 =
83
+ Now with more awesome. Redesigned interface will challenge your perceptions of the universe.
84
+
85
+ = 0.2.2 =
86
+ Fixed version information
87
+ Fixed plugin specific defines
88
+
89
  = 0.2.1 =
90
+ Fixed PHP round() issue.
91
 
92
  = 0.2 =
93
  Change thumbnails aspect ratio (only works for medium/large. Will work for thumbnail if the crop checkbox isn't checked under Media Settings)
94
 
95
  = 0.1.1 =
96
  This version fixes a IE8/firefox javascript error.
97
+
apps/fancybox/README.markdown DELETED
@@ -1,4 +0,0 @@
1
- Fancy Box Jquery Plugin
2
- =======================
3
-
4
- I just wanted to have a git repository for the [fancybox jQuery plugin](http://fancybox.net/) so that I could use it for my submodules. Originally this was just to recreate exactly the structure of the zip file you could download from the official site. So the official zip structure can be found in the example branch while the master is a cut of the fancybox directory with an additional closure compiled/minified version of the fancybox plugin.
 
 
 
 
apps/fancybox/blank.gif DELETED
Binary file
apps/fancybox/fancy_close.png DELETED
Binary file
apps/fancybox/fancy_loading.png DELETED
Binary file
apps/fancybox/fancy_nav_left.png DELETED
Binary file
apps/fancybox/fancy_nav_right.png DELETED
Binary file
apps/fancybox/fancy_shadow_e.png DELETED
Binary file
apps/fancybox/fancy_shadow_n.png DELETED
Binary file
apps/fancybox/fancy_shadow_ne.png DELETED
Binary file
apps/fancybox/fancy_shadow_nw.png DELETED
Binary file
apps/fancybox/fancy_shadow_s.png DELETED
Binary file
apps/fancybox/fancy_shadow_se.png DELETED
Binary file
apps/fancybox/fancy_shadow_sw.png DELETED
Binary file
apps/fancybox/fancy_shadow_w.png DELETED
Binary file
apps/fancybox/fancy_title_left.png DELETED
Binary file
apps/fancybox/fancy_title_main.png DELETED
Binary file
apps/fancybox/fancy_title_over.png DELETED
Binary file
apps/fancybox/fancy_title_right.png DELETED
Binary file
apps/fancybox/fancybox-x.png DELETED
Binary file
apps/fancybox/fancybox-y.png DELETED
Binary file
apps/fancybox/fancybox.png DELETED
Binary file
apps/fancybox/jquery.easing-1.3.pack.js DELETED
@@ -1,72 +0,0 @@
1
- /*
2
- * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3
- *
4
- * Uses the built in easing capabilities added In jQuery 1.1
5
- * to offer multiple easing options
6
- *
7
- * TERMS OF USE - jQuery Easing
8
- *
9
- * Open source under the BSD License.
10
- *
11
- * Copyright © 2008 George McGinley Smith
12
- * All rights reserved.
13
- *
14
- * Redistribution and use in source and binary forms, with or without modification,
15
- * are permitted provided that the following conditions are met:
16
- *
17
- * Redistributions of source code must retain the above copyright notice, this list of
18
- * conditions and the following disclaimer.
19
- * Redistributions in binary form must reproduce the above copyright notice, this list
20
- * of conditions and the following disclaimer in the documentation and/or other materials
21
- * provided with the distribution.
22
- *
23
- * Neither the name of the author nor the names of contributors may be used to endorse
24
- * or promote products derived from this software without specific prior written permission.
25
- *
26
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
27
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
31
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34
- * OF THE POSSIBILITY OF SUCH DAMAGE.
35
- *
36
- */
37
-
38
- // t: current time, b: begInnIng value, c: change In value, d: duration
39
- 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}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))
40
-
41
- /*
42
- *
43
- * TERMS OF USE - EASING EQUATIONS
44
- *
45
- * Open source under the BSD License.
46
- *
47
- * Copyright © 2001 Robert Penner
48
- * All rights reserved.
49
- *
50
- * Redistribution and use in source and binary forms, with or without modification,
51
- * are permitted provided that the following conditions are met:
52
- *
53
- * Redistributions of source code must retain the above copyright notice, this list of
54
- * conditions and the following disclaimer.
55
- * Redistributions in binary form must reproduce the above copyright notice, this list
56
- * of conditions and the following disclaimer in the documentation and/or other materials
57
- * provided with the distribution.
58
- *
59
- * Neither the name of the author nor the names of contributors may be used to endorse
60
- * or promote products derived from this software without specific prior written permission.
61
- *
62
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
63
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
64
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
65
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
66
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
67
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
68
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
69
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
70
- * OF THE POSSIBILITY OF SUCH DAMAGE.
71
- *
72
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apps/fancybox/jquery.fancybox-1.3.4.css DELETED
@@ -1,359 +0,0 @@
1
- /*
2
- * FancyBox - jQuery Plugin
3
- * Simple and fancy lightbox alternative
4
- *
5
- * Examples and documentation at: http://fancybox.net
6
- *
7
- * Copyright (c) 2008 - 2010 Janis Skarnelis
8
- * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
9
- *
10
- * Version: 1.3.4 (11/11/2010)
11
- * Requires: jQuery v1.3+
12
- *
13
- * Dual licensed under the MIT and GPL licenses:
14
- * http://www.opensource.org/licenses/mit-license.php
15
- * http://www.gnu.org/licenses/gpl.html
16
- */
17
-
18
- #fancybox-loading {
19
- position: fixed;
20
- top: 50%;
21
- left: 50%;
22
- width: 40px;
23
- height: 40px;
24
- margin-top: -20px;
25
- margin-left: -20px;
26
- cursor: pointer;
27
- overflow: hidden;
28
- z-index: 1104;
29
- display: none;
30
- }
31
-
32
- #fancybox-loading div {
33
- position: absolute;
34
- top: 0;
35
- left: 0;
36
- width: 40px;
37
- height: 480px;
38
- background-image: url('fancybox.png');
39
- }
40
-
41
- #fancybox-overlay {
42
- position: absolute;
43
- top: 0;
44
- left: 0;
45
- width: 100%;
46
- z-index: 1100;
47
- display: none;
48
- }
49
-
50
- #fancybox-tmp {
51
- padding: 0;
52
- margin: 0;
53
- border: 0;
54
- overflow: auto;
55
- display: none;
56
- }
57
-
58
- #fancybox-wrap {
59
- position: absolute;
60
- top: 0;
61
- left: 0;
62
- padding: 20px;
63
- z-index: 1101;
64
- outline: none;
65
- display: none;
66
- }
67
-
68
- #fancybox-outer {
69
- position: relative;
70
- width: 100%;
71
- height: 100%;
72
- background: #fff;
73
- }
74
-
75
- #fancybox-content {
76
- width: 0;
77
- height: 0;
78
- padding: 0;
79
- outline: none;
80
- position: relative;
81
- overflow: hidden;
82
- z-index: 1102;
83
- border: 0px solid #fff;
84
- }
85
-
86
- #fancybox-hide-sel-frame {
87
- position: absolute;
88
- top: 0;
89
- left: 0;
90
- width: 100%;
91
- height: 100%;
92
- background: transparent;
93
- z-index: 1101;
94
- }
95
-
96
- #fancybox-close {
97
- position: absolute;
98
- top: -15px;
99
- right: -15px;
100
- width: 30px;
101
- height: 30px;
102
- background: transparent url('fancybox.png') -40px 0px;
103
- cursor: pointer;
104
- z-index: 1103;
105
- display: none;
106
- }
107
-
108
- #fancybox-error {
109
- color: #444;
110
- font: normal 12px/20px Arial;
111
- padding: 14px;
112
- margin: 0;
113
- }
114
-
115
- #fancybox-img {
116
- width: 100%;
117
- height: 100%;
118
- padding: 0;
119
- margin: 0;
120
- border: none;
121
- outline: none;
122
- line-height: 0;
123
- vertical-align: top;
124
- }
125
-
126
- #fancybox-frame {
127
- width: 100%;
128
- height: 100%;
129
- border: none;
130
- display: block;
131
- }
132
-
133
- #fancybox-left, #fancybox-right {
134
- position: absolute;
135
- bottom: 0px;
136
- height: 100%;
137
- width: 35%;
138
- cursor: pointer;
139
- outline: none;
140
- background: transparent url('blank.gif');
141
- z-index: 1102;
142
- display: none;
143
- }
144
-
145
- #fancybox-left {
146
- left: 0px;
147
- }
148
-
149
- #fancybox-right {
150
- right: 0px;
151
- }
152
-
153
- #fancybox-left-ico, #fancybox-right-ico {
154
- position: absolute;
155
- top: 50%;
156
- left: -9999px;
157
- width: 30px;
158
- height: 30px;
159
- margin-top: -15px;
160
- cursor: pointer;
161
- z-index: 1102;
162
- display: block;
163
- }
164
-
165
- #fancybox-left-ico {
166
- background-image: url('fancybox.png');
167
- background-position: -40px -30px;
168
- }
169
-
170
- #fancybox-right-ico {
171
- background-image: url('fancybox.png');
172
- background-position: -40px -60px;
173
- }
174
-
175
- #fancybox-left:hover, #fancybox-right:hover {
176
- visibility: visible; /* IE6 */
177
- }
178
-
179
- #fancybox-left:hover span {
180
- left: 20px;
181
- }
182
-
183
- #fancybox-right:hover span {
184
- left: auto;
185
- right: 20px;
186
- }
187
-
188
- .fancybox-bg {
189
- position: absolute;
190
- padding: 0;
191
- margin: 0;
192
- border: 0;
193
- width: 20px;
194
- height: 20px;
195
- z-index: 1001;
196
- }
197
-
198
- #fancybox-bg-n {
199
- top: -20px;
200
- left: 0;
201
- width: 100%;
202
- background-image: url('fancybox-x.png');
203
- }
204
-
205
- #fancybox-bg-ne {
206
- top: -20px;
207
- right: -20px;
208
- background-image: url('fancybox.png');
209
- background-position: -40px -162px;
210
- }
211
-
212
- #fancybox-bg-e {
213
- top: 0;
214
- right: -20px;
215
- height: 100%;
216
- background-image: url('fancybox-y.png');
217
- background-position: -20px 0px;
218
- }
219
-
220
- #fancybox-bg-se {
221
- bottom: -20px;
222
- right: -20px;
223
- background-image: url('fancybox.png');
224
- background-position: -40px -182px;
225
- }
226
-
227
- #fancybox-bg-s {
228
- bottom: -20px;
229
- left: 0;
230
- width: 100%;
231
- background-image: url('fancybox-x.png');
232
- background-position: 0px -20px;
233
- }
234
-
235
- #fancybox-bg-sw {
236
- bottom: -20px;
237
- left: -20px;
238
- background-image: url('fancybox.png');
239
- background-position: -40px -142px;
240
- }
241
-
242
- #fancybox-bg-w {
243
- top: 0;
244
- left: -20px;
245
- height: 100%;
246
- background-image: url('fancybox-y.png');
247
- }
248
-
249
- #fancybox-bg-nw {
250
- top: -20px;
251
- left: -20px;
252
- background-image: url('fancybox.png');
253
- background-position: -40px -122px;
254
- }
255
-
256
- #fancybox-title {
257
- font-family: Helvetica;
258
- font-size: 12px;
259
- z-index: 1102;
260
- }
261
-
262
- .fancybox-title-inside {
263
- padding-bottom: 10px;
264
- text-align: center;
265
- color: #333;
266
- background: #fff;
267
- position: relative;
268
- }
269
-
270
- .fancybox-title-outside {
271
- padding-top: 10px;
272
- color: #fff;
273
- }
274
-
275
- .fancybox-title-over {
276
- position: absolute;
277
- bottom: 0;
278
- left: 0;
279
- color: #FFF;
280
- text-align: left;
281
- }
282
-
283
- #fancybox-title-over {
284
- padding: 10px;
285
- background-image: url('fancy_title_over.png');
286
- display: block;
287
- }
288
-
289
- .fancybox-title-float {
290
- position: absolute;
291
- left: 0;
292
- bottom: -20px;
293
- height: 32px;
294
- }
295
-
296
- #fancybox-title-float-wrap {
297
- border: none;
298
- border-collapse: collapse;
299
- width: auto;
300
- }
301
-
302
- #fancybox-title-float-wrap td {
303
- border: none;
304
- white-space: nowrap;
305
- }
306
-
307
- #fancybox-title-float-left {
308
- padding: 0 0 0 15px;
309
- background: url('fancybox.png') -40px -90px no-repeat;
310
- }
311
-
312
- #fancybox-title-float-main {
313
- color: #FFF;
314
- line-height: 29px;
315
- font-weight: bold;
316
- padding: 0 0 3px 0;
317
- background: url('fancybox-x.png') 0px -40px;
318
- }
319
-
320
- #fancybox-title-float-right {
321
- padding: 0 0 0 15px;
322
- background: url('fancybox.png') -55px -90px no-repeat;
323
- }
324
-
325
- /* IE6 */
326
-
327
- .fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); }
328
-
329
- .fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); }
330
- .fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); }
331
-
332
- .fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
333
- .fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); }
334
- .fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); }
335
- .fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); }
336
-
337
- .fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame {
338
- height: expression(this.parentNode.clientHeight + "px");
339
- }
340
-
341
- #fancybox-loading.fancybox-ie6 {
342
- position: absolute; margin-top: 0;
343
- top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px');
344
- }
345
-
346
- #fancybox-loading.fancybox-ie6 div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); }
347
-
348
- /* IE6, IE7, IE8 */
349
-
350
- .fancybox-ie .fancybox-bg { background: transparent !important; }
351
-
352
- .fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
353
- .fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
354
- .fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
355
- .fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
356
- .fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
357
- .fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
358
- .fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
359
- .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apps/fancybox/jquery.fancybox-1.3.4.js DELETED
@@ -1,1156 +0,0 @@
1
- /*
2
- * FancyBox - jQuery Plugin
3
- * Simple and fancy lightbox alternative
4
- *
5
- * Examples and documentation at: http://fancybox.net
6
- *
7
- * Copyright (c) 2008 - 2010 Janis Skarnelis
8
- * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
9
- *
10
- * Version: 1.3.4 (11/11/2010)
11
- * Requires: jQuery v1.3+
12
- *
13
- * Dual licensed under the MIT and GPL licenses:
14
- * http://www.opensource.org/licenses/mit-license.php
15
- * http://www.gnu.org/licenses/gpl.html
16
- */
17
-
18
- ;(function($) {
19
- var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right,
20
-
21
- selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],
22
-
23
- ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,
24
-
25
- loadingTimer, loadingFrame = 1,
26
-
27
- titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }),
28
-
29
- isIE6 = $.browser.msie && $.browser.version < 7 && !window.XMLHttpRequest,
30
-
31
- /*
32
- * Private methods
33
- */
34
-
35
- _abort = function() {
36
- loading.hide();
37
-
38
- imgPreloader.onerror = imgPreloader.onload = null;
39
-
40
- if (ajaxLoader) {
41
- ajaxLoader.abort();
42
- }
43
-
44
- tmp.empty();
45
- },
46
-
47
- _error = function() {
48
- if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) {
49
- loading.hide();
50
- busy = false;
51
- return;
52
- }
53
-
54
- selectedOpts.titleShow = false;
55
-
56
- selectedOpts.width = 'auto';
57
- selectedOpts.height = 'auto';
58
-
59
- tmp.html( '<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>' );
60
-
61
- _process_inline();
62
- },
63
-
64
- _start = function() {
65
- var obj = selectedArray[ selectedIndex ],
66
- href,
67
- type,
68
- title,
69
- str,
70
- emb,
71
- ret;
72
-
73
- _abort();
74
-
75
- selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));
76
-
77
- ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts);
78
-
79
- if (ret === false) {
80
- busy = false;
81
- return;
82
- } else if (typeof ret == 'object') {
83
- selectedOpts = $.extend(selectedOpts, ret);
84
- }
85
-
86
- title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || '';
87
-
88
- if (obj.nodeName && !selectedOpts.orig) {
89
- selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
90
- }
91
-
92
- if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) {
93
- title = selectedOpts.orig.attr('alt');
94
- }
95
-
96
- href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null;
97
-
98
- if ((/^(?:javascript)/i).test(href) || href == '#') {
99
- href = null;
100
- }
101
-
102
- if (selectedOpts.type) {
103
- type = selectedOpts.type;
104
-
105
- if (!href) {
106
- href = selectedOpts.content;
107
- }
108
-
109
- } else if (selectedOpts.content) {
110
- type = 'html';
111
-
112
- } else if (href) {
113
- if (href.match(imgRegExp)) {
114
- type = 'image';
115
-
116
- } else if (href.match(swfRegExp)) {
117
- type = 'swf';
118
-
119
- } else if ($(obj).hasClass("iframe")) {
120
- type = 'iframe';
121
-
122
- } else if (href.indexOf("#") === 0) {
123
- type = 'inline';
124
-
125
- } else {
126
- type = 'ajax';
127
- }
128
- }
129
-
130
- if (!type) {
131
- _error();
132
- return;
133
- }
134
-
135
- if (type == 'inline') {
136
- obj = href.substr(href.indexOf("#"));
137
- type = $(obj).length > 0 ? 'inline' : 'ajax';
138
- }
139
-
140
- selectedOpts.type = type;
141
- selectedOpts.href = href;
142
- selectedOpts.title = title;
143
-
144
- if (selectedOpts.autoDimensions) {
145
- if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') {
146
- selectedOpts.width = 'auto';
147
- selectedOpts.height = 'auto';
148
- } else {
149
- selectedOpts.autoDimensions = false;
150
- }
151
- }
152
-
153
- if (selectedOpts.modal) {
154
- selectedOpts.overlayShow = true;
155
- selectedOpts.hideOnOverlayClick = false;
156
- selectedOpts.hideOnContentClick = false;
157
- selectedOpts.enableEscapeButton = false;
158
- selectedOpts.showCloseButton = false;
159
- }
160
-
161
- selectedOpts.padding = parseInt(selectedOpts.padding, 10);
162
- selectedOpts.margin = parseInt(selectedOpts.margin, 10);
163
-
164
- tmp.css('padding', (selectedOpts.padding + selectedOpts.margin));
165
-
166
- $('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
167
- $(this).replaceWith(content.children());
168
- });
169
-
170
- switch (type) {
171
- case 'html' :
172
- tmp.html( selectedOpts.content );
173
- _process_inline();
174
- break;
175
-
176
- case 'inline' :
177
- if ( $(obj).parent().is('#fancybox-content') === true) {
178
- busy = false;
179
- return;
180
- }
181
-
182
- $('<div class="fancybox-inline-tmp" />')
183
- .hide()
184
- .insertBefore( $(obj) )
185
- .bind('fancybox-cleanup', function() {
186
- $(this).replaceWith(content.children());
187
- }).bind('fancybox-cancel', function() {
188
- $(this).replaceWith(tmp.children());
189
- });
190
-
191
- $(obj).appendTo(tmp);
192
-
193
- _process_inline();
194
- break;
195
-
196
- case 'image':
197
- busy = false;
198
-
199
- $.fancybox.showActivity();
200
-
201
- imgPreloader = new Image();
202
-
203
- imgPreloader.onerror = function() {
204
- _error();
205
- };
206
-
207
- imgPreloader.onload = function() {
208
- busy = true;
209
-
210
- imgPreloader.onerror = imgPreloader.onload = null;
211
-
212
- _process_image();
213
- };
214
-
215
- imgPreloader.src = href;
216
- break;
217
-
218
- case 'swf':
219
- selectedOpts.scrolling = 'no';
220
-
221
- str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
222
- emb = '';
223
-
224
- $.each(selectedOpts.swf, function(name, val) {
225
- str += '<param name="' + name + '" value="' + val + '"></param>';
226
- emb += ' ' + name + '="' + val + '"';
227
- });
228
-
229
- str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';
230
-
231
- tmp.html(str);
232
-
233
- _process_inline();
234
- break;
235
-
236
- case 'ajax':
237
- busy = false;
238
-
239
- $.fancybox.showActivity();
240
-
241
- selectedOpts.ajax.win = selectedOpts.ajax.success;
242
-
243
- ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, {
244
- url : href,
245
- data : selectedOpts.ajax.data || {},
246
- error : function(XMLHttpRequest, textStatus, errorThrown) {
247
- if ( XMLHttpRequest.status > 0 ) {
248
- _error();
249
- }
250
- },
251
- success : function(data, textStatus, XMLHttpRequest) {
252
- var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader;
253
- if (o.status == 200) {
254
- if ( typeof selectedOpts.ajax.win == 'function' ) {
255
- ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest);
256
-
257
- if (ret === false) {
258
- loading.hide();
259
- return;
260
- } else if (typeof ret == 'string' || typeof ret == 'object') {
261
- data = ret;
262
- }
263
- }
264
-
265
- tmp.html( data );
266
- _process_inline();
267
- }
268
- }
269
- }));
270
-
271
- break;
272
-
273
- case 'iframe':
274
- _show();
275
- break;
276
- }
277
- },
278
-
279
- _process_inline = function() {
280
- var
281
- w = selectedOpts.width,
282
- h = selectedOpts.height;
283
-
284
- if (w.toString().indexOf('%') > -1) {
285
- w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px';
286
-
287
- } else {
288
- w = w == 'auto' ? 'auto' : w + 'px';
289
- }
290
-
291
- if (h.toString().indexOf('%') > -1) {
292
- h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px';
293
-
294
- } else {
295
- h = h == 'auto' ? 'auto' : h + 'px';
296
- }
297
-
298
- tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>');
299
-
300
- selectedOpts.width = tmp.width();
301
- selectedOpts.height = tmp.height();
302
-
303
- _show();
304
- },
305
-
306
- _process_image = function() {
307
- selectedOpts.width = imgPreloader.width;
308
- selectedOpts.height = imgPreloader.height;
309
-
310
- $("<img />").attr({
311
- 'id' : 'fancybox-img',
312
- 'src' : imgPreloader.src,
313
- 'alt' : selectedOpts.title
314
- }).appendTo( tmp );
315
-
316
- _show();
317
- },
318
-
319
- _show = function() {
320
- var pos, equal;
321
-
322
- loading.hide();
323
-
324
- if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
325
- $.event.trigger('fancybox-cancel');
326
-
327
- busy = false;
328
- return;
329
- }
330
-
331
- busy = true;
332
-
333
- $(content.add( overlay )).unbind();
334
-
335
- $(window).unbind("resize.fb scroll.fb");
336
- $(document).unbind('keydown.fb');
337
-
338
- if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') {
339
- wrap.css('height', wrap.height());
340
- }
341
-
342
- currentArray = selectedArray;
343
- currentIndex = selectedIndex;
344
- currentOpts = selectedOpts;
345
-
346
- if (currentOpts.overlayShow) {
347
- overlay.css({
348
- 'background-color' : currentOpts.overlayColor,
349
- 'opacity' : currentOpts.overlayOpacity,
350
- 'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto',
351
- 'height' : $(document).height()
352
- });
353
-
354
- if (!overlay.is(':visible')) {
355
- if (isIE6) {
356
- $('select:not(#fancybox-tmp select)').filter(function() {
357
- return this.style.visibility !== 'hidden';
358
- }).css({'visibility' : 'hidden'}).one('fancybox-cleanup', function() {
359
- this.style.visibility = 'inherit';
360
- });
361
- }
362
-
363
- overlay.show();
364
- }
365
- } else {
366
- overlay.hide();
367
- }
368
-
369
- final_pos = _get_zoom_to();
370
-
371
- _process_title();
372
-
373
- if (wrap.is(":visible")) {
374
- $( close.add( nav_left ).add( nav_right ) ).hide();
375
-
376
- pos = wrap.position(),
377
-
378
- start_pos = {
379
- top : pos.top,
380
- left : pos.left,
381
- width : wrap.width(),
382
- height : wrap.height()
383
- };
384
-
385
- equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);
386
-
387
- content.fadeTo(currentOpts.changeFade, 0.3, function() {
388
- var finish_resizing = function() {
389
- content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish);
390
- };
391
-
392
- $.event.trigger('fancybox-change');
393
-
394
- content
395
- .empty()
396
- .removeAttr('filter')
397
- .css({
398
- 'border-width' : currentOpts.padding,
399
- 'width' : final_pos.width - currentOpts.padding * 2,
400
- 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
401
- });
402
-
403
- if (equal) {
404
- finish_resizing();
405
-
406
- } else {
407
- fx.prop = 0;
408
-
409
- $(fx).animate({prop: 1}, {
410
- duration : currentOpts.changeSpeed,
411
- easing : currentOpts.easingChange,
412
- step : _draw,
413
- complete : finish_resizing
414
- });
415
- }
416
- });
417
-
418
- return;
419
- }
420
-
421
- wrap.removeAttr("style");
422
-
423
- content.css('border-width', currentOpts.padding);
424
-
425
- if (currentOpts.transitionIn == 'elastic') {
426
- start_pos = _get_zoom_from();
427
-
428
- content.html( tmp.contents() );
429
-
430
- wrap.show();
431
-
432
- if (currentOpts.opacity) {
433
- final_pos.opacity = 0;
434
- }
435
-
436
- fx.prop = 0;
437
-
438
- $(fx).animate({prop: 1}, {
439
- duration : currentOpts.speedIn,
440
- easing : currentOpts.easingIn,
441
- step : _draw,
442
- complete : _finish
443
- });
444
-
445
- return;
446
- }
447
-
448
- if (currentOpts.titlePosition == 'inside' && titleHeight > 0) {
449
- title.show();
450
- }
451
-
452
- content
453
- .css({
454
- 'width' : final_pos.width - currentOpts.padding * 2,
455
- 'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
456
- })
457
- .html( tmp.contents() );
458
-
459
- wrap
460
- .css(final_pos)
461
- .fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
462
- },
463
-
464
- _format_title = function(title) {
465
- if (title && title.length) {
466
- if (currentOpts.titlePosition == 'float') {
467
- return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>';
468
- }
469
-
470
- return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>';
471
- }
472
-
473
- return false;
474
- },
475
-
476
- _process_title = function() {
477
- titleStr = currentOpts.title || '';
478
- titleHeight = 0;
479
-
480
- title
481
- .empty()
482
- .removeAttr('style')
483
- .removeClass();
484
-
485
- if (currentOpts.titleShow === false) {
486
- title.hide();
487
- return;
488
- }
489
-
490
- titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr);
491
-
492
- if (!titleStr || titleStr === '') {
493
- title.hide();
494
- return;
495
- }
496
-
497
- title
498
- .addClass('fancybox-title-' + currentOpts.titlePosition)
499
- .html( titleStr )
500
- .appendTo( 'body' )
501
- .show();
502
-
503
- switch (currentOpts.titlePosition) {
504
- case 'inside':
505
- title
506
- .css({
507
- 'width' : final_pos.width - (currentOpts.padding * 2),
508
- 'marginLeft' : currentOpts.padding,
509
- 'marginRight' : currentOpts.padding
510
- });
511
-
512
- titleHeight = title.outerHeight(true);
513
-
514
- title.appendTo( outer );
515
-
516
- final_pos.height += titleHeight;
517
- break;
518
-
519
- case 'over':
520
- title
521
- .css({
522
- 'marginLeft' : currentOpts.padding,
523
- 'width' : final_pos.width - (currentOpts.padding * 2),
524
- 'bottom' : currentOpts.padding
525
- })
526
- .appendTo( outer );
527
- break;
528
-
529
- case 'float':
530
- title
531
- .css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1)
532
- .appendTo( wrap );
533
- break;
534
-
535
- default:
536
- title
537
- .css({
538
- 'width' : final_pos.width - (currentOpts.padding * 2),
539
- 'paddingLeft' : currentOpts.padding,
540
- 'paddingRight' : currentOpts.padding
541
- })
542
- .appendTo( wrap );
543
- break;
544
- }
545
-
546
- title.hide();
547
- },
548
-
549
- _set_navigation = function() {
550
- if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) {
551
- $(document).bind('keydown.fb', function(e) {
552
- if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
553
- e.preventDefault();
554
- $.fancybox.close();
555
-
556
- } else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') {
557
- e.preventDefault();
558
- $.fancybox[ e.keyCode == 37 ? 'prev' : 'next']();
559
- }
560
- });
561
- }
562
-
563
- if (!currentOpts.showNavArrows) {
564
- nav_left.hide();
565
- nav_right.hide();
566
- return;
567
- }
568
-
569
- if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
570
- nav_left.show();
571
- }
572
-
573
- if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
574
- nav_right.show();
575
- }
576
- },
577
-
578
- _finish = function () {
579
- if (!$.support.opacity) {
580
- content.get(0).style.removeAttribute('filter');
581
- wrap.get(0).style.removeAttribute('filter');
582
- }
583
-
584
- if (selectedOpts.autoDimensions) {
585
- content.css('height', 'auto');
586
- }
587
-
588
- wrap.css('height', 'auto');
589
-
590
- if (titleStr && titleStr.length) {
591
- title.show();
592
- }
593
-
594
- if (currentOpts.showCloseButton) {
595
- close.show();
596
- }
597
-
598
- _set_navigation();
599
-
600
- if (currentOpts.hideOnContentClick) {
601
- content.bind('click', $.fancybox.close);
602
- }
603
-
604
- if (currentOpts.hideOnOverlayClick) {
605
- overlay.bind('click', $.fancybox.close);
606
- }
607
-
608
- $(window).bind("resize.fb", $.fancybox.resize);
609
-
610
- if (currentOpts.centerOnScroll) {
611
- $(window).bind("scroll.fb", $.fancybox.center);
612
- }
613
-
614
- if (currentOpts.type == 'iframe') {
615
- $('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content);
616
- }
617
-
618
- wrap.show();
619
-
620
- busy = false;
621
-
622
- $.fancybox.center();
623
-
624
- currentOpts.onComplete(currentArray, currentIndex, currentOpts);
625
-
626
- _preload_images();
627
- },
628
-
629
- _preload_images = function() {
630
- var href,
631
- objNext;
632
-
633
- if ((currentArray.length -1) > currentIndex) {
634
- href = currentArray[ currentIndex + 1 ].href;
635
-
636
- if (typeof href !== 'undefined' && href.match(imgRegExp)) {
637
- objNext = new Image();
638
- objNext.src = href;
639
- }
640
- }
641
-
642
- if (currentIndex > 0) {
643
- href = currentArray[ currentIndex - 1 ].href;
644
-
645
- if (typeof href !== 'undefined' && href.match(imgRegExp)) {
646
- objNext = new Image();
647
- objNext.src = href;
648
- }
649
- }
650
- },
651
-
652
- _draw = function(pos) {
653
- var dim = {
654
- width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10),
655
- height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10),
656
-
657
- top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10),
658
- left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10)
659
- };
660
-
661
- if (typeof final_pos.opacity !== 'undefined') {
662
- dim.opacity = pos < 0.5 ? 0.5 : pos;
663
- }
664
-
665
- wrap.css(dim);
666
-
667
- content.css({
668
- 'width' : dim.width - currentOpts.padding * 2,
669
- 'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2
670
- });
671
- },
672
-
673
- _get_viewport = function() {
674
- return [
675
- $(window).width() - (currentOpts.margin * 2),
676
- $(window).height() - (currentOpts.margin * 2),
677
- $(document).scrollLeft() + currentOpts.margin,
678
- $(document).scrollTop() + currentOpts.margin
679
- ];
680
- },
681
-
682
- _get_zoom_to = function () {
683
- var view = _get_viewport(),
684
- to = {},
685
- resize = currentOpts.autoScale,
686
- double_padding = currentOpts.padding * 2,
687
- ratio;
688
-
689
- if (currentOpts.width.toString().indexOf('%') > -1) {
690
- to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10);
691
- } else {
692
- to.width = currentOpts.width + double_padding;
693
- }
694
-
695
- if (currentOpts.height.toString().indexOf('%') > -1) {
696
- to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10);
697
- } else {
698
- to.height = currentOpts.height + double_padding;
699
- }
700
-
701
- if (resize && (to.width > view[0] || to.height > view[1])) {
702
- if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
703
- ratio = (currentOpts.width ) / (currentOpts.height );
704
-
705
- if ((to.width ) > view[0]) {
706
- to.width = view[0];
707
- to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10);
708
- }
709
-
710
- if ((to.height) > view[1]) {
711
- to.height = view[1];
712
- to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10);
713
- }
714
-
715
- } else {
716
- to.width = Math.min(to.width, view[0]);
717
- to.height = Math.min(to.height, view[1]);
718
- }
719
- }
720
-
721
- to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10);
722
- to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10);
723
-
724
- return to;
725
- },
726
-
727
- _get_obj_pos = function(obj) {
728
- var pos = obj.offset();
729
-
730
- pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0;
731
- pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0;
732
-
733
- pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0;
734
- pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0;
735
-
736
- pos.width = obj.width();
737
- pos.height = obj.height();
738
-
739
- return pos;
740
- },
741
-
742
- _get_zoom_from = function() {
743
- var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
744
- from = {},
745
- pos,
746
- view;
747
-
748
- if (orig && orig.length) {
749
- pos = _get_obj_pos(orig);
750
-
751
- from = {
752
- width : pos.width + (currentOpts.padding * 2),
753
- height : pos.height + (currentOpts.padding * 2),
754
- top : pos.top - currentOpts.padding - 20,
755
- left : pos.left - currentOpts.padding - 20
756
- };
757
-
758
- } else {
759
- view = _get_viewport();
760
-
761
- from = {
762
- width : currentOpts.padding * 2,
763
- height : currentOpts.padding * 2,
764
- top : parseInt(view[3] + view[1] * 0.5, 10),
765
- left : parseInt(view[2] + view[0] * 0.5, 10)
766
- };
767
- }
768
-
769
- return from;
770
- },
771
-
772
- _animate_loading = function() {
773
- if (!loading.is(':visible')){
774
- clearInterval(loadingTimer);
775
- return;
776
- }
777
-
778
- $('div', loading).css('top', (loadingFrame * -40) + 'px');
779
-
780
- loadingFrame = (loadingFrame + 1) % 12;
781
- };
782
-
783
- /*
784
- * Public methods
785
- */
786
-
787
- $.fn.fancybox = function(options) {
788
- if (!$(this).length) {
789
- return this;
790
- }
791
-
792
- $(this)
793
- .data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
794
- .unbind('click.fb')
795
- .bind('click.fb', function(e) {
796
- e.preventDefault();
797
-
798
- if (busy) {
799
- return;
800
- }
801
-
802
- busy = true;
803
-
804
- $(this).blur();
805
-
806
- selectedArray = [];
807
- selectedIndex = 0;
808
-
809
- var rel = $(this).attr('rel') || '';
810
-
811
- if (!rel || rel == '' || rel === 'nofollow') {
812
- selectedArray.push(this);
813
-
814
- } else {
815
- selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]");
816
- selectedIndex = selectedArray.index( this );
817
- }
818
-
819
- _start();
820
-
821
- return;
822
- });
823
-
824
- return this;
825
- };
826
-
827
- $.fancybox = function(obj) {
828
- var opts;
829
-
830
- if (busy) {
831
- return;
832
- }
833
-
834
- busy = true;
835
- opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};
836
-
837
- selectedArray = [];
838
- selectedIndex = parseInt(opts.index, 10) || 0;
839
-
840
- if ($.isArray(obj)) {
841
- for (var i = 0, j = obj.length; i < j; i++) {
842
- if (typeof obj[i] == 'object') {
843
- $(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
844
- } else {
845
- obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
846
- }
847
- }
848
-
849
- selectedArray = jQuery.merge(selectedArray, obj);
850
-
851
- } else {
852
- if (typeof obj == 'object') {
853
- $(obj).data('fancybox', $.extend({}, opts, obj));
854
- } else {
855
- obj = $({}).data('fancybox', $.extend({content : obj}, opts));
856
- }
857
-
858
- selectedArray.push(obj);
859
- }
860
-
861
- if (selectedIndex > selectedArray.length || selectedIndex < 0) {
862
- selectedIndex = 0;
863
- }
864
-
865
- _start();
866
- };
867
-
868
- $.fancybox.showActivity = function() {
869
- clearInterval(loadingTimer);
870
-
871
- loading.show();
872
- loadingTimer = setInterval(_animate_loading, 66);
873
- };
874
-
875
- $.fancybox.hideActivity = function() {
876
- loading.hide();
877
- };
878
-
879
- $.fancybox.next = function() {
880
- return $.fancybox.pos( currentIndex + 1);
881
- };
882
-
883
- $.fancybox.prev = function() {
884
- return $.fancybox.pos( currentIndex - 1);
885
- };
886
-
887
- $.fancybox.pos = function(pos) {
888
- if (busy) {
889
- return;
890
- }
891
-
892
- pos = parseInt(pos);
893
-
894
- selectedArray = currentArray;
895
-
896
- if (pos > -1 && pos < currentArray.length) {
897
- selectedIndex = pos;
898
- _start();
899
-
900
- } else if (currentOpts.cyclic && currentArray.length > 1) {
901
- selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1;
902
- _start();
903
- }
904
-
905
- return;
906
- };
907
-
908
- $.fancybox.cancel = function() {
909
- if (busy) {
910
- return;
911
- }
912
-
913
- busy = true;
914
-
915
- $.event.trigger('fancybox-cancel');
916
-
917
- _abort();
918
-
919
- selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);
920
-
921
- busy = false;
922
- };
923
-
924
- // Note: within an iframe use - parent.$.fancybox.close();
925
- $.fancybox.close = function() {
926
- if (busy || wrap.is(':hidden')) {
927
- return;
928
- }
929
-
930
- busy = true;
931
-
932
- if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
933
- busy = false;
934
- return;
935
- }
936
-
937
- _abort();
938
-
939
- $(close.add( nav_left ).add( nav_right )).hide();
940
-
941
- $(content.add( overlay )).unbind();
942
-
943
- $(window).unbind("resize.fb scroll.fb");
944
- $(document).unbind('keydown.fb');
945
-
946
- content.find('iframe').attr('src', isIE6 && /^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank');
947
-
948
- if (currentOpts.titlePosition !== 'inside') {
949
- title.empty();
950
- }
951
-
952
- wrap.stop();
953
-
954
- function _cleanup() {
955
- overlay.fadeOut('fast');
956
-
957
- title.empty().hide();
958
- wrap.hide();
959
-
960
- $.event.trigger('fancybox-cleanup');
961
-
962
- content.empty();
963
-
964
- currentOpts.onClosed(currentArray, currentIndex, currentOpts);
965
-
966
- currentArray = selectedOpts = [];
967
- currentIndex = selectedIndex = 0;
968
- currentOpts = selectedOpts = {};
969
-
970
- busy = false;
971
- }
972
-
973
- if (currentOpts.transitionOut == 'elastic') {
974
- start_pos = _get_zoom_from();
975
-
976
- var pos = wrap.position();
977
-
978
- final_pos = {
979
- top : pos.top ,
980
- left : pos.left,
981
- width : wrap.width(),
982
- height : wrap.height()
983
- };
984
-
985
- if (currentOpts.opacity) {
986
- final_pos.opacity = 1;
987
- }
988
-
989
- title.empty().hide();
990
-
991
- fx.prop = 1;
992
-
993
- $(fx).animate({ prop: 0 }, {
994
- duration : currentOpts.speedOut,
995
- easing : currentOpts.easingOut,
996
- step : _draw,
997
- complete : _cleanup
998
- });
999
-
1000
- } else {
1001
- wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
1002
- }
1003
- };
1004
-
1005
- $.fancybox.resize = function() {
1006
- if (overlay.is(':visible')) {
1007
- overlay.css('height', $(document).height());
1008
- }
1009
-
1010
- $.fancybox.center(true);
1011
- };
1012
-
1013
- $.fancybox.center = function() {
1014
- var view, align;
1015
-
1016
- if (busy) {
1017
- return;
1018
- }
1019
-
1020
- align = arguments[0] === true ? 1 : 0;
1021
- view = _get_viewport();
1022
-
1023
- if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) {
1024
- return;
1025
- }
1026
-
1027
- wrap
1028
- .stop()
1029
- .animate({
1030
- 'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)),
1031
- 'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding))
1032
- }, typeof arguments[0] == 'number' ? arguments[0] : 200);
1033
- };
1034
-
1035
- $.fancybox.init = function() {
1036
- if ($("#fancybox-wrap").length) {
1037
- return;
1038
- }
1039
-
1040
- $('body').append(
1041
- tmp = $('<div id="fancybox-tmp"></div>'),
1042
- loading = $('<div id="fancybox-loading"><div></div></div>'),
1043
- overlay = $('<div id="fancybox-overlay"></div>'),
1044
- wrap = $('<div id="fancybox-wrap"></div>')
1045
- );
1046
-
1047
- outer = $('<div id="fancybox-outer"></div>')
1048
- .append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>')
1049
- .appendTo( wrap );
1050
-
1051
- outer.append(
1052
- content = $('<div id="fancybox-content"></div>'),
1053
- close = $('<a id="fancybox-close"></a>'),
1054
- title = $('<div id="fancybox-title"></div>'),
1055
-
1056
- nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
1057
- nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
1058
- );
1059
-
1060
- close.click($.fancybox.close);
1061
- loading.click($.fancybox.cancel);
1062
-
1063
- nav_left.click(function(e) {
1064
- e.preventDefault();
1065
- $.fancybox.prev();
1066
- });
1067
-
1068
- nav_right.click(function(e) {
1069
- e.preventDefault();
1070
- $.fancybox.next();
1071
- });
1072
-
1073
- if ($.fn.mousewheel) {
1074
- wrap.bind('mousewheel.fb', function(e, delta) {
1075
- if (busy) {
1076
- e.preventDefault();
1077
-
1078
- } else if ($(e.target).get(0).clientHeight == 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
1079
- e.preventDefault();
1080
- $.fancybox[ delta > 0 ? 'prev' : 'next']();
1081
- }
1082
- });
1083
- }
1084
-
1085
- if (!$.support.opacity) {
1086
- wrap.addClass('fancybox-ie');
1087
- }
1088
-
1089
- if (isIE6) {
1090
- loading.addClass('fancybox-ie6');
1091
- wrap.addClass('fancybox-ie6');
1092
-
1093
- $('<iframe id="fancybox-hide-sel-frame" src="' + (/^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank' ) + '" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(outer);
1094
- }
1095
- };
1096
-
1097
- $.fn.fancybox.defaults = {
1098
- padding : 10,
1099
- margin : 40,
1100
- opacity : false,
1101
- modal : false,
1102
- cyclic : false,
1103
- scrolling : 'auto', // 'auto', 'yes' or 'no'
1104
-
1105
- width : 560,
1106
- height : 340,
1107
-
1108
- autoScale : true,
1109
- autoDimensions : true,
1110
- centerOnScroll : false,
1111
-
1112
- ajax : {},
1113
- swf : { wmode: 'transparent' },
1114
-
1115
- hideOnOverlayClick : true,
1116
- hideOnContentClick : false,
1117
-
1118
- overlayShow : true,
1119
- overlayOpacity : 0.7,
1120
- overlayColor : '#777',
1121
-
1122
- titleShow : true,
1123
- titlePosition : 'float', // 'float', 'outside', 'inside' or 'over'
1124
- titleFormat : null,
1125
- titleFromAlt : false,
1126
-
1127
- transitionIn : 'fade', // 'elastic', 'fade' or 'none'
1128
- transitionOut : 'fade', // 'elastic', 'fade' or 'none'
1129
-
1130
- speedIn : 300,
1131
- speedOut : 300,
1132
-
1133
- changeSpeed : 300,
1134
- changeFade : 'fast',
1135
-
1136
- easingIn : 'swing',
1137
- easingOut : 'swing',
1138
-
1139
- showCloseButton : true,
1140
- showNavArrows : true,
1141
- enableEscapeButton : true,
1142
- enableKeyboardNav : true,
1143
-
1144
- onStart : function(){},
1145
- onCancel : function(){},
1146
- onComplete : function(){},
1147
- onCleanup : function(){},
1148
- onClosed : function(){},
1149
- onError : function(){}
1150
- };
1151
-
1152
- $(document).ready(function() {
1153
- $.fancybox.init();
1154
- });
1155
-
1156
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apps/fancybox/jquery.fancybox-1.3.4.min.js DELETED
@@ -1,29 +0,0 @@
1
- (function(b){var m,t,u,f,D,j,E,n,z,A,q=0,e={},o=[],p=0,d={},l=[],G=null,v=new Image,J=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,W=/[^\.]\.(swf)\s*$/i,K,L=1,y=0,s="",r,i,h=false,B=b.extend(b("<div/>")[0],{prop:0}),M=b.browser.msie&&b.browser.version<7&&!window.XMLHttpRequest,N=function(){t.hide();v.onerror=v.onload=null;G&&G.abort();m.empty()},O=function(){if(false===e.onError(o,q,e)){t.hide();h=false}else{e.titleShow=false;e.width="auto";e.height="auto";m.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');
2
- F()}},I=function(){var a=o[q],c,g,k,C,P,w;N();e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));w=e.onStart(o,q,e);if(w===false)h=false;else{if(typeof w=="object")e=b.extend(e,w);k=e.title||(a.nodeName?b(a).attr("title"):a.title)||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(k===""&&e.orig&&e.titleFromAlt)k=e.orig.attr("alt");c=e.href||(a.nodeName?b(a).attr("href"):a.href)||null;if(/^(?:javascript)/i.test(c)||
3
- c=="#")c=null;if(e.type){g=e.type;if(!c)c=e.content}else if(e.content)g="html";else if(c)g=c.match(J)?"image":c.match(W)?"swf":b(a).hasClass("iframe")?"iframe":c.indexOf("#")===0?"inline":"ajax";if(g){if(g=="inline"){a=c.substr(c.indexOf("#"));g=b(a).length>0?"inline":"ajax"}e.type=g;e.href=c;e.title=k;if(e.autoDimensions)if(e.type=="html"||e.type=="inline"||e.type=="ajax"){e.width="auto";e.height="auto"}else e.autoDimensions=false;if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick=
4
- false;e.enableEscapeButton=false;e.showCloseButton=false}e.padding=parseInt(e.padding,10);e.margin=parseInt(e.margin,10);m.css("padding",e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(j.children())});switch(g){case "html":m.html(e.content);F();break;case "inline":if(b(a).parent().is("#fancybox-content")===true){h=false;break}b('<div class="fancybox-inline-tmp" />').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(j.children())}).bind("fancybox-cancel",
5
- function(){b(this).replaceWith(m.children())});b(a).appendTo(m);F();break;case "image":h=false;b.fancybox.showActivity();v=new Image;v.onerror=function(){O()};v.onload=function(){h=true;v.onerror=v.onload=null;e.width=v.width;e.height=v.height;b("<img />").attr({id:"fancybox-img",src:v.src,alt:e.title}).appendTo(m);Q()};v.src=c;break;case "swf":e.scrolling="no";C='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+e.width+'" height="'+e.height+'"><param name="movie" value="'+c+
6
- '"></param>';P="";b.each(e.swf,function(x,H){C+='<param name="'+x+'" value="'+H+'"></param>';P+=" "+x+'="'+H+'"'});C+='<embed src="'+c+'" type="application/x-shockwave-flash" width="'+e.width+'" height="'+e.height+'"'+P+"></embed></object>";m.html(C);F();break;case "ajax":h=false;b.fancybox.showActivity();e.ajax.win=e.ajax.success;G=b.ajax(b.extend({},e.ajax,{url:c,data:e.ajax.data||{},error:function(x){x.status>0&&O()},success:function(x,H,R){if((typeof R=="object"?R:G).status==200){if(typeof e.ajax.win==
7
- "function"){w=e.ajax.win(c,x,H,R);if(w===false){t.hide();return}else if(typeof w=="string"||typeof w=="object")x=w}m.html(x);F()}}}));break;case "iframe":Q()}}else O()}},F=function(){var a=e.width,c=e.height;a=a.toString().indexOf("%")>-1?parseInt((b(window).width()-e.margin*2)*parseFloat(a)/100,10)+"px":a=="auto"?"auto":a+"px";c=c.toString().indexOf("%")>-1?parseInt((b(window).height()-e.margin*2)*parseFloat(c)/100,10)+"px":c=="auto"?"auto":c+"px";m.wrapInner('<div style="width:'+a+";height:"+c+
8
- ";overflow: "+(e.scrolling=="auto"?"auto":e.scrolling=="yes"?"scroll":"hidden")+';position:relative;"></div>');e.width=m.width();e.height=m.height();Q()},Q=function(){var a,c;t.hide();if(f.is(":visible")&&false===d.onCleanup(l,p,d)){b.event.trigger("fancybox-cancel");h=false}else{h=true;b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");f.is(":visible")&&d.titlePosition!=="outside"&&f.css("height",f.height());l=o;p=q;d=e;if(d.overlayShow){u.css({"background-color":d.overlayColor,
9
- opacity:d.overlayOpacity,cursor:d.hideOnOverlayClick?"pointer":"auto",height:b(document).height()});if(!u.is(":visible")){if(M)b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"});u.show()}}else u.hide();i=X();s=d.title||"";y=0;n.empty().removeAttr("style").removeClass();if(d.titleShow!==false){if(b.isFunction(d.titleFormat))a=d.titleFormat(s,l,p,d);else a=s&&
10
- s.length?d.titlePosition=="float"?'<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">'+s+'</td><td id="fancybox-title-float-right"></td></tr></table>':'<div id="fancybox-title-'+d.titlePosition+'">'+s+"</div>":false;s=a;if(!(!s||s==="")){n.addClass("fancybox-title-"+d.titlePosition).html(s).appendTo("body").show();switch(d.titlePosition){case "inside":n.css({width:i.width-d.padding*2,marginLeft:d.padding,
11
- marginRight:d.padding});y=n.outerHeight(true);n.appendTo(D);i.height+=y;break;case "over":n.css({marginLeft:d.padding,width:i.width-d.padding*2,bottom:d.padding}).appendTo(D);break;case "float":n.css("left",parseInt((n.width()-i.width-40)/2,10)*-1).appendTo(f);break;default:n.css({width:i.width-d.padding*2,paddingLeft:d.padding,paddingRight:d.padding}).appendTo(f)}}}n.hide();if(f.is(":visible")){b(E.add(z).add(A)).hide();a=f.position();r={top:a.top,left:a.left,width:f.width(),height:f.height()};c=
12
- r.width==i.width&&r.height==i.height;j.fadeTo(d.changeFade,0.3,function(){var g=function(){j.html(m.contents()).fadeTo(d.changeFade,1,S)};b.event.trigger("fancybox-change");j.empty().removeAttr("filter").css({"border-width":d.padding,width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2});if(c)g();else{B.prop=0;b(B).animate({prop:1},{duration:d.changeSpeed,easing:d.easingChange,step:T,complete:g})}})}else{f.removeAttr("style");j.css("border-width",d.padding);if(d.transitionIn==
13
- "elastic"){r=V();j.html(m.contents());f.show();if(d.opacity)i.opacity=0;B.prop=0;b(B).animate({prop:1},{duration:d.speedIn,easing:d.easingIn,step:T,complete:S})}else{d.titlePosition=="inside"&&y>0&&n.show();j.css({width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2}).html(m.contents());f.css(i).fadeIn(d.transitionIn=="none"?0:d.speedIn,S)}}}},Y=function(){if(d.enableEscapeButton||d.enableKeyboardNav)b(document).bind("keydown.fb",function(a){if(a.keyCode==27&&d.enableEscapeButton){a.preventDefault();
14
- b.fancybox.close()}else if((a.keyCode==37||a.keyCode==39)&&d.enableKeyboardNav&&a.target.tagName!=="INPUT"&&a.target.tagName!=="TEXTAREA"&&a.target.tagName!=="SELECT"){a.preventDefault();b.fancybox[a.keyCode==37?"prev":"next"]()}});if(d.showNavArrows){if(d.cyclic&&l.length>1||p!==0)z.show();if(d.cyclic&&l.length>1||p!=l.length-1)A.show()}else{z.hide();A.hide()}},S=function(){if(!b.support.opacity){j.get(0).style.removeAttribute("filter");f.get(0).style.removeAttribute("filter")}e.autoDimensions&&
15
- j.css("height","auto");f.css("height","auto");s&&s.length&&n.show();d.showCloseButton&&E.show();Y();d.hideOnContentClick&&j.bind("click",b.fancybox.close);d.hideOnOverlayClick&&u.bind("click",b.fancybox.close);b(window).bind("resize.fb",b.fancybox.resize);d.centerOnScroll&&b(window).bind("scroll.fb",b.fancybox.center);if(d.type=="iframe")b('<iframe id="fancybox-frame" name="fancybox-frame'+(new Date).getTime()+'" frameborder="0" hspace="0" '+(b.browser.msie?'allowtransparency="true""':"")+' scrolling="'+
16
- e.scrolling+'" src="'+d.href+'"></iframe>').appendTo(j);f.show();h=false;b.fancybox.center();d.onComplete(l,p,d);var a,c;if(l.length-1>p){a=l[p+1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}if(p>0){a=l[p-1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}},T=function(a){var c={width:parseInt(r.width+(i.width-r.width)*a,10),height:parseInt(r.height+(i.height-r.height)*a,10),top:parseInt(r.top+(i.top-r.top)*a,10),left:parseInt(r.left+(i.left-r.left)*a,10)};if(typeof i.opacity!==
17
- "undefined")c.opacity=a<0.5?0.5:a;f.css(c);j.css({width:c.width-d.padding*2,height:c.height-y*a-d.padding*2})},U=function(){return[b(window).width()-d.margin*2,b(window).height()-d.margin*2,b(document).scrollLeft()+d.margin,b(document).scrollTop()+d.margin]},X=function(){var a=U(),c={},g=d.autoScale,k=d.padding*2;c.width=d.width.toString().indexOf("%")>-1?parseInt(a[0]*parseFloat(d.width)/100,10):d.width+k;c.height=d.height.toString().indexOf("%")>-1?parseInt(a[1]*parseFloat(d.height)/100,10):d.height+
18
- k;if(g&&(c.width>a[0]||c.height>a[1]))if(e.type=="image"||e.type=="swf"){g=d.width/d.height;if(c.width>a[0]){c.width=a[0];c.height=parseInt((c.width-k)/g+k,10)}if(c.height>a[1]){c.height=a[1];c.width=parseInt((c.height-k)*g+k,10)}}else{c.width=Math.min(c.width,a[0]);c.height=Math.min(c.height,a[1])}c.top=parseInt(Math.max(a[3]-20,a[3]+(a[1]-c.height-40)*0.5),10);c.left=parseInt(Math.max(a[2]-20,a[2]+(a[0]-c.width-40)*0.5),10);return c},V=function(){var a=e.orig?b(e.orig):false,c={};if(a&&a.length){c=
19
- a.offset();c.top+=parseInt(a.css("paddingTop"),10)||0;c.left+=parseInt(a.css("paddingLeft"),10)||0;c.top+=parseInt(a.css("border-top-width"),10)||0;c.left+=parseInt(a.css("border-left-width"),10)||0;c.width=a.width();c.height=a.height();c={width:c.width+d.padding*2,height:c.height+d.padding*2,top:c.top-d.padding-20,left:c.left-d.padding-20}}else{a=U();c={width:d.padding*2,height:d.padding*2,top:parseInt(a[3]+a[1]*0.5,10),left:parseInt(a[2]+a[0]*0.5,10)}}return c},Z=function(){if(t.is(":visible")){b("div",
20
- t).css("top",L*-40+"px");L=(L+1)%12}else clearInterval(K)};b.fn.fancybox=function(a){if(!b(this).length)return this;b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(c){c.preventDefault();if(!h){h=true;b(this).blur();o=[];q=0;c=b(this).attr("rel")||"";if(!c||c==""||c==="nofollow")o.push(this);else{o=b("a[rel="+c+"], area[rel="+c+"]");q=o.index(this)}I()}});return this};b.fancybox=function(a,c){var g;if(!h){h=true;g=typeof c!=="undefined"?
21
- c:{};o=[];q=parseInt(g.index,10)||0;if(b.isArray(a)){for(var k=0,C=a.length;k<C;k++)if(typeof a[k]=="object")b(a[k]).data("fancybox",b.extend({},g,a[k]));else a[k]=b({}).data("fancybox",b.extend({content:a[k]},g));o=jQuery.merge(o,a)}else{if(typeof a=="object")b(a).data("fancybox",b.extend({},g,a));else a=b({}).data("fancybox",b.extend({content:a},g));o.push(a)}if(q>o.length||q<0)q=0;I()}};b.fancybox.showActivity=function(){clearInterval(K);t.show();K=setInterval(Z,66)};b.fancybox.hideActivity=function(){t.hide()};
22
- b.fancybox.next=function(){return b.fancybox.pos(p+1)};b.fancybox.prev=function(){return b.fancybox.pos(p-1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a);o=l;if(a>-1&&a<l.length){q=a;I()}else if(d.cyclic&&l.length>1){q=a>=l.length?0:l.length-1;I()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");N();e.onCancel(o,q,e);h=false}};b.fancybox.close=function(){function a(){u.fadeOut("fast");n.empty().hide();f.hide();b.event.trigger("fancybox-cleanup");j.empty();d.onClosed(l,
23
- p,d);l=e=[];p=q=0;d=e={};h=false}if(!(h||f.is(":hidden"))){h=true;if(d&&false===d.onCleanup(l,p,d))h=false;else{N();b(E.add(z).add(A)).hide();b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");j.find("iframe").attr("src",M&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");d.titlePosition!=="inside"&&n.empty();f.stop();if(d.transitionOut=="elastic"){r=V();var c=f.position();i={top:c.top,left:c.left,width:f.width(),height:f.height()};
24
- if(d.opacity)i.opacity=1;n.empty().hide();B.prop=1;b(B).animate({prop:0},{duration:d.speedOut,easing:d.easingOut,step:T,complete:a})}else f.fadeOut(d.transitionOut=="none"?0:d.speedOut,a)}}};b.fancybox.resize=function(){u.is(":visible")&&u.css("height",b(document).height());b.fancybox.center(true)};b.fancybox.center=function(a){var c,g;if(!h){g=a===true?1:0;c=U();!g&&(f.width()>c[0]||f.height()>c[1])||f.stop().animate({top:parseInt(Math.max(c[3]-20,c[3]+(c[1]-j.height()-40)*0.5-d.padding)),left:parseInt(Math.max(c[2]-
25
- 20,c[2]+(c[0]-j.width()-40)*0.5-d.padding))},typeof a=="number"?a:200)}};b.fancybox.init=function(){if(!b("#fancybox-wrap").length){b("body").append(m=b('<div id="fancybox-tmp"></div>'),t=b('<div id="fancybox-loading"><div></div></div>'),u=b('<div id="fancybox-overlay"></div>'),f=b('<div id="fancybox-wrap"></div>'));D=b('<div id="fancybox-outer"></div>').append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>').appendTo(f);
26
- D.append(j=b('<div id="fancybox-content"></div>'),E=b('<a id="fancybox-close"></a>'),n=b('<div id="fancybox-title"></div>'),z=b('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),A=b('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));E.click(b.fancybox.close);t.click(b.fancybox.cancel);z.click(function(a){a.preventDefault();b.fancybox.prev()});A.click(function(a){a.preventDefault();b.fancybox.next()});
27
- b.fn.mousewheel&&f.bind("mousewheel.fb",function(a,c){if(h)a.preventDefault();else if(b(a.target).get(0).clientHeight==0||b(a.target).get(0).scrollHeight===b(a.target).get(0).clientHeight){a.preventDefault();b.fancybox[c>0?"prev":"next"]()}});b.support.opacity||f.addClass("fancybox-ie");if(M){t.addClass("fancybox-ie6");f.addClass("fancybox-ie6");b('<iframe id="fancybox-hide-sel-frame" src="'+(/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank")+'" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(D)}}};
28
- b.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing",
29
- easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};b(document).ready(function(){b.fancybox.init()})})(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apps/fancybox/jquery.fancybox-1.3.4.pack.js DELETED
@@ -1,46 +0,0 @@
1
- /*
2
- * FancyBox - jQuery Plugin
3
- * Simple and fancy lightbox alternative
4
- *
5
- * Examples and documentation at: http://fancybox.net
6
- *
7
- * Copyright (c) 2008 - 2010 Janis Skarnelis
8
- * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
9
- *
10
- * Version: 1.3.4 (11/11/2010)
11
- * Requires: jQuery v1.3+
12
- *
13
- * Dual licensed under the MIT and GPL licenses:
14
- * http://www.opensource.org/licenses/mit-license.php
15
- * http://www.gnu.org/licenses/gpl.html
16
- */
17
-
18
- ;(function(b){var m,t,u,f,D,j,E,n,z,A,q=0,e={},o=[],p=0,d={},l=[],G=null,v=new Image,J=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,W=/[^\.]\.(swf)\s*$/i,K,L=1,y=0,s="",r,i,h=false,B=b.extend(b("<div/>")[0],{prop:0}),M=b.browser.msie&&b.browser.version<7&&!window.XMLHttpRequest,N=function(){t.hide();v.onerror=v.onload=null;G&&G.abort();m.empty()},O=function(){if(false===e.onError(o,q,e)){t.hide();h=false}else{e.titleShow=false;e.width="auto";e.height="auto";m.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');
19
- F()}},I=function(){var a=o[q],c,g,k,C,P,w;N();e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));w=e.onStart(o,q,e);if(w===false)h=false;else{if(typeof w=="object")e=b.extend(e,w);k=e.title||(a.nodeName?b(a).attr("title"):a.title)||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(k===""&&e.orig&&e.titleFromAlt)k=e.orig.attr("alt");c=e.href||(a.nodeName?b(a).attr("href"):a.href)||null;if(/^(?:javascript)/i.test(c)||
20
- c=="#")c=null;if(e.type){g=e.type;if(!c)c=e.content}else if(e.content)g="html";else if(c)g=c.match(J)?"image":c.match(W)?"swf":b(a).hasClass("iframe")?"iframe":c.indexOf("#")===0?"inline":"ajax";if(g){if(g=="inline"){a=c.substr(c.indexOf("#"));g=b(a).length>0?"inline":"ajax"}e.type=g;e.href=c;e.title=k;if(e.autoDimensions)if(e.type=="html"||e.type=="inline"||e.type=="ajax"){e.width="auto";e.height="auto"}else e.autoDimensions=false;if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick=
21
- false;e.enableEscapeButton=false;e.showCloseButton=false}e.padding=parseInt(e.padding,10);e.margin=parseInt(e.margin,10);m.css("padding",e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(j.children())});switch(g){case "html":m.html(e.content);F();break;case "inline":if(b(a).parent().is("#fancybox-content")===true){h=false;break}b('<div class="fancybox-inline-tmp" />').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(j.children())}).bind("fancybox-cancel",
22
- function(){b(this).replaceWith(m.children())});b(a).appendTo(m);F();break;case "image":h=false;b.fancybox.showActivity();v=new Image;v.onerror=function(){O()};v.onload=function(){h=true;v.onerror=v.onload=null;e.width=v.width;e.height=v.height;b("<img />").attr({id:"fancybox-img",src:v.src,alt:e.title}).appendTo(m);Q()};v.src=c;break;case "swf":e.scrolling="no";C='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+e.width+'" height="'+e.height+'"><param name="movie" value="'+c+
23
- '"></param>';P="";b.each(e.swf,function(x,H){C+='<param name="'+x+'" value="'+H+'"></param>';P+=" "+x+'="'+H+'"'});C+='<embed src="'+c+'" type="application/x-shockwave-flash" width="'+e.width+'" height="'+e.height+'"'+P+"></embed></object>";m.html(C);F();break;case "ajax":h=false;b.fancybox.showActivity();e.ajax.win=e.ajax.success;G=b.ajax(b.extend({},e.ajax,{url:c,data:e.ajax.data||{},error:function(x){x.status>0&&O()},success:function(x,H,R){if((typeof R=="object"?R:G).status==200){if(typeof e.ajax.win==
24
- "function"){w=e.ajax.win(c,x,H,R);if(w===false){t.hide();return}else if(typeof w=="string"||typeof w=="object")x=w}m.html(x);F()}}}));break;case "iframe":Q()}}else O()}},F=function(){var a=e.width,c=e.height;a=a.toString().indexOf("%")>-1?parseInt((b(window).width()-e.margin*2)*parseFloat(a)/100,10)+"px":a=="auto"?"auto":a+"px";c=c.toString().indexOf("%")>-1?parseInt((b(window).height()-e.margin*2)*parseFloat(c)/100,10)+"px":c=="auto"?"auto":c+"px";m.wrapInner('<div style="width:'+a+";height:"+c+
25
- ";overflow: "+(e.scrolling=="auto"?"auto":e.scrolling=="yes"?"scroll":"hidden")+';position:relative;"></div>');e.width=m.width();e.height=m.height();Q()},Q=function(){var a,c;t.hide();if(f.is(":visible")&&false===d.onCleanup(l,p,d)){b.event.trigger("fancybox-cancel");h=false}else{h=true;b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");f.is(":visible")&&d.titlePosition!=="outside"&&f.css("height",f.height());l=o;p=q;d=e;if(d.overlayShow){u.css({"background-color":d.overlayColor,
26
- opacity:d.overlayOpacity,cursor:d.hideOnOverlayClick?"pointer":"auto",height:b(document).height()});if(!u.is(":visible")){M&&b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"});u.show()}}else u.hide();i=X();s=d.title||"";y=0;n.empty().removeAttr("style").removeClass();if(d.titleShow!==false){if(b.isFunction(d.titleFormat))a=d.titleFormat(s,l,p,d);else a=s&&s.length?
27
- d.titlePosition=="float"?'<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">'+s+'</td><td id="fancybox-title-float-right"></td></tr></table>':'<div id="fancybox-title-'+d.titlePosition+'">'+s+"</div>":false;s=a;if(!(!s||s==="")){n.addClass("fancybox-title-"+d.titlePosition).html(s).appendTo("body").show();switch(d.titlePosition){case "inside":n.css({width:i.width-d.padding*2,marginLeft:d.padding,marginRight:d.padding});
28
- y=n.outerHeight(true);n.appendTo(D);i.height+=y;break;case "over":n.css({marginLeft:d.padding,width:i.width-d.padding*2,bottom:d.padding}).appendTo(D);break;case "float":n.css("left",parseInt((n.width()-i.width-40)/2,10)*-1).appendTo(f);break;default:n.css({width:i.width-d.padding*2,paddingLeft:d.padding,paddingRight:d.padding}).appendTo(f)}}}n.hide();if(f.is(":visible")){b(E.add(z).add(A)).hide();a=f.position();r={top:a.top,left:a.left,width:f.width(),height:f.height()};c=r.width==i.width&&r.height==
29
- i.height;j.fadeTo(d.changeFade,0.3,function(){var g=function(){j.html(m.contents()).fadeTo(d.changeFade,1,S)};b.event.trigger("fancybox-change");j.empty().removeAttr("filter").css({"border-width":d.padding,width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2});if(c)g();else{B.prop=0;b(B).animate({prop:1},{duration:d.changeSpeed,easing:d.easingChange,step:T,complete:g})}})}else{f.removeAttr("style");j.css("border-width",d.padding);if(d.transitionIn=="elastic"){r=V();j.html(m.contents());
30
- f.show();if(d.opacity)i.opacity=0;B.prop=0;b(B).animate({prop:1},{duration:d.speedIn,easing:d.easingIn,step:T,complete:S})}else{d.titlePosition=="inside"&&y>0&&n.show();j.css({width:i.width-d.padding*2,height:e.autoDimensions?"auto":i.height-y-d.padding*2}).html(m.contents());f.css(i).fadeIn(d.transitionIn=="none"?0:d.speedIn,S)}}}},Y=function(){if(d.enableEscapeButton||d.enableKeyboardNav)b(document).bind("keydown.fb",function(a){if(a.keyCode==27&&d.enableEscapeButton){a.preventDefault();b.fancybox.close()}else if((a.keyCode==
31
- 37||a.keyCode==39)&&d.enableKeyboardNav&&a.target.tagName!=="INPUT"&&a.target.tagName!=="TEXTAREA"&&a.target.tagName!=="SELECT"){a.preventDefault();b.fancybox[a.keyCode==37?"prev":"next"]()}});if(d.showNavArrows){if(d.cyclic&&l.length>1||p!==0)z.show();if(d.cyclic&&l.length>1||p!=l.length-1)A.show()}else{z.hide();A.hide()}},S=function(){if(!b.support.opacity){j.get(0).style.removeAttribute("filter");f.get(0).style.removeAttribute("filter")}e.autoDimensions&&j.css("height","auto");f.css("height","auto");
32
- s&&s.length&&n.show();d.showCloseButton&&E.show();Y();d.hideOnContentClick&&j.bind("click",b.fancybox.close);d.hideOnOverlayClick&&u.bind("click",b.fancybox.close);b(window).bind("resize.fb",b.fancybox.resize);d.centerOnScroll&&b(window).bind("scroll.fb",b.fancybox.center);if(d.type=="iframe")b('<iframe id="fancybox-frame" name="fancybox-frame'+(new Date).getTime()+'" frameborder="0" hspace="0" '+(b.browser.msie?'allowtransparency="true""':"")+' scrolling="'+e.scrolling+'" src="'+d.href+'"></iframe>').appendTo(j);
33
- f.show();h=false;b.fancybox.center();d.onComplete(l,p,d);var a,c;if(l.length-1>p){a=l[p+1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}if(p>0){a=l[p-1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}},T=function(a){var c={width:parseInt(r.width+(i.width-r.width)*a,10),height:parseInt(r.height+(i.height-r.height)*a,10),top:parseInt(r.top+(i.top-r.top)*a,10),left:parseInt(r.left+(i.left-r.left)*a,10)};if(typeof i.opacity!=="undefined")c.opacity=a<0.5?0.5:a;f.css(c);
34
- j.css({width:c.width-d.padding*2,height:c.height-y*a-d.padding*2})},U=function(){return[b(window).width()-d.margin*2,b(window).height()-d.margin*2,b(document).scrollLeft()+d.margin,b(document).scrollTop()+d.margin]},X=function(){var a=U(),c={},g=d.autoScale,k=d.padding*2;c.width=d.width.toString().indexOf("%")>-1?parseInt(a[0]*parseFloat(d.width)/100,10):d.width+k;c.height=d.height.toString().indexOf("%")>-1?parseInt(a[1]*parseFloat(d.height)/100,10):d.height+k;if(g&&(c.width>a[0]||c.height>a[1]))if(e.type==
35
- "image"||e.type=="swf"){g=d.width/d.height;if(c.width>a[0]){c.width=a[0];c.height=parseInt((c.width-k)/g+k,10)}if(c.height>a[1]){c.height=a[1];c.width=parseInt((c.height-k)*g+k,10)}}else{c.width=Math.min(c.width,a[0]);c.height=Math.min(c.height,a[1])}c.top=parseInt(Math.max(a[3]-20,a[3]+(a[1]-c.height-40)*0.5),10);c.left=parseInt(Math.max(a[2]-20,a[2]+(a[0]-c.width-40)*0.5),10);return c},V=function(){var a=e.orig?b(e.orig):false,c={};if(a&&a.length){c=a.offset();c.top+=parseInt(a.css("paddingTop"),
36
- 10)||0;c.left+=parseInt(a.css("paddingLeft"),10)||0;c.top+=parseInt(a.css("border-top-width"),10)||0;c.left+=parseInt(a.css("border-left-width"),10)||0;c.width=a.width();c.height=a.height();c={width:c.width+d.padding*2,height:c.height+d.padding*2,top:c.top-d.padding-20,left:c.left-d.padding-20}}else{a=U();c={width:d.padding*2,height:d.padding*2,top:parseInt(a[3]+a[1]*0.5,10),left:parseInt(a[2]+a[0]*0.5,10)}}return c},Z=function(){if(t.is(":visible")){b("div",t).css("top",L*-40+"px");L=(L+1)%12}else clearInterval(K)};
37
- b.fn.fancybox=function(a){if(!b(this).length)return this;b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(c){c.preventDefault();if(!h){h=true;b(this).blur();o=[];q=0;c=b(this).attr("rel")||"";if(!c||c==""||c==="nofollow")o.push(this);else{o=b("a[rel="+c+"], area[rel="+c+"]");q=o.index(this)}I()}});return this};b.fancybox=function(a,c){var g;if(!h){h=true;g=typeof c!=="undefined"?c:{};o=[];q=parseInt(g.index,10)||0;if(b.isArray(a)){for(var k=
38
- 0,C=a.length;k<C;k++)if(typeof a[k]=="object")b(a[k]).data("fancybox",b.extend({},g,a[k]));else a[k]=b({}).data("fancybox",b.extend({content:a[k]},g));o=jQuery.merge(o,a)}else{if(typeof a=="object")b(a).data("fancybox",b.extend({},g,a));else a=b({}).data("fancybox",b.extend({content:a},g));o.push(a)}if(q>o.length||q<0)q=0;I()}};b.fancybox.showActivity=function(){clearInterval(K);t.show();K=setInterval(Z,66)};b.fancybox.hideActivity=function(){t.hide()};b.fancybox.next=function(){return b.fancybox.pos(p+
39
- 1)};b.fancybox.prev=function(){return b.fancybox.pos(p-1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a);o=l;if(a>-1&&a<l.length){q=a;I()}else if(d.cyclic&&l.length>1){q=a>=l.length?0:l.length-1;I()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");N();e.onCancel(o,q,e);h=false}};b.fancybox.close=function(){function a(){u.fadeOut("fast");n.empty().hide();f.hide();b.event.trigger("fancybox-cleanup");j.empty();d.onClosed(l,p,d);l=e=[];p=q=0;d=e={};h=false}if(!(h||f.is(":hidden"))){h=
40
- true;if(d&&false===d.onCleanup(l,p,d))h=false;else{N();b(E.add(z).add(A)).hide();b(j.add(u)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");j.find("iframe").attr("src",M&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");d.titlePosition!=="inside"&&n.empty();f.stop();if(d.transitionOut=="elastic"){r=V();var c=f.position();i={top:c.top,left:c.left,width:f.width(),height:f.height()};if(d.opacity)i.opacity=1;n.empty().hide();B.prop=1;
41
- b(B).animate({prop:0},{duration:d.speedOut,easing:d.easingOut,step:T,complete:a})}else f.fadeOut(d.transitionOut=="none"?0:d.speedOut,a)}}};b.fancybox.resize=function(){u.is(":visible")&&u.css("height",b(document).height());b.fancybox.center(true)};b.fancybox.center=function(a){var c,g;if(!h){g=a===true?1:0;c=U();!g&&(f.width()>c[0]||f.height()>c[1])||f.stop().animate({top:parseInt(Math.max(c[3]-20,c[3]+(c[1]-j.height()-40)*0.5-d.padding)),left:parseInt(Math.max(c[2]-20,c[2]+(c[0]-j.width()-40)*0.5-
42
- d.padding))},typeof a=="number"?a:200)}};b.fancybox.init=function(){if(!b("#fancybox-wrap").length){b("body").append(m=b('<div id="fancybox-tmp"></div>'),t=b('<div id="fancybox-loading"><div></div></div>'),u=b('<div id="fancybox-overlay"></div>'),f=b('<div id="fancybox-wrap"></div>'));D=b('<div id="fancybox-outer"></div>').append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>').appendTo(f);
43
- D.append(j=b('<div id="fancybox-content"></div>'),E=b('<a id="fancybox-close"></a>'),n=b('<div id="fancybox-title"></div>'),z=b('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),A=b('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));E.click(b.fancybox.close);t.click(b.fancybox.cancel);z.click(function(a){a.preventDefault();b.fancybox.prev()});A.click(function(a){a.preventDefault();b.fancybox.next()});
44
- b.fn.mousewheel&&f.bind("mousewheel.fb",function(a,c){if(h)a.preventDefault();else if(b(a.target).get(0).clientHeight==0||b(a.target).get(0).scrollHeight===b(a.target).get(0).clientHeight){a.preventDefault();b.fancybox[c>0?"prev":"next"]()}});b.support.opacity||f.addClass("fancybox-ie");if(M){t.addClass("fancybox-ie6");f.addClass("fancybox-ie6");b('<iframe id="fancybox-hide-sel-frame" src="'+(/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank")+'" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(D)}}};
45
- b.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing",
46
- easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};b(document).ready(function(){b.fancybox.init()})})(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apps/fancybox/jquery.mousewheel-3.0.4.pack.js DELETED
@@ -1,14 +0,0 @@
1
- /*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
2
- * Licensed under the MIT License (LICENSE.txt).
3
- *
4
- * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
5
- * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6
- * Thanks to: Seamus Leahy for adding deltaX and deltaY
7
- *
8
- * Version: 3.0.4
9
- *
10
- * Requires: 1.2.2+
11
- */
12
-
13
- (function(d){function g(a){var b=a||window.event,i=[].slice.call(arguments,1),c=0,h=0,e=0;a=d.event.fix(b);a.type="mousewheel";if(a.wheelDelta)c=a.wheelDelta/120;if(a.detail)c=-a.detail/3;e=c;if(b.axis!==undefined&&b.axis===b.HORIZONTAL_AXIS){e=0;h=-1*c}if(b.wheelDeltaY!==undefined)e=b.wheelDeltaY/120;if(b.wheelDeltaX!==undefined)h=-1*b.wheelDeltaX/120;i.unshift(a,c,h,e);return d.event.handle.apply(this,i)}var f=["DOMMouseScroll","mousewheel"];d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=
14
- f.length;a;)this.addEventListener(f[--a],g,false);else this.onmousewheel=g},teardown:function(){if(this.removeEventListener)for(var a=f.length;a;)this.removeEventListener(f[--a],g,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apps/jquery-tmpl/.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ build/dist
2
+ docs
3
+ .project
4
+ *~
5
+ *.diff
6
+ *.patch
7
+ .DS_Store
apps/jquery-tmpl/README.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # jQuery Templates plugin v1.0.0pre.
2
+
3
+ _Note: This plugin is currently in beta form and may change significantly before version 1.0 is released. See tagged versions for stable Beta releases. Requires jquery version 1.4.2._
4
+
5
+ jQuery templates contain markup with binding expressions ('Template tags'). Templates are applied to data objects or arrays, and rendered into the HTML DOM
6
+
7
+ Documentation for the _jQuery Templates_ plugin can be found on the jQuery documentation site:
8
+ [http://api.jquery.com/category/plugins/templates/] (http://api.jquery.com/category/plugins/templates)
9
+
10
+ See also [http://www.borismoore.com/2010/10/jquery-templates-is-now-official-jquery.html] (http://www.borismoore.com/2010/10/jquery-templates-is-now-official-jquery.html) for more background.
11
+
12
+ Live versions of demos from this repository can be found at [http://jquery.github.com/jquery-tmpl/demos/step-by-step.html] (http://jquery.github.com/jquery-tmpl/demos/step-by-step.html).
13
+
14
+ <p>The beta1 version of jQuery Templates is available on CDN at:
15
+ <ul>
16
+ <li><a href="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js">http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js</a></li>
17
+ <li><a href="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js">http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js</a></li>
18
+ </ul></p>
19
+
apps/jquery-tmpl/demos/movies/PagesCore/movies.html ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using templates for a more complete and
4
+ realistic scenario.
5
+
6
+ It uses the NetFlix OData JSONP services as a source of data.
7
+
8
+ This version of the movies sample demo uses the
9
+ $( templateSelector ).tmpl( data ).appendTo( targetSelector )
10
+ pattern, and does not use the tmplPlus features (.tmplCmd, or the rendered event).
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml">
13
+ <head>
14
+ <title>jQuery + OData + Netflix Catalog API</title>
15
+ <link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
16
+ <link href="../css/movies.css" rel="stylesheet" type="text/css" />
17
+ </head>
18
+ <body>
19
+ <div id="pageBody">
20
+ <h1>Netflix: Book a Movie...</h1>
21
+
22
+ <ul id="genres">
23
+ <li class="selected">Cartoons</li>
24
+ <li>Drama</li>
25
+ <li>Foreign</li>
26
+ <li>Action Classics</li>
27
+ <li>Horror</li>
28
+ <li>Sci-Fi Cult Classics</li>
29
+ </ul>
30
+
31
+ <div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>
32
+
33
+ <div id="movieList"></div>
34
+ <table id="bookingsList">
35
+ <tbody><tr class="cart"><td class="cart-false" colspan="4">
36
+ <span class="text">0 items in Cart...</span>
37
+ </td></tr></tbody>
38
+ </table>
39
+ <br/>
40
+ </div>
41
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
42
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
43
+ <script src="../components/jquery.pager.js" type="text/javascript"></script>
44
+ <script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>
45
+
46
+ <script id="movieTmpl" type="text/x-jquery-tmpl">
47
+ <div>
48
+ <div><img src="${BoxArt.LargeUrl}" /> </div>
49
+ <strong>${Name}</strong>
50
+ <p>{{html Synopsis}}</p>
51
+ <input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
52
+ <br/>
53
+ </div>
54
+ </script>
55
+
56
+ <script id="cartTmpl" type="text/x-jquery-tmpl">
57
+ <td class="cart-${!!count}" colspan="4">
58
+ <span class="text">${count} items in Cart...</span>
59
+ {{if count}}
60
+ <span id="submit">Checkout</span>
61
+ <span id="cancel">Remove All</span>
62
+ {{if count>1}}
63
+ <span id="sort"><span id="sortBtn">Sort</span>:
64
+ <select>
65
+ <option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
66
+ <option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
67
+ <option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
68
+ </select>
69
+ </span>
70
+ {{/if}}
71
+ </select>
72
+ {{/if}}
73
+ </td>
74
+ </script>
75
+
76
+ <script id="bookingTitleTmpl" type="text/x-jquery-tmpl">
77
+ <tr class="bookingTitle${$item.mode}">
78
+ <td>${movie.Name}</td><td>${movieTheater}</td>
79
+ <td>${formatDate(date)}</td>
80
+ <td>
81
+ ${quantity}
82
+ <span class="ui-icon close"></span>
83
+ </td>
84
+ </tr>
85
+ </script>
86
+
87
+ <script id="bookingEditTmpl" type="text/x-jquery-tmpl">
88
+ {{tmpl($data, {mode: "Edit"}) "#bookingTitleTmpl"}}
89
+ <tr class="bookingEdit">
90
+ <td colspan="4">
91
+ <div class="fields">
92
+ <span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
93
+ <span>Date: </span><input class="date" type="text" value="${formatDate(date)}" /><br/>
94
+ <span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
95
+ </div>
96
+ <div><img src="${movie.BoxArt.LargeUrl}" /></div>
97
+ </td>
98
+ </tr>
99
+ </script>
100
+
101
+ <script type="text/javascript">
102
+ var genre="Cartoons", pageIndex = 1, pageSize = 3, pageCount = 0,
103
+ cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = {}, selectedBooking;
104
+
105
+ getMovies( pageIndex );
106
+
107
+ $( "#genres li" ).click( selectGenre );
108
+
109
+ $( ".cart" )
110
+ .delegate( "select", "change", sort )
111
+ .delegate( "#sortBtn", "click", sort )
112
+ .delegate( "#submit", "click", function() {
113
+ alert( cart.count + " bookings submitted for payment...");
114
+ removeBookings();
115
+ })
116
+ .delegate( "#cancel", "click", function() {
117
+ removeBookings();
118
+ })
119
+ .empty();
120
+
121
+ $( "#cartTmpl" )
122
+ .tmpl( cart )
123
+ .appendTo( ".cart", cart );
124
+
125
+ var cartTmplItem = $( ".cart td" ).tmplItem();
126
+
127
+ function selectGenre() {
128
+ $( "#genres li" ).removeClass( "selected" );
129
+ $( this ).addClass( "selected" );
130
+
131
+ pageIndex = 1;
132
+ genre = encodeURI( $(this).text() );
133
+ getMovies( pageIndex );
134
+ }
135
+
136
+ function sort() {
137
+ var compare = compareName, reverse = false, data = [];
138
+ cart.sortBy = $( "#sort select" ).val();
139
+ switch ( $( "#sort select" ).val() ) {
140
+ case "1":
141
+ reverse = true;
142
+ break;
143
+ case "2":
144
+ compare = compareDate;
145
+ break;
146
+ }
147
+
148
+ for ( var item in cart.bookings ) {
149
+ data.push( cart.bookings[item] );
150
+ }
151
+ data = data.sort( compare );
152
+
153
+ for ( var i = 0, l = data.length; i < l; i++ ) {
154
+ $( bookingTmplItems[data[i].movie.Id].nodes ).appendTo( "#bookingsList" );
155
+ }
156
+
157
+ function compareName( a, b ) {
158
+ return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
159
+ }
160
+ function compareDate( a, b ) {
161
+ return a.date - b.date;
162
+ }
163
+ }
164
+
165
+ function getMovies( index ) {
166
+ var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
167
+ "?$format=json" +
168
+ "&$inlinecount=allpages" + // get total number of records
169
+ "&$skip=" + (index-1) * pageSize + // skip to first record of page
170
+ "&$top=" + pageSize; // page size
171
+
172
+ pageIndex = index;
173
+
174
+ $( "#movieList" )
175
+ .fadeOut( "medium", function () {
176
+ $.ajax({
177
+ dataType: "jsonp",
178
+ url: query,
179
+ jsonp: "$callback",
180
+ success: showMovies
181
+ });
182
+ });
183
+ }
184
+
185
+ function showMovies( data ) {
186
+ pageCount = Math.ceil( data.d.__count/pageSize ),
187
+ movies = data.d.results;
188
+
189
+ $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });
190
+
191
+ $( "#movieList" ).empty();
192
+
193
+ $( "#movieTmpl" )
194
+ // Render movies using the movieTemplate
195
+ .tmpl( movies )
196
+
197
+ // Display rendered movies in the movieList container
198
+ .appendTo( "#movieList" )
199
+
200
+ // Animate
201
+ .find( "div" ).fadeIn( 4000 ).end()
202
+
203
+ // Add click handler
204
+ .find( ".buyButton" ).click( function() {
205
+ buyTickets( $(this).tmplItem().data );
206
+ });
207
+
208
+ $( "#movieList" ).fadeIn( "medium" )
209
+ }
210
+
211
+ function buyTickets( movie ) {
212
+ // Add item to cart
213
+ var booking = cart.bookings[movie.Id];
214
+ if ( booking ) {
215
+ booking.quantity++;
216
+ } else {
217
+ cart.count++;
218
+ cartTmplItem.update();
219
+ booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
220
+ }
221
+ selectBooking( booking );
222
+ }
223
+
224
+ function selectBooking( booking ) {
225
+ if ( selectedBooking ) {
226
+ if ( selectedBooking === booking ) {
227
+ updateBooking( bookingTmplItems[selectedBooking.movie.Id]);
228
+ return;
229
+ }
230
+ // Collapse previously selected booking, and switch to non-edit view
231
+ var oldSelected = selectedBooking;
232
+ $( "div", bookingTmplItems[oldSelected.movie.Id].nodes ).animate( { height: 0 }, 500, function() {
233
+ switchView( oldSelected );
234
+ });
235
+ }
236
+ selectedBooking = booking;
237
+ if ( !booking ) {
238
+ return;
239
+ }
240
+ if ( cart.bookings[booking.movie.Id] ) {
241
+ switchView( booking, true );
242
+ } else {
243
+ cart.bookings[booking.movie.Id] = booking;
244
+
245
+ var bookingNode = $( "#bookingEditTmpl" )
246
+
247
+ // Render the booking for the chosen movie using the bookingEditTemplate
248
+ .tmpl( booking, { animate: true } )
249
+
250
+ // Append the rendered booking to the bookings list
251
+ .appendTo( "#bookingsList" )
252
+
253
+ // Get the 2nd <tr> of the appended booking
254
+ .last()[0];
255
+
256
+ // Get the template item for the 2nd <tr>, which is the template item for the "bookingEditTmpl" template
257
+ var newItem = $.tmplItem( bookingNode );
258
+ bookingTmplItems[booking.movie.Id] = newItem;
259
+
260
+ // Attach handlers etc. on the rendered template.
261
+ bookingEditRendered( newItem );
262
+ }
263
+ }
264
+
265
+ function bookingEditRendered( item ) {
266
+ var data = item.data, nodes = item.nodes;
267
+
268
+ $( nodes[0] ).click( function() {
269
+ selectBooking();
270
+ });
271
+
272
+ $( ".close", nodes ).click( removeBooking );
273
+
274
+ $( ".date", nodes ).change( function() {
275
+ data.date = $(this).datepicker( "getDate" );
276
+ updateBooking( item );
277
+ })
278
+ .datepicker({ dateFormat: "DD, d MM, yy" });
279
+
280
+ $( ".quantity", nodes ).change( function() {
281
+ data.quantity = $(this).val();
282
+ updateBooking( item );
283
+ });
284
+
285
+ $( ".theater", nodes ).change( function() {
286
+ data.movieTheater = $(this).val();
287
+ updateBooking( item );
288
+ });
289
+
290
+ if ( item.animate ) {
291
+ $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
292
+ }
293
+ }
294
+
295
+ function bookingRendered( item ) {
296
+ $( item.nodes ).click( function() {
297
+ selectBooking( item.data );
298
+ });
299
+ $( ".close", item.nodes ).click( removeBooking );
300
+ }
301
+
302
+ function switchView( booking, edit ) {
303
+ if ( !booking ) {
304
+ return;
305
+ }
306
+ var item = bookingTmplItems[booking.movie.Id],
307
+ tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template();
308
+ if ( item.tmpl !== tmpl) {
309
+ item.tmpl = tmpl;
310
+ item.update();
311
+ (edit ? bookingEditRendered : bookingRendered)( item );
312
+ }
313
+ }
314
+
315
+ function updateBooking( item ) {
316
+ item.animate = false;
317
+ item.update();
318
+ (item.data === selectedBooking ? bookingEditRendered : bookingRendered)( item );
319
+ item.animate = true;
320
+ }
321
+
322
+ function removeBooking() {
323
+ var booking = $.tmplItem(this).data;
324
+ if ( booking === selectedBooking ) {
325
+ selectedBooking = null;
326
+ }
327
+ delete cart.bookings[booking.movie.Id];
328
+ cart.count--;
329
+ cartTmplItem.update();
330
+ $( bookingTmplItems[booking.movie.Id].nodes ).remove();
331
+ delete bookingTmplItems[booking.movie.Id];
332
+ return false;
333
+ }
334
+
335
+ function removeBookings() {
336
+ for ( var item in bookingTmplItems ) {
337
+ $( bookingTmplItems[item].nodes ).remove();
338
+ delete bookingTmplItems[item];
339
+ }
340
+ bookingTmplItems = {};
341
+ cart.count = 0;
342
+ cart.bookings = {};
343
+ selectedBooking = null;
344
+ cartTmplItem.update();
345
+ }
346
+
347
+ function formatDate( date ) {
348
+ return date.toLocaleDateString();
349
+ }
350
+ </script>
351
+
352
+ </body>
353
+ </html>
apps/jquery-tmpl/demos/movies/PagesCore/moviesNoGlobals.html ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using templates for a more complete and
4
+ realistic scenario.
5
+
6
+ It uses the NetFlix OData JSONP services as a source of data.
7
+
8
+ This version of the movies sample demo uses the
9
+ $( templateSelector ).tmpl( data ).appendTo( targetSelector )
10
+ pattern, and does not use the tmplPlus features (.tmplCmd, or the rendered event).
11
+
12
+ Notice that in the example there are no global variables:
13
+ Code is wrapped in a function closure: (function($) {...})(jQuery);
14
+ The formatDate function within the closure is called from within the
15
+ template by passing it in with options:
16
+ $( "#bookingEditTmpl" ).tmpl( booking, { formatDate: formatDate } )
17
+ and accessing it on the template item, $item:
18
+ ${$item.formatDate()}.
19
+ -->
20
+ <html xmlns="http://www.w3.org/1999/xhtml">
21
+ <head>
22
+ <title>jQuery + OData + Netflix Catalog API</title>
23
+ <link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
24
+ <link href="../css/movies.css" rel="stylesheet" type="text/css" />
25
+ </head>
26
+ <body>
27
+ <div id="pageBody">
28
+ <h1>Netflix: Book a Movie...</h1>
29
+
30
+ <ul id="genres">
31
+ <li class="selected">Cartoons</li>
32
+ <li>Drama</li>
33
+ <li>Foreign</li>
34
+ <li>Action Classics</li>
35
+ <li>Horror</li>
36
+ <li>Sci-Fi Cult Classics</li>
37
+ </ul>
38
+
39
+ <div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>
40
+
41
+ <div id="movieList"></div>
42
+ <table id="bookingsList">
43
+ <tbody><tr class="cart"><td class="cart-false" colspan="4">
44
+ <span class="text">0 items in Cart...</span>
45
+ </td></tr></tbody>
46
+ </table>
47
+ <br/>
48
+ </div>
49
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
50
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
51
+ <script src="../components/jquery.pager.js" type="text/javascript"></script>
52
+ <script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>
53
+
54
+ <script id="movieTmpl" type="text/x-jquery-tmpl">
55
+ <div>
56
+ <div><img src="${BoxArt.LargeUrl}" /> </div>
57
+ <strong>${Name}</strong>
58
+ <p>{{html Synopsis}}</p>
59
+ <input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
60
+ <br/>
61
+ </div>
62
+ </script>
63
+
64
+ <script id="cartTmpl" type="text/x-jquery-tmpl">
65
+ <td class="cart-${!!count}" colspan="4">
66
+ <span class="text">${count} items in Cart...</span>
67
+ {{if count}}
68
+ <span id="submit">Checkout</span>
69
+ <span id="cancel">Remove All</span>
70
+ {{if count>1}}
71
+ <span id="sort"><span id="sortBtn">Sort</span>:
72
+ <select>
73
+ <option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
74
+ <option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
75
+ <option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
76
+ </select>
77
+ </span>
78
+ {{/if}}
79
+ </select>
80
+ {{/if}}
81
+ </td>
82
+ </script>
83
+
84
+ <script id="bookingTitleTmpl" type="text/x-jquery-tmpl">
85
+ <tr class="bookingTitle${$item.mode}">
86
+ <td>${movie.Name}</td><td>${movieTheater}</td>
87
+ <td>${$item.formatDate()}</td>
88
+ <td>
89
+ ${quantity}
90
+ <span class="ui-icon close"></span>
91
+ </td>
92
+ </tr>
93
+ </script>
94
+
95
+ <script id="bookingEditTmpl" type="text/x-jquery-tmpl">
96
+ {{tmpl($data, { mode: "Edit", formatDate: $item.formatDate }) "#bookingTitleTmpl"}}
97
+ <tr class="bookingEdit">
98
+ <td colspan="4">
99
+ <div class="fields">
100
+ <span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
101
+ <span>Date: </span><input class="date" type="text" value="${$item.formatDate()}" /><br/>
102
+ <span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
103
+ </div>
104
+ <div><img src="${movie.BoxArt.LargeUrl}" /></div>
105
+ </td>
106
+ </tr>
107
+ </script>
108
+
109
+ <script type="text/javascript">
110
+ (function($) {
111
+ var genre="Cartoons", pageIndex = 1, pageSize = 3, pageCount = 0,
112
+ cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = {}, selectedBooking;
113
+
114
+ getMovies( pageIndex );
115
+
116
+ $( "#genres li" ).click( selectGenre );
117
+
118
+ $( ".cart" )
119
+ .delegate( "select", "change", sort )
120
+ .delegate( "#sortBtn", "click", sort )
121
+ .delegate( "#submit", "click", function() {
122
+ alert( cart.count + " bookings submitted for payment...");
123
+ removeBookings();
124
+ })
125
+ .delegate( "#cancel", "click", function() {
126
+ removeBookings();
127
+ })
128
+ .empty();
129
+
130
+ $( "#cartTmpl" )
131
+ .tmpl( cart )
132
+ .appendTo( ".cart", cart );
133
+
134
+ var cartTmplItem = $( ".cart td" ).tmplItem();
135
+
136
+ function selectGenre() {
137
+ $( "#genres li" ).removeClass( "selected" );
138
+ $( this ).addClass( "selected" );
139
+
140
+ pageIndex = 1;
141
+ genre = encodeURI( $(this).text() );
142
+ getMovies( pageIndex );
143
+ }
144
+
145
+ function sort() {
146
+ var compare = compareName, reverse = false, data = [];
147
+ cart.sortBy = $( "#sort select" ).val();
148
+ switch ( $( "#sort select" ).val() ) {
149
+ case "1":
150
+ reverse = true;
151
+ break;
152
+ case "2":
153
+ compare = compareDate;
154
+ break;
155
+ }
156
+
157
+ for ( var item in cart.bookings ) {
158
+ data.push( cart.bookings[item] );
159
+ }
160
+ data = data.sort( compare );
161
+
162
+ for ( var i = 0, l = data.length; i < l; i++ ) {
163
+ $( bookingTmplItems[data[i].movie.Id].nodes ).appendTo( "#bookingsList" );
164
+ }
165
+
166
+ function compareName( a, b ) {
167
+ return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
168
+ }
169
+ function compareDate( a, b ) {
170
+ return a.date - b.date;
171
+ }
172
+ }
173
+
174
+ function getMovies( index ) {
175
+ var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
176
+ "?$format=json" +
177
+ "&$inlinecount=allpages" + // get total number of records
178
+ "&$skip=" + (index-1) * pageSize + // skip to first record of page
179
+ "&$top=" + pageSize; // page size
180
+
181
+ pageIndex = index;
182
+
183
+ $( "#movieList" )
184
+ .fadeOut( "medium", function () {
185
+ $.ajax({
186
+ dataType: "jsonp",
187
+ url: query,
188
+ jsonp: "$callback",
189
+ success: showMovies
190
+ });
191
+ });
192
+ }
193
+
194
+ function showMovies( data ) {
195
+ pageCount = Math.ceil( data.d.__count/pageSize ),
196
+ movies = data.d.results;
197
+
198
+ $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });
199
+
200
+ $( "#movieList" ).empty();
201
+
202
+ $( "#movieTmpl" )
203
+ // Render movies using the movieTemplate
204
+ .tmpl( movies )
205
+
206
+ // Display rendered movies in the movieList container
207
+ .appendTo( "#movieList" )
208
+
209
+ // Animate
210
+ .find( "div" ).fadeIn( 4000 ).end()
211
+
212
+ // Add click handler
213
+ .find( ".buyButton" ).click( function() {
214
+ buyTickets( $(this).tmplItem().data );
215
+ });
216
+
217
+ $( "#movieList" ).fadeIn( "medium" )
218
+ }
219
+
220
+ function buyTickets( movie ) {
221
+ // Add item to cart
222
+ var booking = cart.bookings[movie.Id];
223
+ if ( booking ) {
224
+ booking.quantity++;
225
+ } else {
226
+ cart.count++;
227
+ cartTmplItem.update();
228
+ booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
229
+ }
230
+ selectBooking( booking );
231
+ }
232
+
233
+ function selectBooking( booking ) {
234
+ if ( selectedBooking ) {
235
+ if ( selectedBooking === booking ) {
236
+ updateBooking( bookingTmplItems[selectedBooking.movie.Id]);
237
+ return;
238
+ }
239
+ // Collapse previously selected booking, and switch to non-edit view
240
+ var oldSelected = selectedBooking;
241
+ $( "div", bookingTmplItems[oldSelected.movie.Id].nodes ).animate( { height: 0 }, 500, function() {
242
+ switchView( oldSelected );
243
+ });
244
+ }
245
+ selectedBooking = booking;
246
+ if ( !booking ) {
247
+ return;
248
+ }
249
+ if ( cart.bookings[booking.movie.Id] ) {
250
+ switchView( booking, true );
251
+ } else {
252
+ cart.bookings[booking.movie.Id] = booking;
253
+
254
+ var bookingNode = $( "#bookingEditTmpl" )
255
+
256
+ // Render the booking for the chosen movie using the bookingEditTemplate
257
+ .tmpl( booking, { animate: true, formatDate: formatDate } )
258
+
259
+ // Append the rendered booking to the bookings list
260
+ .appendTo( "#bookingsList" )
261
+
262
+ // Get the 2nd <tr> of the appended booking
263
+ .last()[0];
264
+
265
+ // Get the template item for the 2nd <tr>, which is the template item for the "bookingEditTmpl" template
266
+ var newItem = $.tmplItem( bookingNode );
267
+ bookingTmplItems[booking.movie.Id] = newItem;
268
+
269
+ // Attach handlers etc. on the rendered template.
270
+ bookingEditRendered( newItem );
271
+ }
272
+ }
273
+
274
+ function bookingEditRendered( item ) {
275
+ var data = item.data, nodes = item.nodes;
276
+
277
+ $( nodes[0] ).click( function() {
278
+ selectBooking();
279
+ });
280
+
281
+ $( ".close", nodes ).click( removeBooking );
282
+
283
+ $( ".date", nodes ).change( function() {
284
+ data.date = $(this).datepicker( "getDate" );
285
+ updateBooking( item );
286
+ })
287
+ .datepicker({ dateFormat: "DD, d MM, yy" });
288
+
289
+ $( ".quantity", nodes ).change( function() {
290
+ data.quantity = $(this).val();
291
+ updateBooking( item );
292
+ });
293
+
294
+ $( ".theater", nodes ).change( function() {
295
+ data.movieTheater = $(this).val();
296
+ updateBooking( item );
297
+ });
298
+
299
+ if ( item.animate ) {
300
+ $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
301
+ }
302
+ }
303
+
304
+ function bookingRendered( item ) {
305
+ $( item.nodes ).click( function() {
306
+ selectBooking( item.data );
307
+ });
308
+ $( ".close", item.nodes ).click( removeBooking );
309
+ }
310
+
311
+ function switchView( booking, edit ) {
312
+ if ( !booking ) {
313
+ return;
314
+ }
315
+ var item = bookingTmplItems[booking.movie.Id],
316
+ tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template();
317
+ if ( item.tmpl !== tmpl) {
318
+ item.tmpl = tmpl;
319
+ item.update();
320
+ (edit ? bookingEditRendered : bookingRendered)( item );
321
+ }
322
+ }
323
+
324
+ function updateBooking( item ) {
325
+ item.animate = false;
326
+ item.update();
327
+ (item.data === selectedBooking ? bookingEditRendered : bookingRendered)( item );
328
+ item.animate = true;
329
+ }
330
+
331
+ function removeBooking() {
332
+ var booking = $.tmplItem(this).data;
333
+ if ( booking === selectedBooking ) {
334
+ selectedBooking = null;
335
+ }
336
+ delete cart.bookings[booking.movie.Id];
337
+ cart.count--;
338
+ cartTmplItem.update();
339
+ $( bookingTmplItems[booking.movie.Id].nodes ).remove();
340
+ delete bookingTmplItems[booking.movie.Id];
341
+ return false;
342
+ }
343
+
344
+ function removeBookings() {
345
+ for ( var item in bookingTmplItems ) {
346
+ $( bookingTmplItems[item].nodes ).remove();
347
+ delete bookingTmplItems[item];
348
+ }
349
+ bookingTmplItems = {};
350
+ cart.count = 0;
351
+ cart.bookings = {};
352
+ selectedBooking = null;
353
+ cartTmplItem.update();
354
+ }
355
+
356
+ function formatDate() {
357
+ return this.data.date.toLocaleDateString();
358
+ }
359
+ })(jQuery);
360
+ </script>
361
+
362
+ </body>
363
+ </html>
apps/jquery-tmpl/demos/movies/PagesTmplPlus/movies1.html ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using templates for a more complete and
4
+ realistic scenario.
5
+
6
+ It is similar to the movies/PagesCore/movies.html sample,
7
+ except that it uses jquery.tmplPlus.js in order to take advantage
8
+ of the .tmplCmd() features. It does not use the rendered event.
9
+ -->
10
+ <html xmlns="http://www.w3.org/1999/xhtml">
11
+ <head>
12
+ <title>jQuery + OData + Netflix Catalog API</title>
13
+ <link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
14
+ <link href="../css/movies.css" rel="stylesheet" type="text/css" />
15
+ </head>
16
+ <body>
17
+ <div id="pageBody">
18
+ <h1>Netflix: Book a Movie...</h1>
19
+
20
+ <ul id="genres">
21
+ <li class="selected">Cartoons</li>
22
+ <li>Drama</li>
23
+ <li>Foreign</li>
24
+ <li>Action Classics</li>
25
+ <li>Horror</li>
26
+ <li>Sci-Fi Cult Classics</li>
27
+ </ul>
28
+
29
+ <div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>
30
+
31
+ <div id="movieList"></div>
32
+ <table id="bookingsList">
33
+ <tbody><tr class="cart"><td class="cart-false" colspan="4">
34
+ <span class="text">0 items in Cart...</span>
35
+ </td></tr></tbody>
36
+ </table>
37
+ <br/>
38
+ </div>
39
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
40
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
41
+ <script src="../../../jquery.tmplPlus.js" type="text/javascript"></script>
42
+ <script src="../components/jquery.pager.js" type="text/javascript"></script>
43
+ <script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>
44
+
45
+ <script id="movieTmpl" type="text/x-jquery-tmpl">
46
+ <div>
47
+ <div><img src="${BoxArt.LargeUrl}" /> </div>
48
+ <strong>${Name}</strong>
49
+ <p>{{html Synopsis}}</p>
50
+ <input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
51
+ <br/>
52
+ </div>
53
+ </script>
54
+
55
+ <script id="cartTmpl" type="text/x-jquery-tmpl">
56
+ <td class="cart-${!!count}" colspan="4">
57
+ <span class="text">${count} items in Cart...</span>
58
+ {{if count}}
59
+ <span id="submit">Checkout</span>
60
+ <span id="cancel">Remove All</span>
61
+ {{if count>1}}
62
+ <span id="sort"><span id="sortBtn">Sort</span>:
63
+ <select>
64
+ <option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
65
+ <option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
66
+ <option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
67
+ </select>
68
+ </span>
69
+ {{/if}}
70
+ </select>
71
+ {{/if}}
72
+ </td>
73
+ </script>
74
+
75
+ <script id="bookingTitleTmpl" type="text/x-jquery-tmpl">
76
+ <tr class="bookingTitle${$item.mode}">
77
+ <td>${movie.Name}</td><td>${movieTheater}</td>
78
+ <td>${formatDate(date)}</td>
79
+ <td>
80
+ ${quantity}
81
+ <span class="ui-icon close"></span>
82
+ </td>
83
+ </tr>
84
+ </script>
85
+
86
+ <script id="bookingEditTmpl" type="text/x-jquery-tmpl">
87
+ {{tmpl($data, {mode: "Edit"}) "#bookingTitleTmpl"}}
88
+ <tr class="bookingEdit">
89
+ <td colspan="4">
90
+ <div class="fields">
91
+ <span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
92
+ <span>Date: </span><input class="date" type="text" value="${formatDate(date)}" /><br/>
93
+ <span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
94
+ </div>
95
+ <div><img src="${movie.BoxArt.LargeUrl}" /></div>
96
+ </td>
97
+ </tr>
98
+ </script>
99
+
100
+ <script type="text/javascript">
101
+ var genre="Cartoons", pageIndex = 1, pageSize = 3, pageCount = 0,
102
+ cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = [], selectedBooking;
103
+
104
+ getMovies( pageIndex );
105
+
106
+ $( "#genres li" ).click( selectGenre );
107
+
108
+ $( ".cart" )
109
+ .delegate( "select", "change", sort )
110
+ .delegate( "#sortBtn", "click", sort )
111
+ .delegate( "#submit", "click", function() {
112
+ alert( cart.count + " bookings submitted for payment...");
113
+ removeBookings();
114
+ })
115
+ .delegate( "#cancel", "click", function() {
116
+ removeBookings();
117
+ })
118
+ .empty();
119
+
120
+ $( "#cartTmpl" )
121
+ .tmpl( cart )
122
+ .appendTo( ".cart", cart );
123
+
124
+ var cartTmplItem = $( ".cart td" ).tmplItem();
125
+
126
+ function selectGenre() {
127
+ $( "#genres li" ).removeClass( "selected" );
128
+ $( this ).addClass( "selected" );
129
+
130
+ pageIndex = 1;
131
+ genre = encodeURI( $(this).text() );
132
+ getMovies( pageIndex );
133
+ }
134
+
135
+ function sort() {
136
+ var compare = compareName, reverse = false, data = [];
137
+ cart.sortBy = $( "#sort select" ).val();
138
+ switch ( $( "#sort select" ).val() ) {
139
+ case "1":
140
+ reverse = true;
141
+ break;
142
+ case "2":
143
+ compare = compareDate;
144
+ break;
145
+ }
146
+
147
+ for ( var item in cart.bookings ) {
148
+ data.push( cart.bookings[item] );
149
+ }
150
+ data = data.sort( compare );
151
+
152
+ bookingTmplItems = $.tmplCmd( "replace", data, bookingTmplItems );
153
+
154
+ function compareName( a, b ) {
155
+ return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
156
+ }
157
+ function compareDate( a, b ) {
158
+ return a.date - b.date;
159
+ }
160
+ }
161
+
162
+ function getMovies( index ) {
163
+ var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
164
+ "?$format=json" +
165
+ "&$inlinecount=allpages" + // get total number of records
166
+ "&$skip=" + (index-1) * pageSize + // skip to first record of page
167
+ "&$top=" + pageSize; // page size
168
+
169
+ pageIndex = index;
170
+
171
+ $( "#movieList" )
172
+ .fadeOut( "medium", function () {
173
+ $.ajax({
174
+ dataType: "jsonp",
175
+ url: query,
176
+ jsonp: "$callback",
177
+ success: showMovies
178
+ });
179
+ });
180
+ }
181
+
182
+ function showMovies( data ) {
183
+ pageCount = Math.ceil( data.d.__count/pageSize ),
184
+ movies = data.d.results;
185
+
186
+ $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });
187
+
188
+ // show movies in template
189
+ $( "#movieList" ).empty();
190
+
191
+ $( "#movieTmpl" )
192
+ // Render movies using the movieTemplate
193
+ .tmpl( movies )
194
+
195
+ // Display rendered movies in the movieList container
196
+ .appendTo( "#movieList" )
197
+
198
+ // Animate
199
+ .find( "div" ).fadeIn( 4000 ).end()
200
+
201
+ // Add click handler
202
+ .find( ".buyButton" ).click( function() {
203
+ buyTickets( $(this).tmplItem().data );
204
+ });
205
+
206
+ $( "#movieList" ).fadeIn( "medium" )
207
+ }
208
+
209
+ function buyTickets( movie ) {
210
+ // Add item to cart
211
+ var booking = cart.bookings[movie.Id];
212
+ if ( booking ) {
213
+ booking.quantity++;
214
+ } else {
215
+ cart.count++;
216
+ cartTmplItem.update();
217
+ booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
218
+ }
219
+ selectBooking( booking );
220
+ }
221
+
222
+ function selectBooking( booking ) {
223
+ if ( selectedBooking ) {
224
+ if ( selectedBooking === booking ) {
225
+ updateBooking( bookingItem( selectedBooking ));
226
+ return;
227
+ }
228
+ // Collapse previously selected booking, and switch to non-edit view
229
+ var oldSelected = selectedBooking;
230
+ $( "div", bookingItem( oldSelected ).nodes ).animate( { height: 0 }, 500, function() {
231
+ switchView( oldSelected );
232
+ });
233
+ }
234
+ selectedBooking = booking;
235
+ if ( !booking ) {
236
+ return;
237
+ }
238
+ if ( cart.bookings[booking.movie.Id] ) {
239
+ switchView( booking, true );
240
+ } else {
241
+ cart.bookings[booking.movie.Id] = booking;
242
+
243
+ var bookingNode = $( "#bookingEditTmpl" )
244
+
245
+ // Render the booking for the chosen movie using the bookingEditTemplate
246
+ .tmpl( booking, { animate: true } )
247
+
248
+ // Append the rendered booking to the bookings list
249
+ .appendTo( "#bookingsList" )
250
+
251
+ // Get the 2nd <tr> of the appended booking
252
+ .last()[0];
253
+
254
+ // Get the template item for the 2nd <tr>, which is the template item for the "bookingEditTmpl" template
255
+ var newItem = $.tmplItem( bookingNode );
256
+ bookingTmplItems.push( newItem );
257
+
258
+ // Attach handlers etc. on the rendered template.
259
+ bookingEditRendered( newItem );
260
+ }
261
+ }
262
+
263
+ function bookingEditRendered( item ) {
264
+ var data = item.data, nodes = item.nodes;
265
+
266
+ $( nodes[0] ).click( function() {
267
+ selectBooking();
268
+ });
269
+
270
+ $( ".close", nodes ).click( removeBooking );
271
+
272
+ $( ".date", nodes ).change( function() {
273
+ data.date = $(this).datepicker( "getDate" );
274
+ updateBooking( item );
275
+ })
276
+ .datepicker({ dateFormat: "DD, d MM, yy" });
277
+
278
+ $( ".quantity", nodes ).change( function() {
279
+ data.quantity = $(this).val();
280
+ updateBooking( item );
281
+ });
282
+
283
+ $( ".theater", nodes ).change( function() {
284
+ data.movieTheater = $(this).val();
285
+ updateBooking( item );
286
+ });
287
+
288
+ if ( item.animate ) {
289
+ $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
290
+ }
291
+ }
292
+
293
+ function bookingRendered( item ) {
294
+ $( item.nodes ).click( function() {
295
+ selectBooking( item.data );
296
+ });
297
+ $( ".close", item.nodes ).click( removeBooking );
298
+ }
299
+
300
+ function switchView( booking, edit ) {
301
+ if ( !booking ) {
302
+ return;
303
+ }
304
+ var item = bookingItem( booking ),
305
+ tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template();
306
+ if ( item.tmpl !== tmpl) {
307
+ item.tmpl = tmpl;
308
+ item.update();
309
+ (edit ? bookingEditRendered : bookingRendered)( item );
310
+ }
311
+ }
312
+
313
+ function updateBooking( item ) {
314
+ item.animate = false;
315
+ item.update();
316
+ (item.data === selectedBooking ? bookingEditRendered : bookingRendered)( item );
317
+ item.animate = true;
318
+ }
319
+
320
+ function removeBooking() {
321
+ var booking = $.tmplItem(this).data;
322
+ if ( booking === selectedBooking ) {
323
+ selectedBooking = null;
324
+ }
325
+ delete cart.bookings[booking.movie.Id];
326
+ cart.count--;
327
+ cartTmplItem.update();
328
+ $.tmplCmd( "remove", booking, bookingTmplItems );
329
+ return false;
330
+ }
331
+
332
+ function removeBookings() {
333
+ $.tmplCmd( "remove", bookingTmplItems );
334
+ bookingTmplItems = [];
335
+ cart.count = 0;
336
+ cart.bookings = {};
337
+ selectedBooking = null;
338
+ cartTmplItem.update();
339
+ }
340
+
341
+ function formatDate( date ) {
342
+ return date.toLocaleDateString();
343
+ }
344
+
345
+ function bookingItem( booking ) {
346
+ return $.tmplCmd( "find", booking, bookingTmplItems)[0];
347
+ }
348
+ </script>
349
+
350
+ </body>
351
+ </html>
apps/jquery-tmpl/demos/movies/PagesTmplPlus/movies2.html ADDED
@@ -0,0 +1,342 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using templates for a more complete and
4
+ realistic scenario.
5
+
6
+ It is similar to the movies/PagesCore/movies.html sample,
7
+ except that it uses jquery.tmplPlus.js in order to take advantage
8
+ of the .tmplCmd() features and the rendered event.
9
+ -->
10
+ <html xmlns="http://www.w3.org/1999/xhtml">
11
+ <head>
12
+ <title>jQuery + OData + Netflix Catalog API</title>
13
+ <link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
14
+ <link href="../css/movies.css" rel="stylesheet" type="text/css" />
15
+ </head>
16
+ <body>
17
+ <div id="pageBody">
18
+ <h1>Netflix: Book a Movie...</h1>
19
+
20
+ <ul id="genres">
21
+ <li class="selected">Cartoons</li>
22
+ <li>Drama</li>
23
+ <li>Foreign</li>
24
+ <li>Action Classics</li>
25
+ <li>Horror</li>
26
+ <li>Sci-Fi Cult Classics</li>
27
+ </ul>
28
+
29
+ <div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>
30
+
31
+ <div id="movieList"></div>
32
+ <table id="bookingsList">
33
+ <tbody><tr class="cart"><td class="cart-false" colspan="4">
34
+ <span class="text">0 items in Cart...</span>
35
+ </td></tr></tbody>
36
+ </table>
37
+ <br/>
38
+ </div>
39
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
40
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
41
+ <script src="../../../jquery.tmplPlus.js" type="text/javascript"></script>
42
+ <script src="../components/jquery.pager.js" type="text/javascript"></script>
43
+ <script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>
44
+
45
+ <script id="movieTmpl" type="text/x-jquery-tmpl">
46
+ <div>
47
+ <div><img src="${BoxArt.LargeUrl}" /> </div>
48
+ <strong>${Name}</strong>
49
+ <p>{{html Synopsis}}</p>
50
+ <input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
51
+ <br/>
52
+ </div>
53
+ </script>
54
+
55
+ <script id="cartTmpl" type="text/x-jquery-tmpl">
56
+ <td class="cart-${!!count}" colspan="4">
57
+ <span class="text">${count} items in Cart...</span>
58
+ {{if count}}
59
+ <span id="submit">Checkout</span>
60
+ <span id="cancel">Remove All</span>
61
+ {{if count>1}}
62
+ <span id="sort"><span id="sortBtn">Sort</span>:
63
+ <select>
64
+ <option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
65
+ <option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
66
+ <option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
67
+ </select>
68
+ </span>
69
+ {{/if}}
70
+ </select>
71
+ {{/if}}
72
+ </td>
73
+ </script>
74
+
75
+ <script id="bookingTitleTmpl" type="text/x-jquery-tmpl">
76
+ <tr class="bookingTitle${$item.mode}">
77
+ <td>${movie.Name}</td><td>${movieTheater}</td>
78
+ <td>${formatDate(date)}</td>
79
+ <td>
80
+ ${quantity}
81
+ <span class="ui-icon close"></span>
82
+ </td>
83
+ </tr>
84
+ </script>
85
+
86
+ <script id="bookingEditTmpl" type="text/x-jquery-tmpl">
87
+ {{tmpl($data, {mode: "Edit"}) "#bookingTitleTmpl"}}
88
+ <tr class="bookingEdit">
89
+ <td colspan="4">
90
+ <div class="fields">
91
+ <span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
92
+ <span>Date: </span><input class="date" type="text" value="${formatDate(date)}" /><br/>
93
+ <span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
94
+ </div>
95
+ <div><img src="${movie.BoxArt.LargeUrl}" /></div>
96
+ </td>
97
+ </tr>
98
+ </script>
99
+
100
+ <script type="text/javascript">
101
+ var genre="Cartoons", pageIndex = 1, pageSize = 3, pageCount = 0,
102
+ cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = [], selectedBooking;
103
+
104
+ getMovies( pageIndex );
105
+
106
+ $( "#genres li" ).click( selectGenre );
107
+
108
+ $( ".cart" )
109
+ .delegate( "select", "change", sort )
110
+ .delegate( "#sortBtn", "click", sort )
111
+ .delegate( "#submit", "click", function() {
112
+ alert( cart.count + " bookings submitted for payment...");
113
+ removeBookings();
114
+ })
115
+ .delegate( "#cancel", "click", function() {
116
+ removeBookings();
117
+ })
118
+ .empty();
119
+ $( "#cartTmpl" )
120
+ .tmpl( cart )
121
+ .appendTo( ".cart", cart );
122
+
123
+ var cartTmplItem = $( ".cart td" ).tmplItem();
124
+
125
+ function selectGenre() {
126
+ $( "#genres li" ).removeClass( "selected" );
127
+ $( this ).addClass( "selected" );
128
+
129
+ pageIndex = 1;
130
+ genre = encodeURI( $(this).text() );
131
+ getMovies( pageIndex );
132
+ }
133
+
134
+ function sort() {
135
+ var compare = compareName, reverse = false, data = [];
136
+ cart.sortBy = $( "#sort select" ).val();
137
+ switch ( $( "#sort select" ).val() ) {
138
+ case "1":
139
+ reverse = true;
140
+ break;
141
+ case "2":
142
+ compare = compareDate;
143
+ break;
144
+ }
145
+
146
+ for ( var item in cart.bookings ) {
147
+ data.push( cart.bookings[item] );
148
+ }
149
+ data = data.sort( compare );
150
+
151
+ bookingTmplItems = $.tmplCmd( "replace", data, bookingTmplItems );
152
+
153
+ function compareName( a, b ) {
154
+ return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
155
+ }
156
+ function compareDate( a, b ) {
157
+ return a.date - b.date;
158
+ }
159
+ }
160
+
161
+ function getMovies( index ) {
162
+ var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
163
+ "?$format=json" +
164
+ "&$inlinecount=allpages" + // get total number of records
165
+ "&$skip=" + (index-1) * pageSize + // skip to first record of page
166
+ "&$top=" + pageSize; // page size
167
+
168
+ pageIndex = index;
169
+
170
+ $( "#movieList" )
171
+ .fadeOut( "medium", function () {
172
+ $.ajax({
173
+ dataType: "jsonp",
174
+ url: query,
175
+ jsonp: "$callback",
176
+ success: showMovies
177
+ });
178
+ });
179
+ }
180
+
181
+ function showMovies( data ) {
182
+ pageCount = Math.ceil( data.d.__count/pageSize ),
183
+ movies = data.d.results;
184
+
185
+ $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });
186
+
187
+ // show movies in template
188
+ $( "#movieList" ).empty();
189
+
190
+ $( "#movieTmpl" )
191
+ // Render movies using the movieTemplate
192
+ .tmpl( movies, { rendered: onMovieRendered } )
193
+
194
+ // Display rendered movies in the movieList container
195
+ .appendTo( "#movieList" );
196
+
197
+ $( "#movieList" ).fadeIn( "medium" )
198
+ }
199
+
200
+ function buyTickets( movie ) {
201
+ // Add item to cart
202
+ var booking = cart.bookings[movie.Id];
203
+ if ( booking ) {
204
+ booking.quantity++;
205
+ } else {
206
+ cart.count++;
207
+ cartTmplItem.update();
208
+ booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
209
+ }
210
+ selectBooking( booking );
211
+ }
212
+
213
+ function selectBooking( booking ) {
214
+ if ( selectedBooking ) {
215
+ if ( selectedBooking === booking ) {
216
+ updateBooking( bookingItem( selectedBooking ));
217
+ return;
218
+ }
219
+ // Collapse previously selected booking, and switch to non-edit view
220
+ var oldSelected = selectedBooking;
221
+ $( "div", bookingItem( oldSelected ).nodes ).animate( { height: 0 }, 500, function() {
222
+ switchView( oldSelected );
223
+ });
224
+ }
225
+ selectedBooking = booking;
226
+ if ( !booking ) {
227
+ return;
228
+ }
229
+ if ( cart.bookings[booking.movie.Id] ) {
230
+ switchView( booking, true );
231
+ } else {
232
+ cart.bookings[booking.movie.Id] = booking;
233
+
234
+ $( "#bookingEditTmpl" )
235
+
236
+ // Render the booking for the chosen movie using the bookingEditTemplate
237
+ .tmpl( booking, {
238
+ animate: true,
239
+ rendered: onBookingEditRendered,
240
+ addedTmplItems: bookingTmplItems
241
+ })
242
+
243
+ // Append the rendered booking to the bookings list
244
+ .appendTo( "#bookingsList" );
245
+ }
246
+ }
247
+
248
+ function switchView( booking, edit ) {
249
+ if ( !booking ) {
250
+ return;
251
+ }
252
+ var item = bookingItem( booking ),
253
+ rendered = edit ? onBookingEditRendered : onBookingRendered;
254
+ if ( item.rendered !== rendered) {
255
+ item.tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template();
256
+ item.rendered = rendered;
257
+ item.update();
258
+ }
259
+ }
260
+
261
+ function onMovieRendered( item ) {
262
+ $( "div", item.nodes ).fadeIn( 4000 );
263
+ $( ".buyButton", item.nodes ).click( function() {
264
+ buyTickets( item.data );
265
+ });
266
+ }
267
+
268
+ function onBookingRendered( item ) {
269
+ $( item.nodes ).click( function() {
270
+ selectBooking( item.data );
271
+ });
272
+ $( ".close", item.nodes ).click( removeBooking );
273
+ }
274
+
275
+ function onBookingEditRendered( item ) {
276
+ var data = item.data, nodes = item.nodes;
277
+
278
+ $( nodes[0] ).click( function() {
279
+ selectBooking();
280
+ });
281
+
282
+ $( ".close", nodes ).click( removeBooking );
283
+
284
+ $( ".date", nodes ).change( function() {
285
+ data.date = $(this).datepicker( "getDate" );
286
+ updateBooking( item );
287
+ })
288
+ .datepicker({ dateFormat: "DD, d MM, yy" });
289
+
290
+ $( ".quantity", nodes ).change( function() {
291
+ data.quantity = $(this).val();
292
+ updateBooking( item );
293
+ });
294
+
295
+ $( ".theater", nodes ).change( function() {
296
+ data.movieTheater = $(this).val();
297
+ updateBooking( item );
298
+ });
299
+
300
+ if ( item.animate ) {
301
+ $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
302
+ }
303
+ }
304
+
305
+ function updateBooking( item ) {
306
+ item.animate = false;
307
+ item.update();
308
+ item.animate = true;
309
+ }
310
+
311
+ function removeBooking() {
312
+ var booking = $.tmplItem(this).data;
313
+ if ( booking === selectedBooking ) {
314
+ selectedBooking = null;
315
+ }
316
+ delete cart.bookings[booking.movie.Id];
317
+ cart.count--;
318
+ cartTmplItem.update();
319
+ $.tmplCmd( "remove", booking, bookingTmplItems );
320
+ return false;
321
+ }
322
+
323
+ function removeBookings() {
324
+ $.tmplCmd( "remove", bookingTmplItems );
325
+ bookingTmplItems = [];
326
+ cart.count = 0;
327
+ cart.bookings = {};
328
+ selectedBooking = null;
329
+ cartTmplItem.update();
330
+ }
331
+
332
+ function formatDate( date ) {
333
+ return date.toLocaleDateString();
334
+ }
335
+
336
+ function bookingItem( booking ) {
337
+ return $.tmplCmd( "find", booking, bookingTmplItems)[0];
338
+ }
339
+ </script>
340
+
341
+ </body>
342
+ </html>
apps/jquery-tmpl/demos/movies/PagesTmplPlus/movies3.html ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using templates for a more complete and
4
+ realistic scenario.
5
+
6
+ It is similar to the movies/PagesCore/movies.html sample,
7
+ except that it uses jquery.tmplPlus.js in order to take advantage
8
+ of the
9
+ $( targetSelector ).append( templateSelector, data )
10
+ pattern, as well as the .tmplCmd() features and the rendered event.
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml">
13
+ <head>
14
+ <title>jQuery + OData + Netflix Catalog API</title>
15
+ <link href="../css/jquery-ui-1.8.1.custom.css" rel="stylesheet" type="text/css" />
16
+ <link href="../css/movies.css" rel="stylesheet" type="text/css" />
17
+ </head>
18
+ <body>
19
+ <div id="pageBody">
20
+ <h1>Netflix: Book a Movie...</h1>
21
+
22
+ <ul id="genres">
23
+ <li class="selected">Cartoons</li>
24
+ <li>Drama</li>
25
+ <li>Foreign</li>
26
+ <li>Action Classics</li>
27
+ <li>Horror</li>
28
+ <li>Sci-Fi Cult Classics</li>
29
+ </ul>
30
+
31
+ <div id="pager"><ul class="pages"><li class="pgEmpty">first</li><li class="pgEmpty">prev</li></ul></div>
32
+
33
+ <div id="movieList"></div>
34
+ <table id="bookingsList">
35
+ <tbody><tr class="cart"><td class="cart-false" colspan="4">
36
+ <span class="text">0 items in Cart...</span>
37
+ </td></tr></tbody>
38
+ </table>
39
+ <br/>
40
+ </div>
41
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
42
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
43
+ <script src="../../../jquery.tmplPlus.js" type="text/javascript"></script>
44
+ <script src="../components/jquery.pager.js" type="text/javascript"></script>
45
+ <script src="../components/jquery-ui-1.8.1.custom.js" type="text/javascript"></script>
46
+
47
+ <script id="movieTmpl" type="text/x-jquery-tmpl">
48
+ <div>
49
+ <div><img src="${BoxArt.LargeUrl}" /> </div>
50
+ <strong>${Name}</strong>
51
+ <p>{{html Synopsis}}</p>
52
+ <input type="button" title="Buy tickets for '${Name}'" value="Add to cart..." class="buyButton"/>
53
+ <br/>
54
+ </div>
55
+ </script>
56
+
57
+ <script id="cartTmpl" type="text/x-jquery-tmpl">
58
+ <td class="cart-${!!count}" colspan="4">
59
+ <span class="text">${count} items in Cart...</span>
60
+ {{if count}}
61
+ <span id="submit">Checkout</span>
62
+ <span id="cancel">Remove All</span>
63
+ {{if count>1}}
64
+ <span id="sort"><span id="sortBtn">Sort</span>:
65
+ <select>
66
+ <option value="0" {{if sortBy==="0"}}selected{{/if}}>Name A-Z</option>
67
+ <option value="1" {{if sortBy==="1"}}selected{{/if}}>Name Z-A</option>
68
+ <option value="2" {{if sortBy==="2"}}selected{{/if}}>Date</option>
69
+ </select>
70
+ </span>
71
+ {{/if}}
72
+ </select>
73
+ {{/if}}
74
+ </td>
75
+ </script>
76
+
77
+ <script id="bookingTitleTmpl" type="text/x-jquery-tmpl">
78
+ <tr class="bookingTitle${$item.mode}">
79
+ <td>${movie.Name}</td><td>${movieTheater}</td>
80
+ <td>${formatDate(date)}</td>
81
+ <td>
82
+ ${quantity}
83
+ <span class="ui-icon close"></span>
84
+ </td>
85
+ </tr>
86
+ </script>
87
+
88
+ <script id="bookingEditTmpl" type="text/x-jquery-tmpl">
89
+ {{tmpl($data, {mode: "Edit"}) "#bookingTitleTmpl"}}
90
+ <tr class="bookingEdit">
91
+ <td colspan="4">
92
+ <div class="fields">
93
+ <span>Movie Theater: </span><input class="theater" type="text" value="${movieTheater}" /><br/>
94
+ <span>Date: </span><input class="date" type="text" value="${formatDate(date)}" /><br/>
95
+ <span>Quantity: </span><input class="quantity" type="text" value="${quantity}" />
96
+ </div>
97
+ <div><img src="${movie.BoxArt.LargeUrl}" /></div>
98
+ </td>
99
+ </tr>
100
+ </script>
101
+
102
+ <script type="text/javascript">
103
+ var genre="Cartoons", pageIndex = 1, pageSize = 3, pageCount = 0,
104
+ cart = { bookings: {}, count: 0, sortBy:0 }, bookingTmplItems = [], selectedBooking;
105
+
106
+ getMovies( pageIndex );
107
+
108
+ $( "#genres li" ).click( selectGenre );
109
+
110
+ $( ".cart" )
111
+ .delegate( "select", "change", sort )
112
+ .delegate( "#sortBtn", "click", sort )
113
+ .delegate( "#submit", "click", function() {
114
+ alert( cart.count + " bookings submitted for payment...");
115
+ removeBookings();
116
+ })
117
+ .delegate( "#cancel", "click", function() {
118
+ removeBookings();
119
+ })
120
+ .empty()
121
+ .append( "#cartTmpl", cart );
122
+
123
+ var cartTmplItem = $( ".cart td" ).tmplItem();
124
+
125
+ function selectGenre() {
126
+ $( "#genres li" ).removeClass( "selected" );
127
+ $( this ).addClass( "selected" );
128
+
129
+ pageIndex = 1;
130
+ genre = encodeURI( $(this).text() );
131
+ getMovies( pageIndex );
132
+ }
133
+
134
+ function sort() {
135
+ var compare = compareName, reverse = false, data = [];
136
+ cart.sortBy = $( "#sort select" ).val();
137
+ switch ( $( "#sort select" ).val() ) {
138
+ case "1":
139
+ reverse = true;
140
+ break;
141
+ case "2":
142
+ compare = compareDate;
143
+ break;
144
+ }
145
+
146
+ for ( var item in cart.bookings ) {
147
+ data.push( cart.bookings[item] );
148
+ }
149
+ data = data.sort( compare );
150
+
151
+ bookingTmplItems = $.tmplCmd( "replace", data, bookingTmplItems );
152
+
153
+ function compareName( a, b ) {
154
+ return a == b ? 0 : (((a.movie.Name > b.movie.Name) !== reverse) ? 1 : -1);
155
+ }
156
+ function compareDate( a, b ) {
157
+ return a.date - b.date;
158
+ }
159
+ }
160
+
161
+ function getMovies( index ) {
162
+ var query = "http://odata.netflix.com/Catalog/Genres('" + genre + "')/Titles" +
163
+ "?$format=json" +
164
+ "&$inlinecount=allpages" + // get total number of records
165
+ "&$skip=" + (index-1) * pageSize + // skip to first record of page
166
+ "&$top=" + pageSize; // page size
167
+
168
+ pageIndex = index;
169
+
170
+ $( "#movieList" )
171
+ .fadeOut( "medium", function () {
172
+ $.ajax({
173
+ dataType: "jsonp",
174
+ url: query,
175
+ jsonp: "$callback",
176
+ success: showMovies
177
+ });
178
+ });
179
+ }
180
+
181
+ function showMovies( data ) {
182
+ pageCount = Math.ceil( data.d.__count/pageSize ),
183
+ movies = data.d.results;
184
+
185
+ $( "#pager" ).pager({ pagenumber: pageIndex, pagecount: pageCount, buttonClickCallback: getMovies });
186
+
187
+ $( "#movieList" )
188
+ .empty()
189
+
190
+ // Render movies using the movieTemplate, and display rendered movies in the movieList container
191
+ .append( "#movieTmpl", movies, { rendered: onMovieRendered } )
192
+
193
+ .fadeIn( "medium" );
194
+ }
195
+
196
+ function buyTickets( movie ) {
197
+ // Add item to cart
198
+ var booking = cart.bookings[movie.Id];
199
+ if ( booking ) {
200
+ booking.quantity++;
201
+ } else {
202
+ cart.count++;
203
+ cartTmplItem.update();
204
+ booking = { movie: movie, date: new Date(), quantity: 1, movieTheater: "" };
205
+ }
206
+ selectBooking( booking );
207
+ }
208
+
209
+ function selectBooking( booking ) {
210
+ if ( selectedBooking ) {
211
+ if ( selectedBooking === booking ) {
212
+ updateBooking( bookingItem( selectedBooking ));
213
+ return;
214
+ }
215
+ // Collapse previously selected booking, and switch to non-edit view
216
+ var oldSelected = selectedBooking;
217
+ $( "div", bookingItem( oldSelected ).nodes ).animate( { height: 0 }, 500, function() {
218
+ switchView( oldSelected );
219
+ });
220
+ }
221
+ selectedBooking = booking;
222
+ if ( !booking ) {
223
+ return;
224
+ }
225
+ if ( cart.bookings[booking.movie.Id] ) {
226
+ switchView( booking, true );
227
+ } else {
228
+ cart.bookings[booking.movie.Id] = booking;
229
+
230
+ // Render the booking for the chosen movie using the bookingEditTemplate, and append the rendered booking to the bookings list
231
+ $( "#bookingsList" ).append( "#bookingEditTmpl", booking, {
232
+ animate: true,
233
+ rendered: onBookingEditRendered,
234
+ addedTmplItems: bookingTmplItems
235
+ });
236
+ }
237
+ }
238
+
239
+ function switchView( booking, edit ) {
240
+ if ( !booking ) {
241
+ return;
242
+ }
243
+ var item = bookingItem( booking ),
244
+ rendered = edit ? onBookingEditRendered : onBookingRendered;
245
+ if ( item.rendered !== rendered) {
246
+ item.tmpl = $( edit ? "#bookingEditTmpl" : "#bookingTitleTmpl" ).template();
247
+ item.rendered = rendered;
248
+ item.update();
249
+ }
250
+ }
251
+
252
+ function onMovieRendered( item ) {
253
+ $( "div", item.nodes ).fadeIn( 4000 );
254
+ $( ".buyButton", item.nodes ).click( function() {
255
+ buyTickets( item.data );
256
+ });
257
+ }
258
+
259
+ function onBookingRendered( item ) {
260
+ $( item.nodes ).click( function() {
261
+ selectBooking( item.data );
262
+ });
263
+ $( ".close", item.nodes ).click( removeBooking );
264
+ }
265
+
266
+ function onBookingEditRendered( item ) {
267
+ var data = item.data, nodes = item.nodes;
268
+
269
+ $( nodes[0] ).click( function() {
270
+ selectBooking();
271
+ });
272
+
273
+ $( ".close", nodes ).click( removeBooking );
274
+
275
+ $( ".date", nodes ).change( function() {
276
+ data.date = $(this).datepicker( "getDate" );
277
+ updateBooking( item );
278
+ })
279
+ .datepicker({ dateFormat: "DD, d MM, yy" });
280
+
281
+ $( ".quantity", nodes ).change( function() {
282
+ data.quantity = $(this).val();
283
+ updateBooking( item );
284
+ });
285
+
286
+ $( ".theater", nodes ).change( function() {
287
+ data.movieTheater = $(this).val();
288
+ updateBooking( item );
289
+ });
290
+
291
+ if ( item.animate ) {
292
+ $( "div", nodes ).css( "height", 0 ).animate( { height: 116 }, 500 );
293
+ }
294
+ }
295
+
296
+ function updateBooking( item ) {
297
+ item.animate = false;
298
+ item.update();
299
+ item.animate = true;
300
+ }
301
+
302
+ function removeBooking() {
303
+ var booking = $.tmplItem(this).data;
304
+ if ( booking === selectedBooking ) {
305
+ selectedBooking = null;
306
+ }
307
+ delete cart.bookings[booking.movie.Id];
308
+ cart.count--;
309
+ cartTmplItem.update();
310
+ $.tmplCmd( "remove", booking, bookingTmplItems );
311
+ return false;
312
+ }
313
+
314
+ function removeBookings() {
315
+ $.tmplCmd( "remove", bookingTmplItems );
316
+ bookingTmplItems = [];
317
+ cart.count = 0;
318
+ cart.bookings = {};
319
+ selectedBooking = null;
320
+ cartTmplItem.update();
321
+ }
322
+
323
+ function formatDate( date ) {
324
+ return date.toLocaleDateString();
325
+ }
326
+
327
+ function bookingItem( booking ) {
328
+ return $.tmplCmd( "find", booking, bookingTmplItems)[0];
329
+ }
330
+ </script>
331
+
332
+ </body>
333
+ </html>
apps/jquery-tmpl/demos/movies/components/jquery-ui-1.8.1.custom.js ADDED
@@ -0,0 +1,1929 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI 1.8.1
3
+ *
4
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
6
+ * and GPL (GPL-LICENSE.txt) licenses.
7
+ *
8
+ * http://docs.jquery.com/UI
9
+ */
10
+ ;jQuery.ui || (function($) {
11
+
12
+ //Helper functions and ui object
13
+ $.ui = {
14
+ version: "1.8.1",
15
+
16
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
17
+ plugin: {
18
+ add: function(module, option, set) {
19
+ var proto = $.ui[module].prototype;
20
+ for(var i in set) {
21
+ proto.plugins[i] = proto.plugins[i] || [];
22
+ proto.plugins[i].push([option, set[i]]);
23
+ }
24
+ },
25
+ call: function(instance, name, args) {
26
+ var set = instance.plugins[name];
27
+ if(!set || !instance.element[0].parentNode) { return; }
28
+
29
+ for (var i = 0; i < set.length; i++) {
30
+ if (instance.options[set[i][0]]) {
31
+ set[i][1].apply(instance.element, args);
32
+ }
33
+ }
34
+ }
35
+ },
36
+
37
+ contains: function(a, b) {
38
+ return document.compareDocumentPosition
39
+ ? a.compareDocumentPosition(b) & 16
40
+ : a !== b && a.contains(b);
41
+ },
42
+
43
+ hasScroll: function(el, a) {
44
+
45
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
46
+ if ($(el).css('overflow') == 'hidden') { return false; }
47
+
48
+ var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
49
+ has = false;
50
+
51
+ if (el[scroll] > 0) { return true; }
52
+
53
+ // TODO: determine which cases actually cause this to happen
54
+ // if the element doesn't have the scroll set, see if it's possible to
55
+ // set the scroll
56
+ el[scroll] = 1;
57
+ has = (el[scroll] > 0);
58
+ el[scroll] = 0;
59
+ return has;
60
+ },
61
+
62
+ isOverAxis: function(x, reference, size) {
63
+ //Determines when x coordinate is over "b" element axis
64
+ return (x > reference) && (x < (reference + size));
65
+ },
66
+
67
+ isOver: function(y, x, top, left, height, width) {
68
+ //Determines when x, y coordinates is over "b" element
69
+ return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
70
+ },
71
+
72
+ keyCode: {
73
+ ALT: 18,
74
+ BACKSPACE: 8,
75
+ CAPS_LOCK: 20,
76
+ COMMA: 188,
77
+ CONTROL: 17,
78
+ DELETE: 46,
79
+ DOWN: 40,
80
+ END: 35,
81
+ ENTER: 13,
82
+ ESCAPE: 27,
83
+ HOME: 36,
84
+ INSERT: 45,
85
+ LEFT: 37,
86
+ NUMPAD_ADD: 107,
87
+ NUMPAD_DECIMAL: 110,
88
+ NUMPAD_DIVIDE: 111,
89
+ NUMPAD_ENTER: 108,
90
+ NUMPAD_MULTIPLY: 106,
91
+ NUMPAD_SUBTRACT: 109,
92
+ PAGE_DOWN: 34,
93
+ PAGE_UP: 33,
94
+ PERIOD: 190,
95
+ RIGHT: 39,
96
+ SHIFT: 16,
97
+ SPACE: 32,
98
+ TAB: 9,
99
+ UP: 38
100
+ }
101
+ };
102
+
103
+ //jQuery plugins
104
+ $.fn.extend({
105
+ _focus: $.fn.focus,
106
+ focus: function(delay, fn) {
107
+ return typeof delay === 'number'
108
+ ? this.each(function() {
109
+ var elem = this;
110
+ setTimeout(function() {
111
+ $(elem).focus();
112
+ (fn && fn.call(elem));
113
+ }, delay);
114
+ })
115
+ : this._focus.apply(this, arguments);
116
+ },
117
+
118
+ enableSelection: function() {
119
+ return this
120
+ .attr('unselectable', 'off')
121
+ .css('MozUserSelect', '');
122
+ },
123
+
124
+ disableSelection: function() {
125
+ return this
126
+ .attr('unselectable', 'on')
127
+ .css('MozUserSelect', 'none');
128
+ },
129
+
130
+ scrollParent: function() {
131
+ var scrollParent;
132
+ if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
133
+ scrollParent = this.parents().filter(function() {
134
+ return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
135
+ }).eq(0);
136
+ } else {
137
+ scrollParent = this.parents().filter(function() {
138
+ return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
139
+ }).eq(0);
140
+ }
141
+
142
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
143
+ },
144
+
145
+ zIndex: function(zIndex) {
146
+ if (zIndex !== undefined) {
147
+ return this.css('zIndex', zIndex);
148
+ }
149
+
150
+ if (this.length) {
151
+ var elem = $(this[0]), position, value;
152
+ while (elem.length && elem[0] !== document) {
153
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
154
+ // This makes behavior of this function consistent across browsers
155
+ // WebKit always returns auto if the element is positioned
156
+ position = elem.css('position');
157
+ if (position == 'absolute' || position == 'relative' || position == 'fixed')
158
+ {
159
+ // IE returns 0 when zIndex is not specified
160
+ // other browsers return a string
161
+ // we ignore the case of nested elements with an explicit value of 0
162
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
163
+ value = parseInt(elem.css('zIndex'));
164
+ if (!isNaN(value) && value != 0) {
165
+ return value;
166
+ }
167
+ }
168
+ elem = elem.parent();
169
+ }
170
+ }
171
+
172
+ return 0;
173
+ }
174
+ });
175
+
176
+
177
+ //Additional selectors
178
+ $.extend($.expr[':'], {
179
+ data: function(elem, i, match) {
180
+ return !!$.data(elem, match[3]);
181
+ },
182
+
183
+ focusable: function(element) {
184
+ var nodeName = element.nodeName.toLowerCase(),
185
+ tabIndex = $.attr(element, 'tabindex');
186
+ return (/input|select|textarea|button|object/.test(nodeName)
187
+ ? !element.disabled
188
+ : 'a' == nodeName || 'area' == nodeName
189
+ ? element.href || !isNaN(tabIndex)
190
+ : !isNaN(tabIndex))
191
+ // the element and all of its ancestors must be visible
192
+ // the browser may report that the area is hidden
193
+ && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
194
+ },
195
+
196
+ tabbable: function(element) {
197
+ var tabIndex = $.attr(element, 'tabindex');
198
+ return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
199
+ }
200
+ });
201
+
202
+ })(jQuery);
203
+ /*
204
+ * jQuery UI Datepicker 1.8.1
205
+ *
206
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
207
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
208
+ * and GPL (GPL-LICENSE.txt) licenses.
209
+ *
210
+ * http://docs.jquery.com/UI/Datepicker
211
+ *
212
+ * Depends:
213
+ * jquery.ui.core.js
214
+ */
215
+
216
+ (function($) { // hide the namespace
217
+
218
+ $.extend($.ui, { datepicker: { version: "1.8.1" } });
219
+
220
+ var PROP_NAME = 'datepicker';
221
+ var dpuuid = new Date().getTime();
222
+
223
+ /* Date picker manager.
224
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
225
+ Settings for (groups of) date pickers are maintained in an instance object,
226
+ allowing multiple different settings on the same page. */
227
+
228
+ function Datepicker() {
229
+ this.debug = false; // Change this to true to start debugging
230
+ this._curInst = null; // The current instance in use
231
+ this._keyEvent = false; // If the last event was a key event
232
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
233
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
234
+ this._inDialog = false; // True if showing within a "dialog", false if not
235
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
236
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
237
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
238
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
239
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
240
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
241
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
242
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
243
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
244
+ this.regional = []; // Available regional settings, indexed by language code
245
+ this.regional[''] = { // Default regional settings
246
+ closeText: 'Done', // Display text for close link
247
+ prevText: 'Prev', // Display text for previous month link
248
+ nextText: 'Next', // Display text for next month link
249
+ currentText: 'Today', // Display text for current month link
250
+ monthNames: ['January','February','March','April','May','June',
251
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
252
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
253
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
254
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
255
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
256
+ weekHeader: 'Wk', // Column header for week of the year
257
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
258
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
259
+ isRTL: false, // True if right-to-left language, false if left-to-right
260
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
261
+ yearSuffix: '' // Additional text to append to the year in the month headers
262
+ };
263
+ this._defaults = { // Global defaults for all the date picker instances
264
+ showOn: 'focus', // 'focus' for popup on focus,
265
+ // 'button' for trigger button, or 'both' for either
266
+ showAnim: 'show', // Name of jQuery animation for popup
267
+ showOptions: {}, // Options for enhanced animations
268
+ defaultDate: null, // Used when field is blank: actual date,
269
+ // +/-number for offset from today, null for today
270
+ appendText: '', // Display text following the input box, e.g. showing the format
271
+ buttonText: '...', // Text for trigger button
272
+ buttonImage: '', // URL for trigger button image
273
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
274
+ hideIfNoPrevNext: false, // True to hide next/previous month links
275
+ // if not applicable, false to just disable them
276
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
277
+ gotoCurrent: false, // True if today link goes back to current selection instead
278
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
279
+ changeYear: false, // True if year can be selected directly, false if only prev/next
280
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
281
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
282
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
283
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
284
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
285
+ showWeek: false, // True to show week of the year, false to not show it
286
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
287
+ // takes a Date and returns the number of the week for it
288
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
289
+ // > this are in the previous century,
290
+ // string value starting with '+' for current year + value
291
+ minDate: null, // The earliest selectable date, or null for no limit
292
+ maxDate: null, // The latest selectable date, or null for no limit
293
+ duration: '_default', // Duration of display/closure
294
+ beforeShowDay: null, // Function that takes a date and returns an array with
295
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
296
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
297
+ beforeShow: null, // Function that takes an input field and
298
+ // returns a set of custom settings for the date picker
299
+ onSelect: null, // Define a callback function when a date is selected
300
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
301
+ onClose: null, // Define a callback function when the datepicker is closed
302
+ numberOfMonths: 1, // Number of months to show at a time
303
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
304
+ stepMonths: 1, // Number of months to step back/forward
305
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
306
+ altField: '', // Selector for an alternate field to store selected dates into
307
+ altFormat: '', // The date format to use for the alternate field
308
+ constrainInput: true, // The input is constrained by the current date format
309
+ showButtonPanel: false, // True to show button panel, false to not show it
310
+ autoSize: false // True to size the input for the date format, false to leave as is
311
+ };
312
+ $.extend(this._defaults, this.regional['']);
313
+ this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
314
+ }
315
+
316
+ $.extend(Datepicker.prototype, {
317
+ /* Class name added to elements to indicate already configured with a date picker. */
318
+ markerClassName: 'hasDatepicker',
319
+
320
+ /* Debug logging (if enabled). */
321
+ log: function () {
322
+ if (this.debug)
323
+ console.log.apply('', arguments);
324
+ },
325
+
326
+ // TODO rename to "widget" when switching to widget factory
327
+ _widgetDatepicker: function() {
328
+ return this.dpDiv;
329
+ },
330
+
331
+ /* Override the default settings for all instances of the date picker.
332
+ @param settings object - the new settings to use as defaults (anonymous object)
333
+ @return the manager object */
334
+ setDefaults: function(settings) {
335
+ extendRemove(this._defaults, settings || {});
336
+ return this;
337
+ },
338
+
339
+ /* Attach the date picker to a jQuery selection.
340
+ @param target element - the target input field or division or span
341
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
342
+ _attachDatepicker: function(target, settings) {
343
+ // check for settings on the control itself - in namespace 'date:'
344
+ var inlineSettings = null;
345
+ for (var attrName in this._defaults) {
346
+ var attrValue = target.getAttribute('date:' + attrName);
347
+ if (attrValue) {
348
+ inlineSettings = inlineSettings || {};
349
+ try {
350
+ inlineSettings[attrName] = eval(attrValue);
351
+ } catch (err) {
352
+ inlineSettings[attrName] = attrValue;
353
+ }
354
+ }
355
+ }
356
+ var nodeName = target.nodeName.toLowerCase();
357
+ var inline = (nodeName == 'div' || nodeName == 'span');
358
+ if (!target.id)
359
+ target.id = 'dp' + (++this.uuid);
360
+ var inst = this._newInst($(target), inline);
361
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
362
+ if (nodeName == 'input') {
363
+ this._connectDatepicker(target, inst);
364
+ } else if (inline) {
365
+ this._inlineDatepicker(target, inst);
366
+ }
367
+ },
368
+
369
+ /* Create a new instance object. */
370
+ _newInst: function(target, inline) {
371
+ var id = target[0].id.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars
372
+ return {id: id, input: target, // associated target
373
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
374
+ drawMonth: 0, drawYear: 0, // month being drawn
375
+ inline: inline, // is datepicker inline or not
376
+ dpDiv: (!inline ? this.dpDiv : // presentation div
377
+ $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
378
+ },
379
+
380
+ /* Attach the date picker to an input field. */
381
+ _connectDatepicker: function(target, inst) {
382
+ var input = $(target);
383
+ inst.append = $([]);
384
+ inst.trigger = $([]);
385
+ if (input.hasClass(this.markerClassName))
386
+ return;
387
+ this._attachments(input, inst);
388
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
389
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
390
+ bind("setData.datepicker", function(event, key, value) {
391
+ inst.settings[key] = value;
392
+ }).bind("getData.datepicker", function(event, key) {
393
+ return this._get(inst, key);
394
+ });
395
+ this._autoSize(inst);
396
+ $.data(target, PROP_NAME, inst);
397
+ },
398
+
399
+ /* Make attachments based on settings. */
400
+ _attachments: function(input, inst) {
401
+ var appendText = this._get(inst, 'appendText');
402
+ var isRTL = this._get(inst, 'isRTL');
403
+ if (inst.append)
404
+ inst.append.remove();
405
+ if (appendText) {
406
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
407
+ input[isRTL ? 'before' : 'after'](inst.append);
408
+ }
409
+ input.unbind('focus', this._showDatepicker);
410
+ if (inst.trigger)
411
+ inst.trigger.remove();
412
+ var showOn = this._get(inst, 'showOn');
413
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
414
+ input.focus(this._showDatepicker);
415
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
416
+ var buttonText = this._get(inst, 'buttonText');
417
+ var buttonImage = this._get(inst, 'buttonImage');
418
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
419
+ $('<img/>').addClass(this._triggerClass).
420
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
421
+ $('<button type="button"></button>').addClass(this._triggerClass).
422
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
423
+ { src:buttonImage, alt:buttonText, title:buttonText })));
424
+ input[isRTL ? 'before' : 'after'](inst.trigger);
425
+ inst.trigger.click(function() {
426
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
427
+ $.datepicker._hideDatepicker();
428
+ else
429
+ $.datepicker._showDatepicker(input[0]);
430
+ return false;
431
+ });
432
+ }
433
+ },
434
+
435
+ /* Apply the maximum length for the date format. */
436
+ _autoSize: function(inst) {
437
+ if (this._get(inst, 'autoSize') && !inst.inline) {
438
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
439
+ var dateFormat = this._get(inst, 'dateFormat');
440
+ if (dateFormat.match(/[DM]/)) {
441
+ var findMax = function(names) {
442
+ var max = 0;
443
+ var maxI = 0;
444
+ for (var i = 0; i < names.length; i++) {
445
+ if (names[i].length > max) {
446
+ max = names[i].length;
447
+ maxI = i;
448
+ }
449
+ }
450
+ return maxI;
451
+ };
452
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
453
+ 'monthNames' : 'monthNamesShort'))));
454
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
455
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
456
+ }
457
+ inst.input.attr('size', this._formatDate(inst, date).length);
458
+ }
459
+ },
460
+
461
+ /* Attach an inline date picker to a div. */
462
+ _inlineDatepicker: function(target, inst) {
463
+ var divSpan = $(target);
464
+ if (divSpan.hasClass(this.markerClassName))
465
+ return;
466
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
467
+ bind("setData.datepicker", function(event, key, value){
468
+ inst.settings[key] = value;
469
+ }).bind("getData.datepicker", function(event, key){
470
+ return this._get(inst, key);
471
+ });
472
+ $.data(target, PROP_NAME, inst);
473
+ this._setDate(inst, this._getDefaultDate(inst), true);
474
+ this._updateDatepicker(inst);
475
+ this._updateAlternate(inst);
476
+ },
477
+
478
+ /* Pop-up the date picker in a "dialog" box.
479
+ @param input element - ignored
480
+ @param date string or Date - the initial date to display
481
+ @param onSelect function - the function to call when a date is selected
482
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
483
+ @param pos int[2] - coordinates for the dialog's position within the screen or
484
+ event - with x/y coordinates or
485
+ leave empty for default (screen centre)
486
+ @return the manager object */
487
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
488
+ var inst = this._dialogInst; // internal instance
489
+ if (!inst) {
490
+ var id = 'dp' + (++this.uuid);
491
+ this._dialogInput = $('<input type="text" id="' + id +
492
+ '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
493
+ this._dialogInput.keydown(this._doKeyDown);
494
+ $('body').append(this._dialogInput);
495
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
496
+ inst.settings = {};
497
+ $.data(this._dialogInput[0], PROP_NAME, inst);
498
+ }
499
+ extendRemove(inst.settings, settings || {});
500
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
501
+ this._dialogInput.val(date);
502
+
503
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
504
+ if (!this._pos) {
505
+ var browserWidth = document.documentElement.clientWidth;
506
+ var browserHeight = document.documentElement.clientHeight;
507
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
508
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
509
+ this._pos = // should use actual width/height below
510
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
511
+ }
512
+
513
+ // move input on screen for focus, but hidden behind dialog
514
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
515
+ inst.settings.onSelect = onSelect;
516
+ this._inDialog = true;
517
+ this.dpDiv.addClass(this._dialogClass);
518
+ this._showDatepicker(this._dialogInput[0]);
519
+ if ($.blockUI)
520
+ $.blockUI(this.dpDiv);
521
+ $.data(this._dialogInput[0], PROP_NAME, inst);
522
+ return this;
523
+ },
524
+
525
+ /* Detach a datepicker from its control.
526
+ @param target element - the target input field or division or span */
527
+ _destroyDatepicker: function(target) {
528
+ var $target = $(target);
529
+ var inst = $.data(target, PROP_NAME);
530
+ if (!$target.hasClass(this.markerClassName)) {
531
+ return;
532
+ }
533
+ var nodeName = target.nodeName.toLowerCase();
534
+ $.removeData(target, PROP_NAME);
535
+ if (nodeName == 'input') {
536
+ inst.append.remove();
537
+ inst.trigger.remove();
538
+ $target.removeClass(this.markerClassName).
539
+ unbind('focus', this._showDatepicker).
540
+ unbind('keydown', this._doKeyDown).
541
+ unbind('keypress', this._doKeyPress).
542
+ unbind('keyup', this._doKeyUp);
543
+ } else if (nodeName == 'div' || nodeName == 'span')
544
+ $target.removeClass(this.markerClassName).empty();
545
+ },
546
+
547
+ /* Enable the date picker to a jQuery selection.
548
+ @param target element - the target input field or division or span */
549
+ _enableDatepicker: function(target) {
550
+ var $target = $(target);
551
+ var inst = $.data(target, PROP_NAME);
552
+ if (!$target.hasClass(this.markerClassName)) {
553
+ return;
554
+ }
555
+ var nodeName = target.nodeName.toLowerCase();
556
+ if (nodeName == 'input') {
557
+ target.disabled = false;
558
+ inst.trigger.filter('button').
559
+ each(function() { this.disabled = false; }).end().
560
+ filter('img').css({opacity: '1.0', cursor: ''});
561
+ }
562
+ else if (nodeName == 'div' || nodeName == 'span') {
563
+ var inline = $target.children('.' + this._inlineClass);
564
+ inline.children().removeClass('ui-state-disabled');
565
+ }
566
+ this._disabledInputs = $.map(this._disabledInputs,
567
+ function(value) { return (value == target ? null : value); }); // delete entry
568
+ },
569
+
570
+ /* Disable the date picker to a jQuery selection.
571
+ @param target element - the target input field or division or span */
572
+ _disableDatepicker: function(target) {
573
+ var $target = $(target);
574
+ var inst = $.data(target, PROP_NAME);
575
+ if (!$target.hasClass(this.markerClassName)) {
576
+ return;
577
+ }
578
+ var nodeName = target.nodeName.toLowerCase();
579
+ if (nodeName == 'input') {
580
+ target.disabled = true;
581
+ inst.trigger.filter('button').
582
+ each(function() { this.disabled = true; }).end().
583
+ filter('img').css({opacity: '0.5', cursor: 'default'});
584
+ }
585
+ else if (nodeName == 'div' || nodeName == 'span') {
586
+ var inline = $target.children('.' + this._inlineClass);
587
+ inline.children().addClass('ui-state-disabled');
588
+ }
589
+ this._disabledInputs = $.map(this._disabledInputs,
590
+ function(value) { return (value == target ? null : value); }); // delete entry
591
+ this._disabledInputs[this._disabledInputs.length] = target;
592
+ },
593
+
594
+ /* Is the first field in a jQuery collection disabled as a datepicker?
595
+ @param target element - the target input field or division or span
596
+ @return boolean - true if disabled, false if enabled */
597
+ _isDisabledDatepicker: function(target) {
598
+ if (!target) {
599
+ return false;
600
+ }
601
+ for (var i = 0; i < this._disabledInputs.length; i++) {
602
+ if (this._disabledInputs[i] == target)
603
+ return true;
604
+ }
605
+ return false;
606
+ },
607
+
608
+ /* Retrieve the instance data for the target control.
609
+ @param target element - the target input field or division or span
610
+ @return object - the associated instance data
611
+ @throws error if a jQuery problem getting data */
612
+ _getInst: function(target) {
613
+ try {
614
+ return $.data(target, PROP_NAME);
615
+ }
616
+ catch (err) {
617
+ throw 'Missing instance data for this datepicker';
618
+ }
619
+ },
620
+
621
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
622
+ @param target element - the target input field or division or span
623
+ @param name object - the new settings to update or
624
+ string - the name of the setting to change or retrieve,
625
+ when retrieving also 'all' for all instance settings or
626
+ 'defaults' for all global defaults
627
+ @param value any - the new value for the setting
628
+ (omit if above is an object or to retrieve a value) */
629
+ _optionDatepicker: function(target, name, value) {
630
+ var inst = this._getInst(target);
631
+ if (arguments.length == 2 && typeof name == 'string') {
632
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
633
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
634
+ this._get(inst, name)) : null));
635
+ }
636
+ var settings = name || {};
637
+ if (typeof name == 'string') {
638
+ settings = {};
639
+ settings[name] = value;
640
+ }
641
+ if (inst) {
642
+ if (this._curInst == inst) {
643
+ this._hideDatepicker();
644
+ }
645
+ var date = this._getDateDatepicker(target, true);
646
+ extendRemove(inst.settings, settings);
647
+ this._attachments($(target), inst);
648
+ this._autoSize(inst);
649
+ this._setDateDatepicker(target, date);
650
+ this._updateDatepicker(inst);
651
+ }
652
+ },
653
+
654
+ // change method deprecated
655
+ _changeDatepicker: function(target, name, value) {
656
+ this._optionDatepicker(target, name, value);
657
+ },
658
+
659
+ /* Redraw the date picker attached to an input field or division.
660
+ @param target element - the target input field or division or span */
661
+ _refreshDatepicker: function(target) {
662
+ var inst = this._getInst(target);
663
+ if (inst) {
664
+ this._updateDatepicker(inst);
665
+ }
666
+ },
667
+
668
+ /* Set the dates for a jQuery selection.
669
+ @param target element - the target input field or division or span
670
+ @param date Date - the new date */
671
+ _setDateDatepicker: function(target, date) {
672
+ var inst = this._getInst(target);
673
+ if (inst) {
674
+ this._setDate(inst, date);
675
+ this._updateDatepicker(inst);
676
+ this._updateAlternate(inst);
677
+ }
678
+ },
679
+
680
+ /* Get the date(s) for the first entry in a jQuery selection.
681
+ @param target element - the target input field or division or span
682
+ @param noDefault boolean - true if no default date is to be used
683
+ @return Date - the current date */
684
+ _getDateDatepicker: function(target, noDefault) {
685
+ var inst = this._getInst(target);
686
+ if (inst && !inst.inline)
687
+ this._setDateFromField(inst, noDefault);
688
+ return (inst ? this._getDate(inst) : null);
689
+ },
690
+
691
+ /* Handle keystrokes. */
692
+ _doKeyDown: function(event) {
693
+ var inst = $.datepicker._getInst(event.target);
694
+ var handled = true;
695
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
696
+ inst._keyEvent = true;
697
+ if ($.datepicker._datepickerShowing)
698
+ switch (event.keyCode) {
699
+ case 9: $.datepicker._hideDatepicker();
700
+ handled = false;
701
+ break; // hide on tab out
702
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
703
+ add($('td.' + $.datepicker._currentClass, inst.dpDiv));
704
+ if (sel[0])
705
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
706
+ else
707
+ $.datepicker._hideDatepicker();
708
+ return false; // don't submit the form
709
+ break; // select the value on enter
710
+ case 27: $.datepicker._hideDatepicker();
711
+ break; // hide on escape
712
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
713
+ -$.datepicker._get(inst, 'stepBigMonths') :
714
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
715
+ break; // previous month/year on page up/+ ctrl
716
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
717
+ +$.datepicker._get(inst, 'stepBigMonths') :
718
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
719
+ break; // next month/year on page down/+ ctrl
720
+ case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
721
+ handled = event.ctrlKey || event.metaKey;
722
+ break; // clear on ctrl or command +end
723
+ case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
724
+ handled = event.ctrlKey || event.metaKey;
725
+ break; // current on ctrl or command +home
726
+ case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
727
+ handled = event.ctrlKey || event.metaKey;
728
+ // -1 day on ctrl or command +left
729
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
730
+ -$.datepicker._get(inst, 'stepBigMonths') :
731
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
732
+ // next month/year on alt +left on Mac
733
+ break;
734
+ case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
735
+ handled = event.ctrlKey || event.metaKey;
736
+ break; // -1 week on ctrl or command +up
737
+ case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
738
+ handled = event.ctrlKey || event.metaKey;
739
+ // +1 day on ctrl or command +right
740
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
741
+ +$.datepicker._get(inst, 'stepBigMonths') :
742
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
743
+ // next month/year on alt +right
744
+ break;
745
+ case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
746
+ handled = event.ctrlKey || event.metaKey;
747
+ break; // +1 week on ctrl or command +down
748
+ default: handled = false;
749
+ }
750
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
751
+ $.datepicker._showDatepicker(this);
752
+ else {
753
+ handled = false;
754
+ }
755
+ if (handled) {
756
+ event.preventDefault();
757
+ event.stopPropagation();
758
+ }
759
+ },
760
+
761
+ /* Filter entered characters - based on date format. */
762
+ _doKeyPress: function(event) {
763
+ var inst = $.datepicker._getInst(event.target);
764
+ if ($.datepicker._get(inst, 'constrainInput')) {
765
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
766
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
767
+ return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
768
+ }
769
+ },
770
+
771
+ /* Synchronise manual entry and field/alternate field. */
772
+ _doKeyUp: function(event) {
773
+ var inst = $.datepicker._getInst(event.target);
774
+ if (inst.input.val() != inst.lastVal) {
775
+ try {
776
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
777
+ (inst.input ? inst.input.val() : null),
778
+ $.datepicker._getFormatConfig(inst));
779
+ if (date) { // only if valid
780
+ $.datepicker._setDateFromField(inst);
781
+ $.datepicker._updateAlternate(inst);
782
+ $.datepicker._updateDatepicker(inst);
783
+ }
784
+ }
785
+ catch (event) {
786
+ $.datepicker.log(event);
787
+ }
788
+ }
789
+ return true;
790
+ },
791
+
792
+ /* Pop-up the date picker for a given input field.
793
+ @param input element - the input field attached to the date picker or
794
+ event - if triggered by focus */
795
+ _showDatepicker: function(input) {
796
+ input = input.target || input;
797
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
798
+ input = $('input', input.parentNode)[0];
799
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
800
+ return;
801
+ var inst = $.datepicker._getInst(input);
802
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
803
+ $.datepicker._curInst.dpDiv.stop(true, true);
804
+ }
805
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
806
+ extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
807
+ inst.lastVal = null;
808
+ $.datepicker._lastInput = input;
809
+ $.datepicker._setDateFromField(inst);
810
+ if ($.datepicker._inDialog) // hide cursor
811
+ input.value = '';
812
+ if (!$.datepicker._pos) { // position below input
813
+ $.datepicker._pos = $.datepicker._findPos(input);
814
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
815
+ }
816
+ var isFixed = false;
817
+ $(input).parents().each(function() {
818
+ isFixed |= $(this).css('position') == 'fixed';
819
+ return !isFixed;
820
+ });
821
+ if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
822
+ $.datepicker._pos[0] -= document.documentElement.scrollLeft;
823
+ $.datepicker._pos[1] -= document.documentElement.scrollTop;
824
+ }
825
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
826
+ $.datepicker._pos = null;
827
+ // determine sizing offscreen
828
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
829
+ $.datepicker._updateDatepicker(inst);
830
+ // fix width for dynamic number of date pickers
831
+ // and adjust position before showing
832
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
833
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
834
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
835
+ left: offset.left + 'px', top: offset.top + 'px'});
836
+ if (!inst.inline) {
837
+ var showAnim = $.datepicker._get(inst, 'showAnim');
838
+ var duration = $.datepicker._get(inst, 'duration');
839
+ var postProcess = function() {
840
+ $.datepicker._datepickerShowing = true;
841
+ var borders = $.datepicker._getBorders(inst.dpDiv);
842
+ inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
843
+ css({left: -borders[0], top: -borders[1],
844
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
845
+ };
846
+ inst.dpDiv.zIndex($(input).zIndex()+1);
847
+ if ($.effects && $.effects[showAnim])
848
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
849
+ else
850
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
851
+ if (!showAnim || !duration)
852
+ postProcess();
853
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
854
+ inst.input.focus();
855
+ $.datepicker._curInst = inst;
856
+ }
857
+ },
858
+
859
+ /* Generate the date picker content. */
860
+ _updateDatepicker: function(inst) {
861
+ var self = this;
862
+ var borders = $.datepicker._getBorders(inst.dpDiv);
863
+ inst.dpDiv.empty().append(this._generateHTML(inst))
864
+ .find('iframe.ui-datepicker-cover') // IE6- only
865
+ .css({left: -borders[0], top: -borders[1],
866
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
867
+ .end()
868
+ .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
869
+ .bind('mouseout', function(){
870
+ $(this).removeClass('ui-state-hover');
871
+ if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
872
+ if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
873
+ })
874
+ .bind('mouseover', function(){
875
+ if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
876
+ $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
877
+ $(this).addClass('ui-state-hover');
878
+ if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
879
+ if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
880
+ }
881
+ })
882
+ .end()
883
+ .find('.' + this._dayOverClass + ' a')
884
+ .trigger('mouseover')
885
+ .end();
886
+ var numMonths = this._getNumberOfMonths(inst);
887
+ var cols = numMonths[1];
888
+ var width = 17;
889
+ if (cols > 1)
890
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
891
+ else
892
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
893
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
894
+ 'Class']('ui-datepicker-multi');
895
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
896
+ 'Class']('ui-datepicker-rtl');
897
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
898
+ inst.input.is(':visible') && !inst.input.is(':disabled'))
899
+ inst.input.focus();
900
+ },
901
+
902
+ /* Retrieve the size of left and top borders for an element.
903
+ @param elem (jQuery object) the element of interest
904
+ @return (number[2]) the left and top borders */
905
+ _getBorders: function(elem) {
906
+ var convert = function(value) {
907
+ return {thin: 1, medium: 2, thick: 3}[value] || value;
908
+ };
909
+ return [parseFloat(convert(elem.css('border-left-width'))),
910
+ parseFloat(convert(elem.css('border-top-width')))];
911
+ },
912
+
913
+ /* Check positioning to remain on screen. */
914
+ _checkOffset: function(inst, offset, isFixed) {
915
+ var dpWidth = inst.dpDiv.outerWidth();
916
+ var dpHeight = inst.dpDiv.outerHeight();
917
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
918
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
919
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
920
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
921
+
922
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
923
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
924
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
925
+
926
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
927
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
928
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
929
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
930
+ Math.abs(dpHeight + inputHeight) : 0);
931
+
932
+ return offset;
933
+ },
934
+
935
+ /* Find an object's position on the screen. */
936
+ _findPos: function(obj) {
937
+ var inst = this._getInst(obj);
938
+ var isRTL = this._get(inst, 'isRTL');
939
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
940
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
941
+ }
942
+ var position = $(obj).offset();
943
+ return [position.left, position.top];
944
+ },
945
+
946
+ /* Hide the date picker from view.
947
+ @param input element - the input field attached to the date picker */
948
+ _hideDatepicker: function(input) {
949
+ var inst = this._curInst;
950
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
951
+ return;
952
+ if (this._datepickerShowing) {
953
+ var showAnim = this._get(inst, 'showAnim');
954
+ var duration = this._get(inst, 'duration');
955
+ var postProcess = function() {
956
+ $.datepicker._tidyDialog(inst);
957
+ this._curInst = null;
958
+ };
959
+ if ($.effects && $.effects[showAnim])
960
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
961
+ else
962
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
963
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
964
+ if (!showAnim)
965
+ postProcess();
966
+ var onClose = this._get(inst, 'onClose');
967
+ if (onClose)
968
+ onClose.apply((inst.input ? inst.input[0] : null),
969
+ [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback
970
+ this._datepickerShowing = false;
971
+ this._lastInput = null;
972
+ if (this._inDialog) {
973
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
974
+ if ($.blockUI) {
975
+ $.unblockUI();
976
+ $('body').append(this.dpDiv);
977
+ }
978
+ }
979
+ this._inDialog = false;
980
+ }
981
+ },
982
+
983
+ /* Tidy up after a dialog display. */
984
+ _tidyDialog: function(inst) {
985
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
986
+ },
987
+
988
+ /* Close date picker if clicked elsewhere. */
989
+ _checkExternalClick: function(event) {
990
+ if (!$.datepicker._curInst)
991
+ return;
992
+ var $target = $(event.target);
993
+ if ($target[0].id != $.datepicker._mainDivId &&
994
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
995
+ !$target.hasClass($.datepicker.markerClassName) &&
996
+ !$target.hasClass($.datepicker._triggerClass) &&
997
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
998
+ $.datepicker._hideDatepicker();
999
+ },
1000
+
1001
+ /* Adjust one of the date sub-fields. */
1002
+ _adjustDate: function(id, offset, period) {
1003
+ var target = $(id);
1004
+ var inst = this._getInst(target[0]);
1005
+ if (this._isDisabledDatepicker(target[0])) {
1006
+ return;
1007
+ }
1008
+ this._adjustInstDate(inst, offset +
1009
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
1010
+ period);
1011
+ this._updateDatepicker(inst);
1012
+ },
1013
+
1014
+ /* Action for current link. */
1015
+ _gotoToday: function(id) {
1016
+ var target = $(id);
1017
+ var inst = this._getInst(target[0]);
1018
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
1019
+ inst.selectedDay = inst.currentDay;
1020
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
1021
+ inst.drawYear = inst.selectedYear = inst.currentYear;
1022
+ }
1023
+ else {
1024
+ var date = new Date();
1025
+ inst.selectedDay = date.getDate();
1026
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1027
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1028
+ }
1029
+ this._notifyChange(inst);
1030
+ this._adjustDate(target);
1031
+ },
1032
+
1033
+ /* Action for selecting a new month/year. */
1034
+ _selectMonthYear: function(id, select, period) {
1035
+ var target = $(id);
1036
+ var inst = this._getInst(target[0]);
1037
+ inst._selectingMonthYear = false;
1038
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
1039
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
1040
+ parseInt(select.options[select.selectedIndex].value,10);
1041
+ this._notifyChange(inst);
1042
+ this._adjustDate(target);
1043
+ },
1044
+
1045
+ /* Restore input focus after not changing month/year. */
1046
+ _clickMonthYear: function(id) {
1047
+ var target = $(id);
1048
+ var inst = this._getInst(target[0]);
1049
+ if (inst.input && inst._selectingMonthYear && !$.browser.msie)
1050
+ inst.input.focus();
1051
+ inst._selectingMonthYear = !inst._selectingMonthYear;
1052
+ },
1053
+
1054
+ /* Action for selecting a day. */
1055
+ _selectDay: function(id, month, year, td) {
1056
+ var target = $(id);
1057
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
1058
+ return;
1059
+ }
1060
+ var inst = this._getInst(target[0]);
1061
+ inst.selectedDay = inst.currentDay = $('a', td).html();
1062
+ inst.selectedMonth = inst.currentMonth = month;
1063
+ inst.selectedYear = inst.currentYear = year;
1064
+ this._selectDate(id, this._formatDate(inst,
1065
+ inst.currentDay, inst.currentMonth, inst.currentYear));
1066
+ },
1067
+
1068
+ /* Erase the input field and hide the date picker. */
1069
+ _clearDate: function(id) {
1070
+ var target = $(id);
1071
+ var inst = this._getInst(target[0]);
1072
+ this._selectDate(target, '');
1073
+ },
1074
+
1075
+ /* Update the input field with the selected date. */
1076
+ _selectDate: function(id, dateStr) {
1077
+ var target = $(id);
1078
+ var inst = this._getInst(target[0]);
1079
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
1080
+ if (inst.input)
1081
+ inst.input.val(dateStr);
1082
+ this._updateAlternate(inst);
1083
+ var onSelect = this._get(inst, 'onSelect');
1084
+ if (onSelect)
1085
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
1086
+ else if (inst.input)
1087
+ inst.input.trigger('change'); // fire the change event
1088
+ if (inst.inline)
1089
+ this._updateDatepicker(inst);
1090
+ else {
1091
+ this._hideDatepicker();
1092
+ this._lastInput = inst.input[0];
1093
+ if (typeof(inst.input[0]) != 'object')
1094
+ inst.input.focus(); // restore focus
1095
+ this._lastInput = null;
1096
+ }
1097
+ },
1098
+
1099
+ /* Update any alternate field to synchronise with the main field. */
1100
+ _updateAlternate: function(inst) {
1101
+ var altField = this._get(inst, 'altField');
1102
+ if (altField) { // update alternate field too
1103
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
1104
+ var date = this._getDate(inst);
1105
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
1106
+ $(altField).each(function() { $(this).val(dateStr); });
1107
+ }
1108
+ },
1109
+
1110
+ /* Set as beforeShowDay function to prevent selection of weekends.
1111
+ @param date Date - the date to customise
1112
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
1113
+ noWeekends: function(date) {
1114
+ var day = date.getDay();
1115
+ return [(day > 0 && day < 6), ''];
1116
+ },
1117
+
1118
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1119
+ @param date Date - the date to get the week for
1120
+ @return number - the number of the week within the year that contains this date */
1121
+ iso8601Week: function(date) {
1122
+ var checkDate = new Date(date.getTime());
1123
+ // Find Thursday of this week starting on Monday
1124
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
1125
+ var time = checkDate.getTime();
1126
+ checkDate.setMonth(0); // Compare with Jan 1
1127
+ checkDate.setDate(1);
1128
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
1129
+ },
1130
+
1131
+ /* Parse a string value into a date object.
1132
+ See formatDate below for the possible formats.
1133
+
1134
+ @param format string - the expected format of the date
1135
+ @param value string - the date in the above format
1136
+ @param settings Object - attributes include:
1137
+ shortYearCutoff number - the cutoff year for determining the century (optional)
1138
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1139
+ dayNames string[7] - names of the days from Sunday (optional)
1140
+ monthNamesShort string[12] - abbreviated names of the months (optional)
1141
+ monthNames string[12] - names of the months (optional)
1142
+ @return Date - the extracted date value or null if value is blank */
1143
+ parseDate: function (format, value, settings) {
1144
+ if (format == null || value == null)
1145
+ throw 'Invalid arguments';
1146
+ value = (typeof value == 'object' ? value.toString() : value + '');
1147
+ if (value == '')
1148
+ return null;
1149
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
1150
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1151
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1152
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1153
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1154
+ var year = -1;
1155
+ var month = -1;
1156
+ var day = -1;
1157
+ var doy = -1;
1158
+ var literal = false;
1159
+ // Check whether a format character is doubled
1160
+ var lookAhead = function(match) {
1161
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1162
+ if (matches)
1163
+ iFormat++;
1164
+ return matches;
1165
+ };
1166
+ // Extract a number from the string value
1167
+ var getNumber = function(match) {
1168
+ lookAhead(match);
1169
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
1170
+ (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
1171
+ var digits = new RegExp('^\\d{1,' + size + '}');
1172
+ var num = value.substring(iValue).match(digits);
1173
+ if (!num)
1174
+ throw 'Missing number at position ' + iValue;
1175
+ iValue += num[0].length;
1176
+ return parseInt(num[0], 10);
1177
+ };
1178
+ // Extract a name from the string value and convert to an index
1179
+ var getName = function(match, shortNames, longNames) {
1180
+ var names = (lookAhead(match) ? longNames : shortNames);
1181
+ for (var i = 0; i < names.length; i++) {
1182
+ if (value.substr(iValue, names[i].length) == names[i]) {
1183
+ iValue += names[i].length;
1184
+ return i + 1;
1185
+ }
1186
+ }
1187
+ throw 'Unknown name at position ' + iValue;
1188
+ };
1189
+ // Confirm that a literal character matches the string value
1190
+ var checkLiteral = function() {
1191
+ if (value.charAt(iValue) != format.charAt(iFormat))
1192
+ throw 'Unexpected literal at position ' + iValue;
1193
+ iValue++;
1194
+ };
1195
+ var iValue = 0;
1196
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1197
+ if (literal)
1198
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1199
+ literal = false;
1200
+ else
1201
+ checkLiteral();
1202
+ else
1203
+ switch (format.charAt(iFormat)) {
1204
+ case 'd':
1205
+ day = getNumber('d');
1206
+ break;
1207
+ case 'D':
1208
+ getName('D', dayNamesShort, dayNames);
1209
+ break;
1210
+ case 'o':
1211
+ doy = getNumber('o');
1212
+ break;
1213
+ case 'm':
1214
+ month = getNumber('m');
1215
+ break;
1216
+ case 'M':
1217
+ month = getName('M', monthNamesShort, monthNames);
1218
+ break;
1219
+ case 'y':
1220
+ year = getNumber('y');
1221
+ break;
1222
+ case '@':
1223
+ var date = new Date(getNumber('@'));
1224
+ year = date.getFullYear();
1225
+ month = date.getMonth() + 1;
1226
+ day = date.getDate();
1227
+ break;
1228
+ case '!':
1229
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
1230
+ year = date.getFullYear();
1231
+ month = date.getMonth() + 1;
1232
+ day = date.getDate();
1233
+ break;
1234
+ case "'":
1235
+ if (lookAhead("'"))
1236
+ checkLiteral();
1237
+ else
1238
+ literal = true;
1239
+ break;
1240
+ default:
1241
+ checkLiteral();
1242
+ }
1243
+ }
1244
+ if (year == -1)
1245
+ year = new Date().getFullYear();
1246
+ else if (year < 100)
1247
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
1248
+ (year <= shortYearCutoff ? 0 : -100);
1249
+ if (doy > -1) {
1250
+ month = 1;
1251
+ day = doy;
1252
+ do {
1253
+ var dim = this._getDaysInMonth(year, month - 1);
1254
+ if (day <= dim)
1255
+ break;
1256
+ month++;
1257
+ day -= dim;
1258
+ } while (true);
1259
+ }
1260
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
1261
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
1262
+ throw 'Invalid date'; // E.g. 31/02/*
1263
+ return date;
1264
+ },
1265
+
1266
+ /* Standard date formats. */
1267
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
1268
+ COOKIE: 'D, dd M yy',
1269
+ ISO_8601: 'yy-mm-dd',
1270
+ RFC_822: 'D, d M y',
1271
+ RFC_850: 'DD, dd-M-y',
1272
+ RFC_1036: 'D, d M y',
1273
+ RFC_1123: 'D, d M yy',
1274
+ RFC_2822: 'D, d M yy',
1275
+ RSS: 'D, d M y', // RFC 822
1276
+ TICKS: '!',
1277
+ TIMESTAMP: '@',
1278
+ W3C: 'yy-mm-dd', // ISO 8601
1279
+
1280
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
1281
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
1282
+
1283
+ /* Format a date object into a string value.
1284
+ The format can be combinations of the following:
1285
+ d - day of month (no leading zero)
1286
+ dd - day of month (two digit)
1287
+ o - day of year (no leading zeros)
1288
+ oo - day of year (three digit)
1289
+ D - day name short
1290
+ DD - day name long
1291
+ m - month of year (no leading zero)
1292
+ mm - month of year (two digit)
1293
+ M - month name short
1294
+ MM - month name long
1295
+ y - year (two digit)
1296
+ yy - year (four digit)
1297
+ @ - Unix timestamp (ms since 01/01/1970)
1298
+ ! - Windows ticks (100ns since 01/01/0001)
1299
+ '...' - literal text
1300
+ '' - single quote
1301
+
1302
+ @param format string - the desired format of the date
1303
+ @param date Date - the date value to format
1304
+ @param settings Object - attributes include:
1305
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
1306
+ dayNames string[7] - names of the days from Sunday (optional)
1307
+ monthNamesShort string[12] - abbreviated names of the months (optional)
1308
+ monthNames string[12] - names of the months (optional)
1309
+ @return string - the date in the above format */
1310
+ formatDate: function (format, date, settings) {
1311
+ if (!date)
1312
+ return '';
1313
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
1314
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
1315
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
1316
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
1317
+ // Check whether a format character is doubled
1318
+ var lookAhead = function(match) {
1319
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1320
+ if (matches)
1321
+ iFormat++;
1322
+ return matches;
1323
+ };
1324
+ // Format a number, with leading zero if necessary
1325
+ var formatNumber = function(match, value, len) {
1326
+ var num = '' + value;
1327
+ if (lookAhead(match))
1328
+ while (num.length < len)
1329
+ num = '0' + num;
1330
+ return num;
1331
+ };
1332
+ // Format a name, short or long as requested
1333
+ var formatName = function(match, value, shortNames, longNames) {
1334
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
1335
+ };
1336
+ var output = '';
1337
+ var literal = false;
1338
+ if (date)
1339
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
1340
+ if (literal)
1341
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1342
+ literal = false;
1343
+ else
1344
+ output += format.charAt(iFormat);
1345
+ else
1346
+ switch (format.charAt(iFormat)) {
1347
+ case 'd':
1348
+ output += formatNumber('d', date.getDate(), 2);
1349
+ break;
1350
+ case 'D':
1351
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
1352
+ break;
1353
+ case 'o':
1354
+ output += formatNumber('o',
1355
+ (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
1356
+ break;
1357
+ case 'm':
1358
+ output += formatNumber('m', date.getMonth() + 1, 2);
1359
+ break;
1360
+ case 'M':
1361
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
1362
+ break;
1363
+ case 'y':
1364
+ output += (lookAhead('y') ? date.getFullYear() :
1365
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
1366
+ break;
1367
+ case '@':
1368
+ output += date.getTime();
1369
+ break;
1370
+ case '!':
1371
+ output += date.getTime() * 10000 + this._ticksTo1970;
1372
+ break;
1373
+ case "'":
1374
+ if (lookAhead("'"))
1375
+ output += "'";
1376
+ else
1377
+ literal = true;
1378
+ break;
1379
+ default:
1380
+ output += format.charAt(iFormat);
1381
+ }
1382
+ }
1383
+ return output;
1384
+ },
1385
+
1386
+ /* Extract all possible characters from the date format. */
1387
+ _possibleChars: function (format) {
1388
+ var chars = '';
1389
+ var literal = false;
1390
+ // Check whether a format character is doubled
1391
+ var lookAhead = function(match) {
1392
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
1393
+ if (matches)
1394
+ iFormat++;
1395
+ return matches;
1396
+ };
1397
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
1398
+ if (literal)
1399
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
1400
+ literal = false;
1401
+ else
1402
+ chars += format.charAt(iFormat);
1403
+ else
1404
+ switch (format.charAt(iFormat)) {
1405
+ case 'd': case 'm': case 'y': case '@':
1406
+ chars += '0123456789';
1407
+ break;
1408
+ case 'D': case 'M':
1409
+ return null; // Accept anything
1410
+ case "'":
1411
+ if (lookAhead("'"))
1412
+ chars += "'";
1413
+ else
1414
+ literal = true;
1415
+ break;
1416
+ default:
1417
+ chars += format.charAt(iFormat);
1418
+ }
1419
+ return chars;
1420
+ },
1421
+
1422
+ /* Get a setting value, defaulting if necessary. */
1423
+ _get: function(inst, name) {
1424
+ return inst.settings[name] !== undefined ?
1425
+ inst.settings[name] : this._defaults[name];
1426
+ },
1427
+
1428
+ /* Parse existing date and initialise date picker. */
1429
+ _setDateFromField: function(inst, noDefault) {
1430
+ if (inst.input.val() == inst.lastVal) {
1431
+ return;
1432
+ }
1433
+ var dateFormat = this._get(inst, 'dateFormat');
1434
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
1435
+ var date, defaultDate;
1436
+ date = defaultDate = this._getDefaultDate(inst);
1437
+ var settings = this._getFormatConfig(inst);
1438
+ try {
1439
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
1440
+ } catch (event) {
1441
+ this.log(event);
1442
+ dates = (noDefault ? '' : dates);
1443
+ }
1444
+ inst.selectedDay = date.getDate();
1445
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1446
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1447
+ inst.currentDay = (dates ? date.getDate() : 0);
1448
+ inst.currentMonth = (dates ? date.getMonth() : 0);
1449
+ inst.currentYear = (dates ? date.getFullYear() : 0);
1450
+ this._adjustInstDate(inst);
1451
+ },
1452
+
1453
+ /* Retrieve the default date shown on opening. */
1454
+ _getDefaultDate: function(inst) {
1455
+ return this._restrictMinMax(inst,
1456
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
1457
+ },
1458
+
1459
+ /* A date may be specified as an exact value or a relative one. */
1460
+ _determineDate: function(inst, date, defaultDate) {
1461
+ var offsetNumeric = function(offset) {
1462
+ var date = new Date();
1463
+ date.setDate(date.getDate() + offset);
1464
+ return date;
1465
+ };
1466
+ var offsetString = function(offset) {
1467
+ try {
1468
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
1469
+ offset, $.datepicker._getFormatConfig(inst));
1470
+ }
1471
+ catch (e) {
1472
+ // Ignore
1473
+ }
1474
+ var date = (offset.toLowerCase().match(/^c/) ?
1475
+ $.datepicker._getDate(inst) : null) || new Date();
1476
+ var year = date.getFullYear();
1477
+ var month = date.getMonth();
1478
+ var day = date.getDate();
1479
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
1480
+ var matches = pattern.exec(offset);
1481
+ while (matches) {
1482
+ switch (matches[2] || 'd') {
1483
+ case 'd' : case 'D' :
1484
+ day += parseInt(matches[1],10); break;
1485
+ case 'w' : case 'W' :
1486
+ day += parseInt(matches[1],10) * 7; break;
1487
+ case 'm' : case 'M' :
1488
+ month += parseInt(matches[1],10);
1489
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
1490
+ break;
1491
+ case 'y': case 'Y' :
1492
+ year += parseInt(matches[1],10);
1493
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
1494
+ break;
1495
+ }
1496
+ matches = pattern.exec(offset);
1497
+ }
1498
+ return new Date(year, month, day);
1499
+ };
1500
+ date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
1501
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
1502
+ date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
1503
+ if (date) {
1504
+ date.setHours(0);
1505
+ date.setMinutes(0);
1506
+ date.setSeconds(0);
1507
+ date.setMilliseconds(0);
1508
+ }
1509
+ return this._daylightSavingAdjust(date);
1510
+ },
1511
+
1512
+ /* Handle switch to/from daylight saving.
1513
+ Hours may be non-zero on daylight saving cut-over:
1514
+ > 12 when midnight changeover, but then cannot generate
1515
+ midnight datetime, so jump to 1AM, otherwise reset.
1516
+ @param date (Date) the date to check
1517
+ @return (Date) the corrected date */
1518
+ _daylightSavingAdjust: function(date) {
1519
+ if (!date) return null;
1520
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
1521
+ return date;
1522
+ },
1523
+
1524
+ /* Set the date(s) directly. */
1525
+ _setDate: function(inst, date, noChange) {
1526
+ var clear = !(date);
1527
+ var origMonth = inst.selectedMonth;
1528
+ var origYear = inst.selectedYear;
1529
+ date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
1530
+ inst.selectedDay = inst.currentDay = date.getDate();
1531
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
1532
+ inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
1533
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
1534
+ this._notifyChange(inst);
1535
+ this._adjustInstDate(inst);
1536
+ if (inst.input) {
1537
+ inst.input.val(clear ? '' : this._formatDate(inst));
1538
+ }
1539
+ },
1540
+
1541
+ /* Retrieve the date(s) directly. */
1542
+ _getDate: function(inst) {
1543
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
1544
+ this._daylightSavingAdjust(new Date(
1545
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
1546
+ return startDate;
1547
+ },
1548
+
1549
+ /* Generate the HTML for the current state of the date picker. */
1550
+ _generateHTML: function(inst) {
1551
+ var today = new Date();
1552
+ today = this._daylightSavingAdjust(
1553
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
1554
+ var isRTL = this._get(inst, 'isRTL');
1555
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
1556
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
1557
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
1558
+ var numMonths = this._getNumberOfMonths(inst);
1559
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
1560
+ var stepMonths = this._get(inst, 'stepMonths');
1561
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
1562
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
1563
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1564
+ var minDate = this._getMinMaxDate(inst, 'min');
1565
+ var maxDate = this._getMinMaxDate(inst, 'max');
1566
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
1567
+ var drawYear = inst.drawYear;
1568
+ if (drawMonth < 0) {
1569
+ drawMonth += 12;
1570
+ drawYear--;
1571
+ }
1572
+ if (maxDate) {
1573
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
1574
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
1575
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
1576
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
1577
+ drawMonth--;
1578
+ if (drawMonth < 0) {
1579
+ drawMonth = 11;
1580
+ drawYear--;
1581
+ }
1582
+ }
1583
+ }
1584
+ inst.drawMonth = drawMonth;
1585
+ inst.drawYear = drawYear;
1586
+ var prevText = this._get(inst, 'prevText');
1587
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
1588
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
1589
+ this._getFormatConfig(inst)));
1590
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
1591
+ '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
1592
+ '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
1593
+ ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
1594
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
1595
+ var nextText = this._get(inst, 'nextText');
1596
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
1597
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
1598
+ this._getFormatConfig(inst)));
1599
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
1600
+ '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
1601
+ '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
1602
+ ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
1603
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
1604
+ var currentText = this._get(inst, 'currentText');
1605
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
1606
+ currentText = (!navigationAsDateFormat ? currentText :
1607
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
1608
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
1609
+ '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
1610
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
1611
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
1612
+ '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
1613
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
1614
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
1615
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
1616
+ var showWeek = this._get(inst, 'showWeek');
1617
+ var dayNames = this._get(inst, 'dayNames');
1618
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
1619
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
1620
+ var monthNames = this._get(inst, 'monthNames');
1621
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
1622
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
1623
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
1624
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
1625
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
1626
+ var defaultDate = this._getDefaultDate(inst);
1627
+ var html = '';
1628
+ for (var row = 0; row < numMonths[0]; row++) {
1629
+ var group = '';
1630
+ for (var col = 0; col < numMonths[1]; col++) {
1631
+ var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
1632
+ var cornerClass = ' ui-corner-all';
1633
+ var calender = '';
1634
+ if (isMultiMonth) {
1635
+ calender += '<div class="ui-datepicker-group';
1636
+ if (numMonths[1] > 1)
1637
+ switch (col) {
1638
+ case 0: calender += ' ui-datepicker-group-first';
1639
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
1640
+ case numMonths[1]-1: calender += ' ui-datepicker-group-last';
1641
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
1642
+ default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
1643
+ }
1644
+ calender += '">';
1645
+ }
1646
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
1647
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
1648
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
1649
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
1650
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
1651
+ '</div><table class="ui-datepicker-calendar"><thead>' +
1652
+ '<tr>';
1653
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
1654
+ for (var dow = 0; dow < 7; dow++) { // days of the week
1655
+ var day = (dow + firstDay) % 7;
1656
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
1657
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
1658
+ }
1659
+ calender += thead + '</tr></thead><tbody>';
1660
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
1661
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
1662
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
1663
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
1664
+ var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
1665
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
1666
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
1667
+ calender += '<tr>';
1668
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
1669
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
1670
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
1671
+ var daySettings = (beforeShowDay ?
1672
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
1673
+ var otherMonth = (printDate.getMonth() != drawMonth);
1674
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
1675
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
1676
+ tbody += '<td class="' +
1677
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
1678
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
1679
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
1680
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
1681
+ // or defaultDate is current printedDate and defaultDate is selectedDate
1682
+ ' ' + this._dayOverClass : '') + // highlight selected day
1683
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
1684
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
1685
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
1686
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
1687
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
1688
+ (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
1689
+ inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
1690
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
1691
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
1692
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
1693
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
1694
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
1695
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
1696
+ printDate.setDate(printDate.getDate() + 1);
1697
+ printDate = this._daylightSavingAdjust(printDate);
1698
+ }
1699
+ calender += tbody + '</tr>';
1700
+ }
1701
+ drawMonth++;
1702
+ if (drawMonth > 11) {
1703
+ drawMonth = 0;
1704
+ drawYear++;
1705
+ }
1706
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
1707
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
1708
+ group += calender;
1709
+ }
1710
+ html += group;
1711
+ }
1712
+ html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
1713
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
1714
+ inst._keyEvent = false;
1715
+ return html;
1716
+ },
1717
+
1718
+ /* Generate the month and year header. */
1719
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
1720
+ secondary, monthNames, monthNamesShort) {
1721
+ var changeMonth = this._get(inst, 'changeMonth');
1722
+ var changeYear = this._get(inst, 'changeYear');
1723
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
1724
+ var html = '<div class="ui-datepicker-title">';
1725
+ var monthHtml = '';
1726
+ // month selection
1727
+ if (secondary || !changeMonth)
1728
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
1729
+ else {
1730
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
1731
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
1732
+ monthHtml += '<select class="ui-datepicker-month" ' +
1733
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
1734
+ 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
1735
+ '>';
1736
+ for (var month = 0; month < 12; month++) {
1737
+ if ((!inMinYear || month >= minDate.getMonth()) &&
1738
+ (!inMaxYear || month <= maxDate.getMonth()))
1739
+ monthHtml += '<option value="' + month + '"' +
1740
+ (month == drawMonth ? ' selected="selected"' : '') +
1741
+ '>' + monthNamesShort[month] + '</option>';
1742
+ }
1743
+ monthHtml += '</select>';
1744
+ }
1745
+ if (!showMonthAfterYear)
1746
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
1747
+ // year selection
1748
+ if (secondary || !changeYear)
1749
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
1750
+ else {
1751
+ // determine range of years to display
1752
+ var years = this._get(inst, 'yearRange').split(':');
1753
+ var thisYear = new Date().getFullYear();
1754
+ var determineYear = function(value) {
1755
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
1756
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
1757
+ parseInt(value, 10)));
1758
+ return (isNaN(year) ? thisYear : year);
1759
+ };
1760
+ var year = determineYear(years[0]);
1761
+ var endYear = Math.max(year, determineYear(years[1] || ''));
1762
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
1763
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
1764
+ html += '<select class="ui-datepicker-year" ' +
1765
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
1766
+ 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
1767
+ '>';
1768
+ for (; year <= endYear; year++) {
1769
+ html += '<option value="' + year + '"' +
1770
+ (year == drawYear ? ' selected="selected"' : '') +
1771
+ '>' + year + '</option>';
1772
+ }
1773
+ html += '</select>';
1774
+ }
1775
+ html += this._get(inst, 'yearSuffix');
1776
+ if (showMonthAfterYear)
1777
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
1778
+ html += '</div>'; // Close datepicker_header
1779
+ return html;
1780
+ },
1781
+
1782
+ /* Adjust one of the date sub-fields. */
1783
+ _adjustInstDate: function(inst, offset, period) {
1784
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
1785
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
1786
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
1787
+ (period == 'D' ? offset : 0);
1788
+ var date = this._restrictMinMax(inst,
1789
+ this._daylightSavingAdjust(new Date(year, month, day)));
1790
+ inst.selectedDay = date.getDate();
1791
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
1792
+ inst.drawYear = inst.selectedYear = date.getFullYear();
1793
+ if (period == 'M' || period == 'Y')
1794
+ this._notifyChange(inst);
1795
+ },
1796
+
1797
+ /* Ensure a date is within any min/max bounds. */
1798
+ _restrictMinMax: function(inst, date) {
1799
+ var minDate = this._getMinMaxDate(inst, 'min');
1800
+ var maxDate = this._getMinMaxDate(inst, 'max');
1801
+ date = (minDate && date < minDate ? minDate : date);
1802
+ date = (maxDate && date > maxDate ? maxDate : date);
1803
+ return date;
1804
+ },
1805
+
1806
+ /* Notify change of month/year. */
1807
+ _notifyChange: function(inst) {
1808
+ var onChange = this._get(inst, 'onChangeMonthYear');
1809
+ if (onChange)
1810
+ onChange.apply((inst.input ? inst.input[0] : null),
1811
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
1812
+ },
1813
+
1814
+ /* Determine the number of months to show. */
1815
+ _getNumberOfMonths: function(inst) {
1816
+ var numMonths = this._get(inst, 'numberOfMonths');
1817
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
1818
+ },
1819
+
1820
+ /* Determine the current maximum date - ensure no time components are set. */
1821
+ _getMinMaxDate: function(inst, minMax) {
1822
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
1823
+ },
1824
+
1825
+ /* Find the number of days in a given month. */
1826
+ _getDaysInMonth: function(year, month) {
1827
+ return 32 - new Date(year, month, 32).getDate();
1828
+ },
1829
+
1830
+ /* Find the day of the week of the first of a month. */
1831
+ _getFirstDayOfMonth: function(year, month) {
1832
+ return new Date(year, month, 1).getDay();
1833
+ },
1834
+
1835
+ /* Determines if we should allow a "next/prev" month display change. */
1836
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
1837
+ var numMonths = this._getNumberOfMonths(inst);
1838
+ var date = this._daylightSavingAdjust(new Date(curYear,
1839
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
1840
+ if (offset < 0)
1841
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
1842
+ return this._isInRange(inst, date);
1843
+ },
1844
+
1845
+ /* Is the given date in the accepted range? */
1846
+ _isInRange: function(inst, date) {
1847
+ var minDate = this._getMinMaxDate(inst, 'min');
1848
+ var maxDate = this._getMinMaxDate(inst, 'max');
1849
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
1850
+ (!maxDate || date.getTime() <= maxDate.getTime()));
1851
+ },
1852
+
1853
+ /* Provide the configuration settings for formatting/parsing. */
1854
+ _getFormatConfig: function(inst) {
1855
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
1856
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
1857
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
1858
+ return {shortYearCutoff: shortYearCutoff,
1859
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
1860
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
1861
+ },
1862
+
1863
+ /* Format the given date for display. */
1864
+ _formatDate: function(inst, day, month, year) {
1865
+ if (!day) {
1866
+ inst.currentDay = inst.selectedDay;
1867
+ inst.currentMonth = inst.selectedMonth;
1868
+ inst.currentYear = inst.selectedYear;
1869
+ }
1870
+ var date = (day ? (typeof day == 'object' ? day :
1871
+ this._daylightSavingAdjust(new Date(year, month, day))) :
1872
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
1873
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
1874
+ }
1875
+ });
1876
+
1877
+ /* jQuery extend now ignores nulls! */
1878
+ function extendRemove(target, props) {
1879
+ $.extend(target, props);
1880
+ for (var name in props)
1881
+ if (props[name] == null || props[name] == undefined)
1882
+ target[name] = props[name];
1883
+ return target;
1884
+ };
1885
+
1886
+ /* Determine whether an object is an array. */
1887
+ function isArray(a) {
1888
+ return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
1889
+ (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
1890
+ };
1891
+
1892
+ /* Invoke the datepicker functionality.
1893
+ @param options string - a command, optionally followed by additional parameters or
1894
+ Object - settings for attaching new datepicker functionality
1895
+ @return jQuery object */
1896
+ $.fn.datepicker = function(options){
1897
+
1898
+ /* Initialise the date picker. */
1899
+ if (!$.datepicker.initialized) {
1900
+ $(document).mousedown($.datepicker._checkExternalClick).
1901
+ find('body').append($.datepicker.dpDiv);
1902
+ $.datepicker.initialized = true;
1903
+ }
1904
+
1905
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
1906
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
1907
+ return $.datepicker['_' + options + 'Datepicker'].
1908
+ apply($.datepicker, [this[0]].concat(otherArgs));
1909
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
1910
+ return $.datepicker['_' + options + 'Datepicker'].
1911
+ apply($.datepicker, [this[0]].concat(otherArgs));
1912
+ return this.each(function() {
1913
+ typeof options == 'string' ?
1914
+ $.datepicker['_' + options + 'Datepicker'].
1915
+ apply($.datepicker, [this].concat(otherArgs)) :
1916
+ $.datepicker._attachDatepicker(this, options);
1917
+ });
1918
+ };
1919
+
1920
+ $.datepicker = new Datepicker(); // singleton instance
1921
+ $.datepicker.initialized = false;
1922
+ $.datepicker.uuid = new Date().getTime();
1923
+ $.datepicker.version = "1.8.1";
1924
+
1925
+ // Workaround for #4055
1926
+ // Add another global to avoid noConflict issues with inline event handlers
1927
+ window['DP_jQuery_' + dpuuid] = $;
1928
+
1929
+ })(jQuery);
apps/jquery-tmpl/demos/movies/components/jquery-ui-1.8.1.custom.min.js ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI 1.8.1
3
+ *
4
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
6
+ * and GPL (GPL-LICENSE.txt) licenses.
7
+ *
8
+ * http://docs.jquery.com/UI
9
+ */
10
+ jQuery.ui||function(c){c.ui={version:"1.8.1",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")=="hidden")return false;
11
+ b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,
12
+ PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||
13
+ /absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==
14
+ undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&
15
+ !c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}(jQuery);
16
+ ;/*
17
+ * jQuery UI Datepicker 1.8.1
18
+ *
19
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
20
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
21
+ * and GPL (GPL-LICENSE.txt) licenses.
22
+ *
23
+ * http://docs.jquery.com/UI/Datepicker
24
+ *
25
+ * Depends:
26
+ * jquery.ui.core.js
27
+ */
28
+ (function(d){function J(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
29
+ "ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
30
+ "Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
31
+ minDate:null,maxDate:null,duration:"_default",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}function E(a,b){d.extend(a,
32
+ b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.1"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=
33
+ f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id)a.id="dp"+ ++this.uuid;var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
34
+ _connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
35
+ b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
36
+ ""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
37
+ c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
38
+ true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){a="dp"+ ++this.uuid;this._dialogInput=d('<input type="text" id="'+a+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==Date?
39
+ this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);
40
+ d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},
41
+ _enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=
42
+ d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;
43
+ for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&
44
+ this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&
45
+ !a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass,b.dpDiv).add(d("td."+d.datepicker._currentClass,b.dpDiv));c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();
46
+ return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||
47
+ a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,
48
+ a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));
49
+ var c=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||
50
+ a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);
51
+ d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&
52
+ d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,
53
+ h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");
54
+ this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");
55
+ this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");
56
+ a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),
57
+ k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"];
58
+ a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():
59
+ "",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&
60
+ !a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;
61
+ b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]);
62
+ a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a,
63
+ "")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||
64
+ this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;
65
+ for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"?4:p=="o"?3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+
66
+ s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,w,G){p=o(p)?G:w;for(w=0;w<p.length;w++)if(b.substr(s,p[w].length)==p[w]){s+=p[w].length;return w+1}throw"Unknown name at position "+s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(j)if(a.charAt(z)=="'"&&!o("'"))j=false;else r();else switch(a.charAt(z)){case "d":l=m("d");break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":k=m("m");break;case "M":k=n("M",i,g);break;
67
+ case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))r();else j=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,
68
+ k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?
69
+ c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+1<a.length&&a.charAt(j+1)==o)&&j++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},k=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var j=0;j<a.length;j++)if(u)if(a.charAt(j)=="'"&&!i("'"))u=false;else l+=a.charAt(j);else switch(a.charAt(j)){case "d":l+=g("d",b.getDate(),2);break;
70
+ case "D":l+=k("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=k("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(j)}return l},_possibleChars:function(a){for(var b="",c=false,
71
+ e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),
72
+ e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},
73
+ _determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,k=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,j=u.exec(h);j;){switch(j[2]||"d"){case "d":case "D":g+=parseInt(j[1],10);break;case "w":case "W":g+=parseInt(j[1],
74
+ 10)*7;break;case "m":case "M":l+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break;case "y":case "Y":k+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break}j=u.exec(h)}return new Date(k,l,g)};if(b=(b=b==null?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):b)&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;
75
+ a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||
76
+ a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?
77
+ new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&n<j?j:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));
78
+ n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,
79
+ g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&
80
+ a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+
81
+ y+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C<i[0];C++){for(var L=
82
+ "",D=0;D<i[1];D++){var M=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?
83
+ f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,
84
+ A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N<A;N++){x+="<tr>";var O=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&q<j||o&&q>o;O+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==M.getTime()&&g==a.selectedMonth&&
85
+ a._keyEvent||K.getTime()==q.getTime()&&K.getTime()==M.getTime()?" "+this._dayOverClass:"")+(I?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!w?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!B||w)&&F[2]?' title="'+F[2]+'"':"")+(I?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!w?"&#xa0;":I?'<span class="ui-state-default">'+q.getDate()+
86
+ "</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':
87
+ "");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='<div class="ui-datepicker-title">',o="";if(h||!k)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+
88
+ a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(j+=o+(h||!(k&&l)?"&#xa0;":""));if(h||!l)j+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,
89
+ i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)j+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";j+="</select>"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?"&#xa0;":"")+o;j+="</div>";return j},_adjustInstDate:function(a,b,c){var e=
90
+ a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,
91
+ "onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);
92
+ c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
93
+ "dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
94
+ function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));
95
+ return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.1";window["DP_jQuery_"+y]=d})(jQuery);
96
+ ;
apps/jquery-tmpl/demos/movies/components/jquery.pager.js ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery pager plugin
3
+ * Version 1.0 (12/22/2008)
4
+ * @requires jQuery v1.2.6 or later
5
+ *
6
+ * Example at: http://jonpauldavies.github.com/JQuery/Pager/PagerDemo.html
7
+ *
8
+ * Copyright (c) 2008-2009 Jon Paul Davies
9
+ * Dual licensed under the MIT and GPL licenses:
10
+ * http://www.opensource.org/licenses/mit-license.php
11
+ * http://www.gnu.org/licenses/gpl.html
12
+ *
13
+ * Read the related blog post and contact the author at http://www.j-dee.com/2008/12/22/jquery-pager-plugin/
14
+ *
15
+ * This version is far from perfect and doesn't manage it's own state, therefore contributions are more than welcome!
16
+ *
17
+ * Usage: .pager({ pagenumber: 1, pagecount: 15, buttonClickCallback: PagerClickTest });
18
+ *
19
+ * Where pagenumber is the visible page number
20
+ * pagecount is the total number of pages to display
21
+ * buttonClickCallback is the method to fire when a pager button is clicked.
22
+ *
23
+ * buttonClickCallback signiture is PagerClickTest = function(pageclickednumber)
24
+ * Where pageclickednumber is the number of the page clicked in the control.
25
+ *
26
+ * The included Pager.CSS file is a dependancy but can obviously tweaked to your wishes
27
+ * Tested in IE6 IE7 Firefox & Safari. Any browser strangeness, please report.
28
+ */
29
+ (function($) {
30
+
31
+ $.fn.pager = function(options) {
32
+
33
+ var opts = $.extend({}, $.fn.pager.defaults, options);
34
+
35
+ return this.each(function() {
36
+
37
+ // empty out the destination element and then render out the pager with the supplied options
38
+ $(this).empty().append(renderpager(parseInt(options.pagenumber), parseInt(options.pagecount), options.buttonClickCallback));
39
+
40
+ // specify correct cursor activity
41
+ $('.pages li').mouseover(function() { document.body.style.cursor = "pointer"; }).mouseout(function() { document.body.style.cursor = "auto"; });
42
+ });
43
+ };
44
+
45
+ // render and return the pager with the supplied options
46
+ function renderpager(pagenumber, pagecount, buttonClickCallback) {
47
+
48
+ // setup $pager to hold render
49
+ var $pager = $('<ul class="pages"></ul>');
50
+
51
+ // add in the previous and next buttons
52
+ $pager.append(renderButton('first', pagenumber, pagecount, buttonClickCallback)).append(renderButton('prev', pagenumber, pagecount, buttonClickCallback));
53
+
54
+ // pager currently only handles 10 viewable pages ( could be easily parameterized, maybe in next version ) so handle edge cases
55
+ var startPoint = 1;
56
+ var endPoint = 9;
57
+
58
+ if (pagenumber > 4) {
59
+ startPoint = pagenumber - 4;
60
+ endPoint = pagenumber + 4;
61
+ }
62
+
63
+ if (endPoint > pagecount) {
64
+ startPoint = pagecount - 8;
65
+ endPoint = pagecount;
66
+ }
67
+
68
+ if (startPoint < 1) {
69
+ startPoint = 1;
70
+ }
71
+
72
+ // loop thru visible pages and render buttons
73
+ for (var page = startPoint; page <= endPoint; page++) {
74
+
75
+ var currentButton = $('<li class="page-number">' + (page) + '</li>');
76
+
77
+ page == pagenumber ? currentButton.addClass('pgCurrent') : currentButton.click(function() { buttonClickCallback(this.firstChild.data); });
78
+ currentButton.appendTo($pager);
79
+ }
80
+
81
+ // render in the next and last buttons before returning the whole rendered control back.
82
+ $pager.append(renderButton('next', pagenumber, pagecount, buttonClickCallback)).append(renderButton('last', pagenumber, pagecount, buttonClickCallback));
83
+
84
+ return $pager;
85
+ }
86
+
87
+ // renders and returns a 'specialized' button, ie 'next', 'previous' etc. rather than a page number button
88
+ function renderButton(buttonLabel, pagenumber, pagecount, buttonClickCallback) {
89
+
90
+ var $Button = $('<li class="pgNext">' + buttonLabel + '</li>');
91
+
92
+ var destPage = 1;
93
+
94
+ // work out destination page for required button type
95
+ switch (buttonLabel) {
96
+ case "first":
97
+ destPage = 1;
98
+ break;
99
+ case "prev":
100
+ destPage = pagenumber - 1;
101
+ break;
102
+ case "next":
103
+ destPage = pagenumber + 1;
104
+ break;
105
+ case "last":
106
+ destPage = pagecount;
107
+ break;
108
+ }
109
+
110
+ // disable and 'grey' out buttons if not needed.
111
+ if (buttonLabel == "first" || buttonLabel == "prev") {
112
+ pagenumber <= 1 ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); });
113
+ }
114
+ else {
115
+ pagenumber >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function() { buttonClickCallback(destPage); });
116
+ }
117
+
118
+ return $Button;
119
+ }
120
+
121
+ // pager defaults. hardly worth bothering with in this case but used as placeholder for expansion in the next version
122
+ $.fn.pager.defaults = {
123
+ pagenumber: 1,
124
+ pagecount: 1
125
+ };
126
+
127
+ })(jQuery);
128
+
129
+
130
+
131
+
132
+
apps/jquery-tmpl/demos/movies/css/jquery-ui-1.8.1.custom.css ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery UI CSS Framework
3
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
4
+ * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
5
+ */
6
+
7
+ /* Layout helpers
8
+ ----------------------------------*/
9
+ .ui-helper-hidden { display: none; }
10
+ .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
11
+ .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
12
+ .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
13
+ .ui-helper-clearfix { display: inline-block; }
14
+ /* required comment for clearfix to work in Opera \*/
15
+ * html .ui-helper-clearfix { height:1%; }
16
+ .ui-helper-clearfix { display:block; }
17
+ /* end clearfix */
18
+ .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
19
+
20
+
21
+ /* Interaction Cues
22
+ ----------------------------------*/
23
+ .ui-state-disabled { cursor: default !important; }
24
+
25
+
26
+ /* Icons
27
+ ----------------------------------*/
28
+
29
+ /* states and images */
30
+ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
31
+
32
+
33
+ /* Misc visuals
34
+ ----------------------------------*/
35
+
36
+ /* Overlays */
37
+ .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
38
+
39
+
40
+ /*
41
+ * jQuery UI CSS Framework
42
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
43
+ * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
44
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial,sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=cc0000&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=15&borderColorHeader=e3a1a1&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=eeeeee&fcContent=333333&iconColorContent=cc0000&bgColorDefault=eeeeee&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=100&borderColorDefault=d8dcdf&fcDefault=004276&iconColorDefault=cc0000&bgColorHover=f6f6f6&bgTextureHover=04_highlight_hard.png&bgImgOpacityHover=100&borderColorHover=cdd5da&fcHover=111111&iconColorHover=cc0000&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=eeeeee&fcActive=cc0000&iconColorActive=cc0000&bgColorHighlight=fbf8ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcd3a1&fcHighlight=444444&iconColorHighlight=004276&bgColorError=f3d8d8&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=75&borderColorError=cc0000&fcError=2e2e2e&iconColorError=cc0000&bgColorOverlay=a6a6a6&bgTextureOverlay=09_dots_small.png&bgImgOpacityOverlay=65&opacityOverlay=40&bgColorShadow=333333&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=10&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
45
+ */
46
+
47
+
48
+ /* Component containers
49
+ ----------------------------------*/
50
+ .ui-widget { font-family: Arial,sans-serif; font-size: 1.1em; }
51
+ .ui-widget .ui-widget { font-size: 1em; }
52
+ .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial,sans-serif; font-size: 1em; }
53
+ .ui-widget-content { border: 1px solid #eeeeee; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #333333; }
54
+ .ui-widget-content a { color: #333333; }
55
+ .ui-widget-header { border: 1px solid #e3a1a1; background: #cc0000 url(images/ui-bg_highlight-soft_15_cc0000_1x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
56
+ .ui-widget-header a { color: #ffffff; }
57
+
58
+ /* Interaction states
59
+ ----------------------------------*/
60
+ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d8dcdf; background: #eeeeee url(images/ui-bg_highlight-hard_100_eeeeee_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #004276; }
61
+ .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #004276; text-decoration: none; }
62
+ .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #cdd5da; background: #f6f6f6 url(images/ui-bg_highlight-hard_100_f6f6f6_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #111111; }
63
+ .ui-state-hover a, .ui-state-hover a:hover { color: #111111; text-decoration: none; }
64
+ .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #eeeeee; background: #ffffff url(images/ui-bg_flat_65_ffffff_40x100.png) 50% 50% repeat-x; font-weight: bold; color: #cc0000; }
65
+ .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #cc0000; text-decoration: none; }
66
+ .ui-widget :active { outline: none; }
67
+
68
+ /* Interaction Cues
69
+ ----------------------------------*/
70
+ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcd3a1; background: #fbf8ee url(images/ui-bg_glass_55_fbf8ee_1x400.png) 50% 50% repeat-x; color: #444444; }
71
+ .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #444444; }
72
+ .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cc0000; background: #f3d8d8 url(images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png) 50% 50% repeat; color: #2e2e2e; }
73
+ .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #2e2e2e; }
74
+ .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #2e2e2e; }
75
+ .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
76
+ .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
77
+ .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
78
+
79
+ /* Icons
80
+ ----------------------------------*/
81
+
82
+ /* states and images */
83
+ .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_cc0000_256x240.png); }
84
+ .ui-widget-content .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
85
+ .ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
86
+ .ui-state-default .ui-icon { background-image: url(images/ui-icons_cc0000_256x240.png); }
87
+ .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
88
+ .ui-state-active .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
89
+ .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_004276_256x240.png); }
90
+ .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cc0000_256x240.png); }
91
+
92
+ /* positioning */
93
+ .ui-icon-carat-1-n { background-position: 0 0; }
94
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
95
+ .ui-icon-carat-1-e { background-position: -32px 0; }
96
+ .ui-icon-carat-1-se { background-position: -48px 0; }
97
+ .ui-icon-carat-1-s { background-position: -64px 0; }
98
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
99
+ .ui-icon-carat-1-w { background-position: -96px 0; }
100
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
101
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
102
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
103
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
104
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
105
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
106
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
107
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
108
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
109
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
110
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
111
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
112
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
113
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
114
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
115
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
116
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
117
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
118
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
119
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
120
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
121
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
122
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
123
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
124
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
125
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
126
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
127
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
128
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
129
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
130
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
131
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
132
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
133
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
134
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
135
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
136
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
137
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
138
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
139
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
140
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
141
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
142
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
143
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
144
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
145
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
146
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
147
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
148
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
149
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
150
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
151
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
152
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
153
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
154
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
155
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
156
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
157
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
158
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
159
+ .ui-icon-extlink { background-position: -32px -80px; }
160
+ .ui-icon-newwin { background-position: -48px -80px; }
161
+ .ui-icon-refresh { background-position: -64px -80px; }
162
+ .ui-icon-shuffle { background-position: -80px -80px; }
163
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
164
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
165
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
166
+ .ui-icon-folder-open { background-position: -16px -96px; }
167
+ .ui-icon-document { background-position: -32px -96px; }
168
+ .ui-icon-document-b { background-position: -48px -96px; }
169
+ .ui-icon-note { background-position: -64px -96px; }
170
+ .ui-icon-mail-closed { background-position: -80px -96px; }
171
+ .ui-icon-mail-open { background-position: -96px -96px; }
172
+ .ui-icon-suitcase { background-position: -112px -96px; }
173
+ .ui-icon-comment { background-position: -128px -96px; }
174
+ .ui-icon-person { background-position: -144px -96px; }
175
+ .ui-icon-print { background-position: -160px -96px; }
176
+ .ui-icon-trash { background-position: -176px -96px; }
177
+ .ui-icon-locked { background-position: -192px -96px; }
178
+ .ui-icon-unlocked { background-position: -208px -96px; }
179
+ .ui-icon-bookmark { background-position: -224px -96px; }
180
+ .ui-icon-tag { background-position: -240px -96px; }
181
+ .ui-icon-home { background-position: 0 -112px; }
182
+ .ui-icon-flag { background-position: -16px -112px; }
183
+ .ui-icon-calendar { background-position: -32px -112px; }
184
+ .ui-icon-cart { background-position: -48px -112px; }
185
+ .ui-icon-pencil { background-position: -64px -112px; }
186
+ .ui-icon-clock { background-position: -80px -112px; }
187
+ .ui-icon-disk { background-position: -96px -112px; }
188
+ .ui-icon-calculator { background-position: -112px -112px; }
189
+ .ui-icon-zoomin { background-position: -128px -112px; }
190
+ .ui-icon-zoomout { background-position: -144px -112px; }
191
+ .ui-icon-search { background-position: -160px -112px; }
192
+ .ui-icon-wrench { background-position: -176px -112px; }
193
+ .ui-icon-gear { background-position: -192px -112px; }
194
+ .ui-icon-heart { background-position: -208px -112px; }
195
+ .ui-icon-star { background-position: -224px -112px; }
196
+ .ui-icon-link { background-position: -240px -112px; }
197
+ .ui-icon-cancel { background-position: 0 -128px; }
198
+ .ui-icon-plus { background-position: -16px -128px; }
199
+ .ui-icon-plusthick { background-position: -32px -128px; }
200
+ .ui-icon-minus { background-position: -48px -128px; }
201
+ .ui-icon-minusthick { background-position: -64px -128px; }
202
+ .ui-icon-close { background-position: -80px -128px; }
203
+ .ui-icon-closethick { background-position: -96px -128px; }
204
+ .ui-icon-key { background-position: -112px -128px; }
205
+ .ui-icon-lightbulb { background-position: -128px -128px; }
206
+ .ui-icon-scissors { background-position: -144px -128px; }
207
+ .ui-icon-clipboard { background-position: -160px -128px; }
208
+ .ui-icon-copy { background-position: -176px -128px; }
209
+ .ui-icon-contact { background-position: -192px -128px; }
210
+ .ui-icon-image { background-position: -208px -128px; }
211
+ .ui-icon-video { background-position: -224px -128px; }
212
+ .ui-icon-script { background-position: -240px -128px; }
213
+ .ui-icon-alert { background-position: 0 -144px; }
214
+ .ui-icon-info { background-position: -16px -144px; }
215
+ .ui-icon-notice { background-position: -32px -144px; }
216
+ .ui-icon-help { background-position: -48px -144px; }
217
+ .ui-icon-check { background-position: -64px -144px; }
218
+ .ui-icon-bullet { background-position: -80px -144px; }
219
+ .ui-icon-radio-off { background-position: -96px -144px; }
220
+ .ui-icon-radio-on { background-position: -112px -144px; }
221
+ .ui-icon-pin-w { background-position: -128px -144px; }
222
+ .ui-icon-pin-s { background-position: -144px -144px; }
223
+ .ui-icon-play { background-position: 0 -160px; }
224
+ .ui-icon-pause { background-position: -16px -160px; }
225
+ .ui-icon-seek-next { background-position: -32px -160px; }
226
+ .ui-icon-seek-prev { background-position: -48px -160px; }
227
+ .ui-icon-seek-end { background-position: -64px -160px; }
228
+ .ui-icon-seek-start { background-position: -80px -160px; }
229
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
230
+ .ui-icon-seek-first { background-position: -80px -160px; }
231
+ .ui-icon-stop { background-position: -96px -160px; }
232
+ .ui-icon-eject { background-position: -112px -160px; }
233
+ .ui-icon-volume-off { background-position: -128px -160px; }
234
+ .ui-icon-volume-on { background-position: -144px -160px; }
235
+ .ui-icon-power { background-position: 0 -176px; }
236
+ .ui-icon-signal-diag { background-position: -16px -176px; }
237
+ .ui-icon-signal { background-position: -32px -176px; }
238
+ .ui-icon-battery-0 { background-position: -48px -176px; }
239
+ .ui-icon-battery-1 { background-position: -64px -176px; }
240
+ .ui-icon-battery-2 { background-position: -80px -176px; }
241
+ .ui-icon-battery-3 { background-position: -96px -176px; }
242
+ .ui-icon-circle-plus { background-position: 0 -192px; }
243
+ .ui-icon-circle-minus { background-position: -16px -192px; }
244
+ .ui-icon-circle-close { background-position: -32px -192px; }
245
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
246
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
247
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
248
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
249
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
250
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
251
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
252
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
253
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
254
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
255
+ .ui-icon-circle-check { background-position: -208px -192px; }
256
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
257
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
258
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
259
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
260
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
261
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
262
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
263
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
264
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
265
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
266
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
267
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
268
+
269
+
270
+ /* Misc visuals
271
+ ----------------------------------*/
272
+
273
+ /* Corner radius */
274
+ .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; }
275
+ .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
276
+ .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
277
+ .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
278
+ .ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
279
+ .ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
280
+ .ui-corner-right { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
281
+ .ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
282
+ .ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; }
283
+
284
+ /* Overlays */
285
+ .ui-widget-overlay { background: #a6a6a6 url(images/ui-bg_dots-small_65_a6a6a6_2x2.png) 50% 50% repeat; opacity: .40;filter:Alpha(Opacity=40); }
286
+ .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #333333 url(images/ui-bg_flat_0_333333_40x100.png) 50% 50% repeat-x; opacity: .10;filter:Alpha(Opacity=10); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* Accordion
287
+ ----------------------------------*/
288
+ .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
289
+ .ui-accordion .ui-accordion-li-fix { display: inline; }
290
+ .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
291
+ .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
292
+ /* IE7-/Win - Fix extra vertical space in lists */
293
+ .ui-accordion a { zoom: 1; }
294
+ .ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
295
+ .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
296
+ .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
297
+ .ui-accordion .ui-accordion-content-active { display: block; }/* Button
298
+ ----------------------------------*/
299
+
300
+ .ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
301
+ .ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
302
+ button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
303
+ .ui-button-icons-only { width: 3.4em; }
304
+ button.ui-button-icons-only { width: 3.7em; }
305
+
306
+ /*button text element */
307
+ .ui-button .ui-button-text { display: block; line-height: 1.4; }
308
+ .ui-button-text-only .ui-button-text { padding: .4em 1em; }
309
+ .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
310
+ .ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
311
+ .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
312
+ /* no icon support for input elements, provide padding by default */
313
+ input.ui-button { padding: .4em 1em; }
314
+
315
+ /*button icon element(s) */
316
+ .ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
317
+ .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
318
+ .ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
319
+ .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
320
+
321
+ /*button sets*/
322
+ .ui-buttonset { margin-right: 7px; }
323
+ .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
324
+
325
+ /* workarounds */
326
+ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
327
+
328
+
329
+
330
+
331
+
332
+ /* Slider
333
+ ----------------------------------*/
334
+ .ui-slider { position: relative; text-align: left; }
335
+ .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
336
+ .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
337
+
338
+ .ui-slider-horizontal { height: .8em; }
339
+ .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
340
+ .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
341
+ .ui-slider-horizontal .ui-slider-range-min { left: 0; }
342
+ .ui-slider-horizontal .ui-slider-range-max { right: 0; }
343
+
344
+ .ui-slider-vertical { width: .8em; height: 100px; }
345
+ .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
346
+ .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
347
+ .ui-slider-vertical .ui-slider-range-min { bottom: 0; }
348
+ .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Datepicker
349
+ ----------------------------------*/
350
+ .ui-datepicker { width: 17em; padding: .2em .2em 0; }
351
+ .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
352
+ .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
353
+ .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
354
+ .ui-datepicker .ui-datepicker-prev { left:2px; }
355
+ .ui-datepicker .ui-datepicker-next { right:2px; }
356
+ .ui-datepicker .ui-datepicker-prev-hover { left:1px; }
357
+ .ui-datepicker .ui-datepicker-next-hover { right:1px; }
358
+ .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
359
+ .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
360
+ .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
361
+ .ui-datepicker select.ui-datepicker-month-year {width: 100%;}
362
+ .ui-datepicker select.ui-datepicker-month,
363
+ .ui-datepicker select.ui-datepicker-year { width: 49%;}
364
+ .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
365
+ .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
366
+ .ui-datepicker td { border: 0; padding: 1px; }
367
+ .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
368
+ .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
369
+ .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
370
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
371
+
372
+ /* with multiple calendars */
373
+ .ui-datepicker.ui-datepicker-multi { width:auto; }
374
+ .ui-datepicker-multi .ui-datepicker-group { float:left; }
375
+ .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
376
+ .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
377
+ .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
378
+ .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
379
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
380
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
381
+ .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
382
+ .ui-datepicker-row-break { clear:both; width:100%; }
383
+
384
+ /* RTL support */
385
+ .ui-datepicker-rtl { direction: rtl; }
386
+ .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
387
+ .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
388
+ .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
389
+ .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
390
+ .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
391
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
392
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
393
+ .ui-datepicker-rtl .ui-datepicker-group { float:right; }
394
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
395
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
396
+
397
+ /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
398
+ .ui-datepicker-cover {
399
+ display: none; /*sorry for IE5*/
400
+ display/**/: block; /*sorry for IE5*/
401
+ position: absolute; /*must have*/
402
+ z-index: -1; /*must have*/
403
+ filter: mask(); /*must have*/
404
+ top: -4px; /*must have*/
405
+ left: -4px; /*must have*/
406
+ width: 200px; /*must have*/
407
+ height: 200px; /*must have*/
408
+ }
apps/jquery-tmpl/demos/movies/css/movies.css ADDED
@@ -0,0 +1,279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body
2
+ {
3
+ background-color: #b9090b;
4
+ font-family: Verdana;
5
+ font-size: 12px;
6
+ }
7
+
8
+ #pageBody
9
+ {
10
+ display: block;
11
+ clear: both;
12
+ position: relative;
13
+ margin: auto;
14
+ width: 90%;
15
+ background-color: #F9F5FA;
16
+ padding: 10px 15px 5px 15px;
17
+ }
18
+
19
+ #genres
20
+ {
21
+ clear: both;
22
+ display: block;
23
+ padding: 0;
24
+ }
25
+
26
+ #genres li
27
+ {
28
+ list-style: none;
29
+ float: left;
30
+ border: 1px solid #888;
31
+ text-decoration: none;
32
+ margin: 0 5px 0 0;
33
+ padding: 5px;
34
+ cursor: pointer;
35
+ background-color: #fff;
36
+ }
37
+
38
+ #genres li:hover
39
+ {
40
+ border: 1px solid #003f7e;
41
+ }
42
+
43
+ #genres li.selected
44
+ {
45
+ border: 1px solid #003f7e;
46
+ color: #042CCA;
47
+ font-weight: 700;
48
+ background: url(../images/ui-bg_glass_75_dadada_1x400.png) repeat-x 50% 50%;
49
+ }
50
+
51
+ #pager
52
+ {
53
+ width: 100%;
54
+ float: left;
55
+ clear: left;
56
+ margin: 0 0 10px;
57
+ }
58
+
59
+ #pager ul.pages
60
+ {
61
+ display: block;
62
+ border: none;
63
+ text-transform: uppercase;
64
+ font-size: 10px;
65
+ padding: 0;
66
+ }
67
+
68
+ #pager ul.pages li
69
+ {
70
+ list-style: none;
71
+ float: left;
72
+ border: 1px solid #888;
73
+ text-decoration: none;
74
+ margin: 0 5px 0 0;
75
+ padding: 5px;
76
+ background-color: #fff;
77
+ }
78
+
79
+ #pager ul.pages li:hover
80
+ {
81
+ border: 1px solid #00376f;
82
+ }
83
+
84
+ #pager ul.pages li.pgEmpty
85
+ {
86
+ border: 1px solid #ccc;
87
+ color: #aaa;
88
+ cursor: default;
89
+ }
90
+
91
+ #pager ul.pages li.pgCurrent
92
+ {
93
+ border: 1px solid #003f7e;
94
+ color: #042CCA;
95
+ font-weight: 700;
96
+ background: url(../images/ui-bg_glass_75_dadada_1x400.png) #dadada repeat-x 50% 50%;
97
+ }
98
+
99
+ #movieList
100
+ {
101
+ display: block;
102
+ float: left;
103
+ width: 49.7%;
104
+ clear: both;
105
+ }
106
+
107
+ #movieList > div
108
+ {
109
+ border: 1px solid #00509f;
110
+ margin-bottom: 10px;
111
+ padding: 8px;
112
+ background-color: #fff;
113
+ height: 180px;
114
+ }
115
+
116
+ #movieList div div
117
+ {
118
+ margin-right: 8px;
119
+ float: left;
120
+ width: 120px;
121
+ height: 150px;
122
+ float: left;
123
+ clear: both;
124
+ }
125
+
126
+ #movieList div img
127
+ {
128
+ height: 150px;
129
+ }
130
+
131
+ #movieList div br, #pageBody br
132
+ {
133
+ clear: both;
134
+ }
135
+
136
+ .buyButton
137
+ {
138
+ float: left;
139
+ clear: both;
140
+ margin-left: 6px;
141
+ margin-top: 6px;
142
+ }
143
+
144
+ #bookingsList
145
+ {
146
+ border-collapse: collapse;
147
+ border: 3px double #00509f;
148
+ width: 49.7%;
149
+ float: right;
150
+ background-color: #fff;
151
+ margin-bottom: 10px;
152
+ }
153
+
154
+ #bookingsList tr
155
+ {
156
+ border: 1px solid #00509f;
157
+ padding: 5px
158
+ }
159
+
160
+ .cart td
161
+ {
162
+ height: 30px;
163
+ border: 3px double #00509f;
164
+ background-color: #F9F5FA;
165
+ text-align:center;
166
+ }
167
+
168
+ .cart .cart-true
169
+ {
170
+ background-color: #E8DAEB;
171
+ }
172
+
173
+ .cart span.text
174
+ {
175
+ color: #2F5071;
176
+ float:none;
177
+ height: 25px;
178
+ line-height: 25px;
179
+ font-size: 14px;
180
+ font-style: italic;
181
+ border: none;
182
+ }
183
+
184
+ #submit, #cancel, #sort
185
+ {
186
+ color: #2F5071;
187
+ font-weight: 700;
188
+ float: right;
189
+ height: 25px;
190
+ line-height: 25px;
191
+ font-style: italic;
192
+ margin: 0 15px;
193
+ }
194
+
195
+ #submit, #cancel, #sortBtn
196
+ {
197
+ text-decoration: underline;
198
+ cursor: pointer;
199
+ }
200
+
201
+ #submit
202
+ {
203
+ float: left;
204
+ }
205
+
206
+ .bookingTitle
207
+ {
208
+ color: #2F5071;
209
+ font-weight: bold;
210
+ background: url(../images/ui-bg_highlight-hard_100_eeeeee_1x100.png) #e6e6e6 repeat-x 50% 50%;
211
+ cursor: pointer;
212
+ }
213
+
214
+ .bookingTitle:hover, .bookingTitleEdit:hover
215
+ {
216
+ background: url(../images/ui-bg_glass_75_dadada_1x400.png) #dadada repeat-x 50% 50%;
217
+ }
218
+
219
+ .bookingTitleEdit
220
+ {
221
+ color: #042CCA;
222
+ font-weight: bold;
223
+ background: url(../images/ui-bg_highlight-hard_100_eeeeee_1x100.png) #e6e6e6 repeat-x 50% 50%;
224
+ cursor: pointer;
225
+ }
226
+
227
+ .bookingTitle td
228
+ {
229
+ padding: 8px;
230
+ }
231
+
232
+ .bookingTitleEdit td
233
+ {
234
+ padding: 7px 8px 7px 8px;
235
+ }
236
+
237
+ .bookingEdit div
238
+ {
239
+ float: right;
240
+ height: 116px;
241
+ }
242
+
243
+ .bookingEdit .fields
244
+ {
245
+ float: left;
246
+ }
247
+
248
+ .bookingEdit .fields span
249
+ {
250
+ margin: 12px 0 0 8px;
251
+ display: inline-block;
252
+ width: 100px;
253
+ }
254
+
255
+ .bookingEdit .fields input
256
+ {
257
+ margin: 12px 0 0 8px;
258
+ width: 250px;
259
+ }
260
+
261
+ .bookingEdit img
262
+ {
263
+ height: 100px;
264
+ margin: 8px;
265
+ }
266
+
267
+ .close
268
+ {
269
+ background-position: -96px -128px;
270
+ float: right;
271
+ cursor: pointer;
272
+ }
273
+
274
+ .ui-icon
275
+ {
276
+ width: 16px;
277
+ height: 16px;
278
+ background-image: url(../images/ui-icons_cc0000_256x240.png);
279
+ }
apps/jquery-tmpl/demos/movies/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_dots-small_65_a6a6a6_2x2.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_flat_0_333333_40x100.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_flat_65_ffffff_40x100.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_flat_75_ffffff_40x100.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_glass_55_fbf8ee_1x400.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_glass_75_dadada_1x400.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_highlight-hard_100_eeeeee_1x100.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_highlight-hard_100_f6f6f6_1x100.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-bg_highlight-soft_15_cc0000_1x100.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-icons_004276_256x240.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-icons_cc0000_256x240.png ADDED
Binary file
apps/jquery-tmpl/demos/movies/images/ui-icons_ffffff_256x240.png ADDED
Binary file
apps/jquery-tmpl/demos/resources/demos.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ body { padding: 10px; font-family: Verdana; font-size: small }
2
+ h4 { font-size: inherit`; font-variant: small-caps; }
3
+ .height { width: 100%; margin-bottom:10px; float: left; clear: both; }
4
+ .bottom { height:400px; width: 100%; margin-bottom:10px; float: left; clear: both; }
5
+ body > button { float: left; clear: right; margin: 3px }
6
+ .subhead { margin: 15px 0 4px 0; font-weight:bolder; color:#116; font-family:Arial; font-size:10pt }
7
+ a { color: #55b}
apps/jquery-tmpl/demos/resources/movielist.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ table { border-collapse: collapse; }
2
+ table tr { color: blue; height: 25px; }
3
+ .header { color: #009; border-bottom: solid #77c 2px; background-color: #E8E8F7; }
4
+ .header th { padding:5px; border: 1px solid #77c; }
5
+ #movieList tr td:first-child { width: 100px; }
6
+ table { border: 2px solid blue; width: 480px; margin: 4px 0 4px 4px; padding: 2px; background-color: #f8f8f8; }
7
+ table td { padding: 3px; margin: 3px; border: solid #77c 1px; }
apps/jquery-tmpl/demos/resources/syntaxhighlighter.css ADDED
@@ -0,0 +1,513 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * SyntaxHighlighter
3
+ * http://alexgorbatchev.com/
4
+ *
5
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
6
+ * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate
7
+ *
8
+ * @version
9
+ * 2.0.296 (March 01 2009)
10
+ *
11
+ * @copyright
12
+ * Copyright (C) 2004-2009 Alex Gorbatchev.
13
+ *
14
+ * @license
15
+ * This file is part of SyntaxHighlighter.
16
+ *
17
+ * SyntaxHighlighter is free software: you can redistribute it and/or modify
18
+ * it under the terms of the GNU General Public License as published by
19
+ * the Free Software Foundation, either version 3 of the License, or
20
+ * (at your option) any later version.
21
+ *
22
+ * SyntaxHighlighter is distributed in the hope that it will be useful,
23
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
+ * GNU General Public License for more details.
26
+ *
27
+ * You should have received a copy of the GNU General Public License
28
+ * along with SyntaxHighlighter. If not, see <http://www.gnu.org/licenses/>.
29
+ */
30
+ .syntaxhighlighter,
31
+ .syntaxhighlighter div,
32
+ .syntaxhighlighter code,
33
+ .syntaxhighlighter span
34
+ {
35
+ margin: 0 !important;
36
+ padding: 0 !important;
37
+ border: 0 !important;
38
+ outline: 0 !important;
39
+ background: none !important;
40
+ text-align: left !important;
41
+ float: none !important;
42
+ vertical-align: baseline !important;
43
+ position: static !important;
44
+ left: auto !important;
45
+ top: auto !important;
46
+ right: auto !important;
47
+ bottom: auto !important;
48
+ height: auto !important;
49
+ width: auto !important;
50
+ line-height: 1.1em !important;
51
+ font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
52
+ font-weight: normal !important;
53
+ font-style: normal !important;
54
+ font-size: 1em !important;
55
+ }
56
+
57
+ .syntaxhighlighter
58
+ {
59
+ width: 100% !important;
60
+ margin: 1em 0 1em 0 !important;
61
+ padding: 1px !important; /* adds a little border on top and bottom */
62
+ position: relative !important;
63
+ }
64
+
65
+ .syntaxhighlighter .bold {
66
+ font-weight: bold !important;
67
+ }
68
+
69
+ .syntaxhighlighter .italic {
70
+ font-style: italic !important;
71
+ }
72
+
73
+ .syntaxhighlighter .line .number
74
+ {
75
+ float: left !important;
76
+ width: 3em !important;
77
+ padding-right: .3em !important;
78
+ text-align: right !important;
79
+ display: block !important;
80
+ }
81
+
82
+ /* Disable numbers when no gutter option is set */
83
+ .syntaxhighlighter.nogutter .line .number
84
+ {
85
+ display: none !important;
86
+ }
87
+
88
+ .syntaxhighlighter .line .content
89
+ {
90
+ margin-left: 3.3em !important;
91
+ padding-left: .5em !important;
92
+ display: block !important;
93
+ }
94
+
95
+ .syntaxhighlighter .line .content .block
96
+ {
97
+ display: block !important;
98
+ padding-left: 1.5em !important;
99
+ text-indent: -1.5em !important;
100
+ }
101
+
102
+ .syntaxhighlighter .line .content .spaces
103
+ {
104
+ display: none !important;
105
+ }
106
+
107
+ /* Disable border and margin on the lines when no gutter option is set */
108
+ .syntaxhighlighter.nogutter .line .content
109
+ {
110
+ margin-left: 0 !important;
111
+ border-left: none !important;
112
+ }
113
+
114
+ .syntaxhighlighter .bar
115
+ {
116
+ }
117
+
118
+ .syntaxhighlighter.collapsed .bar
119
+ {
120
+
121
+ }
122
+
123
+ .syntaxhighlighter.nogutter .ruler
124
+ {
125
+ margin-left: 0 !important;
126
+ padding-left: 0 !important;
127
+ }
128
+
129
+ .syntaxhighlighter .ruler
130
+ {
131
+ padding: 0 0 .5em .5em !important;
132
+ margin-left: 3.3em !important;
133
+ overflow: hidden !important;
134
+ }
135
+
136
+ /* Adjust some properties when collapsed */
137
+
138
+ .syntaxhighlighter.collapsed .lines,
139
+ .syntaxhighlighter.collapsed .ruler
140
+ {
141
+ display: none !important;
142
+ }
143
+
144
+ /* Styles for the toolbar */
145
+
146
+ .syntaxhighlighter .toolbar
147
+ {
148
+ position: absolute !important;
149
+ right: 0px !important;
150
+ top: 0px !important;
151
+ font-size: 1px !important;
152
+ padding: 8px 8px 8px 0 !important; /* in px because images don't scale with ems */
153
+ }
154
+
155
+ .syntaxhighlighter.collapsed .toolbar
156
+ {
157
+ font-size: 80% !important;
158
+ padding: .2em 0 .5em .5em !important;
159
+ position: static !important;
160
+ }
161
+
162
+ .syntaxhighlighter .toolbar a.item,
163
+ .syntaxhighlighter .toolbar .item
164
+ {
165
+ display: block !important;
166
+ float: left !important;
167
+ margin-left: 8px !important;
168
+ background-repeat: no-repeat !important;
169
+ overflow: hidden !important;
170
+ text-indent: -5000px !important;
171
+ }
172
+
173
+ .syntaxhighlighter.collapsed .toolbar .item
174
+ {
175
+ display: none !important;
176
+ }
177
+
178
+ .syntaxhighlighter.collapsed .toolbar .item.expandSource
179
+ {
180
+ background-image: url(magnifier.png) !important;
181
+ display: inline !important;
182
+ text-indent: 0 !important;
183
+ width: auto !important;
184
+ float: none !important;
185
+ height: 16px !important;
186
+ padding-left: 20px !important;
187
+ }
188
+
189
+ .syntaxhighlighter .toolbar .item.viewSource
190
+ {
191
+ background-image: url(page_white_code.png) !important;
192
+ }
193
+
194
+ .syntaxhighlighter .toolbar .item.printSource
195
+ {
196
+ background-image: url(printer.png) !important;
197
+ }
198
+
199
+ .syntaxhighlighter .toolbar .item.copyToClipboard
200
+ {
201
+ text-indent: 0 !important;
202
+ background: none !important;
203
+ overflow: visible !important;
204
+ }
205
+
206
+ .syntaxhighlighter .toolbar .item.about
207
+ {
208
+ background-image: url(help.png) !important;
209
+ }
210
+
211
+ /**
212
+ * Print view.
213
+ * Colors are based on the default theme without background.
214
+ */
215
+
216
+ .syntaxhighlighter.printing,
217
+ .syntaxhighlighter.printing .line.alt1 .content,
218
+ .syntaxhighlighter.printing .line.alt2 .content,
219
+ .syntaxhighlighter.printing .line.highlighted .number,
220
+ .syntaxhighlighter.printing .line.highlighted.alt1 .content,
221
+ .syntaxhighlighter.printing .line.highlighted.alt2 .content,
222
+ .syntaxhighlighter.printing .line .content .block
223
+ {
224
+ background: none !important;
225
+ }
226
+
227
+ /* Gutter line numbers */
228
+ .syntaxhighlighter.printing .line .number
229
+ {
230
+ color: #bbb !important;
231
+ }
232
+
233
+ /* Add border to the lines */
234
+ .syntaxhighlighter.printing .line .content
235
+ {
236
+ color: #000 !important;
237
+ }
238
+
239
+ /* Toolbar when visible */
240
+ .syntaxhighlighter.printing .toolbar,
241
+ .syntaxhighlighter.printing .ruler
242
+ {
243
+ display: none !important;
244
+ }
245
+
246
+ .syntaxhighlighter.printing a
247
+ {
248
+ text-decoration: none !important;
249
+ }
250
+
251
+ .syntaxhighlighter.printing .plain,
252
+ .syntaxhighlighter.printing .plain a
253
+ {
254
+ color: #000 !important;
255
+ }
256
+
257
+ .syntaxhighlighter.printing .comments,
258
+ .syntaxhighlighter.printing .comments a
259
+ {
260
+ color: #008200 !important;
261
+ }
262
+
263
+ .syntaxhighlighter.printing .string,
264
+ .syntaxhighlighter.printing .string a
265
+ {
266
+ color: blue !important;
267
+ }
268
+
269
+ .syntaxhighlighter.printing .keyword
270
+ {
271
+ color: #069 !important;
272
+ font-weight: bold !important;
273
+ }
274
+
275
+ .syntaxhighlighter.printing .preprocessor
276
+ {
277
+ color: gray !important;
278
+ }
279
+
280
+ .syntaxhighlighter.printing .variable
281
+ {
282
+ color: #a70 !important;
283
+ }
284
+
285
+ .syntaxhighlighter.printing .value
286
+ {
287
+ color: #090 !important;
288
+ }
289
+
290
+ .syntaxhighlighter.printing .functions
291
+ {
292
+ color: #ff1493 !important;
293
+ }
294
+
295
+ .syntaxhighlighter.printing .constants
296
+ {
297
+ color: #0066CC !important;
298
+ }
299
+
300
+ .syntaxhighlighter.printing .script
301
+ {
302
+ font-weight: bold !important;
303
+ }
304
+
305
+ .syntaxhighlighter.printing .color1,
306
+ .syntaxhighlighter.printing .color1 a
307
+ {
308
+ color: #808080 !important;
309
+ }
310
+
311
+ .syntaxhighlighter.printing .color2,
312
+ .syntaxhighlighter.printing .color2 a
313
+ {
314
+ color: #ff1493 !important;
315
+ }
316
+
317
+ .syntaxhighlighter.printing .color3,
318
+ .syntaxhighlighter.printing .color3 a
319
+ {
320
+ color: red !important;
321
+ }
322
+
323
+ /**
324
+ * SyntaxHighlighter
325
+ * http://alexgorbatchev.com/
326
+ *
327
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
328
+ * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate
329
+ *
330
+ * @version
331
+ * 2.0.296 (March 01 2009)
332
+ *
333
+ * @copyright
334
+ * Copyright (C) 2004-2009 Alex Gorbatchev.
335
+ *
336
+ * @license
337
+ * This file is part of SyntaxHighlighter.
338
+ *
339
+ * SyntaxHighlighter is free software: you can redistribute it and/or modify
340
+ * it under the terms of the GNU General Public License as published by
341
+ * the Free Software Foundation, either version 3 of the License, or
342
+ * (at your option) any later version.
343
+ *
344
+ * SyntaxHighlighter is distributed in the hope that it will be useful,
345
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
346
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
347
+ * GNU General Public License for more details.
348
+ *
349
+ * You should have received a copy of the GNU General Public License
350
+ * along with SyntaxHighlighter. If not, see <http://www.gnu.org/licenses/>.
351
+ */
352
+ /************************************
353
+ * Default Syntax Highlighter theme.
354
+ *
355
+ * Interface elements.
356
+ ************************************/
357
+
358
+ .syntaxhighlighter
359
+ {
360
+ background-color: #E7E5DC !important;
361
+ }
362
+
363
+ /* Highlighed line number */
364
+ .syntaxhighlighter .line.highlighted .number
365
+ {
366
+ background-color: #6CE26C !important;
367
+ color: black !important;
368
+ }
369
+
370
+ /* Highlighed line */
371
+ .syntaxhighlighter .line.highlighted.alt1 .content,
372
+ .syntaxhighlighter .line.highlighted.alt2 .content
373
+ {
374
+ background-color: #6CE26C !important;
375
+ }
376
+
377
+ /* Gutter line numbers */
378
+ .syntaxhighlighter .line .number
379
+ {
380
+ color: #5C5C5C !important;
381
+ }
382
+
383
+ /* Add border to the lines */
384
+ .syntaxhighlighter .line .content
385
+ {
386
+ border-left: 3px solid #6CE26C !important;
387
+ color: #000 !important;
388
+ }
389
+
390
+ .syntaxhighlighter.printing .line .content
391
+ {
392
+ border: 0 !important;
393
+ }
394
+
395
+ /* First line */
396
+ .syntaxhighlighter .line.alt1 .content
397
+ {
398
+ background-color: #fff !important;
399
+ }
400
+
401
+ /* Second line */
402
+ .syntaxhighlighter .line.alt2 .content
403
+ {
404
+ background-color: #F8F8F8 !important;
405
+ }
406
+
407
+ .syntaxhighlighter .line .content .block
408
+ {
409
+ background: url(wrapping.png) 0 1.1em no-repeat !important;
410
+ }
411
+
412
+ .syntaxhighlighter .ruler
413
+ {
414
+ color: silver !important;
415
+ background-color: #F8F8F8 !important;
416
+ border-left: 3px solid #6CE26C !important;
417
+ }
418
+
419
+ .syntaxhighlighter.nogutter .ruler
420
+ {
421
+ border: 0 !important;
422
+ }
423
+
424
+ .syntaxhighlighter .toolbar
425
+ {
426
+ background-color: #F8F8F8 !important;
427
+ border: #E7E5DC solid 1px !important;
428
+ }
429
+
430
+ .syntaxhighlighter .toolbar a
431
+ {
432
+ color: #a0a0a0 !important;
433
+ }
434
+
435
+ .syntaxhighlighter .toolbar a:hover
436
+ {
437
+ color: red !important;
438
+ }
439
+
440
+ /************************************
441
+ * Actual syntax highlighter colors.
442
+ ************************************/
443
+ .syntaxhighlighter .plain,
444
+ .syntaxhighlighter .plain a
445
+ {
446
+ color: #000 !important;
447
+ }
448
+
449
+ .syntaxhighlighter .comments,
450
+ .syntaxhighlighter .comments a
451
+ {
452
+ color: #008200 !important;
453
+ }
454
+
455
+ .syntaxhighlighter .string,
456
+ .syntaxhighlighter .string a
457
+ {
458
+ color: blue !important;
459
+ }
460
+
461
+ .syntaxhighlighter .keyword
462
+ {
463
+ color: #069 !important;
464
+ font-weight: bold !important;
465
+ }
466
+
467
+ .syntaxhighlighter .preprocessor
468
+ {
469
+ color: gray !important;
470
+ }
471
+
472
+ .syntaxhighlighter .variable
473
+ {
474
+ color: #a70 !important;
475
+ }
476
+
477
+ .syntaxhighlighter .value
478
+ {
479
+ color: #090 !important;
480
+ }
481
+
482
+ .syntaxhighlighter .functions
483
+ {
484
+ color: #ff1493 !important;
485
+ }
486
+
487
+ .syntaxhighlighter .constants
488
+ {
489
+ color: #0066CC !important;
490
+ }
491
+
492
+ .syntaxhighlighter .script
493
+ {
494
+ background-color: yellow !important;
495
+ }
496
+
497
+ .syntaxhighlighter .color1,
498
+ .syntaxhighlighter .color1 a
499
+ {
500
+ color: #808080 !important;
501
+ }
502
+
503
+ .syntaxhighlighter .color2,
504
+ .syntaxhighlighter .color2 a
505
+ {
506
+ color: #ff1493 !important;
507
+ }
508
+
509
+ .syntaxhighlighter .color3,
510
+ .syntaxhighlighter .color3 a
511
+ {
512
+ color: red !important;
513
+ }
apps/jquery-tmpl/demos/resources/syntaxhighlighter.min.js ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * SyntaxHighlighter
3
+ * http://alexgorbatchev.com/
4
+ *
5
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
6
+ * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate
7
+ *
8
+ * @version
9
+ * 2.0.296 (March 01 2009)
10
+ *
11
+ * @copyright
12
+ * Copyright (C) 2004-2009 Alex Gorbatchev.
13
+ *
14
+ * @license
15
+ * This file is part of SyntaxHighlighter.
16
+ *
17
+ * SyntaxHighlighter is free software: you can redistribute it and/or modify
18
+ * it under the terms of the GNU General Public License as published by
19
+ * the Free Software Foundation, either version 3 of the License, or
20
+ * (at your option) any later version.
21
+ *
22
+ * SyntaxHighlighter is distributed in the hope that it will be useful,
23
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
+ * GNU General Public License for more details.
26
+ *
27
+ * You should have received a copy of the GNU General Public License
28
+ * along with SyntaxHighlighter. If not, see <http://www.gnu.org/licenses/>.
29
+ */
30
+ eval(function(e,d,a,c,b,f){b=function(a){return(a<d?"":b(parseInt(a/d)))+((a=a%d)>35?String.fromCharCode(a+29):a.toString(36))};if(!"".replace(/^/,String)){while(a--)f[b(a)]=c[a]||b(a);c=[function(a){return f[a]}];b=function(){return"\\w+"};a=1}while(a--)if(c[a])e=e.replace(new RegExp("\\b"+b(a)+"\\b","g"),c[a]);return e}('f(!1o.31){p 31=h(){p l={5S:{"1e-1c":"","73-2E":1,"2a-1P":u,"1I":u,"6T-6S":U,"1F-1P":4,"5F":O,"5x":U,"1q":U,"5v":O,"6i-6p":U,"6J":O},Q:{5D:u,5i:16,5k:16,7P:O,7I:"5L",1b:{4e:"91 1i",3Y:"92 1i",5l:"93 90 6K",6X:"8Z I 8W 1X 8X 6K 8Y",3u:"3u",6h:"?",1u:"31\\n\\n",5Z:"94\'t 95 7J C: ",7z:"9b 9c\'t 9a C 2j-2n 99: ",6B:"<!96 2j 97 \\"-//98//8b 8V 1.0 8U//8I\\" \\"2y://7A.7E.7o/8J/86/8b/86-8K.8H\\"><2j 8G=\\"2y://7A.7E.7o/8D/8E\\"><70><8F 2y-8L=\\"8M-8S\\" 5h=\\"2c/2j; 8T=8R-8\\" /><36>8Q 31</36></70><2R 1f=\\"2a-7T:8N,\'7h 8O 8P\',7h,7L;9d-53:#9e;53:#9D;2a-1P:9E;2c-8i:85;\\"><z 1f=\\"2c-8i:85;5n-4z:9F;\\"><z 1f=\\"2a-7T:9C,9B,9y,8C-7L;2a-1P:9z-9A;\\">31</z><z 1f=\\"2a-1P:.9G;5n-9H:9N;\\"><z>84 2.0.9O (9M 9L 6H)</z><z><a 2q=\\"2y://6a.4a\\" 9I=\\"4P\\" 1f=\\"53:#9J;2c-9K:9x;\\">2y://6a.4a</a></z></z><z>9w I 9k 9l.</z><z>9m 9j-6H 9i 9f.</z></z></2R></2j>"},7j:O},1p:{59:u,3q:u,3o:u,5j:{}},30:{},8a:{9g:/\\/\\*[\\s\\S]*?\\*\\//4M,9h:/\\/\\/.*$/4M,9n:/#.*$/4M,9o:/"(?:\\.|(\\\\\\")|[^\\""\\n])*"/g,9u:/\'(?:\\.|(\\\\\\\')|[^\\\'\'\\n])*\'/g,9v:/"(?:\\.|(\\\\\\")|[^\\""])*"/g,9t:/\'(?:\\.|(\\\\\\\')|[^\\\'\'])*\'/g,3e:/\\w+:\\/\\/[\\w-.\\/?%&=]*/g,9s:{E:/(&1C;|<)\\?=?/g,17:/\\?(&2m;|>)/g},9p:{E:/(&1C;|<)%=?/g,17:/%(&2m;|>)/g},9q:{E:/(&1C;|<)\\s*2n.*?(&2m;|>)/47,17:/(&1C;|<)\\/\\s*2n\\s*(&2m;|>)/47}},1q:{15:h(32){p 38=J.1t("37"),4L=l.1q.77;38.Y="1q";C(p 2N 1X 4L){p 6j=4L[2N],4G=R 6j(32),22=4G.15();32.5E[2N]=4G;f(22==u){1V}f(9r(22)=="9P"){22=l.1q.6C(22,32.1j,2N)}22.Y+="8w "+2N;38.1z(22)}q 38},6C:h(4v,6O,4w){p a=J.1t("a"),5e=a.1f,4F=l.Q,57=4F.5i,5c=4F.5k;a.2q="#"+4w;a.36=4v;a.5P=6O;a.6c=4w;a.1r=4v;f(5z(57)==O){5e.1N=57+"5H"}f(5z(5c)==O){5e.2u=5c+"5H"}a.8q=h(e){8j{l.1q.6f(c,e||1o.6g,c.5P,c.6c)}8m(e){l.B.1u(e.6F)}q O};q a},6f:h(7i,7a,5T,7O,72){p 4Y=l.1p.5j[5T],45;f(4Y==u||(45=4Y.5E[7O])==u){q u}q 45.2h(7i,7a,72)},77:{4e:h(4p){c.15=h(){f(4p.T("5v")!=U){q}q l.Q.1b.4e};c.2h=h(4q,8v,8B){p z=4p.z;4q.71.51(4q);z.Y=z.Y.D("5t","")}},3Y:h(8g){c.15=h(){q l.Q.1b.3Y};c.2h=h(8p,8o,8t){p 33=l.B.3d(8g.5r).D(/</g,"&1C;"),2b=l.B.4y("","4P",8r,8n,"8x=0, 8k=1, 8s=0, 6n=1");33=l.B.2W(33);2b.J.3t("<5L>"+33+"</5L>");2b.J.4N()}},5l:h(4S){p 3x,8y,5M=4S.1j;c.15=h(){p 2A=l.Q;f(2A.5D==u){q u}h 1L(5C){p 5s="";C(p 5A 1X 5C){5s+="<8z 1c=\'"+5A+"\' 1W=\'"+5C[5A]+"\'/>"}q 5s};h 2p(43){p 5p="";C(p 5o 1X 43){5p+=" "+5o+"=\'"+43[5o]+"\'"}q 5p};p 48={1N:2A.5i,2u:2A.5k,1j:5M+"ai",6z:"bu/x-74-79",36:l.Q.1b.5l},46={bl:"bm",bx:"bA",bz:"5P="+5M,bF:"O"},4t=2A.5D,35;f(/aQ/i.1R(61.6b)){35="<8h"+2p({aT:"bd:bf-b9-b5-b4-b7",b8:"2y://ba.be.4a/bb/74/bc/79/b3.b2#84=9,0,0,0"})+2p(48)+">"+1L(46)+1L({aU:4t})+"</8h>"}F{35="<aS"+2p(48)+2p(46)+2p({aR:4t})+"/>"}3x=J.1t("z");3x.1r=35;q 3x};c.2h=h(aV,aW,4R){p 68=4R.b1;6V(68){2J"7C":p 5d=l.B.2W(l.B.3d(4S.5r).D(/&1C;/g,"<").D(/&2m;/g,">").D(/&b0;/g,"&"));f(1o.6e){1o.6e.aZ("2c",5d)}F{q l.B.2W(5d)}2J"aX":l.B.1u(l.Q.1b.6X);2B;2J"aY":l.B.1u(4R.6F);2B}}},bh:h(4I){c.15=h(){q l.Q.1b.3u};c.2h=h(bg,by,bB){p 25=J.1t("bG"),1J=u;f(l.1p.3o!=u){J.2R.51(l.1p.3o)}l.1p.3o=25;25.1f.bC="bE:bD;1N:6m;2u:6m;E:-6l;4z:-6l;";J.2R.1z(25);1J=25.4J.J;6t(1J,1o.J);1J.3t("<z 1e=\\""+4I.z.Y.D("5t","")+" bn\\">"+4I.z.1r+"</z>");1J.4N();25.4J.4A();25.4J.3u();h 6t(6A,6s){p 2S=6s.7M("4K");C(p i=0;i<2S.v;i++){f(2S[i].6r.bk()=="6q"&&/bi\\.12$/.1R(2S[i].2q)){6A.3t("<4K 6z=\\"2c/12\\" 6r=\\"6q\\" 2q=\\""+2S[i].2q+"\\"></4K>")}}}}},bj:h(bo){c.15=h(){q l.Q.1b.6h};c.2h=h(bv,bt){p 2b=l.B.4y("","4P",bq,bs,"6n=0"),1J=2b.J;1J.3t(l.Q.1b.6B);1J.4N();2b.4A()}}}},B:{5m:h(6R){q 6R+3z.aN(3z.aa()*ab).2f()},5u:h(4E,4x){p 3l={},1S;C(1S 1X 4E){3l[1S]=4E[1S]}C(1S 1X 4x){3l[1S]=4x[1S]}q 3l},7w:h(4u){6V(4u){2J"U":q U;2J"O":q O}q 4u},4y:h(3e,6M,4D,4C,2I){p x=(6N.1N-4D)/2,y=(6N.2u-4C)/2;2I+=", E="+x+", 4z="+y+", 1N="+4D+", 2u="+4C;2I=2I.D(/^,/,"");p 4Q=1o.9Q(3e,6M,2I);4Q.4A();q 4Q},78:h(1A,29,23){f(1A.6D){1A["e"+29+23]=23;1A[29+23]=h(){1A["e"+29+23](1o.6g)};1A.6D("a6"+29,1A[29+23])}F{1A.a7(29,23,O)}},1u:h(A){1u(l.Q.1b.1u+A)},4c:h(5a,5Y){p 2k=l.1p.59,3j=u;f(2k==u){2k={};C(p 55 1X l.30){p 3g=l.30[55].ac;f(3g==u){1V}C(p i=0;i<3g.v;i++){2k[3g[i]]=55}}l.1p.59=2k}3j=l.30[2k[5a]];f(3j==u&&5Y!=O){l.B.1u(l.Q.1b.5Z+5a)}q 3j},42:h(A,60){p 2T=A.21("\\n");C(p i=0;i<2T.v;i++){2T[i]=60(2T[i])}q 2T.4h("\\n")},6x:h(){p z=J.1t("z"),3h=J.1t("z"),6d=10,i=1;28(i<=aO){f(i%6d===0){z.1r+=i;i+=(i+"").v}F{z.1r+="&ah;";i++}}3h.Y="5F 2E";3h.1z(z);q 3h},6U:h(A){q A.D(/^[ ]*[\\n]+|[\\n]*[ ]*$/g,"")},7d:h(A){p 3i,4V={},5b=R M("^\\\\[(?<54>(.*?))\\\\]$"),69=R M("(?<1c>[\\\\w-]+)"+"\\\\s*:\\\\s*"+"(?<1W>"+"[\\\\w-%#]+|"+"\\\\[.*?\\\\]|"+"\\".*?\\"|"+"\'.*?\'"+")\\\\s*;?","g");28((3i=69.N(A))!=u){p 2g=3i.1W.D(/^[\'"]|[\'"]$/g,"");f(2g!=u&&5b.1R(2g)){p m=5b.N(2g);2g=m.54.v>0?m.54.21(/\\s*,\\s*/):[]}4V[3i.1c]=2g}q 4V},80:h(A,12){f(A==u||A.v==0||A=="\\n"){q A}A=A.D(/</g,"&1C;");A=A.D(/ {2,}/g,h(m){p 4U="";C(p i=0;i<m.v-1;i++){4U+="&1O;"}q 4U+" "});f(12!=u){A=l.B.42(A,h(2i){f(2i.v==0){q""}p 3k="";2i=2i.D(/^(&1O;| )+/,h(s){3k=s;q""});f(2i.v==0){q 3k}q 3k+"<I 1e=\\""+12+"\\">"+2i+"</I>"})}q A},7f:h(66,67){p 2Z=66.2f();28(2Z.v<67){2Z="0"+2Z}q 2Z},5y:h(){p 3b=J.1t("z"),3f,3a=0,52=J.2R,1j=l.B.5m("5y"),2O="<z 1e=\\"",2Q="</z>",4W="</1T>";3b.1r=2O+"6L\\">"+2O+"26\\">"+2O+"2E\\">"+2O+"5h"+"\\"><1T 1e=\\"7V\\"><1T 1j=\\""+1j+"\\">&1O;"+4W+4W+2Q+2Q+2Q+2Q;52.1z(3b);3f=J.a5(1j);f(/a4/i.1R(61.6b)){p 5Q=1o.9V(3f,u);3a=7l(5Q.9W("1N"))}F{3a=3f.9U}52.51(3b);q 3a},6Q:h(7R,6Y){p 1F="";C(p i=0;i<6Y;i++){1F+=" "}q 7R.D(/\\t/g,1F)},6P:h(2P,41){p 9T=2P.21("\\n"),1F="\\t",5f="";C(p i=0;i<50;i++){5f+=" "}h 7X(3c,18,7Z){q 3c.1M(0,18)+5f.1M(0,7Z)+3c.1M(18+1,3c.v)};2P=l.B.42(2P,h(20){f(20.1h(1F)==-1){q 20}p 18=0;28((18=20.1h(1F))!=-1){p 7U=41-18%41;20=7X(20,18,7U)}q 20});q 2P},3d:h(A){q(l.Q.7P==U)?A.D(/<br\\s*\\/?>|&1C;br\\s*\\/?&2m;/47,"\\n"):A},3P:h(A){q A.D(/\\s*$/g,"").D(/^\\s*/,"")},2W:h(A){p 1Q=l.B.3d(A).21("\\n"),9X=R 5B(),7S=/^\\s*/,24=9Y;C(p i=0;i<1Q.v&&24>0;i++){p 3V=1Q[i];f(l.B.3P(3V).v==0){1V}p 3S=7S.N(3V);f(3S==u){q A}24=3z.24(3S[0].v,24)}f(24>0){C(p i=0;i<1Q.v;i++){1Q[i]=1Q[i].1M(24)}}q 1Q.4h("\\n")},7B:h(2L,2K){f(2L.H<2K.H){q-1}F{f(2L.H>2K.H){q 1}F{f(2L.v<2K.v){q-1}F{f(2L.v>2K.v){q 1}}}}q 0},2D:h(8d,2G){h 8e(3W,81){q[R l.4i(3W[0],3W.H,81.12)]};p a2=0,3X=u,3y=[],8c=2G.4m?2G.4m:8e;28((3X=2G.3D.N(8d))!=u){3y=3y.2H(8c(3X,2G))}q 3y},6o:h(8f){q 8f.D(l.8a.3e,h(m){q"<a 2q=\\""+m+"\\">"+m+"</a>"})}},1I:h(7c,4l){h 88(4s){p 49=[];C(p i=0;i<4s.v;i++){49.K(4s[i])}q 49};p 3m=4l?[4l]:88(J.7M(l.Q.7I)),7g="1r",2t=u;f(3m.v===0){q}C(p i=0;i<3m.v;i++){p 2F=3m[i],2s=l.B.7d(2F.Y),2Y;2s=l.B.5u(7c,2s);2Y=2s["7J"];f(2Y==u){1V}f(2s["2j-2n"]=="U"){2t=R l.44(2Y)}F{p 4o=l.B.4c(2Y);f(4o){2t=R 4o()}F{1V}}2t.1I(2F[7g],2s);p 2l=2t.z;f(l.Q.7j){2l=J.1t("a0");2l.1W=2t.z.1r;2l.1f.1N="aj";2l.1f.2u="aE"}2F.71.aF(2l,2F)}},aD:h(76){l.B.78(1o,"aC",h(){l.1I(76)})}};l.4i=h(4j,75,12){c.1W=4j;c.H=75;c.v=4j.v;c.12=12};l.4i.Z.2f=h(){q c.1W};l.44=h(4g){p 1H=l.B.4c(4g),4f=R l.30.aA(),aB=u;f(1H==u){q}1H=R 1H();c.4X=4f;f(1H.3K==u){l.B.1u(l.Q.1b.7z+4g);q}4f.4B.K({3D:1H.3K.I,4m:7F});h 39(4d,7G){C(p j=0;j<4d.v;j++){4d[j].H+=7G}};h 7F(14,aH){p 7x=14.I,1E=[],4k=1H.4B,7p=14.H+14.E.v,2X=1H.3K,1n;C(p i=0;i<4k.v;i++){1n=l.B.2D(7x,4k[i]);39(1n,7p);1E=1E.2H(1n)}f(2X.E!=u&&14.E!=u){1n=l.B.2D(14.E,2X.E);39(1n,14.H);1E=1E.2H(1n)}f(2X.17!=u&&14.17!=u){1n=l.B.2D(14.17,2X.17);39(1n,14.H+14[0].aM(14.17));1E=1E.2H(1n)}q 1E}};l.44.Z.1I=h(7u,7t){c.4X.1I(7u,7t);c.z=c.4X.z};l.87=h(){};l.87.Z={T:h(7v,7n){p 5J=c.1L[7v];q l.B.7w(5J==u?7n:5J)},15:h(7y){q J.1t(7y)},7m:h(5G){C(p i=0;i<c.1Y.v;i++){p 2V=c.1Y[i];f(2V===u){1V}f((5G.H>2V.H)&&(5G.H<2V.H+2V.v)){q U}}q O},6v:h(3v,7D){p 2e=[];f(3v!=u){C(p i=0;i<3v.v;i++){2e=2e.2H(l.B.2D(7D,3v[i]))}}2e=2e.aL(l.B.7B);q 2e},6u:h(){C(p i=0;i<c.1Y.v;i++){f(c.7m(c.1Y[i])){c.1Y[i]=u}}},6k:h(2C){p 3w=2C.21(/\\n/g),3s=7l(c.T("73-2E")),7e=(3s+3w.v).2f().v,89=c.T("1I",[]);2C="";C(p i=0;i<3w.v;i++){p 1s=3w[i],2w=/^(&1O;|\\s)+/.N(1s),5w="2E aK"+(i%2==0?1:2),82=l.B.7f(3s+i,7e),83=89.1h((3s+i).2f())!=-1,1D=u;f(2w!=u){1D=2w[0].2f();1s=1s.1M(1D.v);1D=1D.D(/&1O;/g," ");2w=l.1p.3q*1D.v}F{2w=0}1s=l.B.3P(1s);f(1s.v==0){1s="&1O;"}f(83){5w+=" aI"}2C+="<z 1e=\\""+5w+"\\">"+"<I 1e=\\"aJ\\">"+82+".</I>"+"<1T 1e=\\"5h\\">"+(1D!=u?"<I 1e=\\"az\\">"+1D.D(/\\s/g,"&1O;")+"</I>":"")+"<1T 1e=\\"7V\\" 1f=\\"5n-E: "+2w+"5H !aq;\\">"+1s+"</1T>"+"</1T>"+"</z>"}q 2C},6w:h(5N,5K){p 18=0,3n="",3r=l.B.80;C(p i=0;i<5K.v;i++){p 1y=5K[i];f(1y===u||1y.v===0){1V}3n+=3r(5N.1M(18,1y.H-18),"63")+3r(1y.1W,1y.12);18=1y.H+1y.v}3n+=3r(5N.1M(18),"63");q 3n},1I:h(1g,5R){p am=l.Q,3p=l.1p,z,34;c.1L={};c.z=u;c.26=u;c.I=u;c.2d=u;c.5E={};c.1j=l.B.5m("ar");3p.5j[c.1j]=c;f(1g===u){1g=""}f(3p.3q===u){3p.3q=l.B.5y()}c.1L=l.B.5u(l.5S,5R||{});f(c.T("6J")==U){c.1L.1q=c.1L.5x=O}c.z=z=c.15("37");c.26=c.15("37");c.26.Y="26";z.Y="6L";z.1j=c.1j;f(c.T("5v")){z.Y+=" 5t"}f(c.T("5x")==O){z.Y+=" ax"}z.Y+=" "+c.T("1e-1c");z.1f.av=c.T("2a-1P","");c.5r=1g;c.I=l.B.6U(1g).D(/\\r/g," ");34=c.T("1F-1P");c.I=c.T("6T-6S")==U?l.B.6P(c.I,34):l.B.6Q(c.I,34);c.I=l.B.2W(c.I);f(c.T("1q")){c.2d=c.15("37");c.2d.Y="2d";c.2d.1z(l.1q.15(c));z.1z(c.2d)}f(c.T("5F")){z.1z(l.B.6x())}z.1z(c.26);c.1Y=c.6v(c.4B,c.I);c.6u();1g=c.6w(c.I,c.1Y);1g=c.6k(l.B.3P(1g));f(c.T("6i-6p")){1g=l.B.6o(1g)}c.26.1r=1g},au:h(A){A=A.D(/^\\s+|\\s+$/g,"").D(/\\s+/g,"\\\\b|\\\\b");q"\\\\b"+A+"\\\\b"},at:h(2z){c.3K={E:{3D:2z.E,12:"2n"},17:{3D:2z.17,12:"2n"},I:R M("(?<E>"+2z.E.1i+")"+"(?<I>.*?)"+"(?<17>"+2z.17.1i+")","aw")}}};q l}()}f(!5B.1h){5B.Z.1h=h(5V,3J){3J=3z.as(3J||0,0);C(p i=3J;i<c.v;i++){f(c[i]==5V){q i}}q-1}}f(!1o.M){(h(){p 2v={N:V.Z.N,64:5q.Z.64,D:5q.Z.D,21:5q.Z.21},1G={11:/(?:[^\\\\([#\\s.]+|\\\\(?!k<[\\w$]+>|[65]{[^}]+})[\\S\\s]?|\\((?=\\?(?!#|<[\\w$]+>)))+|(\\()(?:\\?(?:(#)[^)]*\\)|<([$\\w]+)>))?|\\\\(?:k<([\\w$]+)>|[65]{([^}]+)})|(\\[\\^?)|([\\S\\s])/g,al:/(?:[^$]+|\\$(?![1-9$&`\']|{[$\\w]+}))+|\\$(?:([1-9]\\d*|[$&`\'])|{([$\\w]+)})/g,3F:/^(?:\\s+|#.*)+/,3R:/^(?:[?*+]|{\\d+(?:,\\d*)?})/,7H:/&&\\[\\^?/g,7q:/]/g},7N=h(5I,7Y,7K){C(p i=7K||0;i<5I.v;i++){f(5I[i]===7Y){q i}}q-1},7k=/()??/.N("")[1]!==3A,3L={};M=h(1d,1U){f(1d 4T V){f(1U!==3A){3G 62("56\'t 58 an 6G ao 5X V ap ay")}q 1d.3I()}p 1U=1U||"",7s=1U.1h("s")>-1,7r=1U.1h("x")>-1,4b=O,3C=[],13=[],11=1G.11,G,3N,3O,3E,3B;11.L=0;28(G=2v.N.2x(11,1d)){f(G[2]){f(!1G.3R.1R(1d.19(11.L))){13.K("(?:)")}}F{f(G[1]){3C.K(G[3]||u);f(G[3]){4b=U}13.K("(")}F{f(G[4]){3E=7N(3C,G[4]);13.K(3E>-1?"\\\\"+(3E+1)+(5z(1d.5O(11.L))?"":"(?:)"):G[0])}F{f(G[5]){13.K(3L.6Z?3L.6Z.7C(G[5],G[0].5O(1)==="P"):G[0])}F{f(G[6]){f(1d.5O(11.L)==="]"){13.K(G[6]==="["?"(?!)":"[\\\\S\\\\s]");11.L++}F{3N=M.6E("&&"+1d.19(G.H),1G.7H,1G.7q,"",{5W:"\\\\"})[0];13.K(G[6]+3N+"]");11.L+=3N.v+1}}F{f(G[7]){f(7s&&G[7]==="."){13.K("[\\\\S\\\\s]")}F{f(7r&&1G.3F.1R(G[7])){3O=2v.N.2x(1G.3F,1d.19(11.L-1))[0].v;f(!1G.3R.1R(1d.19(11.L-1+3O))){13.K("(?:)")}11.L+=3O-1}F{13.K(G[7])}}}F{13.K(G[0])}}}}}}}3B=V(13.4h(""),2v.D.2x(1U,/[aG]+/g,""));3B.1v={1i:1d,2o:4b?3C:u};q 3B};M.ak=h(1c,o){3L[1c]=o};V.Z.N=h(A){p 1a=2v.N.2x(c,A),1c,i,5g;f(1a){f(7k&&1a.v>1){5g=R V("^"+c.1i+"$(?!\\\\s)",c.3U());2v.D.2x(1a[0],5g,h(){C(i=1;i<7b.v-2;i++){f(7b[i]===3A){1a[i]=3A}}})}f(c.1v&&c.1v.2o){C(i=1;i<1a.v;i++){1c=c.1v.2o[i-1];f(1c){1a[1c]=1a[i]}}}f(c.3H&&c.L>(1a.H+1a[0].v)){c.L--}}q 1a}})()}V.Z.3U=h(){q(c.3H?"g":"")+(c.9Z?"i":"")+(c.6W?"m":"")+(c.3F?"x":"")+(c.a1?"y":"")};V.Z.3I=h(7Q){p 3T=R M(c.1i,(7Q||"")+c.3U());f(c.1v){3T.1v={1i:c.1v.1i,2o:c.1v.2o?c.1v.2o.19(0):u}}q 3T};V.Z.2x=h(a3,A){q c.N(A)};V.Z.9S=h(9R,7W){q c.N(7W[0])};M.3Z=h(4r,4Z){p 40="/"+4r+"/"+(4Z||"");q M.3Z[40]||(M.3Z[40]=R M(4r,4Z))};M.3M=h(A){q A.D(/[-[\\]{}()*+?.\\\\^$|,#\\s]/g,"\\\\$&")};M.6E=h(A,E,W,1k,2M){p 2M=2M||{},2U=2M.5W,X=2M.af,1k=1k||"",4O=1k.1h("g")>-1,6y=1k.1h("i")>-1,5U=1k.1h("m")>-1,4H=1k.1h("y")>-1,1k=1k.D(/y/g,""),E=E 4T V?(E.3H?E:E.3I("g")):R M(E,"g"+1k),W=W 4T V?(W.3H?W:W.3I("g")):R M(W,"g"+1k),1K=[],2r=0,1m=0,1l=0,1x=0,27,1Z,1w,1B,3Q,4n;f(2U){f(2U.v>1){3G ae("56\'t 58 ag ad 5X 3M 6I")}f(5U){3G 62("56\'t 58 3M 6I 6G a8 a9 6W aP")}3Q=M.3M(2U);4n=R V("^(?:"+3Q+"[\\\\S\\\\s]|(?:(?!"+E.1i+"|"+W.1i+")[^"+3Q+"])+)+",6y?"i":"")}28(U){E.L=W.L=1l+(2U?(4n.N(A.19(1l))||[""])[0].v:0);1w=E.N(A);1B=W.N(A);f(1w&&1B){f(1w.H<=1B.H){1B=u}F{1w=u}}f(1w||1B){1m=(1w||1B).H;1l=(1w?E:W).L}F{f(!2r){2B}}f(4H&&!2r&&1m>1x){2B}f(1w){f(!2r++){27=1m;1Z=1l}}F{f(1B&&2r){f(!--2r){f(X){f(X[0]&&27>1x){1K.K([X[0],A.19(1x,27),1x,27])}f(X[1]){1K.K([X[1],A.19(27,1Z),27,1Z])}f(X[2]){1K.K([X[2],A.19(1Z,1m),1Z,1m])}f(X[3]){1K.K([X[3],A.19(1m,1l),1m,1l])}}F{1K.K(A.19(1Z,1m))}1x=1l;f(!4O){2B}}}F{E.L=W.L=0;3G b6("bw bp 8l 8u 8A")}}f(1m===1l){1l++}}f(4O&&!4H&&X&&X[0]&&A.v>1x){1K.K([X[0],A.19(1x),1x,A.v])}E.L=W.L=0;q 1K};',62,725,"||||||||||||this|||if||function||||sh||||var|return||||null|length||||div|str|utils|for|replace|left|else|_109|index|code|document|push|lastIndex|XRegExp|exec|false||config|new||getParam|true|RegExp|_121|vN|className|prototype||part|css|_107|_c3|create||right|pos|slice|_111|strings|name|_101|class|style|_ed|indexOf|source|id|_122|_12d|_12c|_ca|window|vars|toolbar|innerHTML|_e0|createElement|alert|_x|_131|_12e|_ec|appendChild|obj|_132|lt|_e5|_c6|tab|lib|_bd|highlight|doc|_12a|params|substr|width|nbsp|size|_97|test|_4b|span|_102|continue|value|in|matches|_130|_91|split|_8|_57|min|_3c|lines|_12f|while|_56|font|wnd|text|bar|_d7|toString|_6e|execute|_75|html|_5b|_b7|gt|script|captureNames|attributes|href|_12b|_b4|_b1|height|_f8|_e1|call|http|_f4|_28|break|_da|getMatches|line|_b3|_a1|concat|_51|case|m2|m1|_123|_5|_80|_88|_81|body|_40|_62|_124|_d4|unindent|_c9|_b5|_7a|brushes|SyntaxHighlighter|_2|_22|_f2|_32|title|DIV|_3|offsetMatches|_7d|_7b|_8e|fixForBlogger|url|_7c|_5e|_65|_6a|_5c|_76|_4a|_af|_e9|printFrame|_f0|spaceWidth|_ea|_dc|write|print|_d5|_db|_25|_a6|Math|undefined|_10d|_106|regex|_10c|extended|throw|global|addFlags|_f6|htmlScript|_100|escape|cc|len|trim|_133|quantifier|_9d|_116|getNativeFlags|_9c|_a2|_a5|viewSource|cache|key|_89|eachLine|_2c|HtmlScript|_18|_30|gi|_2f|_ad|com|_105|findBrush|_c0|expandSource|_be|_bc|join|Match|_b9|_c7|_ab|func|esc|_b6|_19|_1a|_11b|_ac|swf|_4c|_9|_b|_49|popup|top|focus|regexList|_50|_4f|_48|_e|_7|_129|_38|contentWindow|link|_4|gm|close|_126|_blank|win|_35|_24|instanceof|_73|_6b|_82|xmlBrush|_17|_11c||removeChild|_7e|color|values|_5d|can|_f|supply|discoveredBrushes|_59|_6c|_10|_37|_d|_8c|r2|content|toolbarItemWidth|highlighters|toolbarItemHeight|copyToClipboard|guid|margin|_2e|_2d|String|originalCode|_2a|collapsed|merge|collapse|_e2|gutter|measureSpace|isNaN|_2b|Array|_29|clipboardSwf|toolbarCommands|ruler|_d2|px|_fb|_d0|_e7|pre|_27|_e6|charAt|highlighterId|_83|_ee|defaults|_14|_128|_f5|escapeChar|one|_5a|noBrush|_61|navigator|TypeError|plain|match|pP|_78|_79|_36|_6d|alexgorbatchev|userAgent|commandName|_66|clipboardData|executeCommand|event|help|auto|_6|createDisplayLines|500px|0px|scrollbars|processUrls|links|stylesheet|rel|_3f|copyStyles|removeNestedMatches|findMatches|processMatches|createRuler|_127|type|_3e|aboutDialog|createButton|attachEvent|matchRecursive|message|when|2009|character|light|clipboard|syntaxhighlighter|_4e|screen|_a|processSmartTabs|processTabs|_47|tabs|smart|trimFirstAndLastLines|switch|multiline|copyToClipboardConfirmation|_85|unicode|head|parentNode|_16|first|shockwave|_ba|_b8|items|addEvent|flash|_13|arguments|_aa|parseParams|_dd|padNumber|_b0|Times|_12|debug|_ff|parseInt|isMatchNested|_cf|org|_c8|classRight|_104|_103|_cd|_cc|_ce|toBoolean|_c5|_d1|brushNotHtmlScript|www|matchesSortCallback|get|_d6|w3|process|_c1|classLeft|tagName|brush|_fd|serif|getElementsByTagName|_fa|_15|bloggerMode|_115|_84|_99|family|_93|block|args|insertSpaces|_fc|_90|decorate|_a3|_e3|_e4|version|center|xhtml1|Highlighter|toArray|_de|regexLib|DTD|_a7|_a0|defaultAdd|_a8|_1e|object|align|try|resizable|contains|catch|400|_20|_1f|onclick|750|menubar|_21|unbalanced|_1b|item|location|_26|param|delimiters|_1c|sans|1999|xhtml|meta|xmlns|dtd|EN|TR|transitional|equiv|Content|Georgia|New|Roman|About|utf|Type|charset|Transitional|XHTML|is|your|now|The|to|expand|view|copy|Can|find|DOCTYPE|PUBLIC|W3C|option|configured|Brush|wasn|background|fff|Gorbatchev|multiLineCComments|singleLineCComments|Alex|2004|syntax|highlighter|Copyright|singleLinePerlComments|doubleQuotedString|aspScriptTags|scriptScriptTags|typeof|phpScriptTags|multiLineSingleQuotedString|singleQuotedString|multiLineDoubleQuotedString|JavaScript|none|Helvetica|xx|large|Arial|Geneva|000|1em|3em|75em|bottom|target|0099FF|decoration|01|March|4em|296|string|open|_119|apply|_8a|offsetWidth|getComputedStyle|getPropertyValue|_98|1000|ignoreCase|textarea|sticky|_a4|_117|opera|getElementById|on|addEventListener|using|the|random|1000000|aliases|than|SyntaxError|valueNames|more|middot|_clipboard|70em|addPlugin|replaceVar|_ef|flags|constructing|from|important|highlighter_|max|forHtmlScript|getKeywords|fontSize|sgi|nogutter|another|spaces|Xml|_bf|load|all|30em|replaceChild|sx|_c4|highlighted|number|alt|sort|lastIndexOf|round|150|flag|msie|src|embed|classid|movie|_33|_34|ok|error|setData|amp|command|cab|swflash|96b8|11cf|Error|444553540000|codebase|ae6d|download|pub|cabs|clsid|macromedia|d27cdb6e|_39|printSource|shCore|about|toLowerCase|allowScriptAccess|always|printing|_42|data|500||250|_44|application|_43|subject|wmode|_3a|flashVars|transparent|_3b|cssText|absolute|position|menu|IFRAME".split("|"),0,{}));SyntaxHighlighter.brushes.JScript=function(){var a="abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var void volatile while with";this.regexList=[{regex:SyntaxHighlighter.regexLib.singleLineCComments,css:"comments"},{regex:SyntaxHighlighter.regexLib.multiLineCComments,css:"comments"},{regex:SyntaxHighlighter.regexLib.doubleQuotedString,css:"string"},{regex:SyntaxHighlighter.regexLib.singleQuotedString,css:"string"},{regex:/\s*#.*/gm,css:"preprocessor"},{regex:new RegExp(this.getKeywords(a),"gm"),css:"keyword"}];this.forHtmlScript(SyntaxHighlighter.regexLib.scriptScriptTags)};SyntaxHighlighter.brushes.JScript.prototype=new SyntaxHighlighter.Highlighter;SyntaxHighlighter.brushes.JScript.aliases=["js","jscript","javascript"];SyntaxHighlighter.brushes.Xml=function(){function a(b){var e=SyntaxHighlighter.Match,f=b[0],d=(new XRegExp("(&lt;|<)[\\s\\/\\?]*(?<name>[:\\w-\\.]+)","xg")).exec(f),c=[];if(b.attributes!=null){var a,g=new XRegExp("(?<name> [\\w:\\-\\.]+)\\s*=\\s*(?<value> \".*?\"|'.*?'|\\w+)","xg");while((a=g.exec(f))!=null){c.push(new e(a.name,b.index+a.index,"color1"));c.push(new e(a.value,b.index+a.index+a[0].indexOf(a.value),"string"))}}d!=null&&c.push(new e(d.name,b.index+d[0].indexOf(d.name),"keyword"));return c}this.regexList=[{regex:new XRegExp("(\\&lt;|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](\\&gt;|>)","gm"),css:"color2"},{regex:new XRegExp("(\\&lt;|<)!--\\s*.*?\\s*--(\\&gt;|>)","gm"),css:"comments"},{regex:new XRegExp("(&lt;|<)[\\s\\/\\?]*(\\w+)(?<attributes>.*?)[\\s\\/\\?]*(&gt;|>)","sg"),func:a}]};SyntaxHighlighter.brushes.Xml.prototype=new SyntaxHighlighter.Highlighter;SyntaxHighlighter.brushes.Xml.aliases=["xml","xhtml","xslt","html","xhtml"];SyntaxHighlighter.config.bloggerMode=true;SyntaxHighlighter.config.clipboardSwf="http://alexgorbatchev.com/pub/sh/2.0.296/scripts/clipboard.swf";SyntaxHighlighter.defaults.toolbar=false;SyntaxHighlighter.defaults.smartTabs=true;SyntaxHighlighter.defaults.gutter=false;SyntaxHighlighter.all()
apps/jquery-tmpl/demos/samplesCore/Interactive/resources/collapsed.png ADDED
Binary file
apps/jquery-tmpl/demos/samplesCore/Interactive/resources/empty.png ADDED
Binary file
apps/jquery-tmpl/demos/samplesCore/Interactive/resources/expanded.png ADDED
Binary file
apps/jquery-tmpl/demos/samplesCore/Interactive/resources/folder.png ADDED
Binary file
apps/jquery-tmpl/demos/samplesCore/Interactive/resources/tabs.css ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body
2
+ {
3
+ font-family: Arial;
4
+ }
5
+
6
+ .special
7
+ {
8
+ color: Red;
9
+ font-family: Comic Sans MS;
10
+ font-size: 20px;
11
+ font-style: italic;
12
+ }
13
+
14
+ .tabsView .body
15
+ {
16
+ height: 200px;
17
+ }
18
+
19
+ .tabsView .body div
20
+ {
21
+ padding: 15px;
22
+ height: 60px;
23
+ vertical-align: middle;
24
+ text-align: center;
25
+ }
26
+
27
+ .tabsView .body h3
28
+ {
29
+ text-align:center;
30
+ }
31
+
32
+ .tabsView td
33
+ {
34
+ border: solid 1px #0000A6;
35
+ border-top: none;
36
+ border-right: solid 2px #1E1ED2;
37
+ }
38
+
39
+ .tabsView th
40
+ {
41
+ cursor: pointer;
42
+ padding: 2px;
43
+ font-weight: normal;
44
+ font-style: italic;
45
+ color: #888;
46
+ border: solid 1px #bbb;
47
+ border-right: none;
48
+ background-color: #f8f8f8;
49
+ border-bottom: solid 1px #1E1ED2;
50
+ }
51
+
52
+ .tabsView
53
+ {
54
+ width: 500px;
55
+ border-collapse: collapse;
56
+ border: none;
57
+ margin-top: 20px;
58
+ }
59
+
60
+ .tabsView tr
61
+ {
62
+ border-right: solid 1px #bbb;
63
+ }
64
+
65
+ .tabsView th.header_true
66
+ {
67
+ cursor:default;
68
+ font-weight: bold;
69
+ border: solid 1px #0000A6;
70
+ border-right: solid 2px #1E1ED2;
71
+ border-bottom: solid 1px #eee;
72
+ color: #0000A6;
73
+ background-color: #fff;
74
+ }
75
+
apps/jquery-tmpl/demos/samplesCore/Interactive/resources/treeView.css ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .treeView, .treeView ul
2
+ {
3
+ padding: 0;
4
+ margin: 0;
5
+ }
6
+
7
+ .treeView li
8
+ {
9
+ list-style-type: none;
10
+ padding: 2px;
11
+ }
12
+
13
+ .treeView li li
14
+ {
15
+ margin-left: 18px;
16
+ }
17
+
18
+ .treeView img
19
+ {
20
+ vertical-align: middle;
21
+ border: 0px;
22
+ margin-right:7px;
23
+ }
24
+
25
+ img.folder
26
+ {
27
+ width:15px;
28
+ height:14px;
29
+ }
30
+
31
+ img.expand
32
+ {
33
+ width:8px;
34
+ width:9px;
35
+ }
36
+
37
+ .treeView li.folderItem
38
+ {
39
+ cursor: pointer;
40
+ color:Blue;
41
+ text-decoration: underline;
42
+ font-style:italic;
43
+ margin-bottom: 4px;
44
+ }
45
+
46
+ .content_true
47
+ {
48
+ cursor: pointer;
49
+ font-weight: bold;
50
+ }
apps/jquery-tmpl/demos/samplesCore/Interactive/tabsTmpl.html ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ A tabs control against data, using {{tmpl}}
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title>A tabs control against data, using {{tmpl}}</title>
8
+ <link href="resources/tabs.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+
12
+ <h1>Tabs</h1>
13
+ <div id="tabsView">..loading</div>
14
+
15
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
16
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
17
+
18
+ <script id="tabsTmpl" type="text/x-jquery-tmpl">
19
+ <table class="tabsView"><tbody>
20
+ <tr>{{tmpl(items) "#headerItemTmpl"}}</tr>
21
+ <tr><td colspan="${items.length}">
22
+ <div class="body">{{tmpl(activeDataItem) "#contentTmpl"}}</div>
23
+ </td></tr>
24
+ </tbody></table>
25
+ </script>
26
+
27
+ <script id="headerItemTmpl" type="text/x-jquery-tmpl">
28
+ <th class="header_${$data === activeDataItem}">${name}</th>
29
+ </script>
30
+
31
+ <script id="contentTmpl" type="text/x-jquery-tmpl">
32
+ <h3>${title}</h3>
33
+ <div>{{html description}}</div>
34
+ </script>
35
+
36
+ <script type="text/javascript">
37
+
38
+ // ******************** Data for categories and samples ********************
39
+
40
+ var samples = {
41
+ title: "Templating samples",
42
+ items: [
43
+ { name: "Inline", title: "Template inline in a script block",
44
+ description:"Rendering a <span class='special'>template</span> declared in script block" },
45
+ { name: "String", title: "Template as string",
46
+ description:"Rendering a <span class='special'>template</span> passed as a string" },
47
+ { name: "Remote", title: "Render remote data",
48
+ description:"Rendering remote data using <span class='special'>templates</span>" },
49
+ { name: "TreeView", title: "Building a Tree View",
50
+ description:"A tree view using recursive nested <span class='special'>templates</span>" },
51
+ { name: "Tabs", title: "A Tabs control",
52
+ description:"Create a tabs control using <span class='special'>templates</span>" }
53
+ ]
54
+ },
55
+
56
+ activeDataItem = samples.items[0];
57
+
58
+ // ******************** Load UI ********************
59
+
60
+ $( "#tabsView" ).empty();
61
+ $( "#tabsTmpl" ).tmpl( samples ).appendTo( "#tabsView" );
62
+
63
+ // ******************** Events ********************
64
+
65
+ $( "#tabsView" )
66
+ .delegate( ".header_false", "click", function() {
67
+ // Get the 'template item' for this tab
68
+ var activeHeaderTmplItem = $.tmplItem( this );
69
+ activeDataItem = activeHeaderTmplItem.data;
70
+
71
+ // Update the template item for the whole tabs control
72
+ activeHeaderTmplItem.parent.update();
73
+ })
74
+ </script>
75
+
76
+ </body>
77
+ </html>
apps/jquery-tmpl/demos/samplesCore/Interactive/tabsWrap.html ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ A tabs control against HTML markup, using {{wrap}}
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title>A tabs control against HTML markup, using {{wrap}}</title>
8
+ <link href="resources/tabs.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+
12
+ <h1>Tabs</h1>
13
+
14
+ <div id="tabsView">..loading</div>
15
+
16
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
17
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
18
+
19
+ <script id="tabsTmpl" type="text/x-jquery-tmpl">
20
+ {{wrap(null, {state: state}) "#tabsWrap"}}
21
+
22
+ <h3>Inline</h3>
23
+ <div>
24
+ Rendering a <span class='special'>template</span> declared in script block
25
+ </div>
26
+
27
+ <h3>String</h3>
28
+ <div>
29
+ Rendering a <span class='special'>template</span> passed as a string
30
+ </div>
31
+
32
+ <h3>Remote</h3>
33
+ <div>
34
+ Rendering remote data using <span class='special'>templates</span>
35
+ </div>
36
+
37
+ {{/wrap}}
38
+ </script>
39
+
40
+ <script id="tabsWrap" type="text/x-jquery-tmpl">
41
+ <table class="tabsView"><tbody>
42
+ <tr>
43
+ {{each tabs()}}
44
+ <th class="${headerClass($index)}">
45
+ ${$value}
46
+ </th>
47
+ {{/each}}
48
+ </tr>
49
+ <tr><td colspan="${tabCount()}">
50
+ <div class="body">
51
+ {{html tabContent()}}
52
+ </div>
53
+ </td></tr>
54
+ </tbody></table>
55
+ </script>
56
+
57
+ <script type="text/javascript">
58
+
59
+ var state = { activeIndex: 0 };
60
+
61
+ // ******************** Load UI ********************
62
+
63
+ $( "#tabsView" ).empty();
64
+ $( "#tabsTmpl" ).tmpl().appendTo( "#tabsView" );
65
+
66
+ // ******************** Events ********************
67
+
68
+ $( "#tabsView" )
69
+ .delegate( ".header_false", "click", function() {
70
+ var ti = $.tmplItem( this );
71
+ ti.state.activeIndex = $(this).index();
72
+ ti.update();
73
+ });
74
+
75
+ // ******************** Helper functions ********************
76
+
77
+ function tabs() {
78
+ return this.html("h3", true);
79
+ }
80
+ function tabCount() {
81
+ return this.html("h3").length;
82
+ }
83
+ function headerClass( index ) {
84
+ return index === this.state.activeIndex ? "header_true" : "header_false";
85
+ }
86
+
87
+ function tabContent() {
88
+ return this.html("div")[this.state.activeIndex];
89
+ }
90
+
91
+ </script>
92
+
93
+ </body>
94
+ </html>
apps/jquery-tmpl/demos/samplesCore/Interactive/tabsWrapImperative.html ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ A tabs control against HTML markup, using imperative API to provide wrapped HTML content
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title>A tabs control against HTML markup, using imperative API to provide wrapped HTML content</title>
8
+ <link href="resources/tabs.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+
12
+ <h1>Tabs</h1>
13
+
14
+ <div id="tabsView">..loading</div>
15
+
16
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
17
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
18
+
19
+ <div id="tabsContent" style="display:none">
20
+ <h3>Inline</h3>
21
+ <div>
22
+ Rendering a <span class='special'>template</span> declared in script block
23
+ </div>
24
+
25
+ <h3>String</h3>
26
+ <div>
27
+ Rendering a <span class='special'>template</span> passed as a string
28
+ </div>
29
+
30
+ <h3>Remote</h3>
31
+ <div>
32
+ Rendering remote data using <span class='special'>templates</span>
33
+ </div>
34
+ </div>
35
+
36
+ <script id="tabsWrap" type="text/x-jquery-tmpl">
37
+ <table class="tabsView"><tbody>
38
+ <tr>
39
+ {{each $item.html("h3", true)}}
40
+ <th class="header_${$index === $item.state.activeIndex}">
41
+ ${$value}
42
+ </th>
43
+ {{/each}}
44
+ </tr>
45
+ <tr><td colspan='${$item.html("h3").length}'>
46
+ <div class="body">
47
+ {{html $item.html("div")[$item.state.activeIndex]}}
48
+ </div>
49
+ </td></tr>
50
+ </tbody></table>
51
+ </script>
52
+
53
+ <script type="text/javascript">
54
+
55
+ var state = { activeIndex: 0 };
56
+
57
+ // ******************** Load UI ********************
58
+
59
+ $( "#tabsView" ).empty();
60
+ $( "#tabsWrap" ).tmpl( null, {state: state, wrapped: "#tabsContent"} ).appendTo( "#tabsView" );
61
+
62
+ // ******************** Events ********************
63
+
64
+ $( "#tabsView" )
65
+ .delegate( ".header_false", "click", function() {
66
+ var ti = $.tmplItem( this );
67
+ ti.state.activeIndex = $(this).index();
68
+ ti.update();
69
+ });
70
+
71
+ </script>
72
+
73
+ </body>
74
+ </html>
apps/jquery-tmpl/demos/samplesCore/Interactive/tabsWrapNested.html ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ Nested tabs controls against HTML markup, using {{wrap}}
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title>Nested tabs controls against HTML markup, using {{wrap}}</title>
8
+ <link href="resources/tabs.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+
12
+ <h1>Tabs</h1>
13
+
14
+ <div id="tabsView">..loading</div>
15
+
16
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
17
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
18
+
19
+ <script id="tabsTmpl" type="text/x-jquery-tmpl">
20
+ {{wrap(null, {state: outerState}) "#tabsWrap"}}
21
+
22
+ <h3>Inline</h3>
23
+ <div>
24
+ Rendering a <span class='special'>template</span> declared in script block
25
+ </div>
26
+
27
+ <h3>String</h3>
28
+ <div>
29
+ Rendering a <span class='special'>template</span> passed as a string
30
+ </div>
31
+
32
+ <h3>Remote</h3>
33
+ <div>
34
+ Rendering remote data using <span class='special'>templates</span>
35
+
36
+ {{wrap(null, {state: innerState}) "#tabsWrap"}}
37
+
38
+ <h3>GET</h3>
39
+ <div>
40
+ Using <b>GET</b> to fetch data
41
+ </div>
42
+
43
+ <h3>POST</h3>
44
+ <div>
45
+ Using <b>POST</b> to update server data
46
+ </div>
47
+
48
+ {{/wrap}}
49
+
50
+ </div>
51
+
52
+ {{/wrap}}
53
+ </script>
54
+
55
+ <script id="tabsWrap" type="text/x-jquery-tmpl">
56
+ <table class="tabsView"><tbody>
57
+ <tr>
58
+ {{each tabs()}}
59
+ <th class="${headerClass($index)}">
60
+ ${$value}
61
+ </th>
62
+ {{/each}}
63
+ </tr>
64
+ <tr><td colspan="${tabCount()}">
65
+ <div class="body">
66
+ {{html tabContent()}}
67
+ </div>
68
+ </td></tr>
69
+ </tbody></table>
70
+ </script>
71
+
72
+ <script type="text/javascript">
73
+
74
+ var innerState = { activeIndex: 0 },
75
+ outerState = { activeIndex: 2 };
76
+
77
+ // ******************** Load UI ********************
78
+
79
+ function refresh() {
80
+ $( "#tabsView" ).empty();
81
+ $( "#tabsTmpl" ).tmpl().appendTo( "#tabsView" );
82
+ }
83
+ refresh();
84
+
85
+
86
+ // ******************** Events ********************
87
+
88
+ $( "#tabsView" )
89
+ .delegate( ".header_false", "click", function() {
90
+ var ti = $.tmplItem( this );
91
+ ti.state.activeIndex = $(this).index();
92
+ refresh();
93
+ });
94
+
95
+ // ******************** Helper functions ********************
96
+
97
+ function tabs() {
98
+ return this.html("h3", true);
99
+ }
100
+
101
+ function tabCount() {
102
+ return this.html("h3").length;
103
+ }
104
+
105
+ function headerClass( index ) {
106
+ return index === this.state.activeIndex ? "header_true" : "header_false";
107
+ }
108
+
109
+ function tabContent() {
110
+ return this.html("div")[this.state.activeIndex];
111
+ }
112
+
113
+ </script>
114
+
115
+ </body>
116
+ </html>
apps/jquery-tmpl/demos/samplesCore/Interactive/treeView.html ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ A tree view control using recursive templates
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <title>A tree view control using recursive templates</title>
8
+ <link href="resources/treeView.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+
12
+ <h1>Tree View</h1>
13
+
14
+ <div><ul id="samplesList" class="treeView"><li>Loading...</li></ul></div>
15
+
16
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
17
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
18
+
19
+ <script id="folderTmpl" type="text/x-jquery-tmpl">
20
+ <li class="content_${hasContent($item)}">
21
+ <img class="expand" src="resources/${expanderImage()}.png" />
22
+ <img class="folder" src="resources/folder.png" />
23
+ <span>${name}</span>
24
+ </li>
25
+ {{if expanded}}
26
+ <li>
27
+ <ul>{{tmpl(getSamples($item)) "#itemTmpl"}}</ul>
28
+ <ul>{{tmpl(getFolders($item)) "#folderTmpl"}}</ul>
29
+ </li>
30
+ {{/if}}
31
+ </script>
32
+
33
+ <script id="itemTmpl" type="text/x-jquery-tmpl">
34
+ <li class="folderItem">${name}</li>
35
+ </script>
36
+
37
+ <script type="text/javascript">
38
+
39
+ // ******************** Data for folders hierarchy, and samples ********************
40
+
41
+ var folders = {
42
+ name: "Samples",
43
+ folders: [
44
+ { name: "API", folders: [
45
+ { name: ".tmpl"},
46
+ { name: ".tmplItem" }
47
+ ]},
48
+ { name: "Template markup", folders: [
49
+ { name: "Tags", folders: [
50
+ { name: "tmpl"},
51
+ { name: "if" },
52
+ { name: "each" }
53
+ ]},
54
+ ]},
55
+ ]
56
+ };
57
+
58
+ var samples = [
59
+ { name: "Template in script block",
60
+ folders: [ ".tmpl" ],
61
+ description: "Rendering a template declared in script block" },
62
+ { name: "Template as string",
63
+ folders: [ ".tmpl" ],
64
+ description:"Rendering a template passed as a string" },
65
+ { name: "Render remote data",
66
+ folders: [ "API" ],
67
+ description: "Rendering remote data using templates" },
68
+ { name: "Tree View",
69
+ folders: [ "tmpl", ".tmpl" ],
70
+ description: "A tree view using recursive nested templates" }
71
+ ];
72
+
73
+ // ******************** Load UI ********************
74
+
75
+ $( "#samplesList" ).empty();
76
+ $( "#folderTmpl" ).tmpl( folders ).appendTo( "#samplesList" );
77
+
78
+ // ******************** Events ********************
79
+
80
+ $( "#samplesList" )
81
+ .delegate( ".content_true", "click", function() {
82
+ // Get the 'template item' for this folder
83
+ var fldrTmplItem = $.tmplItem( this );
84
+
85
+ // Toggle expanded property on data
86
+ fldrTmplItem.data.expanded = !fldrTmplItem.data.expanded;
87
+
88
+ // Update the template item
89
+ fldrTmplItem.update();
90
+ })
91
+ .delegate( ".folderItem", "click", function() {
92
+ // Get the 'template item' for this folder item
93
+ var dataItem = $.tmplItem( this ).data;
94
+ alert( dataItem.description );
95
+ });
96
+
97
+ // ******************** Helper functions ********************
98
+
99
+ function getSamples( folderTmplItem ) {
100
+ return $.map( samples, function( sample ) {
101
+ return $.inArray( folderTmplItem.data.name, sample.folders ) > -1 ? sample : null;
102
+ });
103
+ }
104
+
105
+ function getFolders( folderTmplItem ) {
106
+ return folderTmplItem.data.folders || [];
107
+ }
108
+
109
+ function expanderImage() {
110
+ if ( hasContent( this ) ) {
111
+ return this.data.expanded ? "expanded" : "collapsed";
112
+ }
113
+ return "empty"
114
+ }
115
+
116
+ function hasContent( folderTmplItem ) {
117
+ return getFolders( folderTmplItem ).length > 0 || getSamples( folderTmplItem ).length > 0;
118
+ }
119
+
120
+ </script>
121
+
122
+ </body>
123
+ </html>
apps/jquery-tmpl/demos/samplesCore/basic.html ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates some basic templating features and scenarios.
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <style type="text/css">
8
+ .clickable {
9
+ cursor:pointer;
10
+ color: Blue;
11
+ }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
16
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
17
+ <script type="text/javascript">
18
+
19
+ var dataObject = {
20
+ firstName: "John",
21
+ lastName: "Resig",
22
+ url: "http://ejohn.org/",
23
+ cities: [
24
+ "Boston, MA",
25
+ "San Francisco, CA"
26
+ ]
27
+ };
28
+
29
+ var arrayOfDataObjects = [
30
+ dataObject
31
+ ,
32
+ {
33
+ firstName: "Dave",
34
+ lastName: "Reed",
35
+ url: "http://dave.org/",
36
+ cities: [
37
+ "Seattle, WA",
38
+ "Los Angeles, CA",
39
+ "New York, NY"
40
+ ]
41
+ },
42
+ {
43
+ firstName: "Boris",
44
+ lastName: "Moore",
45
+ url: "http://boris.org/",
46
+ cities: [
47
+ "Redmond, WA",
48
+ "Seattle, WA",
49
+ "New York, NY"
50
+ ]
51
+ }
52
+ ];
53
+
54
+ function cityJoin( separator ) {
55
+ return this.data.cities.join( separator || ", " );
56
+ }
57
+
58
+ function getName() {
59
+ return this.data.firstName + " " + this.data.lastName;
60
+ }
61
+
62
+ function index( array ) {
63
+ return $.inArray( this.data, array ) + 1;
64
+ }
65
+
66
+ jQuery(function(){
67
+ // A template string
68
+ var tmpl = '<li><a href="${url}">${getName()}</a> {{if $item.showCities}}(${cityJoin()}){{/if}}</li>';
69
+
70
+ // Renders one LI, filled with data, then appends it into the UL
71
+ $.tmpl( tmpl, dataObject )
72
+ .appendTo( "ul" );
73
+
74
+ // Store a string as a compiled template for later use
75
+ $.template( "myTmpl", '<li>My template: <a href="${url}">${getName()}</a> {{if $item.showCities}}(${cityJoin()}){{/if}}</li>' );
76
+
77
+ // Render stored template and insert after target.
78
+ // Target wrapped set has more than one element, so rendered template cloned into two places in DOM
79
+ $.tmpl( "myTmpl", dataObject )
80
+ .insertAfter( ".multiple" );
81
+
82
+ // Use a template declared in a script block
83
+ // Appends multiple LIs - one for each item.
84
+ $( "#sometmpl" )
85
+ .tmpl( arrayOfDataObjects )
86
+ .appendTo( "ul" );
87
+
88
+ // Store a template declared in a script block as a named template for later use.
89
+ $( "#sometmpl" ).template( "peopleList" );
90
+
91
+ // Use the named template
92
+ $.tmpl( "peopleList", arrayOfDataObjects )
93
+ .appendTo( "ul" );
94
+
95
+ // Set options: showCities and array, referenced within the template.
96
+ $( "#sometmpl" )
97
+ .tmpl( arrayOfDataObjects, { array: arrayOfDataObjects, showCities: true } )
98
+ .prependTo( "ul" );
99
+
100
+ // Getting to the data in a click event.
101
+ $( "#sometmpl" )
102
+ .tmpl( arrayOfDataObjects )
103
+ .prependTo( "ul" )
104
+ .find( "span" )
105
+ .addClass( "clickable" )
106
+ .click( function() {
107
+ var item = $.tmplItem(this);
108
+ alert( item.data.firstName + " at " + item.data.url );
109
+ });
110
+
111
+ // Example of template that has leading or trailing text
112
+ $( "#leadingOrTrailingText" )
113
+ .tmpl( arrayOfDataObjects )
114
+ .insertBefore( ".target" );
115
+ });
116
+ </script>
117
+
118
+ <script id="sometmpl" type="text/x-jquery-tmpl">
119
+ <li>
120
+ {{if $item.array}}
121
+ ${index($item.array)} of ${$item.array.length})
122
+ {{/if}}
123
+ <span>${getName()}</span>
124
+ {{if $item.showCities}}
125
+ Cities: {{each cities}} ${this} {{/each}}
126
+ {{else}}
127
+ No Cities
128
+ {{/if}}
129
+ </li>
130
+ </script>
131
+
132
+ <script id="leadingOrTrailingText" type="text/x-jquery-tmpl">
133
+ ${firstName} <strong>${lastName}</strong> <br/>
134
+ </script>
135
+
136
+ <ul><li class="multiple">first</li><li class="multiple">last</li></ul>
137
+
138
+ <div class="target"></div>
139
+
140
+ </body>
141
+ </html>
apps/jquery-tmpl/demos/samplesCore/composition.html ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates template composition, including passing parameters to a {{tmpl}} tag.
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <style type="text/css">
8
+ .peopleTable td { border:2px solid #555; text-align:center; }
9
+ .person{ background-color:#AFA; }
10
+ .personAlt{ background-color:#9ED; }
11
+ .citySeparator { background-color:#CCC; height:4px;}
12
+ .separator { background-color:#C77; height:6px;}
13
+ .peopleTable { border-collapse:collapse; border:2px solid #555; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+
18
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
19
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
20
+ <script type="text/javascript">
21
+ var people = [
22
+ {
23
+ firstName: "John",
24
+ lastName: "Resig",
25
+ url: "http://ejohn.org/",
26
+ cities: [
27
+ { name: "Boston", state: "MA" },
28
+ { name: "San Francisco", state: "CA" }
29
+ ]
30
+ },
31
+ {
32
+ firstName: "Dave",
33
+ lastName: "Reed",
34
+ url: "http://dave.org/"
35
+ },
36
+ {
37
+ firstName: "Boris",
38
+ lastName: "Moore",
39
+ url: "http://boris.org/",
40
+ cities: [
41
+ { name: "Redmond", state: "WA" },
42
+ { name: "Seattle", state: "WA" },
43
+ { name: "New York", state: "NY" }
44
+ ]
45
+ }
46
+ ];
47
+
48
+ function getName() {
49
+ return this.data.firstName + " " + this.data.lastName;
50
+ }
51
+
52
+ function alternate( item, array ) {
53
+ return ($.inArray( item, array ) % 2) ? "personAlt" : "person";
54
+ }
55
+
56
+ function cityNumber() {
57
+ return $.inArray( this.data, this.parent.data.cities ) + 1;
58
+ }
59
+
60
+ function getTemplate( key ) {
61
+ return $( "#tmpl" + key ).template();
62
+ }
63
+
64
+ $(function(){
65
+ // Create named template, to be used in composition below
66
+ $.template( "citySeparator", '<tr class="citySeparator"><td colspan="2"></td></tr>' );
67
+
68
+ $( "#tmplPeople" )
69
+ .tmpl( people )
70
+ .appendTo( ".peopleTable" );
71
+ $( "#tmplSeparator" )
72
+ .tmpl()
73
+ .appendTo( ".peopleTable" );
74
+ });
75
+ </script>
76
+
77
+ <script id="tmplPeople" type="text/x-jquery-tmpl">
78
+ {{tmpl "#tmplSeparator"}}
79
+ <tr class="${alternate(this.data, people)}"><td colspan="2"><a href="${url}">${getName()}</a></td></tr>
80
+ {{if cities}}
81
+ {{tmpl(cities) getTemplate("City")}}
82
+ {{/if}}
83
+ </script>
84
+
85
+ <script id="tmplSeparator" type="text/x-jquery-tmpl">
86
+ <tr class="separator"><td colspan="2"></td></tr>
87
+ </script>
88
+
89
+ <script id="tmplCity" type="text/x-jquery-tmpl">
90
+ {{tmpl "citySeparator"}}
91
+ <tr class="${alternate(this.parent.data, people)}"><td colspan="2"><b><i>City ${cityNumber()}:</i></b></td></tr>
92
+ <tr class="${alternate(this.parent.data, people)}"><td><b>${name}</b></td><td>${state}</td></tr>
93
+ </script>
94
+
95
+ <table class="peopleTable"><tbody></tbody></table>
96
+
97
+ </body>
98
+ </html>
apps/jquery-tmpl/demos/samplesCore/conditional.html ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates use of conditional template tags {{if}} and {{else}}.
4
+ The comment tag {{! }} is also shown.
5
+ -->
6
+ <html xmlns="http://www.w3.org/1999/xhtml">
7
+ <body>
8
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
9
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
10
+ <script type="text/javascript">
11
+ $(function(){
12
+ $( "#movieTemplate" )
13
+ .tmpl( movies )
14
+ .appendTo( "#movieList" );
15
+ });
16
+
17
+ var movies = [
18
+ { Name: "Meet Joe Black", Languages: "French", Subtitles: "English" },
19
+ { Name: "The Mighty", Subtitles: "French and Spanish" },
20
+ { Name: "The Mighty" },
21
+ { Name: "City Hunter", Languages: "Mandarin and Cantonese" }
22
+ ];
23
+ </script>
24
+
25
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
26
+ <li>
27
+ Title: ${Name}.
28
+ {{if Languages}}
29
+ (Alternative languages: ${Languages}).
30
+ {{else Subtitles}}
31
+ (Original language only. Subtitles in ${Subtitles}).
32
+ {{else}}
33
+ (Original version only, without subtitles).
34
+ {{/if}}
35
+ </li>
36
+ </script>
37
+
38
+ <ul id="movieList"></ul>
39
+
40
+ </body>
41
+ </html>
apps/jquery-tmpl/demos/samplesCore/each.html ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using the {{each}} template tag,
4
+ for iterative rendering of nested markup within a template.
5
+ -->
6
+ <html xmlns="http://www.w3.org/1999/xhtml">
7
+ <head>
8
+ <style type="text/css">
9
+ .peopleTable td { border:2px solid #555; text-align:center; }
10
+ .person{ background-color:#AFA; }
11
+ .personAlt{ background-color:#9ED; }
12
+ .separator { background-color:#C77; height:6px;}
13
+ .cityseparator { background-color:#CCC; height:4px;}
14
+ .peopleTable { border-collapse:collapse; border:2px solid #555; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
19
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
20
+ <script type="text/javascript">
21
+ $(function(){
22
+ $("#tmplPeople")
23
+ .tmpl( people )
24
+ .appendTo(".peopleTable");
25
+ });
26
+
27
+ var people = [
28
+ {
29
+ firstName: "John",
30
+ lastName: "Resig",
31
+ url: "http://ejohn.org/",
32
+ cities: [
33
+ { name: "Boston", state: "MA" },
34
+ { name: "San Francisco", state: "CA" }
35
+ ]
36
+ },
37
+ {
38
+ firstName: "Dave",
39
+ lastName: "Reed",
40
+ url: "http://dave.org/",
41
+ cities: [
42
+ { name: "Seattle", state: "WA" },
43
+ { name: "Los Angeles", state: "CA" },
44
+ { name: "New York", state: "NY" }
45
+ ]
46
+ },
47
+ {
48
+ firstName: "Boris",
49
+ lastName: "Moore",
50
+ url: "http://boris.org/",
51
+ cities: [
52
+ { name: "Redmond", state: "WA" }
53
+ ]
54
+ }
55
+ ];
56
+
57
+ function index( item, array ) {
58
+ return $.inArray( item, array ) + 1;
59
+ }
60
+
61
+ function getName() {
62
+ return this.data.firstName + " " + this.data.lastName;
63
+ }
64
+
65
+ function alternate( item, array ) {
66
+ return ($.inArray( item, array ) % 2) ? "personAlt" : "person";
67
+ }
68
+ </script>
69
+
70
+ <script id="tmplPeople" type="text/x-jquery-tmpl">
71
+ <tr class="${alternate($data, people)}"><td colspan="2"><a href="${url}">${getName()}</a></td></tr>
72
+ {{each cities}}
73
+ <tr class="cityseparator"><td colspan="2"></td></tr>
74
+ <tr class="${alternate($data, people)}"><td colspan="2"><b><i>City ${index($value, cities)}:</i></b></td></tr>
75
+ <tr class="${alternate($data, people)}"><td><b>${name}</b></td><td>${state}</td></tr>
76
+ {{/each}}
77
+ <tr class="separator"><td colspan="2"></td></tr>
78
+ </script>
79
+
80
+ <table class="peopleTable"><tbody>
81
+ <tr class="separator"><td colspan="2"></td></tr>
82
+ </tbody></table>
83
+
84
+ </body>
85
+ </html>
apps/jquery-tmpl/demos/samplesCore/parameters.html ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample illustrates using the {{if}}, {{each}} and {{tmpl}} template tags, with parameters.
4
+ -->
5
+ <html xmlns="http://www.w3.org/1999/xhtml">
6
+ <head>
7
+ <style type="text/css">
8
+ .peopleTable td { border:2px solid #555; text-align:center; }
9
+ .person{ background-color:#AFA; }
10
+ .personAlt{ background-color:#9ED; }
11
+ .separator { background-color:#C77; height:6px;}
12
+ .cityseparator { background-color:#CCC; height:4px;}
13
+ .peopleTable { border-collapse:collapse; border:2px solid #555; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
18
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
19
+ <script type="text/javascript">
20
+ $(function(){
21
+ $("#tmplPeople")
22
+ .tmpl( people )
23
+ .appendTo(".peopleTable");
24
+ });
25
+
26
+ var people = [
27
+ {
28
+ firstName: "John",
29
+ lastName: "Resig",
30
+ url: "http://ejohn.org/",
31
+ cities: [ "BSTN", "NY", "SF" ]
32
+ },
33
+ {
34
+ firstName: "Dave",
35
+ lastName: "Reed",
36
+ url: "http://dave.org/",
37
+ cities: [ "RDMD", "STL", "SF", "LA" ]
38
+ },
39
+ {
40
+ firstName: "Boris",
41
+ lastName: "Moore",
42
+ url: "http://boris.org/",
43
+ cities: [ "RDMD" ]
44
+ }
45
+ ];
46
+
47
+ var allCities = {
48
+ BSTN: { name: "Boston", state: "MA", weather: "Cold" },
49
+ SF: { name: "San Francisco", state: "CA", weather: "Warm" },
50
+ STL: { name: "Seattle", state: "WA", weather: "Wet" },
51
+ RDMD: { name: "Redmond", state: "WA", weather: "Wet" },
52
+ LA: { name: "Los Angeles", state: "CA", weather: "Hot" },
53
+ NY: { name: "New York", state: "NY", weather: "Variable" }
54
+ };
55
+
56
+ function getName() {
57
+ return this.data.firstName + " " + this.data.lastName;
58
+ }
59
+
60
+ function getCities( begin, end ) {
61
+ return $.map(this.data.cities.slice(begin, end), function(city) {
62
+ return allCities[city];
63
+ });
64
+ }
65
+
66
+ function getCityCount( begin, end ) {
67
+ return this.data.cities.slice(begin, end).length;
68
+ }
69
+
70
+ function alternate() {
71
+ return ($.inArray( this.data, people ) % 2) ? "personAlt" : "person";
72
+ }
73
+
74
+ var startIndex = 1, endIndex = 3;
75
+ </script>
76
+
77
+ <script id="tmplPeople" type="text/x-jquery-tmpl">
78
+ <tr class="${alternate()}"><td colspan="3"><a href="${url}">${getName()}</a></td></tr>
79
+ {{tmpl "#tmplSeparator"}}
80
+ {{if getCityCount(startIndex, endIndex)}}
81
+ <tr class="${alternate()}"><td colspan="3"><i>Favorite Cities</i></td></tr>
82
+ {{each getCities(startIndex, endIndex)}}
83
+ {{tmpl(null, {type:"city"}) "#tmplSeparator"}}
84
+ <tr class="${alternate()}">
85
+ <td>${$index + 1}</td>
86
+ <td><b>${name}</b></td>
87
+ <td>${state}</td>
88
+ </tr>
89
+ <tr class="${alternate()}"><td colspan="3"><i>${weather}...</i></td></tr>
90
+ {{/each}}
91
+ {{tmpl "#tmplSeparator"}}
92
+ {{/if}}
93
+ </script>
94
+
95
+ <script id="tmplSeparator" type="text/x-jquery-tmpl">
96
+ <tr class="${$item.type}separator"><td colspan="3"></td></tr>
97
+ </script>
98
+
99
+ <table class="peopleTable"><tbody>
100
+ <tr class="separator"><td colspan="3"></td></tr>
101
+ </tbody></table>
102
+
103
+ </body>
104
+ </html>
apps/jquery-tmpl/demos/samplesTmplPlus/basic.html ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample is equivalent to the samplesCore/basic.html sample,
4
+ except that it uses jquery.tmplPlus.js in order to take advantage
5
+ of the alternative API:
6
+ $( targetContainer ).append( template, data, options );
7
+ rather than
8
+ $( template ).tmpl( data, options ).appendTo( targetContainer );
9
+ -->
10
+ <html xmlns="http://www.w3.org/1999/xhtml">
11
+ <body>
12
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
13
+ <script src="../../jquery.tmpl.js" type="text/javascript" ></script>
14
+ <script src="../../jquery.tmplPlus.js" type="text/javascript"></script>
15
+ <script type="text/javascript">
16
+
17
+ var dataObject = {
18
+ firstName: "John",
19
+ lastName: "Resig",
20
+ url: "http://ejohn.org/",
21
+ cities: [
22
+ "Boston, MA",
23
+ "San Francisco, CA"
24
+ ]
25
+ };
26
+
27
+ var arrayOfDataObjects = [
28
+ dataObject
29
+ ,
30
+ {
31
+ firstName: "Dave",
32
+ lastName: "Reed",
33
+ url: "http://dave.org/",
34
+ cities: [
35
+ "Seattle, WA",
36
+ "Los Angeles, CA",
37
+ "New York, NY"
38
+ ]
39
+ },
40
+ {
41
+ firstName: "Boris",
42
+ lastName: "Moore",
43
+ url: "http://boris.org/",
44
+ cities: [
45
+ "Redmond, WA",
46
+ "Seattle, WA",
47
+ "New York, NY"
48
+ ]
49
+ }
50
+ ];
51
+
52
+ function cityJoin( separator ) {
53
+ return this.data.cities.join( separator || ", " );
54
+ }
55
+
56
+ function getName() {
57
+ return this.data.firstName + " " + this.data.lastName;
58
+ }
59
+
60
+ function index( array ) {
61
+ return $.inArray( this.data, array ) + 1;
62
+ }
63
+
64
+ jQuery(function(){
65
+ // A template string
66
+ var tmpl = '<li><a href="${url}">${getName()}</a> {{if $item.showCities}}(${cityJoin()}){{/if}}</li>';
67
+
68
+ // Renders one LI, filled with data, then appends it into the UL
69
+ $("ul").append( tmpl, dataObject, null );
70
+
71
+ // Store a string as a compiled template for later use
72
+ $.template( "myTmpl", '<li>My template: <a href="${url}">${getName()}</a> {{if $item.showCities}}(${cityJoin()}){{/if}}</li>' );
73
+
74
+ // Render stored template and insert after target.
75
+ // Target wrapped set has more than one element, so rendered template cloned into two places in DOM
76
+ $(".multiple").after( "myTmpl", dataObject );
77
+
78
+ // Appends multiple LIs for each item. Set options: showCities and array, referenced within the template.
79
+ $("ul").prepend( "#sometmpl", arrayOfDataObjects, { array: arrayOfDataObjects, showCities: true } );
80
+
81
+ // Example of template that has leading or trailing text
82
+ $("#target").before( "#leadingOrTrailingText", arrayOfDataObjects );
83
+ });
84
+ </script>
85
+
86
+ <script id="sometmpl" type="text/x-jquery-tmpl">
87
+ <li>${index($item.array)} of ${$item.array.length}) <a href="${url}">${getName()}</a>
88
+ {{if $item.showCities}}
89
+ Cities: {{each cities}} ${this} {{/each}}
90
+ {{else}}
91
+ No Cities
92
+ {{/if}}
93
+ </li>
94
+ </script>
95
+
96
+ <script id="leadingOrTrailingText" type="text/x-jquery-tmpl">
97
+ ${firstName} <strong>${lastName}</strong> <br/>
98
+ </script>
99
+
100
+ <ul><li class="multiple">first</li><li class="multiple">last</li></ul>
101
+
102
+ <div id="target">Target</div>
103
+
104
+ </body>
105
+ </html>
apps/jquery-tmpl/demos/samplesTmplPlus/composition.html ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample is equivalent to the samplesCore/composition.html sample,
4
+ except that it uses jquery.tmplPlus.js in order to take advantage
5
+ of the alternative API:
6
+ $( targetContainer ).append( template, data, options );
7
+ rather than
8
+ $( template ).tmpl( data, options ).appendTo( targetContainer );
9
+ -->
10
+ <html xmlns="http://www.w3.org/1999/xhtml">
11
+ <head>
12
+ <style type="text/css">
13
+ .peopleTable td { border:2px solid #555; text-align:center; }
14
+ .person{ background-color:#AFA; }
15
+ .personAlt{ background-color:#9ED; }
16
+ .citySeparator { background-color:#CCC; height:4px;}
17
+ .separator { background-color:#C77; height:6px;}
18
+ .peopleTable { border-collapse:collapse; border:2px solid #555; }
19
+ </style>
20
+ </head>
21
+ <body>
22
+
23
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
24
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
25
+ <script src="../../jquery.tmplPlus.js" type="text/javascript"></script>
26
+ <script type="text/javascript">
27
+ var people = [
28
+ {
29
+ firstName: "John",
30
+ lastName: "Resig",
31
+ url: "http://ejohn.org/",
32
+ cities: [
33
+ { name: "Boston", state: "MA" },
34
+ { name: "San Francisco", state: "CA" }
35
+ ]
36
+ },
37
+ {
38
+ firstName: "Dave",
39
+ lastName: "Reed",
40
+ url: "http://dave.org/"
41
+ },
42
+ {
43
+ firstName: "Boris",
44
+ lastName: "Moore",
45
+ url: "http://boris.org/",
46
+ cities: [
47
+ { name: "Redmond", state: "WA" },
48
+ { name: "Seattle", state: "WA" },
49
+ { name: "New York", state: "NY" }
50
+ ]
51
+ }
52
+ ];
53
+
54
+ function getName() {
55
+ return this.data.firstName + " " + this.data.lastName;
56
+ }
57
+
58
+ function alternate( item, array ) {
59
+ return ($.inArray( item, array ) % 2) ? "personAlt" : "person";
60
+ }
61
+
62
+ function cityNumber() {
63
+ return $.inArray( this.data, this.parent.data.cities ) + 1;
64
+ }
65
+
66
+ function getTemplate( key ) {
67
+ return $( "#tmpl" + key ).template();
68
+ }
69
+
70
+ $(function(){
71
+ $( ".peopleTable" )
72
+ .append( "#tmplPeople", people );
73
+ $( ".peopleTable" )
74
+ .append( "#tmplSeparator", {} );
75
+ });
76
+ </script>
77
+
78
+ <script id="tmplPeople" type="text/x-jquery-tmpl">
79
+ {{tmpl "#tmplSeparator"}}
80
+ <tr class="${alternate($data, people)}"><td colspan="2"><a href="${url}">${getName()}</a></td></tr>
81
+ {{if cities}}
82
+ {{tmpl(cities) getTemplate("City")}}
83
+ {{/if}}
84
+ </script>
85
+
86
+ <script id="tmplSeparator" type="text/x-jquery-tmpl">
87
+ <tr class="separator"><td colspan="2"></td></tr>
88
+ </script>
89
+
90
+ <script id="tmplCitySeparator" type="text/x-jquery-tmpl">
91
+ <tr class="citySeparator"><td colspan="2"></td></tr>
92
+ </script>
93
+
94
+ <script id="tmplCity" type="text/x-jquery-tmpl">
95
+ {{tmpl "#tmplCitySeparator"}}
96
+ <tr class="${alternate(this.parent.data, people)}"><td colspan="2"><b><i>City ${cityNumber()}:</i></b></td></tr>
97
+ <tr class="${alternate(this.parent.data, people)}"><td><b>${name}</b></td><td>${state}</td></tr>
98
+ </script>
99
+
100
+ <table class="peopleTable"><tbody></tbody></table>
101
+
102
+ </body>
103
+ </html>
apps/jquery-tmpl/demos/samplesTmplPlus/parameters.html ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <!--
3
+ This sample is equivalent to the samplesCore/parameters.html sample,
4
+ except that it uses jquery.tmplPlus.js in order to take advantage
5
+ of the alternative API:
6
+ $( targetContainer ).append( template, data, options );
7
+ rather than
8
+ $( template ).tmpl( data, options ).appendTo( targetContainer );
9
+ -->
10
+ <html xmlns="http://www.w3.org/1999/xhtml">
11
+ <head>
12
+ <style type="text/css">
13
+ .peopleTable td { border:2px solid #555; text-align:center; }
14
+ .person{ background-color:#AFA; }
15
+ .personAlt{ background-color:#9ED; }
16
+ .separator { background-color:#C77; height:6px;}
17
+ .cityseparator { background-color:#CCC; height:4px;}
18
+ .peopleTable { border-collapse:collapse; border:2px solid #555; }
19
+ </style>
20
+ </head>
21
+ <body>
22
+
23
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
24
+ <script src="../../jquery.tmpl.js" type="text/javascript"></script>
25
+ <script src="../../jquery.tmplPlus.js" type="text/javascript"></script>
26
+ <script type="text/javascript">
27
+ $(function(){
28
+ $(".peopleTable")
29
+ .append("#tmplPeople", people, {allCities: allCities} );
30
+ });
31
+
32
+ var people = [
33
+ {
34
+ firstName: "John",
35
+ lastName: "Resig",
36
+ url: "http://ejohn.org/",
37
+ cities: [ "BSTN", "NY", "SF" ]
38
+ },
39
+ {
40
+ firstName: "Dave",
41
+ lastName: "Reed",
42
+ url: "http://dave.org/",
43
+ cities: [ "RDMD", "STL", "SF", "LA" ]
44
+ },
45
+ {
46
+ firstName: "Boris",
47
+ lastName: "Moore",
48
+ url: "http://boris.org/",
49
+ cities: [ "RDMD" ]
50
+ }
51
+ ];
52
+
53
+ var allCities = {
54
+ BSTN: { name: "Boston", state: "MA", weather: "Cold" },
55
+ SF: { name: "San Francisco", state: "CA", weather: "Warm" },
56
+ STL: { name: "Seattle", state: "WA", weather: "Wet" },
57
+ RDMD: { name: "Redmond", state: "WA", weather: "Wet" },
58
+ LA: { name: "Los Angeles", state: "CA", weather: "Hot" },
59
+ NY: { name: "New York", state: "NY", weather: "Variable" }
60
+ };
61
+
62
+ function getName() {
63
+ return this.data.firstName + " " + this.data.lastName;
64
+ }
65
+
66
+ function getCities( begin, end ) {
67
+ return $.map(this.data.cities.slice(begin, end), function(city) {
68
+ return allCities[city];
69
+ });
70
+ }
71
+
72
+ function getCityCount( begin, end ) {
73
+ return this.data.cities.slice(begin, end).length;
74
+ }
75
+
76
+ function alternate() {
77
+ return ($.inArray( this.data, people ) % 2) ? "personAlt" : "person";
78
+ }
79
+
80
+ var startIndex = 1, endIndex = 3;
81
+ </script>
82
+
83
+ <script id="tmplPeople" type="text/x-jquery-tmpl">
84
+ <tr class="${alternate()}"><td colspan="3"><a href="${url}">${getName()}</a></td></tr>
85
+ {{tmpl "#tmplSeparator"}}
86
+ {{if getCityCount(startIndex, endIndex)}}
87
+ <tr class="${alternate()}"><td colspan="3"><i>Favorite Cities</i></td></tr>
88
+ {{each getCities(startIndex, endIndex)}}
89
+ {{tmpl(null, {type:"city"}) "#tmplSeparator"}}
90
+ <tr class="${alternate()}">
91
+ <td>${$index + 1}</td>
92
+ <td><b>${name}</b></td>
93
+ <td>${state}</td>
94
+ </tr>
95
+ <tr class="${alternate()}"><td colspan="3"><i>${weather}...</i></td></tr>
96
+ {{/each}}
97
+ {{tmpl "#tmplSeparator"}}
98
+ {{/if}}
99
+ </script>
100
+
101
+ <script id="tmplSeparator" type="text/x-jquery-tmpl">
102
+ <tr class="${$item.type}separator"><td colspan="3"></td></tr>
103
+ </script>
104
+
105
+ <table class="peopleTable"><tbody>
106
+ <tr class="separator"><td colspan="3"></td></tr>
107
+ </tbody></table>
108
+
109
+ </body>
110
+ </html>
apps/jquery-tmpl/demos/step-by-step.html ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <link href="resources/demos.css" rel="stylesheet" type="text/css" />
5
+ </head>
6
+ <body>
7
+ <h2>jQuery Templates: Step by Step Examples</h2>
8
+ <h3>App Example</h3>
9
+ <a href="movies/PagesCore/movies.html">Movies</a><br />
10
+
11
+ <h3>Read-only rendering</h3>
12
+ <div class="subhead">API: $( "#template" ).tmpl( data ).appendTo( "#list");</div>
13
+ <a href="step-by-step/0_tmpl-read-only/0_local-data.html">Local data</a><br />
14
+ <a href="step-by-step/0_tmpl-read-only/1_remote-data.html">Remote data</a><br />
15
+
16
+ <div class="subhead">Tags - Content</div>
17
+ <a href="step-by-step/0_tmpl-read-only/2_html-tag.html">${} and {{html}}</a><br />
18
+ <a href="step-by-step/0_tmpl-read-only/3_if-else-tag.html">{{if}} and {{else}}</a><br />
19
+ <a href="step-by-step/0_tmpl-read-only/4_each-tag.html">{{each}}</a><br />
20
+ <a href="step-by-step/0_tmpl-read-only/5_javascript.html">javascript demo</a><br />
21
+
22
+ <div class="subhead">Tags - Composition</div>
23
+
24
+ <a href="step-by-step/0_tmpl-read-only/6_hierarchical-data.html">Hierarchical data - {{tmpl}}</a><br />
25
+
26
+ <h3>Interactivity</h3>
27
+ <div class="subhead">Navigating through data</div>
28
+ <a href="step-by-step/1_tmpl-interactive/0_accordion-switching-template.html">Switch templates: Accordion</a><br />
29
+ <a href="step-by-step/1_tmpl-interactive/1_tree-view-using-tmpl-tag.html">Recursive Tree View - {{tmpl}}</a><br />
30
+ <a href="step-by-step/1_tmpl-interactive/2_tabs-using-wrap-tag.html">Tabs View - {{wrap}}</a><br />
31
+
32
+ </body>
33
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/0_local-data-source.html ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
9
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
10
+ </head>
11
+ <body>
12
+ <a href="../../step-by-step.html">Home</a><br />
13
+ <a href="0_local-data.html">Run</a>
14
+
15
+ <h3>Demo: Render template against local data</h3>
16
+
17
+ <!--=================== Demo Section ===================-->
18
+
19
+ <script id="movieTemplate" type="text/x-jquery-tmpl"><li>
20
+ <b>${Name}</b> (${ReleaseYear})
21
+ </li></script>
22
+
23
+ <ul id="movieList"></ul>
24
+
25
+ <script type="text/javascript">
26
+
27
+ var movies = [
28
+ { Name: "The Red Violin", ReleaseYear: "1998" },
29
+ { Name: "Eyes Wide Shut", ReleaseYear: "1999" },
30
+ { Name: "The Inheritance", ReleaseYear: "1976" }
31
+ ];
32
+
33
+ // Render the template with the movies data and insert
34
+ // the rendered HTML under the "movieList" element
35
+ $("#movieTemplate").tmpl(movies)
36
+ .appendTo("#movieList");
37
+
38
+ </script>
39
+
40
+ <!--================ End of Demo Section ================-->
41
+
42
+ <h4>Data:</h4>
43
+ <pre class="brush: js;">var movies = [
44
+ { Name: "The Red Violin", ReleaseYear: "1998" },
45
+ { Name: "Eyes Wide Shut", ReleaseYear: "1999" },
46
+ { Name: "The Inheritance", ReleaseYear: "1976" }
47
+ ];</pre>
48
+
49
+ <h4>HTML:</h4>
50
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
51
+ &lt;li>
52
+ &lt;b>${Name}&lt;/b> (${ReleaseYear})
53
+ &lt;/li>
54
+ &lt;/script>
55
+
56
+ &lt;ul id="movieList">&lt;/ul></pre>
57
+
58
+ <h4>Script:</h4>
59
+ <pre class="brush: js;">$( "#movieTemplate" ).tmpl( movies )
60
+ .appendTo( "#movieList" );</pre>
61
+
62
+ </body>
63
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/0_local-data.html ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+ </head>
8
+ <body>
9
+ <a href="../../step-by-step.html">Home</a><br />
10
+ <a href="0_local-data-source.html">Source</a>
11
+
12
+ <h3>Demo: Render template against local data</h3>
13
+
14
+ <!--=================== Demo Section ===================-->
15
+
16
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
17
+ <li>
18
+ <b>${Name}</b> (${ReleaseYear})
19
+ </li>
20
+ </script>
21
+
22
+ <ul id="movieList"></ul>
23
+
24
+ <script type="text/javascript">
25
+
26
+ var movies = [
27
+ { Name: "The Red Violin", ReleaseYear: "1998" },
28
+ { Name: "Eyes Wide Shut", ReleaseYear: "1999" },
29
+ { Name: "The Inheritance", ReleaseYear: "1976" }
30
+ ];
31
+
32
+ $( "#movieTemplate" ).tmpl( movies )
33
+ .appendTo( "#movieList" );
34
+
35
+ </script>
36
+
37
+ <!--================ End of Demo Section ================-->
38
+
39
+ </body>
40
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/1_remote-data-source.html ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
9
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
10
+ </head>
11
+ <body>
12
+ <a href="../../step-by-step.html">Home</a><br />
13
+ <a href="1_remote-data.html">Run</a>
14
+
15
+ <h3>Demo: Render template against remote data</h3>
16
+
17
+ <!--=================== Demo Section ===================-->
18
+
19
+ <script id="movieTemplate" type="text/x-jquery-tmpl"><li>
20
+ <b>${Name}</b> (${ReleaseYear})
21
+ </li></script>
22
+
23
+ <button id="cartoonsBtn">Cartoons</button>
24
+ <button id="dramaBtn">Drama</button><br /><br />
25
+
26
+ <div class="height">
27
+ <div class="plusViewer edit">
28
+ <ul id="movieList"></ul>
29
+ </div>
30
+ </div>
31
+
32
+ <script type="text/javascript">
33
+
34
+ function getMovies( genre, skip, top ) {
35
+ $.ajax({
36
+
37
+ dataType: "jsonp",
38
+
39
+ url: "http://odata.netflix.com/Catalog/Genres('" + genre
40
+ + "')/Titles?$format=json&$skip="
41
+ + skip + "&$top=" + top,
42
+
43
+ jsonp: "$callback",
44
+
45
+ success: function( data ) {
46
+ var movies = data.d; // Get movies array from the data
47
+
48
+ $( "#movieList" ).empty(); // Remove current set of movie template items
49
+
50
+ $( "#movieTemplate" ).tmpl( movies ) // Render template with movies data
51
+ .appendTo( "#movieList" ); // and insert rendered HTML under "movieList" element
52
+ }
53
+ });
54
+ }
55
+
56
+ $( "#cartoonsBtn" ).click( function() {
57
+ getMovies( "Cartoons", 0, 6 );
58
+ });
59
+
60
+ $( "#dramaBtn" ).click( function() {
61
+ getMovies( "Drama", 0, 6 );
62
+ });
63
+
64
+ </script>
65
+
66
+ <!--================ End of Demo Section ================-->
67
+
68
+ <h4>HTML:</h4>
69
+
70
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
71
+ &lt;li>
72
+ &lt;b>${Name}&lt;/b> (${ReleaseYear})
73
+ &lt;/li>
74
+ &lt;/script>
75
+
76
+ &lt;ul id="movieList">&lt;/ul></pre>
77
+
78
+ <h4>Script:</h4>
79
+ <pre class="brush: js;">$.ajax({
80
+
81
+ dataType: "jsonp",
82
+
83
+ url: "http://odata.netflix.com/Catalog/Genres('" + genre
84
+ + "')/Titles?$format=json&$skip="
85
+ + skip + "&$top=" + top,
86
+
87
+ jsonp: "$callback",
88
+
89
+ success: function( data ) {
90
+ var movies = data.d; // Get the movies array from the data
91
+
92
+ $( "#movieList" ).empty(); // Remove current set of movie template items
93
+
94
+ $( "#movieTemplate" ).tmpl( movies ) // Render the template with the movies data
95
+ .appendTo( "#movieList" ); // and insert the rendered HTML under the "movieList" element
96
+ }
97
+ });
98
+ </pre>
99
+ </body>
100
+ </html>
101
+
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/1_remote-data.html ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+ </head>
8
+ <body>
9
+ <a href="../../step-by-step.html">Home</a><br />
10
+ <a href="1_remote-data-source.html">Source</a>
11
+
12
+ <h3>Demo: Render template against remote data</h3>
13
+
14
+ <!--=================== Demo Section ===================-->
15
+
16
+ <script id="movieTemplate" type="text/x-jquery-tmpl"><li>
17
+ <b>${Name}</b> (${ReleaseYear})
18
+ </li></script>
19
+
20
+ <button id="cartoonsBtn">Cartoons</button>
21
+ <button id="dramaBtn">Drama</button>
22
+
23
+ <div class="height">
24
+ <ul id="movieList"></ul>
25
+ </div>
26
+
27
+ <script type="text/javascript">
28
+
29
+ function getMovies( genre, skip, top ) {
30
+ $.ajax({
31
+
32
+ dataType: "jsonp",
33
+
34
+ url: "http://odata.netflix.com/Catalog/Genres('" + genre
35
+ + "')/Titles?$format=json&$skip="
36
+ + skip + "&$top=" + top,
37
+
38
+ jsonp: "$callback",
39
+
40
+ success: function( data ) {
41
+ var movies = data.d; // Get the movies array from the data
42
+
43
+ $( "#movieList" ).empty(); // Remove current set of movie template items
44
+
45
+ $( "#movieTemplate" ).tmpl( movies ) // Render the template with the movies data
46
+ .appendTo( "#movieList" ); // and insert the rendered HTML under the "movieList" element
47
+ }
48
+ });
49
+ }
50
+
51
+ $( "#cartoonsBtn" ).click( function() {
52
+ getMovies( "Cartoons", 0, 6 );
53
+ });
54
+
55
+ $( "#dramaBtn" ).click( function() {
56
+ getMovies( "Drama", 0, 6 );
57
+ });
58
+
59
+ </script>
60
+
61
+ <!--================ End of Demo Section ================-->
62
+ </body>
63
+ </html>
64
+
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/2_html-tag-source.html ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
9
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
10
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
11
+
12
+ <style type="text/css">
13
+ .role { font-weight: bold; font-style: italic; background-color: Yellow; }
14
+ .synopsis { background-color: white; padding: 15px; }
15
+ .red { font-weight: bold; font-style: italic; color: red; }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <a href="../../step-by-step.html">Home</a><br />
20
+ <a href="2_html-tag.html">Run</a>
21
+
22
+ <h3>Demo: Using ${} or {{html}} to render data values or expressions</h3>
23
+
24
+ <ul>
25
+ <li>${} is equivalent to {{= }}. It HTML encodes. (Better security, but slight perf cost)</li>
26
+ <li>{{html}} does not encode. Used to render values that include html markup</li>
27
+ </ul><br />
28
+
29
+ <!--=================== Demo Section ===================-->
30
+
31
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
32
+ <tr>
33
+ <td>${Title}</td>
34
+ <td class="synopsis">{{html Synopsis}}</td>
35
+ </tr>
36
+ </script>
37
+
38
+ <table><tbody class="header"><tr><th>Title</th><th>Synopsis</th></tr></tbody>
39
+ <tbody id="movieList"></tbody>
40
+ </table>
41
+
42
+ <script type="text/javascript">
43
+
44
+ var movies = [
45
+ {
46
+ Title: "Meet Joe Black",
47
+ Synopsis: "The <span class='role'>grim reaper</span> (<a href='http://www.netflix.com/RoleDisplay/Brad_Pitt/73919'>Brad Pitt</a>) visits <span class='role'>Bill Parrish</span> (<a href='http://www.netflix.com/RoleDisplay/Anthony_Hopkins/43014'>Anthony Hopkins</a>)..."
48
+ },
49
+ {
50
+ Title: "Eyes Wide Shut",
51
+ Synopsis: "Director <span class='red'>Stanley Kubrick's</span> final film: <br/><br/><img src='http://cdn-4.nflximg.com/US/boxshots/large/5670434.jpg'/>"
52
+ }
53
+ ];
54
+
55
+ $( "#movieTemplate" ).tmpl( movies )
56
+ .appendTo( "#movieList" );
57
+
58
+ </script>
59
+
60
+ <!--================ End of Demo Section ================-->
61
+
62
+ <h4>Data:</h4>
63
+
64
+ <pre class="brush: js;">var movies = [
65
+ {
66
+ Title: "Eyes Wide Shut",
67
+ Synopsis: "Director &lt;span class='red'>Stanley Kubrick's&lt;/span> final film:&lt;img src='...'/>"
68
+ }
69
+ ];</pre>
70
+
71
+ <h4>HTML:</h4>
72
+
73
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
74
+ &lt;tr>
75
+ &lt;td>${Title}&lt;/td>
76
+ &lt;td class="synopsis">{{html Synopsis}}&lt;/td>
77
+ &lt;/tr>
78
+ &lt;/script></pre>
79
+
80
+ </body>
81
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/2_html-tag.html ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ <style type="text/css">
10
+ .role { font-weight: bold; font-style: italic; background-color: Yellow; }
11
+ .synopsis { background-color: white; padding: 15px; }
12
+ .director { font-weight: bold; font-style: italic; color: red; }
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <a href="../../step-by-step.html">Home</a><br />
17
+ <a href="2_html-tag-source.html">Source</a>
18
+
19
+ <h3>Demo: Using ${} or {{html}} to render data values or expressions</h3>
20
+
21
+ <ul>
22
+ <li>${} is equivalent to {{= }}. It HTML encodes. (Better security, but slight perf cost)</li>
23
+ <li>{{html}} does not encode. Used to render values that include html markup</li>
24
+ </ul><br />
25
+
26
+ <!--=================== Demo Section ===================-->
27
+
28
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
29
+ <tr>
30
+ <td>${Title}</td>
31
+ <td class="synopsis">{{html Synopsis}}</td>
32
+ </tr>
33
+ </script>
34
+
35
+ <table><tbody class="header"><tr><th>Title</th><th>Synopsis</th></tr></tbody>
36
+ <tbody id="movieList"></tbody>
37
+ </table>
38
+
39
+ <script type="text/javascript">
40
+
41
+ var movies = [
42
+ {
43
+ Title: "Meet Joe Black",
44
+ Synopsis: "The <span class='role'>grim reaper</span> (<a href='http://www.netflix.com/RoleDisplay/Brad_Pitt/73919'>Brad Pitt</a>) visits <span class='role'>Bill Parrish</span> (<a href='http://www.netflix.com/RoleDisplay/Anthony_Hopkins/43014'>Anthony Hopkins</a>)..."
45
+ },
46
+ {
47
+ Title: "Eyes Wide Shut",
48
+ Synopsis: "Director <span class='director'>Stanley Kubrick's</span> final film: <br/><br/><img src='http://cdn-4.nflximg.com/US/boxshots/large/5670434.jpg'/>"
49
+ }
50
+ ];
51
+
52
+ $( "#movieTemplate" ).tmpl( movies )
53
+ .appendTo( "#movieList" );
54
+
55
+ </script>
56
+
57
+ <!--================ End of Demo Section ================-->
58
+
59
+ </body>
60
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/3_if-else-tag-source.html ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
10
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
11
+ </head>
12
+ <body>
13
+ <a href="../../step-by-step.html">Home</a><br />
14
+ <a href="3_if-else-tag.html">Run</a>
15
+
16
+ <h3>Demo: Using {{if}} and {{else}} to render conditional sections.</h3>
17
+
18
+ <!--=================== Demo Section ===================-->
19
+
20
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
21
+ <tr>
22
+ <td>${Title}</td>
23
+ <td>
24
+ {{if Languages}}
25
+ Alternative languages: <em>${Languages}</em>.
26
+ {{else Subtitles}}
27
+ Original language only... <br/>Subtitles in <em>${Subtitles}</em>.
28
+ {{else}}
29
+ Original version only, without subtitles.
30
+ {{/if}}
31
+ </td>
32
+ </tr>
33
+ </script>
34
+
35
+ <table><tbody class="header"><tr><th>Synopsis</th><th>Title</th></tr></tbody>
36
+ <tbody id="movieList"></tbody>
37
+ </table>
38
+
39
+ <script type="text/javascript">
40
+
41
+ var movies = [
42
+ {
43
+ Title: "Meet Joe Black",
44
+ Languages: "English and French",
45
+ Subtitles: "English"
46
+ },
47
+ {
48
+ Title: "Eyes Wide Shut",
49
+ Subtitles: "French and Spanish"
50
+ },
51
+ {
52
+ Title: "The Mighty"
53
+ },
54
+ {
55
+ Title: "City Hunter",
56
+ Languages: "Mandarin and Chinese"
57
+ }
58
+ ];
59
+
60
+ $( "#movieTemplate" ).tmpl( movies )
61
+ .appendTo( "#movieList" );
62
+
63
+ </script>
64
+
65
+ <!--================ End of Demo Section ================-->
66
+
67
+ <h4>Data:</h4>
68
+
69
+ <pre class="brush: js;">var movies = [
70
+ {
71
+ Title: "Meet Joe Black",
72
+ Languages: "English and French",
73
+ Subtitles: "English"
74
+ },
75
+ {
76
+ Title: "Eyes Wide Shut",
77
+ Subtitles: "French and Spanish"
78
+ },
79
+ {
80
+ Title: "The Mighty"
81
+ }
82
+ ];</pre>
83
+
84
+ <h4>HTML:</h4>
85
+
86
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
87
+ &lt;tr>
88
+ &lt;td>${Title}&lt;/td>
89
+ &lt;td>
90
+ {{if Languages}}
91
+ Alternative languages: &lt;em>${Languages}&lt;/em>.
92
+ {{else Subtitles}}
93
+ Original language only... &lt;br/>Subtitles in &lt;em>${Subtitles}&lt;/em>.
94
+ {{else}}
95
+ Original version only, without subtitles.
96
+ {{/if}}
97
+ &lt;/td>
98
+ &lt;/tr>
99
+ &lt;/script></pre>
100
+
101
+ </body>
102
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/3_if-else-tag.html ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+ <a href="../../step-by-step.html">Home</a><br />
12
+ <a href="3_if-else-tag-source.html">Source</a>
13
+
14
+ <h3>Demo: Using {{if}} and {{else}} to render conditional sections.</h3>
15
+
16
+ <!--=================== Demo Section ===================-->
17
+
18
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
19
+ <tr>
20
+ <td>${Title}</td>
21
+ <td>
22
+ {{if Languages}}
23
+ Alternative languages: <em>${Languages}</em>.
24
+ {{else Subtitles}}
25
+ Original language only... <br/>Subtitles in <em>${Subtitles}</em>.
26
+ {{else}}
27
+ Original version only, without subtitles.
28
+ {{/if}}
29
+ </td>
30
+ </tr>
31
+ </script>
32
+
33
+ <table><tbody class="header"><tr><th>Synopsis</th><th>Title</th></tr></tbody>
34
+ <tbody id="movieList"></tbody>
35
+ </table>
36
+
37
+ <script type="text/javascript">
38
+
39
+ var movies = [
40
+ {
41
+ Title: "Meet Joe Black",
42
+ Languages: "English and French",
43
+ Subtitles: "English"
44
+ },
45
+ {
46
+ Title: "Eyes Wide Shut",
47
+ Subtitles: "French and Spanish"
48
+ },
49
+ {
50
+ Title: "The Mighty"
51
+ },
52
+ {
53
+ Title: "City Hunter",
54
+ Languages: "Mandarin and Chinese"
55
+ }
56
+ ];
57
+
58
+ $( "#movieTemplate" ).tmpl( movies )
59
+ .appendTo( "#movieList" );
60
+
61
+ </script>
62
+
63
+ <!--================ End of Demo Section ================-->
64
+
65
+ </body>
66
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/4_each-tag-source.html ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
10
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
11
+ </head>
12
+ <body>
13
+ <a href="../../step-by-step.html">Home</a><br />
14
+ <a href="4_each-tag.html">Run</a>
15
+
16
+ <h3>Demo: Using {{each}} to render repeating sections.</h3>
17
+
18
+ <!--=================== Demo Section ===================-->
19
+
20
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
21
+ <tr>
22
+ <td>${Title}</td>
23
+ <td>Languages:
24
+ <em>
25
+ {{each Languages}}
26
+ ${$value.Name}
27
+ {{/each}}
28
+ </em>
29
+ </td>
30
+ </tr>
31
+ </script>
32
+
33
+ <table><tbody class="header"><tr><th>Synopsis</th><th>Title</th></tr></tbody>
34
+ <tbody id="movieList"></tbody>
35
+ </table>
36
+
37
+ <script type="text/javascript">
38
+
39
+ function namePlusSeparator( name, index, length ){
40
+ var ret = name;
41
+ if ( index < length - 1 ) {
42
+ if ( index === length - 2 ) {
43
+ ret += " and";
44
+ } else {
45
+ ret += ",";
46
+ }
47
+ }
48
+ return ret;
49
+ }
50
+
51
+ var movies = [
52
+ {
53
+ Title: "Meet Joe Black",
54
+ Languages: [
55
+ { Name: "English" },
56
+ { Name: "French" }
57
+ ]
58
+ },
59
+ {
60
+ Title: "Eyes Wide Shut",
61
+ Languages: [
62
+ { Name: "French" },
63
+ { Name: "German" },
64
+ { Name: "Spanish" }
65
+ ]
66
+ }
67
+ ];
68
+
69
+ $( "#movieTemplate" ).tmpl( movies )
70
+ .appendTo( "#movieList" );
71
+
72
+ </script>
73
+
74
+ <!--================ End of Demo Section ================-->
75
+
76
+ <h4>Data:</h4>
77
+
78
+ <pre class="brush: js;">var movies = [
79
+ {
80
+ Title: "Meet Joe Black",
81
+ Languages: [
82
+ { Name: "English" },
83
+ { Name: "French" }
84
+ ]
85
+ }
86
+ ];</pre>
87
+
88
+ <h4>HTML:</h4>
89
+
90
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
91
+ &lt;tr>
92
+ &lt;td>${Title}&lt;/td>
93
+ &lt;td>Languages:
94
+ &lt;em>
95
+ {{each Languages}}
96
+ ${$value.Name}
97
+ {{/each}}
98
+ &lt;/em>
99
+ &lt;/td>
100
+ &lt;/tr>
101
+ &lt;/script></pre>
102
+
103
+ </body>
104
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/4_each-tag.html ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+ <a href="../../step-by-step.html">Home</a><br />
12
+ <a href="4_each-tag-source.html">Source</a>
13
+
14
+ <h3>Demo: Using {{each}} to render repeating sections.</h3>
15
+
16
+ <!--=================== Demo Section ===================-->
17
+
18
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
19
+ <tr>
20
+ <td>${Title}</td>
21
+ <td>Languages:
22
+ <em>
23
+ {{each Languages}}
24
+ ${$value.Name}
25
+ {{/each}}
26
+ </em>
27
+ </td>
28
+ </tr>
29
+ </script>
30
+
31
+ <table><tbody class="header"><tr><th>Synopsis</th><th>Title</th></tr></tbody>
32
+ <tbody id="movieList"></tbody>
33
+ </table>
34
+
35
+ <script type="text/javascript">
36
+
37
+ function namePlusSeparator( name, index, length ){
38
+ var ret = name;
39
+ if ( index < length - 1 ) {
40
+ if ( index === length - 2 ) {
41
+ ret += " and";
42
+ } else {
43
+ ret += ",";
44
+ }
45
+ }
46
+ return ret;
47
+ }
48
+
49
+ var movies = [
50
+ {
51
+ Title: "Meet Joe Black",
52
+ Languages: [
53
+ { Name: "English" },
54
+ { Name: "French" }
55
+ ]
56
+ },
57
+ {
58
+ Title: "Eyes Wide Shut",
59
+ Languages: [
60
+ { Name: "French" },
61
+ { Name: "German" },
62
+ { Name: "Spanish" }
63
+ ]
64
+ }
65
+ ];
66
+
67
+ $( "#movieTemplate" ).tmpl( movies )
68
+ .appendTo( "#movieList" );
69
+
70
+ </script>
71
+
72
+ <!--================ End of Demo Section ================-->
73
+
74
+ </body>
75
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/5_javascript-source.html ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
10
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
11
+ </head>
12
+ <body>
13
+ <a href="../../step-by-step.html">Home</a><br />
14
+ <a href="5_javascript.html">Run</a>
15
+
16
+ <h3>Demo: Using JavaScript expressions and functions calls within templates.</h3>
17
+
18
+ <!--=================== Demo Section ===================-->
19
+
20
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
21
+ <tr>
22
+ <td>${Title}</td>
23
+ <td><b>Languages:</b>
24
+ <em>
25
+ {{each Languages}}
26
+ ${$value.Name}{{if $index < Languages.length - 2}}, {{else $index === Languages.length - 2}} and {{/if}}
27
+ {{/each}}
28
+ </em><br/><br/>
29
+ <b>Subtitles:</b>
30
+ <em>
31
+ {{each( i, lang ) Subtitles}}
32
+ ${namePlusSeparator( lang.Name, i, Subtitles.length )}
33
+ {{/each}}
34
+ </em>
35
+ </td>
36
+ </tr>
37
+ </script>
38
+
39
+ <table><tbody class="header"><tr><th>Synopsis</th><th>Title</th></tr></tbody>
40
+ <tbody id="movieList"></tbody>
41
+ </table>
42
+
43
+ <script type="text/javascript">
44
+
45
+ function namePlusSeparator( name, index, length ){
46
+ var ret = name.toUpperCase();
47
+ if ( index < length - 1 ) {
48
+ if ( index === length - 2 ) {
49
+ ret += " and";
50
+ } else {
51
+ ret += ",";
52
+ }
53
+ }
54
+ return ret;
55
+ }
56
+
57
+ var movies = [
58
+ {
59
+ Title: "Meet Joe Black",
60
+ Languages: [
61
+ { Name: "English" },
62
+ { Name: "French" }
63
+ ],
64
+ Subtitles: [
65
+ { Name: "English" },
66
+ { Name: "French" },
67
+ { Name: "Chinese" }
68
+ ]
69
+ },
70
+ {
71
+ Title: "Eyes Wide Shut",
72
+ Languages: [
73
+ { Name: "French" },
74
+ { Name: "German" },
75
+ { Name: "Spanish" }
76
+ ],
77
+ Subtitles: [
78
+ { Name: "English" }
79
+ ]
80
+ }
81
+ ];
82
+
83
+ $( "#movieTemplate" ).tmpl( movies )
84
+ .appendTo( "#movieList" );
85
+
86
+ </script>
87
+
88
+ <!--================ End of Demo Section ================-->
89
+
90
+ <h4>HTML:</h4>
91
+
92
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
93
+ &lt;td>${Title}&lt;/td>
94
+ &lt;td>&lt;b>Languages:&lt;/b>
95
+ &lt;em>
96
+ {{each Languages}}
97
+ ${$value.Name}{{if $index &lt; Languages.length - 2}}, {{else $index === Languages.length - 2}} and {{/if}}
98
+ {{/each}}
99
+ &lt;/em>&lt;br/>&lt;br/>
100
+ &lt;b>Subtitles:&lt;/b>
101
+ &lt;em>
102
+ {{each( i, lang ) Subtitles}}
103
+ ${namePlusSeparator( lang.Name, i, Subtitles.length )}
104
+ {{/each}}
105
+ &lt;/em>
106
+ &lt;/td>
107
+ &lt;/script></pre>
108
+
109
+ <h4>Script:</h4>
110
+ <pre class="brush: js;">function namePlusSeparator( name, index, length ){
111
+ var ret = name.toUpperCase();
112
+ if ( index < length - 1 ) {
113
+ if ( index === length - 2 ) {
114
+ ret += " and";
115
+ } else {
116
+ ret += ",";
117
+ }
118
+ }
119
+ return ret;
120
+ }</pre>
121
+
122
+ </body>
123
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/5_javascript.html ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+ <a href="../../step-by-step.html">Home</a><br />
12
+ <a href="5_javascript-source.html">Source</a>
13
+
14
+ <h3>Demo: Using JavaScript expressions and functions calls within templates.</h3>
15
+
16
+ <!--=================== Demo Section ===================-->
17
+
18
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
19
+ <tr>
20
+ <td>${Title}</td>
21
+ <td><b>Languages:</b>
22
+ <em>
23
+ {{each Languages}}
24
+ ${$value.Name}{{if $index < Languages.length - 2}}, {{else $index === Languages.length - 2}} and {{/if}}
25
+ {{/each}}
26
+ </em><br/><br/>
27
+ <b>Subtitles:</b>
28
+ <em>
29
+ {{each( i, lang ) Subtitles}}
30
+ ${namePlusSeparator( lang.Name, i, Subtitles.length )}
31
+ {{/each}}
32
+ </em>
33
+ </td>
34
+ </tr>
35
+ </script>
36
+
37
+ <table><tbody class="header"><tr><th>Synopsis</th><th>Title</th></tr></tbody>
38
+ <tbody id="movieList"></tbody>
39
+ </table>
40
+
41
+ <script type="text/javascript">
42
+
43
+ function namePlusSeparator( name, index, length ){
44
+ var ret = name.toUpperCase();
45
+ if ( index < length - 1 ) {
46
+ if ( index === length - 2 ) {
47
+ ret += " and";
48
+ } else {
49
+ ret += ",";
50
+ }
51
+ }
52
+ return ret;
53
+ }
54
+
55
+ var movies = [
56
+ {
57
+ Title: "Meet Joe Black",
58
+ Languages: [
59
+ { Name: "English" },
60
+ { Name: "French" }
61
+ ],
62
+ Subtitles: [
63
+ { Name: "English" },
64
+ { Name: "French" },
65
+ { Name: "Chinese" }
66
+ ]
67
+ },
68
+ {
69
+ Title: "Eyes Wide Shut",
70
+ Languages: [
71
+ { Name: "French" },
72
+ { Name: "German" },
73
+ { Name: "Spanish" }
74
+ ],
75
+ Subtitles: [
76
+ { Name: "English" }
77
+ ]
78
+ }
79
+ ];
80
+
81
+ $( "#movieTemplate" ).tmpl( movies )
82
+ .appendTo( "#movieList" );
83
+
84
+ </script>
85
+
86
+ <!--================ End of Demo Section ================-->
87
+
88
+ </body>
89
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/6_hierarchical-data-source.html ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
10
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
11
+ </head>
12
+ <body>
13
+ <a href="../../step-by-step.html">Home</a><br />
14
+ <a href="6_hierarchical-data.html">Run</a>
15
+
16
+ <h3>Demo: Using {{tmpl}} to render hierarchical data.</h3>
17
+
18
+ <!--=================== Demo Section ===================-->
19
+
20
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
21
+ <tr>
22
+ <td>${Title}</td>
23
+ <td>
24
+ {{tmpl(Languages) "#languageTemplate"}}
25
+ </td>
26
+ </tr>
27
+ </script>
28
+
29
+ <script id="languageTemplate" type="text/x-jquery-tmpl">
30
+ <div>${Name}</div>
31
+ </script>
32
+
33
+ <div class="height">
34
+ <table><tbody class="header"><tr><th>Title</th><th>Languages</th></tr></tbody>
35
+ <tbody id="movieList"></tbody>
36
+ </table>
37
+ </div>
38
+
39
+ <script type="text/javascript">
40
+
41
+ var movies = [
42
+ {
43
+ Title: "Meet Joe Black",
44
+ Languages: [
45
+ { Name: "English" },
46
+ { Name: "French" }
47
+ ]
48
+ },
49
+ {
50
+ Title: "Eyes Wide Shut",
51
+ Languages: [
52
+ { Name: "French" },
53
+ { Name: "German" },
54
+ { Name: "Spanish" }
55
+ ]
56
+ }
57
+ ];
58
+
59
+ $( "#movieTemplate" ).tmpl( movies )
60
+ .appendTo( "#movieList" );
61
+
62
+ </script>
63
+
64
+ <!--================ End of Demo Section ================-->
65
+
66
+ <h4>Data:</h4>
67
+ <pre class="brush: js;">var movies = [
68
+ { Name: "Meet Joe Black",
69
+ Languages:[
70
+ { Name: "English" },
71
+ { Name: "French" }
72
+ ]
73
+ },
74
+ { Name: "Eyes Wide Shut",
75
+ Languages:[
76
+ { Name: "French" },
77
+ { Name: "German" } ,
78
+ { Name: "Spanish" }
79
+ ]
80
+ }
81
+ ];</pre>
82
+
83
+ <h4>HTML:</h4>
84
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
85
+ &lt;tr>
86
+ &lt;td>${Name}&lt;/td>
87
+ &lt;td>{{tmpl(Languages) "#languageTemplate"}}&lt;/td>
88
+ &lt;/tr>
89
+ &lt;/script>
90
+
91
+ &lt;script id="languageTemplate" type="text/x-jquery-tmpl">
92
+ &lt;div>${Name}&lt;/div>
93
+ &lt;/script></pre>
94
+
95
+ </body>
96
+ </html>
apps/jquery-tmpl/demos/step-by-step/0_tmpl-read-only/6_hierarchical-data.html ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/movielist.css" rel="stylesheet" type="text/css" />
9
+ </head>
10
+ <body>
11
+ <a href="../../step-by-step.html">Home</a><br />
12
+ <a href="6_hierarchical-data-source.html">Source</a>
13
+
14
+ <h3>Demo: Using {{tmpl}} to render hierarchical data.</h3>
15
+
16
+ <!--=================== Demo Section ===================-->
17
+
18
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
19
+ <tr>
20
+ <td>${Title}</td>
21
+ <td>
22
+ {{tmpl(Languages) "#languageTemplate"}}
23
+ </td>
24
+ </tr>
25
+ </script>
26
+
27
+ <script id="languageTemplate" type="text/x-jquery-tmpl">
28
+ <div>
29
+ <em>${Name}</em>
30
+ </div>
31
+ </script>
32
+
33
+ <table><tbody class="header"><tr><th>Title</th><th>Languages</th></tr></tbody>
34
+ <tbody id="movieList"></tbody>
35
+ </table>
36
+
37
+ <script type="text/javascript">
38
+
39
+ var movies = [
40
+ {
41
+ Title: "Meet Joe Black",
42
+ Languages: [
43
+ { Name: "English" },
44
+ { Name: "French" }
45
+ ]
46
+ },
47
+ {
48
+ Title: "Eyes Wide Shut",
49
+ Languages: [
50
+ { Name: "French" },
51
+ { Name: "German" },
52
+ { Name: "Spanish" }
53
+ ]
54
+ }
55
+ ];
56
+
57
+ $( "#movieTemplate" ).tmpl( movies )
58
+ .appendTo( "#movieList" );
59
+
60
+ </script>
61
+
62
+ <!--================ End of Demo Section ================-->
63
+
64
+ </body>
65
+ </html>
66
+
67
+
apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/0_accordion-switching-template-source.html ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
9
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
10
+ <style type="text/css">
11
+ table { cursor:pointer; border-collapse:collapse; border:2px solid blue; width:300px; margin:8px; }
12
+ table tr { border:1px solid blue; color:blue; background-color:#f8f8f8; } table td { padding:3px; } table tr:hover { color:red; }
13
+ .movieDetail { background-color:yellow; } .movieDetail.row1 { border-bottom:none; } .movieDetail.row2 { border-top:none; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <a href="../../step-by-step.html">Home</a><br />
18
+ <a href="0_accordion-switching-template.html">Run</a>
19
+
20
+ <h3>Accordion: Using dynamic switching of templates</h3>
21
+
22
+ <!--=================== Demo Section ===================-->
23
+
24
+ <script id="summaryTemplate" type="text/x-jquery-tmpl">
25
+ <tr class='movieSummary'><td>
26
+ ${Title}
27
+ </td></tr>
28
+ </script>
29
+
30
+ <script id="detailTemplate" type="text/x-jquery-tmpl">
31
+ <tr class='movieDetail row1'><td>
32
+ ${Title}
33
+ </td></tr>
34
+ <tr class='movieDetail row2'><td><b>Languages:</b>
35
+ {{tmpl(Languages) "#languageTemplate"}}
36
+ </td></tr>
37
+ </script>
38
+
39
+ <script id="languageTemplate" type="text/x-jquery-tmpl">
40
+ <div>
41
+ <em>${Name}</em>
42
+ </div>
43
+ </script>
44
+
45
+ Click for details:
46
+ <div class="height">
47
+ <table><tbody id="movieList"></tbody></table>
48
+ </div>
49
+
50
+ <script type="text/javascript">
51
+
52
+ var selectedItem = null,
53
+
54
+ movies = [
55
+ {
56
+ Title: "The Red Violin",
57
+ Languages: [
58
+ { Name: "English" },
59
+ { Name: "French" }
60
+ ]
61
+ },
62
+ {
63
+ Title: "Eyes Wide Shut",
64
+ Languages: [
65
+ { Name: "French" },
66
+ { Name: "German" },
67
+ { Name: "Spanish" }
68
+ ]
69
+ },
70
+ {
71
+ Title: "The Inheritance",
72
+ ReleaseYear: "1976",
73
+ Languages: [
74
+ { Name: "English" },
75
+ { Name: "Dutch" }
76
+ ]
77
+ }
78
+ ],
79
+
80
+ detailTemplate = $( "#detailTemplate" ).template(),
81
+
82
+ summaryTemplate = $( "#summaryTemplate" ).template();
83
+
84
+ function unselect( tmplItem ) {
85
+ /* Set the template of the selected item
86
+ back to the summary template */
87
+ if ( selectedItem ) {
88
+ selectedItem.tmpl = summaryTemplate;
89
+ selectedItem.update();
90
+ selectedItem = null;
91
+ }
92
+ }
93
+
94
+ /* Render the summaryTemplate with the "movies" data */
95
+ $( "#summaryTemplate" )
96
+ .tmpl( movies )
97
+ .appendTo( "#movieList" );
98
+
99
+ /* Add onclick handlers for movie template items
100
+ using the summary or details template */
101
+ $("#movieList")
102
+ .delegate( ".movieSummary", "click", function () {
103
+ /* Unselect the currently selected item */
104
+ unselect( selectedItem );
105
+
106
+ /* Get the template item data structure
107
+ which this clicked element belongs to,
108
+ and make it the selected item */
109
+ selectedItem = $.tmplItem(this);
110
+
111
+ /* Set the template on this item to the detail template */
112
+ selectedItem.tmpl = detailTemplate;
113
+ selectedItem.update();
114
+ })
115
+ .delegate( ".movieDetail", "click", function () {
116
+ /* Unselect the currently selected item */
117
+ unselect();
118
+ });
119
+
120
+ </script>
121
+
122
+ <!--================ End of Demo Section ================-->
123
+
124
+ <h4>Data:</h4>
125
+ <pre class="brush: js;">var movies = [
126
+ {
127
+ Title: "The Red Violin",
128
+ Languages: [
129
+ { Name: "English" },
130
+ { Name: "French" }
131
+ ]
132
+ },
133
+ ...
134
+ ];
135
+ ;</pre>
136
+
137
+ <h4>HTML:</h4>
138
+ <pre class="brush: xml;">&lt;script id="summaryTemplate" type="text/x-jquery-tmpl">
139
+ &lt;tr class='movieSummary'>&lt;td>
140
+ ${Title}
141
+ &lt;/td>&lt;/tr>
142
+ &lt;/script>
143
+
144
+ &lt;script id="detailTemplate" type="text/x-jquery-tmpl">
145
+ &lt;tr class='movieDetail'>&lt;td>
146
+ ${Title}
147
+ &lt;/td>&lt;/tr>
148
+ &lt;tr class='movieDetail'>&lt;td>&lt;b>Languages:&lt;/b>
149
+ {{tmpl(Languages) "#languageTemplate"}}
150
+ &lt;/td>&lt;/tr>
151
+ &lt;/script>
152
+ </pre>
153
+
154
+ <h4>Script:</h4>
155
+ <pre class="brush: js;">var selectedItem = null;
156
+
157
+ $("#movieList")
158
+ .delegate( ".movieSummary", "click", function () {
159
+ /* Unselect the currently selected item */
160
+ unselect( selectedItem );
161
+
162
+ /* Get template item clicked element belongs to, and make it the selected item */
163
+ selectedItem = $.tmplItem(this);
164
+
165
+ /* Swap template on this item to the detail template, and update item */
166
+ selectedItem.tmpl = detailTemplate;
167
+ selectedItem.update();
168
+ })
169
+ .delegate( ".movieDetail", "click", function () {
170
+ /* Unselect the currently selected item */
171
+ unselect();
172
+ });
173
+
174
+ function unselect( tmplItem ) {
175
+ if ( selectedItem ) {
176
+ /* Swap template back to the summary template and update item */
177
+ selectedItem.tmpl = summaryTemplate;
178
+ selectedItem.update();
179
+ selectedItem = null;
180
+ }
181
+ }</pre>
182
+
183
+ </body>
184
+ </html>
apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/0_accordion-switching-template.html ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <style type="text/css">
9
+ table { cursor:pointer; border-collapse:collapse; border:2px solid blue; width:300px; margin:8px; }
10
+ table tr { border:1px solid blue; color:blue; background-color:#f8f8f8; } table td { padding:3px; } table tr:hover { color:red; }
11
+ .movieDetail { background-color:yellow; } .movieDetail.row1 { border-bottom:none; } .movieDetail.row2 { border-top:none; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <a href="../../step-by-step.html">Home</a><br />
16
+ <a href="0_accordion-switching-template-source.html">Source</a>
17
+
18
+ <h3>Accordion: Using dynamic switching of templates</h3>
19
+
20
+ <!--=================== Demo Section ===================-->
21
+
22
+ <script id="summaryTemplate" type="text/x-jquery-tmpl">
23
+ <tr class='movieSummary'><td>
24
+ ${Title}
25
+ </td></tr>
26
+ </script>
27
+
28
+ <script id="detailTemplate" type="text/x-jquery-tmpl">
29
+ <tr class='movieDetail row1'><td>
30
+ ${Title}
31
+ </td></tr>
32
+ <tr class='movieDetail row2'><td><b>Languages:</b>
33
+ {{tmpl(Languages) "#languageTemplate"}}
34
+ </td></tr>
35
+ </script>
36
+
37
+ <script id="languageTemplate" type="text/x-jquery-tmpl">
38
+ <div>
39
+ <em>${Name}</em>
40
+ </div>
41
+ </script>
42
+
43
+ Click for details:
44
+ <div class="height">
45
+ <table><tbody id="movieList"></tbody></table>
46
+ </div>
47
+
48
+ <script type="text/javascript">
49
+
50
+ var selectedItem = null,
51
+
52
+ movies = [
53
+ {
54
+ Title: "The Red Violin",
55
+ Languages: [
56
+ { Name: "English" },
57
+ { Name: "French" }
58
+ ]
59
+ },
60
+ {
61
+ Title: "Eyes Wide Shut",
62
+ Languages: [
63
+ { Name: "French" },
64
+ { Name: "German" },
65
+ { Name: "Spanish" }
66
+ ]
67
+ },
68
+ {
69
+ Title: "The Inheritance",
70
+ ReleaseYear: "1976",
71
+ Languages: [
72
+ { Name: "English" },
73
+ { Name: "Dutch" }
74
+ ]
75
+ }
76
+ ],
77
+
78
+ detailTemplate = $( "#detailTemplate" ).template(),
79
+
80
+ summaryTemplate = $( "#summaryTemplate" ).template();
81
+
82
+ function unselect( tmplItem ) {
83
+ /* Set the template of the selected item
84
+ back to the summary template */
85
+ if ( selectedItem ) {
86
+ selectedItem.tmpl = summaryTemplate;
87
+ selectedItem.update();
88
+ selectedItem = null;
89
+ }
90
+ }
91
+
92
+ /* Render the summaryTemplate with the "movies" data */
93
+ $( "#summaryTemplate" )
94
+ .tmpl( movies )
95
+ .appendTo( "#movieList" );
96
+
97
+ /* Add onclick handlers for movie template items
98
+ using the summary or details template */
99
+ $("#movieList")
100
+ .delegate( ".movieSummary", "click", function () {
101
+ /* Unselect the currently selected item */
102
+ unselect( selectedItem );
103
+
104
+ /* Get the template item data structure
105
+ which this clicked element belongs to,
106
+ and make it the selected item */
107
+ selectedItem = $.tmplItem(this);
108
+
109
+ /* Set the template on this item to the detail template */
110
+ selectedItem.tmpl = detailTemplate;
111
+ selectedItem.update();
112
+ })
113
+ .delegate( ".movieDetail", "click", function () {
114
+ /* Unselect the currently selected item */
115
+ unselect();
116
+ });
117
+
118
+ </script>
119
+
120
+ <!--================ End of Demo Section ================-->
121
+
122
+ </body>
123
+ </html>
apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/1_tree-view-using-tmpl-tag-source.html ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
9
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
10
+ <style type="text/css">
11
+ .treeView li li {margin-left:24px;}
12
+ .toggle {cursor:pointer;vertical-align:middle;margin-right:7px;display:inline-block;border:1px solid #555;text-align:center;height:12px;width:12px;line-height:11px;background-color:#f8f8f8;color:Blue;}
13
+ .treeView, .treeView ul {padding:0;margin:0;} .treeView li {margin-left:8px;list-style-type:none;padding:2px;}
14
+ .treeView li.folderItem {color:Blue;text-decoration:underline;font-style:italic;margin-bottom:4px;}
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <a href="../../step-by-step.html">Home</a><br />
19
+ <a href="1_tree-view-using-tmpl-tag.html">Run</a>
20
+
21
+ <h3>Tree view: using recursive nested {{tmpl}} tags.</h3>
22
+
23
+ <!--=================== Demo Section ===================-->
24
+
25
+ <ul id="movieList" class="treeView"></ul>
26
+
27
+ <script id="folderTemplate" type="text/x-jquery-tmpl">
28
+ <li>
29
+ {{if hasContent($data)}}
30
+ <span class="toggle">${$data.expanded ? "-" : "+"}</span>
31
+ {{/if}}
32
+ <span>${name}</span>
33
+ </li>
34
+ {{if expanded}}
35
+ <li>
36
+ <ul>{{tmpl(getFolderItems(name)) "#itemTemplate"}}</ul>
37
+ <ul>{{tmpl($data.folders || []) "#folderTemplate"}}</ul>
38
+ </li>
39
+ {{/if}}
40
+ </script>
41
+
42
+ <script id="itemTemplate" type="text/x-jquery-tmpl">
43
+ <li class="folderItem">${name}</li>
44
+ </script>
45
+
46
+ <script type="text/javascript">
47
+
48
+ /* Hierarchy of named folders */
49
+ var rootFolder = {
50
+ name: "Categories",
51
+ folders: [
52
+ { name: "Drama", folders: [
53
+ { name: "Courtroom" },
54
+ { name: "Political" }
55
+ ]},
56
+ { name: "Classic", folders: [
57
+ { name: "Musicals", folders: [
58
+ { name: "Jazz"},
59
+ { name: "R&B/Soul"}
60
+ ]},
61
+ ]}
62
+ ]
63
+ };
64
+
65
+ /* Array for the folder items. Each item can show up in one or more folders */
66
+ var movies = [
67
+ { name: "12 Angry Men",
68
+ folders: [ "Courtroom" ],
69
+ description: "A jury of 12 men must decide the fate of an 18-year-old boy."
70
+ },
71
+ { name: "Word of Honor",
72
+ folders: [ "Courtroom", "Classic" ],
73
+ description: "One man's word against the U.S. military."
74
+ }
75
+ ];
76
+
77
+ /* Declare the functions for getting the items and subfolders, etc. */
78
+ function getFolderItems( name ) {
79
+ return $.map( movies, function( movie ) {
80
+ return $.inArray( name, movie.folders ) > -1 ? movie : null;
81
+ });
82
+ }
83
+
84
+ function hasContent( folder ) {
85
+ return folder.expanded || folder.folders && folder.folders.length || getFolderItems(folder.name).length;
86
+ }
87
+
88
+ /* Render the folderTemplate with the "movies" data */
89
+ $( "#folderTemplate" ).tmpl( rootFolder ).appendTo( "#movieList" );
90
+
91
+ $( "#movieList" )
92
+ .delegate( ".toggle", "click", function() {
93
+ /* Toggle expanded property on data, then update rendering */
94
+ var tmplItem = $.tmplItem( this );
95
+ tmplItem.data.expanded = !tmplItem.data.expanded;
96
+ tmplItem.update();
97
+ })
98
+ .delegate( ".folderItem", "click", function() {
99
+ alert( $.tmplItem( this ).data.description );
100
+ });
101
+
102
+ </script>
103
+
104
+ <!--================ End of Demo Section ================-->
105
+
106
+ <h4>Data:</h4>
107
+ <pre class="brush: js;">var rootFolder = {
108
+ name: "Categories",
109
+ folders: [
110
+ { name: "Drama", folders: [
111
+ { name: "Courtroom" },
112
+ { name: "Political" }
113
+ ]},
114
+ { name: "Classic", folders: [
115
+ { name: "Musicals", folders: [
116
+ { name: "Jazz"},
117
+ { name: "R&B/Soul"}
118
+ ]},
119
+ ]}
120
+ ]
121
+ };
122
+
123
+ /* Array for the folder items. Each item can show up in one or more folders */
124
+ var movies = [
125
+ { name: "12 Angry Men",
126
+ folders: [ "Courtroom" ],
127
+ description: "A jury of 12 men must decide the fate of an 18-year-old boy."
128
+ },
129
+ { name: "Word of Honor",
130
+ folders: [ "Courtroom", "Classic" ],
131
+ description: "One man's word against the U.S. military."
132
+ }
133
+ ];</pre>
134
+
135
+ <h4>HTML:</h4>
136
+ <pre class="brush: xml;">&lt;script id="folderTemplate" type="text/x-jquery-tmpl">
137
+ &lt;li>
138
+ {{if hasContent($data)}}
139
+ &lt;span class="toggle">${$data.expanded ? "-" : "+"}&lt;/span>
140
+ {{/if}}
141
+ &lt;span>${name}&lt;/span>
142
+ &lt;/li>
143
+ {{if expanded}}
144
+ &lt;li>
145
+ &lt;ul>{{tmpl(getFolderItems(name)) "#itemTemplate"}}&lt;/ul>
146
+ &lt;ul>{{tmpl($data.folders || []) "#folderTemplate"}}&lt;/ul>
147
+ &lt;/li>
148
+ {{/if}}
149
+ &lt;/script>
150
+
151
+ &lt;script id="itemTemplate" type="text/x-jquery-tmpl">
152
+ &lt;li class="folderItem">${name}&lt;/li>
153
+ &lt;/script>
154
+ </pre>
155
+
156
+ <h4>Script:</h4>
157
+ <pre class="brush: js;">$( "#folderTmpl" ).tmpl( folders ).appendTo( "#movieList" );
158
+
159
+ $( "#movieList" )
160
+ .delegate( ".toggle", "click", function() {
161
+ /* Toggle expanded property on data, then update rendering */
162
+ var tmplItem = $.tmplItem( this );
163
+ tmplItem.data.expanded = !tmplItem.data.expanded;
164
+ tmplItem.update();
165
+ })
166
+ .delegate( ".folderItem", "click", function() {
167
+ alert( $.tmplItem( this ).data.description );
168
+ });</pre>
169
+
170
+ </body>
171
+ </html>
172
+ <script>
173
+
apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/1_tree-view-using-tmpl-tag.html ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <style type="text/css">
9
+ .treeView li li {margin-left:24px;}
10
+ .toggle {cursor:pointer;vertical-align:middle;margin-right:7px;display:inline-block;border:1px solid #555;text-align:center;height:12px;width:12px;line-height:11px;background-color:#f8f8f8;color:Blue;}
11
+ .treeView, .treeView ul {padding:0;margin:0;} .treeView li {margin-left:8px;list-style-type:none;padding:2px;}
12
+ .treeView li.folderItem {color:Blue;text-decoration:underline;font-style:italic;margin-bottom:4px;}
13
+ </style>
14
+ </head>
15
+ <body>
16
+ <a href="../../step-by-step.html">Home</a><br />
17
+ <a href="1_tree-view-using-tmpl-tag-source.html">Source</a>
18
+
19
+ <h3>Tree view: using recursive nested {{tmpl}} tags.</h3>
20
+
21
+ <!--=================== Demo Section ===================-->
22
+
23
+ <ul id="movieList" class="treeView"></ul>
24
+
25
+ <script id="folderTemplate" type="text/x-jquery-tmpl">
26
+ <li>
27
+ {{if hasContent($data)}}
28
+ <span class="toggle">${$data.expanded ? "-" : "+"}</span>
29
+ {{/if}}
30
+ <span>${name}</span>
31
+ </li>
32
+ {{if expanded}}
33
+ <li>
34
+ <ul>{{tmpl(getFolderItems(name)) "#itemTemplate"}}</ul>
35
+ <ul>{{tmpl($data.folders || []) "#folderTemplate"}}</ul>
36
+ </li>
37
+ {{/if}}
38
+ </script>
39
+
40
+ <script id="itemTemplate" type="text/x-jquery-tmpl">
41
+ <li class="folderItem">${name}</li>
42
+ </script>
43
+
44
+ <script type="text/javascript">
45
+
46
+ /* Hierarchy of named folders */
47
+ var rootFolder = {
48
+ name: "Categories",
49
+ folders: [
50
+ { name: "Drama", folders: [
51
+ { name: "Courtroom" },
52
+ { name: "Political" }
53
+ ]},
54
+ { name: "Classic", folders: [
55
+ { name: "Musicals", folders: [
56
+ { name: "Jazz"},
57
+ { name: "R&B/Soul"}
58
+ ]},
59
+ ]}
60
+ ]
61
+ };
62
+
63
+ /* Array for the folder items. Each item can show up in one or more folders */
64
+ var movies = [
65
+ { name: "12 Angry Men",
66
+ folders: [ "Courtroom" ],
67
+ description: "A jury of 12 men must decide the fate of an 18-year-old boy."
68
+ },
69
+ { name: "Word of Honor",
70
+ folders: [ "Courtroom", "Classic" ],
71
+ description: "One man's word against the U.S. military."
72
+ }
73
+ ];
74
+
75
+ /* Declare the functions for getting the items and subfolders, etc. */
76
+ function getFolderItems( name ) {
77
+ return $.map( movies, function( movie ) {
78
+ return $.inArray( name, movie.folders ) > -1 ? movie : null;
79
+ });
80
+ }
81
+
82
+ function hasContent( folder ) {
83
+ return folder.expanded || folder.folders && folder.folders.length || getFolderItems(folder.name).length;
84
+ }
85
+
86
+ /* Render the folderTemplate with the "movies" data */
87
+ $( "#folderTemplate" ).tmpl( rootFolder ).appendTo( "#movieList" );
88
+
89
+ $( "#movieList" )
90
+ .delegate( ".toggle", "click", function() {
91
+ /* Toggle expanded property on data, then update rendering */
92
+ var tmplItem = $.tmplItem( this );
93
+ tmplItem.data.expanded = !tmplItem.data.expanded;
94
+ tmplItem.update();
95
+ })
96
+ .delegate( ".folderItem", "click", function() {
97
+ alert( $.tmplItem( this ).data.description );
98
+ });
99
+
100
+ </script>
101
+
102
+ <!--================ End of Demo Section ================-->
103
+
104
+ </body>
105
+ </html>
106
+ <script>
107
+
apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/2_tabs-using-wrap-tag-source.html ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <link href="../../resources/syntaxhighlighter.css" rel="stylesheet" type="text/css" />
9
+ <script src="../../resources/syntaxhighlighter.min.js" type="text/javascript"></script>
10
+ <style type="text/css">
11
+ .body { height: 175px; background-color: #fff; }
12
+ .body div { height: 60px; padding: 12px; font-weight: bold; color: #222; }
13
+ .body div span { margin: 7px 0 10px 0; font-style:italic; font-weight: normal; padding: 3px;}
14
+ .body div img { float: left; margin-right: 30px; }
15
+ .body h3 { text-align: center; }
16
+ .tabsView td { border: solid 1px #0000A6; border-top: none; border-right: solid 2px #1E1ED2; }
17
+ .tabsView th { cursor: pointer; padding: 2px; font-weight: normal; font-style: italic; color: #888; border: solid 1px #bbb; border-right: none; background-color: #f8f8f8; border-bottom: solid 1px #1E1ED2; }
18
+ #tabsView > .tabsView { width: 465px; }
19
+ .tabsView { width: 450px; border-collapse: collapse; border: none; margin: 5px; }
20
+ .tabsView tr { border-right: solid 1px #bbb; }
21
+ th.header_true { font-weight: bold; border: solid 1px #0000A6; border-right: solid 2px #1E1ED2; border-bottom: solid 1px #eee; color: #0000A6; background-color: #fff; }
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <a href="../../step-by-step.html">Home</a><br />
26
+ <a href="2_tabs-using-wrap-tag.html">Run</a>
27
+
28
+ <h3>Tab View: Using {{wrap}} for template composition incorporating wrapped HTML</h3>
29
+
30
+ <!--=================== Demo Section ===================-->
31
+
32
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
33
+ <h2>${Title}</h2>
34
+
35
+ {{wrap "#tabsTemplate"}}
36
+ <h3>Details</h3>
37
+ <div>
38
+
39
+ Title: <span>${Title}</span><br/>
40
+ <h4>Languages:</h4>
41
+ {{each Languages}}<span>${$value.Name}</span><br/>{{/each}}
42
+
43
+ </div>
44
+
45
+ <h3>Description</h3>
46
+ <div>
47
+
48
+ <img src='http://cdn-4.nflximg.com/US/boxshots/large/5670434.jpg'/><br/><br/>
49
+ Director Stanley Kubrick's<br/> final film.
50
+
51
+ </div>
52
+
53
+ <h3>Comments</h3>
54
+ <div>
55
+
56
+ <ul>
57
+ <li>Great film...</li>
58
+ <li>The best</li>
59
+ <li>So boring, I couldn't keep my eyes open</li>
60
+ </ul>
61
+
62
+ </div>
63
+ {{/wrap}}
64
+ </script>
65
+
66
+ <script id="tabsTemplate" type="text/x-jquery-tmpl">
67
+ <table class="tabsView"><tbody>
68
+ <tr>
69
+ {{each $item.html("h3", true)}}
70
+ <th class="header_${$index === selectedTab}">
71
+ ${$value}
72
+ </th>
73
+ {{/each}}
74
+ </tr>
75
+ <tr><td colspan='${$item.html("h3").length}'>
76
+ <div class="body">
77
+ {{html $item.html("div")[selectedTab]}}
78
+ </div>
79
+ </td></tr>
80
+ </tbody></table>
81
+ </script>
82
+
83
+ <br />
84
+ <div id="tabsView">..loading</div>
85
+
86
+ <script type="text/javascript">
87
+
88
+ /* Track the selected tab index for inner and outer tab views */
89
+ var movie = {
90
+ Title: "Meet Joe Black",
91
+ Languages: [
92
+ { Name: "English" },
93
+ { Name: "French" }
94
+ ],
95
+ selectedTab: 0
96
+ };
97
+
98
+
99
+ function refresh() {
100
+ $( "#tabsView" ).empty();
101
+
102
+ $( "#movieTemplate" ).tmpl( movie )
103
+ .appendTo( "#tabsView" );
104
+ }
105
+
106
+ /* Render tabs view */
107
+ refresh();
108
+
109
+ $( "#tabsView" )
110
+ .delegate( ".tabsView th", "click", function() {
111
+ /* Set the selected tab index to this tab */
112
+ $.tmplItem( this ).data.selectedTab = $(this).index();
113
+
114
+ /* update the rendering */
115
+ refresh();
116
+ });
117
+
118
+ </script>
119
+
120
+ <!--================ End of Demo Section ================-->
121
+
122
+ <h4>HTML:</h4>
123
+ <pre class="brush: xml;">&lt;script id="movieTemplate" type="text/x-jquery-tmpl">
124
+ &lt;h2>${Title}&lt;/h2>
125
+
126
+ {{wrap "#tabsTemplate"}}
127
+ &lt;h3>Details&lt;/h3>
128
+ &lt;div>
129
+ Title: &lt;input value="${Title}" >
130
+ Languages:
131
+ {{each Languages}}&lt;span>${$value.Name}&lt;/span>{{/each}}
132
+ &lt;/div>
133
+
134
+ &lt;h3>Description&lt;/h3>
135
+ &lt;div>
136
+ ... content of tab 2
137
+ &lt;/div>
138
+
139
+ &lt;h3>Comments&lt;/h3>
140
+ &lt;div>
141
+ ... content of tab 3
142
+ &lt;/div>
143
+ {{/wrap}}
144
+ &lt;/script>
145
+
146
+ &lt;script id="tabsTemplate" type="text/x-jquery-tmpl">
147
+ &lt;table>&lt;tbody>
148
+ &lt;tr>
149
+ {{each $item.html("h3", true)}}
150
+ &lt;th class="header_${$index === selectedTab}">
151
+ ${$value}
152
+ &lt;/th>
153
+ {{/each}}
154
+ &lt;/tr>
155
+ &lt;tr>&lt;td colspan='${$item.html("h3").length}'>
156
+ &lt;div>
157
+ {{html $item.html("div")[selectedTab]}}
158
+ &lt;/div>
159
+ &lt;/td>&lt;/tr>
160
+ &lt;/tbody>&lt;/table>
161
+ &lt;/script>
162
+ </pre>
163
+
164
+ <h4>Script:</h4>
165
+ <pre class="brush: js;"> function refresh() {
166
+ $( "#tabsView" ).empty();
167
+
168
+ $( "#movieTemplate" ).tmpl( movie )
169
+ .appendTo( "#tabsView" );
170
+ }
171
+
172
+ $( "#tabsView" )
173
+ .delegate( ".tabsView th", "click", function() {
174
+ /* Set the selected tab index to this tab */
175
+ $.tmplItem( this ).data.selectedTab = $(this).index();
176
+
177
+ /* update the rendering */
178
+ refresh();
179
+ });</pre>
180
+ </body>
181
+ </html>
apps/jquery-tmpl/demos/step-by-step/1_tmpl-interactive/2_tabs-using-wrap-tag.html ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
5
+ <script src="../../../jquery.tmpl.js" type="text/javascript"></script>
6
+ <link href="../../resources/demos.css" rel="stylesheet" type="text/css" />
7
+
8
+ <style type="text/css">
9
+ .body { height: 175px; background-color: #fff; }
10
+ .body div { height: 60px; padding: 12px; font-weight: bold; color: #222; }
11
+ .body div span { margin: 7px 0 10px 0; font-style:italic; font-weight: normal; padding: 3px;}
12
+ .body div img { float: left; margin-right: 30px; }
13
+ .body h3 { text-align: center; }
14
+ .tabsView td { border: solid 1px #0000A6; border-top: none; border-right: solid 2px #1E1ED2; }
15
+ .tabsView th { cursor: pointer; padding: 2px; font-weight: normal; font-style: italic; color: #888; border: solid 1px #bbb; border-right: none; background-color: #f8f8f8; border-bottom: solid 1px #1E1ED2; }
16
+ #tabsView > .tabsView { width: 465px; }
17
+ .tabsView { width: 450px; border-collapse: collapse; border: none; margin: 5px; }
18
+ .tabsView tr { border-right: solid 1px #bbb; }
19
+ th.header_true { font-weight: bold; border: solid 1px #0000A6; border-right: solid 2px #1E1ED2; border-bottom: solid 1px #eee; color: #0000A6; background-color: #fff; }
20
+ </style>
21
+ </head>
22
+ <body>
23
+ <a href="../../step-by-step.html">Home</a><br />
24
+ <a href="2_tabs-using-wrap-tag-source.html">Source</a>
25
+
26
+ <h3>Tab View: Using {{wrap}} for template composition incorporating wrapped HTML</h3>
27
+
28
+ <!--=================== Demo Section ===================-->
29
+
30
+ <script id="movieTemplate" type="text/x-jquery-tmpl">
31
+ <h2>${Title}</h2>
32
+
33
+ {{wrap "#tabsTemplate"}}
34
+ <h3>Details</h3>
35
+ <div>
36
+
37
+ Title: <span>${Title}</span><br/>
38
+ <h4>Languages:</h4>
39
+ {{each Languages}}<span>${$value.Name}</span><br/>{{/each}}
40
+
41
+ </div>
42
+
43
+ <h3>Description</h3>
44
+ <div>
45
+
46
+ <img src='http://cdn-4.nflximg.com/US/boxshots/large/5670434.jpg'/><br/><br/>
47
+ Director Stanley Kubrick's<br/> final film.
48
+
49
+ </div>
50
+
51
+ <h3>Comments</h3>
52
+ <div>
53
+
54
+ <ul>
55
+ <li>Great film...</li>
56
+ <li>The best</li>
57
+ <li>So boring, I couldn't keep my eyes open</li>
58
+ </ul>
59
+
60
+ </div>
61
+ {{/wrap}}
62
+ </script>
63
+
64
+ <script id="tabsTemplate" type="text/x-jquery-tmpl">
65
+ <table class="tabsView"><tbody>
66
+ <tr>
67
+ {{each $item.html("h3", true)}}
68
+ <th class="header_${$index === selectedTab}">
69
+ ${$value}
70
+ </th>
71
+ {{/each}}
72
+ </tr>
73
+ <tr><td colspan='${$item.html("h3").length}'>
74
+ <div class="body">
75
+ {{html $item.html("div")[selectedTab]}}
76
+ </div>
77
+ </td></tr>
78
+ </tbody></table>
79
+ </script>
80
+
81
+ <br />
82
+ <div id="tabsView">..loading</div><br />
83
+
84
+ <script type="text/javascript">
85
+
86
+ /* Track the selected tab index for inner and outer tab views */
87
+ var movie = {
88
+ Title: "Meet Joe Black",
89
+ Languages: [
90
+ { Name: "English" },
91
+ { Name: "French" }
92
+ ],
93
+ selectedTab: 0
94
+ };
95
+
96
+
97
+ function refresh() {
98
+ $( "#tabsView" ).empty();
99
+ $( "#movieTemplate" ).tmpl( movie )
100
+ .appendTo( "#tabsView" );
101
+ }
102
+
103
+ /* Render tabs view */
104
+ refresh();
105
+
106
+ $( "#tabsView" )
107
+ .delegate( ".tabsView th", "click", function() {
108
+ /* Set the selected tab index to this tab */
109
+ $.tmplItem( this ).data.selectedTab = $(this).index();
110
+
111
+ /* update the rendering */
112
+ refresh();
113
+ });
114
+
115
+ </script>
116
+
117
+ <!--================ End of Demo Section ================-->
118
+
119
+ </body>
120
+ </html>
apps/jquery-tmpl/jquery.tmpl.js ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery Templates Plugin 1.0.0pre
3
+ * http://github.com/jquery/jquery-tmpl
4
+ * Requires jQuery 1.4.2
5
+ *
6
+ * Copyright Software Freedom Conservancy, Inc.
7
+ * Dual licensed under the MIT or GPL Version 2 licenses.
8
+ * http://jquery.org/license
9
+ */
10
+ (function( jQuery, undefined ){
11
+ var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
12
+ newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
13
+
14
+ function newTmplItem( options, parentItem, fn, data ) {
15
+ // Returns a template item data structure for a new rendered instance of a template (a 'template item').
16
+ // The content field is a hierarchical array of strings and nested items (to be
17
+ // removed and replaced by nodes field of dom elements, once inserted in DOM).
18
+ var newItem = {
19
+ data: data || (data === 0 || data === false) ? data : (parentItem ? parentItem.data : {}),
20
+ _wrap: parentItem ? parentItem._wrap : null,
21
+ tmpl: null,
22
+ parent: parentItem || null,
23
+ nodes: [],
24
+ calls: tiCalls,
25
+ nest: tiNest,
26
+ wrap: tiWrap,
27
+ html: tiHtml,
28
+ update: tiUpdate
29
+ };
30
+ if ( options ) {
31
+ jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
32
+ }
33
+ if ( fn ) {
34
+ // Build the hierarchical content to be used during insertion into DOM
35
+ newItem.tmpl = fn;
36
+ newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
37
+ newItem.key = ++itemKey;
38
+ // Keep track of new template item, until it is stored as jQuery Data on DOM element
39
+ (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
40
+ }
41
+ return newItem;
42
+ }
43
+
44
+ // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
45
+ jQuery.each({
46
+ appendTo: "append",
47
+ prependTo: "prepend",
48
+ insertBefore: "before",
49
+ insertAfter: "after",
50
+ replaceAll: "replaceWith"
51
+ }, function( name, original ) {
52
+ jQuery.fn[ name ] = function( selector ) {
53
+ var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
54
+ parent = this.length === 1 && this[0].parentNode;
55
+
56
+ appendToTmplItems = newTmplItems || {};
57
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
58
+ insert[ original ]( this[0] );
59
+ ret = this;
60
+ } else {
61
+ for ( i = 0, l = insert.length; i < l; i++ ) {
62
+ cloneIndex = i;
63
+ elems = (i > 0 ? this.clone(true) : this).get();
64
+ jQuery( insert[i] )[ original ]( elems );
65
+ ret = ret.concat( elems );
66
+ }
67
+ cloneIndex = 0;
68
+ ret = this.pushStack( ret, name, insert.selector );
69
+ }
70
+ tmplItems = appendToTmplItems;
71
+ appendToTmplItems = null;
72
+ jQuery.tmpl.complete( tmplItems );
73
+ return ret;
74
+ };
75
+ });
76
+
77
+ jQuery.fn.extend({
78
+ // Use first wrapped element as template markup.
79
+ // Return wrapped set of template items, obtained by rendering template against data.
80
+ tmpl: function( data, options, parentItem ) {
81
+ return jQuery.tmpl( this[0], data, options, parentItem );
82
+ },
83
+
84
+ // Find which rendered template item the first wrapped DOM element belongs to
85
+ tmplItem: function() {
86
+ return jQuery.tmplItem( this[0] );
87
+ },
88
+
89
+ // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
90
+ template: function( name ) {
91
+ return jQuery.template( name, this[0] );
92
+ },
93
+
94
+ domManip: function( args, table, callback, options ) {
95
+ if ( args[0] && jQuery.isArray( args[0] )) {
96
+ var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
97
+ while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
98
+ if ( tmplItem && cloneIndex ) {
99
+ dmArgs[2] = function( fragClone ) {
100
+ // Handler called by oldManip when rendered template has been inserted into DOM.
101
+ jQuery.tmpl.afterManip( this, fragClone, callback );
102
+ };
103
+ }
104
+ oldManip.apply( this, dmArgs );
105
+ } else {
106
+ oldManip.apply( this, arguments );
107
+ }
108
+ cloneIndex = 0;
109
+ if ( !appendToTmplItems ) {
110
+ jQuery.tmpl.complete( newTmplItems );
111
+ }
112
+ return this;
113
+ }
114
+ });
115
+
116
+ jQuery.extend({
117
+ // Return wrapped set of template items, obtained by rendering template against data.
118
+ tmpl: function( tmpl, data, options, parentItem ) {
119
+ var ret, topLevel = !parentItem;
120
+ if ( topLevel ) {
121
+ // This is a top-level tmpl call (not from a nested template using {{tmpl}})
122
+ parentItem = topTmplItem;
123
+ tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
124
+ wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
125
+ } else if ( !tmpl ) {
126
+ // The template item is already associated with DOM - this is a refresh.
127
+ // Re-evaluate rendered template for the parentItem
128
+ tmpl = parentItem.tmpl;
129
+ newTmplItems[parentItem.key] = parentItem;
130
+ parentItem.nodes = [];
131
+ if ( parentItem.wrapped ) {
132
+ updateWrapped( parentItem, parentItem.wrapped );
133
+ }
134
+ // Rebuild, without creating a new template item
135
+ return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
136
+ }
137
+ if ( !tmpl ) {
138
+ return []; // Could throw...
139
+ }
140
+ if ( typeof data === "function" ) {
141
+ data = data.call( parentItem || {} );
142
+ }
143
+ if ( options && options.wrapped ) {
144
+ updateWrapped( options, options.wrapped );
145
+ }
146
+ ret = jQuery.isArray( data ) ?
147
+ jQuery.map( data, function( dataItem ) {
148
+ return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
149
+ }) :
150
+ [ newTmplItem( options, parentItem, tmpl, data ) ];
151
+ return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
152
+ },
153
+
154
+ // Return rendered template item for an element.
155
+ tmplItem: function( elem ) {
156
+ var tmplItem;
157
+ if ( elem instanceof jQuery ) {
158
+ elem = elem[0];
159
+ }
160
+ while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
161
+ return tmplItem || topTmplItem;
162
+ },
163
+
164
+ // Set:
165
+ // Use $.template( name, tmpl ) to cache a named template,
166
+ // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
167
+ // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
168
+
169
+ // Get:
170
+ // Use $.template( name ) to access a cached template.
171
+ // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
172
+ // will return the compiled template, without adding a name reference.
173
+ // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
174
+ // to $.template( null, templateString )
175
+ template: function( name, tmpl ) {
176
+ if (tmpl) {
177
+ // Compile template and associate with name
178
+ if ( typeof tmpl === "string" ) {
179
+ // This is an HTML string being passed directly in.
180
+ tmpl = buildTmplFn( tmpl );
181
+ } else if ( tmpl instanceof jQuery ) {
182
+ tmpl = tmpl[0] || {};
183
+ }
184
+ if ( tmpl.nodeType ) {
185
+ // If this is a template block, use cached copy, or generate tmpl function and cache.
186
+ tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
187
+ // Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space.
188
+ // This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x.
189
+ // To correct this, include space in tag: foo="${ x }" -> foo="value of x"
190
+ }
191
+ return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
192
+ }
193
+ // Return named compiled template
194
+ return name ? (typeof name !== "string" ? jQuery.template( null, name ):
195
+ (jQuery.template[name] ||
196
+ // If not in map, and not containing at least on HTML tag, treat as a selector.
197
+ // (If integrated with core, use quickExpr.exec)
198
+ jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
199
+ },
200
+
201
+ encode: function( text ) {
202
+ // Do HTML encoding replacing < > & and ' and " by corresponding entities.
203
+ return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
204
+ }
205
+ });
206
+
207
+ jQuery.extend( jQuery.tmpl, {
208
+ tag: {
209
+ "tmpl": {
210
+ _default: { $2: "null" },
211
+ open: "if($notnull_1){__=__.concat($item.nest($1,$2));}"
212
+ // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
213
+ // This means that {{tmpl foo}} treats foo as a template (which IS a function).
214
+ // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
215
+ },
216
+ "wrap": {
217
+ _default: { $2: "null" },
218
+ open: "$item.calls(__,$1,$2);__=[];",
219
+ close: "call=$item.calls();__=call._.concat($item.wrap(call,__));"
220
+ },
221
+ "each": {
222
+ _default: { $2: "$index, $value" },
223
+ open: "if($notnull_1){$.each($1a,function($2){with(this){",
224
+ close: "}});}"
225
+ },
226
+ "if": {
227
+ open: "if(($notnull_1) && $1a){",
228
+ close: "}"
229
+ },
230
+ "else": {
231
+ _default: { $1: "true" },
232
+ open: "}else if(($notnull_1) && $1a){"
233
+ },
234
+ "html": {
235
+ // Unecoded expression evaluation.
236
+ open: "if($notnull_1){__.push($1a);}"
237
+ },
238
+ "=": {
239
+ // Encoded expression evaluation. Abbreviated form is ${}.
240
+ _default: { $1: "$data" },
241
+ open: "if($notnull_1){__.push($.encode($1a));}"
242
+ },
243
+ "!": {
244
+ // Comment tag. Skipped by parser
245
+ open: ""
246
+ }
247
+ },
248
+
249
+ // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
250
+ complete: function( items ) {
251
+ newTmplItems = {};
252
+ },
253
+
254
+ // Call this from code which overrides domManip, or equivalent
255
+ // Manage cloning/storing template items etc.
256
+ afterManip: function afterManip( elem, fragClone, callback ) {
257
+ // Provides cloned fragment ready for fixup prior to and after insertion into DOM
258
+ var content = fragClone.nodeType === 11 ?
259
+ jQuery.makeArray(fragClone.childNodes) :
260
+ fragClone.nodeType === 1 ? [fragClone] : [];
261
+
262
+ // Return fragment to original caller (e.g. append) for DOM insertion
263
+ callback.call( elem, fragClone );
264
+
265
+ // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
266
+ storeTmplItems( content );
267
+ cloneIndex++;
268
+ }
269
+ });
270
+
271
+ //========================== Private helper functions, used by code above ==========================
272
+
273
+ function build( tmplItem, nested, content ) {
274
+ // Convert hierarchical content into flat string array
275
+ // and finally return array of fragments ready for DOM insertion
276
+ var frag, ret = content ? jQuery.map( content, function( item ) {
277
+ return (typeof item === "string") ?
278
+ // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
279
+ (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
280
+ // This is a child template item. Build nested template.
281
+ build( item, tmplItem, item._ctnt );
282
+ }) :
283
+ // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
284
+ tmplItem;
285
+ if ( nested ) {
286
+ return ret;
287
+ }
288
+
289
+ // top-level template
290
+ ret = ret.join("");
291
+
292
+ // Support templates which have initial or final text nodes, or consist only of text
293
+ // Also support HTML entities within the HTML markup.
294
+ ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
295
+ frag = jQuery( middle ).get();
296
+
297
+ storeTmplItems( frag );
298
+ if ( before ) {
299
+ frag = unencode( before ).concat(frag);
300
+ }
301
+ if ( after ) {
302
+ frag = frag.concat(unencode( after ));
303
+ }
304
+ });
305
+ return frag ? frag : unencode( ret );
306
+ }
307
+
308
+ function unencode( text ) {
309
+ // Use createElement, since createTextNode will not render HTML entities correctly
310
+ var el = document.createElement( "div" );
311
+ el.innerHTML = text;
312
+ return jQuery.makeArray(el.childNodes);
313
+ }
314
+
315
+ // Generate a reusable function that will serve to render a template against data
316
+ function buildTmplFn( markup ) {
317
+ return new Function("jQuery","$item",
318
+ // Use the variable __ to hold a string array while building the compiled template. (See https://github.com/jquery/jquery-tmpl/issues#issue/10).
319
+ "var $=jQuery,call,__=[],$data=$item.data;" +
320
+
321
+ // Introduce the data as local variables using with(){}
322
+ "with($data){__.push('" +
323
+
324
+ // Convert the template into pure JavaScript
325
+ jQuery.trim(markup)
326
+ .replace( /([\\'])/g, "\\$1" )
327
+ .replace( /[\r\t\n]/g, " " )
328
+ .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
329
+ .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
330
+ function( all, slash, type, fnargs, target, parens, args ) {
331
+ var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
332
+ if ( !tag ) {
333
+ throw "Unknown template tag: " + type;
334
+ }
335
+ def = tag._default || [];
336
+ if ( parens && !/\w$/.test(target)) {
337
+ target += parens;
338
+ parens = "";
339
+ }
340
+ if ( target ) {
341
+ target = unescape( target );
342
+ args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
343
+ // Support for target being things like a.toLowerCase();
344
+ // In that case don't call with template item as 'this' pointer. Just evaluate...
345
+ expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
346
+ exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
347
+ } else {
348
+ exprAutoFnDetect = expr = def.$1 || "null";
349
+ }
350
+ fnargs = unescape( fnargs );
351
+ return "');" +
352
+ tag[ slash ? "close" : "open" ]
353
+ .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
354
+ .split( "$1a" ).join( exprAutoFnDetect )
355
+ .split( "$1" ).join( expr )
356
+ .split( "$2" ).join( fnargs || def.$2 || "" ) +
357
+ "__.push('";
358
+ }) +
359
+ "');}return __;"
360
+ );
361
+ }
362
+ function updateWrapped( options, wrapped ) {
363
+ // Build the wrapped content.
364
+ options._wrap = build( options, true,
365
+ // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
366
+ jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
367
+ ).join("");
368
+ }
369
+
370
+ function unescape( args ) {
371
+ return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
372
+ }
373
+ function outerHtml( elem ) {
374
+ var div = document.createElement("div");
375
+ div.appendChild( elem.cloneNode(true) );
376
+ return div.innerHTML;
377
+ }
378
+
379
+ // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
380
+ function storeTmplItems( content ) {
381
+ var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
382
+ for ( i = 0, l = content.length; i < l; i++ ) {
383
+ if ( (elem = content[i]).nodeType !== 1 ) {
384
+ continue;
385
+ }
386
+ elems = elem.getElementsByTagName("*");
387
+ for ( m = elems.length - 1; m >= 0; m-- ) {
388
+ processItemKey( elems[m] );
389
+ }
390
+ processItemKey( elem );
391
+ }
392
+ function processItemKey( el ) {
393
+ var pntKey, pntNode = el, pntItem, tmplItem, key;
394
+ // Ensure that each rendered template inserted into the DOM has its own template item,
395
+ if ( (key = el.getAttribute( tmplItmAtt ))) {
396
+ while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
397
+ if ( pntKey !== key ) {
398
+ // The next ancestor with a _tmplitem expando is on a different key than this one.
399
+ // So this is a top-level element within this template item
400
+ // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
401
+ pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
402
+ if ( !(tmplItem = newTmplItems[key]) ) {
403
+ // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
404
+ tmplItem = wrappedItems[key];
405
+ tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
406
+ tmplItem.key = ++itemKey;
407
+ newTmplItems[itemKey] = tmplItem;
408
+ }
409
+ if ( cloneIndex ) {
410
+ cloneTmplItem( key );
411
+ }
412
+ }
413
+ el.removeAttribute( tmplItmAtt );
414
+ } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
415
+ // This was a rendered element, cloned during append or appendTo etc.
416
+ // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
417
+ cloneTmplItem( tmplItem.key );
418
+ newTmplItems[tmplItem.key] = tmplItem;
419
+ pntNode = jQuery.data( el.parentNode, "tmplItem" );
420
+ pntNode = pntNode ? pntNode.key : 0;
421
+ }
422
+ if ( tmplItem ) {
423
+ pntItem = tmplItem;
424
+ // Find the template item of the parent element.
425
+ // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
426
+ while ( pntItem && pntItem.key != pntNode ) {
427
+ // Add this element as a top-level node for this rendered template item, as well as for any
428
+ // ancestor items between this item and the item of its parent element
429
+ pntItem.nodes.push( el );
430
+ pntItem = pntItem.parent;
431
+ }
432
+ // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
433
+ delete tmplItem._ctnt;
434
+ delete tmplItem._wrap;
435
+ // Store template item as jQuery data on the element
436
+ jQuery.data( el, "tmplItem", tmplItem );
437
+ }
438
+ function cloneTmplItem( key ) {
439
+ key = key + keySuffix;
440
+ tmplItem = newClonedItems[key] =
441
+ (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
442
+ }
443
+ }
444
+ }
445
+
446
+ //---- Helper functions for template item ----
447
+
448
+ function tiCalls( content, tmpl, data, options ) {
449
+ if ( !content ) {
450
+ return stack.pop();
451
+ }
452
+ stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
453
+ }
454
+
455
+ function tiNest( tmpl, data, options ) {
456
+ // nested template, using {{tmpl}} tag
457
+ return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
458
+ }
459
+
460
+ function tiWrap( call, wrapped ) {
461
+ // nested template, using {{wrap}} tag
462
+ var options = call.options || {};
463
+ options.wrapped = wrapped;
464
+ // Apply the template, which may incorporate wrapped content,
465
+ return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
466
+ }
467
+
468
+ function tiHtml( filter, textOnly ) {
469
+ var wrapped = this._wrap;
470
+ return jQuery.map(
471
+ jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
472
+ function(e) {
473
+ return textOnly ?
474
+ e.innerText || e.textContent :
475
+ e.outerHTML || outerHtml(e);
476
+ });
477
+ }
478
+
479
+ function tiUpdate() {
480
+ var coll = this.nodes;
481
+ jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
482
+ jQuery( coll ).remove();
483
+ }
484
+ })( jQuery );
apps/jquery-tmpl/jquery.tmpl.min.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery Templates Plugin 1.0.0pre
3
+ * http://github.com/jquery/jquery-tmpl
4
+ * Requires jQuery 1.4.2
5
+ *
6
+ * Copyright Software Freedom Conservancy, Inc.
7
+ * Dual licensed under the MIT or GPL Version 2 licenses.
8
+ * http://jquery.org/license
9
+ */
10
+ (function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},i=0,c=0,l=[];function g(g,d,h,e){var c={data:e||(e===0||e===false)?e:d?d.data:{},_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};g&&a.extend(c,g,{nodes:[],parent:d});if(h){c.tmpl=h;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++i;(l.length?f:b)[i]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h<m;h++){c=h;k=(h>0?this.clone(true):this).get();a(i[h])[d](k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,m,k){if(d[0]&&a.isArray(d[0])){var g=a.makeArray(arguments),h=d[0],j=h.length,i=0,f;while(i<j&&!(f=a.data(h[i++],"tmplItem")));if(f&&c)g[2]=function(b){a.tmpl.afterManip(this,b,k)};r.apply(this,g)}else r.apply(this,arguments);c=0;!e&&a.tmpl.complete(b);return this}});a.extend({tmpl:function(d,h,e,c){var i,k=!c;if(k){c=p;d=a.template[d]||a.template(null,d);f={}}else if(!d){d=c.tmpl;b[c.key]=c;c.nodes=[];c.wrapped&&n(c,c.wrapped);return a(j(c,null,c.tmpl(a,c)))}if(!d)return[];if(typeof h==="function")h=h.call(c||{});e&&e.wrapped&&n(e,e.wrapped);i=a.isArray(h)?a.map(h,function(a){return a?g(e,c,d,a):null}):[g(e,c,d,h)];return k?a(j(c,null,i)):i},tmplItem:function(b){var c;if(b instanceof a)b=b[0];while(b&&b.nodeType===1&&!(c=a.data(b,"tmplItem"))&&(b=b.parentNode));return c||p},template:function(c,b){if(b){if(typeof b==="string")b=o(b);else if(b instanceof a)b=b[0]||{};if(b.nodeType)b=a.data(b,"tmpl")||a.data(b,"tmpl",o(b.innerHTML));return typeof c==="string"?(a.template[c]=b):b}return c?typeof c!=="string"?a.template(null,c):a.template[c]||a.template(null,q.test(c)?c:a(c)):null},encode:function(a){return(""+a).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){__=__.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(__,$1,$2);__=[];",close:"call=$item.calls();__=call._.concat($item.wrap(call,__));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){__.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){__.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function j(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:j(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=k(c).concat(b);if(d)b=b.concat(k(d))});return b?b:k(c)}function k(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,__=[],$data=$item.data;with($data){__.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,k,g,b,c,d){var j=a.tmpl.tag[k],i,e,f;if(!j)throw"Unknown template tag: "+k;i=j._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=h(b);d=d?","+h(d)+")":c?")":"";e=c?b.indexOf(".")>-1?b+h(c):"("+b+").call($item"+d:b;f=c?e:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else f=e=i.$1||"null";g=h(g);return"');"+j[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(f).split("$1").join(e).split("$2").join(g||i.$2||"")+"__.push('"})+"');}return __;")}function n(c,b){c._wrap=j(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function h(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,h;for(e=0,p=o.length;e<p;e++){if((k=o[e]).nodeType!==1)continue;j=k.getElementsByTagName("*");for(h=j.length-1;h>=0;h--)m(j[h]);m(k)}function m(j){var p,h=j,k,e,m;if(m=j.getAttribute(d)){while(h.parentNode&&(h=h.parentNode).nodeType===1&&!(p=h.getAttribute(d)));if(p!==m){h=h.parentNode?h.nodeType===11?0:h.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[h]||f[h]);e.key=++i;b[i]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;h=a.data(j.parentNode,"tmplItem");h=h?h.key:0}if(e){k=e;while(k&&k.key!=h){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery);
apps/jquery-tmpl/jquery.tmplPlus.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * tmplPlus.js: for jQuery Templates Plugin 1.0.0pre
3
+ * Additional templating features or support for more advanced/less common scenarios.
4
+ * Requires jquery.tmpl.js
5
+ * http://github.com/jquery/jquery-tmpl
6
+ *
7
+ * Copyright Software Freedom Conservancy, Inc.
8
+ * Dual licensed under the MIT or GPL Version 2 licenses.
9
+ * http://jquery.org/license
10
+ */
11
+ (function (jQuery) {
12
+ var oldComplete = jQuery.tmpl.complete, oldManip = jQuery.fn.domManip;
13
+
14
+ // Override jQuery.tmpl.complete in order to provide rendered event.
15
+ jQuery.tmpl.complete = function( tmplItems ) {
16
+ var tmplItem;
17
+ oldComplete( tmplItems);
18
+ for ( tmplItem in tmplItems ) {
19
+ tmplItem = tmplItems[tmplItem];
20
+ if ( tmplItem.addedTmplItems && jQuery.inArray( tmplItem, tmplItem.addedTmplItems ) === -1 ) {
21
+ tmplItem.addedTmplItems.push( tmplItem );
22
+ }
23
+ }
24
+ for ( tmplItem in tmplItems ) {
25
+ tmplItem = tmplItems[tmplItem];
26
+ // Raise rendered event
27
+ if ( tmplItem.rendered ) {
28
+ tmplItem.rendered( tmplItem );
29
+ }
30
+ }
31
+ };
32
+
33
+ jQuery.extend({
34
+ tmplCmd: function( command, data, tmplItems ) {
35
+ var retTmplItems = [], before;
36
+ function find( data, tmplItems ) {
37
+ var found = [], tmplItem, ti, tl = tmplItems.length, dataItem, di = 0, dl = data.length;
38
+ for ( ; di < dl; ) {
39
+ dataItem = data[di++];
40
+ for ( ti = 0; ti < tl; ) {
41
+ tmplItem = tmplItems[ti++];
42
+ if ( tmplItem.data === dataItem ) {
43
+ found.push( tmplItem );
44
+ }
45
+ }
46
+ }
47
+ return found;
48
+ }
49
+
50
+ data = jQuery.isArray( data ) ? data : [ data ];
51
+ switch ( command ) {
52
+ case "find":
53
+ return find( data, tmplItems );
54
+ case "replace":
55
+ data.reverse();
56
+ }
57
+ jQuery.each( tmplItems ? find( data, tmplItems ) : data, function( i, tmplItem ) {
58
+ coll = tmplItem.nodes;
59
+ switch ( command ) {
60
+ case "update":
61
+ tmplItem.update();
62
+ break;
63
+ case "remove":
64
+ jQuery( coll ).remove();
65
+ if ( tmplItems ) {
66
+ tmplItems.splice( jQuery.inArray( tmplItem, tmplItems ), 1 );
67
+ }
68
+ break;
69
+ case "replace":
70
+ before = before ?
71
+ jQuery( coll ).insertBefore( before )[0] :
72
+ jQuery( coll ).appendTo( coll[0].parentNode )[0];
73
+ retTmplItems.unshift( tmplItem );
74
+ }
75
+ });
76
+ return retTmplItems;
77
+ }
78
+ });
79
+
80
+ jQuery.fn.extend({
81
+ domManip: function (args, table, callback, options) {
82
+ var data = args[1], tmpl = args[0], dmArgs;
83
+ if ( args.length >= 2 && typeof data === "object" && !data.nodeType && !(data instanceof jQuery)) {
84
+ // args[1] is data, for a template.
85
+ dmArgs = jQuery.makeArray( arguments );
86
+
87
+ // Eval template to obtain fragment to clone and insert
88
+ dmArgs[0] = [ jQuery.tmpl( jQuery.template( tmpl ), data, args[2], args[3] ) ];
89
+
90
+ dmArgs[2] = function( fragClone ) {
91
+ // Handler called by oldManip when rendered template has been inserted into DOM.
92
+ jQuery.tmpl.afterManip( this, fragClone, callback );
93
+ };
94
+ return oldManip.apply( this, dmArgs );
95
+ }
96
+ return oldManip.apply( this, arguments );
97
+ }
98
+ });
99
+ })(jQuery);
apps/jquery-tmpl/jquery.tmplPlus.min.js ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * tmplPlus.js: for jQuery Templates Plugin 1.0.0pre
3
+ * Additional templating features or support for more advanced/less common scenarios.
4
+ * Requires jquery.tmpl.js
5
+ * http://github.com/jquery/jquery-tmpl
6
+ *
7
+ * Copyright Software Freedom Conservancy, Inc.
8
+ * Dual licensed under the MIT or GPL Version 2 licenses.
9
+ * http://jquery.org/license
10
+ */
11
+ (function (a) { var c = a.tmpl.complete, b = a.fn.domManip; a.tmpl.complete = function (d) { var b; c(d); for (b in d) { b = d[b]; b.addedTmplItems && a.inArray(b, b.addedTmplItems) === -1 && b.addedTmplItems.push(b) } for (b in d) { b = d[b]; b.rendered && b.rendered(b) } }; a.extend({ tmplCmd: function (f, b, c) { var e = [], d; function g(f, c) { for (var e = [], a, b, i = c.length, d, g = 0, h = f.length; g < h; ) { d = f[g++]; for (b = 0; b < i; ) { a = c[b++]; a.data === d && e.push(a) } } return e } b = a.isArray(b) ? b : [b]; switch (f) { case "find": return g(b, c); case "replace": b.reverse() } a.each(c ? g(b, c) : b, function (g, b) { coll = b.nodes; switch (f) { case "update": b.update(); break; case "remove": a(coll).remove(); c && c.splice(a.inArray(b, c), 1); break; case "replace": d = d ? a(coll).insertBefore(d)[0] : a(coll).appendTo(coll[0].parentNode)[0]; e.unshift(b) } }); return e } }); a.fn.extend({ domManip: function (c, i, f) { var e = c[1], g = c[0], d; if (c.length >= 2 && typeof e === "object" && !e.nodeType && !(e instanceof a)) { d = a.makeArray(arguments); d[0] = [a.tmpl(a.template(g), e, c[2], c[3])]; d[2] = function (b) { a.tmpl.afterManip(this, b, f) }; return b.apply(this, d) } return b.apply(this, arguments) } }) })(jQuery);
apps/jquery-tmpl/tests/core.js ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var testData = {
2
+ one: "first",
3
+ two: "second",
4
+ v: "test",
5
+ arr: ["AA","BB","CC"],
6
+ dict: {"leovinus":"this","scraliontis":"that","brobostigon":"other"},
7
+ fun: function () {
8
+ return 'RETURNED';
9
+ },
10
+ html: '<a>'
11
+ };
12
+
13
+ var R = function ( tmpl, data ) {
14
+ try {
15
+ return jQuery.tmpl( tmpl, data ).text();
16
+ }
17
+ catch ( e ) {
18
+ if ( typeof e === 'string' ) {
19
+ return 'ERROR: ' + e;
20
+ }
21
+ return e;
22
+ }
23
+ };
24
+
25
+ function test_handler( test_name, res, exp ) {
26
+ var is_err = ($.isFunction(exp) && exp.prototype instanceof Error);
27
+ if ( is_err && res instanceof exp ) {
28
+ ok( res instanceof exp, test_name );
29
+ }
30
+ else {
31
+ same( res, exp, test_name );
32
+ }
33
+ }
34
+
35
+ // these are used throughout to test if tag blocks suppress them
36
+ jQuery.tmpl.tag.syntax_error = { open: "throw SyntaxError('test syntax error');" };
37
+ jQuery.tmpl.tag.reference_error = { open: "throw ReferenceError('test reference error');" };
38
+ jQuery.tmpl.tag.type_error = { open: "throw TypeError('test type error');" };
39
+
40
+ module("Basics");
41
+
42
+
43
+ test("Basic Function", function() {
44
+ test_handler( 'plain text passes through untouched', R('lorem ipsum', testData), 'lorem ipsum' );
45
+ // TODO fixme
46
+ //test_handler( 'whitespace is left untouched', R('\n\tlorem\n\n\tipsum \t', testData), '\n\tlorem\n\n\tipsum \t' );
47
+ test_handler( 'simple variable output', R("${ one }", testData), "first" );
48
+
49
+ // throw errors with incomplete syntax
50
+ test_handler( 'multi word variable tag', R("${ a b c }}"), SyntaxError );
51
+ test_handler( "_ (underscore) cannot by used by data", R('${ _ }', {'_':'foo'}), TypeError );
52
+ test_handler( "$ cannot be used by data", R('${ $ }', {'$':'foo'}), TypeError );
53
+
54
+ });
55
+
56
+ // test errors are passed back correctly
57
+ test("Error Passing", function(){
58
+ test_handler( 'syntax', R("{{syntax_error }}", testData), SyntaxError );
59
+ test_handler( 'reference', R("{{reference_error }}", testData), ReferenceError );
60
+ test_handler( 'type', R("{{type_error }}", testData), TypeError );
61
+ });
62
+
63
+ // newlines should work because: ${ foo + "\n" } and they have whitespace management benefits
64
+ test("Newlines / Escaping", function(){
65
+ test_handler( "newlines do not kill tags", R('${\n \none\n }', testData), 'first');
66
+ // TODO fixme
67
+ //test_handler( "newlines in strings don't kill tags", R('${ "on\ne" }', testData), 'on\ne' );
68
+ //test_handler( "returns do not kill tags", R('${\r \r\none\r\n }', testData), 'first');
69
+ //test_handler( "returns in strings don't kill tags", R('${ "on\re" }', testData), 'on\re' );
70
+ //test_handler( "slashes in strings don't kill tags", R('${ "on\\e" }', testData), 'on\\e');
71
+ //test_handler( "newlines don't kill parsing", R('a\nb\nc${ 8 }.'), 'a\nb\nc8.');
72
+ });
73
+
74
+ test("Empty Tag", function() {
75
+ // TODO fixme
76
+ //test_handler( 'default', R("{{}}", testData), '{{}}' );
77
+ //test_handler( 'with whitespace', R("{{ }}"), '{{ }}' );
78
+ //test_handler( 'with tabs whitespace', R("{{\t\t}}"), '{{\t\t}}' );
79
+ });
80
+
81
+ test("Incorrect Nesting", function() {
82
+ test_handler( 'default', R("{{if 1}}{{if 1}}{{/if}}", testData), SyntaxError );
83
+ test_handler( 'extra /if', R("{{if 1}}{{/if}}{{/if}}", testData), SyntaxError );
84
+ test_handler( 'but terminated', R("{{if 1}}{{each arr}}{{/if}}{{/each}}", testData), SyntaxError );
85
+ });
86
+
87
+ test("Ignore Malformed Tags", function() {
88
+ test_handler( 'a {{one } b', R("a {{one } b", testData), 'a {{one } b' );
89
+ test_handler( 'first} {{second }', R("${ one }} {{two }", testData), 'first} {{two }' );
90
+ test_handler( '{{one }', R('{{one }', testData), '{{one }' );
91
+ });
92
+
93
+ // reserved words
94
+ test("Reserved Words", function(){
95
+ // TODO fixme
96
+ //test_handler( "Disallow new operator", R('${ new Object() }',{}), SyntaxError );
97
+ //test_handler( "Disallow delete operator", R('${ delete a }',{a:1}), SyntaxError );
98
+ test_handler( "Disallow function operator", R('${ function(){} }',{}), SyntaxError );
99
+ test_handler( "Disallow return", R('${ return a }',{a:1}), SyntaxError );
100
+ test_handler( "Disallow for", R('${ for a }',{a:1}), SyntaxError );
101
+ test_handler( "Disallow do/while", R('${ do{ a }while(a) }',{a:1}), SyntaxError );
102
+ test_handler( "Disallow if", R('${ if a }',{a:1}), SyntaxError );
103
+ test_handler( "Disallow try/catch", R('${ try{b.s}catch(e){} }',{a:1}), SyntaxError );
104
+ test_handler( "Disallow return keyword", R('${ return a }',{a:1}), SyntaxError );
105
+ test_handler( "Disallow with keyword", R('${ with (s) }',{a:1}), SyntaxError );
106
+ test_handler( "Disallow throw keyword", R('${ throw "foo" }',{a:1}), SyntaxError );
107
+ });
108
+
109
+ // these tests are a bit awkward because caching is done in $.render, not $.tmpl
110
+ test("Caching via $.template() and .template()", function() {
111
+ $.template('nametmpl', '<span>name: ${ v }</span>' );
112
+ test_handler( "using a named template", $.tmpl('nametmpl', testData).text(), 'name: test' );
113
+
114
+ var $elm = $( "<span>name: ${ v }</span>" );
115
+ $elm.template('nametmpl2');
116
+ test_handler( "using a named template created from a node", $.tmpl('nametmpl2', testData).text(), 'name: test' );
117
+ });
118
+
119
+ test("Bracketed Accessors", function(){
120
+ test_handler( "foo[\"bar\"]", R('${ foo["bar"] }',{foo:{bar:'baz'}}), 'baz' );
121
+ test_handler( "foo['bar']", R("${ foo['bar'] }",{foo:{bar:'baz'}}), 'baz' );
122
+ });
123
+
124
+ test("Escaping", function(){
125
+ // TODO fixme
126
+ //test_handler( 'echoing escapes html', R("${ 'foo<div>bar</div>baz' }"), 'foo&lt;div&gt;bar&lt;/div&gt;baz' );
127
+ //test_handler( 'echoing escapes html (lookup)', R("${ r }", {r:'foo<div>bar</div>baz'}), 'foo&lt;div&gt;bar&lt;/div&gt;baz' );
128
+ //test_handler( 'echoing escapes ampersands 1', R("${ '&' }"), '&amp;' );
129
+ //test_handler( 'echoing escapes ampersands 2', R("${ '&amp;' }"), '&amp;amp;' );
130
+ //test_handler( 'echoing escapes & < >', R("${ '-<&>-<&>-' }"), '-&lt;&amp;&gt;-&lt;&amp;&gt;-' );
131
+ });
132
+
133
+ test("Comments", function() {
134
+ test_handler( "comments are removed", R('A{{! comments test }}B', testData), "AB" );
135
+ test_handler( "comments are removed (2)", R('{{! inky }}foo{{! blinky }}', testData), 'foo' );
136
+ // TODO fixme
137
+ return;
138
+ test_handler( "comments may include string of comments", R('A{{! comments "}}" test }}B', testData), "AB" );
139
+ test_handler( "comments cannot nest other comments", R('A{# C{# E #}D #}B', testData), "AD #}B" );
140
+ test_handler( "comments may include strings with escapes (double)", R('A{# comments "str\"ing" test #}B', testData), "AB" );
141
+ test_handler( "comments may include strings with escapes (single)", R("A{# comments 'str\'ing' test #}B", testData), "AB" );
142
+ test_handler( "comments may include tags", R("A{# {{= v }} #}B", testData), "AB" );
143
+ test_handler( "comments may span lines", R("A{# \ncomments test\n #}B", testData), "AB" );
144
+
145
+ test_handler( "comments may contain invalid content (invalid tag)", R('1{{! {{ INVALID_TAG }} }}2', testData), '12' );
146
+ test_handler( "comments may contain invalid content (stray end tag)", R('1{{! {{/if}} }}2', testData), '12' );
147
+ test_handler( "comments may contain invalid content (stray else)", R('1{{! {{else}} }}2', testData), '12' );
148
+ test_handler( "comments may contain invalid content (invalid javascript)", R('1{{! {{if ...}} }}2', testData), '12' );
149
+
150
+ });
151
+
152
+ test("Variables", function() {
153
+
154
+ test_handler( "variable replacement", R('${ one }', testData), "first" );
155
+ test_handler( "many variables work", R('${ one }/${ two }', testData), "first/second" );
156
+ test_handler( "alternative variable syntax", R('${ one }', testData), "first" );
157
+ test_handler( "many variables work with alt syntax", R('${ one }/${ two }', testData), "first/second" );
158
+
159
+ test_handler( "basic string output (double)", R('${ "string" }', testData), "string" );
160
+ test_handler( "basic string output (single)", R("${ 'string' }", testData), "string" );
161
+ test_handler( "string quote escapes (double)", R('${ "str\\"i\\"ng" }', testData), 'str"i"ng' );
162
+ test_handler( "string quote escapes (single)", R("${ 'str\\'i\\'ng' }", testData), "str'i'ng" );
163
+
164
+ // TODO fixme
165
+ //test_handler( "string output with tag", R('${ "\\{\\{ tag \\}\\}" }', testData), "{{ tag }}" );
166
+ //test_handler( "string output with end of tag", R('${ "\\}\\}" }', testData), "}}" );
167
+
168
+ test_handler( 'empty variable tag (with tabs whitespace)', R("{{=\t\t}}", "self"), 'self' );
169
+ test_handler( 'empty variable tag', R("{{= }}", "self"), 'self' );
170
+ test_handler( 'empty variable tag (with space)', R("{{=}}", "self"), 'self' );
171
+
172
+ test_handler( "variable lookup error suppression", R('${ is_undefined }', testData), '' );
173
+ // TODO fixme
174
+ //test_handler( "variable lookup error suppression (with member)", R('${ is_undefined.member }', testData), '' );
175
+
176
+ test_handler( "variable and text (1)", R('A${ one }', testData), 'Afirst' );
177
+ test_handler( "variable and text (2)", R('${ one }B', testData), 'firstB' );
178
+ test_handler( "variable and text (3)", R('A${ one }B', testData), 'AfirstB' );
179
+
180
+ test_handler( "lookups work for submembers", R('${ a.b.c }', {a:{b:{c:"abc"}}}), 'abc' );
181
+ test_handler( "error suppression works for submembers", R('${ a.b.c }', {a:{b:{c:"abc"}}}), 'abc' );
182
+
183
+ test_handler( "functions can be called with in tags", R('${ foo() }', { foo:function(s){ return "bar"; }}), 'bar' );
184
+ test_handler( "functions pass strings correctly", R('${ foo("bar") }', { foo:function(s){ return s; }}), 'bar' );
185
+ test_handler( "functions pass arguments correctly", R('${ foo(bar) }', { foo:function(s){ return s; }, 'bar':'baz'}), 'baz' );
186
+
187
+ var cls = {
188
+ toString:function () {return 'S';},
189
+ toValue:function () {return 'V';}
190
+ }
191
+ test_handler( 'variables use toString, not toValue', R("${ foo }",{foo:cls}), 'S' );
192
+
193
+ test_handler( 'comma passes variables correctly', R("${ dot,dot,comma,dash }",{dot:'.','comma':',','dash':'-'}), '-' );
194
+
195
+ // TODO fixme
196
+ // @borgar says: I don't like this: it should use foo() to be consistant with foo().bar()
197
+ test_handler( 'variable gets called if it is callable', R("${ fun }", testData), 'RETURNED' );
198
+ test_handler( 'last variable in sequence gets called if it is callable', R("${ obj.fun }",{obj: testData}), 'RETURNED' );
199
+
200
+ var cls = {
201
+ foo: function () {
202
+ return { bar: function () {return 'BAZ'; } };
203
+ }
204
+ }
205
+ test_handler( 'member functions in a sequence don\'t get called', R("${ foo.bar }", cls), '' );
206
+
207
+ });
208
+
209
+ test("Falsy Values", function(){
210
+ test_handler( "(0)", R('${ 0 }'), '0' );
211
+ test_handler( "(false)", R('${ false }'), 'false' );
212
+ test_handler( "(null)", R('${ zero }'), '' ); // it's debatable what we want here
213
+ test_handler( "(undefined)", R('${ undefined }'), '' );
214
+ test_handler( "(\"\")", R('${ "" }'), '' );
215
+ test_handler( "('')", R("${ '' }"), '' );
216
+ });
217
+
218
+ test("Falsy Lookups", function(){
219
+ test_handler( "(false)", R('${ zero }', {zero: 0}), '0' );
220
+ test_handler( "(false)", R('${ zero }', {zero: false}), 'false' );
221
+ test_handler( "(null)", R('${ zero }', {zero: null}), '' ); // it's debatable what we want here
222
+ test_handler( "(undefined)", R('${ zero }', {zero: undefined}), '' );
223
+ test_handler( "('')", R('${ zero }', {zero: ""}), '' );
224
+ });
225
+
226
+ test("Javascript Operations", function(){
227
+ test_handler( "string concatination", R('${ one + "foo" }', testData), "firstfoo" );
228
+ test_handler( "adding", R('${ 1 + 5 }', testData), "6" );
229
+ test_handler( "subtracting", R('${ 9 - 5 }', testData), "4" );
230
+ test_handler( "modulo", R('${ 5 % 2 }', testData), "1" );
231
+ test_handler( "unary minus", R('${ -n }',{n:10}), "-10" );
232
+ test_handler( "unary plus", R('${ +n }',{n:"10"}), "10" );
233
+
234
+ test_handler( "in operator", R('${ "bar" in foo }',{foo:{bar:'baz'}}), "true" );
235
+ test_handler( "instanceof operator", R('${ foo instanceof Date }',{foo:new Date()}), "true" );
236
+ test_handler( "typeof operator", R('${ typeof "str" }',{}), "string" );
237
+
238
+ test_handler( "bitwise AND", R('${ n & 1 }',{n:5}), "1" );
239
+ test_handler( "bitwise OR", R('${ n | 1 }',{n:4}), "5" );
240
+ test_handler( "bitwise XOR", R('${ n ^ 1 }',{n:5}), "4" );
241
+ test_handler( "bitwise NOT", R('${ ~n }',{n:5}), "-6" );
242
+ test_handler( "left shift", R('${ n << 1 }',{n:5}), "10" );
243
+ test_handler( "right shift", R('${ n >> 1 }',{n:5}), "2" );
244
+ test_handler( "zero-fill right shift", R('${ n >>> 1 }',{n:5}), "2" );
245
+
246
+ test_handler( "comparing ==", R('${ 1 == 5 }', testData), "false" );
247
+ test_handler( "comparing !=", R('${ 1 != 5 }', testData), "true" );
248
+ test_handler( "comparing ===", R('${ 5 === 5 }', testData), "true" );
249
+ test_handler( "comparing !==", R('${ 5 !== 5 }', testData), "false" );
250
+ test_handler( "comparing >=", R('${ 1 >= 5 }', testData), "false" );
251
+ test_handler( "comparing >", R('${ 1 > 5 }', testData), "false" );
252
+ test_handler( "comparing <=", R('${ 1 <= 5 }', testData), "true" );
253
+ test_handler( "comparing <", R('${ 1 < 5 }', testData), "true" );
254
+ test_handler( "Logical OR", R('${ zero || "FALSY" }',{ zero: 0 }), "FALSY" );
255
+ test_handler( "Logical AND", R('${ zero && "TRUEY" }',{ zero: 1 }), "TRUEY" );
256
+ test_handler( "Conditional Operator", R('${ zero ? "zero" : "other" }',{ zero: 1 }), "zero" );
257
+ test_handler( "Unary logical NOT", R('${ !zero }',{ zero: 1 }), "false" );
258
+
259
+ test_handler( "Single-Quoted Strings", R("${ 'test' }",{}), "test" );
260
+ test_handler( "Single-Quoted Comparison", R("${ 'test' == testvar }",{ testvar: 'test' }), "true" );
261
+ });
262
+
263
+ test("Disallowed / Illegal", function(){
264
+ // TODO fixme
265
+ /*
266
+ test_handler( "Disallow incremental assignment", R('${ a += 1 }', {a:1}), SyntaxError );
267
+ test_handler( "Disallow decremental assignment", R('${ a -= 1 }', {a:1}), SyntaxError );
268
+ test_handler( "Disallow multiply assignment", R('${ a *= 1 }', {a:1}), SyntaxError );
269
+ test_handler( "Disallow division assignment", R('${ a /= 1 }', {a:1}), SyntaxError );
270
+ test_handler( "Disallow left shift assignment", R('${ a <<= 1 }', {a:1}), SyntaxError );
271
+ test_handler( "Disallow right shift assignment", R('${ a >>= 1 }', {a:1}), SyntaxError );
272
+ test_handler( "Disallow zero-fill right shift assignment", R('${ a >>>= 1 }', {a:1}), SyntaxError );
273
+ test_handler( "Disallow bitwise AND assignment", R('${ a &= 1 }', {a:1}), SyntaxError );
274
+ test_handler( "Disallow bitwise OR assignment", R('${ a |= 1 }', {a:1}), SyntaxError );
275
+ test_handler( "Disallow bitwise XOR assignment", R('${ a ^= 1 }', {a:1}), SyntaxError );
276
+
277
+ test_handler( "Disallow literal object creation", R('${ { a:"a"} }', {a:1}), SyntaxError );
278
+ test_handler( "Disallow literal array creation", R('${ [1,2,3] }', {a:1}), SyntaxError );
279
+
280
+ test_handler( "Disallow decrement", R('${ --a }',{a:1}), SyntaxError );
281
+ test_handler( "Disallow assignments", R('${ (a = 2) }',{a:1}), SyntaxError );
282
+ */
283
+ });
284
+
285
+ module("Commands");
286
+
287
+ test("Create New Command", function(){
288
+ $.getText = function ( str ) { return str.toUpperCase(); };
289
+ $.tmpl.tag.trans = { open: "_.push($.getText($1));" };
290
+ test_handler( "creating new command works", R('{{trans "translate" }}'), 'TRANSLATE' );
291
+ $.tmpl.tag._ = $.tmpl.tag.trans;
292
+ test_handler( "_ can by assigned a command", R('{{_ "translate" }}', {}), 'TRANSLATE' );
293
+ delete $.getText;
294
+ delete $.tmpl.tag.trans;
295
+ delete $.tmpl.tag._;
296
+ });
297
+
298
+ test("Each {{ each }}", function() {
299
+
300
+ test_handler( "loop", R('{{each arr}}${ $index }:${ this }/{{/each}}', testData), '0:AA/1:BB/2:CC/' );
301
+ test_handler( "loop", R('{{each arr}}${ $index }:${ $value }/{{/each}}', testData), '0:AA/1:BB/2:CC/' );
302
+ test_handler( "loop", R('{{each(i, item) arr}}${ i }:${ item }/{{/each }}', testData), '0:AA/1:BB/2:CC/' );
303
+ test_handler( "loop", R('{{each arr}}${ $index }:${ this }/{{/each }}', testData), '0:AA/1:BB/2:CC/' );
304
+
305
+ // TODO fixme
306
+ //test_handler( "first", R('{{each dict}}${ $index }:{{if $first }}first{{else}}!first{{/if }}/{{/each }}', testData), 'leovinus:first/scraliontis:!first/brobostigon:!first/' );
307
+ //test_handler( "first", R('{{each dict}}{{if !$first }}, {{/if }}${ $index }:${ this }}{{/each }}', testData), 'leovinus:this, scraliontis:that, brobostigon:other' );
308
+
309
+ // TODO fixme
310
+ //test_handler("html content", R('{{each arr}}<a>${ $index }</a>{{/each}}', testData), '<a>0</a><a>1</a><a>2</a>' );
311
+ //test_handler("html content", R('{{each arr}}<a>${ this }</a>{{/each}}', testData), '<a>AA</a><a>BB</a><a>CC</a>' );
312
+ //test_handler("html content", R('{{each this}}<a>${ data }</a>{{/each}}', [{data: 0}, {data: 1}, {data: 2}]), '<a>0</a><a>1</a><a>2</a>' );
313
+ //test_handler("html content with newlines", R('{{each this}}\n<a>${ data }</a>\n{{/each}}', [{data: 0}, {data: 1}, {data: 2}]), '\n<a>0</a>\n\n<a>1</a>\n\n<a>2</a>\n' );
314
+
315
+ test_handler( 'errors are passed back correctly (syntax)', R("{{each arr}}${ $i }{{syntax_error}}{{/each}}", testData), SyntaxError );
316
+ test_handler( 'errors are passed back correctly (reference)', R("{{each arr}}${ $i }{{reference_error}}{{/each}}", testData), ReferenceError );
317
+ test_handler( 'errors are passed back correctly (type)', R("{{each arr}}${ $i }{{type_error}}{{/each}}", testData), TypeError );
318
+
319
+ });
320
+
321
+ test("{{if}} and {{else}}", function() {
322
+ test_handler( "if:true", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:true }), 'TRUE' );
323
+ test_handler( "if:false", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:false }), 'FALSE' );
324
+ test_handler( "if:null", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:null }), 'FALSE' );
325
+ test_handler( "if:undefined", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:undefined }), 'FALSE' );
326
+ test_handler( "if:[]", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:{} }), 'TRUE' );
327
+ test_handler( "if:{}", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:[] }), 'TRUE' );
328
+ test_handler( "if:''", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:"" }), 'FALSE' );
329
+ test_handler( "if:A", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:"A" }), 'TRUE' );
330
+ test_handler( "if:0", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:0 }), 'FALSE' );
331
+ test_handler( "if:1", R('{{if a}}TRUE{{else}}FALSE{{/if}}', { a:1 }), 'TRUE' );
332
+
333
+ test_handler( "/if ignores following text", R('{{if a}}TRUE{{else}}FALSE{{/if a}}', { a:1 }), 'TRUE' );
334
+
335
+ test_handler( 'errors are passed back correctly (syntax)', R("{{if true}}{{syntax_error}}{{/if}}", testData), SyntaxError );
336
+ test_handler( 'errors are passed back correctly (reference)', R("{{if true}}{{reference_error}}{{/if}}", testData), ReferenceError );
337
+ test_handler( 'errors are passed back correctly (type)', R("{{if true}}{{type_error}}{{/if}}", testData), TypeError );
338
+
339
+ });
340
+
341
+ test("{{tmpl() template}}", function() {
342
+
343
+ jQuery.template('test', '${ "test text" }');
344
+ test_handler( "simple include", R('{{tmpl "test"}}'), 'test text' );
345
+
346
+ jQuery.template('test2', '{{each arr}}[${ $value }]-{{/each }}');
347
+ test_handler( "data access", R('{{tmpl "test2"}}', testData), '[AA]-[BB]-[CC]-' );
348
+
349
+ var nestedData = {foo: 'bar'};
350
+
351
+ jQuery.template('nested', '{{tmpl "nested0"}}');
352
+ jQuery.template('nested0', '${ foo }');
353
+
354
+ test_handler( "nested - 1 level", R('{{tmpl "nested"}}', nestedData), 'bar' );
355
+
356
+ jQuery.template('nested0', '{{tmpl "nested1"}}');
357
+ jQuery.template('nested1', '{{tmpl "nested2"}}');
358
+ jQuery.template('nested2', '${ foo }');
359
+
360
+ test_handler( "nested - 2 levels", R('{{tmpl "nested" }}', nestedData), 'bar' );
361
+
362
+ nestedData = {foo: {bar: {sweet: 1} } };
363
+ jQuery.template('nested2', '${ foo.bar.sweet }');
364
+
365
+ test_handler( "nested - 2 levels - complex data", R('{{tmpl "nested" }}', nestedData), '1' );
366
+
367
+ // TODO fixme
368
+ jQuery.template('test', '${ $index }');
369
+ //test_handler( "{{each}} index variable", R('{{each arr}}{{tmpl "test" }}{{/each}}', testData), '012' );
370
+
371
+ jQuery.template('test', '${ n }');
372
+ //test_handler( "{{each}} index variable", R('{{each(n, item) arr}}{{tmpl "test"}}{{/each}}', testData), '012' );
373
+
374
+ jQuery.template('test', '${ item }');
375
+ //test_handler( "{{each}} item variable", R('{{each(n, item) arr}}{{tmpl "test" }}{{/each}}', testData), 'AABBCC' );
376
+ });
377
+
378
+ test("Html Output Unecoded {{html }}", function(){
379
+ // TODO fixme
380
+ //test_handler("encoded", R('{{= html}}', testData), '&lt;a&gt;');
381
+ //test_handler("unencoded", R('{{html html}}', testData), '<a>');
382
+ });
383
+
384
+ module("Script Tag Caching");
385
+
386
+ test("Template Reuse", function(){
387
+ var template = $('#reuse'),
388
+ data = {data: 'pass1'};
389
+
390
+ var pass1 = template.tmpl(data).html();
391
+ data = {data: 'pass2'};
392
+ var pass2 = template.tmpl(data).html();
393
+
394
+ ok( "simple reuse test", pass1 == 'pass1' && pass2 == 'pass2' );
395
+ });
apps/jquery-tmpl/tests/index.html ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>jquery-tmpl unit tests</title>
6
+ <link rel="stylesheet" href="qunit.css" type="text/css" />
7
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
8
+ <script type="text/javascript" src="qunit.js"></script>
9
+ <script type="text/javascript" src="../jquery.tmpl.js"></script>
10
+ <script type="text/javascript" src="core.js"></script>
11
+ </head>
12
+ <body>
13
+ <script type="text/x-jquery-tmpl" id="reuse">
14
+ <a>{{= data}}</a>
15
+ </script>
16
+ <h1 id="qunit-header">jquery-tmpl unit tests</h1>
17
+ <h2 id="qunit-banner"></h2>
18
+ <div id="qunit-testrunner-toolbar"></div>
19
+ <h2 id="qunit-userAgent"></h2>
20
+ <ol id="qunit-tests"></ol>
21
+ </body>
22
+ </html>
apps/jquery-tmpl/tests/qunit.css ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Font Family and Sizes */
2
+
3
+ #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
4
+ font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
5
+ }
6
+
7
+ #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
8
+ #qunit-tests { font-size: smaller; }
9
+
10
+
11
+ /** Resets */
12
+
13
+ #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
14
+ margin: 0;
15
+ padding: 0;
16
+ }
17
+
18
+
19
+ /** Header */
20
+
21
+ #qunit-header {
22
+ padding: 0.5em 0 0.5em 1em;
23
+
24
+ color: #8699a4;
25
+ background-color: #0d3349;
26
+
27
+ font-size: 1.5em;
28
+ line-height: 1em;
29
+ font-weight: normal;
30
+
31
+ border-radius: 15px 15px 0 0;
32
+ -moz-border-radius: 15px 15px 0 0;
33
+ -webkit-border-top-right-radius: 15px;
34
+ -webkit-border-top-left-radius: 15px;
35
+ }
36
+
37
+ #qunit-header a {
38
+ text-decoration: none;
39
+ color: #c2ccd1;
40
+ }
41
+
42
+ #qunit-header a:hover,
43
+ #qunit-header a:focus {
44
+ color: #fff;
45
+ }
46
+
47
+ #qunit-banner {
48
+ height: 5px;
49
+ }
50
+
51
+ #qunit-testrunner-toolbar {
52
+ padding: 0em 0 0.5em 2em;
53
+ }
54
+
55
+ #qunit-userAgent {
56
+ padding: 0.5em 0 0.5em 2.5em;
57
+ background-color: #2b81af;
58
+ color: #fff;
59
+ text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
60
+ }
61
+
62
+
63
+ /** Tests: Pass/Fail */
64
+
65
+ #qunit-tests {
66
+ list-style-position: inside;
67
+ }
68
+
69
+ #qunit-tests li {
70
+ padding: 0.4em 0.5em 0.4em 2.5em;
71
+ border-bottom: 1px solid #fff;
72
+ list-style-position: inside;
73
+ }
74
+
75
+ #qunit-tests li strong {
76
+ cursor: pointer;
77
+ }
78
+
79
+ #qunit-tests ol {
80
+ margin-top: 0.5em;
81
+ padding: 0.5em;
82
+
83
+ background-color: #fff;
84
+
85
+ border-radius: 15px;
86
+ -moz-border-radius: 15px;
87
+ -webkit-border-radius: 15px;
88
+
89
+ box-shadow: inset 0px 2px 13px #999;
90
+ -moz-box-shadow: inset 0px 2px 13px #999;
91
+ -webkit-box-shadow: inset 0px 2px 13px #999;
92
+ }
93
+
94
+ #qunit-tests table {
95
+ border-collapse: collapse;
96
+ margin-top: .2em;
97
+ }
98
+
99
+ #qunit-tests th {
100
+ text-align: right;
101
+ vertical-align: top;
102
+ padding: 0 .5em 0 0;
103
+ }
104
+
105
+ #qunit-tests td {
106
+ vertical-align: top;
107
+ }
108
+
109
+ #qunit-tests pre {
110
+ margin: 0;
111
+ white-space: pre-wrap;
112
+ word-wrap: break-word;
113
+ }
114
+
115
+ #qunit-tests del {
116
+ background-color: #e0f2be;
117
+ color: #374e0c;
118
+ text-decoration: none;
119
+ }
120
+
121
+ #qunit-tests ins {
122
+ background-color: #ffcaca;
123
+ color: #500;
124
+ text-decoration: none;
125
+ }
126
+
127
+ /*** Test Counts */
128
+
129
+ #qunit-tests b.counts { color: black; }
130
+ #qunit-tests b.passed { color: #5E740B; }
131
+ #qunit-tests b.failed { color: #710909; }
132
+
133
+ #qunit-tests li li {
134
+ margin: 0.5em;
135
+ padding: 0.4em 0.5em 0.4em 0.5em;
136
+ background-color: #fff;
137
+ border-bottom: none;
138
+ list-style-position: inside;
139
+ }
140
+
141
+ /*** Passing Styles */
142
+
143
+ #qunit-tests li li.pass {
144
+ color: #5E740B;
145
+ background-color: #fff;
146
+ border-left: 26px solid #C6E746;
147
+ }
148
+
149
+ #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
150
+ #qunit-tests .pass .test-name { color: #366097; }
151
+
152
+ #qunit-tests .pass .test-actual,
153
+ #qunit-tests .pass .test-expected { color: #999999; }
154
+
155
+ #qunit-banner.qunit-pass { background-color: #C6E746; }
156
+
157
+ /*** Failing Styles */
158
+
159
+ #qunit-tests li li.fail {
160
+ color: #710909;
161
+ background-color: #fff;
162
+ border-left: 26px solid #EE5757;
163
+ }
164
+
165
+ #qunit-tests .fail { color: #000000; background-color: #EE5757; }
166
+ #qunit-tests .fail .test-name,
167
+ #qunit-tests .fail .module-name { color: #000000; }
168
+
169
+ #qunit-tests .fail .test-actual { color: #EE5757; }
170
+ #qunit-tests .fail .test-expected { color: green; }
171
+
172
+ #qunit-banner.qunit-fail,
173
+ #qunit-testrunner-toolbar { background-color: #EE5757; }
174
+
175
+
176
+ /** Footer */
177
+
178
+ #qunit-testresult {
179
+ padding: 0.5em 0.5em 0.5em 2.5em;
180
+
181
+ color: #2b81af;
182
+ background-color: #D2E0E6;
183
+
184
+ border-radius: 0 0 15px 15px;
185
+ -moz-border-radius: 0 0 15px 15px;
186
+ -webkit-border-bottom-right-radius: 15px;
187
+ -webkit-border-bottom-left-radius: 15px;
188
+ }
189
+
190
+ /** Fixture */
191
+
192
+ #qunit-fixture {
193
+ position: absolute;
194
+ top: -10000px;
195
+ left: -10000px;
196
+ }
apps/jquery-tmpl/tests/qunit.js ADDED
@@ -0,0 +1,1364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * QUnit - A JavaScript Unit Testing Framework
3
+ *
4
+ * http://docs.jquery.com/QUnit
5
+ *
6
+ * Copyright (c) 2009 John Resig, Jörn Zaefferer
7
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
8
+ * and GPL (GPL-LICENSE.txt) licenses.
9
+ */
10
+
11
+ (function(window) {
12
+
13
+ var defined = {
14
+ setTimeout: typeof window.setTimeout !== "undefined",
15
+ sessionStorage: (function() {
16
+ try {
17
+ return !!sessionStorage.getItem;
18
+ } catch(e){
19
+ return false;
20
+ }
21
+ })()
22
+ }
23
+
24
+ var testId = 0;
25
+
26
+ var Test = function(name, testName, expected, testEnvironmentArg, async, callback) {
27
+ this.name = name;
28
+ this.testName = testName;
29
+ this.expected = expected;
30
+ this.testEnvironmentArg = testEnvironmentArg;
31
+ this.async = async;
32
+ this.callback = callback;
33
+ this.assertions = [];
34
+ };
35
+ Test.prototype = {
36
+ init: function() {
37
+ var tests = id("qunit-tests");
38
+ if (tests) {
39
+ var b = document.createElement("strong");
40
+ b.innerHTML = "Running " + this.name;
41
+ var li = document.createElement("li");
42
+ li.appendChild( b );
43
+ li.id = this.id = "test-output" + testId++;
44
+ tests.appendChild( li );
45
+ }
46
+ },
47
+ setup: function() {
48
+ if (this.module != config.previousModule) {
49
+ if ( this.previousModule ) {
50
+ QUnit.moduleDone( this.module, config.moduleStats.bad, config.moduleStats.all );
51
+ }
52
+ config.previousModule = this.module;
53
+ config.moduleStats = { all: 0, bad: 0 };
54
+ QUnit.moduleStart( this.module, this.moduleTestEnvironment );
55
+ }
56
+
57
+ config.current = this;
58
+ this.testEnvironment = extend({
59
+ setup: function() {},
60
+ teardown: function() {}
61
+ }, this.moduleTestEnvironment);
62
+ if (this.testEnvironmentArg) {
63
+ extend(this.testEnvironment, this.testEnvironmentArg);
64
+ }
65
+
66
+ QUnit.testStart( this.testName, this.testEnvironment );
67
+
68
+ // allow utility functions to access the current test environment
69
+ // TODO why??
70
+ QUnit.current_testEnvironment = this.testEnvironment;
71
+
72
+ try {
73
+ if ( !config.pollution ) {
74
+ saveGlobal();
75
+ }
76
+
77
+ this.testEnvironment.setup.call(this.testEnvironment);
78
+ } catch(e) {
79
+ // TODO use testName instead of name for no-markup message?
80
+ QUnit.ok( false, "Setup failed on " + this.name + ": " + e.message );
81
+ }
82
+ },
83
+ run: function() {
84
+ if ( this.async ) {
85
+ QUnit.stop();
86
+ }
87
+
88
+ try {
89
+ this.callback.call(this.testEnvironment);
90
+ } catch(e) {
91
+ // TODO use testName instead of name for no-markup message?
92
+ fail("Test " + this.name + " died, exception and test follows", e, this.callback);
93
+ QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) );
94
+ // else next test will carry the responsibility
95
+ saveGlobal();
96
+
97
+ // Restart the tests if they're blocking
98
+ if ( config.blocking ) {
99
+ start();
100
+ }
101
+ }
102
+ },
103
+ teardown: function() {
104
+ try {
105
+ checkPollution();
106
+ this.testEnvironment.teardown.call(this.testEnvironment);
107
+ } catch(e) {
108
+ // TODO use testName instead of name for no-markup message?
109
+ QUnit.ok( false, "Teardown failed on " + this.name + ": " + e.message );
110
+ }
111
+ },
112
+ finish: function() {
113
+ if ( this.expected && this.expected != this.assertions.length ) {
114
+ QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" );
115
+ }
116
+
117
+ var good = 0, bad = 0,
118
+ tests = id("qunit-tests");
119
+
120
+ config.stats.all += this.assertions.length;
121
+ config.moduleStats.all += this.assertions.length;
122
+
123
+ if ( tests ) {
124
+ var ol = document.createElement("ol");
125
+
126
+ for ( var i = 0; i < this.assertions.length; i++ ) {
127
+ var assertion = this.assertions[i];
128
+
129
+ var li = document.createElement("li");
130
+ li.className = assertion.result ? "pass" : "fail";
131
+ li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed");
132
+ ol.appendChild( li );
133
+
134
+ if ( assertion.result ) {
135
+ good++;
136
+ } else {
137
+ bad++;
138
+ config.stats.bad++;
139
+ config.moduleStats.bad++;
140
+ }
141
+ }
142
+
143
+ // store result when possible
144
+ defined.sessionStorage && sessionStorage.setItem("qunit-" + this.testName, bad);
145
+
146
+ if (bad == 0) {
147
+ ol.style.display = "none";
148
+ }
149
+
150
+ var b = document.createElement("strong");
151
+ b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
152
+
153
+ addEvent(b, "click", function() {
154
+ var next = b.nextSibling, display = next.style.display;
155
+ next.style.display = display === "none" ? "block" : "none";
156
+ });
157
+
158
+ addEvent(b, "dblclick", function(e) {
159
+ var target = e && e.target ? e.target : window.event.srcElement;
160
+ if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
161
+ target = target.parentNode;
162
+ }
163
+ if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
164
+ window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, ""));
165
+ }
166
+ });
167
+
168
+ var li = id(this.id);
169
+ li.className = bad ? "fail" : "pass";
170
+ li.style.display = resultDisplayStyle(!bad);
171
+ li.removeChild( li.firstChild );
172
+ li.appendChild( b );
173
+ li.appendChild( ol );
174
+
175
+ if ( bad ) {
176
+ var toolbar = id("qunit-testrunner-toolbar");
177
+ if ( toolbar ) {
178
+ toolbar.style.display = "block";
179
+ id("qunit-filter-pass").disabled = null;
180
+ }
181
+ }
182
+
183
+ } else {
184
+ for ( var i = 0; i < this.assertions.length; i++ ) {
185
+ if ( !this.assertions[i].result ) {
186
+ bad++;
187
+ config.stats.bad++;
188
+ config.moduleStats.bad++;
189
+ }
190
+ }
191
+ }
192
+
193
+ try {
194
+ QUnit.reset();
195
+ } catch(e) {
196
+ // TODO use testName instead of name for no-markup message?
197
+ fail("reset() failed, following Test " + this.name + ", exception and reset fn follows", e, QUnit.reset);
198
+ }
199
+
200
+ QUnit.testDone( this.testName, bad, this.assertions.length );
201
+ },
202
+
203
+ queue: function() {
204
+ var test = this;
205
+ synchronize(function() {
206
+ test.init();
207
+ });
208
+ function run() {
209
+ // each of these can by async
210
+ synchronize(function() {
211
+ test.setup();
212
+ });
213
+ synchronize(function() {
214
+ test.run();
215
+ });
216
+ synchronize(function() {
217
+ test.teardown();
218
+ });
219
+ synchronize(function() {
220
+ test.finish();
221
+ });
222
+ }
223
+ // defer when previous test run passed, if storage is available
224
+ var bad = defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.testName);
225
+ if (bad) {
226
+ run();
227
+ } else {
228
+ synchronize(run);
229
+ };
230
+ }
231
+
232
+ }
233
+
234
+ var QUnit = {
235
+
236
+ // call on start of module test to prepend name to all tests
237
+ module: function(name, testEnvironment) {
238
+ config.previousModule = config.currentModule;
239
+ config.currentModule = name;
240
+ config.currentModuleTestEnviroment = testEnvironment;
241
+ },
242
+
243
+ asyncTest: function(testName, expected, callback) {
244
+ if ( arguments.length === 2 ) {
245
+ callback = expected;
246
+ expected = 0;
247
+ }
248
+
249
+ QUnit.test(testName, expected, callback, true);
250
+ },
251
+
252
+ test: function(testName, expected, callback, async) {
253
+ var name = '<span class="test-name">' + testName + '</span>', testEnvironmentArg;
254
+
255
+ if ( arguments.length === 2 ) {
256
+ callback = expected;
257
+ expected = null;
258
+ }
259
+ // is 2nd argument a testEnvironment?
260
+ if ( expected && typeof expected === 'object') {
261
+ testEnvironmentArg = expected;
262
+ expected = null;
263
+ }
264
+
265
+ if ( config.currentModule ) {
266
+ name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
267
+ }
268
+
269
+ if ( !validTest(config.currentModule + ": " + testName) ) {
270
+ return;
271
+ }
272
+
273
+ var test = new Test(name, testName, expected, testEnvironmentArg, async, callback);
274
+ test.previousModule = config.previousModule;
275
+ test.module = config.currentModule;
276
+ test.moduleTestEnvironment = config.currentModuleTestEnviroment;
277
+ test.queue();
278
+ },
279
+
280
+ /**
281
+ * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
282
+ */
283
+ expect: function(asserts) {
284
+ config.current.expected = asserts;
285
+ },
286
+
287
+ /**
288
+ * Asserts true.
289
+ * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
290
+ */
291
+ ok: function(a, msg) {
292
+ a = !!a;
293
+ var details = {
294
+ result: a,
295
+ message: msg
296
+ };
297
+ msg = escapeHtml(msg);
298
+ QUnit.log(a, msg, details);
299
+ config.current.assertions.push({
300
+ result: a,
301
+ message: msg
302
+ });
303
+ },
304
+
305
+ /**
306
+ * Checks that the first two arguments are equal, with an optional message.
307
+ * Prints out both actual and expected values.
308
+ *
309
+ * Prefered to ok( actual == expected, message )
310
+ *
311
+ * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
312
+ *
313
+ * @param Object actual
314
+ * @param Object expected
315
+ * @param String message (optional)
316
+ */
317
+ equal: function(actual, expected, message) {
318
+ QUnit.push(expected == actual, actual, expected, message);
319
+ },
320
+
321
+ notEqual: function(actual, expected, message) {
322
+ QUnit.push(expected != actual, actual, expected, message);
323
+ },
324
+
325
+ deepEqual: function(actual, expected, message) {
326
+ QUnit.push(QUnit.equiv(actual, expected), actual, expected, message);
327
+ },
328
+
329
+ notDeepEqual: function(actual, expected, message) {
330
+ QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message);
331
+ },
332
+
333
+ strictEqual: function(actual, expected, message) {
334
+ QUnit.push(expected === actual, actual, expected, message);
335
+ },
336
+
337
+ notStrictEqual: function(actual, expected, message) {
338
+ QUnit.push(expected !== actual, actual, expected, message);
339
+ },
340
+
341
+ raises: function(block, expected, message) {
342
+ var actual, ok = false;
343
+
344
+ if (typeof expected === 'string') {
345
+ message = expected;
346
+ expected = null;
347
+ }
348
+
349
+ try {
350
+ block();
351
+ } catch (e) {
352
+ actual = e;
353
+ }
354
+
355
+ if (actual) {
356
+ // we don't want to validate thrown error
357
+ if (!expected) {
358
+ ok = true;
359
+ // expected is a regexp
360
+ } else if (QUnit.objectType(expected) === "regexp") {
361
+ ok = expected.test(actual);
362
+ // expected is a constructor
363
+ } else if (actual instanceof expected) {
364
+ ok = true;
365
+ // expected is a validation function which returns true is validation passed
366
+ } else if (expected.call({}, actual) === true) {
367
+ ok = true;
368
+ }
369
+ }
370
+
371
+ QUnit.ok(ok, message);
372
+ },
373
+
374
+ start: function() {
375
+ // A slight delay, to avoid any current callbacks
376
+ if ( defined.setTimeout ) {
377
+ window.setTimeout(function() {
378
+ if ( config.timeout ) {
379
+ clearTimeout(config.timeout);
380
+ }
381
+
382
+ config.blocking = false;
383
+ process();
384
+ }, 13);
385
+ } else {
386
+ config.blocking = false;
387
+ process();
388
+ }
389
+ },
390
+
391
+ stop: function(timeout) {
392
+ config.blocking = true;
393
+
394
+ if ( timeout && defined.setTimeout ) {
395
+ config.timeout = window.setTimeout(function() {
396
+ QUnit.ok( false, "Test timed out" );
397
+ QUnit.start();
398
+ }, timeout);
399
+ }
400
+ }
401
+
402
+ };
403
+
404
+ // Backwards compatibility, deprecated
405
+ QUnit.equals = QUnit.equal;
406
+ QUnit.same = QUnit.deepEqual;
407
+
408
+ // Maintain internal state
409
+ var config = {
410
+ // The queue of tests to run
411
+ queue: [],
412
+
413
+ // block until document ready
414
+ blocking: true
415
+ };
416
+
417
+ // Load paramaters
418
+ (function() {
419
+ var location = window.location || { search: "", protocol: "file:" },
420
+ GETParams = location.search.slice(1).split('&');
421
+
422
+ for ( var i = 0; i < GETParams.length; i++ ) {
423
+ GETParams[i] = decodeURIComponent( GETParams[i] );
424
+ if ( GETParams[i] === "noglobals" ) {
425
+ GETParams.splice( i, 1 );
426
+ i--;
427
+ config.noglobals = true;
428
+ } else if ( GETParams[i].search('=') > -1 ) {
429
+ GETParams.splice( i, 1 );
430
+ i--;
431
+ }
432
+ }
433
+
434
+ // restrict modules/tests by get parameters
435
+ config.filters = GETParams;
436
+
437
+ // Figure out if we're running the tests from a server or not
438
+ QUnit.isLocal = !!(location.protocol === 'file:');
439
+ })();
440
+
441
+ // Expose the API as global variables, unless an 'exports'
442
+ // object exists, in that case we assume we're in CommonJS
443
+ if ( typeof exports === "undefined" || typeof require === "undefined" ) {
444
+ extend(window, QUnit);
445
+ window.QUnit = QUnit;
446
+ } else {
447
+ extend(exports, QUnit);
448
+ exports.QUnit = QUnit;
449
+ }
450
+
451
+ // define these after exposing globals to keep them in these QUnit namespace only
452
+ extend(QUnit, {
453
+ config: config,
454
+
455
+ // Initialize the configuration options
456
+ init: function() {
457
+ extend(config, {
458
+ stats: { all: 0, bad: 0 },
459
+ moduleStats: { all: 0, bad: 0 },
460
+ started: +new Date,
461
+ updateRate: 1000,
462
+ blocking: false,
463
+ autostart: true,
464
+ autorun: false,
465
+ filters: [],
466
+ queue: []
467
+ });
468
+
469
+ var tests = id("qunit-tests"),
470
+ banner = id("qunit-banner"),
471
+ result = id("qunit-testresult");
472
+
473
+ if ( tests ) {
474
+ tests.innerHTML = "";
475
+ }
476
+
477
+ if ( banner ) {
478
+ banner.className = "";
479
+ }
480
+
481
+ if ( result ) {
482
+ result.parentNode.removeChild( result );
483
+ }
484
+ },
485
+
486
+ /**
487
+ * Resets the test setup. Useful for tests that modify the DOM.
488
+ *
489
+ * If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
490
+ */
491
+ reset: function() {
492
+ if ( window.jQuery ) {
493
+ jQuery( "#main, #qunit-fixture" ).html( config.fixture );
494
+ } else {
495
+ var main = id( 'main' ) || id( 'qunit-fixture' );
496
+ if ( main ) {
497
+ main.innerHTML = config.fixture;
498
+ }
499
+ }
500
+ },
501
+
502
+ /**
503
+ * Trigger an event on an element.
504
+ *
505
+ * @example triggerEvent( document.body, "click" );
506
+ *
507
+ * @param DOMElement elem
508
+ * @param String type
509
+ */
510
+ triggerEvent: function( elem, type, event ) {
511
+ if ( document.createEvent ) {
512
+ event = document.createEvent("MouseEvents");
513
+ event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
514
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
515
+ elem.dispatchEvent( event );
516
+
517
+ } else if ( elem.fireEvent ) {
518
+ elem.fireEvent("on"+type);
519
+ }
520
+ },
521
+
522
+ // Safe object type checking
523
+ is: function( type, obj ) {
524
+ return QUnit.objectType( obj ) == type;
525
+ },
526
+
527
+ objectType: function( obj ) {
528
+ if (typeof obj === "undefined") {
529
+ return "undefined";
530
+
531
+ // consider: typeof null === object
532
+ }
533
+ if (obj === null) {
534
+ return "null";
535
+ }
536
+
537
+ var type = Object.prototype.toString.call( obj )
538
+ .match(/^\[object\s(.*)\]$/)[1] || '';
539
+
540
+ switch (type) {
541
+ case 'Number':
542
+ if (isNaN(obj)) {
543
+ return "nan";
544
+ } else {
545
+ return "number";
546
+ }
547
+ case 'String':
548
+ case 'Boolean':
549
+ case 'Array':
550
+ case 'Date':
551
+ case 'RegExp':
552
+ case 'Function':
553
+ return type.toLowerCase();
554
+ }
555
+ if (typeof obj === "object") {
556
+ return "object";
557
+ }
558
+ return undefined;
559
+ },
560
+
561
+ push: function(result, actual, expected, message) {
562
+ var details = {
563
+ result: result,
564
+ message: message,
565
+ actual: actual,
566
+ expected: expected
567
+ };
568
+
569
+ message = escapeHtml(message) || (result ? "okay" : "failed");
570
+ message = '<span class="test-message">' + message + "</span>";
571
+ expected = escapeHtml(QUnit.jsDump.parse(expected));
572
+ actual = escapeHtml(QUnit.jsDump.parse(actual));
573
+ var output = message + '<table><tr class="test-expected"><th>Expected: </th><td><pre>' + expected + '</pre></td></tr>';
574
+ if (actual != expected) {
575
+ output += '<tr class="test-actual"><th>Result: </th><td><pre>' + actual + '</pre></td></tr>';
576
+ output += '<tr class="test-diff"><th>Diff: </th><td><pre>' + QUnit.diff(expected, actual) +'</pre></td></tr>';
577
+ }
578
+ if (!result) {
579
+ var source = sourceFromStacktrace();
580
+ if (source) {
581
+ details.source = source;
582
+ output += '<tr class="test-source"><th>Source: </th><td><pre>' + source +'</pre></td></tr>';
583
+ }
584
+ }
585
+ output += "</table>";
586
+
587
+ QUnit.log(result, message, details);
588
+
589
+ config.current.assertions.push({
590
+ result: !!result,
591
+ message: output
592
+ });
593
+ },
594
+
595
+ // Logging callbacks
596
+ begin: function() {},
597
+ done: function(failures, total) {},
598
+ log: function(result, message) {},
599
+ testStart: function(name, testEnvironment) {},
600
+ testDone: function(name, failures, total) {},
601
+ moduleStart: function(name, testEnvironment) {},
602
+ moduleDone: function(name, failures, total) {}
603
+ });
604
+
605
+ if ( typeof document === "undefined" || document.readyState === "complete" ) {
606
+ config.autorun = true;
607
+ }
608
+
609
+ addEvent(window, "load", function() {
610
+ QUnit.begin();
611
+
612
+ // Initialize the config, saving the execution queue
613
+ var oldconfig = extend({}, config);
614
+ QUnit.init();
615
+ extend(config, oldconfig);
616
+
617
+ config.blocking = false;
618
+
619
+ var userAgent = id("qunit-userAgent");
620
+ if ( userAgent ) {
621
+ userAgent.innerHTML = navigator.userAgent;
622
+ }
623
+ var banner = id("qunit-header");
624
+ if ( banner ) {
625
+ var paramsIndex = location.href.lastIndexOf(location.search);
626
+ if ( paramsIndex > -1 ) {
627
+ var mainPageLocation = location.href.slice(0, paramsIndex);
628
+ if ( mainPageLocation == location.href ) {
629
+ banner.innerHTML = '<a href=""> ' + banner.innerHTML + '</a> ';
630
+ } else {
631
+ var testName = decodeURIComponent(location.search.slice(1));
632
+ banner.innerHTML = '<a href="' + mainPageLocation + '">' + banner.innerHTML + '</a> &#8250; <a href="">' + testName + '</a>';
633
+ }
634
+ }
635
+ }
636
+
637
+ var toolbar = id("qunit-testrunner-toolbar");
638
+ if ( toolbar ) {
639
+ toolbar.style.display = "none";
640
+
641
+ var filter = document.createElement("input");
642
+ filter.type = "checkbox";
643
+ filter.id = "qunit-filter-pass";
644
+ filter.disabled = true;
645
+ addEvent( filter, "click", function() {
646
+ var li = document.getElementsByTagName("li");
647
+ for ( var i = 0; i < li.length; i++ ) {
648
+ if ( li[i].className.indexOf("pass") > -1 ) {
649
+ li[i].style.display = filter.checked ? "none" : "";
650
+ }
651
+ }
652
+ });
653
+ toolbar.appendChild( filter );
654
+
655
+ var label = document.createElement("label");
656
+ label.setAttribute("for", "qunit-filter-pass");
657
+ label.innerHTML = "Hide passed tests";
658
+ toolbar.appendChild( label );
659
+ }
660
+
661
+ var main = id('main') || id('qunit-fixture');
662
+ if ( main ) {
663
+ config.fixture = main.innerHTML;
664
+ }
665
+
666
+ if (config.autostart) {
667
+ QUnit.start();
668
+ }
669
+ });
670
+
671
+ function done() {
672
+ config.autorun = true;
673
+
674
+ // Log the last module results
675
+ if ( config.currentModule ) {
676
+ QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
677
+ }
678
+
679
+ var banner = id("qunit-banner"),
680
+ tests = id("qunit-tests"),
681
+ html = ['Tests completed in ',
682
+ +new Date - config.started, ' milliseconds.<br/>',
683
+ '<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join('');
684
+
685
+ if ( banner ) {
686
+ banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
687
+ }
688
+
689
+ if ( tests ) {
690
+ var result = id("qunit-testresult");
691
+
692
+ if ( !result ) {
693
+ result = document.createElement("p");
694
+ result.id = "qunit-testresult";
695
+ result.className = "result";
696
+ tests.parentNode.insertBefore( result, tests.nextSibling );
697
+ }
698
+
699
+ result.innerHTML = html;
700
+ }
701
+
702
+ QUnit.done( config.stats.bad, config.stats.all );
703
+ }
704
+
705
+ function validTest( name ) {
706
+ var i = config.filters.length,
707
+ run = false;
708
+
709
+ if ( !i ) {
710
+ return true;
711
+ }
712
+
713
+ while ( i-- ) {
714
+ var filter = config.filters[i],
715
+ not = filter.charAt(0) == '!';
716
+
717
+ if ( not ) {
718
+ filter = filter.slice(1);
719
+ }
720
+
721
+ if ( name.indexOf(filter) !== -1 ) {
722
+ return !not;
723
+ }
724
+
725
+ if ( not ) {
726
+ run = true;
727
+ }
728
+ }
729
+
730
+ return run;
731
+ }
732
+
733
+ // so far supports only Firefox, Chrome and Opera (buggy)
734
+ // could be extended in the future to use something like https://github.com/csnover/TraceKit
735
+ function sourceFromStacktrace() {
736
+ try {
737
+ throw new Error();
738
+ } catch ( e ) {
739
+ if (e.stacktrace) {
740
+ // Opera
741
+ return e.stacktrace.split("\n")[6];
742
+ } else if (e.stack) {
743
+ // Firefox, Chrome
744
+ return e.stack.split("\n")[4];
745
+ }
746
+ }
747
+ }
748
+
749
+ function resultDisplayStyle(passed) {
750
+ return passed && id("qunit-filter-pass") && id("qunit-filter-pass").checked ? 'none' : '';
751
+ }
752
+
753
+ function escapeHtml(s) {
754
+ if (!s) {
755
+ return "";
756
+ }
757
+ s = s + "";
758
+ return s.replace(/[\&"<>\\]/g, function(s) {
759
+ switch(s) {
760
+ case "&": return "&amp;";
761
+ case "\\": return "\\\\";
762
+ case '"': return '\"';
763
+ case "<": return "&lt;";
764
+ case ">": return "&gt;";
765
+ default: return s;
766
+ }
767
+ });
768
+ }
769
+
770
+ function synchronize( callback ) {
771
+ config.queue.push( callback );
772
+
773
+ if ( config.autorun && !config.blocking ) {
774
+ process();
775
+ }
776
+ }
777
+
778
+ function process() {
779
+ var start = (new Date()).getTime();
780
+
781
+ while ( config.queue.length && !config.blocking ) {
782
+ if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
783
+ config.queue.shift()();
784
+ } else {
785
+ window.setTimeout( process, 13 );
786
+ break;
787
+ }
788
+ }
789
+ if (!config.blocking && !config.queue.length) {
790
+ done();
791
+ }
792
+ }
793
+
794
+ function saveGlobal() {
795
+ config.pollution = [];
796
+
797
+ if ( config.noglobals ) {
798
+ for ( var key in window ) {
799
+ config.pollution.push( key );
800
+ }
801
+ }
802
+ }
803
+
804
+ function checkPollution( name ) {
805
+ var old = config.pollution;
806
+ saveGlobal();
807
+
808
+ var newGlobals = diff( old, config.pollution );
809
+ if ( newGlobals.length > 0 ) {
810
+ ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
811
+ config.current.expected++;
812
+ }
813
+
814
+ var deletedGlobals = diff( config.pollution, old );
815
+ if ( deletedGlobals.length > 0 ) {
816
+ ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
817
+ config.current.expected++;
818
+ }
819
+ }
820
+
821
+ // returns a new Array with the elements that are in a but not in b
822
+ function diff( a, b ) {
823
+ var result = a.slice();
824
+ for ( var i = 0; i < result.length; i++ ) {
825
+ for ( var j = 0; j < b.length; j++ ) {
826
+ if ( result[i] === b[j] ) {
827
+ result.splice(i, 1);
828
+ i--;
829
+ break;
830
+ }
831
+ }
832
+ }
833
+ return result;
834
+ }
835
+
836
+ function fail(message, exception, callback) {
837
+ if ( typeof console !== "undefined" && console.error && console.warn ) {
838
+ console.error(message);
839
+ console.error(exception);
840
+ console.warn(callback.toString());
841
+
842
+ } else if ( window.opera && opera.postError ) {
843
+ opera.postError(message, exception, callback.toString);
844
+ }
845
+ }
846
+
847
+ function extend(a, b) {
848
+ for ( var prop in b ) {
849
+ a[prop] = b[prop];
850
+ }
851
+
852
+ return a;
853
+ }
854
+
855
+ function addEvent(elem, type, fn) {
856
+ if ( elem.addEventListener ) {
857
+ elem.addEventListener( type, fn, false );
858
+ } else if ( elem.attachEvent ) {
859
+ elem.attachEvent( "on" + type, fn );
860
+ } else {
861
+ fn();
862
+ }
863
+ }
864
+
865
+ function id(name) {
866
+ return !!(typeof document !== "undefined" && document && document.getElementById) &&
867
+ document.getElementById( name );
868
+ }
869
+
870
+ // Test for equality any JavaScript type.
871
+ // Discussions and reference: http://philrathe.com/articles/equiv
872
+ // Test suites: http://philrathe.com/tests/equiv
873
+ // Author: Philippe Rathé <prathe@gmail.com>
874
+ QUnit.equiv = function () {
875
+
876
+ var innerEquiv; // the real equiv function
877
+ var callers = []; // stack to decide between skip/abort functions
878
+ var parents = []; // stack to avoiding loops from circular referencing
879
+
880
+ // Call the o related callback with the given arguments.
881
+ function bindCallbacks(o, callbacks, args) {
882
+ var prop = QUnit.objectType(o);
883
+ if (prop) {
884
+ if (QUnit.objectType(callbacks[prop]) === "function") {
885
+ return callbacks[prop].apply(callbacks, args);
886
+ } else {
887
+ return callbacks[prop]; // or undefined
888
+ }
889
+ }
890
+ }
891
+
892
+ var callbacks = function () {
893
+
894
+ // for string, boolean, number and null
895
+ function useStrictEquality(b, a) {
896
+ if (b instanceof a.constructor || a instanceof b.constructor) {
897
+ // to catch short annotaion VS 'new' annotation of a declaration
898
+ // e.g. var i = 1;
899
+ // var j = new Number(1);
900
+ return a == b;
901
+ } else {
902
+ return a === b;
903
+ }
904
+ }
905
+
906
+ return {
907
+ "string": useStrictEquality,
908
+ "boolean": useStrictEquality,
909
+ "number": useStrictEquality,
910
+ "null": useStrictEquality,
911
+ "undefined": useStrictEquality,
912
+
913
+ "nan": function (b) {
914
+ return isNaN(b);
915
+ },
916
+
917
+ "date": function (b, a) {
918
+ return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf();
919
+ },
920
+
921
+ "regexp": function (b, a) {
922
+ return QUnit.objectType(b) === "regexp" &&
923
+ a.source === b.source && // the regex itself
924
+ a.global === b.global && // and its modifers (gmi) ...
925
+ a.ignoreCase === b.ignoreCase &&
926
+ a.multiline === b.multiline;
927
+ },
928
+
929
+ // - skip when the property is a method of an instance (OOP)
930
+ // - abort otherwise,
931
+ // initial === would have catch identical references anyway
932
+ "function": function () {
933
+ var caller = callers[callers.length - 1];
934
+ return caller !== Object &&
935
+ typeof caller !== "undefined";
936
+ },
937
+
938
+ "array": function (b, a) {
939
+ var i, j, loop;
940
+ var len;
941
+
942
+ // b could be an object literal here
943
+ if ( ! (QUnit.objectType(b) === "array")) {
944
+ return false;
945
+ }
946
+
947
+ len = a.length;
948
+ if (len !== b.length) { // safe and faster
949
+ return false;
950
+ }
951
+
952
+ //track reference to avoid circular references
953
+ parents.push(a);
954
+ for (i = 0; i < len; i++) {
955
+ loop = false;
956
+ for(j=0;j<parents.length;j++){
957
+ if(parents[j] === a[i]){
958
+ loop = true;//dont rewalk array
959
+ }
960
+ }
961
+ if (!loop && ! innerEquiv(a[i], b[i])) {
962
+ parents.pop();
963
+ return false;
964
+ }
965
+ }
966
+ parents.pop();
967
+ return true;
968
+ },
969
+
970
+ "object": function (b, a) {
971
+ var i, j, loop;
972
+ var eq = true; // unless we can proove it
973
+ var aProperties = [], bProperties = []; // collection of strings
974
+
975
+ // comparing constructors is more strict than using instanceof
976
+ if ( a.constructor !== b.constructor) {
977
+ return false;
978
+ }
979
+
980
+ // stack constructor before traversing properties
981
+ callers.push(a.constructor);
982
+ //track reference to avoid circular references
983
+ parents.push(a);
984
+
985
+ for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
986
+ loop = false;
987
+ for(j=0;j<parents.length;j++){
988
+ if(parents[j] === a[i])
989
+ loop = true; //don't go down the same path twice
990
+ }
991
+ aProperties.push(i); // collect a's properties
992
+
993
+ if (!loop && ! innerEquiv(a[i], b[i])) {
994
+ eq = false;
995
+ break;
996
+ }
997
+ }
998
+
999
+ callers.pop(); // unstack, we are done
1000
+ parents.pop();
1001
+
1002
+ for (i in b) {
1003
+ bProperties.push(i); // collect b's properties
1004
+ }
1005
+
1006
+ // Ensures identical properties name
1007
+ return eq && innerEquiv(aProperties.sort(), bProperties.sort());
1008
+ }
1009
+ };
1010
+ }();
1011
+
1012
+ innerEquiv = function () { // can take multiple arguments
1013
+ var args = Array.prototype.slice.apply(arguments);
1014
+ if (args.length < 2) {
1015
+ return true; // end transition
1016
+ }
1017
+
1018
+ return (function (a, b) {
1019
+ if (a === b) {
1020
+ return true; // catch the most you can
1021
+ } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b)) {
1022
+ return false; // don't lose time with error prone cases
1023
+ } else {
1024
+ return bindCallbacks(a, callbacks, [b, a]);
1025
+ }
1026
+
1027
+ // apply transition with (1..n) arguments
1028
+ })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
1029
+ };
1030
+
1031
+ return innerEquiv;
1032
+
1033
+ }();
1034
+
1035
+ /**
1036
+ * jsDump
1037
+ * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
1038
+ * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
1039
+ * Date: 5/15/2008
1040
+ * @projectDescription Advanced and extensible data dumping for Javascript.
1041
+ * @version 1.0.0
1042
+ * @author Ariel Flesler
1043
+ * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
1044
+ */
1045
+ QUnit.jsDump = (function() {
1046
+ function quote( str ) {
1047
+ return '"' + str.toString().replace(/"/g, '\\"') + '"';
1048
+ };
1049
+ function literal( o ) {
1050
+ return o + '';
1051
+ };
1052
+ function join( pre, arr, post ) {
1053
+ var s = jsDump.separator(),
1054
+ base = jsDump.indent(),
1055
+ inner = jsDump.indent(1);
1056
+ if ( arr.join )
1057
+ arr = arr.join( ',' + s + inner );
1058
+ if ( !arr )
1059
+ return pre + post;
1060
+ return [ pre, inner + arr, base + post ].join(s);
1061
+ };
1062
+ function array( arr ) {
1063
+ var i = arr.length, ret = Array(i);
1064
+ this.up();
1065
+ while ( i-- )
1066
+ ret[i] = this.parse( arr[i] );
1067
+ this.down();
1068
+ return join( '[', ret, ']' );
1069
+ };
1070
+
1071
+ var reName = /^function (\w+)/;
1072
+
1073
+ var jsDump = {
1074
+ parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance
1075
+ var parser = this.parsers[ type || this.typeOf(obj) ];
1076
+ type = typeof parser;
1077
+
1078
+ return type == 'function' ? parser.call( this, obj ) :
1079
+ type == 'string' ? parser :
1080
+ this.parsers.error;
1081
+ },
1082
+ typeOf:function( obj ) {
1083
+ var type;
1084
+ if ( obj === null ) {
1085
+ type = "null";
1086
+ } else if (typeof obj === "undefined") {
1087
+ type = "undefined";
1088
+ } else if (QUnit.is("RegExp", obj)) {
1089
+ type = "regexp";
1090
+ } else if (QUnit.is("Date", obj)) {
1091
+ type = "date";
1092
+ } else if (QUnit.is("Function", obj)) {
1093
+ type = "function";
1094
+ } else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") {
1095
+ type = "window";
1096
+ } else if (obj.nodeType === 9) {
1097
+ type = "document";
1098
+ } else if (obj.nodeType) {
1099
+ type = "node";
1100
+ } else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
1101
+ type = "array";
1102
+ } else {
1103
+ type = typeof obj;
1104
+ }
1105
+ return type;
1106
+ },
1107
+ separator:function() {
1108
+ return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
1109
+ },
1110
+ indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
1111
+ if ( !this.multiline )
1112
+ return '';
1113
+ var chr = this.indentChar;
1114
+ if ( this.HTML )
1115
+ chr = chr.replace(/\t/g,' ').replace(/ /g,'&nbsp;');
1116
+ return Array( this._depth_ + (extra||0) ).join(chr);
1117
+ },
1118
+ up:function( a ) {
1119
+ this._depth_ += a || 1;
1120
+ },
1121
+ down:function( a ) {
1122
+ this._depth_ -= a || 1;
1123
+ },
1124
+ setParser:function( name, parser ) {
1125
+ this.parsers[name] = parser;
1126
+ },
1127
+ // The next 3 are exposed so you can use them
1128
+ quote:quote,
1129
+ literal:literal,
1130
+ join:join,
1131
+ //
1132
+ _depth_: 1,
1133
+ // This is the list of parsers, to modify them, use jsDump.setParser
1134
+ parsers:{
1135
+ window: '[Window]',
1136
+ document: '[Document]',
1137
+ error:'[ERROR]', //when no parser is found, shouldn't happen
1138
+ unknown: '[Unknown]',
1139
+ 'null':'null',
1140
+ undefined:'undefined',
1141
+ 'function':function( fn ) {
1142
+ var ret = 'function',
1143
+ name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
1144
+ if ( name )
1145
+ ret += ' ' + name;
1146
+ ret += '(';
1147
+
1148
+ ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join('');
1149
+ return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' );
1150
+ },
1151
+ array: array,
1152
+ nodelist: array,
1153
+ arguments: array,
1154
+ object:function( map ) {
1155
+ var ret = [ ];
1156
+ QUnit.jsDump.up();
1157
+ for ( var key in map )
1158
+ ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) );
1159
+ QUnit.jsDump.down();
1160
+ return join( '{', ret, '}' );
1161
+ },
1162
+ node:function( node ) {
1163
+ var open = QUnit.jsDump.HTML ? '&lt;' : '<',
1164
+ close = QUnit.jsDump.HTML ? '&gt;' : '>';
1165
+
1166
+ var tag = node.nodeName.toLowerCase(),
1167
+ ret = open + tag;
1168
+
1169
+ for ( var a in QUnit.jsDump.DOMAttrs ) {
1170
+ var val = node[QUnit.jsDump.DOMAttrs[a]];
1171
+ if ( val )
1172
+ ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' );
1173
+ }
1174
+ return ret + close + open + '/' + tag + close;
1175
+ },
1176
+ functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
1177
+ var l = fn.length;
1178
+ if ( !l ) return '';
1179
+
1180
+ var args = Array(l);
1181
+ while ( l-- )
1182
+ args[l] = String.fromCharCode(97+l);//97 is 'a'
1183
+ return ' ' + args.join(', ') + ' ';
1184
+ },
1185
+ key:quote, //object calls it internally, the key part of an item in a map
1186
+ functionCode:'[code]', //function calls it internally, it's the content of the function
1187
+ attribute:quote, //node calls it internally, it's an html attribute value
1188
+ string:quote,
1189
+ date:quote,
1190
+ regexp:literal, //regex
1191
+ number:literal,
1192
+ 'boolean':literal
1193
+ },
1194
+ DOMAttrs:{//attributes to dump from nodes, name=>realName
1195
+ id:'id',
1196
+ name:'name',
1197
+ 'class':'className'
1198
+ },
1199
+ HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
1200
+ indentChar:' ',//indentation unit
1201
+ multiline:true //if true, items in a collection, are separated by a \n, else just a space.
1202
+ };
1203
+
1204
+ return jsDump;
1205
+ })();
1206
+
1207
+ // from Sizzle.js
1208
+ function getText( elems ) {
1209
+ var ret = "", elem;
1210
+
1211
+ for ( var i = 0; elems[i]; i++ ) {
1212
+ elem = elems[i];
1213
+
1214
+ // Get the text from text nodes and CDATA nodes
1215
+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
1216
+ ret += elem.nodeValue;
1217
+
1218
+ // Traverse everything else, except comment nodes
1219
+ } else if ( elem.nodeType !== 8 ) {
1220
+ ret += getText( elem.childNodes );
1221
+ }
1222
+ }
1223
+
1224
+ return ret;
1225
+ };
1226
+
1227
+ /*
1228
+ * Javascript Diff Algorithm
1229
+ * By John Resig (http://ejohn.org/)
1230
+ * Modified by Chu Alan "sprite"
1231
+ *
1232
+ * Released under the MIT license.
1233
+ *
1234
+ * More Info:
1235
+ * http://ejohn.org/projects/javascript-diff-algorithm/
1236
+ *
1237
+ * Usage: QUnit.diff(expected, actual)
1238
+ *
1239
+ * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
1240
+ */
1241
+ QUnit.diff = (function() {
1242
+ function diff(o, n){
1243
+ var ns = new Object();
1244
+ var os = new Object();
1245
+
1246
+ for (var i = 0; i < n.length; i++) {
1247
+ if (ns[n[i]] == null)
1248
+ ns[n[i]] = {
1249
+ rows: new Array(),
1250
+ o: null
1251
+ };
1252
+ ns[n[i]].rows.push(i);
1253
+ }
1254
+
1255
+ for (var i = 0; i < o.length; i++) {
1256
+ if (os[o[i]] == null)
1257
+ os[o[i]] = {
1258
+ rows: new Array(),
1259
+ n: null
1260
+ };
1261
+ os[o[i]].rows.push(i);
1262
+ }
1263
+
1264
+ for (var i in ns) {
1265
+ if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
1266
+ n[ns[i].rows[0]] = {
1267
+ text: n[ns[i].rows[0]],
1268
+ row: os[i].rows[0]
1269
+ };
1270
+ o[os[i].rows[0]] = {
1271
+ text: o[os[i].rows[0]],
1272
+ row: ns[i].rows[0]
1273
+ };
1274
+ }
1275
+ }
1276
+
1277
+ for (var i = 0; i < n.length - 1; i++) {
1278
+ if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
1279
+ n[i + 1] == o[n[i].row + 1]) {
1280
+ n[i + 1] = {
1281
+ text: n[i + 1],
1282
+ row: n[i].row + 1
1283
+ };
1284
+ o[n[i].row + 1] = {
1285
+ text: o[n[i].row + 1],
1286
+ row: i + 1
1287
+ };
1288
+ }
1289
+ }
1290
+
1291
+ for (var i = n.length - 1; i > 0; i--) {
1292
+ if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
1293
+ n[i - 1] == o[n[i].row - 1]) {
1294
+ n[i - 1] = {
1295
+ text: n[i - 1],
1296
+ row: n[i].row - 1
1297
+ };
1298
+ o[n[i].row - 1] = {
1299
+ text: o[n[i].row - 1],
1300
+ row: i - 1
1301
+ };
1302
+ }
1303
+ }
1304
+
1305
+ return {
1306
+ o: o,
1307
+ n: n
1308
+ };
1309
+ }
1310
+
1311
+ return function(o, n){
1312
+ o = o.replace(/\s+$/, '');
1313
+ n = n.replace(/\s+$/, '');
1314
+ var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
1315
+
1316
+ var str = "";
1317
+
1318
+ var oSpace = o.match(/\s+/g);
1319
+ if (oSpace == null) {
1320
+ oSpace = [" "];
1321
+ }
1322
+ else {
1323
+ oSpace.push(" ");
1324
+ }
1325
+ var nSpace = n.match(/\s+/g);
1326
+ if (nSpace == null) {
1327
+ nSpace = [" "];
1328
+ }
1329
+ else {
1330
+ nSpace.push(" ");
1331
+ }
1332
+
1333
+ if (out.n.length == 0) {
1334
+ for (var i = 0; i < out.o.length; i++) {
1335
+ str += '<del>' + out.o[i] + oSpace[i] + "</del>";
1336
+ }
1337
+ }
1338
+ else {
1339
+ if (out.n[0].text == null) {
1340
+ for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
1341
+ str += '<del>' + out.o[n] + oSpace[n] + "</del>";
1342
+ }
1343
+ }
1344
+
1345
+ for (var i = 0; i < out.n.length; i++) {
1346
+ if (out.n[i].text == null) {
1347
+ str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
1348
+ }
1349
+ else {
1350
+ var pre = "";
1351
+
1352
+ for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
1353
+ pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
1354
+ }
1355
+ str += " " + out.n[i].text + nSpace[i] + pre;
1356
+ }
1357
+ }
1358
+ }
1359
+
1360
+ return str;
1361
+ };
1362
+ })();
1363
+
1364
+ })(this);
checklist.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Checklist
2
+
3
+ 1. Update jquery-tmpl and any other apps
4
+ * `cd apps/jquery-tmpl`
5
+ * `git fetch upstream`
6
+ * `git merge upstream/master`
7
+ * `git push origin master`
8
+ 2. Run build script: `make`
9
+ * compiles & minifies css/js
10
+ * concatenates into one file
11
+ 3. Update post-thumbnail-editor.php
12
+ * Change the version information in 2 places
13
+ * Set `PTE_DEBUG` to false (switch from dev files to minified ones)
14
+ 4. Modify README.txt
15
+ * Update the requires/tested version information
16
+ * Update the Upgrade Notice
17
+ * Update the Changelog
18
+ * Update screenshots (max-width: 532px)
19
+ * [Test README](http://wordpress.org/extend/plugins/about/validator/)
20
+ 5. Test on Firefox, Chrome, Safari, IE7/8/9 & Linux/Windows/Mac
21
+ * Do the rows change color on selection?
22
+ * Does the height get set correctly?
23
+ 6. Tag the git release
24
+ * `git tag [-a -m 'annotated tag'] version`
25
+ * `git push --tags`
26
+
css/pte.css CHANGED
@@ -1,18 +1,218 @@
1
- #pte-display {
2
- display: none;
3
- width: 600px;
4
- }
5
 
6
- #pte-edit {
7
- width: 400px;
8
- float: left;
9
- padding-right: 10px;
10
- }
11
 
12
- #pte-current img {
13
- width: 190px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- #pte-controls { clear: both; padding-top: 10px}
17
- #pte-controls #pte-save { margin-left: 20px; }
 
 
 
 
 
 
18
 
 
 
 
 
 
 
 
1
 
2
+ /* http://meyerweb.com/eric/tools/css/reset/
3
+ v2.0 | 20110126
4
+ License: none (public domain)
5
+ */
 
6
 
7
+ html, body, div, span, applet, object, iframe,
8
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
9
+ a, abbr, acronym, address, big, cite, code,
10
+ del, dfn, em, img, ins, kbd, q, s, samp,
11
+ small, strike, strong, sub, sup, tt, var,
12
+ b, u, i, center,
13
+ dl, dt, dd, ol, ul, li,
14
+ fieldset, form, label, legend,
15
+ table, caption, tbody, tfoot, thead, tr, th, td,
16
+ article, aside, canvas, details, embed,
17
+ figure, figcaption, footer, header, hgroup,
18
+ menu, nav, output, ruby, section, summary,
19
+ time, mark, audio, video {
20
+ margin: 0;
21
+ padding: 0;
22
+ border: 0;
23
+ font-size: 100%;
24
+ font: inherit;
25
+ vertical-align: baseline;
26
+ }
27
+ /* HTML5 display-role reset for older browsers */
28
+ article, aside, details, figcaption, figure,
29
+ footer, header, hgroup, menu, nav, section {
30
+ display: block;
31
+ }
32
+ body {
33
+ line-height: 1;
34
+ }
35
+ ol, ul {
36
+ list-style: none;
37
+ }
38
+ blockquote, q {
39
+ quotes: none;
40
+ }
41
+ blockquote:before, blockquote:after,
42
+ q:before, q:after {
43
+ content: '';
44
+ content: none;
45
  }
46
+ table {
47
+ border-collapse: collapse;
48
+ border-spacing: 0;
49
+ }
50
+ /* Generated variables */
51
+ a.stage-navigation, a.stage-navigation:visited {
52
+ color: #38ab36;
53
+ font-family: 'Amaranth', serif;
54
+ font-size: 0.8em;
55
+ font-style: italic;
56
+ text-decoration: none;
57
+ text-shadow: none; }
58
+ a.stage-navigation img, a.stage-navigation:visited img {
59
+ border: none;
60
+ vertical-align: bottom; }
61
+
62
+ a {
63
+ color: #444;
64
+ font-family: 'Amaranth', serif;
65
+ font-style: italic;
66
+ text-shadow: none; }
67
+ a:visited {
68
+ color: #black; }
69
+ a img {
70
+ vertical-align: bottom; }
71
+
72
+ h1 {
73
+ color: #2386e2;
74
+ font-family: 'Amaranth', serif;
75
+ font-style: italic;
76
+ font-size: 1.6em;
77
+ text-shadow: white 1px 1px 5px, 2px 2px 10px #999; }
78
+
79
+ body {
80
+ font-family: 'PT Serif', serif;
81
+ /*font-family: 'Puritan', serif;*/
82
+ /*overflow: auto;*/
83
+ overflow-x: hidden;
84
+ margin: auto;
85
+ max-width: 750px;
86
+ background-color: #efefef;
87
+ /*position: relative;*/
88
+ /*border: 1px solid black;*/ }
89
+
90
+ #pte-image {
91
+ float: left;
92
+ margin-top: 5px;
93
+ width: 402px; }
94
+ #pte-image img {
95
+ display: block;
96
+ margin: auto; }
97
+
98
+ #pte-buttons button {
99
+ font-family: "Amaranth", Tahoma, sans-serif;
100
+ font-size: larger;
101
+ line-height: 130%;
102
+ margin: 10px auto;
103
+ padding: 10px;
104
+ width: 100%; }
105
+
106
+ #pte-confirm {
107
+ font-family: "Amaranth", Tahoma, sans-serif;
108
+ font-size: larger;
109
+ line-height: 130%;
110
+ margin: 10px auto;
111
+ padding: 10px;
112
+ width: 75%; }
113
+
114
+ #pte-sizes-container {
115
+ overflow: auto;
116
+ padding-left: 15px;
117
+ float: left;
118
+ width: 331px; }
119
+
120
+ #pte-selectors, #pte-stage2-selectors {
121
+ margin-bottom: 10px; }
122
+
123
+ #pte-sizes {
124
+ overflow-x: hidden;
125
+ overflow-y: scroll;
126
+ position: relative;
127
+ border: 1px solid #dddddd;
128
+ /*width: $pte-sizes-width;*/
129
+ /*width: 100%;*/ }
130
+ #pte-sizes img {
131
+ max-width: 296px; }
132
+
133
+ table tr {
134
+ border-bottom: 1px solid #dddddd; }
135
+ table tr.selected {
136
+ background-color: #fff; }
137
+
138
+ table td {
139
+ position: relative;
140
+ vertical-align: middle;
141
+ padding: 15px 0; }
142
+
143
+ /*.col1 { */
144
+ /*width: 50px; */
145
+ /*}*/
146
+ /*.col2 { */
147
+ /* padding-right: 20px; */
148
+ /*}*/
149
+ .pte-size-label {
150
+ /*background: #bcbcbc;*/
151
+ background: #cdcdcd;
152
+ bottom: 0;
153
+ font-family: 'Amaranth', serif;
154
+ font-weight: bolder;
155
+ padding: 5px 0px 7px 5px;
156
+ /*padding: 5px;*/ }
157
+ .pte-size-label .actual {
158
+ font-size: 0.8em;
159
+ font-weight: normal; }
160
+
161
+ .pte-edit-label {
162
+ display: block; }
163
+
164
+ #pte-loading {
165
+ height: 100%;
166
+ position: absolute;
167
+ top: 0;
168
+ left: 0;
169
+ width: 100%; }
170
+ #pte-loading #pte-loading-opaque {
171
+ background-color: #000;
172
+ height: 100%;
173
+ position: absolute;
174
+ top: 0;
175
+ left: 0;
176
+ width: 100%;
177
+ opacity: 0.8;
178
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
179
+ filter: alpha(opacity=80); }
180
+ #pte-loading #pte-loading-spinner {
181
+ position: relative;
182
+ top: 50%;
183
+ width: 200px;
184
+ margin: 0 auto;
185
+ text-align: center; }
186
+
187
+ .stage {
188
+ float: left;
189
+ left: 0;
190
+ position: relative;
191
+ top: 0;
192
+ /*overflow: hidden;*/
193
+ /*width: $width;*/ }
194
+
195
+ #stage2, #stage3 {
196
+ display: none;
197
+ left: 1500px;
198
+ width: 750px; }
199
+
200
+ table {
201
+ width: 100%; }
202
+
203
+ #stage2 img {
204
+ /*max-width: 100%;*/
205
+ max-width: 710px; }
206
 
207
+ #error {
208
+ color: #aa0000; }
209
+ #error ul {
210
+ list-style: disc;
211
+ margin: 10px 0px 10px 20px;
212
+ /*li { */
213
+ /* list-style-image: 'disc';*/
214
+ /*} */ }
215
 
216
+ #success {
217
+ color: #38ab36;
218
+ font-size: 1.5em; }
css/pte.min.css ADDED
@@ -0,0 +1 @@
 
1
+ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}a.stage-navigation,a.stage-navigation:visited{color:#38ab36;font-family:'Amaranth',serif;font-size:.8em;font-style:italic;text-decoration:none;text-shadow:none}a.stage-navigation img,a.stage-navigation:visited img{border:0;vertical-align:bottom}a{color:#444;font-family:'Amaranth',serif;font-style:italic;text-shadow:none}a:visited{color:#black}a img{vertical-align:bottom}h1{color:#2386e2;font-family:'Amaranth',serif;font-style:italic;font-size:1.6em;text-shadow:white 1px 1px 5px,2px 2px 10px #999}body{font-family:'PT Serif',serif;overflow-x:hidden;margin:auto;max-width:750px;background-color:#efefef}#pte-image{float:left;margin-top:5px;width:402px}#pte-image img{display:block;margin:auto}#pte-buttons button{font-family:"Amaranth",Tahoma,sans-serif;font-size:larger;line-height:130%;margin:10px auto;padding:10px;width:100%}#pte-confirm{font-family:"Amaranth",Tahoma,sans-serif;font-size:larger;line-height:130%;margin:10px auto;padding:10px;width:75%}#pte-sizes-container{overflow:auto;padding-left:15px;float:left;width:331px}#pte-selectors,#pte-stage2-selectors{margin-bottom:10px}#pte-sizes{overflow-x:hidden;overflow-y:scroll;position:relative;border:1px solid #ddd}#pte-sizes img{max-width:296px}table tr{border-bottom:1px solid #ddd}table tr.selected{background-color:#fff}table td{position:relative;vertical-align:middle;padding:15px 0}.pte-size-label{background:#cdcdcd;bottom:0;font-family:'Amaranth',serif;font-weight:bolder;padding:5px 0 7px 5px}.pte-size-label .actual{font-size:.8em;font-weight:normal}.pte-edit-label{display:block}#pte-loading{height:100%;position:absolute;top:0;left:0;width:100%}#pte-loading #pte-loading-opaque{background-color:#000;height:100%;position:absolute;top:0;left:0;width:100%;opacity:.8;-ms-filter:"alpha(opacity=80)";filter:alpha(opacity=80)}#pte-loading #pte-loading-spinner{position:relative;top:50%;width:200px;margin:0 auto;text-align:center}.stage{float:left;left:0;position:relative;top:0}#stage2,#stage3{display:none;left:1500px;width:750px}table{width:100%}#stage2 img{max-width:710px}#error{color:#a00}#error ul{list-style:disc;margin:10px 0 10px 20px}#success{color:#38ab36;font-size:1.5em}
css/pte.scss ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $width: 750px;
2
+ $wp-picture-width: 400px;
3
+ $pte-sizes-container-padding: 15px;
4
+ $table-border: #ddd;
5
+
6
+ /* Generated variables */
7
+ $pte-sizes-width: $width - $wp-picture-width - $pte-sizes-container-padding - 4;
8
+ $pte-sizes-img-width: $pte-sizes-width - 35px;
9
+ $green: #38ab36;
10
+
11
+
12
+ a.stage-navigation, a.stage-navigation:visited {
13
+ color: $green;
14
+ font-family: 'Amaranth', serif;
15
+ font-size: 0.8em;
16
+ font-style: italic;
17
+ text-decoration: none;
18
+ text-shadow: none;
19
+ img {
20
+ border: none;
21
+ vertical-align: bottom;
22
+ }
23
+ }
24
+
25
+ a {
26
+ color: #444;
27
+ font-family: 'Amaranth', serif;
28
+ font-style: italic;
29
+ text-shadow: none;
30
+ &:visited {
31
+ color: #black;
32
+ }
33
+ img {
34
+ vertical-align: bottom;
35
+ }
36
+ }
37
+
38
+ h1, {
39
+ color: #2386e2;
40
+ font-family: 'Amaranth', serif;
41
+ font-style: italic;
42
+ font-size: 1.6em;
43
+ text-shadow: white 1px 1px 5px, 2px 2px 10px #999;
44
+ }
45
+
46
+ body {
47
+ font-family: 'PT Serif', serif;
48
+ /*font-family: 'Puritan', serif;*/
49
+ /*overflow: auto;*/
50
+ overflow-x: hidden;
51
+ margin: auto;
52
+ max-width: $width;
53
+ background-color: #efefef;
54
+ /*position: relative;*/
55
+ /*border: 1px solid black;*/
56
+ }
57
+
58
+ #pte-image {
59
+ float:left;
60
+ margin-top: 5px;
61
+ width: $wp-picture-width + 2;
62
+ img {
63
+ display: block;
64
+ margin: auto;
65
+ }
66
+ }
67
+
68
+ @mixin button {
69
+ font-family: "Amaranth", Tahoma, sans-serif;
70
+ font-size: larger;
71
+ line-height: 130%;
72
+ margin: 10px auto;
73
+ padding: 10px;
74
+ }
75
+ #pte-buttons button {
76
+ @include button;
77
+ width: 100%;
78
+ }
79
+ #pte-confirm {
80
+ @include button;
81
+ width: 75%;
82
+ }
83
+
84
+ #pte-sizes-container {
85
+ overflow: auto;
86
+ padding-left: $pte-sizes-container-padding;
87
+ float: left;
88
+ width: $pte-sizes-width;
89
+ }
90
+
91
+ #pte-selectors, #pte-stage2-selectors{
92
+ margin-bottom: 10px;
93
+ }
94
+
95
+ #pte-sizes {
96
+ overflow-x: hidden;
97
+ overflow-y: scroll;
98
+ position: relative;
99
+ border: 1px solid $table-border;
100
+ /*width: $pte-sizes-width;*/
101
+ /*width: 100%;*/
102
+ img {
103
+ max-width: $pte-sizes-img-width;
104
+ }
105
+ }
106
+
107
+ table tr {
108
+ border-bottom: 1px solid $table-border;
109
+ &.selected {
110
+ background-color: #fff;
111
+ }
112
+ }
113
+
114
+ table td {
115
+ position: relative;
116
+ vertical-align: middle;
117
+ padding: 15px 0;
118
+ }
119
+ /*.col1 { */
120
+ /*width: 50px; */
121
+ /*}*/
122
+ /*.col2 { */
123
+ /* padding-right: 20px; */
124
+ /*}*/
125
+
126
+ .pte-size-label {
127
+ /*background: #bcbcbc;*/
128
+ background: #cdcdcd;
129
+ bottom: 0;
130
+ font-family: 'Amaranth', serif;
131
+ font-weight: bolder;
132
+ padding: 5px 0px 7px 5px;
133
+ /*padding: 5px;*/
134
+ .actual {
135
+ font-size: 0.8em;
136
+ font-weight: normal;
137
+ }
138
+ }
139
+
140
+ .pte-edit-label {
141
+ display: block
142
+ }
143
+
144
+ @mixin full-screen {
145
+ height: 100%;
146
+ position: absolute;
147
+ top: 0;
148
+ left: 0;
149
+ width: 100%;
150
+ }
151
+
152
+ #pte-loading {
153
+ $opacity: 80;
154
+ $opacity_percent: $opacity/100;
155
+ @include full-screen;
156
+ #pte-loading-opaque {
157
+ background-color: #000;
158
+ @include full-screen;
159
+ opacity: $opacity_percent;
160
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + $opacity + ")";
161
+ filter: alpha(opacity=$opacity);
162
+ }
163
+ #pte-loading-spinner {
164
+ position: relative;
165
+ top: 50%;
166
+ width: 200px;
167
+ margin: 0 auto;
168
+ text-align: center;
169
+ }
170
+ }
171
+
172
+ .stage {
173
+ float: left;
174
+ left: 0;
175
+ position: relative;
176
+ top: 0;
177
+ /*overflow: hidden;*/
178
+ /*width: $width;*/
179
+ }
180
+
181
+ #stage2, #stage3 {
182
+ display: none;
183
+ left: $width * 2;
184
+ width: $width;
185
+ }
186
+
187
+ table {
188
+ width: 100%;
189
+ }
190
+
191
+ #stage2 img{
192
+ /*max-width: 100%;*/
193
+ max-width: 710px;
194
+ }
195
+
196
+ #error {
197
+ color: #aa0000;
198
+ ul {
199
+ list-style: disc;
200
+ margin: 10px 0px 10px 20px;
201
+ /*li { */
202
+ /* list-style-image: 'disc';*/
203
+ /*} */
204
+ }
205
+ }
206
+
207
+ #success {
208
+ color: $green;
209
+ font-size: 1.5em;
210
+ }
css/reset.css ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /* http://meyerweb.com/eric/tools/css/reset/
3
+ v2.0 | 20110126
4
+ License: none (public domain)
5
+ */
6
+
7
+ html, body, div, span, applet, object, iframe,
8
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
9
+ a, abbr, acronym, address, big, cite, code,
10
+ del, dfn, em, img, ins, kbd, q, s, samp,
11
+ small, strike, strong, sub, sup, tt, var,
12
+ b, u, i, center,
13
+ dl, dt, dd, ol, ul, li,
14
+ fieldset, form, label, legend,
15
+ table, caption, tbody, tfoot, thead, tr, th, td,
16
+ article, aside, canvas, details, embed,
17
+ figure, figcaption, footer, header, hgroup,
18
+ menu, nav, output, ruby, section, summary,
19
+ time, mark, audio, video {
20
+ margin: 0;
21
+ padding: 0;
22
+ border: 0;
23
+ font-size: 100%;
24
+ font: inherit;
25
+ vertical-align: baseline;
26
+ }
27
+ /* HTML5 display-role reset for older browsers */
28
+ article, aside, details, figcaption, figure,
29
+ footer, header, hgroup, menu, nav, section {
30
+ display: block;
31
+ }
32
+ body {
33
+ line-height: 1;
34
+ }
35
+ ol, ul {
36
+ list-style: none;
37
+ }
38
+ blockquote, q {
39
+ quotes: none;
40
+ }
41
+ blockquote:before, blockquote:after,
42
+ q:before, q:after {
43
+ content: '';
44
+ content: none;
45
+ }
46
+ table {
47
+ border-collapse: collapse;
48
+ border-spacing: 0;
49
+ }
html/pte.html ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
5
+ <title>PTE</title>
6
+ <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Amaranth:regular,italic,bold|Puritan|PT+Serif">
7
+ <style type="text/css" media="screen">
8
+ </style>
9
+ <?php wp_print_styles(); ?>
10
+ <?php wp_print_scripts(); ?>
11
+ <script type="text/javascript" charset="utf-8">
12
+ ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
13
+ thumbnail_info = <?php print(json_encode($size_information)); ?>;
14
+ jQuery(function(){ pte.editor(); });<?php
15
+ if ( PTE_DEBUG ) {
16
+ print( "debug_enabled = true;" );
17
+ } ?>
18
+ </script>
19
+ </head>
20
+ <body>
21
+ <div id="stage1" class="stage">
22
+ <h1 class="stage-header">Post Thumbnail Editor - Step 1</h1>
23
+ <?php global $pte_errors;
24
+ if ( isset( $pte_errors ) && count( $pte_errors ) > 0 ): ?>
25
+ <script type="text/javascript" charset="utf-8">
26
+ var pte_errors = <?php print( json_encode( $pte_errors ) ); ?>
27
+ log(pte_errors);
28
+ </script>
29
+ <!-- <div id="error"><ul><?php
30
+ //print_r($pte_errors);
31
+ foreach ( $pte_errors as $error_message ){
32
+ print( "<li>${error_message}</li>\r\n" );
33
+ }
34
+ ?></ul></div> -->
35
+ <?php endif; ?>
36
+ <div id="pte-image">
37
+ <input type="hidden" id="pte-sizer" value="<?php echo $sizer; ?>" />
38
+ <input type="hidden" id="pte-post-id" value="<?php echo $id; ?>" />
39
+ <img id="pte-preview" src="<?php echo admin_url('admin-ajax.php'); ?>?action=imgedit-preview&amp;_ajax_nonce=<?php echo $nonce; ?>&amp;postid=<?php echo $id; ?>&amp;rand=<?php echo rand(1, 99999); ?>" />
40
+ <div id="pte-buttons" class="buttons">
41
+ <button disabled id="pte-submit">Create Thumbnails</button>
42
+ </div>
43
+
44
+ </div>
45
+ <div id="pte-sizes-container">
46
+ <div style="font-size:smaller;">
47
+ Choose the images/thumbnails that you want to edit:<br>
48
+ </div>
49
+ <div id="pte-selectors">
50
+ Select: <a class="all" href="all">All</a> | <a class="none" href="none">None</a>
51
+ </div>
52
+ <div id="pte-sizes">
53
+ <table>
54
+ <?php foreach ( $size_information as $size_label => $size_array ): ?>
55
+ <tr>
56
+ <td class="col1">
57
+ <input class="pte-size" id="pte-size-<?php print $size_label; ?>" type="checkbox" name="pte-size[]" value="<?php print $size_label; ?>">
58
+ </td>
59
+ <td class="col2">
60
+ <div class="pte-size-label"><?php print $size_label; ?> <?php
61
+ print("(${size_array['width']}x${size_array['height']})");
62
+ print("<br><span class='actual'>Current image: "
63
+ . $size_array['current']['width'] . "x"
64
+ . $size_array['current']['height'] . "</span>");
65
+ ?></div>
66
+ <img src="<?php print( $size_array['current']['url'] . "?" . mt_rand() ); ?>"/><br/>
67
+ </td>
68
+ </tr>
69
+ <?php endforeach; ?>
70
+ </table>
71
+ </div>
72
+ </div>
73
+
74
+ </div>
75
+ <div id="stage2" class="stage">
76
+ </div>
77
+ <script id="stage2template" type="text/x-jquery-tmpl">
78
+ <a onclick="goBack(); return false;" href="#back" class="stage-navigation"
79
+ alt="Return to Step 1" title="Return to Step 1">
80
+ <img src="<?php print( PTE_PLUGINURL . "images/back.gif" ); ?>"/> Back</a>
81
+ <h1 class="stage-header"> Post Thumbnail Editor - Step 2</h1>
82
+ {{if $data['error']}}
83
+ <div id="error">We noticed some potential issues:
84
+ <ul>
85
+ {{each $data['error']}}<li>${$value}</li>{{/each}}
86
+ </ul>
87
+ </div>
88
+ {{/if}}
89
+ <div id="pte-stage2-selectors">
90
+ Select the images you want to keep: <a class="all" href="all">All</a> | <a class="none" href="none">None</a>
91
+ </div>
92
+ <input type="hidden" name="pte-nonce" value="${$data['pte-nonce']}" id="pte-nonce" />
93
+ <input type="hidden" name="pte-delete-nonce" value="${$data['pte-delete-nonce']}" id="pte-delete-nonce" />
94
+ <table>
95
+ {{each $data.thumbnails}}
96
+ <tr class="selected">
97
+ <td><input checked class="pte-confirm" type="checkbox" name="pte_confirm[]" value="${$index}"/></td>
98
+ <td class="col2">
99
+ <div class="pte-size-label">${$index}</div>
100
+ <img src="${$value.url}?${randomness()}"/>
101
+ <input id="pte-${$index}-file" type="hidden" value="${$value.file}"/>
102
+ </td>
103
+ </tr>
104
+ {{/each}}
105
+ </table>
106
+ <div id="stage2-buttons">
107
+ <button id="pte-confirm">
108
+ Okay, these look good...
109
+ </button>&nbsp;
110
+ <a href="#back" id="pte-cancel"
111
+ onclick="goBack(); return false;">
112
+ I'd rather start over...
113
+ </a>
114
+ </a>
115
+ </script>
116
+ <div id="stage3" class="stage">
117
+ </div>
118
+ <script id="stage3template" type="text/x-jquery-tmpl">
119
+ <h1 class="stage-header"> Post Thumbnail Editor</h1>
120
+ {{if $data['success']}}
121
+ <div id="success">
122
+ <p>Images were created successfully.</p>
123
+ <p>Click <a href="" onclick="window.location.reload();">here</a> to modify another thumbnail.</p>
124
+ </div>
125
+ {{if $data['error']}}
126
+ <div id="error">We noticed some potential issues however:
127
+ <ul>
128
+ {{each $data['error']}}<li>${$value}</li>{{/each}}
129
+ </ul>
130
+ </div>
131
+ {{/if}}
132
+ {{/if}}
133
+ </script>
134
+ <div id="pte-loading">
135
+ <div id="pte-loading-opaque"></div>
136
+ <div id="pte-loading-spinner">
137
+ <img src="<?php print PTE_PLUGINURL; ?>images/loading.gif" alt="Please wait" />
138
+ </div></div>
139
+ <div style='clear:both'></div>
140
+ </body>
141
+ </html>
images/back.gif ADDED
Binary file
images/loading.gif ADDED
Binary file
js/header.coffee ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ window = @
2
+ $ = window.jQuery
3
+
4
+ # Call this as
5
+ # <script>
6
+ # $(function(){ pte.admin() });
7
+ # </script>
8
+ window.pte = pte = pte || {}
js/log.coffee ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ window.log = (obj) ->
2
+ return true if not window.debug_enabled
3
+ try
4
+ console.log obj
5
+ catch error
6
+ alert obj
7
+ true
js/pte.coffee ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # TODO:
2
+ # If the aspect ratio is shared by all images then set it
3
+ class TimerFunc
4
+ constructor: (@fn, @timeout) ->
5
+ @timer = null
6
+ doFunc: (e) =>
7
+ window.clearTimeout @timer
8
+ @timer = window.setTimeout @fn, @timeout
9
+ true
10
+
11
+ window.randomness = ->
12
+ Math.floor(Math.random()*1000001).toString(16)
13
+
14
+ window.debugTmpl = (data) ->
15
+ log data
16
+ true
17
+
18
+ # ===========================================================
19
+ # Change stages
20
+ # ===========================================================
21
+ window.goBack = (e) ->
22
+ e?.preventDefault()
23
+ $('#stage2').animate
24
+ left: 1200
25
+ , 500, 'swing', ->
26
+ # COMMENT: this = stage2
27
+ $(this).hide()
28
+ $('#stage1').show 0, ->
29
+ # this = stage1
30
+ $(this).animate
31
+ left: 0
32
+ , 500, 'swing', ->
33
+ log "okay cleanup"
34
+ # send cleanup request
35
+ delete_options =
36
+ "id": $('#pte-post-id').val()
37
+ 'action': 'pte_ajax'
38
+ 'pte-action': 'delete-images'
39
+ 'pte-nonce': $('#pte-delete-nonce').val()
40
+ # use ajax:global - false
41
+ $.ajax
42
+ url: ajaxurl,
43
+ data: delete_options
44
+ global: false
45
+ dataType: "json"
46
+ success: (data, status, xhr) ->
47
+ if data.error?
48
+ log data.error
49
+ else
50
+ log "Deleted tmp files"
51
+
52
+
53
+
54
+ gcd = (a, b) ->
55
+ return b if a is 0
56
+ while b > 0
57
+ if a > b
58
+ a = a - b
59
+ else
60
+ b = b - a
61
+ if a < 0 or b < 0 then return null
62
+ a
63
+
64
+ # functionally take a list of sizes
65
+ # convert to crop/width/height
66
+ # determine current ar and test against other ar's
67
+ # throw exception if more than 1?
68
+ # _(list).reduce( determineAspectRatio , ar)
69
+ determineAspectRatio = (current_ar, size) ->
70
+ {crop, width, height} = thumbnail_info[size]
71
+ crop = +crop
72
+ width = +width
73
+ height = +height
74
+ gc = gcd width, height
75
+ if crop? and crop > 0
76
+ tmp_ar = null
77
+ if (width? > 0 and height? > 0)
78
+ if gc?
79
+ tmp_ar = "#{ width / gc }:#{ height / gc }"
80
+ else
81
+ tmp_ar = "#{ width }:#{ height }"
82
+ if current_ar? and tmp_ar? and tmp_ar isnt current_ar
83
+ #alert "2 images are trying to set different aspect ratios, disabling..."
84
+ throw "Too many Aspect Ratios. Disabling"
85
+ current_ar = tmp_ar
86
+
87
+ do (pte) ->
88
+ # Call this on page instantiation
89
+ editor = pte.editor = ->
90
+ setPageHeight()
91
+ addRowListeners()
92
+ initImgAreaSelect()
93
+ addRowListener()
94
+ addSubmitListener()
95
+ addVerifyListener()
96
+ addCheckAllNoneListener()
97
+
98
+ # ===========================================================
99
+ # This is our loading div
100
+ # ===========================================================
101
+ $loading_screen = $('#pte-loading')
102
+ closeLoadingScreen = ->
103
+ log "Closing load screen"
104
+ $loading_screen.hide()
105
+ true
106
+ $('#pte-preview').load closeLoadingScreen
107
+ $loading_screen
108
+ .ajaxStart( ->
109
+ $(this).fadeIn 200
110
+ ).ajaxStop( ->
111
+ $(this).fadeOut 200
112
+ )
113
+ window.setTimeout closeLoadingScreen, 2000
114
+ true
115
+
116
+
117
+
118
+
119
+ # ===========================================================
120
+ # Set the height of the options
121
+ # ===========================================================
122
+ # Sets a timeout to be a little bit more responsive
123
+ setPageHeight = ->
124
+ reflow = new TimerFunc ->
125
+ log "reflow called..."
126
+ offset = $("#pte-sizes").offset()
127
+ window_height = $(window).height() - offset.top - 2
128
+ $("#pte-sizes").height window_height
129
+ , 100
130
+ # Add to the resize and load events
131
+ $(window).resize(reflow.doFunc).load(reflow.doFunc)
132
+
133
+
134
+ # ===========================================================
135
+ # Code to highlight selected rows
136
+ # ===========================================================
137
+ addRowListeners = ->
138
+ enableRowFeatures = ($elem) ->
139
+ #$('#stage2').delegate 'tr', 'click', (e) ->
140
+ $elem.delegate 'tr', 'click', (e) ->
141
+ if e.target.type isnt 'checkbox'
142
+ $('input:checkbox', this).click()
143
+ true
144
+ #$('#stage2').delegate ':checkbox', 'click', (e) ->
145
+ $elem.delegate 'input:checkbox', 'click', (e) ->
146
+ if this.checked or $(this).is('input:checked')
147
+ $(this).parents('tr').first().removeClass 'selected'
148
+ else
149
+ $(this).parents('tr').first().addClass 'selected'
150
+ true
151
+ enableRowFeatures $('#stage2')
152
+ enableRowFeatures $('#stage1')
153
+ # ===========================================================
154
+
155
+
156
+
157
+
158
+ # ===========================================================
159
+ ### Enable imgareaselect plugin ###
160
+ # ===========================================================
161
+ ias_instance = null
162
+ ias_defaults =
163
+ #parent: parent
164
+ keys: true
165
+ minWidth: 3
166
+ minHeight: 3
167
+ handles: true
168
+ zIndex: 1200
169
+ instance: true
170
+ onSelectEnd: (img, s) ->
171
+ if s.width && s.width > 0 and s.height && s.height > 0 and $('.pte-size').filter(':checked').size() > 0
172
+ log "Enabling button"
173
+ $('#pte-submit').removeAttr('disabled')
174
+ else
175
+ log "Disabling button"
176
+ $('#pte-submit').attr('disabled', true)
177
+
178
+
179
+ initImgAreaSelect = ->
180
+ ias_instance = $('#pte-image img').imgAreaSelect ias_defaults
181
+ iasSetAR = (ar) ->
182
+ log "setting aspectRatio: #{ ar }"
183
+ ias_instance.setOptions
184
+ aspectRatio: ar
185
+ ias_instance.update()
186
+
187
+
188
+
189
+
190
+ # ===========================================================
191
+ # Setting aspectRatio
192
+ # This is what happens when a box is checked
193
+ # Functional call to reduce would work well here (underscore.js)
194
+ #
195
+ # TODO: Fix when ar is disabled, don't tell the user until you renable it
196
+ # and disable it again
197
+ # ===========================================================
198
+ addRowListener = ->
199
+ pteCheckHandler = new TimerFunc ->
200
+ #log "# checked: #{ $('.pte-size:checked').size() }"
201
+ ar = null
202
+ selected_elements = $('input.pte-size').filter(':checked').each (i,elem) ->
203
+ try
204
+ ar = determineAspectRatio ar, $(elem).val()
205
+ catch error
206
+ ar = null
207
+ if ar isnt ias_instance.getOptions().aspectRatio
208
+ alert error
209
+ return false
210
+ true
211
+ iasSetAR ar
212
+
213
+ # Call our check to set the buttons' ability/disability
214
+ ias_defaults.onSelectEnd null, ias_instance.getSelection()
215
+ true
216
+ , 50
217
+ $('input.pte-size').click pteCheckHandler.doFunc
218
+
219
+
220
+ # ===========================================================
221
+ ### Callback for resizing images (Stage 1 to 2) ###
222
+ # ===========================================================
223
+ # What do you do when you click submit --> onResizeImages
224
+ addSubmitListener = ->
225
+ $('#pte-submit').click (e) ->
226
+ log "Clicked Submit..."
227
+ selection = ias_instance.getSelection()
228
+ scale_factor = $('#pte-sizer').val()
229
+ submit_data =
230
+ 'id': $('#pte-post-id').val()
231
+ 'action': 'pte_ajax'
232
+ 'pte-action': 'resize-images'
233
+ 'pte-sizes[]': $('.pte-size').filter(':checked').map(->
234
+ $(this).val()
235
+ ).get()
236
+ 'x': Math.floor(selection.x1/scale_factor)
237
+ 'y': Math.floor(selection.y1/scale_factor)
238
+ 'w': Math.floor(selection.width/scale_factor)
239
+ 'h': Math.floor(selection.height/scale_factor)
240
+ log submit_data
241
+ ias_instance.setOptions
242
+ hide: true
243
+ x1: 0
244
+ y1: 0
245
+ x2: 0
246
+ y2: 0
247
+
248
+ #$('#pte-loading').fadeToggle 200
249
+ # Disable button
250
+ $('#pte-submit').attr('disabled', true)
251
+ $.getJSON(ajaxurl, submit_data, onResizeImages)
252
+ true
253
+
254
+ onResizeImages = (data, status, xhr) ->
255
+ ### Evaluate data ###
256
+ log data
257
+ if data.error? and not data.thumbnails?
258
+ alert(data.error)
259
+ return
260
+
261
+ $('#stage1').animate
262
+ left: -$(window).width()
263
+ , 500, 'swing', ->
264
+ $(this).hide()
265
+ $('#stage2').html($('#stage2template').tmpl(data)).show(0, ->
266
+ $(this).animate(
267
+ left: 0
268
+ , 500)
269
+ true
270
+ )
271
+ #$('#stage2').animate({left: 0}, 500)
272
+ true
273
+ false
274
+ # ===========================================================
275
+
276
+ # ===========================================================
277
+ ### Callback for Stage 2 to 3 ###
278
+ # ===========================================================
279
+ addVerifyListener = ->
280
+ $('#pte-confirm').live 'click', (e) ->
281
+ log "Confirming"
282
+ thumbnail_data = {}
283
+ $('input.pte-confirm').filter(':checked').each (i, elem) ->
284
+ size = $(elem).val()
285
+ thumbnail_data[size] = $("\#pte-#{ size }-file").val()
286
+ submit_data =
287
+ 'id': $('#pte-post-id').val()
288
+ 'action': 'pte_ajax'
289
+ 'pte-action': 'confirm-images'
290
+ 'pte-nonce': $('#pte-nonce').val()
291
+ 'pte-confirm': thumbnail_data
292
+ log submit_data
293
+ $.getJSON(ajaxurl, submit_data, onConfirmImages)
294
+
295
+ onConfirmImages = (data, status, xhr) ->
296
+ log data
297
+ $('#stage2').animate
298
+ left: -$(window).width()
299
+ , 500, 'swing', ->
300
+ $(this).hide()
301
+ $('#stage3').html($('#stage3template').tmpl(data)).show(0, ->
302
+ $(this).animate(
303
+ left: 0
304
+ , 500)
305
+ true
306
+ )
307
+ true
308
+ false
309
+ # ===========================================================
310
+
311
+ # ===========================================================
312
+ ### Select ALL|NONE ###
313
+ # ===========================================================
314
+ # Let the user quickly check/uncheck all the items
315
+ addCheckAllNoneListener = ->
316
+ uncheckAllSizes = (e) ->
317
+ e?.preventDefault()
318
+ elements = e.data?.selector ? '.pte-size'
319
+ #$('.pte-size').filter(':checked').click()
320
+ #log elements
321
+ $(elements).filter(':checked').click()
322
+
323
+ checkAllSizes = (e) ->
324
+ e?.preventDefault()
325
+ elements = e?.data?.selector ? '.pte-size'
326
+ #log elements
327
+ #$('.pte-size').not(':checked').click()
328
+ $(elements).not(':checked').click()
329
+
330
+ $("#pte-selectors .all").click(checkAllSizes)
331
+ $("#pte-selectors .none").click(uncheckAllSizes).click()
332
+ $('#stage2').delegate '#pte-stage2-selectors .all', 'click', {selector: '.pte-confirm'}, checkAllSizes
333
+ $('#stage2').delegate '#pte-stage2-selectors .none', 'click', {selector: '.pte-confirm'}, uncheckAllSizes
334
+
335
+ # Finished
336
+ true
337
+
js/pte.full.js ADDED
@@ -0,0 +1,915 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery Templates Plugin 1.0.0pre
3
+ * http://github.com/jquery/jquery-tmpl
4
+ * Requires jQuery 1.4.2
5
+ *
6
+ * Copyright Software Freedom Conservancy, Inc.
7
+ * Dual licensed under the MIT or GPL Version 2 licenses.
8
+ * http://jquery.org/license
9
+ */
10
+ (function( jQuery, undefined ){
11
+ var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
12
+ newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
13
+
14
+ function newTmplItem( options, parentItem, fn, data ) {
15
+ // Returns a template item data structure for a new rendered instance of a template (a 'template item').
16
+ // The content field is a hierarchical array of strings and nested items (to be
17
+ // removed and replaced by nodes field of dom elements, once inserted in DOM).
18
+ var newItem = {
19
+ data: data || (data === 0 || data === false) ? data : (parentItem ? parentItem.data : {}),
20
+ _wrap: parentItem ? parentItem._wrap : null,
21
+ tmpl: null,
22
+ parent: parentItem || null,
23
+ nodes: [],
24
+ calls: tiCalls,
25
+ nest: tiNest,
26
+ wrap: tiWrap,
27
+ html: tiHtml,
28
+ update: tiUpdate
29
+ };
30
+ if ( options ) {
31
+ jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
32
+ }
33
+ if ( fn ) {
34
+ // Build the hierarchical content to be used during insertion into DOM
35
+ newItem.tmpl = fn;
36
+ newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
37
+ newItem.key = ++itemKey;
38
+ // Keep track of new template item, until it is stored as jQuery Data on DOM element
39
+ (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
40
+ }
41
+ return newItem;
42
+ }
43
+
44
+ // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
45
+ jQuery.each({
46
+ appendTo: "append",
47
+ prependTo: "prepend",
48
+ insertBefore: "before",
49
+ insertAfter: "after",
50
+ replaceAll: "replaceWith"
51
+ }, function( name, original ) {
52
+ jQuery.fn[ name ] = function( selector ) {
53
+ var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems,
54
+ parent = this.length === 1 && this[0].parentNode;
55
+
56
+ appendToTmplItems = newTmplItems || {};
57
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
58
+ insert[ original ]( this[0] );
59
+ ret = this;
60
+ } else {
61
+ for ( i = 0, l = insert.length; i < l; i++ ) {
62
+ cloneIndex = i;
63
+ elems = (i > 0 ? this.clone(true) : this).get();
64
+ jQuery( insert[i] )[ original ]( elems );
65
+ ret = ret.concat( elems );
66
+ }
67
+ cloneIndex = 0;
68
+ ret = this.pushStack( ret, name, insert.selector );
69
+ }
70
+ tmplItems = appendToTmplItems;
71
+ appendToTmplItems = null;
72
+ jQuery.tmpl.complete( tmplItems );
73
+ return ret;
74
+ };
75
+ });
76
+
77
+ jQuery.fn.extend({
78
+ // Use first wrapped element as template markup.
79
+ // Return wrapped set of template items, obtained by rendering template against data.
80
+ tmpl: function( data, options, parentItem ) {
81
+ return jQuery.tmpl( this[0], data, options, parentItem );
82
+ },
83
+
84
+ // Find which rendered template item the first wrapped DOM element belongs to
85
+ tmplItem: function() {
86
+ return jQuery.tmplItem( this[0] );
87
+ },
88
+
89
+ // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
90
+ template: function( name ) {
91
+ return jQuery.template( name, this[0] );
92
+ },
93
+
94
+ domManip: function( args, table, callback, options ) {
95
+ if ( args[0] && jQuery.isArray( args[0] )) {
96
+ var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
97
+ while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
98
+ if ( tmplItem && cloneIndex ) {
99
+ dmArgs[2] = function( fragClone ) {
100
+ // Handler called by oldManip when rendered template has been inserted into DOM.
101
+ jQuery.tmpl.afterManip( this, fragClone, callback );
102
+ };
103
+ }
104
+ oldManip.apply( this, dmArgs );
105
+ } else {
106
+ oldManip.apply( this, arguments );
107
+ }
108
+ cloneIndex = 0;
109
+ if ( !appendToTmplItems ) {
110
+ jQuery.tmpl.complete( newTmplItems );
111
+ }
112
+ return this;
113
+ }
114
+ });
115
+
116
+ jQuery.extend({
117
+ // Return wrapped set of template items, obtained by rendering template against data.
118
+ tmpl: function( tmpl, data, options, parentItem ) {
119
+ var ret, topLevel = !parentItem;
120
+ if ( topLevel ) {
121
+ // This is a top-level tmpl call (not from a nested template using {{tmpl}})
122
+ parentItem = topTmplItem;
123
+ tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
124
+ wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
125
+ } else if ( !tmpl ) {
126
+ // The template item is already associated with DOM - this is a refresh.
127
+ // Re-evaluate rendered template for the parentItem
128
+ tmpl = parentItem.tmpl;
129
+ newTmplItems[parentItem.key] = parentItem;
130
+ parentItem.nodes = [];
131
+ if ( parentItem.wrapped ) {
132
+ updateWrapped( parentItem, parentItem.wrapped );
133
+ }
134
+ // Rebuild, without creating a new template item
135
+ return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
136
+ }
137
+ if ( !tmpl ) {
138
+ return []; // Could throw...
139
+ }
140
+ if ( typeof data === "function" ) {
141
+ data = data.call( parentItem || {} );
142
+ }
143
+ if ( options && options.wrapped ) {
144
+ updateWrapped( options, options.wrapped );
145
+ }
146
+ ret = jQuery.isArray( data ) ?
147
+ jQuery.map( data, function( dataItem ) {
148
+ return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
149
+ }) :
150
+ [ newTmplItem( options, parentItem, tmpl, data ) ];
151
+ return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
152
+ },
153
+
154
+ // Return rendered template item for an element.
155
+ tmplItem: function( elem ) {
156
+ var tmplItem;
157
+ if ( elem instanceof jQuery ) {
158
+ elem = elem[0];
159
+ }
160
+ while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
161
+ return tmplItem || topTmplItem;
162
+ },
163
+
164
+ // Set:
165
+ // Use $.template( name, tmpl ) to cache a named template,
166
+ // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
167
+ // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
168
+
169
+ // Get:
170
+ // Use $.template( name ) to access a cached template.
171
+ // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
172
+ // will return the compiled template, without adding a name reference.
173
+ // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
174
+ // to $.template( null, templateString )
175
+ template: function( name, tmpl ) {
176
+ if (tmpl) {
177
+ // Compile template and associate with name
178
+ if ( typeof tmpl === "string" ) {
179
+ // This is an HTML string being passed directly in.
180
+ tmpl = buildTmplFn( tmpl );
181
+ } else if ( tmpl instanceof jQuery ) {
182
+ tmpl = tmpl[0] || {};
183
+ }
184
+ if ( tmpl.nodeType ) {
185
+ // If this is a template block, use cached copy, or generate tmpl function and cache.
186
+ tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML ));
187
+ // Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space.
188
+ // This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x.
189
+ // To correct this, include space in tag: foo="${ x }" -> foo="value of x"
190
+ }
191
+ return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
192
+ }
193
+ // Return named compiled template
194
+ return name ? (typeof name !== "string" ? jQuery.template( null, name ):
195
+ (jQuery.template[name] ||
196
+ // If not in map, and not containing at least on HTML tag, treat as a selector.
197
+ // (If integrated with core, use quickExpr.exec)
198
+ jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null;
199
+ },
200
+
201
+ encode: function( text ) {
202
+ // Do HTML encoding replacing < > & and ' and " by corresponding entities.
203
+ return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
204
+ }
205
+ });
206
+
207
+ jQuery.extend( jQuery.tmpl, {
208
+ tag: {
209
+ "tmpl": {
210
+ _default: { $2: "null" },
211
+ open: "if($notnull_1){__=__.concat($item.nest($1,$2));}"
212
+ // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
213
+ // This means that {{tmpl foo}} treats foo as a template (which IS a function).
214
+ // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
215
+ },
216
+ "wrap": {
217
+ _default: { $2: "null" },
218
+ open: "$item.calls(__,$1,$2);__=[];",
219
+ close: "call=$item.calls();__=call._.concat($item.wrap(call,__));"
220
+ },
221
+ "each": {
222
+ _default: { $2: "$index, $value" },
223
+ open: "if($notnull_1){$.each($1a,function($2){with(this){",
224
+ close: "}});}"
225
+ },
226
+ "if": {
227
+ open: "if(($notnull_1) && $1a){",
228
+ close: "}"
229
+ },
230
+ "else": {
231
+ _default: { $1: "true" },
232
+ open: "}else if(($notnull_1) && $1a){"
233
+ },
234
+ "html": {
235
+ // Unecoded expression evaluation.
236
+ open: "if($notnull_1){__.push($1a);}"
237
+ },
238
+ "=": {
239
+ // Encoded expression evaluation. Abbreviated form is ${}.
240
+ _default: { $1: "$data" },
241
+ open: "if($notnull_1){__.push($.encode($1a));}"
242
+ },
243
+ "!": {
244
+ // Comment tag. Skipped by parser
245
+ open: ""
246
+ }
247
+ },
248
+
249
+ // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
250
+ complete: function( items ) {
251
+ newTmplItems = {};
252
+ },
253
+
254
+ // Call this from code which overrides domManip, or equivalent
255
+ // Manage cloning/storing template items etc.
256
+ afterManip: function afterManip( elem, fragClone, callback ) {
257
+ // Provides cloned fragment ready for fixup prior to and after insertion into DOM
258
+ var content = fragClone.nodeType === 11 ?
259
+ jQuery.makeArray(fragClone.childNodes) :
260
+ fragClone.nodeType === 1 ? [fragClone] : [];
261
+
262
+ // Return fragment to original caller (e.g. append) for DOM insertion
263
+ callback.call( elem, fragClone );
264
+
265
+ // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
266
+ storeTmplItems( content );
267
+ cloneIndex++;
268
+ }
269
+ });
270
+
271
+ //========================== Private helper functions, used by code above ==========================
272
+
273
+ function build( tmplItem, nested, content ) {
274
+ // Convert hierarchical content into flat string array
275
+ // and finally return array of fragments ready for DOM insertion
276
+ var frag, ret = content ? jQuery.map( content, function( item ) {
277
+ return (typeof item === "string") ?
278
+ // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
279
+ (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
280
+ // This is a child template item. Build nested template.
281
+ build( item, tmplItem, item._ctnt );
282
+ }) :
283
+ // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
284
+ tmplItem;
285
+ if ( nested ) {
286
+ return ret;
287
+ }
288
+
289
+ // top-level template
290
+ ret = ret.join("");
291
+
292
+ // Support templates which have initial or final text nodes, or consist only of text
293
+ // Also support HTML entities within the HTML markup.
294
+ ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
295
+ frag = jQuery( middle ).get();
296
+
297
+ storeTmplItems( frag );
298
+ if ( before ) {
299
+ frag = unencode( before ).concat(frag);
300
+ }
301
+ if ( after ) {
302
+ frag = frag.concat(unencode( after ));
303
+ }
304
+ });
305
+ return frag ? frag : unencode( ret );
306
+ }
307
+
308
+ function unencode( text ) {
309
+ // Use createElement, since createTextNode will not render HTML entities correctly
310
+ var el = document.createElement( "div" );
311
+ el.innerHTML = text;
312
+ return jQuery.makeArray(el.childNodes);
313
+ }
314
+
315
+ // Generate a reusable function that will serve to render a template against data
316
+ function buildTmplFn( markup ) {
317
+ return new Function("jQuery","$item",
318
+ // Use the variable __ to hold a string array while building the compiled template. (See https://github.com/jquery/jquery-tmpl/issues#issue/10).
319
+ "var $=jQuery,call,__=[],$data=$item.data;" +
320
+
321
+ // Introduce the data as local variables using with(){}
322
+ "with($data){__.push('" +
323
+
324
+ // Convert the template into pure JavaScript
325
+ jQuery.trim(markup)
326
+ .replace( /([\\'])/g, "\\$1" )
327
+ .replace( /[\r\t\n]/g, " " )
328
+ .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
329
+ .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
330
+ function( all, slash, type, fnargs, target, parens, args ) {
331
+ var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
332
+ if ( !tag ) {
333
+ throw "Unknown template tag: " + type;
334
+ }
335
+ def = tag._default || [];
336
+ if ( parens && !/\w$/.test(target)) {
337
+ target += parens;
338
+ parens = "";
339
+ }
340
+ if ( target ) {
341
+ target = unescape( target );
342
+ args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
343
+ // Support for target being things like a.toLowerCase();
344
+ // In that case don't call with template item as 'this' pointer. Just evaluate...
345
+ expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
346
+ exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
347
+ } else {
348
+ exprAutoFnDetect = expr = def.$1 || "null";
349
+ }
350
+ fnargs = unescape( fnargs );
351
+ return "');" +
352
+ tag[ slash ? "close" : "open" ]
353
+ .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
354
+ .split( "$1a" ).join( exprAutoFnDetect )
355
+ .split( "$1" ).join( expr )
356
+ .split( "$2" ).join( fnargs || def.$2 || "" ) +
357
+ "__.push('";
358
+ }) +
359
+ "');}return __;"
360
+ );
361
+ }
362
+ function updateWrapped( options, wrapped ) {
363
+ // Build the wrapped content.
364
+ options._wrap = build( options, true,
365
+ // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
366
+ jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
367
+ ).join("");
368
+ }
369
+
370
+ function unescape( args ) {
371
+ return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
372
+ }
373
+ function outerHtml( elem ) {
374
+ var div = document.createElement("div");
375
+ div.appendChild( elem.cloneNode(true) );
376
+ return div.innerHTML;
377
+ }
378
+
379
+ // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
380
+ function storeTmplItems( content ) {
381
+ var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
382
+ for ( i = 0, l = content.length; i < l; i++ ) {
383
+ if ( (elem = content[i]).nodeType !== 1 ) {
384
+ continue;
385
+ }
386
+ elems = elem.getElementsByTagName("*");
387
+ for ( m = elems.length - 1; m >= 0; m-- ) {
388
+ processItemKey( elems[m] );
389
+ }
390
+ processItemKey( elem );
391
+ }
392
+ function processItemKey( el ) {
393
+ var pntKey, pntNode = el, pntItem, tmplItem, key;
394
+ // Ensure that each rendered template inserted into the DOM has its own template item,
395
+ if ( (key = el.getAttribute( tmplItmAtt ))) {
396
+ while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
397
+ if ( pntKey !== key ) {
398
+ // The next ancestor with a _tmplitem expando is on a different key than this one.
399
+ // So this is a top-level element within this template item
400
+ // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
401
+ pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
402
+ if ( !(tmplItem = newTmplItems[key]) ) {
403
+ // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
404
+ tmplItem = wrappedItems[key];
405
+ tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
406
+ tmplItem.key = ++itemKey;
407
+ newTmplItems[itemKey] = tmplItem;
408
+ }
409
+ if ( cloneIndex ) {
410
+ cloneTmplItem( key );
411
+ }
412
+ }
413
+ el.removeAttribute( tmplItmAtt );
414
+ } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
415
+ // This was a rendered element, cloned during append or appendTo etc.
416
+ // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
417
+ cloneTmplItem( tmplItem.key );
418
+ newTmplItems[tmplItem.key] = tmplItem;
419
+ pntNode = jQuery.data( el.parentNode, "tmplItem" );
420
+ pntNode = pntNode ? pntNode.key : 0;
421
+ }
422
+ if ( tmplItem ) {
423
+ pntItem = tmplItem;
424
+ // Find the template item of the parent element.
425
+ // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
426
+ while ( pntItem && pntItem.key != pntNode ) {
427
+ // Add this element as a top-level node for this rendered template item, as well as for any
428
+ // ancestor items between this item and the item of its parent element
429
+ pntItem.nodes.push( el );
430
+ pntItem = pntItem.parent;
431
+ }
432
+ // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
433
+ delete tmplItem._ctnt;
434
+ delete tmplItem._wrap;
435
+ // Store template item as jQuery data on the element
436
+ jQuery.data( el, "tmplItem", tmplItem );
437
+ }
438
+ function cloneTmplItem( key ) {
439
+ key = key + keySuffix;
440
+ tmplItem = newClonedItems[key] =
441
+ (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
442
+ }
443
+ }
444
+ }
445
+
446
+ //---- Helper functions for template item ----
447
+
448
+ function tiCalls( content, tmpl, data, options ) {
449
+ if ( !content ) {
450
+ return stack.pop();
451
+ }
452
+ stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
453
+ }
454
+
455
+ function tiNest( tmpl, data, options ) {
456
+ // nested template, using {{tmpl}} tag
457
+ return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
458
+ }
459
+
460
+ function tiWrap( call, wrapped ) {
461
+ // nested template, using {{wrap}} tag
462
+ var options = call.options || {};
463
+ options.wrapped = wrapped;
464
+ // Apply the template, which may incorporate wrapped content,
465
+ return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
466
+ }
467
+
468
+ function tiHtml( filter, textOnly ) {
469
+ var wrapped = this._wrap;
470
+ return jQuery.map(
471
+ jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
472
+ function(e) {
473
+ return textOnly ?
474
+ e.innerText || e.textContent :
475
+ e.outerHTML || outerHtml(e);
476
+ });
477
+ }
478
+
479
+ function tiUpdate() {
480
+ var coll = this.nodes;
481
+ jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
482
+ jQuery( coll ).remove();
483
+ }
484
+ })( jQuery );
485
+ (function() {
486
+ var $, TimerFunc, determineAspectRatio, gcd, pte, window;
487
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
488
+ window = this;
489
+ $ = window.jQuery;
490
+ window.pte = pte = pte || {};
491
+ window.log = function(obj) {
492
+ if (!window.debug_enabled) {
493
+ return true;
494
+ }
495
+ try {
496
+ console.log(obj);
497
+ } catch (error) {
498
+ alert(obj);
499
+ }
500
+ return true;
501
+ };
502
+ /*
503
+ POST-THUMBNAIL-EDITOR Script for Wordpress
504
+
505
+ Hooks into the Wordpress Media Library
506
+ */
507
+ (function(pte) {
508
+ return pte.admin = function() {
509
+ var $getLink, checkExistingThickbox, fixThickbox, image_id, injectPTE, launchPTE, pte_url, thickbox, timeout;
510
+ timeout = 300;
511
+ thickbox = "&TB_iframe=true&height=" + pte_tb_height + "&width=" + pte_tb_width;
512
+ image_id = null;
513
+ pte_url = function(override_id) {
514
+ var id;
515
+ id = override_id || image_id || $("#attachment-id").val();
516
+ return "" + ajaxurl + "?action=pte_ajax&pte-action=launch&id=" + id + thickbox;
517
+ };
518
+ $getLink = function(id) {
519
+ return $("<a class=\"thickbox\" href=\"" + (pte_url(id)) + "\">" + objectL10n.PTE + "</a>");
520
+ };
521
+ fixThickbox = function(parent) {
522
+ var height, p$, width;
523
+ p$ = parent.jQuery;
524
+ if (p$ === null) {
525
+ return;
526
+ }
527
+ log("Got thickbox");
528
+ width = pte_tb_width + 40;
529
+ height = pte_tb_height;
530
+ thickbox = p$("#TB_window").css({
531
+ 'margin-left': 0 - (width / 2),
532
+ 'width': width
533
+ }).children("iframe").css({
534
+ 'width': width
535
+ });
536
+ return parent.setTimeout(function() {
537
+ return p$("iframe", thickbox).css({
538
+ height: height + 100
539
+ });
540
+ }, 1000);
541
+ };
542
+ checkExistingThickbox = function(e) {
543
+ log("Start PTE...");
544
+ if (window.parent.frames.length > 0) {
545
+ log("Modifying thickbox...");
546
+ __bind(function() {
547
+ window.parent.tb_click();
548
+ fixThickbox(window.parent);
549
+ return true;
550
+ }, this)();
551
+ return e.stopPropagation();
552
+ }
553
+ };
554
+ injectPTE = function() {
555
+ $('.media-item').each(function(i, elem) {
556
+ var post_id;
557
+ post_id = elem.id.replace("media-item-", "");
558
+ return $getLink(post_id).css({
559
+ 'font-size': '.8em',
560
+ 'margin-left': '5px'
561
+ }).click(checkExistingThickbox).appendTo($('tr.image-size th.label', elem));
562
+ });
563
+ if (imageEdit.open != null) {
564
+ imageEdit.oldopen = imageEdit.open;
565
+ imageEdit.open = function(id, nonce) {
566
+ image_id = id;
567
+ imageEdit.oldopen(id, nonce);
568
+ return launchPTE();
569
+ };
570
+ }
571
+ return true;
572
+ };
573
+ launchPTE = function() {
574
+ var $editmenu, selector;
575
+ selector = "#imgedit-save-target-" + image_id;
576
+ $editmenu = $(selector);
577
+ if (($editmenu != null ? $editmenu.size() : void 0) < 1) {
578
+ window.log("Edit Thumbnail Menu not visible, waiting for " + timeout + "ms");
579
+ window.setTimeout(launchPTE, timeout);
580
+ return false;
581
+ }
582
+ return $editmenu.append($getLink().click(checkExistingThickbox));
583
+ };
584
+ return injectPTE();
585
+ };
586
+ })(pte);
587
+ TimerFunc = (function() {
588
+ function TimerFunc(fn, timeout) {
589
+ this.fn = fn;
590
+ this.timeout = timeout;
591
+ this.doFunc = __bind(this.doFunc, this);
592
+ this.timer = null;
593
+ }
594
+ TimerFunc.prototype.doFunc = function(e) {
595
+ window.clearTimeout(this.timer);
596
+ this.timer = window.setTimeout(this.fn, this.timeout);
597
+ return true;
598
+ };
599
+ return TimerFunc;
600
+ })();
601
+ window.randomness = function() {
602
+ return Math.floor(Math.random() * 1000001).toString(16);
603
+ };
604
+ window.debugTmpl = function(data) {
605
+ log(data);
606
+ return true;
607
+ };
608
+ window.goBack = function(e) {
609
+ if (e != null) {
610
+ e.preventDefault();
611
+ }
612
+ return $('#stage2').animate({
613
+ left: 1200
614
+ }, 500, 'swing', function() {
615
+ $(this).hide();
616
+ return $('#stage1').show(0, function() {
617
+ return $(this).animate({
618
+ left: 0
619
+ }, 500, 'swing', function() {
620
+ var delete_options;
621
+ log("okay cleanup");
622
+ delete_options = {
623
+ "id": $('#pte-post-id').val(),
624
+ 'action': 'pte_ajax',
625
+ 'pte-action': 'delete-images',
626
+ 'pte-nonce': $('#pte-delete-nonce').val()
627
+ };
628
+ return $.ajax({
629
+ url: ajaxurl,
630
+ data: delete_options,
631
+ global: false,
632
+ dataType: "json",
633
+ success: function(data, status, xhr) {
634
+ if (data.error != null) {
635
+ return log(data.error);
636
+ } else {
637
+ return log("Deleted tmp files");
638
+ }
639
+ }
640
+ });
641
+ });
642
+ });
643
+ });
644
+ };
645
+ gcd = function(a, b) {
646
+ if (a === 0) {
647
+ return b;
648
+ }
649
+ while (b > 0) {
650
+ if (a > b) {
651
+ a = a - b;
652
+ } else {
653
+ b = b - a;
654
+ }
655
+ }
656
+ if (a < 0 || b < 0) {
657
+ return null;
658
+ }
659
+ return a;
660
+ };
661
+ determineAspectRatio = function(current_ar, size) {
662
+ var crop, gc, height, tmp_ar, width, _ref;
663
+ _ref = thumbnail_info[size], crop = _ref.crop, width = _ref.width, height = _ref.height;
664
+ crop = +crop;
665
+ width = +width;
666
+ height = +height;
667
+ gc = gcd(width, height);
668
+ if ((crop != null) && crop > 0) {
669
+ tmp_ar = null;
670
+ if ((width != null) > 0 && (height != null) > 0) {
671
+ if (gc != null) {
672
+ tmp_ar = "" + (width / gc) + ":" + (height / gc);
673
+ } else {
674
+ tmp_ar = "" + width + ":" + height;
675
+ }
676
+ }
677
+ if ((current_ar != null) && (tmp_ar != null) && tmp_ar !== current_ar) {
678
+ throw "Too many Aspect Ratios. Disabling";
679
+ }
680
+ return current_ar = tmp_ar;
681
+ }
682
+ };
683
+ (function(pte) {
684
+ var addCheckAllNoneListener, addRowListener, addRowListeners, addSubmitListener, addVerifyListener, editor, iasSetAR, ias_defaults, ias_instance, initImgAreaSelect, setPageHeight;
685
+ editor = pte.editor = function() {
686
+ var $loading_screen, closeLoadingScreen;
687
+ setPageHeight();
688
+ addRowListeners();
689
+ initImgAreaSelect();
690
+ addRowListener();
691
+ addSubmitListener();
692
+ addVerifyListener();
693
+ addCheckAllNoneListener();
694
+ $loading_screen = $('#pte-loading');
695
+ closeLoadingScreen = function() {
696
+ log("Closing load screen");
697
+ $loading_screen.hide();
698
+ return true;
699
+ };
700
+ $('#pte-preview').load(closeLoadingScreen);
701
+ $loading_screen.ajaxStart(function() {
702
+ return $(this).fadeIn(200);
703
+ }).ajaxStop(function() {
704
+ return $(this).fadeOut(200);
705
+ });
706
+ window.setTimeout(closeLoadingScreen, 2000);
707
+ return true;
708
+ };
709
+ setPageHeight = function() {
710
+ var reflow;
711
+ reflow = new TimerFunc(function() {
712
+ var offset, window_height;
713
+ log("reflow called...");
714
+ offset = $("#pte-sizes").offset();
715
+ window_height = $(window).height() - offset.top - 2;
716
+ return $("#pte-sizes").height(window_height);
717
+ }, 100);
718
+ return $(window).resize(reflow.doFunc).load(reflow.doFunc);
719
+ };
720
+ addRowListeners = function() {
721
+ var enableRowFeatures;
722
+ enableRowFeatures = function($elem) {
723
+ $elem.delegate('tr', 'click', function(e) {
724
+ if (e.target.type !== 'checkbox') {
725
+ $('input:checkbox', this).click();
726
+ }
727
+ return true;
728
+ });
729
+ return $elem.delegate('input:checkbox', 'click', function(e) {
730
+ if (this.checked || $(this).is('input:checked')) {
731
+ $(this).parents('tr').first().removeClass('selected');
732
+ } else {
733
+ $(this).parents('tr').first().addClass('selected');
734
+ }
735
+ return true;
736
+ });
737
+ };
738
+ enableRowFeatures($('#stage2'));
739
+ return enableRowFeatures($('#stage1'));
740
+ };
741
+ /* Enable imgareaselect plugin */
742
+ ias_instance = null;
743
+ ias_defaults = {
744
+ keys: true,
745
+ minWidth: 3,
746
+ minHeight: 3,
747
+ handles: true,
748
+ zIndex: 1200,
749
+ instance: true,
750
+ onSelectEnd: function(img, s) {
751
+ if (s.width && s.width > 0 && s.height && s.height > 0 && $('.pte-size').filter(':checked').size() > 0) {
752
+ log("Enabling button");
753
+ return $('#pte-submit').removeAttr('disabled');
754
+ } else {
755
+ log("Disabling button");
756
+ return $('#pte-submit').attr('disabled', true);
757
+ }
758
+ }
759
+ };
760
+ initImgAreaSelect = function() {
761
+ return ias_instance = $('#pte-image img').imgAreaSelect(ias_defaults);
762
+ };
763
+ iasSetAR = function(ar) {
764
+ log("setting aspectRatio: " + ar);
765
+ ias_instance.setOptions({
766
+ aspectRatio: ar
767
+ });
768
+ return ias_instance.update();
769
+ };
770
+ addRowListener = function() {
771
+ var pteCheckHandler;
772
+ pteCheckHandler = new TimerFunc(function() {
773
+ var ar, selected_elements;
774
+ ar = null;
775
+ selected_elements = $('input.pte-size').filter(':checked').each(function(i, elem) {
776
+ try {
777
+ ar = determineAspectRatio(ar, $(elem).val());
778
+ } catch (error) {
779
+ ar = null;
780
+ if (ar !== ias_instance.getOptions().aspectRatio) {
781
+ alert(error);
782
+ }
783
+ return false;
784
+ }
785
+ return true;
786
+ });
787
+ iasSetAR(ar);
788
+ ias_defaults.onSelectEnd(null, ias_instance.getSelection());
789
+ return true;
790
+ }, 50);
791
+ return $('input.pte-size').click(pteCheckHandler.doFunc);
792
+ };
793
+ /* Callback for resizing images (Stage 1 to 2) */
794
+ addSubmitListener = function() {
795
+ var onResizeImages;
796
+ $('#pte-submit').click(function(e) {
797
+ var scale_factor, selection, submit_data;
798
+ log("Clicked Submit...");
799
+ selection = ias_instance.getSelection();
800
+ scale_factor = $('#pte-sizer').val();
801
+ submit_data = {
802
+ 'id': $('#pte-post-id').val(),
803
+ 'action': 'pte_ajax',
804
+ 'pte-action': 'resize-images',
805
+ 'pte-sizes[]': $('.pte-size').filter(':checked').map(function() {
806
+ return $(this).val();
807
+ }).get(),
808
+ 'x': Math.floor(selection.x1 / scale_factor),
809
+ 'y': Math.floor(selection.y1 / scale_factor),
810
+ 'w': Math.floor(selection.width / scale_factor),
811
+ 'h': Math.floor(selection.height / scale_factor)
812
+ };
813
+ log(submit_data);
814
+ ias_instance.setOptions({
815
+ hide: true,
816
+ x1: 0,
817
+ y1: 0,
818
+ x2: 0,
819
+ y2: 0
820
+ });
821
+ $('#pte-submit').attr('disabled', true);
822
+ $.getJSON(ajaxurl, submit_data, onResizeImages);
823
+ return true;
824
+ });
825
+ return onResizeImages = function(data, status, xhr) {
826
+ /* Evaluate data */ log(data);
827
+ if ((data.error != null) && !(data.thumbnails != null)) {
828
+ alert(data.error);
829
+ return;
830
+ }
831
+ $('#stage1').animate({
832
+ left: -$(window).width()
833
+ }, 500, 'swing', function() {
834
+ $(this).hide();
835
+ $('#stage2').html($('#stage2template').tmpl(data)).show(0, function() {
836
+ $(this).animate({
837
+ left: 0
838
+ }, 500);
839
+ return true;
840
+ });
841
+ return true;
842
+ });
843
+ return false;
844
+ };
845
+ };
846
+ /* Callback for Stage 2 to 3 */
847
+ addVerifyListener = function() {
848
+ var onConfirmImages;
849
+ $('#pte-confirm').live('click', function(e) {
850
+ var submit_data, thumbnail_data;
851
+ log("Confirming");
852
+ thumbnail_data = {};
853
+ $('input.pte-confirm').filter(':checked').each(function(i, elem) {
854
+ var size;
855
+ size = $(elem).val();
856
+ return thumbnail_data[size] = $("\#pte-" + size + "-file").val();
857
+ });
858
+ submit_data = {
859
+ 'id': $('#pte-post-id').val(),
860
+ 'action': 'pte_ajax',
861
+ 'pte-action': 'confirm-images',
862
+ 'pte-nonce': $('#pte-nonce').val(),
863
+ 'pte-confirm': thumbnail_data
864
+ };
865
+ log(submit_data);
866
+ return $.getJSON(ajaxurl, submit_data, onConfirmImages);
867
+ });
868
+ return onConfirmImages = function(data, status, xhr) {
869
+ log(data);
870
+ $('#stage2').animate({
871
+ left: -$(window).width()
872
+ }, 500, 'swing', function() {
873
+ $(this).hide();
874
+ $('#stage3').html($('#stage3template').tmpl(data)).show(0, function() {
875
+ $(this).animate({
876
+ left: 0
877
+ }, 500);
878
+ return true;
879
+ });
880
+ return true;
881
+ });
882
+ return false;
883
+ };
884
+ };
885
+ /* Select ALL|NONE */
886
+ return addCheckAllNoneListener = function() {
887
+ var checkAllSizes, uncheckAllSizes;
888
+ uncheckAllSizes = function(e) {
889
+ var elements, _ref, _ref2;
890
+ if (e != null) {
891
+ e.preventDefault();
892
+ }
893
+ elements = (_ref = (_ref2 = e.data) != null ? _ref2.selector : void 0) != null ? _ref : '.pte-size';
894
+ return $(elements).filter(':checked').click();
895
+ };
896
+ checkAllSizes = function(e) {
897
+ var elements, _ref, _ref2;
898
+ if (e != null) {
899
+ e.preventDefault();
900
+ }
901
+ elements = (_ref = e != null ? (_ref2 = e.data) != null ? _ref2.selector : void 0 : void 0) != null ? _ref : '.pte-size';
902
+ return $(elements).not(':checked').click();
903
+ };
904
+ $("#pte-selectors .all").click(checkAllSizes);
905
+ $("#pte-selectors .none").click(uncheckAllSizes).click();
906
+ $('#stage2').delegate('#pte-stage2-selectors .all', 'click', {
907
+ selector: '.pte-confirm'
908
+ }, checkAllSizes);
909
+ $('#stage2').delegate('#pte-stage2-selectors .none', 'click', {
910
+ selector: '.pte-confirm'
911
+ }, uncheckAllSizes);
912
+ return true;
913
+ };
914
+ })(pte);
915
+ }).call(this);
js/pte.full.min.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function(a){function B(b,c,f,d){d={data:d||d===0||d===false?d:c?c.data:{},_wrap:c?c._wrap:null,tmpl:null,parent:c||null,nodes:[],calls:m,nest:n,wrap:v,html:s,update:w};b&&a.extend(d,b,{nodes:[],parent:c});if(f){d.tmpl=f;d._ctnt=d._ctnt||d.tmpl(a,d);d.key=++k;(A.length?x:q)[k]=d}return d}function E(b,c,f){var d;f=f?a.map(f,function(h){return typeof h==="string"?b.key?h.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+y+'="'+b.key+'" $2'):h:E(h,b,h._ctnt)}):b;if(c)return f;f=f.join("");f.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,
2
+ function(h,i,o,t){d=a(o).get();l(d);if(i)d=I(i).concat(d);if(t)d=d.concat(I(t))});return d?d:I(f)}function I(b){var c=document.createElement("div");c.innerHTML=b;return a.makeArray(c.childNodes)}function F(b){return new Function("jQuery","$item","var $=jQuery,call,__=[],$data=$item.data;with($data){__.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
3
+ function(c,f,d,h,i,o,t){c=a.tmpl.tag[d];if(!c)throw"Unknown template tag: "+d;d=c._default||[];if(o&&!/\w$/.test(i)){i+=o;o=""}if(i){i=G(i);t=t?","+G(t)+")":o?")":"";t=o?i.indexOf(".")>-1?i+G(o):"("+i+").call($item"+t:i;o=o?t:"(typeof("+i+")==='function'?("+i+").call($item):("+i+"))"}else o=t=d.$1||"null";h=G(h);return"');"+c[f?"close":"open"].split("$notnull_1").join(i?"typeof("+i+")!=='undefined' && ("+i+")!=null":"true").split("$1a").join(o).split("$1").join(t).split("$2").join(h||d.$2||"")+"__.push('"})+
4
+ "');}return __;")}function p(b,c){b._wrap=E(b,true,a.isArray(c)?c:[j.test(c)?c:a(c).html()]).join("")}function G(b){return b?b.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function l(b){function c(H){function M(L){L+=f;r=i[L]=i[L]||B(r,q[r.parent.key+f]||r.parent)}var C,z=H,r,K;if(K=H.getAttribute(y)){for(;z.parentNode&&(z=z.parentNode).nodeType===1&&!(C=z.getAttribute(y)););if(C!==K){z=z.parentNode?z.nodeType===11?0:z.getAttribute(y)||0:0;if(!(r=q[K])){r=x[K];r=B(r,q[z]||x[z]);r.key=++k;q[k]=r}u&&
5
+ M(K)}H.removeAttribute(y)}else if(u&&(r=a.data(H,"tmplItem"))){M(r.key);q[r.key]=r;z=(z=a.data(H.parentNode,"tmplItem"))?z.key:0}if(r){for(C=r;C&&C.key!=z;){C.nodes.push(H);C=C.parent}delete r._ctnt;delete r._wrap;a.data(H,"tmplItem",r)}}var f="_"+u,d,h,i={},o,t,J;o=0;for(t=b.length;o<t;o++)if((d=b[o]).nodeType===1){h=d.getElementsByTagName("*");for(J=h.length-1;J>=0;J--)c(h[J]);c(d)}}function m(b,c,f,d){if(!b)return A.pop();A.push({_:b,tmpl:c,item:this,data:f,options:d})}function n(b,c,f){return a.tmpl(a.template(b),
6
+ c,f,this)}function v(b,c){var f=b.options||{};f.wrapped=c;return a.tmpl(a.template(b.tmpl),b.data,f,b.item)}function s(b,c){var f=this._wrap;return a.map(a(a.isArray(f)?f.join(""):f).filter(b||"*"),function(d){if(c)d=d.innerText||d.textContent;else{var h;if(!(h=d.outerHTML)){h=document.createElement("div");h.appendChild(d.cloneNode(true));h=h.innerHTML}d=h}return d})}function w(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}var D=a.fn.domManip,y="_tmplitem",j=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
7
+ q={},x={},g,e={key:0,data:{}},k=0,u=0,A=[];a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(b,c){a.fn[b]=function(f){var d=[];f=a(f);var h,i,o;h=this.length===1&&this[0].parentNode;g=q||{};if(h&&h.nodeType===11&&h.childNodes.length===1&&f.length===1){f[c](this[0]);d=this}else{i=0;for(o=f.length;i<o;i++){u=i;h=(i>0?this.clone(true):this).get();a(f[i])[c](h);d=d.concat(h)}u=0;d=this.pushStack(d,b,f.selector)}f=g;g=null;a.tmpl.complete(f);
8
+ return d}});a.fn.extend({tmpl:function(b,c,f){return a.tmpl(this[0],b,c,f)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(b,c,f){if(b[0]&&a.isArray(b[0])){for(var d=a.makeArray(arguments),h=b[0],i=h.length,o=0,t;o<i&&!(t=a.data(h[o++],"tmplItem")););if(t&&u)d[2]=function(J){a.tmpl.afterManip(this,J,f)};D.apply(this,d)}else D.apply(this,arguments);u=0;g||a.tmpl.complete(q);return this}});a.extend({tmpl:function(b,c,f,d){var h=!d;
9
+ if(h){d=e;b=a.template[b]||a.template(null,b);x={}}else if(!b){b=d.tmpl;q[d.key]=d;d.nodes=[];d.wrapped&&p(d,d.wrapped);return a(E(d,null,d.tmpl(a,d)))}if(!b)return[];if(typeof c==="function")c=c.call(d||{});f&&f.wrapped&&p(f,f.wrapped);c=a.isArray(c)?a.map(c,function(i){return i?B(f,d,b,i):null}):[B(f,d,b,c)];return h?a(E(d,null,c)):c},tmplItem:function(b){var c;if(b instanceof a)b=b[0];for(;b&&b.nodeType===1&&!(c=a.data(b,"tmplItem"))&&(b=b.parentNode););return c||e},template:function(b,c){if(c){if(typeof c===
10
+ "string")c=F(c);else if(c instanceof a)c=c[0]||{};if(c.nodeType)c=a.data(c,"tmpl")||a.data(c,"tmpl",F(c.innerHTML));return typeof b==="string"?a.template[b]=c:c}return b?typeof b!=="string"?a.template(null,b):a.template[b]||a.template(null,j.test(b)?b:a(b)):null},encode:function(b){return(""+b).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){__=__.concat($item.nest($1,$2));}"},
11
+ wrap:{_default:{$2:"null"},open:"$item.calls(__,$1,$2);__=[];",close:"call=$item.calls();__=call._.concat($item.wrap(call,__));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){__.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){__.push($.encode($1a));}"},"!":{open:""}},complete:function(){q=
12
+ {}},afterManip:function(b,c,f){var d=c.nodeType===11?a.makeArray(c.childNodes):c.nodeType===1?[c]:[];f.call(b,c);l(d);u++}})})(jQuery);
13
+ (function(){var a,B,E,I,F,p,G=function(l,m){return function(){return l.apply(m,arguments)}};p=this;a=p.jQuery;p.pte=F=F||{};p.log=function(l){if(!p.debug_enabled)return true;try{console.log(l)}catch(m){alert(l)}return true};(function(l){return l.admin=function(){var m,n,v,s,w,D,y;y="&TB_iframe=true&height="+pte_tb_height+"&width="+pte_tb_width;s=null;D=function(j){j=j||s||a("#attachment-id").val();return""+ajaxurl+"?action=pte_ajax&pte-action=launch&id="+j+y};m=function(j){return a('<a class="thickbox" href="'+
14
+ D(j)+'">'+objectL10n.PTE+"</a>")};v=function(j){var q,x,g;x=j.jQuery;if(x!==null){log("Got thickbox");g=pte_tb_width+40;q=pte_tb_height;y=x("#TB_window").css({"margin-left":0-g/2,width:g}).children("iframe").css({width:g});return j.setTimeout(function(){return x("iframe",y).css({height:q+100})},1E3)}};n=function(j){log("Start PTE...");if(p.parent.frames.length>0){log("Modifying thickbox...");G(function(){p.parent.tb_click();v(p.parent);return true},this)();return j.stopPropagation()}};w=function(){var j;
15
+ j=a("#imgedit-save-target-"+s);if((j!=null?j.size():void 0)<1){p.log("Edit Thumbnail Menu not visible, waiting for 300ms");p.setTimeout(w,300);return false}return j.append(m().click(n))};return function(){a(".media-item").each(function(j,q){var x;x=q.id.replace("media-item-","");return m(x).css({"font-size":".8em","margin-left":"5px"}).click(n).appendTo(a("tr.image-size th.label",q))});if(imageEdit.open!=null){imageEdit.oldopen=imageEdit.open;imageEdit.open=function(j,q){s=j;imageEdit.oldopen(j,q);
16
+ return w()}}return true}()}})(F);B=function(){function l(m,n){this.fn=m;this.timeout=n;this.doFunc=G(this.doFunc,this);this.timer=null}l.prototype.doFunc=function(){p.clearTimeout(this.timer);this.timer=p.setTimeout(this.fn,this.timeout);return true};return l}();p.randomness=function(){return Math.floor(Math.random()*1000001).toString(16)};p.debugTmpl=function(l){log(l);return true};p.goBack=function(l){l!=null&&l.preventDefault();return a("#stage2").animate({left:1200},500,"swing",function(){a(this).hide();
17
+ return a("#stage1").show(0,function(){return a(this).animate({left:0},500,"swing",function(){var m;log("okay cleanup");m={id:a("#pte-post-id").val(),action:"pte_ajax","pte-action":"delete-images","pte-nonce":a("#pte-delete-nonce").val()};return a.ajax({url:ajaxurl,data:m,global:false,dataType:"json",success:function(n){return n.error!=null?log(n.error):log("Deleted tmp files")}})})})})};I=function(l,m){if(l===0)return m;for(;m>0;)if(l>m)l-=m;else m-=l;if(l<0||m<0)return null;return l};E=function(l,
18
+ m){var n,v,s,w;v=thumbnail_info[m];n=v.crop;w=v.width;s=v.height;n=+n;w=+w;s=+s;v=I(w,s);if(n!=null&&n>0){n=null;if((w!=null)>0&&(s!=null)>0)n=v!=null?""+w/v+":"+s/v:""+w+":"+s;if(l!=null&&n!=null&&n!==l)throw"Too many Aspect Ratios. Disabling";return n}};(function(l){var m,n,v,s,w,D,y,j,q,x;l.editor=function(){var g,e;x();v();q();n();s();w();m();g=a("#pte-loading");e=function(){log("Closing load screen");g.hide();return true};a("#pte-preview").load(e);g.ajaxStart(function(){return a(this).fadeIn(200)}).ajaxStop(function(){return a(this).fadeOut(200)});
19
+ p.setTimeout(e,2E3);return true};x=function(){var g;g=new B(function(){var e;log("reflow called...");e=a("#pte-sizes").offset();e=a(p).height()-e.top-2;return a("#pte-sizes").height(e)},100);return a(p).resize(g.doFunc).load(g.doFunc)};v=function(){var g;g=function(e){e.delegate("tr","click",function(k){k.target.type!=="checkbox"&&a("input:checkbox",this).click();return true});return e.delegate("input:checkbox","click",function(){this.checked||a(this).is("input:checked")?a(this).parents("tr").first().removeClass("selected"):
20
+ a(this).parents("tr").first().addClass("selected");return true})};g(a("#stage2"));return g(a("#stage1"))};j=null;y={keys:true,minWidth:3,minHeight:3,handles:true,zIndex:1200,instance:true,onSelectEnd:function(g,e){if(e.width&&e.width>0&&e.height&&e.height>0&&a(".pte-size").filter(":checked").size()>0){log("Enabling button");return a("#pte-submit").removeAttr("disabled")}else{log("Disabling button");return a("#pte-submit").attr("disabled",true)}}};q=function(){return j=a("#pte-image img").imgAreaSelect(y)};
21
+ D=function(g){log("setting aspectRatio: "+g);j.setOptions({aspectRatio:g});return j.update()};n=function(){var g;g=new B(function(){var e;e=null;a("input.pte-size").filter(":checked").each(function(k,u){try{e=E(e,a(u).val())}catch(A){e=null;e!==j.getOptions().aspectRatio&&alert(A);return false}return true});D(e);y.onSelectEnd(null,j.getSelection());return true},50);return a("input.pte-size").click(g.doFunc)};s=function(){var g;a("#pte-submit").click(function(){var e,k;log("Clicked Submit...");k=j.getSelection();
22
+ e=a("#pte-sizer").val();e={id:a("#pte-post-id").val(),action:"pte_ajax","pte-action":"resize-images","pte-sizes[]":a(".pte-size").filter(":checked").map(function(){return a(this).val()}).get(),x:Math.floor(k.x1/e),y:Math.floor(k.y1/e),w:Math.floor(k.width/e),h:Math.floor(k.height/e)};log(e);j.setOptions({hide:true,x1:0,y1:0,x2:0,y2:0});a("#pte-submit").attr("disabled",true);a.getJSON(ajaxurl,e,g);return true});return g=function(e){log(e);if(e.error!=null&&e.thumbnails==null)alert(e.error);else{a("#stage1").animate({left:-a(p).width()},
23
+ 500,"swing",function(){a(this).hide();a("#stage2").html(a("#stage2template").tmpl(e)).show(0,function(){a(this).animate({left:0},500);return true});return true});return false}}};w=function(){var g;a("#pte-confirm").live("click",function(){var e,k;log("Confirming");k={};a("input.pte-confirm").filter(":checked").each(function(u,A){var b;b=a(A).val();return k[b]=a("#pte-"+b+"-file").val()});e={id:a("#pte-post-id").val(),action:"pte_ajax","pte-action":"confirm-images","pte-nonce":a("#pte-nonce").val(),
24
+ "pte-confirm":k};log(e);return a.getJSON(ajaxurl,e,g)});return g=function(e){log(e);a("#stage2").animate({left:-a(p).width()},500,"swing",function(){a(this).hide();a("#stage3").html(a("#stage3template").tmpl(e)).show(0,function(){a(this).animate({left:0},500);return true});return true});return false}};return m=function(){var g,e;e=function(k){var u,A;k!=null&&k.preventDefault();k=(u=(A=k.data)!=null?A.selector:void 0)!=null?u:".pte-size";return a(k).filter(":checked").click()};g=function(k){var u,
25
+ A;k!=null&&k.preventDefault();k=(u=k!=null?(A=k.data)!=null?A.selector:void 0:void 0)!=null?u:".pte-size";return a(k).not(":checked").click()};a("#pte-selectors .all").click(g);a("#pte-selectors .none").click(e).click();a("#stage2").delegate("#pte-stage2-selectors .all","click",{selector:".pte-confirm"},g);a("#stage2").delegate("#pte-stage2-selectors .none","click",{selector:".pte-confirm"},e);return true}})(F)}).call(this);
js/pte_admin.coffee ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ###
2
+ POST-THUMBNAIL-EDITOR Script for Wordpress
3
+
4
+ Hooks into the Wordpress Media Library
5
+ ###
6
+ do (pte) ->
7
+
8
+ pte.admin = ->
9
+ timeout = 300
10
+ thickbox = """&TB_iframe=true&height=#{ pte_tb_height }&width=#{ pte_tb_width }"""
11
+ image_id = null
12
+ pte_url = (override_id) ->
13
+ id = override_id || image_id || $("#attachment-id").val()
14
+ "#{ ajaxurl }?action=pte_ajax&pte-action=launch&id=#{ id }#{ thickbox }"
15
+ $getLink = (id) ->
16
+ $("""<a class="thickbox" href="#{ pte_url id }">#{ objectL10n.PTE }</a>""")
17
+
18
+
19
+
20
+ fixThickbox = (parent) ->
21
+ p$ = parent.jQuery
22
+ if p$ == null then return
23
+ log "Got thickbox"
24
+ width = pte_tb_width + 40
25
+ height = pte_tb_height
26
+ thickbox = p$("#TB_window").css
27
+ 'margin-left': 0 - (width / 2)
28
+ 'width': width
29
+ .children("iframe").css
30
+ 'width': width
31
+ parent.setTimeout ->
32
+ p$("iframe", thickbox).css
33
+ height: height + 100
34
+ #.resize()
35
+ , 1000
36
+
37
+ checkExistingThickbox = (e) ->
38
+ log "Start PTE..."
39
+ #if (window.parent?.tb_remove?)
40
+ #if window.parent isnt window
41
+ if window.parent.frames.length > 0
42
+ log "Modifying thickbox..."
43
+ # Bind the current context (a href=...) so that thickbox
44
+ # can act independent of me...
45
+ do =>
46
+ #window.parent.setTimeout tb_click, 0
47
+ window.parent.tb_click()
48
+ # Set the correct width/height
49
+ fixThickbox(window.parent)
50
+ #$(window.parent.document).append(this).click()
51
+ #$(this).appendTo($("body", window.parent.document)).unbind().click()
52
+ true
53
+ e.stopPropagation()
54
+ #
55
+ # Entry to our code
56
+ # Override the imgEdit.open function
57
+ #
58
+ injectPTE = ->
59
+ # Find and inject pte-url into size cell...
60
+ $('.media-item').each (i,elem) ->
61
+ post_id = elem.id.replace "media-item-",""
62
+ $getLink(post_id)
63
+ .css
64
+ 'font-size': '.8em'
65
+ 'margin-left': '5px'
66
+ .click(checkExistingThickbox)
67
+ .appendTo $ 'tr.image-size th.label', elem
68
+
69
+ if imageEdit.open?
70
+ imageEdit.oldopen = imageEdit.open
71
+ imageEdit.open = (id, nonce) ->
72
+ image_id = id
73
+ imageEdit.oldopen id,nonce
74
+ launchPTE()
75
+ true
76
+
77
+ launchPTE = ->
78
+ # Check if elements are loaded
79
+ #selector = """p[id^="imgedit-save-target-#{ image_id }"]"""
80
+ selector = """#imgedit-save-target-#{ image_id }"""
81
+ $editmenu = $(selector)
82
+ if $editmenu?.size() < 1
83
+ window.log "Edit Thumbnail Menu not visible, waiting for #{ timeout }ms"
84
+ window.setTimeout(launchPTE, timeout)
85
+ return false
86
+
87
+ # Add convenience functions to menu
88
+ #$editmenu.append $("""<a class="thickbox" href="#{ pte_url() }">#{ objectL10n.PTE }</a>""")
89
+ $editmenu.append $getLink().click checkExistingThickbox
90
+
91
+ injectPTE()
92
+
js/pte_admin_media.js DELETED
@@ -1,325 +0,0 @@
1
- // log
2
- function log(obj){
3
- if (!window.console )
4
- {
5
- var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
6
- "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
7
-
8
- window.console = {};
9
- for (var i = 0; i < names.length; ++i)
10
- //window.console[names[i]] = function() {}
11
- window.console[names[i]] = alert
12
- }
13
- if (!console) console = window.console;
14
-
15
- /*
16
- * TODO: Comment this out when publishing to WORDPRESS.ORG
17
- */
18
- //console.log(obj);
19
- }
20
-
21
- jQuery(document).ready(function($){
22
- var pte_timeout = 1000;
23
- var pte_max_attempts = 50;
24
- var ias_instance = null;
25
-
26
- /*
27
- * Entry to our code
28
- * Override the imgEdit.open function
29
- */
30
- if (imageEdit.open){
31
- imageEdit.oldopen = imageEdit.open;
32
- imageEdit.open = function(id, nonce){
33
- getImageEditor();
34
- imageEdit.oldopen(id,nonce);
35
- }
36
- }
37
-
38
- // Make it an option to turn on debug statements?
39
- function imgDebug(img, s){
40
- //$('#pte-debug').html( "x1: " + s.x1 + "<br />"
41
- // + "y1: " + s.y1 + "<br />"
42
- // + "x2: " + s.x2 + "<br />"
43
- // + "y2: " + s.y2 + "<br />"
44
- // + "width: " + s.width + "<br />"
45
- // + "height: " + s.height + "<br />");
46
- }
47
-
48
- function closeImgAreaSelect(){
49
- if (ias_instance){
50
- ias_instance.setOptions({ show: false
51
- , disable: true
52
- , hide: true
53
- , remove: true
54
- });
55
- ias_instance.update();
56
- }
57
- }
58
-
59
- // http://en.wikipedia.org/wiki/Euclidean_algorithm#Implementations
60
- function gcd(a, b){
61
- if (a == 0) return b
62
- while(b > 0){
63
- if (a > b){
64
- a = a - b
65
- }
66
- else {
67
- b = b - a
68
- }
69
- }
70
- if ( a < 0 || b < 0 ) return null
71
- return a
72
- }
73
-
74
- function savePostThumbnail(){
75
- if (!ias_instance) return;
76
- var selection = ias_instance.getSelection();
77
- log(selection);
78
-
79
- var id = getID();
80
- if (!id) return false;
81
-
82
- var size = $("#pte-thumb").val()
83
- log("Clicked: " + size);
84
- if (!size || size == "" || size.length == 0) return false;
85
-
86
- // Our script needs to know the REAL x1, y1 and x2, y2
87
- // so it can crop and then scale...
88
- var scale_factor = $('#imgedit-sizer-'+id).val();
89
- var data = { 'action': 'pte_ajax'
90
- , 'pte_action': 'resize-img'
91
- , 'id': id
92
- , 'size': size
93
- , 'x': Math.floor(selection.x1/scale_factor)
94
- , 'y': Math.floor(selection.y1/scale_factor)
95
- , 'w': Math.floor(selection.width/scale_factor)
96
- , 'h': Math.floor(selection.height/scale_factor)
97
- , '_ajax_nonce': $('body').data('nonce')
98
- }
99
- log(data);
100
- $.get( ajaxurl
101
- , data
102
- , function(data, txtstatus, xhr){
103
- log(data);
104
- if (data.error){
105
- alert("Sorry, we encountered an issue: " + data.error);
106
- }
107
- if (data.url){
108
- closeImgAreaSelect();
109
- $('#pte-display').html('<strong>Updated image</strong>: <br/>'
110
- + '<img src="'+data.url+'?'+randomness()+'"/><br>'
111
- + 'Reload your cache (Shift+F5 on the page you want to see the changes)'
112
- + ' and everything should work...');
113
- }
114
- else
115
- $.fancybox.close();
116
- }
117
- , 'json'
118
- );
119
- }
120
-
121
- function createPteDisplay(){
122
- var pte_display = $('#pte-display')
123
- .find('#pte-edit').empty().end()
124
- .find('#pte-current').empty().end();
125
- var pte_display_html = '<div id="pte-edit"></div>'
126
- + '<div id="pte-info">Currently: (it\'s scaled to fit horizontally)...</div>'
127
- + '<div id="pte-current"></div>'
128
- + '<div id="pte-debug"></div>'
129
- + '<div id="pte-controls">'
130
- + '<input type="button" id="pte-stop" name="pte-stop" class="button" value="Cancel"/>'
131
- + '<input type="button" id="pte-save" name="pte-save" class="button-primary" value="Save"/>'
132
- + '</div>'
133
- if (pte_display.length > 0){ // Exists
134
- pte_display.html(pte_display_html);
135
- }
136
- else { // Doesn't exist
137
- pte_display = $('<div id="pte-display">')
138
- .html(pte_display_html)
139
- .appendTo($('body'))
140
- }
141
- pte_display
142
- .find("#pte-stop").click($.fancybox.close).end()
143
- .find("#pte-save").click(savePostThumbnail)
144
- }
145
-
146
- function randomness(){
147
- return Math.floor(Math.random()*1000001).toString(16);
148
- }
149
-
150
- function getID(){
151
- try{
152
- //var id = "pte-" + $(".image-editor").attr("id");
153
- var id = /\d+$/.exec($(".image-editor").attr("id"))[0];
154
- log(id);
155
- return id;
156
- }
157
- catch(e){
158
- log("oops");
159
- }
160
- return null;
161
- }
162
-
163
- // sent from click on pte-submit event
164
- function createPostThumbnailEdit(event){
165
- var size = $("#pte-thumb").val()
166
- log("Clicked: " + size);
167
- if (!size || size == "" || size.length == 0) return false;
168
-
169
- var id = getID();
170
- if (!id) return false;
171
-
172
- // Find the aspect ratio
173
- var sizes = $('body').data('sizes');
174
-
175
- // Get the images (the fake one & the thumbnail)
176
- //var main_img_url = $('#image-preview-'+id).attr('src');
177
- createPteDisplay();
178
- var img_preview = $('#image-preview-'+id)
179
- ias_instance = img_preview
180
- .clone(false)
181
- .appendTo('#pte-edit')
182
- .css({'height': img_preview.height()})
183
- .imgAreaSelect({ handles: true
184
- , zIndex: 1200
185
- , instance: true
186
- , onSelectEnd: imgDebug
187
- });
188
-
189
- if (sizes[size]['crop'] != 0){
190
- // set aspect ratio
191
- log("Set aspect ratio: " + sizes[size]['crop']);
192
- var ar = null;
193
- var cd = gcd( parseInt(sizes[size]['width'])
194
- , parseInt(sizes[size]['height']));
195
-
196
- if (cd){
197
- ar = parseInt(sizes[size]['width']) / cd
198
- + ":"
199
- + parseInt(sizes[size]['height']) / cd;
200
- var options = ias_instance.getOptions();
201
- options['aspectRatio'] = ar;
202
- // YAY, IE dies here due to a bug in imgAreaSelect
203
- // HOWEVER, it doesn't seem to matter...
204
- try {
205
- ias_instance.setOptions(options);
206
- }
207
- catch(e){
208
- }
209
- }
210
- //ias_instance.update(false);
211
- }
212
-
213
- $.get( ajaxurl
214
- , { 'action': 'pte_ajax'
215
- , 'pte_action': 'get-image-data'
216
- , 'id': id
217
- , 'size': size
218
- }
219
- , function(data,txt,xhr){
220
- log(data);
221
- $('body').data('nonce', data.nonce);
222
- var img = $('<img src="' + data.url + '?' + randomness() + '">').appendTo('#pte-current');
223
- var img_width = sizes[size]['width'];
224
- if (img_width < parseInt(img.width())){
225
- log("Smallen [sic] the width");
226
- img.css('width', img_width);
227
- }
228
- }
229
- , 'json'
230
- );
231
-
232
- $('<a class="inline" href="#pte-display">Gnarly</a>')
233
- .fancybox( {
234
- // Fix for issue #1... IE8 & fancybox inline workaround...
235
- 'href': '#pte-display'
236
- , 'onStart': function(){
237
- $('#pte-display').show();
238
- $.fancybox.center();
239
- }
240
- , 'onClosed': function(){
241
- closeImgAreaSelect();
242
- $('#pte-display').hide()
243
- }
244
- }
245
- )
246
- .trigger('click')
247
- //$('<a class="inline" href="#pte-display">Gnarly</a>').fancybox().trigger('click');
248
-
249
- log("done with create Edit");
250
- return false;
251
- }
252
-
253
- function getImageEditor(){
254
- // HTML to inject into the editor
255
- // This might need to be loaded by AJAX for localization purposes
256
- var editbox = $("<div class='imgedit-group pte-thumbs'>"
257
- + "<div class='imgedit-group-top'><strong>Edit Post Thumbnails</strong></div>"
258
- + "<select id='pte-thumb' name='pte-thumb'>"
259
- + "<option value=0 disabled selected>Choose a size to edit:</option>"
260
- + "</select><br/>"
261
- + "<input class='button-primary' type='submit' name='pte-edit-thumb' id='pte-submit' value='Edit'/>"
262
- + "</div");
263
-
264
- //log("Attempts remaining: " + pte_max_attempts);
265
- var editor = $(".imgedit-settings");
266
- if (editor.size() < 1 && pte_max_attempts-- < 0){
267
- //log("Tried too many times, stopping");
268
- return;
269
- }
270
- else if (editor.size() < 1){
271
- //log("No editor... Try again.");
272
- window.setTimeout(getImageEditor, pte_timeout);
273
- return;
274
- }
275
-
276
- //log("Found: " + editor.size());
277
-
278
- // Action: create image pop-up
279
- // Used when the user selects a post thumbnail to edit
280
- // OPTION 1: Create an ajax/php script to recreate the picture/setup that already exists
281
- // on the current page
282
- // OPTION 2: Borrow the parameters, add the thumbnail that you're attempting to process
283
- // and send the data to your script.
284
- //
285
- // Let's try OPTION 2...
286
- editbox.find("#pte-submit").click(createPostThumbnailEdit);
287
-
288
- // Add the above HTML to the image-editor GUI
289
- editor.append(editbox)
290
- $('.imgedit-submit input.button').click(function(e){
291
- log("Removing that bastard");
292
- editbox.remove().find("#pte-thumb").empty();
293
- });
294
-
295
- // Get list of available sizes
296
- //log("ADMINAJAX: " + ajaxurl);
297
- $.get(ajaxurl
298
- , { 'action': 'pte_ajax'
299
- , 'pte_action': 'get-alternate-sizes'}
300
- , function(data, status, xhr){
301
- //log(data);
302
- $('body').data('sizes',data.sizes);
303
- try {
304
- $.each(data.sizes, function(i,elem){
305
- editbox.find("#pte-thumb")
306
- .append("<option value='" + i
307
- + "'>" + i
308
- + ": " + elem.width + "x" + elem.height
309
- + "</option>");
310
- })
311
- }
312
- catch(e){
313
- log("ERROR: " + e);
314
- }
315
- }
316
- , 'json'
317
- );
318
- }
319
-
320
- // Listens for "Edit" event
321
- //$('input[id^="imgedit-open"]').bind('click', function(){
322
- // log("pushed the button");
323
- // getImageEditor();
324
- //});
325
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
local.mk ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ GOOGLE_WORK = $(wildcard /home/brent/build/closure/compiler.jar)
2
+ GOOGLE = $(if $(GOOGLE_WORK),$(GOOGLE_WORK),$(shell cygpath -w -a ~/build/google_closure/compiler.jar))
3
+
4
+ YUI_WORK = $(wildcard /home/brent/build/yui_compressor/yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar)
5
+ YUI = $(if $(YUI_WORK),$(YUI_WORK),$(shell cygpath -w -a ~/build/yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar))
6
+
7
+ #JSMINIFIER = java -jar "$(GOOGLE)" --js $(JSOUTPUT_DEV) --js_output_file $(JSOUTPUT_MIN)
8
+ #JSMINIFIER = java -jar "$(GOOGLE)" --js $(JSOUTPUT_DEV) --js_output_file $(JSOUTPUT_MIN) --compilation_level ADVANCED_OPTIMIZATIONS
9
+ #CSSMINIFIER = java -jar "$(YUI)" --type css -o $(CSSOUTPUT_MIN) $(CSSOUTPUT_DEV)
post-thumbnail-editor.php CHANGED
@@ -3,10 +3,11 @@
3
  Plugin URI: http://wordpress.org/extend/plugins/post-thumbnail-editor/
4
  Author: sewpafly
5
  Author URI: http://sewpafly.github.com/post-thumbnail-editor
6
- Version: 0.2.2
7
  Description: Individually manage your post thumbnails
8
 
9
  LICENSE
 
10
 
11
  Copyright 2011 (email : sewpafly@gmail.com)
12
 
@@ -24,6 +25,8 @@
24
  along with this program; if not, write to the Free Software
25
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
 
 
 
27
  */
28
 
29
  /*
@@ -31,68 +34,111 @@
31
  */
32
  define( 'PTE_PLUGINURL', plugins_url(basename( dirname(__FILE__))) . "/");
33
  define( 'PTE_PLUGINPATH', dirname(__FILE__) . "/");
34
- define( 'PTE_VERSION', "0.2.2");
35
- define( 'PTE_POST_DATA', "pte-data");
 
 
 
 
 
 
36
 
37
  /*
38
  * Put Hooks and immediate hook functions in this file
39
  */
40
 
41
  /* Hook into the Edit Image page */
42
- function pte_admin_media_styles(){
43
- wp_enqueue_style('fancybox',
44
- PTE_PLUGINURL . 'apps/fancybox/jquery.fancybox-1.3.4.css');
45
- wp_enqueue_style( 'pte'
46
- , PTE_PLUGINURL . 'css/pte.css'
47
- , false
48
- , PTE_VERSION
49
- );
50
  }
51
 
52
  function pte_admin_media_scripts(){
53
- wp_enqueue_script('imgareaselect');
54
- wp_enqueue_script('fancybox',
55
- PTE_PLUGINURL . 'apps/fancybox/jquery.fancybox-1.3.4.min.js',
56
- array('jquery')
57
- );
58
- wp_enqueue_script( 'pte'
59
- , PTE_PLUGINURL . 'js/pte_admin_media.js'
60
- , array('jquery')
61
- , PTE_VERSION
62
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
64
 
65
  function pte_ajax(){
66
  // Move all adjuntant functions to a separate file and include that here
67
  require_once(PTE_PLUGINPATH . 'pte_functions.php');
68
- switch ($_GET['pte_action'])
 
69
  {
70
- case "get-alternate-sizes":
71
- pte_get_alternate_sizes();
72
- break;
73
- case "get-image-data":
74
- pte_get_image_data($_GET['id'], $_GET['size']);
75
- break;
76
- case "resize-img":
77
- pte_resize_img($_GET['id'],
78
- $_GET['size'],
79
- $_GET['x'],
80
- $_GET['y'],
81
- $_GET['w'],
82
- $_GET['h']
83
- );
84
- break;
85
  }
86
  die(-1);
87
  }
88
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  /* This is the main admin media page */
90
- add_action('admin_print_styles-media.php', 'pte_admin_media_styles');
91
- add_action('admin_print_scripts-media.php', 'pte_admin_media_scripts');
92
 
93
  /* This is for the popup media page */
94
- add_action('admin_print_styles-media-upload-popup', 'pte_admin_media_styles');
95
- add_action('admin_print_scripts-media-upload-popup', 'pte_admin_media_scripts');
 
 
 
 
 
 
 
 
96
 
97
  /* For all purpose needs */
98
  add_action('wp_ajax_pte_ajax', 'pte_ajax');
3
  Plugin URI: http://wordpress.org/extend/plugins/post-thumbnail-editor/
4
  Author: sewpafly
5
  Author URI: http://sewpafly.github.com/post-thumbnail-editor
6
+ Version: 1.0.0
7
  Description: Individually manage your post thumbnails
8
 
9
  LICENSE
10
+ =======
11
 
12
  Copyright 2011 (email : sewpafly@gmail.com)
13
 
25
  along with this program; if not, write to the Free Software
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
 
28
+ CREDITS
29
+ =======
30
  */
31
 
32
  /*
34
  */
35
  define( 'PTE_PLUGINURL', plugins_url(basename( dirname(__FILE__))) . "/");
36
  define( 'PTE_PLUGINPATH', dirname(__FILE__) . "/");
37
+ define( 'PTE_VERSION', "1.0.0");
38
+ define( 'PTE_TB_WIDTH', 750 ); // Only edit this if you feel like living dangerously... Thar be dragons...
39
+ define( 'PTE_TB_HEIGHT', 550 ); // This could go larger but I wouldn't go much smaller
40
+ // Pictures take up 400px with the header and potential error space
41
+ // 600 seems the best safe number.
42
+ // Difficult to say with different screen heights
43
+
44
+ define( 'PTE_DEBUG', false ); // Eventually add a control panel option for this
45
 
46
  /*
47
  * Put Hooks and immediate hook functions in this file
48
  */
49
 
50
  /* Hook into the Edit Image page */
51
+ function pte_enable_thickbox(){
52
+ wp_enqueue_style( 'thickbox' );
53
+ wp_enqueue_script( 'thickbox' );
 
 
 
 
 
54
  }
55
 
56
  function pte_admin_media_scripts(){
57
+ pte_enable_thickbox();
58
+
59
+ if ( PTE_DEBUG ){
60
+ wp_enqueue_script( 'pte'
61
+ , PTE_PLUGINURL . 'js/pte.full.js'
62
+ , array('jquery')
63
+ , PTE_VERSION
64
+ );
65
+ }
66
+ else {
67
+ wp_enqueue_script( 'pte'
68
+ , PTE_PLUGINURL . 'js/pte.full.min.js'
69
+ , array('jquery')
70
+ , PTE_VERSION
71
+ );
72
+ }
73
+ wp_localize_script('pte'
74
+ , 'objectL10n'
75
+ , array('PTE' => __('Post Thumbnail Editor'))
76
+ );
77
+ add_action("admin_head","pte_enable_admin_js",100);
78
+ }
79
+
80
+ function pte_enable_admin_js(){
81
+ $debug = PTE_DEBUG ? "var debug_enabled = true;" : "";
82
+ $pte_tb_width = PTE_TB_WIDTH;
83
+ $pte_tb_height = PTE_TB_HEIGHT;
84
+ echo <<<EOT
85
+ <script type="text/javascript">
86
+ {$debug}
87
+ var pte_tb_width = {$pte_tb_width};
88
+ var pte_tb_height = {$pte_tb_height};
89
+ jQuery( function(){ pte.admin(); } );
90
+ </script>
91
+ EOT;
92
  }
93
 
94
  function pte_ajax(){
95
  // Move all adjuntant functions to a separate file and include that here
96
  require_once(PTE_PLUGINPATH . 'pte_functions.php');
97
+
98
+ switch ($_GET['pte-action'])
99
  {
100
+ case "launch":
101
+ pte_launch();
102
+ break;
103
+ case "resize-images":
104
+ pte_resize_images();
105
+ break;
106
+ case "confirm-images":
107
+ pte_confirm_images();
108
+ break;
109
+ case "delete-images":
110
+ pte_delete_images();
111
+ break;
 
 
 
112
  }
113
  die(-1);
114
  }
115
 
116
+ function pte_media_row_actions($actions, $post, $detached){
117
+ if ( !current_user_can( 'edit_post', $post->ID ) ){
118
+ return $actions;
119
+ }
120
+ $pte_url = admin_url('admin-ajax.php')
121
+ . "?action=pte_ajax&pte-action=launch&id="
122
+ . $post->ID
123
+ . "&TB_iframe=true&height=". PTE_TB_HEIGHT ."&width=". PTE_TB_WIDTH;
124
+ $actions['pte'] = "<a class='thickbox' href='${pte_url}' title='Edit Thumbnails'>Thumbnails</a>";
125
+ return $actions;
126
+ }
127
+
128
  /* This is the main admin media page */
129
+ add_action('admin_print_styles-media.php', 'pte_admin_media_scripts');
 
130
 
131
  /* This is for the popup media page */
132
+ /* Slight redirect so this isn't called on all versions of the media upload page */
133
+ function pte_admin_media_upload(){
134
+ add_action('admin_print_scripts-media-upload-popup', 'pte_admin_media_scripts');
135
+ }
136
+ add_action('media_upload_gallery', 'pte_admin_media_upload');
137
+ add_action('media_upload_library', 'pte_admin_media_upload');
138
+
139
+ /* Adds the Thumbnail option to the media library list */
140
+ add_action('admin_print_styles-upload.php', 'pte_enable_thickbox');
141
+ add_filter('media_row_actions', 'pte_media_row_actions', 10, 3); // priority: 10, args: 3
142
 
143
  /* For all purpose needs */
144
  add_action('wp_ajax_pte_ajax', 'pte_ajax');
pte_functions.php CHANGED
@@ -1,306 +1,580 @@
1
  <?php
2
 
3
- function pte_json_encode($mixed){
4
- if ( function_exists('json_encode') ){
5
- die( json_encode($mixed) );
6
- }
7
- else {
8
- pte_error( "json_encode not available, upgrade your php" );
9
- }
10
  }
11
 
12
- /**
13
- * Validation functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  *
15
- * Return if the GET/POST data is valid
16
- * pte-error/die if invalid
17
  */
18
- function validate_image_data_inputs($id, $size){
19
- if ( !is_numeric( $id ) )
20
- pte_error("Parameter 'id' is not numeric");
21
-
22
- $fullsizepath = get_attached_file( $id );
23
- $path_information = image_get_intermediate_size($id, $size);
24
-
25
- $size_information = pte_get_alternate_sizes(true);
26
- if (! array_key_exists( $size, $size_information ) ){
27
- pte_error("Invalid size: {$size}");
28
- }
29
- return compact( 'fullsizepath'
30
- , 'path_information'
31
- , 'size_information'
32
- );
33
  }
34
 
35
- function validate_resize_inputs( $id, $thumb_size, $x, $y, $w, $h ){
36
- // Verifies that the user has proper access and intent
37
- check_ajax_referer("pte-{$id}-{$thumb_size}");
38
-
39
- //Check that the parameters are digits
40
- if ( !( is_numeric($id) &&
41
- is_numeric($x) &&
42
- is_numeric($y) &&
43
- is_numeric($w) &&
44
- is_numeric($h) ) ){
45
- pte_error("One of 'id', 'x', 'y', 'w', or 'h' is not numeric");
46
- }
47
-
48
- // Check the POST
49
- $id = (int) $id;
50
- if ( !$post =& get_post( $id ) )
51
- pte_error("Invalid id: {$id}");
52
-
53
- $file = get_attached_file( $id );
54
- $image = wp_load_image( $file );
55
-
56
- $size_information = pte_get_alternate_sizes(true);
57
- if (! array_key_exists( $thumb_size, $size_information ) ){
58
- pte_error("Invalid size: {$thumb_size}");
59
- }
60
-
61
- if (! $path_information = image_get_intermediate_size($id, $thumb_size)){
62
- pte_error("Invalid image: {$id} {$thumb_size}");
63
- }
64
-
65
- if ( !is_resource( $image ) )
66
- pte_error("Error loading image");
67
-
68
- $size = @getimagesize( $file );
69
- if ( !$size )
70
- pte_error("Could not read image size");
71
-
72
- list($orig_w, $orig_h, $orig_type) = $size;
73
-
74
- // Error checking that the src is big enough to go into dst?
75
- if (
76
- $x < 0 ||
77
- $y < 0 ||
78
- $x + $w > $orig_w ||
79
- $y + $h > $orig_h ||
80
- $w <= 0 ||
81
- $h <= 0 ){
82
- pte_error("Invalid input parameters: {$x} {$y} {$w} {$h}");
83
- }
84
- $array = compact('id'
85
- , 'post'
86
- , 'file'
87
- , 'image'
88
- , 'size_information'
89
- , 'path_information'
90
- , 'orig_w'
91
- , 'orig_h'
92
- , 'orig_type'
93
- );
94
- return $array;
95
  }
96
- /** END VALIDATION **/
97
-
98
- function pte_get_alternate_sizes($return_php = false){
99
- global $_wp_additional_image_sizes;
100
- $sizes = array();
101
- foreach (get_intermediate_image_sizes() as $s){
102
- if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) // For theme-added sizes
103
- $width = intval( $_wp_additional_image_sizes[$s]['width'] );
104
- else // For default sizes set in options
105
- $width = get_option( "{$s}_size_w" );
106
-
107
- if ( isset( $_wp_additional_image_sizes[$s]['height'] ) ) // For theme-added sizes
108
- $height = intval( $_wp_additional_image_sizes[$s]['height'] );
109
- else // For default sizes set in options
110
- $height = get_option( "{$s}_size_h" );
111
-
112
- if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) ) // For theme-added sizes
113
- $crop = intval( $_wp_additional_image_sizes[$s]['crop'] );
114
- else // For default sizes set in options
115
- $crop = get_option( "{$s}_crop" );
116
- $sizes[$s] = array(
117
- 'width' => $width,
118
- 'height' => $height,
119
- 'crop' => $crop
120
- );
121
- }
122
-
123
- if ( $return_php ) return $sizes;
124
- pte_json_encode( array( 'sizes' => $sizes ) );
125
  }
126
 
127
- function pte_get_image_data($id, $size){
128
-
129
- // Validate the inputs
130
- // Create and return:
131
- // $fullsizepath
132
- // $path_information
133
- // $size_information
134
- extract( validate_image_data_inputs( $id, $size ) );
135
-
136
- // Get/Create nonce
137
- // - This key grants limited 24 hour access to modify the attachment $id's $size
138
- $nonce = wp_create_nonce("pte-{$id}-{$size}");
139
-
140
- if ( $path_information &&
141
- @file_exists(dirname($fullsizepath)."/".$path_information['file']))
142
- {
143
- $path_information['nonce'] = $nonce;
144
- //$path_information['debug'] = "Finished without regenerating image";
145
- pte_json_encode($path_information);
146
- }
147
-
148
- // We don't really care how it gets generated, just that it is...
149
- // see ajax-thumbnail-rebuild plugin for inspiration
150
- if ( FALSE !== $fullsizepath && @file_exists($fullsizepath) ) {
151
- // Create the image and update the wordpress metadata
152
- $resized = image_make_intermediate_size( $fullsizepath,
153
- $size_information[$size]['width'],
154
- $size_information[$size]['height'],
155
- $size_information[$size]['crop']
156
- );
157
- if ($resized){
158
- $metadata = wp_get_attachment_metadata($id);
159
- $metadata['sizes'][$size] = $resized;
160
- wp_update_attachment_metadata( $id, $metadata);
161
- }
162
- }
163
-
164
- // Finish how we started
165
- $path_information = image_get_intermediate_size($id, $size);
166
- if ($path_information){
167
- $path_information['nonce'] = $nonce;
168
- pte_json_encode($path_information);
169
- }
170
- else {
171
- //print("{\"error\":\"Couldn't find metadata for image: $id\"}");
172
- pte_error("Couldn't find metadata for image");
173
- }
174
  }
175
 
176
- function pte_error($message){
177
- die("{\"error\":\"{$message}\"}");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  }
179
 
180
- /*
181
- * See wordpress: wp-includes/media.php for image_resize
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  *
183
- * TODO: Break into smaller pieces
184
- * TODO: Test saving POST META
 
 
185
  */
186
- function pte_resize_img($id, $thumb_size, $x, $y, $w, $h, $save = true){
187
- // Check your inputs...
188
- // Also creates and returns:
189
- // $post
190
- // $file
191
- // $image
192
- // $size_information
193
- // $path_information
194
- // $orig_w
195
- // $orig_h
196
- // $orig_type
197
- //extract(validate_resize_inputs( $id, $thumb_size, $x, $y, $w, $h ));
198
- $validation = validate_resize_inputs( $id, $thumb_size, $x, $y, $w, $h );
199
- extract( $validation );
200
-
201
- // Set the output (destination) information
202
- $dst_x = 0;
203
- $dst_y = 0;
204
-
205
- // ==============================
206
- // Get Destination width & height
207
- // ==============================
208
- // When the crop isn't set the biggest dimension is accurate,
209
- // but the other dimension is wrong
210
- if ($size_information[$thumb_size]['crop']){
211
- $dst_w = $size_information[$thumb_size]['width'];
212
- $dst_h = $size_information[$thumb_size]['height'];
213
- }
214
- // Crop isn't set so the height / width should be based on the biggest side
215
- // Filename changes
216
- // Update wp_attachment_metadata with the correct file/width/height
217
- else if ($w > $h){
218
- $dst_w = $size_information[$thumb_size]['width'];
219
- $dst_h = round( ($dst_w/$w) * $h, 0);
220
- }
221
- else {
222
- $dst_h = $size_information[$thumb_size]['height'];
223
- $dst_w = round( ($dst_h/$h) * $w, 0);
224
- }
225
- // ==============================
226
-
227
-
228
- // ================
229
- // Get the filename
230
- // ================
231
- // See image_resize function in wp-includes/media.php to follow the same conventions
232
- $info = pathinfo($file);
233
- $dir = $info['dirname'];
234
- $ext = $info['extension'];
235
- $name = wp_basename($file, ".$ext");
236
- $suffix = "{$dst_w}x{$dst_h}-pte";
237
- $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
238
- // ================
239
-
240
- // Set the input information
241
- $src_x = $x;
242
- $src_y = $y;
243
- $src_w = $w;
244
- $src_h = $h;
245
-
246
- // Now let's get down to business...
247
- $newimage = wp_imagecreatetruecolor( $dst_w, $dst_h );
248
-
249
- // Save the conversion data so if a batch script (a la ajax-thumbnail-rebuild)
250
- // that we can find what the scale/crop area and rebuild using it.
251
- if ($save){
252
- $data = get_post_meta( $post->ID, PTE_POST_DATA, true );
253
- $data[$thumb_size] = compact( 'dst_x', 'dst_y', 'dst_w', 'dst_h'
254
- , 'src_x', 'src_y', 'src_w', 'src_h'
255
- );
256
- update_post_meta($post->ID, PTE_POST_DATA, $data);
257
- }
258
-
259
- imagecopyresampled( $newimage, $image
260
- , $dst_x, $dst_y, $src_x, $src_y
261
- , $dst_w, $dst_h, $src_w, $src_h );
262
-
263
- // convert from full colors to index colors, like original PNG.
264
- if ( IMAGETYPE_PNG == $orig_type && function_exists('imageistruecolor') && !imageistruecolor( $image ) )
265
- imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) );
266
-
267
- // we don't need the original in memory anymore
268
- imagedestroy( $image );
269
-
270
- if ( IMAGETYPE_GIF == $orig_type ) {
271
- if ( !imagegif( $newimage, $destfilename ) )
272
- //return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
273
- pte_error("Resize path invalid");
274
- }
275
- elseif ( IMAGETYPE_PNG == $orig_type ) {
276
- if ( !imagepng( $newimage, $destfilename ) )
277
- //return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
278
- pte_error("Resize path invalid");
279
- }
280
- else {
281
- // all other formats are converted to jpg
282
- //if ( !imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality, 'image_resize' ) ) )
283
- if ( !imagejpeg( $newimage, $destfilename, 90) )
284
- //return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
285
- pte_error("Resize path invalid: " . $destfilename);
286
- }
287
-
288
- imagedestroy( $newimage );
289
-
290
- // Set correct file permissions
291
- $stat = stat( dirname( $destfilename ));
292
- $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
293
- @ chmod( $destfilename, $perms );
294
-
295
- // Update attachment metadata
296
- $metadata = wp_get_attachment_metadata($id);
297
- $metadata['sizes'][$thumb_size] = array( 'file' => "{$name}-{$suffix}.{$ext}"
298
- , 'width' => $dst_w
299
- , 'height' => $dst_h
300
- );
301
- wp_update_attachment_metadata( $id, $metadata);
302
-
303
- $path_information = image_get_intermediate_size($id, $thumb_size);
304
- pte_json_encode( array( "url" => $path_information['url'] ) );
305
  }
306
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ function pte_require_json() {
4
+ if ( function_exists( 'ob_start' ) ){
5
+ ob_start();
6
+ }
 
 
 
7
  }
8
 
9
+ /*
10
+ * This is used to output JSON
11
+ */
12
+ function pte_json_encode($mixed = null){
13
+ global $pte_errors;
14
+ // If a buffer was started this will check for any residual output
15
+ // and add to the existing errors.
16
+ if ( function_exists( 'ob_get_flush' ) ){
17
+ $buffer = ob_get_clean();
18
+ if ( isset( $buffer ) && strlen( $buffer ) > 0 ){
19
+ pte_add_error("Buffered output: {$buffer}");
20
+ }
21
+ }
22
+
23
+ if ( ! function_exists('json_encode') ){
24
+ pte_add_error( "json_encode not available, upgrade your php" );
25
+ $messages = implode( "\r\n", $pte_errors );
26
+ die("{\"error\":\"{$messages}\"}");
27
+ }
28
+
29
+ if ( ! isset($mixed) ){
30
+ $mixed = array();
31
+ }
32
+ else if ( ! is_array( $mixed ) ){
33
+ $mixed = array($mixed);
34
+ }
35
+
36
+ if ( count( $pte_errors ) > 0 ){
37
+ $mixed = array_merge_recursive( $mixed, array( 'error' => $pte_errors ) );
38
+ }
39
+
40
+ print( json_encode($mixed) );
41
+ return true;
42
+ }
43
+
44
+ /*
45
+ * pte_json_error
46
+ */
47
+ function pte_json_error($error){
48
+ pte_add_error( $error );
49
+ return pte_json_encode();
50
+ }
51
+
52
+ /*
53
+ * pte_add_error
54
+ */
55
+ function pte_add_error($error){
56
+ global $pte_errors;
57
+ if ( ! isset( $pte_errors ) || ! is_array( $pte_errors ) ){
58
+ $pte_errors = array();
59
+ }
60
+
61
+ if ( !in_array( $error, $pte_errors ) ){
62
+ if ( is_string( $error ) ){
63
+ $pte_errors[] = $error;
64
+ }
65
+ else if ( is_array( $error ) ){
66
+ $pte_errors = array_merge( $error, $pte_errors );
67
+ }
68
+ }
69
+ }
70
+
71
+ /*
72
+ * pte_filter_sizes
73
+ *
74
+ * This is used by the get_sizes functions to determine which sizes to
75
+ * reduce to
76
+ */
77
+ function pte_filter_sizes( $element ){
78
+ global $pte_sizes;
79
+ if ( is_array( $pte_sizes ) && !in_array( $element, $pte_sizes )
80
+ ){
81
+ return false;
82
+ }
83
+ return true;
84
+ }
85
+
86
+ /*
87
+ * pte_get_alternate_sizes
88
+ *
89
+ * Creates an array of each thumbnail size and the corresponding data:
90
+ * * height
91
+ * * width
92
+ * * crop boolean
93
+ *
94
+ * Thanks to the ajax_thumbnail_rebuild plugin
95
+ */
96
+ function pte_get_alternate_sizes(){
97
+ //Put in some code to check if it's already been called...
98
+ global $_wp_additional_image_sizes, $pte_gas;
99
+ if ( !isset($pte_gas) ){
100
+ $pte_gas = array();
101
+ foreach (array_filter( get_intermediate_image_sizes(), 'pte_filter_sizes' ) as $s){
102
+ if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) // For theme-added sizes
103
+ $width = intval( $_wp_additional_image_sizes[$s]['width'] );
104
+ else // For default sizes set in options
105
+ $width = get_option( "{$s}_size_w" );
106
+
107
+ if ( isset( $_wp_additional_image_sizes[$s]['height'] ) ) // For theme-added sizes
108
+ $height = intval( $_wp_additional_image_sizes[$s]['height'] );
109
+ else // For default sizes set in options
110
+ $height = get_option( "{$s}_size_h" );
111
+
112
+ if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) ) // For theme-added sizes
113
+ $crop = intval( $_wp_additional_image_sizes[$s]['crop'] );
114
+ else // For default sizes set in options
115
+ $crop = get_option( "{$s}_crop" );
116
+ $pte_gas[$s] = array(
117
+ 'width' => $width,
118
+ 'height' => $height,
119
+ 'crop' => $crop
120
+ );
121
+ }
122
+ }
123
+ return $pte_gas;
124
+ }
125
+
126
+ /*
127
+ * pte_get_image_data
128
+ *
129
+ * Gets specific data for a given image (id) at a given size (size)
130
+ * Optionally can return the JSON value or PHP array
131
+ */
132
+ function pte_get_image_data( $id, $size, $size_data ){
133
+
134
+ $fullsizepath = get_attached_file( $id );
135
+ $path_information = image_get_intermediate_size($id, $size);
136
+
137
+ if ( $path_information &&
138
+ @file_exists( dirname( $fullsizepath ) . DIRECTORY_SEPARATOR . $path_information['file'] )
139
+ ){
140
+ //print_r( $path_information );
141
+ return $path_information;
142
+ }
143
+ //print("NOPE, no path information...");
144
+ //print_r($path_information);
145
+ //print("END PI");
146
+
147
+ // We don't really care how it gets generated, just that it is...
148
+ // see ajax-thumbnail-rebuild plugin for inspiration
149
+ if ( FALSE !== $fullsizepath && @file_exists($fullsizepath) ) {
150
+ // Create the image and update the wordpress metadata
151
+ $resized = image_make_intermediate_size( $fullsizepath,
152
+ $size_data['width'],
153
+ $size_data['height'],
154
+ $size_data['crop']
155
+ );
156
+ if ($resized){
157
+ $metadata = wp_get_attachment_metadata($id);
158
+ $metadata['sizes'][$size] = $resized;
159
+ wp_update_attachment_metadata( $id, $metadata);
160
+ }
161
+ }
162
+
163
+ // Finish how we started
164
+ $path_information = image_get_intermediate_size($id, $size);
165
+ if ($path_information){
166
+ return $path_information;
167
+ }
168
+ else {
169
+ pte_add_error( "Couldn't find or generate metadata for image: {$id}-{$size}" );
170
+ }
171
+ return false;
172
+ }
173
+
174
+ /*
175
+ * pte_get_all_alternate_size_information
176
  *
177
+ * Gets all pertinent data describing the alternate sizes
 
178
  */
179
+ function pte_get_all_alternate_size_information( $id ){
180
+ $sizes = pte_get_alternate_sizes();
181
+ foreach ( $sizes as $size => &$info ){
182
+ $info['current'] = pte_get_image_data( $id, $size, $info );
183
+ }
184
+ return $sizes;
 
 
 
 
 
 
 
 
 
185
  }
186
 
187
+ /*
188
+ * pte_launch
189
+ *
190
+ * Outputs the base HTML needed to display and transform the inages
191
+ *
192
+ * Requires post id as $_GET['id']
193
+ */
194
+ function pte_launch(){
195
+ //wp_register_script( 'jquery-tmpl'
196
+ // , PTE_PLUGINURL . 'apps/jquery-tmpl/jquery.tmpl.min.js'
197
+ // , array('jquery')
198
+ // , '1.0.0pre'
199
+ //);
200
+ if ( PTE_DEBUG ) {
201
+ wp_enqueue_script( 'pte'
202
+ , PTE_PLUGINURL . 'js/pte.full.js'
203
+ , array('jquery','imgareaselect')
204
+ , PTE_VERSION
205
+ );
206
+ wp_enqueue_style( 'pte'
207
+ , PTE_PLUGINURL . 'css/pte.css'
208
+ , array('imgareaselect')
209
+ , PTE_VERSION
210
+ );
211
+ }
212
+ else { // Minified versions
213
+ wp_enqueue_script( 'pte'
214
+ , PTE_PLUGINURL . 'js/pte.full.min.js'
215
+ , array('jquery','imgareaselect')
216
+ , PTE_VERSION
217
+ );
218
+ wp_enqueue_style( 'pte'
219
+ , PTE_PLUGINURL . 'css/pte.min.css'
220
+ , array('imgareaselect')
221
+ , PTE_VERSION
222
+ );
223
+ }
224
+
225
+ $id = pte_check_id((int) $_GET['id']);
226
+
227
+ $size_information = pte_get_all_alternate_size_information( $id );
228
+
229
+ // Get the information needed for image preview
230
+ // (See wp-admin/includes/image-edit.php)
231
+ $nonce = wp_create_nonce("image_editor-$id");
232
+ $meta = wp_get_attachment_metadata($id);
233
+
234
+ if ( is_array($meta) && isset($meta['width']) )
235
+ $big = max( $meta['width'], $meta['height'] );
236
+
237
+ $sizer = $big > 400 ? 400 / $big : 1;
238
+
239
+ require( PTE_PLUGINPATH . "html/pte.html" );
 
 
 
 
 
 
 
240
  }
241
+
242
+ function pte_check_id( $id ){
243
+ if ( !$post =& get_post( $id ) ){
244
+ pte_add_error( "Invalid id: {$id}" );
245
+ return false;
246
+ }
247
+ if ( !current_user_can( 'edit_post', $id ) ){
248
+ pte_add_error( "User does not have permission to edit this item" );
249
+ return false;
250
+ }
251
+ return $id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  }
253
 
254
+ function pte_check_int( $int ){
255
+ if (! is_numeric( $int ) ){
256
+ pte_add_error("PARAM not numeric: '{$int}'");
257
+ return false;
258
+ }
259
+ return $int;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
 
262
+ /*
263
+ * Get Destination width & height
264
+ * ==============================
265
+ * When the crop isn't set:
266
+ * the size information for the biggest dimension is accurate,
267
+ * but the other dimension is wrong
268
+ */
269
+ function pte_get_width_height( $size_information, $w, $h ){
270
+ if ( $size_information['crop'] == 1 ){
271
+ $dst_w = $size_information['width'];
272
+ $dst_h = $size_information['height'];
273
+ }
274
+ // Crop isn't set so the height / width should be based on the biggest side
275
+ else if ($w > $h){
276
+ $dst_w = $size_information['width'];
277
+ $dst_h = round( ($dst_w/$w) * $h, 0);
278
+ }
279
+ else {
280
+ $dst_h = $size_information['height'];
281
+ $dst_w = round( ($dst_h/$h) * $w, 0);
282
+ }
283
+ $return = compact( "dst_w", "dst_h" );
284
+ return $return;
285
  }
286
 
287
+ /*
288
+ * ================
289
+ * Get the filename
290
+ * ================
291
+ * See image_resize function in wp-includes/media.php to follow the same conventions
292
+ * - Check if the file exists
293
+ */
294
+ function pte_generate_filename( $file, $w, $h ){
295
+ $info = pathinfo( $file );
296
+ $ext = $info['extension'];
297
+ $name = wp_basename( $file, ".$ext" );
298
+ $suffix = "{$w}x{$h}";
299
+ //print_r( compact( "file", "info", "ext", "name", "suffix" ) );
300
+ return "{$name}-{$suffix}.{$ext}";
301
+ }
302
+
303
+ /*
304
+ * pte_create_image
305
+ */
306
+ function pte_create_image($original_image, $type,
307
+ $dst_x, $dst_y, $dst_w, $dst_h,
308
+ $src_x, $src_y, $src_w, $src_h )
309
+ {
310
+ $new_image = wp_imagecreatetruecolor( $dst_w, $dst_h );
311
+
312
+ //print_r( compact( "original_image", 'type', 'dst_x', 'dst_y', 'dst_w', 'dst_h',
313
+ // 'src_x','src_y','src_w','src_h' ) );
314
+
315
+ imagecopyresampled( $new_image, $original_image,
316
+ $dst_x, $dst_y, $src_x, $src_y,
317
+ $dst_w, $dst_h, $src_w, $src_h
318
+ );
319
+
320
+ // convert from full colors to index colors, like original PNG.
321
+ if ( IMAGETYPE_PNG == $type &&
322
+ function_exists('imageistruecolor') &&
323
+ !imageistruecolor( $original_image )
324
+ ){
325
+ imagetruecolortopalette( $newimage, false, imagecolorstotal( $original_image ) );
326
+ }
327
+
328
+ return $new_image;
329
+ }
330
+
331
+ function pte_write_image( $image, $orig_type, $destfilename ){
332
+ $dir = dirname( $destfilename );
333
+ if ( ! is_dir( $dir ) ){
334
+ if ( ! mkdir( $dir, 0777, true ) ){
335
+ pte_add_error("Error creating directory: {$dir}");
336
+ }
337
+ }
338
+
339
+ if ( IMAGETYPE_GIF == $orig_type ) {
340
+ if ( !imagegif( $image, $destfilename ) ){
341
+ pte_add_error("Resize path invalid");
342
+ return false;
343
+ }
344
+ }
345
+ elseif ( IMAGETYPE_PNG == $orig_type ) {
346
+ if ( !imagepng( $image, $destfilename ) ){
347
+ pte_add_error("Resize path invalid");
348
+ return false;
349
+ }
350
+ }
351
+ else {
352
+ // all other formats are converted to jpg
353
+ if ( !imagejpeg( $image, $destfilename, 90) ){
354
+ pte_add_error("Resize path invalid: " . $destfilename);
355
+ return false;
356
+ }
357
+ }
358
+
359
+ imagedestroy( $image );
360
+
361
+ // Set correct file permissions
362
+ $stat = stat( dirname( $destfilename ));
363
+ $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
364
+ @ chmod( $destfilename, $perms );
365
+
366
+ return true;
367
+ }
368
+
369
+
370
+ /*
371
+ * resize_images
372
+ *
373
+ * Take an array of sizes along with the associated resize data (w/h/x/y)
374
+ * and save the images to a temp directory
375
+ *
376
+ * OUTPUT: JSON object 'size: url'
377
+ */
378
+ function pte_resize_images(){
379
+ global $pte_sizes;
380
+
381
+ // Require JSON output
382
+ pte_require_json();
383
+
384
+ $id = pte_check_id( $_GET['id'] );
385
+ $w = pte_check_int( $_GET['w'] );
386
+ $h = pte_check_int( $_GET['h'] );
387
+ $x = pte_check_int( $_GET['x'] );
388
+ $y = pte_check_int( $_GET['y'] );
389
+
390
+ if ( $id === false
391
+ || $w === false
392
+ || $h === false
393
+ || $x === false
394
+ || $y === false
395
+ ){
396
+ return pte_json_error( "ResizeImages initialization failed: '{$id}-{$w}-{$h}-{$x}-{$y}'" );
397
+ }
398
+
399
+ // Get the sizes to process
400
+ $pte_sizes = $_GET['pte-sizes'];
401
+ $sizes = pte_get_all_alternate_size_information( $id );
402
+
403
+ // The following information is common to all sizes
404
+ // *** common-info
405
+ $dst_x = 0;
406
+ $dst_y = 0;
407
+ $original_file = get_attached_file( $id );
408
+ $original_image = wp_load_image( $original_file );
409
+ $original_size = @getimagesize( $original_file );
410
+ $uploads = wp_upload_dir();
411
+ $PTE_TMP_DIR = $uploads['basedir'] . DIRECTORY_SEPARATOR . "ptetmp" . DIRECTORY_SEPARATOR;
412
+ $PTE_TMP_URL = $uploads['baseurl'] . "/ptetmp/";
413
+
414
+ if ( !$original_size ){
415
+ return pte_json_error("Could not read image size");
416
+ }
417
+
418
+ list( $orig_w, $orig_h, $orig_type ) = $original_size;
419
+ // *** End common-info
420
+
421
+ foreach ( $sizes as $size => $data ){
422
+ // Get all the data needed to run image_create
423
+ //
424
+ // $dst_w, $dst_h
425
+ extract( pte_get_width_height( $data, $w, $h ) );
426
+ //
427
+ // Set the directory
428
+ $basename = pte_generate_filename( $original_file, $dst_w, $dst_h );
429
+ // Set the file and URL's - defines set in pte_ajax
430
+ $tmpfile = "{$PTE_TMP_DIR}{$id}" . DIRECTORY_SEPARATOR . "{$basename}";
431
+ $tmpurl = "{$PTE_TMP_URL}{$id}/{$basename}";
432
+
433
+ // === CREATE IMAGE ===================
434
+ $image = pte_create_image( $original_image, $orig_type,
435
+ $dst_x, $dst_y, $dst_w, $dst_h,
436
+ $x, $y, $w, $h );
437
+
438
+ if ( ! isset( $image ) ){
439
+ pte_add_error( "Error creating image: {$size}" );
440
+ continue;
441
+ }
442
+
443
+ if ( ! pte_write_image( $image, $orig_type, $tmpfile ) ){
444
+ pte_add_error( "Error writing image: {$size} to '{$tmpfile}'" );
445
+ continue;
446
+ }
447
+ // === END CREATE IMAGE ===============
448
+
449
+ // URL: wp_upload_dir => base_url/subdir + /basename of $tmpfile
450
+ // This is for the output
451
+ $thumbnails[$size]['url'] = $tmpurl;
452
+ $thumbnails[$size]['file'] = basename( $tmpfile );
453
+ }
454
+
455
+ // we don't need the original in memory anymore
456
+ imagedestroy( $original_image );
457
+
458
+ // Did you process anything?
459
+ if ( count( $thumbnails ) < 1 ){
460
+ return pte_json_error("No images processed");
461
+ }
462
+
463
+ return pte_json_encode( array(
464
+ 'thumbnails' => $thumbnails,
465
+ 'pte-nonce' => wp_create_nonce( "pte-{$id}" ),
466
+ 'pte-delete-nonce' => wp_create_nonce( "pte-delete-{$id}" )
467
+ ) );
468
+ }
469
+
470
+ /*
471
+ * pte_confirm_images
472
  *
473
+ * Take an array of image sizes, an ID and a nonce and then move the confirmed images
474
+ * to the official position and update metadata...
475
+ *
476
+ * Clean up and return error/success information...
477
  */
478
+ function pte_confirm_images(){
479
+ global $pte_sizes, $pte_errors;
480
+
481
+ // Require JSON output
482
+ pte_require_json();
483
+
484
+ $id = pte_check_id( (int) $_GET['id'] );
485
+ if ( $id === false ){
486
+ return pte_json_error( "ID invalid: {$id}" );
487
+ }
488
+
489
+ // Check nonce
490
+ if ( !check_ajax_referer( "pte-{$id}", 'pte-nonce', false ) ){
491
+ return pte_json_error( "CSRF Check failed" );
492
+ }
493
+
494
+ // Get the available sizes
495
+ if ( is_array( $_GET['pte-confirm'] ) ){
496
+ $pte_sizes = array_keys( $_GET['pte-confirm'] );
497
+ $sizes = pte_get_all_alternate_size_information( $id );
498
+ }
499
+ else {
500
+ return pte_json_error( "Invalid Parameters: can't find sizes" );
501
+ }
502
+ // === END INITIALIZATION ================================
503
+
504
+ // Foreach size:
505
+ // Move good image
506
+ // Update metadata
507
+ // Delete old image
508
+ // Remove PTE/$id directory
509
+ $uploads = wp_upload_dir();
510
+ $PTE_TMP_DIR = $uploads['basedir'] . DIRECTORY_SEPARATOR . "ptetmp" . DIRECTORY_SEPARATOR . $id;
511
+ foreach ( $sizes as $size => $data ){
512
+ // Make sure we're only moving our files
513
+ $good_file = $PTE_TMP_DIR
514
+ . DIRECTORY_SEPARATOR
515
+ . basename( $_GET['pte-confirm'][$size] );
516
+
517
+ if ( ! ( isset( $good_file ) && file_exists( $good_file ) ) ){
518
+ return pte_json_error("FILE is invalid: {$good_file}");
519
+ }
520
+
521
+ $dir = dirname( get_attached_file( $id ) );
522
+ $new_file = $dir
523
+ . DIRECTORY_SEPARATOR
524
+ . basename( $good_file );
525
+ if ( isset( $data['file'] ) ){
526
+ $old_file = $dir
527
+ . DIRECTORY_SEPARATOR
528
+ . $data['file'];
529
+ }
530
+
531
+ // Move good image
532
+ rename( $good_file, $new_file );
533
+
534
+ // Update metadata
535
+ $image_dimensions = @getimagesize( $new_file );
536
+ list( $w, $h, $type ) = $image_dimensions;
537
+ //print("IMAGE DIMENSIONS...");
538
+ //print_r( $image_dimensions );
539
+ $metadata = wp_get_attachment_metadata( $id );
540
+ $metadata['sizes'][$size] = array(
541
+ 'file' => basename( $new_file ),
542
+ 'width' => $w,
543
+ 'height' => $h
544
+ );
545
+ //print_r($metadata['sizes'][$size]);
546
+ wp_update_attachment_metadata( $id, $metadata);
547
+
548
+ // Delete/unlink old file
549
+ if ( isset( $old_file )
550
+ && $old_file !== $new_file
551
+ && file_exists( $old_file ) )
552
+ {
553
+ //print( "OLD FILE: {$old_file}" );
554
+ unlink( $old_file );
555
+ }
556
+ }
557
+ // Delete tmpdir
558
+ rmdir( $PTE_TMP_DIR );
559
+ return pte_json_encode( array( 'success' => "Yay!" ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  }
561
 
562
+ function pte_delete_images()
563
+ {
564
+ // Require JSON output
565
+ pte_require_json();
566
+
567
+ $id = pte_check_id( (int) $_GET['id'] );
568
+ if ( $id === false ){
569
+ return pte_json_error( "ID invalid: {$id}" );
570
+ }
571
+ // Check nonce
572
+ if ( !check_ajax_referer( "pte-delete-{$id}", 'pte-nonce', false ) ){
573
+ return pte_json_error( "CSRF Check failed" );
574
+ }
575
+ $uploads = wp_upload_dir();
576
+ $PTE_TMP_DIR = $uploads['basedir'] . DIRECTORY_SEPARATOR . "ptetmp" . DIRECTORY_SEPARATOR . $id;
577
+ // Delete tmpdir
578
+ unlink( $PTE_TMP_DIR );
579
+ return pte_json_encode( array( "success" => "Yay!" ) );
580
+ }
screenshot-2.jpg CHANGED
Binary file
screenshot-3.jpg CHANGED
Binary file
screenshot-4.jpg ADDED
Binary file
screenshot-5.jpg ADDED
Binary file
screenshot-6.jpg ADDED
Binary file